Blame src/getnetconfig.c

Packit Service 4f68e0
/*
Packit Service 4f68e0
 * Copyright (c) 2009, Sun Microsystems, Inc.
Packit Service 4f68e0
 * All rights reserved.
Packit Service 4f68e0
 *
Packit Service 4f68e0
 * Redistribution and use in source and binary forms, with or without
Packit Service 4f68e0
 * modification, are permitted provided that the following conditions are met:
Packit Service 4f68e0
 * - Redistributions of source code must retain the above copyright notice,
Packit Service 4f68e0
 *   this list of conditions and the following disclaimer.
Packit Service 4f68e0
 * - Redistributions in binary form must reproduce the above copyright notice,
Packit Service 4f68e0
 *   this list of conditions and the following disclaimer in the documentation
Packit Service 4f68e0
 *   and/or other materials provided with the distribution.
Packit Service 4f68e0
 * - Neither the name of Sun Microsystems, Inc. nor the names of its
Packit Service 4f68e0
 *   contributors may be used to endorse or promote products derived
Packit Service 4f68e0
 *   from this software without specific prior written permission.
Packit Service 4f68e0
 *
Packit Service 4f68e0
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Packit Service 4f68e0
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit Service 4f68e0
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit Service 4f68e0
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
Packit Service 4f68e0
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
Packit Service 4f68e0
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
Packit Service 4f68e0
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
Packit Service 4f68e0
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
Packit Service 4f68e0
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
Packit Service 4f68e0
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
Packit Service 4f68e0
 * POSSIBILITY OF SUCH DAMAGE.
Packit Service 4f68e0
 */
Packit Service 4f68e0
Packit Service 4f68e0
/*
Packit Service 4f68e0
 * Copyright (c) 1989 by Sun Microsystems, Inc.
Packit Service 4f68e0
 */
Packit Service 4f68e0
 
Packit Service 4f68e0
#include <pthread.h>
Packit Service 4f68e0
#include <reentrant.h>
Packit Service 4f68e0
#include <stdio.h>
Packit Service 4f68e0
#include <errno.h>
Packit Service 4f68e0
#include <netconfig.h>
Packit Service 4f68e0
#include <stddef.h>
Packit Service 4f68e0
#include <stdlib.h>
Packit Service 4f68e0
#include <string.h>
Packit Service 4f68e0
#include <rpc/rpc.h>
Packit Service 4f68e0
#include <unistd.h>
Packit Service 4f68e0
#include "rpc_com.h"
Packit Service 4f68e0
Packit Service 4f68e0
/*
Packit Service 4f68e0
 * The five library routines in this file provide application access to the
Packit Service 4f68e0
 * system network configuration database, /etc/netconfig.  In addition to the
Packit Service 4f68e0
 * netconfig database and the routines for accessing it, the environment
Packit Service 4f68e0
 * variable NETPATH and its corresponding routines in getnetpath.c may also be
Packit Service 4f68e0
 * used to specify the network transport to be used.
Packit Service 4f68e0
 */
Packit Service 4f68e0
Packit Service 4f68e0
/*
Packit Service 4f68e0
 * netconfig errors
Packit Service 4f68e0
 */
Packit Service 4f68e0
Packit Service 4f68e0
#define NC_NONETCONFIG	ENOENT
Packit Service 4f68e0
#define NC_NOMEM	ENOMEM
Packit Service 4f68e0
#define NC_NOTINIT	EINVAL	    /* setnetconfig was not called first */
Packit Service 4f68e0
#define NC_BADFILE	EBADF	    /* format for netconfig file is bad */
Packit Service 4f68e0
#define NC_NOTFOUND	ENOPROTOOPT /* specified netid was not found */
Packit Service 4f68e0
Packit Service 4f68e0
/*
Packit Service 4f68e0
 * semantics as strings (should be in netconfig.h)
Packit Service 4f68e0
 */
Packit Service 4f68e0
#define NC_TPI_CLTS_S	    "tpi_clts"
Packit Service 4f68e0
#define	NC_TPI_COTS_S	    "tpi_cots"
Packit Service 4f68e0
#define	NC_TPI_COTS_ORD_S   "tpi_cots_ord"
Packit Service 4f68e0
#define	NC_TPI_RAW_S        "tpi_raw"
Packit Service 4f68e0
Packit Service 4f68e0
/*
Packit Service 4f68e0
 * flags as characters (also should be in netconfig.h)
Packit Service 4f68e0
 */
Packit Service 4f68e0
#define	NC_NOFLAG_C	'-'
Packit Service 4f68e0
#define	NC_VISIBLE_C	'v'
Packit Service 4f68e0
#define	NC_BROADCAST_C	'b'
Packit Service 4f68e0
Packit Service 4f68e0
/*
Packit Service 4f68e0
 * Character used to indicate there is no name-to-address lookup library
Packit Service 4f68e0
 */
