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> 18 static uint64_t swap64(uint64_t unsignedvalue, uint32_t (*swap_byte_order)(uint32_t)) {
19 #if __BYTE_ORDER == __BIG_ENDIAN 21 #elif __BYTE_ORDER == __LITTLE_ENDIAN 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));
28 #error "The system seems to be neither little endian nor big endian..." 32 static uint8_t is_if_tun(
int sFd,
char *devname) {
33 struct ethtool_drvinfo drvinfo;
34 struct ifreq ethtool_ifr;
36 drvinfo.cmd=ETHTOOL_GDRVINFO;
37 strncpy(ethtool_ifr.ifr_name,devname,IFNAMSIZ);
38 ethtool_ifr.ifr_data=(
void *)&drvinfo;
40 return ioctl(sFd,SIOCETHTOOL,ðtool_ifr)!=-1 && strncmp(drvinfo.bus_info,
"tun",ETHTOOL_BUSINFO_LEN)==0;
100 }
else if(mac[0]==0xFF && mac[1]==0xFF && mac[2]==0xFF && mac[3]==0xFF && mac[4]==0xFF && mac[5]==0xFF) {
102 }
else if(mac[0]==0x00 && mac[1]==0x00 && mac[2]==0x00 && mac[3]==0x00 && mac[4]==0x00 && mac[5]==0x00) {
153 struct ifaddrs *ifaddr_head, *ifaddr_it;
155 struct ifreq wifireq;
157 struct iflist *iflist_head=NULL;
158 struct iflist *curr_ptr=NULL;
159 struct iflist *iflist_it=NULL;
160 struct iflist *iflist_u=NULL;
170 struct ifaddrs *ifaddr_ptr;
174 sFd=socket(AF_INET,SOCK_DGRAM,0);
177 goto sock_error_occurred;
181 if(getifaddrs(&ifaddr_head)==-1) {
183 goto getifaddrs_error_occurred;
187 memset(&wifireq,0,
sizeof(wifireq));
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)) {
192 strncpy(devname,ifaddr_it->ifa_name,IFNAMSIZ);
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)))) {
205 strncpy(wifireq.ifr_name,ifaddr_it->ifa_name,IFNAMSIZ);
208 ioctl_result=ioctl(sFd,SIOCGIWNAME,&wifireq);
212 if(ifaddr_it->ifa_addr!=NULL && (ifaddr_it->ifa_flags & IFF_UP) && !(ifaddr_it->ifa_flags & IFF_LOOPBACK)) {
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;
222 curr_ptr->next=iflist_head;
223 iflist_head=curr_ptr;
234 if(iflist_head==NULL) {
243 strncpy(devname,iflist_head->ifaddr_ptr->ifa_name,IFNAMSIZ);
252 iflist_it=iflist_head;
253 while(index<=ifno-2) {
254 iflist_it=iflist_it->next;
257 strncpy(devname,iflist_it->ifaddr_ptr->ifa_name,IFNAMSIZ);
263 strncpy(wifireq.ifr_name,devname,IFNAMSIZ);
264 if(ioctl(sFd,SIOCGIFHWADDR,&wifireq)!=-1) {
274 strncpy(wifireq.ifr_name,devname,IFNAMSIZ);
275 if(ioctl(sFd,SIOCGIFINDEX,&wifireq)!=-1) {
276 *ifindex=wifireq.ifr_ifindex;
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;
297 freeifaddrs(ifaddr_head);
298 for(iflist_it=iflist_head;iflist_it!=NULL;iflist_it=iflist_u) {
299 iflist_u=iflist_it->next;
303 getifaddrs_error_occurred:
329 struct ifaddrs *ifaddr_head, *ifaddr_it;
330 struct ifreq wifireq;
335 sFd=socket(AF_INET,SOCK_DGRAM,0);
341 if(getifaddrs(&ifaddr_head)==-1) {
346 fprintf(stream,
"Interface name | Interface type | Interface internal index\n" 347 "-------------- | -------------- | ------------------------\n");
350 memset(&wifireq,0,
sizeof(wifireq));
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)");
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)) {
361 fprintf(stream,
"%-*s | %-14s | (wlan) %d\t\n",IFNAMSIZ,ifaddr_it->ifa_name,
"Wireless",wlan_ifno);
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);
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);
402 fprintf(stream,
"wlanLookup: No interfaces found.\n");
406 fprintf(stream,
"wlanLookup: socket creation error.\n");
410 fprintf(stream,
"wlanLookup: getifaddrs() error.\n");
414 fprintf(stream,
"wlanLookup: wrong index specified.\n");
418 fprintf(stream,
"wlanLookup: unable to get source MAC address.\n");
422 fprintf(stream,
"wlanLookup: unable to get interface index.\n");
426 fprintf(stream,
"wlanLookup: unable to get source IP address.\n");
430 fprintf(stream,
"IP4headPopulateB: socket creation error.\n");
434 fprintf(stream,
"IP4headPopulateB: unable to retrieve source IP address.\n");
438 fprintf(stream,
"No error.\n");
462 fprintf(stdout,
"%s -> ",text);
464 fprintf(stdout,
"%02x ",packet[i]);
466 fprintf(stdout,
"\n");
490 fprintf(stdout,
"%s -> ",text);
492 fprintf(stdout,
"%c",packet[i]);
494 fprintf(stdout,
"\n");
514 return swap64(hostu64,&htonl);
533 return swap64(netu64,&ntohl);
557 unsigned char broadcastMAC[ETHER_ADDR_LEN]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
559 memcpy(etherHeader->ether_dhost,broadcastMAC,ETHER_ADDR_LEN);
560 memcpy(etherHeader->ether_shost,mac,ETHER_ADDR_LEN);
561 etherHeader->ether_type = htons(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);
613 size_t packetsize=
sizeof(
struct ether_header)+sdusize;
615 memcpy(packet,header,
sizeof(
struct ether_header));
616 memcpy(packet+
sizeof(
struct ether_header),sdu,sdusize);
635 memcpy(macsrc,etherHeader->ether_shost,ETHER_ADDR_LEN);
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;
681 struct ifreq wifireq;
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;
694 sFd=socket(AF_INET,SOCK_DGRAM,0);
698 strncpy(wifireq.ifr_name,devname,IFNAMSIZ);
699 wifireq.ifr_addr.sa_family = AF_INET;
700 if(ioctl(sFd,SIOCGIFADDR,&wifireq)!=0) {
705 IPhead->saddr=((
struct sockaddr_in*)&wifireq.ifr_addr)->sin_addr.s_addr;
707 addrs->
src=IPhead->saddr;
708 addrs->
dst=IPhead->daddr;
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) {
757 struct ifreq wifireq;
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;
769 sFd=socket(AF_INET,SOCK_DGRAM,0);
773 strncpy(wifireq.ifr_name,devname,IFNAMSIZ);
774 wifireq.ifr_addr.sa_family = AF_INET;
775 if(ioctl(sFd,SIOCGIFADDR,&wifireq)!=0) {
780 IPhead->saddr=((
struct sockaddr_in*)&wifireq.ifr_addr)->sin_addr.s_addr;
782 addrs->
src=IPhead->saddr;
783 addrs->
dst=IPhead->daddr;
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;
833 struct ifreq wifireq;
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;
846 sFd=socket(AF_INET,SOCK_DGRAM,0);
850 strncpy(wifireq.ifr_name,devname,IFNAMSIZ);
851 wifireq.ifr_addr.sa_family = AF_INET;
852 if(ioctl(sFd,SIOCGIFADDR,&wifireq)!=0) {
857 IPhead->saddr=((
struct sockaddr_in*)&wifireq.ifr_addr)->sin_addr.s_addr;
859 addrs->
src=IPhead->saddr;
860 addrs->
dst=IPhead->daddr;
887 IPhead->id=htons(
id);
905 IPhead->tot_len=htons(len);
927 size_t packetsize=
sizeof(
struct iphdr)+sdusize;
929 header->tot_len=htons(packetsize);
934 memcpy(packet,header,
sizeof(
struct iphdr));
935 memcpy(packet+
sizeof(
struct iphdr),sdu,sdusize);
960 void UDPheadPopulate(
struct udphdr *UDPhead,
unsigned short sourceport,
unsigned short destport) {
961 UDPhead->source=htons(sourceport);
962 UDPhead->dest=htons(destport);
989 size_t packetsize=
sizeof(
struct udphdr)+payloadsize;
991 header->len=htons(packetsize);
994 memcpy(packet,header,
sizeof(
struct udphdr));
995 memcpy(packet+
sizeof(
struct udphdr),data,payloadsize);
999 memcpy(packet,header,
sizeof(
struct udphdr));
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));
1101 bool returnVal=
false;
1108 if(type>=0x80 && combinedcsum==NULL) {
1115 headerPtr=(
struct iphdr*)(packet+
sizeof(
struct ether_header));
1119 storedCsum=((
struct iphdr *) headerPtr)->check;
1120 ((
struct iphdr *) headerPtr)->check=0;
1122 currCsum=
ip_fast_csum((__u8 *)headerPtr, ((
struct iphdr *) headerPtr)->ihl);
1124 ((
struct iphdr *) headerPtr)->check=storedCsum;
1126 returnVal=(currCsum==csum);
1135 packetsize=
sizeof(
struct udphdr)+*((
size_t *) args);
1137 headerPtr=(
struct iphdr*)(packet+
sizeof(
struct ether_header));
1138 payloadPtr=(
struct udphdr*)(packet+
sizeof(
struct ether_header)+
sizeof(
struct iphdr));
1140 storedCsum=((
struct udphdr *) payloadPtr)->check;
1141 ((
struct udphdr *) payloadPtr)->check=0;
1143 currCsum=
minirighi_udp_checksum(payloadPtr,packetsize,((
struct iphdr *)headerPtr)->saddr,((
struct iphdr *)headerPtr)->daddr);
1145 ((
struct udphdr *) payloadPtr)->check=storedCsum;
1147 returnVal=(currCsum==csum);
1150 if(combinedcsum==NULL) {
1154 storedCsum=((
struct iphdr *) headerPtr)->check;
1155 ((
struct iphdr *) headerPtr)->check=0;
1157 currCsum=
ip_fast_csum((__u8 *)headerPtr, ((
struct iphdr *)headerPtr)->ihl);
1159 ((
struct iphdr *) headerPtr)->check=storedCsum;
1161 returnVal=returnVal && (currCsum==(*combinedcsum));
1187 struct iphdr *IPheader=(
struct iphdr *) IPpacket;
1189 if(IPpacket!=NULL) {
1191 if(IPheader->check!=0xFF) {
1192 IPheader->check=IPheader->check+1;
1194 IPheader->check=0x00;
1213 struct udphdr *UDPheader=(
struct udphdr *) UDPpacket;
1215 if(UDPheader!=NULL) {
1217 if(UDPheader->check!=0xFF) {
1218 UDPheader->check=UDPheader->check+1;
1220 UDPheader->check=0x00;
void display_packet(const char *text, byte_t *packet, unsigned int len)
Display packet in hexadecimal form.
size_t etherEncapsulate(byte_t *packet, struct ether_header *header, byte_t *sdu, size_t sdusize)
Combine Ethernet SDU and PCI.
void etherheadPopulate(struct ether_header *etherHeader, macaddr_t macsrc, macaddr_t macdst, ethertype_t type)
Populate Ethernet header.
size_t IP4Encapsulate(byte_t *packet, struct iphdr *header, byte_t *sdu, size_t sdusize)
Combine IPv4 SDU and PCI.
#define ERR_WLAN_GETIFINDEX
#define ERR_VIFPRINTER_SOCK
void etherheadPopulateB(struct ether_header *etherHeader, macaddr_t mac, ethertype_t type)
Populate broadcast Ethernet header (variant of etherheadPopulate())
void getSrcMAC(struct ether_header *etherHeader, macaddr_t macsrc)
Retrieve source MAC address field from Ethernet header.
unsigned int macAddrTypeGet(macaddr_t mac)
Get the MAC address type.
uint64_t ntoh64(uint64_t netu64)
Convert a 64-bit unsigned value between network and host byte order.
#define ERR_WLAN_GETSRCIP
Structure to store a couple of source and destinaion IPv4 addresses.
macaddr_t prepareMacAddrT()
Prepare a macaddr_t variable.
void freeMacAddrT(macaddr_t mac)
Free a macaddr_t variable.
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...
uint64_t hton64(uint64_t hostu64)
Convert a 64-bit unsigned value between host and network byte order.
#define ERR_WLAN_GETIFADDRS
void rs_printerror(FILE *stream, rawsockerr_t code)
Print more detailed error messages.
#define ERR_WLAN_GETSRCMAC
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())
rawsockerr_t vifPrinter(FILE *stream)
Print information about available interfaces.
void UDPheadPopulate(struct udphdr *UDPhead, unsigned short sourceport, unsigned short destport)
Populate UDP header.
void test_injectIPCsumError(byte_t *IPpacket)
Test function: inject a checksum error in an IP packet.
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.
unsigned short UDPgetpayloadsize(struct udphdr *UDPheader)
Get UDP payload size, given a UDP header.
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()) ...
size_t UDPencapsulate(byte_t *packet, struct udphdr *header, byte_t *data, size_t payloadsize, struct ipaddrs addrs)
Combine UDP payload and header.
void IP4headAddTotLen(struct iphdr *IPhead, unsigned short len)
Add Total Length to a given IPv4 header.
unsigned short ethertype_t
#define ERR_IPHEAD_NOSRCADDR
#define ERR_VIFPRINTER_GETIFADDRS
#define WLANLOOKUP_NONWLAN
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)
void IP4headAddID(struct iphdr *IPhead, unsigned short id)
Add ID to a given IPv4 header.
void test_injectUDPCsumError(byte_t *UDPpacket)
Test function: inject a checksum error in an UDP packet.
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.
__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) ...
void display_packetc(const char *text, byte_t *packet, unsigned int len)
Display packet in character form.
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.