Rawsock library  v0.3.4
Library to make the use of raw sockets easier, under Linux. Currently supporting IPv4, UDP and a custom latency measurement protocol (LaMP - supported both in raw and non-raw sockets).
rawsock.c
1 // Rawsock library, licensed under GPLv2
2 // Version 0.3.4
3 #include "rawsock.h"
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <ifaddrs.h>
7 #include <string.h>
8 #include <unistd.h>
9 #include <linux/wireless.h>
10 #include <linux/ethtool.h>
11 #include <linux/sockios.h>
12 #include <sys/types.h>
13 #include <sys/ioctl.h>
14 #include <arpa/inet.h>
15 #include "ipcsum_alth.h"
16 #include "minirighi_udp_checksum.h"
17 
18 static uint64_t swap64(uint64_t unsignedvalue, uint32_t (*swap_byte_order)(uint32_t)) {
19  #if __BYTE_ORDER == __BIG_ENDIAN
20  return hostu64;
21  #elif __BYTE_ORDER == __LITTLE_ENDIAN
22  uint32_t low;
23  uint32_t high;
24  high=(uint32_t) (unsignedvalue>>32);
25  low=(uint32_t) (unsignedvalue & ((1ULL << 32) - 1));
26  return ((uint64_t) swap_byte_order(low))<<32 | ((uint64_t) swap_byte_order(high));
27  #else
28  #error "The system seems to be neither little endian nor big endian..."
29  #endif
30 }
31 
32 static uint8_t is_if_tun(int sFd,char *devname) {
33  struct ethtool_drvinfo drvinfo;
34  struct ifreq ethtool_ifr;
35 
36  drvinfo.cmd=ETHTOOL_GDRVINFO;
37  strncpy(ethtool_ifr.ifr_name,devname,IFNAMSIZ);
38  ethtool_ifr.ifr_data=(void *)&drvinfo;
39 
40  return ioctl(sFd,SIOCETHTOOL,&ethtool_ifr)!=-1 && strncmp(drvinfo.bus_info,"tun",ETHTOOL_BUSINFO_LEN)==0;
41 }
42 
55  macaddr_t mac;
56  int i;
57 
58  mac=malloc(MAC_ADDR_SIZE*sizeof(uint8_t));
59 
60  if(mac) {
61  for(i=0;i<MAC_ADDR_SIZE;i++) {
62  mac[i]=0xFF;
63  }
64  }
65 
66  return mac;
67 }
68 
79  free(mac);
80 }
81 
96 unsigned int macAddrTypeGet(macaddr_t mac) {
97  if(mac!=NULL) {
98  if(mac[0]==0x01) {
99  return MAC_MULTICAST;
100  } else if(mac[0]==0xFF && mac[1]==0xFF && mac[2]==0xFF && mac[3]==0xFF && mac[4]==0xFF && mac[5]==0xFF) {
101  return MAC_BROADCAST;
102  } else if(mac[0]==0x00 && mac[1]==0x00 && mac[2]==0x00 && mac[3]==0x00 && mac[4]==0x00 && mac[5]==0x00) {
103  return MAC_ZERO;
104  } else {
105  return MAC_UNICAST;
106  }
107  } else {
108  return MAC_NULL;
109  }
110 }
111 
149 rawsockerr_t wlanLookup(char *devname, int *ifindex, macaddr_t mac, struct in_addr *srcIP, int index, int mode) {
150  // Variables for wlan interfaces detection
151  int sFd=-1;
152  // struct ifaddrs used to look for available interfaces and bind to a wireless interface
153  struct ifaddrs *ifaddr_head, *ifaddr_it;
154  // struct ifreq to check whether an interface is wireless or not. The ifr_name field is used to specify which device to affect.
155  struct ifreq wifireq;
156  // Pointers to manage the list containing all valid wireless interfaces
157  struct iflist *iflist_head=NULL; // Head
158  struct iflist *curr_ptr=NULL; // Current element
159  struct iflist *iflist_it=NULL; // To iterate the list
160  struct iflist *iflist_u=NULL; // To free the list
161  int ifno=0;
162  int ioctl_result=0; // Result of the call to ioctl(sFd,SIOCGIWNAME,&wifireq)
163  int return_value=1; // Return value: >0 ok - # of found interfaces, <=0 error
164  // (=0 for no WLAN interfaces, =-1 for socket error, =-2 for getifaddrs error)
165  // (=-3 for wrong index, =-4 unable to get MAC address, =-5 unable to get ifindex)
166 
167  // Linked list nodes to store the WLAN interfaces
168  struct iflist {
169  struct iflist *next;
170  struct ifaddrs *ifaddr_ptr;
171  };
172 
173  // Open socket (needed)
174  sFd=socket(AF_INET,SOCK_DGRAM,0); // Any socket should be fine (to be better investigated!)
175  if(sFd==-1) {
176  return_value=ERR_WLAN_SOCK;
177  goto sock_error_occurred;
178  }
179 
180  // Getting all interface addresses
181  if(getifaddrs(&ifaddr_head)==-1) {
182  return_value=ERR_WLAN_GETIFADDRS;
183  goto getifaddrs_error_occurred;
184  }
185 
186  // Looking for wlan interfaces
187  memset(&wifireq,0,sizeof(wifireq));
188  // Iterating over the interfaces linked list
189  for(ifaddr_it=ifaddr_head;ifaddr_it!=NULL;ifaddr_it=ifaddr_it->ifa_next) {
190  if(index==-1 && ifaddr_it->ifa_addr!=NULL && (ifaddr_it->ifa_flags & IFF_LOOPBACK)) {
191  // This is the first loopback interface
192  strncpy(devname,ifaddr_it->ifa_name,IFNAMSIZ);
193 
194  // One loopback interface is returned
195  return_value=1;
196 
197  break;
198  } else {
199  if(ifaddr_it->ifa_addr!=NULL && (ifaddr_it->ifa_addr->sa_family == AF_PACKET || (ifaddr_it->ifa_addr->sa_family == AF_INET && is_if_tun(sFd,ifaddr_it->ifa_name)))) {
200  // fprintf(stdout,"Checking interface %s for use.\n",ifaddr_it->ifa_name);
201  // IFNAMSIZ is defined by system libraries and it "defines the maximum buffer size needed to hold an interface name,
202  // including its terminating zero byte"
203  // This is done because (from man7.org) "normally, the user specifies which device to affect by setting
204  // ifr_name to the name of the interface"
205  strncpy(wifireq.ifr_name,ifaddr_it->ifa_name,IFNAMSIZ);
206 
207  // Trying to get the Wireless Extensions (a socket descriptor must be specified to ioctl())
208  ioctl_result=ioctl(sFd,SIOCGIWNAME,&wifireq);
209 
210  // Current interface should be considered
211  if((ioctl_result!=-1 && mode==WLANLOOKUP_WLAN) || (ioctl_result==-1 && mode==WLANLOOKUP_NONWLAN)) {
212  if(ifaddr_it->ifa_addr!=NULL && (ifaddr_it->ifa_flags & IFF_UP) && !(ifaddr_it->ifa_flags & IFF_LOOPBACK)) {
213  // If the interface is up, add it to the head of the "iflist" (it is not added to the tail in order to
214  // avoid defining an extra pointer)
215  ifno++;
216  curr_ptr=malloc(sizeof(struct iflist));
217  curr_ptr->ifaddr_ptr=ifaddr_it;
218  if(iflist_head==NULL) {
219  iflist_head=curr_ptr;
220  iflist_head->next=NULL;
221  } else {
222  curr_ptr->next=iflist_head;
223  iflist_head=curr_ptr;
224  }
225  }
226  }
227  }
228  }
229  }
230 
231  // Scan the list of returned interfaces only if lookback was not specified
232  if(index!=-1) {
233  // No wireless interfaces found (the list is empty)
234  if(iflist_head==NULL) {
235  return_value=0;
236  goto error_occurred;
237  } else if(ifno==1) {
238  // Only one wireless interface found
239  if(index>=1) {
240  return_value=ERR_WLAN_INDEX;
241  goto error_occurred;
242  }
243  strncpy(devname,iflist_head->ifaddr_ptr->ifa_name,IFNAMSIZ);
244  } else {
245  // Multiple interfaces found -> use the value of 'index'
246  if(index>=ifno) {
247  return_value=ERR_WLAN_INDEX;
248  goto error_occurred;
249  }
250  return_value=ifno; // Return the number of interfaces found
251  // Iterate the list until the chosen interface is reached
252  iflist_it=iflist_head;
253  while(index<=ifno-2) {
254  iflist_it=iflist_it->next;
255  index++;
256  }
257  strncpy(devname,iflist_it->ifaddr_ptr->ifa_name,IFNAMSIZ);
258  }
259  }
260 
261  // Get MAC address of the interface (if requested by the user with a non-NULL mac)
262  if(mac!=NULL) {
263  strncpy(wifireq.ifr_name,devname,IFNAMSIZ);
264  if(ioctl(sFd,SIOCGIFHWADDR,&wifireq)!=-1) {
265  memcpy(mac,wifireq.ifr_hwaddr.sa_data,MAC_ADDR_SIZE);
266  } else {
267  return_value=ERR_WLAN_GETSRCMAC;
268  goto error_occurred;
269  }
270  }
271 
272  // Get interface index of the interface (if requested by the user with a non-NULL ifindex)
273  if(ifindex!=NULL) {
274  strncpy(wifireq.ifr_name,devname,IFNAMSIZ);
275  if(ioctl(sFd,SIOCGIFINDEX,&wifireq)!=-1) {
276  *ifindex=wifireq.ifr_ifindex;
277  } else {
278  return_value=ERR_WLAN_GETIFINDEX;
279  goto error_occurred;
280  }
281  }
282 
283  // Get the IP address of the interface (if requested by the user with a non-NULL struct in_addr)
284  if(srcIP!=NULL) {
285  strncpy(wifireq.ifr_name,devname,IFNAMSIZ);
286  wifireq.ifr_addr.sa_family = AF_INET;
287  if(ioctl(sFd,SIOCGIFADDR,&wifireq)!=-1) {
288  *srcIP=((struct sockaddr_in*)&wifireq.ifr_addr)->sin_addr;
289  } else {
290  return_value=ERR_WLAN_GETSRCIP;
291  // No need to go to error_occurred, as we are already there
292  }
293  }
294 
295  error_occurred:
296  // iflist and the other list are no more useful -> free them
297  freeifaddrs(ifaddr_head);
298  for(iflist_it=iflist_head;iflist_it!=NULL;iflist_it=iflist_u) {
299  iflist_u=iflist_it->next;
300  free(iflist_it);
301  }
302 
303  getifaddrs_error_occurred:
304  // Close socket
305  close(sFd);
306 
307  sock_error_occurred:
308  return return_value;
309 }
310 
327 rawsockerr_t vifPrinter(FILE *stream) {
328  int sFd=-1;
329  struct ifaddrs *ifaddr_head, *ifaddr_it;
330  struct ifreq wifireq;
331  int wlan_ifno=0;
332  int nonwlan_ifno=0;
333 
334  // Open socket (needed)
335  sFd=socket(AF_INET,SOCK_DGRAM,0); // Any socket should be fine (to be better investigated!)
336  if(sFd==-1) {
337  return ERR_VIFPRINTER_SOCK;
338  }
339 
340  // Getting all interface addresses
341  if(getifaddrs(&ifaddr_head)==-1) {
342  close(sFd);
344  }
345 
346  fprintf(stream,"Interface name | Interface type | Interface internal index\n"
347  "-------------- | -------------- | ------------------------\n");
348 
349  // Looking for wlan interfaces
350  memset(&wifireq,0,sizeof(wifireq));
351  // Iterating over the interfaces linked list
352  for(ifaddr_it=ifaddr_head;ifaddr_it!=NULL;ifaddr_it=ifaddr_it->ifa_next) {
353  if(ifaddr_it->ifa_addr!=NULL && (ifaddr_it->ifa_flags & IFF_LOOPBACK) && ifaddr_it->ifa_addr->sa_family==AF_PACKET) {
354  fprintf(stream,"%s\t\t | %-14s | %s\t\n",ifaddr_it->ifa_name,"Loopback","(lo)");
355  } else {
356  if(ifaddr_it->ifa_addr!=NULL && ifaddr_it->ifa_addr->sa_family==AF_PACKET) {
357  strncpy(wifireq.ifr_name,ifaddr_it->ifa_name,IFNAMSIZ);
358  if(ioctl(sFd,SIOCGIWNAME,&wifireq)!=-1) {
359  if(ioctl(sFd,SIOCGIFFLAGS,&wifireq)!=-1 && (wifireq.ifr_flags & IFF_UP)) {
360  // If the interface is up, print the information related to such interface
361  fprintf(stream,"%-*s | %-14s | (wlan) %d\t\n",IFNAMSIZ,ifaddr_it->ifa_name,"Wireless",wlan_ifno);
362  wlan_ifno++;
363  }
364  } else {
365  // Interface is not wireless
366  if(ifaddr_it->ifa_addr!=NULL && (ifaddr_it->ifa_flags & IFF_UP)) {
367  fprintf(stream,"%-*s | %-14s | (non-wlan) %d\t\n",IFNAMSIZ,ifaddr_it->ifa_name,"Non-wireless",nonwlan_ifno);
368  nonwlan_ifno++;
369  }
370  }
371  } else if(ifaddr_it->ifa_addr!=NULL && ifaddr_it->ifa_addr->sa_family==AF_INET && is_if_tun(sFd,ifaddr_it->ifa_name)) {
372  fprintf(stream,"%-*s | %-14s | (non-wlan) %d\t\n",IFNAMSIZ,ifaddr_it->ifa_name,"tun (AF_INET)",nonwlan_ifno);
373  nonwlan_ifno++;
374  }
375  }
376  }
377 
378  return 1;
379 }
380 
399 void rs_printerror(FILE *stream,rawsockerr_t code) {
400  switch(code) {
401  case ERR_WLAN_NOIF:
402  fprintf(stream,"wlanLookup: No interfaces found.\n");
403  break;
404 
405  case ERR_WLAN_SOCK:
406  fprintf(stream,"wlanLookup: socket creation error.\n");
407  break;
408 
409  case ERR_WLAN_GETIFADDRS:
410  fprintf(stream,"wlanLookup: getifaddrs() error.\n");
411  break;
412 
413  case ERR_WLAN_INDEX:
414  fprintf(stream,"wlanLookup: wrong index specified.\n");
415  break;
416 
417  case ERR_WLAN_GETSRCMAC:
418  fprintf(stream,"wlanLookup: unable to get source MAC address.\n");
419  break;
420 
421  case ERR_WLAN_GETIFINDEX:
422  fprintf(stream,"wlanLookup: unable to get interface index.\n");
423  break;
424 
425  case ERR_WLAN_GETSRCIP:
426  fprintf(stream,"wlanLookup: unable to get source IP address.\n");
427  break;
428 
429  case ERR_IPHEAD_SOCK:
430  fprintf(stream,"IP4headPopulateB: socket creation error.\n");
431  break;
432 
434  fprintf(stream,"IP4headPopulateB: unable to retrieve source IP address.\n");
435  break;
436 
437  default:
438  fprintf(stream,"No error.\n");
439  }
440 }
441 
459 void display_packet(const char *text,byte_t *packet,unsigned int len) {
460  int i;
461 
462  fprintf(stdout,"%s -> ",text);
463  for(i=0;i<len;i++) {
464  fprintf(stdout,"%02x ",packet[i]);
465  }
466  fprintf(stdout,"\n");
467  fflush(stdout);
468 }
469 
487 void display_packetc(const char *text,byte_t *packet,unsigned int len) {
488  int i;
489 
490  fprintf(stdout,"%s -> ",text);
491  for(i=0;i<len;i++) {
492  fprintf(stdout,"%c",packet[i]);
493  }
494  fprintf(stdout,"\n");
495  fflush(stdout);
496 }
497 
513 uint64_t hton64 (uint64_t hostu64) {
514  return swap64(hostu64,&htonl);
515 }
516 
532 uint64_t ntoh64 (uint64_t netu64) {
533  return swap64(netu64,&ntohl);
534 }
535 
556 void etherheadPopulateB(struct ether_header *etherHeader, macaddr_t mac, ethertype_t type) {
557  unsigned char broadcastMAC[ETHER_ADDR_LEN]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
558 
559  memcpy(etherHeader->ether_dhost,broadcastMAC,ETHER_ADDR_LEN);
560  memcpy(etherHeader->ether_shost,mac,ETHER_ADDR_LEN);
561  etherHeader->ether_type = htons(type);
562 }
563 
587 void etherheadPopulate(struct ether_header *etherHeader, macaddr_t macsrc, macaddr_t macdst, ethertype_t type) {
588  memcpy(etherHeader->ether_dhost,macdst,ETHER_ADDR_LEN);
589  memcpy(etherHeader->ether_shost,macsrc,ETHER_ADDR_LEN);
590  etherHeader->ether_type = htons(type);
591 }
592 
612 size_t etherEncapsulate(byte_t *packet,struct ether_header *header,byte_t *sdu,size_t sdusize) {
613  size_t packetsize=sizeof(struct ether_header)+sdusize;
614 
615  memcpy(packet,header,sizeof(struct ether_header));
616  memcpy(packet+sizeof(struct ether_header),sdu,sdusize);
617 
618  return packetsize;
619 }
620 
633 void getSrcMAC(struct ether_header *etherHeader, macaddr_t macsrc) {
634  if(macsrc) {
635  memcpy(macsrc,etherHeader->ether_shost,ETHER_ADDR_LEN);
636  }
637 }
638 
678 rawsockerr_t IP4headPopulate(struct iphdr *IPhead, char *devname, char *destIP, unsigned char tos,unsigned short frag_offset, unsigned char ttl, unsigned char protocol,unsigned int flags,struct ipaddrs *addrs) {
679  struct in_addr destIPAddr;
680  int sFd; // To get the current IP address
681  struct ifreq wifireq;
682 
683  IPhead->ihl=BASIC_IHL;
684  IPhead->version=IPV4;
685  IPhead->tos=(__u8) tos;
686  IPhead->frag_off=htons(frag_offset);
687  IPhead->frag_off=(IPhead->frag_off) | flags;
688  IPhead->ttl=(__u8) ttl;
689  IPhead->protocol=(__u8) protocol;
690  inet_pton(AF_INET,destIP,(struct in_addr *)&destIPAddr);
691  IPhead->daddr=destIPAddr.s_addr;
692 
693  // Get own IP address
694  sFd=socket(AF_INET,SOCK_DGRAM,0);
695  if(sFd==-1) {
696  return ERR_IPHEAD_SOCK;
697  }
698  strncpy(wifireq.ifr_name,devname,IFNAMSIZ);
699  wifireq.ifr_addr.sa_family = AF_INET;
700  if(ioctl(sFd,SIOCGIFADDR,&wifireq)!=0) {
701  close(sFd);
702  return ERR_IPHEAD_NOSRCADDR;
703  }
704  close(sFd);
705  IPhead->saddr=((struct sockaddr_in*)&wifireq.ifr_addr)->sin_addr.s_addr;
706  if(addrs!=NULL) {
707  addrs->src=IPhead->saddr;
708  addrs->dst=IPhead->daddr;
709  }
710 
711  // Initialize checksum to 0
712  IPhead->check=0;
713 
714  // Initialize ID to 0
715  IPhead->id=0;
716 
717  return 0;
718 }
719 
755 rawsockerr_t IP4headPopulateS(struct iphdr *IPhead, char *devname, struct in_addr destIP, unsigned char tos,unsigned short frag_offset, unsigned char ttl, unsigned char protocol,unsigned int flags,struct ipaddrs *addrs) {
756  int sFd; // To get the current IP address
757  struct ifreq wifireq;
758 
759  IPhead->ihl=BASIC_IHL;
760  IPhead->version=IPV4;
761  IPhead->tos=(__u8) tos;
762  IPhead->frag_off=htons(frag_offset);
763  IPhead->frag_off=(IPhead->frag_off) | flags;
764  IPhead->ttl=(__u8) ttl;
765  IPhead->protocol=(__u8) protocol;
766  IPhead->daddr=destIP.s_addr;
767 
768  // Get own IP address
769  sFd=socket(AF_INET,SOCK_DGRAM,0);
770  if(sFd==-1) {
771  return ERR_IPHEAD_SOCK;
772  }
773  strncpy(wifireq.ifr_name,devname,IFNAMSIZ);
774  wifireq.ifr_addr.sa_family = AF_INET;
775  if(ioctl(sFd,SIOCGIFADDR,&wifireq)!=0) {
776  close(sFd);
777  return ERR_IPHEAD_NOSRCADDR;
778  }
779  close(sFd);
780  IPhead->saddr=((struct sockaddr_in*)&wifireq.ifr_addr)->sin_addr.s_addr;
781  if(addrs!=NULL) {
782  addrs->src=IPhead->saddr;
783  addrs->dst=IPhead->daddr;
784  }
785 
786  // Initialize checksum to 0
787  IPhead->check=0;
788 
789  // Initialize ID to 0
790  IPhead->id=0;
791 
792  return 0;
793 }
794 
830 rawsockerr_t IP4headPopulateB(struct iphdr *IPhead, char *devname,unsigned char tos,unsigned short frag_offset, unsigned char ttl, unsigned char protocol,unsigned int flags,struct ipaddrs *addrs) {
831  struct in_addr broadIPAddr;
832  int sFd; // To get the current IP address
833  struct ifreq wifireq;
834 
835  IPhead->ihl=BASIC_IHL;
836  IPhead->version=IPV4;
837  IPhead->tos=(__u8) tos;
838  IPhead->frag_off=htons(frag_offset);
839  IPhead->frag_off=(IPhead->frag_off) | flags;
840  IPhead->ttl=(__u8) ttl;
841  IPhead->protocol=(__u8) protocol;
842  inet_pton(AF_INET,"255.255.255.255",(struct in_addr *)&broadIPAddr);
843  IPhead->daddr=broadIPAddr.s_addr;
844 
845  // Get own IP address
846  sFd=socket(AF_INET,SOCK_DGRAM,0);
847  if(sFd==-1) {
848  return ERR_IPHEAD_SOCK;
849  }
850  strncpy(wifireq.ifr_name,devname,IFNAMSIZ);
851  wifireq.ifr_addr.sa_family = AF_INET;
852  if(ioctl(sFd,SIOCGIFADDR,&wifireq)!=0) {
853  close(sFd);
854  return ERR_IPHEAD_NOSRCADDR;
855  }
856  close(sFd);
857  IPhead->saddr=((struct sockaddr_in*)&wifireq.ifr_addr)->sin_addr.s_addr;
858  if(addrs!=NULL) {
859  addrs->src=IPhead->saddr;
860  addrs->dst=IPhead->daddr;
861  }
862 
863  // Initialize checksum to 0
864  IPhead->check=0;
865 
866  // Initialize ID to 0
867  IPhead->id=0;
868 
869  return 0;
870 }
871 
886 void IP4headAddID(struct iphdr *IPhead, unsigned short id) {
887  IPhead->id=htons(id);
888 }
889 
904 void IP4headAddTotLen(struct iphdr *IPhead, unsigned short len) {
905  IPhead->tot_len=htons(len);
906 }
907 
926 size_t IP4Encapsulate(byte_t *packet,struct iphdr *header,byte_t *sdu,size_t sdusize) {
927  size_t packetsize=sizeof(struct iphdr)+sdusize;
928 
929  header->tot_len=htons(packetsize);
930  header->check=0; // Reset to 0 in case of subsequent calls
931 
932  header->check=ip_fast_csum((__u8 *)header, BASIC_IHL);
933 
934  memcpy(packet,header,sizeof(struct iphdr));
935  memcpy(packet+sizeof(struct iphdr),sdu,sdusize);
936 
937  return packetsize;
938 }
939 
960 void UDPheadPopulate(struct udphdr *UDPhead, unsigned short sourceport, unsigned short destport) {
961  UDPhead->source=htons(sourceport);
962  UDPhead->dest=htons(destport);
963 
964  // Initialize checksum to 0
965  UDPhead->check=0;
966 }
967 
988 size_t UDPencapsulate(byte_t *packet,struct udphdr *header,byte_t *data,size_t payloadsize,struct ipaddrs addrs) {
989  size_t packetsize=sizeof(struct udphdr)+payloadsize;
990 
991  header->len=htons(packetsize);
992  header->check=0; // Reset to 0 in case of subsequent calls
993 
994  memcpy(packet,header,sizeof(struct udphdr));
995  memcpy(packet+sizeof(struct udphdr),data,payloadsize);
996 
997  header->check=minirighi_udp_checksum(packet,packetsize,addrs.src,addrs.dst);
998 
999  memcpy(packet,header,sizeof(struct udphdr));
1000 
1001  return packetsize;
1002 }
1003 
1034 byte_t *UDPgetpacketpointers(byte_t *pktbuf,struct ether_header **etherHeader, struct iphdr **IPheader,struct udphdr **UDPheader) {
1035  byte_t *payload=NULL;
1036 
1037  if(pktbuf!=NULL) {
1038  if(etherHeader) *etherHeader=(struct ether_header*) pktbuf;
1039  if(IPheader) *IPheader=(struct iphdr*)(pktbuf+sizeof(struct ether_header));
1040  if(UDPheader) *UDPheader=(struct udphdr*)(pktbuf+sizeof(struct ether_header)+sizeof(struct iphdr));
1041  payload=(pktbuf+sizeof(struct ether_header)+sizeof(struct iphdr)+sizeof(struct udphdr));
1042  } else {
1043  payload=NULL;
1044  }
1045 
1046  return payload;
1047 }
1048 
1060 unsigned short UDPgetpayloadsize(struct udphdr *UDPheader) {
1061  return (ntohs(UDPheader->len)-UDPHEADERLEN);
1062 }
1063 
1099 bool validateEthCsum(byte_t *packet, csum16_t csum, csum16_t *combinedcsum, csumt_t type, void *args) {
1100  csum16_t currCsum;
1101  bool returnVal=false;
1102  void *headerPtr; // Generic header pointer
1103  void *payloadPtr; // Generic payload/SDU pointer
1104  size_t packetsize; // Used in UDP checksum calculation
1105  __sum16 storedCsum; // To store the current value of checksum, read from 'packet'
1106 
1107  // Directly return 'false' (as an error occurred) if a combined type is specified but combinedcsum is NULL
1108  if(type>=0x80 && combinedcsum==NULL) {
1109  return false;
1110  }
1111 
1112  // Discriminate the different protocols
1113  switch(type) {
1114  case CSUM_IP:
1115  headerPtr=(struct iphdr*)(packet+sizeof(struct ether_header));
1116 
1117  // Checksum should start with a value of 0x0000 in order to be correctly computed:
1118  // set it to 0 and restore it, to avoid making a copy of the packet in memory
1119  storedCsum=((struct iphdr *) headerPtr)->check;
1120  ((struct iphdr *) headerPtr)->check=0;
1121 
1122  currCsum=ip_fast_csum((__u8 *)headerPtr, ((struct iphdr *) headerPtr)->ihl);
1123 
1124  ((struct iphdr *) headerPtr)->check=storedCsum;
1125 
1126  returnVal=(currCsum==csum);
1127  break;
1128  case CSUM_UDP:
1129  case CSUM_UDPIP:
1130  // payloadsize should be specified, otherwise 'false' will be always returneds
1131  if(args==NULL) {
1132  returnVal=false;
1133  } else {
1134  // Get packetsize
1135  packetsize=sizeof(struct udphdr)+*((size_t *) args);
1136 
1137  headerPtr=(struct iphdr*)(packet+sizeof(struct ether_header));
1138  payloadPtr=(struct udphdr*)(packet+sizeof(struct ether_header)+sizeof(struct iphdr));
1139 
1140  storedCsum=((struct udphdr *) payloadPtr)->check;
1141  ((struct udphdr *) payloadPtr)->check=0;
1142 
1143  currCsum=minirighi_udp_checksum(payloadPtr,packetsize,((struct iphdr *)headerPtr)->saddr,((struct iphdr *)headerPtr)->daddr);
1144 
1145  ((struct udphdr *) payloadPtr)->check=storedCsum;
1146 
1147  returnVal=(currCsum==csum);
1148 
1149  if(type==CSUM_UDPIP) {
1150  if(combinedcsum==NULL) {
1151  returnVal=false;
1152  } else {
1153  // Compute IP checksum
1154  storedCsum=((struct iphdr *) headerPtr)->check;
1155  ((struct iphdr *) headerPtr)->check=0;
1156 
1157  currCsum=ip_fast_csum((__u8 *)headerPtr, ((struct iphdr *)headerPtr)->ihl);
1158 
1159  ((struct iphdr *) headerPtr)->check=storedCsum;
1160 
1161  returnVal=returnVal && (currCsum==(*combinedcsum));
1162  }
1163  }
1164  }
1165  break;
1166  default:
1167  returnVal=false;
1168  }
1169 
1170  return returnVal;
1171 }
1172 
1186  // Get header pointer
1187  struct iphdr *IPheader=(struct iphdr *) IPpacket;
1188 
1189  if(IPpacket!=NULL) {
1190  // Change checksum, avoiding possible overflow situations
1191  if(IPheader->check!=0xFF) {
1192  IPheader->check=IPheader->check+1;
1193  } else {
1194  IPheader->check=0x00;
1195  }
1196  }
1197 }
1198 
1212  // Get header pointer
1213  struct udphdr *UDPheader=(struct udphdr *) UDPpacket;
1214 
1215  if(UDPheader!=NULL) {
1216  // Change checksum, avoiding possible overflow situations
1217  if(UDPheader->check!=0xFF) {
1218  UDPheader->check=UDPheader->check+1;
1219  } else {
1220  UDPheader->check=0x00;
1221  }
1222  }
1223 }
#define ERR_WLAN_SOCK
Definition: rawsock.h:32
#define CSUM_UDP
Definition: rawsock.h:80
void display_packet(const char *text, byte_t *packet, unsigned int len)
Display packet in hexadecimal form.
Definition: rawsock.c:459
size_t etherEncapsulate(byte_t *packet, struct ether_header *header, byte_t *sdu, size_t sdusize)
Combine Ethernet SDU and PCI.
Definition: rawsock.c:612
unsigned char csumt_t
Definition: rawsock.h:108
void etherheadPopulate(struct ether_header *etherHeader, macaddr_t macsrc, macaddr_t macdst, ethertype_t type)
Populate Ethernet header.
Definition: rawsock.c:587
size_t IP4Encapsulate(byte_t *packet, struct iphdr *header, byte_t *sdu, size_t sdusize)
Combine IPv4 SDU and PCI.
Definition: rawsock.c:926
#define IPV4
Definition: rawsock.h:66
#define ERR_WLAN_GETIFINDEX
Definition: rawsock.h:36
#define ERR_WLAN_INDEX
Definition: rawsock.h:34
#define ERR_VIFPRINTER_SOCK
Definition: rawsock.h:42
void etherheadPopulateB(struct ether_header *etherHeader, macaddr_t mac, ethertype_t type)
Populate broadcast Ethernet header (variant of etherheadPopulate())
Definition: rawsock.c:556
#define CSUM_UDPIP
Definition: rawsock.h:81
#define MAC_ZERO
Definition: rawsock.h:54
void getSrcMAC(struct ether_header *etherHeader, macaddr_t macsrc)
Retrieve source MAC address field from Ethernet header.
Definition: rawsock.c:633
unsigned int macAddrTypeGet(macaddr_t mac)
Get the MAC address type.
Definition: rawsock.c:96
uint64_t ntoh64(uint64_t netu64)
Convert a 64-bit unsigned value between network and host byte order.
Definition: rawsock.c:532
#define ERR_WLAN_GETSRCIP
Definition: rawsock.h:37
Structure to store a couple of source and destinaion IPv4 addresses.
Definition: rawsock.h:115
macaddr_t prepareMacAddrT()
Prepare a macaddr_t variable.
Definition: rawsock.c:54
uint8_t * macaddr_t
Definition: rawsock.h:105
void freeMacAddrT(macaddr_t mac)
Free a macaddr_t variable.
Definition: rawsock.c:78
bool validateEthCsum(byte_t *packet, csum16_t csum, csum16_t *combinedcsum, csumt_t type, void *args)
Validate the checksum of a raw "Ethernet" packet, i.e. of any packet containing a struct ether_header...
Definition: rawsock.c:1099
#define MAC_BROADCAST
Definition: rawsock.h:51
uint64_t hton64(uint64_t hostu64)
Convert a 64-bit unsigned value between host and network byte order.
Definition: rawsock.c:513
#define ERR_WLAN_GETIFADDRS
Definition: rawsock.h:33
void rs_printerror(FILE *stream, rawsockerr_t code)
Print more detailed error messages.
Definition: rawsock.c:399
#define ERR_WLAN_GETSRCMAC
Definition: rawsock.h:35
#define MAC_UNICAST
Definition: rawsock.h:52
rawsockerr_t IP4headPopulateB(struct iphdr *IPhead, char *devname, unsigned char tos, unsigned short frag_offset, unsigned char ttl, unsigned char protocol, unsigned int flags, struct ipaddrs *addrs)
Populate broadcast IP version 4 header (variant of IP4headPopulate())
Definition: rawsock.c:830
__sum16 csum16_t
Definition: rawsock.h:109
rawsockerr_t vifPrinter(FILE *stream)
Print information about available interfaces.
Definition: rawsock.c:327
#define MAC_NULL
Definition: rawsock.h:50
void UDPheadPopulate(struct udphdr *UDPhead, unsigned short sourceport, unsigned short destport)
Populate UDP header.
Definition: rawsock.c:960
void test_injectIPCsumError(byte_t *IPpacket)
Test function: inject a checksum error in an IP packet.
Definition: rawsock.c:1185
rawsockerr_t wlanLookup(char *devname, int *ifindex, macaddr_t mac, struct in_addr *srcIP, int index, int mode)
Automatically look for available WLAN, non-WLAN or loopback interfaces.
Definition: rawsock.c:149
unsigned short UDPgetpayloadsize(struct udphdr *UDPheader)
Get UDP payload size, given a UDP header.
Definition: rawsock.c:1060
rawsockerr_t IP4headPopulateS(struct iphdr *IPhead, char *devname, struct in_addr destIP, unsigned char tos, unsigned short frag_offset, unsigned char ttl, unsigned char protocol, unsigned int flags, struct ipaddrs *addrs)
Populate IP version 4 header with struct in_addr addresses (variant of IP4headPopulate()) ...
Definition: rawsock.c:755
uint8_t byte_t
Definition: rawsock.h:102
in_addr_t src
Definition: rawsock.h:116
size_t UDPencapsulate(byte_t *packet, struct udphdr *header, byte_t *data, size_t payloadsize, struct ipaddrs addrs)
Combine UDP payload and header.
Definition: rawsock.c:988
void IP4headAddTotLen(struct iphdr *IPhead, unsigned short len)
Add Total Length to a given IPv4 header.
Definition: rawsock.c:904
unsigned short ethertype_t
Definition: rawsock.h:106
#define MAC_ADDR_SIZE
Definition: rawsock.h:28
int rawsockerr_t
Definition: rawsock.h:107
#define UDPHEADERLEN
Definition: rawsock.h:70
#define ERR_IPHEAD_NOSRCADDR
Definition: rawsock.h:40
#define ERR_VIFPRINTER_GETIFADDRS
Definition: rawsock.h:43
#define MAC_MULTICAST
Definition: rawsock.h:53
#define WLANLOOKUP_NONWLAN
Definition: rawsock.h:47
in_addr_t dst
Definition: rawsock.h:117
uint16_t minirighi_udp_checksum(const void *buff, size_t len, in_addr_t src_addr, in_addr_t dest_addr)
Calculate the UDP checksum (calculated with the whole packet)
#define CSUM_IP
Definition: rawsock.h:79
#define WLANLOOKUP_WLAN
Definition: rawsock.h:46
#define ERR_WLAN_NOIF
Definition: rawsock.h:31
void IP4headAddID(struct iphdr *IPhead, unsigned short id)
Add ID to a given IPv4 header.
Definition: rawsock.c:886
void test_injectUDPCsumError(byte_t *UDPpacket)
Test function: inject a checksum error in an UDP packet.
Definition: rawsock.c:1211
#define BASIC_IHL
Definition: rawsock.h:65
rawsockerr_t IP4headPopulate(struct iphdr *IPhead, char *devname, char *destIP, unsigned char tos, unsigned short frag_offset, unsigned char ttl, unsigned char protocol, unsigned int flags, struct ipaddrs *addrs)
Populate IP version 4 header.
Definition: rawsock.c:678
__sum16 ip_fast_csum(const void *iph, unsigned int ihl)
Calculate the IPv4 checksum (optimized for IP headers, which always checksum on 4 octet boundaries) ...
Definition: ipcsum_alth.c:84
void display_packetc(const char *text, byte_t *packet, unsigned int len)
Display packet in character form.
Definition: rawsock.c:487
#define ERR_IPHEAD_SOCK
Definition: rawsock.h:39
byte_t * UDPgetpacketpointers(byte_t *pktbuf, struct ether_header **etherHeader, struct iphdr **IPheader, struct udphdr **UDPheader)
Get pointers to headers and payload in UDP packet buffer.
Definition: rawsock.c:1034