pcap(bpf) packet injection not-acceptable on FreeBSD host.

Norikatsu Shigemura nork at FreeBSD.org
Sun Jul 5 05:53:28 UTC 2009


Hi.

	I have a trouble that an application packet-injecting by pcap(bpf)'s
	pcap_sendpacket function doesn't communicate to FreeBSD host, but
	can communicate to other machine.  So I researched, and I noticed
	that sys/net/if_ethersubr.c has a structured issue(?)(I didn't know).
	Do you have any idea?


	I made a test program (attached file, fake-arp-reply.c).  Do 'gcc
	fake-arp-reply -lpcap'.  I tested 2 case (8-current self,
	8-current -> 7-stable):

test platform (I tested on 8-current, 7.2-stable)
on 8-current:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
$ ifconfig rl0
rl0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=8<VLAN_MTU>
        ether 00:0b:97:33:1c:30
        inet 192.168.36.6 netmask 0xffffff00 broadcast 192.168.36.255
        media: Ethernet autoselect (100baseTX <full-duplex>)
        status: active
$ arp -an
? (192.168.36.6) at 00:0b:97:33:1c:30 on rl0 permanent [ethernet]
? (192.168.36.1) at 00:1b:78:37:f1:cf on rl0 [ethernet]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

on 7-stable:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
$ ifconfig bge0
bge0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=98<VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM>
        ether 00:1b:78:37:f1:cf
        inet 192.168.36.1 netmask 0xffffff00 broadcast 192.168.36.255
        inet6 fe80::21b:78ff:fe37:f1cf%bge0 prefixlen 64 scopeid 0x1 
        media: Ethernet autoselect (1000baseTX <full-duplex>)
        status: active
$ arp -an
? (192.168.36.1) at 00:1b:78:37:f1:cf on bge0 permanent [ethernet]
? (192.168.36.6) at 00:0b:97:33:1c:30 on bge0 [ethernet]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

TEST 1: 8-current self (same 7-stable self, too)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# ./a.out -d rl0 -i 192.168.36.64 -m 10-20-30-40-50-60
rl0, 192.168.36.64 10:20:30:40:50:60
(on other console, ping 192.168.36.64)
arp request catched, arp replyed and done.
# arp -an
? (192.168.36.6) at 00:0b:97:33:1c:30 on rl0 permanent [ethernet]
? (192.168.36.1) at 00:1b:78:37:f1:cf on rl0 [ethernet]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

