Subject: linux SLIP/PPP howto(中文)

From: [email-masked] (Vincent Chen)
Date: Sat, 18 Feb 1995 20:31:06 CST

TCP/IP over serial line

一、　ＳＬＩＰ

　SLIP在實際應用上分為標準SLIP、封包壓縮CSLIP兩種。事實上，
所謂的封包壓縮只是壓縮封包的表頭部分，對資料傳輸上，有部分
提昇。然而，在與主機端連線時必須確認對方所使用的協定種類，
否則大部分的功能將無法使用。

　完成SLIP連線共包含三個步驟，數據機撥號接通主機、設定硬體
界面、設定route table。這三個步驟可分別執行dial、ifconfig
、route三個指令來完成。這�我們不分別說明這三個程式如何執行
，我們把焦點集中在dip這個程式，它可以自動呼叫其他程式，完成
整個SLIP連線工作。

　下dip -t指令可以進入測試模式，得到dip所有指令列表，我們也
不對測式模式多作介紹，所有動作都可以寫入script中，撥號、簽
入、從主機送出的訊息抓出我們的IP一次完成。

  這�是dip所有指令列表：

DIP: Dialup IP Protocol Driver version 3.3.7l-uri (27 Dec 94)
Written by Fred N. van Kempen, MicroWalt Corporation.

DIP> help
DIP knows about the following commands:

        bootp    break    chatkey  config   databits
        dec      default  dial     echo     flush
        get      goto     help     if       inc
        init     mode     modem    netmask  parity
        password proxyarp print    port     quit
        reset    securidf securid  send     skey
        sleep    speed    stopbits term     timeout
        wait

  下面我們透過一個script範例來看整個連線過程：

＊　dip只有支援四個內部變數，$local存放主機指定給我們的IP，
　　$remote存放SLIP主機的IP，$mtu存放最大傳輸封包大小，
　　$errlvl存放指令執行傳回值。目前尚沒有支援使用者自定變數
    。

＊　dip的script沒有迥路的功能，只有簡單的if-goto邏輯判斷、
    及goto的分支執行

＊　在完成slip連線後，我們所擁有的IP及domain皆為主機所指定，
　　在執行ftp、telnet等程式不會有問題。特別要注意e-mail時，
　　發信人地址是用我們所設的domain，別人在回信時會無法投遞，
　　因為自設的domain沒有註冊，對方的信件程式無法從domain找
    出您的IP。如果要測試信件收發，可以用<user>@<ip addr>的
    方式傳遞。

#
# xxx.dip       Dialup IP connection support script. (dynamic)
#
# Version:      xxx.dip 1.0     08/12/94
#
# Author:       Vincent Chen
#
# Features:     Support multiple phone numbers
#               Redial automatically when busy
#

main:

  #
  # Set serial port and speed.
  #
  port cua1                             # 指定modem連接port (COM2)
  speed 57600                           # RS-232傳輸速度
  netmask 255.255.0.0

  #
  # Prepare for dialing.
  #
  # send <string>: 傳送指令給modem
  # \r代表CR字元，modem在收到CR後開始解釋、執行指令
  # \n代表LF+CR
  #
  send AT&FL1S0=0S7=25\r
  if $errlvl != 0 goto modemerr         # modem指令執行失敗的處理
  #
  # wait <string> <n>
  # 在<n>秒內從modem取得<string>，成功傳回0
  #
  wait OK 3                             # 等待modem傳回執行結果
  if $errlvl != 0 goto modemerr
  #
  # print <string>: 在螢幕上顯示<string>
  #
  print DIP script for XXX SLIP server by Vincent Chen 08/12/1994
  print ---------------------------------------------------------
  print ............... AutoDial procedure started ..............
  print ................. Press Ctrl-C to abort .................

dialsvr:

  #
  # Now trying the 1st number
　# 先撥第一支電話
  #
  # sleep <n>: 暫停執行n秒
  #
  sleep 3
  print .................... Trying xxx-xxxx ....................
  send ATDTxxx-xxxx\r                   # 撥server電話號碼
  if $errlvl != 0 goto modemerr
  wait BUSY 15                          # 判斷是否佔線
  if $errlvl == 0 goto next
  wait CONNECT 10                       # 等待連線訊息
  if $errlvl != 0 goto next
  goto login                            # 連線成功，開始簽入主機

