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
23 /*
24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27
28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
30
31
32 /*
33 * nlsaddr.c:
34 *
35 * name/address conversion routines for listener and nlsadmin
36 * and other user processes. Converts internal address <--> external addr
37 *
38 * internal address is any number of octets. (length must be provided)
39 * external address is ascii/hex string. (implicit length)
40 *
41 *
42 * nlscalloc: dynamically allocates a t_call structure large enough
43 * to hold the external representations of addr, opt and udata.
44 * Use t_free to release the call structure.
45 *
46 * nlsaddr2c: Convert internal address to external form.
47 *
48 * nlsc2addr: Convert external address to internal form.
49 *
50 */
51
52 #include <ctype.h>
53 #include <sys/tiuser.h>
54
55 #ifndef T_NONE
56 #define T_NONE 0
57 #endif
58
59 /*
60 * define DEBUGMODE for diagnostic printf's to stderr
61 */
62
63 /* #define DEBUGMODE */
64
65 #ifdef DEBUGMODE
66 #include <stdio.h>
67 #endif
68
69 /* use to debug in listener *only* (not in user programs) */
70 /* #define DEBUG(args) debug args */
71
72 #ifndef DEBUG
73 #define DEBUG(args)
74 #endif
75
76
77 /*
78 * asctohex(X): convert char X to integer value
79 * assumes isxdigit(X). returns integer value.
80 * Note that 'a' > 'A'. See usage in code below.
81 */
82
83 #define asctohex(X) \
84 ((int)(isdigit(X) ? (int)(X-'0') : (X>='a') ? (X-'a')+10 : (X-'A')+10))
85
86 /*
87 * externsz(I): returns the number of chars required to hold an external
88 * address whose internal representation contains I octets.
89 * Adds enough space for a 16 char environ name to be prepended
90 * to the external name for the listener.
91 */
92
93 #define externsz(I) (unsigned int)((I<<1) + 41)
94
95
96 /*
97 * nlscalloc: allocate a call structure large enough to hold the
98 * external representation of the addr, opt and udata fields.
99 * similar to the way t_alloc works for the internal
100 * representation of an address.
101 *
102 * returns a pointer to the t_call strucure if successful,
103 * a NULL pointer indicates failure. The external integer
104 * t_errno will contain an error code.
105 *
106 */
107
108 struct t_call *
nlscalloc(fd)109 nlscalloc(fd)
110 int fd;
111 {
112 struct t_info info;
113 struct t_call *call;
114 register unsigned size;
115 register char *p;
116 extern char *malloc(), *t_alloc();
117 extern int t_getinfo();
118 extern char *malloc();
119 extern int t_errno, errno;
120
121 if (t_getinfo(fd, &info) == -1) {
122 DEBUG((5, "nlscalloc: t_getinfo failed, t_errno %d errno %d"));
123 return ((struct t_call *)0);
124 }
125
126 if (!(call = (struct t_call *)t_alloc(fd, T_CALL, T_NONE))) {
127 DEBUG((5, "nlscalloc: t_alloc failed, t_errno %d errno %d"));
128 return ((struct t_call *)0);
129 }
130
131 if (size = externsz((unsigned)info.addr))
132 if (!(p = malloc(size)))
133 goto fail;
134 if (call->addr.maxlen = size)
135 call->addr.buf = p;
136
137 if (size = externsz((unsigned)info.options))
138 if (!(p = malloc(size)))
139 goto fail;
140 if (call->opt.maxlen = size)
141 call->opt.buf = p;
142
143 if (size = externsz((unsigned)info.connect))
144 if (!(p = malloc(size)))
145 goto fail;
146 if (call->udata.maxlen = size)
147 call->udata.buf = p;
148
149 return(call);
150
151 fail:
152 DEBUG((1, "nlscalloc: malloc failed!"));
153 t_free((char *)call, T_CALL); /* t_free will release allocated mem*/
154 t_errno = TSYSERR; /* errno must be ENOMEM */
155 return((struct t_call *)0);
156 }
157
158
159 /*
160 * nlsaddr2c: given a pointer to a logical address and it's length
161 * and a receiving buffer, addr2char converts the
162 * logical address to the hex/ascii char
163 * representation of that address.
164 *
165 * WARNING: The receiving buffer must be large enough.
166 * rcv buffer must be at least (2*len)+1 bytes.
167 *
168 */
169
170 static char hex_digits[] = "0123456789ABCDEF";
171
172 void
nlsaddr2c(charaddr,addr,len)173 nlsaddr2c(charaddr, addr, len)
174 char *charaddr, *addr;
175 int len;
176 {
177 register unsigned i;
178
179 while (len--) {
180 i = (unsigned)*addr++;
181 *charaddr++ = hex_digits[(i>>4) & 0xf];
182 *charaddr++ = hex_digits[i & 0xf];
183 }
184 *charaddr = (char)0;
185 }
186
187
188 /*
189 * nlsc2addr: Given a buffer containing the hex/ascii representation
190 * of a logical address, the buffer's size and an address
191 * of a receiving buffer, char2addr converts the logical
192 * addr to internal format and returns the size of the logical
193 * address. A negative value is returned and the receiving
194 * buffers contents are undefined if:
195 *
196 * A. The receiving buffer is not large enough. (rc = -1)
197 * B. If 'charaddr' does not contain a series of octets
198 * (strlen(charaddr) must be even). (rc = -2)
199 * C. Any character in 'charaddr' is not an ASCII hex digit.
200 * (rc = -3)
201 *
202 * NOTE: that even if the internal representation of an address is
203 * an ASCII string, there is no guarantee that the output will be
204 * null terminated, thus the returned length must be used when
205 * accessing the internal address.
206 */
207
208
209 int
nlsc2addr(addr,maxlen,charaddr)210 nlsc2addr(addr, maxlen, charaddr)
211 char *addr, *charaddr;
212 int maxlen;
213 {
214 int len;
215 int i;
216 char c;
217 unsigned char val;
218
219 if (strlen(charaddr) & 1)
220 return(-1);
221
222 for (len = 0; ((maxlen--) && (*charaddr)); ++len) {
223 for (i = 2, val = 0; i--; ) {
224 c = *charaddr++;
225 if (!(isxdigit(c)))
226 return(-3);
227 val = (val << 4) | (unsigned char)asctohex(c);
228 }
229
230 *addr++ = (char)val;
231 }
232
233 #ifdef DEBUGMODE
234 fprintf(stderr, "nlsc2addr: returned length = %d\n", len);
235 #endif
236
237 return(*charaddr ? -2 : len);
238 }
239
240