xref: /freebsd/usr.sbin/ppp/arp.c (revision 99c02d39bc884ca9fc4940c9790934602ce19355)
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