next:

  #
  # Now trying the 2nd number
  # 第一支電話無法連上，改撥第二支
  #
  sleep 3
  print .................... Trying 368-9280 ....................
  send ATDT368-9280\r
  if $errlvl != 0 goto modemerr
  wait BUSY 15
  if $errlvl == 0 goto dialsvr
  wait CONNECT 15
  if $errlvl != 0 goto dialsvr
  goto login

#
# 數據機連線成功，開始簽入主機
#

login:

  wait login: 10                        # 等主機送出簽入的提示訊息
  if $errlvl != 0 goto error
  send slip\r                           # 送出您的帳號
  if $errlvl != 0 goto error
  #wait password: 10                    # 等待主機要求輸入密碼
  #if $errlvl != 0 goto error
  #send xxxxx\r                         # 送出您的密碼
  #if $errlvl != 0 goto error
  #
  # Catch the key word to confirm that IP will show up shortly.
  #
  wait \nEnter 5                      # 等待主機送出我們IP前的字串
  if $errlvl != 0 goto error          # '\n'是專為臺大而設的
  #
  # Get dynamic IP from strings that sent by server
  #
  # get $local <remote/ip address> <n>
  # 在<n>秒內取得我們的ip，可指定dip自行抓或由我們直接指定
  # get $local remote <n>: 讓dip從server送出的訊息抓我們的ip
  # get $local xxx.xxx.xxx.xxx <n>: 直接告訴dip我們的ip
  #
  # 注意：在下get指令之前必須確定不會有類似ip的字串重複出現
  #       ，否則會造成dip誤判，前面之所以要等Enter字串就是
  #       考慮到這一點。
  #
  get $local remote 3                   # 由dip分析我們的IP
  if $errlvl != 0 goto error
  #
  # Get gateway IP from strings that sent by server
  #
  # get $remote <remote/ip address> <n>
  # 在<n>秒內取得server的ip，可指定dip自行抓或由我們直接指定
  # get $remote remote <n>: 讓dip從server送出的訊息抓server的ip
  # get $remote xxx.xxx.xxx.xxx <n>: 直接告訴dip server的ip
  #
  get $remote remote 3                  # 由dip分析主機的IP
  if $errlvl != 0 goto error

  #
  # Set up the SLIP operating parameters.
  #
  get $mtu 1024                         # 設封包長度最大值

  #
  # Set Destination net/address as type 'default' (vice an address).
  # This is used by the 'route' command to set the kernel routing table.
  # Some machines seem to require this be done for SLIP to work properly.
  #
  default                               # 由dip自行建立route table

#
# Give the connection report !
#

done:

  print ****** Connected ******
  print IP address is $local
  print Remote gateway is $remote
  #
  # mode <SLIP/CSLIP/PPP>
  #
  mode SLIP                             # 進入SLIP傳輸模式
  goto exit

error:

  print SLIP connection failed.
  goto exit

modemerr:

  print Modem initializing failed.
  goto exit

exit:

　在script完成後，只要輸入dip <script filename>，dip根據預
設的流程自動連上主機。以下是整個script執行過程：

bash# dip /etc/xxxxx
DIP: Dialup IP Protocol Driver version 3.3.7l-uri (27 Dec 94)
Written by Fred N. van Kempen, MicroWalt Corporation.

DIP script for xxx SLIP server by Vincent Chen 08/12/1994
---------------------------------------------------------
............... AutoDial procedure started ..............
................. Press Ctrl-C to abort .................
.................... Trying xxx-xxxx ....................
****** Connected ******
IP address is xxx.xxx.xxx.xxx
Remote gateway is yyy.yyy.yyy.yyy

　從上面可看到在撥第一支電話後，成功的連上主機。主機指定給
我們的IP是xxx.xxx.xxx.xxx，Server的IP是yyy.yyy.yyy.yyy。本
範例會在忙線時，接著撥第二支電話，直到連線完成，只要稍作修
改可以支援第三、第四支電話。

  連線完成後我們可以用ifconfig指令看到dip已經為我們設定好
sl0這個slip channel，在1.1.78版之前的核心只支援4個channel，
目前新的核心可以支援到16個channel，對外連線不論您同時ftp、
telnet幾部主機都只佔用一個channel。這表示如果您把linux當作
一部slip server的話，您還有15個channel提供dial-in的服務。

