分类 wifidog分析 下的文章

OpenWRT 增加内核模块及应用方法

进入package目录,创建模块目录
cd mcp/branches/V1.1-beta1/mcp/package
mkdir example
进入example目录,创建Makefile文件和代码路径

cd example
touch Makefile
mkdir src

Makefile具体内容如下:

# Kernel module example
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=example
PKG_RELEASE:=1
include $(INCLUDE_DIR)/package.mk

define KernelPackage/example
  SUBMENU:=Other modules
  DEPENDS:=@TARGET_octeon
  TITLE:=Support Module for example
  AUTOLOAD:=$(call AutoLoad,81,example)
  FILES:=$(PKG_BUILD_DIR)/example/example.$(LINUX_KMOD_SUFFIX)
endef

define Build/Prepare
  mkdir -p $(PKG_BUILD_DIR)
  $(CP) -R ./src/* $(PKG_BUILD_DIR)/
endef

define Build/Compile
  $(MAKE) -C "$(LINUX_DIR)" \
    CROSS_COMPILE="$(TARGET_CROSS)" \
    ARCH="$(LINUX_KARCH)" \
    SUBDIRS="$(PKG_BUILD_DIR)/example" \
    EXTRA_CFLAGS="-g $(BUILDFLAGS)" \
    modules
endef

$(eval $(call KernelPackage,example))

进入src目录,创建代码路径和相关源文件

cd src
mkdir example
cd example
touch example.c Kconfig Makefile

example.c具体内容如下:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

/* hello_init ---- 初始化函数,当模块装载时被调用,如果成功装载返回0 否则返回非0值 */
static int __init hello_init(void)
{
   printk("I bear a charmed life.\n");
   return 0;
}

