errors_linux.odin 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. #+build linux
  2. package net
  3. /*
  4. Package net implements cross-platform Berkeley Sockets, DNS resolution and associated procedures.
  5. For other protocols and their features, see subdirectories of this package.
  6. */
  7. /*
  8. Copyright 2022 Tetralux <[email protected]>
  9. Copyright 2022 Colin Davidson <[email protected]>
  10. Copyright 2022 Jeroen van Rijn <[email protected]>.
  11. Copyright 2024 Feoramund <[email protected]>.
  12. Made available under Odin's BSD-3 license.
  13. List of contributors:
  14. Tetralux: Initial implementation
  15. Colin Davidson: Linux platform code, OSX platform code, Odin-native DNS resolver
  16. Jeroen van Rijn: Cross platform unification, code style, documentation
  17. flysand: Move dependency from core:linux.Errno to core:sys/linux
  18. Feoramund: FreeBSD platform code
  19. */
  20. import "core:reflect"
  21. import "core:sys/linux"
  22. @(private="file", thread_local)
  23. _last_error: linux.Errno
  24. _last_platform_error :: proc() -> i32 {
  25. return i32(_last_error)
  26. }
  27. _last_platform_error_string :: proc() -> string {
  28. description, _ := reflect.enum_name_from_value(_last_error)
  29. return description
  30. }
  31. _set_last_platform_error :: proc(err: i32) {
  32. _last_error = linux.Errno(err)
  33. }
  34. _create_socket_error :: proc(errno: linux.Errno) -> Create_Socket_Error {
  35. assert(errno != nil)
  36. _last_error = errno
  37. #partial switch errno {
  38. case .EMFILE, .ENFILE, .ENOBUFS, .EPROTONOSUPPORT:
  39. return .Insufficient_Resources
  40. case .EAFNOSUPPORT, .EPROTOTYPE:
  41. return .Invalid_Argument
  42. case .EACCES, .EPERM:
  43. return .Insufficient_Permissions
  44. case:
  45. return .Unknown
  46. }
  47. }
  48. _dial_error :: proc(errno: linux.Errno) -> Dial_Error {
  49. assert(errno != nil)
  50. _last_error = errno
  51. #partial switch errno {
  52. case .EAGAIN:
  53. return .Insufficient_Resources
  54. case .EBADF, .EINVAL, .ENOTSOCK, .EADDRNOTAVAIL, .EAFNOSUPPORT, .EFAULT:
  55. return .Invalid_Argument
  56. case .EISCONN:
  57. return .Already_Connected
  58. case .EALREADY:
  59. return .Already_Connecting
  60. case .EADDRINUSE:
  61. return .Address_In_Use
  62. case .ENETUNREACH:
  63. return .Network_Unreachable
  64. case .EHOSTUNREACH:
  65. return .Host_Unreachable
  66. case .ECONNREFUSED:
  67. return .Refused
  68. case .ECONNRESET:
  69. return .Reset
  70. case .ETIMEDOUT:
  71. return .Timeout
  72. case .EINPROGRESS:
  73. return .Would_Block
  74. case .EINTR:
  75. return .Interrupted
  76. case .EACCES:
  77. return .Broadcast_Not_Supported
  78. case:
  79. return .Unknown
  80. }
  81. }
  82. _bind_error :: proc(errno: linux.Errno) -> Bind_Error {
  83. assert(errno != nil)
  84. _last_error = errno
  85. #partial switch errno {
  86. case .EAGAIN, .ENOTSOCK, .EADDRNOTAVAIL, .EAFNOSUPPORT, .EFAULT:
  87. return .Insufficient_Resources
  88. case .EINVAL:
  89. return .Already_Bound
  90. case .EBADF:
  91. return .Invalid_Argument
  92. case .EACCES:
  93. return .Insufficient_Permissions_For_Address
  94. case .EADDRINUSE:
  95. return .Address_In_Use
  96. case:
  97. return .Unknown
  98. }
  99. }
  100. _listen_error :: proc(errno: linux.Errno) -> Listen_Error {
  101. assert(errno != nil)
  102. _last_error = errno
  103. #partial switch errno {
  104. case .EBADF, .ENOTSOCK:
  105. return .Invalid_Argument
  106. case .EDESTADDRREQ, .EOPNOTSUPP:
  107. return .Unsupported_Socket
  108. case .EINVAL:
  109. return .Already_Connected
  110. case:
  111. return .Unknown
  112. }
  113. }
  114. _accept_error :: proc(errno: linux.Errno) -> Accept_Error {
  115. assert(errno != nil)
  116. _last_error = errno
  117. #partial switch errno {
  118. case .EMFILE, .ENFILE, .ENOBUFS, .ENOMEM:
  119. return .Insufficient_Resources
  120. case .EBADF, .ENOTSOCK, .EFAULT:
  121. return .Invalid_Argument
  122. case .EINVAL:
  123. return .Not_Listening
  124. case .ECONNABORTED:
  125. return .Aborted
  126. case .EWOULDBLOCK:
  127. return .Would_Block
  128. case .EINTR:
  129. return .Interrupted
  130. case:
  131. return .Unknown
  132. }
  133. }
  134. _tcp_recv_error :: proc(errno: linux.Errno) -> TCP_Recv_Error {
  135. assert(errno != nil)
  136. _last_error = errno
  137. #partial switch errno {
  138. case .EBADF, .ENOTSOCK, .EFAULT:
  139. return .Invalid_Argument
  140. case .ENOTCONN:
  141. return .Not_Connected
  142. case .ECONNREFUSED, .ECONNRESET:
  143. return .Connection_Closed
  144. case .ETIMEDOUT:
  145. return .Timeout
  146. case .EAGAIN:
  147. return .Would_Block
  148. case .EINTR:
  149. return .Interrupted
  150. case:
  151. return .Unknown
  152. }
  153. }
  154. _udp_recv_error :: proc(errno: linux.Errno) -> UDP_Recv_Error {
  155. assert(errno != nil)
  156. _last_error = errno
  157. #partial switch errno {
  158. case .EBADF, .ENOTSOCK, .EFAULT:
  159. return .Invalid_Argument
  160. case .ECONNREFUSED, .ENOTCONN, .ECONNRESET:
  161. return .Connection_Refused
  162. case .ETIMEDOUT:
  163. return .Timeout
  164. case .EAGAIN:
  165. return .Would_Block
  166. case .EINTR:
  167. return .Interrupted
  168. case:
  169. return .Unknown
  170. }
  171. }
  172. _tcp_send_error :: proc(errno: linux.Errno) -> TCP_Send_Error {
  173. assert(errno != nil)
  174. _last_error = errno
  175. #partial switch errno {
  176. case .EBADF, .EACCES, .ENOTSOCK, .EFAULT, .EMSGSIZE, .EDESTADDRREQ, .EINVAL, .EISCONN, .EOPNOTSUPP:
  177. return .Invalid_Argument
  178. case .ENOBUFS, .ENOMEM:
  179. return .Insufficient_Resources
  180. case .ECONNRESET, .EPIPE:
  181. return .Connection_Closed
  182. case .ENOTCONN:
  183. return .Not_Connected
  184. case .EHOSTUNREACH:
  185. return .Host_Unreachable
  186. case .EHOSTDOWN:
  187. return .Host_Unreachable
  188. case .ENETDOWN:
  189. return .Network_Unreachable
  190. case .EAGAIN:
  191. return .Would_Block
  192. case .EINTR:
  193. return .Interrupted
  194. case:
  195. return .Unknown
  196. }
  197. }
  198. _udp_send_error :: proc(errno: linux.Errno) -> UDP_Send_Error {
  199. assert(errno != nil)
  200. _last_error = errno
  201. #partial switch errno {
  202. case .EBADF, .EACCES, .ENOTSOCK, .EFAULT, .EMSGSIZE, .EDESTADDRREQ, .EINVAL, .EISCONN, .EOPNOTSUPP:
  203. return .Invalid_Argument
  204. case .ENOBUFS, .ENOMEM:
  205. return .Insufficient_Resources
  206. case .ECONNRESET, .EPIPE:
  207. return .Connection_Refused
  208. case .EHOSTUNREACH:
  209. return .Host_Unreachable
  210. case .EHOSTDOWN:
  211. return .Host_Unreachable
  212. case .ENETDOWN:
  213. return .Network_Unreachable
  214. case .EAGAIN:
  215. return .Would_Block
  216. case .EINTR:
  217. return .Interrupted
  218. case:
  219. return .Unknown
  220. }
  221. }
  222. _shutdown_error :: proc(errno: linux.Errno) -> Shutdown_Error {
  223. assert(errno != nil)
  224. _last_error = errno
  225. #partial switch errno {
  226. case .EBADF, .EINVAL, .ENOTSOCK, .ENOTCONN:
  227. return .Invalid_Argument
  228. case:
  229. return .Unknown
  230. }
  231. }
  232. _socket_info_error :: proc(errno: linux.Errno) -> Socket_Info_Error {
  233. assert(errno != nil)
  234. _last_error = errno
  235. #partial switch errno {
  236. case .EBADF, .ENOTSOCK, .EFAULT, .EINVAL:
  237. return .Invalid_Argument
  238. case .ENOTCONN:
  239. return .Network_Unreachable
  240. case .ENOBUFS:
  241. return .Insufficient_Resources
  242. case:
  243. return .Unknown
  244. }
  245. }
  246. _socket_option_error :: proc(errno: linux.Errno) -> Socket_Option_Error {
  247. assert(errno != nil)
  248. _last_error = errno
  249. #partial switch errno {
  250. case .ENOMEM, .ENOBUFS:
  251. return .Insufficient_Resources
  252. case .EBADF, .ENOTSOCK:
  253. return .Invalid_Socket
  254. case .ENOPROTOOPT, .EINVAL:
  255. return .Invalid_Option
  256. case .EFAULT, .EDOM:
  257. return .Invalid_Value
  258. case:
  259. return .Unknown
  260. }
  261. }
  262. _set_blocking_error :: proc(errno: linux.Errno) -> Set_Blocking_Error {
  263. assert(errno != nil)
  264. _last_error = errno
  265. #partial switch errno {
  266. case .EBADF:
  267. return .Invalid_Argument
  268. case:
  269. return .Unknown
  270. }
  271. }