高度な検索
Developer Connection
Member Login ログイン | ご入会 ADC連絡先



NW54 - Open Transport エラー -3151 および -3160 と Option Management

(98 年 4 月 24 日)

Q: OptionManagement 関数でエンドポイントのオプションを設定しようとすると、エラー-3151 (不正なオプション) または エラー -3160 (バッファオーバーフロー) のいずれかのエラーメッセージが通知されます。このエラーを解決するには何を調べたらよいでしょうか。

A: エラー -3151 は Open Transport のエンドポイントに対して不正なオプションまたは不正なオプション値が渡されたことを示します。以下の回答はOTOptionManagement の知識を前提としています。OTOptionManagement関数の詳細については、『Inside Macintosh: Networking With Open Transport』の第 7 章「Option Management」を参照してください。このドキュメントは Open Transport の Web ページからダウンロードすることができます。

エラー -3151 の一般的な原因は次の通りです。

1. オプションの長さが正しくありません。Open Transport の Option Management オプションの値の長さはほとんど 4 バイトです。しかし、文字列や構造体の値を取るオプションもあります。TOptMgmtopt.len フィールドと TOptionHeaderlen の両方をオプション要求バッファの長さに正しく設定しなければなりません。このバッファと TOptMgmt 構造体は、Option Management からの応答を受け取るためにも使用することができますが、それについては次のエラー-3160 の説明のなかで触れます。

エラー -3151 が最も発生するのは、オプションの値が 1 バイトなのに、4 バイトの長さが指定されている場合です。ここでも同様に、長さの引数は TOptMgmt 構造体と TOptionHeader 構造体の 2 箇所に設定しなければなりません。

2. OTOptionManagement 関数で応答を受け取る TOptMgmt ポインタを渡しているのに、maxlen フィールドが正しく設定されていません。このパラメータを設定しないと、入力値によっては、エラー -3160 が発生します。「OpenTransport SDK」の OTMultiCastPitch コードのサンプルでも、IP_ADD_MEMBERSHIP オプションを設定する箇所でこの問題が発生します。正しい呼び出しは以下の通りです。

        optReq.flags = T_NEGOTIATE;
        optReq.opt.len = sizeof(optBuffer);     // バッファのサイズを指定
        optReq.opt.maxlen = sizeof(optBuffer);  // <--- この行のコードを追加
        optReq.opt.buf = (UInt8*) optBuffer;
        OTMemzero(optBuffer, sizeof(optBuffer));
        opt->level = INET_IP;
        opt->name = IP_ADD_MEMBERSHIP;
        opt->len = sizeof(optBuffer);           // オプションのサイズを指定

同じコードサンプルで、IP_MULTICAST_TTL オプションを設定する箇所でも、同様の修正が必要です。あとで変更済みのサンプルコードを掲載します。

上記の修正は「Open Transport SDK v1.3」以前の場合に該当します。

3. Open Transport v1.3 以前のバージョンを使用する際に既知の問題があります。OTOptionManagement 関数で T_ALLOPT を使って現在の IP オプション設定すべてを一度の呼び出しで取得しようとすると、このエラーが発生します。この問題は、OTMulticastPitchSample のコードを Open Transport v1.3 以前で動作させると発生します。回避方法は、現在、値が知りたいオプションだけを個別に調べることです。

エラー -3160 の一般的な原因は次の通りです。

1. TOptMgmtopt.maxlen が初期化されていないか、値が正しくありません。このエラーは、オプションのネゴシエートが成功した場合でも返されることがあります。解決方法は、maxlen フィールドを正しく設定することです。

2. Open Transport v1.3 以前のバージョンを使用する際に既知の問題があります。長さが 1 バイトか 2 バイトの TCP/IP オプションのネゴシエートで、応答バッファの長さを 4 バイトより小さい値に設定すると、Open Transport はこのエラーを返します。おもしろいことに、オプションのネゴシエート自体は成功する場合があります。この問題を回避するには、バッファサイズは kOTFourByteOptionSize に定義し直し、2 つの len フィールドは kOTOneByteOptionSize または kOTTwoByteOptionSize のままで設定することです (これを書いている時点では、2 バイトのオプション設定はありません) 。

応答パラメータが指定されていないと、エラー -3160 は返されません。一方、返り値をチェックしないと、オプション設定の呼び出しのステータスが T_SUCCESS かどうか調べることができません。この問題は、次のオプションを設定しようとする場合に発生します。

オプションレベル オプション名
INET_UDP UDP_RX_ICMP
INET_IP IP_RECVOPTS
INET_IP IP_TOS
INET_IP IP_TTL
INET_IP IP_MULTICAST_LOOP
INET_IP IP_MULTICAST_TTL
INET_IP IP_RECVDSTADDR
INET_IP IP_RECVIFADDR


OTMultiCastPitchSample.cp ファイルの変更と修正です。

修正 1: IP_MULTICAST_TTL オプション設定のためのサンプルコードの変更

        //
        //  マルチキャスト送信の Time-to-live の値の設定 (デフォルトは 1)
        //  TOptMgmt は再利用できるが、Option 自体は別。
        //  上のバッファは再利用可能だが、正確を期すため正しい方法を取る。
        //

        UInt8    ttlOptBuffer[ kOTFourByteOptionSize ]; // <-- 4 バイト長のオプションバッファ

TOption* ttlOpt = (TOption*)ttlOptBuffer; optReq.flags = T_NEGOTIATE; optReq.opt.len = kOTOneByteOptionSize; // <-- オプション長は 1 バイトのまま optReq.opt.maxlen = sizeof(ttlOptBuffer); // <-- 応答バッファの最大長を設定 optReq.opt.buf = (UInt8*) ttlOptBuffer; OTMemzero(optBuffer, sizeof(ttlOptBuffer)); ttlOpt->level = INET_IP; ttlOpt->name = IP_MULTICAST_TTL; ttlOpt->len = kOTOneByteOptionSize; // <-- オプション長は 1 バイトのまま *(char*)(ttlOpt->value) = kDefaultTTL; err = gEndpt->OptionManagement(&optReq, &optReq);
修正 2: IP_MULTICAST_LOOP オプションを設定するサンプルコードの変更

    //
    //  ループバックをオフにする - 自分で送信したパケットを受け取りたい場合はオフにしない
    //

    TOptMgmt    optReq;
    UInt8       optBuffer[ kOTFourByteOptionSize ];   // <-- 4 バイト長のオプションバッファ
    TOption*    opt = (TOption*)optBuffer;

    OTMemzero(optBuffer, sizeof(optBuffer));
    optReq.flags    = T_NEGOTIATE;
    optReq.opt.len  = kOTOneByteOptionSize;           // <-- オプション長は 1 バイトのまま

optReq.opt.maxlen = sizeof(optBuffer); // <-- 応答バッファの最大長を設定する optReq.opt.buf = (UInt8*) optBuffer; opt->level = INET_IP; opt->name = IP_MULTICAST_LOOP; opt->len = kOTOneByteOptionSize; // <-- オプション長は 1 バイトのまま *(char *)(opt->value) = gLoopbackState; err = gEndpt->OptionManagement(&optReq, &optReq);

-- Rich Kubota
devsupport@apple.com


[ Technical Q&A's : Communications & Collaboration : Networking : NW54 ]