I am making a program similar to simpletun from here.
an application sends out UDP broadcasts to the tap interface.
program listening on the tap interface (similar to simpletun)receives the packet and echoes it again as broadcast.
I am able to see both the packets on wireshark but the application does not receive it. seems that the kernel is dropping them.
If similar packets are sent from a different machine . it works fine.
tun/tap code:-
char datagram[4096];
struct pseudo_header
{
u_int32_t source_address;
u_int32_t dest_address;
u_int8_t placeholder;
u_int8_t protocol;
u_int16_t udp_length;
};
struct pseudo_header psh;
char *pseudogram;
nread = cread(tap_fd, buffer, BUFSIZE);
memcpy(&source_port,(char *)(buffer+14+20),2);
memset (datagram, 0, 4096);
memcpy(datagram,buffer,14); //copy eth-header
datagram[6] = 0xXX;//change mac address
datagram[7] = 0xXX;
datagram[8] = 0xXX;
//IP header
struct iphdr *iph = (struct iphdr *) (datagram +14);
//TCP header
struct udphdr *udph = (struct udphdr *) (datagram + 14 + sizeof (struct iphdr));
data = datagram + sizeof(struct iphdr) + sizeof(struct udphdr) +14;
strcpy(data,"Any string");
iph->ihl = 5;
iph->version = 4;
iph->tos = 0;
iph->tot_len = sizeof (struct iphdr) + sizeof (struct udphdr) + strlen(data);
iph->id = htonl (54321); //Id of this packet
iph->frag_off = 0;
iph->ttl = 255;
iph->protocol = IPPROTO_UDP;
iph->check = 0; //Set to 0 before calculating checksum
strcpy(source_ip , "192.168.0.99");
iph->saddr = inet_addr ( source_ip ); //Spoof the source ip address
strcpy(destination_ip , "255.255.255.255");
iph->daddr = inet_addr (destination_ip);
udph->source = htons(5933);
//udph->dest = htons(source_port);
udph->dest = (source_port);
udph->len = htons(sizeof(struct udphdr) + strlen(data));
//Now the UDP checksum
psh.source_address = inet_addr( source_ip );
psh.dest_address = inet_addr(destination_ip);
psh.placeholder = 0;
psh.protocol = IPPROTO_UDP;
psh.udp_length = htons(sizeof(struct udphdr) + strlen(data) );
int psize = sizeof(struct pseudo_header) + sizeof(struct udphdr) + strlen(data);
pseudogram = malloc(psize);
memcpy(pseudogram , (char*) &psh , sizeof (struct pseudo_header));
memcpy(pseudogram + sizeof(struct pseudo_header) , udph , sizeof(struct udphdr) + strlen(data));
memcpy(pseudogram + sizeof(struct pseudo_header) + sizeof(struct udphdr), data , strlen(data));
udph->check = 0;
udph->check = csum( (unsigned short*) pseudogram , psize);
//Ip checksum
iph->check = csum ((unsigned short *) datagram, iph->tot_len);
//writeback
cwrite(tap_fd,datagram,iph->tot_len +14);
The above code when run from another machine using raw sockets read and write works well. (without eth-header).
Receiving Application code:-
int broadcast =1;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
err("socket");
setsockopt(sockfd,SOL_SOCKET,SO_BINDTODEVICE,"tun0",5);
bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(PORT);
memset(&my_addr.sin_addr.s_addr,255,sizeof(my_addr.sin_addr.s_addr));
ret = setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,&broadcast,sizeof(broadcast));
if(ret<0)
printf("setsockopt bindto failed");
if (sendto(sockfd,buf,500,0, (struct sockaddr*)&my_addr,slen_len) == -1)
err("send()");
recvfrom(sockfd, buf, 500, 0, (struct sockaddr*)&cli_addr, &slen);
int broadcast = 1;
– hiteshradia