/ * hello_exit ---- 退出函数,当模块卸载时被调用 */
static void __exit hello_exit(void)
{
   printk("Out, out, brief candle\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("zhangjiefeng");

Kconfig具体内容如下:

config EXAMPLE
  tristate "Just a example"
  default n
  help
   This is a example, for debugging kernel model.
   If unsure, say N.

Makefile具体内如如下:

obj-m := example.o

回到主路径 mcp/branches/V1.1-beta1/mcp/,编译选项配置保存并编译

make menuconfig
  Kernel modules --->
    Other modules --->
      kmod-example

选项设置为M,保存退出
  然后编译该模块:

make package/example/compile

编译出的文件可以在主路径的以下路径找到

./staging_dir/target-mips64_eglibc-2.10.1/root-octeon/lib/modules/2.6.30.9/
./build_dir/linux-octeon/example/ipkg-octeon/kmod-example/lib/modules/2.6.30.9/
./build_dir/linux-octeon/example/example/

文件名为:example.ko
  注:我们使用./build_dir/linux-octeon/example/example/example.ko

用户态工具添加方法
进入package目录,创建工具目录

cd mcp/branches/V1.1-beta1/mcp/package
mkdir example1

进入example1目录,创建Makefile文件和代码路径

cd example1
touch Makefile
mkdir src
 该Makefile具体内容如下:
#User mode tool example
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=example1
PKG_RELEASE:=1
PKG_BUILD_DIR := $(KERNEL_BUILD_DIR)/$(PKG_NAME)
include $(INCLUDE_DIR)/package.mk

define Package/example1
 SECTION:=utils
 CATEGORY:=Base system
 TITLE:=Build for example1 commands
endef

define Package/example1/description
 This package contains an utility useful to use example1 commands.
endef

define Build/Prepare
  mkdir -p $(PKG_BUILD_DIR)
  $(CP) ./src/* $(PKG_BUILD_DIR)/
endef

target=$(firstword $(subst -, ,$(BOARD)))
MAKE_FLAGS += TARGET="$(target)"
TARGET_CFLAGS += -Dtarget_$(target)=1 -Wall

define Build/example1/compile
  $(MAKE) -C "$(LINUX_DIR)" \
   CROSS_COMPILE="$(TARGET_CROSS)" \
   ARCH="$(LINUX_KARCH)" \
   SUBDIRS="$(PKG_BUILD_DIR)" \
   EXTRA_CFLAGS="$(BUILDFLAGS)"
endef

define Package/example1/install
  $(INSTALL_DIR) $(1)/sbin
  $(INSTALL_BIN) $(PKG_BUILD_DIR)/example1 $(1)/sbin/
endef

$(eval $(call BuildPackage,example1))

进入src目录,创建相关源文件

cd src
touch example1.c Makefile

example1.c 具体内容如下:

#include <stdio.h>
int main(void)
{
  printf("Hello, world\n");
  return 0;
}

Makefile文件具体内容如下:

.NOTPARALLEL:
#OCTEON_ROOT=$(PWD)/src/
CC=~/openwrt/main/staging_dir/toolchain-mips64_gcc-4.4.1_eglibc-2.10.1/usr/bin/mips64-openwrt-linux-gnu-gcc
CFLAGS=-mips64r2 -mabi=64 -march=octeon -mtune=octeon
LFLAGS=
.PHONY: all
all: example1
example1:example1.c
  ${CC} ${CFLAGS} ${LFLAGS} -W -g -Wall -Wno-unused-parameter -DUSE_RUNTIME_MODEL_CHECKS=1 \
    -o $@ example1.c

回到主路径 mcp/branches/V1.1-beta1/mcp/,编译选项配置保存并编译

make menuconfig
  Base system --->
   example1

选项设置为M,保存退出
然后编译该模块:

make package/example1/compile

编译出的文件可以在主路径的以下路径找到

./staging_dir/target-mips64_eglibc-2.10.1/root-octeon/sbin/
./build_dir/linux-octeon/example1/ipkg-octeon/example1/sbin/
./build_dir/linux-octeon/example1/

文件名为:example1
注:我们使用./build_dir/linux-octeon/example1/example1
根据OpenWrt安装介绍,将内核模块和用户态工具在板子上运行,到这就简单了往下我就不贴了。

本文章由 http://www.wifidog.pro/2015/01/30/openwrt%E6%B7%BB%E5%8A%A0%E6%A8%A1%E5%9D%97.html 整理编辑,转载请注明出处

openwrt系统 sysupgrade 命令执行过程分析

对这个openwrt的细节方面了解的还比较欠缺,故从实际中的经常用的功能说起,研究研究,可以了解更多的细节。

在openwrt的页面中已经涉及到下面的内容如:
1.jpg

其中在更新系统时候有进行配置保存及恢复的功能。

1:sysupgrade是的交互式使用命令如下:
2.jpg

经过上面的系统更新之后,会保存上面显示的配置文件中的内容,故更新系统不会影响配置的丢失。

2:脚本分析

脚本有点多,其中分析主要的脚本就可以了,其他的加一些打印信息可以帮助分析执行流程。

上面就是通过openwrt系统提供的sysupgrade命令来对系统进行更新的。  
root@OpenWrt:~# which sysupgrade  
/sbin/sysupgrade  
看看脚本中的主要内容,  
include /lib/upgrade  

do_save_conffiles() {  
    local conf_tar="${1:-$CONF_TAR}"  

    [ -z "$(rootfs_type)" ] && {  
        echo "Cannot save config while running from ramdisk."  
        ask_bool 0 "Abort" && exit  
        return 0  
    }  
    run_hooks "$CONFFILES" $sysupgrade_init_conffiles  
    ask_bool 0 "Edit config file list" && vi "$CONFFILES"  

    v "Saving config files..."  
    [ "$VERBOSE" -gt 1 ] && TAR_V="v" || TAR_V=""  
    tar c${TAR_V}zf "$conf_tar" -T "$CONFFILES" 2>/dev/null  
}  
其中run_hooks函数的定义如下,其主要是执行钩子函数,即,第一个参数为:函数参数,第二个参数之后为:调用函数。  

run_hooks() {  
    local arg="$1"; shift  
    for func in "$@"; do  
        eval "$func $arg"  
    done  
}  
    run_hooks "$CONFFILES" $sysupgrade_init_conffiles 的作用就是将需要保存的文件名字保存到"$CONFFILES"文件中,保存那些文件了  
    定义在add_uci_conffiles()和add_overlayfiles()函数中。  
add_uci_conffiles() {  
    local file="$1"  
    ( find $(sed -ne '/^[[:space:]]*$/d; /^#/d; p' \  
        /etc/sysupgrade.conf /lib/upgrade/keep.d/* 2>/dev/null) \  
        -type f 2>/dev/null;  
      opkg list-changed-conffiles ) | sort -u > "$file"  
    return 0  
}  

add_overlayfiles() {  
    local file="$1"  
    find /overlay/etc/ -type f | sed \  
        -e 's,^/overlay/,/,' \  
        -e '\,/META_[a-zA-Z0-9]*$,d' \  
        -e '\,/functions.sh$,d' \  
        -e '\,/[^/]*-opkg$,d' \  
    > "$file"  
    return 0  
}  
默认保存的文件内容如下:如果需要对自定  
etc/wifidog.conf  
etc/sysctl.conf  
etc/squid/squid.conf  
etc/shells  
etc/rc.local  
etc/profile  
etc/passwd  
etc/inittab  
etc/hosts  
etc/group  
etc/dropbear/dropbear_rsa_host_key  
etc/dropbear/dropbear_dss_host_key  
etc/crontabs/root  
etc/config/wifidog  
etc/config/uhttpd  
etc/config/system  
etc/config/redirect  
etc/config/network  
etc/config/ip  
etc/config/firewall  
etc/config/dropbear  
etc/config/dhcp  
函数ask_bool()实现是否与命令行进行交互式的处理。  
    v "Saving config files..."  
    [ "$VERBOSE" -gt 1 ] && TAR_V="v" || TAR_V=""  
    tar c${TAR_V}zf "$conf_tar" -T "$CONFFILES" 2>/dev/null  
实现对上面的数据文件进行压缩处理,其文件名称为:/tmp/sysupgrade.tgz  

if [ -n "$CONF_IMAGE" ]; then  
        case "$(get_magic_word $CONF_IMAGE cat)" in  
                # .gz files  
                1f8b) ;;  
                *)  
                        echo "Invalid config file. Please use only .tar.gz files"  
                        exit 1  
                ;;  
        esac  
        get_image "$CONF_IMAGE" "cat" > "$CONF_TAR"  
        export SAVE_CONFIG=1  
elif ask_bool $SAVE_CONFIG "Keep config files over reflash"; then  
        do_save_conffiles  
        export SAVE_CONFIG=1  
else  
        export SAVE_CONFIG=0  
fi  
上面的条件判断执行的是elif,即默认是保存更改过的配置文件。 export SAVE_CONFIG=1  

其中语句  
kill_remaining TERM  
sleep 3  
kill_remaining KILL  
实现对进程的term和kill操作  
kill_remaining() { # [ <signal> ]  
    local sig="${1:-TERM}"  
    echo -n "Sending $sig to remaining processes ... "  

    local stat  
    for stat in /proc/[0-9]*/stat; do  
        [ -f "$stat" ] || continue  

        local pid name state ppid rest  
        read pid name state ppid rest < $stat  
        name="${name#(}"; name="${name%)}"  

        local cmdline  
        read cmdline < /proc/$pid/cmdline  

        # Skip kernel threads   
        [ -n "$cmdline" ] || continue  

        case "$name" in  
            # Skip essential services  
            *ash*|*init*|*watchdog*|*ssh*|*dropbear*|*telnet*|*login*|*hostapd*|*wpa_supplicant*) : ;;  

            # Killable process  
            *)  
                if [ $pid -ne $$ ] && [ $ppid -ne $$ ]; then  
                    echo -n "$name "  
                    kill -$sig $pid 2>/dev/null  
                fi  
            ;;  
        esac  
    done  
    echo ""  
}  

