問題描述:之前一直對公司產品的ppp撥號流程存在很多不解的問題,主要是對pppd的那麼多參數不太明晰,所以針對pppd命令的使用做一下研究。
摘要
本文主要介紹了嵌入式Linux系統下使用pppd 2.4.4來進行PPP撥號需要使用的腳本是如何配置的,配置項的含義,同時也說明了如何來配置參數,實現ppp撥號上網。
一.問題提出嵌入式Linux操作系統下,如果要進行PPP連接,就需要配置撥號要使用的連接腳本。這些腳本參數就決定了PPPD的行為,會對PPP連接產生很大的影響。所以需要對這些腳本的參數以及具體含義有所了解。
二.解決思路和PPP連接關系密切的有兩個腳本是chat和options兩個腳本。其中,chat腳本是用來進行AT呼叫和控制的腳本,而options腳本就影響PPP連接的。
1. CHAT腳本
一個簡單的chat腳本有下面的結構:
"" AT
OK ATDT dialnumber
CONNECT ""
一個chat腳本都是由字符串對來組成的。前面的字符串都是期望獲取的串,緊跟的是發送的字符串。這個腳本每一項的具體含義是這樣的:
1) MODEM期望空字符串。這句話的意思直接理解就是MODEM不管收到什麼字符串,先發出字符串AT;
2) 期望收到“OK”字符串,然後發送字符串“ATDT dialnumber”
3) 如果收到“CONNECT”,就不再發送,認為數據鏈路已建立連接。
這樣的chat腳本是最簡單的,如果需要進行超時控制,就可以加入如下字段:
TIMEOUT 10
如果要增加對特殊情況的處理,就加入下面字段:
ABORT BUSY
ABORT NO ANSWER
ABORT RINGING
這三行語句的意思是:如果收到字符串“BUSY”、“NO ANSWER”、“RINGING”就退出執行。
所以在考慮到各種特殊情況下,配置一個PPP連接的CHAT腳本就可以像下面這樣:
TIMEOUT 30
ABORT BUSY
ABORT NO ANSWER
ABORT RINGING
"" AT
OK ATDT dialnumber
CONNECT ""
2.OPTIONS腳本
OPTIONS腳本的內容,為PPP連接指定了連接使用的設備、使用的控制字符傳輸速率、指定了硬件加速、溢出控制等。
例如下面的options腳本:
ttyS0 ---- 指定連接使用的設備,例如:ttyS0、ttyS1等
57600 ---- 設置連接使用的控制字符傳輸速率,可以設置為57600、115200等
debug ---- 如果需要加入調試信息,就加入參數debug
logfile /var/ ppplog ---- 將連接過程中的信息輸入到某個文件中
mtu 1500
-detach
noipdefault ---- 不使用默認IP就可以加入參數noipdefault
defaultroute
usepeerdns ---- 使用服務器端協商的DNS就可以設置參數usepeerdns
lcp-echo-failure 4 ---- 當連續4次沒有收到發出的LCP回聲請求時,就認為服務器端已不再響應,就退出執行。這裡的失敗次數可以靈活來決定。
-ccp ---- 不使用壓縮控制協議
-vj ---- 關掉式IP頭壓縮
-chap ---- 不使用chap鑒權
-mschap-v2 ---- 不使用mschap鑒權
user
hide-password
connect "/usr/bin/chat -v -t6 -f /var/ chat" ---- 制定了要使用的chat腳本的位置。加上參數-v 告訴 chat命令將其所有的輸出/入拷貝到系統記錄裡(通常是 /var/log/messages)。-t 6 指定了執行chat該命令的時間為6s。chat腳本的位置可以位於/etc/目錄下,也可以位於/var下,這個可以更加需要靈活設置。
persist --- 永久鏈接(自動重撥)
crtscts --- 告訴ppp使用modem的硬件流量控制
modem --- 使ppp使用DCD信號來判斷連接是否正常,有無掉線現象
deflate --- 使pppd使用defalte壓縮方式
idle --- 設置了一個時間限制,當在300秒的時間內沒有數據傳送,就斷開連接
lock --- 則創建一個鎖定文件,其他程序在發現存在這個文件後,就能得知相應的串口已經被使用。
demond --- 參數告訴pppd停留在後台,監視網絡數據,一旦有要求就立即進行連網,超時後就斷開連接,但pppd仍然停留在後台等待下次數據傳送
其他的參數具體含義可以參照參考PPPD2.4.4 中options.c中注釋:
/*
* Option variables and default values.
*/
int debug = 0; /* Debug flag */
int kdebugflag = 0; /* Tell kernel to print debug messages */
int default_device = 1; /* Using /dev/tty or equivalent */
char devnam[MAXPATHLEN]; /* Device name */
bool nodetach = 0; /* Don't detach from controlling tty */
bool updetach = 0; /* Detach once link is up */
int maxconnect = 0; /* Maximum connect time */
char user[MAXNAMELEN]; /* Username for PAP */
char passwd[MAXSECRETLEN]; /* Password for PAP */
bool persist = 0; /* Reopen link after it goes down */
char our_name[MAXNAMELEN]; /* Our name for authentication purposes */
bool demand = 0; /* do dial-on-demand */
char *ipparam = NULL; /* Extra parameter for ip up/down scripts */
int idle_time_limit = 0; /* Disconnect if idle for this many seconds */
int holdoff = 30; /* # seconds to pause before reconnecting */
bool holdoff_specified; /* true if a holdoff value has been given */
int log_to_fd = 1; /* send log messages to this fd too */
bool log_default = 1; /* log_to_fd is default (stdout) */
int maxfail = 10; /* max # of unsuccessful connection attempts */
char linkname[MAXPATHLEN]; /* logical name for link */
bool tune_kernel; /* may alter kernel settings */
int connect_delay = 1000; /* wait this many ms after connect script */
int req_unit = -1; /* requested interface unit */
bool multilink = 0; /* Enable multilink operation */
char *bundle_name = NULL; /* bundle name for multilink */
bool dump_options; /* print out option values */
bool dryrun; /* print out option values and exit */
char *domain; /* domain name set by domain option */
int child_wait = 5; /* # seconds to wait for children at exit */
3. 鑒權腳本
一般情況下,PPP連接是需要進行身份認證的。簽權方式有兩種,一種是PAP鑒權,另一種是CHAP鑒權。鑒權需要的用戶名和密碼是存放在PAP-secrets和chap-secrets腳本中,以如下方式存放:
Username * password
需要進行鑒權時,通過在options腳本中指定鑒權方式為PAP或CHAP,PPP模塊就會從PAP-secrets和chap-secrets腳本中讀出用戶名和密碼,附加到PPP的鑒權包中,發送到服務器端進行身份認證。
4. PPP撥號過程與腳本之間的關系
腳本設置成功以後,怎麼和pppd2.4.4一起工作呢?這個需要從pppd程序的主函數入手。
這個過程是這樣的:
Pppd程序啟動以後,就會按照pathname.h中所指定的文家位置去尋找options腳本文件。這個可以按照需要指定文件的位置,確保pppd能夠准確找到該文件。或者使用 file 選項,後面跟上事先將配置信息存放的文件(option文件)。
Pppd找到options文件後,按順序讀入參數行。在這裡,就可以獲取系統要使用的是哪個設備來進行聯網、設備的速率是多少。
Pppd 將配置的參數解析為程序當中的全局變量標識符,進行pppd連接控制。
三.實踐情況下面是FT282 上的PPP連接使用的OPTIONS、 CHAT和PAP-SECRETS腳本。
OPTIONS:
connect "/usr/bin/chat -v -t6 -f /var/ppp/td-scdma_chat"
ttyUSB0
115200
debug
logfile /var/log/ppplog
mtu 1500
-detach
noauth
noipdefault
defaultroute
usepeerdns
crtscts
lock
lcp-echo-failure 4
-ccp
-vj
-chap
-mschap-v2
user
hide-password
CHAT:
"" AT
OK ATDT*98*1#
CONNECT ""
PAP-SECRETS:
wap *wap
經過在FT282上進行測試,發現能夠順利進行PPP連接。
以上流程成功後,會由移動或聯通的基站分配一個IP地址作為自己的客戶端地址,接下來按照如下流程建立客戶端與服務端的連接。
(1)socket(int domain,int type,int protocol);
該函數建立新的socket,以建立一個新的通信端口並獲得文件描述符。函數中的參數domain確定一個協議族,這裡定義為AF_INET,type指定套接字類型,該處使用SOCK_STREAM,protocol一般為0,使用默認協議。
(2)connect(int sockfd,struct sockaddr *address,size_t address_len);
當調用socket建立傳輸端口後,調用connect函數建立與遠程服務器相連的連接線路。
(3) recv(int sockfd,void *buf,int len,unsigned int flags);
該函數用於接收從套接口傳來的信息,socket用connect連接的套接口,buf是指向內存塊的指針,用於存儲接受的消息,len指明內存塊的大小,flags是一個操作標志。
(4)Base64_Code();//對登陸信息或附件內容進行加密
(5)send(int sockfd,const void *msg,int len,unsigned int flags);
該函數是用來通過套接口向其它程序傳遞數據的。sockfd是用來傳輸數據的socked描述符,msg是一個指向要發送數據的指針,len是以字節為單位的數據的長度,flags一般情況下設置為0。
其中對附件文件的發送需要預先設定每次讀取的字節數和每次發送的字節數,將附件分批讀取編碼發送。