153c9f6c0SAtsushi Murai /* 253c9f6c0SAtsushi Murai * sys-bsd.c - System-dependent procedures for setting up 353c9f6c0SAtsushi Murai * PPP interfaces on bsd-4.4-ish systems (including 386BSD, NetBSD, etc.) 453c9f6c0SAtsushi Murai * 553c9f6c0SAtsushi Murai * Copyright (c) 1989 Carnegie Mellon University. 653c9f6c0SAtsushi Murai * All rights reserved. 753c9f6c0SAtsushi Murai * 853c9f6c0SAtsushi Murai * Redistribution and use in source and binary forms are permitted 953c9f6c0SAtsushi Murai * provided that the above copyright notice and this paragraph are 1053c9f6c0SAtsushi Murai * duplicated in all such forms and that any documentation, 1153c9f6c0SAtsushi Murai * advertising materials, and other materials related to such 1253c9f6c0SAtsushi Murai * distribution and use acknowledge that the software was developed 1353c9f6c0SAtsushi Murai * by Carnegie Mellon University. The name of the 1453c9f6c0SAtsushi Murai * University may not be used to endorse or promote products derived 1553c9f6c0SAtsushi Murai * from this software without specific prior written permission. 1653c9f6c0SAtsushi Murai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1753c9f6c0SAtsushi Murai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1853c9f6c0SAtsushi Murai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1953c9f6c0SAtsushi Murai * 2099c02d39SWarner Losh * $Id: arp.c,v 1.6 1997/01/03 20:19:42 wollman Exp $ 2153c9f6c0SAtsushi Murai * 2253c9f6c0SAtsushi Murai */ 2353c9f6c0SAtsushi Murai 2453c9f6c0SAtsushi Murai /* 2553c9f6c0SAtsushi Murai * TODO: 2653c9f6c0SAtsushi Murai */ 2753c9f6c0SAtsushi Murai 2853c9f6c0SAtsushi Murai #include <sys/ioctl.h> 2953c9f6c0SAtsushi Murai #include <sys/types.h> 307b64106aSPoul-Henning Kamp #include <sys/uio.h> 3153c9f6c0SAtsushi Murai #include <sys/socket.h> 3253c9f6c0SAtsushi Murai #include <sys/time.h> 3353c9f6c0SAtsushi Murai #include <sys/errno.h> 347b64106aSPoul-Henning Kamp #include <unistd.h> 357b64106aSPoul-Henning Kamp #include <string.h> 3653c9f6c0SAtsushi Murai 3753c9f6c0SAtsushi Murai #include <net/if.h> 38702a1d01SGarrett Wollman #include <net/if_var.h> 3953c9f6c0SAtsushi Murai #include <net/route.h> 4053c9f6c0SAtsushi Murai #include <net/if_dl.h> 4153c9f6c0SAtsushi Murai #include <netinet/in.h> 4253c9f6c0SAtsushi Murai #include <stdio.h> 4353c9f6c0SAtsushi Murai #include <fcntl.h> 4453c9f6c0SAtsushi Murai #ifdef __bsdi__ 4553c9f6c0SAtsushi Murai #include <kvm.h> 4653c9f6c0SAtsushi Murai #endif 4753c9f6c0SAtsushi Murai #include <net/if_types.h> 4853c9f6c0SAtsushi Murai #include <netinet/in_var.h> 4953c9f6c0SAtsushi Murai #include <netinet/if_ether.h> 5053c9f6c0SAtsushi Murai #include "log.h" 5153c9f6c0SAtsushi Murai 5253c9f6c0SAtsushi Murai #if RTM_VERSION >= 3 5353c9f6c0SAtsushi Murai #include <netinet/if_ether.h> 5453c9f6c0SAtsushi Murai #endif 5553c9f6c0SAtsushi Murai 5653c9f6c0SAtsushi Murai static int rtm_seq; 5753c9f6c0SAtsushi Murai 58ed6a16c1SPoul-Henning Kamp static int get_ether_addr __P((int, u_long, struct sockaddr_dl *)); 59ed6a16c1SPoul-Henning Kamp 6053c9f6c0SAtsushi Murai #define BCOPY(s, d, l) memcpy(d, s, l) 6153c9f6c0SAtsushi Murai #define BZERO(s, n) memset(s, 0, n) 6253c9f6c0SAtsushi Murai /* 6353c9f6c0SAtsushi Murai * SET_SA_FAMILY - set the sa_family field of a struct sockaddr, 6453c9f6c0SAtsushi Murai * if it exists. 6553c9f6c0SAtsushi Murai */ 6653c9f6c0SAtsushi Murai #define SET_SA_FAMILY(addr, family) \ 6753c9f6c0SAtsushi Murai BZERO((char *) &(addr), sizeof(addr)); \ 6853c9f6c0SAtsushi Murai addr.sa_family = (family); \ 6953c9f6c0SAtsushi Murai addr.sa_len = sizeof(addr); 7053c9f6c0SAtsushi Murai 7153c9f6c0SAtsushi Murai 7253c9f6c0SAtsushi Murai #if RTM_VERSION >= 3 7353c9f6c0SAtsushi Murai 7453c9f6c0SAtsushi Murai /* 7553c9f6c0SAtsushi Murai * sifproxyarp - Make a proxy ARP entry for the peer. 7653c9f6c0SAtsushi Murai */ 7753c9f6c0SAtsushi Murai static struct { 7853c9f6c0SAtsushi Murai struct rt_msghdr hdr; 7953c9f6c0SAtsushi Murai struct sockaddr_inarp dst; 8053c9f6c0SAtsushi Murai struct sockaddr_dl hwa; 8153c9f6c0SAtsushi Murai char extra[128]; 8253c9f6c0SAtsushi Murai } arpmsg; 8353c9f6c0SAtsushi Murai 8453c9f6c0SAtsushi Murai static int arpmsg_valid; 8553c9f6c0SAtsushi Murai 8653c9f6c0SAtsushi Murai int 8753c9f6c0SAtsushi Murai sifproxyarp(unit, hisaddr) 8853c9f6c0SAtsushi Murai int unit; 8953c9f6c0SAtsushi Murai u_long hisaddr; 9053c9f6c0SAtsushi Murai { 9153c9f6c0SAtsushi Murai int routes; 9253c9f6c0SAtsushi Murai 9353c9f6c0SAtsushi Murai /* 9453c9f6c0SAtsushi Murai * Get the hardware address of an interface on the same subnet 9553c9f6c0SAtsushi Murai * as our local address. 9653c9f6c0SAtsushi Murai */ 9753c9f6c0SAtsushi Murai memset(&arpmsg, 0, sizeof(arpmsg)); 9853c9f6c0SAtsushi Murai if (!get_ether_addr(unit, hisaddr, &arpmsg.hwa)) { 9953c9f6c0SAtsushi Murai logprintf("Cannot determine ethernet address for proxy ARP\n"); 10053c9f6c0SAtsushi Murai return 0; 10153c9f6c0SAtsushi Murai } 10253c9f6c0SAtsushi Murai 10353c9f6c0SAtsushi Murai if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) { 10453c9f6c0SAtsushi Murai logprintf("sifproxyarp: opening routing socket: \n"); 10553c9f6c0SAtsushi Murai return 0; 10653c9f6c0SAtsushi Murai } 10753c9f6c0SAtsushi Murai 10853c9f6c0SAtsushi Murai arpmsg.hdr.rtm_type = RTM_ADD; 10953c9f6c0SAtsushi Murai arpmsg.hdr.rtm_flags = RTF_ANNOUNCE | RTF_HOST | RTF_STATIC; 11053c9f6c0SAtsushi Murai arpmsg.hdr.rtm_version = RTM_VERSION; 11153c9f6c0SAtsushi Murai arpmsg.hdr.rtm_seq = ++rtm_seq; 11253c9f6c0SAtsushi Murai arpmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY; 11353c9f6c0SAtsushi Murai arpmsg.hdr.rtm_inits = RTV_EXPIRE; 11453c9f6c0SAtsushi Murai arpmsg.dst.sin_len = sizeof(struct sockaddr_inarp); 11553c9f6c0SAtsushi Murai arpmsg.dst.sin_family = AF_INET; 11653c9f6c0SAtsushi Murai arpmsg.dst.sin_addr.s_addr = hisaddr; 11753c9f6c0SAtsushi Murai arpmsg.dst.sin_other = SIN_PROXY; 11853c9f6c0SAtsushi Murai 11953c9f6c0SAtsushi Murai arpmsg.hdr.rtm_msglen = (char *) &arpmsg.hwa - (char *) &arpmsg 12053c9f6c0SAtsushi Murai + arpmsg.hwa.sdl_len; 12153c9f6c0SAtsushi Murai if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) { 12253c9f6c0SAtsushi Murai logprintf("add proxy arp entry: \n"); 12353c9f6c0SAtsushi Murai close(routes); 12453c9f6c0SAtsushi Murai return 0; 12553c9f6c0SAtsushi Murai } 12653c9f6c0SAtsushi Murai 12753c9f6c0SAtsushi Murai close(routes); 12853c9f6c0SAtsushi Murai arpmsg_valid = 1; 12953c9f6c0SAtsushi Murai return 1; 13053c9f6c0SAtsushi Murai } 13153c9f6c0SAtsushi Murai 13253c9f6c0SAtsushi Murai /* 13353c9f6c0SAtsushi Murai * cifproxyarp - Delete the proxy ARP entry for the peer. 13453c9f6c0SAtsushi Murai */ 13553c9f6c0SAtsushi Murai int 13653c9f6c0SAtsushi Murai cifproxyarp(unit, hisaddr) 13753c9f6c0SAtsushi Murai int unit; 13853c9f6c0SAtsushi Murai u_long hisaddr; 13953c9f6c0SAtsushi Murai { 14053c9f6c0SAtsushi Murai int routes; 14153c9f6c0SAtsushi Murai 14253c9f6c0SAtsushi Murai if (!arpmsg_valid) 14353c9f6c0SAtsushi Murai return 0; 14453c9f6c0SAtsushi Murai arpmsg_valid = 0; 14553c9f6c0SAtsushi Murai 14653c9f6c0SAtsushi Murai arpmsg.hdr.rtm_type = RTM_DELETE; 14753c9f6c0SAtsushi Murai arpmsg.hdr.rtm_seq = ++rtm_seq; 14853c9f6c0SAtsushi Murai 14953c9f6c0SAtsushi Murai if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) { 15053c9f6c0SAtsushi Murai logprintf("sifproxyarp: opening routing socket: \n"); 15153c9f6c0SAtsushi Murai return 0; 15253c9f6c0SAtsushi Murai } 15353c9f6c0SAtsushi Murai 15453c9f6c0SAtsushi Murai if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) { 15553c9f6c0SAtsushi Murai logprintf("delete proxy arp entry: \n"); 15653c9f6c0SAtsushi Murai close(routes); 15753c9f6c0SAtsushi Murai return 0; 15853c9f6c0SAtsushi Murai } 15953c9f6c0SAtsushi Murai 16053c9f6c0SAtsushi Murai close(routes); 16153c9f6c0SAtsushi Murai return 1; 16253c9f6c0SAtsushi Murai } 16353c9f6c0SAtsushi Murai 16453c9f6c0SAtsushi Murai #else /* RTM_VERSION */ 16553c9f6c0SAtsushi Murai 16653c9f6c0SAtsushi Murai /* 16753c9f6c0SAtsushi Murai * sifproxyarp - Make a proxy ARP entry for the peer. 16853c9f6c0SAtsushi Murai */ 16953c9f6c0SAtsushi Murai int 17053c9f6c0SAtsushi Murai sifproxyarp(unit, hisaddr) 17153c9f6c0SAtsushi Murai int unit; 17253c9f6c0SAtsushi Murai u_long hisaddr; 17353c9f6c0SAtsushi Murai { 17453c9f6c0SAtsushi Murai struct arpreq arpreq; 17553c9f6c0SAtsushi Murai struct { 17653c9f6c0SAtsushi Murai struct sockaddr_dl sdl; 17753c9f6c0SAtsushi Murai char space[128]; 17853c9f6c0SAtsushi Murai } dls; 17953c9f6c0SAtsushi Murai 18053c9f6c0SAtsushi Murai BZERO(&arpreq, sizeof(arpreq)); 18153c9f6c0SAtsushi Murai 18253c9f6c0SAtsushi Murai /* 18353c9f6c0SAtsushi Murai * Get the hardware address of an interface on the same subnet 18453c9f6c0SAtsushi Murai * as our local address. 18553c9f6c0SAtsushi Murai */ 18653c9f6c0SAtsushi Murai if (!get_ether_addr(unit, hisaddr, &dls.sdl)) { 1879c749ffbSPoul-Henning Kamp LogPrintf(LOG_PHASE_BIT, "Cannot determine ethernet address for proxy ARP\n"); 18853c9f6c0SAtsushi Murai return 0; 18953c9f6c0SAtsushi Murai } 19053c9f6c0SAtsushi Murai 19153c9f6c0SAtsushi Murai arpreq.arp_ha.sa_len = sizeof(struct sockaddr); 19253c9f6c0SAtsushi Murai arpreq.arp_ha.sa_family = AF_UNSPEC; 19353c9f6c0SAtsushi Murai BCOPY(LLADDR(&dls.sdl), arpreq.arp_ha.sa_data, dls.sdl.sdl_alen); 19453c9f6c0SAtsushi Murai SET_SA_FAMILY(arpreq.arp_pa, AF_INET); 19553c9f6c0SAtsushi Murai ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr; 19653c9f6c0SAtsushi Murai arpreq.arp_flags = ATF_PERM | ATF_PUBL; 19753c9f6c0SAtsushi Murai if (ioctl(unit, SIOCSARP, (caddr_t)&arpreq) < 0) { 19853c9f6c0SAtsushi Murai fprintf(stderr, "ioctl(SIOCSARP): \n"); 19953c9f6c0SAtsushi Murai return 0; 20053c9f6c0SAtsushi Murai } 20153c9f6c0SAtsushi Murai 20253c9f6c0SAtsushi Murai return 1; 20353c9f6c0SAtsushi Murai } 20453c9f6c0SAtsushi Murai 20553c9f6c0SAtsushi Murai /* 20653c9f6c0SAtsushi Murai * cifproxyarp - Delete the proxy ARP entry for the peer. 20753c9f6c0SAtsushi Murai */ 20853c9f6c0SAtsushi Murai int 20953c9f6c0SAtsushi Murai cifproxyarp(unit, hisaddr) 21053c9f6c0SAtsushi Murai int unit; 21153c9f6c0SAtsushi Murai u_long hisaddr; 21253c9f6c0SAtsushi Murai { 21353c9f6c0SAtsushi Murai struct arpreq arpreq; 21453c9f6c0SAtsushi Murai 21553c9f6c0SAtsushi Murai BZERO(&arpreq, sizeof(arpreq)); 21653c9f6c0SAtsushi Murai SET_SA_FAMILY(arpreq.arp_pa, AF_INET); 21753c9f6c0SAtsushi Murai ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr; 21853c9f6c0SAtsushi Murai if (ioctl(unit, SIOCDARP, (caddr_t)&arpreq) < 0) { 21953c9f6c0SAtsushi Murai fprintf(stderr, "ioctl(SIOCDARP): \n"); 22053c9f6c0SAtsushi Murai return 0; 22153c9f6c0SAtsushi Murai } 22253c9f6c0SAtsushi Murai return 1; 22353c9f6c0SAtsushi Murai } 22453c9f6c0SAtsushi Murai #endif /* RTM_VERSION */ 22553c9f6c0SAtsushi Murai 22653c9f6c0SAtsushi Murai 22753c9f6c0SAtsushi Murai /* 22853c9f6c0SAtsushi Murai * get_ether_addr - get the hardware address of an interface on the 22953c9f6c0SAtsushi Murai * the same subnet as ipaddr. 23053c9f6c0SAtsushi Murai */ 23153c9f6c0SAtsushi Murai #define MAX_IFS 32 23253c9f6c0SAtsushi Murai 23353c9f6c0SAtsushi Murai int 23453c9f6c0SAtsushi Murai get_ether_addr(s, ipaddr, hwaddr) 23553c9f6c0SAtsushi Murai int s; 23653c9f6c0SAtsushi Murai u_long ipaddr; 23753c9f6c0SAtsushi Murai struct sockaddr_dl *hwaddr; 23853c9f6c0SAtsushi Murai { 23953c9f6c0SAtsushi Murai struct ifreq *ifr, *ifend, *ifp; 24053c9f6c0SAtsushi Murai u_long ina, mask; 24153c9f6c0SAtsushi Murai struct sockaddr_dl *dla; 24253c9f6c0SAtsushi Murai struct ifreq ifreq; 24353c9f6c0SAtsushi Murai struct ifconf ifc; 24453c9f6c0SAtsushi Murai struct ifreq ifs[MAX_IFS]; 24553c9f6c0SAtsushi Murai 24653c9f6c0SAtsushi Murai ifc.ifc_len = sizeof(ifs); 24753c9f6c0SAtsushi Murai ifc.ifc_req = ifs; 24853c9f6c0SAtsushi Murai if (ioctl(s, SIOCGIFCONF, &ifc) < 0) { 24953c9f6c0SAtsushi Murai fprintf(stderr, "ioctl(SIOCGIFCONF): \n"); 25053c9f6c0SAtsushi Murai return 0; 25153c9f6c0SAtsushi Murai } 25253c9f6c0SAtsushi Murai 25353c9f6c0SAtsushi Murai /* 25453c9f6c0SAtsushi Murai * Scan through looking for an interface with an Internet 25553c9f6c0SAtsushi Murai * address on the same subnet as `ipaddr'. 25653c9f6c0SAtsushi Murai */ 25753c9f6c0SAtsushi Murai ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); 25853c9f6c0SAtsushi Murai for (ifr = ifc.ifc_req; ifr < ifend; ) { 25953c9f6c0SAtsushi Murai if (ifr->ifr_addr.sa_family == AF_INET) { 26053c9f6c0SAtsushi Murai ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr; 26153c9f6c0SAtsushi Murai strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name)); 26299c02d39SWarner Losh ifreq.ifr_name[sizeof(ifreq.ifr_name)-1]='\0'; 26353c9f6c0SAtsushi Murai /* 26453c9f6c0SAtsushi Murai * Check that the interface is up, and not point-to-point 26553c9f6c0SAtsushi Murai * or loopback. 26653c9f6c0SAtsushi Murai */ 26753c9f6c0SAtsushi Murai if (ioctl(s, SIOCGIFFLAGS, &ifreq) < 0) 26853c9f6c0SAtsushi Murai continue; 26953c9f6c0SAtsushi Murai if ((ifreq.ifr_flags & 27053c9f6c0SAtsushi Murai (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP)) 27153c9f6c0SAtsushi Murai != (IFF_UP|IFF_BROADCAST)) 27253c9f6c0SAtsushi Murai goto nextif; 27353c9f6c0SAtsushi Murai /* 27453c9f6c0SAtsushi Murai * Get its netmask and check that it's on the right subnet. 27553c9f6c0SAtsushi Murai */ 27653c9f6c0SAtsushi Murai if (ioctl(s, SIOCGIFNETMASK, &ifreq) < 0) 27753c9f6c0SAtsushi Murai continue; 27853c9f6c0SAtsushi Murai mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr; 27953c9f6c0SAtsushi Murai if ((ipaddr & mask) != (ina & mask)) 28053c9f6c0SAtsushi Murai goto nextif; 28153c9f6c0SAtsushi Murai 28253c9f6c0SAtsushi Murai break; 28353c9f6c0SAtsushi Murai } 28453c9f6c0SAtsushi Murai nextif: 28553c9f6c0SAtsushi Murai ifr = (struct ifreq *) ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len); 28653c9f6c0SAtsushi Murai } 28753c9f6c0SAtsushi Murai 28853c9f6c0SAtsushi Murai if (ifr >= ifend) 28953c9f6c0SAtsushi Murai return 0; 2909c749ffbSPoul-Henning Kamp LogPrintf(LOG_PHASE_BIT, "found interface %s for proxy arp\n", ifr->ifr_name); 29153c9f6c0SAtsushi Murai 29253c9f6c0SAtsushi Murai /* 29353c9f6c0SAtsushi Murai * Now scan through again looking for a link-level address 29453c9f6c0SAtsushi Murai * for this interface. 29553c9f6c0SAtsushi Murai */ 29653c9f6c0SAtsushi Murai ifp = ifr; 29753c9f6c0SAtsushi Murai for (ifr = ifc.ifc_req; ifr < ifend; ) { 29853c9f6c0SAtsushi Murai if (strcmp(ifp->ifr_name, ifr->ifr_name) == 0 29953c9f6c0SAtsushi Murai && ifr->ifr_addr.sa_family == AF_LINK) { 30053c9f6c0SAtsushi Murai /* 30153c9f6c0SAtsushi Murai * Found the link-level address - copy it out 30253c9f6c0SAtsushi Murai */ 30353c9f6c0SAtsushi Murai dla = (struct sockaddr_dl *) &ifr->ifr_addr; 30453c9f6c0SAtsushi Murai #ifdef __bsdi__ 30553c9f6c0SAtsushi Murai if (dla->sdl_alen == 0) 30653c9f6c0SAtsushi Murai kmemgetether(ifr->ifr_name, dla); 30753c9f6c0SAtsushi Murai #endif 30853c9f6c0SAtsushi Murai BCOPY(dla, hwaddr, dla->sdl_len); 30953c9f6c0SAtsushi Murai return 1; 31053c9f6c0SAtsushi Murai } 31153c9f6c0SAtsushi Murai ifr = (struct ifreq *) ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len); 31253c9f6c0SAtsushi Murai } 31353c9f6c0SAtsushi Murai 31453c9f6c0SAtsushi Murai return 0; 31553c9f6c0SAtsushi Murai } 31653c9f6c0SAtsushi Murai 31753c9f6c0SAtsushi Murai #ifdef __bsdi__ 31853c9f6c0SAtsushi Murai #include <nlist.h> 31953c9f6c0SAtsushi Murai 32053c9f6c0SAtsushi Murai struct nlist nl[] = { 32153c9f6c0SAtsushi Murai #define N_IFNET 0 32253c9f6c0SAtsushi Murai { "_ifnet" }, 32353c9f6c0SAtsushi Murai "", 32453c9f6c0SAtsushi Murai }; 32553c9f6c0SAtsushi Murai 32653c9f6c0SAtsushi Murai 32753c9f6c0SAtsushi Murai kvm_t *kvmd; 32853c9f6c0SAtsushi Murai 32953c9f6c0SAtsushi Murai /* 33053c9f6c0SAtsushi Murai * Read kernel memory, return 0 on success. 33153c9f6c0SAtsushi Murai */ 33253c9f6c0SAtsushi Murai int 33353c9f6c0SAtsushi Murai kread(addr, buf, size) 33453c9f6c0SAtsushi Murai u_long addr; 33553c9f6c0SAtsushi Murai char *buf; 33653c9f6c0SAtsushi Murai int size; 33753c9f6c0SAtsushi Murai { 33853c9f6c0SAtsushi Murai 33953c9f6c0SAtsushi Murai if (kvm_read(kvmd, addr, buf, size) != size) { 34053c9f6c0SAtsushi Murai /* XXX this duplicates kvm_read's error printout */ 34153c9f6c0SAtsushi Murai (void)fprintf(stderr, "kvm_read %s\n", 34253c9f6c0SAtsushi Murai kvm_geterr(kvmd)); 34353c9f6c0SAtsushi Murai return (-1); 34453c9f6c0SAtsushi Murai } 34553c9f6c0SAtsushi Murai return (0); 34653c9f6c0SAtsushi Murai } 34753c9f6c0SAtsushi Murai 34853c9f6c0SAtsushi Murai kmemgetether(ifname, dlo) 34953c9f6c0SAtsushi Murai char *ifname; 35053c9f6c0SAtsushi Murai struct sockaddr_dl *dlo; 35153c9f6c0SAtsushi Murai { 35253c9f6c0SAtsushi Murai struct ifnet ifnet; 35353c9f6c0SAtsushi Murai int n; 35453c9f6c0SAtsushi Murai u_long addr, ifaddraddr, ifnetfound, ifaddrfound; 35599c02d39SWarner Losh char name[16+32]; 35653c9f6c0SAtsushi Murai struct sockaddr *sa; 35753c9f6c0SAtsushi Murai char *cp; 35853c9f6c0SAtsushi Murai struct sockaddr_dl *sdl; 35953c9f6c0SAtsushi Murai union { 36053c9f6c0SAtsushi Murai struct ifaddr ifa; 36153c9f6c0SAtsushi Murai struct in_ifaddr in; 36253c9f6c0SAtsushi Murai } ifaddr; 36353c9f6c0SAtsushi Murai struct arpcom ac; 36453c9f6c0SAtsushi Murai 36553c9f6c0SAtsushi Murai kvmd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL); 36653c9f6c0SAtsushi Murai if (kvmd) { 36753c9f6c0SAtsushi Murai n = kvm_nlist(kvmd, nl); 36853c9f6c0SAtsushi Murai if (n >= 0) { 36953c9f6c0SAtsushi Murai addr = nl[N_IFNET].n_value; 37053c9f6c0SAtsushi Murai kread(addr, (char *)&addr, sizeof(addr)); 37153c9f6c0SAtsushi Murai ifaddraddr = ifnetfound = 0; 37253c9f6c0SAtsushi Murai while (addr || ifaddraddr) { 37353c9f6c0SAtsushi Murai ifnetfound = addr; 37453c9f6c0SAtsushi Murai if (ifaddraddr == 0) { 37553c9f6c0SAtsushi Murai if (kread(addr, (char *)&ifnet, sizeof(ifnet)) || 37653c9f6c0SAtsushi Murai kread((u_long)ifnet.if_name, name, 16)) 37753c9f6c0SAtsushi Murai return; 37853c9f6c0SAtsushi Murai name[15] = 0; 37953c9f6c0SAtsushi Murai addr = (u_long) ifnet.if_next; 38053c9f6c0SAtsushi Murai cp = (char *)index(name, '\0'); 38153c9f6c0SAtsushi Murai cp += sprintf(cp, "%d", ifnet.if_unit); 38253c9f6c0SAtsushi Murai *cp = '\0'; 38353c9f6c0SAtsushi Murai ifaddraddr = (u_long)ifnet.if_addrlist; 38453c9f6c0SAtsushi Murai } 38553c9f6c0SAtsushi Murai ifaddrfound = ifaddraddr; 38653c9f6c0SAtsushi Murai if (ifaddraddr) { 38753c9f6c0SAtsushi Murai if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) { 38853c9f6c0SAtsushi Murai ifaddraddr = 0; 38953c9f6c0SAtsushi Murai continue; 39053c9f6c0SAtsushi Murai } 39153c9f6c0SAtsushi Murai #define CP(x) ((char *)(x)) 39253c9f6c0SAtsushi Murai cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) + CP(&ifaddr); 39353c9f6c0SAtsushi Murai sa = (struct sockaddr *)cp; 39453c9f6c0SAtsushi Murai if (sa->sa_family == AF_LINK && strcmp(ifname, name) == 0) { 39553c9f6c0SAtsushi Murai sdl = (struct sockaddr_dl *)sa; 39653c9f6c0SAtsushi Murai cp = (char *)LLADDR(sdl); 39753c9f6c0SAtsushi Murai n = sdl->sdl_alen; 39853c9f6c0SAtsushi Murai if (ifnet.if_type == IFT_ETHER) { 39953c9f6c0SAtsushi Murai if (n == 0) { 40053c9f6c0SAtsushi Murai kread(ifnetfound, (char *)&ac, sizeof(ac)); 40153c9f6c0SAtsushi Murai cp = (char *)LLADDR(sdl); 40253c9f6c0SAtsushi Murai bcopy((char *)ac.ac_enaddr, cp, 6); 40353c9f6c0SAtsushi Murai sdl->sdl_alen = 6; 40453c9f6c0SAtsushi Murai } 40553c9f6c0SAtsushi Murai bcopy(sdl, dlo, sizeof(*sdl)); 40653c9f6c0SAtsushi Murai return; 40753c9f6c0SAtsushi Murai } 40853c9f6c0SAtsushi Murai } 40953c9f6c0SAtsushi Murai ifaddraddr = (u_long)ifaddr.ifa.ifa_next; 41053c9f6c0SAtsushi Murai } 41153c9f6c0SAtsushi Murai } 41253c9f6c0SAtsushi Murai } 41353c9f6c0SAtsushi Murai } 41453c9f6c0SAtsushi Murai } 41553c9f6c0SAtsushi Murai #endif 41653c9f6c0SAtsushi Murai 41753c9f6c0SAtsushi Murai #ifdef DEBUG 41853c9f6c0SAtsushi Murai main() 41953c9f6c0SAtsushi Murai { 42053c9f6c0SAtsushi Murai u_long ipaddr; 42153c9f6c0SAtsushi Murai int s; 42253c9f6c0SAtsushi Murai 42353c9f6c0SAtsushi Murai s = socket(AF_INET, SOCK_DGRAM, 0); 42453c9f6c0SAtsushi Murai ipaddr = inet_addr("192.168.1.32"); 42553c9f6c0SAtsushi Murai sifproxyarp(s, ipaddr); 42653c9f6c0SAtsushi Murai close(s); 42753c9f6c0SAtsushi Murai } 42853c9f6c0SAtsushi Murai #endif 429