1121934Sharti/* 2121934Sharti * Copyright (c) 1996-2003 3121934Sharti * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4121934Sharti * All rights reserved. 5121934Sharti * 6131826Sharti * Author: Hartmut Brandt <harti@freebsd.org> 7131826Sharti * 8121934Sharti * Redistribution and use in source and binary forms, with or without 9121934Sharti * modification, are permitted provided that the following conditions 10121934Sharti * are met: 11121934Sharti * 1. Redistributions of source code must retain the above copyright 12121934Sharti * notice, this list of conditions and the following disclaimer. 13121934Sharti * 2. Redistributions in binary form must reproduce the above copyright 14121934Sharti * notice, this list of conditions and the following disclaimer in the 15121934Sharti * documentation and/or other materials provided with the distribution. 16121934Sharti * 17121934Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18121934Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19121934Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20121934Sharti * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21121934Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22121934Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23121934Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24121934Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25121934Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26121934Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27121934Sharti * SUCH DAMAGE. 28121934Sharti * 29131826Sharti * $Begemot: libunimsg/netnatm/misc/straddr.c,v 1.4 2004/07/08 08:22:02 brandt Exp $ 30121934Sharti */ 31121934Sharti 32121934Sharti#include <sys/types.h> 33121934Sharti#ifdef _KERNEL 34121934Sharti#include <sys/ctype.h> 35121934Sharti#include <sys/libkern.h> 36121934Sharti#else 37121934Sharti#include <ctype.h> 38121934Sharti#include <string.h> 39121934Sharti#endif 40121934Sharti#include <netnatm/addr.h> 41121934Sharti 42121934Sharti/* 43121934Sharti * Convert an NSAP address from the ASCII format to the binary. 44121934Sharti * ASCII format means each byte formatted as a 2-byte hex number 45121934Sharti * with dots freely interspersed between the bytes. 46121934Sharti * If the conversion is succesful, the function returns 0, -1 47121934Sharti * on conversion errors. 48121934Sharti */ 49121934Shartiint 50121934Shartiuni_str2nsap(u_char *out, const char *in) 51121934Sharti{ 52121934Sharti int i; 53121934Sharti int c; 54121934Sharti 55121934Sharti for(i = 0; i < 20; i++) { 56121934Sharti while((c = *in++) == '.') 57121934Sharti ; 58121934Sharti if(!isascii(c) || !isxdigit(c)) 59121934Sharti return -1; 60121934Sharti out[i] = isdigit(c) ? (c - '0') 61121934Sharti : islower(c) ? (c - 'a' + 10) 62121934Sharti : (c - 'A' + 10); 63121934Sharti out[i] <<= 4; 64121934Sharti c = *in++; 65121934Sharti if(!isascii(c) || !isxdigit(c)) 66121934Sharti return -1; 67121934Sharti out[i] |= isdigit(c) ? (c - '0') 68121934Sharti : islower(c) ? (c - 'a' + 10) 69121934Sharti : (c - 'A' + 10); 70121934Sharti } 71121934Sharti return *in != '\0'; 72121934Sharti} 73121934Sharti 74121934Sharti/* 75121934Sharti * Parse an emebedded E.164 NSAP address. 76121934Sharti * If check is 0, the contents of the last 11 bytes are ignored 77121934Sharti * If check is 1, the contents of all of these but the selector byte 78121934Sharti * are checked to be zero. If check is 2 all 11 bytes must be 0. 79121934Sharti */ 80121934Shartiint 81121934Shartiuni_nsap2e164(char *e164, const u_char *nsap, int check) 82121934Sharti{ 83121934Sharti char *p = e164; 84121934Sharti u_int d; 85121934Sharti int i; 86121934Sharti 87121934Sharti if(nsap[0] != 0x45) 88121934Sharti return -1; 89121934Sharti if((nsap[8] & 0xf) != 0xf) 90121934Sharti return -1; 91121934Sharti for(i = 1; i <= 7; i++) { 92121934Sharti d = (nsap[i] >> 4) & 0xf; 93121934Sharti if(d == 0x00 && p == e164) 94121934Sharti continue; 95121934Sharti if(d >= 0xa) 96121934Sharti return -1; 97121934Sharti *p++ = d + '0'; 98121934Sharti 99121934Sharti d = nsap[i] & 0xf; 100121934Sharti if(d == 0x00 && p == e164) 101121934Sharti continue; 102121934Sharti if(d >= 0xa) 103121934Sharti return -1; 104121934Sharti *p++ = d + '0'; 105121934Sharti } 106121934Sharti d = (nsap[i] >> 4) & 0xf; 107121934Sharti if(d != 0x00 || p == e164) { 108121934Sharti if(d >= 0xa) 109121934Sharti return -1; 110121934Sharti *p++ = d + '0'; 111121934Sharti } 112121934Sharti if(p == e164) 113121934Sharti return -1; 114121934Sharti *p++ = 0; 115121934Sharti 116121934Sharti if(check == 0) 117121934Sharti return 0; 118121934Sharti while(i < ((check == 1) ? 19 : 20)) { 119121934Sharti if(nsap[i] != 0x00) 120121934Sharti return -1; 121121934Sharti i++; 122121934Sharti } 123121934Sharti 124121934Sharti return 0; 125121934Sharti} 126121934Sharti 127121934Sharti/* 128121934Sharti * Convert a binary representation to ASCII. The standard formats are 129121934Sharti * recognized and dotted. Non-standard formats get no dots altogether. 130121934Sharti */ 131121934Shartivoid 132121934Shartiuni_prefix2str(char *out, const u_char *in, u_int len, int dotit) 133121934Sharti{ 134121934Sharti static char hex[16] = "0123456789abcdef"; 135121934Sharti static int fmt[3][6] = { 136121934Sharti { 1, 2, 10, 6, 1, 0 }, 137121934Sharti { 1, 2, 10, 6, 1, 0 }, 138121934Sharti { 1, 8, 4, 6, 1, 0 }, 139121934Sharti }; 140121934Sharti int f, b; 141121934Sharti u_int i; 142121934Sharti 143121934Sharti if (len > 20) 144121934Sharti len = 20; 145121934Sharti 146121934Sharti if(dotit) { 147121934Sharti switch(*in) { 148121934Sharti 149121934Sharti case 0x39: /* DCC */ 150121934Sharti i = 0; 151121934Sharti fmt: 152121934Sharti for(f = 0; fmt[i][f]; f++) { 153121934Sharti if (len == 0) 154121934Sharti goto done; 155121934Sharti if(f != 0) 156121934Sharti *out++ = '.'; 157121934Sharti for(b = 0; b < fmt[i][f]; b++) { 158121934Sharti if (len-- == 0) 159121934Sharti goto done; 160121934Sharti *out++ = hex[(*in >> 4) & 0xf]; 161121934Sharti *out++ = hex[*in & 0xf]; 162121934Sharti in++; 163121934Sharti } 164121934Sharti } 165121934Sharti done: 166121934Sharti *out = '\0'; 167121934Sharti return; 168121934Sharti 169121934Sharti case 0x47: /* ICD */ 170121934Sharti i = 1; 171121934Sharti goto fmt; 172121934Sharti 173121934Sharti case 0x45: /* E.164 */ 174121934Sharti i = 2; 175121934Sharti goto fmt; 176121934Sharti } 177121934Sharti } 178121934Sharti 179121934Sharti /* undotted */ 180121934Sharti for(i = 0; i < len; i++) { 181121934Sharti *out++ = hex[(*in >> 4) & 0xf]; 182121934Sharti *out++ = hex[*in & 0xf]; 183121934Sharti in++; 184121934Sharti } 185121934Sharti *out = '\0'; 186121934Sharti} 187121934Sharti 188121934Shartivoid 189121934Shartiuni_nsap2str(char *out, const u_char *in, int dotit) 190121934Sharti{ 191121934Sharti uni_prefix2str(out, in, 20, dotit); 192121934Sharti} 193121934Sharti 194121934Sharti/* 195121934Sharti * Make an embedded E.164 NSAP address from a NSAP address. 196121934Sharti * The E.164 address is a string of digits, at least one digit and 197121934Sharti * not more than 15 digits long. The NSAP address will start with 198121934Sharti * byte 0x45 and then a 8 byte field, which contains the right 199121934Sharti * justified E.164 address in BCD coding, filled with a 0xf to the 200121934Sharti * right. The rest of the address is zero. 201121934Sharti * The function returns 0 if everything is ok, -1 in case of a wrong 202121934Sharti * E.164 address. 203121934Sharti */ 204121934Shartiint 205121934Shartiuni_e1642nsap(u_char *nsap, const char *e164) 206121934Sharti{ 207121934Sharti size_t len; 208121934Sharti int fill; 209121934Sharti u_int i; 210121934Sharti 211121934Sharti if((len = strlen(e164)) > 15 || len == 0) 212121934Sharti return -1; 213121934Sharti for(i = 0; i < len; i++) 214121934Sharti if(!isdigit(e164[i])) 215121934Sharti return -1; 216121934Sharti 217121934Sharti *nsap++ = 0x45; 218121934Sharti fill = (15 - len) / 2; 219121934Sharti while(fill--) 220121934Sharti *nsap++ = 0x00; 221121934Sharti if((len & 1) == 0) { 222121934Sharti *nsap++ = *e164++ - '0'; 223121934Sharti len--; 224121934Sharti } 225121934Sharti while(len > 1) { 226121934Sharti len -= 2; 227121934Sharti *nsap = (*e164++ - '0') << 4; 228121934Sharti *nsap++ |= *e164 - '0'; 229121934Sharti } 230121934Sharti *nsap++ = ((*e164++ - '0') << 4) | 0xf; 231121934Sharti for(fill = 0; fill < 11; fill++) 232121934Sharti *nsap++ = 0; 233121934Sharti 234121934Sharti return 0; 235121934Sharti} 236