00001 #include <linux/kernel.h>
00002 #include <linux/module.h>
00003 #include <rtl_sched.h>
00004 #include <unistd.h>
00005
00006 static unsigned char *IP;
00007
00008 MODULE_LICENSE("GPL");
00009 MODULE_AUTHOR("Sergio Perez <serpeal@upvnet.upv.es>");
00010 MODULE_DESCRIPTION("Ping implementation for testing Ethernet drivers.");
00011 MODULE_PARM(IP,"s");
00012 MODULE_PARM_DESC(IP, "The IP address used to be \"pinged\".");
00013
00014 #define MAX_MTU 1536
00015 #define ECHO_REPLY 0x00
00016 #define IP_PACKET 0x0800
00017 #define ARP_PACKET 0x0806
00018 #define ARP_REPLY 0x02
00019 #define ICMP_PACKET 0x01
00020 #define ECHO_REQUEST 0x08
00021
00022 struct memory{
00023 void *mem;
00024 };
00025
00026 pthread_t pingpong_thread;
00027 unsigned char out_buf[MAX_MTU];
00028 int fd;
00029
00030 static int atoi(const char* s);
00031 static void *memcopy(void* dst, const void* src, size_t count);
00032 static unsigned int convert_ip_string_to_int(unsigned char *ip, int len);
00033 static void prepare_icmp_echo_reply(unsigned char *out_buf, unsigned char *in_buf,
00034 int len);
00035 static void prepare_arp_reply(unsigned char *out_buf, unsigned char *in_buf, int len,
00036 int sender_ip, unsigned char *sender_ha);
00037
00038
00039 static void * ping_pong(void *arg){
00040 struct memory receive_buffer;
00041 unsigned char *in_buf;
00042 int len;
00043 int my_ip;
00044 unsigned char MAC[6], NIC_IP[16];
00045
00046
00047 memcopy(NIC_IP,IP,strlen(IP));
00048 NIC_IP[strlen(IP)]='\0';
00049
00050 my_ip = convert_ip_string_to_int(NIC_IP,strlen(IP));
00051
00052
00053 ioctl(fd, 2, (unsigned long) MAC);
00054
00055 while(1){
00056
00057
00058 len = read(fd,(void *) &receive_buffer,1536);
00059
00060
00061
00062
00063 in_buf = (char *) receive_buffer.mem;
00064
00065
00066 if(htons(*(unsigned short *)&(in_buf[12])) == IP_PACKET){
00067
00068
00069 if(in_buf[23] == ICMP_PACKET){
00070
00071
00072 if(in_buf[34] == ECHO_REQUEST){
00073
00074
00075 prepare_icmp_echo_reply(out_buf, in_buf, len);
00076
00077
00078 write(fd,out_buf,len);
00079 }
00080 }
00081 }
00082 else{
00083
00084 if(htons(*(unsigned short *)&(in_buf[12])) == ARP_PACKET){
00085
00086
00087 if(htonl(*(unsigned int *)&(in_buf[38])) == my_ip){
00088
00089
00090 prepare_arp_reply(out_buf, in_buf, len, my_ip, MAC);
00091
00092
00093 write(fd,out_buf,len);
00094 }
00095 }
00096 }
00097 }
00098
00099 return NULL;
00100 }
00101
00102
00103
00104
00105 int init_module(void){
00106 pthread_attr_t attr;
00107
00108 if(IP == NULL){
00109
00110 printk("\nThis module requires parameters.\n\n");
00111 printk("Usage:\n");
00112 printk(" insmod ping.o IP=ip_address\n\n");
00113 printk("Example:\n");
00114 printk(" insmod ping.o IP=\"162.58.0.1\"\n");
00115 printk("\nFor more information type as root:\n");
00116 printk(" modinfo ping.o\n\n");
00117
00118 return -1;
00119 }else{
00120
00121 printk("\n\n Hard Ping example module inserted.\n\n");
00122
00123 if((fd=open("/dev/eth0",0)) == -1){
00124 rtl_printf("ERROR OPENING /dev/eth0\n");
00125 return -1;
00126 }
00127
00128 pthread_attr_init(&attr);
00129 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00130 if(pthread_create(&(pingpong_thread),&attr, ping_pong, NULL)) {
00131 rtl_printf("ERROR: cannot create pthread!\n");
00132 return -1;
00133 }
00134
00135 return 0;
00136 }
00137 }
00138
00139
00140
00141 void cleanup_module(void){
00142
00143 pthread_delete_np(pingpong_thread);
00144 close(fd);
00145
00146 printk("\n\nHard Ping example module removed.\n\n");
00147 }
00148
00149
00150
00151 static int atoi(const char* s) {
00152 long int v=0;
00153 int sign=1;
00154 while ( *s == ' ' || (unsigned int)(*s - 9) < 5u) s++;
00155 switch (*s) {
00156 case '-': sign=-1;
00157 case '+': ++s;
00158 }
00159 while ((unsigned int) (*s - '0') < 10u) {
00160 v=v*10+*s-'0'; ++s;
00161 }
00162 return sign==-1?-v:v;
00163 }
00164
00165
00166
00167 static void *memcopy(void* dst, const void* src, size_t count) {
00168 register char *d=dst;
00169 register const char *s=src;
00170 ++count;
00171 while (--count) {
00172 *d = *s;
00173 ++d; ++s;
00174 }
00175 return dst;
00176 }
00177
00178
00179
00180
00181 static unsigned int convert_ip_string_to_int(unsigned char *ip, int len){
00182 unsigned int integer_ip=0, last_dot_pos=-1;
00183 unsigned short i, n_dots = 0;
00184 unsigned char part[3];
00185
00186
00187 for(i = 0; i<len; i++)
00188 if(ip[i] == '.'){
00189 memcopy(part, &ip[last_dot_pos+1], i-last_dot_pos-1);
00190 n_dots++;
00191 last_dot_pos = i;
00192 integer_ip |= atoi(part)<<(32-(n_dots*8));
00193 part[0] = part[1] = part[2] = 0x00;
00194 if(n_dots == 3) break;
00195 }
00196
00197 memcopy(part, &ip[last_dot_pos+1], len-last_dot_pos+1);
00198
00199 integer_ip |= atoi(part);
00200
00201 return integer_ip;
00202 }
00203
00204
00205
00206
00207 void prepare_icmp_echo_reply(unsigned char *out_buf, unsigned char *in_buf, int len){
00208
00209 memcopy(out_buf, in_buf, len);
00210
00211
00212 memcopy(out_buf, &in_buf[6], 6);
00213 memcopy(&out_buf[6],in_buf, 6);
00214
00215
00216 memcopy(&out_buf[26], &in_buf[30], 4);
00217 memcopy(&out_buf[30], &in_buf[26], 4);
00218
00219
00220
00221
00222
00223
00224 out_buf[34] = ECHO_REPLY;
00225
00226
00227
00228
00229 }
00230
00231
00232
00233 void prepare_arp_reply(unsigned char *out_buf, unsigned char *in_buf, int len, int
00234 sender_ip, unsigned char *sender_ha){
00235 unsigned int net_ip = ntohl(sender_ip);
00236
00237
00238 memcopy(out_buf, in_buf, len);
00239
00240
00241 memcopy(out_buf, &in_buf[6], 6);
00242 memcopy(&out_buf[6], sender_ha, 6);
00243
00244
00245 out_buf[21] = ARP_REPLY;
00246
00247
00248 memcopy(&out_buf[38], &in_buf[28], 4);
00249 memcopy(&out_buf[32], &in_buf[22], 6);
00250 memcopy(&out_buf[28], &net_ip, 4);
00251 memcopy(&out_buf[22], sender_ha, 6);
00252 }