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