在升级操作之前有一个run_ramfs(),将一个最小能运行的系统mount到内存中去。为后的操作提供运行环境。  
run_ramfs() { # <command> [...]  
    install_bin /bin/busybox /bin/ash /bin/sh /bin/mount /bin/umount        \  
        /sbin/pivot_root /usr/bin/wget /sbin/reboot /bin/sync /bin/dd   \  
        /bin/grep /bin/cp /bin/mv /bin/tar /usr/bin/md5sum "/usr/bin/[" \  
        /bin/vi /bin/ls /bin/cat /usr/bin/awk /usr/bin/hexdump          \  
        /bin/sleep /bin/zcat /usr/bin/bzcat /usr/bin/printf /usr/bin/wc  

    install_bin /sbin/mtd  
    for file in $RAMFS_COPY_BIN; do  
        install_bin $file  
    done  
    install_file /etc/resolv.conf /lib/functions.sh /lib/functions.sh /lib/upgrade/*.sh $RAMFS_COPY_DATA  

    pivot $RAM_ROOT /mnt || {  
        echo "Failed to switch over to ramfs. Please reboot."  
        exit 1  
    }  

    mount -o remount,ro /mnt  
    umount -l /mnt  

    grep /overlay /proc/mounts > /dev/null && {  
        mount -o remount,ro /overlay  
        umount -l /overlay  
    }  

    # spawn a new shell from ramdisk to reduce the probability of cache issues  
    exec /bin/busybox ash -c "$*"  
}  
在整整操作之前先看看 mtd,sysupgrade 更新过程实际使用的就是mtd命令  
root@OpenWrt:/overlay/etc#mtd   
Usage: mtd [<options> ...] <command> [<arguments> ...] <device>[:<device>...]  

The device is in the format of mtdX (eg: mtd4) or its label.  
mtd recognizes these commands:  
        unlock                  unlock the device  
        refresh                 refresh mtd partition  
        erase                   erase all data on device  
        write <imagefile>|-     write <imagefile> (use - for stdin) to device  
        jffs2write <file>       append <file> to the jffs2 partition on the device  
Following options are available:  
        -q                      quiet mode (once: no [w] on writing,  
                                           twice: no status messages)  
        -n                      write without first erasing the blocks  
        -r                      reboot after successful command  
        -f                      force write without trx checks  
        -e <device>             erase <device> before executing the command  
        -d <name>               directory for jffs2write, defaults to "tmp"  
        -j <name>               integrate <file> into jffs2 data when writing an image  
        -p                      write beginning at partition offset  

Example: To write linux.trx to mtd4 labeled as linux and reboot afterwards  
         mtd -r write linux.trx linux  


do_upgrade() {  
    v "Performing system upgrade..."  
    if type 'platform_do_upgrade' >/dev/null 2>/dev/null; then  
        platform_do_upgrade "$ARGV"  
    else  
        default_do_upgrade "$ARGV"  
    fi  
    [ "$SAVE_CONFIG" -eq 1 -a -n "$USE_REFRESH" ] && {  
        v "Refreshing partitions"  
        if type 'platform_refresh_partitions' >/dev/null 2>/dev/null; then  
            platform_refresh_partitions  
        else  
            refresh_mtd_partitions  
        fi  
        if type 'platform_copy_config' >/dev/null 2>/dev/null; then  
            platform_copy_config  
        else  
            jffs2_copy_config  
        fi  
    }  
    v "Upgrade completed"  
    [ -n "$DELAY" ] && sleep "$DELAY"  
    ask_bool 1 "Reboot" && {  
        v "Rebooting system..."  
        reboot -f  
        sleep 5  
        echo b 2>/dev/null >/proc/sysrq-trigger  
    }  
}  

default_do_upgrade() {  
    sync  
    if [ "$SAVE_CONFIG" -eq 1 -a -z "$USE_REFRESH" ]; then  
        get_image "$1" | mtd -j "$CONF_TAR" write - "${PART_NAME:-image}"  
    else  
        get_image "$1" | mtd write - "${PART_NAME:-image}"  
    fi  
}  

platform_do_upgrade() {  
    local rootfs="$(x86_get_rootfs)"  
    local rootfsdev="${rootfs##*:}"  

    sync  
    [ -b ${rootfsdev%[0-9]} ] && get_image "$@" | dd of=${rootfsdev%[0-9]} bs=4096 conv=fsync  
    sleep 1  
}  


x86_get_rootfs() {  
    local rootfsdev  
    local rootfstype  

    rootfstype="$(awk 'BEGIN { RS=" "; FS="="; } ($1 == "rootfstype") { print $2 }' < /proc/cmdline)"  
    case "$rootfstype" in  
        squashfs|jffs2)  
            rootfsdev="$(awk 'BEGIN { RS=" "; FS="="; } ($1 == "block2mtd.block2mtd") { print substr($2,1,index($2, ",")-1) }' < /proc/cmdline)";;  
        ext4)  
            rootfsdev="$(awk 'BEGIN { RS=" "; FS="="; } ($1 == "root") { print $2 }' < /proc/cmdline)";;  
    esac  

    echo "$rootfstype:$rootfsdev"  
}  

jffs2_copy_config() {  
    if grep rootfs_data /proc/mtd >/dev/null; then  
        # squashfs+jffs2  
        mtd -e rootfs_data jffs2write "$CONF_TAR" rootfs_data  
    else  
        # jffs2  
        mtd jffs2write "$CONF_TAR" rootfs  
    fi  
}  
refresh_mtd_partitions() {  
    mtd refresh rootfs  
}  

其中需要注意的是不同的平台如,Atheros和x86的各个平台的执行过程有所不同,最终一点是需要将$CONF_TAR保存到系统的rootfs_data或者rootfs_data分区数据中去。

转自:http://blog.csdn.net/stone8761/article/details/39692769

本文章由 http://www.wifidog.pro/2015/01/30/openwrt-sysupgrade.html 整理编辑,转载请注明出处

wifidog lua字符匹配

匹配下列格式的数据中的 source和MAC地址:

Chain WiFiDog_br-lan_Outgoing (1 references)  
    pkts      bytes target     prot opt in     out     source               destination           
     705   109595 MARK       all  --  *      *       10.1.1.191           0.0.0.0/0            MAC C4:6A:B7:6F:7A:AB MARK or 0x200  
     705   109595 MARK       all  --  *      *       10.1.1.192           0.0.0.0/0            MAC C4:6A:B7:6F:7A:BB MARK or 0x200  
     705   109595 MARK       all  --  *      *       10.1.1.193           0.0.0.0/0            MAC C4:6A:B7:6F:7A:CB MARK or 0x200  
     705   109595 MARK       all  --  *      *       10.1.1.194           0.0.0.0/0            MAC C4:6A:B7:6F:7A:DB MARK or 0x200  

简单实现如下,在已知格式的情况下,使用最简单快捷的方式来解决问题。

local file  

file = io.open("format", "r")  

for line in file:lines() do  
    print(string.match(line, "%d+.%d+.%d+.%d+"))  
    print(string.match(line, "%x+:%x+:%x+:%x+:%x+:%x+"))  
end  
file:close()  

执行结果如下

>lua -e "io.stdout:setvbuf 'no'" "match.lua" 
nil
nil
nil
nil
10.1.1.191
C4:6A:B7:6F:7A:AB
10.1.1.192
C4:6A:B7:6F:7A:BB
10.1.1.193
C4:6A:B7:6F:7A:CB
10.1.1.194
C4:6A:B7:6F:7A:DB
>Exit code: 0

原理如下:

http://www.cnitblog.com/kenlistian/archive/2008/10/15/50292.html

本文章由 http://www.wifidog.pro/2015/01/29/wifidog-lua.html 整理编辑,转载请注明出处

搭建专业商用WIFI热点

在国外一些酒店、餐厅、咖啡厅、商业中心或其他的商家,经常可以看到客人使用笔记本或手机使用商家提供的无线Wifi网络上网。这是一个非常好的手段,客人得到了便利,商家赢得了客流。

其实,架设一个普通的家用WiFi热点是非常简单的。用一个普通的无线路由器(Wireless Router)就可以实现。但是在商业场合,这种方式往往就不能满足需求了。因为,普通家用的开放式的WiFi热点没有安全验证机制,任何用户都可以使用热点,甚至是商家以外的用户也可以“蹭网”。这就大大影响了网络热点的安全性和网络的稳定性。即使用WEP或WAP等验证方式也难以完全保证热点的安全性,而且也会大大限制了热点的便利性。而商用WiFi热点的构筑则是完全不一样的概念。

创建专业的商用WiFi热点的做法是,为欲使用热点的用户提供一个Web认证页面,一般是用强制网络门户系统(Captive Portal)/热点管理系统来实现的。以此认证页面为基础提供对用户多元化的认证方式。用户只有通过认证后,才能接入Wifi热点以使用Internet。同时,商家也可利用强制网络门户系统的后台实现与客户的一定互动。例如,可以在用户认证前向用户提示热点使用协议;或者发布商家或赞助商的广告;向客户推送商家最新促销信息等。甚至,还可以要求热点用户在线支付一定费用后才允许接入热点等等。一般,商家还可在强制网络门户系统的后台实现一些高级安全设置。如,客户端黑名单限制,地址限制,流量控制等。

架设这样的强制网络门户/热点管理系统有多种方法。但技术原理都是类似的,一般需要一个防火墙/网关系统,一个用于认证管理和控制的后台系统。
常见的技术解决方案有NoCat、Wifidog、Chillispot等。这类系统的构筑都分别有各种系统需求和构筑方法,由于构成的组件和子系统比较多,所以相对都比较繁琐。

此外,也有一些整套的服务商解决方案,比如FON,Wiwiz,ile sans fil,Sputnik和FreeSpot等。相对配置简单很多,用户一般只需要购买这些服务商提供的无线路由器设备或自行配置网关设备即可,而后台系统可使用这些服务商提供的后台服务。

这里着重介绍一下Wiwiz,因为Wiwiz是一个开放式的系统,不仅有中文版,安装配置的方式也最为灵活。最方便的是Wiwiz可以使用用户现有的无线路由器或AP设备。如果无线路由器已经安装或支持DD-WRT固件,只需要简单的设置即可。如果用户的无线路由器不支持DD-WRT,还可以使用用户的本地计算机或虚拟机。

笔者进行了对Wiwiz系统试验。因为笔者的无线路由器并不支持DD-WRT,所以笔者采用了虚拟机的安装方式。

介绍一下系统环境。计算机采用普通家用PC机,Windows XP SP2系统。Internet连接采用的是联通的ADSL接入。普通无线路由器一台。

首先,将ADSL调制解调器的网线另一端连接着无线路由器的WAN/Internet口。将另一根网线的一端插入无线路由器的一个LAN口,另一端接到PC的以太网插口。然后,设置无线路由器。在PC上打开浏览器,访问192.168.1.1,输入用户名密码后即可打开路由器的设置页面。设置好ADSL连接后,PC就可以正常访问Internet了。

接下来就要安装和配置Wiwiz的客户端了。因为是采用虚拟机的安装方式,所以先要下载并安装一个虚拟机软件。笔者使用的是免费的VMWare Player。下载之后直接打开安装程序并按照提示的步骤完成安装即可。

然后,下载Wiwiz的虚拟机镜像文件。在Wiwiz官网的下载页面有下载链接。镜像文件为Zip格式,大约180MB。下载后解压缩。双击后缀为.vmx的文件后,VMWare Player就会自动启动这个虚拟机镜像了,然后立即会看到一个提示,选择Keep。接着会看到一个Linux系统正在启动。

当启动完成后,点击虚拟机的界面以进入操作环境。此处要求用户登录系统,默认的用户名是root,密码为wiwiz-user。然后输入命令/usr/local/hsbuilder/hsbuilder_setup.sh setup ,并按回车。

之后一路回车,直到出现设置成功的提示。此时就已经大功告成了。

最后,用一台有无限网卡的电脑(或者有Wifi功能的手机)测试一下。在测试用的电脑上连接笔者的无线路由器的热点,连接成功后,打开任何一个网址都会见到默认认证页面。

因为笔者在虚拟机中执行设置的命令时使用的都是默认的配置,所以显示的热点认证页面也是默认的。其实,用户可以使用Wiwiz的服务后台创建并定制自己的热点。包括认证方式、是否付费及费率、认证页面的外观样式、颜色、图片以及服务条款等都可以进行定制。同时,还有一些高级权限控制的功能。专业版的用户(付费用户)还可以进行更高级别的设置并使用一些附加功能。详细的内容可以参考Wiwiz的官方网站(www.wiwiz.com)。这里就不做深入讲解了。

本文章由 http://www.wifidog.pro/2015/01/29/%E5%95%86%E7%94%A8wifi.html 整理编辑,转载请注明出处