TEST 2: 8-current -> 7-stable(same 8-current -> 7-stable, too)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# ./a.out -d rl0 -i 192.168.36.64 -m 10-20-30-40-50-60
rl0, 192.168.36.64 10:20:30:40:50:60
 (on other machine's console, ping 192.168.36.64...)
arp request catched, arp replyed and done.

On other machine:
$ ping 192.168.36.64
PING 192.168.36.64 (192.168.36.64): 56 data bytes
^C
--- 192.168.36.64 ping statistics ---
2 packets transmitted, 0 packets received, 100.0% packet loss
$ arp -an
? (192.168.36.1) at 00:1b:78:37:f1:cf on bge0 permanent [ethernet]
? (192.168.36.6) at 00:0b:97:33:1c:30 on bge0 [ethernet]
? (192.168.36.64) at 10:20:30:40:50:60 on bge0 [ethernet]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-------------- next part --------------
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <pcap.h>

struct sendpkt {
	u_char	dmac[6];
	u_char	smac[6];
	u_char	etype[2];
	u_char	htype[2];
	u_char	ptype[2];
	u_char	hlen[1];
	u_char	plen[1];
	u_char	op[2];
	u_char	src_mac[6];
	u_char	src_ipv4[4];
	u_char	dst_mac[6];
	u_char	dst_ipv4[4];
	u_char	trailer[18];
} __packed;

struct sendpkt sendpkt = {
	{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }, /* overwrite live packet */
	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, /* overwrite argument */
	{ 0x08, 0x06, },			 /* constant */
	{ 0x00, 0x01, },			 /* constant */
	{ 0x08, 0x00, },			 /* constant */
	{ 0x06, },				 /* constant */
	{ 0x04, },				 /* constant */
	{ 0x00, 0x02, },			 /* constant */
	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, /* overwrite live packet */
	{ 0x00, 0x00, 0x00, 0x00, },		 /* overwrite live packet */
	{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }, /* overwrite argument */
	{ 0xff, 0xff, 0xff, 0xff, },		 /* overwrite argument */
	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	 /* constant */
	  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
};

int
main(int argc, char *argv[])
{
	int	ch;
	u_char	dev[30] = "lo0",
		mac[6]  = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, },
		ipv4[4] = { 0, 0, 0, 0, };
	pcap_t	*p;
	static char errbuf[PCAP_ERRBUF_SIZE];

	while(  (ch = getopt(argc, argv, "d:i:m:")) != -1  )  {
		switch (ch)  {
		case 'd':
			strlcpy(dev, optarg, sizeof(dev));
			break;
		case 'i':
			sscanf(optarg, "%hhd%*[.]%hhd%*[.]%hhd%*[.]%hhd",
				&ipv4[0], &ipv4[1], &ipv4[2], &ipv4[3]);
			break;
		case 'm':
			sscanf(optarg, "%hhx%*[:.-]%hhx%*[:.-]%hhx%*[:.-]%hhx%*[:.-]%hhx%*[:.-]%hhx",
				&mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
			break;
		default:
			fprintf(stderr, "-d Device Name -i IPv4 Address -m MAC Addresss\n");
			exit(0);
			/* NOT REACHABLE */
		}
	}

	printf("%s, %d.%d.%d.%d %02x:%02x:%02x:%02x:%02x:%02x\n",
		dev,
		ipv4[0], ipv4[1], ipv4[2], ipv4[3],
		mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);

	memcpy(&sendpkt.smac,     mac,  sizeof(sendpkt.smac));
	memcpy(&sendpkt.src_mac,  mac,  sizeof(sendpkt.src_mac));
	memcpy(&sendpkt.src_ipv4, ipv4, sizeof(sendpkt.src_ipv4));

	if(  (p = pcap_open_live(dev, 1500/*bytes*/, 1/*TRUE*/, 10/*msec*/, errbuf))  )  {
		int in_loop = 1;
		while(  in_loop  )  {
			struct pcap_pkthdr pkt_info;
			u_char *recvpkt;
			if(  (recvpkt = (u_char *)pcap_next(p, &pkt_info))  )  {
				if(  recvpkt[12] == 0x08    && recvpkt[13] == 0x06
				&&   recvpkt[20] == 0x00    && recvpkt[21] == 0x01
				&&   recvpkt[38] == ipv4[0] && recvpkt[39] == ipv4[1]
				&&   recvpkt[40] == ipv4[2] && recvpkt[41] == ipv4[3]  )  {
					memcpy(sendpkt.dmac,     &recvpkt[6],  sizeof(sendpkt.dmac));
					memcpy(sendpkt.dst_mac,  &recvpkt[22], sizeof(sendpkt.dst_mac));
					memcpy(sendpkt.dst_ipv4, &recvpkt[28], sizeof(sendpkt.dst_ipv4));
					pcap_sendpacket(p, (u_char *)&sendpkt, sizeof(sendpkt));
					printf("arp request catched, arp replyed and done.\n");
					in_loop = 0;
				}  else  {
					printf("len=%d           \r", pkt_info.caplen);
					if(  recvpkt[12] == 0x08    && recvpkt[13] == 0x06
					&&   recvpkt[20] == 0x00    && recvpkt[21] == 0x01  )  {
						printf("arp? recv=%d.%d.%d.%d / argv=%d.%d.%d.%d\n",
							recvpkt[38], recvpkt[39], recvpkt[40], recvpkt[41],
							ipv4[0], ipv4[1], ipv4[2], ipv4[3]);
					}
					fflush(stdout);
				}
			}
			usleep(100);
		}

		pcap_close(p);
	}  else  {
		fprintf(stderr, "pcap_open_live: error '%s'\n", errbuf);
	}

	return 0;
}


More information about the freebsd-net mailing list