wifidog 程式碼簡單分析(1)

weixin_34249678發表於2015-02-02

本文針對wifidog-20090925版本解釋下wifidog的程式碼功能。

原始碼包括wifidog閘道器協議src 資料夾以及自帶的libhttpd 庫libhttpd 資料夾(libhttpd庫用來建立wifidog 的http 服務,後面會提到這個庫具體做什麼),wifidog的配置檔案wifidog.conf,這裡主要分析src 資料夾裡的原始碼。

按照看原始碼的習慣,在gateway.c main 裡的開始,按流程分析。

config_get_config()函式,是一個獲取全域性變數config的函式,全域性變數config 是關於閘道器全部配置的結構體,config 的成員變數都在wifidog.conf 檔案裡,這個變數時貫穿全部流程的一個全域性變數,要看懂主要的變數的作用。如下所說config 都是指這個全域性變數config。

config_init()函式,設定config 成員的預設初始值,有些設定成NULL,詳細的看conf.c 的config_init函式,對照config 的結構體定義。

parse_commandline()函式,通過命令列獲取config 結構體的某些成員值,如wifidog -c /etc/wifidog.conf, 通過-c 設定configfile 的值。

config_read(),讀取configfile, 設定config 的成員值。這裡要注意,config_read會覆蓋parse_commandline 設定的config 成員值,parse_commandline會覆蓋config_init設定的config 成員值。

config_validate(),檢查config 的auth_server 和 gw_interface 值是否為空,因為這兩個變數值最為重要。

client_list_init(), 這個函式涉及到另一個全域性變數firstclient, 這個結構體主要儲存客戶端的資訊,如ip, mac, token, incoming, outgoing等,客戶端資訊被儲存到一個連結串列裡,firstclient是連結串列頭。

init_signals(),處理一些訊號,如quit 訊號,會清理一些iptables 規則,殺掉ping 協議執行緒和counter 協議執行緒,前者是閘道器不斷髮ping 包給認證伺服器證明自己是活的,後者是閘道器向認證伺服器更新客戶端資訊。

main_loop(),wifidog 流程開始。

首先檢查config 的 gw_address 和 gw_id 有沒有值,如果沒有值,通過get_iface_ip 和get_iface_mac 來獲取,這裡gw_id 設定成閘道器gw_interface 的mac 地址,gw_address 是閘道器 gw_interface 的IP,一般gw_interface 是br0, 在wifidog.conf 裡設定。

接著在閘道器 gw_interface 的IP 和 gw_port 上用libhttpd 庫執行一個http server,並建立對於檔案'wifidog'、''、'about'、'auth'、'status'的訪問回撥函式:http_callback_wifidog、http_callback_wifidog、http_callback_about、http_callback_auth以及http_callback_status,這裡所謂的訪問回撥函式可以理解成當客戶端訪問auth 檔案時會執行http_callback_auth函式,其他函式同理。

這裡還有一個libhttpd的函式,httpdAddC404Content,這個函式是用來處理客戶端第一次http 訪問外網時執行回撥函式,回撥函式就是這個函式的第二個引數http_callback_404。

對於上面四個訪問回撥函式,我們下面會提到http_callback_auth,其餘三個不重要,這裡就不細說了。在此之前,我們先來看一下流程用到的第一個函式http_callback_404。

這裡需要有個場景:我們連上了一個路由器(等同於這裡的閘道器),這個路由器有wifigdog,並且繫結到了無線的interface 上,然後我們第一次上網,輸入url: www.baidu.com。

在http_callback_404函式裡,會把上述場景中的url 請求通過lihttpd 記錄下來,然後判斷認證伺服器是否可達,接著就會把客戶端的瀏覽器重定向到認證伺服器: http://auth_server/login/?gw_id=xxx&gw_address=xxx&gw_port=xxx&url=www.baidu.com。

接著閘道器就是等待認證伺服器重定向客戶端瀏覽器http://gatewayip:gatewayport/wifidog/auth?token=xxx, 這個token是認證伺服器生成的,用來標識唯一客戶端。瀏覽器重新訪問閘道器,閘道器呼叫auth 的回撥函式:http_callback_auth,這個函式就是拿著客戶端瀏覽器傳送的token 去認證伺服器上核對token 的過程。

http_callback_auth(),該函式首先會檢查http 報文裡有沒有token,然後通過arp_get 拿該報文傳送者的ip 對應的MAC 地址,然後到之前提到的客戶端連結串列裡搜此ip 和mac 對應的客戶端,如果搜不到,說明是新的客戶端接入,那麼就需要把它追加到連結串列裡;如果這個客戶端是logout請求(http報文請求裡有logout),那麼閘道器會發一個關於此客戶端下線的通知到認證伺服器;如果不是logout請求,那麼不管是不是新的客戶端,都需要再次認證一下,這時交由函式authenticate_client 處理。

authenticate_client(),因為我們之前已經把這個客戶端追加到連結串列裡了,所以首先去客戶端連結串列裡找,如果找得到這個客戶端,那麼就繼續進行。閘道器將此客戶端的mac、ip、token傳送個login 請求到認證伺服器[auth_server_request(&auth_response, REQUEST_TYPE_LOGIN, r->clientAddr, mac, token, 0, 0);],驗證此token 和之前認證伺服器給客戶端的token 是否一致,如果一致會返回一個auth code=auth_allowed 給閘道器,通知閘道器對此客戶端放通,閘道器收到後會將此客戶端加入上網白名單(設定iptables 規則允許上網,客戶端不再看到訪問www.baidu.com 彈出非百度視窗),然後將客戶端重定向到http://auth_server/portal/?gw_id=xxx, 到此閘道器協議工作完成,但我們的原始碼解析還沒有完成,下面回到http 幾個回撥函式地方,接著講解。

本文由http://www.wifidog.pro/2014/12/09/wifidog%E4%BB%A3%E7%A0%81%E5%88%86%E6%9E%90.html整理編輯,轉載請註明出處

相關文章