8    Tru64 UNIX における STREAMS とソケットの共存

この章では,ifnet STREAMS モジュールと,dlb STREAMS 擬似ドライバの通信ブリッジについて説明します。 この章は,STREAMS とソケットの基本的な概念に習熟しており,第 4 章および第 5 章の内容を理解していることが前提となっています。

オペレーティング・システムのネットワーク・プログラミング環境は,ネットワーク・プログラミング用に,STREAMS およびソケットの両方のフレームワークをサポートしています。 ただし,この 2 つのフレームワーク間には,データ・リンク層における固有の通信パスはありません。 共存という用語は,ソケットと STREAMS のフレームワーク間で,データを交換できることを指します。 通信ブリッジという用語は,2 つのフレームワークがデータ・リンク層でデータを交換できるようにするソフトウェア (ifnet STREAMS モジュールまたは dlb STREAMS 擬似ドライバ) を指します。

ソケットおよび STREAMS に合わせて作成されたプログラムは,次の理由から相互通信をしなければなりません。

8.1    STREAMS ドライバからソケット・プロトコル・スタックへのブリッジ

ifnet STREAMS モジュールは,通信ブリッジです。 これによって,STREAMS ネットワーク・ドライバは,ソケット・ベースのネットワーク・プロトコルにアクセスできます。 ifnet STREAMS モジュールは,他の STREAMS モジュールと同様に機能し,STREAMS デバイス・ドライバの上にあるストリーム上にプッシュされます。 一度,ストリーム上にプッシュされると,このモジュールは,STREAMS ドライバの DLPI インタフェースと BSD ifnet 層との間で必要なすべての変換処理を行います。 ifnet STREAMS モジュールは,標準の STREAMS インタフェースと,ifnet 層インタフェースの両方をエクスポートします。

また,STREAMSネットワーク・ドライバも,ifnet STREAMS モジュールを使用している間は,STREAMS ベースのネットワーク・プロトコルの使用を継続することができます。

図 8-1 は,ifnet STREAMS モジュールを強調表示して,ネットワーク・プログラミング環境における位置付けを示しています。

図 8-1:  ifnet STREAMS モジュール

8.1.1    STREAMS ドライバ

この項では,STREAMS ドライバを実行して ifnet STREAMS モジュールを使用するシステムを準備する方法について説明します。

注意

ifnet STREAMS モジュールは,イーサネット STREAMS デバイス・ドライバだけをサポートします。

また,この項には,ifnet STREAMS モジュールを正常に操作するために,STREAMS ドライバがサポートしなければならない DLPI プリミティブの一覧も記載します。

8.1.1.1    ifnet STREAMS モジュールの使用

デバイス・ドライバが,8.1.1.2 項に示すプリミティブをサポートする場合には,ifnet STREAMS モジュールを使用するために,ドライバまたは STREAMS カーネル・コードのいずれもソース・コードを変更する必要はありません。

ifnet STREAMS モジュールを使用するためには,STRIFNET および DLPI オプションをカーネル構成ファイルに追加し,ドライバに対して STREAMS をセットアップする必要があります。

STRIFNET および DLPI は,インストール時にシステムに組み込むことができます (オプションの構成については,『インストレーション・ガイド』を参照)。 オプションが構成されているかどうかは,次のコマンドで調べることができます。

# /usr/sbin/strsetup -c
 

ifnet あるいは dlb が名前の欄に表示されれば,それらのオプションはカーネルに組み込まれています。 組み込まれていない場合は,doconfig コマンドを使用してそれらを組み込む必要があります。

