00001
00002 #include <unistd.h>
00003 #include <stdio.h>
00004 #include <stdlib.h>
00005 #include <string.h>
00006 #include <inttypes.h>
00007
00008 #include "receiver.h"
00009 #include "ip.h"
00010
00011
00012 void process_ipv4( uint16_t size, char *packet);
00013 void process_icmp( uint16_t size, char *packet, uint16_t icmp_offset);
00014 uint16_t ip_checksum(void *start, unsigned int count, uint32_t initial_value);
00015
00016
00017 static int tun_fd = -1;
00018
00019 void process_packet(uint16_t size, char *packet) {
00020 if (size < 20)
00021 return;
00022
00023 if ( (packet[IP_VERSION] & 0xF0) == 0x40 ) {
00024 process_ipv4(size, packet);
00025 }
00026 else {
00027 printf("IP version %x not implemented\n",(packet[IP_VERSION] % 0xF0 ));
00028 }
00029 }
00030
00031
00032 void print_packet(uint16_t size, char *packet ) {
00033 int i;
00034 for (i=0; i<size; i++)
00035 printf("%02X ",*(uint8_t *)(packet+i));
00036 puts("");
00037 }
00038
00039 void process_ipv4(uint16_t size, char *packet) {
00040 uint8_t protocol=packet[IPV4_PROTOCOL];
00041 switch(protocol) {
00042 case IP_PROT_ICMP: printf("ICMP package, size %i\n",size-20);
00043 process_icmp(size,packet,20);
00044 break;
00045 case IP_PROT_UDP: printf("UDP package, size %i\n",size-20);
00046 break;
00047 case IP_PROT_TCP: printf("TCP package, size %i\n",size-20);
00048 break;
00049 default: printf("Unknown IP payload %x\n",protocol);
00050 }
00051 }
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 #define PING_BOOSTER
00067 void process_icmp( uint16_t size, char *packet, uint16_t icmp_offset) {
00068 #ifdef PING_BOOSTER
00069 uint8_t *icmp_frame= (uint8_t *) packet+icmp_offset;
00070 uint16_t checksum;
00071
00072
00073 if ( icmp_frame[ICMP_TYPE] != ICMP_ECHO_REQUEST )
00074 return;
00075
00076 puts("PingBoost!");
00077 uint8_t *ping_reply=malloc(size);
00078 uint32_t src,dst;
00079
00080 if (ping_reply==NULL) {
00081 puts("Malloc failed");
00082 return;
00083 }
00084
00085 memcpy(ping_reply, packet, size);
00086 icmp_frame= (uint8_t *) ping_reply+icmp_offset;
00087 dst=GET_UINT32(packet,IPV4_DESTINATION);
00088 src=GET_UINT32(packet,IPV4_SOURCE);
00089
00090 icmp_frame[ICMP_TYPE]=ICMP_ECHO_REPLY;
00091 icmp_frame[ICMP_CODE]=ICMP_ECHO_REPLY;
00092
00093
00094 icmp_frame[ICMP_CRC] =0x00;
00095 icmp_frame[ICMP_CRC+1]=0x00;
00096
00097 checksum=ip_checksum(icmp_frame,size-20,0);
00098 printf("ICMP Check over size %i: %x",size-20,checksum);
00099 SET_UINT16(icmp_frame,ICMP_CRC, checksum);
00100
00101
00102 SET_UINT32(ping_reply,IPV4_SOURCE,dst);
00103 SET_UINT32(ping_reply,IPV4_DESTINATION,src);
00104
00105 SET_UINT16(ping_reply,IPV4_CHECKSUM,0);
00106 checksum=ip_checksum(ping_reply,20,0);
00107 SET_UINT16(ping_reply,IPV4_CHECKSUM,checksum);
00108
00109 print_packet(size, (char *) ping_reply);
00110
00111
00112 if ( write(tun_fd,ping_reply,size) == -1) {
00113 perror("PingBooster write error: ");
00114 }
00115
00116
00117 free(ping_reply);
00118
00119
00120
00121
00122 #endif
00123 }
00124
00125
00126
00127
00134 uint16_t ip_checksum(void *start, unsigned int count, uint32_t initial_value)
00135 {
00136 uint32_t sum = initial_value;
00137
00138 uint16_t * piStart;
00139
00140 piStart = start;
00141 while (count > 1) {
00142 sum += *piStart++;
00143 count -= 2;
00144 }
00145
00146 if (count)
00147 sum += *(unsigned char *)piStart;
00148
00149 while (sum >> 16)
00150 sum = (sum & 0xFFFF) + (sum >> 16);
00151
00152 sum=htons(sum);
00153 return ~sum;
00154 }
00155
00156
00157
00158
00159 void * receiver_run(void *arg) {
00160 char buf[BUFSIZE];
00161 ssize_t bytes_read;
00162 tun_fd = *((int *)arg);
00163 int running=1;
00164
00165 while(running) {
00166 bytes_read=read(tun_fd, buf, BUFSIZE);
00167 if (bytes_read == 0) {
00168 running=0;
00169 continue;
00170 }
00171 else if (bytes_read == -1) {
00172 perror("Error reading from TUN: ");
00173 running=1;
00174 continue;
00175 }
00176 printf("Read %i bytes\n", bytes_read);
00177 print_packet(bytes_read,buf);
00178 process_packet(bytes_read, buf);
00179 }
00180 puts("Receiver thread down.");
00181 return 0;
00182 }