Packit Service 4f68e0
#define NC_NOLOOKUP	"-"
Packit Service 4f68e0
Packit Service 4f68e0
static const char * const _nc_errors[] = {
Packit Service 4f68e0
    "Netconfig database not found",
Packit Service 4f68e0
    "Not enough memory",
Packit Service 4f68e0
    "Not initialized",
Packit Service 4f68e0
    "Netconfig database has invalid format",
Packit Service 4f68e0
    "Netid not found in netconfig database"
Packit Service 4f68e0
};
Packit Service 4f68e0
Packit Service 4f68e0
struct netconfig_info {
Packit Service 4f68e0
    int		eof;	/* all entries has been read */
Packit Service 4f68e0
    int		ref;	/* # of times setnetconfig() has been called */
Packit Service 4f68e0
    struct netconfig_list	*head;	/* head of the list */
Packit Service 4f68e0
    struct netconfig_list	*tail;	/* last of the list */
Packit Service 4f68e0
};
Packit Service 4f68e0
Packit Service 4f68e0
struct netconfig_list {
Packit Service 4f68e0
    char			*linep;	/* hold line read from netconfig */
Packit Service 4f68e0
    struct netconfig		*ncp;
Packit Service 4f68e0
    struct netconfig_list	*next;
Packit Service 4f68e0
};
Packit Service 4f68e0
Packit Service 4f68e0
struct netconfig_vars {
Packit Service 4f68e0
    int   valid;	/* token that indicates a valid netconfig_vars */
Packit Service 4f68e0
    int   flag;		/* first time flag */
Packit Service 4f68e0
    struct netconfig_list *nc_configs;  /* pointer to the current netconfig entry */
Packit Service 4f68e0
};
Packit Service 4f68e0
Packit Service 4f68e0
#define NC_VALID	0xfeed
Packit Service 4f68e0
#define NC_STORAGE	0xf00d
Packit Service 4f68e0
#define NC_INVALID	0
Packit Service 4f68e0
Packit Service 4f68e0
Packit Service 4f68e0
static int *__nc_error(void);
Packit Service 4f68e0
static int parse_ncp(char *, struct netconfig *);
Packit Service 4f68e0
static struct netconfig *dup_ncp(struct netconfig *);
Packit Service 4f68e0
Packit Service 4f68e0
Packit Service 4f68e0
static FILE *nc_file;		/* for netconfig db */
Packit Service 4f68e0
static struct netconfig_info	ni = { 0, 0, NULL, NULL};
Packit Service 4f68e0
extern pthread_mutex_t nc_db_lock;
Packit Service 4f68e0
Packit Service 4f68e0
#define MAXNETCONFIGLINE    1000
Packit Service 4f68e0
Packit Service 4f68e0
static int *
Packit Service 4f68e0
__nc_error()
Packit Service 4f68e0
{
Packit Service 4f68e0
	static pthread_mutex_t nc_lock = PTHREAD_MUTEX_INITIALIZER;
Packit Service 4f68e0
	extern thread_key_t nc_key;
Packit Service 4f68e0
	static int nc_error = 0;
Packit Service 4f68e0
	int error, *nc_addr;
Packit Service 4f68e0
Packit Service 4f68e0
	/*
Packit Service 4f68e0
	 * Use the static `nc_error' if we are the main thread
Packit Service 4f68e0
	 * (including non-threaded programs), or if an allocation
Packit Service 4f68e0
	 * fails.
Packit Service 4f68e0
	 */
Packit Service 4f68e0
	if (nc_key == KEY_INITIALIZER) {
Packit Service 4f68e0
		error = 0;
Packit Service 4f68e0
		mutex_lock(&nc_lock);
Packit Service 4f68e0
		if (nc_key == KEY_INITIALIZER)
Packit Service 4f68e0
			error = thr_keycreate(&nc_key, free);
Packit Service 4f68e0
		mutex_unlock(&nc_lock);
Packit Service 4f68e0
		if (error)
Packit Service 4f68e0
			return (&nc_error);
Packit Service 4f68e0
	}
Packit Service 4f68e0
	if ((nc_addr = (int *)thr_getspecific(nc_key)) == NULL) {
Packit Service 4f68e0
		if((nc_addr = (int *)malloc(sizeof (int))) == NULL)
Packit Service 4f68e0
			return (&nc_error);
Packit Service 4f68e0
		if (thr_setspecific(nc_key, (void *) nc_addr) != 0) {
Packit Service 4f68e0
			if (nc_addr)
Packit Service 4f68e0
				free(nc_addr);
Packit Service 4f68e0
			return (&nc_error);
Packit Service 4f68e0
		}
Packit Service 4f68e0
		*nc_addr = 0;
Packit Service 4f68e0
	}
Packit Service 4f68e0
	return (nc_addr);
Packit Service 4f68e0
}
Packit Service 4f68e0
Packit Service 4f68e0
#define nc_error        (*(__nc_error()))
Packit Service 4f68e0
/*
Packit Service 4f68e0
 * A call to setnetconfig() establishes a /etc/netconfig "session".  A session
Packit Service 4f68e0
 * "handle" is returned on a successful call.  At the start of a session (after
Packit Service 4f68e0
 * a call to setnetconfig()) searches through the /etc/netconfig database will
Packit Service 4f68e0
 * proceed from the start of the file.  The session handle must be passed to
Packit Service 4f68e0
 * getnetconfig() to parse the file.  Each call to getnetconfig() using the
Packit Service 4f68e0
 * current handle will process one subsequent entry in /etc/netconfig.
Packit Service 4f68e0
 * setnetconfig() must be called before the first call to getnetconfig().
Packit Service 4f68e0
 * (Handles are used to allow for nested calls to setnetpath()).
Packit Service 4f68e0
 *
Packit Service 4f68e0
 * A new session is established with each call to setnetconfig(), with a new
Packit Service 4f68e0
 * handle being returned on each call.  Previously established sessions remain
Packit Service 4f68e0
 * active until endnetconfig() is called with that session's handle as an
Packit Service 4f68e0
 * argument.
Packit Service 4f68e0
 *
Packit Service 4f68e0
 * setnetconfig() need *not* be called before a call to getnetconfigent().
Packit Service 4f68e0
 * setnetconfig() returns a NULL pointer on failure (for example, if
Packit Service 4f68e0
 * the netconfig database is not present).
Packit Service 4f68e0
 */