STRIFNET および DLPI をカーネルに組み込むには,次の手順に従います。

  1. スーパユーザとしてログインする。

  2. /usr/sbin/doconfig コマンドを入力する。

    構成ファイルをカスタマイズしている場合は /usr/sbin/doconfig -c コマンドを使用します。 詳細については, doconfig(8) を参照してください。

  3. カーネル構成ファイルの名前を入力する。

    この名前は,大文字のシステム名です。 通常,省略時の値が大カッコ ([]) の中に表示されます。 次に例を示します。

    Enter a name for the kernel configuration file. [HOST1]: [RETURN]
     
    

  4. システム構成ファイルを置き換えるかどうかのプロンプトに対して,y を入力する。

    A configuration file with the name 'HOST1' already exists.
    Do you want to replace it? (y/n) [n]: y
     
    Saving /sys/conf/HOST1 as /sys/conf/HOST1.bck
     
    *** KERNEL CONFIGURATION AND BUILD PROCEDURE ***
     
    

  5. カーネルに組み込むオプションをメニューから選択する。

    注意

    STRIFNET および DLPI オプションは,メニューからは選択できません。 これらのオプションを組み込むには,以下の手順で構成ファイルを編集する必要があります。

  6. カーネル構成ファイルのオプション・セクションに DLPI および STRIFNET を追加する。

    カーネル構成ファイルを編集するかどうかを尋ねられたら,y を入力する。

    doconfig コマンドでは,ed エディタを使用して構成ファイルを編集できます。 ed エディタの使用方法についての詳細は, ed(1) を参照してください。

    次の例は,ed 編集セッションで,DLPI オプションおよび STRIFNET オプションを host1 用のカーネル構成ファイルに追加する方法を示しています。 新しい行を追加する行番号は,カーネル構成ファイルによって異なる場合があります。

    Do you want to edit the configuration file? (y/n) [n]: y
     
    Using ed to edit the configuration file.  Press return when ready,
    or type 'quit' to skip the editing session: 
    2153
     
    48a
    options         DLPI
    options         STRIFNET
    .
    1,$w
    2185
    q
     
    *** PERFORMING KERNEL BUILD ***
     
    

  7. 新しいカーネルが構築された後,そのカーネルを,doconfig が置いたディレクトリからルート・ディレクトリ (/) に移動して,システムをリブートする。

    リブートすると,strsetup -i コマンドが自動的に実行され,新しい STREAMS モジュールに対してデバイス特殊ファイルが作成されます。

  8. strsetup -c コマンドを実行して,デバイスが正しく構成されたことを確認する。

    次の例は,strsetup -c コマンドからの出力を示しています。

    # /usr/sbin/strsetup -c
    STREAMS Configuration Information...Thu Nov  9 08:38:17 1995
     
               Name       Type   Major  Module ID
               ----       ----   -----  ---------
              clone                 32          0
                dlb     device      52       5010
               dlpi     device      53        800
              kinfo     device      54       5020
                log     device      55         44
               nuls     device      56       5001
               echo     device      57       5000
                sad     device      58         45
               pipe     device      59       5304
           xtisoUDP     device      60       5010
           xtisoTCP     device      61       5010
          xtisoUDP+     device      62       5010
           xtisoTCP+     device      63       5010
                ptm     device      64       7609
                pts     device       6       7608
                bba     device      65      24880
                lat     device       5          5
              pppif     module               6002
           pppasync     module               6000
            pppcomp     module               6001
            bufcall     module                  0
              ifnet     module               5501
               null     module               5002
               pass     module               5003
               errm     module               5003
               ptem     module               5003
              spass     module               5007
             rspass     module               5008
            pipemod     module               5303
              timod     module               5006
             tirdwr     module                  0
              ldtty     module               7701
     
            Configured devices = 16, modules = 15
     
    

カーネルの再構成または doconfig コマンドについての詳細は,『システム管理ガイド』および doconfig(8) を参照してください。

ドライバ用にストリームをセットアップするには,次の手順に従ってください。

  1. 次のようなアプリケーション・プログラムを作成する。

    /*
     * Application program to set up the "pifnet" streams for IP
     * and ARP. This must be run prior to ifconfig
     */
    #include <stdio.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <stropts.h>
    #include <sys/ioctl.h>
    #include <signal.h>
    #include "dlpihdr.h"
     
    #define IP_PROTOCOL             0x800
    #define ARP_PROTOCOL            0x806
    #define PIFNET_IOCTL_UNIT       1236
     
    main(argc, argv)
            int argc;
            char *argv[];
    {
            extern char *getenv();
            char *p;
            short unit = 0;
            char devName[256];
     
            if (argc != 3) usage();
            strcpy(devName, argv[1]);
            unit = atoi(argv[2]);
     
            sigignore(SIGHUP);
            setupStream(devName, unit, IP_PROTOCOL);
            setupStream(devName, unit, ARP_PROTOCOL);
     
            /*
             * sleep forever to keep the Streams alive.
             */
            if (fork())  /* detach */
                exit();
            pause();
    }
     
    usage()
    {
           fprintf(stderr, "usage: pifnetd devname unit-number\n");
           exit(1);
    }
     
    setupStream(devName, unit, serviceClass)
      char *devName;
      short unit;
      u_long serviceClass;
    {
            int fd, status;
            dl_bind_req_t bindreq;
            dl_bind_ack_t bindack;
            int flags;
            struct strioctl str;
            struct strbuf pstrbufctl, pstrbufdata, gstrbufctl, \
                                                   gstrbufdata;
            char ebuf[256];
     
            /*
             * build the stream
             */
            fd = open(devName, O_RDWR, 0);
            if (fd < 0)
            {
                    sprintf(ebuf, " open '%s' failed", devName);
                    perror(ebuf);
                    exit(1);
            }
            if (ioctl(fd, I_PUSH, "ifnet") < 0)
            {
                    sprintf(ebuf, " ioctl I_PUSH failed");
                    perror(ebuf);
                    exit(1);
            }
     
            /*
             * tell pifnet the unit number for the device
             */
            str.ic_cmd = PIFNET_IOCTL_UNIT;
            str.ic_timout = 15;
            str.ic_len = sizeof (short);
            str.ic_dp = (char *) &unit;
            status = ioctl(fd, I_STR, &str);
            if (status < 0)
            {
                    sprintf(ebuf, " %s - ioctl");
                    perror(ebuf);
                    exit(1);
            }
     
            /*
             * bind the stream to a protocol
             */
            bindreq.dl_primitive = DL_BIND_REQ;
            bindreq.dl_sap = serviceClass;
            bindreq.dl_max_conind = 0;
            bindreq.dl_service_mode = DL_CLDLS;
            bindreq.dl_conn_mgmt = 0;
            bindreq.dl_xidtest_flg = 0;
            pstrbufctl.len = sizeof(dl_bind_req_t);
            pstrbufctl.buf = (void *)&bindreq;
     
            pstrbufdata.buf = (char *)0;
            pstrbufdata.len = -1;
            pstrbufdata.maxlen = 0;
     
            status = putmsg(fd, &pstrbufctl, (struct strbuf *)0, 0);
            if (status < 0)
            {
                    perror("putmsg");
                    exit(1);
            }
     
            /*
             * Check requested binding
             */
            gstrbufctl.buf = (char *)&bindack;
            gstrbufctl.maxlen = sizeof(dl_bind_ack_t);
            gstrbufctl.len = 0;
            status = getmsg(fd, &gstrbufctl, (struct strbuf *)0, &flags);
            if (status < 0)
            {
                    perror("getmsg");
                    exit(1);
            }
     
            if (bindack.dl_primitive != DL_BIND_ACK)
            {
                    errno = EPROTO;
                    perror(" DL_BIND_ACK");
                    exit(1);
            }
    }
     
     
    

    このアプリケーション例では,ドライバの名前は /dev/streams/ln です。 このアプリケーションは,2 つのストリームを作成します。 1 つはインターネット・プロトコル (IP) 用であり,もう 1 つはアドレス解決プロトコル (ARP) 用です。 ストリームをセットアップした後,このアプリケーションは,ストリームを保持しておくために,pause コマンドを使用して,実行を継続しなければなりません。

    ドライバがスタイル 2 のドライバの場合には,アプリケーション・プログラムに DL_ATTACH_REQ プリミティブを追加しなければなりません。 DL_ATTACH_REQ プリミティブまたはスタイル 2 のドライバについての詳細は,/usr/share/doclib/dlpi/dlpi.ps の DLPI 仕様を参照してください。

  2. アプリケーションの実行可能ファイルを生成する。

    エラーなしで実行できるまで,プログラムをコンパイル,リンク,およびデバッグします。

  3. ユーザに都合のよいディレクトリに,実行可能プログラムを移動する。

    実行可能プログラムは,どのディレクトリにもいれることができます。

  4. このプログラムを呼び出す行を,/sbin/init.d/inet ファイルに追加する。

    このプログラムは,リブートするたびに手動で起動できます。 ただし,/sbin/init.d/inet ファイルに 1 行追加して,システムのリブート時に自動的に実行させると非常に便利です。 この行は必ず,システムの ifconfig 行より前に追加してください。

    次の例では,システムがリブートするたびに,/sbin/init.d/inet ファイルは,/etc ディレクトリにある run_ifnet というプログラムを実行します。


    .
    .
    .
    # # Enable network # case $1 in   echo "Configuring network" /sbin/hostname $HOSTNAME echo "hostname: \c" /sbin/hostname if [ "$NETDEV_0" != '' ]; then echo >/tmp/ifconfig_"$NETDEV_0".tmp # place command invoking executable BEFORE \ ifconfig lines /etc/run_ifnet /sbin/ifconfig $NETDEV_0 $IFCONFIG_0 > \ /tmp/ifconfig_"$NETDEV_0".tmp 2>&1 if [ $? != 0 ]; then ERROR=`cat /tmp/ifconfig_"$NETDEV_0".tmp` if [ "$ERROR" = "$ERRSTRING" ]; then /sbin/ifconfig $NETDEV_0 up else echo "$0: $ERROR" fi fi rm /tmp/ifconfig_"$NETDEV_0".tmp fi
    .
    .
    .

  5. システムをリブートする。

    /usr/sbin/shutdown -r コマンドを使用して,システムをシャットダウンし,自動的にリブートさせます。 次に例を示します。

    # /usr/sbin/shutdown -r now
     
    

