1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23 /* All Rights Reserved */ 24 25 26 /* 27 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 /* 34 * nlsenv.c: 35 * 36 * Utilities for servers to access environment set by listener. 37 * 38 * nlsgetcall: Returns pointer to t_call structure listener recieved during 39 * the t_listen. Gets data from environment and converts 40 * the data to internal address form. 41 * 42 * nlsprovider: Returns name of provider from environment. 43 * 44 */ 45 46 #include <ctype.h> 47 #include <strings.h> 48 #include <sys/tiuser.h> 49 #include "listen.h" 50 51 /* 52 * define DEBUGMODE for diagnostic printf's to stderr 53 */ 54 55 /* #define DEBUGMODE */ 56 57 #ifdef DEBUGMODE 58 #include <stdio.h> 59 #endif 60 61 /* 62 * nlsenv: (static) 63 * 64 * Given an environment variable name, a receiving buffer and the length 65 * of the receiving buffer, getenv gets the environment variable, decodes 66 * it and places the decoded data in addr. The return value is the length 67 * of "addr" if succesful, or a negative value if unsuccessful. 68 */ 69 70 extern char *getenv(); 71 72 int 73 nlsenv(struct netbuf *buf, char *envname) 74 { 75 char *charaddr; 76 extern char *calloc(); 77 extern int nlsc2addr(); 78 int length; 79 80 if (!(charaddr = getenv(envname))) 81 return(-11); 82 83 #ifdef DEBUGMODE 84 fprintf(stderr, "nlsenv: environ %s = %s len = %d\n", 85 envname, charaddr, strlen(charaddr)); 86 #endif 87 88 if ((int)strlen(charaddr) & 1) 89 return(-12); 90 91 length = (strlen(charaddr) + 1) / 2; 92 if (!(buf->buf = calloc(1, length))) 93 return(-13); 94 else 95 buf->maxlen = length; 96 return(nlsc2addr(buf->buf, buf->maxlen, charaddr)); 97 } 98 99 100 /* 101 * nlsgetcall: Get calling data provided by the client via the listener. 102 * 103 * nlsgetcall allows network server processes started by the 104 * network listener process to access the callers 't_call' 105 * structure provided in the client's t_connect primitive. 106 * 107 * This routine gets this data from the environment 108 * via putenv(3C), interprets the data and places the data 109 * in a t_call structure allocated via t_alloc. 110 * 111 * synopsis: 112 * 113 * struct t_call *nlsgetcall(fd); 114 * int fd; arg now ignored 115 * 116 * 117 * returns: Address of an allocated t_call structure 118 * or 119 * NULL for failure. (calloc failed) 120 * If calloc succeeds, non-existant 121 * env. variables or data is indicated 122 * by a negative 'len' field in the approp. 123 * netbuf structure. A length of zero in the 124 * netbuf structure is valid. 125 * 126 */ 127 128 struct t_call * 129 nlsgetcall(int fd) 130 { 131 struct t_call *call; 132 extern char *calloc(); 133 134 if (!(call = (struct t_call *) calloc(1, sizeof(struct t_call)))) 135 return((struct t_call *)0); 136 137 /* 138 * Note: space for buffers gets allocated by nlsenv on the fly 139 */ 140 141 call->addr.len = nlsenv(&call->addr, NLSADDR); 142 call->opt.len = nlsenv(&call->opt, NLSOPT); 143 call->udata.len = nlsenv(&call->udata, NLSUDATA); 144 145 return (call); 146 } 147 148 149 /* 150 * nlsprovider: Return the name of the transport provider 151 * as placed in the environment by the Network listener 152 * process. If the variable is not defined in the 153 * environment, a NULL pointer is returned. 154 * 155 * If the provider is "/dev/starlan", nlsprovider 156 * returns a pointer to the null terminated character string: 157 * "/dev/starlan" if this calling process is a child of the 158 * network listener process. 159 */ 160 161 char * 162 nlsprovider() 163 { 164 return(getenv(NLSPROVIDER)); 165 } 166 167 168 /* 169 * nlsc2addr: Convert external address to internal form. 170 * (from nlsaddr.c) 171 */ 172 173 /* 174 * asctohex(X): convert char X to integer value 175 * assumes isxdigit(X). returns integer value. 176 * Note that 'a' > 'A'. See usage in code below. 177 */ 178 179 #define asctohex(X) \ 180 ((int)(isdigit(X) ? (int)(X-'0') : (X>='a') ? (X-'a')+10 : (X-'A')+10)) 181 182 /* 183 * nlsc2addr: Given a buffer containing the hex/ascii representation 184 * of a logical address, the buffer's size and an address 185 * of a receiving buffer, char2addr converts the logical 186 * addr to internal format and returns the size of the logical 187 * address. A negative value is returned and the receiving 188 * buffers contents are undefined if: 189 * 190 * A. The receiving buffer is not large enough. (rc = -1) 191 * B. If 'charaddr' does not contain a series of octets 192 * (strlen(charaddr) must be even). (rc = -2) 193 * C. Any character in 'charaddr' is not an ASCII hex digit. 194 * (rc = -3) 195 * 196 * NOTE: that even if the internal representation of an address is 197 * an ASCII string, there is no guarantee that the output will be 198 * null terminated, thus the returned length must be used when 199 * accessing the internal address. 200 */ 201 202 203 int 204 nlsc2addr(char *addr, int maxlen, char *charaddr) 205 { 206 int len; 207 int i; 208 char c; 209 unsigned char val; 210 211 if (strlen(charaddr) & 1) 212 return(-1); 213 214 for (len = 0; ((maxlen--) && (*charaddr)); ++len) { 215 for (i = 2, val = 0; i--; ) { 216 c = *charaddr++; 217 if (!(isxdigit(c))) 218 return(-3); 219 val = (val << 4) | (unsigned char)asctohex(c); 220 } 221 222 *addr++ = (char)val; 223 } 224 225 #ifdef DEBUGMODE 226 fprintf(stderr, "nlsc2addr: returned length = %d\n", len); 227 #endif 228 229 return(*charaddr ? -2 : len); 230 } 231