/contrib/ntp/libntp/ntp_rfc2553.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 443 lines · 295 code · 36 blank · 112 comment · 85 complexity · b7af2861534e8e231a4f4eea8acc2c86 MD5 · raw file

  1. /*
  2. * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the project nor the names of its contributors
  14. * may be used to endorse or promote products derived from this software
  15. * without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
  21. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. */
  29. /*
  30. * Copyright (c) 1982, 1986, 1990, 1993
  31. * The Regents of the University of California. All rights reserved.
  32. *
  33. * Redistribution and use in source and binary forms, with or without
  34. * modification, are permitted provided that the following conditions
  35. * are met:
  36. * 1. Redistributions of source code must retain the above copyright
  37. * notice, this list of conditions and the following disclaimer.
  38. * 2. Redistributions in binary form must reproduce the above copyright
  39. * notice, this list of conditions and the following disclaimer in the
  40. * documentation and/or other materials provided with the distribution.
  41. * 3. All advertising materials mentioning features or use of this software
  42. * must display the following acknowledgement:
  43. * This product includes software developed by the University of
  44. * California, Berkeley and its contributors.
  45. * 4. Neither the name of the University nor the names of its contributors
  46. * may be used to endorse or promote products derived from this software
  47. * without specific prior written permission.
  48. *
  49. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  50. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  51. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  52. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  53. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  54. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  55. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  56. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  57. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  58. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  59. * SUCH DAMAGE.
  60. *
  61. */
  62. /*
  63. * Compatability shims with the rfc2553 API to simplify ntp.
  64. */
  65. #include <config.h>
  66. #include <sys/types.h>
  67. #include <ctype.h>
  68. #include <sys/socket.h>
  69. #include <isc/net.h>
  70. #ifdef HAVE_NETINET_IN_H
  71. #include <netinet/in.h>
  72. #endif
  73. #include "ntp_rfc2553.h"
  74. #include "ntpd.h"
  75. #include "ntp_malloc.h"
  76. #include "ntp_stdlib.h"
  77. #include "ntp_string.h"
  78. #ifndef ISC_PLATFORM_HAVEIPV6
  79. static char *ai_errlist[] = {
  80. "Success",
  81. "Address family for hostname not supported", /* EAI_ADDRFAMILY */
  82. "Temporary failure in name resolution", /* EAI_AGAIN */
  83. "Invalid value for ai_flags", /* EAI_BADFLAGS */
  84. "Non-recoverable failure in name resolution", /* EAI_FAIL */
  85. "ai_family not supported", /* EAI_FAMILY */
  86. "Memory allocation failure", /* EAI_MEMORY */
  87. "No address associated with hostname", /* EAI_NODATA */
  88. "hostname nor servname provided, or not known", /* EAI_NONAME */
  89. "servname not supported for ai_socktype", /* EAI_SERVICE */
  90. "ai_socktype not supported", /* EAI_SOCKTYPE */
  91. "System error returned in errno", /* EAI_SYSTEM */
  92. "Invalid value for hints", /* EAI_BADHINTS */
  93. "Resolved protocol is unknown", /* EAI_PROTOCOL */
  94. "Unknown error", /* EAI_MAX */
  95. };
  96. /*
  97. * Local declaration
  98. */
  99. int
  100. DNSlookup_name(
  101. const char *name,
  102. int ai_family,
  103. struct hostent **Addresses
  104. );
  105. #ifndef SYS_WINNT
  106. /*
  107. * Encapsulate gethostbyname to control the error code
  108. */
  109. int
  110. DNSlookup_name(
  111. const char *name,
  112. int ai_family,
  113. struct hostent **Addresses
  114. )
  115. {
  116. *Addresses = gethostbyname(name);
  117. return (h_errno);
  118. }
  119. #endif
  120. static int do_nodename P((const char *nodename, struct addrinfo *ai,
  121. const struct addrinfo *hints));
  122. int
  123. getaddrinfo (const char *nodename, const char *servname,
  124. const struct addrinfo *hints, struct addrinfo **res)
  125. {
  126. int rval;
  127. struct servent *sp;
  128. struct addrinfo *ai = NULL;
  129. int port;
  130. const char *proto = NULL;
  131. int family, socktype, flags, protocol;
  132. /*
  133. * If no name is provide just return an error
  134. */
  135. if (nodename == NULL && servname == NULL)
  136. return (EAI_NONAME);
  137. ai = calloc(sizeof(struct addrinfo), 1);
  138. if (ai == NULL)
  139. return (EAI_MEMORY);
  140. /*
  141. * Copy default values from hints, if available
  142. */
  143. if (hints != NULL) {
  144. ai->ai_flags = hints->ai_flags;
  145. ai->ai_family = hints->ai_family;
  146. ai->ai_socktype = hints->ai_socktype;
  147. ai->ai_protocol = hints->ai_protocol;
  148. family = hints->ai_family;
  149. socktype = hints->ai_socktype;
  150. protocol = hints->ai_protocol;
  151. flags = hints->ai_flags;
  152. switch (family) {
  153. case AF_UNSPEC:
  154. switch (hints->ai_socktype) {
  155. case SOCK_STREAM:
  156. proto = "tcp";
  157. break;
  158. case SOCK_DGRAM:
  159. proto = "udp";
  160. break;
  161. }
  162. break;
  163. case AF_INET:
  164. case AF_INET6:
  165. switch (hints->ai_socktype) {
  166. case 0:
  167. break;
  168. case SOCK_STREAM:
  169. proto = "tcp";
  170. break;
  171. case SOCK_DGRAM:
  172. proto = "udp";
  173. break;
  174. case SOCK_RAW:
  175. break;
  176. default:
  177. return (EAI_SOCKTYPE);
  178. }
  179. break;
  180. #ifdef AF_LOCAL
  181. case AF_LOCAL:
  182. switch (hints->ai_socktype) {
  183. case 0:
  184. break;
  185. case SOCK_STREAM:
  186. break;
  187. case SOCK_DGRAM:
  188. break;
  189. default:
  190. return (EAI_SOCKTYPE);
  191. }
  192. break;
  193. #endif
  194. default:
  195. return (EAI_FAMILY);
  196. }
  197. } else {
  198. protocol = 0;
  199. family = 0;
  200. socktype = 0;
  201. flags = 0;
  202. }
  203. rval = do_nodename(nodename, ai, hints);
  204. if (rval != 0) {
  205. freeaddrinfo(ai);
  206. return (rval);
  207. }
  208. /*
  209. * First, look up the service name (port) if it was
  210. * requested. If the socket type wasn't specified, then
  211. * try and figure it out.
  212. */
  213. if (servname != NULL) {
  214. char *e;
  215. port = strtol(servname, &e, 10);
  216. if (*e == '\0') {
  217. if (socktype == 0)
  218. return (EAI_SOCKTYPE);
  219. if (port < 0 || port > 65535)
  220. return (EAI_SERVICE);
  221. port = htons((unsigned short) port);
  222. } else {
  223. sp = getservbyname(servname, proto);
  224. if (sp == NULL)
  225. return (EAI_SERVICE);
  226. port = sp->s_port;
  227. if (socktype == 0) {
  228. if (strcmp(sp->s_proto, "tcp") == 0)
  229. socktype = SOCK_STREAM;
  230. else if (strcmp(sp->s_proto, "udp") == 0)
  231. socktype = SOCK_DGRAM;
  232. }
  233. }
  234. } else
  235. port = 0;
  236. /*
  237. *
  238. * Set up the port number
  239. */
  240. if (ai->ai_family == AF_INET)
  241. ((struct sockaddr_in *)ai->ai_addr)->sin_port = (unsigned short) port;
  242. else if (ai->ai_family == AF_INET6)
  243. ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = (unsigned short) port;
  244. *res = ai;
  245. return (0);
  246. }
  247. void
  248. freeaddrinfo(struct addrinfo *ai)
  249. {
  250. if (ai->ai_canonname != NULL)
  251. {
  252. free(ai->ai_canonname);
  253. ai->ai_canonname = NULL;
  254. }
  255. if (ai->ai_addr != NULL)
  256. {
  257. free(ai->ai_addr);
  258. ai->ai_addr = NULL;
  259. }
  260. free(ai);
  261. ai = NULL;
  262. }
  263. int
  264. getnameinfo (const struct sockaddr *sa, u_int salen, char *host,
  265. size_t hostlen, char *serv, size_t servlen, int flags)
  266. {
  267. struct hostent *hp;
  268. int namelen;
  269. if (sa->sa_family != AF_INET)
  270. return (EAI_FAMILY);
  271. hp = gethostbyaddr(
  272. (const char *)&((const struct sockaddr_in *)sa)->sin_addr,
  273. 4, AF_INET);
  274. if (hp == NULL) {
  275. if (h_errno == TRY_AGAIN)
  276. return (EAI_AGAIN);
  277. else
  278. return (EAI_FAIL);
  279. }
  280. if (host != NULL && hostlen > 0) {
  281. /*
  282. * Don't exceed buffer
  283. */
  284. namelen = min(strlen(hp->h_name), hostlen - 1);
  285. if (namelen > 0) {
  286. strncpy(host, hp->h_name, namelen);
  287. host[namelen] = '\0';
  288. }
  289. }
  290. return (0);
  291. }
  292. char *
  293. gai_strerror(int ecode)
  294. {
  295. if (ecode < 0 || ecode > EAI_MAX)
  296. ecode = EAI_MAX;
  297. return ai_errlist[ecode];
  298. }
  299. static int
  300. do_nodename(
  301. const char *nodename,
  302. struct addrinfo *ai,
  303. const struct addrinfo *hints)
  304. {
  305. struct hostent *hp = NULL;
  306. struct sockaddr_in *sockin;
  307. struct sockaddr_in6 *sockin6;
  308. int errval;
  309. ai->ai_addr = calloc(sizeof(struct sockaddr_storage), 1);
  310. if (ai->ai_addr == NULL)
  311. return (EAI_MEMORY);
  312. /*
  313. * For an empty node name just use the wildcard.
  314. * NOTE: We need to assume that the address family is
  315. * set elsewhere so that we can set the appropriate wildcard
  316. */
  317. if (nodename == NULL) {
  318. ai->ai_addrlen = sizeof(struct sockaddr_storage);
  319. if (ai->ai_family == AF_INET)
  320. {
  321. sockin = (struct sockaddr_in *)ai->ai_addr;
  322. sockin->sin_family = (short) ai->ai_family;
  323. sockin->sin_addr.s_addr = htonl(INADDR_ANY);
  324. }
  325. else
  326. {
  327. sockin6 = (struct sockaddr_in6 *)ai->ai_addr;
  328. sockin6->sin6_family = (short) ai->ai_family;
  329. /*
  330. * we have already zeroed out the address
  331. * so we don't actually need to do this
  332. * This assignment is causing problems so
  333. * we don't do what this would do.
  334. sockin6->sin6_addr = in6addr_any;
  335. */
  336. }
  337. #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
  338. ai->ai_addr->sa_len = SOCKLEN(ai->ai_addr);
  339. #endif
  340. return (0);
  341. }
  342. /*
  343. * See if we have an IPv6 address
  344. */
  345. if(strchr(nodename, ':') != NULL) {
  346. if (inet_pton(AF_INET6, nodename,
  347. &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr) == 1) {
  348. ((struct sockaddr_in6 *)ai->ai_addr)->sin6_family = AF_INET6;
  349. ai->ai_family = AF_INET6;
  350. ai->ai_addrlen = sizeof(struct sockaddr_in6);
  351. return (0);
  352. }
  353. }
  354. /*
  355. * See if we have an IPv4 address
  356. */
  357. if (inet_pton(AF_INET, nodename,
  358. &((struct sockaddr_in *)ai->ai_addr)->sin_addr) == 1) {
  359. ((struct sockaddr *)ai->ai_addr)->sa_family = AF_INET;
  360. ai->ai_family = AF_INET;
  361. ai->ai_addrlen = sizeof(struct sockaddr_in);
  362. return (0);
  363. }
  364. /*
  365. * If the numeric host flag is set, don't attempt resolution
  366. */
  367. if (hints != NULL && (hints->ai_flags & AI_NUMERICHOST))
  368. return (EAI_NONAME);
  369. /*
  370. * Look for a name
  371. */
  372. errval = DNSlookup_name(nodename, AF_INET, &hp);
  373. if (hp == NULL) {
  374. if (errval == TRY_AGAIN || errval == EAI_AGAIN)
  375. return (EAI_AGAIN);
  376. else if (errval == EAI_NONAME) {
  377. if (inet_pton(AF_INET, nodename,
  378. &((struct sockaddr_in *)ai->ai_addr)->sin_addr) == 1) {
  379. ((struct sockaddr *)ai->ai_addr)->sa_family = AF_INET;
  380. ai->ai_family = AF_INET;
  381. ai->ai_addrlen = sizeof(struct sockaddr_in);
  382. return (0);
  383. }
  384. return (errval);
  385. }
  386. else
  387. {
  388. return (errval);
  389. }
  390. }
  391. ai->ai_family = hp->h_addrtype;
  392. ai->ai_addrlen = sizeof(struct sockaddr);
  393. sockin = (struct sockaddr_in *)ai->ai_addr;
  394. memcpy(&sockin->sin_addr, hp->h_addr, hp->h_length);
  395. ai->ai_addr->sa_family = hp->h_addrtype;
  396. #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
  397. ai->ai_addr->sa_len = sizeof(struct sockaddr);
  398. #endif
  399. if (hints != NULL && hints->ai_flags & AI_CANONNAME) {
  400. ai->ai_canonname = malloc(strlen(hp->h_name) + 1);
  401. if (ai->ai_canonname == NULL)
  402. return (EAI_MEMORY);
  403. strcpy(ai->ai_canonname, hp->h_name);
  404. }
  405. return (0);
  406. }
  407. #endif /* !ISC_PLATFORM_HAVEIPV6 */