Packit Service 4f68e0
void *
Packit Service 4f68e0
setnetconfig()
Packit Service 4f68e0
{
Packit Service 4f68e0
    struct netconfig_vars *nc_vars;
Packit Service 4f68e0
Packit Service 4f68e0
    if ((nc_vars = (struct netconfig_vars *)malloc(sizeof
Packit Service 4f68e0
		(struct netconfig_vars))) == NULL) {
Packit Service 4f68e0
	return(NULL);
Packit Service 4f68e0
    }
Packit Service 4f68e0
Packit Service 4f68e0
    /*
Packit Service 4f68e0
     * For multiple calls, i.e. nc_file is not NULL, we just return the
Packit Service 4f68e0
     * handle without reopening the netconfig db.
Packit Service 4f68e0
     */
Packit Service 4f68e0
    mutex_lock(&nc_db_lock);
Packit Service 4f68e0
    ni.ref++;
Packit Service 4f68e0
    if ((nc_file != NULL) || (nc_file = fopen(NETCONFIG, "r")) != NULL) {
Packit Service 4f68e0
	nc_vars->valid = NC_VALID;
Packit Service 4f68e0
	nc_vars->flag = 0;
Packit Service 4f68e0
	nc_vars->nc_configs = ni.head;
Packit Service 4f68e0
	mutex_unlock(&nc_db_lock);
Packit Service 4f68e0
	return ((void *)nc_vars);
Packit Service 4f68e0
    }
Packit Service 4f68e0
    ni.ref--;
Packit Service 4f68e0
    mutex_unlock(&nc_db_lock);
Packit Service 4f68e0
    nc_error = NC_NONETCONFIG;
Packit Service 4f68e0
    free(nc_vars);
Packit Service 4f68e0
    return (NULL);
Packit Service 4f68e0
}
Packit Service 4f68e0
Packit Service 4f68e0
Packit Service 4f68e0
/*
Packit Service 4f68e0
 * When first called, getnetconfig() returns a pointer to the first entry in
Packit Service 4f68e0
 * the netconfig database, formatted as a struct netconfig.  On each subsequent
Packit Service 4f68e0
 * call, getnetconfig() returns a pointer to the next entry in the database.
Packit Service 4f68e0
 * getnetconfig() can thus be used to search the entire netconfig file.
Packit Service 4f68e0
 * getnetconfig() returns NULL at end of file.
Packit Service 4f68e0
 */
