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