getservent.c (157779) | getservent.c (158115) |
---|---|
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 --- 21 unchanged lines hidden (view full) --- 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#if defined(LIBC_SCCS) && !defined(lint) 35static char sccsid[] = "@(#)getservent.c 8.1 (Berkeley) 6/4/93"; 36#endif /* LIBC_SCCS and not lint */ 37#include <sys/cdefs.h> | 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 --- 21 unchanged lines hidden (view full) --- 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#if defined(LIBC_SCCS) && !defined(lint) 35static char sccsid[] = "@(#)getservent.c 8.1 (Berkeley) 6/4/93"; 36#endif /* LIBC_SCCS and not lint */ 37#include <sys/cdefs.h> |
38__FBSDID("$FreeBSD: head/lib/libc/net/getservent.c 157779 2006-04-15 16:20:27Z ume $"); | 38__FBSDID("$FreeBSD: head/lib/libc/net/getservent.c 158115 2006-04-28 12:03:38Z ume $"); |
39 40#include <sys/param.h> 41#include <sys/types.h> 42#include <sys/socket.h> 43#include <arpa/inet.h> 44#include <errno.h> 45#include <limits.h> 46#include <netdb.h> | 39 40#include <sys/param.h> 41#include <sys/types.h> 42#include <sys/socket.h> 43#include <arpa/inet.h> 44#include <errno.h> 45#include <limits.h> 46#include <netdb.h> |
47#include <nsswitch.h> |
|
47#include <stdio.h> 48#include <string.h> 49#include <stdlib.h> | 48#include <stdio.h> 49#include <string.h> 50#include <stdlib.h> |
51#include <unistd.h> |
|
50#ifdef YP 51#include <rpc/rpc.h> 52#include <rpcsvc/yp_prot.h> 53#include <rpcsvc/ypclnt.h> 54#endif 55#include "namespace.h" 56#include "reentrant.h" 57#include "un-namespace.h" 58#include "netdb_private.h" | 52#ifdef YP 53#include <rpc/rpc.h> 54#include <rpcsvc/yp_prot.h> 55#include <rpcsvc/ypclnt.h> 56#endif 57#include "namespace.h" 58#include "reentrant.h" 59#include "un-namespace.h" 60#include "netdb_private.h" |
61#ifdef NS_CACHING 62#include "nscache.h" 63#endif 64#include "nss_tls.h" |
|
59 | 65 |
60NETDB_THREAD_ALLOC(servent_data) 61NETDB_THREAD_ALLOC(servdata) | 66enum constants 67{ 68 SETSERVENT = 1, 69 ENDSERVENT = 2, 70 SERVENT_STORAGE_INITIAL = 1 << 10, /* 1 KByte */ 71 SERVENT_STORAGE_MAX = 1 << 20, /* 1 MByte */ 72}; |
62 | 73 |
63static void 64servent_data_clear(struct servent_data *sed) | 74struct servent_mdata |
65{ | 75{ |
66 if (sed->fp) { 67 fclose(sed->fp); 68 sed->fp = NULL; 69 } | 76 enum nss_lookup_type how; 77 int compat_mode; 78}; 79 80static const ns_src defaultsrc[] = { 81 { NSSRC_COMPAT, NS_SUCCESS }, 82 { NULL, 0 } 83}; 84 85static int servent_unpack(char *, struct servent *, char **, size_t, int *); 86 87/* files backend declarations */ 88struct files_state 89{ 90 FILE *fp; 91 int stayopen; 92 93 int compat_mode_active; 94}; 95static void files_endstate(void *); 96NSS_TLS_HANDLING(files); 97 98static int files_servent(void *, void *, va_list); 99static int files_setservent(void *, void *, va_list); 100 |
70#ifdef YP | 101#ifdef YP |
71 free(sed->yp_key); 72 sed->yp_key = NULL; | 102/* nis backend declarations */ 103static int nis_servent(void *, void *, va_list); 104static int nis_setservent(void *, void *, va_list); 105 106struct nis_state 107{ 108 int yp_stepping; 109 char yp_domain[MAXHOSTNAMELEN]; 110 char *yp_key; 111 int yp_keylen; 112}; 113static void nis_endstate(void *); 114NSS_TLS_HANDLING(nis); 115 116static int nis_servent(void *, void *, va_list); 117static int nis_setservent(void *, void *, va_list); |
73#endif | 118#endif |
74} | |
75 | 119 |
76static void 77servent_data_free(void *ptr) | 120/* compat backend declarations */ 121static int compat_setservent(void *, void *, va_list); 122 123/* get** wrappers for get**_r functions declarations */ 124struct servent_state { 125 struct servent serv; 126 char *buffer; 127 size_t bufsize; 128}; 129static void servent_endstate(void *); 130NSS_TLS_HANDLING(servent); 131 132struct key { 133 const char *proto; 134 union { 135 const char *name; 136 int port; 137 }; 138}; 139 140static int wrap_getservbyname_r(struct key, struct servent *, char *, size_t, 141 struct servent **); 142static int wrap_getservbyport_r(struct key, struct servent *, char *, size_t, 143 struct servent **); 144static int wrap_getservent_r(struct key, struct servent *, char *, size_t, 145 struct servent **); 146static struct servent *getserv(int (*fn)(struct key, struct servent *, char *, 147 size_t, struct servent **), struct key); 148 149#ifdef NS_CACHING 150static int serv_id_func(char *, size_t *, va_list, void *); 151static int serv_marshal_func(char *, size_t *, void *, va_list, void *); 152static int serv_unmarshal_func(char *, size_t, void *, va_list, void *); 153#endif 154 155static int 156servent_unpack(char *p, struct servent *serv, char **aliases, 157 size_t aliases_size, int *errnop) |
78{ | 158{ |
79 struct servent_data *sed = ptr; | 159 char *cp, **q, *endp; 160 long l; |
80 | 161 |
81 servent_data_clear(sed); 82 free(sed); | 162 if (*p == '#') 163 return -1; 164 165 memset(serv, 0, sizeof(struct servent)); 166 167 cp = strpbrk(p, "#\n"); 168 if (cp != NULL) 169 *cp = '\0'; 170 serv->s_name = p; 171 172 p = strpbrk(p, " \t"); 173 if (p == NULL) 174 return -1; 175 *p++ = '\0'; 176 while (*p == ' ' || *p == '\t') 177 p++; 178 cp = strpbrk(p, ",/"); 179 if (cp == NULL) 180 return -1; 181 182 *cp++ = '\0'; 183 l = strtol(p, &endp, 10); 184 if (endp == p || *endp != '\0' || l < 0 || l > USHRT_MAX) 185 return -1; 186 serv->s_port = htons((in_port_t)l); 187 serv->s_proto = cp; 188 189 q = serv->s_aliases = aliases; 190 cp = strpbrk(cp, " \t"); 191 if (cp != NULL) 192 *cp++ = '\0'; 193 while (cp && *cp) { 194 if (*cp == ' ' || *cp == '\t') { 195 cp++; 196 continue; 197 } 198 if (q < &aliases[aliases_size - 1]) { 199 *q++ = cp; 200 } else { 201 *q = NULL; 202 *errnop = ERANGE; 203 return -1; 204 } 205 cp = strpbrk(cp, " \t"); 206 if (cp != NULL) 207 *cp++ = '\0'; 208 } 209 *q = NULL; 210 211 return 0; |
83} 84 | 212} 213 |
85static void 86servdata_free(void *ptr) | 214/* files backend implementation */ 215static void 216files_endstate(void *p) |
87{ | 217{ |
88 free(ptr); | 218 FILE * f; 219 220 if (p == NULL) 221 return; 222 223 f = ((struct files_state *)p)->fp; 224 if (f != NULL) 225 fclose(f); 226 227 free(p); |
89} 90 | 228} 229 |
91int 92__copy_servent(struct servent *se, struct servent *sptr, char *buf, 93 size_t buflen) | 230/* 231 * compat structures. compat and files sources functionalities are almost 232 * equal, so they all are managed by files_servent function 233 */ 234static int 235files_servent(void *retval, void *mdata, va_list ap) |
94{ | 236{ |
95 char *cp; 96 int i, n; 97 int numptr, len; | 237 static const ns_src compat_src[] = { 238#ifdef YP 239 { NSSRC_NIS, NS_SUCCESS }, 240#endif 241 { NULL, 0 } 242 }; 243 ns_dtab compat_dtab[] = { 244#ifdef YP 245 { NSSRC_NIS, nis_servent, 246 (void *)((struct servent_mdata *)mdata)->how }, 247#endif 248 { NULL, NULL, NULL } 249 }; |
98 | 250 |
99 /* Find out the amount of space required to store the answer. */ 100 numptr = 1; /* NULL ptr */ 101 len = (char *)ALIGN(buf) - buf; 102 for (i = 0; se->s_aliases[i]; i++, numptr++) { 103 len += strlen(se->s_aliases[i]) + 1; | 251 struct files_state *st; 252 int rv; 253 int stayopen; 254 255 struct servent_mdata *serv_mdata; 256 char *name; 257 char *proto; 258 int port; 259 260 struct servent *serv; 261 char *buffer; 262 size_t bufsize; 263 int *errnop; 264 265 char **aliases; 266 int aliases_size; 267 size_t linesize; 268 char *line; 269 char **cp; 270 271 name = NULL; 272 proto = NULL; 273 serv_mdata = (struct servent_mdata *)mdata; 274 switch (serv_mdata->how) { 275 case nss_lt_name: 276 name = va_arg(ap, char *); 277 proto = va_arg(ap, char *); 278 break; 279 case nss_lt_id: 280 port = va_arg(ap, int); 281 proto = va_arg(ap, char *); 282 break; 283 case nss_lt_all: 284 break; 285 default: 286 return NS_NOTFOUND; 287 }; 288 289 serv = va_arg(ap, struct servent *); 290 buffer = va_arg(ap, char *); 291 bufsize = va_arg(ap, size_t); 292 errnop = va_arg(ap,int *); 293 294 *errnop = files_getstate(&st); 295 if (*errnop != 0) 296 return (NS_UNAVAIL); 297 298 if (st->fp == NULL) 299 st->compat_mode_active = 0; 300 301 if (st->fp == NULL && (st->fp = fopen(_PATH_SERVICES, "r")) == NULL) { 302 *errnop = errno; 303 return (NS_UNAVAIL); |
104 } | 304 } |
105 len += strlen(se->s_name) + 1; 106 len += strlen(se->s_proto) + 1; 107 len += numptr * sizeof(char*); | |
108 | 305 |
109 if (len > (int)buflen) { 110 errno = ERANGE; 111 return (-1); | 306 if (serv_mdata->how == nss_lt_all) 307 stayopen = 1; 308 else { 309 rewind(st->fp); 310 stayopen = st->stayopen; |
112 } 113 | 311 } 312 |
114 /* copy port value */ 115 sptr->s_port = se->s_port; | 313 rv = NS_NOTFOUND; 314 do { 315 if (!st->compat_mode_active) { 316 if ((line = fgetln(st->fp, &linesize)) == NULL) { 317 *errnop = errno; 318 rv = NS_RETURN; 319 break; 320 } |
116 | 321 |
117 cp = (char *)ALIGN(buf) + numptr * sizeof(char *); | 322 if (*line=='+') { 323 if (serv_mdata->compat_mode != 0) 324 st->compat_mode_active = 1; 325 } else { 326 if (bufsize <= linesize + _ALIGNBYTES + 327 sizeof(char *)) { 328 *errnop = ERANGE; 329 rv = NS_RETURN; 330 break; 331 } 332 aliases = (char **)_ALIGN(&buffer[linesize+1]); 333 aliases_size = (buffer + bufsize - 334 (char *)aliases) / sizeof(char *); 335 if (aliases_size < 1) { 336 *errnop = ERANGE; 337 rv = NS_RETURN; 338 break; 339 } |
118 | 340 |
119 /* copy official name */ 120 n = strlen(se->s_name) + 1; 121 strcpy(cp, se->s_name); 122 sptr->s_name = cp; 123 cp += n; | 341 memcpy(buffer, line, linesize); 342 buffer[linesize] = '\0'; 343 } 344 } |
124 | 345 |
125 /* copy aliases */ 126 sptr->s_aliases = (char **)ALIGN(buf); 127 for (i = 0 ; se->s_aliases[i]; i++) { 128 n = strlen(se->s_aliases[i]) + 1; 129 strcpy(cp, se->s_aliases[i]); 130 sptr->s_aliases[i] = cp; 131 cp += n; | 346 if (st->compat_mode_active != 0) { 347 switch (serv_mdata->how) { 348 case nss_lt_name: 349 rv = nsdispatch(retval, compat_dtab, 350 NSDB_SERVICES_COMPAT, "getservbyname_r", 351 compat_src, name, proto, serv, buffer, 352 bufsize, errnop); 353 break; 354 case nss_lt_id: 355 rv = nsdispatch(retval, compat_dtab, 356 NSDB_SERVICES_COMPAT, "getservbyport_r", 357 compat_src, port, proto, serv, buffer, 358 bufsize, errnop); 359 break; 360 case nss_lt_all: 361 rv = nsdispatch(retval, compat_dtab, 362 NSDB_SERVICES_COMPAT, "getservent_r", 363 compat_src, serv, buffer, bufsize, errnop); 364 break; 365 } 366 367 if (!(rv & NS_TERMINATE) || 368 serv_mdata->how != nss_lt_all) 369 st->compat_mode_active = 0; 370 371 continue; 372 } 373 374 rv = servent_unpack(buffer, serv, aliases, aliases_size, 375 errnop); 376 if (rv !=0 ) { 377 if (*errnop == 0) { 378 rv = NS_NOTFOUND; 379 continue; 380 } 381 else { 382 rv = NS_RETURN; 383 break; 384 } 385 } 386 387 rv = NS_NOTFOUND; 388 switch (serv_mdata->how) { 389 case nss_lt_name: 390 if (strcmp(name, serv->s_name) == 0) 391 goto gotname; 392 for (cp = serv->s_aliases; *cp; cp++) 393 if (strcmp(name, *cp) == 0) 394 goto gotname; 395 396 continue; 397 gotname: 398 if (proto == 0 || strcmp(serv->s_proto, proto) == 0) 399 rv = NS_SUCCESS; 400 break; 401 case nss_lt_id: 402 if (port != serv->s_port) 403 continue; 404 405 if (proto == 0 || strcmp(serv->s_proto, proto) == 0) 406 rv = NS_SUCCESS; 407 break; 408 case nss_lt_all: 409 rv = NS_SUCCESS; 410 break; 411 } 412 413 } while (!(rv & NS_TERMINATE)); 414 415 if (!stayopen && st->fp != NULL) { 416 fclose(st->fp); 417 st->fp = NULL; |
132 } | 418 } |
133 sptr->s_aliases[i] = NULL; | |
134 | 419 |
135 /* copy proto */ 136 n = strlen(se->s_proto) + 1; 137 strcpy(cp, se->s_proto); 138 sptr->s_proto = cp; 139 cp += n; | 420 if ((rv == NS_SUCCESS) && (retval != NULL)) 421 *(struct servent **)retval=serv; |
140 | 422 |
141 return (0); | 423 return (rv); |
142} 143 | 424} 425 |
426static int 427files_setservent(void *retval, void *mdata, va_list ap) 428{ 429 struct files_state *st; 430 int rv; 431 int f; 432 433 rv = files_getstate(&st); 434 if (rv != 0) 435 return (NS_UNAVAIL); 436 437 switch ((enum constants)mdata) { 438 case SETSERVENT: 439 f = va_arg(ap,int); 440 if (st->fp == NULL) 441 st->fp = fopen(_PATH_SERVICES, "r"); 442 else 443 rewind(st->fp); 444 st->stayopen |= f; 445 break; 446 case ENDSERVENT: 447 if (st->fp != NULL) { 448 fclose(st->fp); 449 st->fp = NULL; 450 } 451 st->stayopen = 0; 452 break; 453 default: 454 break; 455 }; 456 457 st->compat_mode_active = 0; 458 return (NS_UNAVAIL); 459} 460 461/* nis backend implementation */ |
|
144#ifdef YP | 462#ifdef YP |
463static void 464nis_endstate(void *p) 465{ 466 if (p == NULL) 467 return; 468 469 free(((struct nis_state *)p)->yp_key); 470 free(p); 471} 472 |
|
145static int | 473static int |
146_getservbyport_yp(struct servent_data *sed) | 474nis_servent(void *retval, void *mdata, va_list ap) |
147{ | 475{ |
148 char *result; 149 int resultlen; | 476 char *resultbuf, *lastkey; 477 int resultbuflen; |
150 char buf[YPMAXRECORD + 2]; | 478 char buf[YPMAXRECORD + 2]; |
479 480 struct nis_state *st; |
|
151 int rv; 152 | 481 int rv; 482 |
153 snprintf(buf, sizeof(buf), "%d/%s", ntohs(sed->yp_port), 154 sed->yp_proto); | 483 enum nss_lookup_type how; 484 char *name; 485 char *proto; 486 int port; |
155 | 487 |
156 sed->yp_port = 0; 157 sed->yp_proto = NULL; | 488 struct servent *serv; 489 char *buffer; 490 size_t bufsize; 491 int *errnop; |
158 | 492 |
159 if (!sed->yp_domain) { 160 if (yp_get_default_domain(&sed->yp_domain)) 161 return (0); | 493 char **aliases; 494 int aliases_size; 495 496 name = NULL; 497 proto = NULL; 498 how = (enum nss_lookup_type)mdata; 499 switch (how) { 500 case nss_lt_name: 501 name = va_arg(ap, char *); 502 proto = va_arg(ap, char *); 503 break; 504 case nss_lt_id: 505 port = va_arg(ap, int); 506 proto = va_arg(ap, char *); 507 break; 508 case nss_lt_all: 509 break; 510 default: 511 return NS_NOTFOUND; 512 }; 513 514 serv = va_arg(ap, struct servent *); 515 buffer = va_arg(ap, char *); 516 bufsize = va_arg(ap, size_t); 517 errnop = va_arg(ap, int *); 518 519 *errnop = nis_getstate(&st); 520 if (*errnop != 0) 521 return (NS_UNAVAIL); 522 523 if (st->yp_domain[0] == '\0') { 524 if (getdomainname(st->yp_domain, sizeof st->yp_domain)) { 525 *errnop = errno; 526 return (NS_UNAVAIL); 527 } |
162 } 163 | 528 } 529 |
164 /* 165 * We have to be a little flexible here. Ideally you're supposed 166 * to have both a services.byname and a services.byport map, but 167 * some systems have only services.byname. FreeBSD cheats a little 168 * by putting the services.byport information in the same map as 169 * services.byname so that either case will work. We allow for both 170 * possibilities here: if there is no services.byport map, we try 171 * services.byname instead. 172 */ 173 if ((rv = yp_match(sed->yp_domain, "services.byport", buf, strlen(buf), 174 &result, &resultlen))) { 175 if (rv == YPERR_MAP) { 176 if (yp_match(sed->yp_domain, "services.byname", buf, 177 strlen(buf), &result, &resultlen)) 178 return(0); | 530 do { 531 switch (how) { 532 case nss_lt_name: 533 snprintf(buf, sizeof(buf), "%s/%s", name, proto); 534 if (yp_match(st->yp_domain, "services.byname", buf, 535 strlen(buf), &resultbuf, &resultbuflen)) { 536 rv = NS_NOTFOUND; 537 goto fin; 538 } 539 break; 540 case nss_lt_id: 541 snprintf(buf, sizeof(buf), "%d/%s", ntohs(port), 542 proto); 543 544 /* 545 * We have to be a little flexible 546 * here. Ideally you're supposed to have both 547 * a services.byname and a services.byport 548 * map, but some systems have only 549 * services.byname. FreeBSD cheats a little by 550 * putting the services.byport information in 551 * the same map as services.byname so that 552 * either case will work. We allow for both 553 * possibilities here: if there is no 554 * services.byport map, we try services.byname 555 * instead. 556 */ 557 rv = yp_match(st->yp_domain, "services.byport", buf, 558 strlen(buf), &resultbuf, &resultbuflen); 559 if (rv) { 560 if (rv == YPERR_MAP) { 561 if (yp_match(st->yp_domain, 562 "services.byname", buf, 563 strlen(buf), &resultbuf, 564 &resultbuflen)) { 565 rv = NS_NOTFOUND; 566 goto fin; 567 } 568 } else { 569 rv = NS_NOTFOUND; 570 goto fin; 571 } 572 } 573 574 break; 575 case nss_lt_all: 576 if (!st->yp_stepping) { 577 free(st->yp_key); 578 rv = yp_first(st->yp_domain, "services.byname", 579 &st->yp_key, &st->yp_keylen, &resultbuf, 580 &resultbuflen); 581 if (rv) { 582 rv = NS_NOTFOUND; 583 goto fin; 584 } 585 st->yp_stepping = 1; 586 } else { 587 lastkey = st->yp_key; 588 rv = yp_next(st->yp_domain, "services.byname", 589 st->yp_key, st->yp_keylen, &st->yp_key, 590 &st->yp_keylen, &resultbuf, &resultbuflen); 591 free(lastkey); 592 if (rv) { 593 st->yp_stepping = 0; 594 rv = NS_NOTFOUND; 595 goto fin; 596 } 597 } 598 break; 599 }; 600 601 /* we need a room for additional \n symbol */ 602 if (bufsize <= 603 resultbuflen + 1 + _ALIGNBYTES + sizeof(char *)) { 604 *errnop = ERANGE; 605 rv = NS_RETURN; 606 break; 607 } 608 609 aliases = (char **)_ALIGN(&buffer[resultbuflen + 2]); 610 aliases_size = 611 (buffer + bufsize - (char *)aliases) / sizeof(char *); 612 if (aliases_size < 1) { 613 *errnop = ERANGE; 614 rv = NS_RETURN; 615 break; 616 } 617 618 /* 619 * servent_unpack expects lines terminated with \n -- 620 * make it happy 621 */ 622 memcpy(buffer, resultbuf, resultbuflen); 623 buffer[resultbuflen] = '\n'; 624 buffer[resultbuflen + 1] = '\0'; 625 626 if (servent_unpack(buffer, serv, aliases, aliases_size, 627 errnop) != 0) { 628 if (*errnop == 0) 629 rv = NS_NOTFOUND; 630 else 631 rv = NS_RETURN; |
179 } else | 632 } else |
180 return(0); 181 } | 633 rv = NS_SUCCESS; 634 free(resultbuf); |
182 | 635 |
183 /* getservent() expects lines terminated with \n -- make it happy */ 184 snprintf(sed->line, sizeof sed->line, "%.*s\n", resultlen, result); | 636 } while (!(rv & NS_TERMINATE) && how == nss_lt_all); |
185 | 637 |
186 free(result); 187 return(1); | 638fin: 639 if (rv == NS_SUCCESS && retval != NULL) 640 *(struct servent **)retval = serv; 641 642 return (rv); |
188} 189 190static int | 643} 644 645static int |
191_getservbyname_yp(struct servent_data *sed) | 646nis_setservent(void *result, void *mdata, va_list ap) |
192{ | 647{ |
193 char *result; 194 int resultlen; 195 char buf[YPMAXRECORD + 2]; | 648 struct nis_state *st; 649 int rv; |
196 | 650 |
197 if(!sed->yp_domain) { 198 if(yp_get_default_domain(&sed->yp_domain)) 199 return (0); 200 } | 651 rv = nis_getstate(&st); 652 if (rv != 0) 653 return (NS_UNAVAIL); |
201 | 654 |
202 snprintf(buf, sizeof(buf), "%s/%s", sed->yp_name, sed->yp_proto); | 655 switch ((enum constants)mdata) { 656 case SETSERVENT: 657 case ENDSERVENT: 658 free(st->yp_key); 659 st->yp_key = NULL; 660 st->yp_stepping = 0; 661 break; 662 default: 663 break; 664 }; |
203 | 665 |
204 sed->yp_name = 0; 205 sed->yp_proto = NULL; | 666 return (NS_UNAVAIL); 667} 668#endif |
206 | 669 |
207 if (yp_match(sed->yp_domain, "services.byname", buf, strlen(buf), 208 &result, &resultlen)) { 209 return(0); 210 } | 670/* compat backend implementation */ 671static int 672compat_setservent(void *retval, void *mdata, va_list ap) 673{ 674 static const ns_src compat_src[] = { 675#ifdef YP 676 { NSSRC_NIS, NS_SUCCESS }, 677#endif 678 { NULL, 0 } 679 }; 680 ns_dtab compat_dtab[] = { 681#ifdef YP 682 { NSSRC_NIS, nis_setservent, mdata }, 683#endif 684 { NULL, NULL, NULL } 685 }; 686 int f; |
211 | 687 |
212 /* getservent() expects lines terminated with \n -- make it happy */ 213 snprintf(sed->line, sizeof sed->line, "%.*s\n", resultlen, result); | 688 (void)files_setservent(retval, mdata, ap); |
214 | 689 |
215 free(result); 216 return(1); | 690 switch ((enum constants)mdata) { 691 case SETSERVENT: 692 f = va_arg(ap,int); 693 (void)nsdispatch(retval, compat_dtab, NSDB_SERVICES_COMPAT, 694 "setservent", compat_src, f); 695 break; 696 case ENDSERVENT: 697 (void)nsdispatch(retval, compat_dtab, NSDB_SERVICES_COMPAT, 698 "endservent", compat_src); 699 break; 700 default: 701 break; 702 } 703 704 return (NS_UNAVAIL); |
217} 218 | 705} 706 |
707#ifdef NS_CACHING |
|
219static int | 708static int |
220_getservent_yp(struct servent_data *sed) | 709serv_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata) |
221{ | 710{ |
222 char *lastkey, *result; 223 int resultlen; 224 int rv; | 711 char *name; 712 char *proto; 713 int port; |
225 | 714 |
226 if (!sed->yp_domain) { 227 if (yp_get_default_domain(&sed->yp_domain)) 228 return (0); 229 } | 715 size_t desired_size, size, size2; 716 enum nss_lookup_type lookup_type; 717 int res = NS_UNAVAIL; |
230 | 718 |
231 if (!sed->yp_stepping) { 232 free(sed->yp_key); 233 rv = yp_first(sed->yp_domain, "services.byname", &sed->yp_key, 234 &sed->yp_keylen, &result, &resultlen); 235 if (rv) { 236 sed->yp_stepping = 0; 237 return(0); | 719 lookup_type = (enum nss_lookup_type)cache_mdata; 720 switch (lookup_type) { 721 case nss_lt_name: 722 name = va_arg(ap, char *); 723 proto = va_arg(ap, char *); 724 725 size = strlen(name); 726 desired_size = sizeof(enum nss_lookup_type) + size + 1; 727 if (proto != NULL) { 728 size2 = strlen(proto); 729 desired_size += size2 + 1; 730 } else 731 size2 = 0; 732 733 if (desired_size > *buffer_size) { 734 res = NS_RETURN; 735 goto fin; |
238 } | 736 } |
239 sed->yp_stepping = 1; 240 } else { 241 lastkey = sed->yp_key; 242 rv = yp_next(sed->yp_domain, "services.byname", sed->yp_key, 243 sed->yp_keylen, &sed->yp_key, &sed->yp_keylen, &result, 244 &resultlen); 245 free(lastkey); 246 if (rv) { 247 sed->yp_stepping = 0; 248 return (0); | 737 738 memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type)); 739 memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1); 740 741 if (proto != NULL) 742 memcpy(buffer + sizeof(enum nss_lookup_type) + size + 1, 743 proto, size2 + 1); 744 745 res = NS_SUCCESS; 746 break; 747 case nss_lt_id: 748 port = va_arg(ap, int); 749 proto = va_arg(ap, char *); 750 751 desired_size = sizeof(enum nss_lookup_type) + sizeof(int); 752 if (proto != NULL) { 753 size = strlen(proto); 754 desired_size += size + 1; 755 } else 756 size = 0; 757 758 if (desired_size > *buffer_size) { 759 res = NS_RETURN; 760 goto fin; |
249 } | 761 } |
762 763 memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type)); 764 memcpy(buffer + sizeof(enum nss_lookup_type), &port, 765 sizeof(int)); 766 767 if (proto != NULL) 768 memcpy(buffer + sizeof(enum nss_lookup_type) + 769 sizeof(int), proto, size + 1); 770 771 res = NS_SUCCESS; 772 break; 773 default: 774 /* should be unreachable */ 775 return (NS_UNAVAIL); |
|
250 } 251 | 776 } 777 |
252 /* getservent() expects lines terminated with \n -- make it happy */ 253 snprintf(sed->line, sizeof sed->line, "%.*s\n", resultlen, result); | 778fin: 779 *buffer_size = desired_size; 780 return (res); 781} |
254 | 782 |
255 free(result); | 783int 784serv_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap, 785 void *cache_mdata) 786{ 787 char *name; 788 char *proto; 789 int port; 790 struct servent *serv; 791 char *orig_buf; 792 size_t orig_buf_size; |
256 | 793 |
257 return(1); | 794 struct servent new_serv; 795 size_t desired_size; 796 char **alias; 797 char *p; 798 size_t size; 799 size_t aliases_size; 800 801 switch ((enum nss_lookup_type)cache_mdata) { 802 case nss_lt_name: 803 name = va_arg(ap, char *); 804 proto = va_arg(ap, char *); 805 break; 806 case nss_lt_id: 807 port = va_arg(ap, int); 808 proto = va_arg(ap, char *); 809 break; 810 case nss_lt_all: 811 break; 812 default: 813 /* should be unreachable */ 814 return (NS_UNAVAIL); 815 } 816 817 serv = va_arg(ap, struct servent *); 818 orig_buf = va_arg(ap, char *); 819 orig_buf_size = va_arg(ap, size_t); 820 821 desired_size = _ALIGNBYTES + sizeof(struct servent) + sizeof(char *); 822 if (serv->s_name != NULL) 823 desired_size += strlen(serv->s_name) + 1; 824 if (serv->s_proto != NULL) 825 desired_size += strlen(serv->s_proto) + 1; 826 827 aliases_size = 0; 828 if (serv->s_aliases != NULL) { 829 for (alias = serv->s_aliases; *alias; ++alias) { 830 desired_size += strlen(*alias) + 1; 831 ++aliases_size; 832 } 833 834 desired_size += _ALIGNBYTES + 835 sizeof(char *) * (aliases_size + 1); 836 } 837 838 if (*buffer_size < desired_size) { 839 /* this assignment is here for future use */ 840 *buffer_size = desired_size; 841 return (NS_RETURN); 842 } 843 844 memcpy(&new_serv, serv, sizeof(struct servent)); 845 memset(buffer, 0, desired_size); 846 847 *buffer_size = desired_size; 848 p = buffer + sizeof(struct servent) + sizeof(char *); 849 memcpy(buffer + sizeof(struct servent), &p, sizeof(char *)); 850 p = (char *)_ALIGN(p); 851 852 if (new_serv.s_name != NULL) { 853 size = strlen(new_serv.s_name); 854 memcpy(p, new_serv.s_name, size); 855 new_serv.s_name = p; 856 p += size + 1; 857 } 858 859 if (new_serv.s_proto != NULL) { 860 size = strlen(new_serv.s_proto); 861 memcpy(p, new_serv.s_proto, size); 862 new_serv.s_proto = p; 863 p += size + 1; 864 } 865 866 if (new_serv.s_aliases != NULL) { 867 p = (char *)_ALIGN(p); 868 memcpy(p, new_serv.s_aliases, sizeof(char *) * aliases_size); 869 new_serv.s_aliases = (char **)p; 870 p += sizeof(char *) * (aliases_size + 1); 871 872 for (alias = new_serv.s_aliases; *alias; ++alias) { 873 size = strlen(*alias); 874 memcpy(p, *alias, size); 875 *alias = p; 876 p += size + 1; 877 } 878 } 879 880 memcpy(buffer, &new_serv, sizeof(struct servent)); 881 return (NS_SUCCESS); |
258} | 882} |
259#endif | |
260 | 883 |
261void 262__setservent_p(int f, struct servent_data *sed) | 884int 885serv_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap, 886 void *cache_mdata) |
263{ | 887{ |
264 if (sed->fp == NULL) 265 sed->fp = fopen(_PATH_SERVICES, "r"); 266 else 267 rewind(sed->fp); 268 sed->stayopen |= f; | 888 char *name; 889 char *proto; 890 int port; 891 struct servent *serv; 892 char *orig_buf; 893 char *p; 894 char **alias; 895 size_t orig_buf_size; 896 int *ret_errno; 897 898 switch ((enum nss_lookup_type)cache_mdata) { 899 case nss_lt_name: 900 name = va_arg(ap, char *); 901 proto = va_arg(ap, char *); 902 break; 903 case nss_lt_id: 904 port = va_arg(ap, int); 905 proto = va_arg(ap, char *); 906 break; 907 case nss_lt_all: 908 break; 909 default: 910 /* should be unreachable */ 911 return (NS_UNAVAIL); 912 } 913 914 serv = va_arg(ap, struct servent *); 915 orig_buf = va_arg(ap, char *); 916 orig_buf_size = va_arg(ap, size_t); 917 ret_errno = va_arg(ap, int *); 918 919 if (orig_buf_size < 920 buffer_size - sizeof(struct servent) - sizeof(char *)) { 921 *ret_errno = ERANGE; 922 return (NS_RETURN); 923 } 924 925 memcpy(serv, buffer, sizeof(struct servent)); 926 memcpy(&p, buffer + sizeof(struct servent), sizeof(char *)); 927 928 orig_buf = (char *)_ALIGN(orig_buf); 929 memcpy(orig_buf, buffer + sizeof(struct servent) + sizeof(char *) + 930 (_ALIGN(p) - (size_t)p), 931 buffer_size - sizeof(struct servent) - sizeof(char *) - 932 (_ALIGN(p) - (size_t)p)); 933 p = (char *)_ALIGN(p); 934 935 NS_APPLY_OFFSET(serv->s_name, orig_buf, p, char *); 936 NS_APPLY_OFFSET(serv->s_proto, orig_buf, p, char *); 937 if (serv->s_aliases != NULL) { 938 NS_APPLY_OFFSET(serv->s_aliases, orig_buf, p, char **); 939 940 for (alias = serv->s_aliases; *alias; ++alias) 941 NS_APPLY_OFFSET(*alias, orig_buf, p, char *); 942 } 943 944 if (retval != NULL) 945 *((struct servent **)retval) = serv; 946 return (NS_SUCCESS); |
269} 270 | 947} 948 |
271void 272__endservent_p(struct servent_data *sed) | 949NSS_MP_CACHE_HANDLING(services); 950#endif /* NS_CACHING */ 951 952/* get**_r functions implementation */ 953int 954getservbyname_r(const char *name, const char *proto, struct servent *serv, 955 char *buffer, size_t bufsize, struct servent **result) |
273{ | 956{ |
274 servent_data_clear(sed); 275 sed->stayopen = 0; | 957 static const struct servent_mdata mdata = { nss_lt_name, 0 }; 958 static const struct servent_mdata compat_mdata = { nss_lt_name, 1 }; 959#ifdef NS_CACHING 960 static const nss_cache_info cache_info = 961 NS_COMMON_CACHE_INFO_INITIALIZER( 962 services, (void *)nss_lt_name, 963 serv_id_func, serv_marshal_func, serv_unmarshal_func); 964#endif /* NS_CACHING */ 965 static const ns_dtab dtab[] = { 966 { NSSRC_FILES, files_servent, (void *)&mdata }, |
276#ifdef YP | 967#ifdef YP |
277 sed->yp_stepping = 0; 278 sed->yp_domain = NULL; | 968 { NSSRC_NIS, nis_servent, (void *)nss_lt_name }, |
279#endif | 969#endif |
970 { NSSRC_COMPAT, files_servent, (void *)&compat_mdata }, 971#ifdef NS_CACHING 972 NS_CACHE_CB(&cache_info) 973#endif 974 { NULL, NULL, NULL } 975 }; 976 int rv, ret_errno; 977 978 ret_errno = 0; 979 *result = NULL; 980 rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservbyname_r", 981 defaultsrc, name, proto, serv, buffer, bufsize, &ret_errno); 982 983 if (rv == NS_SUCCESS) 984 return (0); 985 else 986 return (ret_errno); |
|
280} 281 282int | 987} 988 989int |
283__getservent_p(struct servent *se, struct servent_data *sed) | 990getservbyport_r(int port, const char *proto, struct servent *serv, 991 char *buffer, size_t bufsize, struct servent **result) |
284{ | 992{ |
285 char *p; 286 char *cp, **q, *endp; 287 long l; 288 289#ifdef YP 290 if (sed->yp_stepping && _getservent_yp(sed)) { 291 p = sed->line; 292 goto unpack; 293 } 294tryagain: | 993 static const struct servent_mdata mdata = { nss_lt_id, 0 }; 994 static const struct servent_mdata compat_mdata = { nss_lt_id, 1 }; 995#ifdef NS_CACHING 996 static const nss_cache_info cache_info = 997 NS_COMMON_CACHE_INFO_INITIALIZER( 998 services, (void *)nss_lt_id, 999 serv_id_func, serv_marshal_func, serv_unmarshal_func); |
295#endif | 1000#endif |
296 if (sed->fp == NULL && (sed->fp = fopen(_PATH_SERVICES, "r")) == NULL) 297 return (-1); 298again: 299 if ((p = fgets(sed->line, sizeof sed->line, sed->fp)) == NULL) 300 return (-1); | 1001 static const ns_dtab dtab[] = { 1002 { NSSRC_FILES, files_servent, (void *)&mdata }, |
301#ifdef YP | 1003#ifdef YP |
302 if (*p == '+' && _yp_check(NULL)) { 303 if (sed->yp_name != NULL) { 304 if (!_getservbyname_yp(sed)) 305 goto tryagain; 306 } 307 else if (sed->yp_port != 0) { 308 if (!_getservbyport_yp(sed)) 309 goto tryagain; 310 } 311 else if (!_getservent_yp(sed)) 312 goto tryagain; 313 } 314unpack: | 1004 { NSSRC_NIS, nis_servent, (void *)nss_lt_id }, |
315#endif | 1005#endif |
316 if (*p == '#') 317 goto again; 318 cp = strpbrk(p, "#\n"); 319 if (cp != NULL) 320 *cp = '\0'; 321 se->s_name = p; 322 p = strpbrk(p, " \t"); 323 if (p == NULL) 324 goto again; 325 *p++ = '\0'; 326 while (*p == ' ' || *p == '\t') 327 p++; 328 cp = strpbrk(p, ",/"); 329 if (cp == NULL) 330 goto again; 331 *cp++ = '\0'; 332 l = strtol(p, &endp, 10); 333 if (endp == p || *endp != '\0' || l < 0 || l > USHRT_MAX) 334 goto again; 335 se->s_port = htons((in_port_t)l); 336 se->s_proto = cp; 337 q = se->s_aliases = sed->aliases; 338 cp = strpbrk(cp, " \t"); 339 if (cp != NULL) 340 *cp++ = '\0'; 341 while (cp && *cp) { 342 if (*cp == ' ' || *cp == '\t') { 343 cp++; 344 continue; 345 } 346 if (q < &sed->aliases[_MAXALIASES - 1]) 347 *q++ = cp; 348 cp = strpbrk(cp, " \t"); 349 if (cp != NULL) 350 *cp++ = '\0'; 351 } 352 *q = NULL; 353 return (0); | 1006 { NSSRC_COMPAT, files_servent, (void *)&compat_mdata }, 1007#ifdef NS_CACHING 1008 NS_CACHE_CB(&cache_info) 1009#endif 1010 { NULL, NULL, NULL } 1011 }; 1012 int rv, ret_errno; 1013 1014 ret_errno = 0; 1015 *result = NULL; 1016 rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservbyport_r", 1017 defaultsrc, port, proto, serv, buffer, bufsize, &ret_errno); 1018 1019 if (rv == NS_SUCCESS) 1020 return (0); 1021 else 1022 return (ret_errno); |
354} 355 356int | 1023} 1024 1025int |
357getservent_r(struct servent *sptr, char *buffer, size_t buflen, | 1026getservent_r(struct servent *serv, char *buffer, size_t bufsize, |
358 struct servent **result) 359{ | 1027 struct servent **result) 1028{ |
360 struct servent se; 361 struct servent_data *sed; | 1029 static const struct servent_mdata mdata = { nss_lt_all, 0 }; 1030 static const struct servent_mdata compat_mdata = { nss_lt_all, 1 }; 1031#ifdef NS_CACHING 1032 static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER( 1033 services, (void *)nss_lt_all, 1034 serv_marshal_func, serv_unmarshal_func); 1035#endif 1036 static const ns_dtab dtab[] = { 1037 { NSSRC_FILES, files_servent, (void *)&mdata }, 1038#ifdef YP 1039 { NSSRC_NIS, nis_servent, (void *)nss_lt_all }, 1040#endif 1041 { NSSRC_COMPAT, files_servent, (void *)&compat_mdata }, 1042#ifdef NS_CACHING 1043 NS_CACHE_CB(&cache_info) 1044#endif 1045 { NULL, NULL, NULL } 1046 }; 1047 int rv, ret_errno; |
362 | 1048 |
363 if ((sed = __servent_data_init()) == NULL) 364 return (-1); | 1049 ret_errno = 0; 1050 *result = NULL; 1051 rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservent_r", 1052 defaultsrc, serv, buffer, bufsize, &ret_errno); |
365 | 1053 |
366 if (__getservent_p(&se, sed) != 0) 367 return (-1); 368 if (__copy_servent(&se, sptr, buffer, buflen) != 0) 369 return (-1); 370 *result = sptr; 371 return (0); | 1054 if (rv == NS_SUCCESS) 1055 return (0); 1056 else 1057 return (ret_errno); |
372} 373 374void | 1058} 1059 1060void |
375setservent(int f) | 1061setservent(int stayopen) |
376{ | 1062{ |
377 struct servent_data *sed; | 1063#ifdef NS_CACHING 1064 static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER( 1065 services, (void *)nss_lt_all, 1066 NULL, NULL); 1067#endif 1068 static const ns_dtab dtab[] = { 1069 { NSSRC_FILES, files_setservent, (void *)SETSERVENT }, 1070#ifdef YP 1071 { NSSRC_NIS, nis_setservent, (void *)SETSERVENT }, 1072#endif 1073 { NSSRC_COMPAT, compat_setservent, (void *)SETSERVENT }, 1074#ifdef NS_CACHING 1075 NS_CACHE_CB(&cache_info) 1076#endif 1077 { NULL, NULL, NULL } 1078 }; |
378 | 1079 |
379 if ((sed = __servent_data_init()) == NULL) 380 return; 381 __setservent_p(f, sed); | 1080 (void)nsdispatch(NULL, dtab, NSDB_SERVICES, "setservent", defaultsrc, 1081 stayopen); |
382} 383 384void | 1082} 1083 1084void |
385endservent(void) | 1085endservent() |
386{ | 1086{ |
387 struct servent_data *sed; | 1087#ifdef NS_CACHING 1088 static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER( 1089 services, (void *)nss_lt_all, 1090 NULL, NULL); 1091#endif 1092 static const ns_dtab dtab[] = { 1093 { NSSRC_FILES, files_setservent, (void *)ENDSERVENT }, 1094#ifdef YP 1095 { NSSRC_NIS, nis_setservent, (void *)ENDSERVENT }, 1096#endif 1097 { NSSRC_COMPAT, compat_setservent, (void *)ENDSERVENT }, 1098#ifdef NS_CACHING 1099 NS_CACHE_CB(&cache_info) 1100#endif 1101 { NULL, NULL, NULL } 1102 }; |
388 | 1103 |
389 if ((sed = __servent_data_init()) == NULL) | 1104 (void)nsdispatch(NULL, dtab, NSDB_SERVICES, "endservent", defaultsrc); 1105} 1106 1107/* get** wrappers for get**_r functions implementation */ 1108static void 1109servent_endstate(void *p) 1110{ 1111 if (p == NULL) |
390 return; | 1112 return; |
391 __endservent_p(sed); | 1113 1114 free(((struct servent_state *)p)->buffer); 1115 free(p); |
392} 393 | 1116} 1117 |
1118static int 1119wrap_getservbyname_r(struct key key, struct servent *serv, char *buffer, 1120 size_t bufsize, struct servent **res) 1121{ 1122 return (getservbyname_r(key.name, key.proto, serv, buffer, bufsize, 1123 res)); 1124} 1125 1126static int 1127wrap_getservbyport_r(struct key key, struct servent *serv, char *buffer, 1128 size_t bufsize, struct servent **res) 1129{ 1130 return (getservbyport_r(key.port, key.proto, serv, buffer, bufsize, 1131 res)); 1132} 1133 1134static int 1135wrap_getservent_r(struct key key, struct servent *serv, char *buffer, 1136 size_t bufsize, struct servent **res) 1137{ 1138 return (getservent_r(serv, buffer, bufsize, res)); 1139} 1140 1141static struct servent * 1142getserv(int (*fn)(struct key, struct servent *, char *, size_t, 1143 struct servent **), struct key key) 1144{ 1145 int rv; 1146 struct servent *res; 1147 struct servent_state * st; 1148 1149 rv = servent_getstate(&st); 1150 if (rv != 0) { 1151 errno = rv; 1152 return NULL; 1153 } 1154 1155 if (st->buffer == NULL) { 1156 st->buffer = malloc(SERVENT_STORAGE_INITIAL); 1157 if (st->buffer == NULL) 1158 return (NULL); 1159 st->bufsize = SERVENT_STORAGE_INITIAL; 1160 } 1161 do { 1162 rv = fn(key, &st->serv, st->buffer, st->bufsize, &res); 1163 if (res == NULL && rv == ERANGE) { 1164 free(st->buffer); 1165 if ((st->bufsize << 1) > SERVENT_STORAGE_MAX) { 1166 st->buffer = NULL; 1167 errno = ERANGE; 1168 return (NULL); 1169 } 1170 st->bufsize <<= 1; 1171 st->buffer = malloc(st->bufsize); 1172 if (st->buffer == NULL) 1173 return (NULL); 1174 } 1175 } while (res == NULL && rv == ERANGE); 1176 if (rv != 0) 1177 errno = rv; 1178 1179 return (res); 1180} 1181 |
|
394struct servent * | 1182struct servent * |
395getservent(void) | 1183getservbyname(const char *name, const char *proto) |
396{ | 1184{ |
397 struct servdata *sd; 398 struct servent *rval; | 1185 struct key key; |
399 | 1186 |
400 if ((sd = __servdata_init()) == NULL) 401 return (NULL); 402 if (getservent_r(&sd->serv, sd->data, sizeof(sd->data), &rval) != 0) 403 return (NULL); 404 return (rval); | 1187 key.name = name; 1188 key.proto = proto; 1189 1190 return (getserv(wrap_getservbyname_r, key)); |
405} | 1191} |
1192 1193struct servent * 1194getservbyport(int port, const char *proto) 1195{ 1196 struct key key; 1197 1198 key.port = port; 1199 key.proto = proto; 1200 1201 return (getserv(wrap_getservbyport_r, key)); 1202} 1203 1204struct servent * 1205getservent() 1206{ 1207 struct key key; 1208 1209 key.proto = NULL; 1210 key.port = 0; 1211 1212 return (getserv(wrap_getservent_r, key)); 1213} |
|