netdb.odin 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. package posix
  2. import "core:c"
  3. when ODIN_OS == .Darwin {
  4. foreign import lib "system:System.framework"
  5. } else {
  6. foreign import lib "system:c"
  7. }
  8. // netdb.h - definitions for network database operations
  9. foreign lib {
  10. /*
  11. Translate node/serv name and return a set of socket addresses and associated information to be
  12. used in creating a socket with which to address the specified service.
  13. Example:
  14. // The following (incomplete) program demonstrates the use of getaddrinfo() to obtain the
  15. // socket address structure(s) for the service named in the program's command-line argument.
  16. // The program then loops through each of the address structures attempting to create and bind
  17. // a socket to the address, until it performs a successful bind().
  18. args := runtime.args__
  19. if len(args) != 2 {
  20. fmt.eprintfln("Usage: %s port", args[0])
  21. posix.exit(1)
  22. }
  23. hints: posix.addrinfo
  24. hints.ai_socktype = .DGRAM
  25. hints.ai_flags = { .PASSIVE }
  26. result: ^posix.addrinfo
  27. s := posix.getaddrinfo(nil, args[1], &hints, &result)
  28. if s != .NONE {
  29. fmt.eprintfln("getaddrinfo: %s", posix.gai_strerror(s))
  30. posix.exit(1)
  31. }
  32. defer posix.freeaddrinfo(result)
  33. // Try each address until a successful bind().
  34. rp: ^posix.addrinfo
  35. for rp = result; rp != nil; rp = rp.ai_next {
  36. sfd := posix.socket(rp.ai_family, rp.ai_socktype, rp.ai_protocol)
  37. if sfd == -1 {
  38. continue
  39. }
  40. if posix.bind(sfd, rp.ai_addr, rp.ai_addrlen) == 0 {
  41. // Success.
  42. break
  43. }
  44. posix.close(sfd)
  45. }
  46. if rp == nil {
  47. fmt.eprintln("Could not bind")
  48. posix.exit(1)
  49. }
  50. // Use the socket...
  51. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/getaddrinfo.html ]]
  52. */
  53. getaddrinfo :: proc(
  54. nodename: cstring,
  55. servname: cstring,
  56. hints: ^addrinfo,
  57. res: ^^addrinfo,
  58. ) -> Info_Errno ---
  59. /*
  60. Frees the given address info linked list.
  61. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/getaddrinfo.html ]]
  62. */
  63. freeaddrinfo :: proc(ai: ^addrinfo) ---
  64. /*
  65. Translate a socket address to a node name and service location.
  66. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/getnameinfo.html ]]
  67. */
  68. getnameinfo :: proc(
  69. sa: ^sockaddr, salen: socklen_t,
  70. node: [^]byte, nodelen: socklen_t,
  71. service: [^]byte, servicelen: socklen_t,
  72. flags: Nameinfo_Flags,
  73. ) -> Info_Errno ---
  74. /*
  75. Get a textual description for the address info errors.
  76. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/gai_strerror.html ]]
  77. */
  78. gai_strerror :: proc(ecode: Info_Errno) -> cstring ---
  79. /*
  80. Opens a connection to the database and set the next entry to the first entry in the database.
  81. This reads /etc/hosts on most systems.
  82. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/sethostent.html ]]
  83. */
  84. sethostent :: proc(stayopen: b32) ---
  85. /*
  86. Reads the next entry in the database, opening and closing a connection as necessary.
  87. This reads /etc/hosts on most systems.
  88. Example:
  89. posix.sethostent(true)
  90. defer posix.endhostent()
  91. for ent := posix.gethostent(); ent != nil; ent = posix.gethostent() {
  92. fmt.println(ent)
  93. fmt.println(ent.h_addr_list[0][:ent.h_length])
  94. }
  95. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/sethostent.html ]]
  96. */
  97. gethostent :: proc() -> ^hostent ---
  98. /*
  99. Closes the connection to the database.
  100. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/sethostent.html ]]
  101. */
  102. endhostent :: proc() ---
  103. /*
  104. Opens and rewinds the database.
  105. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/setnetent.html ]]
  106. */
  107. setnetent :: proc(stayopen: b32) ---
  108. /*
  109. Reads the next entry of the database.
  110. Example:
  111. posix.setnetent(true)
  112. defer posix.endnetent()
  113. for ent := posix.getnetent(); ent != nil; ent = posix.getnetent() {
  114. fmt.println(ent)
  115. fmt.println(transmute([4]byte)ent.n_net)
  116. }
  117. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/setnetent.html ]]
  118. */
  119. getnetent :: proc() -> ^netent ---
  120. /*
  121. Search the database from the beginning, and find the first entry that matches.
  122. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/setnetent.html ]]
  123. */
  124. getnetbyaddr :: proc(net: c.uint32_t, type: AF) -> ^netent ---
  125. /*
  126. Search the database from the beginning, and find the first entry that matches.
  127. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/setnetent.html ]]
  128. */
  129. getnetbyname :: proc(name: cstring) -> ^netent ---
  130. /*
  131. Closes the database.
  132. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/setnetent.html ]]
  133. */
  134. endnetent :: proc() ---
  135. /*
  136. Opens and rewinds the database.
  137. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/setprotoent.html ]]
  138. */
  139. setprotoent :: proc(stayopen: b32) ---
  140. /*
  141. Reads the next entry of the database.
  142. Example:
  143. posix.setprotoent(true)
  144. defer posix.endprotoent()
  145. for ent := posix.getprotoent(); ent != nil; ent = posix.getprotoent() {
  146. fmt.println(ent)
  147. }
  148. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/setprotoent.html ]]
  149. */
  150. getprotoent :: proc() -> ^protoent ---
  151. /*
  152. Search the database from the beginning, and find the first entry that matches.
  153. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/setprotoent.html ]]
  154. */
  155. getprotobyname :: proc(name: cstring) -> ^protoent ---
  156. /*
  157. Search the database from the beginning, and find the first entry that matches.
  158. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/setprotoent.html ]]
  159. */
  160. getprotobynumber :: proc(proto: c.int) -> ^protoent ---
  161. /*
  162. Closes the database.
  163. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/setprotoent.html ]]
  164. */
  165. endprotoent :: proc() ---
  166. /*
  167. Opens and rewinds the database.
  168. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/setservent.html ]]
  169. */
  170. setservent :: proc(stayopen: b32) ---
  171. /*
  172. Reads the next entry of the database.
  173. Example:
  174. posix.setservent(true)
  175. defer posix.endservent()
  176. for ent := posix.getservent(); ent != nil; ent = posix.getservent() {
  177. fmt.println(ent)
  178. }
  179. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/setservent.html ]]
  180. */
  181. getservent :: proc() -> ^servent ---
  182. /*
  183. Search the database from the beginning, and find the first entry that matches.
  184. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/setservent.html ]]
  185. */
  186. getservbyname :: proc(name: cstring, proto: cstring) -> ^servent ---
  187. /*
  188. Search the database from the beginning, and find the first entry that matches.
  189. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/setservent.html ]]
  190. */
  191. getservbyport :: proc(port: c.int, proto: cstring) -> ^servent ---
  192. /*
  193. Closes the database.
  194. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/setservent.html ]]
  195. */
  196. endservent :: proc() ---
  197. }
  198. Addrinfo_Flag_Bits :: enum c.int {
  199. // Socket address is intended for bind().
  200. PASSIVE = log2(AI_PASSIVE),
  201. // Request for canonical name.
  202. CANONNAME = log2(AI_CANONNAME),
  203. // Return numeric host address as name.
  204. NUMERICHOST = log2(AI_NUMERICHOST),
  205. // Inhibit service name resolution.
  206. NUMERICSERV = log2(AI_NUMERICSERV),
  207. // If no IPv6 addresses are found, query for IPv4 addresses and return them to the
  208. // caller as IPv4-mapped IPv6 addresses.
  209. V4MAPPED = log2(AI_V4MAPPED),
  210. // Query for both IPv4 and IPv6 addresses.
  211. ALL = log2(AI_ALL),
  212. // Query for IPv4 addresses only when an IPv4 address is configured; query for IPv6 addresses
  213. // only when an IPv6 address is configured.
  214. ADDRCONFIG = log2(AI_ADDRCONFIG),
  215. }
  216. Addrinfo_Flags :: bit_set[Addrinfo_Flag_Bits; c.int]
  217. Nameinfo_Flag_Bits :: enum c.int {
  218. // Only the nodename portion of the FQDN is returned for local hosts.
  219. NOFQDN = log2(NI_NOFQDN),
  220. // The numeric form of the node's address is returned instead of its name.
  221. NUMERICHOST = log2(NI_NUMERICHOST),
  222. // Return an error if the node's name cannot be located in the database.
  223. NAMEREQD = log2(NI_NAMEREQD),
  224. // The numeric form of the service address is returned instead of its name.
  225. NUMERICSERV = log2(NI_NUMERICSERV),
  226. // For IPv6 addresses, the numeric form of the scope identifier is returned instead of its name.
  227. NUMERICSCOPE = log2(NI_NUMERICSCOPE),
  228. // Indicates that the service is a datagram service (SOCK_DGRAM).
  229. DGRAM = log2(NI_DGRAM),
  230. }
  231. Nameinfo_Flags :: bit_set[Nameinfo_Flag_Bits; c.int]
  232. Info_Errno :: enum c.int {
  233. NONE = 0,
  234. // The name could not be resolved at this time. Future attempts may succeed.
  235. AGAIN = EAI_AGAIN,
  236. // The flags had an invalid value.
  237. BADFLAGS = EAI_BADFLAGS,
  238. // A non-recoverable error ocurred.
  239. FAIL = EAI_FAIL,
  240. // The address family was not recognized or the address length was invald for the specified family.
  241. FAMILY = EAI_FAMILY,
  242. // There was a memory allocation failure.
  243. MEMORY = EAI_MEMORY,
  244. // The name does not resolve for the supplied parameters.
  245. NONAME = EAI_NONAME,
  246. // The service passed was not recognized for the specified socket.
  247. SERVICE = EAI_SERVICE,
  248. // The intended socket type was not recognized.
  249. SOCKTYPE = EAI_SOCKTYPE,
  250. // A system error occurred. The error code can be found in errno.
  251. SYSTEM = EAI_SYSTEM,
  252. // An argument buffer overflowed.
  253. OVERFLOW = EAI_OVERFLOW,
  254. }
  255. when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD {
  256. hostent :: struct {
  257. h_name: cstring, /* [PSX] official name of host */
  258. h_aliases: [^]cstring `fmt:"v,0"`, /* [PSX] alias list */
  259. h_addrtype: AF, /* [PSX] host address type */
  260. h_length: c.int, /* [PSX] length of address */
  261. h_addr_list: [^][^]byte `fmt:"v,0"`, /* [PSX] list of addresses from name server */
  262. }
  263. netent :: struct {
  264. n_name: cstring, /* [PSX] official name of net */
  265. n_aliases: [^]cstring `fmt:"v,0"`, /* [PSX] alias list */
  266. n_addrtype: AF, /* [PSX] net address type */
  267. n_net: c.uint32_t, /* [PSX] network # */
  268. }
  269. protoent :: struct {
  270. p_name: cstring, /* [PSX] official protocol name */
  271. p_aliases: [^]cstring `fmt:"v,0"`, /* [PSX] alias list */
  272. p_proto: c.int, /* [PSX] protocol # */
  273. }
  274. servent :: struct {
  275. s_name: cstring, /* [PSX] official service name */
  276. s_aliases: [^]cstring `fmt:"v,0"`, /* [PSX] alias list */
  277. s_port: c.int, /* [PSX] port # */
  278. s_proto: cstring, /* [PSX] protocol # */
  279. }
  280. // The highest reserved port number.
  281. IPPORT_RESERVED :: 1024
  282. addrinfo :: struct {
  283. ai_flags: Addrinfo_Flags, /* [PSX] input flags */
  284. ai_family: AF, /* [PSX] address family of socket */
  285. ai_socktype: Sock, /* [PSX] socket type */
  286. ai_protocol: Protocol, /* [PSX] protocol of socket */
  287. ai_addrlen: socklen_t, /* [PSX] length of socket address */
  288. ai_canonname: cstring, /* [PSX] canonical name of service location */
  289. ai_addr: ^sockaddr, /* [PSX] binary address */
  290. ai_next: ^addrinfo, /* [PSX] pointer to next in list */
  291. }
  292. when ODIN_OS == .Darwin {
  293. AI_PASSIVE :: 0x00000001
  294. AI_CANONNAME :: 0x00000002
  295. AI_NUMERICHOST :: 0x00000004
  296. AI_NUMERICSERV :: 0x00001000
  297. AI_V4MAPPED :: 0x00000800
  298. AI_ALL :: 0x00000100
  299. AI_ADDRCONFIG :: 0x00000400
  300. NI_NOFQDN :: 0x00000001
  301. NI_NUMERICHOST :: 0x00000002
  302. NI_NAMEREQD :: 0x00000004
  303. NI_NUMERICSERV :: 0x00000008
  304. NI_NUMERICSCOPE :: 0x00000100
  305. NI_DGRAM :: 0x00000010
  306. } else when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD {
  307. AI_PASSIVE :: 0x00000001
  308. AI_CANONNAME :: 0x00000002
  309. AI_NUMERICHOST :: 0x00000004
  310. AI_NUMERICSERV :: 0x00000008
  311. AI_V4MAPPED :: 0x00000800 // NOTE: not implemented on netbsd
  312. AI_ALL :: 0x00000100 // NOTE: not implemented on netbsd
  313. AI_ADDRCONFIG :: 0x00000400
  314. NI_NOFQDN :: 0x00000001
  315. NI_NUMERICHOST :: 0x00000002
  316. NI_NAMEREQD :: 0x00000004
  317. NI_NUMERICSERV :: 0x00000008
  318. NI_NUMERICSCOPE :: 0x00000010
  319. NI_DGRAM :: 0x00000020
  320. } else when ODIN_OS == .OpenBSD {
  321. AI_PASSIVE :: 1
  322. AI_CANONNAME :: 2
  323. AI_NUMERICHOST :: 4
  324. AI_NUMERICSERV :: 16
  325. AI_V4MAPPED :: 0x00000800 // NOTE: not implemented
  326. AI_ALL :: 0x00000100 // NOTE: not implemented
  327. AI_ADDRCONFIG :: 64
  328. NI_NOFQDN :: 4
  329. NI_NUMERICHOST :: 1
  330. NI_NAMEREQD :: 8
  331. NI_NUMERICSERV :: 2
  332. NI_NUMERICSCOPE :: 32
  333. NI_DGRAM :: 16
  334. }
  335. when ODIN_OS == .OpenBSD {
  336. EAI_AGAIN :: -3
  337. EAI_BADFLAGS :: -1
  338. EAI_FAIL :: -4
  339. EAI_FAMILY :: -6
  340. EAI_MEMORY :: -10
  341. EAI_NONAME :: -2
  342. EAI_SERVICE :: -8
  343. EAI_SOCKTYPE :: -7
  344. EAI_SYSTEM :: -11
  345. EAI_OVERFLOW :: -14
  346. } else {
  347. EAI_AGAIN :: 2
  348. EAI_BADFLAGS :: 3
  349. EAI_FAIL :: 4
  350. EAI_FAMILY :: 5
  351. EAI_MEMORY :: 6
  352. EAI_NONAME :: 8
  353. EAI_SERVICE :: 9
  354. EAI_SOCKTYPE :: 10
  355. EAI_SYSTEM :: 11
  356. EAI_OVERFLOW :: 14
  357. }
  358. }else {
  359. #panic("posix is unimplemented for the current target")
  360. }