　接著我們先用ifconfig指令檢查dip是否已經設好slip界面。

bash# ifconfig

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Bcast:127.255.255.255  Mask:255.0.0.0
          UP BROADCAST LOOPBACK RUNNING  MTU:2000  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0
          TX packets:20 errors:0 dropped:0 overruns:0

sl0       Link encap:VJ Serial Line IP
          inet addr:xxx.xxx.xxx.xxx  P-t-P:yyy.yyy.yyy.yyy  Mask:255.255.0.0
          UP POINTOPOINT RUNNING  MTU:1024  Metric:1
          RX packets:0 errors:0 dropped:0 compressed:0
          TX packets:0 errors:0 dropped:0 compressed:0

eth0      Link encap:10Mbps Ethernet  HWaddr 00:00:C0:00:02:F1
          inet addr:192.168.1.1  Bcast:192.168.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING  MTU:1500  Metric:1
          RX packets:2 errors:0 dropped:0 overruns:0
          TX packets:0 errors:0 dropped:0 overruns:0
          Interrupt:15 Base address:0x340

  在下表我們可以看到除了原有的loop back、ethernet之外又多了
xxx.xxx.xxx.xxx及default這兩個dip為我們設好的封包傳輸路徑。
default route是一個特殊的封包傳輸路徑，所有目的地不在傳輸路
徑表上的封包都透這個管道對外傳送，我們可以看到default route
是以xxx.xxx.xxx.xxx為getway，因此必須另外指定送往xxx.xxx.xxx
.xxx的封包是透過sl0昦面傳送。

bash# route

Kernel routing table
Destination     Gateway         Genmask         Flags MSS    Window Use Iface
xxx.xxx.xxx.xxx *               255.255.255.255 UH    960    0        0 sl0
192.168.1.0     *               255.255.255.0   U     1436   0        0 eth0
loopback        *               255.0.0.0       U     1936   0       20 lo
default         xxx.xxx.xxx.xxx *               UG    960    0        0 sl0

　要結束連線時只要下dip -k指令，dip會幫我們掛斷電話、清除傳
輸路徑表、關閉sl0傳輸界面等所有工作，回復未連線前的系統狀況
。當然用kill -9 <dip process id>也有同樣的效果。

bash# dip -k

DIP: Dialup IP Protocol Driver version 3.3.7l-uri (27 Dec 94)
Written by Fred N. van Kempen, MicroWalt Corporation.

DIP: process 115 killed.

ＳＬＩＰ　ＣＨＥＣＫＬＩＳＴ：

１．　/etc/HOSTNAME及/etc/hosts檔內有定義您自已的linux主機嗎?
２．　/etc/resolv.conf檔內有定義您的nameserver嗎?
３．　dip script內mode <protocol>指令和主機端所用的協定相符嗎?
４．　連線後所顯示的local IP和Gateway IP正確嗎?
５．　ifconfig和route指令查看的結果都正確嗎?

二、　ＰＰＰ

　PPP協定比SLIP更加完備，您用'man pppd'指令去看一下那一串參
數就會相信了。 :-) 具有錯誤更正能力，光是主機和使用者雙方的
的查核方式就有兩種，兩端的'pppd'程式會自動協調連線參數。
在HOWTO文件中提到使用PPP的時機有：一、您別無選擇，二、通信品
質不良，三、您須要SLIP所不具備的功能。

　言歸正傳，如果您有安裝PPP，所有的檔案都會放在/usr/lib/ppp
內，但是'pppd'程式在執行時會到/etc/ppp/options檔內讀取連線
參數。下列幾個程式是較常用的：

　１．　unlock <device>
        刪除COM port鎖定檔，如果DIP、Minicom等程式不是以正
        常方式結束時，會留下這個檔案。
　
　２．　fix-cua <device>
        在chat程式和主機連線後，把COM port鎖定檔改成只有root
        可以刪除。

　３．　chat
        負責撥號建立連線載波(carrier)。

　４．　ppp-off
        刪除pppd的process結束連線。

  ５．　ppp-on
        呼叫其他程式完成PPP連線。

１．  建立ppp-on連線script

#! /bin/sh
#
#  PPP script for Seednet v1.0
#