Packit Service 4f68e0
Packit Service 4f68e0
struct netconfig *
Packit Service 4f68e0
getnetconfig(handlep)
Packit Service 4f68e0
void *handlep;
Packit Service 4f68e0
{
Packit Service 4f68e0
    struct netconfig_vars *ncp = (struct netconfig_vars *)handlep;
Packit Service 4f68e0
    char *stringp;		/* tmp string pointer */
Packit Service 4f68e0
    struct netconfig_list	*list;
Packit Service 4f68e0
    struct netconfig *np;
Packit Service 4f68e0
    struct netconfig *result;
Packit Service 4f68e0
Packit Service 4f68e0
    /*
Packit Service 4f68e0
     * Verify that handle is valid
Packit Service 4f68e0
     */
Packit Service 4f68e0
    mutex_lock(&nc_db_lock);
Packit Service 4f68e0
    if (ncp == NULL || nc_file == NULL) {
Packit Service 4f68e0
	nc_error = NC_NOTINIT;
Packit Service 4f68e0
	mutex_unlock(&nc_db_lock);
Packit Service 4f68e0
	return (NULL);
Packit Service 4f68e0
    }
Packit Service 4f68e0
Packit Service 4f68e0
    switch (ncp->valid) {
Packit Service 4f68e0
    case NC_VALID:
Packit Service 4f68e0
	/*
Packit Service 4f68e0
	 * If entry has already been read into the list,
Packit Service 4f68e0
	 * we return the entry in the linked list.
Packit Service 4f68e0
	 * If this is the first time call, check if there are any entries in
Packit Service 4f68e0
	 * linked list.  If no entries, we need to read the netconfig db.
Packit Service 4f68e0
	 * If we have been here and the next entry is there, we just return
Packit Service 4f68e0
	 * it.
Packit Service 4f68e0
	 */
Packit Service 4f68e0
	if (ncp->flag == 0) {	/* first time */
Packit Service 4f68e0
	    ncp->flag = 1;
Packit Service 4f68e0
	    ncp->nc_configs = ni.head;
Packit Service 4f68e0
	    if (ncp->nc_configs != NULL)	/* entry already exist */ {
Packit Service 4f68e0
		mutex_unlock(&nc_db_lock);
Packit Service 4f68e0
		return(ncp->nc_configs->ncp);
Packit Service 4f68e0
		}
Packit Service 4f68e0
	}
Packit Service 4f68e0
	else if (ncp->nc_configs != NULL && ncp->nc_configs->next != NULL) {
Packit Service 4f68e0
	    ncp->nc_configs = ncp->nc_configs->next;
Packit Service 4f68e0
	    mutex_unlock(&nc_db_lock);
Packit Service 4f68e0
	    return(ncp->nc_configs->ncp);
Packit Service 4f68e0
	}
Packit Service 4f68e0
Packit Service 4f68e0
	/*
Packit Service 4f68e0
	 * If we cannot find the entry in the list and is end of file,
Packit Service 4f68e0
	 * we give up.
Packit Service 4f68e0
	 */
Packit Service 4f68e0
	if (ni.eof == 1) {
Packit Service 4f68e0
	    mutex_unlock(&nc_db_lock);
Packit Service 4f68e0
	    return(NULL);
Packit Service 4f68e0
	}
Packit Service 4f68e0
	break;
Packit Service 4f68e0
    default:
Packit Service 4f68e0
	nc_error = NC_NOTINIT;
Packit Service 4f68e0
	mutex_unlock(&nc_db_lock);
Packit Service 4f68e0
	return (NULL);
Packit Service 4f68e0
    }
Packit Service 4f68e0
Packit Service 4f68e0
    stringp = (char *) malloc(MAXNETCONFIGLINE);
Packit Service 4f68e0
    if (stringp == NULL) {
Packit Service 4f68e0
    mutex_unlock(&nc_db_lock);
Packit Service 4f68e0
    return (NULL);
Packit Service 4f68e0
    }
Packit Service 4f68e0
Packit Service 4f68e0
#ifdef MEM_CHK
Packit Service 4f68e0
    if (malloc_verify() == 0) {
Packit Service 4f68e0
	fprintf(stderr, "memory heap corrupted in getnetconfig\n");
Packit Service 4f68e0
	exit(1);
Packit Service 4f68e0
    }
Packit Service 4f68e0
#endif
Packit Service 4f68e0
Packit Service 4f68e0
    /*
Packit Service 4f68e0
     * Read a line from netconfig file.
Packit Service 4f68e0
     */
Packit Service 4f68e0
    do {
Packit Service 4f68e0
	if (fgets(stringp, MAXNETCONFIGLINE, nc_file) == NULL) {
Packit Service 4f68e0
	    free(stringp);
Packit Service 4f68e0
	    ni.eof = 1;
Packit Service 4f68e0
	    mutex_unlock(&nc_db_lock);
Packit Service 4f68e0
	    return (NULL);
Packit Service 4f68e0
        }
Packit Service 4f68e0
    } while (*stringp == '#');
Packit Service 4f68e0
Packit Service 4f68e0
    list = (struct netconfig_list *) malloc(sizeof (struct netconfig_list));
Packit Service 4f68e0
    if (list == NULL) {
Packit Service 4f68e0
    	free(stringp);
Packit Service 4f68e0
		mutex_unlock(&nc_db_lock);
Packit Service 4f68e0
    	return(NULL);
Packit Service 4f68e0
    }
Packit Service 4f68e0
    np = (struct netconfig *) malloc(sizeof (struct netconfig));
Packit Service 4f68e0
    if (np == NULL) {
Packit Service 4f68e0
    	free(stringp);
Packit Service 4f68e0
		free(list);
Packit Service 4f68e0
		mutex_unlock(&nc_db_lock);
Packit Service 4f68e0
    	return(NULL);
Packit Service 4f68e0
    }
Packit Service 4f68e0
    list->ncp = np;
Packit Service 4f68e0
    list->next = NULL;
Packit Service 4f68e0
    list->ncp->nc_lookups = NULL;
Packit Service 4f68e0
    list->linep = stringp;
Packit Service 4f68e0
    if (parse_ncp(stringp, list->ncp) == -1) {
Packit Service 4f68e0
	free(stringp);
Packit Service 4f68e0
	free(np);
Packit Service 4f68e0
	free(list);
Packit Service 4f68e0
	mutex_unlock(&nc_db_lock);
Packit Service 4f68e0
	return (NULL);
Packit Service 4f68e0
    }
Packit Service 4f68e0
    else {
Packit Service 4f68e0
	/*
Packit Service 4f68e0
	 * If this is the first entry that's been read, it is the head of
Packit Service 4f68e0
	 * the list.  If not, put the entry at the end of the list.
Packit Service 4f68e0
	 * Reposition the current pointer of the handle to the last entry
Packit Service 4f68e0
	 * in the list.
Packit Service 4f68e0
	 */
Packit Service 4f68e0
	if (ni.head == NULL) {	/* first entry */
Packit Service 4f68e0
	    ni.head = ni.tail = list;
Packit Service 4f68e0
	}
Packit Service 4f68e0
    	else {
Packit Service 4f68e0
    	    ni.tail->next = list;
Packit Service 4f68e0
    	    ni.tail = ni.tail->next;
Packit Service 4f68e0
    	}
Packit Service 4f68e0
	ncp->nc_configs = ni.tail;
Packit Service 4f68e0
	result = ni.tail->ncp;
Packit Service 4f68e0
	mutex_unlock(&nc_db_lock);
Packit Service 4f68e0
	return result;
Packit Service 4f68e0
    }
Packit Service 4f68e0
}
Packit Service 4f68e0
Packit Service 4f68e0
/*
Packit Service 4f68e0
 * endnetconfig() may be called to "unbind" or "close" the netconfig database
Packit Service 4f68e0
 * when processing is complete, releasing resources for reuse.  endnetconfig()
Packit Service 4f68e0
 * may not be called before setnetconfig().  endnetconfig() returns 0 on
Packit Service 4f68e0
 * success and -1 on failure (for example, if setnetconfig() was not called
Packit Service 4f68e0
 * previously).
Packit Service 4f68e0
 */
