Reputation: 4720
In linux, how can I transmit an UDP packet using 0.0.0.0 as source address.
Here is what I have tried so far.
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <net/if.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
int main(int argc, const char *argv[])
{
struct sockaddr_in dst, src;
struct ifreq ifr;
int sock, tmp;
char payload[128];
memset(payload, 0, 128);
memset(&dst, 0, sizeof(dst));
dst.sin_family = AF_INET;
dst.sin_addr.s_addr = inet_addr("255.255.255.255");
dst.sin_port = htons(67);
memset(&src,0,sizeof(src));
src.sin_family = AF_INET;
src.sin_addr.s_addr = inet_addr("0.0.0.0");
src.sin_port = htons(68);
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0)
perror("Failed to create socket");
tmp = 1;
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &tmp, sizeof(tmp)) < 0)
perror("SO_BROADCAST failed");
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp)) < 0)
perror("SO_REUSEADDR failed");
if (setsockopt(sock, IPPROTO_IP, IP_FREEBIND, &tmp, sizeof(tmp)) < 0)
perror("IP_FREEBIND failed");
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, "eth1", sizeof(ifr.ifr_name));
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0)
perror("SO_BINDTODEVICE failed");
if (bind(sock, (const struct sockaddr*)&src, sizeof(struct sockaddr_in)) < 0)
perror("bind failed");
if (connect(sock, (const struct sockaddr*)&dst, sizeof(struct sockaddr_in)) < 0)
perror("bind failed");
if (write(sock, payload, 128) < 0 )
perror("Write failed");
close(sock);
return 0;
}
The problem is the the source address is only set to 0.0.0.0 if no interfaces has an IPv4 address. If just one interface has an IPv4 address, this address is used as source address.
I have looked at the source code of some of the existing DHCP clients, and found that they are using RAW sockets and building the IP and UDP header manually. This is possibility, but I would like to avoid doing this manually.
Upvotes: 7
Views: 3865
Reputation: 3489
You should use RAW SOCKET and construct packet with your own efforts.
As an example you can take this: https://github.com/fycth/DHCP-server-scanner/blob/master/src/dhcpd-detector.c
This is my educational project. It is small and you can look how exactly this task is solved there.
Upvotes: 4
Reputation: 91139
I think if it was possible to do it via UDP sockets, they would do it instead of building one manually. So I'd suppose it doesn't work at all...
Upvotes: 0