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