11573Srgrimes/* 21573Srgrimes * Copyright (c) 1983, 1993 31573Srgrimes * The Regents of the University of California. All rights reserved. 41573Srgrimes * 51573Srgrimes * Redistribution and use in source and binary forms, with or without 61573Srgrimes * modification, are permitted provided that the following conditions 71573Srgrimes * are met: 81573Srgrimes * 1. Redistributions of source code must retain the above copyright 91573Srgrimes * notice, this list of conditions and the following disclaimer. 101573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111573Srgrimes * notice, this list of conditions and the following disclaimer in the 121573Srgrimes * documentation and/or other materials provided with the distribution. 131573Srgrimes * 4. Neither the name of the University nor the names of its contributors 141573Srgrimes * may be used to endorse or promote products derived from this software 151573Srgrimes * without specific prior written permission. 161573Srgrimes * 171573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201573Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271573Srgrimes * SUCH DAMAGE. 281573Srgrimes */ 291573Srgrimes 301573Srgrimes#if defined(LIBC_SCCS) && !defined(lint) 311573Srgrimesstatic char sccsid[] = "@(#)getprotoent.c 8.1 (Berkeley) 6/4/93"; 321573Srgrimes#endif /* LIBC_SCCS and not lint */ 3392889Sobrien#include <sys/cdefs.h> 3492889Sobrien__FBSDID("$FreeBSD: releng/10.2/lib/libc/net/getprotoent.c 254700 2013-08-23 13:59:47Z jilles $"); 351573Srgrimes 36157779Sume#include <sys/param.h> 371573Srgrimes#include <sys/types.h> 381573Srgrimes#include <sys/socket.h> 39157779Sume#include <errno.h> 40149313Sstefanf#include <limits.h> 411573Srgrimes#include <netdb.h> 42158115Sume#include <nsswitch.h> 431573Srgrimes#include <stdio.h> 441573Srgrimes#include <stdlib.h> 451573Srgrimes#include <string.h> 46145279Sume#include "namespace.h" 47145279Sume#include "reentrant.h" 48145279Sume#include "un-namespace.h" 49145279Sume#include "netdb_private.h" 50158115Sume#ifdef NS_CACHING 51158115Sume#include "nscache.h" 52158115Sume#endif 53158115Sume#include "nss_tls.h" 541573Srgrimes 55158115Sumestatic const ns_src defaultsrc[] = { 56158115Sume { NSSRC_FILES, NS_SUCCESS }, 57158115Sume { NULL, 0 } 58158115Sume}; 59158115Sume 60157779SumeNETDB_THREAD_ALLOC(protoent_data) 61157779SumeNETDB_THREAD_ALLOC(protodata) 621573Srgrimes 63145279Sumestatic void 64145279Sumeprotoent_data_clear(struct protoent_data *ped) 65145279Sume{ 66145279Sume if (ped->fp) { 67145279Sume fclose(ped->fp); 68145279Sume ped->fp = NULL; 69145279Sume } 70145279Sume} 711573Srgrimes 72145279Sumestatic void 73157779Sumeprotoent_data_free(void *ptr) 74145279Sume{ 75157779Sume struct protoent_data *ped = ptr; 76145279Sume 77157779Sume protoent_data_clear(ped); 78157779Sume free(ped); 79145279Sume} 80145279Sume 81145279Sumestatic void 82157779Sumeprotodata_free(void *ptr) 83145279Sume{ 84157779Sume free(ptr); 85145279Sume} 86145279Sume 87158115Sume#ifdef NS_CACHING 88157779Sumeint 89158115Sume__proto_id_func(char *buffer, size_t *buffer_size, va_list ap, 90158115Sume void *cache_mdata) 91158115Sume{ 92158115Sume char *name; 93158115Sume int proto; 94158115Sume 95158115Sume size_t desired_size, size; 96158115Sume enum nss_lookup_type lookup_type; 97158115Sume int res = NS_UNAVAIL; 98158115Sume 99158115Sume lookup_type = (enum nss_lookup_type)cache_mdata; 100158115Sume switch (lookup_type) { 101158115Sume case nss_lt_name: 102158115Sume name = va_arg(ap, char *); 103158115Sume 104158115Sume size = strlen(name); 105158115Sume desired_size = sizeof(enum nss_lookup_type) + size + 1; 106158115Sume if (desired_size > *buffer_size) { 107158115Sume res = NS_RETURN; 108158115Sume goto fin; 109158115Sume } 110158115Sume 111158115Sume memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type)); 112158115Sume memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1); 113158115Sume 114158115Sume res = NS_SUCCESS; 115158115Sume break; 116158115Sume case nss_lt_id: 117158115Sume proto = va_arg(ap, int); 118158115Sume 119158115Sume desired_size = sizeof(enum nss_lookup_type) + sizeof(int); 120158115Sume if (desired_size > *buffer_size) { 121158115Sume res = NS_RETURN; 122158115Sume goto fin; 123158115Sume } 124158115Sume 125158115Sume memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type)); 126158115Sume memcpy(buffer + sizeof(enum nss_lookup_type), &proto, 127158115Sume sizeof(int)); 128158115Sume 129158115Sume res = NS_SUCCESS; 130158115Sume break; 131158115Sume default: 132158115Sume /* should be unreachable */ 133158115Sume return (NS_UNAVAIL); 134158115Sume } 135158115Sume 136158115Sumefin: 137158115Sume *buffer_size = desired_size; 138158115Sume return (res); 139158115Sume} 140158115Sume 141158115Sume 142158115Sumeint 143158115Sume__proto_marshal_func(char *buffer, size_t *buffer_size, void *retval, 144158115Sume va_list ap, void *cache_mdata) 145158115Sume{ 146158115Sume char *name; 147158115Sume int num; 148158115Sume struct protoent *proto; 149158115Sume char *orig_buf; 150158115Sume size_t orig_buf_size; 151158115Sume 152158115Sume struct protoent new_proto; 153158115Sume size_t desired_size, size, aliases_size; 154158115Sume char *p; 155158115Sume char **alias; 156158115Sume 157158115Sume switch ((enum nss_lookup_type)cache_mdata) { 158158115Sume case nss_lt_name: 159158115Sume name = va_arg(ap, char *); 160158115Sume break; 161158115Sume case nss_lt_id: 162158115Sume num = va_arg(ap, int); 163158115Sume break; 164158115Sume case nss_lt_all: 165158115Sume break; 166158115Sume default: 167158115Sume /* should be unreachable */ 168158115Sume return (NS_UNAVAIL); 169158115Sume } 170158115Sume 171158115Sume proto = va_arg(ap, struct protoent *); 172158115Sume orig_buf = va_arg(ap, char *); 173158115Sume orig_buf_size = va_arg(ap, size_t); 174158115Sume 175158115Sume desired_size = _ALIGNBYTES + sizeof(struct protoent) + sizeof(char *); 176158115Sume if (proto->p_name != NULL) 177158115Sume desired_size += strlen(proto->p_name) + 1; 178158115Sume 179158115Sume if (proto->p_aliases != NULL) { 180158115Sume aliases_size = 0; 181158115Sume for (alias = proto->p_aliases; *alias; ++alias) { 182158115Sume desired_size += strlen(*alias) + 1; 183158115Sume ++aliases_size; 184158115Sume } 185158115Sume 186158115Sume desired_size += _ALIGNBYTES + (aliases_size + 1) * 187158115Sume sizeof(char *); 188158115Sume } 189158115Sume 190158115Sume if (*buffer_size < desired_size) { 191158115Sume /* this assignment is here for future use */ 192158115Sume *buffer_size = desired_size; 193158115Sume return (NS_RETURN); 194158115Sume } 195158115Sume 196158115Sume memcpy(&new_proto, proto, sizeof(struct protoent)); 197158115Sume 198158115Sume *buffer_size = desired_size; 199158115Sume memset(buffer, 0, desired_size); 200158115Sume p = buffer + sizeof(struct protoent) + sizeof(char *); 201158115Sume memcpy(buffer + sizeof(struct protoent), &p, sizeof(char *)); 202158115Sume p = (char *)_ALIGN(p); 203158115Sume 204158115Sume if (new_proto.p_name != NULL) { 205158115Sume size = strlen(new_proto.p_name); 206158115Sume memcpy(p, new_proto.p_name, size); 207158115Sume new_proto.p_name = p; 208158115Sume p += size + 1; 209158115Sume } 210158115Sume 211158115Sume if (new_proto.p_aliases != NULL) { 212158115Sume p = (char *)_ALIGN(p); 213158115Sume memcpy(p, new_proto.p_aliases, sizeof(char *) * aliases_size); 214158115Sume new_proto.p_aliases = (char **)p; 215158115Sume p += sizeof(char *) * (aliases_size + 1); 216158115Sume 217158115Sume for (alias = new_proto.p_aliases; *alias; ++alias) { 218158115Sume size = strlen(*alias); 219158115Sume memcpy(p, *alias, size); 220158115Sume *alias = p; 221158115Sume p += size + 1; 222158115Sume } 223158115Sume } 224158115Sume 225158115Sume memcpy(buffer, &new_proto, sizeof(struct protoent)); 226158115Sume return (NS_SUCCESS); 227158115Sume} 228158115Sume 229158115Sumeint 230158115Sume__proto_unmarshal_func(char *buffer, size_t buffer_size, void *retval, 231158115Sume va_list ap, void *cache_mdata) 232158115Sume{ 233158115Sume char *name; 234158115Sume int num; 235158115Sume struct protoent *proto; 236158115Sume char *orig_buf; 237158115Sume size_t orig_buf_size; 238158115Sume int *ret_errno; 239158115Sume 240158115Sume char *p; 241158115Sume char **alias; 242158115Sume 243158115Sume switch ((enum nss_lookup_type)cache_mdata) { 244158115Sume case nss_lt_name: 245158115Sume name = va_arg(ap, char *); 246158115Sume break; 247158115Sume case nss_lt_id: 248158115Sume num = va_arg(ap, int); 249158115Sume break; 250158115Sume case nss_lt_all: 251158115Sume break; 252158115Sume default: 253158115Sume /* should be unreachable */ 254158115Sume return (NS_UNAVAIL); 255158115Sume } 256158115Sume 257158115Sume proto = va_arg(ap, struct protoent *); 258158115Sume orig_buf = va_arg(ap, char *); 259158115Sume orig_buf_size = va_arg(ap, size_t); 260158115Sume ret_errno = va_arg(ap, int *); 261158115Sume 262158115Sume if (orig_buf_size < 263158115Sume buffer_size - sizeof(struct protoent) - sizeof(char *)) { 264158115Sume *ret_errno = ERANGE; 265158115Sume return (NS_RETURN); 266158115Sume } 267158115Sume 268158115Sume memcpy(proto, buffer, sizeof(struct protoent)); 269158115Sume memcpy(&p, buffer + sizeof(struct protoent), sizeof(char *)); 270158115Sume 271158115Sume orig_buf = (char *)_ALIGN(orig_buf); 272158115Sume memcpy(orig_buf, buffer + sizeof(struct protoent) + sizeof(char *) + 273158115Sume _ALIGN(p) - (size_t)p, 274158115Sume buffer_size - sizeof(struct protoent) - sizeof(char *) - 275158115Sume _ALIGN(p) + (size_t)p); 276158115Sume p = (char *)_ALIGN(p); 277158115Sume 278158115Sume NS_APPLY_OFFSET(proto->p_name, orig_buf, p, char *); 279158115Sume if (proto->p_aliases != NULL) { 280158115Sume NS_APPLY_OFFSET(proto->p_aliases, orig_buf, p, char **); 281158115Sume 282158115Sume for (alias = proto->p_aliases; *alias; ++alias) 283158115Sume NS_APPLY_OFFSET(*alias, orig_buf, p, char *); 284158115Sume } 285158115Sume 286158115Sume if (retval != NULL) 287158115Sume *((struct protoent **)retval) = proto; 288158115Sume 289158115Sume return (NS_SUCCESS); 290158115Sume} 291158115Sume 292158115SumeNSS_MP_CACHE_HANDLING(protocols); 293158115Sume#endif /* NS_CACHING */ 294158115Sume 295158115Sumeint 296157779Sume__copy_protoent(struct protoent *pe, struct protoent *pptr, char *buf, 297157779Sume size_t buflen) 298145279Sume{ 299157779Sume char *cp; 300157779Sume int i, n; 301157779Sume int numptr, len; 302145279Sume 303157779Sume /* Find out the amount of space required to store the answer. */ 304157779Sume numptr = 1; /* NULL ptr */ 305157779Sume len = (char *)ALIGN(buf) - buf; 306157779Sume for (i = 0; pe->p_aliases[i]; i++, numptr++) { 307157779Sume len += strlen(pe->p_aliases[i]) + 1; 308157779Sume } 309157779Sume len += strlen(pe->p_name) + 1; 310157779Sume len += numptr * sizeof(char*); 311157779Sume 312157779Sume if (len > (int)buflen) { 313157779Sume errno = ERANGE; 314157779Sume return (-1); 315157779Sume } 316157779Sume 317157779Sume /* copy protocol value*/ 318157779Sume pptr->p_proto = pe->p_proto; 319157779Sume 320157779Sume cp = (char *)ALIGN(buf) + numptr * sizeof(char *); 321157779Sume 322157779Sume /* copy official name */ 323157779Sume n = strlen(pe->p_name) + 1; 324157779Sume strcpy(cp, pe->p_name); 325157779Sume pptr->p_name = cp; 326157779Sume cp += n; 327157779Sume 328157779Sume /* copy aliases */ 329157779Sume pptr->p_aliases = (char **)ALIGN(buf); 330157779Sume for (i = 0 ; pe->p_aliases[i]; i++) { 331157779Sume n = strlen(pe->p_aliases[i]) + 1; 332157779Sume strcpy(cp, pe->p_aliases[i]); 333157779Sume pptr->p_aliases[i] = cp; 334157779Sume cp += n; 335157779Sume } 336157779Sume pptr->p_aliases[i] = NULL; 337157779Sume 338157779Sume return (0); 339145279Sume} 340145279Sume 3411573Srgrimesvoid 342157779Sume__setprotoent_p(int f, struct protoent_data *ped) 3431573Srgrimes{ 344145279Sume if (ped->fp == NULL) 345254700Sjilles ped->fp = fopen(_PATH_PROTOCOLS, "re"); 3461573Srgrimes else 347145279Sume rewind(ped->fp); 348145279Sume ped->stayopen |= f; 3491573Srgrimes} 3501573Srgrimes 3511573Srgrimesvoid 352157779Sume__endprotoent_p(struct protoent_data *ped) 3531573Srgrimes{ 354145279Sume if (ped->fp) { 355145279Sume fclose(ped->fp); 356145279Sume ped->fp = NULL; 3571573Srgrimes } 358145279Sume ped->stayopen = 0; 3591573Srgrimes} 3601573Srgrimes 361145279Sumeint 362157779Sume__getprotoent_p(struct protoent *pe, struct protoent_data *ped) 3631573Srgrimes{ 3641573Srgrimes char *p; 365145279Sume char *cp, **q, *endp; 366145279Sume long l; 3671573Srgrimes 368254700Sjilles if (ped->fp == NULL && (ped->fp = fopen(_PATH_PROTOCOLS, "re")) == NULL) 369145279Sume return (-1); 3701573Srgrimesagain: 371145626Sume if ((p = fgets(ped->line, sizeof ped->line, ped->fp)) == NULL) 372145279Sume return (-1); 3731573Srgrimes if (*p == '#') 3741573Srgrimes goto again; 3751573Srgrimes cp = strpbrk(p, "#\n"); 376139612Ssobomax if (cp != NULL) 377139612Ssobomax *cp = '\0'; 378145279Sume pe->p_name = p; 3791573Srgrimes cp = strpbrk(p, " \t"); 3801573Srgrimes if (cp == NULL) 3811573Srgrimes goto again; 3821573Srgrimes *cp++ = '\0'; 3831573Srgrimes while (*cp == ' ' || *cp == '\t') 3841573Srgrimes cp++; 3851573Srgrimes p = strpbrk(cp, " \t"); 3861573Srgrimes if (p != NULL) 3871573Srgrimes *p++ = '\0'; 388145279Sume l = strtol(cp, &endp, 10); 389145279Sume if (endp == cp || *endp != '\0' || l < 0 || l > USHRT_MAX) 390145279Sume goto again; 391145279Sume pe->p_proto = l; 392145279Sume q = pe->p_aliases = ped->aliases; 3931573Srgrimes if (p != NULL) { 3941573Srgrimes cp = p; 3951573Srgrimes while (cp && *cp) { 3961573Srgrimes if (*cp == ' ' || *cp == '\t') { 3971573Srgrimes cp++; 3981573Srgrimes continue; 3991573Srgrimes } 400145626Sume if (q < &ped->aliases[_MAXALIASES - 1]) 4011573Srgrimes *q++ = cp; 4021573Srgrimes cp = strpbrk(cp, " \t"); 4031573Srgrimes if (cp != NULL) 4041573Srgrimes *cp++ = '\0'; 4051573Srgrimes } 4061573Srgrimes } 4071573Srgrimes *q = NULL; 408145279Sume return (0); 4091573Srgrimes} 410145279Sume 411158115Sumestatic int 412158115Sumefiles_getprotoent_r(void *retval, void *mdata, va_list ap) 413157779Sume{ 414157779Sume struct protoent pe; 415157779Sume struct protoent_data *ped; 416157779Sume 417158115Sume struct protoent *pptr; 418158115Sume char *buffer; 419158115Sume size_t buflen; 420158115Sume int *errnop; 421158115Sume 422158115Sume pptr = va_arg(ap, struct protoent *); 423158115Sume buffer = va_arg(ap, char *); 424158115Sume buflen = va_arg(ap, size_t); 425158115Sume errnop = va_arg(ap, int *); 426158115Sume 427211276Sume if ((ped = __protoent_data_init()) == NULL) { 428211276Sume *errnop = errno; 429211276Sume return (NS_NOTFOUND); 430211276Sume } 431157779Sume 432158115Sume if (__getprotoent_p(&pe, ped) != 0) { 433158115Sume *errnop = errno; 434158115Sume return (NS_NOTFOUND); 435158115Sume } 436158115Sume 437158115Sume if (__copy_protoent(&pe, pptr, buffer, buflen) != 0) { 438158115Sume *errnop = errno; 439211276Sume return (NS_RETURN); 440158115Sume } 441158115Sume 442158115Sume *((struct protoent **)retval) = pptr; 443158115Sume return (NS_SUCCESS); 444157779Sume} 445157779Sume 446158115Sumestatic int 447158115Sumefiles_setprotoent(void *retval, void *mdata, va_list ap) 448145279Sume{ 449157779Sume struct protoent_data *ped; 450158115Sume int f; 451145279Sume 452158115Sume f = va_arg(ap, int); 453157779Sume if ((ped = __protoent_data_init()) == NULL) 454158115Sume return (NS_UNAVAIL); 455158115Sume 456157779Sume __setprotoent_p(f, ped); 457158115Sume return (NS_UNAVAIL); 458145279Sume} 459145279Sume 460158115Sumestatic int 461158115Sumefiles_endprotoent(void *retval, void *mdata, va_list ap) 462145279Sume{ 463157779Sume struct protoent_data *ped; 464145279Sume 465157779Sume if ((ped = __protoent_data_init()) == NULL) 466158115Sume return (NS_UNAVAIL); 467158115Sume 468157779Sume __endprotoent_p(ped); 469158115Sume return (NS_UNAVAIL); 470145279Sume} 471145279Sume 472158115Sumeint 473158115Sumegetprotoent_r(struct protoent *pptr, char *buffer, size_t buflen, 474158115Sume struct protoent **result) 475158115Sume{ 476158115Sume#ifdef NS_CACHING 477158115Sume static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER( 478158115Sume protocols, (void *)nss_lt_all, 479158115Sume __proto_marshal_func, __proto_unmarshal_func); 480158115Sume#endif 481158115Sume static const ns_dtab dtab[] = { 482158115Sume { NSSRC_FILES, files_getprotoent_r, (void *)nss_lt_all }, 483158115Sume#ifdef NS_CACHING 484158115Sume NS_CACHE_CB(&cache_info) 485158115Sume#endif 486158115Sume { NULL, NULL, NULL } 487158115Sume }; 488158115Sume int rv, ret_errno; 489158115Sume 490158115Sume ret_errno = 0; 491158115Sume *result = NULL; 492158115Sume rv = nsdispatch(result, dtab, NSDB_PROTOCOLS, "getprotoent_r", 493158115Sume defaultsrc, pptr, buffer, buflen, &ret_errno); 494158115Sume 495211276Sume if (rv != NS_SUCCESS) { 496211276Sume errno = ret_errno; 497213453Sume return (ret_errno); 498211276Sume } 499211276Sume return (0); 500158115Sume} 501158115Sume 502158115Sumevoid 503158115Sumesetprotoent(int stayopen) 504158115Sume{ 505158115Sume#ifdef NS_CACHING 506158115Sume static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER( 507158115Sume protocols, (void *)nss_lt_all, 508158115Sume NULL, NULL); 509158115Sume#endif 510158115Sume 511158115Sume static const ns_dtab dtab[] = { 512158115Sume { NSSRC_FILES, files_setprotoent, NULL }, 513158115Sume#ifdef NS_CACHING 514158115Sume NS_CACHE_CB(&cache_info) 515158115Sume#endif 516158115Sume { NULL, NULL, NULL } 517158115Sume }; 518158115Sume 519158115Sume (void)nsdispatch(NULL, dtab, NSDB_PROTOCOLS, "setprotoent", defaultsrc, 520158115Sume stayopen); 521158115Sume} 522158115Sume 523158115Sumevoid 524158115Sumeendprotoent(void) 525158115Sume{ 526158115Sume#ifdef NS_CACHING 527158115Sume static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER( 528158115Sume protocols, (void *)nss_lt_all, 529158115Sume NULL, NULL); 530158115Sume#endif 531158115Sume 532158115Sume static const ns_dtab dtab[] = { 533158115Sume { NSSRC_FILES, files_endprotoent, NULL }, 534158115Sume#ifdef NS_CACHING 535158115Sume NS_CACHE_CB(&cache_info) 536158115Sume#endif 537158115Sume { NULL, NULL, NULL } 538158115Sume }; 539158115Sume 540158115Sume (void)nsdispatch(NULL, dtab, NSDB_PROTOCOLS, "endprotoent", defaultsrc); 541158115Sume} 542158115Sume 543145279Sumestruct protoent * 544145279Sumegetprotoent(void) 545145279Sume{ 546145279Sume struct protodata *pd; 547157779Sume struct protoent *rval; 548145279Sume 549145279Sume if ((pd = __protodata_init()) == NULL) 550145279Sume return (NULL); 551157779Sume if (getprotoent_r(&pd->proto, pd->data, sizeof(pd->data), &rval) != 0) 552145279Sume return (NULL); 553157779Sume return (rval); 554145279Sume} 555