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