/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Portions of this source code were derived from Berkeley 4.3 BSD
* under license from the Regents of the University of California.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include "mt.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <netconfig.h>
#include <malloc.h>
#include <libintl.h>
#include <syslog.h>
#include "netcspace.h"
/*
* Local routines used by the library procedures
*/
static int blank(char *);
static int comment(char *);
static void netconfig_free(struct netconfig *);
static unsigned int getflag(char *);
static char **getlookups(char *);
static struct netconfig **getnetlist(void);
static unsigned int getnlookups(char *);
static char *gettoken(char *, int);
static void shift1left(char *);
static void netlist_free(struct netconfig ***);
static void free_entry(void *);
extern const char __nsl_dom[];
/*
* Static global variables used by the library procedures:
*
* netpp - points to the beginning of the list of netconfig
* entries used by setnetconfig() and setnetpath().
* Once netpp is initialized, that memory is *never*
* released. This was necessary to improve performance.
*
* file (used for debugging and for nc_perror()).
*
* fieldnum - the current field number of the current line
* nc_perror()).
*
* nc_error - the error condition encountered.
*/
/*
* routines, which will always be executed once, and within the netpp_mutex.
* They are global to allow the nc_sperror routine to provide better
*/
static int *
__nc_error(void)
{
int *ret;
if (thr_main())
return (&nc_error);
/* if thr_get_storage fails we return the address of nc_error */
}
/*
* setnetconfig() has the effect of "initializing" the
* network configuration database. It reads in the
* netcf entries (if not already read in).
*/
void *
setnetconfig(void)
{
(void) mutex_lock(&netpp_mutex);
(void) mutex_unlock(&netpp_mutex);
return (NULL);
}
(void) mutex_unlock(&netpp_mutex);
return (NULL);
}
return ((void *)retp);
}
/*
* endnetconfig() frees up all data allocated by setnetconfig()
*/
int
{
(void) mutex_lock(&netpp_mutex);
(void) mutex_unlock(&netpp_mutex);
return (-1);
}
(void) mutex_unlock(&netpp_mutex);
return (0);
}
/*
* getnetconfig() returns the current entry in the list
* of netconfig structures. It uses the nconf_handlep argument
* to determine the current entry. If setnetconfig() was not
* called previously to set up the list, return failure.
* It also check if ipv6 interface is present(ipv6_present) and
* skips udp6 & tcp6 entries if ipv6 is not supported.
*/
struct netconfig *
{
(void) mutex_lock(&netpp_mutex);
(void) mutex_unlock(&netpp_mutex);
return (NULL);
}
(void) mutex_unlock(&netpp_mutex);
for (;;) {
if (ipv6_present == -1)
if (!ipv6_present) {
++(nconf_handlep->nc_curr);
continue;
}
}
break;
}
++(nconf_handlep->nc_curr);
} else {
}
return (retp);
}
/*
* getnetconfig() searches the netconfig database for a
* given network id. Returns a pointer to the netconfig
* structure or a NULL if not found.
* It also check if ipv6 interface is present(ipv6_present) and
* skips udp6 & tcp6 entries if ipv6 is not supported.
*/
struct netconfig *
{
int ipv6_present;
(void) mutex_lock(&netpp_mutex);
(void) mutex_unlock(&netpp_mutex);
return (NULL);
}
(void) mutex_unlock(&netpp_mutex);
if (!ipv6_present) {
return (NULL);
}
}
return (netconfig_dup(*tpp));
}
}
return (NULL);
}
/*
* freenetconfigent frees the data allocated by getnetconfigent()
*/
void
{
}
/*
* getnetlist() reads the netconfig file and creates a
* NULL-terminated list of entries.
* Returns the pointer to the head of the list or a NULL
* on failure.
*/
static struct netconfig **
getnetlist(void)
{
return (NULL);
}
count = 0;
++count;
}
}
if (count == 0) {
return (NULL);
}
return (NULL);
}
/*
* The following loop fills in the list (loops until
* fgetnetconfig() returns a NULL) and counts the
* number of entries placed in the list. Note that
* when the loop is completed, the last entry in the
* list will contain a NULL (signifying the end of
* the list).
*/
linenum = 0;
;
return (listpp);
}
/*
* fgetnetconfig() parses a line of the netconfig file into
* a netconfig structure. It returns a pointer to the
* structure of success and a NULL on failure or EOF.
*/
static struct netconfig *
{
/* skip past blank lines and comments. */
linenum++;
break;
}
}
return (NULL);
}
fieldnum = 0;
return (NULL);
}
return (NULL);
}
return (NULL);
}
((netconfigp->nc_semantics =
netconfigp = NULL;
}
return (netconfigp);
}
/*
* setnetpath() has the effect of "initializing" the
* NETPATH variable. It reads in the netcf entries (if not
* already read in), creates a list corresponding to the entries
* in the NETPATH variable (or the "visible" entries og netconfig
* if NETPATH is not set).
*/
void *
setnetpath(void)
{
/*
* Read in the netconfig database if not already read in
*/
(void) mutex_lock(&netpp_mutex);
(void) mutex_unlock(&netpp_mutex);
return (NULL);
}
(void) mutex_unlock(&netpp_mutex);
return (NULL);
}
/*
* Get the valid entries of the NETPATH variable (and
* count the number of entries while doing it).
*
* This is done every time the procedure is called just
* in case NETPATH has changed from call to call.
*
* If NETPATH is too long, we ignore it altogether as
* it can only be a buffer overflow attack.
* Since we add one colon for each entry, but colons only
* need to exist between entries, we have to subtract one.
*/
count = 0;
valid_netpath[0] = '\0';
/*
* If NETPATH variable is not set or invalid,
* the valid NETPATH consist of all "visible"
* netids from the netconfig database.
*/
count++;
}
}
} else {
/*
* Copy the value of NETPATH (since '\0's will be
* put into the string) and create the valid NETPATH
* (by throwing away all netids not in the database).
* If an entry appears more than one, it *will* be
* listed twice in the list of valid netpath entries.
*/
while (*tp) {
/* Skip all leading ':'s */
tp++;
break; /* last one */
tp++;
if (*tp)
(void) strcat(valid_netpath,
count++;
break;
}
}
}
}
/* Get space to hold the valid list (+1 for the NULL) */
return (NULL);
}
/*
* Populate the NETPATH list, ending it with a NULL.
* Each entry in the list points to the structure in the
* "netpp" list (the entry must exist in the list, otherwise
* it wouldn't appear in valid_netpath[]).
*/
while (*tp) {
tp++;
if (*tp)
*tp++ = '\0';
break;
}
}
}
return ((void *)retp);
}
/*
* endnetpath() frees up all of the memory allocated by setnetpath().
* It returns -1 (error) if setnetpath was never called.
*/
int
{
/* The argument is really a NCONF_HANDLE; cast it here */
(void) mutex_lock(&netpp_mutex);
(void) mutex_unlock(&netpp_mutex);
return (-1);
}
(void) mutex_unlock(&netpp_mutex);
return (0);
}
/*
* getnetpath() returns the current entry in the list
* from the NETPATH variable. If setnetpath() was not called
* previously to set up the list, return NULL.
*/
struct netconfig *
{
/* The argument is really a NCONF_HANDLE; cast it here */
(void) mutex_lock(&netpp_mutex);
(void) mutex_unlock(&netpp_mutex);
return (NULL);
}
(void) mutex_unlock(&netpp_mutex);
for (;;) {
if (ipv6_present == -1)
if (!ipv6_present) {
++(nconf_handlep->nc_curr);
continue;
}
}
break;
}
if (retp) {
++(nconf_handlep->nc_curr);
} else {
}
return (retp);
}
/*
* blank() returns true if the line is a blank line, 0 otherwise
*/
static int
{
cp++;
}
return (*cp == '\0');
}
/*
* comment() returns true if the line is a comment, 0 otherwise.
*/
static int
{
cp++;
}
return (*cp == '#');
}
/*
* getvalue() searches for the given string in the given array,
* and return the integer value associated with the string.
*/
static unsigned int
{
int i; /* used to index through the given struct nc_data array */
break;
}
}
}
/*
* getflag() creates a bitmap of the one-character flags in
* the given string. It uses nc_flags array to get the values.
*/
static unsigned int
{
int i; /* indexs through the nc_flag array */
while (*cp) {
break;
}
}
cp++;
}
return (mask);
}
/*
* getlookups() creates and returns an array of string representing
* the directory lookup libraries, given as a comma-seperated list
* in the argument "cp".
*/
static char **
{
char *start;
if (num == 0)
return (NULL);
return (NULL);
while (num--) {
/*
* Traverse the string looking for the next entry
* of the list (i.e, where the ',' or end of the
* string appears). If a "\" is found, shift the
* token over 1 to the left (taking the next char
* literally).
*/
shift1left(cp);
}
cp++;
}
if (*cp)
*cp++ = '\0';
return (NULL);
}
}
return (listpp);
}
/*
* getnlookups() returns the number of entries in a comma-separated
* string of tokens. A "-" means no strings are present.
*/
static unsigned int
{
return (0);
count = 1;
while (*cp) {
if (*cp == ',') {
count++;
}
/*
* If a "\" is in the string, take the next character
* literally. Onlly skip the character if "\" is
* not the last character of the token.
*/
cp++;
}
cp++;
}
return (count);
}
/*
* gettoken() behaves much like strtok(), except that
* it knows about escaped space characters (i.e., space characters
* preceeded by a '\' are taken literally).
*/
static char *
{
char *p; /* the beginning of the new token */
fieldnum++;
/* Determine if first or subsequent call */
/* Return if no tokens remain. */
if (p == 0)
return (NULL);
while (isspace(*p))
p++;
if (*p == '\0')
return (NULL);
/*
* Save the location of the token and then skip past it
*/
retp = p;
while (*p) {
if (isspace(*p))
shift1left(p);
continue;
} else
break;
/*
* Only process the escape of the space seperator;
* since the token may contain other separators,
* let the other routines handle the escape of
* specific characters in the token.
*/
shift1left(p);
}
p++;
}
if (*p == '\0') {
savep = 0; /* indicate this is last token */
} else {
*p = '\0';
savep = ++p;
}
}
/*
* shift1left() moves all characters in the string over 1 to
* the left.
*/
static void
shift1left(char *p)
{
for (; *p; p++)
*p = *(p + 1);
}
char *
nc_sperror(void)
{
buf_main :
"nc_sperror: malloc failed when trying to create buffer\n");
return (NULL);
}
switch (nc_error) {
case NC_NOERROR:
break;
case NC_NOMEM:
BUFSIZ);
break;
case NC_NOSET:
"routine called before calling \
setnetpath() or setnetconfig()"), BUFSIZ);
break;
case NC_OPENFAIL:
BUFSIZ);
break;
case NC_BADLINE:
break;
case NC_NOTFOUND:
break;
case NC_NOMOREENTRIES:
break;
default:
BUFSIZ);
break;
}
return (retstr);
}
void
{
if (string)
else
}
static void
{
}
}
static void
{
int i;
if (netconfigp == NULL)
return;
if (netconfigp->nc_lookups)
for (i = 0; i < netconfigp->nc_nlookups; i++)
}
static struct netconfig *
{
int i;
return (NULL);
}
* sizeof (char *));
return (NULL);
}
for (i = 0; i < netconfigp->nc_nlookups; i++) {
nconf->nc_nlookups = i;
return (NULL);
}
}
return (nconf);
}
static void
{
if (foo)
}