分类 wifidog原理 下的文章

广告路由器开发(一)数据流-wifidog版

最近无事时对广告路由器进行了一个分析
常用的广告路由器一般是通过普通路由器刷openwrt或是ddwrt等固件后安装wifidog组件做的,我们这里分析的即是wifidog加authpuppy
以下数据为截取自authpuppy和wifidog的交互

1.用户请求页面http://www.gov.cn/guowuyuan/2014-09/23/content_2755108.htm  
--------------------------------------------------------------------------------------  
request:  
/login/?gw_address=192.168.4.1&gw_port=2060&gw_id=default&mac=00:0e:c6:f0:06:b2&url=http%3A//www.gov.cn/guowuyuan/2014-09/23/content_2755108.htm  

response:  
<form action="http://192.168.1.251:81/login/?gw_address=192.168.4.1&gw_port=2060&gw_id=default&mac=00:0e:c6:f0:06:b2&url=http%3A//www.gov.cn/guowuyuan/2014-09/23/content_2755108.htm" method="POST">  
    <input type="hidden" name="gw_id" value="default" />  
  <input type="hidden" name="gw_address" value="192.168.4.1" />  
  <input type="hidden" name="gw_port" value="2060" />  
        <input type="hidden" id="authenticators" name="authenticator" value="apAuthLocalUser"/>  
      <div id="authPlugin_apAuthLocalUser" style="display: none">  
            <h1>Local network user authentication</h1>  

                    <input type="submit" name="submit[apAuthLocalUserconnect]" id="submit[apAuthLocalUserconnect]" value="Connect" onClick="deleteLinkElement()" />  
                    <input type="password" name="apAuthLocalUser[password]" value="Pb4AoWdlOhqu4B2T535zDg==" id="apAuthLocalUser_password" />  
                    <label for="apAuthLocalUser_remember_me">Remember me</label>  
                    <input type="checkbox" name="apAuthLocalUser[remember_me]" value="1" checked="checked" id="apAuthLocalUser_remember_me" />  
</form>  

array (  
  'REDIRECT_STATUS' => '200',  
  'HTTP_HOST' => '192.168.1.251:81',  
  'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',  
  'HTTP_COOKIE' => 'authpuppy=usb6bslekske7ek5rlorknvf43; localUserCookie=226f362768d281ff14cf428fa3c3b8c87a6c4834',  
  'HTTP_USER_AGENT' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/600.1.17 (KHTML, like Gecko) Version/7.1 Safari/537.85.10',  
  'HTTP_REFERER' => 'http://news.baidu.com/',  
  'SCRIPT_FILENAME' => 'F:/phpStudyAll/WWW/authpuppy/web/index.php',  
  'REMOTE_PORT' => '53961',  
  'REDIRECT_QUERY_STRING' => 'gw_address=192.168.4.1&gw_port=2060&gw_id=default&mac=00:0e:c6:f0:06:b2&url=http%3A//www.gov.cn/guowuyuan/2014-09/23/content_2755108.htm',  
  'REDIRECT_URL' => '/login/',  
  'GATEWAY_INTERFACE' => 'CGI/1.1',  
  'SERVER_PROTOCOL' => 'HTTP/1.1',  
  'REQUEST_METHOD' => 'GET',  
  'QUERY_STRING' => 'gw_address=192.168.4.1&gw_port=2060&gw_id=default&mac=00:0e:c6:f0:06:b2&url=http%3A//www.gov.cn/guowuyuan/2014-09/23/content_2755108.htm',  
  'REQUEST_URI' => '/login/?gw_address=192.168.4.1&gw_port=2060&gw_id=default&mac=00:0e:c6:f0:06:b2&url=http%3A//www.gov.cn/guowuyuan/2014-09/23/content_2755108.htm',  
)  
++++++++++++++++++++++++++++++++++++++++++++++++  


2.登录成功以后而返回如下  
--------------------------------------------------------------------------------------  
request:  
/login/?gw_address=192.168.4.1&gw_port=2060&gw_id=default&mac=00:0e:c6:f0:06:b2&url=http%3A//www.gov.cn/guowuyuan/2014-09/23/content_2755108.htm  

response:  
<html><head><meta http-equiv="refresh" content="0;url=http://192.168.4.1:2060/wifidog/auth?token=60bb7efe229270c4d6d36ed60bb5e98886900126"/></head></html>  

