I'm looking at the ARP packages in my network and have come over a request that I can't classify. Here is the content of Ethernet Header and ARP that I have problem with.
Ethernet Header
|-Source Address : b8:ae:ed:7f:9c:3b
|-Destination Address : f4:4d:30:6b:c7:e7
|-Protocol : 806
Ether_ARP
Sender: 192.168.1.37 b8:ae:ed:7f:9c:3b
Target: 192.168.1.76 f4:4d:30:6b:c7:e7
Format of hardware address. = 0x0001
Format of protocol address. = 0x0800
Length of hardware address. = 0x06
Length of protocol address. = 0x04
ARP opcode (command) = 0x0001
With the opcode = 1 I only know of ARP Request, Probe and Announce and all of these use boadcast MAC address in the destination address.
Appreciate if someone can explain to me what I'm seeing.
Thanks!
I think the answer you're looking for is in section 2.3.2.1 of RFC1122 which talks about refreshing the ARP cache for known hosts using a Unicast Poll. Pretty sure this is what you're seeing. ARP is normally 'taught' without mentioning unicast requests because the original intent for the protocol (RFC826) was as a mechanism for discovery using broadcast requests. These days the vast majority of ARP traffic on a network is RFC1122 style cache updates using unicast requests. Very confusing when you're expecting to only see broadcasts.
Related
I'm programming an offline packets decoding program in C under Windows 7 x86.
I wonder how it is possible to know packet protocol, either if it is UDP or TCP?
You can know by checking the IP packet header, there is a Protocol field in the packet header that is used to indicate the type of the packet according to its value :
1 is ICMP
6 is TCP
17 is UDP
and so on. More information on this is available on Wikipedia
Edit: Here's the list of all the possible values for that field.
P.S:
I'm assuming IPv4 here, I don't know if things are the same with IPv6
The protocol is available in the IP header. Read more here
I'm building an embedded system for a camera controller in Linux (not real-time). I'm having a problem getting the networking to do what I want it to do. The system has 3 NICs, 1 100base-T and 2 gigabit ports. I hook the slower one up to the camera (that's all it supports) and the faster ones are point-to-point connections to other machines. What I am attempting to do is get an image from the camera, do a little processing, then broadcast it using UDP to each of the other NICs.
Here is my network configuration:
eth0: addr: 192.168.1.200 Bcast 192.168.1.255 Mask: 255.255.255.0 (this is the 100base-t)
eth1: addr: 192.168.2.100 Bcast 192.168.2.255 Mask: 255.255.255.0
eth2: addr: 192.168.3.100 Bcast 192.168.3.255 Mask: 255.255.255.0
The image is coming in off eth0 in a proprietary protocol, so it's a raw socket. I can broadcast it to eth1 or eth2 just fine. But when I try to broadcast it to both, one after the other, I get lots of network hiccups and errors on eth0.
I initialize the UDP sockets like this:
sock2=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); // Or sock3
sa.sin_family=AF_INET;
sa.sin_port=htons(8000);
inet_aton("192.168.2.255",&sa.sin_addr); // Or 192.168.3.255
setsockopt(sock2, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast));
bind(sock2,(sockaddr*)&sa,sizeof(sa));
sendto(sock2,&data,sizeof(data),0,(sockaddr*)&sa,sizeof(sa)); // sizeof(data)<1100 bytes
I do this for each socket separately, and call sendto separately. When I do one or the other, it's fine. When I try to send on both, eth0 starts getting bad packets.
Any ideas on why this is happening? Is it a configuration error, is there a better way to do this?
EDIT:
Thanks for all the help, I've been trying some things and looking into this more. The issue does not appear to be broadcasting, strictly speaking. I replaced the broadcast code with a unicast command and it has the same behavior. I think I understand the behavior better, but not how to fix it.
Here is what is happening. On eth0 I am supposed to get an image every 50ms. When I send out an image on eth1 (or 2) it takes about 1.5ms to send the image. When I try to send on both eth1 and eth2 at the same time it takes about 45ms, occasionally jumping to 90ms. When this goes beyond the 50ms window, eth0's buffer starts to build. I lose packets when the buffer gets full, of course.
So my revised question. Why would it go from 1.5ms to 45ms just by going from one ethernet port to two?
Here is my initialization code:
sock[i]=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
sa[i].sin_family=AF_INET;
sa[i].sin_port=htons(8000);
inet_aton(ip,&sa[i].sin_addr);
//If Broadcasting
char buffer[]="eth1" // or eth2
setsockopt(sock[i],SOL_SOCKET,SO_BINDTODEVICE,buffer,5);
int b=1;
setsockopt(sock[i],SOL_SOCKET,SO_BROADCAST,&b,sizeof(b));
Here is my sending code:
for(i=0;i<65;i++) {
sendto(sock[0],&data[i],sizeof(data),0,sa[0],sizeof(sa[0]));
sendto(sock[1],&data[i],sizeof(data),0,sa[1],sizeof(sa[1]));
}
It's pretty basic.
Any ideas? Thanks for all your great help!
Paul
Maybe your UDP stack runs out of memory?
(1) Check /proc/sys/net/ipv4/udp_mem (see man 7 udp for details). Make sure that the first number is at least 8x times the image size. This sets the memory for all UDP sockets in the system.
(2) Make sure you per-socket buffer for sending socket is big enough. Use setsockopt(sock2, SOL_SOCKET, SO_SNDBUF, image_size*2) to set send buffer on both sockets. You might need to increase maximumu allowed value in /proc/sys/net/core/wmem_max. See man 7 socket for details.
(3) You might as well increase RX buffer for receiving socket. Write a big number to .../rmem_max, then use SO_RCVBUF to increase the receiving buffer size.
A workaround until this issue is actually solved may be to createa bridge for eth1+eth2 and send the packet to that bridge.
Thus it's only mapped to kernel-memory once and not twice per image.
It's been a long time, but I found the answer to my question, so I thought I would put it here in case anyone else ever finds it.
The two Gigabit Ethernet ports were actually on a PCI bridge off the PCI-express bus. The PCI-express bus was internal to the motherboard, but it was a PCI bus going to the cards. The bridge and the bus did not have enough bandwidth to actually send out the images that fast. With only one NIC enabled the data was sent to the buffer and it looked very quick to me, but it took much longer to actually get through the bus, out the card, and on to the wire. The second NIC was slower because the buffer was full. Although changing the buffer size masked the problem, it did not actually send the data out any faster and I was still getting dropped packets on the third NIC.
In the end, the 100Base-T card was actually built onto the motherboard, therefore had a faster bus to it, resulting in overall faster bandwidth than the gigabit ports.. By switching the camera to a gigabit line and one of the gigabit lines to the 100Base-T line I was able to meet the requirements.
Strange.
I am opening a TAP device using
p->fd = open("/dev/net/tun", O_RDWR);
// skipping error handling code
ifr.ifr_flags = IFF_TAP | IFF_ONE_QUEUE | IFF_NO_PI;
strncpy(ifr.ifr_name, p->name, IFNAMSIZ-1);
result = ioctl(p->fd, TUNSETIFF, &ifr);
// skipping error handling and setting ipv4 address & netmask code
ifr.ifr_flags = (IFF_UP | IFF_RUNNING);
result = ioctl(dummySock, SIOCSIFFLAGS, &ifr);
The problem I am facing is when an application (say mozilla) wants to send out a packet via the tap device, it needs to get the dst mac address. So the kernel sends out an ARP request. The application I am writing forwards the arp request (via a raw socket on a physical eth device) and gets an arp reply. This arp reply is forwarded back to the tap device, but the kernel refuses to accept this. If I add an arp entry manually, no arp request is generated and there is two way ip packet exchange (mozilla is happy).
Wireshark is able to receive the packet and finds no errors. Same is the case with ICMPv6 packets (neighbor solicitation & advertisement). Any application listening on the device gets the packet intact. But the kernel does not process it for ARP/ICMP.
My question is, why doesn't the kernel accept the arp reply/ICMPv6 msgs? Is there some ioctl call that we need to call?
Edit:
Here is the details of packet captured (tshark output) at the tap device "ethgress"
9 16.548328 fc00:1::2 -> ff02::1:ff00:1 ICMPv6 86 Neighbor Solicitation
10 17.243247 fc00:1::100 -> fc00:1::2 ICMPv6 86 Neighbor Advertisement
11 17.548652 fc00:1::2 -> ff02::1:ff00:1 ICMPv6 86 Neighbor Solicitation
12 17.668736 fc00:1::100 -> fc00:1::2 ICMPv6 86 Neighbor Advertisement
This is the ifconfig output for "ethgress"
ethgress Link encap:Ethernet HWaddr 00:01:02:03:04:05
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:83 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:10000
RX bytes:0 (0.0 b) TX bytes:7062 (6.8 KiB)
As can be seen, the kernel is refusing the accept the ICMPv6 packets as received. But the tx packets are incremented.
The tap device "ethgress" is configured with IPv6 address fc00:1::2 and it an application wants to communicate to fc00:1::1. fc00:1::1 is at the same interface as fc00:1:100 which is responding with the neighbor advertisement (the target ip is fc00:1::1 in that packet) with proper mac address. Tcpdump is able to capture it and wireshark/tshark is able to decode it without and says its a properly formed packet. But Rx counters are not incremented by the kernel, nor does it update its arp cache. Same is the case with ARP packets.
Edit 2:
The network looks like this. There are two external boxes which are configured to be redundant. Only one of them will be active. They are connected to a pc via a physical NIC each. The application I am writing runs on this pc and opens a raw socket on each of the NICs. It also opens a TAP device. The NICs are not configured with an IP address. The TAP device is configured with both IPv4 and IPv6 address. A standard application, say mozilla, opens a socket via the tap device and wants to connect to the active box. For that the kernel generates an ARP request/Neighbor solicitation message on the tap device. The application reads this message and forwards it to both the NICs. The active box responds to the ARP request with an ARP reply which the application reads and writes it to the TAP device. This arp reply packet is captured by tcpdump, but the kernel doesn't update its arp cache. The mac address of both NICs and the TAP device are the same.
Other parameters asked for.
cat /proc/sys/net/ipv4/conf/all/log_martians
0
cat /proc/sys/net/ipv4/conf/all/rp_filter
1
cat /proc/sys/net/ipv4/conf/all/arp_filter
0
This question is very old now.
(You also have the difference between TUN and TAP devices https://security.stackexchange.com/questions/46442/openvpn-tap-vs-tun-mode )
If your device is indeed a TAP device that includes ARP, hardware addressing etc:
Your traffic-dump does not include the ethernet frame. Two important details for these ARP and ICMPv6 packets are the HW dst and src addresses. The RP filter is a part of this, but probably does not allow ALL possible combinations to pass.
For a TUN device: there should be no need for ARP etc, this device is "blind" IP device
Background: I'm teaching myself about packet sniffing. I run a very simple server in one shell, telnet to it from another, then try different methods to sniff on traffic. When I use raw sockets (IPPROTO_TCP), I capture what I send fine. I capture merely what I send, nothing else from the internet. libcap's behavior confuses me as follows:
(1) First, to check it out, I capture all devices with pcap_findalldevs (see (2) below as well). I find wlan0 fine. If I connect to 'all traffic' (per the man page) using
if ( !( pcap_handle = pcap_open_live(NULL, 4096, 1, 0, errbuf) ) )
I capture what I send (plus more, see (3)).
when I try to connect to it using
if ( !( pcap_handle = pcap_open_live("wlan0", 4096, 1, 0, errbuf) ) )
, which to me seems the proper way of doing this, not 'all', i capture lots of general traffic, but nothing I send. Ideas?
(2) I first find all devices using pcap_findalldevs. As the pcap_if_t structure possibly has several elements, I print all those out, to see the following:
Devices found:
1. eth0 - None:
family: 17, address: 2.0.0.0
2. wlan0 - None:
family: 17, address: 3.0.0.0
family: AF_INET, address: 192.168.0.159
family: 10, address: 0.0.0.0
3. usbmon1 - USB bus number 1:
4. usbmon2 - USB bus number 2:
5. usbmon3 - USB bus number 3:
6. usbmon4 - USB bus number 4:
7. usbmon5 - USB bus number 5:
8. any - Pseudo-device that captures on all interfaces:
9. lo - None:
family: 17, address: 1.0.0.0
family: AF_INET, address: 127.0.0.1
family: 10, address: 0.0.0.0
I am all new to this. Some devices offer capturing of AF_INET (=IPv4), IPv6 (10), and packet (17). when I connect to "wlan0", how is it ensured I connect to the proper of the 'addresses' of some device? Is that related to the problem?
(3) When using raw sockets, I really only capture what I sent to my server. When I use libcap, I also capture what, from the bytes printed out, must be internet headers. I am all new to this. If someone could elaborate what exactly I capture here which i don't capture on raw sockets, this would be appreciated. Are those UDP or ICMP packets which, by definition, my IPPPROTO_TCP socket would not capture, which would be why I didn't see those using raw sockets?
Many thanks.
Edit: I work under Ubuntu 10.04 on a Toshiba netbook, using gcc/gdb combo.
It's somewhat surprising that, when capturing on wlan0, you're not seeing packets you send, if they're actually being sent over your Wi-Fi device. Are you sending them to other machines on your Wi-Fi network? If, for example, you're sending them to other processes on your machine, they'll show up on lo, not on wlan0 (and if you send them to other machines on your Wi-Fi network, rather than to other processes on your machine, they will not show up on lo - no, all traffic doesn't eventually go through the loopback interface).
The list of addresses you get from pcap_findalldevs() is NOT a list of addresses for which you can capture on that interface, it's just a list of network addresses the system has for that interface. You don't get to choose which addresses for which to capture - it captures for all of them. You capture on an interface, not an address.
Libpcap is different from a raw socket; it gives you lower-layer headers than the ones for the data being sent or received, as well as that data. For an Ethernet device, you'll see Ethernet headers; for a Wi-Fi device, what you see depends on the OS you're on and the headers you select (on Linux, which is what you're using, you'll probably see Ethernet headers unless you capture in "monitor mode", in which case you'll either see Wi-Fi headers or some "radio" header such as radiotap headers followed by Wi-Fi headers); for the "any" device, you'll see "Linux cooked headers"; and so on. You'll need to call pcap_datalink() after calling pcap_open_live() to find out the header type for the interface; see the list of link-layer types (pcap_datalink() will return the DLT_ value, as listed there; don't assume the number given there is the same as the DLT_ value, compare with the DLT_ value by name).
A crazy question, but is there anyway to discover the default gateway without DHCP?
This would be for a device on a network which does not use DHCP which does not have an IP address as yet. I was thinking if I could discover the default gateway, then i could try to guess an unused ip address then broadcast on the network to see if it's being used.
I may be asking for trouble i understand. E.g. if there is already a computer which has a static IP and is shutdown.
Packet sniff for a while and then apply heuristics. I'm assuming IPv4 and Ethernet for the rest of this. This won't work so well if Ethernet Switches are used rather than HUBs. More on that at the end.
Create your own RARP (reverse address resolution) table based on the Ethernet (or whatever) and IP headers you see as well as actual ARP packets (ignoring broadcast and multicast IP and MAC addresses). Make sure that your table is able to map multiple IP addresses to a single hardware interface. Any IP addresses in the table that are entered or verified by actual ARP packets should be flagged as such.
The gateway(s) is likely to recieve and send more traffic. This traffic is likely to have many IP addresses from many different networks but have the same hardware address. The gateway will show up in your table as one MAC address with lots of IP addresses. It is likely that you will have observed an ARP transaction involving this MAC address address, so you can look for an IP address that aliases that MAC that also has the seen in ARP packet flag set. That is almost certainly a gateway's IP address.
You will probably be able to guess the network address and subnet mask based on the IP address of the gateway, but this might not be something you can trust. If you want to try to make this work on a network with a non-standard netmask you can try to do the following.
Make two IP address sized accumulator variables:
uint32_t acc_and = 0xFFffFFff;
uint32_t acc_or = 0x00000000;
And then for each ARP verified address in your table you do
acc_and &= ip_addr;
acc_or |= ip_addr;
You could also use destination IP addresses (that aren't multicast) in packets that came from the gateway for this, but you would have to know the gateway before you could flag them as such.
finding the netmask and network address
The network portion of the address should stay the same in both (after the first operation), but in acc_and the bottom bits should start clearing out while in the acc_or the bottom bits should start filling up. With enough samples you would be able to determine the network address by:
uint32_t net_addr = acc_and & acc_or;
and the netmask by:
uint32_t net_mask = acc_and ^ acc_or;
Getting enough sampled local IP addresses could take too long, so you can start trying to narrow it down by:
uint32_t almost_net_mask = acc_and ^ acc_or;
int i = 0;
while ( 1 & almost_net_mask ) {
i++;
almost_net_mask >>= 1;
}
uint32_t net_mask = 0xFFffFFff;
while( i-- ) {
net_mask <<=1;
}
This would find you the last 1 bit set. The lowest 0 bit is obviously not part of the local portion of the address. Alternately you could get the same i by:
i = ffs( ~ ( acc_and ^ acc_or ) ) ; // assuming that int on your system is 32 bit. if not use ffsl
If you really really want to be sure of your netmask and network address now you can try some other things. You can try to see if the gateway will attempt to forward packets you send it to what you think should be local addresses to them. For this would would have to go ahead and assign yourself an IP address, which is risky if your netmask isn't right.
choosing an IP for yourself
Try to choose the lowest legal IP address that you haven't seen traffic to or from to increase the chance that it is not out of range. You could spoof an ARP request for that address and look for any replies (you could use your own real MAC address but possibly make up an IP for this. doesn't have to be your IP, which might confuse things for a little bit). After you have found an IP address that you can't ARP claim it for yourself.
It is possible that you ended up with an IP address that is actually too high. This is difficult to know for sure since your netmask is still just a good guess. You're out of luck if this is the case because there is not free slot for you to live.
back to the netmask
To see if your netmask needs adjusting try sending IP packets with destination addresses that you haven't see in the local network but that could be in the local network based on your guesses at the netmask and the network address. If these guesses are off they should have too many bits assigned to the network address, so sending to addresses which change the lower bits from the netmasked portion of the (so far) best guessed network address is what you want. You can try sending these as you normally would by ARPing the IP address and seeing if anyone replies, but since you are guessing addresses and likely to miss, it might be better to try creating the packet(s) with the destination MAC address set to the gateway to see if it would forward it. It may be configured not to, so you could try to see if it would by first doing this for a member of the network which you have already observed in the network and then see if it forwards it for you. If the gateway forwards the packet then you can rely on its idea of the netmask to narrow down your idea of the netmask. If the gateway will not forward for packets destine for known members of the local network then you can either just keep using your idea of the local netmask and network until you have a reason to adjust it or send out ARP requests for addresses in that range (which will only answer your question as either "yes" or "maybe" with no possibility of a sure "no").
if you are using an Ethernet switch, rather than a HUB
If you are using an Ethernet switch things get much more difficult because the switch will not forward Ethernet frames to you if it knows that the frames should go somewhere else, so you will not see them. It will forward many ARP requests, though, since they are broadcast unless the sender still has an entry for that IP in its ARP cache and is just trying for an early renewal of that entry (this may not be done by all systems). This will make building your idea of the network and its members much more difficult, but you will likely be able to do a decent job. You will probably have to rely on the quantity of ARP request for the gateway and from the gateway being higher than the other systems to spot it, though. This is error prone as a file server could have similar traffic.
Could be done but not in easy way (according to my poor knowledge).
Solution I would analyze further:
Detect Gateway - 2 possibilities (all off them related with data sniffing):
capture DHCP offer packets and
retrieve gateway
look for packet which is addressed to outer network (e.g. do arp request on each target IP address - if no answer you have probable mac address of the default gateway - you need to find IP address of this gateway (analyze arp packets, all packets, etc..)
one you have ip address do a arp requests and find you free ip.
sniffing library I think is libpcap or winpcap.
Never done even something similiar but If I wouldn't find any references on google I would go this way I think.
On a Windows network, you could use IP 0.0.0.0 and open a UDP socket with port 67 (or maybe 68) and wait for SMB broadcast messages to learn an IP address. From there, you can use ARP packets to search for devices on addresses close to that IP.
Try to find an unused address that as close to the original IP (identical upper bits) in case the network uses a netmask smaller than 255.255.255.0. Once you find an unused IP, claim it for your device and send a gratuitous ARP.
Now continue your ARP scan, and whenever you find a device that responds, temporarily set it as your default gateway and try to ping a known IP address of a device on the Internet that will respond. If you get a response, you've found your gateway.
That's a lot of work when using DHCP will get you there 99% of the time.