http://www.perlmonks.org?node_id=552987

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

Say I have a perl program that listens on a udp port/socket on a Linux 2.6 kernel system.

How do I get the source physical/hardware/ethernet address of the received packets?

I want to do this without looking at /proc/net/arp or running /sbin/arp - because this will only have stuff that has a verified IP address.

I know how to get the source IPs of the received packets (the getpeer thingies etc), and the interface the packets come in on (using the Linux specific IP_PKTINFO stuff).

So is it possible to similarly access something like the sockaddr_ll stuff at normal udp socket levels?

I do not want to resort to using a PF_PACKET,SOCK_RAW/SOCK_DGRAM socket or libpcap because I do not want the program to parse and sift through "all" packets. Just want packets destined to that port.

And yes I know ethernet addresses can also be spoofed, I just would like to know what they are when a packet comes in.

Thanks!

2006-06-03 Retitled by g0n, as per Monastery guidelines
Original title: 'Getting the source hardware address of received UDP packets?'

Replies are listed 'Best First'.
Re: (OT) Getting the source hardware address of received UDP packets?
by ikegami (Patriarch) on Jun 01, 2006 at 07:59 UTC

    recv "returns the address of the sender if SOCKET's protocol supports this" (which it does). I don't know if the destination address is available.

    Update: Disregard the above. I misread your question. Time for bed.

    The source address for UDP is an IP address. Ethernet packets can encapsulate IP packets, but they are completely unrelated. Neither the sender nor the receiver needs to use Ethernet to send or receive UDP packets. Asking for the Ethernet address for an IP address is akin to asking for the street address for an IP address. It may be possible, but it requires an external protocol (like ARP?).

    If you do receive your IP packets from an Ethernet, the source address on the packet will be the one of your router and not the one of the computer sending the UDP packet (unless the sender is on your LAN).

    By the way, I don't think getpeername works on UDP sockets, since there is no peer associated with a UDP socket. They are "unconnected". That's why the function that returns the sender's address (recv) is associated with a packet, not a socket.

Re: (OT) Getting the source hardware address of received UDP packets?
by isotope (Deacon) on Jun 01, 2006 at 16:26 UTC
    IP packets have no concept of MAC address. That's already been removed by the OS by the time you get the packet. There are few ways to get that information at this point:
    • Checking the ARP table would be the easy way, but you don't want to do that.
    • Using libpcap would be the more reliable way, if you don't trust the source IP address, but you don't want to do that.
    • Writing your own ethernet driver in Perl might work, but if you don't want to filter packets with pcap, you're certainly not going to want to write a complete driver.
    Now that you've eliminated the reasonable answers, my question is: What are you really trying to accomplish? I suspect there's a much easier way to do what you want.


    --isotope
      Say a dhcp client without an IP address sends a dhcp request (broadcast).

      While a dhcp request/discover payload usually contains the alleged hardware address of the client, it may still be useful to log the hardware address of the frame if things go wrong.

      But I don't want the program to see all frames. Only just the relevant packets.

      I suppose that's not a good enough reason - so I guess that's why there's no easy way to do that :).

        It is possible to make DHCP requests to a server outside of one's LAN*, but only because DHCP allows you to specify your MAC address inside of your request. The DHCP request looks a bit like "My MAC address is 00:00:00:00:00:00. Please give me an IP address." In other words, the client must explicitly place the MAC address in the DHCP request. There's no IP or UDP (or even TCP) solution to your problem.

        You can do the same as DHCP — have the clients send their MAC address along with their request — with your UDP-based protocol if you're still developing the protocol.

        * — That requires the co-operation of the gateway, but only because the machine doesn't have an IP address yet.

        That really is a good application for Net::Pcap. You dismissed pcap because you didn't want to handle all received frames, but pcap allows you to define a filter so you'd actually be able to select just dhcpc messages if you wanted.


        --isotope