array (  
  'REDIRECT_STATUS' => '200',  
  'HTTP_HOST' => '192.168.1.251:81',  
  'CONTENT_TYPE' => 'application/x-www-form-urlencoded',  
  'HTTP_ORIGIN' => 'http://192.168.1.251:81',  
  'HTTP_COOKIE' => 'authpuppy=usb6bslekske7ek5rlorknvf43; localUserCookie=226f362768d281ff14cf428fa3c3b8c87a6c4834',  
  'HTTP_USER_AGENT' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/600.1.17 (KHTML, like Gecko) Version/7.1 Safari/537.85.10',  
  'HTTP_REFERER' => 'http://192.168.1.251:81/login/?gw_address=192.168.4.1&gw_port=2060&gw_id=default&mac=00:0e:c6:f0:06:b2&url=http%3A//www.gov.cn/guowuyuan/2014-09/23/content_2755108.htm',  
  'HTTP_ACCEPT_LANGUAGE' => 'en-us',  
  'HTTP_ACCEPT_ENCODING' => 'gzip, deflate',  
  'REMOTE_ADDR' => '192.168.1.106',  
  'REMOTE_PORT' => '53950',  
  'REDIRECT_QUERY_STRING' => 'gw_address=192.168.4.1&gw_port=2060&gw_id=default&mac=00:0e:c6:f0:06:b2&url=http%3A//www.gov.cn/guowuyuan/2014-09/23/content_2755108.htm',  
  'REDIRECT_URL' => '/login/',  
  'GATEWAY_INTERFACE' => 'CGI/1.1',  
  'SERVER_PROTOCOL' => 'HTTP/1.1',  
  'REQUEST_METHOD' => 'POST',  
  'QUERY_STRING' => 'gw_address=192.168.4.1&gw_port=2060&gw_id=default&mac=00:0e:c6:f0:06:b2&url=http%3A//www.gov.cn/guowuyuan/2014-09/23/content_2755108.htm',  
  'REQUEST_URI' => '/login/?gw_address=192.168.4.1&gw_port=2060&gw_id=default&mac=00:0e:c6:f0:06:b2&url=http%3A//www.gov.cn/guowuyuan/2014-09/23/content_2755108.htm',  
  'REQUEST_TIME' => 1411547194,  
)  
++++++++++++++++++++++++++++++++++++++++++++++++  

3. 在2中进行跳转后则WiFiDog服务器向授权服务器端发送GET授权请求 若成功则而返回Auth: 1  
--------------------------------------------------------------------------------------  
request:  
/auth/?stage=login&ip=192.168.4.186&mac=00:0e:c6:f0:06:b2&token=60bb7efe229270c4d6d36ed60bb5e98886900126&incoming=0&outgoing=0&gw_id=default  

response://千万要注意这里Auth:与1之间有一个空格否则不能通过验证  
Auth: 1  

array (  
  'REDIRECT_STATUS' => '200',  
  'HTTP_USER_AGENT' => 'WiFiDog 20130917',  
  'HTTP_HOST' => '192.168.1.251',  
  'SERVER_PORT' => '81',  
  'REMOTE_ADDR' => '192.168.1.106',  
  'REMOTE_PORT' => '33264',  
  'REDIRECT_QUERY_STRING' => 'stage=login&ip=192.168.4.186&mac=00:0e:c6:f0:06:b2&token=60bb7efe229270c4d6d36ed60bb5e98886900126&incoming=0&outgoing=0&gw_id=default',  
  'REDIRECT_URL' => '/auth/',  
  'GATEWAY_INTERFACE' => 'CGI/1.1',  
  'SERVER_PROTOCOL' => 'HTTP/1.0',  
  'REQUEST_METHOD' => 'GET',  
  'QUERY_STRING' => 'stage=login&ip=192.168.4.186&mac=00:0e:c6:f0:06:b2&token=60bb7efe229270c4d6d36ed60bb5e98886900126&incoming=0&outgoing=0&gw_id=default',  
  'REQUEST_URI' => '/auth/?stage=login&ip=192.168.4.186&mac=00:0e:c6:f0:06:b2&token=60bb7efe229270c4d6d36ed60bb5e98886900126&incoming=0&outgoing=0&gw_id=default',  
  'REQUEST_TIME' => 1411547194,  
)  
++++++++++++++++++++++++++++++++++++++++++++++++  

