I am writing a rogue DHCP server detector and am stumped with a problem. I need to set up a socket that will read packages with DHCP offers sent by DHCP servers. But I need to examine the entire incoming packet, including the link layer header in order to get the hardware address of the sending server.

So I have been trying to do this by setting up a raw data socket and then binding it to the known DHCP port. However, either I get an error when trying to bind to my port of "Invalid arguments" or when I am successful in getting things to work, I only get data from the IP header and afterwards when using recvfrom. In other words, I cannot seem to set this up so that I also can get the hardware address information.

What I have tried that lets bind work without error:

struct sockaddr_in se_addr;
struct sockaddr_ll raw_addr;

sockfd = socket(PF_INET, SOCK_RAW,IPPROTO_UDP);

memset(&se_addr, 0, sizeof se_addr);
se_addr.sin_family = AF_INET;
se_addr.sin_port = htons(DHCP_SERVER_PORT);

bind(sockfd, (struct sockaddr *) &se_addr, sizeof(se_addr)) < 0;

raw_addr_size = sizeof(raw_addr);
status = recvfrom(sockfd,packet,2048,0,(SA *)&raw_addr,&raw_addr_size);

If I try anything else like using PF_PACKET instead of PF_INET, then the call to bind gives the error Invalid Argument.

Can anyone help me here? How to tweak this with the correct parameters to socket, bind and maybe recvfrom so that I can get returned the information about the hardware address of the sender yet bind the socket so that it only receives packets for a specific port?

Thanks for any help!