Print this page
OS-4348 libnsl should seek netconfig file in native root
Reviewed by: Robert Mustacchi <rm@joyent.com>
OS-3812 lxbrand nfs mounting fails
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/libnsl/netselect/netselect.c
+++ new/usr/src/lib/libnsl/netselect/netselect.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 + * Copyright 2015 Joyent, Inc.
25 26 */
26 27
27 28 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
28 29 /* All Rights Reserved */
29 30
30 31 /*
31 32 * Portions of this source code were derived from Berkeley 4.3 BSD
32 33 * under license from the Regents of the University of California.
33 34 */
34 35
35 -#pragma ident "%Z%%M% %I% %E% SMI"
36 -
37 36 #include "mt.h"
38 37 #include "../rpc/rpc_mt.h" /* for MT declarations only */
39 38 #include <rpc/types.h>
40 39 #include <stdio.h>
41 40 #include <stdlib.h>
42 41 #include <string.h>
43 42 #include <ctype.h>
44 43 #include <netconfig.h>
45 44 #include <malloc.h>
46 45 #include <libintl.h>
47 46 #include <syslog.h>
47 +#include <zone.h>
48 48 #include "netcspace.h"
49 49
50 50 #define FAILURE (unsigned)(-1)
51 51
52 52 /*
53 53 * Local routines used by the library procedures
54 54 */
55 55
56 56 static int blank(char *);
57 57 static int comment(char *);
58 58 static struct netconfig *fgetnetconfig(FILE *, char *);
59 59 static void netconfig_free(struct netconfig *);
60 60 static unsigned int getflag(char *);
61 61 static char **getlookups(char *);
62 62 static struct netconfig **getnetlist(void);
|
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
63 63 static unsigned int getnlookups(char *);
64 64 static char *gettoken(char *, int);
65 65 static unsigned int getvalue(char *, struct nc_data nc_data[]);
66 66 static void shift1left(char *);
67 67 static void netlist_free(struct netconfig ***);
68 68 static void free_entry(void *);
69 69 static struct netconfig *netconfig_dup(struct netconfig *);
70 70
71 71 extern const char __nsl_dom[];
72 72
73 +static int (*brand_get_sz)(void) = NULL;
74 +static struct netconfig *(*brand_get_net_ent)(int) = NULL;
75 +
73 76 /*
74 77 * Static global variables used by the library procedures:
75 78 *
76 79 * netpp - points to the beginning of the list of netconfig
77 80 * entries used by setnetconfig() and setnetpath().
78 81 * Once netpp is initialized, that memory is *never*
79 82 * released. This was necessary to improve performance.
80 83 *
81 84 * linenum - the current line number of the /etc/netconfig
82 85 * file (used for debugging and for nc_perror()).
83 86 *
84 87 * fieldnum - the current field number of the current line
85 88 * of /etc/netconfig (used for debugging and for
86 89 * nc_perror()).
87 90 *
88 91 * nc_error - the error condition encountered.
89 92 */
90 93
91 94 static struct netconfig **netpp = NULL;
92 95 mutex_t netpp_mutex = DEFAULTMUTEX;
93 96 /*
94 97 * The following two variables are used by the /etc/netconfig parsing
95 98 * routines, which will always be executed once, and within the netpp_mutex.
96 99 * They are global to allow the nc_sperror routine to provide better
97 100 * information to the user about /etc/netconfig file problems.
98 101 */
99 102 static int linenum = 0; /* "owned" by getnetlist() */
100 103 static int fieldnum = 0; /* "owned" by fgetnetconfig() */
101 104
102 105
103 106 static int *
104 107 __nc_error(void)
105 108 {
106 109 static pthread_key_t nc_error_key = PTHREAD_ONCE_KEY_NP;
107 110 static int nc_error = NC_NOERROR;
108 111 int *ret;
109 112
110 113 if (thr_main())
111 114 return (&nc_error);
112 115 ret = thr_get_storage(&nc_error_key, sizeof (int), free);
113 116 /* if thr_get_storage fails we return the address of nc_error */
114 117 return (ret ? ret : &nc_error);
115 118 }
116 119 #define nc_error (*(__nc_error()))
117 120
118 121 /*
119 122 * setnetconfig() has the effect of "initializing" the
120 123 * network configuration database. It reads in the
121 124 * netcf entries (if not already read in).
122 125 */
123 126
124 127 void *
125 128 setnetconfig(void)
126 129 {
127 130 NCONF_HANDLE *retp;
128 131
129 132 (void) mutex_lock(&netpp_mutex);
130 133 if ((netpp == NULL) && ((netpp = getnetlist()) == NULL)) {
131 134 (void) mutex_unlock(&netpp_mutex);
132 135 return (NULL);
133 136 }
134 137 (void) mutex_unlock(&netpp_mutex);
135 138 if ((retp = malloc(sizeof (NCONF_HANDLE))) == NULL) {
136 139 nc_error = NC_NOMEM;
137 140 return (NULL);
138 141 }
139 142 nc_error = NC_NOERROR;
140 143 retp->nc_head = retp->nc_curr = netpp;
141 144 return ((void *)retp);
142 145 }
143 146
144 147 /*
145 148 * endnetconfig() frees up all data allocated by setnetconfig()
146 149 */
147 150
148 151 int
149 152 endnetconfig(void *vdata)
150 153 {
151 154 NCONF_HANDLE *nconf_handlep = (NCONF_HANDLE *)vdata;
152 155
153 156 (void) mutex_lock(&netpp_mutex);
154 157 if (netpp == NULL || nconf_handlep == NULL) {
155 158 nc_error = NC_NOSET;
156 159 (void) mutex_unlock(&netpp_mutex);
157 160 return (-1);
158 161 }
159 162 (void) mutex_unlock(&netpp_mutex);
160 163
161 164 nc_error = NC_NOERROR;
162 165 free(nconf_handlep);
163 166 return (0);
164 167 }
165 168
166 169 /*
167 170 * getnetconfig() returns the current entry in the list
168 171 * of netconfig structures. It uses the nconf_handlep argument
169 172 * to determine the current entry. If setnetconfig() was not
170 173 * called previously to set up the list, return failure.
171 174 * It also check if ipv6 interface is present(ipv6_present) and
172 175 * skips udp6 & tcp6 entries if ipv6 is not supported.
173 176 */
174 177
175 178 struct netconfig *
176 179 getnetconfig(void *vdata)
177 180 {
178 181 NCONF_HANDLE *nconf_handlep = (NCONF_HANDLE *)vdata;
179 182 struct netconfig *retp; /* holds the return value */
180 183 int ipv6_present = -1;
181 184
182 185 (void) mutex_lock(&netpp_mutex);
183 186 if ((netpp == NULL) || (nconf_handlep == NULL)) {
184 187 nc_error = NC_NOSET;
185 188 (void) mutex_unlock(&netpp_mutex);
186 189 return (NULL);
187 190 }
188 191 (void) mutex_unlock(&netpp_mutex);
189 192 for (;;) {
190 193 retp = *(nconf_handlep->nc_curr);
191 194 if (retp && (strcmp(retp->nc_netid, "udp6") == 0 ||
192 195 strcmp(retp->nc_netid, "tcp6") == 0)) {
193 196 if (ipv6_present == -1)
194 197 ipv6_present = __can_use_af(AF_INET6);
195 198 if (!ipv6_present) {
196 199 ++(nconf_handlep->nc_curr);
197 200 continue;
198 201 }
199 202 }
200 203 break;
201 204 }
202 205 if (retp != NULL) {
203 206 ++(nconf_handlep->nc_curr);
204 207 nc_error = NC_NOERROR;
205 208 } else {
206 209 nc_error = NC_NOMOREENTRIES;
207 210 }
208 211 return (retp);
209 212 }
210 213
211 214 /*
212 215 * getnetconfig() searches the netconfig database for a
213 216 * given network id. Returns a pointer to the netconfig
214 217 * structure or a NULL if not found.
215 218 * It also check if ipv6 interface is present(ipv6_present) and
216 219 * skips udp6 & tcp6 entries if ipv6 is not supported.
217 220 */
218 221
219 222 struct netconfig *
220 223 getnetconfigent(const char *netid)
221 224 {
222 225 struct netconfig **tpp;
223 226 int ipv6_present;
224 227
225 228 (void) mutex_lock(&netpp_mutex);
226 229 if ((netpp == NULL) && ((netpp = getnetlist()) == NULL)) {
227 230 (void) mutex_unlock(&netpp_mutex);
228 231 return (NULL);
229 232 }
230 233 (void) mutex_unlock(&netpp_mutex);
231 234 for (tpp = netpp; *tpp; tpp++) {
232 235 if (strcmp((*tpp)->nc_netid, netid) == 0) {
233 236 if (*tpp && (strcmp((*tpp)->nc_netid, "udp6") == 0 ||
234 237 strcmp((*tpp)->nc_netid, "tcp6") == 0)) {
235 238 ipv6_present = __can_use_af(AF_INET6);
236 239 if (!ipv6_present) {
237 240 nc_error = NC_NOTFOUND;
238 241 return (NULL);
239 242 }
240 243 }
241 244 return (netconfig_dup(*tpp));
242 245 }
243 246 }
244 247 nc_error = NC_NOTFOUND;
245 248 return (NULL);
246 249 }
247 250
|
↓ open down ↓ |
165 lines elided |
↑ open up ↑ |
248 251 /*
249 252 * freenetconfigent frees the data allocated by getnetconfigent()
250 253 */
251 254
252 255 void
253 256 freenetconfigent(struct netconfig *netp)
254 257 {
255 258 netconfig_free(netp);
256 259 }
257 260
261 +void
262 +_nsl_brand_set_hooks(int (*set_sz_func)(void),
263 + struct netconfig *(*get_ent_func)(int))
264 +{
265 + brand_get_sz = set_sz_func;
266 + brand_get_net_ent = get_ent_func;
267 +}
268 +
258 269 /*
259 270 * getnetlist() reads the netconfig file and creates a
260 271 * NULL-terminated list of entries.
261 272 * Returns the pointer to the head of the list or a NULL
262 273 * on failure.
263 274 */
264 275
265 276 static struct netconfig **
266 277 getnetlist(void)
267 278 {
268 - char line[BUFSIZ]; /* holds each line of NETCONFIG */
269 - FILE *fp; /* file stream for NETCONFIG */
279 + FILE *fp = NULL; /* file stream for NETCONFIG */
270 280 struct netconfig **listpp; /* the beginning of the netconfig list */
271 281 struct netconfig **tpp; /* used to traverse the netconfig list */
272 282 int count; /* the number of entries in file */
283 + char nc_path[MAXPATHLEN];
284 + const char *zroot = zone_get_nroot();
273 285
274 - if ((fp = fopen(NETCONFIG, "rF")) == NULL) {
275 - nc_error = NC_OPENFAIL;
276 - return (NULL);
277 - }
286 + /*
287 + * If we are running in a branded zone, ensure we use the "/native"
288 + * prefix when opening the netconfig file:
289 + */
290 + (void) snprintf(nc_path, sizeof (nc_path), "%s%s", zroot != NULL ?
291 + zroot : "", NETCONFIG);
278 292
279 - count = 0;
280 - while (fgets(line, BUFSIZ, fp)) {
281 - if (!(blank(line) || comment(line))) {
282 - ++count;
293 + if (brand_get_sz != NULL) {
294 + count = brand_get_sz();
295 + } else {
296 + char line[BUFSIZ]; /* holds each line of NETCONFIG */
297 +
298 + if ((fp = fopen(nc_path, "rF")) == NULL) {
299 + nc_error = NC_OPENFAIL;
300 + return (NULL);
283 301 }
302 +
303 + count = 0;
304 + while (fgets(line, BUFSIZ, fp)) {
305 + if (!(blank(line) || comment(line))) {
306 + ++count;
307 + }
308 + }
309 + rewind(fp);
284 310 }
285 - rewind(fp);
286 311
287 312 if (count == 0) {
288 313 nc_error = NC_NOTFOUND;
289 - (void) fclose(fp);
314 + if (fp != NULL)
315 + (void) fclose(fp);
290 316 return (NULL);
291 317 }
318 +
292 319 if ((listpp = malloc((count + 1) *
293 320 sizeof (struct netconfig *))) == NULL) {
294 321 nc_error = NC_NOMEM;
295 - (void) fclose(fp);
322 + if (fp != NULL)
323 + (void) fclose(fp);
296 324 return (NULL);
297 325 }
298 326
299 - /*
300 - * The following loop fills in the list (loops until
301 - * fgetnetconfig() returns a NULL) and counts the
302 - * number of entries placed in the list. Note that
303 - * when the loop is completed, the last entry in the
304 - * list will contain a NULL (signifying the end of
305 - * the list).
306 - */
307 - linenum = 0;
308 - for (tpp = listpp; *tpp = fgetnetconfig(fp, NULL); tpp++)
309 - ;
310 - (void) fclose(fp);
327 + if (brand_get_net_ent != NULL) {
328 + int i;
311 329
312 - if (nc_error != NC_NOMOREENTRIES) /* Something is screwed up */
313 - netlist_free(&listpp);
330 + tpp = listpp;
331 + for (i = 0; i < count; i++) {
332 + *tpp = brand_get_net_ent(i);
333 + tpp++;
334 + }
335 + *tpp = NULL;
336 + nc_error = NC_NOMOREENTRIES;
337 + } else {
338 + /*
339 + * The following loop fills in the list (loops until
340 + * fgetnetconfig() returns a NULL) and counts the
341 + * number of entries placed in the list. Note that
342 + * when the loop is completed, the last entry in the
343 + * list will contain a NULL (signifying the end of
344 + * the list).
345 + */
346 + linenum = 0;
347 + for (tpp = listpp; *tpp = fgetnetconfig(fp, NULL); tpp++)
348 + ;
349 + (void) fclose(fp);
350 +
351 + if (nc_error != NC_NOMOREENTRIES) /* Something is screwed up */
352 + netlist_free(&listpp);
353 + }
354 +
314 355 return (listpp);
315 356 }
316 357
317 358 /*
318 359 * fgetnetconfig() parses a line of the netconfig file into
319 360 * a netconfig structure. It returns a pointer to the
320 361 * structure of success and a NULL on failure or EOF.
321 362 */
322 363
323 364 static struct netconfig *
324 365 fgetnetconfig(FILE *fp, char *netid)
325 366 {
326 367 char linep[BUFSIZ]; /* pointer to a line in the file */
327 368 struct netconfig *netconfigp; /* holds the new netconfig structure */
328 369 char *tok1, *tok2, *tok3; /* holds a token from the line */
329 370 char *retvalp; /* the return value of fgets() */
330 371 char *entnetid; /* netid for the current entry */
331 372
332 373 /* skip past blank lines and comments. */
333 374 while (retvalp = fgets(linep, BUFSIZ, fp)) {
334 375 linenum++;
335 376 if (!(blank(linep) || comment(linep))) {
336 377 break;
337 378 }
338 379 retvalp = NULL;
339 380 }
340 381 if (retvalp == NULL) {
341 382 nc_error = NC_NOMOREENTRIES;
342 383 return (NULL);
343 384 }
344 385 fieldnum = 0;
345 386 if ((entnetid = gettoken(linep, FALSE)) == NULL) {
346 387 nc_error = NC_BADLINE;
347 388 return (NULL);
348 389 }
349 390 if (netid && (strcmp(netid, entnetid) != 0)) {
350 391 free(entnetid);
351 392 nc_error = NC_NOTFOUND;
352 393 return (NULL);
353 394 }
354 395 if ((netconfigp = calloc(1, sizeof (struct netconfig))) == NULL) {
355 396 free(entnetid);
356 397 nc_error = NC_NOMEM;
357 398 return (NULL);
358 399 }
359 400
360 401 tok1 = tok2 = tok3 = NULL;
361 402 netconfigp->nc_netid = entnetid;
362 403 if (((tok1 = gettoken(NULL, FALSE)) == NULL) ||
363 404 ((netconfigp->nc_semantics =
364 405 getvalue(tok1, nc_semantics)) == FAILURE) ||
365 406 ((tok2 = gettoken(NULL, FALSE)) == NULL) ||
366 407 ((netconfigp->nc_flag = getflag(tok2)) == FAILURE) ||
367 408 ((netconfigp->nc_protofmly = gettoken(NULL, FALSE)) == NULL) ||
368 409 ((netconfigp->nc_proto = gettoken(NULL, FALSE)) == NULL) ||
369 410 ((netconfigp->nc_device = gettoken(NULL, FALSE)) == NULL) ||
370 411 ((tok3 = gettoken(NULL, TRUE)) == NULL) ||
371 412 (((netconfigp->nc_nlookups = getnlookups(tok3)) != 0) &&
372 413 ((netconfigp->nc_lookups = getlookups(tok3)) == NULL))) {
373 414 netconfig_free(netconfigp);
374 415 nc_error = NC_BADLINE;
375 416 netconfigp = NULL;
376 417 }
377 418 free(tok1);
378 419 free(tok2);
379 420 free(tok3);
380 421 return (netconfigp);
381 422 }
382 423
383 424 /*
384 425 * setnetpath() has the effect of "initializing" the
385 426 * NETPATH variable. It reads in the netcf entries (if not
386 427 * already read in), creates a list corresponding to the entries
387 428 * in the NETPATH variable (or the "visible" entries og netconfig
388 429 * if NETPATH is not set).
389 430 */
390 431
391 432 void *
392 433 setnetpath(void)
393 434 {
394 435 int count; /* the number of entries in NETPATH */
395 436 char valid_netpath[BUFSIZ]; /* holds the valid entries if NETPATH */
396 437 char templine[BUFSIZ]; /* has value of NETPATH when scanning */
397 438 struct netconfig **curr_pp; /* scans the list from NETPATH */
398 439 struct netconfig **tpp; /* scans the list from netconfig file */
399 440 struct netconfig **rnetpp; /* the list of entries from NETPATH */
400 441 char *netpath; /* value of NETPATH from environment */
401 442 char *netid; /* holds a component of NETPATH */
402 443 char *tp; /* used to scan NETPATH string */
403 444 NCONF_HANDLE *retp; /* the return value */
404 445
405 446 /*
406 447 * Read in the netconfig database if not already read in
407 448 */
408 449 (void) mutex_lock(&netpp_mutex);
409 450 if ((netpp == NULL) && ((netpp = getnetlist()) == NULL)) {
410 451 (void) mutex_unlock(&netpp_mutex);
411 452 return (NULL);
412 453 }
413 454 (void) mutex_unlock(&netpp_mutex);
414 455
415 456 if ((retp = malloc(sizeof (NCONF_HANDLE))) == NULL) {
416 457 nc_error = NC_NOMEM;
417 458 return (NULL);
418 459 }
419 460
420 461 /*
421 462 * Get the valid entries of the NETPATH variable (and
422 463 * count the number of entries while doing it).
423 464 *
424 465 * This is done every time the procedure is called just
425 466 * in case NETPATH has changed from call to call.
426 467 *
427 468 * If NETPATH is too long, we ignore it altogether as
428 469 * it can only be a buffer overflow attack.
429 470 * Since we add one colon for each entry, but colons only
430 471 * need to exist between entries, we have to subtract one.
431 472 */
432 473 count = 0;
433 474 valid_netpath[0] = '\0';
434 475 if ((netpath = getenv(NETPATH)) == NULL ||
435 476 strlen(netpath) >= sizeof (templine) - 1) {
436 477 /*
437 478 * If NETPATH variable is not set or invalid,
438 479 * the valid NETPATH consist of all "visible"
439 480 * netids from the netconfig database.
440 481 */
441 482
442 483 for (tpp = netpp; *tpp; tpp++) {
443 484 if ((*tpp)->nc_flag & NC_VISIBLE) {
444 485 (void) strcat(valid_netpath, (*tpp)->nc_netid);
445 486 (void) strcat(valid_netpath, ":");
446 487 count++;
447 488 }
448 489 }
449 490 } else {
450 491
451 492 /*
452 493 * Copy the value of NETPATH (since '\0's will be
453 494 * put into the string) and create the valid NETPATH
454 495 * (by throwing away all netids not in the database).
455 496 * If an entry appears more than one, it *will* be
456 497 * listed twice in the list of valid netpath entries.
457 498 */
458 499
459 500 (void) strcpy(templine, netpath);
460 501 tp = templine;
461 502
462 503 while (*tp) {
463 504 /* Skip all leading ':'s */
464 505 while (*tp && *tp == ':')
465 506 tp++;
466 507 if (*tp == NULL)
467 508 break; /* last one */
468 509 netid = tp;
469 510 while (*tp && *tp != ':')
470 511 tp++;
471 512 if (*tp)
472 513 *tp++ = '\0'; /* isolate netid */
473 514
474 515 for (tpp = netpp; *tpp; tpp++) {
475 516 if (strcmp(netid, (*tpp)->nc_netid) == 0) {
476 517 (void) strcat(valid_netpath,
477 518 (*tpp)->nc_netid);
478 519 (void) strcat(valid_netpath, ":");
479 520 count++;
480 521 break;
481 522 }
482 523 }
483 524 }
484 525 }
485 526
486 527 /* Get space to hold the valid list (+1 for the NULL) */
487 528
488 529 if ((rnetpp = malloc((count + 1) *
489 530 sizeof (struct netconfig *))) == NULL) {
490 531 free(retp);
491 532 nc_error = NC_NOMEM;
492 533 return (NULL);
493 534 }
494 535
495 536 /*
496 537 * Populate the NETPATH list, ending it with a NULL.
497 538 * Each entry in the list points to the structure in the
498 539 * "netpp" list (the entry must exist in the list, otherwise
499 540 * it wouldn't appear in valid_netpath[]).
500 541 */
501 542
502 543 curr_pp = rnetpp;
503 544 netid = tp = valid_netpath;
504 545 while (*tp) {
505 546 netid = tp;
506 547 while (*tp && *tp != ':')
507 548 tp++;
508 549 if (*tp)
509 550 *tp++ = '\0';
510 551 for (tpp = netpp; *tpp; tpp++) {
511 552 if (strcmp(netid, (*tpp)->nc_netid) == 0) {
512 553 *curr_pp++ = *tpp;
513 554 break;
514 555 }
515 556 }
516 557 }
517 558 *curr_pp = NULL;
518 559
519 560 retp->nc_curr = retp->nc_head = rnetpp;
520 561 return ((void *)retp);
521 562 }
522 563
523 564 /*
524 565 * endnetpath() frees up all of the memory allocated by setnetpath().
525 566 * It returns -1 (error) if setnetpath was never called.
526 567 */
527 568
528 569 int
529 570 endnetpath(void *vdata)
530 571 {
531 572 /* The argument is really a NCONF_HANDLE; cast it here */
532 573 NCONF_HANDLE *nconf_handlep = (NCONF_HANDLE *)vdata;
533 574
534 575 (void) mutex_lock(&netpp_mutex);
535 576 if (netpp == NULL || nconf_handlep == NULL) {
536 577 nc_error = NC_NOSET;
537 578 (void) mutex_unlock(&netpp_mutex);
538 579 return (-1);
539 580 }
540 581 (void) mutex_unlock(&netpp_mutex);
541 582
542 583 free(nconf_handlep->nc_head);
543 584 free(nconf_handlep);
544 585 return (0);
545 586 }
546 587
547 588 /*
548 589 * getnetpath() returns the current entry in the list
549 590 * from the NETPATH variable. If setnetpath() was not called
550 591 * previously to set up the list, return NULL.
551 592 */
552 593
553 594 struct netconfig *
554 595 getnetpath(void *vdata)
555 596 {
556 597 /* The argument is really a NCONF_HANDLE; cast it here */
557 598 NCONF_HANDLE *nconf_handlep = (NCONF_HANDLE *)vdata;
558 599 struct netconfig *retp; /* holds the return value */
559 600 int ipv6_present = -1;
560 601
561 602 (void) mutex_lock(&netpp_mutex);
562 603 if (netpp == NULL) {
563 604 nc_error = NC_NOSET;
564 605 (void) mutex_unlock(&netpp_mutex);
565 606 return (NULL);
566 607 }
567 608 (void) mutex_unlock(&netpp_mutex);
568 609 for (;;) {
569 610 retp = *(nconf_handlep->nc_curr);
570 611 if (retp && (strcmp(retp->nc_netid, "udp6") == 0 ||
571 612 strcmp(retp->nc_netid, "tcp6") == 0)) {
572 613 if (ipv6_present == -1)
573 614 ipv6_present = __can_use_af(AF_INET6);
574 615 if (!ipv6_present) {
575 616 ++(nconf_handlep->nc_curr);
576 617 continue;
577 618 }
578 619 }
579 620 break;
580 621 }
581 622 if (retp) {
582 623 ++(nconf_handlep->nc_curr);
583 624 nc_error = NC_NOERROR;
584 625 } else {
585 626 nc_error = NC_NOMOREENTRIES;
586 627 }
587 628
588 629 return (retp);
589 630 }
590 631
591 632 /*
592 633 * blank() returns true if the line is a blank line, 0 otherwise
593 634 */
594 635
595 636 static int
596 637 blank(char *cp)
597 638 {
598 639 while (*cp && isspace(*cp)) {
599 640 cp++;
600 641 }
601 642 return (*cp == '\0');
602 643 }
603 644
604 645 /*
605 646 * comment() returns true if the line is a comment, 0 otherwise.
606 647 */
607 648
608 649 static int
609 650 comment(char *cp)
610 651 {
611 652 while (*cp && isspace(*cp)) {
612 653 cp++;
613 654 }
614 655 return (*cp == '#');
615 656 }
616 657
617 658 /*
618 659 * getvalue() searches for the given string in the given array,
619 660 * and return the integer value associated with the string.
620 661 */
621 662
622 663 static unsigned int
623 664 getvalue(char *cp, struct nc_data nc_data[])
624 665 {
625 666 int i; /* used to index through the given struct nc_data array */
626 667
627 668 for (i = 0; nc_data[i].string; i++) {
628 669 if (strcmp(nc_data[i].string, cp) == 0) {
629 670 break;
630 671 }
631 672 }
632 673 return (nc_data[i].value);
633 674 }
634 675
635 676 /*
636 677 * getflag() creates a bitmap of the one-character flags in
637 678 * the given string. It uses nc_flags array to get the values.
638 679 */
639 680
640 681 static unsigned int
641 682 getflag(char *cp)
642 683 {
643 684 int i; /* indexs through the nc_flag array */
644 685 unsigned int mask = 0; /* holds bitmask of flags */
645 686
646 687 while (*cp) {
647 688 for (i = 0; nc_flag[i].string; i++) {
648 689 if (*nc_flag[i].string == *cp) {
649 690 mask |= nc_flag[i].value;
650 691 break;
651 692 }
652 693 }
653 694 cp++;
654 695 }
655 696 return (mask);
656 697 }
657 698
658 699 /*
659 700 * getlookups() creates and returns an array of string representing
660 701 * the directory lookup libraries, given as a comma-seperated list
661 702 * in the argument "cp".
662 703 */
663 704
664 705 static char **
665 706 getlookups(char *cp)
666 707 {
667 708 unsigned int num; /* holds the number of entries in the list */
668 709 char **listpp; /* the beginning of the list of dir routines */
669 710 char **tpp; /* traverses the list, populating it */
670 711 char *start;
671 712
672 713 num = getnlookups(cp);
673 714 if (num == 0)
674 715 return (NULL);
675 716 if ((listpp = malloc((num + 1) * sizeof (char *))) == NULL)
676 717 return (NULL);
677 718
678 719 tpp = listpp;
679 720 while (num--) {
680 721 start = cp;
681 722
682 723 /*
683 724 * Traverse the string looking for the next entry
684 725 * of the list (i.e, where the ',' or end of the
685 726 * string appears). If a "\" is found, shift the
686 727 * token over 1 to the left (taking the next char
687 728 * literally).
688 729 */
689 730
690 731 while (*cp && *cp != ',') {
691 732 if (*cp == '\\' && *(cp + 1)) {
692 733 shift1left(cp);
693 734 }
694 735 cp++;
695 736 }
696 737 if (*cp)
697 738 *cp++ = '\0';
698 739 if ((*tpp++ = strdup(start)) == NULL) {
699 740 for (tpp = listpp; *tpp; tpp++)
700 741 free(*tpp);
701 742 free(listpp);
702 743 return (NULL);
703 744 }
704 745 }
705 746 *tpp = NULL;
706 747 return (listpp);
707 748 }
708 749
709 750 /*
710 751 * getnlookups() returns the number of entries in a comma-separated
711 752 * string of tokens. A "-" means no strings are present.
712 753 */
713 754
714 755 static unsigned int
715 756 getnlookups(char *cp)
716 757 {
717 758 unsigned int count; /* the number of tokens in the string */
718 759
719 760 if (strcmp(cp, "-") == 0)
720 761 return (0);
721 762
722 763 count = 1;
723 764 while (*cp) {
724 765 if (*cp == ',') {
725 766 count++;
726 767 }
727 768
728 769 /*
729 770 * If a "\" is in the string, take the next character
730 771 * literally. Onlly skip the character if "\" is
731 772 * not the last character of the token.
732 773 */
733 774 if (*cp == '\\' && *(cp + 1)) {
734 775 cp++;
735 776 }
736 777 cp++;
737 778 }
738 779 return (count);
739 780 }
740 781
741 782 /*
742 783 * gettoken() behaves much like strtok(), except that
743 784 * it knows about escaped space characters (i.e., space characters
744 785 * preceeded by a '\' are taken literally).
745 786 */
746 787
747 788 static char *
748 789 gettoken(char *cp, int skip)
749 790 {
750 791 static char *savep; /* the place where we left off */
751 792 char *p; /* the beginning of the new token */
752 793 char *retp; /* the token to be returned */
753 794
754 795 fieldnum++;
755 796
756 797 /* Determine if first or subsequent call */
757 798 p = (cp == NULL)? savep: cp;
758 799
759 800 /* Return if no tokens remain. */
760 801 if (p == 0)
761 802 return (NULL);
762 803
763 804 while (isspace(*p))
764 805 p++;
765 806
766 807 if (*p == '\0')
767 808 return (NULL);
768 809
769 810 /*
770 811 * Save the location of the token and then skip past it
771 812 */
772 813
773 814 retp = p;
774 815 while (*p) {
775 816 if (isspace(*p))
776 817 if (skip == TRUE) {
777 818 shift1left(p);
778 819 continue;
779 820 } else
780 821 break;
781 822 /*
782 823 * Only process the escape of the space seperator;
783 824 * since the token may contain other separators,
784 825 * let the other routines handle the escape of
785 826 * specific characters in the token.
786 827 */
787 828
788 829 if (*p == '\\' && *(p + 1) != '\n' && isspace(*(p + 1))) {
789 830 shift1left(p);
790 831 }
791 832 p++;
792 833 }
793 834 if (*p == '\0') {
794 835 savep = 0; /* indicate this is last token */
795 836 } else {
796 837 *p = '\0';
797 838 savep = ++p;
798 839 }
799 840 return (strdup(retp));
800 841 }
801 842
802 843 /*
803 844 * shift1left() moves all characters in the string over 1 to
804 845 * the left.
805 846 */
806 847
807 848 static void
808 849 shift1left(char *p)
809 850 {
810 851 for (; *p; p++)
811 852 *p = *(p + 1);
812 853 }
813 854
814 855 char *
815 856 nc_sperror(void)
816 857 {
817 858 static char buf_main[BUFSIZ];
818 859 static pthread_key_t perror_key = PTHREAD_ONCE_KEY_NP;
819 860 char *retstr = thr_main()?
820 861 buf_main :
821 862 thr_get_storage(&perror_key, BUFSIZ, free);
822 863
823 864 if (retstr == NULL) {
824 865 syslog(LOG_WARNING,
825 866 "nc_sperror: malloc failed when trying to create buffer\n");
826 867 return (NULL);
827 868 }
828 869
829 870 switch (nc_error) {
830 871 case NC_NOERROR:
831 872 (void) strlcpy(retstr, dgettext(__nsl_dom, "no error"), BUFSIZ);
832 873 break;
833 874 case NC_NOMEM:
834 875 (void) strlcpy(retstr, dgettext(__nsl_dom, "out of memory"),
835 876 BUFSIZ);
836 877 break;
837 878 case NC_NOSET:
838 879 (void) strlcpy(retstr, dgettext(__nsl_dom,
839 880 "routine called before calling \
840 881 setnetpath() or setnetconfig()"), BUFSIZ);
841 882 break;
842 883 case NC_OPENFAIL:
843 884 (void) strlcpy(retstr,
844 885 dgettext(__nsl_dom, "cannot open /etc/netconfig"),
845 886 BUFSIZ);
846 887 break;
847 888 case NC_BADLINE:
848 889 (void) snprintf(retstr, BUFSIZ, dgettext(__nsl_dom,
849 890 "error in /etc/netconfig: field %d of line %d\n"),
850 891 fieldnum, linenum);
851 892 break;
852 893 case NC_NOTFOUND:
853 894 (void) snprintf(retstr, BUFSIZ,
854 895 dgettext(__nsl_dom,
855 896 "netid not found in /etc/netconfig"));
856 897 break;
857 898 case NC_NOMOREENTRIES:
858 899 (void) snprintf(retstr, BUFSIZ,
859 900 dgettext(__nsl_dom,
860 901 "no more entries in /etc/netconfig"));
861 902 break;
862 903 default:
863 904 (void) strlcpy(retstr, dgettext(__nsl_dom, "unknown error"),
864 905 BUFSIZ);
865 906 break;
866 907 }
867 908 return (retstr);
868 909 }
869 910
870 911 void
871 912 nc_perror(const char *string)
872 913 {
873 914 if (string)
874 915 (void) fprintf(stderr, "%s: %s\n", string, nc_sperror());
875 916 else
876 917 (void) fprintf(stderr, "%s\n", nc_sperror());
877 918 }
878 919
879 920 static void
880 921 netlist_free(struct netconfig ***netppp)
881 922 {
882 923 struct netconfig **tpp;
883 924
884 925 for (tpp = *netppp; *tpp; tpp++) {
885 926 netconfig_free(*tpp);
886 927 }
887 928 free(*netppp);
888 929 *netppp = NULL;
889 930 }
890 931
891 932 static void
892 933 netconfig_free(struct netconfig *netconfigp)
893 934 {
894 935 int i;
895 936
896 937 if (netconfigp == NULL)
897 938 return;
898 939 free_entry(netconfigp->nc_netid);
899 940 free_entry(netconfigp->nc_protofmly);
900 941 free_entry(netconfigp->nc_proto);
901 942 free_entry(netconfigp->nc_device);
902 943 if (netconfigp->nc_lookups)
903 944 for (i = 0; i < netconfigp->nc_nlookups; i++)
904 945 free_entry(netconfigp->nc_lookups[i]);
905 946 free_entry(netconfigp->nc_lookups);
906 947 free(netconfigp);
907 948 }
908 949
909 950 static struct netconfig *
910 951 netconfig_dup(struct netconfig *netconfigp)
911 952 {
912 953 struct netconfig *nconf;
913 954 int i;
914 955
915 956 nconf = calloc(1, sizeof (struct netconfig));
916 957 if (nconf == NULL) {
917 958 nc_error = NC_NOMEM;
918 959 return (NULL);
919 960 }
920 961 nconf->nc_netid = strdup(netconfigp->nc_netid);
921 962 nconf->nc_protofmly = strdup(netconfigp->nc_protofmly);
922 963 nconf->nc_proto = strdup(netconfigp->nc_proto);
923 964 nconf->nc_device = strdup(netconfigp->nc_device);
924 965 nconf->nc_lookups = malloc((netconfigp->nc_nlookups + 1)
925 966 * sizeof (char *));
926 967 if (!(nconf->nc_lookups && nconf->nc_netid &&
927 968 nconf->nc_protofmly && nconf->nc_proto &&
928 969 nconf->nc_device)) {
929 970 nc_error = NC_NOMEM;
930 971 netconfig_free(nconf);
931 972 return (NULL);
932 973 }
933 974
934 975 for (i = 0; i < netconfigp->nc_nlookups; i++) {
935 976 nconf->nc_lookups[i] = strdup(netconfigp->nc_lookups[i]);
936 977 if (nconf->nc_lookups[i] == NULL) {
937 978 nconf->nc_nlookups = i;
938 979 netconfig_free(nconf);
939 980 nc_error = NC_NOMEM;
940 981 return (NULL);
941 982 }
942 983 }
943 984 nconf->nc_lookups[i] = NULL;
944 985 nconf->nc_nlookups = netconfigp->nc_nlookups;
945 986 nconf->nc_flag = netconfigp->nc_flag;
946 987 nconf->nc_semantics = netconfigp->nc_semantics;
947 988 return (nconf);
948 989 }
949 990
950 991 static void
951 992 free_entry(void *foo)
952 993 {
953 994 if (foo)
954 995 free(foo);
955 996 }
|
↓ open down ↓ |
632 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX