Linux ISDN
Installation and Configuration


The Kernel

Once upon a time there was the 1.2.13 kernel, which was included in the most distributions. This kernel did a poor job for i4l, when no ISDN drivers existed in the kernel code. So i4l users mostly used 1.3.x, the so-called "hacker kernels".

These days you should take a kernel version 1.3.97 or younger (there are kernel internal drivers available since kernel 1.3.69, but this thing only is stable enough since 1.3.97).

Now, while kernel 2.0 is released, we will talk about this kernel. You should look for the kernel at your SunSite, e.g. at

  ftp.leo.org/pub/comp/os/linux/Linus/v2.0/linux-2.0.7.tar.gz
and you also should fetch the new modules package:
  ftp.leo.org/pub/comp/os/linux/Linus/v2.0/modules-2.0.0.tar.gz
Handle the kernel as you are used to - have a look at the kernel-HOWTO:
  ftp.leo.org/pub/comp/os/linux/sunsite/docs/HOWTO/Kernel-HOWTO.gz
You should decompree your modules and install them as described in the Kernel-HOWTO.

You don't need to apply a patch to this kernel (only kernel 2.0.0 needed the two patches isdn4kernel-2.0-patch1+2).

You must set now the following items while "make config" or its graphical relatives "make menuconfig" or "make xconfig":

Code maturity level options":
  Prompt for development and/or incomplete code/drivers: Yes
Section "General Setup":
  Networking support: Yes
Section "Networking options":
  TCP/IP networking: Yes
  all other items are up to you
Section "Network device support":
  Network device support: Yes
  PPP (point-to-point) support: Yes  
  all other items are up to you
Section "ISDN subsystem":
  ISDN support: Yes
  Support synchronous PPP: Yes (!)
  Use VJ compression with synchronous PPP: Yes
  Support audio via ISDN: Yes
  Support generic MP (RFC 1717): Yes
  Mark your own PC card here, too.
If this kernel later works properly you could think about defining some of the parts of it to modules instead of using a monolithic kernel.

ISDN Driver Software

You also need the active version of Fritz Elfert's "isdn4kernel utilities":
  ftp.franken.de/pub/isdn4linux/isdn4k-utils-2.0.tar.gz
Put it into the /usr/src directory and unpack it by "tar zxfv isdn4k-utils-2.0.tar.gz". Now in the directory
  /usr/src/isdn4k-utils-2.0
you find all the files you need to operate i4l. At first the programs need to be built. You do this by typing in "make", create the ISDN device files by "make devices" and finally install all executables by "make install" in the /sbin directory (also the man pages where they need to be).

You also need to define the card parameters - please read the ISDN4Linux manual

  /usr/src/linux/Documentation/isdn/README
These parameters will be set while booting or while loading the i4l modules.

Now you have finished the base installation.

Configuration

Hint:
There are some large script files following. They are downloadable within this tutorial package - just click onto the script headlines!

Configuration files

To keep configuration simple, two central configuration file are used for all script files described here: /etc/i4l.config contains data about the provider, /etc/i4l.param contains personal data (because of this you must secure this file using chmod 700 /etc/i4l.param!!!). /etc/i4l.config may remain readable worldwide, but must be defined executable for root: chmod 744 /etc/i4l.config

You can load down a database with ready-to-use configuration files for several universities and other providers. It is simple to create a new file - you could load down a template or cut the proper section out of the database.

This file defines some environment variables, which are used in the scripts described here. Perhaps I will later write a script which is able to change all required files out of i4l.config and i4l.param - but this is difficult. Yet you have to edit all the files in /etc yourself.

By the way: I would be pleased to get the configuration file for your provider - just mail it!

