- 締切済み
自作PINGプログラムで特定の機器のみプログラムが止まる
はじめまして、よろしくお願いいたします。 現在私はFreeBSD6.2上でPINGを送信するプログラムを作成していますが、 特定の機器に対してPINGを送信した場合プログラムが n = recv(sock, buf, sizeof(buf), 0); の部分で止まってしまいます。 特定の機器とは、現在私が把握している限りではAlliedTelesisのL3スイッチに 割り当てられているIPアドレスに対してPINGを送信した場合に再現します。(CentreCOM8624XL、CentreCOM8724XL) ためしにAlliedTelesisのL3スイッチにミラーポートを設定し、ICMPパケットを観察 しましたが、プログラムを動かしているPCからのICMPパケットが一切到達していませんでした。 ネットワークの設定に問題があるのではないかと考え、BSDに標準搭載のPINGではきちんと AlliedTelesisのL3スイッチへのPINGが成功しているので、やはりプログラムに問題があるとしか思えません。 どうか、お力をお貸しください。 コンパイル環境 Thread model: posix gcc version 3.4.6 [FreeBSD] 20060305 ソースコードは http://www.geekpage.jp/programming/linux-network/simple-ping.php よりFreeBSD上で動くように改良しました。 #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in_systm.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_icmp.h> unsigned short int checksum(unsigned short *buf, int bufsz) { unsigned long int sum = 0; while (bufsz > 1) { sum += *buf; buf++; bufsz -= 2; } if (bufsz == 1) { sum += *(unsigned char *)buf; } sum = (sum & 0xff) + (sum >> 16); sum = (sum & 0xff) + (sum >> 16); return ~sum; } int main(int argc, char *argv[]) { int sock; struct icmp hdr; // netinet/ip_icmp.h struct sockaddr_in addr; int n; char buf[2000]; struct icmp *icmphdrptr; // netinet/ip_icmp.h struct ip *iphdrptr; // netinet/ip.h if (argc != 2) { printf("usage : %s IPADDR\n", argv[0]); return 1; } addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr(argv[1]); sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if (sock < 0) { perror("socket"); return 1; } memset(&hdr, 0, sizeof(hdr)); hdr.icmp_type = ICMP_ECHO; hdr.icmp_code = 0; hdr.icmp_cksum = 0; hdr.icmp_id = 0; hdr.icmp_seq = 0; hdr.icmp_cksum = checksum((unsigned short *)&hdr, sizeof(hdr)); n = sendto(sock, (char *)&hdr, sizeof(hdr), 0, (struct sockaddr *)&addr, sizeof(addr)); if (n < 1) { perror("sendto"); } memset(buf, 0, sizeof(buf)); n = recv(sock, buf, sizeof(buf), 0); if (n < 1) { perror("recv"); } iphdrptr = (struct ip *)buf; icmphdrptr = (struct ip *)(buf + (iphdrptr->ip_hl * 4)); if (icmphdrptr->icmp_type == ICMP_ECHOREPLY) { printf("received ICMP ECHO REPLY\n"); } else { printf("received ICMP %d\n", icmphdrptr->icmp_type); } close(sock); return 0; }
- みんなの回答 (1)
- 専門家の回答
みんなの回答
- omomuro_z
- ベストアンサー率0% (0/0)
特定の機器で応答を返したり、返さなかったりという問題はさておいて・・ checksum()で返るICMPのチェックサムの値は正しいでしょうか? 単純にチェックサムを「0xf7ff」にすると正しく応答しませんか? #大雑把ですみません
お礼
アドバイスいただきましたチェックサムを「0xf7ff」に してみましたが、うまくいきませんでした。 しかし、omomuro_zさんからのアドバイスをヒントに、 各種変数のパラメータを弄くってみると、問題が解決いたしました。 きっかけを作っていただいてありがとうございました。 それでは、また機会がございましたらよろしくお願いいたします。 hdr.icmp_id = 0; hdr.icmp_seq = 0; の部分を hdr.icmp_id = 1; hdr.icmp_seq = 1; それと、掲載したソースコードの一部が間違っていました icmphdrptr = (struct ip *)(buf + (iphdrptr->ip_hl * 4)); の部分は icmphdrptr = (struct icmp *)(buf + (iphdrptr->ip_hl * 4)); の間違いでした、申し訳ございませんでした。
補足
omomuro_zさん、回答ありがとうございます。 現在別件で動いておりますので、明日、確認をしてみます。 申し訳ございません。