Advertisement
Guest User

Untitled

a guest
Aug 28th, 2016
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.46 KB | None | 0 0
  1. ;; Simple TCP echo server in x86_64 assembly, using Linux syscalls
  2. ;;
  3. ;; nasm -felf64 -o server.o server.asm
  4. ;; ld server.o -o server
  5. ;; ./server
  6. ;;
  7.  
  8. global _start
  9.  
  10. ;; Data definitions
  11. struc sockaddr_in
  12. .sin_family resw 1
  13. .sin_port resw 1
  14. .sin_addr resd 1
  15. .sin_zero resb 8
  16. endstruc
  17.  
  18. section .bss
  19. sock resw 2
  20. client resw 2
  21. echobuf resb 256
  22. read_count resw 2
  23.  
  24. section .data
  25. sock_err_msg db "Failed to initialise socket", 0x0a, 0
  26. sock_err_msg_len equ $ - sock_err_msg
  27.  
  28. bind_err_msg db "Failed to bind socket to listening address", 0x0a, 0
  29. bind_err_msg_len equ $ - bind_err_msg
  30.  
  31. lstn_err_msg db "Failed to listen on socket", 0x0a, 0
  32. lstn_err_msg_len equ $ - lstn_err_msg
  33.  
  34. accept_err_msg db "Could not accept connection attempt", 0x0a, 0
  35. accept_err_msg_len equ $ - accept_err_msg
  36.  
  37. accept_msg db "Client connected!", 0x0a, 0
  38. accept_msg_len equ $ - accept_msg
  39.  
  40. ;; sockaddr_in structure for the address the listening socket binds to
  41. pop_sa istruc sockaddr_in
  42. at sockaddr_in.sin_family, dw 2 ; AF_INET
  43. at sockaddr_in.sin_port, dw 0xa1ed ; port 60833
  44. at sockaddr_in.sin_addr, dd 0 ; localhost
  45. at sockaddr_in.sin_zero, dd 0, 0
  46. iend
  47. sockaddr_in_len equ $ - pop_sa
  48.  
  49. section .text
  50.  
  51. ;; Main entry point for the server.
  52. _start:
  53. ;; Initialise listening and client socket values to 0, used for cleanup handling
  54. mov word [sock], 0
  55. mov word [client], 0
  56.  
  57. ;; Initialize socket
  58. call _socket
  59.  
  60. ;; Bind and Listen
  61. call _listen
  62.  
  63. ;; Main loop handles clients connecting (accept()) then echoes any input
  64. ;; back to the client
  65. .mainloop:
  66. call _accept
  67.  
  68. ;; Read and re-send all bytes sent by the client until the client hangs
  69. ;; up the connection on their end.
  70. .readloop:
  71. call _read
  72. call _echo
  73.  
  74. ;; read_count is set to zero when client hangs up
  75. mov rax, [read_count]
  76. cmp rax, 0
  77. je .read_complete
  78. jmp .readloop
  79.  
  80. .read_complete:
  81. ;; Close client socket
  82. mov rdi, [client]
  83. call _close_sock
  84. mov word [client], 0
  85. jmp .mainloop
  86.  
  87. ;; Exit with success (return 0)
  88. mov rdi, 0
  89. call _exit
  90.  
  91. ;; Performs a sys_socket call to initialise a TCP/IP listening socket, storing
  92. ;; socket file descriptor in the sock variable
  93. _socket:
  94. mov rax, 41 ; SYS_SOCKET
  95. mov rdi, 2 ; AF_INET
  96. mov rsi, 1 ; SOCK_STREAM
  97. mov rdx, 0
  98. syscall
  99.  
  100. ;; Check socket was created correctly
  101. cmp rax, 0
  102. jle _socket_fail
  103.  
  104. ;; Store socket descriptor in variable
  105. mov [sock], rax
  106.  
  107. ret
  108.  
  109. ;; Calls sys_bind and sys_listen to start listening for connections
  110. _listen:
  111. mov rax, 49 ; SYS_BIND
  112. mov rdi, [sock] ; listening socket fd
  113. mov rsi, pop_sa ; sockaddr_in struct
  114. mov rdx, sockaddr_in_len ; length of sockaddr_in
  115. syscall
  116.  
  117. ;; Check call succeeded
  118. cmp rax, 0
  119. jl _bind_fail
  120.  
  121. ;; Bind succeeded, call sys_listen
  122. mov rax, 50 ; SYS_LISTEN
  123. mov rsi, 1 ; backlog (dummy value really)
  124. syscall
  125.  
  126. ;; Check for success
  127. cmp rax, 0
  128. jl _listen_fail
  129.  
  130. ret
  131.  
  132. ;; Accepts a connection from a client, storing the client socket file descriptor
  133. ;; in the client variable and logging the connection to stdout
  134. _accept:
  135. ;; Call sys_accept
  136. mov rax, 43 ; SYS_ACCEPT
  137. mov rdi, [sock] ; listening socket fd
  138. mov rsi, 0 ; NULL sockaddr_in value as we don't need that data
  139. mov rdx, 0 ; NULLs have length 0
  140. syscall
  141.  
  142. ;; Check call succeeded
  143. cmp rax, 0
  144. jl _accept_fail
  145.  
  146. ;; Store returned fd in variable
  147. mov [client], rax
  148.  
  149. ;; Log connection to stdout
  150. mov rax, 1 ; SYS_WRITE
  151. mov rdi, 1 ; STDOUT
  152. mov rsi, accept_msg
  153. mov rdx, accept_msg_len
  154. syscall
  155.  
  156. ret
  157.  
  158. ;; Reads up to 256 bytes from the client into echobuf and sets the read_count variable
  159. ;; to be the number of bytes read by sys_read
  160. _read:
  161. ;; Call sys_read
  162. mov rax, 0 ; SYS_READ
  163. mov rdi, [client] ; client socket fd
  164. mov rsi, echobuf ; buffer
  165. mov rdx, 256 ; read 256 bytes
  166. syscall
  167.  
  168. ;; Copy number of bytes read to variable
  169. mov [read_count], rax
  170.  
  171. ret
  172.  
  173. ;; Sends up to the value of read_count bytes from echobuf to the client socket
  174. ;; using sys_write
  175. _echo:
  176. mov rax, 1 ; SYS_WRITE
  177. mov rdi, [client] ; client socket fd
  178. mov rsi, echobuf ; buffer
  179. mov rdx, [read_count] ; number of bytes received in _read
  180. syscall
  181.  
  182. ret
  183.  
  184. ;; Performs sys_close on the socket in rdi
  185. _close_sock:
  186. mov rax, 3 ; SYS_CLOSE
  187. syscall
  188.  
  189. ret
  190.  
  191. ;; Error Handling code
  192. ;; _*_fail handle the population of the rsi and rdx registers with the correct
  193. ;; error messages for the labelled situation. They then call _fail to show the
  194. ;; error message and exit the application.
  195. _socket_fail:
  196. mov rsi, sock_err_msg
  197. mov rdx, sock_err_msg_len
  198. call _fail
  199.  
  200. _bind_fail:
  201. mov rsi, bind_err_msg
  202. mov rdx, bind_err_msg_len
  203. call _fail
  204.  
  205. _listen_fail:
  206. mov rsi, lstn_err_msg
  207. mov rdx, lstn_err_msg_len
  208. call _fail
  209.  
  210. _accept_fail:
  211. mov rsi, accept_err_msg
  212. mov rdx, accept_err_msg_len
  213. call _fail
  214.  
  215. ;; Calls the sys_write syscall, writing an error message to stderr, then exits
  216. ;; the application. rsi and rdx must be populated with the error message and
  217. ;; length of the error message before calling _fail
  218. _fail:
  219. mov rax, 1 ; SYS_WRITE
  220. mov rdi, 2 ; STDERR
  221. syscall
  222.  
  223. mov rdi, 1
  224. call _exit
  225.  
  226. ;; Exits cleanly, checking if the listening or client sockets need to be closed
  227. ;; before calling sys_exit
  228. _exit:
  229. mov rax, [sock]
  230. cmp rax, 0
  231. je .client_check
  232. mov rdi, [sock]
  233. call _close_sock
  234.  
  235. .client_check:
  236. mov rax, [client]
  237. cmp rax, 0
  238. je .perform_exit
  239. mov rdi, [client]
  240. call _close_sock
  241.  
  242. .perform_exit:
  243. mov rax, 60
  244. syscall
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement