Example of use libpcap (1) Author: small four
-------------------------------------------------- ------------------------ / usr / include / pcap.htypedef struct PCAP PCAP_T; PCAP-INT.H defines struct PCAP {} struct PCAP {int fd; int snapshot; int linktype; int tzoff; / * timezone offset * / int offset; / * offset for proper alignment * / struct pcap_sf sf; struct pcap_md md; int bufsize; / * Read buffer * / u_char * buffer ; u_char * bp; int cc; u_char * pkt; / * Place holder for pcap_next () * / struct bpf_program fcode; / * Placeholder for filter code if bpf not in kernel * / char errbuf [PCAP_ERRBUF_SIZE];};. - -------------------------------------------------- --------------------- Int PCAP_LOOKUPNET (Char * Device, BPF_U_INT32 * NE TP, BPF_U_INT32 * MASKP, CHAR * Errbuf; This function is used to get the IP address of the specified network interface, the subnet mask. Don't be confused by Netp's name, it corresponds to the IP address, MASKP corresponds to the subnet mask. /usr/include/pcap.htypedef u_int BPF_U_INT32; It is clearly understood that 32-bit can be understood. Returns -1, errbuf contains failure if the call fails. INT PCAP_COMPILE (PCAP_T * P, Struct BPF_PROGRAM * FP, CHAR * STR, INT OPTIMIZE, BPF_U_INT32 NETMASK); This function is used to resolve the filter rule string, fill in the BPF_Program structure. STR points to the filter rule string, the format is visited by TCPDUMP's Manbook, such as tcpdump -x -vv -n -t ip proto // TCP and TCP [13] / & 2 = 2 This filtering rule will capture All TCP packets carrying the SYN logo to 192.168.8.90. The filtering rule string can be an empty string (""), which represents all the passing messages. Optimize is 1 to optimize the filtering rule. NetMask specifies the subnet mask, which is generally obtained from the PCAP_LOOKUPNET () call. The return value is less than zero indicates that the call failed.
This function may be more difficult to understand, the concept involved in the BPF, the Linux system does not have this concept, but libpcap uses PCAP_Compile () and PCAP_SETFILTER () combined with the combination of various link layers, whether it is SOCK_PACKET, DLPI . I have written in the Chinese Security version of the Chinese version of the << Nuclear Package Capture Filtering mechanism introduction >>, see this text to strengthen understanding. -------------------------------------------------- ------------------------ # tcpdump -d ip proto // TCP and DST 192.168.8.90 and TCP [13] / & 2 = 2 (000 LDH [-4096] (001) JEQ # 0x800 JT 2 JF 13 (002) LDB [9] (003) JEQ # 0x6 JT 4 JF 13 (004) LD [16] (005) JEQ # 0XC0A8085A JT 6 JF 13 (006) LDH [6] (007) JSET # 0x1FFF JT 13 JF 8 (008) LDXB 4 * ([0] & 0xF) (009) LDB [x 13] (010) AND # 0X2 (011) JEQ # 0x2 JT 12 JF 13 (012) RET # 65535 (013) RET # 0 # /usr/include/net/bpf.h/* Structure for BiocSetf. * / Struct BPF_Program {u_int bf_len; struct bpf_insn * bf_insns;}; / * * The instruction data structure * / struct bpf_insn {u_short code; u_char jt; u_char jf; bpf_int32 k;};.. / ** Macros for insn array initializers * / # define BPF_STMT (code, k) {(u_short) (code ), 0, 0, k} #define bpf_jump (code, k, jt, jf) {(u_short) (code), JT, JF, K} ------------------------------ ----------------- ---------------------------------------- int PCAP_SETFILTER (PCAP_T * P, Struct BPF_PROGRAM * Fp); This function is used to set the filtration rules for PCAP_Compile () parsing, if you are smart enough (Yugong? ), You can provide filtering rules yourself, no need to PCAP_COMPILE () intervention, just like you write Password Sniffer for i386 / freebsd. Successfully returned 0, failed to return -1. INT PCAP_DISPATCH (PCAP_T * P, INT CNT, PCAP_HANDLER CALLBACK, U_CHAR * User); This function is used to capture packets, distribute packets to pre-specify the processing function (callback function). PCAP_DISPATCH () receives enough CNT packets to return, if the CNT is -1 means that all packets are concentrated in a buffer. If the CNT is 0, only an error occurs, read to EOF or read timeout (specified in PCAP_OPEN_LIVE) to stop capturing packets and returns.
Callback specifies the following types of callback functions to handle packets captured by PCAP_DISPATCH (): typedef void (* pcap_handler) (u_char *, const struct pcap_pkthdr *, const u_char *); PCAP_DISPATCH () Returns the captured message Number, if you touch EOF when you read a static file (in the previous package capture process), it returns 0. Returns -1 indicates an error, at which point PCAP_PERROR (), PCAP_GETERR () can be displayed. Let's take a look at that callback function, there are three parameters, the first parameter from PCAP_DISPATCH (), usually our own package capture procedure does not need to provide it, always null. The second denominating is located to the PCAP_PKTHDR structure, which is located in front of the real physical frame for eliminating the differences in different link layers. The final form is the physical frame of the captured message. -------------------------------------------------- ----------------------- / usr / include / pcap.h / ** Each packet in the dump file is prepended with this generic header. * this gets around the problem of different headers for different * packet interfaces * / struct pcap_pkthdr {struct timeval ts;. / * time stamp * / bpf_u_int32 caplen; / * length of portion present * / bpf_u_int32 len; / * length this packet (off wire ) * /};. / usr / include / net / bpf.h / ** Structure prepended to each packet * / struct bpf_hdr {struct timeval bh_tstamp; / * time stamp * / bpf_u_int32 bh_caplen; / * length of captured portion * / bpf_u_int32 bh_datalen; / * original length of packet * / u_short bh_hdrlen; / * length of bpf header (this struct plus alignment padding) * /}; / ** Because the structure above is not a multiple of 4 bytes, some compilers * will Insist Onserting Padding; Hence, Sizeof (Struct BP) F_HDR) Won't work. * ONLY THE; Applications Use Bh_HDRLEN. * / # ifdef kernel # define sizeof_bpf_hdr 18 # Endif ------------------------------------------------------------------------------------------------------ -------------------------------------------------- ------ Void PCAP_CLOSE (PCAP_T * P); This function is used to close the package capture handle for PCAP_OPEN_LIVE (), release the relevant resources.
Void PCAP_PERROR (PCAP_T * P, Char * PREFIX); the first reference is from PCAP_Open_Live (), the role of the second line of parameters similar to PERROR (), specifies the prefix of the error message, the same as PERROR (), the end is automatically output A wrap. The output of PCAP_PERROR (P, "PCAP_Compile") is similar to this effect: PCAP_Compile: Unknown IP Proto ... PCAP_PERROR is not automatically exit (), like PERROR (), if needed, you should explicitly call EXIT (). Introduce here, you can already write simple Sniffer. For complete demonstration purposes, this is available in Sample Code. Do not ask any questions about the code, annoying.
-------------------------------------------------- ------------------------ / ** File: Sniffer Program for i386 / linux using libpcap * Version: 0.01 aleph * author: anonymous (don't Ask anything.) * Complie: gcc -o3-p pcap pcap_sniffer.c -lpcap `libnet-config --defines --cflags` -wall *: strip pcap * usage: ./pcap -h * Date : 2000-12-15 16:35 * // *********************************************** ****************************** ** ** *************** *********************************************************** **** / # include
/ * Abstract package capture handle * // *************************************************** ************************** ******** ************************* *********************************************************** ** / static void atexit (void (* func) (void)); static void bpf_dump (struct bpf_program * p, int option); char * bpf_image (struct bpf_insn * p, int n); static void outputBinary (const u_char * byteArray, const size_t byteArrayLen); static void pcap_callback (u_char * none, const struct pcap_pkthdr * pcap_head, const u_char * packet); static pcap_t * pcap_init (char * dev, char * filter, int snaplen, int timeout, int dumplevel); Static void PCAP_READ (PCAP_T * P); static void sig_end (int Signo); SIGFUNC * SIGNAL (Int Signo, SIGFUNC * FUNC); Static SIGFUNC * SIGNAL (int Signo, SIGFUNC * FUNC); / * for ou signal () function * / static void Terminate (void); static void usage (char * arg); / * ---------- -------------------------------------------------- -------- * / static void Atexit (Void (* func)) {IF (Atexit (FUNC)! = 0) {EXIT (FAILURE);} Return;} / * end of Atexit * / static void bpf_dump (struct bpf_program * p, int option) {struct bpf_insn * insn; int i; int n = p-> bf_len; INSN = P-> bf_insns; if (option> 2) {fprintf (stderr, "% d / n", n); for (i = 0; i i) {fprintf (stderr, "% u% u% u% u / n", INSN-> Code, INSN-> JT, INSN-> JF, INSN-> K);} return;} if (option> 1 ) {For (i = 0; i [x % D] "; Break; case bpf_ld | bpf_b | bpf_ind: op =" ldb "; fmt =" [x % d] "; Break; case bpf_ld | bpf_imm: op =" ld "; fmt =" # 0x% x "; Break; Case BPF_LDX | BPF_IMM: OP =" LDX "; FMT =" # 0x% x "; Break; Case BPF_LDX | BPF_MSH | BPF_B: OP =" LDXB "; FMT =" 4 * ([[[[ % D] & 0xF) "; Break; Case BPF_LD | BPF_MEM: OP =" LD "; FMT =" M% D] "; Break; Case BPF_LDX | BPF_MEM: OP =" LDX "; FMT =" M [% D ], ";, CASE BPF_ST: OP =" ST "; FMT =" M% D] "; Break; Case BPF_STX: OP =" Stx "; FMT =" M [% D] "; Break; Case BPF_JMP | BPF_JA: OP = "ja"; FMT = "% D"; v = N 1 P-> K; Break; Case BPF_JMP | BPF_JGT | BPF_K: OP = "JGT"; FMT = "# 0x% x"; Break; case bpf_jmp | bpf_jge | BPF_K: OP = "JGE"; FMT = "# 0x% x"; Break; Case BPF_JMP | BPF_JEQ | BPF_K: OP = "JEQ"; FMT = "# 0x% x"; Break; case bpf_jmp | bpf_jset | bpf_k: op = "jset"; fmt = "# 0x% x"; Break; case bpf_jmp | bpf_jgt | bpf_x: op = "jgt"; fmt = "x"; break; case bpf_jmp | bpf_jge | bpf_x: op = "jge"; fmt = "x"; Break; case bpf_jmp | bpf_jeq | bpf_x: op = "jeq"; FMT = "x"; Break; Case BPF_JMP | BPF_JSET | BPF_X: OP = "jset"; FMT = "X"; Break; Case BPF_ALU | BPF_ADD | BPF_X: OP = "add"; fmt = "x"; Break; Case BPF_ALU | BPF_SUB | BPF_X: OP = "SUB"; FMT = "X"; Break; Case BPF_ALU | BPF_MUL | BPF_X: OP = "MUL"; FMT = "X"; Break; Case BPF_ALU | BPF_DIV | BPF_X: OP = "Div"; fmt = "x"; break; case bpf_alu | bpf_and | bpf_x: op = "and"; fmt = "x"; break; case bpf_alu | bpf_or | bpf_x: op = "or"; fmt = " x "; Break; Case BPF_ALU | BPF_LSH | BPF_X: OP =" LSH "; FMT =" X "; Break; Case BPF_ALU | BPF_RSH | BPF_X: OP =" RSH "; FMT =" X "; Break; Case BPF_ALU | BPF_ADD | BPF_K: OP = "Add"; FMT = "#% D"; Break; Case BPF_ALU | BPF_SUB | BPF_K: OP = "Sub"; FMT = "#% D"; BREAK; CASE BPF_ALU | BPF_MUL | BPF_K: Op = "mul"; FMT = "#% d"; Break; Case BPF_ALU | BPF_DIV | BPF_K: OP = "DIV"; FMT = "#% D"; Break; Case BPF_ALU | BPF_and | BPF_K: OP = "and"; fmt = "# 0x% X "; Break; Case BPF_ALU | BPF_OR | BPF_K: OP =" OR "; FMT =" # 0x% x "; Break; Case BPF_ALU | BPF_LSH | BPF_K: OP =" LSH "; FMT =" #% d "; Break; Case BPF_ALU | BPF_RSH | BPF_K: OP =" RSH "; FMT =" #% D "; Break; Case BPF_ALU | BPF_NEG: OP =" NEG "; FMT ="; "" ""; BREAK; CASE BPF_MISC | BPF_TAX: OP = "TAX"; FMT = ""; Break; Case BPF_MISC | BPF_TXA: OP = "TXA"; FMT = ""; Break;} / * end of switch * / (void) Sprintf (Operand, FMT) , V); (void) sprintf (image, (bpf_class (p-> code) == bpf_jmp && bpf_op (p-> code)! = Bpf_ja)? "(% 03D)% -8S% -16S jt% D / TJF% D ":" (% 03D)% -8S% S ", N, OP, OPERAND, N 1 P-> JT, N 1 P-> jf); return image;} / * end of BPF_IMAGE * / static void outputbinary (const size_t byterraylen) {u_long offset; INT I, J, K; FPRINTF (stderr, "ByteArray [% lu bytes] ----> / n", (Long unsigned INTEARRAYLEN; if (ByteaRraylen <= 0) {return;} i = 0; Offset = 0; for (k = byterraylen / 16; k> 0; k - = 16) {FPRINTF (STDERR, "% 08X", (unsigned int) OFFSET; for (j = 0; j <16; j , i ) {IF ( J == 8) {FPRINTF (stderr, "-% 02x", byteArray [i]);} else {fprintf (stderr, "% 02x", byteArray [i]);}} fprintf (stderr, ""); I - = 16; for (j = 0; j <16; J , i ) {/ * If (ISPRINT (INT) BYTEARRAY [I]) * / IF ((ByteArray [i]> = ') && (ByteArray [i] <= 255) {fprintf (stderr, "% C ", ByteArray [i]);} else {fprintf (stderr,". ");}} Fprintf (stderr," / n ");} / * end of for * / k = byterraylen - i; if (k < = 0) {return;} fprintf (STDERR, "% 08X", (unsigned int) Offset; for (j = 0; j