Packit Service 4f68e0
int
Packit Service 4f68e0
endnetconfig(handlep)
Packit Service 4f68e0
void *handlep;
Packit Service 4f68e0
{
Packit Service 4f68e0
    struct netconfig_vars *nc_handlep = (struct netconfig_vars *)handlep;
Packit Service 4f68e0
Packit Service 4f68e0
    struct netconfig_list *q, *p;
Packit Service 4f68e0
Packit Service 4f68e0
    /*
Packit Service 4f68e0
     * Verify that handle is valid
Packit Service 4f68e0
     */
Packit Service 4f68e0
    if (nc_handlep == NULL || (nc_handlep->valid != NC_VALID &&
Packit Service 4f68e0
	    nc_handlep->valid != NC_STORAGE)) {
Packit Service 4f68e0
	nc_error = NC_NOTINIT;
Packit Service 4f68e0
	return (-1);
Packit Service 4f68e0
    }
Packit Service 4f68e0
Packit Service 4f68e0
    /*
Packit Service 4f68e0
     * Return 0 if anyone still needs it.
Packit Service 4f68e0
     */
Packit Service 4f68e0
    nc_handlep->valid = NC_INVALID;
Packit Service 4f68e0
    nc_handlep->flag = 0;
Packit Service 4f68e0
    nc_handlep->nc_configs = NULL;
Packit Service 4f68e0
    mutex_lock(&nc_db_lock);
Packit Service 4f68e0
    if (--ni.ref > 0) {
Packit Service 4f68e0
	mutex_unlock(&nc_db_lock);
Packit Service 4f68e0
	free(nc_handlep);
Packit Service 4f68e0
	return(0);
Packit Service 4f68e0
    }
Packit Service 4f68e0
Packit Service 4f68e0
    /*
Packit Service 4f68e0
     * Noone needs these entries anymore, then frees them.
Packit Service 4f68e0
     * Make sure all info in netconfig_info structure has been reinitialized.
Packit Service 4f68e0
     */
Packit Service 4f68e0
    q = p = ni.head;
Packit Service 4f68e0
    ni.eof = ni.ref = 0;
Packit Service 4f68e0
    ni.head = NULL;
Packit Service 4f68e0
    ni.tail = NULL;
Packit Service 4f68e0
    while (q) {
Packit Service 4f68e0
	p = q->next;
Packit Service 4f68e0
	if (q->ncp->nc_lookups != NULL) free(q->ncp->nc_lookups);
Packit Service 4f68e0
	free(q->ncp);
Packit Service 4f68e0
	free(q->linep);
Packit Service 4f68e0
	free(q);
Packit Service 4f68e0
	q = p;
Packit Service 4f68e0
    }
Packit Service 4f68e0
    free(nc_handlep);
Packit Service 4f68e0
    if(nc_file != NULL) {
Packit Service 4f68e0
        fclose(nc_file);
Packit Service 4f68e0
    }
Packit Service 4f68e0
    nc_file = NULL;
Packit Service 4f68e0
    mutex_unlock(&nc_db_lock);
Packit Service 4f68e0
    return (0);
Packit Service 4f68e0
}
Packit Service 4f68e0
Packit Service 4f68e0
/*
Packit Service 4f68e0
 * getnetconfigent(netid) returns a pointer to the struct netconfig structure
Packit Service 4f68e0
 * corresponding to netid.  It returns NULL if netid is invalid (that is, does
Packit Service 4f68e0
 * not name an entry in the netconfig database).  It returns NULL and sets
Packit Service 4f68e0
 * errno in case of failure (for example, if the netconfig database cannot be
Packit Service 4f68e0
 * opened).
Packit Service 4f68e0
 */
Packit Service 4f68e0
Packit Service 4f68e0
struct netconfig *
Packit Service 4f68e0
getnetconfigent(netid)
Packit Service 4f68e0
	const char *netid;
