straddr.c revision 6935f61b0d202f1b87f0234824e4a6ab88c492ac
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * CDDL HEADER START
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * The contents of this file are subject to the terms of the
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Common Development and Distribution License (the "License").
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * You may not use this file except in compliance with the License.
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * or http://www.opensolaris.org/os/licensing.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * See the License for the specific language governing permissions
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * and limitations under the License.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * When distributing Covered Code, include this CDDL HEADER in each
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * If applicable, add the following below this CDDL HEADER, with the
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * fields enclosed by brackets "[]" replaced with your own identifying
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * information: Portions Copyright [yyyy] [name of copyright owner]
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * CDDL HEADER END
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Use is subject to license terms.
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz/* All Rights Reserved */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <ctype.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <stdio.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <tiuser.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <netdir.h>
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#include <netconfig.h>
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#include <sys/utsname.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <sys/param.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <string.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <stdlib.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The generic name to address mappings for any transport that
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * has strings for address (e.g., ISO Starlan).
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Address in ISO Starlan consist of arbitrary strings of
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * characters. Because of this, the following routines
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * create an "address" based on two strings, one gotten
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * from a "host" file and one gotten from a "services" file.
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz * The two strings are catenated together (with a "." between
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz * them). The hosts file is /etc/net/starlan/hosts and
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * contain lines of the form:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * arbitrary_string machname
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * To make things simple, the "arbitrary string" should be the
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz * machine name.
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The services file is /etc/net/starlan/services and has lines
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * of the form:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * service_name arbitrary_string
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Again, to make things easer, the "arbitrary name" should be the
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * service name.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define HOSTFILE "/etc/net/%s/hosts"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define SERVICEFILE "/etc/net/%s/services"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define FIELD1 1
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define FIELD2 2
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define LOCALHOST "localhost"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int searchhost(struct netconfig *, char *, int, char *);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int searchserv(struct netconfig *, char *, int, char *);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * _netdir_getbyname() returns all of the addresses for
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * a specified host and service.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstruct nd_addrlist *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin_netdir_getbyname(struct netconfig *netconfigp,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct nd_hostserv *nd_hostservp)
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner{
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner char fulladdr[BUFSIZ]; /* holds the full address string */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct nd_addrlist *retp; /* the return structure */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct netbuf *netbufp; /* indexes through the addresses */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * HOST_BROADCAST is not supported.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (strcmp(nd_hostservp->h_host, HOST_BROADCAST) == 0) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _nderror = ND_NOHOST;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (NULL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (searchhost(netconfigp, nd_hostservp->h_host, FIELD2,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fulladdr) == 0) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _nderror = ND_NOHOST;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (NULL);
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Now simply fill in the address by forming strings of the
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * form "string_from_hosts.string_from_services"
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if (nd_hostservp->h_serv &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (strcmp(nd_hostservp->h_serv, "rpcbind") == 0)) {
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner (void) strcat(fulladdr, ".");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (void) strcat(fulladdr, "rpc"); /* hard coded */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin } else {
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner /*
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * Get the address from the services file
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner */
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if (nd_hostservp->h_serv && (nd_hostservp->h_serv[0] != '\0')) {
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner (void) strcat(fulladdr, ".");
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if (searchserv(netconfigp, nd_hostservp->h_serv, FIELD1,
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner fulladdr + strlen(fulladdr)) == 0) {
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner _nderror = ND_NOSERV;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (NULL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner }
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner }
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if ((retp = malloc(sizeof (struct nd_addrlist))) == NULL) {
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner _nderror = ND_NOMEM;
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner return (NULL);
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner }
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner /*
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * We do not worry about multiple addresses here. Loopbacks
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * have only one interface.
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner */
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner retp->n_cnt = 1;
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if ((retp->n_addrs = malloc(sizeof (struct netbuf))) == NULL) {
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner free(retp);
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner _nderror = ND_NOMEM;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (NULL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner netbufp = retp->n_addrs;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Don't include the terminating NULL character in the
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * length.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin netbufp->len = netbufp->maxlen = (int)strlen(fulladdr);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((netbufp->buf = strdup(fulladdr)) == NULL) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free(netbufp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free(retp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _nderror = ND_NOMEM;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (NULL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _nderror = ND_OK;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (retp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * _netdir_getbyaddr() takes an address (hopefully obtained from
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * someone doing a _netdir_getbyname()) and returns all hosts with
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * that address.
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainzstruct nd_hostservlist *
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz_netdir_getbyaddr(struct netconfig *netconfigp, struct netbuf *netbufp)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz{
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz char fulladdr[BUFSIZ]; /* a copy of the address string */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz char servbuf[BUFSIZ]; /* a buffer for service string */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz char hostbuf[BUFSIZ]; /* points to list of host names */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz char *hostname; /* the "first" path of the string */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz char *servname; /* the "second" part of string */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz struct nd_hostservlist *retp; /* the return structure */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz char *serv; /* resultant service name obtained */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz int nhost; /* the number of hosts in hostpp */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz struct nd_hostserv *nd_hostservp; /* traverses the host structures */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz char *nexttok; /* next token to process */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz /*
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz * Separate the two parts of the address string.
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (void) strlcpy(fulladdr, netbufp->buf, sizeof (fulladdr));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin hostname = strtok_r(fulladdr, ".", &nexttok);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (hostname == NULL) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _nderror = ND_NOHOST;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (NULL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin servname = strtok_r(NULL, " \n\t", &nexttok);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Search for all the hosts associated with the
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * first part of the address string.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nhost = searchhost(netconfigp, hostname, FIELD1, hostbuf);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (nhost == 0) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _nderror = ND_NOHOST;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (NULL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Search for the service associated with the second
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * path of the address string.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (servname == NULL) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _nderror = ND_NOSERV;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (NULL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin servbuf[0] = '\0';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin serv = servbuf;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (searchserv(netconfigp, servname, FIELD2, servbuf) == 0) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin serv = _taddr2uaddr(netconfigp, netbufp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (void) strcpy(servbuf, serv);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free(serv);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin serv = servbuf;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (*serv != '.')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin serv++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Allocate space to hold the return structure, set the number
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * of hosts, and allocate space to hold them.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((retp = malloc(sizeof (struct nd_hostservlist))) == NULL) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _nderror = ND_NOMEM;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (NULL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin retp->h_cnt = nhost;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin retp->h_hostservs = calloc(nhost, sizeof (struct nd_hostserv));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (retp->h_hostservs == NULL) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free(retp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _nderror = ND_NOMEM;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (NULL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Loop through the host structues and fill them in with
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * each host name (and service name).
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nd_hostservp = retp->h_hostservs;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin hostname = strtok_r(hostbuf, ",", &nexttok);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (hostname && nhost--) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (((nd_hostservp->h_host = strdup(hostname)) == NULL) ||
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ((nd_hostservp->h_serv = strdup(serv)) == NULL)) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin netdir_free(retp, ND_HOSTSERVLIST);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _nderror = ND_NOMEM;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (NULL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nd_hostservp++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin hostname = strtok_r(NULL, ",", &nexttok);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _nderror = ND_OK;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (retp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * _taddr2uaddr() translates a address into a "universal" address.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Since the address is a string, simply return the string as the
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * universal address (but replace all non-printable characters with
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * the \ddd form, where ddd is three octal digits). The '\n' character
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * is also replace by \ddd and the '\' character is placed as two
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * '\' characters.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* ARGSUSED */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinchar *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin_taddr2uaddr(struct netconfig *netconfigp, struct netbuf *netbufp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char *retp; /* pointer the return string */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char *to; /* traverses and populates the return string */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char *from; /* traverses the string to be converted */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int i; /* indexes through the given string */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * BUFSIZ is perhaps too big for this one and there is a better
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * way to optimize it, but for now we will just assume BUFSIZ
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((retp = malloc(BUFSIZ)) == NULL) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _nderror = ND_NOMEM;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (NULL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin to = retp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin from = netbufp->buf;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 0; i < netbufp->len; i++) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*from == '\\') {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *to++ = '\\';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *to++ = '\\';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin } else {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*from == '\n' || !isprint((unsigned char)*from)) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (void) sprintf(to, "\\%.3o", *from & 0xff);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin to += 4;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin } else {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *to++ = *from;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin from++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *to = '\0';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (retp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * _uaddr2taddr() translates a universal address back into a
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * netaddr structure. Since the universal address is a string,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * put that into the TLI buffer (making sure to change all \ddd
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * characters back and strip off the trailing \0 character).
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* ARGSUSED */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstruct netbuf *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin_uaddr2taddr(struct netconfig *netconfigp, char *uaddr)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct netbuf *retp; /* the return structure */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char *holdp; /* holds the converted address */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char *to; /* traverses and populates the new address */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char *from; /* traverses the universal address */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin holdp = malloc(strlen(uaddr) + 1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (holdp == NULL) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _nderror = ND_NOMEM;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (NULL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin from = uaddr;
to = holdp;
while (*from) {
if (*from == '\\') {
if (*(from+1) == '\\') {
*to = '\\';
from += 2;
} else {
*to = ((*(from+1) - '0') << 6) +
((*(from+2) - '0') << 3) +
(*(from+3) - '0');
from += 4;
}
} else {
*to = *from++;
}
to++;
}
*to = '\0';
if ((retp = malloc(sizeof (struct netbuf))) == NULL) {
free(holdp);
_nderror = ND_NOMEM;
return (NULL);
}
retp->maxlen = retp->len = (int)(to - holdp);
retp->buf = holdp;
return (retp);
}
/*
* _netdir_options() is a "catch-all" routine that does
* transport specific things. The only thing that these
* routines have to worry about is ND_MERGEADDR.
*/
/* ARGSUSED */
int
_netdir_options(struct netconfig *netconfigp, int option, int fd, void *par)
{
struct nd_mergearg *argp; /* the argument for mergeaddr */
switch (option) {
case ND_MERGEADDR:
/*
* Translate the universal address into something that
* makes sense to the caller. This is a no-op in
* loopback's case, so just return the universal address.
*/
argp = (struct nd_mergearg *)par;
argp->m_uaddr = strdup(argp->s_uaddr);
return (argp->m_uaddr == NULL? -1 : 0);
default:
_nderror = ND_NOCTRL;
return (-1);
}
}
/*
* searchhost() looks for the specified token in the host file.
* The "field" parameter signifies which field to compare the token
* on, and returns all comma separated values associated with the token.
*/
static int
searchhost(struct netconfig *netconfigp, char *token, int field, char *hostbuf)
{
char searchfile[MAXPATHLEN]; /* the name of file to be opened */
char buf[BUFSIZ]; /* holds each line of the file */
char *fileaddr; /* the first token in each line */
char *filehost; /* the second token in each line */
char *cmpstr; /* the string to compare token to */
char *retstr; /* the string to return if compare succeeds */
char *nexttok; /* next token to process */
FILE *fp; /* the opened searchfile */
int nelements = 0; /* total number of elements found */
struct utsname utsname;
/*
* Unless /etc/netconfig has been altered, the only transport that
* will use straddr.so is loopback. In this case, we always
* return "localhost" if either our nodename, or "localhost", or
* some of special-case host names were passed, or we fail.
*/
if ((strcmp(token, HOST_SELF_BIND) == 0) ||
(strcmp(token, HOST_SELF_CONNECT) == 0) ||
(strcmp(token, HOST_ANY) == 0) ||
(strcmp(token, LOCALHOST) == 0) ||
(uname(&utsname) >= 0 && strcmp(token, utsname.nodename) == 0)) {
(void) strcpy(hostbuf, LOCALHOST);
return (1);
}
if (strcmp(netconfigp->nc_protofmly, NC_LOOPBACK) == 0)
return (0);
/*
* We only get here if an administrator has modified
* /etc/netconfig to use straddr.so for a transport other than
* loopback (which is questionable but something we'll need to
* EOL at a later point in time). In this case, we fallback to
* searching for the associated key in the appropriate hosts
* file (based on nc_netid).
*/
(void) snprintf(searchfile, sizeof (searchfile), HOSTFILE,
netconfigp->nc_netid);
fp = fopen(searchfile, "rF");
if (fp == NULL)
return (0);
/*
* Loop through the file looking for the tokens and creating
* the list of strings to be returned.
*/
while (fgets(buf, BUFSIZ, fp) != NULL) {
/*
* Ignore comments and bad lines.
*/
fileaddr = strtok_r(buf, " \t\n", &nexttok);
if (fileaddr == NULL || *fileaddr == '#')
continue;
if ((filehost = strtok_r(NULL, " \t\n", &nexttok)) == NULL)
continue;
/*
* determine which to compare the token to, then
* compare it, and if they match, add the return
* string to the list.
*/
cmpstr = (field == FIELD1)? fileaddr : filehost;
retstr = (field == FIELD1)? filehost : fileaddr;
if (strcmp(token, cmpstr) == 0) {
nelements++;
if (field == FIELD2) {
/*
* called by _netdir_getbyname
*/
(void) strcpy(hostbuf, retstr);
break;
}
if (nelements > 1) {
/*
* Assuming that "," will never be a part
* of any host name.
*/
(void) strcat(hostbuf, ",");
}
(void) strcat(hostbuf, retstr);
}
}
(void) fclose(fp);
return (nelements);
}
/*
* searchserv() looks for the specified token in the service file.
* The "field" parameter signifies which field to compare the token
* on, and returns the string associated with the token in servname.
*/
static int
searchserv(struct netconfig *netconfigp, char *token, int field, char *servname)
{
char searchfile[MAXPATHLEN]; /* the name of file to be opened */
char buf[BUFSIZ]; /* buffer space for lines in file */
char *fileservice; /* the first token in each line */
char *fileport; /* the second token in each line */
char *cmpstr; /* the string to compare the token to */
char *retstr; /* temporarily hold token in line of file */
char *nexttok; /* next token to process */
FILE *fp; /* the opened searchfile */
(void) snprintf(searchfile, sizeof (searchfile), SERVICEFILE,
netconfigp->nc_netid);
fp = fopen(searchfile, "rF");
if (fp == NULL)
return (0);
/*
* Loop through the services file looking for the token.
*/
while (fgets(buf, BUFSIZ, fp) != NULL) {
/*
* If comment or bad line, continue.
*/
fileservice = strtok_r(buf, " \t\n", &nexttok);
if (fileservice == NULL || *fileservice == '#')
continue;
if ((fileport = strtok_r(NULL, " \t\n", &nexttok)) == NULL)
continue;
cmpstr = (field == FIELD1)? fileservice : fileport;
retstr = (field == FIELD1)? fileport : fileservice;
if (strcmp(token, cmpstr) == 0) {
(void) strcpy(servname, retstr);
(void) fclose(fp);
return (1);
}
}
(void) fclose(fp);
return (0);
}