straddr.c revision 131827
1255736Sdavidch/*
2265797Sdavidcs * Copyright (c) 1996-2003
3255736Sdavidch *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4255736Sdavidch * 	All rights reserved.
5255736Sdavidch *
6255736Sdavidch * Author: Hartmut Brandt <harti@freebsd.org>
7255736Sdavidch *
8255736Sdavidch * Redistribution and use in source and binary forms, with or without
9255736Sdavidch * modification, are permitted provided that the following conditions
10255736Sdavidch * are met:
11255736Sdavidch * 1. Redistributions of source code must retain the above copyright
12255736Sdavidch *    notice, this list of conditions and the following disclaimer.
13255736Sdavidch * 2. Redistributions in binary form must reproduce the above copyright
14255736Sdavidch *    notice, this list of conditions and the following disclaimer in the
15255736Sdavidch *    documentation and/or other materials provided with the distribution.
16255736Sdavidch *
17255736Sdavidch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18255736Sdavidch * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19255736Sdavidch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20255736Sdavidch * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21255736Sdavidch * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22255736Sdavidch * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23255736Sdavidch * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24255736Sdavidch * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25255736Sdavidch * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26255736Sdavidch * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27255736Sdavidch * SUCH DAMAGE.
28255736Sdavidch *
29255736Sdavidch * $Begemot: libunimsg/netnatm/misc/straddr.c,v 1.4 2004/07/08 08:22:02 brandt Exp $
30255736Sdavidch */
31255736Sdavidch
32255736Sdavidch#include <sys/types.h>
33255736Sdavidch#ifdef _KERNEL
34255736Sdavidch#include <sys/ctype.h>
35255736Sdavidch#include <sys/libkern.h>
36255736Sdavidch#else
37255736Sdavidch#include <ctype.h>
38255736Sdavidch#include <string.h>
39255736Sdavidch#endif
40255736Sdavidch#include <netnatm/addr.h>
41255736Sdavidch
42255736Sdavidch/*
43255736Sdavidch * Convert an NSAP address from the ASCII format to the binary.
44255736Sdavidch * ASCII format means each byte formatted as a 2-byte hex number
45255736Sdavidch * with dots freely interspersed between the bytes.
46255736Sdavidch * If the conversion is succesful, the function returns 0, -1
47255736Sdavidch * on conversion errors.
48255736Sdavidch */
49255736Sdavidchint
50255736Sdavidchuni_str2nsap(u_char *out, const char *in)
51255736Sdavidch{
52255736Sdavidch	int i;
53255736Sdavidch	int c;
54255736Sdavidch
55255736Sdavidch	for(i = 0; i < 20; i++) {
56255736Sdavidch		while((c = *in++) == '.')
57255736Sdavidch			;
58255736Sdavidch		if(!isascii(c) || !isxdigit(c))
59255736Sdavidch			return -1;
60255736Sdavidch		out[i] = isdigit(c) ? (c - '0')
61255736Sdavidch			: islower(c) ? (c - 'a' + 10)
62255736Sdavidch			: (c - 'A' + 10);
63255736Sdavidch		out[i] <<= 4;
64255736Sdavidch		c = *in++;
65255736Sdavidch		if(!isascii(c) || !isxdigit(c))
66255736Sdavidch			return -1;
67255736Sdavidch		out[i] |= isdigit(c) ? (c - '0')
68255736Sdavidch			: islower(c) ? (c - 'a' + 10)
69255736Sdavidch			: (c - 'A' + 10);
70255736Sdavidch	}
71255736Sdavidch	return *in != '\0';
72255736Sdavidch}
73255736Sdavidch
74255736Sdavidch/*
75255736Sdavidch * Parse an emebedded E.164 NSAP address.
76255736Sdavidch * If check is 0, the contents of the last 11 bytes are ignored
77255736Sdavidch * If check is 1, the contents of all of these but the selector byte
78255736Sdavidch * are checked to be zero. If check is 2 all 11 bytes must be 0.
79255736Sdavidch */
80255736Sdavidchint
81255736Sdavidchuni_nsap2e164(char *e164, const u_char *nsap, int check)
82255736Sdavidch{
83255736Sdavidch	char *p = e164;
84255736Sdavidch	u_int d;
85255736Sdavidch	int i;
86255736Sdavidch
87255736Sdavidch	if(nsap[0] != 0x45)
88255736Sdavidch		return -1;
89255736Sdavidch	if((nsap[8] & 0xf) != 0xf)
90255736Sdavidch		return -1;
91255736Sdavidch	for(i = 1; i <= 7; i++) {
92255736Sdavidch		d = (nsap[i] >> 4) & 0xf;
93255736Sdavidch		if(d == 0x00 && p == e164)
94255736Sdavidch			continue;
95255736Sdavidch		if(d >= 0xa)
96255736Sdavidch			return -1;
97255736Sdavidch		*p++ = d + '0';
98255736Sdavidch
99255736Sdavidch		d = nsap[i] & 0xf;
100255736Sdavidch		if(d == 0x00 && p == e164)
101255736Sdavidch			continue;
102255736Sdavidch		if(d >= 0xa)
103255736Sdavidch			return -1;
104255736Sdavidch		*p++ = d + '0';
105255736Sdavidch	}
106255736Sdavidch	d = (nsap[i] >> 4) & 0xf;
107255736Sdavidch	if(d != 0x00 || p == e164) {
108255736Sdavidch		if(d >= 0xa)
109255736Sdavidch			return -1;
110255736Sdavidch		*p++ = d + '0';
111255736Sdavidch	}
112255736Sdavidch	if(p == e164)
113255736Sdavidch		return -1;
114255736Sdavidch	*p++ = 0;
115255736Sdavidch
116255736Sdavidch	if(check == 0)
117255736Sdavidch		return 0;
118255736Sdavidch	while(i < ((check == 1) ? 19 : 20)) {
119255736Sdavidch		if(nsap[i] != 0x00)
120255736Sdavidch			return -1;
121255736Sdavidch		i++;
122255736Sdavidch	}
123255736Sdavidch
124255736Sdavidch	return 0;
125255736Sdavidch}
126255736Sdavidch
127255736Sdavidch/*
128255736Sdavidch * Convert a binary representation to ASCII. The standard formats are
129255736Sdavidch * recognized and dotted. Non-standard formats get no dots altogether.
130255736Sdavidch */
131255736Sdavidchvoid
132255736Sdavidchuni_prefix2str(char *out, const u_char *in, u_int len, int dotit)
133255736Sdavidch{
134255736Sdavidch	static char hex[16] = "0123456789abcdef";
135255736Sdavidch	static int fmt[3][6] = {
136255736Sdavidch		{ 1, 2, 10, 6, 1, 0 },
137255736Sdavidch		{ 1, 2, 10, 6, 1, 0 },
138255736Sdavidch		{ 1, 8,  4, 6, 1, 0 },
139255736Sdavidch	};
140255736Sdavidch	int f, b;
141255736Sdavidch	u_int i;
142255736Sdavidch
143255736Sdavidch	if (len > 20)
144255736Sdavidch		len = 20;
145255736Sdavidch
146255736Sdavidch	if(dotit) {
147255736Sdavidch		switch(*in) {
148255736Sdavidch
149255736Sdavidch		  case 0x39:	/* DCC */
150255736Sdavidch			i = 0;
151255736Sdavidch  fmt:
152255736Sdavidch			for(f = 0; fmt[i][f]; f++) {
153255736Sdavidch				if (len == 0)
154255736Sdavidch					goto done;
155255736Sdavidch				if(f != 0)
156255736Sdavidch					*out++ = '.';
157255736Sdavidch				for(b = 0; b < fmt[i][f]; b++) {
158255736Sdavidch					if (len-- == 0)
159255736Sdavidch						goto done;
160255736Sdavidch					*out++ = hex[(*in >> 4) & 0xf];
161255736Sdavidch					*out++ = hex[*in & 0xf];
162255736Sdavidch					in++;
163255736Sdavidch				}
164255736Sdavidch			}
165255736Sdavidch  done:
166255736Sdavidch			*out = '\0';
167255736Sdavidch			return;
168255736Sdavidch
169255736Sdavidch		  case 0x47:	/* ICD */
170255736Sdavidch			i = 1;
171255736Sdavidch			goto fmt;
172255736Sdavidch
173255736Sdavidch		  case 0x45:	/* E.164 */
174255736Sdavidch			i = 2;
175255736Sdavidch			goto fmt;
176255736Sdavidch		}
177255736Sdavidch	}
178255736Sdavidch
179255736Sdavidch	/* undotted */
180255736Sdavidch	for(i = 0; i < len; i++) {
181255736Sdavidch		*out++ = hex[(*in >> 4) & 0xf];
182255736Sdavidch		*out++ = hex[*in & 0xf];
183255736Sdavidch		in++;
184255736Sdavidch	}
185255736Sdavidch	*out = '\0';
186255736Sdavidch}
187255736Sdavidch
188255736Sdavidchvoid
189255736Sdavidchuni_nsap2str(char *out, const u_char *in, int dotit)
190255736Sdavidch{
191255736Sdavidch	uni_prefix2str(out, in, 20, dotit);
192255736Sdavidch}
193255736Sdavidch
194255736Sdavidch/*
195255736Sdavidch * Make an embedded E.164 NSAP address from a NSAP address.
196255736Sdavidch * The E.164 address is a string of digits, at least one digit and
197255736Sdavidch * not more than 15 digits long. The NSAP address will start with
198255736Sdavidch * byte 0x45 and then a 8 byte field, which contains the right
199255736Sdavidch * justified E.164 address in BCD coding, filled with a 0xf to the
200255736Sdavidch * right. The rest of the address is zero.
201255736Sdavidch * The function returns 0 if everything is ok, -1 in case of a wrong
202255736Sdavidch * E.164 address.
203255736Sdavidch */
204255736Sdavidchint
205255736Sdavidchuni_e1642nsap(u_char *nsap, const char *e164)
206255736Sdavidch{
207255736Sdavidch	size_t len;
208255736Sdavidch	int fill;
209255736Sdavidch	u_int i;
210255736Sdavidch
211255736Sdavidch	if((len = strlen(e164)) > 15 || len == 0)
212255736Sdavidch		return -1;
213255736Sdavidch	for(i = 0; i < len; i++)
214255736Sdavidch		if(!isdigit(e164[i]))
215255736Sdavidch			return -1;
216255736Sdavidch
217255736Sdavidch	*nsap++ = 0x45;
218255736Sdavidch	fill = (15 - len) / 2;
219255736Sdavidch	while(fill--)
220255736Sdavidch		*nsap++ = 0x00;
221255736Sdavidch	if((len & 1) == 0) {
222255736Sdavidch		*nsap++ = *e164++ - '0';
223255736Sdavidch		len--;
224255736Sdavidch	}
225255736Sdavidch	while(len > 1) {
226255736Sdavidch		len -= 2;
227255736Sdavidch		*nsap = (*e164++ - '0') << 4;
228255736Sdavidch		*nsap++ |= *e164 - '0';
229255736Sdavidch	}
230255736Sdavidch	*nsap++ = ((*e164++ - '0') << 4) | 0xf;
231255736Sdavidch	for(fill = 0; fill < 11; fill++)
232255736Sdavidch		*nsap++ = 0;
233255736Sdavidch
234255736Sdavidch	return 0;
235255736Sdavidch}
236255736Sdavidch