ndk编译libpcap 1.7.4
android完全菜鸟,绝对的第一次接触,想做手机抓包,在网上搜又是NDK 又是JNI 又是JNETPCAP 完全蒙了,让我这种android和java都弄不明白什么关系的人情何以堪!
静下心想一想,无非是编译一个库,好在C和LINUX都有10年的经验,就直接下最新的libpcap 1.7.4 一步步编译,成功了,写个测试也OK。现将过程写出,以做备忘。
下载安装 android studio、android-ndk-r10d、jdk、libpcap 1.7.4 我这面是全下的WIN7 64对应版本
1. 把libpcap的gz包托到VMWare上的ARCHLINUX里,tar xzf xxxxxx 然后
./configure --disable-ipv6 --disable-usb --disable-bluetooth --disable-canusb --disable-can --disable-dbus
make > res.txt
生成文件如下
gcc -fpic -I. -I/usr/include/libnl3 -DHAVE_CONFIG_H -D_U_="__attribute__((unused))" -g -O2 -c ./pcap-linux.c gcc -fpic -I. -I/usr/include/libnl3 -DHAVE_CONFIG_H -D_U_="__attribute__((unused))" -g -O2 -c ./pcap-netfilter-linux.c gcc -fpic -I. -I/usr/include/libnl3 -DHAVE_CONFIG_H -D_U_="__attribute__((unused))" -g -O2 -c ./fad-getad.c if grep GIT ./VERSION >/dev/null; then \ read ver <./VERSION; \ echo $ver | tr -d '\012'; \ date +_%Y_%m_%d; \ else \ cat ./VERSION; \ fi | sed -e 's/.*/static const char pcap_version_string[] = "libpcap version &";/' > version.h gcc -fpic -I. -I/usr/include/libnl3 -DHAVE_CONFIG_H -D_U_="__attribute__((unused))" -g -O2 -c ./pcap.c gcc -fpic -I. -I/usr/include/libnl3 -DHAVE_CONFIG_H -D_U_="__attribute__((unused))" -g -O2 -c ./inet.c gcc -fpic -I. -I/usr/include/libnl3 -DHAVE_CONFIG_H -D_U_="__attribute__((unused))" -g -O2 -c ./gencode.c gcc -fpic -I. -I/usr/include/libnl3 -DHAVE_CONFIG_H -D_U_="__attribute__((unused))" -g -O2 -c ./optimize.c gcc -fpic -I. -I/usr/include/libnl3 -DHAVE_CONFIG_H -D_U_="__attribute__((unused))" -g -O2 -c ./nametoaddr.c gcc -fpic -I. -I/usr/include/libnl3 -DHAVE_CONFIG_H -D_U_="__attribute__((unused))" -g -O2 -c ./etherent.c gcc -fpic -I. -I/usr/include/libnl3 -DHAVE_CONFIG_H -D_U_="__attribute__((unused))" -g -O2 -c ./savefile.c gcc -fpic -I. -I/usr/include/libnl3 -DHAVE_CONFIG_H -D_U_="__attribute__((unused))" -g -O2 -c ./sf-pcap.c gcc -fpic -I. -I/usr/include/libnl3 -DHAVE_CONFIG_H -D_U_="__attribute__((unused))" -g -O2 -c ./sf-pcap-ng.c gcc -fpic -I. -I/usr/include/libnl3 -DHAVE_CONFIG_H -D_U_="__attribute__((unused))" -g -O2 -c ./pcap-common.c gcc -fpic -I. -I/usr/include/libnl3 -DHAVE_CONFIG_H -D_U_="__attribute__((unused))" -g -O2 -c ./bpf_image.c gcc -fpic -I. -I/usr/include/libnl3 -DHAVE_CONFIG_H -D_U_="__attribute__((unused))" -g -O2 -c ./bpf_dump.c ./runlex.sh flex -Ppcap_ -oscanner.c scanner.l mv scanner.c scanner.c.bottom cat ./scanner.c.top scanner.c.bottom > scanner.c bison -y -p pcap_ -d grammar.y mv y.tab.c grammar.c mv y.tab.h tokdefs.h gcc -fpic -I. -I/usr/include/libnl3 -DHAVE_CONFIG_H -D_U_="__attribute__((unused))" -g -O2 -c scanner.c gcc -fpic -I. -I/usr/include/libnl3 -DHAVE_CONFIG_H -D_U_="__attribute__((unused))" -g -O2 -Dyylval=pcap_lval -c grammar.c rm -f bpf_filter.c ln -s ./bpf/net/bpf_filter.c bpf_filter.c gcc -fpic -I. -I/usr/include/libnl3 -DHAVE_CONFIG_H -D_U_="__attribute__((unused))" -g -O2 -c bpf_filter.c if grep GIT ./VERSION >/dev/null; then \ read ver <./VERSION; \ echo $ver | tr -d '\012'; \ date +_%Y_%m_%d; \ else \ cat ./VERSION; \ fi | sed -e 's/.*/char pcap_version[] = "&";/' > version.c gcc -fpic -I. -I/usr/include/libnl3 -DHAVE_CONFIG_H -D_U_="__attribute__((unused))" -g -O2 -c version.c ar rc libpcap.a pcap-linux.o pcap-netfilter-linux.o fad-getad.o pcap.o inet.o gencode.o optimize.o nametoaddr.o etherent.o savefile.o sf-pcap.o sf-pcap-ng.o pcap-common.o bpf_image.o bpf_dump.o scanner.o grammar.o bpf_filter.o version.o ranlib libpcap.a VER=`cat ./VERSION`; \ MAJOR_VER=`sed 's/\([0-9][0-9]*\)\..*/\1/' ./VERSION`; \ gcc -shared -Wl,-soname,libpcap.so.$MAJOR_VER \ -o libpcap.so.$VER pcap-linux.o pcap-netfilter-linux.o fad-getad.o pcap.o inet.o gencode.o optimize.o nametoaddr.o etherent.o savefile.o sf-pcap.o sf-pcap-ng.o pcap-common.o bpf_image.o bpf_dump.o scanner.o grammar.o bpf_filter.o version.o -lnl-genl-3 -lnl-3 ./config.status --file=pcap-config.tmp:./pcap-config.in config.status: creating pcap-config.tmp mv pcap-config.tmp pcap-config chmod a+x pcap-config
编译过程非常简单,但有五个文件是生成的(scanner.c grammar.c tokdefs.h version.c version.h),全部托到WINDOWS下,放到LIBPCAP源码目录。
另外,还有一个bpf_filter.c在子目录里,LINUX 建了一个软链接,WINDOWS里干脆直接COPY到源码里。
此时已经可以开始编译了,但出错是肯定的。。一个个来
完全不用什么SHELL之类的,就在源码目录里编译以下文件
D:\Android\android-ndk-r10d\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin\arm-linux-androideabi-gcc.exe -DNDEBUG -D_U_="__attribute__((unused))" -O2 -fomit-frame-pointer -Wall -pipe -I. -ID:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include -c ./pcap-linux.c D:\Android\android-ndk-r10d\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin\arm-linux-androideabi-gcc.exe -DNDEBUG -D_U_="__attribute__((unused))" -O2 -fomit-frame-pointer -Wall -pipe -I. -ID:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include -c ./pcap-netfilter-linux.c D:\Android\android-ndk-r10d\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin\arm-linux-androideabi-gcc.exe -DNDEBUG -D_U_="__attribute__((unused))" -O2 -fomit-frame-pointer -Wall -pipe -I. -ID:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include -c ./fad-getad.c D:\Android\android-ndk-r10d\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin\arm-linux-androideabi-gcc.exe -DNDEBUG -D_U_="__attribute__((unused))" -O2 -fomit-frame-pointer -Wall -pipe -I. -ID:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include -c ./pcap.c D:\Android\android-ndk-r10d\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin\arm-linux-androideabi-gcc.exe -DNDEBUG -D_U_="__attribute__((unused))" -O2 -fomit-frame-pointer -Wall -pipe -I. -ID:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include -c ./inet.c D:\Android\android-ndk-r10d\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin\arm-linux-androideabi-gcc.exe -DNDEBUG -D_U_="__attribute__((unused))" -O2 -fomit-frame-pointer -Wall -pipe -I. -ID:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include -c ./gencode.c D:\Android\android-ndk-r10d\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin\arm-linux-androideabi-gcc.exe -DNDEBUG -D_U_="__attribute__((unused))" -O2 -fomit-frame-pointer -Wall -pipe -I. -ID:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include -c ./optimize.c D:\Android\android-ndk-r10d\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin\arm-linux-androideabi-gcc.exe -DNDEBUG -D_U_="__attribute__((unused))" -O2 -fomit-frame-pointer -Wall -pipe -I. -ID:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include -c ./nametoaddr.c D:\Android\android-ndk-r10d\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin\arm-linux-androideabi-gcc.exe -DNDEBUG -D_U_="__attribute__((unused))" -O2 -fomit-frame-pointer -Wall -pipe -I. -ID:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include -c ./etherent.c D:\Android\android-ndk-r10d\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin\arm-linux-androideabi-gcc.exe -DNDEBUG -D_U_="__attribute__((unused))" -O2 -fomit-frame-pointer -Wall -pipe -I. -ID:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include -c ./savefile.c D:\Android\android-ndk-r10d\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin\arm-linux-androideabi-gcc.exe -DNDEBUG -D_U_="__attribute__((unused))" -O2 -fomit-frame-pointer -Wall -pipe -I. -ID:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include -c ./sf-pcap.c D:\Android\android-ndk-r10d\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin\arm-linux-androideabi-gcc.exe -DNDEBUG -D_U_="__attribute__((unused))" -O2 -fomit-frame-pointer -Wall -pipe -I. -ID:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include -c ./sf-pcap-ng.c D:\Android\android-ndk-r10d\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin\arm-linux-androideabi-gcc.exe -DNDEBUG -D_U_="__attribute__((unused))" -O2 -fomit-frame-pointer -Wall -pipe -I. -ID:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include -c ./pcap-common.c D:\Android\android-ndk-r10d\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin\arm-linux-androideabi-gcc.exe -DNDEBUG -D_U_="__attribute__((unused))" -O2 -fomit-frame-pointer -Wall -pipe -I. -ID:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include -c ./bpf_image.c D:\Android\android-ndk-r10d\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin\arm-linux-androideabi-gcc.exe -DNDEBUG -D_U_="__attribute__((unused))" -O2 -fomit-frame-pointer -Wall -pipe -I. -ID:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include -c ./bpf_dump.c D:\Android\android-ndk-r10d\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin\arm-linux-androideabi-gcc.exe -DNDEBUG -D_U_="__attribute__((unused))" -O2 -fomit-frame-pointer -Wall -pipe -I. -ID:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include -c ./scanner.c D:\Android\android-ndk-r10d\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin\arm-linux-androideabi-gcc.exe -DNDEBUG -D_U_="__attribute__((unused))" -O2 -fomit-frame-pointer -Wall -pipe -I. -ID:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include -c ./bpf_filter.c D:\Android\android-ndk-r10d\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin\arm-linux-androideabi-gcc.exe -DNDEBUG -D_U_="__attribute__((unused))" -O2 -fomit-frame-pointer -Wall -pipe -I. -ID:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include -c ./version.c D:\Android\android-ndk-r10d\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin\arm-linux-androideabi-gcc.exe -DNDEBUG -D_U_="__attribute__((unused))" -Dyylval=pcap_lval -O2 -fomit-frame-pointer -Wall -pipe -I. -ID:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include -c grammar.c
1. pcap-netfilter-linux.c 编译出错
D:\libpcap-1.7.4>D:\Android\android-ndk-r10d\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin\arm-linux-androideabi-gcc.exe -DNDEBUG -D_U_="__attribute__((unused))" -O2 -fomit-frame-pointer -Wall -pipe -I. -ID:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include -c ./pcap-netfilter-linux.c In file included from D:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include/stdlib.h:40:0, from ./pcap-netfilter-linux.c:42: D:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include/string.h:76:15: error: expected declaration specifiers or '...' before '(' token D:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include/string.h:76:15: error: expected declaration specifiers or '...' before '(' token D:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include/string.h:76:15: error: expected declaration specifiers or '...' before '(' token D:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include/string.h:76:15: error: expected ')' before ',' token
这需要在pcap-int.h中进行修改
1 #define HAVE_STRLCPY 1 //加这一句 2 #ifndef HAVE_STRLCPY 3 #define strlcpy(x, y, z) \ 4 (strncpy((x), (y), (z)), \ 5 ((z) <= 0 ? 0 : ((x)[(z) - 1] = '\0')), \ 6 strlen((y))) 7 #endif
2. fad-getad.c 编译出错
./fad-getad.c:50:21: fatal error: ifaddrs.h: No such file or directory compilation terminated.
这个用的接口是getifaddrs 本来就释放不了问题很多,连原来代码里都有提到代码会报错,我看了下里面无非就是列举网卡,就重写了该文件,如下
1 /* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ 2 /* 3 * Copyright (c) 1994, 1995, 1996, 1997, 1998 4 * The Regents of the University of California. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by the Computer Systems 17 * Engineering Group at Lawrence Berkeley Laboratory. 18 * 4. Neither the name of the University nor of the Laboratory may be used 19 * to endorse or promote products derived from this software without 20 * specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #ifdef HAVE_CONFIG_H 36 #include "config.h" 37 #endif 38 39 #include <sys/types.h> 40 #include <sys/socket.h> 41 #include <netinet/in.h> 42 43 #include <net/if.h> 44 45 #include <ctype.h> 46 #include <errno.h> 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <string.h> 50 #include <unistd.h> 51 //#include <linux/if.h> 52 //#include <ifaddrs.h> 53 54 #include "pcap-int.h" 55 56 #ifdef HAVE_OS_PROTO_H 57 #include "os-proto.h" 58 #endif 59 60 /* 61 * We don't do this on Solaris 11 and later, as it appears there aren't 62 * any AF_PACKET addresses on interfaces, so we don't need this, and 63 * we end up including both the OS's <net/bpf.h> and our <pcap/bpf.h>, 64 * and their definitions of some data structures collide. 65 */ 66 #if (defined(linux) || defined(__Lynx__)) && defined(AF_PACKET) 67 # ifdef HAVE_NETPACKET_PACKET_H 68 /* Linux distributions with newer glibc */ 69 # include <netpacket/packet.h> 70 # else /* HAVE_NETPACKET_PACKET_H */ 71 /* LynxOS, Linux distributions with older glibc */ 72 # ifdef __Lynx__ 73 /* LynxOS */ 74 # include <netpacket/if_packet.h> 75 # else /* __Lynx__ */ 76 /* Linux */ 77 # include <linux/types.h> 78 # include <linux/if_packet.h> 79 # endif /* __Lynx__ */ 80 # endif /* HAVE_NETPACKET_PACKET_H */ 81 #endif /* (defined(linux) || defined(__Lynx__)) && defined(AF_PACKET) */ 82 83 /* 84 * This is fun. 85 * 86 * In older BSD systems, socket addresses were fixed-length, and 87 * "sizeof (struct sockaddr)" gave the size of the structure. 88 * All addresses fit within a "struct sockaddr". 89 * 90 * In newer BSD systems, the socket address is variable-length, and 91 * there's an "sa_len" field giving the length of the structure; 92 * this allows socket addresses to be longer than 2 bytes of family 93 * and 14 bytes of data. 94 * 95 * Some commercial UNIXes use the old BSD scheme, some use the RFC 2553 96 * variant of the old BSD scheme (with "struct sockaddr_storage" rather 97 * than "struct sockaddr"), and some use the new BSD scheme. 98 * 99 * Some versions of GNU libc use neither scheme, but has an "SA_LEN()" 100 * macro that determines the size based on the address family. Other 101 * versions don't have "SA_LEN()" (as it was in drafts of RFC 2553 102 * but not in the final version). On the latter systems, we explicitly 103 * check the AF_ type to determine the length; we assume that on 104 * all those systems we have "struct sockaddr_storage". 105 */ 106 #ifndef SA_LEN 107 #ifdef HAVE_SOCKADDR_SA_LEN 108 #define SA_LEN(addr) ((addr)->sa_len) 109 #else /* HAVE_SOCKADDR_SA_LEN */ 110 #ifdef HAVE_SOCKADDR_STORAGE 111 static size_t 112 get_sa_len( struct sockaddr* addr ) 113 { 114 switch ( addr->sa_family ) 115 { 116 117 #ifdef AF_INET 118 case AF_INET: 119 return ( sizeof ( struct sockaddr_in ) ); 120 #endif 121 122 #ifdef AF_INET6 123 case AF_INET6: 124 return ( sizeof ( struct sockaddr_in6 ) ); 125 #endif 126 127 #if (defined(linux) || defined(__Lynx__)) && defined(AF_PACKET) 128 case AF_PACKET: 129 return ( sizeof ( struct sockaddr_ll ) ); 130 #endif 131 132 default: 133 return ( sizeof ( struct sockaddr ) ); 134 } 135 } 136 #define SA_LEN(addr) (get_sa_len(addr)) 137 #else /* HAVE_SOCKADDR_STORAGE */ 138 #define SA_LEN(addr) (sizeof (struct sockaddr)) 139 #endif /* HAVE_SOCKADDR_STORAGE */ 140 #endif /* HAVE_SOCKADDR_SA_LEN */ 141 #endif /* SA_LEN */ 142 143 /* 144 * Get a list of all interfaces that are up and that we can open. 145 * Returns -1 on error, 0 otherwise. 146 * The list, as returned through "alldevsp", may be null if no interfaces 147 * could be opened. 148 */ 149 150 #define MAX_INTERFACE 32 151 struct ifreq ifr[MAX_INTERFACE]; 152 153 154 int pcap_findalldevs_interfaces( pcap_if_t** alldevsp, char* errbuf ) 155 { 156 pcap_if_t* devlist; 157 int i, rc, sock, ifnum; 158 char ifname[IFNAMSIZ]; 159 160 struct sockaddr* addr, *netmask, *broadaddr, *dstaddr; 161 size_t addr_size, broadaddr_size, dstaddr_size; 162 struct ifconf ifc; 163 char* p; 164 165 devlist = NULL; 166 167 sock = socket ( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); 168 if ( sock == -1 ) 169 { 170 ( void )snprintf( errbuf, PCAP_ERRBUF_SIZE, "sock: %s", pcap_strerror( errno ) ); 171 return -1; 172 } 173 174 175 ifc.ifc_len = sizeof( ifr ); 176 ifc.ifc_buf = ( caddr_t ) ifr; 177 rc = ioctl( sock, SIOCGIFCONF, &ifc ); 178 if ( rc == -1 ) 179 { 180 ( void )snprintf( errbuf, PCAP_ERRBUF_SIZE, "ioctl: %s", pcap_strerror( errno ) ); 181 close( sock ); 182 return -1; 183 } 184 185 ifnum = ifc.ifc_len / sizeof ( struct ifreq ); 186 if ( ifnum > MAX_INTERFACE ) 187 { 188 ifnum = MAX_INTERFACE; 189 } 190 191 for ( i = 0; i < ifnum; i ++ ) 192 { 193 rc = ioctl( sock, SIOCGIFFLAGS, ifr + i ); 194 if ( rc == -1 ) 195 { 196 ( void )snprintf( errbuf, PCAP_ERRBUF_SIZE, "ioctl: %s", pcap_strerror( errno ) ); 197 break; 198 } 199 200 //ip netmask 201 rc = ioctl ( sock, SIOCGIFADDR, ifr + i ); 202 if ( rc != -1 ) 203 { 204 addr = &ifr[i].ifr_addr; 205 addr_size = SA_LEN( addr ); 206 207 ioctl ( sock, SIOCGIFNETMASK, ifr + i ); 208 netmask = &ifr[i].ifr_netmask; 209 } 210 else 211 { 212 continue; 213 } 214 215 // broadcast 216 if ( ( ifr[i].ifr_flags & IFF_BROADCAST ) && ( rc = ioctl ( sock, SIOCGIFBRDADDR, ifr + i ) ) != -1 ) 217 { 218 broadaddr = &ifr[i].ifr_broadaddr; 219 broadaddr_size = SA_LEN( broadaddr ); 220 } 221 else 222 { 223 broadaddr = NULL; 224 broadaddr_size = 0; 225 } 226 227 // p2p 228 if ( ( ifr[i].ifr_flags & IFF_POINTOPOINT ) && ( rc = ioctl ( sock, SIOCGIFDSTADDR, ifr + i ) ) != -1 ) 229 { 230 dstaddr = &ifr[i].ifr_dstaddr; 231 dstaddr_size = SA_LEN( dstaddr ); 232 } 233 else 234 { 235 dstaddr = NULL; 236 dstaddr_size = 0; 237 } 238 239 // ifname 240 memset( ifname, 0, sizeof( ifname ) ); 241 strcpy( ifname, ifr[i].ifr_name ); 242 243 /*p = strchr( ifname, ':' ); 244 if ( p != NULL ) 245 { 246 *p = 0; 247 }*/ 248 249 printf("add [%d][%s]\n", i, ifname); 250 if ( add_addr_to_iflist( &devlist, ifname, 251 ifr[i].ifr_flags, addr, addr_size, netmask, addr_size, 252 broadaddr, broadaddr_size, dstaddr, dstaddr_size, 253 errbuf ) < 0 ) 254 { 255 rc = -1; 256 break; 257 } 258 } 259 260 if ( rc == -1 ) 261 { 262 if ( devlist != NULL ) 263 { 264 pcap_freealldevs( devlist ); 265 devlist = NULL; 266 } 267 } 268 269 *alldevsp = devlist; 270 close( sock ); 271 return 0; 272 }
3. pcap.c报错
D:\libpcap-1.7.4\pcap.c: In function 'pcap_strerror': D:\libpcap-1.7.4\pcap.c:1591:27: error: conflicting types for 'sys_errlist' D:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include/stdio.h:239:14: note: previous declaration of 'sys_errlist' was here
修改该函数
1 const char * 2 pcap_strerror(int errnum) 3 { 4 #define HAVE_STRERROR 1//加这一句 5 #ifdef HAVE_STRERROR 6 return (strerror(errnum)); 7 #else 8 extern int sys_nerr; 9 extern const char *const sys_errlist[]; 10 static char ebuf[15+10+1]; 11 12 if ((unsigned int)errnum < sys_nerr) 13 return ((char *)sys_errlist[errnum]); 14 (void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum); 15 return(ebuf); 16 #endif 17 }
4. inet.c警告
---------- ndk-gcc ---------- D:\libpcap-1.7.4\inet.c:71:0: warning: "INT_MAX" redefined [enabled by default] D:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include/sys/limits.h:68:0: note: this is the location of the previous definition
修改为
#define HAVE_LIMITS_H 1 //加这一句 #ifdef HAVE_LIMITS_H #include <limits.h> #else #define INT_MAX 2147483647 #endif
5. gencode.c警告
一大堆,分支可能无法RETURN 变量可能未初始化之类的,不影响,不作修改!
然后开始链接,这里恶心了好久.后来想想也明白了,这个就是嵌入式板子上的一个LINUX系统,没有标准C库。一定要加-nostdlib
还有就是体现出菜鸟本色的东西了,crtend_android.o crtbegin_dynamic.o 这两个东西不知道干什么的,在网上看了下,好像都要,应该是启动代码类的,本来可能是后缀S的汇编。。所以直接COPY到源码文件夹。至于为什么用dynamic,只是因为我要编译SO。不过后缀有SO的可能更好,纠结了半天用的是crtend_so.o crtbegin_so.o。后面测试程序再用上面的两个好了。
然后执行
D:\Android\android-ndk-r10d\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin\arm-linux-androideabi-gcc.exe -nostdlib -Bdynamic -shared -Wl,-soname,libpcap.so -o libpcap.so pcap-linux.o pcap-netfilter-linux.o fad-getad.o pcap.o inet.o gencode.o optimize.o nametoaddr.o etherent.o savefile.o sf-pcap.o sf-pcap-ng.o pcap-common.o bpf_image.o bpf_dump.o scanner.o grammar.o bpf_filter.o version.o crtend_so.o crtbegin_so.o -LD:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\lib -lc -ldl -llog -lgcc -lm -landroid -lz
顺利生成libpcap.so
然后写个程序测下
1 //netpkghdr.h 2 #ifndef _NET_PKG_HDR_H_ 3 #define _NET_PKG_HDR_H_ 4 5 6 7 #define ETHERTYPE_IP 0x0008 // IP协议 (0x0800的网络序) 8 #define TCP_PROTOCAL 0x0006 // TCP协议 (0x0600的网络序) 9 #define BUFF_MAX_LEN 0x10000 // 最大包长 10 11 12 #pragma pack(push, 1) 13 14 // ethernet header 15 typedef struct ether_header 16 { 17 unsigned char dst[6]; // 目标MAC 18 unsigned char src[6]; // 源MAC 19 unsigned short type; // 上层协议标识 20 } eth_hdr; 21 22 // ipv4 address 23 typedef struct ip_address 24 { 25 unsigned char b1, b2, b3, b4; 26 } ip_addr; 27 28 // ipv4 header 29 typedef struct ip_header 30 { 31 unsigned char ver_ihl; // 版本信息(4)头长度(4) 32 unsigned char tos; // 服务类型 33 unsigned short len; // 数据包长度 34 unsigned short id; // 数据包标识 35 unsigned short slice; // 片偏移 36 unsigned char ttl; // ttl 37 unsigned char proto; // 协议 38 unsigned short sum; // 校验和 39 ip_addr saddr; // 源IP 40 ip_addr daddr; // 目标IP 41 } ip_hdr; 42 43 // tcp header 44 typedef struct tcp_header 45 { 46 unsigned short sport; // 源端口 47 unsigned short dport; // 目标端口 48 unsigned int seq; // 序列号 49 unsigned int ack; // 应答 50 unsigned short len_code; // TCP头长度(4)保留(6)标志(6) 51 unsigned short window; // 窗口大小 52 unsigned short sum; // 校验和 53 unsigned short urp; // 紧急数据偏移 54 } tcp_hdr; 55 56 // udp header 57 typedef struct udp_header 58 { 59 unsigned short sport; // 源端口 60 unsigned short dport; // 目标端口 61 unsigned short len; // 包长 62 unsigned short sum; // 校验和 63 } udp_hdr; 64 65 #pragma pack(pop) 66 67 68 #endif /* _NET_PKG_HDR_H_ */
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <pcap.h> 5 #include "netpkghdr.h" 6 7 8 unsigned char g_buffer[BUFF_MAX_LEN] = {0}; 9 10 11 pcap_t* get_pcap( const char* name ) 12 { 13 pcap_if_t* ifs; 14 pcap_if_t* d; 15 pcap_t* pcap; 16 char errbuff[PCAP_ERRBUF_SIZE]; 17 18 if ( pcap_findalldevs( &ifs, errbuff ) == -1 ) 19 { 20 fprintf( stderr, "pcap_findalldevs [%s]\n", errbuff ); 21 return NULL; 22 } 23 24 for ( d = ifs; d; d = d->next ) 25 { 26 if ( memcmp( d->name, name, strlen( name ) ) == 0 ) 27 { 28 break; 29 } 30 } 31 32 pcap = pcap_open_live( d->name, \ 33 BUFF_MAX_LEN, \ 34 0, \ 35 3000, \ 36 errbuff ); 37 38 pcap_freealldevs( ifs ); 39 40 if ( pcap == NULL ) 41 { 42 fprintf( stderr, "pcap_open_live [%s]\n", errbuff ); 43 return NULL; 44 } 45 46 return pcap; 47 } 48 49 int main() 50 { 51 int rc; 52 pcap_t* pcap; 53 struct bpf_program bpf; 54 55 struct pcap_pkthdr* header; 56 const unsigned char* pkt_data; 57 58 59 eth_hdr* eth; 60 61 ip_hdr* ip; 62 unsigned short ip_hdr_len; 63 64 tcp_hdr* tcp; 65 unsigned short tcp_hdr_len; 66 unsigned short tcp_data_len; 67 unsigned char* tcp_pkt_data; 68 69 70 if ( ( pcap = get_pcap( "wlan" ) ) == NULL ) 71 { 72 return -1; 73 } 74 75 76 if ( pcap_compile( pcap, &bpf, "tcp port 80", 1, 0 ) < 0 ) 77 { 78 fprintf( stderr, "pcap_compile error\n" ); 79 return -1; 80 } 81 82 if ( pcap_setfilter( pcap, &bpf ) < 0 ) 83 { 84 fprintf( stderr, "pcap_setfilter\n" ); 85 return -1; 86 } 87 88 89 while ( ( rc = pcap_next_ex( pcap, &header, &pkt_data ) ) >= 0 ) 90 { 91 if ( rc == 0 ) 92 { 93 continue; 94 } 95 96 eth = ( eth_hdr* )pkt_data; 97 98 ip = ( ip_hdr* )( eth + 1 ); 99 ip_hdr_len = ( ( ip->ver_ihl & 0x0F ) << 2 ); 100 101 tcp = ( tcp_hdr* )( pkt_data + sizeof( eth_hdr ) + ip_hdr_len ); 102 tcp_hdr_len = ( ( tcp->len_code & 0x00F0 ) >> 2 ); 103 tcp_data_len = header->len - sizeof( eth_hdr ) - ip_hdr_len - tcp_hdr_len; 104 tcp_pkt_data = ( unsigned char* )tcp + tcp_hdr_len; 105 106 107 if ( tcp_data_len < 3 || \ 108 ( strncmp( ( char* )tcp_pkt_data, "GET", 3 ) && \ 109 strncmp( ( char* )tcp_pkt_data, "POST", 4 ) && \ 110 strncmp( ( char* )tcp_pkt_data, "HTTP/1.1", 8 ) ) ) 111 { 112 continue; 113 } 114 115 memcpy( g_buffer, tcp_pkt_data, tcp_data_len ); 116 g_buffer[tcp_data_len] = 0; 117 118 119 printf( "==============================================\n" ); 120 printf( "%s\n", ( char* )g_buffer ); 121 printf( "**********************************************\n\n" ); 122 } 123 124 125 pcap_close( pcap ); 126 127 128 return 0; 129 }
编译之
D:\Android\android-ndk-r10d\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin\arm-linux-androideabi-gcc.exe -DNDEBUG -O2 -fomit-frame-pointer -Wall -pipe -c main.c -I. -ID:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\include -I./pcap D:\Android\android-ndk-r10d\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin\arm-linux-androideabi-gcc.exe -nostdlib -Bdynamic -Wl,-dynamic-linker,/system/bin/linker -o hello main.o D:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\lib\crtend_android.o D:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\lib\crtbegin_dynamic.o -L. -LD:\Android\android-ndk-r10d\platforms\android-19\arch-arm\usr\lib -lc -ldl -llog -lgcc -lm -landroid -lz -lpcap
报错!!!
d:/android/android-ndk-r10d/toolchains/arm-linux-androideabi-4.6/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld.exe: ./libpcap.so: error: undefined reference to 'pcap_snprintf' d:/android/android-ndk-r10d/toolchains/arm-linux-androideabi-4.6/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld.exe: ./libpcap.so: error: undefined reference to 'pcap_vsnprintf' collect2: ld returned 1 exit status
明显是PCAP源码里这两个函数有问题,回头再去改源码
同样是修改pcap-int.h
#define HAVE_SNPRINTF 1 //添加这一句 #if !defined(HAVE_SNPRINTF) #define snprintf pcap_snprintf extern int snprintf (char *, size_t, const char *, ...); #endif #define HAVE_VSNPRINTF 1 //添加这一句 #if !defined(HAVE_VSNPRINTF) #define vsnprintf pcap_vsnprintf extern int vsnprintf (char *, size_t, const char *, va_list ap); #endif
重新生成SO,并编译程序 ...顺利生成hello
然后用传说中的adb push到里面(这个查了半小时,不知道ADB是什么)
用RE把so放/system/lib 改权限
用RE修改hello权限
adb shell,发现和LINUX一样一样的。。。
执行之
明天再写几个JNI的东西,把这一堆PCAP的函数包成我想要的,然后写JAVA。。。再然后就OK了。。
闲扯几句,开始看了眼JNI吓一跳,后来用和上面一要最土的方法,试了下,发现和C与LUA交互非常像,只是更智能点。