Hi,
I have an program written with an intent to receive the broadcasted UDP
packets. Unfortunately, I am not able to receive them.
I have made several attempts by making modifications here and there in the
program, but in vain. I have now become idealess and I have turned to you
for help/suggestion.
Kindly suggest.
Here are the set of things I do:
1. I have my interface eth0 up, but deliberately I have no IP address
assigned. [This is order to simulate a situation when DHCP discover is sent
during booting.]
2. Create UDP socket.
3. Bind to the eth0 using SO_BINDTODEVICE
4. Enable broadcasting for this socket SO_BROADCAST.
5. Build a DHCPDiscover message.
6. Broadcast the message. This will elicit a response from the DHCP
server in the local LAN. I am able to see the response in wireshark.
7. Call recvfrom() to receive the message. << recvfrom() waits forever.
It is not able to grab the response >>
The program is as follows:
----------------------------------------
[root@sreeramb-linux DHCP]# cat dhcp.c
/* This is a test program to bind a socket to an interface
* instead of to an IP address(which is done normally).
* Also, broadcasting is enabled for this socket so that
* any broadcast packet is sent over this socket.
*/
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#define SA struct sockaddr
#define IFC "eth0"
#define PORT 67
#define IFCSZ sizeof(IFC)
struct dhcp_header {
unsigned char op;
unsigned char htype;
unsigned char hlen;
unsigned char hops;
int xid;
short secs;
short flags;
struct in_addr ciaddr;
struct in_addr yiaddr;
struct in_addr siaddr;
struct in_addr giaddr;
unsigned char chaddr[16];
unsigned char sname[64];
unsigned char file[128];
unsigned char opts[128];
};
int main(int argc, char **argv) {
int sock, retn;
struct sockaddr_in peer, addr;
char mesg[] = "Hello World!";
int val=1, size = sizeof(val);
/* Create an UDP socket first. */
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
perror("Socket");
exit(-1);
}
printf("Created socket successfully.\n");
/* Enable the SO_DEBUG option for this socket. */
retn = setsockopt(sock, SOL_SOCKET, SO_DEBUG, &val, size);
if (retn < 0) {
perror("SO_DEBUG");
close(sock);
exit(-1);
}
printf("Successfully enabled the SO_DEBUG flag for the socket.\n");
/* Now, set the SO_REUSEADDR flag for this socket. */
retn = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, size);
if (retn < 0) {
perror("SO_REUSEADDR");
close(sock);
exit(-1);
}
printf("Successfully set the SO_REUSEADDR flag to this socket.\n");
#if 0
/* Set the structure to send to the broadcast address. */
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(6800);
retn = bind(sock, (SA *)&addr, sizeof(SA));
if (retn < 0) {
perror("BIND_TO_PORT");
close(sock);
exit(-3);
}
printf("Successfully bound to port 68 also.\n");
#endif
/* Now, bind to device, eth0 */
retn = setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, IFC, IFCSZ);
if (retn < 0) {
perror("SO_BINDTODEVICE:eth0");
close(sock);
exit(-1);
}
printf("Successfully bound to device '%s'\n", IFC);
/* Now, set the broadcast flag for this socket. */
val = 1, size = sizeof(val);
retn = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &val, size);
if (retn < 0) {
perror("SO_BROADCAST");
close(sock);
exit(-1);
}
printf("Successfully set the broadcast flag to this socket.\n");
/* Set the structure to send to the broadcast address. */
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
inet_aton("255.255.255.255", &addr.sin_addr);
send_dhcp_discover(sock, addr);
recv_dhcp_offer(sock);
}
int send_dhcp_discover(int sock, struct sockaddr_in addr) {
int retn, i = 0;
struct dhcp_header hdr;
memset(&hdr, 0, sizeof(hdr));
hdr.op = 1;
hdr.htype = 1;
hdr.hlen = 6;
hdr.xid = 1;
hdr.flags = 128;
hdr.chaddr[0] = 0x08;
hdr.chaddr[1] = 0x00;
hdr.chaddr[2] = 0x27;
hdr.chaddr[3] = 0x9D;
hdr.chaddr[4] = 0x13;
hdr.chaddr[5] = 0xEE;
/* The first four octets are supposed to be magic number. */
hdr.opts[i++] = 99;
hdr.opts[i++] = 130;
hdr.opts[i++] = 83;
hdr.opts[i++] = 99;
/* The next option depicts the message type. */
hdr.opts[i++] = 53; // DHCP message type.
hdr.opts[i++] = 1; // Length = 1
hdr.opts[i++] = 1; // DHCP Discover message.
/* Let the client make a wish that it be assigned 192.168.1.25 */
hdr.opts[i++] = 50; // Preferred IP address
hdr.opts[i++] = 4; // Length = 4
inet_aton("192.168.1.25", (struct in_addr *)&hdr.opts[i]);
i += 4;
hdr.opts[i++] = 255; // End of options.
/* Now, broadcast the message. */
retn = sendto(sock, &hdr, sizeof(hdr), 0, (SA *)&addr, sizeof(SA));
if (retn < 0) {
perror("sendto");
close(sock);
exit(-2);
}
printf("Successfully broadcasted the message.\n");
printf("IFC size is %d\n", IFCSZ);
return 0;
}
/* This program will receive the DHCP offer message */
int recv_dhcp_offer(int sock) {
int retn, size = sizeof(SA);
struct sockaddr_in server;
unsigned char mesg[sizeof(struct dhcp_header)];
/* Receive the message */
retn = recvfrom(sock, mesg, sizeof(mesg), 0, (SA *)&server, &size);
if (retn < 0) {
perror("recvfrom");
exit(-1);
}
printf("Received message: DHCP OFFER\n");
return 0;
}
[root@sreeramb-linux DHCP]#
------------------------------------------
Am I missing something very obvious. Kindly guide me.
With regards,
Sreeram