作 者: 張中華
任務(wù):在一臺linux機器上,通過ISDN撥號上網(wǎng)。
經(jīng)過嘗試,我成功地做到了這一點。我的配置為:藍點Linux 2.0,Kernel-2.2.16,isdn4linux v3.1PRe1,上海貝爾生產(chǎn)的ISDN內(nèi)置卡,型號為SBT6021。
下面介紹具體做法。介紹順序為:內(nèi)核->isdn4linux安裝->撥號配置->測試。
1、 內(nèi)核
上海貝爾SBT6021型ISDN內(nèi)置卡,使用的芯片為Winbond W6692,這是一種與西門子HiSax驅(qū)動程序兼容的芯片,該卡是即插即用的,無需手工設(shè)定中斷請求號和I/O地址。要Linux內(nèi)核支持這種卡,在編譯內(nèi)核時,必須選中下列選項:
ISDN Support
Support synchronous PPP
?。ǘ鄶?shù)ISDN設(shè)備撥號上網(wǎng)都是使用同步PPP方式)
Hisax SiemensChipset driver support
Hisax Support for DSS1
(絕大多數(shù)ISDN設(shè)備使用的協(xié)議都是DSS1)
Hisax Support for Winbond W6692
但我不必急于編譯內(nèi)核,假如現(xiàn)有的內(nèi)核已經(jīng)包含這些選項了,我又何必重復(fù)一遍呢。那我怎么知道現(xiàn)有內(nèi)核是否已經(jīng)包含這些選項了呢?看內(nèi)核編譯配置文件/usr/src/linux/.config(注重:文件名以"."開頭的文件是隱藏文件,要用ls -a才可看到。)我看到其中有下面這5行內(nèi)容,對應(yīng)于剛才的5個選項:
CONFIG_ISDN=m
CONFIG_ISDN_PPP=y
CONFIG_ISDN_DRV_HISAX=m
CONFIG_HISAX_EURO=y
CONFIG_HISAX_W6692=y
"=y"表示內(nèi)核直接支持(代碼已鏈入內(nèi)核中),"=m"表示模塊支持(代碼在另外的內(nèi)核中,可由內(nèi)核載入)。于是這就表明,藍點Linux 2.0的原有內(nèi)核已包含這些選項了,我就不用重新編譯內(nèi)核啦。
2、 isdn4linux安裝
欲配置ISDN,要用到isdn4linux這一套軟件。isdn4linux的主要文件有isdnctrl, ipppd等。
獲取isdn4linux源碼的地址為:
http://isdn4linux.org
取得的文件為isdn4k-utils.v3.1pre1.tar.gz,放于/usr/src目錄下。
進入/usr/src目錄中,開始安裝過程。
進入/usr/src:
cd /usr/src
解開壓縮文件:
tar xzvf isdn4k-utils.v3.1pre1.tar.gz
命令完成后多了一個子目錄isdn4k-utils,isdn4linux的源碼文件就在其中。
進入該子目錄:
cd isdn4k-utils
該目錄中的README文件具體介紹了如何安裝isdn4linux,照章行事即可。
進行配置:
make config
不做任何改變,用缺省的即可。
開始編譯:
make
未能通過,失敗原因是linux/autoconf.h文件或目錄不存在。這個文件就是/usr/include/linux/autoconf.h文件,一查確實不存在。它是在編譯內(nèi)核的時候生成的,而我并未編譯內(nèi)核,所以當(dāng)然沒有了。好吧,想辦法生成它吧。
到linux目錄并進行配置:
cd /usr/src/linux
make menUConfig
不做任何改變,退出,保存即可。此時一看,/usr/include/linux/autoconf.h文件出來了,這就夠了,不必真的去編譯內(nèi)核。
回到isdn4linux目錄再編譯:
cd /usr/src/isdn4k-utils
make
剛才的問題沒有了,但還是未能通過,失敗原因是capi20/capi20.c文件中下面幾個符號未定義:
CAPI_GET_FLAGS
CAPI_SET_FLAGS
CAPI_CLR_FLAGS
CAPI_NCCI_GETUNIT
CAPI_NCCI_OPENCOUNT
對應(yīng)的一段源代碼為:
int
capi20ext_get_flags(unsigned ApplID, unsigned *flagsptr)
{
if (ioctl(applid2fd(ApplID), CAPI_GET_FLAGS, flagsptr) < 0)
return CapiMsgOSResourceErr;
return CapiNoError;
}
int
capi20ext_set_flags(unsigned ApplID, unsigned flags)
{
if (ioctl(applid2fd(ApplID), CAPI_SET_FLAGS, &flags) < 0)
return CapiMsgOSResourceErr;
return CapiNoError;
}
int
capi20ext_clr_flags(unsigned ApplID, unsigned flags)
{
if (ioctl(applid2fd(ApplID), CAPI_CLR_FLAGS, &flags) < 0)
return CapiMsgOSResourceErr;
return CapiNoError;
}
char *
capi20ext_get_tty_devname(unsigned applid, unsigned ncci, char *buf, size_t size)
{
int unit;
unit = ioctl(applid2fd(applid), CAPI_NCCI_GETUNIT, &ncci);
if (unit < 0)
return 0;
snprintf(buf, size, "/dev/capi/%d", unit);
return buf;
}
char *
capi20ext_get_raw_devname(unsigned applid, unsigned ncci, char *buf, size_t size)
{
int unit;
unit = ioctl(applid2fd(applid), CAPI_NCCI_GETUNIT, &ncci);
if (unit < 0)
return 0;
snprintf(buf, size, "/dev/capi/r%d", unit);
return buf;
}
int capi20ext_ncci_opencount(unsigned applid, unsigned ncci)
{
return ioctl(applid2fd(applid), CAPI_NCCI_OPENCOUNT, &ncci);
}
作者未定義它們,我也不知道這幾個常量該是多少,怎么辦?我從capi20/capi20.h文件中發(fā)現(xiàn),這幾個函數(shù)是" extentions functions (no standard functions)",擴展的非標準函數(shù),我猜測,這幾個函數(shù)即使功能不正確,也不會影響ISDN的使用,那么,我就可以把那幾個未定義的符號注解起來,使編譯通過。
修改源碼如下:
int
capi20ext_get_flags(unsigned ApplID, unsigned *flagsptr)
{
// if (ioctl(applid2fd(ApplID), CAPI_GET_FLAGS, flagsptr) < 0)
// return CapiMsgOSResourceErr;
return CapiNoError;
}
int
capi20ext_set_flags(unsigned ApplID, unsigned flags)
{
// if (ioctl(applid2fd(ApplID), CAPI_SET_FLAGS, &flags) < 0)
// return CapiMsgOSResourceErr;
return CapiNoError;
}
int
capi20ext_clr_flags(unsigned ApplID, unsigned flags)
{
// if (ioctl(applid2fd(ApplID), CAPI_CLR_FLAGS, &flags) < 0)
// return CapiMsgOSResourceErr;
return CapiNoError;
}
char *
capi20ext_get_tty_devname(unsigned applid, unsigned ncci, char *buf, size_t size)
{
int unit;
// unit = ioctl(applid2fd(applid), CAPI_NCCI_GETUNIT, &ncci);
if (unit < 0)
return 0;
snprintf(buf, size, "/dev/capi/%d", unit);
return buf;
}
char *
capi20ext_get_raw_devname(unsigned applid, unsigned ncci, char *buf, size_t size)
{
int unit;
// unit = ioctl(applid2fd(applid), CAPI_NCCI_GETUNIT, &ncci);
if (unit < 0)
return 0;
snprintf(buf, size, "/dev/capi/r%d", unit);
return buf;
}
int capi20ext_ncci_opencount(unsigned applid, unsigned ncci)
{
// return ioctl(applid2fd(applid), CAPI_NCCI_OPENCOUNT, &ncci);
return 0;
}
再次編譯:
make
通過了,接著安裝:
make install
命令完成后,isdnctrl和ipppd被拷到/sbin目錄下。
3、 撥號配置
我看了一些別人寫的介紹文章,取用他們寫好的例子,修改其中的電話號碼,用戶名等必須修改的相關(guān)內(nèi)容,然后運行。不幸的是,通常都不能成功。因為這些例子都比較完善而復(fù)雜,因此難免和我的配置情況不符合而出錯。我決定從簡單入手,只進行最基本最必要的配置,先不寫成shell文件,而是一條命令一條命令地輸入執(zhí)行,仔細理解其意義,查看其執(zhí)行結(jié)果。等全部試驗成功后,再寫成shell文件?,F(xiàn)在看來,這種做法非常有效,我會同樣來處理類似的問題。
echo 1 > /proc/sys/net/ipv4/ip_dynaddr
撥號上網(wǎng)大部分都是使用動態(tài)IP地址,比如我上163網(wǎng),只知道撥打163號碼,并不知道遠程服務(wù)器(即中國電信機房內(nèi)的163撥號服務(wù)器)的IP地址是多少,也不知道它會給我的機器分配什么IP地址。往/proc/sys/net/ipv4/ip_dynaddr中寫入"1",就是告訴內(nèi)核要使用動態(tài)IP地址。
modprobe hisax type=36 protocol=2
裝入ISDN卡的驅(qū)動程序。前面已經(jīng)說過,上海貝爾SBT6021型ISDN內(nèi)置卡中使用的芯片W6692是由HiSax驅(qū)動程序驅(qū)動的,type=36指明了是使用W6692芯片,protocol=2指明了ISDN協(xié)議是用DSS1,具體內(nèi)容可看/usr/src/linux/Documentation/isdn/README.HiSax文件。
isdnctrl addif ippp0
ISDN通過同步PPP方式上網(wǎng),其對應(yīng)的Interface會是/dev/ippp0, /dev/ippp1, ...等。這條命令告訴內(nèi)核,加入ippp0這個Interface,換句話說,告訴內(nèi)核我有個ISDN設(shè)備,預(yù)備通過同步PPP方式上網(wǎng)。從此以后,ippp0就代表了我的ISDN設(shè)備。
isdnctrl addphone ippp0 out 163
指明撥出的電話號碼,我撥出的是163,在中國大陸,通過中國電信上網(wǎng)的大部分也都是163。
isdnctrl eaz ippp0 3382460
指明我自己這臺ISDN的電話號碼為3382460。