移植DHCP服务器到uclinux
早年写的笔记,压箱底了,翻出来晒晒
目 录
实验环境
u IXDP425 266Mhz 64M ram16M flash
u FC4: kernel 2.6.11-1.1369_FC4smp(FC6 也行),安装在虚拟机上
u arm-linux-tools-20051123.tar.gz: gcc 3.4.4编译器
u snapgear-3.5.0.tar.gz: snapgear 发布的uClinux 包
u snapgear-modules-20071004.sh: snapgear 发布的uClinux 包
u Kernel files in /home/linuxuser/snapgear
u 编译器在/home/linuxuser/usr/
u dhcp-3.0.4.tar.gz,dhcp-3.1.2.tar.gz (isc版本)
u dhcp-4.1.0.tar.gz(isc版本)
u openssl-0.9.8e.tar.gz
u openssl-0_9_8e.patch.gz
配置uclinux内核
因为编译的是应用程序,所以和kernel的关系不大,下面以uclinux2.6作为实验环境。
ISCdhcp需要kernel配置一些网络的支持,CONFIG_PACKET, CONFIG_NETFILTER等都要选上。
1. make menuconfig之后,在主菜单中选择选中Customize Kernel Settings (NEW)
2. 退出后进入Linux Kernel Configuration菜单,选中
Networking ---> Networking options ---> Packet socket
Networking ---> Networking options --->Network packet filtering (replaces ipchains)
编译完之后得到zImage和ramdisk。
编译dhcp-3.0.4
在uclinux中,一共有3个dhcpd可以选择。分别为
Customize Vendor/User Settings-->Network Applications --->dhcp
Customize Vendor/User Settings-->Network Applications --->dhcp(ISC)
Customize Vendor/User Settings-->Network Applications --->BusyBox --->udhcp server
第一个dhcpd太简单,而snapgearuclinux 3.5中包含的dhcpd(ISC)功能最为强大,但是为2.0版本,无法正常运行。busybox中的也可以。决定采用新版本的dhcpd(ISC)。下面以3.0.4版本为例讲解。
修改makefile并编译
dhcp-3.0.4自动配置文件对交叉编译支持的不完整,所以需要手动修改。假定解压dhcp-3.0.4到/home/linuxuser/DHCPD/dhcp-3.0.4。
打开/home/linuxuser/DHCPD/dhcp-3.0.4/Makefile.conf,找到以下内容:
# Minor version number (if applicable)
##--minver--
MINORVERSION=MinorVersion
##--minver--
## Porting::
#
加入
CC=/home/linuxuser/snapgear/tools/ucfront-gccarm-linux-gcc -mbig-endian
LD=arm-linux-ld
改完后看起来如下:
# Minor version number (if applicable)
##--minver--
MINORVERSION=MinorVersion
##--minver--
CC=/home/linuxuser/snapgear/tools/ucfront-gccarm-linux-gcc -mbig-endian
LD=arm-linux-ld
## Porting::
修改完之后输入命令
#cd /home/linuxuser/DHCPD/dhcp-3.0.4
#make clean
#./ configure
#make
命令会产生/home/linuxuser/DHCPD/dhcp-3.0.4/work.linux-2.2目录。并且会根据刚才该的部分产生makefile文件。然后编译全部的文件
准备配置文件
Dhcpd需要两个配置文件,dhcpd.conf和dhcpd.leases。在此,我们准备在172网段上做dhcpd的实验。在/home/linuxuser/DHCPD/dhcp-3.0.4/server下有几个dhcpd.conf样本。以此做一个简单的dhcpd.conf。新建dhcpd.conf文件,内容如下:
/**************************************************************/
# dhcpd.conf
#
# Sample configuration file for ISC dhcpd
#
# option definitions common to all supportednetworks...
option domain-name "ryan.server";
#option domain-name-servers ns1.example.org,ns2.example.org;
default-lease-time 600;
max-lease-time 7200;
# If this DHCP server is the official DHCP server forthe local
# network, the authoritative directive should beuncommented.
#authoritative;
# Use this to send dhcp log messages to a differentlog file (you also
# have to hack syslog.conf to complete theredirection).
#log-facility local7;
ddns-update-style none;
subnet 172.17.0.0 netmask 255.255.255.0 {
range 172.17.0.10172.17.0.100;
optiondomain-name-servers 202.106.46.151;
optionbroadcast-address 172.17.0.255;
optionrouters 172.17.0.1;
default-lease-time 600;
max-lease-time 7200;
}
# No service will be given on this subnet, butdeclaring it helps the
# DHCP server to understand the network topology.
/**************************************************************/
Dhcp(ISC)是根据IP地址范围来判断支持哪个网卡的,所以上面的配置文件里将支持172.17.0.0/255.255.255.0的地址分配。另外新建一个空的文件,命名为dhcpd.leases。这个文件是有dhcpd来写入分配信息的。
集成到ramdisk
在/home/linuxuser/DHCPD/dhcp-3.0.4/下新建prepare_ramdisk目录,将刚才做好的dhcpd.conf和dhcpd.leases复制到prepare_ramdisk。
在/home/linuxuser/DHCPD/dhcp-3.0.4/prepare_ramdisk下新建一个install_dhcpd.txt,内容如下:
/**************************************************************/
umount tmp
rm -rframdisk.gz
rm -rf ramdisk
#make clean
#make
rm -rf tmp
mkdir tmp
cp -f/tftpboot/ramdisk.gz ramdisk.gz
gunzip ramdisk
mount -o loopramdisk tmp
rm -rf stripped
mkdir stripped
cp -rf../work.linux-2.2/server/dhcpd ./stripped/dhcpd
/home/linuxuser/skyeye/usr/local/arm-linux/bin/strip./stripped/*
/home/linuxuser/skyeye/usr/local/arm-linux/bin/strip-R .comment -R .note ./stripped/*
cp -rf./stripped/dhcpd ./tmp/bin/dhcpd
cp -rf./dhcpd.conf ./tmp/etc/
cp -rf./dhcpd.leases ./tmp/etc/
umount tmp
gzip ramdisk
cp -rframdisk.gz /tftpboot/ramdisktest.gz
/**************************************************************/
需要注意的是,snapgear已经编译好的zImage和ramdisk会复制一份到/tftpboot,所以install_dhcpd.txt可以从/tftpboot得到刚编译好的ramdisk。
执行命令:
#chmod +xinstall_dhcpd.txt
#./install_dhcpd.txt
这样ramdisktest.gz就会包含dhcpd需要的所有文件。
在uclinux上运行dhcpd
将刚刚做好的zImage和ramdisktest.gz下载到板子上运行。按照前面章节的说明,需要先启动ixp0网卡。等板子启动后,输入命令:
#ifconfig ixp0172.17.0.1
#/bin/dhcpd -d-cf /etc/dhcpd.conf -lf /etc/dhcpd.leases
正常启动串口应该出现如下信息:
# /bin/dhcpd -d-cf /etc/dhcpd.conf -lf /etc/dhcpd.leases&
[1] 41
Internet SystemsConsortium DHCP Server 4.1.0
Copyright2004-2008 Internet Systems Consortium.
All rightsreserved.
For info, pleasevisit http://www.isc.org/sw/dhcp/
# Wrote 2 leasesto leases file.
Listening onLPF/ixp0/00:02:b3:01:01:01/172.17.0.0/24
Sending on LPF/ixp0/00:02:b3:01:01:01/172.17.0.0/24
Sending on Socket/fallback/fallback-net
#
然后启动一个自动获得IP地址的机器,或者设置网卡为自动获得IP地址,先disable网卡再enable,效果也一样。注意同意网段不要有两台dhcp服务器以免干扰实验。
串口应该出现如下信息:
DHCPDISCOVERfrom 00:0c:29:00:06:a3(bupt-41b1fc21b3) via ixp0
DHCPOFFER on172.17.0.10 to 00:0c:29:00:06:a3(bupt-41b1fc21b3) via ixp0
DHCPREQUEST for172.17.0.10 (172.17.0.1) from 00:0c:29:00:06:a3(bupt-41b1fc21b3) via ixp0
DHCPACK on172.17.0.10 to 00:0c:29:00:06:a3(bupt-41b1fc21b3) via ixp0
至此表示一台机器已经成功的申请到了172.17.0.10的地址。
在后台运行程序
在命令后面加上&即可让程序在后台运行。
编译dhcp-4.1.0
dhcp-4.1.0的配置方法和文件结构和3.x.x的有很大的不同。这个版本支持交叉编译,但是配置也不顺畅。这里采用手工修改的方法。
修改配置文件
解压dhcp-4.1.0到/home/linuxuser/DHCPD/dhcp-4.1.0。在下面11个目录下,一共有11个Makefile.in
./
./client
./common
./dhcpctl
./dst
./includes
./minires
./omapip
./relay
./server
./tests
检查每一个Makefile.in。
将其中的CC = @CC@替换成:
CC=/home/linuxuser/snapgear/tools/ucfront-gccarm-linux-gcc -mbig-endian
LD=arm-linux-ld
将RANLIB =@RANLIB@
替换成
RANLIB=arm-linux-ranlib
有的makefile.in没有RANLIB = @RANLIB@就不用替换RANLIB=arm-linux-ranlib了
打开configure文件,在line3342找到
STD_CWARNINGS="$STD_CWARNINGS-Wall -Werror -fno-strict-aliasing"
替换成
STD_CWARNINGS="$STD_CWARNINGS-Wall -fno-strict-aliasing"
然后执行命令:
./configure –disable-dhcpv6
打开/dhcp-4.1.0/includes/config.h,将其中的
#defineDHCP_BYTE_ORDER LITTLE_ENDIAN
改为
#defineDHCP_BYTE_ORDER BIG_ENDIAN
准备libcrypto库文件
uclibc本身并没有libcrypto,但是可以依靠openssel提供。
将openssl-0.9.8e.tar.gz解压到/home/linuxuser/openssl/openssl-0.9.8e。并将openssl-0_9_8e.patch.gz解压到到/home/linuxuser/openssl/openssl-0.9.8e/。执行如下命令:
#patch -p1 < penssl-0_9_8e.patch
#cd ..
#cp –rf openssl-0.9.8e/home/linuxuser/snapgear/lib/libssl
至此openssl的补丁已经打上,可以靠snapgear来编译openssl。
执行命令
#cd /home/linuxuser/snapgear
#make menuconfig
在Customize Vendor/User Settings-->Library Configuration ---> Build libSSL前面打上*。保存编译内核。
编译完内核之后,在/home/linuxuser/snapgear/lib/libssl/build找到libcrypto.a和libcrypto.so.0.9.8,一起复制到/home/linuxuser/snapgear/uClibc/lib,并且在/home/linuxuser/snapgear/uClibc/lib下建立libcrypto.so.0.9.8的link,链接名为libcrypto.so。
编译,执行
#cd /home/linuxuser/DHCPD/dhcp-4.1.0
#make
在/home/linuxuser/DHCPD/dhcp-4.1.0/server下找到dhcpd。按照dhcp-3.0.4的方法集成到ramdisk。下载到板子上执行情况如下:
# /bin/dhcpd -d-cf /etc/dhcpd.conf -lf /etc/dhcpd.leases&
[1] 36
Internet SystemsConsortium DHCP Server 4.1.0
Copyright2004-2008 Internet Systems Consortium.
All rightsreserved.
For info, pleasevisit http://www.isc.org/sw/dhcp/
# Wrote 0 leasesto leases file.
Listening onLPF/ixp0/00:02:b3:01:01:01/172.17.0.0/24
Sending on LPF/ixp0/00:02:b3:01:01:01/172.17.0.0/24
Sending on Socket/fallback/fallback-net
DHCPDISCOVERfrom 00:0c:29:00:06:a3 via ixp0
DHCPOFFER on 172.17.0.10to 00:0c:29:00:06:a3(bupt-41b1fc21b3) via ixp0
DHCPREQUEST for172.17.0.10 (172.17.0.1) from 00:0c:29:00:06:a3(bupt-41b1fc21b3) via ixp0
DHCPACK on172.17.0.10 to 00:0c:29:00:06:a3(bupt-41b1fc21b3) via ixp0
移植DHCP(ISC)的摸索
使用snapgear3.5自带的DHCPD(ISC)
最简单的方法应该就是使用已经集成好的DHCPD(ISC)。选中Customize Vendor/User Settings-->Network Applications --->dhcp(ISC)之后编译。按照上文的方法准备配置文件,集成ramdisk之后下载到板子上运行,打开了-d选项用来debug。dhcpd.conf文件屏蔽几个选项就行了。
出现如下错误:
# /bin/dhcpd -d-cf /etc/dhcpd.conf -lf /etc/dhcpd.leases
InternetSoftware Consortium DHCP Server 2.0pl5
Copyright 1995,1996, 1997, 1998, 1999 The Internet Software Consortium.
All rightsreserved.
Pleasecontribute if you find this software useful.
For info, pleasevisit http://www.isc.org/dhcp-contrib.html
Listening onLPF/ath1/06:16:16:1c:68:5b/172.17.0.0
Sending on LPF/ath1/06:16:16:1c:68:5b/172.17.0.0
Sending on Socket/fallback/fallback-net
ip length 2048disagrees with bytes received 334.
ip length 2048disagrees with bytes received 334.
ip length 2048disagrees with bytes received 334.
ip length 2048disagrees with bytes received 334.
ip length 2048disagrees with bytes received 334.
5 bad udpchecksums in 5 packets
ip length 2048disagrees with bytes received 334.
ip length 2048disagrees with bytes received 334.
开始怀疑因为使用的是无线AP作为dhcp server端口,而无线的MAC包格式和以太网的不同,所以修改配置,屏蔽ath1,将ixp0配置成172.17.0.1。结果还是一样,重启也没有效果。
于是进入/home/linuxuser/snapgear/user/dhcp-isc搜索“disagrees with bytes received”字符串,发现在dhcp-isc/common/packet.c的decode_udp_ip_header()函数里面。源码是这样的:
/* Check theIP packet length. */
if (ntohs (ip-> ip_len) != buflen)
debug ("ip length %d disagrees withbytes received %d.",
ntohs (ip -> ip_len), buflen);
而在客户端用wireshark抓到的DHCP discover包是正确的。于是在decode_udp_ip_header()中下面两句代码
ip = (struct ip*)(buf + bufix);
udp = (structudphdr *)(buf + bufix + ip_len);
后面加上打印语句如下:
ip = (struct ip *)(buf + bufix);
udp = (struct udphdr *)(buf + bufix +ip_len);
{
intbufi =0;
printf("%d\n",buflen);
for(bufi =0; bufi < 50; bufi++)
{
printf("%2x,",buf[bufi]);
}
printf("\nbufix: %d, ip_len: %d\n",bufix,ip_len);
}
结果如下
328
ff,ff,ff,ff,ff,ff,0, c,29,7e,35,54, 8, 0,45, 0, 1,48, 0,51, 0, 0,80,11,39,55, 0, 0, 0,0,ff,ff,ff,ff, 0,44, 0,43, 1,34,93,41, 1, 1, 6, 0,55,cd,13,97,
bufix: 14,ip_len: 20
ip length 2048disagrees with bytes received 328.
包的接收完全没有错误。
继续打印更多的信息。将打印代码修改如下:
{
intbufi =0;
printf("%d\n",buflen);
for(bufi =0; bufi < 50; bufi++)
{
printf("%2x,",buf[bufi]);
}
printf("\nbufix: %d, ip_len: %d\n",bufix,ip_len);
char* my_ipchar = (char *)ip;
for(bufi =0; bufi < 50; bufi++)
{
printf("%2x,",ip[bufi + bufix]);
}
printf("\nip_hl: %d, ipv :%d, ip_tos :%d, ip_len: %d,ip_id:%d\n", ip->ip_hl, ip->ipv, ip->ip_tos, (ntohs)ip->ip_len,(ntohs)ip->ip_id);
}
另外检查struct ip的定义,在/home/linuxuser/snapgear/user/dhcp-isc/includes/netinet/ip.h里面。
struct ip {
#if __BYTE_ORDER== __LITTLE_ENDIAN
u_int8_t ip_hl:4, /* header length */
ip_v:4; /* version */
#endif
#if __BYTE_ORDER== __BIG_ENDIAN
u_int8_t ip_v:4, /* version */
ip_hl:4; /* header length */
#endif
u_int8_t ip_tos; /* type of service */
int16_t ip_len; /*total length */
u_int16_t ip_id; /* identification */
int16_t ip_off; /*fragment offset field */
#define IP_DF 0x4000 /*dont fragment flag */
#define IP_MF 0x2000 /*more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
u_int8_t ip_ttl; /* time to live */
u_int8_t ip_p; /* protocol */
u_int16_t ip_sum; /* checksum */
struct in_addr ip_src, ip_dst; /* source and destaddress */
};
__BYTE_ORDER根本没有被定义,可能问题出在这个地方。搜索BYTE_ORDER,在dhcpd/includes/hpux.h.里面发现如下定义
#define BIG_ENDIAN 1
#define LITTLE_ENDIEN 2
#define BYTE_ORDER BIG_ENDIAN
这也反应snapgear的一个问题。按照默认编译的程序竟然不能正确运行,可见也并没有完整的测试过,所以不能迷信snapgear.
而在\dhcp-4.1.0\includes\netinet\ip.h里直接就没有BIG_ENDIAN之类的定义。对比snapgear的这个相同的文件,发现日期和版本号一样。但是对endian的处理不一样,说明原本就是同样的文件(因为日期和前面的注释说明)一模一样,只不过uclinux给修改了。
那么将其修改正确。
在ip.h里加入如下定义
#define__LITTLE_ENDIAN 1
#define__BIG_ENDIAN 2
#define__BYTE_ORDER __BIG_ENDIAN
编译之后再运行。
打印信息如下:
328
ff,ff,ff,ff,ff,ff,0, c,29, 0, 6,a3, 8, 0,45, 0, 1,48, 1,a8, 0, 0,80,11,37,fe, 0, 0, 0,0,ff,ff,ff,ff, 0,44, 0,43, 1,34,ce, d, 1, 1, 6, 0,bc,ea,d0, b,
decode_udp_ip_header,ln30:bufix:14, ip_len: 20
45, 0, 1,48,1,a8, 0, 0,80,11,37,fe, 0, 0, 0, 0,ff,ff,ff,ff, 0,44, 0,43, 1,34,ce, d, 1, 1,6, 0,bc,ea,d0, b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
decode_udp_ip_header,ip_hl:5, ipv : 4, ip_tos :0, ip_len: 2048,ip_id: 424
ip length 2048disagrees with bytes received 328.
看起来ip_len的位置完全跑飞了.猜想是word align的问题。如果是这个问题的话,那么肯定ip structure的size就不对。加入ip struct的size的打印,没有问题,是20.
出现错误很奇怪。怀疑根本不是用的ip.h的结构,尝试注释include“ip.h”,发生编译错误,说明还是用的这个定义。那么只好加上pragma试试。Clean之后再make,也没有任何效果。
最后将打印语句修改如下。查看内存的地址和读写的问题。
{
intbufi =0;
printf("%d\n",buflen);
for(bufi =0; bufi < 50; bufi++)
{
printf("%2x,",buf[bufi]);
}
printf("\n%s,ln30:bufix: %d, ip_len: %d\n, ip struct size:%d\n",__FUNCTION__, bufix,ip_len, sizeof(struct ip));
char* my_ipchar = (char *)ip;
for(bufi =0; bufi < 50; bufi++)
{
printf("%2x,",my_ipchar[bufi]);
}
printf("\n%s,ln35 ip_hl: %d, ipv : %d, ip_tos :%d, ip_len:%d,ip_id: %d\n", __FUNCTION__, ip->ip_hl, ip->ip_v, ip->ip_tos,(ntohs)(ip->ip_len), (ntohs)(ip->ip_id));
printf("\nln40address : %s,ip: %u,ip_tos :%u, ip_len: %u,ip_id: %u, ttl: %u, ip_p: %u\n", __FUNCTION__, ip,&(ip->ip_tos), &(ip->ip_len), &(ip->ip_id),&(ip->ip_ttl), &(ip->ip_p));
unsigned short *test1 =&(ip->ip_len);
unsigned short *test2 = &(ip->ip_id);
printf("\n%sln50,ip_hl: %d, ipv : %d, ip_tos :%d, ip_len: %d,ip_id:%d\n", __FUNCTION__, ip->ip_hl, ip->ip_v, *((char*)&(ip->ip_tos)), (ntohs)(*test1), (ntohs)(*test2));
//printf("\nip_hl: %d, ipv :%d, ip_tos :%d, ip_len: %d,ip_id:%d\n", ip->ip_hl, ip->ip_v, ip->ip_tos, (ntohs)ip->ip_len,(ntohs)ip->ip_id);
}
结果发现test1,test2是正确的值,但是ip->ip_len还是错误的,太奇怪。网上搜索hcpd(ISC),最新的已经到了4.1,而自带的这个版本为2.0。至此放弃该版本。
编译dhcp-3.0.4
因为自动的配置对交叉编译支持的不完整。在执行./configure之后,对生成的makefile进行了修改,手动修改了全部makefile的CC和LD,也能编译。后来发现makefile.conf可以用来配置这些makefile。于是修改了makefile.conf,重新执行./configure,就得到配置好的makefile。
编译的时候出现问题:
In file included from/home/linuxuser/snapgear/uClibc/include/sys/types.h:26,
from /home/linuxuser/DHCPD/dhcp-3.0.4_arm/includes/dhcpd.h:36,
from raw.c:53:
/home/linuxuser/snapgear/uClibc/include/features.h:267:32:bits/uClibc_config.h: No such file or directory
In file included from /home/linuxuser/DHCPD/dhcp-3.0.4_arm/includes/dhcpd.h:36,
from raw.c:53:
/home/linuxuser/snapgear/uClibc/include/sys/types.h:30:24:bits/types.h: No such file or directory
In file included from /home/linuxuser/DHCPD/dhcp-3.0.4_arm/includes/dhcpd.h:36,
from raw.c:53:
检查一下uclibc目录,在uclibc里果然没有找到bit等文件夹。想起来刚才对snapgear执行了一次make clean,所以把编译时需要的目录都清除了。这个只需要重新编译一下snapgear就好了。
在一台default settings的机器上按照前面介绍的方法独立编译dhcp-3.0.4后,输入#/bin/dhcpd -d -cf/etc/dhcpd.conf -lf /etc/dhcpd.leases。结果提示错误“Make sure to set CONFIG_PACKET=y and CONFIG_FILTER=y in your kernelconfiguration”。加入前面讲的配置之后就没有问题了。
编译dhcp-3.1.2
3.1.2的配置方法和文件结构与3.0.4非常的类似,修改的方法一样。dhcpd.conf都可以用一样。
编译dhcp-4.1.0
dhcp-4.1.0的配置方法和文件结构和3.x.x的有很大的不同。这个版本支持交叉编译,但是配置也不顺畅。执行
./configure --host=arm-linux--build=i686-pc-linux-gnu --target=arm-linux
会提示/dev/random错误,干脆自己修改好了。
执行./configure,生成了makefile。但是交叉编译的设置都不对,生成的文件都是为i386准备的。当然可以选择手动修改,但是希望能找到类似dhcp-3.0.4中makefile.conf文件。只发现每个文件夹下面有makefile.in文件和makefile.am文件。makefile.am文件很笼统,信息量少,而且不包含交叉编译的配置。
makefile.am文件内容如下:
#
# automake addsdependencies that we don't like, so we explicitly remove them
#
Makefile:
#
# We have a lotof files that we want shipped with the distribution.
#
EXTRA_DIST =RELNOTES LICENSE \
contrib/3.0b1-lease-convert contrib/dhclient-tz-exithook.sh \
contrib/dhcp.spec contrib/sethostname.sh contrib/solaris.init \
contrib/ms2isc/Registry.pm contrib/ms2isc/ms2isc.pl \
contrib/ms2isc/readme.txt \
doc/IANA-arp-parameters doc/Makefile doc/References.html \
doc/References.txt doc/References.xml doc/api+protocol \
doc/ja_JP.eucJP/dhclient-script.8 doc/ja_JP.eucJP/dhclient.8 \
doc/ja_JP.eucJP/dhclient.conf.5 doc/ja_JP.eucJP/dhclient.leases.5 \
doc/ja_JP.eucJP/dhcp-eval.5 doc/ja_JP.eucJP/dhcp-options.5
SUBDIRS =includes tests common minires dst omapip client dhcpctl relay server
nobase_include_HEADERS= dhcpctl/dhcpctl.h
再查看Makefile.in,里面有很多下面类似的语句:
AWK = @AWK@
CC = @CC@
CFLAGS =@CFLAGS@
之类的语句。再看config.status里有如下的语句
s,@CC@,|#_!!_#|gcc,g
s,@CFLAGS@,|#_!!_#|-g-O2 -Wall –Werror -fno-strict-aliasing,g
这个应该就是将makefile.in里相应的关键字替换的含义。尝试修改config.status。
s,@CC@,|#_!!_#|gcc,g为
s,@CC@,|#_!!_#|/home/linuxuser/skyeye/uClinux-dist/tools/ucfront-gccarm-linux-gcc,g
重新执行./configure没有效果。仔细查看执行./configure时候的打印信息,特别注意makefile生成部分的语句,打印信息如下:
checking forstruct msghdr.msg_control... yes
configure:creating ./config.status
config.status:creating Makefile
config.status:WARNING: Makefile.in seems to ignore the--datarootdir setting
config.status:creating client/Makefile
说明config.status是configure生成的。手动修改config.status之后会被重新覆盖的。所以直接修改Makefile.in,将其中的CC = @CC@替换成:
CC=/home/linuxuser/snapgear/tools/ucfront-gccarm-linux-gcc -mbig-endian
LD=arm-linux-ld
将RANLIB =@RANLIB@
替换成
RANLIB=arm-linux-ranlib
这样生成的makefile就会显示
CC=/home/linuxuser/snapgear/tools/ucfront-gccarm-linux-gcc -mbig-endian
LD=arm-linux-ld
uclibc库的问题
修改完之后编译。出现如下错误:
then mv -f".deps/test.Tpo" ".deps/test.Po"; else rm -f".deps/test.Tpo"; exit 1; fi
ucfront-gccarm-linux-gcc -mbig-endian -g -O2 -Wall -Werror -fno-strict-aliasing -o svtest test.o libomapi.a ../dst/libdst.a -lcrypto
/home/linuxuser/skyeye/usr/local/bin/../lib/gcc/arm-linux/3.4.4/../../../../arm-linux/bin/ld:cannot find -lcrypto
collect2: ldreturned 1 exit status
make[1]: ***[svtest] Error 1
make[1]: Leavingdirectory `/home/linuxuser/DHCPD/dhcp-4.1.0/omapip'
make: ***[all-recursive] Error 1
提示没有找到crypto库,这个应该指的是uclibc的库。检查/home/linuxuser/snapgear/uClibc/lib,没有libcrypto。而在PC的/lib下找到了libcrypto.so,所以在PC下能够编译过i386的程序。
而uclibc库是在编译内核的时候由/home/linuxuser/snapgear/uClibc里的代码生成的,在/home/linuxuser/snapgear/uClibc/lib下找到libcrypt.so,/home/linuxuser/snapgear/uClibc也有libcrypt文件夹。但是没有任何libcrypto的文件。怀疑是uclibc的版本太低,到官方网站http://www.uclibc.org/去找到最新的uclibc,也没有libcrypto。
经过网上搜索,发现openssl里面带有libcrypto。于是将openssl集成到snapgear,编译之后,在/home/linuxuser/snapgear/lib/libssl/build找到libcrypto.a和libcrypto.so.0.9.8,一起复制到/home/linuxuser/snapgear/uClibc/lib,并且在/home/linuxuser/snapgear/uClibc/lib下建立libcrypto.so.0.9.8的link,链接名为libcrypto.so。
集成是用另外一台机器,在snapgear, uclinux2.4编译了openssl0.98e。Dhcpd4.10编译通过。说明这些都是应用程序,和kernel无关。
准备完毕之后执行make,得到dhcpd,集成到ramdisk里,下载到板子上运行,打印如下错误:
# /bin/dhcpd -d-cf /etc/dhcpd.conf -lf /etc/dhcpd.leases&
[1] 36
# InternetSystems Consortium DHCP Server 4.1.0
Copyright2004-2008 Internet Systems Consortium.
All rightsreserved.
For info, pleasevisit http://www.isc.org/sw/dhcp/
Wrote 0 leasesto leases file.
Error opening'/proc/net/if_inet6' to list IPv6 interfaces; No such file or directory
Can't get listof interfaces.
If you did notget this software from ftp.isc.org, please
get the latestfrom ftp.isc.org and install that before
requesting help.
If you did getthis software from ftp.isc.org and have not
yet read theREADME, please read it before requesting help.
If you intend torequest help from the dhcp-server@isc.org
mailing list,please read the section on the README about
submitting bugreports and requests for help.
Please do notunder any circumstances send requests for
help directly tothe authors of this software - please
send them to theappropriate mailing list as described in
the README file.
exiting.
[1]+ Exit 1 /bin/dhcpd -d -cf/etc/dhcpd.conf -lf /etc/dhcpd.leases
能够运行,但是IPV6需要配置,看看能不能屏蔽。查看搜索整个dhcp-4.1.0文件夹,发现了DHCPv6的宏定义是关键,是在/home/linuxuser/DHCPD/dhcp-4.1.0/includes/config.h里定义的。这个文件是configure根据config.h,in修改的,如果执行configure, 对config.h的修改就会被覆盖。不过在此已经不需要configure了。顺便发现endian的定义一起修改。原文如下:
/* Define toBIG_ENDIAN for MSB (Motorola or SPARC CPUs) or LITTLE_ENDIAN for
LSB (Intel CPUs). */
#defineDHCP_BYTE_ORDER LITTLE_ENDIAN
/* Define to 1to include DHCPv6 support. */
#define DHCPv6 1
将其修改为
/* Define toBIG_ENDIAN for MSB (Motorola or SPARC CPUs) or LITTLE_ENDIAN for
LSB (Intel CPUs). */
#defineDHCP_BYTE_ORDER BIG_ENDIAN
/* Define to 1to include DHCPv6 support. */
//#define DHCPv61
重新编译,编译的时候出现错误:
Making all inrelay
make[1]:Entering directory `/home/linuxuser/DHCPD/dhcp-4.1.0/relay'
if ucfront-gccarm-linux-gcc -mbig-endian -DHAVE_CONFIG_H -I. -I.-I../includes -DLOCALSTATEDIR='"/var"' -g -O2 -Wall -Werror-fno-strict-aliasing -MT dhcrelay.o -MD -MP -MF ".deps/dhcrelay.Tpo"-c -o dhcrelay.o dhcrelay.c; \
then mv -f".deps/dhcrelay.Tpo" ".deps/dhcrelay.Po"; else rm -f".deps/dhcrelay.Tpo"; exit 1; fi
dhcrelay.c: Infunction `main':
dhcrelay.c:164:warning: 'service_local' might be used uninitialized in this function
dhcrelay.c:164:warning: 'service_remote' might be used uninitialized in this function
dhcrelay.c:165:warning: 'port_local' might be used uninitialized in this function
dhcrelay.c:165:warning: 'port_remote' might be used uninitialized in this function
make[1]: ***[dhcrelay.o] Error 1
make[1]: Leavingdirectory `/home/linuxuser/DHCPD/dhcp-4.1.0/relay'
make: ***[all-recursive] Error 1
检查所有的编译信息,发现只有最后的一个地方出项了error,没有任何提示,前面只有warning,最典型的应该就是-Werror的问题,检查编译选项,果然有-Werror,但是根据刚才看到的makefile.in里面并没有具体的CFLAGS的定义,而是configure文件生成的,所以搜索configure。打开configure文件,在line3342找到
if test"$GCC" = "yes"; then
if test "$CFLAGS" !="$SAVE_CFLAGS"; then
STD_CWARNINGS="$STD_CWARNINGS -Wall-Werror -fno-strict-aliasing"
fi
fi
这个是最可疑的一处,别的地方也有一点- Werror的定义。先将
STD_CWARNINGS="$STD_CWARNINGS-Wall -Werror -fno-strict-aliasing"
替换成
STD_CWARNINGS="$STD_CWARNINGS-Wall -fno-strict-aliasing"
编译完成。下载到板子上实验成功。
最后检查了一下configure的帮助信息。其实可以输入./configure –disable-dhcpv6来屏蔽IPv6的支持。