1#if defined(MODVERSIONS) 2#include <linux/modversions.h> 3#endif 4#include <linux/module.h> 5#include <linux/version.h> 6#include <linux/netfilter_ipv4/ip_tables.h> 7#include <linux/netfilter_ipv4/ipt_ipp2p.h> 8#include <net/tcp.h> 9#include <net/udp.h> 10 11#define get_u8(X,O) (*(__u8 *)(X + O)) 12#define get_u16(X,O) (*(__u16 *)(X + O)) 13#define get_u32(X,O) (*(__u32 *)(X + O)) 14 15MODULE_AUTHOR("Eicke Friedrich/Klaus Degner <ipp2p@ipp2p.org>"); 16MODULE_DESCRIPTION("An extension to iptables to identify P2P traffic."); 17MODULE_LICENSE("GPL"); 18 19/*Search for UDP eDonkey/eMule/Kad commands*/ 20int udp_search_edk(unsigned char *haystack, int packet_len) 21{ 22 unsigned char *t = haystack; 23 t += 8; 24 25 switch (t[0]) { 26 case 0xe3: 27 { /*edonkey */ 28 switch (t[1]) { 29 /* client -> server status request */ 30 case 0x96: 31 if (packet_len == 14) 32 return ((IPP2P_EDK * 100) + 50); 33 break; 34 /* server -> client status request */ 35 case 0x97: 36 if (packet_len == 42) 37 return ((IPP2P_EDK * 100) + 51); 38 break; 39 /* server description request */ 40 /* e3 2a ff f0 .. | size == 6 */ 41 case 0xa2: 42 if ((packet_len == 14) && (get_u16(t, 2) == __constant_htons(0xfff0))) 43 return ((IPP2P_EDK * 100) + 52); 44 break; 45 /* server description response */ 46 /* e3 a3 ff f0 .. | size > 40 && size < 200 */ 47 //case 0xa3: return ((IPP2P_EDK * 100) + 53); 48 // break; 49 case 0x9a: 50 if (packet_len == 26) 51 return ((IPP2P_EDK * 100) + 54); 52 break; 53 54 case 0x92: 55 if (packet_len == 18) 56 return ((IPP2P_EDK * 100) + 55); 57 break; 58 } 59 break; 60 } 61 case 0xe4: 62 { 63 switch (t[1]) { 64 /* e4 20 .. | size == 43 */ 65 case 0x20: 66 if ((packet_len == 43) && (t[2] != 0x00) && (t[34] != 0x00)) 67 return ((IPP2P_EDK * 100) + 60); 68 break; 69 /* e4 00 .. 00 | size == 35 ? */ 70 case 0x00: 71 if ((packet_len == 35) && (t[26] == 0x00)) 72 return ((IPP2P_EDK * 100) + 61); 73 break; 74 /* e4 10 .. 00 | size == 35 ? */ 75 case 0x10: 76 if ((packet_len == 35) && (t[26] == 0x00)) 77 return ((IPP2P_EDK * 100) + 62); 78 break; 79 /* e4 18 .. 00 | size == 35 ? */ 80 case 0x18: 81 if ((packet_len == 35) && (t[26] == 0x00)) 82 return ((IPP2P_EDK * 100) + 63); 83 break; 84 /* e4 52 .. | size = 44 */ 85 case 0x52: 86 if (packet_len == 44) 87 return ((IPP2P_EDK * 100) + 64); 88 break; 89 /* e4 58 .. | size == 6 */ 90 case 0x58: 91 if (packet_len == 14) 92 return ((IPP2P_EDK * 100) + 65); 93 break; 94 /* e4 59 .. | size == 2 */ 95 case 0x59: 96 if (packet_len == 10) 97 return ((IPP2P_EDK * 100) + 66); 98 break; 99 /* e4 28 .. | packet_len == 52,77,102,127... */ 100 case 0x28: 101 if (((packet_len - 52) % 25) == 0) 102 return ((IPP2P_EDK * 100) + 67); 103 break; 104 /* e4 50 xx xx | size == 4 */ 105 case 0x50: 106 if (packet_len == 12) 107 return ((IPP2P_EDK * 100) + 68); 108 break; 109 /* e4 40 xx xx | size == 48 */ 110 case 0x40: 111 if (packet_len == 56) 112 return ((IPP2P_EDK * 100) + 69); 113 break; 114 } 115 break; 116 } 117 } /* end of switch (t[0]) */ 118 return 0; 119} /*udp_search_edk */ 120 121/*Search for UDP Gnutella commands*/ 122int udp_search_gnu(unsigned char *haystack, int packet_len) 123{ 124 unsigned char *t = haystack; 125 t += 8; 126 127 if (memcmp(t, "GND", 3) == 0) 128 return ((IPP2P_GNU * 100) + 51); 129 if (memcmp(t, "GNUTELLA ", 9) == 0) 130 return ((IPP2P_GNU * 100) + 52); 131 return 0; 132} /*udp_search_gnu */ 133 134/*Search for UDP KaZaA commands*/ 135int udp_search_kazaa(unsigned char *haystack, int packet_len) 136{ 137 unsigned char *t = haystack; 138 139 if (t[packet_len - 1] == 0x00) { 140 t += (packet_len - 6); 141 if (memcmp(t, "KaZaA", 5) == 0) 142 return (IPP2P_KAZAA * 100 + 50); 143 } 144 145 return 0; 146} /*udp_search_kazaa */ 147 148/*Search for UDP DirectConnect commands*/ 149int udp_search_directconnect(unsigned char *haystack, int packet_len) 150{ 151 unsigned char *t = haystack; 152 if ((*(t + 8) == 0x24) && (*(t + packet_len - 1) == 0x7c)) { 153 t += 8; 154 if (memcmp(t, "SR ", 3) == 0) 155 return ((IPP2P_DC * 100) + 60); 156 if (memcmp(t, "Ping ", 5) == 0) 157 return ((IPP2P_DC * 100) + 61); 158 } 159 return 0; 160} /*udp_search_directconnect */ 161 162/*Search for UDP BitTorrent commands*/ 163int udp_search_bit(unsigned char *haystack, int packet_len) 164{ 165 switch (packet_len) { 166 case 24: 167 /* ^ 00 00 04 17 27 10 19 80 */ 168 if ((ntohl(get_u32(haystack, 8)) == 0x00000417) && (ntohl(get_u32(haystack, 12)) == 0x27101980)) 169 return (IPP2P_BIT * 100 + 50); 170 break; 171 case 44: 172 if (get_u32(haystack, 16) == __constant_htonl(0x00000400) 173 && get_u32(haystack, 36) == __constant_htonl(0x00000104)) 174 return (IPP2P_BIT * 100 + 51); 175 if (get_u32(haystack, 16) == __constant_htonl(0x00000400)) 176 return (IPP2P_BIT * 100 + 61); 177 break; 178 case 65: 179 if (get_u32(haystack, 16) == __constant_htonl(0x00000404) 180 && get_u32(haystack, 36) == __constant_htonl(0x00000104)) 181 return (IPP2P_BIT * 100 + 52); 182 if (get_u32(haystack, 16) == __constant_htonl(0x00000404)) 183 return (IPP2P_BIT * 100 + 62); 184 break; 185 case 67: 186 if (get_u32(haystack, 16) == __constant_htonl(0x00000406) 187 && get_u32(haystack, 36) == __constant_htonl(0x00000104)) 188 return (IPP2P_BIT * 100 + 53); 189 if (get_u32(haystack, 16) == __constant_htonl(0x00000406)) 190 return (IPP2P_BIT * 100 + 63); 191 break; 192 case 211: 193 if (get_u32(haystack, 8) == __constant_htonl(0x00000405)) 194 return (IPP2P_BIT * 100 + 54); 195 break; 196 case 29: 197 if ((get_u32(haystack, 8) == __constant_htonl(0x00000401))) 198 return (IPP2P_BIT * 100 + 55); 199 break; 200 case 52: 201 if (get_u32(haystack, 8) == __constant_htonl(0x00000827) && 202 get_u32(haystack, 12) == __constant_htonl(0x37502950)) 203 return (IPP2P_BIT * 100 + 80); 204 break; 205 default: 206 /* this packet does not have a constant size */ 207 if (packet_len >= 40 && get_u32(haystack, 16) == __constant_htonl(0x00000402) 208 && get_u32(haystack, 36) == __constant_htonl(0x00000104)) 209 return (IPP2P_BIT * 100 + 56); 210 break; 211 } 212 213 /* some extra-bitcomet rules: 214 * "d1:" [a|r] "d2:id20:" 215 */ 216 if (packet_len > 30 && get_u8(haystack, 8) == 'd' && get_u8(haystack, 9) == '1' && get_u8(haystack, 10) == ':') { 217 if (get_u8(haystack, 11) == 'a' || get_u8(haystack, 11) == 'r') { 218 if (memcmp(haystack + 12, "d2:id20:", 8) == 0) 219 return (IPP2P_BIT * 100 + 57); 220 } 221 } 222 223 return 0; 224} /*udp_search_bit */ 225 226/*Search for Ares commands*/ 227//#define IPP2P_DEBUG_ARES 228int search_ares(const unsigned char *payload, const u16 plen) 229//int search_ares (unsigned char *haystack, int packet_len, int head_len) 230{ 231// const unsigned char *t = haystack + head_len; 232 233 /* all ares packets start with */ 234 if (payload[1] == 0 && (plen - payload[0]) == 3) { 235 switch (payload[2]) { 236 case 0x5a: 237 /* ares connect */ 238 if (plen == 6 && payload[5] == 0x05) 239 return ((IPP2P_ARES * 100) + 1); 240 break; 241 case 0x09: 242 /* ares search, min 3 chars --> 14 bytes 243 * lets define a search can be up to 30 chars --> max 34 bytes 244 */ 245 if (plen >= 14 && plen <= 34) 246 return ((IPP2P_ARES * 100) + 1); 247 break; 248#ifdef IPP2P_DEBUG_ARES 249 default: 250 printk(KERN_DEBUG "Unknown Ares command %x recognized, len: %u \n", (unsigned int)payload[2], plen); 251#endif /* IPP2P_DEBUG_ARES */ 252 } 253 } 254 255 return 0; 256} /*search_ares */ 257 258/*Search for SoulSeek commands*/ 259int search_soul(const unsigned char *payload, const u16 plen) 260{ 261//#define IPP2P_DEBUG_SOUL 262 /* match: xx xx xx xx | xx = sizeof(payload) - 4 */ 263 if (get_u32(payload, 0) == (plen - 4)) { 264 const __u32 m = get_u32(payload, 4); 265 /* match 00 yy yy 00, yy can be everything */ 266 if (get_u8(payload, 4) == 0x00 && get_u8(payload, 7) == 0x00) { 267#ifdef IPP2P_DEBUG_SOUL 268 printk(KERN_DEBUG "0: Soulseek command 0x%x recognized\n", get_u32(payload, 4)); 269#endif /* IPP2P_DEBUG_SOUL */ 270 return ((IPP2P_SOUL * 100) + 1); 271 } 272 273 /* next match: 01 yy 00 00 | yy can be everything */ 274 if (get_u8(payload, 4) == 0x01 && get_u16(payload, 6) == 0x0000) { 275#ifdef IPP2P_DEBUG_SOUL 276 printk(KERN_DEBUG "1: Soulseek command 0x%x recognized\n", get_u16(payload, 4)); 277#endif /* IPP2P_DEBUG_SOUL */ 278 return ((IPP2P_SOUL * 100) + 2); 279 } 280 281 /* other soulseek commandos are: 1-5,7,9,13-18,22,23,26,28,35-37,40-46,50,51,60,62-69,91,92,1001 */ 282 /* try to do this in an intelligent way */ 283 /* get all small commandos */ 284 switch (m) { 285 case 7: 286 case 9: 287 case 22: 288 case 23: 289 case 26: 290 case 28: 291 case 50: 292 case 51: 293 case 60: 294 case 91: 295 case 92: 296 case 1001: 297#ifdef IPP2P_DEBUG_SOUL 298 printk(KERN_DEBUG "2: Soulseek command 0x%x recognized\n", get_u16(payload, 4)); 299#endif /* IPP2P_DEBUG_SOUL */ 300 return ((IPP2P_SOUL * 100) + 3); 301 } 302 303 if (m > 0 && m < 6) { 304#ifdef IPP2P_DEBUG_SOUL 305 printk(KERN_DEBUG "3: Soulseek command 0x%x recognized\n", get_u16(payload, 4)); 306#endif /* IPP2P_DEBUG_SOUL */ 307 return ((IPP2P_SOUL * 100) + 4); 308 } 309 if (m > 12 && m < 19) { 310#ifdef IPP2P_DEBUG_SOUL 311 printk(KERN_DEBUG "4: Soulseek command 0x%x recognized\n", get_u16(payload, 4)); 312#endif /* IPP2P_DEBUG_SOUL */ 313 return ((IPP2P_SOUL * 100) + 5); 314 } 315 316 if (m > 34 && m < 38) { 317#ifdef IPP2P_DEBUG_SOUL 318 printk(KERN_DEBUG "5: Soulseek command 0x%x recognized\n", get_u16(payload, 4)); 319#endif /* IPP2P_DEBUG_SOUL */ 320 return ((IPP2P_SOUL * 100) + 6); 321 } 322 323 if (m > 39 && m < 47) { 324#ifdef IPP2P_DEBUG_SOUL 325 printk(KERN_DEBUG "6: Soulseek command 0x%x recognized\n", get_u16(payload, 4)); 326#endif /* IPP2P_DEBUG_SOUL */ 327 return ((IPP2P_SOUL * 100) + 7); 328 } 329 330 if (m > 61 && m < 70) { 331#ifdef IPP2P_DEBUG_SOUL 332 printk(KERN_DEBUG "7: Soulseek command 0x%x recognized\n", get_u16(payload, 4)); 333#endif /* IPP2P_DEBUG_SOUL */ 334 return ((IPP2P_SOUL * 100) + 8); 335 } 336#ifdef IPP2P_DEBUG_SOUL 337 printk(KERN_DEBUG "unknown SOULSEEK command: 0x%x, first 16 bit: 0x%x, first 8 bit: 0x%x ,soulseek ???\n", 338 get_u32(payload, 4), get_u16(payload, 4) >> 16, get_u8(payload, 4) >> 24); 339#endif /* IPP2P_DEBUG_SOUL */ 340 } 341 342 /* match 14 00 00 00 01 yy 00 00 00 STRING(YY) 01 00 00 00 00 46|50 00 00 00 00 */ 343 /* without size at the beginning !!! */ 344 if (get_u32(payload, 0) == 0x14 && get_u8(payload, 4) == 0x01) { 345 __u32 y = get_u32(payload, 5); 346 /* we need 19 chars + string */ 347 if ((y + 19) <= (plen)) { 348 const unsigned char *w = payload + 9 + y; 349 if (get_u32(w, 0) == 0x01 && (get_u16(w, 4) == 0x4600 || get_u16(w, 4) == 0x5000) 350 && get_u32(w, 6) == 0x00) ; 351#ifdef IPP2P_DEBUG_SOUL 352 printk(KERN_DEBUG "Soulssek special client command recognized\n"); 353#endif /* IPP2P_DEBUG_SOUL */ 354 return ((IPP2P_SOUL * 100) + 9); 355 } 356 } 357 return 0; 358} 359 360/*Search for WinMX commands*/ 361int search_winmx(const unsigned char *payload, const u16 plen) 362{ 363//#define IPP2P_DEBUG_WINMX 364 if (((plen) == 4) && (memcmp(payload, "SEND", 4) == 0)) 365 return ((IPP2P_WINMX * 100) + 1); 366 if (((plen) == 3) && (memcmp(payload, "GET", 3) == 0)) 367 return ((IPP2P_WINMX * 100) + 2); 368 //if (packet_len < (head_len + 10)) return 0; 369 if (plen < 10) 370 return 0; 371 372 if ((memcmp(payload, "SEND", 4) == 0) || (memcmp(payload, "GET", 3) == 0)) { 373 u16 c = 4; 374 const u16 end = plen - 2; 375 u8 count = 0; 376 while (c < end) { 377 if (payload[c] == 0x20 && payload[c + 1] == 0x22) { 378 c++; 379 count++; 380 if (count >= 2) 381 return ((IPP2P_WINMX * 100) + 3); 382 } 383 c++; 384 } 385 } 386 387 if (plen == 149 && payload[0] == '8') { 388#ifdef IPP2P_DEBUG_WINMX 389 printk(KERN_INFO "maybe WinMX\n"); 390#endif 391 if (get_u32(payload, 17) == 0 && get_u32(payload, 21) == 0 && get_u32(payload, 25) == 0 && 392 get_u16(payload, 39) == 0 && get_u16(payload, 135) == __constant_htons(0x7edf) 393 && get_u16(payload, 147) == __constant_htons(0xf792)) 394 { 395#ifdef IPP2P_DEBUG_WINMX 396 printk(KERN_INFO "got WinMX\n"); 397#endif 398 return ((IPP2P_WINMX * 100) + 4); 399 } 400 } 401 return 0; 402} /*search_winmx */ 403 404/*Search for appleJuice commands*/ 405int search_apple(const unsigned char *payload, const u16 plen) 406{ 407 if ((plen > 7) && (payload[6] == 0x0d) && (payload[7] == 0x0a) && (memcmp(payload, "ajprot", 6) == 0)) 408 return (IPP2P_APPLE * 100); 409 410 return 0; 411} 412 413/*Search for BitTorrent commands*/ 414int search_bittorrent(const unsigned char *payload, const u16 plen) 415{ 416 if (plen > 20) { 417 /* test for match 0x13+"BitTorrent protocol" */ 418 if (payload[0] == 0x13) { 419 if (memcmp(payload + 1, "BitTorrent protocol", 19) == 0) 420 return (IPP2P_BIT * 100); 421 } 422 423 /* get tracker commandos, all starts with GET / 424 * then it can follow: scrape| announce 425 * and then ?hash_info= 426 */ 427 if (memcmp(payload, "GET /", 5) == 0) { 428 /* message scrape */ 429 if (memcmp(payload + 5, "scrape?info_hash=", 17) == 0) 430 return (IPP2P_BIT * 100 + 1); 431 /* message announce */ 432 if (memcmp(payload + 5, "announce?info_hash=", 19) == 0) 433 return (IPP2P_BIT * 100 + 2); 434 } 435 } else { 436 /* bitcomet encryptes the first packet, so we have to detect another 437 * one later in the flow */ 438 /* first try failed, too many missdetections */ 439 //if ( size == 5 && get_u32(t,0) == __constant_htonl(1) && t[4] < 3) return (IPP2P_BIT * 100 + 3); 440 441 /* second try: block request packets */ 442 if (plen == 17 && get_u32(payload, 0) == __constant_htonl(0x0d) && payload[4] == 0x06 443 && get_u32(payload, 13) == __constant_htonl(0x4000)) 444 return (IPP2P_BIT * 100 + 3); 445 } 446 447 return 0; 448} 449 450/*check for Kazaa get command*/ 451int search_kazaa(const unsigned char *payload, const u16 plen) 452{ 453 if ((payload[plen - 2] == 0x0d) && (payload[plen - 1] == 0x0a) && memcmp(payload, "GET /.hash=", 11) == 0) 454 return (IPP2P_DATA_KAZAA * 100); 455 456 return 0; 457} 458 459/*check for gnutella get command*/ 460int search_gnu(const unsigned char *payload, const u16 plen) 461{ 462 if ((payload[plen - 2] == 0x0d) && (payload[plen - 1] == 0x0a)) { 463 if (memcmp(payload, "GET /get/", 9) == 0) 464 return ((IPP2P_DATA_GNU * 100) + 1); 465 if (memcmp(payload, "GET /uri-res/", 13) == 0) 466 return ((IPP2P_DATA_GNU * 100) + 2); 467 } 468 return 0; 469} 470 471/*check for gnutella get commands and other typical data*/ 472int search_all_gnu(const unsigned char *payload, const u16 plen) 473{ 474 475 if ((payload[plen - 2] == 0x0d) && (payload[plen - 1] == 0x0a)) { 476 477 if (memcmp(payload, "GNUTELLA CONNECT/", 17) == 0) 478 return ((IPP2P_GNU * 100) + 1); 479 if (memcmp(payload, "GNUTELLA/", 9) == 0) 480 return ((IPP2P_GNU * 100) + 2); 481 482 if ((memcmp(payload, "GET /get/", 9) == 0) || (memcmp(payload, "GET /uri-res/", 13) == 0)) { 483 u16 c = 8; 484 const u16 end = plen - 22; 485 while (c < end) { 486 if (payload[c] == 0x0a && payload[c + 1] == 0x0d 487 && ((memcmp(&payload[c + 2], "X-Gnutella-", 11) == 0) 488 || (memcmp(&payload[c + 2], "X-Queue:", 8) == 0))) 489 return ((IPP2P_GNU * 100) + 3); 490 c++; 491 } 492 } 493 } 494 return 0; 495} 496 497/*check for KaZaA download commands and other typical data*/ 498int search_all_kazaa(const unsigned char *payload, const u16 plen) 499{ 500 if ((payload[plen - 2] == 0x0d) && (payload[plen - 1] == 0x0a)) { 501 502 if (memcmp(payload, "GIVE ", 5) == 0) 503 return ((IPP2P_KAZAA * 100) + 1); 504 505 if (memcmp(payload, "GET /", 5) == 0) { 506 u16 c = 8; 507 const u16 end = plen - 22; 508 while (c < end) { 509 if (payload[c] == 0x0a && payload[c + 1] == 0x0d 510 && ((memcmp(&payload[c + 2], "X-Kazaa-Username: ", 18) == 0) 511 || (memcmp(&payload[c + 2], "User-Agent: PeerEnabler/", 24) == 0))) 512 return ((IPP2P_KAZAA * 100) + 2); 513 c++; 514 } 515 } 516 } 517 return 0; 518} 519 520/*fast check for edonkey file segment transfer command*/ 521int search_edk(const unsigned char *payload, const u16 plen) 522{ 523 if (payload[0] != 0xe3) 524 return 0; 525 else { 526 if (payload[5] == 0x47) 527 return (IPP2P_DATA_EDK * 100); 528 else 529 return 0; 530 } 531} 532 533/*intensive but slower search for some edonkey packets including size-check*/ 534int search_all_edk(const unsigned char *payload, const u16 plen) 535{ 536 if (payload[0] != 0xe3) 537 return 0; 538 else { 539 //t += head_len; 540 const u16 cmd = get_u16(payload, 1); 541 if (cmd == (plen - 5)) { 542 switch (payload[5]) { 543 case 0x01: 544 return ((IPP2P_EDK * 100) + 1); /*Client: hello or Server:hello */ 545 case 0x4c: 546 return ((IPP2P_EDK * 100) + 9); /*Client: Hello-Answer */ 547 } 548 } 549 return 0; 550 } 551} 552 553/*fast check for Direct Connect send command*/ 554int search_dc(const unsigned char *payload, const u16 plen) 555{ 556 557 if (payload[0] != 0x24) 558 return 0; 559 else { 560 if (memcmp(&payload[1], "Send|", 5) == 0) 561 return (IPP2P_DATA_DC * 100); 562 else 563 return 0; 564 } 565 566} 567 568/*intensive but slower check for all direct connect packets*/ 569int search_all_dc(const unsigned char *payload, const u16 plen) 570{ 571// unsigned char *t = haystack; 572 573 if (payload[0] == 0x24 && payload[plen - 1] == 0x7c) { 574 const unsigned char *t = &payload[1]; 575 /* Client-Hub-Protocol */ 576 if (memcmp(t, "Lock ", 5) == 0) 577 return ((IPP2P_DC * 100) + 1); 578 /* Client-Client-Protocol, some are already recognized by client-hub (like lock) */ 579 if (memcmp(t, "MyNick ", 7) == 0) 580 return ((IPP2P_DC * 100) + 38); 581 } 582 return 0; 583} 584 585/*check for mute*/ 586int search_mute(const unsigned char *payload, const u16 plen) 587{ 588 if (plen == 209 || plen == 345 || plen == 473 || plen == 609 || plen == 1121) { 589 //printk(KERN_DEBUG "size hit: %u",size); 590 if (memcmp(payload, "PublicKey: ", 11) == 0) { 591 return ((IPP2P_MUTE * 100) + 0); 592 } 593 } 594 return 0; 595} 596 597/* check for xdcc */ 598int search_xdcc(const unsigned char *payload, const u16 plen) 599{ 600 /* search in small packets only */ 601 if (plen > 20 && plen < 200 && payload[plen - 1] == 0x0a && payload[plen - 2] == 0x0d 602 && memcmp(payload, "PRIVMSG ", 8) == 0) { 603 604 u16 x = 10; 605 const u16 end = plen - 13; 606 607 /* is seems to be a irc private massage, chedck for xdcc command */ 608 while (x < end) { 609 if (payload[x] == ':') { 610 if (memcmp(&payload[x + 1], "xdcc send #", 11) == 0) 611 return ((IPP2P_XDCC * 100) + 0); 612 } 613 x++; 614 } 615 } 616 return 0; 617} 618 619/* search for waste */ 620int search_waste(const unsigned char *payload, const u16 plen) 621{ 622 if (plen >= 8 && memcmp(payload, "GET.sha1:", 9) == 0) 623 return ((IPP2P_WASTE * 100) + 0); 624 625 return 0; 626} 627 628static struct { 629 int command; 630 __u8 short_hand; /*for fucntions included in short hands */ 631 int packet_len; 632 int (*function_name) (const unsigned char *, const u16); 633} matchlist[] = { 634 {IPP2P_EDK, SHORT_HAND_IPP2P, 20, &search_all_edk}, 635// {IPP2P_DATA_KAZAA,SHORT_HAND_DATA,200, &search_kazaa}, 636// {IPP2P_DATA_EDK,SHORT_HAND_DATA,60, &search_edk}, 637// {IPP2P_DATA_DC,SHORT_HAND_DATA,26, &search_dc}, 638 {IPP2P_DC, SHORT_HAND_IPP2P, 5, search_all_dc}, 639// {IPP2P_DATA_GNU,SHORT_HAND_DATA,40, &search_gnu}, 640 {IPP2P_GNU, SHORT_HAND_IPP2P, 5, &search_all_gnu}, 641 {IPP2P_KAZAA, SHORT_HAND_IPP2P, 5, &search_all_kazaa}, 642 {IPP2P_BIT, SHORT_HAND_IPP2P, 20, &search_bittorrent}, 643 {IPP2P_APPLE, SHORT_HAND_IPP2P, 5, &search_apple}, 644 {IPP2P_SOUL, SHORT_HAND_IPP2P, 5, &search_soul}, 645 {IPP2P_WINMX, SHORT_HAND_IPP2P, 2, &search_winmx}, 646 {IPP2P_ARES, SHORT_HAND_IPP2P, 5, &search_ares}, 647 {IPP2P_MUTE, SHORT_HAND_NONE, 200, &search_mute}, 648 {IPP2P_WASTE, SHORT_HAND_NONE, 5, &search_waste}, 649 {IPP2P_XDCC, SHORT_HAND_NONE, 5, &search_xdcc}, 650 {0, 0, 0, NULL} 651}; 652 653static struct { 654 int command; 655 __u8 short_hand; /*for fucntions included in short hands */ 656 int packet_len; 657 int (*function_name) (unsigned char *, int); 658} udp_list[] = { 659 {IPP2P_KAZAA, SHORT_HAND_IPP2P, 14, &udp_search_kazaa}, 660 {IPP2P_BIT, SHORT_HAND_IPP2P, 23, &udp_search_bit}, 661 {IPP2P_GNU, SHORT_HAND_IPP2P, 11, &udp_search_gnu}, 662 {IPP2P_EDK, SHORT_HAND_IPP2P, 9, &udp_search_edk}, 663 {IPP2P_DC, SHORT_HAND_IPP2P, 12, &udp_search_directconnect}, 664 {0, 0, 0, NULL} 665}; 666 667static bool match(const struct sk_buff *skb, struct xt_action_param *par) 668{ 669 const struct ipt_p2p_info *info = par->matchinfo; 670 const int offset = par->fragoff; 671 unsigned char *haystack; 672 struct iphdr *ip = ip_hdr(skb); 673 int p2p_result = 0, i = 0; 674 int hlen = ntohs(ip->tot_len) - (ip->ihl * 4); /*hlen = packet-data length */ 675 676 /*must not be a fragment */ 677 if (offset) { 678 if (info->debug) 679 printk("IPP2P.match: offset found %i \n", offset); 680 return 0; 681 } 682 683 /*make sure that skb is linear */ 684 if (skb_is_nonlinear(skb)) { 685 if (info->debug) 686 printk("IPP2P.match: nonlinear skb found\n"); 687 return 0; 688 } 689 690 haystack = (char *)ip + (ip->ihl * 4); /*haystack = packet data */ 691 692 switch (ip->protocol) { 693 case IPPROTO_TCP: /*what to do with a TCP packet */ 694 { 695 struct tcphdr *tcph = (void *)ip + ip->ihl * 4; 696 697 if (tcph->fin) 698 return 0; /*if FIN bit is set bail out */ 699 if (tcph->syn) 700 return 0; /*if SYN bit is set bail out */ 701 if (tcph->rst) 702 return 0; /*if RST bit is set bail out */ 703 704 haystack += tcph->doff * 4; /*get TCP-Header-Size */ 705 hlen -= tcph->doff * 4; 706 while (matchlist[i].command) { 707 if ((((info->cmd & matchlist[i].command) == matchlist[i].command) || 708 ((info->cmd & matchlist[i].short_hand) == matchlist[i].short_hand)) && 709 (hlen > matchlist[i].packet_len)) { 710 p2p_result = matchlist[i].function_name(haystack, hlen); 711 if (p2p_result) { 712 if (info->debug) 713 printk 714 ("IPP2P.debug:TCP-match: %i from: %pI4:%i to: %pI4:%i Length: %i\n", 715 p2p_result, &ip->saddr, ntohs(tcph->source), 716 &ip->daddr, ntohs(tcph->dest), hlen); 717 return p2p_result; 718 } 719 } 720 i++; 721 } 722 return p2p_result; 723 } 724 725 case IPPROTO_UDP: /*what to do with an UDP packet */ 726 { 727 struct udphdr *udph = (void *)ip + ip->ihl * 4; 728 729 while (udp_list[i].command) { 730 if ((((info->cmd & udp_list[i].command) == udp_list[i].command) || 731 ((info->cmd & udp_list[i].short_hand) == udp_list[i].short_hand)) && 732 (hlen > udp_list[i].packet_len)) { 733 p2p_result = udp_list[i].function_name(haystack, hlen); 734 if (p2p_result) { 735 if (info->debug) 736 printk 737 ("IPP2P.debug:UDP-match: %i from: %pI4:%i to: %pI4:%i Length: %i\n", 738 p2p_result, &ip->saddr, ntohs(udph->source), 739 &ip->daddr, ntohs(udph->dest), hlen); 740 return p2p_result; 741 } 742 } 743 i++; 744 } 745 return p2p_result; 746 } 747 748 default: 749 return 0; 750 } 751} 752 753static int checkentry(const struct xt_mtchk_param *par) 754{ 755 return 0; 756} 757 758static struct xt_match ipp2p_match = { 759 .name = "ipp2p", 760 .family = AF_INET, 761 .match = &match, 762 .matchsize = sizeof(struct ipt_p2p_info), 763 .checkentry = &checkentry, 764 .me = THIS_MODULE, 765}; 766 767static int __init init(void) 768{ 769 printk(KERN_INFO "IPP2P v%s loading\n", IPP2P_VERSION); 770 return xt_register_match(&ipp2p_match); 771} 772 773static void __exit fini(void) 774{ 775 xt_unregister_match(&ipp2p_match); 776 printk(KERN_INFO "IPP2P v%s unloaded\n", IPP2P_VERSION); 777} 778 779module_init(init); 780module_exit(fini); 781