Last active
December 17, 2015 20:49
-
-
Save thommyj/5670519 to your computer and use it in GitHub Desktop.
send packet
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <sys/socket.h> | |
#include <linux/if_packet.h> | |
#include <linux/if_ether.h> | |
#include <linux/if_arp.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <sys/ioctl.h> | |
#include <netinet/in.h> | |
#include <netinet/udp.h> | |
#include <unistd.h> | |
#include <netinet/ip.h> | |
#include <arpa/inet.h> | |
/*our MAC address*/ | |
unsigned char src_mac[6] = {0x00, 0x22, 0x3f, 0xe8, 0x73, 0x68}; | |
/*other host MAC address*/ | |
unsigned char dest_mac[6] = {0x90, 0x55, 0xae, 0x4f, 0x7a, 0x82}; | |
char src_ip[] = {"10.76.84.33"}; | |
char dst_ip[] = {"10.76.84.49"}; | |
//http://www.microhowto.info/howto/calculate_an_internet_protocol_checksum_in_c.html | |
unsigned short ip_checksum(void* vdata,size_t length) { | |
size_t i; | |
unsigned short word; | |
// Cast the data pointer to one that can be indexed. | |
char* data=(char*)vdata; | |
// Initialise the accumulator. | |
unsigned long acc=0xffff; | |
// Handle complete 16-bit blocks. | |
for (i=0;i+1<length;i+=2) { | |
memcpy(&word,data+i,2); | |
acc+=ntohs(word); | |
if (acc>0xffff) { | |
acc-=0xffff; | |
} | |
} | |
// Handle any partial block at the end of the data. | |
if (length&1) { | |
memcpy(&word,data+length-1,1); | |
acc+=ntohs(word); | |
if (acc>0xffff) { | |
acc-=0xffff; | |
} | |
} | |
// Return the checksum in network byte order. | |
return htons(~acc); | |
} | |
//based on snippet found | |
//www.linuxquestions.org/questions/linux-networking-3/udp-checksum-algorithm-845618/ | |
//then modified by Gabriel Serme | |
struct pseudo_hdr { | |
u_int32_t source; | |
u_int32_t dest; | |
u_int8_t zero; //reserved, check http://www.rhyshaden.com/udp.htm | |
u_int8_t protocol; | |
u_int16_t udp_length; | |
}; | |
/* Not my code */ | |
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 ~sum; | |
} | |
uint16_t udp_checksum(const struct iphdr *ip, | |
const struct udphdr *udp, | |
const uint16_t *buf) | |
{ | |
//take in account padding if necessary | |
int calculated_length = ntohs(udp->len)%2 == 0 ? ntohs(udp->len) : ntohs(udp->len) + 1; | |
struct pseudo_hdr ps_hdr = {0}; | |
bzero (&ps_hdr, sizeof(struct pseudo_hdr)); | |
uint8_t data[sizeof(struct pseudo_hdr) + calculated_length]; | |
bzero (data, sizeof(struct pseudo_hdr) + calculated_length ); | |
ps_hdr.source = ip->saddr; | |
ps_hdr.dest = ip->daddr; | |
ps_hdr.protocol = IPPROTO_UDP; //17 | |
ps_hdr.udp_length = udp->len; | |
memcpy(data, &ps_hdr, sizeof(struct pseudo_hdr)); | |
//the remaining bytes are already set to 0 | |
memcpy(data + sizeof(struct pseudo_hdr), buf, ntohs(udp->len) ); | |
return csum((uint16_t *)data, sizeof(data)/2); | |
} | |
int main(int argc, char **argv) | |
{ | |
/*target address*/ | |
struct sockaddr_ll socket_address; | |
/*buffer for ethernet frame*/ | |
void* buffer=NULL; | |
/*pointer to ethenet header*/ | |
unsigned char* etherhead; | |
/*pointer to payload*/ | |
unsigned char* data; | |
struct iphdr* iph; | |
/*pointer to ethernet header*/ | |
struct ethhdr *eh; | |
int send_result = 0,s,j; | |
struct ifreq ifReq; | |
unsigned char databyte = 0x7e; | |
unsigned short framesize = 1500; | |
struct udphdr *udp_header; | |
struct in_addr addr; | |
if(argc<2){ | |
printf("Usage: %s interface [framesize] [pattern]\nPattern should be 8bits long, if given it will be repeated in payload\n",argv[0]); | |
goto error; | |
} | |
if(argc>2){ | |
framesize = strtol(argv[2],NULL,0); | |
} | |
if(argc>3){ | |
databyte = (char)strtol(argv[3],NULL,0); | |
} | |
printf("using pattern 0x%02X\n",databyte); | |
printf("Using frame length %d\n",framesize); | |
/*buffer for ethernet frame*/ | |
buffer = (void*)malloc(framesize); | |
if(!buffer){ | |
printf("error allocating memory for frame\n"); | |
goto error; | |
} | |
memset(buffer,0,framesize); | |
etherhead = buffer; | |
data = buffer + 14; | |
eh = (struct ethhdr *)etherhead; | |
iph = (struct iphdr*)data; | |
/*open socket*/ | |
s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); | |
if (s == -1) { | |
printf("error opening socket\n"); | |
goto error; | |
} | |
memset(&ifReq, 0, sizeof(ifReq)); | |
strncpy(ifReq.ifr_name, argv[1], strlen(argv[1])); | |
if (ioctl(s,SIOCGIFINDEX,&ifReq)==-1) { | |
printf("unable to get index for interface %s\n",argv[1]); | |
goto error; | |
} | |
printf("using index %d\n",ifReq.ifr_ifindex); | |
/*prepare sockaddr_ll*/ | |
/*RAW communication*/ | |
socket_address.sll_family = PF_PACKET; | |
/*we don't use a protocoll above ethernet layer | |
->just use anything here*/ | |
socket_address.sll_protocol = htons(ETH_P_IP); | |
/*index of the network device | |
see full code later how to retrieve it*/ | |
socket_address.sll_ifindex = ifReq.ifr_ifindex; | |
/*ARP hardware identifier is ethernet*/ | |
socket_address.sll_hatype = ARPHRD_ETHER; | |
/*target is another host*/ | |
socket_address.sll_pkttype = PACKET_OTHERHOST; | |
/*address length*/ | |
socket_address.sll_halen = ETH_ALEN; | |
/*MAC - begin*/ | |
socket_address.sll_addr[0] = dest_mac[0]; | |
socket_address.sll_addr[1] = dest_mac[1]; | |
socket_address.sll_addr[2] = dest_mac[2]; | |
socket_address.sll_addr[3] = dest_mac[3]; | |
socket_address.sll_addr[4] = dest_mac[4]; | |
socket_address.sll_addr[5] = dest_mac[6]; | |
/*MAC - end*/ | |
socket_address.sll_addr[6] = 0x00;/*not used*/ | |
socket_address.sll_addr[7] = 0x00;/*not used*/ | |
/*set the frame header*/ | |
memcpy((void*)buffer, (void*)dest_mac, ETH_ALEN); | |
memcpy((void*)(buffer+ETH_ALEN), (void*)src_mac, ETH_ALEN); | |
eh->h_proto = htons(0x800); | |
/*set ip header*/ | |
iph->version = 4; | |
iph->ihl = 5; | |
inet_pton(AF_INET,src_ip,&addr); | |
memcpy(&iph->saddr,&addr,sizeof(struct in_addr)); | |
inet_pton(AF_INET,dst_ip,&addr); | |
memcpy(&iph->daddr,&addr,sizeof(struct in_addr)); | |
iph->tot_len=htons((unsigned short)(framesize-sizeof(struct ethhdr))); | |
iph->ttl=120; | |
iph->protocol = IPPROTO_UDP; | |
iph->id=htons(123); | |
iph->frag_off = htons(0x4000); /* DF */ | |
iph->check=ip_checksum((short*)data,20); | |
data += sizeof(struct iphdr); | |
//inserting udp header | |
udp_header = (struct udphdr *)data; | |
udp_header->source = htons(10000); | |
udp_header->dest = htons(10000); | |
udp_header->len = htons(framesize -sizeof(struct ethhdr) | |
-sizeof(struct iphdr)); | |
data += sizeof(struct udphdr); | |
/*fill the frame with some data*/ | |
for (j = 0; j < framesize-50; j++) { | |
data[j] = databyte;//(unsigned char)((int) (255.0*rand()/(RAND_MAX+1.0))); | |
} | |
//calculated udp checkswum | |
udp_header->check = udp_checksum(iph,udp_header,(uint16_t*)udp_header); | |
while(1){ | |
send_result = sendto(s, buffer, framesize, 0, | |
(struct sockaddr*)&socket_address, sizeof(socket_address)); | |
if (send_result == -1){ | |
printf("error sending frame\n"); | |
goto error; | |
} | |
} | |
error: | |
if(buffer) | |
free(buffer); | |
if(s) | |
close(s); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment