2016-12-08 46 views
0

SO_BINDTODEVICEを使用してソケットをeth0にバインドしようとしています。私はeth0を変数optに渡しています。私のソケット名は、いくつかのデバッグを行うためにはsocketfdSO_BINDTODEVICEを使用してインターフェイスにトラフィックバインドがありません

sockfd = socket(AF_INET, SOCK_DGRAM, 0); 
    if(sockfd < 0) { 
     perror("socket(): error "); 
     return 0; 
    } 
    struct ifreq ifr; 

    memset(&ifr, 0, sizeof(struct ifreq)); 
    fprintf(stderr,ifr.ifr_name, sizeof(ifr.ifr_name), opt); 
    ioctl(sockfd, SIOCGIFINDEX, &ifr); 
    setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, opt, strlen(opt)); 
    fprintf(stderr, "The bind is done on interface %s \n", opt); 
    fprintf(stderr, "opt length is %zu \n", strlen(opt)); 

ですが、私はログファイルにOPTとはstrlen(OPT)の値をリダイレクトすることだし、彼らは正確な値を取得します。


/home/cayman/log.txtバインドは、長さが、私はまた、eth0のが、私ドン上のパケットをキャプチャすることにより検証を行う4

ある
OPTインターフェースeth0上で実行されますeth0を通過するトラフィックは見えません。次のように表示されているものすべてが、他のネットワーク関連のトラフィックです:

tshark -i eth0 
    1 0.000000 Cisco_51:fd:09 -> Spanning-tree-(for-bridges)_00 STP 62 Conf. Root = 32768/78/00:24:50:51:fd:00 Cost = 0 Port = 0x8009 
    2 0.326720 192.168.78.1 -> 224.0.0.13 PIMv2 70 Hello 
    3 1.030538 Cisco_51:fd:09 -> Cisco_51:fd:09 LOOP 62 Reply 
    4 2.004544 Cisco_51:fd:09 -> Spanning-tree-(for-bridges)_00 STP 62 Conf. Root = 32768/78/00:24:50:51:fd:00 Cost = 0 Port = 0x8009 
    5 3.254223 192.168.78.1 -> 224.0.0.10 EIGRP 76 Hello 
    6 4.010168 Cisco_51:fd:09 -> Spanning-tree-(for-bridges)_00 STP 62 Conf. Root = 32768/78/00:24:50:51:fd:00 Cost = 0 Port = 0x8009 
    7 6.014839 Cisco_51:fd:09 -> Spanning-tree-(for-bridges)_00 STP 62 Conf. Root = 32768/78/00:24:50:51:fd:00 Cost = 0 Port = 0x8009 
    8 7.896252 192.168.78.1 -> 224.0.0.10 EIGRP 76 Hello 
    9 8.023003 Cisco_51:fd:09 -> Spanning-tree-(for-bridges)_00 STP 62 Conf. Root = 32768/78/00:24:50:51:fd:00 Cost = 0 Port = 0x8009 

は私もthis threadに見ていたと私は私がスーパーユーザーとして私のコードを実行していることを確認しました。 SO_BINDTODEVICEのman pageも見ましたが、何が欠落しているのかわかりません。何か提案してください?

+0

私は不思議です:どうしてソケットをeth0にバインドしていますか? –

+0

私はUDPリダイレクト機能を実装しています。フロントエンド(eth0/eth1)のユーザーの入力に応じて、バックエンドはソケットをバインドしてトラフィックのリダイレクトを行います –

答えて

0

あなたが行っているほとんどの呼び出しの戻りコードはチェックしていません。それらの1つ以上が追加情報を明らかにする方法で失敗する可能性があります。エラーの戻り値を(常に)チェックする必要があります。

編集:私はあなたのコードにエラー処理を追加しました:

#include <sys/socket.h> 
#include <stdio.h> 
#include <sys/ioctl.h> 
#include <net/if.h> 
#include <string.h> 

int main() { 
    const char* opt = "wlp4s0"; 
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0); 
    if(sockfd < 0) { 
    perror("socket(): error "); 
    return 1; 
    } 
    struct ifreq ifr; 

    memset(&ifr, 0, sizeof(struct ifreq)); 
    fprintf(stderr,ifr.ifr_name, sizeof(ifr.ifr_name), opt); 
    if (ioctl(sockfd, SIOCGIFINDEX, &ifr) < 0) { 
    perror("ioctl(): error "); 
    return 2; 
    } 
    if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, opt, strlen(opt)) > 0) { 
    perror("setsockopt(): error "); 
    return 3; 
    } 
    fprintf(stderr, "The bind is done on interface %s \n", opt); 
    fprintf(stderr, "opt length is %zu \n", strlen(opt)); 
} 

をそしてioctl()が失敗しました。その後、あなたがifr.ifr_nameを初期化していないことに気付きました。 optifr.ifr_nameにコピーすると、問題は解決しますか?

+0

助けてくれてありがとう。はい、ifr。ifr_nameが初期化されていません。それが問題を解決しました! –

0

最初のfprintf()ステートメントが間違っています。 optの値をstderrに正しく出力していないため、SIOCGIFINDEXを呼び出す前にoptifr.ifr_nameにまったくコピーしていません。

代わりに、より多くのこのような何かを試してみてください:

if (strlen(opt) >= sizeof(ifr.ifr_name)) { 
    fprintf(stderr, "%s", "interface name is too long \n"); 
    return 0; 
} 

... 

struct ifreq ifr; 
memset(&ifr, 0, sizeof(struct ifreq)); 
strncpy(ifr.ifr_name, opt, sizeof(ifr.ifr_name)); 

if (ioctl(sockfd, SIOCGIFINDEX, &ifr) < 0) { 
    perror("ioctl(): error "); 
    close(sockfd); 
    return 0; 
} 

は言われていることGet the index number of a Linux network interface in C using SIOCGIFINDEX

を参照してください、あなたはインターフェイス名にバインドしようとしている場合SO_BINDTODEVICEを呼び出す前SIOCGIFINDEXを使用する必要はありません。ただ、それ自体でSO_BINDTODEVICEを呼び出す:

sockfd = socket(AF_INET, SOCK_DGRAM, 0); 
if (sockfd < 0) { 
    perror("socket(): error "); 
    return 0; 
} 

if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, opt, strlen(opt)) < 0) { 
    perror("setsockopt(): error "); 
    close(sockfd); 
    return 0; 
} 

このコンテキストでは意味がありませんSIOCGIFINDEXを使用します。 SIOCGIFADDRを使用してインターフェイスのIPアドレス(Get the IP address of a network interface in C using SIOCGIFADDRを参照)を取得し、SO_BINDTODEVICEにインターフェイス名を渡すのではなく、そのIPをbind()に渡すと意味があります。

関連する問題