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交互非常像,只是更智能点。

 

posted on 2015-08-10 01:04  郁郁思扬  阅读(3262)  评论(0编辑  收藏  举报

导航