xref: /illumos-gate/usr/src/lib/libnls/common/nlsenv.c (revision d48be21240dfd051b689384ce2b23479d757f2d8)
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 /*
32  * nlsenv.c:
33  *
34  * Utilities for servers to access environment set by listener.
35  *
36  * nlsgetcall:	Returns pointer to t_call structure listener recieved during
37  *		the t_listen.  Gets data from environment and converts
38  *		the data to internal address form.
39  *
40  * nlsprovider:	Returns name of provider from environment.
41  *
42  */
43 
44 #include <ctype.h>
45 #include <strings.h>
46 #include <sys/tiuser.h>
47 #include "listen.h"
48 
49 /*
50  * define DEBUGMODE for diagnostic printf's to stderr
51  */
52 
53 /* #define	DEBUGMODE */
54 
55 #ifdef	DEBUGMODE
56 #include <stdio.h>
57 #endif
58 
59 /*
60  * nlsenv: (static)
61  *
62  * Given an environment variable name, a receiving buffer and the length
63  * of the receiving buffer, getenv gets the environment variable, decodes
64  * it and places the decoded data in addr.  The return value is the length
65  * of "addr" if succesful, or a negative value if unsuccessful.
66  */
67 
68 extern char *getenv();
69 
70 int
71 nlsenv(struct netbuf *buf, char *envname)
72 {
73 	char *charaddr;
74 	extern char *calloc();
75 	extern int nlsc2addr();
76 	int length;
77 
78 	if (!(charaddr = getenv(envname)))
79 		return(-11);
80 
81 #ifdef	DEBUGMODE
82 	fprintf(stderr, "nlsenv: environ %s = %s len = %d\n",
83 		envname, charaddr, strlen(charaddr));
84 #endif
85 
86 	if ((int)strlen(charaddr) & 1)
87 		return(-12);
88 
89 	length = (strlen(charaddr) + 1) / 2;
90 	if (!(buf->buf = calloc(1, length)))
91 		return(-13);
92 	else
93 		buf->maxlen = length;
94 	return(nlsc2addr(buf->buf, buf->maxlen, charaddr));
95 }
96 
97 
98 /*
99  * nlsgetcall:	Get calling data provided by the client via the listener.
100  *
101  *		nlsgetcall allows network server processes started by the
102  *		network listener process to access the callers 't_call'
103  *		structure provided in the client's t_connect primitive.
104  *
105  *		This routine gets this data from the environment
106  *		via putenv(3C), interprets the data and places the data
107  *		in a t_call structure allocated via t_alloc.
108  *
109  *		synopsis:
110  *
111  *		struct t_call *nlsgetcall(fd);
112  *		int fd;		arg now ignored
113  *
114  *
115  *		returns:	Address of an allocated t_call structure
116  *				or
117  *				NULL for failure. (calloc failed)
118  *				If calloc succeeds, non-existant
119  *				env. variables or data is indicated
120  *				by a negative 'len' field in the approp.
121  *				netbuf structure.  A length of zero in the
122  *				netbuf structure is valid.
123  *
124  */
125 
126 struct t_call *
127 nlsgetcall(int fd)
128 {
129 	struct t_call *call;
130 	extern char *calloc();
131 
132 	if (!(call = (struct t_call *) calloc(1, sizeof(struct t_call))))
133 		return((struct t_call *)0);
134 
135 /*
136  * Note: space for buffers gets allocated by nlsenv on the fly
137  */
138 
139 	call->addr.len = nlsenv(&call->addr, NLSADDR);
140 	call->opt.len = nlsenv(&call->opt, NLSOPT);
141 	call->udata.len = nlsenv(&call->udata, NLSUDATA);
142 
143 	return (call);
144 }
145 
146 
147 /*
148  * nlsprovider:	Return the name of the transport provider
149  *		as placed in the environment by the Network listener
150  *		process.  If the variable is not defined in the
151  *		environment, a NULL pointer is returned.
152  *
153  *		If the provider is "/dev/starlan", nlsprovider
154  *		returns a pointer to the null terminated character string:
155  *		"/dev/starlan" if this calling process is a child of the
156  *		network listener process.
157  */
158 
159 char *
160 nlsprovider()
161 {
162 	return(getenv(NLSPROVIDER));
163 }
164 
165 
166 /*
167  * nlsc2addr:	Convert external address to internal form.
168  *	(from nlsaddr.c)
169  */
170 
171 /*
172  * asctohex(X):  convert char X to integer value
173  *		 assumes isxdigit(X). returns integer value.
174  *		 Note that 'a' > 'A'.  See usage in code below.
175  */
176 
177 #define asctohex(X)	\
178     ((int)(isdigit(X) ? (int)(X-'0') : (X>='a') ? (X-'a')+10 : (X-'A')+10))
179 
180 /*
181  * nlsc2addr:	Given a buffer containing the hex/ascii representation
182  *		of a logical address, the buffer's size and an address
183  *		of a receiving buffer, char2addr converts the logical
184  *		addr to internal format and returns the size of the logical
185  *		address.  A negative value is returned and the receiving
186  *		buffers contents are undefined if:
187  *
188  *		A.  The receiving buffer is not large enough. (rc = -1)
189  *		B.  If 'charaddr' does not contain a series of octets
190  *		    (strlen(charaddr) must be even). (rc = -2)
191  *		C.  Any character in 'charaddr' is not an ASCII hex digit.
192  *		    (rc = -3)
193  *
194  *	NOTE: that even if the internal representation of an address is
195  *	an ASCII string, there is no guarantee that the output will be
196  *	null terminated, thus the returned length must be used when
197  *	accessing the internal address.
198  */
199 
200 
201 int
202 nlsc2addr(char *addr, int maxlen, char *charaddr)
203 {
204 	int len;
205 	int i;
206 	char c;
207 	unsigned char val;
208 
209 	if (strlen(charaddr) & 1)
210 		return(-1);
211 
212 	for (len = 0; ((maxlen--) && (*charaddr)); ++len)  {
213 		for (i = 2,  val = 0;  i--;  )  {
214 			c = *charaddr++;
215 			if (!(isxdigit(c)))
216 				return(-3);
217 			val = (val << 4) | (unsigned char)asctohex(c);
218 	    	}
219 
220 		*addr++ = (char)val;
221 	}
222 
223 #ifdef	DEBUGMODE
224 	fprintf(stderr, "nlsc2addr: returned length = %d\n", len);
225 #endif
226 
227 	return(*charaddr ? -2 : len);
228 }
229