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 * %sccs.include.redist.c% 9 */ 10 11 #if defined(LIBC_SCCS) && !defined(lint) 12 static char sccsid[] = "@(#)ns_addr.c 8.1 (Berkeley) 06/07/93"; 13 #endif /* LIBC_SCCS and not lint */ 14 15 #include <sys/param.h> 16 #include <netns/ns.h> 17 #include <stdio.h> 18 #include <string.h> 19 20 static struct ns_addr addr, zero_addr; 21 22 static void Field(), cvtbase(); 23 24 struct ns_addr 25 ns_addr(name) 26 const char *name; 27 { 28 char separator; 29 char *hostname, *socketname, *cp; 30 char buf[50]; 31 32 (void)strncpy(buf, name, sizeof(buf) - 1); 33 buf[sizeof(buf) - 1] = '\0'; 34 35 /* 36 * First, figure out what he intends as a field separtor. 37 * Despite the way this routine is written, the prefered 38 * form 2-272.AA001234H.01777, i.e. XDE standard. 39 * Great efforts are made to insure backward compatability. 40 */ 41 if (hostname = strchr(buf, '#')) 42 separator = '#'; 43 else { 44 hostname = strchr(buf, '.'); 45 if ((cp = strchr(buf, ':')) && 46 ((hostname && cp < hostname) || (hostname == 0))) { 47 hostname = cp; 48 separator = ':'; 49 } else 50 separator = '.'; 51 } 52 if (hostname) 53 *hostname++ = 0; 54 55 addr = zero_addr; 56 Field(buf, addr.x_net.c_net, 4); 57 if (hostname == 0) 58 return (addr); /* No separator means net only */ 59 60 socketname = strchr(hostname, separator); 61 if (socketname) { 62 *socketname++ = 0; 63 Field(socketname, (u_char *)&addr.x_port, 2); 64 } 65 66 Field(hostname, addr.x_host.c_host, 6); 67 68 return (addr); 69 } 70 71 static void 72 Field(buf, out, len) 73 char *buf; 74 u_char *out; 75 int len; 76 { 77 register char *bp = buf; 78 int i, ibase, base16 = 0, base10 = 0, clen = 0; 79 int hb[6], *hp; 80 char *fmt; 81 82 /* 83 * first try 2-273#2-852-151-014#socket 84 */ 85 if ((*buf != '-') && 86 (1 < (i = sscanf(buf, "%d-%d-%d-%d-%d", 87 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4])))) { 88 cvtbase(1000L, 256, hb, i, out, len); 89 return; 90 } 91 /* 92 * try form 8E1#0.0.AA.0.5E.E6#socket 93 */ 94 if (1 < (i = sscanf(buf,"%x.%x.%x.%x.%x.%x", 95 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) { 96 cvtbase(256L, 256, hb, i, out, len); 97 return; 98 } 99 /* 100 * try form 8E1#0:0:AA:0:5E:E6#socket 101 */ 102 if (1 < (i = sscanf(buf,"%x:%x:%x:%x:%x:%x", 103 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) { 104 cvtbase(256L, 256, hb, i, out, len); 105 return; 106 } 107 /* 108 * This is REALLY stretching it but there was a 109 * comma notation separting shorts -- definitely non standard 110 */ 111 if (1 < (i = sscanf(buf,"%x,%x,%x", 112 &hb[0], &hb[1], &hb[2]))) { 113 hb[0] = htons(hb[0]); hb[1] = htons(hb[1]); 114 hb[2] = htons(hb[2]); 115 cvtbase(65536L, 256, hb, i, out, len); 116 return; 117 } 118 119 /* Need to decide if base 10, 16 or 8 */ 120 while (*bp) switch (*bp++) { 121 122 case '0': case '1': case '2': case '3': case '4': case '5': 123 case '6': case '7': case '-': 124 break; 125 126 case '8': case '9': 127 base10 = 1; 128 break; 129 130 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': 131 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': 132 base16 = 1; 133 break; 134 135 case 'x': case 'X': 136 *--bp = '0'; 137 base16 = 1; 138 break; 139 140 case 'h': case 'H': 141 base16 = 1; 142 /* fall into */ 143 144 default: 145 *--bp = 0; /* Ends Loop */ 146 } 147 if (base16) { 148 fmt = "%3x"; 149 ibase = 4096; 150 } else if (base10 == 0 && *buf == '0') { 151 fmt = "%3o"; 152 ibase = 512; 153 } else { 154 fmt = "%3d"; 155 ibase = 1000; 156 } 157 158 for (bp = buf; *bp++; ) clen++; 159 if (clen == 0) clen++; 160 if (clen > 18) clen = 18; 161 i = ((clen - 1) / 3) + 1; 162 bp = clen + buf - 3; 163 hp = hb + i - 1; 164 165 while (hp > hb) { 166 (void)sscanf(bp, fmt, hp); 167 bp[0] = 0; 168 hp--; 169 bp -= 3; 170 } 171 (void)sscanf(buf, fmt, hp); 172 cvtbase((long)ibase, 256, hb, i, out, len); 173 } 174 175 static void 176 cvtbase(oldbase,newbase,input,inlen,result,reslen) 177 long oldbase; 178 int newbase; 179 int input[]; 180 int inlen; 181 unsigned char result[]; 182 int reslen; 183 { 184 int d, e; 185 long sum; 186 187 e = 1; 188 while (e > 0 && reslen > 0) { 189 d = 0; e = 0; sum = 0; 190 /* long division: input=input/newbase */ 191 while (d < inlen) { 192 sum = sum*oldbase + (long) input[d]; 193 e += (sum > 0); 194 input[d++] = sum / newbase; 195 sum %= newbase; 196 } 197 result[--reslen] = sum; /* accumulate remainder */ 198 } 199 for (d=0; d < reslen; d++) 200 result[d] = 0; 201 } 202