2011-09-19 18 views
11

GPSやその他の測地センサーを監視する、広く配備されているオープンソースのサービスデーモンであるGPSDを保守します。これは、IPv4とIPv6の両方でポート2947上のクライアントアプリケーション接続をリッスンします。セキュリティとプライバシーのために、通常はループバックアドレスでのみリッスンしますが、デーモンには任意のアドレスでリッスンさせるための-Gオプションがあります。CソケットAPIを使用してすべてのIPV6アドレスをリッスンする方法

問題:-GオプションはIPv4で動作しますが、IPv6で動作させる方法を理解できません。さまざまなチュートリアルの例に基づいて動作するメソッドは、代わりに、アドレスが既に使用されていることを示唆するエラーを生成しません。私は、IPv6ネットワークプログラミングで経験を積んだ人たちからこれを修正する助けを求めています。簡単には、netstat -lで検証されているよう

関連するコードは、http://git.berlios.de/cgi-bin/gitweb.cgi?p=gpsd;a=blob;f=gpsd.c;h=ee2156caf03ca23405f57f3e04e9ef306a75686f;hb=HEAD

このコードは、IPv4下-Gおよび非-G両方の場合に正しく動作です。

"case AF_INET6:"の後に398行目を見てください。 listen_globalオプションは、-Gによって設定されます。 falseの場合、コードは成功します。このように読み込み、未知の要因から継承された次のコメントは、現在のところあり:

私が見上げている様々なチュートリアルの例によると
/* else */ 
     /* BAD: sat.sa_in6.sin6_addr = in6addr_any; 
    * the simple assignment will not work (except as an initializer) 
    * because sin6_addr is an array not a simple type 
    * we could do something like this: 
    * memcpy(sat.sa_in6.sin6_addr, in6addr_any, sizeof(sin6_addr)); 
    * BUT, all zeros is IPv6 wildcard, and we just zeroed the array 
    * so really nothing to do here 
    */ 

、代入「sat.sa_in6.sin6_addr = IN6ADDR_ANY;」コメントにもかかわらず正しいですし、コンパイルします。ただし、-Gを指定して起動すると、リスンアドレスが既に使用中であると主張して失敗します。

割り当ては "sat.sa_in6.sin6_addr = in6addr_any;"ですか?名目上ここで正しい?ほかに何かがあれば、私は行方不明ですか?

+0

デーモンを酷使しようとしましたか? – jpalecek

答えて

19

アドレスがすでに使用されている理由は、多くのIPv6ネットワーキングスタックでは、デフォルトでIPv6ソケットがIPv4とIPv6の両方を同時にリッスンするためです。 IPv4接続は透過的に処理され、subset of the IPv6 spaceにマッピングされます。ただし、これは、IPv6ソケットの設定を変更することなく、IPv4ソケットと同じポート上のIPv6ソケットにバインドできないことを意味します。理にかなっている?

ただ、(これは私のプロジェクトの1から取られる)bindにお電話の前に次の操作を行います。

int on = 1; 
if (addr->sa_family == AF_INET6) { 
    r = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)); 
    if (r) 
     /* error */ 
} 

残念ながら、IPV6_V6ONLYのためのプラットフォーム間でのデフォルト値はありません - 基本的にはあなたが常にする必要があることを意味しています他のプラットフォームを気にしない限り、気にして明示的にオンまたはオフにしてください。 Linuxはデフォルトではオフのまま、Windowsはデフォルトでそれを残し...

+1

Linuxのデフォルトは実際にはsysctlからです。だからあなたはデフォルトでそれに頼ることはできません。しかし、sysadminがそれを変更していなければ、デフォルトではoffになっています。 (オフは最も合理的なデフォルトIMOです)。 –

+1

あなたの答えは正しいですし、私のバグは修正されました。ありがとうございました。 – ESR

1

ランダムLinuxシステムのファイル、in6addr_anyを含んで見た目からはそれほどのように宣言されています

だから、
extern const struct in6_addr in6addr_any;  /* :: */ 
extern const struct in6_addr in6addr_loopback; /* ::1 */ 
#define IN6ADDR_ANY_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } } 

、おそらく間近にINIT配列は、GPSDのソースにそのコメントを残した人は誰でも混乱します。実際のタイプは明確にstruct in6_addrであり、割り当て可能です。

私は周りを見回して、IPv4がすでに "any"アドレスを聴いている場合、IPv6もできないことを示唆するヒントをいくつか見つけました。おそらく、それはあなたを刺すものです。

+0

診断の第2部分は正しいです(Dietrich Eppの回答を参照)。私はあなたが最初の部分についても正しいと思う。 – ESR

関連する問題