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