4.WiFiDog在接收到Auth:1之后向服务器端发送/portal/?gw_id=default的GET请求 授权服务器返回立即跳转的页面如下:  
--------------------------------------------------------------------------------------  
request:  
/portal/?gw_id=default  

reponse:  
<html><head><meta http-equiv="refresh" content="0;url=http://www.gov.cn/guowuyuan/2014-09/23/content_2755108.htm"/></head></html>  

array (  
  'REDIRECT_STATUS' => '200',  
  'HTTP_HOST' => '192.168.1.251:81',  
  'HTTP_ORIGIN' => 'http://192.168.1.251:81',  
  'HTTP_COOKIE' => 'authpuppy=usb6bslekske7ek5rlorknvf43; localUserCookie=226f362768d281ff14cf428fa3c3b8c87a6c4834',  
  'HTTP_CONNECTION' => 'keep-alive',  
  'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',  
  'HTTP_USER_AGENT' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/600.1.17 (KHTML, like Gecko) Version/7.1 Safari/537.85.10',  
  'HTTP_ACCEPT_LANGUAGE' => 'en-us',  
  'HTTP_REFERER' => 'http://192.168.1.251:81/login/?gw_address=192.168.4.1&gw_port=2060&gw_id=default&mac=00:0e:c6:f0:06:b2&url=http%3A//www.gov.cn/guowuyuan/2014-09/23/content_2755108.htm',  
  'HTTP_ACCEPT_ENCODING' => 'gzip, deflate',  
  'REDIRECT_QUERY_STRING' => 'gw_id=default',  
  'REDIRECT_URL' => '/portal/',  
  'GATEWAY_INTERFACE' => 'CGI/1.1',  
  'SERVER_PROTOCOL' => 'HTTP/1.1',  
  'REQUEST_METHOD' => 'GET',  
  'QUERY_STRING' => 'gw_id=default',  
  'REQUEST_URI' => '/portal/?gw_id=default',  
  'SCRIPT_NAME' => '/index.php',  
  'PHP_SELF' => '/index.php',  
  'REQUEST_TIME' => 1411547194,  
)  
++++++++++++++++++++++++++++++++++++++++++++++++  

5.WiFiDog服务器向授权服务器发送ping操作请求 服务器端通过后发送Pong响应串(纯文本)  
--------------------------------------------------------------------------------------  
request:  
/ping/?gw_id=default&sys_uptime=28824&sys_memfree=99284&sys_load=0.08&wifidog_uptime=61  

response:  
Pong  


array (  
  'REDIRECT_STATUS' => '200',  
  'HTTP_USER_AGENT' => 'WiFiDog 20130917',  
  'HTTP_HOST' => '192.168.1.251',  
  'SERVER_SIGNATURE' => '',  
  'SERVER_SOFTWARE' => 'Apache/2.4.9 (Win32) OpenSSL/0.9.8y PHP/5.3.28',  
  'SERVER_NAME' => '192.168.1.251',  
  'SERVER_ADDR' => '192.168.1.251',  
  'SERVER_PORT' => '81',  
  'REMOTE_ADDR' => '192.168.1.106',  
  'DOCUMENT_ROOT' => 'F:/phpStudyAll/WWW/authpuppy/web',  
  'REQUEST_SCHEME' => 'http',  
  'CONTEXT_PREFIX' => '',  
  'CONTEXT_DOCUMENT_ROOT' => 'F:/phpStudyAll/WWW/authpuppy/web',  
  'SERVER_ADMIN' => 'admin@phpStudy.net',  
  'SCRIPT_FILENAME' => 'F:/phpStudyAll/WWW/authpuppy/web/index.php',  
  'REMOTE_PORT' => '33265',  
  'REDIRECT_QUERY_STRING' => 'gw_id=default&sys_uptime=28824&sys_memfree=99284&sys_load=0.08&wifidog_uptime=61',  
  'REDIRECT_URL' => '/ping/',  
  'GATEWAY_INTERFACE' => 'CGI/1.1',  
  'SERVER_PROTOCOL' => 'HTTP/1.0',  
  'REQUEST_METHOD' => 'GET',  
  'QUERY_STRING' => 'gw_id=default&sys_uptime=28824&sys_memfree=99284&sys_load=0.08&wifidog_uptime=61',  
  'REQUEST_URI' => '/ping/?gw_id=default&sys_uptime=28824&sys_memfree=99284&sys_load=0.08&wifidog_uptime=61',  
  'SCRIPT_NAME' => '/index.php',  
  'PHP_SELF' => '/index.php',  
  'REQUEST_TIME' => 1411547224,  
)  
++++++++++++++++++++++++++++++++++++++++++++++++  