Packit Service 4f68e0
{
Packit Service 4f68e0
    FILE *file;		/* NETCONFIG db's file pointer */
Packit Service 4f68e0
    char *linep;	/* holds current netconfig line */
Packit Service 4f68e0
    char *stringp;	/* temporary string pointer */
Packit Service 4f68e0
    struct netconfig *ncp = NULL;   /* returned value */
Packit Service 4f68e0
    struct netconfig_list *list;	/* pointer to cache list */
Packit Service 4f68e0
Packit Service 4f68e0
    nc_error = NC_NOTFOUND;	/* default error. */
Packit Service 4f68e0
    if (netid == NULL || strlen(netid) == 0) {
Packit Service 4f68e0
	return (NULL);
Packit Service 4f68e0
    }
Packit Service 4f68e0
Packit Service 4f68e0
    if (strcmp(netid, "unix") == 0) {
Packit Service 4f68e0
	fprintf(stderr, "The local transport is called \"unix\" ");
Packit Service 4f68e0
	fprintf(stderr, "in /etc/netconfig.\n");
Packit Service 4f68e0
	fprintf(stderr, "Please change this to \"local\" manually ");
Packit Service 4f68e0
	fprintf(stderr, "or run mergemaster(8).\n");
Packit Service 4f68e0
	fprintf(stderr, "See UPDATING entry 20021216 for details.\n");
Packit Service 4f68e0
	fprintf(stderr, "Continuing in 10 seconds\n\n");
Packit Service 4f68e0
	fprintf(stderr, "This warning will be removed 20030301\n");
Packit Service 4f68e0
	sleep(10);
Packit Service 4f68e0
Packit Service 4f68e0
    }
Packit Service 4f68e0
Packit Service 4f68e0
    /*
Packit Service 4f68e0
     * Look up table if the entries have already been read and parsed in
Packit Service 4f68e0
     * getnetconfig(), then copy this entry into a buffer and return it.
Packit Service 4f68e0
     * If we cannot find the entry in the current list and there are more
Packit Service 4f68e0
     * entries in the netconfig db that has not been read, we then read the
Packit Service 4f68e0
     * db and try find the match netid.
Packit Service 4f68e0
     * If all the netconfig db has been read and placed into the list and
Packit Service 4f68e0
     * there is no match for the netid, return NULL.
Packit Service 4f68e0
     */
Packit Service 4f68e0
    mutex_lock(&nc_db_lock);
Packit Service 4f68e0
    if (ni.head != NULL) {
Packit Service 4f68e0
	for (list = ni.head; list; list = list->next) {
Packit Service 4f68e0
	    if (strcmp(list->ncp->nc_netid, netid) == 0) {
Packit Service 4f68e0
			ncp = dup_ncp(list->ncp);
Packit Service 4f68e0
			mutex_unlock(&nc_db_lock);
Packit Service 4f68e0
			return ncp;
Packit Service 4f68e0
	    }
Packit Service 4f68e0
	}
Packit Service 4f68e0
        if (ni.eof == 1) {	/* that's all the entries */
Packit Service 4f68e0
	    	mutex_unlock(&nc_db_lock);
Packit Service 4f68e0
	    	return(NULL);
Packit Service 4f68e0
        }
Packit Service 4f68e0
    }
Packit Service 4f68e0
    mutex_unlock(&nc_db_lock);
Packit Service 4f68e0
Packit Service 4f68e0
    if ((file = fopen(NETCONFIG, "r")) == NULL) {
Packit Service 4f68e0
	nc_error = NC_NONETCONFIG;
Packit Service 4f68e0
	return (NULL);
Packit Service 4f68e0
    }
Packit Service 4f68e0
Packit Service 4f68e0
    if ((linep = malloc(MAXNETCONFIGLINE)) == NULL) {
Packit Service 4f68e0
	fclose(file);
Packit Service 4f68e0
	nc_error = NC_NOMEM;
Packit Service 4f68e0
	return (NULL);
Packit Service 4f68e0
    }
Packit Service 4f68e0
    do {
Packit Service 4f68e0
	ptrdiff_t len;
Packit Service 4f68e0
	char *tmpp;	/* tmp string pointer */
Packit Service 4f68e0
Packit Service 4f68e0
	do {
Packit Service 4f68e0
	    if ((stringp = fgets(linep, MAXNETCONFIGLINE, file)) == NULL) {
Packit Service 4f68e0
		break;
Packit Service 4f68e0
	    }
Packit Service 4f68e0
	} while (*stringp == '#');
Packit Service 4f68e0
	if (stringp == NULL) {	    /* eof */
Packit Service 4f68e0
	    break;
Packit Service 4f68e0
	}
Packit Service 4f68e0
	if ((tmpp = strpbrk(stringp, "\t ")) == NULL) {	/* can't parse file */
Packit Service 4f68e0
	    nc_error = NC_BADFILE;
Packit Service 4f68e0
	    break;
Packit Service 4f68e0
	}
Packit Service 4f68e0
	if (strlen(netid) == (size_t) (len = tmpp - stringp) &&	/* a match */
Packit Service 4f68e0
		strncmp(stringp, netid, (size_t)len) == 0) {
Packit Service 4f68e0
	    if ((ncp = (struct netconfig *)
Packit Service 4f68e0
		    malloc(sizeof (struct netconfig))) == NULL) {
Packit Service 4f68e0
		break;
Packit Service 4f68e0
	    }
Packit Service 4f68e0
	    ncp->nc_lookups = NULL;
Packit Service 4f68e0
	    if (parse_ncp(linep, ncp) == -1) {
Packit Service 4f68e0
		free(ncp);
Packit Service 4f68e0
		ncp = NULL;
Packit Service 4f68e0
	    }
Packit Service 4f68e0
	    break;
Packit Service 4f68e0
	}
Packit Service 4f68e0
    } while (stringp != NULL);
Packit Service 4f68e0
    if (ncp == NULL) {
Packit Service 4f68e0
	free(linep);
Packit Service 4f68e0
    }
Packit Service 4f68e0
    fclose(file);
Packit Service 4f68e0
    return(ncp);
Packit Service 4f68e0
}
Packit Service 4f68e0
Packit Service 4f68e0
/*
Packit Service 4f68e0
 * freenetconfigent(netconfigp) frees the netconfig structure pointed to by
Packit Service 4f68e0
 * netconfigp (previously returned by getnetconfigent()).
Packit Service 4f68e0
 */
Packit Service 4f68e0
Packit Service 4f68e0
void
Packit Service 4f68e0
freenetconfigent(netconfigp)
Packit Service 4f68e0
	struct netconfig *netconfigp;
Packit Service 4f68e0
{
Packit Service 4f68e0
    if (netconfigp != NULL) {
Packit Service 4f68e0
	free(netconfigp->nc_netid);	/* holds all netconfigp's strings */
Packit Service 4f68e0
	if (netconfigp->nc_lookups != NULL)
Packit Service 4f68e0
	    free(netconfigp->nc_lookups);
Packit Service 4f68e0
	free(netconfigp);
Packit Service 4f68e0
    }
Packit Service 4f68e0
    return;
Packit Service 4f68e0
}
Packit Service 4f68e0
Packit Service 4f68e0
/*
Packit Service 4f68e0
 * Parse line and stuff it in a struct netconfig
Packit Service 4f68e0
 * Typical line might look like:
Packit Service 4f68e0
 *	udp tpi_cots vb inet udp /dev/udp /usr/lib/ip.so,/usr/local/ip.so
Packit Service 4f68e0
 *
Packit Service 4f68e0
 * We return -1 if any of the tokens don't parse, or malloc fails.
Packit Service 4f68e0
 *
Packit Service 4f68e0
 * Note that we modify stringp (putting NULLs after tokens) and
Packit Service 4f68e0
 * we set the ncp's string field pointers to point to these tokens within
Packit Service 4f68e0
 * stringp.
Packit Service 4f68e0
 */