Example file (for my provider, the Leibniz-Rechenzentrum in Munich):

  #!/bin/sh
  # i4l.config 
  # (c) 1996 Bernhard Hailer (GNU GPL V.2)

  # Please send your completed file to Bernhard.Hailer@lrz.uni-muenchen.de.
  # Thank you!

  # Provider: Leibniz-Rechenzentrum Muenchen
  # Hotline: (089) 289-28800
  # Data collected: Bernhard Hailer <dl4mhk@lrz.uni-muenchen.de>

  # Telephone numbers for raw terminal programs: 
  # 08928057421, 0892805601

  # Add here data of first provider
  PROV1_PHONE=0892881010              # phone number of provider
  PROV1_NAME=ppp.lrz-muenchen.de      # name of provider
  PROV1_IP=129.187.24.253             # IP address of provider

  # Add here data of second provider
  # (leave empty, if there is none)
  PROV2_PHONE=0892881190              # phone number of provider
  PROV2_NAME=ppp.lrz-muenchen.de      # name of provider
  PROV2_IP=129.187.24.126             # IP address of provider

  # Name servers (add manually to /etc/resolv.conf): 
  #  search lrz-muenchen.de 
  #  nameserver 129.187.10.25, 129.187.16.1

  # Mail server (add manually to /etc/hosts): 
  #  129.187.13.48	sunmailhost.lrz-muenchen.de	getmail

  # News server (add manually to /etc/hosts): 
  #  129.187.13.48	news.lrz-muenchen.de		getnews
The file i4l.param looks like (example):
/etc/i4l.param
  #!/bin/sh
  # /etc/i4l.param Bernhard Hailer 1996

  # ATTENTION! This file contains PASSWORDS and other security belonging data.
  # It MUST be hidden using "chmod 700 /etc/i4l.param"!!!!!

  # used in /sbin/init.d/rc.isdn
  MY_PHONE=8178*****                     # no leading zero!
  MY_DOMAIN=dl4mhk.ampr.org              # my fully qualified domain name

  PROV1_LOGIN=                           # not used currently
  PROV1_PASSWD=                          # not used currently

  PROV2_LOGIN=                           # not used currently
  PROV2_PASSWD=                          # not used currently

  # used in /sbin/transmail
  MAIL_LOGIN=********
  MAIL_PASSWD=********
  MAIL_PATH=/var/spool/mail/dl4mhk       # dl4mhk is my user name at home

  NEWS_LOGIN=                            # not used currently
  NEWS_PASSWD=                           # not used currently

What Happens While Booting

There are two possibilities Linux may boot. One is simpleinit (e.g. Slackware), the other one (more complicated, but also more flexible) is sysvinit (S.u.S.E. 4.2, Debian, Caldera, Red Hat...). These two need different linking of the ISDN startup scripts.

simpleinit

simpleinit has its startup scripts in /etc/rc.d/. There are some single scripts. Important for us are the files rc.M (calls some startup scripts) and rc.6 (reboot script). In this directory we set a new file named rc.isdn, which starts up the ISDN system.

You must create this file. Before this you must add the following to /etc/rc.d/rc.M, because this new file must be known by the booting system:

/etc/rc.d/rc.M, section "# Initialize the NET subsystem."
  . /etc/rc.d/rc.inet1
  . /etc/rc.d/rc.isdn               # <-- add this line!
  . /etc/rc.d/rc.inet2
Now we'll create /etc/rc.d/rc.isdn. This is described shortly after the following chapter, where it is told how the sysvinit works.

sysvinit

Under sysvinit the start-up is completely different. Here the scripts are in the directory /sbin/init.d/, /etc/init.d or /etc/rc.d/. The scripts do have two functionalities: called with the argument "start" it starts up a part of the system, called with the argument "stop" it shuts down. This whole thing works with so-called "run levels"; level 0 is "system halt", level 1 is "single user mode", level 2 is "multi user mode without network", level 3 is "multi user mode with network", and level 6 is running shutdown. The system calls the first three levels one after the other while startup (using "start"). In run level 6 they are called vice versa (using "stop").

This sequence is a bit "tricky": a "master script" looks into the directory of the run level (./rc1.d, ./rc2.d, ./rc3.d and so on) what to do. Therein are a lot of soft links to the scripts I wrote above. All links are named

  SnnScriptName
or
  KnnScriptName
with a number nn, which tells the master script in which order it has to call these scripts. So if we create a script - let's call it rc.isdn (in the scripts directory - attention! SuSE uses a file named i4l!) again -, we must also set two links in the runlevel 2 directory ./rc2.d:
  root:# cd /sbin/init.d/rc2.d  # (please verify path!!)
  root:# ln -s ../rc.isdn K20rc.isdn
  root:# ln -s ../rc.isdn S20rc.isdn
  root:# _

System Start and Stop