6.WiFiDog向服务器发送计费通知  
--------------------------------------------------------------------------------------  

request:  
/auth/?stage=counters&ip=192.168.4.186&mac=00:0e:c6:f0:06:b2&token=60bb7efe229270c4d6d36ed60bb5e98886900126&incoming=4660796&outgoing=192338&gw_id=default  

response:  
Auth: 1//中间一定要有一个空格  

array (  
  'REDIRECT_STATUS' => '200',  
  'HTTP_USER_AGENT' => 'WiFiDog 20130917',  
  'HTTP_HOST' => '192.168.1.251',  
  'SERVER_NAME' => '192.168.1.251',  
  'SERVER_ADDR' => '192.168.1.251',  
  'SERVER_PORT' => '81',  
  'REMOTE_ADDR' => '192.168.1.106',  
  'REMOTE_PORT' => '33266',  
  'REDIRECT_QUERY_STRING' => 'stage=counters&ip=192.168.4.186&mac=00:0e:c6:f0:06:b2&token=60bb7efe229270c4d6d36ed60bb5e98886900126&incoming=4660796&outgoing=192338&gw_id=default',  
  'REDIRECT_URL' => '/auth/',  
  'GATEWAY_INTERFACE' => 'CGI/1.1',  
  'SERVER_PROTOCOL' => 'HTTP/1.0',  
  'REQUEST_METHOD' => 'GET',  
  'QUERY_STRING' => 'stage=counters&ip=192.168.4.186&mac=00:0e:c6:f0:06:b2&token=60bb7efe229270c4d6d36ed60bb5e98886900126&incoming=4660796&outgoing=192338&gw_id=default',  
  'REQUEST_URI' => '/auth/?stage=counters&ip=192.168.4.186&mac=00:0e:c6:f0:06:b2&token=60bb7efe229270c4d6d36ed60bb5e98886900126&incoming=4660796&outgoing=192338&gw_id=default'  
)  
++++++++++++++++++++++++++++++++++++++++++++++++  

7.退出登录  
--------------------------------------------------------------------------------------  

request:  
/auth/?stage=logout&ip=192.168.4.186&mac=00:0e:c6:f0:06:b2&token=60bb7efe229270c4d6d36ed60bb5e98886900126&incoming=0&outgoing=0&gw_id=default  

response:  
Auth: 0  

array (  
  'REDIRECT_STATUS' => '200',  
  'HTTP_USER_AGENT' => 'WiFiDog 20130917',  
  'HTTP_HOST' => '192.168.1.251',  
  'SERVER_NAME' => '192.168.1.251',  
  'SERVER_ADDR' => '192.168.1.251',  
  'SERVER_PORT' => '81',  
  'REMOTE_ADDR' => '192.168.1.106',  
  'REQUEST_SCHEME' => 'http',  
  'CONTEXT_PREFIX' => '','stage=logout&ip=192.168.4.186&mac=00:0e:c6:f0:06:b2&token=60bb7efe229270c4d6d36ed60bb5e98886900126&incoming=0&outgoing=0&gw_id=default',  
  'REDIRECT_URL' => '/auth/',  
  'GATEWAY_INTERFACE' => 'CGI/1.1',  
  'SERVER_PROTOCOL' => 'HTTP/1.0',  
  'REQUEST_METHOD' => 'GET',  
  'QUERY_STRING' => 'stage=logout&ip=192.168.4.186&mac=00:0e:c6:f0:06:b2&token=60bb7efe229270c4d6d36ed60bb5e98886900126&incoming=0&outgoing=0&gw_id=default',  
  'REQUEST_URI' => '/auth/?stage=logout&ip=192.168.4.186&mac=00:0e:c6:f0:06:b2&token=60bb7efe229270c4d6d36ed60bb5e98886900126&incoming=0&outgoing=0&gw_id=default',  
  'SCRIPT_NAME' => '/index.php',  
  'PHP_SELF' => '/index.php',  
  'REQUEST_TIME' => 1411549984,  
)  
++++++++++++++++++++++++++++++++++++++++++++++++  

本文章由 http://www.wifidog.pro/2015/01/30/wifidog%E6%95%B0%E6%8D%AE%E6%B5%81.html 整理编辑,转载请注明出处

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 整理编辑,转载请注明出处