8.1.1.2    データ・リンク・プロバイダ・インタフェース・プリミティブ

STREAMS デバイス・ドライバは,スタイル 1 またはスタイル 2 のいずれの DLPI プロバイダでもかまいません。 これについては,/usr/share/doclib/dlpi/dlpi.ps のデータ・リンク・プロバイダ・インタフェース仕様に説明があります。 この DLPI 仕様にオンラインでアクセスするには,OSFPGMRnnn サブセットがインストールされていなければなりません。

このドライバでは,次の DLPI プリミティブをサポートしなければなりません。 これらのプリミティブとその使用方法についての詳細は,DLPI 仕様を参照してください。

DL_PHYS_ADDR_REQ/DL_PHYS_ADDR_ACK

DL_BIND_REQ/DL_BIND_ACK

DL_UNBIND_REQ

DL_UNITDATA_REQ/DL_UNITDATA_IND/DL_UDERROR_IND

DL_OK_ACK/DL_ERROR_ACK

8.2    BSD ドライバから STREAMS プロトコル・スタックへのブリッジ

dlb STREAMS 擬似デバイス・ドライバによって,BSD スタイルのデバイス・ドライバと,STREAMS プロトコル・スタックをブリッジできます。 STREAMS 擬似デバイス・ドライバは,BSD ベースのドライバとの通信を必要としている,ストリーム内のストリーム・エンドです。 このオペレーティング・システムで提供されている STREAMS 擬似デバイス・ドライバには,2 つのインタフェースがあります。 1 つは,STREAMS プロトコル・スタックと通信する DLPI インタフェースのサブセットであり,もう 1 つは,ソケット・フレームワークの ifnet 層インタフェースにアクセスするインタフェースです。

図 8-2 は,dlb STREAMS 擬似ドライバを強調表示して,ネットワーク・プログラミング環境における位置付けを示しています。

図 8-2:  DLPI STREAMS 擬似ドライバ

8.2.1    サポートする DLPI プリミティブおよびメディア・タイプ

dlb STREAMS 擬似ドライバは,次のコネクションレス・モードのプリミティブとメディア・タイプをサポートします。 これらのプリミティブ,およびその使用方法についての詳細は,/usr/share/doclib/dlpi/dlpi.ps のデータ・リンク・プロバイダ・インタフェース仕様を参照してください。

DL_ATTACH_REQ/DL_DETACH_REQ/DL_OK_ACK

DL_BIND_REQ/DL_BIND_ACK/DL_UNBIND_REQ

DL_ENABMULTI_REQ/DL_DISABLMULTI_REQ

DL_PROMISCON_REQ/DL_PROMISCONOFF_REQ

DL_PHYS_ADDR_REQ/DL_PHYS_ADDR_ACK

DL_SET_PHYS_ADDR_REQ

DL_UNITDATA_REQ/DL_UNITDATA_IND

DL_SUBS_BIND_REQ/DL_SUBS_BIND_ACK

DL_SUBS_UNBIND_REQ/DL_SUBS_UNBIND_ACK

イーサネット・バス (DL_ETHER) は,STREAMS 擬似ドライバがサポートするメディア・タイプです。

8.2.2    STREAMS 擬似ドライバの使用

dlb STREAMS 擬似ドライバを使用するには,DLPI オプションをカーネルに組み込まなければなりません。 DLPI オプションは,インストレーション時にシステムに組み込まれている場合もあります。

DLPI オプションが組み込まれているかどうかを調べるには,次のコマンドを実行します。

# /usr/sbin/strsetup -c
 

名前の欄に dlb が表示されれば,このオプションはカーネルに組み込まれています。 表示されない場合は,doconfig コマンドで追加する必要があります。

doconfig コマンドを使用してカーネルを再構成する方法については,8.1.1.1 項を参照してください。

カーネルの再構成の方法,および doconfig コマンドについての詳細は,『システム管理ガイド』および doconfig(8) を参照してください。 インストール時のオプションの構成については,『インストレーション・ガイド』を参照してください。