111819Sjulian/*
211819Sjulian * Copyright (c) 1986, 1993
311819Sjulian *	The Regents of the University of California.  All rights reserved.
411819Sjulian *
511819Sjulian * This code is derived from software contributed to Berkeley by
611819Sjulian * J.Q. Johnson.
711819Sjulian *
811819Sjulian * Redistribution and use in source and binary forms, with or without
911819Sjulian * modification, are permitted provided that the following conditions
1011819Sjulian * are met:
1111819Sjulian * 1. Redistributions of source code must retain the above copyright
1211819Sjulian *    notice, this list of conditions and the following disclaimer.
1311819Sjulian * 2. Redistributions in binary form must reproduce the above copyright
1411819Sjulian *    notice, this list of conditions and the following disclaimer in the
1511819Sjulian *    documentation and/or other materials provided with the distribution.
1611819Sjulian * 4. Neither the name of the University nor the names of its contributors
1711819Sjulian *    may be used to endorse or promote products derived from this software
1811819Sjulian *    without specific prior written permission.
1911819Sjulian *
2011819Sjulian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2111819Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2211819Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2311819Sjulian * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2411819Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2511819Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2611819Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2711819Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2811819Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2911819Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3011819Sjulian * SUCH DAMAGE.
3111819Sjulian */
3211819Sjulian
3384209Sdillon#include <sys/cdefs.h>
3484209Sdillon__FBSDID("$FreeBSD$");
3584209Sdillon
3611819Sjulian#if defined(LIBC_SCCS) && !defined(lint)
3711819Sjulianstatic char sccsid[] = "@(#)ipx_addr.c";
3811819Sjulian#endif /* LIBC_SCCS and not lint */
3911819Sjulian
4011819Sjulian#include <sys/param.h>
4190868Smike#include <arpa/inet.h>
4211819Sjulian#include <netipx/ipx.h>
4311819Sjulian#include <stdio.h>
4411819Sjulian#include <string.h>
4511819Sjulian
4611819Sjulianstatic struct ipx_addr addr, zero_addr;
4711819Sjulian
4811819Sjulianstatic void Field(), cvtbase();
4911819Sjulian
5011819Sjulianstruct ipx_addr
5111819Sjulianipx_addr(name)
5211819Sjulian	const char *name;
5311819Sjulian{
5411819Sjulian	char separator;
5511819Sjulian	char *hostname, *socketname, *cp;
5611819Sjulian	char buf[50];
5711819Sjulian
5811819Sjulian	(void)strncpy(buf, name, sizeof(buf) - 1);
5911819Sjulian	buf[sizeof(buf) - 1] = '\0';
6011819Sjulian
6111819Sjulian	/*
6272757Skris	 * First, figure out what he intends as a field separator.
6372757Skris	 * Despite the way this routine is written, the preferred
6411819Sjulian	 * form  2-272.AA001234H.01777, i.e. XDE standard.
6572757Skris	 * Great efforts are made to ensure backwards compatibility.
6611819Sjulian	 */
6717141Sjkh	if ( (hostname = strchr(buf, '#')) )
6811819Sjulian		separator = '#';
6911819Sjulian	else {
7011819Sjulian		hostname = strchr(buf, '.');
7111819Sjulian		if ((cp = strchr(buf, ':')) &&
7211819Sjulian		    ((hostname && cp < hostname) || (hostname == 0))) {
7311819Sjulian			hostname = cp;
7411819Sjulian			separator = ':';
7511819Sjulian		} else
7611819Sjulian			separator = '.';
7711819Sjulian	}
7811819Sjulian	if (hostname)
7911819Sjulian		*hostname++ = 0;
8011819Sjulian
8111819Sjulian	addr = zero_addr;
8211819Sjulian	Field(buf, addr.x_net.c_net, 4);
8311819Sjulian	if (hostname == 0)
8411819Sjulian		return (addr);  /* No separator means net only */
8511819Sjulian
8611819Sjulian	socketname = strchr(hostname, separator);
8711819Sjulian	if (socketname) {
8811819Sjulian		*socketname++ = 0;
8911819Sjulian		Field(socketname, (u_char *)&addr.x_port, 2);
9011819Sjulian	}
9111819Sjulian
9211819Sjulian	Field(hostname, addr.x_host.c_host, 6);
9311819Sjulian
9411819Sjulian	return (addr);
9511819Sjulian}
9611819Sjulian
9711819Sjulianstatic void
9811819SjulianField(buf, out, len)
9911819Sjulian	char *buf;
10011819Sjulian	u_char *out;
10111819Sjulian	int len;
10211819Sjulian{
10392913Sobrien	char *bp = buf;
10411819Sjulian	int i, ibase, base16 = 0, base10 = 0, clen = 0;
10511819Sjulian	int hb[6], *hp;
10611819Sjulian	char *fmt;
10711819Sjulian
10811819Sjulian	/*
10911819Sjulian	 * first try 2-273#2-852-151-014#socket
11011819Sjulian	 */
11111819Sjulian	if ((*buf != '-') &&
11211819Sjulian	    (1 < (i = sscanf(buf, "%d-%d-%d-%d-%d",
11311819Sjulian			&hb[0], &hb[1], &hb[2], &hb[3], &hb[4])))) {
11411819Sjulian		cvtbase(1000L, 256, hb, i, out, len);
11511819Sjulian		return;
11611819Sjulian	}
11711819Sjulian	/*
11811819Sjulian	 * try form 8E1#0.0.AA.0.5E.E6#socket
11911819Sjulian	 */
12011819Sjulian	if (1 < (i = sscanf(buf,"%x.%x.%x.%x.%x.%x",
12111819Sjulian			&hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
12211819Sjulian		cvtbase(256L, 256, hb, i, out, len);
12311819Sjulian		return;
12411819Sjulian	}
12511819Sjulian	/*
12611819Sjulian	 * try form 8E1#0:0:AA:0:5E:E6#socket
12711819Sjulian	 */
12811819Sjulian	if (1 < (i = sscanf(buf,"%x:%x:%x:%x:%x:%x",
12911819Sjulian			&hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
13011819Sjulian		cvtbase(256L, 256, hb, i, out, len);
13111819Sjulian		return;
13211819Sjulian	}
13311819Sjulian	/*
13411819Sjulian	 * This is REALLY stretching it but there was a
13572757Skris	 * comma notation separating shorts -- definitely non-standard
13611819Sjulian	 */
13711819Sjulian	if (1 < (i = sscanf(buf,"%x,%x,%x",
13811819Sjulian			&hb[0], &hb[1], &hb[2]))) {
13911819Sjulian		hb[0] = htons(hb[0]); hb[1] = htons(hb[1]);
14011819Sjulian		hb[2] = htons(hb[2]);
14111819Sjulian		cvtbase(65536L, 256, hb, i, out, len);
14211819Sjulian		return;
14311819Sjulian	}
14411819Sjulian
14511819Sjulian	/* Need to decide if base 10, 16 or 8 */
14611819Sjulian	while (*bp) switch (*bp++) {
14711819Sjulian
14811819Sjulian	case '0': case '1': case '2': case '3': case '4': case '5':
14911819Sjulian	case '6': case '7': case '-':
15011819Sjulian		break;
15111819Sjulian
15211819Sjulian	case '8': case '9':
15311819Sjulian		base10 = 1;
15411819Sjulian		break;
15511819Sjulian
15611819Sjulian	case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
15711819Sjulian	case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
15811819Sjulian		base16 = 1;
15911819Sjulian		break;
16011819Sjulian
16111819Sjulian	case 'x': case 'X':
16211819Sjulian		*--bp = '0';
16311819Sjulian		base16 = 1;
16411819Sjulian		break;
16511819Sjulian
16611819Sjulian	case 'h': case 'H':
16711819Sjulian		base16 = 1;
168102411Scharnier		/* FALLTHROUGH */
16911819Sjulian
17011819Sjulian	default:
17111819Sjulian		*--bp = 0; /* Ends Loop */
17211819Sjulian	}
17311819Sjulian	if (base16) {
17411819Sjulian		fmt = "%3x";
17511819Sjulian		ibase = 4096;
17611819Sjulian	} else if (base10 == 0 && *buf == '0') {
17711819Sjulian		fmt = "%3o";
17811819Sjulian		ibase = 512;
17911819Sjulian	} else {
18011819Sjulian		fmt = "%3d";
18111819Sjulian		ibase = 1000;
18211819Sjulian	}
18311819Sjulian
18411819Sjulian	for (bp = buf; *bp++; ) clen++;
18511819Sjulian	if (clen == 0) clen++;
18611819Sjulian	if (clen > 18) clen = 18;
18711819Sjulian	i = ((clen - 1) / 3) + 1;
18811819Sjulian	bp = clen + buf - 3;
18911819Sjulian	hp = hb + i - 1;
19011819Sjulian
19111819Sjulian	while (hp > hb) {
19211819Sjulian		(void)sscanf(bp, fmt, hp);
19311819Sjulian		bp[0] = 0;
19411819Sjulian		hp--;
19511819Sjulian		bp -= 3;
19611819Sjulian	}
19711819Sjulian	(void)sscanf(buf, fmt, hp);
19811819Sjulian	cvtbase((long)ibase, 256, hb, i, out, len);
19911819Sjulian}
20011819Sjulian
20111819Sjulianstatic void
20211819Sjuliancvtbase(oldbase,newbase,input,inlen,result,reslen)
20311819Sjulian	long oldbase;
20411819Sjulian	int newbase;
20511819Sjulian	int input[];
20611819Sjulian	int inlen;
20711819Sjulian	unsigned char result[];
20811819Sjulian	int reslen;
20911819Sjulian{
21011819Sjulian	int d, e;
21111819Sjulian	long sum;
21211819Sjulian
21311819Sjulian	e = 1;
21411819Sjulian	while (e > 0 && reslen > 0) {
21511819Sjulian		d = 0; e = 0; sum = 0;
21611819Sjulian		/* long division: input=input/newbase */
21711819Sjulian		while (d < inlen) {
21811819Sjulian			sum = sum*oldbase + (long) input[d];
21911819Sjulian			e += (sum > 0);
22011819Sjulian			input[d++] = sum / newbase;
22111819Sjulian			sum %= newbase;
22211819Sjulian		}
22311819Sjulian		result[--reslen] = sum;	/* accumulate remainder */
22411819Sjulian	}
22511819Sjulian	for (d=0; d < reslen; d++)
22611819Sjulian		result[d] = 0;
22711819Sjulian}
228