—————————————————
主机操作系统:Centos 6.5
交叉编译器环境:arm-linux-gcc-4.5.4
开发板平台: FL2440
Linux内核版本: linux-3.0
开发模块:无线网卡 RT3070.
作者:hulu<[email protected]>
—————————————————
笔者友情提醒:本文章是在fl2440开发板已经成功移植linux-3.0内核,和可读写的文件系统之上开发的,本次开发使用的是ubifs文件系统格式,且fl2440的DM9000网卡驱动和usb驱动已经成功移植,若还没成功移植DM9000网卡驱动和usb驱动的朋友请参考本人博客驱动开发部分。
此篇文章介绍如何使rt3070工作在AP无线路由器模式,并能连接外网
在--Networking support
<*>RF switch subystem support ----> //这个一定要选上不然会出错
如果没有build in RF选项,在使用hostapd命令时会出错
~>:hostapd hostapd.conf
Configuration file:hostapd.conf
rfkill:Cannot open RFKILL control device
二、配置无线无线路由器的软件移植
2.1.移植Openssl-0.9.8e
==================================================================================================================================================
Hostapd依赖于openssl与libnl这两个库。所以首先要移植openssl与libnl,openssl我们已经移植过了,但我担心版本兼容性的问题,本着学习的心态便又移植了网上普遍使用的openssl-0.9.8e
==================================================================================================================================================
2.1.1下载Openssl-0.9.8e
Openssl-0.9.8e
http://download.csdn.net/detail/u010944778/8940135
[hulu@centos6 openssl-0.9.8e]$ mkdir install
[hulu@centos6 openssl-0.9.8e]$ sudo make && make install
2.2移植 libnl-1.1.4
下载地址http://www.infradead.org/~tgr/libnl/
解压开始安装
[hulu@centos6 libnl-1.1.4]$ mkdir install
./configure–prefix=/home/hulu/fl2440/wifi/AP/libnl-1.1.4/install(指定安装路径) –host=arm-linux
[hulu@centos6 libnl-1.1.4]$make CC=/opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-gcc
[hulu@centos6 libnl-1.1.4]$sudo make install
在你的安装目录里边找到libnl.so.1下载到你的开发板上
2.3移植Hostapd-1.0.tar.gz
下载地址http://download.chinaunix.net/download.php?id=40061&ResourceID=4450
解压修改Makefile 和.config
[hulu@centos6 hostapd-1.0]$ cp defconfig .config
[hulu@centos6 hostapd-1.0]$ vi .config
23:CONFIG_DRICER-NL80211=Y[hulu@centos6 hostapd-1.0]$ vi Makefile
12 CFLAGS +=-I/home/hulu/fl2440/wifi/AP/libnl-1.1.4/install/include/
13 CFLAGS +=-I/home/hulu/fl2440/wifi/AP/openssl-0.9.8e/install/include/
14 LIBS +=-L/home/hulu/fl2440/wifi/AP/libnl-1.1.4/install/lib/
15 LDFLAGS +=-L/home/hulu/fl2440/wifi/AP/libnl-1.1.4/install/lib/
16 LIBS +=-L/home/hulu/fl2440/wifi/AP/openssl-0.9.8e/install/lib/
17 LDFLAGS +=-L/home/hulu/fl2440/wifi/AP/openssl-0.9.8e/install/lib/
[hulu@centos6 hostapd-1.0]$ make CC=/opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-gcc
[hulu@centos6 hostapd-1.0]$sudo make install
在编译过程中出现了如下错误:
从出现的错误中可知是缺少openssl这个库,也就是我之前编译的openssl-0.9.8e有问题,我又从新编译了一下openssl-0.9.8e,成功解决此问题
将生成可执行命令hostapd和配置文件hostapd.conf
hostapd主要就在于配置文件,以下是我的基本配置:
nterface=wlan0 //网络接口设备名称
driver=nl80211 //默认使用nl80211无线驱动
ssid=My_wifi //热点名称
channel=3 //设定无线频道
hw_mode=g //使用80211g协议标准
ignore_broadcast_ssid=0
auth_algs=1 //指定OSA认证算法
wpa=3 //指定WPA/WPA2类型
wpa_passphrase=11111111 //指定认证密钥
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP //启用了WPA或WPA2则需要指定wpa_pairwise或rsn_pairwise
rsn_pairwise=CCMP
上面各项解释如下:
(1) ssid:无线路由器发射的wifi名称;
(2) hw_mode:指定802.11协议,包括 a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g;
===================================================================
无线局域网标准 IEEE 802.11协议
*IEEE 802.11, 1997年,原始标准(2Mbit/s,工作在2.4GHz)。
*IEEE 802.11a,1999年,物理层补充(54Mbit/s,工作在5GHz)。
*IEEE 802.11b,1999年,物理层补充(11Mbit/s工作在2.4GHz)。
*IEEE 802.11g,2003年,物理层补充(54Mbit/s,工作在2.4GHz)。
使用最多的应该是802.11n标准,工作在2.4GHz频段,可达600Mbps(理论值)
===================================================================
(3)channel:设定无线频道;
(4)interface:接入点设备名称,注意不要包含ap后缀,即如果该设备称为wlan0ap,填写wlan0即可;
(5)driver:设定无线驱动,我这里是nl80211;
(6)auth_algs=1
其中auth_algs指定采用哪种认证算法,采用位域(bit fields)方式来制定,其中第一位表示开放系统认证(Open System Authentication, OSA),第二位表示共享密钥认证(Shared Key Authentication, SKA)。我这里设置alth_algs的值为1,表示只采用OSA;
(7)wpa:指定WPA类型,这是一个位域值(bit fields),第一位表示启用WPA,第二位表示启用WPA2。在我的配置中,无论设置成1、2或3,都可以正常连接
(8)wpa_passphrase:WPA/WPA2加密需要指定密钥,这个选项就是配置WPA/WPA2的密钥。注意wpa_passphrase要求8~63个字符。另外还可以通过配置wpa_psk来制定密钥,不过要设置一个256位的16进制密钥,不适合我们的需求;
(9)wpa_pairwise/rsn_pairwise:如果启用了WPA,需要指定wpa_pairwise;如果启用了WPA2,需要指定 rsn_pairwise,或者采用wpa_pairwise的设定。
接下来将hostapd拷贝到的/bin下,并修改可执行权限,将hostapd.conf也拷贝到开发板的/app/AP/目录下
在板子上直接执行hostapd -B hostapd.conf 即可
如果编译过程出现缺少库的错误,请自行检查你hostapd所依赖的libnl库和openssl库是否成功交叉编译。
若出现读取random随机数错误,可采用符号链接的方法解决:
~> mv /dev/random /dev/random.org
~> ln -s /dev/urandom /dev/random
=========================================================================================
Linux中的随机数可以从两个特殊的文件中产生,一个是/dev/urandom.另外一个是/dev/random。上述两种方式都可以产生随机数,dev/urandom 和dev/random都是产生用不为空的随机字符流,但区别是:/dev/random设备会封锁,直到系统产生的随机字符流已经充分够用,所以耗用时间较长。/dev/urandom设备不会封锁,数据的随机程度不高,但是一般情况已经够用。
=========================================================================================
更详细的文章链接:http://www.linuxidc.com/Linux/2012-05/60476.htm
2.4.配置udhcpd
修改/opt/busybox-1.20.2/examples/udhcp/udhcpd.conf然后拷贝到开发板/etc目录下。
因为是实现最基础的功能,所以我们只要简单的修改地址池、默认网关以及dns即可。
以下是我的配置:
1,修改IP池
起始IP的后两位可以随意,但必须在一个网段
192.168.x.y
192.168.x.z
2修改执行dhcp功能的接口
可以用过ifconfig -a或者iwconfig命令来查看接口
3,修改DNS、网关、netmask等
opt dns 8.8.8.8 # DNS地址
option subnet 255.255.255.0 #子网掩码
opt router 192.168.2.1 #网关
其他默认即可
2.4.1 自动分配IP链接wif
因为udhcpd和udhcpc一样都是busybox里面自带的命令。所以我直接把配置文件放到开发板上再执行命令
- ~> ifconfig wlan0 192.168.2.1 netmask 255.255.255.0 (先把要接入点设备ip设置好)
- ~>udhcpd -f /etc/udhcpd.conf //就可以启动dhcp服务器了。
- (注意!!!)这里执行的时候可能会出错!!!
- udhcpd -f /etc/udhcpd.conf
udhcpd (v1.20.2) started
udhcpd: can’t open ‘/var/lib/misc/udhcpd.leases’: No such file or directory
Udhcpd在执行的时候可能会提示没有一个叫做udhcpd.release的租赁文件,这个只要在相应的文件夹下创建即可。执行下面两条命令:
~>mkdir -p /var/lib/misc/
~>touch /var/lib/misc/udhcpd.leases
再次执行!
~>udhcpd -f /etc/udhcpd.conf
udhcpd (v1.20.2) started
Sending OFFER of 192.168.2.20
Sending ACK to 192.168.2.20
Sending ACK to 192.168.2.20
Sending ACK to 192.168.2.20
2.5 iptables移植
===============================================================================
ptables简介:
iptables是基于内核的防火墙,功能非常强大,iptables内置了filter,nat和mangle三张表。
五个规则链。
1.PREROUTING (路由前)
2.INPUT (数据包流入口)
3.FORWARD (转发管卡)
4.OUTPUT(数据包出口)
5.POSTROUTING(路由后)
Filter表负责过滤数据包,包括的规则链有,input,output和forward;
Nat表则涉及到网络地址转换,包括的规则链有,prerouting,postrouting和output;
Mangle表则主要应用在修改数据包内容上,用来做流量整形的。
默认的规则链有:INPUT,OUTPUT,NAT,POSTROUTING,PREROUTING;
INPUT匹配目的IP是本机的数据包,FORWARD匹配流经本机的数据包,PREROUTING用来修改目的地址用来做DNAT,POSTROUTING用来修改源地址用来做SNAT。
===============================================================================
2.5.1下载
iptables-1.4.12.tar.gz
http://download.csdn.net/detail/u010944778/8945513
2.5.2解压之后进入目录
[hulu@centos6 iptables-1.4.12]$ mkdir install
[hulu@centos6 iptables-1.4.12]$./configure --host=arm-linux --enable-static --disable-shared --prefix=/home/hulu/wifi/AP/iptables-1.4.12/install --disable-ipv6 --disable-largefile
[hulu@centos6 iptables1.4.12]$makeCC=/opt/buildroot2012.08/arm920t/usr/bin/arm-linux-gcc CFALGS=--static LDFLAGS=-static
[hulu@centos6 iptables-1.4.12]$sudo make install
========================================================================================================
再理解一次CFLAGS和LDFLAGS:一般我们通过CFLAGS的 -I 选项告诉编译器所依赖的第三方的库的头文件在哪里,通过LDFLAGS的-L选项告诉链接器这些库的库文件在哪里;还有LIBS是告诉链接器要链接哪些库文件。简单地说,LDFLAGS是告诉链接器从哪里寻找库文件,而LIBS是告诉链接器要链接哪些库文件。有时候LIBS指定了却找不到库时可以试试LDFLAGS。
========================================================================================================
[hulu@centos6 iptables-1.4.12]$ cd ./install/sbin
[hulu@centos6 iptables-1.4.12]$ file *
[hulu@centos6 iptables-1.4.12]$ sudo /opt/buildroot2012.08/arm920t/usr/bin/arm-linux-strip xtables-multi
strip的作用是减轻点重量
此时将/install/lib文件夹下的文件都拷贝到开发板的/lib目录下,并赋予可执行权限,将xtables-multi放到开发板的/bin目录下,赋予可执行权限后将xtables-multi改名为iptables
有了iptables命令工具之后我们便要来配置nat转发表,如下:
~> iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables v1.4.2: can’t initialize iptables table `nat’: Table does not exist (do you need to insmod?)
Perhaps iptables or your kernel needs to be upgraded.
怎么会出现以上错误,百度了一下,原来是内核有的选项没选上,解决如下:
配置内核选项
Networking —->
Networking options —->
[*] Network packet filtering (replaces ipchains) —>
Core Netfilter Configuration —>
<*> Netfilter Xtables support (required for ip_tables)
IP: Netfilter Configuration —>
<*> Connection tracking (required for masq/NAT)
<*> IP tables support (required for filtering/masq/NAT)
<*> IP range match support
<*> Packet filtering
<*> REJECT target support
<*> Full NAT
将新编译的内核在烧到开发板上,在重新配置配置nat转发表:
/*将局域网内地址通过eth0接口伪装后转发出去*/
~>:iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
/*开启转发功能,允许已建立连接及相关连接对内转发*/
~>: iptables -A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISH -j ACCEPT
/*对外转发,数据包从wlan0流向eth0*/
~>: iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT
iptables主要参数
iptables定义规则的方式比较复杂:
格式:iptables [-t table] COMMAND chain CRETIRIA -j ACTION
-t table :3个filter nat mangle
COMMAND:定义如何对规则进行管理
chain:指定你接下来的规则到底是在哪个链上操作的,当定义策略的时候,是可以省略的
CRETIRIA:指定匹配标准
-j ACTION :指定如何进行处理
A 向规则链中添加一条规则,默认被添加到末尾
-T指定要操作的表,默认是filter
-D从规则链中删除规则,可以指定序号或者匹配的规则来删除
-R进行规则替换
-I插入一条规则,默认被插入到首部
-F清空所选的链,重启后恢复
-N新建用户自定义的规则链
-X删除用户自定义的规则链
-p用来指定协议可以是tcp,udp,icmp等也可以是数字的协议号,
-s指定源地址
-d指定目的地址
-i进入接口
-o流出接口
-j采取的动作,accept,drop,snat,dnat,masquerade
详情可以参考http://www.cnblogs.com/argb/p/3535179.html这篇文章
=======================================================================================================================================================
关于iptables的nat参考:
MASQUERADE是SNAT网络地址转换的一种,SNAT的使用方法,即可以NAT成一个地址,也可以NAT成多个地址,但是,对于SNAT,不管是几个地址,必须明确的指定destination的ip.如果eth0是动态拨号获取IP,那就需要MASQUERADE来实现SNAT。而我的eth0是接到路由器VAN上的,虽然路由器是拨号上网,但是我的eth0是自己指定的IP,每次都不会变,所以应该也可以使用SNAT的方式来配置iptables。不过我觉得MASQUERADE更方便,这就当为3G动态拨号直连做预热吧。
=======================================================================================================================================================
开启linux 的转发功能! Linux系统是默认进制数据包转发的,所谓的转发就是当主机拥有多块网卡的时候,其中一块收到数据包,根据数据包的目的ip转发到本机的另一张网卡上,该网卡根据路由表继续发送数据包首先保证硬件连通,然后打开系统的转发功能
less /proc/sys/net/ipv4/ip_forward,该文件内容为0,表示禁止数据包转发,1表示允许,将其修改为1。可使用命令echo “1” > /proc/sys/net/ipv4/ip_forward 修改文件内容,重启网络服务或主机后效果不再生效
查看是否已打开 ip 转发(1 表示打开):
~>cat /proc/sys/net/ipv4/ip_forward
如果未打开,则用以下命令打开:
~>echo “1”>/proc/sys/net/ipv4/ip_forward
在以上都准备就绪后,我们一定要记得先实现eth0能上网,eth0要上网的话我们只要再给网关和DNS就可以了。
~>route add default gw 192.168.1.1 //设置默认网关为192.168.1.1;只有eth0联网,这个缺省就行。
至于DNS,linux系统并没有直接配置DNS的命令行。网上都说在/etc/resolv.conf中修改,我们回顾STA模式DHCPC自动分配IP的时候打印信息也有个recreating /etc/resolv.conf因为我在做根文件系统的时候并没有在/etc目录下创建resolv.conf,于是我又到文件系统目录树里面创建了一个。在新建的resolv.conf里面添加nameserver:114.114.114.114 //DNS
然后连上的wifi热点就可以上网了。至此使用hostapd+udhcpd+iptables等工具基于内核mac80211驱动框架就实现了RT3070无线网卡的softAP!!!
以下是我编写同时实现rt3070的sta模式和ap模式的脚本文件,读者可适当参考,若是看不懂,请参考关于shell脚本语法http://tsov.net/sh-script-syntax/
#!/bin/sh
#Copyright (C) 2015 hulu<1334528355qq.com>
#This script is used to start Wifi
export sta=/apps/wireless/sta
export AP=/apps/wireless/ap
read -p "choice Wifi mode(sta or ap):" mode
echo "Worked on $mode now"
DEVICE=${1}
dhcp=${2}
# cp $sta/libcrypto.a /lib
# cp $sta/libcrypto.so.0.9.8 /lib
# cp $sta/libssl.so.0.9.8 /lib
# cp $sta/libssl.a /lib
# cp $sta/wpa_supplicant /bin
# cp $sta/wpa_cli /bin
# cp $sta/wpa_passphrase /bin
# chmod 777 wpa*
# mkdir -p /lib/firmware
# cp $sta/rt2870.bin /lib/firmware
configure_wifi_sta()
{
ifconfig wlan0 up
wpa_supplicant -B -d -Dwext -iwlan0 -c $sta/wpa_supplicant.conf
#ifconfig wlan0 192.168.0.120 broadcast 192.168.0.255 netmask 255.255.255.0 up
# cp $sta/default.script /usr/share/udhcpc/
# chmod 777 default.script
if [ "$dhcp" = "dhcp" ]; then
udhcpc -i wlan0
fi
ifconfig eth0 down
echo "now wifi is active,you can internet."
}
# mkdir /lib/firmware
# cp /apps/wireless/sta/rt2870.bin /lib/firmware/
configure_wifi_ap()
{
mv /dev/random /dev/random.org
ln -s /dev/urandom /dev/random
mkdir -p /var/lib/misc/
touch /var/lib/misc/udhcpd.leases
ifconfig wlan0 192.168.2.1
ifconfig eth0 192.168.0.120 netmask 255.255.255.0 up
route add default gw 192.168.0.1
# cp $AP/libnl.so.1 /lib
hostapd -B $AP/hostapd.conf
if [ "$dhcp" = "dhcp" ]; then
udhcpd /etc/udhcpd.conf
fi
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT
echo "1" >/proc/sys/net/ipv4/ip_forward
echo "now ap is active."
}
stop_wifi()
{
#stop DHCP work on this NIC
dhcp_pid=`ps | grep -v grep | grep "udhcp" | awk '{print $1;}'`
if [ -n "$dhcp_pid" ]; then
kill $dhcp_pid
fi
ifconfig $DEVICE 0.0.0.0
#Stop wpa_supplicant work on STA mode
pid=`ps | grep -v grep | grep "wpa_supplicant" | awk '{print $1;}'`
if [ -n "$pid" ]; then
kill $pid
fi
if [ -d /var/run/wpa_supplicant ]; then
rm -rf /var/run/wpa_supplicant
fi
#Stop hostapd work on AP mode
pid=`ps | grep -v grep | grep "hostapd" | awk '{print $1;}'`
if [ -n "$pid" ]; then
kill $pid
fi
}
#begin!!!!!!!!
if [ $mode = ap ]; then
stop_wifi
configure_wifi_ap
else
stop_wifi
configure_wifi_sta
exit
fi