1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 | /* capture_packet.c - 截獲所有以太網(wǎng)幀數(shù)據(jù)并進(jìn)行具體分析 */ /* 常用函數(shù)的頭文件 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include <unistd.h> #include <signal.h> /* 與網(wǎng)絡(luò)相關(guān)的頭文件 */ #include <netinet/ip_icmp.h> #include <net/if_arp.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netinet/ip.h> #include <netdb.h> #include <netinet/tcp.h> #include <netinet/udp.h> #include <signal.h> #include <net/if.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <fcntl.h> #include <linux/if_ether.h> #include <net/ethernet.h> #include <linux/igmp.h> #include <netinet/tcp.h> /* 全局變量結(jié)構(gòu)的結(jié)構(gòu)體原型 - 包含要記錄的任何全局信息 */ struct global_info { unsigned int bytes; /* 網(wǎng)卡接收的總字節(jié)數(shù) */ unsigned int packet_num; /* 網(wǎng)卡接受的幀的總數(shù)量 */ unsigned int packet_arp; /* 接收到的arp包的數(shù)量 */ unsigned int packet_rarp; /* 接收到的rarp包的數(shù)量 */ unsigned int packet_ip; /* 接收到的ip包的數(shù)量 */ unsigned int packet_icmp; /* 接收到的icmp包的數(shù)量 */ unsigned int packet_igmp; /* 接收到的igmp包的數(shù)量 */ unsigned int packet_tcp; /* 接收到的tcp包的數(shù)量 */ unsigned int packet_udp; /* 接收到的udp包的數(shù)量 */ int print_flag_frame; /* 是否打印幀頭信息標(biāo)志, 1表示打印, 0表示不打印 */ int print_flag_arp; /* 是否打印arp頭信息標(biāo)志 */ int print_flag_ip; /* 是否打印ip頭信息標(biāo)志 */ int print_flag_rarp; /* 是否打印rarp頭信息標(biāo)志 */ int print_flag_tcp; /* 是否打印tcp頭信息標(biāo)志 */ int print_flag_udp; /* 是否打印udp頭信息標(biāo)志 */ int print_flag_icmp; /* 是否打印icmp頭信息標(biāo)志 */ int print_flag_igmp; /* 是否打印igmp頭信息標(biāo)志 */ }; /* 定義一個(gè)全局變量,用于存儲(chǔ)全局信息 */ struct global_info global; struct ip_pair { unsigned int source_ip; unsigned int dest_ip; unsigned int count; }; /* 定義一個(gè)用于存儲(chǔ)ip對(duì)的結(jié)構(gòu)體數(shù)組 */ struct ip_pair ip_pair[10000]; /* 一個(gè)用于初始化全局信息的函數(shù) */ void init_global( struct global_info * var ); /* 一個(gè)用于打印全局信息的函數(shù) */ void print_global( struct global_info var ); /* 打印一個(gè)錯(cuò)誤,并退出 */ void error_and_exit( char * msg, int exit_code ); /* 設(shè)置網(wǎng)卡成混雜模式 */ int set_card_promisc( char * interface_name, int sock ); /* 把mac地址轉(zhuǎn)換一個(gè)字符串 */ void mac_to_str( char * buf, char * mac_buf ); /* 用于打印幫助信息 */ void help( void ); /* 截獲網(wǎng)卡幀數(shù)據(jù),并進(jìn)行數(shù)據(jù)分用*/ void do_frame( int sockfd ); /* 處理ip層數(shù)據(jù) */ void do_ip( char * data ); /* 打印ip頭信息 */ void print_ip( struct iphdr * ); /* 處理arp層數(shù)據(jù) */ void do_arp( char * data ); /* 打印arp頭信息 */ void print_arp( struct arphdr * ); /* 處理rarp數(shù)據(jù) */ void do_rarp( char * data ); /* 處理tcp層數(shù)據(jù) */ void do_tcp( char * data ); /* 打印tcp層頭信息 */ void print_tcp( struct tcphdr * ); /* 處理udp層數(shù)據(jù) */ void do_udp( char * data ); /* 打印udp層頭信息 */ void print_udp( struct udphdr * ); /* 處理icmp層數(shù)據(jù) */ void do_icmp( char * data ); /* 打印icmp頭信息 */ void print_icmp( struct icmphdr * ); /* 處理igmp層數(shù)據(jù) */ void do_igmp( char * data ); /* 打印igmp頭信息 */ void print_igmp( struct igmphdr * ); /* 初始化一個(gè)全局結(jié)構(gòu)體 */ void init_global( struct global_info * var ) { var->bytes = 0; var->packet_num = 0; var->packet_arp = 0; var->packet_rarp = 0; var->packet_ip = 0; var->packet_icmp = 0; var->packet_igmp = 0; var->packet_tcp = 0; var->packet_udp = 0; var->print_flag_frame = 0; var->print_flag_arp = 0; var->print_flag_ip = 0; var->print_flag_rarp = 0; var->print_flag_tcp = 0; var->print_flag_udp = 0; var->print_flag_icmp = 0; var->print_flag_igmp = 0; } /* 一個(gè)用于打印全局信息的函數(shù) */ void print_global( struct global_info var ) { printf ( "\n\n********** 全局信息 *****************\n\n" ); printf ( "總共接收字節(jié)數(shù): %d kbytes.\n" , var.bytes / 1024 ); printf ( "總共接受包數(shù)量: %d\n\n" , var.packet_num ); if ( var.packet_arp ) printf ( "接收 arp 包數(shù)量: %d\n" , var.packet_arp ); if ( var.packet_rarp) printf ( "接收 rarp 包數(shù)量: %d\n" , var.packet_rarp ); if ( var.packet_ip ) printf ( "接收 ip 包數(shù)量: %d\n" , var.packet_ip ); if ( var.packet_icmp) printf ( "接收 icmp 包數(shù)量: %d\n" , var.packet_icmp ); if ( var.packet_igmp) printf ( "接收 igmp 包數(shù)量: %d\n" , var.packet_igmp ); if ( var.packet_tcp ) printf ( "接收 tcp 包數(shù)量: %d\n" , var.packet_tcp ); if ( var.packet_udp ) printf ( "接收 udp 包數(shù)量: %d\n" , var.packet_udp ); printf ( "\n" ); } /* 用于處理當(dāng)下按ctrl-c時(shí)的處理函數(shù) */ void sig_int( int sig ) { print_global( global ); int i; /* for( i=0; i<global.packet_ip; i++ ){ printf("%15s ==>> ", inet_ntoa( *(struct in_addr *)( &ip_pair[i].source_ip ) ) ); printf("%15s \n", inet_ntoa( *(struct in_addr *)( &ip_pair[i].dest_ip ) )); } */ exit ( 0 ); } /* 打印錯(cuò)誤信息,并退出 */ void error_and_exit( char * msg, int exit_code ) { herror( msg ); exit ( exit_code ); } /* 設(shè)置網(wǎng)卡模式成混帳模式,這樣的話(huà)可以截獲以太網(wǎng)幀數(shù)據(jù) */ int set_card_promisc( char * interface_name, int sock ) { /* 用于套接口ioctl的接口請(qǐng)求結(jié)構(gòu)體 */ struct ifreq ifr; /* 復(fù)制網(wǎng)卡名稱(chēng)進(jìn)入請(qǐng)求結(jié)構(gòu)體的名稱(chēng)元素 */ strncpy (ifr.ifr_name, interface_name , strlen ( interface_name )+1); /* 通過(guò)ioctl獲得相應(yīng)信息 */ if ((ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)) { error_and_exit( "ioctl" , 2); } /* 設(shè)置網(wǎng)卡模式標(biāo)志為混雜模式 */ ifr.ifr_flags |= IFF_PROMISC; /* 通過(guò)ioctl把參數(shù)傳遞給網(wǎng)卡 */ if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1 ) error_and_exit( "ioctl" , 3); } /* 把mac地址轉(zhuǎn)換成字符串 */ void mac_to_str( char * buf, char * mac_buf ) { sprintf ( mac_buf, "%02x:%02x:%02x:%02x:%02x:%02x" ,(unsigned char ) *buf, (unsigned char )(*(buf+1)), (unsigned char )(*(buf+2)), (unsigned char )(*(buf+3)), (unsigned char )(*(buf+4)), (unsigned char )(*(buf+5))); mac_buf[17] = 0; } void help( void ) { printf ( "Usage: capture [-h] [協(xié)議名稱(chēng) ...].\n" ); printf ( "默認(rèn)情況: 打印所有包信息.\n" ); } void print_udp( struct udphdr * pudp ) { printf ( "==================== udp 頭信息 ======================\n" ); printf ( "16位源端口號(hào) : %d\n" , ntohs( pudp->source ) ); printf ( "16位目的端口號(hào): %d\n" , ntohs( pudp->dest ) ); printf ( "16位udp長(zhǎng)度: %d\n" , ntohs( pudp->len ) ); printf ( "16位udp校驗(yàn)和: %d\n" , ntohs( pudp->check ) ); if ( ntohs( pudp->len ) != sizeof ( struct udphdr ) && ntohs( pudp->len ) < 20 ){ char * data = ( char * )pudp + sizeof ( struct udphdr ); printf ( "UDP數(shù)據(jù): %s\n" , data ); } } void do_udp( char * data ) { global.packet_udp ++; struct udphdr * pudp = ( struct udphdr * )data; if ( global.print_flag_udp ) print_udp( pudp ); } void print_tcp( struct tcphdr * ptcp ) { printf ( "==================== tcp 頭信息 =====================\n" ); printf ( "源端口號(hào) : %d\n" , ntohs( ptcp->source ) ); printf ( "目的端口號(hào): %d\n" , ntohs( ptcp->dest ) ); printf ( "32位序列號(hào) : %u\n" , ntohl( ptcp->seq ) ); printf ( "32位確認(rèn)序號(hào): %u\n" , ntohl( ptcp->ack_seq ) ); printf ( "首部長(zhǎng)度: %d\n" , ptcp->doff * 4 ); printf ( "6個(gè)標(biāo)志位: \n" ); printf ( " 緊急指針 urg : %d\n" , ptcp->urg ); printf ( " 確認(rèn)序號(hào)位 ack : %d\n" , ptcp->ack ); printf ( " 接受方盡快將報(bào)文交給應(yīng)用層 psh : %d\n" , ptcp->psh ); printf ( " 重建連接 rst : %d\n" , ptcp->rst ); printf ( " 用來(lái)發(fā)起連接的同步序號(hào) syn : %d\n" , ptcp->syn ); printf ( " 發(fā)送端完成任務(wù) fin : %d\n" , ptcp->fin ); printf ( "16位窗口大小: %d\n" , ntohs( ptcp->window ) ); printf ( "16位校驗(yàn)和: %d\n" , ntohs( ptcp->check ) ); printf ( "16位緊急指針: %d\n" , ntohs( ptcp->urg_ptr ) ); if ( ptcp->doff * 4 == 20 ){ printf ( "選項(xiàng)數(shù)據(jù): 沒(méi)有\(zhòng)n" ); } else { printf ( "選項(xiàng)數(shù)據(jù): %d 字節(jié)\n" , ptcp->doff * 4 - 20 ); } char * data = ( char * )ptcp; data += ptcp->doff * 4; printf ( "數(shù)據(jù)長(zhǎng)度: %d 字節(jié)\n" , strlen (data) ); if ( strlen (data) < 10 ) printf ( "數(shù)據(jù): %s\n" , data ); } void do_tcp( char * data ) { global.packet_tcp ++; struct tcphdr * ptcp; ptcp = ( struct tcphdr * )data; if ( global.print_flag_tcp ) print_tcp( ptcp ); } void print_igmp( struct igmphdr * pigmp ) { printf ( "==================== igmp 包信息 ==========================\n" ); printf ( "igmp 版本: %d\n" , pigmp->type & 15 ); printf ( "igmp 類(lèi)型: %d\n" , pigmp->type >> 4 ); printf ( "igmp 碼: %d\n" , pigmp->code ); printf ( "igmp 校驗(yàn)和: %d\n" , ntohs( pigmp->csum ) ); printf ( "igmp 組地址: %d\n" , ntohl( pigmp->group ) ); } void do_igmp( char * data ) { global.packet_igmp ++; struct igmphdr * pigmp = ( struct igmphdr * ) data; if ( global.print_flag_igmp ) print_igmp( pigmp ); } void print_icmp( struct icmphdr * picmp ) { printf ( "==================== icmp 包信息 ===========================\n" ); printf ( "消息類(lèi)型: %d " , picmp->type ); switch ( picmp->type ){ case ICMP_ECHOREPLY: printf ( "Ping的回顯應(yīng)答\n" ); break ; case ICMP_DEST_UNREACH: printf ( "目的不可達(dá)\n" ); break ; case ICMP_SOURCE_QUENCH: printf ( "源端被關(guān)閉\n" ); break ; case ICMP_REDIRECT: printf ( "重定相\n" ); break ; case ICMP_ECHO: printf ( "ping的回顯請(qǐng)求\n" ); break ; case ICMP_TIME_EXCEEDED: printf ( "超時(shí)\n" ); break ; case ICMP_PARAMETERPROB: printf ( "參數(shù)問(wèn)題\n" ); break ; case ICMP_TIMESTAMP: printf ( "時(shí)間戳請(qǐng)求\n" ); break ; case ICMP_TIMESTAMPREPLY: printf ( "時(shí)間戳應(yīng)答\n" ); break ; case ICMP_INFO_REQUEST: printf ( "信息請(qǐng)求\n" ); break ; case ICMP_INFO_REPLY: printf ( "信息應(yīng)答\n" ); break ; case ICMP_ADDRESS: printf ( "地址掩碼請(qǐng)求\n" ); break ; case ICMP_ADDRESSREPLY: printf ( "地址掩碼應(yīng)答\n" ); break ; default : printf ( "未知消息類(lèi)型\n" ); break ; } printf ( "消息類(lèi)型的子選項(xiàng): %d " , picmp->code ); switch ( picmp->type ){ case ICMP_ECHOREPLY: printf ( "Ping的回顯應(yīng)答\n" ); break ; case ICMP_DEST_UNREACH: switch ( picmp->type ){ case ICMP_NET_UNREACH: printf ( "網(wǎng)絡(luò)不可到達(dá)\n" ); break ; case ICMP_HOST_UNREACH: printf ( "主機(jī)不可到達(dá)\n" ); break ; case ICMP_PROT_UNREACH: printf ( "協(xié)議不可到達(dá)\n" ); break ; case ICMP_PORT_UNREACH: printf ( "端口不可到達(dá)\n" ); break ; case ICMP_FRAG_NEEDED: printf ( "需要進(jìn)行分片,但是又設(shè)置不分片位\n" ); break ; case ICMP_SR_FAILED: printf ( "源站選路失敗\n" ); break ; case ICMP_NET_UNKNOWN: printf ( "目的網(wǎng)絡(luò)不認(rèn)識(shí)\n" ); break ; case ICMP_HOST_UNKNOWN: printf ( "目的主機(jī)不認(rèn)識(shí)\n" ); break ; case ICMP_HOST_ISOLATED: printf ( "源主機(jī)北隔離\n" ); break ; case ICMP_NET_ANO: printf ( "目的網(wǎng)絡(luò)被強(qiáng)制禁止\n" ); break ; case ICMP_HOST_ANO: printf ( "目的主機(jī)被強(qiáng)制禁止\n" ); break ; case ICMP_NET_UNR_TOS: printf ( "由于服務(wù)類(lèi)型TOS,網(wǎng)絡(luò)不可到達(dá)\n" ); break ; case ICMP_HOST_UNR_TOS: printf ( "由于服務(wù)類(lèi)型TOS,主機(jī)不可到達(dá)\n" ); break ; case ICMP_PKT_FILTERED: printf ( "由于過(guò)濾,通信被強(qiáng)制禁止\n" ); break ; case ICMP_PREC_VIOLATION: printf ( "主機(jī)越權(quán)\n" ); break ; case ICMP_PREC_CUTOFF: printf ( "優(yōu)先權(quán)中止生效\n" ); break ; default : printf ( "未知代碼\n" ); break ; } break ; case ICMP_SOURCE_QUENCH: printf ( "源端被關(guān)閉\n" ); break ; case ICMP_REDIRECT: switch ( picmp->type ){ case ICMP_REDIR_NET: printf ( "對(duì)網(wǎng)絡(luò)重定向\n" ); break ; case ICMP_REDIR_HOST: printf ( "對(duì)主機(jī)重定向\n" ); break ; case ICMP_REDIR_NETTOS: printf ( "對(duì)服務(wù)類(lèi)型和網(wǎng)絡(luò)重定向\n" ); break ; case ICMP_REDIR_HOSTTOS: printf ( "對(duì)服務(wù)類(lèi)型和主機(jī)重定向\n" ); break ; defalut: printf ( "未知代碼\n" ); break ; } break ; case ICMP_ECHO: printf ( "ping的回顯請(qǐng)求\n" ); break ; case ICMP_TIME_EXCEEDED: switch ( picmp->type ){ case ICMP_EXC_TTL: printf ( "在傳輸期間生存時(shí)間為0\n" ); break ; case ICMP_EXC_FRAGTIME: printf ( "在數(shù)據(jù)組裝期間生存時(shí)間為0\n" ); break ; default : printf ( "未知代碼\n" ); break ; } break ; case ICMP_PARAMETERPROB: switch ( picmp->type ){ case 0: printf ( "IP首部錯(cuò)誤(包括各種差錯(cuò))\n" ); break ; case 1: printf ( "缺少必須的選項(xiàng)\n" ); break ; default : printf ( "原因未知\n" ); break ; } break ; case ICMP_TIMESTAMP: printf ( "時(shí)間戳請(qǐng)求\n" ); break ; case ICMP_TIMESTAMPREPLY: printf ( "時(shí)間戳應(yīng)答\n" ); break ; case ICMP_INFO_REQUEST: printf ( "信息請(qǐng)求\n" ); break ; case ICMP_INFO_REPLY: printf ( "信息應(yīng)答\n" ); break ; case ICMP_ADDRESS: printf ( "地址掩碼請(qǐng)求\n" ); break ; case ICMP_ADDRESSREPLY: printf ( "地址掩碼應(yīng)答\n" ); break ; default : printf ( "未知消息類(lèi)型\n" ); break ; } printf ( "校驗(yàn)和: %d\n" , ntohs(picmp->checksum) ); } void do_icmp( char * data ) { global.packet_icmp ++; struct icmphdr * picmp = ( struct icmphdr * ) data; if ( global.print_flag_icmp ) print_icmp( picmp ); } void print_ip( struct iphdr * iph ) { printf ( "=============== ip 頭信息 ===============\n" ); printf ( "IP 首部長(zhǎng)度:%d\n" , iph->ihl * 4 ); printf ( "IP 版本 :%d\n" , iph->version ); printf ( "服務(wù)類(lèi)型(tos): %d\n" , iph->tos ); printf ( "總長(zhǎng)度字節(jié): %d\n" , ntohs(iph->tot_len) ); printf ( "16位標(biāo)識(shí): %d\n" , ntohs(iph->id) ); printf ( "frag off: %d\n" , ntohs(iph->frag_off) ); printf ( "8位生存事件: %d\n" , iph->ttl ); printf ( "8位協(xié)議: %d\n" , iph->protocol ); printf ( "16位首部校驗(yàn)和: %d\n" , ntohs(iph->check) ); printf ( "32位源IP地址 : %s\n" , inet_ntoa( *( struct in_addr *)(&iph->saddr)) ); printf ( "32位目的IP地址: %s\n" , inet_ntoa( *( struct in_addr *)(&iph->daddr)) ); } void ip_count( struct iphdr * iph ) { ip_pair[ global.packet_ip - 1 ].source_ip = iph->saddr; ip_pair[ global.packet_ip - 1 ].dest_ip = iph->daddr; } void do_ip( char * data ) { global.packet_ip ++; struct iphdr *pip; pip = ( struct iphdr * ) data; /* pip = point to ip layer */ if ( global.print_flag_ip ) print_ip( pip ); ip_count( pip ); char * pdata = data + pip->ihl * 4; switch ( pip->protocol ){ case IPPROTO_ICMP: do_icmp( pdata ); break ; case IPPROTO_IGMP: do_igmp( pdata ); break ; case IPPROTO_TCP: do_tcp( pdata ); break ; case IPPROTO_UDP: do_udp( pdata ); break ; default : printf ( "IP: 未知其上層協(xié)議.\n" ); break ; } } void print_arp( struct arphdr * parp ) { printf ( "硬件類(lèi)型: %d " , ntohs(parp->ar_hrd) ); switch ( ntohs( parp->ar_hrd ) ){ case ARPHRD_ETHER: printf ( "Ethernet 10/100Mbps.\n" ); break ; case ARPHRD_EETHER: printf ( "Experimental Ethernet.\n" ); break ; case ARPHRD_AX25: printf ( "AX.25 Level 2.\n" ); break ; case ARPHRD_PRONET: printf ( "PROnet token ring.\n" ); break ; case ARPHRD_IEEE802: printf ( "IEEE 802.2 Ethernet/TR/TB.\n" ); break ; case ARPHRD_APPLETLK: printf ( "APPLEtalk.\n" ); break ; case ARPHRD_ATM: printf ( "ATM.\n" ); break ; case ARPHRD_IEEE1394: printf ( "IEEE 1394 IPv4 .\n" ); break ; default : printf ( "Unknow.\n" ); break ; } printf ( "映射的協(xié)議地址類(lèi)型: %d " , ntohs(parp->ar_pro) ); switch ( ntohs(parp->ar_pro) ){ case ETHERTYPE_IP: printf ( "IP.\n" ); break ; default : printf ( "error.\n" ); break ; } printf ( "硬件地址長(zhǎng)度: %d\n" , parp->ar_hln ); printf ( "協(xié)議地址長(zhǎng)度: %d\n" , parp->ar_pln ); printf ( "操作碼: %d " , ntohs(parp->ar_op) ); switch ( ntohs(parp->ar_op) ){ case ARPOP_REQUEST: printf ( "ARP 請(qǐng)求.\n" ); break ; case ARPOP_REPLY: printf ( "ARP 應(yīng)答.\n" ); break ; case ARPOP_RREQUEST: printf ( "RARP 請(qǐng)求.\n" ); break ; case ARPOP_RREPLY: printf ( "RARP 應(yīng)答.\n" ); break ; case ARPOP_InREQUEST: printf ( "InARP 請(qǐng)求.\n" ); break ; case ARPOP_InREPLY: printf ( "InARP 應(yīng)答.\n" ); break ; case ARPOP_NAK: printf ( "(ATM)ARP NAK.\n" ); break ; default : printf ( "arp 操作碼錯(cuò)誤.\n" ); break ; } char * addr = ( char *)(parp + 1); char buf[18]; mac_to_str( addr, buf ); printf ( "發(fā)送端以太網(wǎng)地址: %s\n" , buf ); printf ( "發(fā)送端IP地址: %s\n" , inet_ntoa( *( struct in_addr *)(addr+6) )); mac_to_str( addr+10, buf ); printf ( "目的以太網(wǎng)地址: %s\n" , buf ); printf ( "目的IP地址: %s\n" , inet_ntoa( *( struct in_addr *)(addr+16) )); } void do_arp( char * data ) { global.packet_arp ++; struct arphdr * parp; parp = ( struct arphdr * ) data; if ( global.print_flag_arp ) { printf ( "============= arp 頭信息 ==============\n" ); print_arp( parp ); } } void do_rarp( char * data ) { global.packet_rarp ++; struct arphdr * parp; parp = ( struct arphdr * ) data; if ( global.print_flag_rarp ){ printf ( "============= rarp 頭信息 =============\n" ); print_arp( parp ); } } /* 打印以太網(wǎng)幀的包頭信息 */ void print_frame( struct ether_header * peth ) { /* 定義一個(gè)數(shù)組,用于存儲(chǔ)把mac地址轉(zhuǎn)換成字符串后的字符串 */ char buf[ 18 ]; printf ( "\n================================== 第 %d 個(gè)包 =======================================\n\n" , global.packet_num ); printf ( "==== 以太網(wǎng)幀信息 =====\n" ); char * shost = peth->ether_shost; mac_to_str( shost, buf ); printf ( "源以太網(wǎng)地址: %s\n" , buf ); char * dhost = peth->ether_dhost; mac_to_str( dhost, buf ); printf ( "目的以太網(wǎng)地址:%s\n" , buf ); } /* 用于從網(wǎng)卡接受一幀數(shù)據(jù),同時(shí)根據(jù)以太網(wǎng)協(xié)議字段傳遞數(shù)據(jù)給相應(yīng)的上層協(xié)議處理 */ void do_frame( int sock ) { /* 用于存儲(chǔ)一幀數(shù)據(jù) */ char frame_buf[ 2000 ]; /* 清空幀數(shù)據(jù)緩沖區(qū) */ bzero( frame_buf, sizeof (frame_buf) ); int len = sizeof ( frame_buf ); /* 用于存儲(chǔ)接受字節(jié)數(shù) */ int recv_num; /* 用于存儲(chǔ)發(fā)送方的地址信息 */ struct sockaddr_in addr; /* 從網(wǎng)卡接收一幀數(shù)據(jù) */ recv_num = recvfrom( sock, ( char *)frame_buf, sizeof ( frame_buf ), 0, ( struct sockaddr * )&addr, &len ); /* 所接收的包的總數(shù)自加1 */ global.packet_num ++; /* 從網(wǎng)卡接收的字節(jié)總數(shù) */ global.bytes += recv_num; /* 打印接收的包是第幾個(gè)包 */ //printf("此幀數(shù)據(jù)長(zhǎng)度: %d\n", recv_num ); /* 定義一個(gè)用于指向以太網(wǎng)幀的指針 (這里我們只考慮最常見(jiàn)的以太網(wǎng)幀的情況) */ struct ether_header * peth; /* 讓以太網(wǎng)頭指針指向從網(wǎng)卡接受到的幀的數(shù)據(jù)的開(kāi)頭 */ peth = ( struct ether_header *)frame_buf; /* 傳遞以太網(wǎng)幀首地址給打印以太網(wǎng)幀信息的打印函數(shù) */ if ( global.print_flag_frame ) print_frame( peth ); /* 定義一個(gè)數(shù)據(jù)指針,用于指向以太網(wǎng)幀的數(shù)據(jù)部分 */ char * pdata; /* 讓 pdata 指向以太網(wǎng)幀的數(shù)據(jù)部分 */ pdata = frame_buf + sizeof ( struct ether_header ); /* 根據(jù)以太網(wǎng)幀的協(xié)議字段進(jìn)行數(shù)據(jù)分用 - 也就是進(jìn)行數(shù)據(jù)拆封,根據(jù)協(xié)議字段調(diào)用相應(yīng)層的處理函數(shù) */ switch ( ntohs( peth->ether_type ) ){ case ETHERTYPE_PUP: break ; case ETHERTYPE_IP: do_ip( pdata ); break ; case ETHERTYPE_ARP: do_arp( pdata ); break ; case ETHERTYPE_REVARP: do_rarp( pdata ); break ; default : printf ( "Unkonw ethernet type %d %x.\n" , ntohs(peth->ether_type), ntohs(peth->ether_type) ); break ; } } /* 主函數(shù), 處理命令行輸入, 設(shè)置好全局變量, 并調(diào)用接受和處理幀的函數(shù) */ int main( int argc, char ** argv ) { /* 用于存儲(chǔ)套接口文件描述符 */ int sockfd; /* 初始化全局變量 */ init_global( &global ); if ( argc == 1 ) { /* 表示打印所有包頭信息 */ global.print_flag_frame = 1; global.print_flag_arp = 1; global.print_flag_ip = 1; global.print_flag_rarp = 1; global.print_flag_tcp = 1; global.print_flag_udp = 1; global.print_flag_icmp = 1; global.print_flag_igmp = 1; } else { /* 幫助 或者 通過(guò)指定協(xié)議名稱(chēng)只打印某層些協(xié)議 */ if ( !strcasecmp( argv[1], "-h" ) ){ help(); exit ( 0 ); } else { int i; for ( i=1; i < argc; i++ ){ if ( !strcasecmp( argv[i], "frame" ) ) global.print_flag_frame = 1; else if ( !strcasecmp( argv[i], "arp" ) ) global.print_flag_arp = 1; else if ( !strcasecmp( argv[i], "rarp" ) ) global.print_flag_rarp = 1; else if ( !strcasecmp( argv[i], "ip" ) ) global.print_flag_ip = 1; else if ( !strcasecmp( argv[i], "tcp" ) ) global.print_flag_tcp = 1; else if ( !strcasecmp( argv[i], "udp" ) ) global.print_flag_udp = 1; else if ( !strcasecmp( argv[i], "icmp" ) ) global.print_flag_icmp = 1; else if ( !strcasecmp( argv[i], "igmp" ) ) global.print_flag_igmp = 1; } } } /* 通過(guò)協(xié)議族AF_PACKET類(lèi)信SOCK_RAW, 類(lèi)型SOCK_RAW創(chuàng)建一個(gè)用于可以接受網(wǎng)卡幀數(shù)據(jù)的套接口,同時(shí)返回套就口文件描述符 */ if ( (sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)) ) == -1 ) error_and_exit( "socket" , 1 ); /* 如果發(fā)生錯(cuò)誤,返回錯(cuò)誤值, 并退出 */ /* 設(shè)定網(wǎng)卡eth0成混雜模式 */ set_card_promisc( "eth0" , sockfd ); /* 設(shè)定信號(hào)處理函數(shù), 下面是設(shè)置當(dāng)我們按下ctrl-c時(shí)所調(diào)用的處理函數(shù) */ signal ( SIGINT, sig_int ); /* 無(wú)限循環(huán)接收以太網(wǎng)卡數(shù)據(jù)幀, 并進(jìn)行數(shù)據(jù)分用,直到你按下ctrl-c */ while ( 1 ){ do_frame( sockfd ); } return 0; } |
參考資料:
http://www.cnblogs.com/rollenholt/articles/2585432.html
http://www.binarytides.com/blog/c-packet-sniffer-code-with-libpcap-and-linux-sockets-bsd/
http://www.binarytides.com/blog/packet-sniffer-code-in-c-using-linux-sockets-bsd-part-2/
http://www.binarytides.com/blog/packet-sniffer-code-in-c-using-linux-sockets-bsd/
聯(lián)系客服