netdb.odin 13 KB

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