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- -lnl-
./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-\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-\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-\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-\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-\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-\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-\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-\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-\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-\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-\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-\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-\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-\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-\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-\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-\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-\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-\arch-arm\usr\include -c grammar.c
1. pcap-netfilter-linux.c 编译出错
D:\libpcap-1.7.>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-\arch-arm\usr\include -c ./pcap-netfilter-linux.c
In file included from D:\Android\android-ndk-r10d\platforms\android-\arch-arm\usr\include/stdlib.h::,
from ./pcap-netfilter-linux.c::
D:\Android\android-ndk-r10d\platforms\android-\arch-arm\usr\include/string.h::: error: expected declaration specifiers or '...' before '(' token
D:\Android\android-ndk-r10d\platforms\android-\arch-arm\usr\include/string.h::: error: expected declaration specifiers or '...' before '(' token
D:\Android\android-ndk-r10d\platforms\android-\arch-arm\usr\include/string.h::: error: expected declaration specifiers or '...' before '(' token
D:\Android\android-ndk-r10d\platforms\android-\arch-arm\usr\include/string.h::: error: expected ')' before ',' token
这需要在pcap-int.h中进行修改
#define HAVE_STRLCPY 1 //加这一句
#ifndef HAVE_STRLCPY
#define strlcpy(x, y, z) \
(strncpy((x), (y), (z)), \
((z) <= ? : ((x)[(z) - ] = '\0')), \
strlen((y)))
#endif
2. fad-getad.c 编译出错
./fad-getad.c::: fatal error: ifaddrs.h: No such file or directory
compilation terminated.
这个用的接口是getifaddrs 本来就释放不了问题很多,连原来代码里都有提到代码会报错,我看了下里面无非就是列举网卡,就重写了该文件,如下
/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
/*
* Copyright (c) 1994, 1995, 1996, 1997, 1998
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the Computer Systems
* Engineering Group at Lawrence Berkeley Laboratory.
* 4. Neither the name of the University nor of the Laboratory may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/ #ifdef HAVE_CONFIG_H
#include "config.h"
#endif #include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h> #include <net/if.h> #include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
//#include <linux/if.h>
//#include <ifaddrs.h> #include "pcap-int.h" #ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
#endif /*
* We don't do this on Solaris 11 and later, as it appears there aren't
* any AF_PACKET addresses on interfaces, so we don't need this, and
* we end up including both the OS's <net/bpf.h> and our <pcap/bpf.h>,
* and their definitions of some data structures collide.
*/
#if (defined(linux) || defined(__Lynx__)) && defined(AF_PACKET)
# ifdef HAVE_NETPACKET_PACKET_H
/* Linux distributions with newer glibc */
# include <netpacket/packet.h>
# else /* HAVE_NETPACKET_PACKET_H */
/* LynxOS, Linux distributions with older glibc */
# ifdef __Lynx__
/* LynxOS */
# include <netpacket/if_packet.h>
# else /* __Lynx__ */
/* Linux */
# include <linux/types.h>
# include <linux/if_packet.h>
# endif /* __Lynx__ */
# endif /* HAVE_NETPACKET_PACKET_H */
#endif /* (defined(linux) || defined(__Lynx__)) && defined(AF_PACKET) */ /*
* This is fun.
*
* In older BSD systems, socket addresses were fixed-length, and
* "sizeof (struct sockaddr)" gave the size of the structure.
* All addresses fit within a "struct sockaddr".
*
* In newer BSD systems, the socket address is variable-length, and
* there's an "sa_len" field giving the length of the structure;
* this allows socket addresses to be longer than 2 bytes of family
* and 14 bytes of data.
*
* Some commercial UNIXes use the old BSD scheme, some use the RFC 2553
* variant of the old BSD scheme (with "struct sockaddr_storage" rather
* than "struct sockaddr"), and some use the new BSD scheme.
*
* Some versions of GNU libc use neither scheme, but has an "SA_LEN()"
* macro that determines the size based on the address family. Other
* versions don't have "SA_LEN()" (as it was in drafts of RFC 2553
* but not in the final version). On the latter systems, we explicitly
* check the AF_ type to determine the length; we assume that on
* all those systems we have "struct sockaddr_storage".
*/
#ifndef SA_LEN
#ifdef HAVE_SOCKADDR_SA_LEN
#define SA_LEN(addr) ((addr)->sa_len)
#else /* HAVE_SOCKADDR_SA_LEN */
#ifdef HAVE_SOCKADDR_STORAGE
static size_t
get_sa_len( struct sockaddr* addr )
{
switch ( addr->sa_family )
{ #ifdef AF_INET
case AF_INET:
return ( sizeof ( struct sockaddr_in ) );
#endif #ifdef AF_INET6
case AF_INET6:
return ( sizeof ( struct sockaddr_in6 ) );
#endif #if (defined(linux) || defined(__Lynx__)) && defined(AF_PACKET)
case AF_PACKET:
return ( sizeof ( struct sockaddr_ll ) );
#endif default:
return ( sizeof ( struct sockaddr ) );
}
}
#define SA_LEN(addr) (get_sa_len(addr))
#else /* HAVE_SOCKADDR_STORAGE */
#define SA_LEN(addr) (sizeof (struct sockaddr))
#endif /* HAVE_SOCKADDR_STORAGE */
#endif /* HAVE_SOCKADDR_SA_LEN */
#endif /* SA_LEN */ /*
* Get a list of all interfaces that are up and that we can open.
* Returns -1 on error, 0 otherwise.
* The list, as returned through "alldevsp", may be null if no interfaces
* could be opened.
*/ #define MAX_INTERFACE 32
struct ifreq ifr[MAX_INTERFACE]; int pcap_findalldevs_interfaces( pcap_if_t** alldevsp, char* errbuf )
{
pcap_if_t* devlist;
int i, rc, sock, ifnum;
char ifname[IFNAMSIZ]; struct sockaddr* addr, *netmask, *broadaddr, *dstaddr;
size_t addr_size, broadaddr_size, dstaddr_size;
struct ifconf ifc;
char* p; devlist = NULL; sock = socket ( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
if ( sock == - )
{
( void )snprintf( errbuf, PCAP_ERRBUF_SIZE, "sock: %s", pcap_strerror( errno ) );
return -;
} ifc.ifc_len = sizeof( ifr );
ifc.ifc_buf = ( caddr_t ) ifr;
rc = ioctl( sock, SIOCGIFCONF, &ifc );
if ( rc == - )
{
( void )snprintf( errbuf, PCAP_ERRBUF_SIZE, "ioctl: %s", pcap_strerror( errno ) );
close( sock );
return -;
} ifnum = ifc.ifc_len / sizeof ( struct ifreq );
if ( ifnum > MAX_INTERFACE )
{
ifnum = MAX_INTERFACE;
} for ( i = ; i < ifnum; i ++ )
{
rc = ioctl( sock, SIOCGIFFLAGS, ifr + i );
if ( rc == - )
{
( void )snprintf( errbuf, PCAP_ERRBUF_SIZE, "ioctl: %s", pcap_strerror( errno ) );
break;
} //ip netmask
rc = ioctl ( sock, SIOCGIFADDR, ifr + i );
if ( rc != - )
{
addr = &ifr[i].ifr_addr;
addr_size = SA_LEN( addr ); ioctl ( sock, SIOCGIFNETMASK, ifr + i );
netmask = &ifr[i].ifr_netmask;
}
else
{
continue;
} // broadcast
if ( ( ifr[i].ifr_flags & IFF_BROADCAST ) && ( rc = ioctl ( sock, SIOCGIFBRDADDR, ifr + i ) ) != - )
{
broadaddr = &ifr[i].ifr_broadaddr;
broadaddr_size = SA_LEN( broadaddr );
}
else
{
broadaddr = NULL;
broadaddr_size = ;
} // p2p
if ( ( ifr[i].ifr_flags & IFF_POINTOPOINT ) && ( rc = ioctl ( sock, SIOCGIFDSTADDR, ifr + i ) ) != - )
{
dstaddr = &ifr[i].ifr_dstaddr;
dstaddr_size = SA_LEN( dstaddr );
}
else
{
dstaddr = NULL;
dstaddr_size = ;
} // ifname
memset( ifname, , sizeof( ifname ) );
strcpy( ifname, ifr[i].ifr_name ); /*p = strchr( ifname, ':' );
if ( p != NULL )
{
*p = 0;
}*/ printf("add [%d][%s]\n", i, ifname);
if ( add_addr_to_iflist( &devlist, ifname,
ifr[i].ifr_flags, addr, addr_size, netmask, addr_size,
broadaddr, broadaddr_size, dstaddr, dstaddr_size,
errbuf ) < )
{
rc = -;
break;
}
} if ( rc == - )
{
if ( devlist != NULL )
{
pcap_freealldevs( devlist );
devlist = NULL;
}
} *alldevsp = devlist;
close( sock );
return ;
}
3. pcap.c报错
D:\libpcap-1.7.\pcap.c: In function 'pcap_strerror':
D:\libpcap-1.7.\pcap.c::: error: conflicting types for 'sys_errlist'
D:\Android\android-ndk-r10d\platforms\android-\arch-arm\usr\include/stdio.h::: note: previous declaration of 'sys_errlist' was here
修改该函数
const char *
pcap_strerror(int errnum)
{
#define HAVE_STRERROR 1//加这一句
#ifdef HAVE_STRERROR
return (strerror(errnum));
#else
extern int sys_nerr;
extern const char *const sys_errlist[];
static char ebuf[++]; if ((unsigned int)errnum < sys_nerr)
return ((char *)sys_errlist[errnum]);
(void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
return(ebuf);
#endif
}
4. inet.c警告
---------- ndk-gcc ----------
D:\libpcap-1.7.\inet.c::: warning: "INT_MAX" redefined [enabled by default]
D:\Android\android-ndk-r10d\platforms\android-\arch-arm\usr\include/sys/limits.h::: 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
然后写个程序测下
//netpkghdr.h
#ifndef _NET_PKG_HDR_H_
#define _NET_PKG_HDR_H_ #define ETHERTYPE_IP 0x0008 // IP协议 (0x0800的网络序)
#define TCP_PROTOCAL 0x0006 // TCP协议 (0x0600的网络序)
#define BUFF_MAX_LEN 0x10000 // 最大包长 #pragma pack(push, 1) // ethernet header
typedef struct ether_header
{
unsigned char dst[]; // 目标MAC
unsigned char src[]; // 源MAC
unsigned short type; // 上层协议标识
} eth_hdr; // ipv4 address
typedef struct ip_address
{
unsigned char b1, b2, b3, b4;
} ip_addr; // ipv4 header
typedef struct ip_header
{
unsigned char ver_ihl; // 版本信息(4)头长度(4)
unsigned char tos; // 服务类型
unsigned short len; // 数据包长度
unsigned short id; // 数据包标识
unsigned short slice; // 片偏移
unsigned char ttl; // ttl
unsigned char proto; // 协议
unsigned short sum; // 校验和
ip_addr saddr; // 源IP
ip_addr daddr; // 目标IP
} ip_hdr; // tcp header
typedef struct tcp_header
{
unsigned short sport; // 源端口
unsigned short dport; // 目标端口
unsigned int seq; // 序列号
unsigned int ack; // 应答
unsigned short len_code; // TCP头长度(4)保留(6)标志(6)
unsigned short window; // 窗口大小
unsigned short sum; // 校验和
unsigned short urp; // 紧急数据偏移
} tcp_hdr; // udp header
typedef struct udp_header
{
unsigned short sport; // 源端口
unsigned short dport; // 目标端口
unsigned short len; // 包长
unsigned short sum; // 校验和
} udp_hdr; #pragma pack(pop) #endif /* _NET_PKG_HDR_H_ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pcap.h>
#include "netpkghdr.h" unsigned char g_buffer[BUFF_MAX_LEN] = {}; pcap_t* get_pcap( const char* name )
{
pcap_if_t* ifs;
pcap_if_t* d;
pcap_t* pcap;
char errbuff[PCAP_ERRBUF_SIZE]; if ( pcap_findalldevs( &ifs, errbuff ) == - )
{
fprintf( stderr, "pcap_findalldevs [%s]\n", errbuff );
return NULL;
} for ( d = ifs; d; d = d->next )
{
if ( memcmp( d->name, name, strlen( name ) ) == )
{
break;
}
} pcap = pcap_open_live( d->name, \
BUFF_MAX_LEN, \
, \
, \
errbuff ); pcap_freealldevs( ifs ); if ( pcap == NULL )
{
fprintf( stderr, "pcap_open_live [%s]\n", errbuff );
return NULL;
} return pcap;
} int main()
{
int rc;
pcap_t* pcap;
struct bpf_program bpf; struct pcap_pkthdr* header;
const unsigned char* pkt_data; eth_hdr* eth; ip_hdr* ip;
unsigned short ip_hdr_len; tcp_hdr* tcp;
unsigned short tcp_hdr_len;
unsigned short tcp_data_len;
unsigned char* tcp_pkt_data; if ( ( pcap = get_pcap( "wlan" ) ) == NULL )
{
return -;
} if ( pcap_compile( pcap, &bpf, "tcp port 80", , ) < )
{
fprintf( stderr, "pcap_compile error\n" );
return -;
} if ( pcap_setfilter( pcap, &bpf ) < )
{
fprintf( stderr, "pcap_setfilter\n" );
return -;
} while ( ( rc = pcap_next_ex( pcap, &header, &pkt_data ) ) >= )
{
if ( rc == )
{
continue;
} eth = ( eth_hdr* )pkt_data; ip = ( ip_hdr* )( eth + );
ip_hdr_len = ( ( ip->ver_ihl & 0x0F ) << ); tcp = ( tcp_hdr* )( pkt_data + sizeof( eth_hdr ) + ip_hdr_len );
tcp_hdr_len = ( ( tcp->len_code & 0x00F0 ) >> );
tcp_data_len = header->len - sizeof( eth_hdr ) - ip_hdr_len - tcp_hdr_len;
tcp_pkt_data = ( unsigned char* )tcp + tcp_hdr_len; if ( tcp_data_len < || \
( strncmp( ( char* )tcp_pkt_data, "GET", ) && \
strncmp( ( char* )tcp_pkt_data, "POST", ) && \
strncmp( ( char* )tcp_pkt_data, "HTTP/1.1", ) ) )
{
continue;
} memcpy( g_buffer, tcp_pkt_data, tcp_data_len );
g_buffer[tcp_data_len] = ; printf( "==============================================\n" );
printf( "%s\n", ( char* )g_buffer );
printf( "**********************************************\n\n" );
} pcap_close( pcap ); return ;
}
编译之
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-\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-\arch-arm\usr\lib\crtend_android.o D:\Android\android-ndk-r10d\platforms\android-\arch-arm\usr\lib\crtbegin_dynamic.o -L. -LD:\Android\android-ndk-r10d\platforms\android-\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 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交互非常像,只是更智能点。
ndk编译libpcap 1.7.4的更多相关文章
- ndk编译libpcap 1.7.4(最终解决方法)
具体方法和测试见上一篇. 后来才知道,LIBPCAP本来就写了几套获取网卡的函数,这样就简单了.和上篇一样,把那5个文件从LINUX下托下来. 上篇忘了说了,还要将LINUX中/usr/include ...
- 使用ndk编译c可执行程序
1.创建工程目录 在ubuntu系统下搭建好ndk编译环境,创建test目录 mkdir test 在test目录下创建jni目录 cd test mkdir jni 2.编写源代码 vim hel ...
- Android APP使用NDK编译后的ffmpeg库出现undefined reference to 'posix_memalign'错误
在android程序中使用NDK编译后的ffmpeg库的时候出现了如下错误: jni/libs/libavutil.a(mem.o): in function av_malloc:libavutil/ ...
- Linux下NDK编译FFMPEG包含neon参数
FFMPEG编译成Android库已经有很多案例了,编译优化neon的也很多,以下是我通过实践成功的案例,这里主要讲编译的配置文件,其他设置可结合Linux下使用NDK编译FFMPEG(libstag ...
- Linux下使用NDK编译FFMPEG(libstagefright)
这个月要负责一个项目,使用FFMPEG渲染视频,主要是Android端的,由于性能要求,要使用硬解码,但网上大多数教程都是没有libstagefright的,所以个人觉得,生成的so库文件也是没有开启 ...
- Android Studio 中关于NDK编译及jni header生成的问题
之前由于工作原因使用grails这个基于groovy的框架做项目,对groovy感觉很好. 基于groovy的gradle构建系统对我而言自然也是好的没得说. Android Studio 正式版出来 ...
- [原]如何用Android NDK编译FFmpeg
我们知道在Ubuntu下直接编译FFmpeg是很简单的,主要是先执行./configure,接着执行make命令来编译,完了紧接着执行make install执行安装.那么如何使用Android的ND ...
- ffmpeg2.2在ubuntu下使用NDK编译——并在android工程下测试使用
作者:wainiwann 出处:http://www.cnblogs.com/wainiwann/ 本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则 ...
- android开发 NDK 编译和使用静态库、动态库 (转)
在eclipse工程目录下建立一个jni的文件夹 在jni文件夹中建立Android.mk和Application.mk文件 Android.mk文件: Android提供的一种makefile文件, ...
随机推荐
- bzoj2558
哈希+拓扑排序 题意比较绕,先开始没看懂就看了发程序,发现好像理解的不太一样,后来找到了一个题目解释... 摘自jcvb:其实就是说颜色相同且三个出口分别对应相同(注意有可能是合并后才相同)两个结点是 ...
- 栗染-Jsp编码常见问题
如图在我们新建一个jsp的时候想给自己的页面加一个中文就会出现如图所示的问题 遇到这种情况一般是选第二个或者 将<%@ page language="java" import ...
- bzoj 2165: 大楼【Floyd+矩阵乘法+倍增+贪心】
1<<i的结果需要是long long的话i是long long是没用的--要写成1ll<<i--我别是个傻子吧 虽然写的是二进制贪心,但是我觉得二分可能更好写吧(但是会慢) ...
- P3256 [JLOI2013]赛车
传送门 如果把速度看成斜率,起始位置看成截距,这就是一个水平可见直线了-- 不过这题里我实现方法借鉴了CQzhangyu大佬的,先按速度排序,然后维护一个单调栈,如果当前的人速度比栈顶大距离又比它远直 ...
- redis 缓存应用
第1章 部署与安装 wget http://download.redis.io/releases/redis-3.2.10.tar.gz tar xf redis-3.2.10.tar.gz cd r ...
- linux学习之路1 Linux系统安装
VMware workstation虚拟器 网上下载VMware workstation,然后安装任一系统的linux系统,不过选的系统一定要跟你下载好的linux镜像保持一致,博主装的是Red Ha ...
- python程序展现图片
突然想写一个python程序能够显示图片的 ,展示文字的已经实现了 现在就搞一搞这个吧 相信也是很简单 首先是放一张图片在e盘下面 等会程序打包的时候将会用到 就决定是你啦 皮卡丘: 然后就写代码吧:
- jQuery学习笔记(2)-选择器的使用
一.选择器是什么 有了jQuery的选择器,我们几乎可以获取页面上任意一个或一组对象 二.Dom对象和jQuery包装集 1.Dom对象 JavaScript中获取Dom对象的方式 <div i ...
- NodeJs学习记录(一)初步学习,杂乱备忘
2016/12/26 星期一 1.在win7下安装了NodeJs 1)进入官网 https://nodejs.org/en/download/,下载对应的安装包,我目前下载的是node-v6.2.0- ...
- Laravel5.1学习笔记22 Eloquent 调整修改
Eloquent: Mutators Introduction Accessors & Mutators Date Mutators Attribute Casting Introductio ...