1/* 2 * Copyright (c) 1996-2003 3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4 * All rights reserved. 5 * 6 * Author: Hartmut Brandt <harti@freebsd.org> 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $Begemot: libunimsg/netnatm/misc/straddr.c,v 1.4 2004/07/08 08:22:02 brandt Exp $ 30 */ 31 32#include <sys/types.h> 33#ifdef _KERNEL 34#include <sys/ctype.h> 35#include <sys/libkern.h> 36#else 37#include <ctype.h> 38#include <string.h> 39#endif 40#include <netnatm/addr.h> 41 42/* 43 * Convert an NSAP address from the ASCII format to the binary. 44 * ASCII format means each byte formatted as a 2-byte hex number 45 * with dots freely interspersed between the bytes. 46 * If the conversion is succesful, the function returns 0, -1 47 * on conversion errors. 48 */ 49int 50uni_str2nsap(u_char *out, const char *in) 51{ 52 int i; 53 int c; 54 55 for(i = 0; i < 20; i++) { 56 while((c = *in++) == '.') 57 ; 58 if(!isascii(c) || !isxdigit(c)) 59 return -1; 60 out[i] = isdigit(c) ? (c - '0') 61 : islower(c) ? (c - 'a' + 10) 62 : (c - 'A' + 10); 63 out[i] <<= 4; 64 c = *in++; 65 if(!isascii(c) || !isxdigit(c)) 66 return -1; 67 out[i] |= isdigit(c) ? (c - '0') 68 : islower(c) ? (c - 'a' + 10) 69 : (c - 'A' + 10); 70 } 71 return *in != '\0'; 72} 73 74/* 75 * Parse an emebedded E.164 NSAP address. 76 * If check is 0, the contents of the last 11 bytes are ignored 77 * If check is 1, the contents of all of these but the selector byte 78 * are checked to be zero. If check is 2 all 11 bytes must be 0. 79 */ 80int 81uni_nsap2e164(char *e164, const u_char *nsap, int check) 82{ 83 char *p = e164; 84 u_int d; 85 int i; 86 87 if(nsap[0] != 0x45) 88 return -1; 89 if((nsap[8] & 0xf) != 0xf) 90 return -1; 91 for(i = 1; i <= 7; i++) { 92 d = (nsap[i] >> 4) & 0xf; 93 if(d == 0x00 && p == e164) 94 continue; 95 if(d >= 0xa) 96 return -1; 97 *p++ = d + '0'; 98 99 d = nsap[i] & 0xf; 100 if(d == 0x00 && p == e164) 101 continue; 102 if(d >= 0xa) 103 return -1; 104 *p++ = d + '0'; 105 } 106 d = (nsap[i] >> 4) & 0xf; 107 if(d != 0x00 || p == e164) { 108 if(d >= 0xa) 109 return -1; 110 *p++ = d + '0'; 111 } 112 if(p == e164) 113 return -1; 114 *p++ = 0; 115 116 if(check == 0) 117 return 0; 118 while(i < ((check == 1) ? 19 : 20)) { 119 if(nsap[i] != 0x00) 120 return -1; 121 i++; 122 } 123 124 return 0; 125} 126 127/* 128 * Convert a binary representation to ASCII. The standard formats are 129 * recognized and dotted. Non-standard formats get no dots altogether. 130 */ 131void 132uni_prefix2str(char *out, const u_char *in, u_int len, int dotit) 133{ 134 static char hex[16] = "0123456789abcdef"; 135 static int fmt[3][6] = { 136 { 1, 2, 10, 6, 1, 0 }, 137 { 1, 2, 10, 6, 1, 0 }, 138 { 1, 8, 4, 6, 1, 0 }, 139 }; 140 int f, b; 141 u_int i; 142 143 if (len > 20) 144 len = 20; 145 146 if(dotit) { 147 switch(*in) { 148 149 case 0x39: /* DCC */ 150 i = 0; 151 fmt: 152 for(f = 0; fmt[i][f]; f++) { 153 if (len == 0) 154 goto done; 155 if(f != 0) 156 *out++ = '.'; 157 for(b = 0; b < fmt[i][f]; b++) { 158 if (len-- == 0) 159 goto done; 160 *out++ = hex[(*in >> 4) & 0xf]; 161 *out++ = hex[*in & 0xf]; 162 in++; 163 } 164 } 165 done: 166 *out = '\0'; 167 return; 168 169 case 0x47: /* ICD */ 170 i = 1; 171 goto fmt; 172 173 case 0x45: /* E.164 */ 174 i = 2; 175 goto fmt; 176 } 177 } 178 179 /* undotted */ 180 for(i = 0; i < len; i++) { 181 *out++ = hex[(*in >> 4) & 0xf]; 182 *out++ = hex[*in & 0xf]; 183 in++; 184 } 185 *out = '\0'; 186} 187 188void 189uni_nsap2str(char *out, const u_char *in, int dotit) 190{ 191 uni_prefix2str(out, in, 20, dotit); 192} 193 194/* 195 * Make an embedded E.164 NSAP address from a NSAP address. 196 * The E.164 address is a string of digits, at least one digit and 197 * not more than 15 digits long. The NSAP address will start with 198 * byte 0x45 and then a 8 byte field, which contains the right 199 * justified E.164 address in BCD coding, filled with a 0xf to the 200 * right. The rest of the address is zero. 201 * The function returns 0 if everything is ok, -1 in case of a wrong 202 * E.164 address. 203 */ 204int 205uni_e1642nsap(u_char *nsap, const char *e164) 206{ 207 size_t len; 208 int fill; 209 u_int i; 210 211 if((len = strlen(e164)) > 15 || len == 0) 212 return -1; 213 for(i = 0; i < len; i++) 214 if(!isdigit(e164[i])) 215 return -1; 216 217 *nsap++ = 0x45; 218 fill = (15 - len) / 2; 219 while(fill--) 220 *nsap++ = 0x00; 221 if((len & 1) == 0) { 222 *nsap++ = *e164++ - '0'; 223 len--; 224 } 225 while(len > 1) { 226 len -= 2; 227 *nsap = (*e164++ - '0') << 4; 228 *nsap++ |= *e164 - '0'; 229 } 230 *nsap++ = ((*e164++ - '0') << 4) | 0xf; 231 for(fill = 0; fill < 11; fill++) 232 *nsap++ = 0; 233 234 return 0; 235} 236