DEVICE=cua1                             <- cua0 (COM 1)、 cua1 (COM 2)
CONSOLE=/dev/console
LOCKDIR=/var/spool/uucp

PHONE=737-7850

#
# 檢查COM port是否被其他程式佔用。
#
if [ -f $LOCKDIR/LCK..$DEVICE ]
then
    echo -e "Status: Device is locked.\n"
    exit 1
fi

#
# 把COM port的鎖定檔改成只有root可刪除，以確保pppd對COM port
# 的控制權。
#
fix-cua $DEVICE

(

stty 38400 -tostop

echo -e "\nPPP script for Seednet v1.0\n" > $CONSOLE
echo " Step 1. Dialing server ..." > $CONSOLE

#
# 呼叫chat程式撥號及建立連線。
#
if chat -l LCK..$DEVICE ABORT "NO CARRIER" ABORT BUSY "" \
           ATZ OK ATDT$PHONE CONNECT ""
then
    #
    # chat程式完成建立連線的動作，交由pppd開始和遠端主機協
    # 調連線參數。
    #
    echo " Step 2. Negotiating ..." > $CONSOLE
    pppd +ua <pap-file> /dev/$DEVICE 57600 crtscts
    #
    # 休息5秒鐘，讓雙方完成協調的動作。
    #
    sleep 5
    echo -e "Status: Successful.\n" > $CONSOLE
    exit 0
else
    #
    # chat程式由於佔線或主機未回應等因素，沒有完成連線動作。
　　#
    echo -e "Status: Not connected.\n" > $CONSOLE
    exit 1
fi

) < /dev/$DEVICE > /dev/$DEVICE

２．  設定連線參數

      pppd會從/etc/options檔內讀入連線參數，這�是和seednet
      連線的範例，其他參數可用'man pppd'得到更詳細的說明：

      mtu 512                           <- 最大傳輸封包大小
      mru 512                           <- 最大接收封包大小
      noipdefault                       <- 由pppd和主機協調IP
      defaultroute                      <- 產生route table
      netmask 255.255.255.0             <- 指定net mask
      passive

      PPP對使用者的查核，以seednet為例是採用PAP的方式，共須
      帳號及密碼兩項資料，您可以把查核資料放入一個檔案內，
      並加上+ua <pap-file>的參數，讓pppd自動答覆主機的查詢。

      使用者查核資料檔的格式：
      <your account>
      <your password>

３．  連線成功後情形

bash# ifconfig

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Bcast:127.255.255.255  Mask:255.0.0.0
          UP BROADCAST LOOPBACK RUNNING  MTU:2000  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0
          TX packets:20 errors:0 dropped:0 overruns:0

ppp0      Link encap:Point-Point Protocol
          inet addr:xxx.xxx.xxx.xxx  P-t-P:139.175.1.9  Mask:255.255.255.0
          UP POINTOPOINT RUNNING  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0
          TX packets:0 errors:0 dropped:0 overruns:0

eth0      Link encap:10Mbps Ethernet  HWaddr 00:00:C0:00:02:F1
          inet addr:192.168.1.1  Bcast:192.168.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0
          TX packets:0 errors:0 dropped:0 overruns:0
          Interrupt:15 Base address:0x340

bash# route -n

Kernel routing table
Destination     Gateway         Genmask         Flags MSS    Window Use Iface
139.175.1.9     *               255.255.255.255 UH    1436   0        0 ppp0
192.168.1.0     *               255.255.255.0   U     1436   0        0 eth0
127.0.0.0       *               255.0.0.0       U     1936   0       20 lo
default         139.175.1.9     *               UG    1436   0        0 ppp0

ＰＰＰ　ＣＨＥＣＫＬＩＳＴ：

除第三項外，和SLIP的CHECKLIST大致相同。

＊                                        　　　　 　　＊　
＊　　本文除所註明之Slackware範例外，著作權屬陳建業　　＊
＊                                                     ＊
＊　１．　未經作者同意，本文不得任意轉載               ＊
＊　２．　在未經修改條件下，個人可任意使用本文件　　   ＊
＊　３．　在取得作者同意後，歡迎公開陳列本文件         ＊
＊                                                     ＊
＊　　　　　如有任何建議或更正，歡迎email至            ＊
＊             [email-masked]    　          ＊
＊                                                     ＊