PageRenderTime 49ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/libc/net/getprotoent.c

https://bitbucket.org/cooljeanius/dragonflybsd
C | 549 lines | 429 code | 80 blank | 40 comment | 80 complexity | 9a7aa833a5824b3ba6cb6ec04ab2e75e MD5 | raw file
  1. /*
  2. * Copyright (c) 1983, 1993
  3. * The Regents of the University of California. 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 University 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 REGENTS 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 REGENTS 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. * @(#)getprotoent.c 8.1 (Berkeley) 6/4/93
  30. * $FreeBSD: src/lib/libc/net/getprotoent.c,v 1.9 2007/01/09 00:28:02 imp Exp $
  31. * $DragonFly: src/lib/libc/net/getprotoent.c,v 1.5 2005/11/13 02:04:47 swildner Exp $
  32. */
  33. #include <sys/param.h>
  34. #include <sys/types.h>
  35. #include <sys/socket.h>
  36. #include <errno.h>
  37. #include <limits.h>
  38. #include <netdb.h>
  39. #include <nsswitch.h>
  40. #include <stdio.h>
  41. #include <stdlib.h>
  42. #include <string.h>
  43. #include "namespace.h"
  44. #include "reentrant.h"
  45. #include "un-namespace.h"
  46. #include "netdb_private.h"
  47. #ifdef NS_CACHING
  48. #include "nscache.h"
  49. #endif
  50. #include "nss_tls.h"
  51. static const ns_src defaultsrc[] = {
  52. { NSSRC_FILES, NS_SUCCESS },
  53. { NULL, 0 }
  54. };
  55. NETDB_THREAD_ALLOC(protoent_data)
  56. NETDB_THREAD_ALLOC(protodata)
  57. static void
  58. protoent_data_clear(struct protoent_data *ped)
  59. {
  60. if (ped->fp) {
  61. fclose(ped->fp);
  62. ped->fp = NULL;
  63. }
  64. }
  65. static void
  66. protoent_data_free(void *ptr)
  67. {
  68. struct protoent_data *ped = ptr;
  69. protoent_data_clear(ped);
  70. free(ped);
  71. }
  72. static void
  73. protodata_free(void *ptr)
  74. {
  75. free(ptr);
  76. }
  77. #ifdef NS_CACHING
  78. int
  79. __proto_id_func(char *buffer, size_t *buffer_size, va_list ap,
  80. void *cache_mdata)
  81. {
  82. char *name;
  83. int proto;
  84. size_t desired_size, size;
  85. enum nss_lookup_type lookup_type;
  86. int res = NS_UNAVAIL;
  87. lookup_type = (enum nss_lookup_type)cache_mdata;
  88. switch (lookup_type) {
  89. case nss_lt_name:
  90. name = va_arg(ap, char *);
  91. size = strlen(name);
  92. desired_size = sizeof(enum nss_lookup_type) + size + 1;
  93. if (desired_size > *buffer_size) {
  94. res = NS_RETURN;
  95. goto fin;
  96. }
  97. memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
  98. memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1);
  99. res = NS_SUCCESS;
  100. break;
  101. case nss_lt_id:
  102. proto = va_arg(ap, int);
  103. desired_size = sizeof(enum nss_lookup_type) + sizeof(int);
  104. if (desired_size > *buffer_size) {
  105. res = NS_RETURN;
  106. goto fin;
  107. }
  108. memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
  109. memcpy(buffer + sizeof(enum nss_lookup_type), &proto,
  110. sizeof(int));
  111. res = NS_SUCCESS;
  112. break;
  113. default:
  114. /* should be unreachable */
  115. return (NS_UNAVAIL);
  116. }
  117. fin:
  118. *buffer_size = desired_size;
  119. return (res);
  120. }
  121. int
  122. __proto_marshal_func(char *buffer, size_t *buffer_size, void *retval,
  123. va_list ap, void *cache_mdata)
  124. {
  125. char *name;
  126. int num;
  127. struct protoent *proto;
  128. char *orig_buf;
  129. size_t orig_buf_size;
  130. struct protoent new_proto;
  131. size_t desired_size, size, aliases_size;
  132. char *p;
  133. char **alias;
  134. switch ((enum nss_lookup_type)cache_mdata) {
  135. case nss_lt_name:
  136. name = va_arg(ap, char *);
  137. break;
  138. case nss_lt_id:
  139. num = va_arg(ap, int);
  140. break;
  141. case nss_lt_all:
  142. break;
  143. default:
  144. /* should be unreachable */
  145. return (NS_UNAVAIL);
  146. }
  147. proto = va_arg(ap, struct protoent *);
  148. orig_buf = va_arg(ap, char *);
  149. orig_buf_size = va_arg(ap, size_t);
  150. desired_size = _ALIGNBYTES + sizeof(struct protoent) + sizeof(char *);
  151. if (proto->p_name != NULL)
  152. desired_size += strlen(proto->p_name) + 1;
  153. if (proto->p_aliases != NULL) {
  154. aliases_size = 0;
  155. for (alias = proto->p_aliases; *alias; ++alias) {
  156. desired_size += strlen(*alias) + 1;
  157. ++aliases_size;
  158. }
  159. desired_size += _ALIGNBYTES + (aliases_size + 1) *
  160. sizeof(char *);
  161. }
  162. if (*buffer_size < desired_size) {
  163. /* this assignment is here for future use */
  164. *buffer_size = desired_size;
  165. return (NS_RETURN);
  166. }
  167. memcpy(&new_proto, proto, sizeof(struct protoent));
  168. *buffer_size = desired_size;
  169. memset(buffer, 0, desired_size);
  170. p = buffer + sizeof(struct protoent) + sizeof(char *);
  171. memcpy(buffer + sizeof(struct protoent), &p, sizeof(char *));
  172. p = (char *)_ALIGN(p);
  173. if (new_proto.p_name != NULL) {
  174. size = strlen(new_proto.p_name);
  175. memcpy(p, new_proto.p_name, size);
  176. new_proto.p_name = p;
  177. p += size + 1;
  178. }
  179. if (new_proto.p_aliases != NULL) {
  180. p = (char *)_ALIGN(p);
  181. memcpy(p, new_proto.p_aliases, sizeof(char *) * aliases_size);
  182. new_proto.p_aliases = (char **)p;
  183. p += sizeof(char *) * (aliases_size + 1);
  184. for (alias = new_proto.p_aliases; *alias; ++alias) {
  185. size = strlen(*alias);
  186. memcpy(p, *alias, size);
  187. *alias = p;
  188. p += size + 1;
  189. }
  190. }
  191. memcpy(buffer, &new_proto, sizeof(struct protoent));
  192. return (NS_SUCCESS);
  193. }
  194. int
  195. __proto_unmarshal_func(char *buffer, size_t buffer_size, void *retval,
  196. va_list ap, void *cache_mdata)
  197. {
  198. char *name;
  199. int num;
  200. struct protoent *proto;
  201. char *orig_buf;
  202. size_t orig_buf_size;
  203. int *ret_errno;
  204. char *p;
  205. char **alias;
  206. switch ((enum nss_lookup_type)cache_mdata) {
  207. case nss_lt_name:
  208. name = va_arg(ap, char *);
  209. break;
  210. case nss_lt_id:
  211. num = va_arg(ap, int);
  212. break;
  213. case nss_lt_all:
  214. break;
  215. default:
  216. /* should be unreachable */
  217. return (NS_UNAVAIL);
  218. }
  219. proto = va_arg(ap, struct protoent *);
  220. orig_buf = va_arg(ap, char *);
  221. orig_buf_size = va_arg(ap, size_t);
  222. ret_errno = va_arg(ap, int *);
  223. if (orig_buf_size <
  224. buffer_size - sizeof(struct protoent) - sizeof(char *)) {
  225. *ret_errno = ERANGE;
  226. return (NS_RETURN);
  227. }
  228. memcpy(proto, buffer, sizeof(struct protoent));
  229. memcpy(&p, buffer + sizeof(struct protoent), sizeof(char *));
  230. orig_buf = (char *)_ALIGN(orig_buf);
  231. memcpy(orig_buf, buffer + sizeof(struct protoent) + sizeof(char *) +
  232. _ALIGN(p) - (size_t)p,
  233. buffer_size - sizeof(struct protoent) - sizeof(char *) -
  234. _ALIGN(p) + (size_t)p);
  235. p = (char *)_ALIGN(p);
  236. NS_APPLY_OFFSET(proto->p_name, orig_buf, p, char *);
  237. if (proto->p_aliases != NULL) {
  238. NS_APPLY_OFFSET(proto->p_aliases, orig_buf, p, char **);
  239. for (alias = proto->p_aliases; *alias; ++alias)
  240. NS_APPLY_OFFSET(*alias, orig_buf, p, char *);
  241. }
  242. if (retval != NULL)
  243. *((struct protoent **)retval) = proto;
  244. return (NS_SUCCESS);
  245. }
  246. NSS_MP_CACHE_HANDLING(protocols);
  247. #endif /* NS_CACHING */
  248. int
  249. __copy_protoent(struct protoent *pe, struct protoent *pptr, char *buf,
  250. size_t buflen)
  251. {
  252. char *cp;
  253. int i, n;
  254. int numptr, len;
  255. /* Find out the amount of space required to store the answer. */
  256. numptr = 1; /* NULL ptr */
  257. len = (char *)ALIGN(buf) - buf;
  258. for (i = 0; pe->p_aliases[i]; i++, numptr++) {
  259. len += strlen(pe->p_aliases[i]) + 1;
  260. }
  261. len += strlen(pe->p_name) + 1;
  262. len += numptr * sizeof(char*);
  263. if (len > (int)buflen) {
  264. errno = ERANGE;
  265. return (-1);
  266. }
  267. /* copy protocol value*/
  268. pptr->p_proto = pe->p_proto;
  269. cp = (char *)ALIGN(buf) + numptr * sizeof(char *);
  270. /* copy official name */
  271. n = strlen(pe->p_name) + 1;
  272. strcpy(cp, pe->p_name);
  273. pptr->p_name = cp;
  274. cp += n;
  275. /* copy aliases */
  276. pptr->p_aliases = (char **)ALIGN(buf);
  277. for (i = 0 ; pe->p_aliases[i]; i++) {
  278. n = strlen(pe->p_aliases[i]) + 1;
  279. strcpy(cp, pe->p_aliases[i]);
  280. pptr->p_aliases[i] = cp;
  281. cp += n;
  282. }
  283. pptr->p_aliases[i] = NULL;
  284. return (0);
  285. }
  286. void
  287. __setprotoent_p(int f, struct protoent_data *ped)
  288. {
  289. if (ped->fp == NULL)
  290. ped->fp = fopen(_PATH_PROTOCOLS, "r");
  291. else
  292. rewind(ped->fp);
  293. ped->stayopen |= f;
  294. }
  295. void
  296. __endprotoent_p(struct protoent_data *ped)
  297. {
  298. if (ped->fp) {
  299. fclose(ped->fp);
  300. ped->fp = NULL;
  301. }
  302. ped->stayopen = 0;
  303. }
  304. int
  305. __getprotoent_p(struct protoent *pe, struct protoent_data *ped)
  306. {
  307. char *p;
  308. char *cp, **q, *endp;
  309. long l;
  310. if (ped->fp == NULL && (ped->fp = fopen(_PATH_PROTOCOLS, "r")) == NULL)
  311. return (-1);
  312. again:
  313. if ((p = fgets(ped->line, sizeof ped->line, ped->fp)) == NULL)
  314. return (-1);
  315. if (*p == '#')
  316. goto again;
  317. cp = strpbrk(p, "#\n");
  318. if (cp != NULL)
  319. *cp = '\0';
  320. pe->p_name = p;
  321. cp = strpbrk(p, " \t");
  322. if (cp == NULL)
  323. goto again;
  324. *cp++ = '\0';
  325. while (*cp == ' ' || *cp == '\t')
  326. cp++;
  327. p = strpbrk(cp, " \t");
  328. if (p != NULL)
  329. *p++ = '\0';
  330. l = strtol(cp, &endp, 10);
  331. if (endp == cp || *endp != '\0' || l < 0 || l > USHRT_MAX)
  332. goto again;
  333. pe->p_proto = l;
  334. q = pe->p_aliases = ped->aliases;
  335. if (p != NULL) {
  336. cp = p;
  337. while (cp && *cp) {
  338. if (*cp == ' ' || *cp == '\t') {
  339. cp++;
  340. continue;
  341. }
  342. if (q < &ped->aliases[_MAXALIASES - 1])
  343. *q++ = cp;
  344. cp = strpbrk(cp, " \t");
  345. if (cp != NULL)
  346. *cp++ = '\0';
  347. }
  348. }
  349. *q = NULL;
  350. return (0);
  351. }
  352. static int
  353. files_getprotoent_r(void *retval, void *mdata, va_list ap)
  354. {
  355. struct protoent pe;
  356. struct protoent_data *ped;
  357. struct protoent *pptr;
  358. char *buffer;
  359. size_t buflen;
  360. int *errnop;
  361. pptr = va_arg(ap, struct protoent *);
  362. buffer = va_arg(ap, char *);
  363. buflen = va_arg(ap, size_t);
  364. errnop = va_arg(ap, int *);
  365. if ((ped = __protoent_data_init()) == NULL)
  366. return (-1);
  367. if (__getprotoent_p(&pe, ped) != 0) {
  368. *errnop = errno;
  369. return (NS_NOTFOUND);
  370. }
  371. if (__copy_protoent(&pe, pptr, buffer, buflen) != 0) {
  372. *errnop = errno;
  373. return (NS_NOTFOUND);
  374. }
  375. *((struct protoent **)retval) = pptr;
  376. return (NS_SUCCESS);
  377. }
  378. static int
  379. files_setprotoent(void *retval, void *mdata, va_list ap)
  380. {
  381. struct protoent_data *ped;
  382. int f;
  383. f = va_arg(ap, int);
  384. if ((ped = __protoent_data_init()) == NULL)
  385. return (NS_UNAVAIL);
  386. __setprotoent_p(f, ped);
  387. return (NS_UNAVAIL);
  388. }
  389. static int
  390. files_endprotoent(void *retval, void *mdata, va_list ap)
  391. {
  392. struct protoent_data *ped;
  393. if ((ped = __protoent_data_init()) == NULL)
  394. return (NS_UNAVAIL);
  395. __endprotoent_p(ped);
  396. return (NS_UNAVAIL);
  397. }
  398. int
  399. getprotoent_r(struct protoent *pptr, char *buffer, size_t buflen,
  400. struct protoent **result)
  401. {
  402. #ifdef NS_CACHING
  403. static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
  404. protocols, (void *)nss_lt_all,
  405. __proto_marshal_func, __proto_unmarshal_func);
  406. #endif
  407. static const ns_dtab dtab[] = {
  408. { NSSRC_FILES, files_getprotoent_r, (void *)nss_lt_all },
  409. #ifdef NS_CACHING
  410. NS_CACHE_CB(&cache_info)
  411. #endif
  412. { NULL, NULL, NULL }
  413. };
  414. int rv, ret_errno;
  415. ret_errno = 0;
  416. *result = NULL;
  417. rv = nsdispatch(result, dtab, NSDB_PROTOCOLS, "getprotoent_r",
  418. defaultsrc, pptr, buffer, buflen, &ret_errno);
  419. if (rv == NS_SUCCESS)
  420. return (0);
  421. else
  422. return (ret_errno);
  423. }
  424. void
  425. setprotoent(int stayopen)
  426. {
  427. #ifdef NS_CACHING
  428. static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
  429. protocols, (void *)nss_lt_all,
  430. NULL, NULL);
  431. #endif
  432. static const ns_dtab dtab[] = {
  433. { NSSRC_FILES, files_setprotoent, NULL },
  434. #ifdef NS_CACHING
  435. NS_CACHE_CB(&cache_info)
  436. #endif
  437. { NULL, NULL, NULL }
  438. };
  439. nsdispatch(NULL, dtab, NSDB_PROTOCOLS, "setprotoent", defaultsrc,
  440. stayopen);
  441. }
  442. void
  443. endprotoent(void)
  444. {
  445. #ifdef NS_CACHING
  446. static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
  447. protocols, (void *)nss_lt_all,
  448. NULL, NULL);
  449. #endif
  450. static const ns_dtab dtab[] = {
  451. { NSSRC_FILES, files_endprotoent, NULL },
  452. #ifdef NS_CACHING
  453. NS_CACHE_CB(&cache_info)
  454. #endif
  455. { NULL, NULL, NULL }
  456. };
  457. nsdispatch(NULL, dtab, NSDB_PROTOCOLS, "endprotoent", defaultsrc);
  458. }
  459. struct protoent *
  460. getprotoent(void)
  461. {
  462. struct protodata *pd;
  463. struct protoent *rval;
  464. if ((pd = __protodata_init()) == NULL)
  465. return (NULL);
  466. if (getprotoent_r(&pd->proto, pd->data, sizeof(pd->data), &rval) != 0)
  467. return (NULL);
  468. return (rval);
  469. }