ipx.c revision 194610
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: head/sys/netipx/ipx.c 194610 2009-06-21 21:42:29Z rwatson $"); 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; 88194608Srwatsonstruct ipx_ifaddr *ipx_ifaddr; 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; 103169463Srwatson struct ipx_ifaddr *ia; 10411819Sjulian struct ifaddr *ifa; 10511819Sjulian struct ipx_ifaddr *oia; 10611819Sjulian int dstIsNew, hostIsNew; 107183113Sattilio int error = 0, priv; 10811819Sjulian 10911819Sjulian /* 11011819Sjulian * Find address for this interface, if it exists. 11111819Sjulian */ 11225652Sjhay if (ifp == NULL) 11311819Sjulian return (EADDRNOTAVAIL); 114194610Srwatson 115194610Srwatson IPX_IFADDR_WLOCK(); 11625652Sjhay for (ia = ipx_ifaddr; ia != NULL; ia = ia->ia_next) 11711819Sjulian if (ia->ia_ifp == ifp) 11811819Sjulian break; 11911819Sjulian 12011819Sjulian switch (cmd) { 12111819Sjulian case SIOCGIFADDR: 122194610Srwatson if (ia == NULL) { 123194610Srwatson error = EADDRNOTAVAIL; 124194610Srwatson goto out; 125194610Srwatson } 12611819Sjulian *(struct sockaddr_ipx *)&ifr->ifr_addr = ia->ia_addr; 127194610Srwatson goto out; 12811819Sjulian 12911819Sjulian case SIOCGIFBRDADDR: 130194610Srwatson if (ia == NULL) { 131194610Srwatson error = EADDRNOTAVAIL; 132194610Srwatson goto out; 133194610Srwatson } 134194610Srwatson if ((ifp->if_flags & IFF_BROADCAST) == 0) { 135194610Srwatson error = EINVAL; 136194610Srwatson goto out; 137194610Srwatson } 13811819Sjulian *(struct sockaddr_ipx *)&ifr->ifr_dstaddr = ia->ia_broadaddr; 139194610Srwatson goto out; 14011819Sjulian 14111819Sjulian case SIOCGIFDSTADDR: 142194610Srwatson if (ia == NULL) { 143194610Srwatson error = EADDRNOTAVAIL; 144194610Srwatson goto out; 145194610Srwatson } 146194610Srwatson if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { 147194610Srwatson error = EINVAL; 148194610Srwatson goto out; 149194610Srwatson } 15011819Sjulian *(struct sockaddr_ipx *)&ifr->ifr_dstaddr = ia->ia_dstaddr; 151194610Srwatson goto out; 15211819Sjulian } 15311819Sjulian 15411819Sjulian switch (cmd) { 15511819Sjulian case SIOCAIFADDR: 15611819Sjulian case SIOCDIFADDR: 157183113Sattilio priv = (cmd == SIOCAIFADDR) ? PRIV_NET_ADDIFADDR : 158183113Sattilio PRIV_NET_DELIFADDR; 159183113Sattilio if (td && (error = priv_check(td, priv)) != 0) 160194610Srwatson goto out; 16111819Sjulian if (ifra->ifra_addr.sipx_family == AF_IPX) 16225652Sjhay for (oia = ia; ia != NULL; ia = ia->ia_next) { 16311819Sjulian if (ia->ia_ifp == ifp && 16411819Sjulian ipx_neteq(ia->ia_addr.sipx_addr, 16511819Sjulian ifra->ifra_addr.sipx_addr)) 16611819Sjulian break; 16711819Sjulian } 168194610Srwatson if (cmd == SIOCDIFADDR && ia == NULL) { 169194610Srwatson error = EADDRNOTAVAIL; 170194610Srwatson goto out; 171194610Srwatson } 17211819Sjulian /* FALLTHROUGH */ 17311819Sjulian 17411819Sjulian case SIOCSIFADDR: 17511819Sjulian case SIOCSIFDSTADDR: 176183113Sattilio if (td && (error = priv_check(td, PRIV_NET_SETLLADDR)) != 0) 177194610Srwatson goto out; 17825652Sjhay if (ia == NULL) { 17911819Sjulian oia = (struct ipx_ifaddr *) 18069781Sdwmalone malloc(sizeof(*ia), M_IFADDR, 181194610Srwatson M_NOWAIT | M_ZERO); 182194610Srwatson if (oia == NULL) { 183194610Srwatson error = ENOBUFS; 184194610Srwatson goto out; 185194610Srwatson } 18625652Sjhay if ((ia = ipx_ifaddr) != NULL) { 18725652Sjhay for ( ; ia->ia_next != NULL; ia = ia->ia_next) 18811819Sjulian ; 18911819Sjulian ia->ia_next = oia; 19011819Sjulian } else 19111819Sjulian ipx_ifaddr = oia; 19211819Sjulian ia = oia; 19320407Swollman ifa = (struct ifaddr *)ia; 194194602Srwatson ifa_init(ifa); 19511819Sjulian ia->ia_ifp = ifp; 19620407Swollman ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr; 19720407Swollman ifa->ifa_netmask = (struct sockaddr *)&ipx_netmask; 19820407Swollman ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr; 19911819Sjulian if (ifp->if_flags & IFF_BROADCAST) { 20011819Sjulian ia->ia_broadaddr.sipx_family = AF_IPX; 201194595Srwatson ia->ia_broadaddr.sipx_len = 202194595Srwatson sizeof(ia->ia_addr); 203194595Srwatson ia->ia_broadaddr.sipx_addr.x_host = 204194595Srwatson ipx_broadhost; 20511819Sjulian } 206194606Srwatson IF_ADDR_LOCK(ifp); 207194606Srwatson TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link); 208194606Srwatson IF_ADDR_UNLOCK(ifp); 20911819Sjulian } 210183113Sattilio break; 211194595Srwatson 212183113Sattilio default: 213183113Sattilio if (td && (error = priv_check(td, PRIV_NET_HWIOCTL)) != 0) 214194610Srwatson goto out; 21511819Sjulian } 21611819Sjulian 21711819Sjulian switch (cmd) { 21811819Sjulian case SIOCSIFDSTADDR: 219194610Srwatson if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { 220194610Srwatson error = EINVAL; 221194610Srwatson goto out; 222194610Srwatson } 22311819Sjulian if (ia->ia_flags & IFA_ROUTE) { 22411819Sjulian rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 22511819Sjulian ia->ia_flags &= ~IFA_ROUTE; 22611819Sjulian } 227194610Srwatson ifa_ref(&ia->ia_ifa); 228194610Srwatson IPX_IFADDR_WUNLOCK(); 22911819Sjulian if (ifp->if_ioctl) { 230194595Srwatson error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, 231194595Srwatson (void *)ia); 232194610Srwatson if (error) { 233194610Srwatson ifa_free(&ia->ia_ifa); 23411819Sjulian return (error); 235194610Srwatson } 23611819Sjulian } 23711819Sjulian *(struct sockaddr *)&ia->ia_dstaddr = ifr->ifr_dstaddr; 238194610Srwatson ifa_free(&ia->ia_ifa); 23911819Sjulian return (0); 24011819Sjulian 24111819Sjulian case SIOCSIFADDR: 242194610Srwatson ifa_ref(&ia->ia_ifa); 243194610Srwatson IPX_IFADDR_WUNLOCK(); 244194610Srwatson error = ipx_ifinit(ifp, ia, 245194610Srwatson (struct sockaddr_ipx *)&ifr->ifr_addr, 1); 246194610Srwatson ifa_free(&ia->ia_ifa); 247194610Srwatson return (error); 24811819Sjulian 24911819Sjulian case SIOCDIFADDR: 250194610Srwatson /* XXXRW: Potential race here while ipx_ifaddr_rw is dropped. */ 251194610Srwatson ifa_ref(&ia->ia_ifa); 252194610Srwatson IPX_IFADDR_WUNLOCK(); 25311819Sjulian ipx_ifscrub(ifp, ia); 254194610Srwatson IPX_IFADDR_WLOCK(); 255194610Srwatson ifa_free(&ia->ia_ifa); 25620407Swollman ifa = (struct ifaddr *)ia; 257194606Srwatson IF_ADDR_LOCK(ifp); 25820407Swollman TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link); 259194606Srwatson IF_ADDR_UNLOCK(ifp); 26011819Sjulian oia = ia; 26111819Sjulian if (oia == (ia = ipx_ifaddr)) { 26211819Sjulian ipx_ifaddr = ia->ia_next; 26311819Sjulian } else { 26411819Sjulian while (ia->ia_next && (ia->ia_next != oia)) { 26511819Sjulian ia = ia->ia_next; 26611819Sjulian } 26711819Sjulian if (ia->ia_next) 26811819Sjulian ia->ia_next = oia->ia_next; 26911819Sjulian else 27011819Sjulian printf("Didn't unlink ipxifadr from list\n"); 27111819Sjulian } 272194602Srwatson ifa_free(&oia->ia_ifa); 273194610Srwatson IPX_IFADDR_WUNLOCK(); 27411819Sjulian return (0); 275139584Srwatson 27611819Sjulian case SIOCAIFADDR: 27725652Sjhay dstIsNew = 0; 27825652Sjhay hostIsNew = 1; 27911819Sjulian if (ia->ia_addr.sipx_family == AF_IPX) { 28011819Sjulian if (ifra->ifra_addr.sipx_len == 0) { 28111819Sjulian ifra->ifra_addr = ia->ia_addr; 28211819Sjulian hostIsNew = 0; 28311819Sjulian } else if (ipx_neteq(ifra->ifra_addr.sipx_addr, 28411819Sjulian ia->ia_addr.sipx_addr)) 28511819Sjulian hostIsNew = 0; 28611819Sjulian } 287194610Srwatson ifa_ref(&ia->ia_ifa); 288194610Srwatson IPX_IFADDR_WUNLOCK(); 28911819Sjulian if ((ifp->if_flags & IFF_POINTOPOINT) && 29011819Sjulian (ifra->ifra_dstaddr.sipx_family == AF_IPX)) { 29111819Sjulian if (hostIsNew == 0) 29211819Sjulian ipx_ifscrub(ifp, ia); 29311819Sjulian ia->ia_dstaddr = ifra->ifra_dstaddr; 29411819Sjulian dstIsNew = 1; 29511819Sjulian } 29611819Sjulian if (ifra->ifra_addr.sipx_family == AF_IPX && 29711819Sjulian (hostIsNew || dstIsNew)) 29811819Sjulian error = ipx_ifinit(ifp, ia, &ifra->ifra_addr, 0); 299194610Srwatson ifa_free(&ia->ia_ifa); 30011819Sjulian return (error); 30111819Sjulian 30211819Sjulian default: 303194610Srwatson IPX_IFADDR_WUNLOCK(); 30425652Sjhay if (ifp->if_ioctl == NULL) 30511819Sjulian return (EOPNOTSUPP); 30611819Sjulian return ((*ifp->if_ioctl)(ifp, cmd, data)); 30711819Sjulian } 308194610Srwatson 309194610Srwatsonout: 310194610Srwatson IPX_IFADDR_WUNLOCK(); 311194610Srwatson return (error); 31211819Sjulian} 31311819Sjulian 31411819Sjulian/* 315194595Srwatson * Delete any previous route for an old address. 316194595Srwatson */ 31725652Sjhaystatic void 318169463Srwatsonipx_ifscrub(struct ifnet *ifp, struct ipx_ifaddr *ia) 31911819Sjulian{ 320169463Srwatson 32111819Sjulian if (ia->ia_flags & IFA_ROUTE) { 32211819Sjulian if (ifp->if_flags & IFF_POINTOPOINT) { 32311819Sjulian rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 32411819Sjulian } else 32511819Sjulian rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 32611819Sjulian ia->ia_flags &= ~IFA_ROUTE; 32711819Sjulian } 32811819Sjulian} 329194595Srwatson 33011819Sjulian/* 331194595Srwatson * Initialize an interface's internet address and routing table entry. 33211819Sjulian */ 33325652Sjhaystatic int 334169463Srwatsonipx_ifinit(struct ifnet *ifp, struct ipx_ifaddr *ia, 335169463Srwatson struct sockaddr_ipx *sipx, int scrub) 33611819Sjulian{ 33711819Sjulian struct sockaddr_ipx oldaddr; 33811819Sjulian int s = splimp(), error; 33911819Sjulian 34011819Sjulian /* 34111819Sjulian * Set up new addresses. 34211819Sjulian */ 34311819Sjulian oldaddr = ia->ia_addr; 34411819Sjulian ia->ia_addr = *sipx; 34525652Sjhay 34611819Sjulian /* 347194595Srwatson * The convention we shall adopt for naming is that a supplied 348194595Srwatson * address of zero means that "we don't care". Use the MAC address 349194595Srwatson * of the interface. If it is an interface without a MAC address, 350194595Srwatson * like a serial line, the address must be supplied. 35111819Sjulian * 352194595Srwatson * Give the interface a chance to initialize if this is its first 353194595Srwatson * address, and to validate the address if necessary. 35411819Sjulian */ 35525652Sjhay if (ifp->if_ioctl != NULL && 35625652Sjhay (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (void *)ia))) { 35711819Sjulian ia->ia_addr = oldaddr; 35811819Sjulian splx(s); 35925652Sjhay return (error); 36011819Sjulian } 36125652Sjhay splx(s); 36211819Sjulian ia->ia_ifa.ifa_metric = ifp->if_metric; 363194595Srwatson 36411819Sjulian /* 36511819Sjulian * Add route for the network. 36611819Sjulian */ 36711819Sjulian if (scrub) { 36811819Sjulian ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; 36911819Sjulian ipx_ifscrub(ifp, ia); 37011819Sjulian ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 37111819Sjulian } 37211819Sjulian if (ifp->if_flags & IFF_POINTOPOINT) 37311819Sjulian rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 37411819Sjulian else { 37511819Sjulian ia->ia_broadaddr.sipx_addr.x_net = ia->ia_addr.sipx_addr.x_net; 37611819Sjulian rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP); 37711819Sjulian } 37811819Sjulian ia->ia_flags |= IFA_ROUTE; 37911819Sjulian return (0); 38011819Sjulian} 38111819Sjulian 38211819Sjulian/* 38311819Sjulian * Return address info for specified internet network. 38411819Sjulian */ 38511819Sjulianstruct ipx_ifaddr * 386169463Srwatsonipx_iaonnetof(struct ipx_addr *dst) 38711819Sjulian{ 388169463Srwatson struct ipx_ifaddr *ia; 389169463Srwatson struct ipx_addr *compare; 390169463Srwatson struct ifnet *ifp; 39125652Sjhay struct ipx_ifaddr *ia_maybe = NULL; 39211819Sjulian union ipx_net net = dst->x_net; 39311819Sjulian 394194608Srwatson IPX_IFADDR_LOCK_ASSERT(); 395194608Srwatson 39625652Sjhay for (ia = ipx_ifaddr; ia != NULL; ia = ia->ia_next) { 39725652Sjhay if ((ifp = ia->ia_ifp) != NULL) { 39811819Sjulian if (ifp->if_flags & IFF_POINTOPOINT) { 39911819Sjulian compare = &satoipx_addr(ia->ia_dstaddr); 40011819Sjulian if (ipx_hosteq(*dst, *compare)) 40111819Sjulian return (ia); 402194595Srwatson if (ipx_neteqnn(net, 403194595Srwatson ia->ia_addr.sipx_addr.x_net)) 40411819Sjulian ia_maybe = ia; 40511819Sjulian } else { 406194595Srwatson if (ipx_neteqnn(net, 407194595Srwatson ia->ia_addr.sipx_addr.x_net)) 40811819Sjulian return (ia); 40911819Sjulian } 41011819Sjulian } 41111819Sjulian } 41211819Sjulian return (ia_maybe); 41311819Sjulian} 41426965Sjhay 41526965Sjhayvoid 416169463Srwatsonipx_printhost(struct ipx_addr *addr) 41726965Sjhay{ 41826965Sjhay u_short port; 41926965Sjhay struct ipx_addr work = *addr; 420169463Srwatson char *p; u_char *q; 421169463Srwatson char *net = "", *host = ""; 42226965Sjhay char cport[10], chost[15], cnet[15]; 42326965Sjhay 42426965Sjhay port = ntohs(work.x_port); 42526965Sjhay 42626965Sjhay if (ipx_nullnet(work) && ipx_nullhost(work)) { 42726965Sjhay if (port) 42826965Sjhay printf("*.%x", port); 42926965Sjhay else 43026965Sjhay printf("*.*"); 43126965Sjhay 43226965Sjhay return; 43326965Sjhay } 43426965Sjhay 43526965Sjhay if (ipx_wildnet(work)) 43626965Sjhay net = "any"; 43726965Sjhay else if (ipx_nullnet(work)) 43826965Sjhay net = "*"; 43926965Sjhay else { 44026965Sjhay q = work.x_net.c_net; 44141514Sarchie snprintf(cnet, sizeof(cnet), "%x%x%x%x", 44226965Sjhay q[0], q[1], q[2], q[3]); 44326965Sjhay for (p = cnet; *p == '0' && p < cnet + 8; p++) 44426965Sjhay continue; 44526965Sjhay net = p; 44626965Sjhay } 44726965Sjhay 44826965Sjhay if (ipx_wildhost(work)) 44926965Sjhay host = "any"; 45026965Sjhay else if (ipx_nullhost(work)) 45126965Sjhay host = "*"; 45226965Sjhay else { 45326965Sjhay q = work.x_host.c_host; 45441514Sarchie snprintf(chost, sizeof(chost), "%x%x%x%x%x%x", 45526965Sjhay q[0], q[1], q[2], q[3], q[4], q[5]); 45626965Sjhay for (p = chost; *p == '0' && p < chost + 12; p++) 45726965Sjhay continue; 45826965Sjhay host = p; 45926965Sjhay } 46026965Sjhay 46126965Sjhay if (port) { 46226965Sjhay if (strcmp(host, "*") == 0) { 46326965Sjhay host = ""; 46441514Sarchie snprintf(cport, sizeof(cport), "%x", port); 46526965Sjhay } else 46641514Sarchie snprintf(cport, sizeof(cport), ".%x", port); 46726965Sjhay } else 46826965Sjhay *cport = 0; 46926965Sjhay 47026965Sjhay printf("%s.%s%s", net, host, cport); 47126965Sjhay} 472