Now here the file(s) you need for simpleinit or for sysvinit. The following is written for sysvinit, but you easily can extract the simpleinit files (look at the comments!).
/sbin/init.d/rc.isdn
  #!/bin/sh
  # rc.isdn   This shell script boots up the ISDN subsystem.
  # Version:  @(#)/sbin/init.d/rc.isdn  3.0   01-Sep-96
  # Author:   Bernhard Hailer <Bernhard.Hailer@lrz.uni-muenchen.de>

  . /etc/i4l.config
  . /etc/i4l.param

  case "$1" in
    start)

# === The following is /etc/rc.d/rc.isdn for "simpleinit"! =================
      # turn on isdn
      echo "Starting isdn4linux"
      echo "0" >/etc/lines.active          # makes it more comfortable.

      # global
      /sbin/isdnctrl verbose 0             # For debugging set to 2 (max. 4)

      # ISDN device drivers ippp0 (PPP)
      /sbin/isdnctrl addif      ippp0
      /sbin/isdnctrl addphone   ippp0 out $PROV1_PHONE  # 1st provider
      /sbin/isdnctrl addphone   ippp0 in $MY_PHONE  # my telephone no
      /sbin/isdnctrl eaz        ippp0 $MY_EAZ       # my MSN / EAZ
      /sbin/isdnctrl huptimeout ippp0 300           # 5 min
      /sbin/isdnctrl secure     ippp0 on            # nobody may entry

      /sbin/isdnctrl l2_prot    ippp0 hdlc
      /sbin/isdnctrl l3_prot    ippp0 trans
      /sbin/isdnctrl encap      ippp0 syncppp

      /sbin/ifconfig ippp0 $MY_DOMAIN pointopoint prvdr0 metric 1
      /sbin/route add default ippp0                 # interface definitions
      /sbin/ipppd remotename prvdr0 /dev/ippp0 &

      # Now delete Route again to prevent unwanted connections - see chapter
      # "Running". The route must be set at the beginning!
      /sbin/route del default


      # ISDN device drivers ippp1 (PPP)
      # Same again for 2nd provider (not necessary if no 2nd server!)
      /sbin/isdnctrl addif      ippp1
      /sbin/isdnctrl addphone   ippp1 out $PROV2_PHONE
      /sbin/isdnctrl addphone   ippp1 in $MY_PHONE
      /sbin/isdnctrl eaz        ippp1 $MY_EAZ
      /sbin/isdnctrl huptimeout ippp1 300
      /sbin/isdnctrl secure     ippp1 on

      /sbin/isdnctrl l2_prot    ippp1 hdlc
      /sbin/isdnctrl l3_prot    ippp1 trans
      /sbin/isdnctrl encap      ippp1 syncppp

      /sbin/ifconfig ippp1 $MY_DOMAIN pointopoint prvdr1 metric 1
      /sbin/route add default   ippp1
      /sbin/ipppd remotename prvdr1 /dev/ippp1 &

      /sbin/route del default


      # ISDN device driver isdn0 (no PPP)    #  Option: VT100 connection
      /sbin/isdnctrl addif isdn0             #  with terminal program
      /sbin/isdnctrl huptimeout isdn0 300    #  via /dev/ttyI0
# === Until here /etc/rc.d/rc.isdn for "simpleinit"! ======================

      ;;
    stop)
      ## turn off isdn

# === Put this to the beginning of the "rc.6" file for "simpleinit": ======
      echo "Shutting down isdn4linux..."
      /sbin/ifconfig ippp0 down
      /sbin/isdnctrl delif ippp0
      /sbin/ifconfig ippp1 down
      /sbin/isdnctrl delif ippp1
      /sbin/ifconfig isdn0 down
      /sbin/isdnctrl delif isdn0
# === Until here! =========================================================

      ;;
    *)
      echo "Usage: $0 {start|stop}"
              exit 1
      ;;
  esac
By the way: We don't call the standard PPP daemon pppd 2.2.0[ef] here, but an especially patched version named "ipppd". This pppd is part of the ISDN4Linux package and is set while installation to /sbin. Anyway the PPP HOWTO and the pppd manpage is valid. The devices ippp0 and ippp1 are not used simultaneously. If the connection via ippp0 fails (rare situation), then the one via ippp1 should work.

Just one remark to the last few lines: here is a device isdn0 defined, which allows simple terminal operation without PPP. Terminal programs like "minicom" or "seyon" can use this device via /dev/cui0 using these AT commands:

  at&eyyyyy                         (yyyyy: my MSN or EAZ)
  atdnumber for raw terminal programs
