17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5004388ebScasper * Common Development and Distribution License (the "License"). 6004388ebScasper * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 216935f61bSMarcel Telka 226935f61bSMarcel Telka /* 236935f61bSMarcel Telka * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 246935f61bSMarcel Telka */ 256935f61bSMarcel Telka 267c478bd9Sstevel@tonic-gate /* 27004388ebScasper * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 287c478bd9Sstevel@tonic-gate * Use is subject to license terms. 297c478bd9Sstevel@tonic-gate */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 327c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate #include <ctype.h> 357c478bd9Sstevel@tonic-gate #include <stdio.h> 367c478bd9Sstevel@tonic-gate #include <tiuser.h> 377c478bd9Sstevel@tonic-gate #include <netdir.h> 387c478bd9Sstevel@tonic-gate #include <netconfig.h> 397c478bd9Sstevel@tonic-gate #include <sys/utsname.h> 407c478bd9Sstevel@tonic-gate #include <sys/param.h> 417c478bd9Sstevel@tonic-gate #include <string.h> 427c478bd9Sstevel@tonic-gate #include <stdlib.h> 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate /* 457c478bd9Sstevel@tonic-gate * The generic name to address mappings for any transport that 467c478bd9Sstevel@tonic-gate * has strings for address (e.g., ISO Starlan). 477c478bd9Sstevel@tonic-gate * 487c478bd9Sstevel@tonic-gate * Address in ISO Starlan consist of arbitrary strings of 497c478bd9Sstevel@tonic-gate * characters. Because of this, the following routines 507c478bd9Sstevel@tonic-gate * create an "address" based on two strings, one gotten 517c478bd9Sstevel@tonic-gate * from a "host" file and one gotten from a "services" file. 527c478bd9Sstevel@tonic-gate * The two strings are catenated together (with a "." between 537c478bd9Sstevel@tonic-gate * them). The hosts file is /etc/net/starlan/hosts and 547c478bd9Sstevel@tonic-gate * contain lines of the form: 557c478bd9Sstevel@tonic-gate * 567c478bd9Sstevel@tonic-gate * arbitrary_string machname 577c478bd9Sstevel@tonic-gate * 587c478bd9Sstevel@tonic-gate * To make things simple, the "arbitrary string" should be the 597c478bd9Sstevel@tonic-gate * machine name. 607c478bd9Sstevel@tonic-gate * 617c478bd9Sstevel@tonic-gate * The services file is /etc/net/starlan/services and has lines 627c478bd9Sstevel@tonic-gate * of the form: 637c478bd9Sstevel@tonic-gate * 647c478bd9Sstevel@tonic-gate * service_name arbitrary_string 657c478bd9Sstevel@tonic-gate * 667c478bd9Sstevel@tonic-gate * Again, to make things easer, the "arbitrary name" should be the 677c478bd9Sstevel@tonic-gate * service name. 687c478bd9Sstevel@tonic-gate */ 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate #define HOSTFILE "/etc/net/%s/hosts" 717c478bd9Sstevel@tonic-gate #define SERVICEFILE "/etc/net/%s/services" 727c478bd9Sstevel@tonic-gate #define FIELD1 1 737c478bd9Sstevel@tonic-gate #define FIELD2 2 746935f61bSMarcel Telka #define LOCALHOST "localhost" 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate static int searchhost(struct netconfig *, char *, int, char *); 777c478bd9Sstevel@tonic-gate static int searchserv(struct netconfig *, char *, int, char *); 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate /* 807c478bd9Sstevel@tonic-gate * _netdir_getbyname() returns all of the addresses for 817c478bd9Sstevel@tonic-gate * a specified host and service. 827c478bd9Sstevel@tonic-gate */ 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate struct nd_addrlist * 857c478bd9Sstevel@tonic-gate _netdir_getbyname(struct netconfig *netconfigp, 867c478bd9Sstevel@tonic-gate struct nd_hostserv *nd_hostservp) 877c478bd9Sstevel@tonic-gate { 887c478bd9Sstevel@tonic-gate char fulladdr[BUFSIZ]; /* holds the full address string */ 897c478bd9Sstevel@tonic-gate struct nd_addrlist *retp; /* the return structure */ 907c478bd9Sstevel@tonic-gate struct netbuf *netbufp; /* indexes through the addresses */ 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate /* 937c478bd9Sstevel@tonic-gate * HOST_BROADCAST is not supported. 947c478bd9Sstevel@tonic-gate */ 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate if (strcmp(nd_hostservp->h_host, HOST_BROADCAST) == 0) { 977c478bd9Sstevel@tonic-gate _nderror = ND_NOHOST; 987c478bd9Sstevel@tonic-gate return (NULL); 997c478bd9Sstevel@tonic-gate } 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate if (searchhost(netconfigp, nd_hostservp->h_host, FIELD2, 1027c478bd9Sstevel@tonic-gate fulladdr) == 0) { 1037c478bd9Sstevel@tonic-gate _nderror = ND_NOHOST; 1047c478bd9Sstevel@tonic-gate return (NULL); 1057c478bd9Sstevel@tonic-gate } 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate /* 1087c478bd9Sstevel@tonic-gate * Now simply fill in the address by forming strings of the 1097c478bd9Sstevel@tonic-gate * form "string_from_hosts.string_from_services" 1107c478bd9Sstevel@tonic-gate */ 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate if (nd_hostservp->h_serv && 1137c478bd9Sstevel@tonic-gate (strcmp(nd_hostservp->h_serv, "rpcbind") == 0)) { 1147c478bd9Sstevel@tonic-gate (void) strcat(fulladdr, "."); 1157c478bd9Sstevel@tonic-gate (void) strcat(fulladdr, "rpc"); /* hard coded */ 1167c478bd9Sstevel@tonic-gate } else { 1177c478bd9Sstevel@tonic-gate /* 1187c478bd9Sstevel@tonic-gate * Get the address from the services file 1197c478bd9Sstevel@tonic-gate */ 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate if (nd_hostservp->h_serv && (nd_hostservp->h_serv[0] != '\0')) { 1227c478bd9Sstevel@tonic-gate (void) strcat(fulladdr, "."); 1237c478bd9Sstevel@tonic-gate if (searchserv(netconfigp, nd_hostservp->h_serv, FIELD1, 1247c478bd9Sstevel@tonic-gate fulladdr + strlen(fulladdr)) == 0) { 1257c478bd9Sstevel@tonic-gate _nderror = ND_NOSERV; 1267c478bd9Sstevel@tonic-gate return (NULL); 1277c478bd9Sstevel@tonic-gate } 1287c478bd9Sstevel@tonic-gate } 1297c478bd9Sstevel@tonic-gate } 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate if ((retp = malloc(sizeof (struct nd_addrlist))) == NULL) { 1327c478bd9Sstevel@tonic-gate _nderror = ND_NOMEM; 1337c478bd9Sstevel@tonic-gate return (NULL); 1347c478bd9Sstevel@tonic-gate } 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate /* 1377c478bd9Sstevel@tonic-gate * We do not worry about multiple addresses here. Loopbacks 1387c478bd9Sstevel@tonic-gate * have only one interface. 1397c478bd9Sstevel@tonic-gate */ 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate retp->n_cnt = 1; 1427c478bd9Sstevel@tonic-gate if ((retp->n_addrs = malloc(sizeof (struct netbuf))) == NULL) { 1437c478bd9Sstevel@tonic-gate free(retp); 1447c478bd9Sstevel@tonic-gate _nderror = ND_NOMEM; 1457c478bd9Sstevel@tonic-gate return (NULL); 1467c478bd9Sstevel@tonic-gate } 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate netbufp = retp->n_addrs; 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate /* 1517c478bd9Sstevel@tonic-gate * Don't include the terminating NULL character in the 1527c478bd9Sstevel@tonic-gate * length. 1537c478bd9Sstevel@tonic-gate */ 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate netbufp->len = netbufp->maxlen = (int)strlen(fulladdr); 1567c478bd9Sstevel@tonic-gate if ((netbufp->buf = strdup(fulladdr)) == NULL) { 1577c478bd9Sstevel@tonic-gate free(netbufp); 1587c478bd9Sstevel@tonic-gate free(retp); 1597c478bd9Sstevel@tonic-gate _nderror = ND_NOMEM; 1607c478bd9Sstevel@tonic-gate return (NULL); 1617c478bd9Sstevel@tonic-gate } 1627c478bd9Sstevel@tonic-gate _nderror = ND_OK; 1637c478bd9Sstevel@tonic-gate return (retp); 1647c478bd9Sstevel@tonic-gate } 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate /* 1677c478bd9Sstevel@tonic-gate * _netdir_getbyaddr() takes an address (hopefully obtained from 1687c478bd9Sstevel@tonic-gate * someone doing a _netdir_getbyname()) and returns all hosts with 1697c478bd9Sstevel@tonic-gate * that address. 1707c478bd9Sstevel@tonic-gate */ 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate struct nd_hostservlist * 1737c478bd9Sstevel@tonic-gate _netdir_getbyaddr(struct netconfig *netconfigp, struct netbuf *netbufp) 1747c478bd9Sstevel@tonic-gate { 1757c478bd9Sstevel@tonic-gate char fulladdr[BUFSIZ]; /* a copy of the address string */ 1767c478bd9Sstevel@tonic-gate char servbuf[BUFSIZ]; /* a buffer for service string */ 1777c478bd9Sstevel@tonic-gate char hostbuf[BUFSIZ]; /* points to list of host names */ 1787c478bd9Sstevel@tonic-gate char *hostname; /* the "first" path of the string */ 1797c478bd9Sstevel@tonic-gate char *servname; /* the "second" part of string */ 1807c478bd9Sstevel@tonic-gate struct nd_hostservlist *retp; /* the return structure */ 1817c478bd9Sstevel@tonic-gate char *serv; /* resultant service name obtained */ 1827c478bd9Sstevel@tonic-gate int nhost; /* the number of hosts in hostpp */ 1837c478bd9Sstevel@tonic-gate struct nd_hostserv *nd_hostservp; /* traverses the host structures */ 1847c478bd9Sstevel@tonic-gate char *nexttok; /* next token to process */ 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate /* 1877c478bd9Sstevel@tonic-gate * Separate the two parts of the address string. 1887c478bd9Sstevel@tonic-gate */ 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate (void) strlcpy(fulladdr, netbufp->buf, sizeof (fulladdr)); 1917c478bd9Sstevel@tonic-gate hostname = strtok_r(fulladdr, ".", &nexttok); 1927c478bd9Sstevel@tonic-gate if (hostname == NULL) { 1937c478bd9Sstevel@tonic-gate _nderror = ND_NOHOST; 1947c478bd9Sstevel@tonic-gate return (NULL); 1957c478bd9Sstevel@tonic-gate } 1967c478bd9Sstevel@tonic-gate servname = strtok_r(NULL, " \n\t", &nexttok); 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate /* 1997c478bd9Sstevel@tonic-gate * Search for all the hosts associated with the 2007c478bd9Sstevel@tonic-gate * first part of the address string. 2017c478bd9Sstevel@tonic-gate */ 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate nhost = searchhost(netconfigp, hostname, FIELD1, hostbuf); 2047c478bd9Sstevel@tonic-gate if (nhost == 0) { 2057c478bd9Sstevel@tonic-gate _nderror = ND_NOHOST; 2067c478bd9Sstevel@tonic-gate return (NULL); 2077c478bd9Sstevel@tonic-gate } 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate /* 2107c478bd9Sstevel@tonic-gate * Search for the service associated with the second 2117c478bd9Sstevel@tonic-gate * path of the address string. 2127c478bd9Sstevel@tonic-gate */ 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate if (servname == NULL) { 2157c478bd9Sstevel@tonic-gate _nderror = ND_NOSERV; 2167c478bd9Sstevel@tonic-gate return (NULL); 2177c478bd9Sstevel@tonic-gate } 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate servbuf[0] = '\0'; 2207c478bd9Sstevel@tonic-gate serv = servbuf; 2217c478bd9Sstevel@tonic-gate if (searchserv(netconfigp, servname, FIELD2, servbuf) == 0) { 2227c478bd9Sstevel@tonic-gate serv = _taddr2uaddr(netconfigp, netbufp); 2237c478bd9Sstevel@tonic-gate (void) strcpy(servbuf, serv); 2247c478bd9Sstevel@tonic-gate free(serv); 2257c478bd9Sstevel@tonic-gate serv = servbuf; 2267c478bd9Sstevel@tonic-gate while (*serv != '.') 2277c478bd9Sstevel@tonic-gate serv++; 2287c478bd9Sstevel@tonic-gate } 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate /* 2317c478bd9Sstevel@tonic-gate * Allocate space to hold the return structure, set the number 2327c478bd9Sstevel@tonic-gate * of hosts, and allocate space to hold them. 2337c478bd9Sstevel@tonic-gate */ 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate if ((retp = malloc(sizeof (struct nd_hostservlist))) == NULL) { 2367c478bd9Sstevel@tonic-gate _nderror = ND_NOMEM; 2377c478bd9Sstevel@tonic-gate return (NULL); 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate retp->h_cnt = nhost; 2417c478bd9Sstevel@tonic-gate retp->h_hostservs = calloc(nhost, sizeof (struct nd_hostserv)); 2427c478bd9Sstevel@tonic-gate if (retp->h_hostservs == NULL) { 2437c478bd9Sstevel@tonic-gate free(retp); 2447c478bd9Sstevel@tonic-gate _nderror = ND_NOMEM; 2457c478bd9Sstevel@tonic-gate return (NULL); 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate /* 2497c478bd9Sstevel@tonic-gate * Loop through the host structues and fill them in with 2507c478bd9Sstevel@tonic-gate * each host name (and service name). 2517c478bd9Sstevel@tonic-gate */ 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate nd_hostservp = retp->h_hostservs; 2547c478bd9Sstevel@tonic-gate hostname = strtok_r(hostbuf, ",", &nexttok); 2557c478bd9Sstevel@tonic-gate while (hostname && nhost--) { 2567c478bd9Sstevel@tonic-gate if (((nd_hostservp->h_host = strdup(hostname)) == NULL) || 2577c478bd9Sstevel@tonic-gate ((nd_hostservp->h_serv = strdup(serv)) == NULL)) { 2587c478bd9Sstevel@tonic-gate netdir_free(retp, ND_HOSTSERVLIST); 2597c478bd9Sstevel@tonic-gate _nderror = ND_NOMEM; 2607c478bd9Sstevel@tonic-gate return (NULL); 2617c478bd9Sstevel@tonic-gate } 2627c478bd9Sstevel@tonic-gate nd_hostservp++; 2637c478bd9Sstevel@tonic-gate hostname = strtok_r(NULL, ",", &nexttok); 2647c478bd9Sstevel@tonic-gate } 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate _nderror = ND_OK; 2677c478bd9Sstevel@tonic-gate return (retp); 2687c478bd9Sstevel@tonic-gate } 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate /* 2717c478bd9Sstevel@tonic-gate * _taddr2uaddr() translates a address into a "universal" address. 2727c478bd9Sstevel@tonic-gate * Since the address is a string, simply return the string as the 2737c478bd9Sstevel@tonic-gate * universal address (but replace all non-printable characters with 2747c478bd9Sstevel@tonic-gate * the \ddd form, where ddd is three octal digits). The '\n' character 2757c478bd9Sstevel@tonic-gate * is also replace by \ddd and the '\' character is placed as two 2767c478bd9Sstevel@tonic-gate * '\' characters. 2777c478bd9Sstevel@tonic-gate */ 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2807c478bd9Sstevel@tonic-gate char * 2817c478bd9Sstevel@tonic-gate _taddr2uaddr(struct netconfig *netconfigp, struct netbuf *netbufp) 2827c478bd9Sstevel@tonic-gate { 2837c478bd9Sstevel@tonic-gate char *retp; /* pointer the return string */ 2847c478bd9Sstevel@tonic-gate char *to; /* traverses and populates the return string */ 2857c478bd9Sstevel@tonic-gate char *from; /* traverses the string to be converted */ 2867c478bd9Sstevel@tonic-gate int i; /* indexes through the given string */ 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate /* 2897c478bd9Sstevel@tonic-gate * BUFSIZ is perhaps too big for this one and there is a better 2907c478bd9Sstevel@tonic-gate * way to optimize it, but for now we will just assume BUFSIZ 2917c478bd9Sstevel@tonic-gate */ 2927c478bd9Sstevel@tonic-gate if ((retp = malloc(BUFSIZ)) == NULL) { 2937c478bd9Sstevel@tonic-gate _nderror = ND_NOMEM; 2947c478bd9Sstevel@tonic-gate return (NULL); 2957c478bd9Sstevel@tonic-gate } 2967c478bd9Sstevel@tonic-gate to = retp; 2977c478bd9Sstevel@tonic-gate from = netbufp->buf; 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate for (i = 0; i < netbufp->len; i++) { 3007c478bd9Sstevel@tonic-gate if (*from == '\\') { 3017c478bd9Sstevel@tonic-gate *to++ = '\\'; 3027c478bd9Sstevel@tonic-gate *to++ = '\\'; 3037c478bd9Sstevel@tonic-gate } else { 3047c478bd9Sstevel@tonic-gate if (*from == '\n' || !isprint((unsigned char)*from)) { 3057c478bd9Sstevel@tonic-gate (void) sprintf(to, "\\%.3o", *from & 0xff); 3067c478bd9Sstevel@tonic-gate to += 4; 3077c478bd9Sstevel@tonic-gate } else { 3087c478bd9Sstevel@tonic-gate *to++ = *from; 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate } 3117c478bd9Sstevel@tonic-gate from++; 3127c478bd9Sstevel@tonic-gate } 3137c478bd9Sstevel@tonic-gate *to = '\0'; 3147c478bd9Sstevel@tonic-gate return (retp); 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate /* 3187c478bd9Sstevel@tonic-gate * _uaddr2taddr() translates a universal address back into a 3197c478bd9Sstevel@tonic-gate * netaddr structure. Since the universal address is a string, 3207c478bd9Sstevel@tonic-gate * put that into the TLI buffer (making sure to change all \ddd 3217c478bd9Sstevel@tonic-gate * characters back and strip off the trailing \0 character). 3227c478bd9Sstevel@tonic-gate */ 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate /* ARGSUSED */ 3257c478bd9Sstevel@tonic-gate struct netbuf * 3267c478bd9Sstevel@tonic-gate _uaddr2taddr(struct netconfig *netconfigp, char *uaddr) 3277c478bd9Sstevel@tonic-gate { 3287c478bd9Sstevel@tonic-gate struct netbuf *retp; /* the return structure */ 3297c478bd9Sstevel@tonic-gate char *holdp; /* holds the converted address */ 3307c478bd9Sstevel@tonic-gate char *to; /* traverses and populates the new address */ 3317c478bd9Sstevel@tonic-gate char *from; /* traverses the universal address */ 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate holdp = malloc(strlen(uaddr) + 1); 3347c478bd9Sstevel@tonic-gate if (holdp == NULL) { 3357c478bd9Sstevel@tonic-gate _nderror = ND_NOMEM; 3367c478bd9Sstevel@tonic-gate return (NULL); 3377c478bd9Sstevel@tonic-gate } 3387c478bd9Sstevel@tonic-gate from = uaddr; 3397c478bd9Sstevel@tonic-gate to = holdp; 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate while (*from) { 3427c478bd9Sstevel@tonic-gate if (*from == '\\') { 3437c478bd9Sstevel@tonic-gate if (*(from+1) == '\\') { 3447c478bd9Sstevel@tonic-gate *to = '\\'; 3457c478bd9Sstevel@tonic-gate from += 2; 3467c478bd9Sstevel@tonic-gate } else { 3477c478bd9Sstevel@tonic-gate *to = ((*(from+1) - '0') << 6) + 3487c478bd9Sstevel@tonic-gate ((*(from+2) - '0') << 3) + 3497c478bd9Sstevel@tonic-gate (*(from+3) - '0'); 3507c478bd9Sstevel@tonic-gate from += 4; 3517c478bd9Sstevel@tonic-gate } 3527c478bd9Sstevel@tonic-gate } else { 3537c478bd9Sstevel@tonic-gate *to = *from++; 3547c478bd9Sstevel@tonic-gate } 3557c478bd9Sstevel@tonic-gate to++; 3567c478bd9Sstevel@tonic-gate } 3577c478bd9Sstevel@tonic-gate *to = '\0'; 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate if ((retp = malloc(sizeof (struct netbuf))) == NULL) { 3607c478bd9Sstevel@tonic-gate free(holdp); 3617c478bd9Sstevel@tonic-gate _nderror = ND_NOMEM; 3627c478bd9Sstevel@tonic-gate return (NULL); 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate retp->maxlen = retp->len = (int)(to - holdp); 3657c478bd9Sstevel@tonic-gate retp->buf = holdp; 3667c478bd9Sstevel@tonic-gate return (retp); 3677c478bd9Sstevel@tonic-gate } 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate /* 3707c478bd9Sstevel@tonic-gate * _netdir_options() is a "catch-all" routine that does 3717c478bd9Sstevel@tonic-gate * transport specific things. The only thing that these 3727c478bd9Sstevel@tonic-gate * routines have to worry about is ND_MERGEADDR. 3737c478bd9Sstevel@tonic-gate */ 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate /* ARGSUSED */ 3767c478bd9Sstevel@tonic-gate int 3777c478bd9Sstevel@tonic-gate _netdir_options(struct netconfig *netconfigp, int option, int fd, void *par) 3787c478bd9Sstevel@tonic-gate { 3797c478bd9Sstevel@tonic-gate struct nd_mergearg *argp; /* the argument for mergeaddr */ 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate switch (option) { 3827c478bd9Sstevel@tonic-gate case ND_MERGEADDR: 3837c478bd9Sstevel@tonic-gate /* 3847c478bd9Sstevel@tonic-gate * Translate the universal address into something that 3857c478bd9Sstevel@tonic-gate * makes sense to the caller. This is a no-op in 3867c478bd9Sstevel@tonic-gate * loopback's case, so just return the universal address. 3877c478bd9Sstevel@tonic-gate */ 3887c478bd9Sstevel@tonic-gate argp = (struct nd_mergearg *)par; 3897c478bd9Sstevel@tonic-gate argp->m_uaddr = strdup(argp->s_uaddr); 390*9d4de077SMarcel Telka if (argp->m_uaddr == NULL) { 391*9d4de077SMarcel Telka _nderror = ND_NOMEM; 392*9d4de077SMarcel Telka return (-1); 393*9d4de077SMarcel Telka } 394*9d4de077SMarcel Telka return (0); 3957c478bd9Sstevel@tonic-gate default: 3967c478bd9Sstevel@tonic-gate _nderror = ND_NOCTRL; 3977c478bd9Sstevel@tonic-gate return (-1); 3987c478bd9Sstevel@tonic-gate } 3997c478bd9Sstevel@tonic-gate } 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate /* 4027c478bd9Sstevel@tonic-gate * searchhost() looks for the specified token in the host file. 4037c478bd9Sstevel@tonic-gate * The "field" parameter signifies which field to compare the token 4047c478bd9Sstevel@tonic-gate * on, and returns all comma separated values associated with the token. 4057c478bd9Sstevel@tonic-gate */ 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate static int 4087c478bd9Sstevel@tonic-gate searchhost(struct netconfig *netconfigp, char *token, int field, char *hostbuf) 4097c478bd9Sstevel@tonic-gate { 4107c478bd9Sstevel@tonic-gate char searchfile[MAXPATHLEN]; /* the name of file to be opened */ 4117c478bd9Sstevel@tonic-gate char buf[BUFSIZ]; /* holds each line of the file */ 4127c478bd9Sstevel@tonic-gate char *fileaddr; /* the first token in each line */ 4137c478bd9Sstevel@tonic-gate char *filehost; /* the second token in each line */ 4147c478bd9Sstevel@tonic-gate char *cmpstr; /* the string to compare token to */ 4157c478bd9Sstevel@tonic-gate char *retstr; /* the string to return if compare succeeds */ 4167c478bd9Sstevel@tonic-gate char *nexttok; /* next token to process */ 4177c478bd9Sstevel@tonic-gate FILE *fp; /* the opened searchfile */ 4187c478bd9Sstevel@tonic-gate int nelements = 0; /* total number of elements found */ 4196935f61bSMarcel Telka struct utsname utsname; 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate /* 4226935f61bSMarcel Telka * Unless /etc/netconfig has been altered, the only transport that 4236935f61bSMarcel Telka * will use straddr.so is loopback. In this case, we always 4246935f61bSMarcel Telka * return "localhost" if either our nodename, or "localhost", or 4256935f61bSMarcel Telka * some of special-case host names were passed, or we fail. 4267c478bd9Sstevel@tonic-gate */ 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate if ((strcmp(token, HOST_SELF_BIND) == 0) || 4297c478bd9Sstevel@tonic-gate (strcmp(token, HOST_SELF_CONNECT) == 0) || 4307c478bd9Sstevel@tonic-gate (strcmp(token, HOST_ANY) == 0) || 4316935f61bSMarcel Telka (strcmp(token, LOCALHOST) == 0) || 4326935f61bSMarcel Telka (uname(&utsname) >= 0 && strcmp(token, utsname.nodename) == 0)) { 4336935f61bSMarcel Telka (void) strcpy(hostbuf, LOCALHOST); 4347c478bd9Sstevel@tonic-gate return (1); 4357c478bd9Sstevel@tonic-gate } 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate if (strcmp(netconfigp->nc_protofmly, NC_LOOPBACK) == 0) 4387c478bd9Sstevel@tonic-gate return (0); 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate /* 4417c478bd9Sstevel@tonic-gate * We only get here if an administrator has modified 4427c478bd9Sstevel@tonic-gate * /etc/netconfig to use straddr.so for a transport other than 4437c478bd9Sstevel@tonic-gate * loopback (which is questionable but something we'll need to 4447c478bd9Sstevel@tonic-gate * EOL at a later point in time). In this case, we fallback to 4457c478bd9Sstevel@tonic-gate * searching for the associated key in the appropriate hosts 4467c478bd9Sstevel@tonic-gate * file (based on nc_netid). 4477c478bd9Sstevel@tonic-gate */ 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate (void) snprintf(searchfile, sizeof (searchfile), HOSTFILE, 4507c478bd9Sstevel@tonic-gate netconfigp->nc_netid); 4517c478bd9Sstevel@tonic-gate 452004388ebScasper fp = fopen(searchfile, "rF"); 4537c478bd9Sstevel@tonic-gate if (fp == NULL) 4547c478bd9Sstevel@tonic-gate return (0); 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate /* 4577c478bd9Sstevel@tonic-gate * Loop through the file looking for the tokens and creating 4587c478bd9Sstevel@tonic-gate * the list of strings to be returned. 4597c478bd9Sstevel@tonic-gate */ 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate while (fgets(buf, BUFSIZ, fp) != NULL) { 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate /* 4647c478bd9Sstevel@tonic-gate * Ignore comments and bad lines. 4657c478bd9Sstevel@tonic-gate */ 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate fileaddr = strtok_r(buf, " \t\n", &nexttok); 4687c478bd9Sstevel@tonic-gate if (fileaddr == NULL || *fileaddr == '#') 4697c478bd9Sstevel@tonic-gate continue; 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate if ((filehost = strtok_r(NULL, " \t\n", &nexttok)) == NULL) 4727c478bd9Sstevel@tonic-gate continue; 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate /* 4757c478bd9Sstevel@tonic-gate * determine which to compare the token to, then 4767c478bd9Sstevel@tonic-gate * compare it, and if they match, add the return 4777c478bd9Sstevel@tonic-gate * string to the list. 4787c478bd9Sstevel@tonic-gate */ 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate cmpstr = (field == FIELD1)? fileaddr : filehost; 4817c478bd9Sstevel@tonic-gate retstr = (field == FIELD1)? filehost : fileaddr; 4827c478bd9Sstevel@tonic-gate 4837c478bd9Sstevel@tonic-gate if (strcmp(token, cmpstr) == 0) { 4847c478bd9Sstevel@tonic-gate nelements++; 4857c478bd9Sstevel@tonic-gate if (field == FIELD2) { 4867c478bd9Sstevel@tonic-gate /* 4877c478bd9Sstevel@tonic-gate * called by _netdir_getbyname 4887c478bd9Sstevel@tonic-gate */ 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate (void) strcpy(hostbuf, retstr); 4917c478bd9Sstevel@tonic-gate break; 4927c478bd9Sstevel@tonic-gate } 4937c478bd9Sstevel@tonic-gate if (nelements > 1) { 4947c478bd9Sstevel@tonic-gate /* 4957c478bd9Sstevel@tonic-gate * Assuming that "," will never be a part 4967c478bd9Sstevel@tonic-gate * of any host name. 4977c478bd9Sstevel@tonic-gate */ 4987c478bd9Sstevel@tonic-gate (void) strcat(hostbuf, ","); 4997c478bd9Sstevel@tonic-gate } 5007c478bd9Sstevel@tonic-gate (void) strcat(hostbuf, retstr); 5017c478bd9Sstevel@tonic-gate } 5027c478bd9Sstevel@tonic-gate } 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate (void) fclose(fp); 5057c478bd9Sstevel@tonic-gate return (nelements); 5067c478bd9Sstevel@tonic-gate } 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate /* 5097c478bd9Sstevel@tonic-gate * searchserv() looks for the specified token in the service file. 5107c478bd9Sstevel@tonic-gate * The "field" parameter signifies which field to compare the token 5117c478bd9Sstevel@tonic-gate * on, and returns the string associated with the token in servname. 5127c478bd9Sstevel@tonic-gate */ 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate static int 5157c478bd9Sstevel@tonic-gate searchserv(struct netconfig *netconfigp, char *token, int field, char *servname) 5167c478bd9Sstevel@tonic-gate { 5177c478bd9Sstevel@tonic-gate char searchfile[MAXPATHLEN]; /* the name of file to be opened */ 5187c478bd9Sstevel@tonic-gate char buf[BUFSIZ]; /* buffer space for lines in file */ 5197c478bd9Sstevel@tonic-gate char *fileservice; /* the first token in each line */ 5207c478bd9Sstevel@tonic-gate char *fileport; /* the second token in each line */ 5217c478bd9Sstevel@tonic-gate char *cmpstr; /* the string to compare the token to */ 5227c478bd9Sstevel@tonic-gate char *retstr; /* temporarily hold token in line of file */ 5237c478bd9Sstevel@tonic-gate char *nexttok; /* next token to process */ 5247c478bd9Sstevel@tonic-gate FILE *fp; /* the opened searchfile */ 5257c478bd9Sstevel@tonic-gate 5267c478bd9Sstevel@tonic-gate (void) snprintf(searchfile, sizeof (searchfile), SERVICEFILE, 5277c478bd9Sstevel@tonic-gate netconfigp->nc_netid); 5287c478bd9Sstevel@tonic-gate 529004388ebScasper fp = fopen(searchfile, "rF"); 5307c478bd9Sstevel@tonic-gate if (fp == NULL) 5317c478bd9Sstevel@tonic-gate return (0); 5327c478bd9Sstevel@tonic-gate 5337c478bd9Sstevel@tonic-gate /* 5347c478bd9Sstevel@tonic-gate * Loop through the services file looking for the token. 5357c478bd9Sstevel@tonic-gate */ 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate while (fgets(buf, BUFSIZ, fp) != NULL) { 5387c478bd9Sstevel@tonic-gate /* 5397c478bd9Sstevel@tonic-gate * If comment or bad line, continue. 5407c478bd9Sstevel@tonic-gate */ 5417c478bd9Sstevel@tonic-gate fileservice = strtok_r(buf, " \t\n", &nexttok); 5427c478bd9Sstevel@tonic-gate if (fileservice == NULL || *fileservice == '#') 5437c478bd9Sstevel@tonic-gate continue; 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate if ((fileport = strtok_r(NULL, " \t\n", &nexttok)) == NULL) 5467c478bd9Sstevel@tonic-gate continue; 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate cmpstr = (field == FIELD1)? fileservice : fileport; 5497c478bd9Sstevel@tonic-gate retstr = (field == FIELD1)? fileport : fileservice; 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate if (strcmp(token, cmpstr) == 0) { 5527c478bd9Sstevel@tonic-gate (void) strcpy(servname, retstr); 5537c478bd9Sstevel@tonic-gate (void) fclose(fp); 5547c478bd9Sstevel@tonic-gate return (1); 5557c478bd9Sstevel@tonic-gate } 5567c478bd9Sstevel@tonic-gate } 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate (void) fclose(fp); 5597c478bd9Sstevel@tonic-gate return (0); 5607c478bd9Sstevel@tonic-gate } 561