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

Reply via email to