152153Sbp/* 252153Sbp * Copyright (c) 1999, Boris Popov 352153Sbp * All rights reserved. 452153Sbp * 552153Sbp * Redistribution and use in source and binary forms, with or without 652153Sbp * modification, are permitted provided that the following conditions 752153Sbp * are met: 852153Sbp * 1. Redistributions of source code must retain the above copyright 952153Sbp * notice, this list of conditions and the following disclaimer. 1052153Sbp * 2. Redistributions in binary form must reproduce the above copyright 1152153Sbp * notice, this list of conditions and the following disclaimer in the 1252153Sbp * documentation and/or other materials provided with the distribution. 13165920Simp * 3. Neither the name of the author nor the names of any co-contributors 1452153Sbp * may be used to endorse or promote products derived from this software 1552153Sbp * without specific prior written permission. 1652153Sbp * 1752153Sbp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1852153Sbp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1952153Sbp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2052153Sbp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2152153Sbp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2252153Sbp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2352153Sbp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2452153Sbp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2552153Sbp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2652153Sbp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2752153Sbp * SUCH DAMAGE. 2852153Sbp */ 2984213Sdillon 3084213Sdillon#include <sys/cdefs.h> 3184213Sdillon__FBSDID("$FreeBSD$"); 3284213Sdillon 3352153Sbp#include <sys/param.h> 3452153Sbp#include <sys/ioctl.h> 3552153Sbp#include <sys/socket.h> 3652153Sbp#include <sys/sysctl.h> 3752153Sbp#include <sys/time.h> 3852153Sbp 3990868Smike#include <arpa/inet.h> 4052153Sbp#include <net/if.h> 4152153Sbp#include <net/if_var.h> 4252153Sbp#include <net/if_dl.h> 4352153Sbp#include <net/if_types.h> 4452153Sbp#include <net/route.h> 4552153Sbp 4652153Sbp/* IPX */ 4752153Sbp#include <netipx/ipx.h> 4852153Sbp#include <netipx/ipx_if.h> 4952153Sbp 5052153Sbp#include <ctype.h> 5152153Sbp#include <err.h> 5252153Sbp#include <errno.h> 5352153Sbp#include <fcntl.h> 5452153Sbp#include <stdio.h> 5552153Sbp#include <stdlib.h> 5652153Sbp#include <string.h> 5752153Sbp#include <unistd.h> 5852153Sbp 5952153Sbp#include <netncp/ncp_lib.h> 6052153Sbp 6152153Sbp#define IPX_NODE_LEN 6 6252153Sbp 6352153Sbptypedef u_long IPXNet; 6452153Sbptypedef u_short IPXPort; 6552153Sbptypedef union ipx_host IPXNode; 6652153Sbp 6752153Sbp 6852153Sbpvoid 6952153Sbpipx_fprint_node(FILE * file, IPXNode node){ 7052153Sbp fprintf(file, "%02X%02X%02X%02X%02X%02X", 7152153Sbp (unsigned char) node.c_host[0], 7252153Sbp (unsigned char) node.c_host[1], 7352153Sbp (unsigned char) node.c_host[2], 7452153Sbp (unsigned char) node.c_host[3], 7552153Sbp (unsigned char) node.c_host[4], 7652153Sbp (unsigned char) node.c_host[5] 7752153Sbp ); 7852153Sbp} 7952153Sbp 8052153Sbpvoid 8152153Sbpipx_fprint_network(FILE * file, const IPXNet net){ 8252153Sbp fprintf(file, "%08X", (u_int32_t)ntohl(net)); 8352153Sbp} 8452153Sbp 8552153Sbpvoid 8652153Sbpipx_fprint_port(FILE * file, IPXPort port) 8752153Sbp{ 8852153Sbp fprintf(file, "%04X", ntohs(port)); 8952153Sbp} 9052153Sbp 9152153Sbpvoid 9252153Sbpipx_fprint_addr(FILE * file, struct ipx_addr *ipx) 9352153Sbp{ 9452153Sbp ipx_fprint_network(file, ipx_netlong(*ipx)); 9552153Sbp fprintf(file, ":"); 9652153Sbp ipx_fprint_node(file, ipx->x_host); 9752153Sbp fprintf(file, ":"); 9852153Sbp ipx_fprint_port(file, ipx->x_port); 9952153Sbp} 10052153Sbp 10152153Sbpvoid 10252153Sbpipx_print_node(IPXNode node) 10352153Sbp{ 10452153Sbp ipx_fprint_node(stdout, node); 10552153Sbp} 10652153Sbp 10752153Sbpvoid 10852153Sbpipx_print_network(IPXNet net) 10952153Sbp{ 11052153Sbp ipx_fprint_network(stdout, net); 11152153Sbp} 11252153Sbp 11352153Sbpvoid 11452153Sbpipx_print_port(IPXPort port) 11552153Sbp{ 11652153Sbp ipx_fprint_port(stdout, port); 11752153Sbp} 11852153Sbp 11952153Sbpvoid 12052153Sbpipx_print_addr(struct ipx_addr *ipx) 12152153Sbp{ 12252153Sbp ipx_fprint_addr(stdout, ipx); 12352153Sbp} 12452153Sbp 12552153Sbpint 12652153Sbpipx_sscanf_node(char *buf, unsigned char node[6]) 12752153Sbp{ 12852153Sbp int i; 12952153Sbp int n[6]; 13052153Sbp 13152153Sbp if ((i = sscanf(buf, "%2x%2x%2x%2x%2x%2x", 13252153Sbp &(n[0]), &(n[1]), &(n[2]), 13352153Sbp &(n[3]), &(n[4]), &(n[5]))) != 6) 13452153Sbp { 13552153Sbp return i; 13652153Sbp } 13752153Sbp for (i = 0; i < 6; i++) 13852153Sbp { 13952153Sbp node[i] = n[i]; 14052153Sbp } 14152153Sbp return 6; 14252153Sbp} 14352153Sbp 14452153Sbpint 14552153Sbpipx_sscanf_saddr(char *buf, struct sockaddr_ipx *target) 14652153Sbp{ 14752153Sbp char *p; 14852153Sbp struct sockaddr_ipx addr; 14952153Sbp unsigned long sipx_net; 15052153Sbp 15152153Sbp addr.sipx_family = AF_IPX; 15252153Sbp/*!! addr.sipx_type = NCP_PTYPE;*/ 15352153Sbp 15452153Sbp if (sscanf(buf, "%lx", &sipx_net) != 1) 15552153Sbp { 15652153Sbp return 1; 15752153Sbp } 15852153Sbp ((union ipx_net_u*)(&addr.sipx_addr.x_net))->long_e = htonl(sipx_net); 15952153Sbp if ((p = strchr(buf, ':')) == NULL){ 16052153Sbp return 1; 16152153Sbp } 16252153Sbp p += 1; 16352153Sbp if (ipx_sscanf_node(p, addr.sipx_node) != 6) 16452153Sbp { 16552153Sbp return 1; 16652153Sbp } 16752153Sbp if ((p = strchr(p, ':')) == NULL) 16852153Sbp { 16952153Sbp return 1; 17052153Sbp } 17152153Sbp p += 1; 17252153Sbp if (sscanf(p, "%hx", &addr.sipx_port) != 1) 17352153Sbp { 17452153Sbp return 1; 17552153Sbp } 17652153Sbp addr.sipx_port = htons(addr.sipx_port); 17752153Sbp *target = addr; 17852153Sbp return 0; 17952153Sbp} 18052153Sbp 18152153Sbp 18252153Sbpvoid ipx_assign_node(IPXNode *dest, IPXNode *src) { 18352153Sbp memcpy(dest, src, IPX_NODE_LEN); 18452153Sbp} 18552153Sbp 18652153Sbp 18792917Sobrienstatic void rt_xaddrs(caddr_t, caddr_t, struct rt_addrinfo *); 18892941Sobrienstatic int if_ipxscan(int addrcount, struct sockaddr_dl *sdl, 18992941Sobrien struct if_msghdr *ifm, struct ifa_msghdr *ifam, 19092941Sobrien struct ipx_addr *addr); 19152153Sbp 19252153Sbp/* 19352153Sbp * Find an IPX interface. 19452153Sbp * ifname specifies interface name, if NULL search for all interfaces 19552153Sbp * if ifname[0]='0', also all interfaces, but return its name 19652153Sbp * addr on input preferred net address can be specified or 0 for any, 19752153Sbp * on return contains full address (except port) 19852153Sbp * returns 0 if interface was found 19952153Sbp */ 20052153Sbpint 20152153Sbpipx_iffind(char *ifname,struct ipx_addr *addr){ 20252153Sbp char name[32]; 20352153Sbp int all=0, flags, foundit = 0, addrcount; 20452153Sbp struct if_msghdr *ifm, *nextifm; 20552153Sbp struct ifa_msghdr *ifam; 20652153Sbp struct sockaddr_dl *sdl; 20752153Sbp char *buf, *lim, *next; 20852153Sbp size_t needed; 20952153Sbp int mib[6]; 21052153Sbp 21152153Sbp if( ifname!=NULL ) { 21252153Sbp strncpy(name,ifname,sizeof(name)-1); 21352153Sbp if( name[0]==0 ) 21452153Sbp all=1; 21552153Sbp } else 21652153Sbp all = 1; 21752153Sbp 21852153Sbp mib[0] = CTL_NET; 21952153Sbp mib[1] = PF_ROUTE; 22052153Sbp mib[2] = 0; 22152153Sbp mib[3] = AF_IPX; 22252153Sbp mib[4] = NET_RT_IFLIST; 22352153Sbp mib[5] = 0; 22452153Sbp 22552153Sbp if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) 22652153Sbp return(1); 22752153Sbp if ((buf = malloc(needed)) == NULL) 22852153Sbp return(1); 22952153Sbp if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { 23052153Sbp free(buf); 23152153Sbp return(1); 23252153Sbp } 23352153Sbp lim = buf + needed; 23452153Sbp 23552153Sbp next = buf; 23652153Sbp while (next < lim) { 23752153Sbp ifm = (struct if_msghdr *)next; 23852153Sbp if (ifm->ifm_type == RTM_IFINFO) { 23952153Sbp sdl = (struct sockaddr_dl *)(ifm + 1); 24052153Sbp flags = ifm->ifm_flags; 24152153Sbp } else { 24252153Sbp fprintf(stderr, "if_ipxfind: out of sync parsing NET_RT_IFLIST\n"); 24352153Sbp fprintf(stderr, "expected %d, got %d\n", RTM_IFINFO, ifm->ifm_type); 24452153Sbp fprintf(stderr, "msglen = %d\n", ifm->ifm_msglen); 24552153Sbp fprintf(stderr, "buf:%p, next:%p, lim:%p\n", buf, next, lim); 24652153Sbp free(buf); 24752153Sbp return(1); 24852153Sbp } 24952153Sbp 25052153Sbp next += ifm->ifm_msglen; 25152153Sbp ifam = NULL; 25252153Sbp addrcount = 0; 25352153Sbp while (next < lim) { 25452153Sbp nextifm = (struct if_msghdr *)next; 25552153Sbp if (nextifm->ifm_type != RTM_NEWADDR) 25652153Sbp break; 25752153Sbp if (ifam == NULL) 25852153Sbp ifam = (struct ifa_msghdr *)nextifm; 25952153Sbp addrcount++; 26052153Sbp next += nextifm->ifm_msglen; 26152153Sbp } 26252153Sbp 26352153Sbp if (all) { 26452153Sbp if ((flags & IFF_UP) == 0) 26552153Sbp continue; /* not up */ 26652153Sbp strncpy(name, sdl->sdl_data, sdl->sdl_nlen); 26752153Sbp name[sdl->sdl_nlen] = '\0'; 26852153Sbp } else { 26952153Sbp if (strlen(name) != sdl->sdl_nlen) 27052153Sbp continue; /* not same len */ 27152153Sbp if (strncmp(name, sdl->sdl_data, sdl->sdl_nlen) != 0) 27252153Sbp continue; /* not same name */ 27352153Sbp } 27452153Sbp 27552153Sbp foundit=if_ipxscan(addrcount, sdl, ifm, ifam, addr); 27652153Sbp if( foundit ) { 27752153Sbp if( ifname!=NULL && ifname[0]==0) { 27852153Sbp strncpy(ifname,sdl->sdl_data, sdl->sdl_nlen); 27952153Sbp ifname[sdl->sdl_nlen]=0; 28052153Sbp } 28152153Sbp break; 28252153Sbp } 28352153Sbp } 28452153Sbp free(buf); 28552153Sbp 28652153Sbp return foundit ? 0:1; 28752153Sbp} 28852153Sbp 28952153Sbp 29052153Sbpint 29152153Sbpif_ipxscan(addrcount, sdl, ifm, ifam, addr) 29252153Sbp int addrcount; 29352153Sbp struct sockaddr_dl *sdl; 29452153Sbp struct if_msghdr *ifm; 29552153Sbp struct ifa_msghdr *ifam; 29652153Sbp struct ipx_addr *addr; 29752153Sbp{ 29852153Sbp struct rt_addrinfo info; 29952153Sbp struct sockaddr_ipx *sipx; 30052153Sbp int s; 30152153Sbp 30252153Sbp if ((s = socket(AF_IPX, SOCK_DGRAM, 0)) < 0) { 30352153Sbp perror("ifconfig: socket"); 30452153Sbp return 0; 30552153Sbp } 30652153Sbp 30752153Sbp while (addrcount > 0) { 30852153Sbp info.rti_addrs = ifam->ifam_addrs; 30952153Sbp /* Expand the compacted addresses */ 31052153Sbp rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam, &info); 31152153Sbp addrcount--; 31252153Sbp ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen); 31352153Sbp if (info.rti_info[RTAX_IFA]->sa_family == AF_IPX) { 31452153Sbp sipx = (struct sockaddr_ipx *)info.rti_info[RTAX_IFA]; 31552153Sbp if( ipx_nullnet(sipx->sipx_addr) ) continue; 31652153Sbp if( ipx_nullnet(*addr) || 31752153Sbp ipx_neteq(sipx->sipx_addr,*addr) ) { 31852153Sbp *addr=sipx->sipx_addr; 31952153Sbp close(s); 32052153Sbp return(1); 32152153Sbp } 32252153Sbp } 32352153Sbp } 32452153Sbp close(s); 32552153Sbp return(0); 32652153Sbp} 32752153Sbp/* 32852153Sbp * Expand the compacted form of addresses as returned via the 32952153Sbp * configuration read via sysctl(). 33052153Sbp */ 33152153Sbp 33252153Sbp#define ROUNDUP(a) \ 33352153Sbp ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 33452153Sbp#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 33552153Sbp 33652153Sbpstatic void 33752153Sbprt_xaddrs(cp, cplim, rtinfo) 33852153Sbp caddr_t cp, cplim; 33952153Sbp struct rt_addrinfo *rtinfo; 34052153Sbp{ 34152153Sbp struct sockaddr *sa; 34252153Sbp int i; 34352153Sbp 34452153Sbp memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info)); 34552153Sbp for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { 34652153Sbp if ((rtinfo->rti_addrs & (1 << i)) == 0) 34752153Sbp continue; 34852153Sbp rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; 34952153Sbp ADVANCE(cp, sa); 35052153Sbp } 35152153Sbp} 35252153Sbp 353