You may use now the host computer, do a telnet to other computers or so. Of course you could write a small script for that.

More Files

To get this stuff working you must edit the following files as root:
/etc/ppp/options (options file for the ipppd)
  user <your LRZ login>  #  your user name at the provider
  ipcp-accept-local      #  accept IP suggestion of provider for your computer
  ipcp-accept-remote     #  accept IP suggestion of provider for the host
  noipdefault            #  we don't require any fixed IP
  useifip                #  accept IP address from network interface
  -vjccomp               #  switch off VJ compression of connection ID
  -ac                    #  switch off compression of address/control field
  -pc                    #  switch off compression of protocol field
  -bsdcomp               #  switch off BSD compression (ipppd can't handle it)
  -vj                    #  no Van Jacobson compression - see below!
  mru 1024               #  Maximum Receive Unit
  debug                  #  ATTENTION! Transmitted passwords are also logged -
                         #    you MUST secure the involved files by
                         #    "chmod 600 <file>"!
  -detach                #  process may not go into background
Remark to option "-vj": If you don't define this option the system may get very angry. X Window sessions simply may hang, while common vt100 sessions may show some "kernel oopses". You may especially see the line "Aiee, killing interrupt handler".
/etc/resolv.conf:
  domain <my.own.domain.name>
  nameserver <1st nameserver>
  nameserver <2nd nameserver>
  nameserver <3rd nameserver>

/etc/hosts:
  # For loopbacking.
  127.0.0.1       localhost
  # My own IP address
  192.168.1.1     machine.name                alias    # or your own IP address
  # (192.168.x.x is free, you always may use it!)
  # Rest of the World
  IP.1st.provider name.of.1st.provider        prvdr0    # 1st provider
  IP.2nd.provider name.of.2nd.provider        prvdr1    # 2nd provider
  
  129.187.10.22   sun3.lrz-muenchen.de        sun3     # (example)
  129.187.13.48   sunmailhost.lrz-muenchen.de sunmail  # for email
  129.187.13.3    mailhost.lrz-muenchen.de    lrzmail  # (see chapter 6.1.!)

/etc/networks (no need to change)
  loopback        127.0.0.0
  localnet        127.0.0.0                   #  or your own network

Authentification

You must authentificate yourself at the provider if you use PPP. Therefore two methods exist: PAP (Password Authentification Protocol) and CHAP (Challenge Authentification Protocol). PAP is widely used, but CHAP offers the provider more security. The secrets are in the file /etc/ppp/pap-secrets or /etc/ppp/chap-secrets. Attention! The/etc/ppp/pap-secrets file contains passwords and must be secured in any cases against unauthorized access!
  root:# chmod 600 /etc/ppp/pap-secrets (or /etc/ppp/chap-secrets)
  root:# _

PAP

/etc/ppp/pap-secrets
  # Secrets for authentification using PAP
  # client          server           secret          IP addresses
  <provider_login>  <1st provider>   <password>      -
  <provider_login>  <2nd provider>   <password>      -

CHAP

Providers don't know your fully qualified hostname in most cases. So you have to rename your machine to the same name as your login at your provider - don't use a domain. But you can do it a more elegant way: give "name <provider_login>" as option while calling the ipppd (or make an entry in /etc/ppp/options). Instead of /etc/ppp/pap-secrets you must create a file /etc/ppp/chap-secrets like this (please note: there are two lines required per provider entry!):
/etc/ppp/chap-secrets
  # Secrets for authentification using PAP
  # client          server           secret          IP addresses
  <provider_login>  <1st provider>   <password>      -
  <provider_login>  <2nd provider>   <password>      -

Some Polish

Now you should bend the PPP log to an extra file for debugging. Therefore you should edit /etc/syslog.conf and add the following line (remark: use only tabulator characters, no spaces!):
  daemon.*                      /var/log/ppp-log
With this all the stuff the PPP daemon tells is saved to /var/log/ppp-log.

Running

The system sometimes likes to connect more or less without any motivation to the provider. This is because of the nature of the system: If there is any IP packet (e.g. a name server request) Linux wants to get rid of it. Because this costs money we must switch it off. You could do it by deleting the default route, so that Linux now doesn't know any longer the way out.

