1139823Simp/*-
211819Sjulian * Copyright (c) 1984, 1985, 1986, 1987, 1993
3194610Srwatson *	The Regents of the University of California.
4194610Srwatson * Copyright (c) 2009 Robert N. M. Watson
5194610Srwatson * All rights reserved.
611819Sjulian *
711819Sjulian * Redistribution and use in source and binary forms, with or without
811819Sjulian * modification, are permitted provided that the following conditions
911819Sjulian * are met:
1011819Sjulian * 1. Redistributions of source code must retain the above copyright
1111819Sjulian *    notice, this list of conditions and the following disclaimer.
1211819Sjulian * 2. Redistributions in binary form must reproduce the above copyright
1311819Sjulian *    notice, this list of conditions and the following disclaimer in the
1411819Sjulian *    documentation and/or other materials provided with the distribution.
15165899Srwatson * 4. Neither the name of the University nor the names of its contributors
16165899Srwatson *    may be used to endorse or promote products derived from this software
17165899Srwatson *    without specific prior written permission.
18165899Srwatson *
19165899Srwatson * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20165899Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21165899Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22165899Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23165899Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24165899Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25165899Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26165899Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27165899Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28165899Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29165899Srwatson * SUCH DAMAGE.
30165899Srwatson *
31165899Srwatson * Copyright (c) 1995, Mike Mitchell
32165899Srwatson *
33165899Srwatson * Redistribution and use in source and binary forms, with or without
34165899Srwatson * modification, are permitted provided that the following conditions
35165899Srwatson * are met:
36165899Srwatson * 1. Redistributions of source code must retain the above copyright
37165899Srwatson *    notice, this list of conditions and the following disclaimer.
38165899Srwatson * 2. Redistributions in binary form must reproduce the above copyright
39165899Srwatson *    notice, this list of conditions and the following disclaimer in the
40165899Srwatson *    documentation and/or other materials provided with the distribution.
4111819Sjulian * 3. All advertising materials mentioning features or use of this software
4211819Sjulian *    must display the following acknowledgement:
4311819Sjulian *	This product includes software developed by the University of
4411819Sjulian *	California, Berkeley and its contributors.
4511819Sjulian * 4. Neither the name of the University nor the names of its contributors
4611819Sjulian *    may be used to endorse or promote products derived from this software
4711819Sjulian *    without specific prior written permission.
4811819Sjulian *
4911819Sjulian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
5011819Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5111819Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5211819Sjulian * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
5311819Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5411819Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5511819Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5611819Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5711819Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5811819Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5911819Sjulian * SUCH DAMAGE.
60139584Srwatson *
6112057Sjulian *	@(#)ipx.c
6211819Sjulian */
6311819Sjulian
64116189Sobrien#include <sys/cdefs.h>
65116189Sobrien__FBSDID("$FreeBSD$");
66116189Sobrien
6711819Sjulian#include <sys/param.h>
68134445Srwatson#include <sys/kernel.h>
6911819Sjulian#include <sys/systm.h>
70194608Srwatson#include <sys/lock.h>
7126965Sjhay#include <sys/malloc.h>
72170689Srwatson#include <sys/priv.h>
73194608Srwatson#include <sys/rwlock.h>
7424204Sbde#include <sys/sockio.h>
7511819Sjulian#include <sys/socket.h>
7611819Sjulian
7711819Sjulian#include <net/if.h>
7811819Sjulian#include <net/route.h>
7911819Sjulian
8011819Sjulian#include <netipx/ipx.h>
8111819Sjulian#include <netipx/ipx_if.h>
8225652Sjhay#include <netipx/ipx_var.h>
8311819Sjulian
84134445Srwatson/*
85194608Srwatson * The IPX-layer address list is protected by ipx_ifaddr_rw.
86134445Srwatson */
87194608Srwatsonstruct rwlock		 ipx_ifaddr_rw;
88194905Srwatsonstruct ipx_ifaddrhead	 ipx_ifaddrhead;
8911819Sjulian
90194595Srwatsonstatic void	ipx_ifscrub(struct ifnet *ifp, struct ipx_ifaddr *ia);
91194595Srwatsonstatic int	ipx_ifinit(struct ifnet *ifp, struct ipx_ifaddr *ia,
92194595Srwatson		    struct sockaddr_ipx *sipx, int scrub);
9325652Sjhay
9411819Sjulian/*
9511819Sjulian * Generic internet control operations (ioctl's).
9611819Sjulian */
9711819Sjulianint
98169463Srwatsonipx_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
99169463Srwatson    struct thread *td)
10011819Sjulian{
101169463Srwatson	struct ifreq *ifr = (struct ifreq *)data;
102169463Srwatson	struct ipx_aliasreq *ifra = (struct ipx_aliasreq *)data;
103194905Srwatson	struct ipx_ifaddr *ia;
10411819Sjulian	struct ifaddr *ifa;
10511819Sjulian	int dstIsNew, hostIsNew;
106194857Srwatson	int error, priv;
10711819Sjulian
10811819Sjulian	/*
10911819Sjulian	 * Find address for this interface, if it exists.
11011819Sjulian	 */
11125652Sjhay	if (ifp == NULL)
11211819Sjulian		return (EADDRNOTAVAIL);
113194610Srwatson
114194857Srwatson	IPX_IFADDR_RLOCK();
115194905Srwatson	TAILQ_FOREACH(ia, &ipx_ifaddrhead, ia_link) {
11611819Sjulian		if (ia->ia_ifp == ifp)
11711819Sjulian			break;
118194905Srwatson	}
119194857Srwatson	if (ia != NULL)
120194857Srwatson		ifa_ref(&ia->ia_ifa);
121194857Srwatson	IPX_IFADDR_RUNLOCK();
12211819Sjulian
123194857Srwatson	error = 0;
12411819Sjulian	switch (cmd) {
12511819Sjulian	case SIOCGIFADDR:
126194610Srwatson		if (ia == NULL) {
127194610Srwatson			error = EADDRNOTAVAIL;
128194610Srwatson			goto out;
129194610Srwatson		}
13011819Sjulian		*(struct sockaddr_ipx *)&ifr->ifr_addr = ia->ia_addr;
131194610Srwatson		goto out;
13211819Sjulian
13311819Sjulian	case SIOCGIFBRDADDR:
134194610Srwatson		if (ia == NULL) {
135194610Srwatson			error = EADDRNOTAVAIL;
136194610Srwatson			goto out;
137194610Srwatson		}
138194610Srwatson		if ((ifp->if_flags & IFF_BROADCAST) == 0) {
139194610Srwatson			error = EINVAL;
140194610Srwatson			goto out;
141194610Srwatson		}
14211819Sjulian		*(struct sockaddr_ipx *)&ifr->ifr_dstaddr = ia->ia_broadaddr;
143194610Srwatson		goto out;
14411819Sjulian
14511819Sjulian	case SIOCGIFDSTADDR:
146194610Srwatson		if (ia == NULL) {
147194610Srwatson			error = EADDRNOTAVAIL;
148194610Srwatson			goto out;
149194610Srwatson		}
150194610Srwatson		if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
151194610Srwatson			error = EINVAL;
152194610Srwatson			goto out;
153194610Srwatson		}
15411819Sjulian		*(struct sockaddr_ipx *)&ifr->ifr_dstaddr = ia->ia_dstaddr;
155194610Srwatson		goto out;
15611819Sjulian	}
15711819Sjulian
15811819Sjulian	switch (cmd) {
15911819Sjulian	case SIOCAIFADDR:
16011819Sjulian	case SIOCDIFADDR:
161183113Sattilio		priv = (cmd == SIOCAIFADDR) ? PRIV_NET_ADDIFADDR :
162183113Sattilio		    PRIV_NET_DELIFADDR;
163183113Sattilio		if (td && (error = priv_check(td, priv)) != 0)
164194610Srwatson			goto out;
165194857Srwatson
166194857Srwatson		IPX_IFADDR_RLOCK();
167194857Srwatson		if (ifra->ifra_addr.sipx_family == AF_IPX) {
168194905Srwatson			struct ipx_ifaddr *oia;
169194905Srwatson
170194905Srwatson			for (oia = ia; ia; ia = TAILQ_NEXT(ia, ia_link)) {
171194857Srwatson				if (ia->ia_ifp == ifp  &&
172194857Srwatson				    ipx_neteq(ia->ia_addr.sipx_addr,
173194857Srwatson				    ifra->ifra_addr.sipx_addr))
174194857Srwatson					break;
175194857Srwatson			}
176194857Srwatson			if (oia != NULL && oia != ia)
177194857Srwatson				ifa_free(&oia->ia_ifa);
178194857Srwatson			if (ia != NULL && oia != ia)
179194857Srwatson				ifa_ref(&ia->ia_ifa);
180194857Srwatson		}
181194857Srwatson		IPX_IFADDR_RUNLOCK();
182194610Srwatson		if (cmd == SIOCDIFADDR && ia == NULL) {
183194610Srwatson			error = EADDRNOTAVAIL;
184194610Srwatson			goto out;
185194610Srwatson		}
18611819Sjulian		/* FALLTHROUGH */
18711819Sjulian
18811819Sjulian	case SIOCSIFADDR:
18911819Sjulian	case SIOCSIFDSTADDR:
190183113Sattilio		if (td && (error = priv_check(td, PRIV_NET_SETLLADDR)) != 0)
191194610Srwatson			goto out;
19225652Sjhay		if (ia == NULL) {
193194857Srwatson			ia = malloc(sizeof(*ia), M_IFADDR, M_NOWAIT | M_ZERO);
194194857Srwatson			if (ia == NULL) {
195194610Srwatson				error = ENOBUFS;
196194610Srwatson				goto out;
197194610Srwatson			}
19820407Swollman			ifa = (struct ifaddr *)ia;
199194602Srwatson			ifa_init(ifa);
20011819Sjulian			ia->ia_ifp = ifp;
20120407Swollman			ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr;
20220407Swollman			ifa->ifa_netmask = (struct sockaddr *)&ipx_netmask;
20320407Swollman			ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
20411819Sjulian			if (ifp->if_flags & IFF_BROADCAST) {
20511819Sjulian				ia->ia_broadaddr.sipx_family = AF_IPX;
206194595Srwatson				ia->ia_broadaddr.sipx_len =
207194595Srwatson				    sizeof(ia->ia_addr);
208194595Srwatson				ia->ia_broadaddr.sipx_addr.x_host =
209194595Srwatson				    ipx_broadhost;
21011819Sjulian			}
211194905Srwatson			ifa_ref(&ia->ia_ifa);		/* ipx_ifaddrhead */
212194857Srwatson			IPX_IFADDR_WLOCK();
213194905Srwatson			TAILQ_INSERT_TAIL(&ipx_ifaddrhead, ia, ia_link);
214194857Srwatson			IPX_IFADDR_WUNLOCK();
215194857Srwatson
216194857Srwatson			ifa_ref(&ia->ia_ifa);		/* if_addrhead */
217229621Sjhb			IF_ADDR_WLOCK(ifp);
218194606Srwatson			TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
219229621Sjhb			IF_ADDR_WUNLOCK(ifp);
22011819Sjulian		}
221183113Sattilio		break;
222194595Srwatson
223183113Sattilio	default:
224183113Sattilio		if (td && (error = priv_check(td, PRIV_NET_HWIOCTL)) != 0)
225194610Srwatson			goto out;
22611819Sjulian	}
22711819Sjulian
22811819Sjulian	switch (cmd) {
22911819Sjulian	case SIOCSIFDSTADDR:
230194610Srwatson		if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
231194610Srwatson			error = EINVAL;
232194610Srwatson			goto out;
233194610Srwatson		}
23411819Sjulian		if (ia->ia_flags & IFA_ROUTE) {
23511819Sjulian			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
23611819Sjulian			ia->ia_flags &= ~IFA_ROUTE;
23711819Sjulian		}
23811819Sjulian		if (ifp->if_ioctl) {
239194595Srwatson			error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR,
240194595Srwatson			    (void *)ia);
241194857Srwatson			if (error)
242194857Srwatson				goto out;
24311819Sjulian		}
24411819Sjulian		*(struct sockaddr *)&ia->ia_dstaddr = ifr->ifr_dstaddr;
245194857Srwatson		goto out;
24611819Sjulian
24711819Sjulian	case SIOCSIFADDR:
248194610Srwatson		error = ipx_ifinit(ifp, ia,
249194610Srwatson		    (struct sockaddr_ipx *)&ifr->ifr_addr, 1);
250194857Srwatson		goto out;
25111819Sjulian
25211819Sjulian	case SIOCDIFADDR:
25311819Sjulian		ipx_ifscrub(ifp, ia);
25420407Swollman		ifa = (struct ifaddr *)ia;
255194857Srwatson
256229621Sjhb		IF_ADDR_WLOCK(ifp);
25720407Swollman		TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
258229621Sjhb		IF_ADDR_WUNLOCK(ifp);
259194857Srwatson		ifa_free(ifa);				/* if_addrhead */
260194857Srwatson
261194857Srwatson		IPX_IFADDR_WLOCK();
262194905Srwatson		TAILQ_REMOVE(&ipx_ifaddrhead, ia, ia_link);
263194610Srwatson		IPX_IFADDR_WUNLOCK();
264194905Srwatson		ifa_free(&ia->ia_ifa);			/* ipx_ifaddrhead */
265194857Srwatson		goto out;
266139584Srwatson
26711819Sjulian	case SIOCAIFADDR:
26825652Sjhay		dstIsNew = 0;
26925652Sjhay		hostIsNew = 1;
27011819Sjulian		if (ia->ia_addr.sipx_family == AF_IPX) {
27111819Sjulian			if (ifra->ifra_addr.sipx_len == 0) {
27211819Sjulian				ifra->ifra_addr = ia->ia_addr;
27311819Sjulian				hostIsNew = 0;
27411819Sjulian			} else if (ipx_neteq(ifra->ifra_addr.sipx_addr,
27511819Sjulian					 ia->ia_addr.sipx_addr))
27611819Sjulian				hostIsNew = 0;
27711819Sjulian		}
27811819Sjulian		if ((ifp->if_flags & IFF_POINTOPOINT) &&
27911819Sjulian		    (ifra->ifra_dstaddr.sipx_family == AF_IPX)) {
28011819Sjulian			if (hostIsNew == 0)
28111819Sjulian				ipx_ifscrub(ifp, ia);
28211819Sjulian			ia->ia_dstaddr = ifra->ifra_dstaddr;
28311819Sjulian			dstIsNew  = 1;
28411819Sjulian		}
28511819Sjulian		if (ifra->ifra_addr.sipx_family == AF_IPX &&
28611819Sjulian					    (hostIsNew || dstIsNew))
28711819Sjulian			error = ipx_ifinit(ifp, ia, &ifra->ifra_addr, 0);
288194857Srwatson		goto out;
28911819Sjulian
29011819Sjulian	default:
291194857Srwatson		if (ifp->if_ioctl == NULL) {
292194857Srwatson			error = EOPNOTSUPP;
293194857Srwatson			goto out;
294194857Srwatson		}
295194857Srwatson		error = ((*ifp->if_ioctl)(ifp, cmd, data));
29611819Sjulian	}
297194610Srwatson
298194610Srwatsonout:
299194857Srwatson	if (ia != NULL)
300194857Srwatson		ifa_free(&ia->ia_ifa);
301194610Srwatson	return (error);
30211819Sjulian}
30311819Sjulian
30411819Sjulian/*
305194595Srwatson * Delete any previous route for an old address.
306194595Srwatson */
30725652Sjhaystatic void
308169463Srwatsonipx_ifscrub(struct ifnet *ifp, struct ipx_ifaddr *ia)
30911819Sjulian{
310169463Srwatson
31111819Sjulian	if (ia->ia_flags & IFA_ROUTE) {
31211819Sjulian		if (ifp->if_flags & IFF_POINTOPOINT) {
31311819Sjulian			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
31411819Sjulian		} else
31511819Sjulian			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
31611819Sjulian		ia->ia_flags &= ~IFA_ROUTE;
31711819Sjulian	}
31811819Sjulian}
319194595Srwatson
32011819Sjulian/*
321194595Srwatson * Initialize an interface's internet address and routing table entry.
32211819Sjulian */
32325652Sjhaystatic int
324169463Srwatsonipx_ifinit(struct ifnet *ifp, struct ipx_ifaddr *ia,
325169463Srwatson    struct sockaddr_ipx *sipx, int scrub)
32611819Sjulian{
32711819Sjulian	struct sockaddr_ipx oldaddr;
32811819Sjulian	int s = splimp(), error;
32911819Sjulian
33011819Sjulian	/*
33111819Sjulian	 * Set up new addresses.
33211819Sjulian	 */
33311819Sjulian	oldaddr = ia->ia_addr;
33411819Sjulian	ia->ia_addr = *sipx;
33525652Sjhay
33611819Sjulian	/*
337194595Srwatson	 * The convention we shall adopt for naming is that a supplied
338194595Srwatson	 * address of zero means that "we don't care".  Use the MAC address
339194595Srwatson	 * of the interface.  If it is an interface without a MAC address,
340194595Srwatson	 * like a serial line, the address must be supplied.
34111819Sjulian	 *
342194595Srwatson	 * Give the interface a chance to initialize if this is its first
343194595Srwatson	 * address, and to validate the address if necessary.
34411819Sjulian	 */
34525652Sjhay	if (ifp->if_ioctl != NULL &&
34625652Sjhay	    (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (void *)ia))) {
34711819Sjulian		ia->ia_addr = oldaddr;
34811819Sjulian		splx(s);
34925652Sjhay		return (error);
35011819Sjulian	}
35125652Sjhay	splx(s);
35211819Sjulian	ia->ia_ifa.ifa_metric = ifp->if_metric;
353194595Srwatson
35411819Sjulian	/*
35511819Sjulian	 * Add route for the network.
35611819Sjulian	 */
35711819Sjulian	if (scrub) {
35811819Sjulian		ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
35911819Sjulian		ipx_ifscrub(ifp, ia);
36011819Sjulian		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
36111819Sjulian	}
36211819Sjulian	if (ifp->if_flags & IFF_POINTOPOINT)
36311819Sjulian		rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
36411819Sjulian	else {
36511819Sjulian		ia->ia_broadaddr.sipx_addr.x_net = ia->ia_addr.sipx_addr.x_net;
36611819Sjulian		rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
36711819Sjulian	}
36811819Sjulian	ia->ia_flags |= IFA_ROUTE;
36911819Sjulian	return (0);
37011819Sjulian}
37111819Sjulian
37211819Sjulian/*
37311819Sjulian * Return address info for specified internet network.
37411819Sjulian */
37511819Sjulianstruct ipx_ifaddr *
376169463Srwatsonipx_iaonnetof(struct ipx_addr *dst)
37711819Sjulian{
378169463Srwatson	struct ipx_ifaddr *ia;
379169463Srwatson	struct ipx_addr *compare;
380169463Srwatson	struct ifnet *ifp;
38125652Sjhay	struct ipx_ifaddr *ia_maybe = NULL;
38211819Sjulian	union ipx_net net = dst->x_net;
38311819Sjulian
384194608Srwatson	IPX_IFADDR_LOCK_ASSERT();
385194608Srwatson
386194905Srwatson	TAILQ_FOREACH(ia, &ipx_ifaddrhead, ia_link) {
38725652Sjhay		if ((ifp = ia->ia_ifp) != NULL) {
38811819Sjulian			if (ifp->if_flags & IFF_POINTOPOINT) {
38911819Sjulian				compare = &satoipx_addr(ia->ia_dstaddr);
39011819Sjulian				if (ipx_hosteq(*dst, *compare))
39111819Sjulian					return (ia);
392194595Srwatson				if (ipx_neteqnn(net,
393194595Srwatson				    ia->ia_addr.sipx_addr.x_net))
39411819Sjulian					ia_maybe = ia;
39511819Sjulian			} else {
396194595Srwatson				if (ipx_neteqnn(net,
397194595Srwatson				    ia->ia_addr.sipx_addr.x_net))
39811819Sjulian					return (ia);
39911819Sjulian			}
40011819Sjulian		}
40111819Sjulian	}
40211819Sjulian	return (ia_maybe);
40311819Sjulian}
40426965Sjhay
40526965Sjhayvoid
406169463Srwatsonipx_printhost(struct ipx_addr *addr)
40726965Sjhay{
40826965Sjhay	u_short port;
40926965Sjhay	struct ipx_addr work = *addr;
410169463Srwatson	char *p; u_char *q;
411169463Srwatson	char *net = "", *host = "";
41226965Sjhay	char cport[10], chost[15], cnet[15];
41326965Sjhay
41426965Sjhay	port = ntohs(work.x_port);
41526965Sjhay
41626965Sjhay	if (ipx_nullnet(work) && ipx_nullhost(work)) {
41726965Sjhay		if (port)
41826965Sjhay			printf("*.%x", port);
41926965Sjhay		else
42026965Sjhay			printf("*.*");
42126965Sjhay
42226965Sjhay		return;
42326965Sjhay	}
42426965Sjhay
42526965Sjhay	if (ipx_wildnet(work))
42626965Sjhay		net = "any";
42726965Sjhay	else if (ipx_nullnet(work))
42826965Sjhay		net = "*";
42926965Sjhay	else {
43026965Sjhay		q = work.x_net.c_net;
43141514Sarchie		snprintf(cnet, sizeof(cnet), "%x%x%x%x",
43226965Sjhay			q[0], q[1], q[2], q[3]);
43326965Sjhay		for (p = cnet; *p == '0' && p < cnet + 8; p++)
43426965Sjhay			continue;
43526965Sjhay		net = p;
43626965Sjhay	}
43726965Sjhay
43826965Sjhay	if (ipx_wildhost(work))
43926965Sjhay		host = "any";
44026965Sjhay	else if (ipx_nullhost(work))
44126965Sjhay		host = "*";
44226965Sjhay	else {
44326965Sjhay		q = work.x_host.c_host;
44441514Sarchie		snprintf(chost, sizeof(chost), "%x%x%x%x%x%x",
44526965Sjhay			q[0], q[1], q[2], q[3], q[4], q[5]);
44626965Sjhay		for (p = chost; *p == '0' && p < chost + 12; p++)
44726965Sjhay			continue;
44826965Sjhay		host = p;
44926965Sjhay	}
45026965Sjhay
45126965Sjhay	if (port) {
45226965Sjhay		if (strcmp(host, "*") == 0) {
45326965Sjhay			host = "";
45441514Sarchie			snprintf(cport, sizeof(cport), "%x", port);
45526965Sjhay		} else
45641514Sarchie			snprintf(cport, sizeof(cport), ".%x", port);
45726965Sjhay	} else
45826965Sjhay		*cport = 0;
45926965Sjhay
46026965Sjhay	printf("%s.%s%s", net, host, cport);
46126965Sjhay}
462