ipx_addr.c revision 90868
1/* 2 * Copyright (c) 1986, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * J.Q. Johnson. 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 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37#include <sys/cdefs.h> 38__FBSDID("$FreeBSD: head/lib/libipx/ipx_addr.c 90868 2002-02-18 20:35:27Z mike $"); 39 40#if defined(LIBC_SCCS) && !defined(lint) 41static char sccsid[] = "@(#)ipx_addr.c"; 42#endif /* LIBC_SCCS and not lint */ 43 44#include <sys/param.h> 45#include <arpa/inet.h> 46#include <netipx/ipx.h> 47#include <stdio.h> 48#include <string.h> 49 50static struct ipx_addr addr, zero_addr; 51 52static void Field(), cvtbase(); 53 54struct ipx_addr 55ipx_addr(name) 56 const char *name; 57{ 58 char separator; 59 char *hostname, *socketname, *cp; 60 char buf[50]; 61 62 (void)strncpy(buf, name, sizeof(buf) - 1); 63 buf[sizeof(buf) - 1] = '\0'; 64 65 /* 66 * First, figure out what he intends as a field separator. 67 * Despite the way this routine is written, the preferred 68 * form 2-272.AA001234H.01777, i.e. XDE standard. 69 * Great efforts are made to ensure backwards compatibility. 70 */ 71 if ( (hostname = strchr(buf, '#')) ) 72 separator = '#'; 73 else { 74 hostname = strchr(buf, '.'); 75 if ((cp = strchr(buf, ':')) && 76 ((hostname && cp < hostname) || (hostname == 0))) { 77 hostname = cp; 78 separator = ':'; 79 } else 80 separator = '.'; 81 } 82 if (hostname) 83 *hostname++ = 0; 84 85 addr = zero_addr; 86 Field(buf, addr.x_net.c_net, 4); 87 if (hostname == 0) 88 return (addr); /* No separator means net only */ 89 90 socketname = strchr(hostname, separator); 91 if (socketname) { 92 *socketname++ = 0; 93 Field(socketname, (u_char *)&addr.x_port, 2); 94 } 95 96 Field(hostname, addr.x_host.c_host, 6); 97 98 return (addr); 99} 100 101static void 102Field(buf, out, len) 103 char *buf; 104 u_char *out; 105 int len; 106{ 107 register char *bp = buf; 108 int i, ibase, base16 = 0, base10 = 0, clen = 0; 109 int hb[6], *hp; 110 char *fmt; 111 112 /* 113 * first try 2-273#2-852-151-014#socket 114 */ 115 if ((*buf != '-') && 116 (1 < (i = sscanf(buf, "%d-%d-%d-%d-%d", 117 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4])))) { 118 cvtbase(1000L, 256, hb, i, out, len); 119 return; 120 } 121 /* 122 * try form 8E1#0.0.AA.0.5E.E6#socket 123 */ 124 if (1 < (i = sscanf(buf,"%x.%x.%x.%x.%x.%x", 125 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) { 126 cvtbase(256L, 256, hb, i, out, len); 127 return; 128 } 129 /* 130 * try form 8E1#0:0:AA:0:5E:E6#socket 131 */ 132 if (1 < (i = sscanf(buf,"%x:%x:%x:%x:%x:%x", 133 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) { 134 cvtbase(256L, 256, hb, i, out, len); 135 return; 136 } 137 /* 138 * This is REALLY stretching it but there was a 139 * comma notation separating shorts -- definitely non-standard 140 */ 141 if (1 < (i = sscanf(buf,"%x,%x,%x", 142 &hb[0], &hb[1], &hb[2]))) { 143 hb[0] = htons(hb[0]); hb[1] = htons(hb[1]); 144 hb[2] = htons(hb[2]); 145 cvtbase(65536L, 256, hb, i, out, len); 146 return; 147 } 148 149 /* Need to decide if base 10, 16 or 8 */ 150 while (*bp) switch (*bp++) { 151 152 case '0': case '1': case '2': case '3': case '4': case '5': 153 case '6': case '7': case '-': 154 break; 155 156 case '8': case '9': 157 base10 = 1; 158 break; 159 160 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': 161 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': 162 base16 = 1; 163 break; 164 165 case 'x': case 'X': 166 *--bp = '0'; 167 base16 = 1; 168 break; 169 170 case 'h': case 'H': 171 base16 = 1; 172 /* fall into */ 173 174 default: 175 *--bp = 0; /* Ends Loop */ 176 } 177 if (base16) { 178 fmt = "%3x"; 179 ibase = 4096; 180 } else if (base10 == 0 && *buf == '0') { 181 fmt = "%3o"; 182 ibase = 512; 183 } else { 184 fmt = "%3d"; 185 ibase = 1000; 186 } 187 188 for (bp = buf; *bp++; ) clen++; 189 if (clen == 0) clen++; 190 if (clen > 18) clen = 18; 191 i = ((clen - 1) / 3) + 1; 192 bp = clen + buf - 3; 193 hp = hb + i - 1; 194 195 while (hp > hb) { 196 (void)sscanf(bp, fmt, hp); 197 bp[0] = 0; 198 hp--; 199 bp -= 3; 200 } 201 (void)sscanf(buf, fmt, hp); 202 cvtbase((long)ibase, 256, hb, i, out, len); 203} 204 205static void 206cvtbase(oldbase,newbase,input,inlen,result,reslen) 207 long oldbase; 208 int newbase; 209 int input[]; 210 int inlen; 211 unsigned char result[]; 212 int reslen; 213{ 214 int d, e; 215 long sum; 216 217 e = 1; 218 while (e > 0 && reslen > 0) { 219 d = 0; e = 0; sum = 0; 220 /* long division: input=input/newbase */ 221 while (d < inlen) { 222 sum = sum*oldbase + (long) input[d]; 223 e += (sum > 0); 224 input[d++] = sum / newbase; 225 sum %= newbase; 226 } 227 result[--reslen] = sum; /* accumulate remainder */ 228 } 229 for (d=0; d < reslen; d++) 230 result[d] = 0; 231} 232