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文件, ...
随机推荐
- MVC post 方法导出word文档
View code: function ExportWord(){ var html = $("#div_workInfo").html(); $("#hidWord&q ...
- ubuntu 14.04中: 像ubuntu16.04 一样可以在文件夹内打开此路径下的shell
sudo apt-get install nautilus-open-terminal 然后重启 ok!
- UEditor动态添加图片访问路径前缀
在使用UEditor上传图片时发现上传图片后在编辑器中不能显示上传的图片,在这里是需要在jsp/config.json中设置图片访问路径前缀,即项目的根路径,在config.json只能填写字符串的配 ...
- 3-4章 第3章 form表单组件与小程序前后端通信
View它相当于是一个点击触发一个事件,但是它的事件应该是相对来说可能是比较是偏向于页面上的一些展示,或者说是页面上的一些导航的一些跳转.Button它是一个标签, button是一个标签,一般去触发 ...
- 基于CentOS7.5的 Rsync 服务详解
第1章 Rsync概述 1.1 Rsync基本概述 rsync是一款开源的备份工具,可以在不同服务器(主机)之间进行同步备份, 可实现完全备份与增量备份,因此非常适合用于架构集中式备份或异地备份等应用 ...
- 栗染-git命令搭建简单的个人的网页
本来一个很简单的东西被自己搞了很久 可能是对于一个小白来说第一次认识到github的魅力吧,以前只是听别人说过用github搭建网站,听起来很厉害的样子,一直也没有尝试过,突然兴起今天去网上找一些教程 ...
- P1266 速度限制(分层图spfa)
P1266 速度限制 题目描述 在这个繁忙的社会中,我们往往不再去选择最短的道路,而是选择最快的路线.开车时每条道路的限速成为最关键的问题.不幸的是,有一些限速的标志丢失了,因此你无法得知应该开多快. ...
- mysql的大数据量的查询
mysql的大数据量查询分页应该用where 条件进行分页,limit 100000,100,mysql先查询100100数据量,查询完以后,将 这些100000数据量屏蔽去掉,用100的量,但是如果 ...
- 例题 5-1 STL
Raju and Meena love to play with Marbles. They have got a lot of marbles with numbers written on the ...
- Juicer.js模板引擎问题
由于jsp中的EL表达式语法和jquery.tmpl十分类似,,所以单纯的使用${name},数据是渲染不上tmpl的. SO.. 要加上转义: ${'${'}amount} 或者 \${amount ...