Hi,
I am facing the same problem as Grant has quoted in this thread.
I am using Linux. I have my interface up and running, but it is not configured with an IP address, intentionally. So, it should be able to accept broadcast messages.
[root@sreeramb-linux Network]# uname -a
Linux sreeramb-linux 2.6.35.6-45.fc14.i686 #1 SMP Mon Oct 18 23:56:17 UTC 2010 i686 i686 i386 GNU/Linux
[root@sreeramb-linux Network]# ifconfig eth0
eth0 Link encap:Ethernet HWaddr 08:00:27:9D:13:EE
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:161628 errors:0 dropped:0 overruns:0 frame:0
TX packets:32748 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:23403260 (22.3 MiB) TX bytes:2727456 (2.6 MiB)
[root@sreeramb-linux Network]#
The rp-filter is also set to 0.
[root@sreeramb-linux Network]# cat /proc/sys/net/ipv4/conf/eth0/rp_filter
0
[root@sreeramb-linux Network]# cat /proc/sys/net/ipv4/conf/all/rp_filter
0
[root@sreeramb-linux Network]#
In my program, I am doing the following:
1. Open a UDP socket.
2. Set SO_DEBUG and SO_REUSEADDR.
3. Set SO_BROADCAST flag.
4. Bind to port 68 (I have made sure that there is no other dhcp client running).
5. Perform SO_BINDTODEVICE to eth0
6. recvfrom() on the socket.
I elicit a broadcast response from the server, which I expect to read from my application. The response is reaching my PC since I am able to see it from wireshark, but my application is not catching it.
Should I use any more socket options to accept the broadcast packets?
Should I make any changes to any of the files in the system to obtain broadcast pkts?
Kindly suggest.
My program:
-------------------
[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");
/* 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");
/* 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);
/* Set the structure to send to the broadcast address. */
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(68);
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");
/* 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 */
printf("About to call recvfrom().\n");
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]#
Please guide.
Regards,
Sreeram