Packit Service 4f68e0
Packit Service 4f68e0
static int
Packit Service 4f68e0
parse_ncp(stringp, ncp)
Packit Service 4f68e0
char *stringp;		/* string to parse */
Packit Service 4f68e0
struct netconfig *ncp;	/* where to put results */
Packit Service 4f68e0
{
Packit Service 4f68e0
    char    *tokenp;	/* for processing tokens */
Packit Service 4f68e0
    char    *lasts;
Packit Service 4f68e0
Packit Service 4f68e0
    nc_error = NC_BADFILE;	/* nearly anything that breaks is for this reason */
Packit Service 4f68e0
    stringp[strlen(stringp)-1] = '\0';	/* get rid of newline */
Packit Service 4f68e0
    /* netid */
Packit Service 4f68e0
    if ((ncp->nc_netid = strtok_r(stringp, "\t ", &lasts)) == NULL) {
Packit Service 4f68e0
	return (-1);
Packit Service 4f68e0
    }
Packit Service 4f68e0
Packit Service 4f68e0
    /* semantics */
Packit Service 4f68e0
    if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) {
Packit Service 4f68e0
	return (-1);
Packit Service 4f68e0
    }
Packit Service 4f68e0
    if (strcmp(tokenp, NC_TPI_COTS_ORD_S) == 0)
Packit Service 4f68e0
	ncp->nc_semantics = NC_TPI_COTS_ORD;
Packit Service 4f68e0
    else if (strcmp(tokenp, NC_TPI_COTS_S) == 0)
Packit Service 4f68e0
	ncp->nc_semantics = NC_TPI_COTS;
Packit Service 4f68e0
    else if (strcmp(tokenp, NC_TPI_CLTS_S) == 0)
Packit Service 4f68e0
	ncp->nc_semantics = NC_TPI_CLTS;
Packit Service 4f68e0
    else if (strcmp(tokenp, NC_TPI_RAW_S) == 0)
Packit Service 4f68e0
	ncp->nc_semantics = NC_TPI_RAW;
Packit Service 4f68e0
    else
Packit Service 4f68e0
	return (-1);
Packit Service 4f68e0
Packit Service 4f68e0
    /* flags */
Packit Service 4f68e0
    if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) {
Packit Service 4f68e0
	return (-1);
Packit Service 4f68e0
    }
Packit Service 4f68e0
    for (ncp->nc_flag = NC_NOFLAG; *tokenp != '\0';
Packit Service 4f68e0
	    tokenp++) {
Packit Service 4f68e0
	switch (*tokenp) {
Packit Service 4f68e0
	case NC_NOFLAG_C:
Packit Service 4f68e0
	    break;
Packit Service 4f68e0
	case NC_VISIBLE_C:
Packit Service 4f68e0
	    ncp->nc_flag |= NC_VISIBLE;
Packit Service 4f68e0
	    break;
Packit Service 4f68e0
	case NC_BROADCAST_C:
Packit Service 4f68e0
	    ncp->nc_flag |= NC_BROADCAST;
Packit Service 4f68e0
	    break;
Packit Service 4f68e0
	default:
Packit Service 4f68e0
	    return (-1);
Packit Service 4f68e0
	}
Packit Service 4f68e0
    }
Packit Service 4f68e0
    /* protocol family */
Packit Service 4f68e0
    if ((ncp->nc_protofmly = strtok_r(NULL, "\t ", &lasts)) == NULL) {
Packit Service 4f68e0
	return (-1);
Packit Service 4f68e0
    }
Packit Service 4f68e0
    /* protocol name */
Packit Service 4f68e0
    if ((ncp->nc_proto = strtok_r(NULL, "\t ", &lasts)) == NULL) {
Packit Service 4f68e0
	return (-1);
Packit Service 4f68e0
    }
Packit Service 4f68e0
    /* network device */
Packit Service 4f68e0
    if ((ncp->nc_device = strtok_r(NULL, "\t ", &lasts)) == NULL) {
Packit Service 4f68e0
	return (-1);
Packit Service 4f68e0
    }
Packit Service 4f68e0
    if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) {
Packit Service 4f68e0
	return (-1);
Packit Service 4f68e0
    }
Packit Service 4f68e0
    if (strcmp(tokenp, NC_NOLOOKUP) == 0) {
Packit Service 4f68e0
	ncp->nc_nlookups = 0;
Packit Service 4f68e0
	ncp->nc_lookups = NULL;
Packit Service 4f68e0
    } else {
Packit Service 4f68e0
	char *cp;	    /* tmp string */
Packit Service 4f68e0
Packit Service 4f68e0
	if (ncp->nc_lookups != NULL)	/* from last visit */
Packit Service 4f68e0
	    free(ncp->nc_lookups);
Packit Service 4f68e0
	/* preallocate one string pointer */
Packit Service 4f68e0
	ncp->nc_lookups = (char **)malloc(sizeof (char *));
Packit Service 4f68e0
	ncp->nc_nlookups = 0;
Packit Service 4f68e0
	while ((cp = tokenp) != NULL) {
Packit Service 4f68e0
	    tokenp = _get_next_token(cp, ',');
Packit Service 4f68e0
	    ncp->nc_lookups[(size_t)ncp->nc_nlookups++] = cp;
Packit Service 4f68e0
	    ncp->nc_lookups = (char **)realloc(ncp->nc_lookups,
Packit Service 4f68e0
		(size_t)(ncp->nc_nlookups+1) *sizeof(char *));	/* for next loop */
Packit Service 4f68e0
	}
Packit Service 4f68e0
    }
