Skip to content

Instantly share code, notes, and snippets.

@thommyj
Last active December 17, 2015 20:49
Show Gist options
  • Save thommyj/5670519 to your computer and use it in GitHub Desktop.
Save thommyj/5670519 to your computer and use it in GitHub Desktop.
send packet
#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