On Wed, May 02, 2012 at 05:13:41PM +0530, Sreeram BS wrote:

> 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:

Sorry, this has little to do with OpenBSD. Ask your question on some
Linux list.

        -Otto
> 
> ----------------------------------------
> [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