Packit Service 4f68e0
    return (0);
Packit Service 4f68e0
}
Packit Service 4f68e0
Packit Service 4f68e0
Packit Service 4f68e0
/*
Packit Service 4f68e0
 * Returns a string describing the reason for failure.
Packit Service 4f68e0
 */
Packit Service 4f68e0
char *
Packit Service 4f68e0
nc_sperror()
Packit Service 4f68e0
{
Packit Service 4f68e0
    const char *message;
Packit Service 4f68e0
Packit Service 4f68e0
    switch(nc_error) {
Packit Service 4f68e0
    case NC_NONETCONFIG:
Packit Service 4f68e0
	message = _nc_errors[0];
Packit Service 4f68e0
	break;
Packit Service 4f68e0
    case NC_NOMEM:
Packit Service 4f68e0
	message = _nc_errors[1];
Packit Service 4f68e0
	break;
Packit Service 4f68e0
    case NC_NOTINIT:
Packit Service 4f68e0
	message = _nc_errors[2];
Packit Service 4f68e0
	break;
Packit Service 4f68e0
    case NC_BADFILE:
Packit Service 4f68e0
	message = _nc_errors[3];
Packit Service 4f68e0
	break;
Packit Service 4f68e0
    case NC_NOTFOUND:
Packit Service 4f68e0
	message = _nc_errors[4];
Packit Service 4f68e0
	break;
Packit Service 4f68e0
    default:
Packit Service 4f68e0
	message = "Unknown network selection error";
Packit Service 4f68e0
    }
Packit Service 4f68e0
    /* LINTED const castaway */
Packit Service 4f68e0
    return ((char *)message);
Packit Service 4f68e0
}
Packit Service 4f68e0
Packit Service 4f68e0
/*
Packit Service 4f68e0
 * Prints a message onto standard error describing the reason for failure.
Packit Service 4f68e0
 */
Packit Service 4f68e0
void
Packit Service 4f68e0
nc_perror(s)
Packit Service 4f68e0
	const char *s;
Packit Service 4f68e0
{
Packit Service 4f68e0
    fprintf(stderr, "%s: %s\n", s, nc_sperror());
Packit Service 4f68e0
}
Packit Service 4f68e0
Packit Service 4f68e0
/*
Packit Service 4f68e0
 * Duplicates the matched netconfig buffer.
Packit Service 4f68e0
 */
Packit Service 4f68e0
static struct netconfig *
Packit Service 4f68e0
dup_ncp(ncp)
Packit Service 4f68e0
struct netconfig	*ncp;
Packit Service 4f68e0
{
Packit Service 4f68e0
    struct netconfig	*p;
Packit Service 4f68e0
    char	*tmp;
Packit Bot de569b
    char	*t;
Packit Service 4f68e0
    u_int	i;
Packit Service 4f68e0
Packit Service 4f68e0
    if ((tmp=malloc(MAXNETCONFIGLINE)) == NULL)
Packit Service 4f68e0
	return(NULL);
Packit Service 4f68e0
    if ((p=(struct netconfig *)malloc(sizeof(struct netconfig))) == NULL) {
Packit Service 4f68e0
	free(tmp);
Packit Service 4f68e0
	return(NULL);
Packit Service 4f68e0
    }
Packit Service 4f68e0
    /*
Packit Service 4f68e0
     * First we dup all the data from matched netconfig buffer.  Then we
Packit Service 4f68e0
     * adjust some of the member pointer to a pre-allocated buffer where
Packit Service 4f68e0
     * contains part of the data.
Packit Service 4f68e0
     * To follow the convention used in parse_ncp(), we store all the
Packit Service 4f68e0
     * necessary information in the pre-allocated buffer and let each
Packit Service 4f68e0
     * of the netconfig char pointer member point to the right address
Packit Service 4f68e0
     * in the buffer.
Packit Service 4f68e0
     */
Packit Service 4f68e0
    *p = *ncp;
Packit Service 4f68e0
    p->nc_netid = (char *)strcpy(tmp,ncp->nc_netid);
Packit Bot de569b
    t = strchr(tmp, 0) + 1;
Packit Bot de569b
    p->nc_protofmly = (char *)strcpy(t,ncp->nc_protofmly);
Packit Bot de569b
    t = strchr(t, 0) + 1;
Packit Bot de569b
    p->nc_proto = (char *)strcpy(t,ncp->nc_proto);
Packit Bot de569b
    t = strchr(t, 0) + 1;
Packit Bot de569b
    p->nc_device = (char *)strcpy(t,ncp->nc_device);
Packit Service 4f68e0
    p->nc_lookups = (char **)malloc((size_t)(p->nc_nlookups+1) * sizeof(char *));
Packit Service 4f68e0
    if (p->nc_lookups == NULL) {
Packit Bot 579830
	free(p);
Packit Bot 579830
	free(tmp);
Packit Service 4f68e0
	return(NULL);
Packit Service 4f68e0
    }
Packit Service 4f68e0
    for (i=0; i < p->nc_nlookups; i++) {
Packit Bot de569b
	t = strchr(t, 0) + 1;
Packit Bot de569b
	p->nc_lookups[i] = (char *)strcpy(t,ncp->nc_lookups[i]);
Packit Service 4f68e0
    }
Packit Service 4f68e0
    return(p);
Packit Service 4f68e0
}