2015年1月

广告路由器开发(二)实践-wifidog版

上篇文章中分析了wifidog下authpuppy之间的数据流这篇文章中我就介绍一下如何书写一个简单的广告路由器
经过以上分析不难看出 实现一个广告路由器还是非常简单的
由于我本人对symfony框架不感冒 故以下示例代码使用了phalcon框架进行书写(只是演示用而已)

<?php  

namespace controllers;  

class InterfaceController extends \Phalcon\Mvc\Controller  
{  

    public function initialize( )  
    {  

    }  

    public function indexAction( )  
    {  
    }  

    public function loginAction( )  
    {  
        if( $this->request->isGet() && null == $this->request->getQuery( 'advs' ) )  
        {  
            $strDebug = var_export( $_SERVER, true );  

            $this->view->setVar( 'iRefreshTime', 10 ); //广告时间10秒  
            $this->view->setVar( 'url', $this->request->getServer( 'REQUEST_URI' ) . '&advs=advs' );  

            $this->view->pick( 'interface/advs' );//这里展示广告  
        }  
        else  
        {  
            $this->view->disable();  

            $strToken = sha1( rand() . time() );  
            $this->persistent->set( 'redirectUrl', $this->request->getQuery( 'url' ));  
            $this->response->redirect( 'http://' . $this->request->get( 'gw_address' ) . ':' . $this->request->get( 'gw_port' ) . '/wifidog/auth?token=' . $strToken, true );  
        }  

    }  

    public function logoutAction( )  
    {  
        echo 'Auth:0';  
    }  

    public function portalAction( )  
    {//广告过后在此函数内进行跳转  
        $this->view->disable();  
        if( null != $strUrl = $this->persistent->get( 'redirectUrl' ) )  
        {  
            $this->response->redirect( $strUrl, true );  
        }  
        else   
        {  
            $this->response->redirect( 'http://blog.csdn.net/qzfzz', true );  
        }  
    }  

    public function pingAction( )  
    {  
        echo 'Pong';  
    }  

    public function msgAction( )  
    {  
    }  

    public function authAction( )  
    {  
        echo 'Auth: 1';  
    }  

}  

以下为视图

<!--advs.phtml-->  
<!doctype html  
<html>  
<head>  
<meta http-equiv="refresh" content="<?php echo $iRefreshTime;?>;url=<?php echo $url;?>"/>  
<title>Login</title>  
</head>  
<body>  
<p>这里可以展示广告等信息</p>  
</body>  
</html> 

经过以上的开发一个简单的广告路由器即完成了

本文章由 http://www.wifidog.pro/2015/01/30/wifidog%E5%BC%80%E5%8F%91.html 整理编辑,转载请注明出处

广告路由器开发(一)数据流-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 整理编辑,转载请注明出处