The newer kernels since 1.3.100 have a something painful behavior: they set the default route automatically when a interface is defined. To prevent collisions you need to wait until a connect is completely built up (dialing, PPP handshake) before setting the default route. The following script does this. It is written so that you may call it more than once, so the first application (e.g. exchanging email) makes the connect, and the next applications don't need to open more lines. The last application cleans up: it hangs up and deletes the default route. Call this script as /sbin/isdn on und /sbin/isdn off.

/sbin/isdn
  #!/bin/sh
  # isdn:    connects to / disconnects from provider
  # Author:  Bernhard Hailer <Bernhard.Hailer@lrz.uni-muenchen.de>
  # Version: 3.0 (01-Sep-96)

  . /etc/i4l.config
  . /etc/i4l.param

  case $1 in
    on)
      declare -i con_apps                 #  line already active?
      read con_apps </etc/lines.active
      let con_apps+=1
      echo $con_apps >/etc/lines.active

      line="0"

      while [ $line!="finished" ]
      do

        if [ $con_apps -lt 2 ]
        then
          echo "Calling ippp$line"
          /sbin/isdnctrl dial ippp$line
          echo "Sleeping 8 sec for PPP handshaking..."
          sleep 8s
          /sbin/route add default ippp$line
          echo "Line open - checking..."
        else
          let con_apps-=1
          echo "Line seems to be open already $con_apps time(s) - checking..."
          let con_apps+=1
        fi

        set `ping -qc5 -i1 prvdr$line | grep transmitted`
        if [ $4 -gt 0 ];
        then
          echo "8-) Line is ok - have fun!"
          line="finished"                                   # paranoia setting
          break
        else
          /sbin/isdnctrl hangup ippp$line
          route del default
          read con_apps </etc/lines.active
          echo "0" >/etc/lines.active
          if [ $con_apps -gt 0 ]
          then
            echo ":-| Hmm, no. Trying to rebuild..."
            let con_apps=1
            echo $con_apps >/etc/lines.active
            line="0"                                        # paranoia setting
            continue
          else
            case $line in
            0)
              if [ $PROV_NAME_2 = "" ]
              then
                echo ":-[ Sorry, Line is down. Bad luck... Try later!"
                line="finished"
                echo "0" >/etc/lines.active
                con_apps=1
                break
              else
                echo ":-( Sorry, Line 0 is down. Trying second line."
                line="1"
                continue
              fi
              ;;
            1)
              echo "0" >/etc/lines.active
              con_apps=1
              echo ":-[ Sorry, Line 1 is also down. Bad luck... Try later!"
              line="finished"
              break
              ;;
            *) 
              echo "=:-0 THIS CANNOT HAPPEN. Fatal Error in script /sbin/isdn!"
              break
              ;;
            esac
          fi
        fi
      done
      ;;
    off)
      declare -i con_apps
      read con_apps </etc/lines.active

      if [ $con_apps -gt 0 ]             #  line active, indeed?
      then
        let con_apps-=1
        echo $con_apps >/etc/lines.active
        if [ $con_apps -eq 0 ]
        then
          echo "Last application stopped - closing line."
          /sbin/isdnctrl hangup ippp0
          /sbin/isdnctrl hangup ippp1
          /sbin/route del default         #  and delete route.
        else
          echo "There are $con_apps more applications running - keeping line."
        fi
      else
        echo "Hey boss, there had no line been active!"
      fi
      ;;
    *)
      echo -e "\aUsage:"
      echo "isdn on:  opens line to the provider,"
      echo "isdn off: closes line."
      ;;
  esac
Put this script to /sbin and make it executable (route may be called only by "root"!):
  root:# chmod 744 /sbin/isdn
  root:# _
Hints for more experiments:

Test:

  root:# isdn on
  Calling ippp0
  Dialing of ippp0 triggered
  Sleeping 8 sec for PPP handshaking...
  Line open - checking...
  :-) Line is ok - have fun!
  root:# telnet sun3
  [...]
(now log in as usual; later type in "exit" to finish)
  root:# isdn off
  Last application stopped - closing line.
  ippp0 hung up
  ippp1 not connected
  root:# _

More Utilities

There are some more very useful tools within the ISDN4Linux package. One is the X program "isdnmon" by Andreas Kool, wich shows the actual state of the S0 bus (free or connected).

Have a look at the README by Fritz Elfert.


Bernhard Hailer
Last modification: 02-Sep-96 BeH