#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
// The packet length
#define PACKET_LENGTH 8192
unsigned short csum(unsigned short *buf, int nwords)
{
unsigned long sum;
for(sum=0; nwords>0; nwords--){
sum += *buf++;
}
sum = (sum >> 16) + (sum &0xffff);
sum += (sum >> 16);
return (unsigned short)(~sum);
}
// Source IP, source port, target IP, target port from the command line arguments
int main(int argc, char *argv[])
{
int sd;
char buffer[PACKET_LENGTH];
struct iphdr *ip = (struct iphdr *) buffer;
struct udphdr *udp = (struct udphdr *) (buffer + sizeof(struct iphdr));
struct sockaddr_in sin, din;
int one = 1;
const int *val = &one;
memset(buffer, '|', PACKET_LENGTH);
if(argc != 5){
printf("- Invalid parameters!!!\n");
exit(-1);
}
sd = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);
if(sd < 0){
perror("socket() error");
exit(-1);
}else{
printf("socket() - Using SOCK_RAW socket and UDP protocol is OK.\n");
}
sin.sin_family = AF_INET;
din.sin_family = AF_INET;
sin.sin_port = htons(atoi(argv[2]));
din.sin_port = htons(atoi(argv[4]));
sin.sin_addr.s_addr = inet_addr(argv[1]);
din.sin_addr.s_addr = inet_addr(argv[3]);
ip->ihl = 5;
ip->version = 4;
ip->tos = 16; // Low delay
ip->tot_len = sizeof(struct iphdr) + sizeof(struct udphdr);
ip->id = htons(54321);
ip->ttl = 64; // hops
ip->protocol = 17; // UDP
ip->saddr = inet_addr(argv[1]);
ip->daddr = inet_addr(argv[3]);
udp->source = htons(atoi(argv[2]));
udp->dest = htons(atoi(argv[4]));
udp->len = htons(sizeof(struct udphdr));
ip->check = csum((unsigned short *)buffer, sizeof(struct iphdr) + sizeof(struct udphdr));
//告诉kernel packet中包含headers
if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0){
perror("setsockopt() error");
exit(-1);
}else{
printf("setsockopt() is OK.\n");
}
printf("Trying...\n");
printf("Using raw socket and UDP protocol\n");
printf("Using Source IP: %s port: %u, Target IP: %s port: %u.\n", argv[1], atoi(argv[2]), argv[3], atoi(argv[4]));
while(1){
if(sendto(sd, buffer, ip->tot_len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0){
perror("sendto() error");
exit(-1);
}else{
printf("sendto() is successful.\n");
sleep(2);
}
}
close(sd);
return 0;
}
=======================================================================
./test 192.168.0.123 23 192.168.31.129 8008
可以使用wireshark抓包: