質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.51%

  • C

    3684questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • FreeBSD

    79questions

    FreeBSDは、Unix系のオープンソースのOSです。PC/AT互換機用ですが、他のプラットフォームにも移植されています。優れたネットワーク・セキュリティ・ストレージ機能で人気のOSです。ソースコードと共に無償で公開されており、多くの コミュニティによって長年に渡って開発されています。

bind()の引数が無効であるというエラーについて

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 297

ts13331

score 1

「ルータ自作でわかるパケットの流れ」小俣光之著を参考にパケットキャプチャを作成しています。この本ではLinux(CentOS 5.5)を使用しているみたいなのですが、私はFreeBSDを用いています。そのため、変更箇所が多数あり、やっとエラーメッセージが出なくなり実行する段階まで進みました。
ソースコードは以下の4つありますが、ここではpcap.c、analyze.c、print.cの3つを掲載します。また、字数の関係で、この質問に無関係な関数等は端折って掲載します。
・pcap.c(キャプチャのメイン処理)
・analyze.c(パケットを解析する)
・print.c(内容表用関数を記述)
・checksum.c(チェックサムをチェックする)

/* pcap.c */
int InitRawSocket(char *device, int promiscFlag, int ipOnly)
{
struct ifreq    ifreq;
struct sockaddr_ll      sa;
int soc;
        if(ipOnly){
                if((soc=socket(AF_INET6,SOCK_RAW,ETHERTYPE_IP)) < 0){
                        perror("socket");
                        return(-1);
                }
        }
        else{
                if((soc=socket(AF_INET6,SOCK_RAW,0)) < 0){
                        perror("socket");
                        return(-1);
                }
        }

        memset(&ifreq,0,sizeof(struct ifreq));
        strncpy(ifreq.ifr_name,device,sizeof(ifreq.ifr_name)-1);
        if(ioctl(soc,SIOCGIFINDEX,&ifreq) < 0){
                perror("ioctl");
                close(soc);
                return(-1);
        }
        sa.sll_protocol=0;
        if(ipOnly){
                sa.sll_protocol=ETHERTYPE_IP;
        }
        else{
                sa.sll_protocol=0;
        }
        sa.sll_ifindex=ifreq.ifr_index;
        if(bind(soc,(struct sockaddr *)&sa,sizeof(sa)) < 0){
                perror("bind");
                close(soc);
                return(-1);
         }

        if(promiscFlag){
                if(ioctl(soc,SIOCGIFFLAGS,&ifreq) < 0){
                        perror("ioctl");
                        close(soc);
                        return(-1);
}
                ifreq.ifr_flags=ifreq.ifr_flags|IFF_PROMISC;
                if(ioctl(soc,SIOCSIFFLAGS,&ifreq) < 0){
                        perror("ioctl");
                        close(soc);
                        return(-1);
                }
        }
        return(soc);
}

int main(int argc,char *argv[],char *envp[])
{
int     soc,size;
u_char  buf[65535];

        if(argc <= 1){
                fprintf(stderr,"pcap device-name\n");
                return(1);
        }

        if((soc=InitRawSocket(argv[1],0,0)) == -1){
                fprintf(stderr,"InitRawSocket:error:%s\n",argv[1]);
                return(-1);
        }

        while(1){
                if((size=read(soc,buf,sizeof(buf))) <= 0){
                        perror("read");
                }else{
                        AnalyzePacket(buf,size);
                }
        }
        close(soc);
        return(0);
}
/* analyze.c */
#ifndef ETHERTYPE_IPV6
#define ETHERTYPE_IPV6  0x86dd
#endif

int AnalyzePacket(u_char *data,int size)
{
u_char  *ptr;
int     lest;
struct  ether_header    *eh;

        ptr=data;
        lest=size;

        if(lest<sizeof(struct ether_header)){
                fprintf(stderr,"lest(%d)<sizeof(struct ether_header)\n",lest);
                return(-1);
        }
        eh=(struct ether_header *)ptr;
        ptr+=sizeof(struct ether_header);
        lest-=sizeof(struct ether_header);

        if(ntohs(eh->ether_type) == ETHERTYPE_ARP){
                fprintf(stderr,"Packet[%dbytes]\n",size);
                PrintEtherHeader(eh,stdout);
                AnalyzeArp(ptr,lest);
        }else if(ntohs(eh->ether_type) == ETHERTYPE_IP){
                fprintf(stderr,"Packet[%dbytes]\n",size);
                PrintEtherHeader(eh,stdout);
                AnalyzeIp(ptr,lest);
        }else if(ntohs(eh->ether_type) == ETHERTYPE_IPV6){
                fprintf(stderr,"Packet[%dbytes]\n",size);
                PrintEtherHeader(eh,stdout);
                AnalyzeIpv6(ptr,lest);
        }
        return(0);
}
/* print.c */
#ifndef ETHERTYPE_IPV6
#define ETHERTYPE_IPV6  0x86dd
#endif

char *my_ether_ntoa_r(u_char *hwaddr,char *buf,socklen_t size)
{
        snprintf(buf,size,"%02x:%02x:%02x:%02x:%02x:%02x",hwaddr[0],hwaddr[1],hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5]);
        return(buf);
}

char *arp_ip2str(uint8_t *ip,char *buf,socklen_t size)
{
        snprintf(buf,size,"%u.%u.%u.%u",ip[0],ip[1],ip[2],ip[3]);
        return(buf);
}

char *ip_ip2str(uint32_t ip,char *buf,socklen_t size)
{
struct in_addr          *addr;

        addr = (struct in_addr *)&ip;
        inet_ntop(AF_INET,addr,buf,size);

        return(buf);
}

int PrintEtherHeader(struct ether_header *eh,FILE *fp)
{
char    buf[80];
        fprintf(fp,"ether_header *------------------------------\n");
        fprintf(fp,"ether_dhost=%s\n",my_ether_ntoa_r(eh->ether_dhost,buf,sizeof(buf)));
        fprintf(fp,"ether_shost=%s\n",my_ether_ntoa_r(eh->ether_shost,buf,sizeof(buf)));
        fprintf(fp,"ether_type=%02X",ntohs(eh->ether_type));
        switch(ntohs(eh->ether_type)){
                case    ETHERTYPE_IP:
                        fprintf(fp,"(IP)\n");
                        break;
                case    ETHERTYPE_IPV6:
                        fprintf(fp,"(IPv6)\n");
                        break;
                case    ETHERTYPE_ARP:
                        fprintf(fp,"(ARP)\n");
                        break;
                default:
                        fprintf(fp,"(unknown)\n");
                        break;
        }

        return(0);
}

int PrintArp(struct ether_arp *arp,FILE *fp)
{
static char *hrd[]={
        "From KA9Q: NET/ROM pseudo",
        "Ethernet 10/100Mbps.",
        "Experimental Ethernet.",
        "AX.25 Level 2.",
        "PROnet token ring.",
        "Chaosnet.",
        "IEEE 802.2 Ethernet/TR/TB.",
        "ARCnet.",
        "APPLEtalk.",
        "undefine",
        "undefine",
        "undefine",
        "undefine",
        "undefine",
        "undefine",
        "Frame Relay DLCI.",
        "undefine",
        "undefine",
        "undefine",
        "ATM.",
        "undefine",
        "undefine",
        "undefine",
        "Metricom STRIP (new IANA id)."
};

static char *op[]={
        "undefined",
        "ARP request.",
        "ARP reply.",
        "RARP request.",
        "RARP reply.",
        "undefined",
        "undefined",
        "undefined",
        "Metricom STRIP (new IANA id)"
};

char    buf[80];

        fprintf(fp,"arp------------------------------\n");
        fprintf(fp,"arp_hrd=%u",ntohs(arp->arp_hrd));
        if(ntohs(arp->arp_hrd)<=23){
                fprintf(fp,"(%s),",hrd[ntohs(arp->arp_hrd)]);
        }
        else{
                fprintf(fp,"(undefined),");
        }
        fprintf(fp,"arp_pro=%u",ntohs(arp->arp_pro));
        switch(ntohs(arp->arp_pro)){
                case    ETHERTYPE_IP:
                        fprintf(fp,"(IP)\n");
                        break;
                case    ETHERTYPE_ARP:
                        fprintf(fp,"(Address resolution)\n");
                        break;
                case    ETHERTYPE_REVARP:
                        fprintf(fp,"(Reverse ARP)\n");
                        break;
                case    ETHERTYPE_IPV6:
                        fprintf(fp,"(IPv6)\n");
                        break;
                default:
                        fprintf(fp,"(unknown)\n");
                        break;
        }
        fprintf(fp,"arp_hln=%u,",arp->arp_hln);
        fprintf(fp,"arp_pln=%u,",arp->arp_pln);
        fprintf(fp,"arp_op=%u",ntohs(arp->arp_op));
        if(ntohs(arp->arp_op)<=10){
                fprintf(fp,"(%s)\n",op[ntohs(arp->arp_op)]);
        }
        else{
                fprintf(fp,"(undefine)\n");
        }
        fprintf(fp,"arp_sha=%s\n",
               my_ether_ntoa_r(arp->arp_sha,buf,sizeof(buf)));
        fprintf(fp,"arp_spa=%s\n",arp_ip2str(arp->arp_spa,buf,sizeof(buf)));
        fprintf(fp,"arp_tha=%s\n",
               my_ether_ntoa_r(arp->arp_tha,buf,sizeof(buf)));
        fprintf(fp,"arp_tpa=%s\n",arp_ip2str(arp->arp_tpa,buf,sizeof(buf)));
        return(0);
}

int PrintIpHeader(struct ip *iphdr,u_char *option,int optionLen,FILE *fp)
{
int     i;
char    buf[80];

        fprintf(fp,"ip------------------------------\n");
        fprintf(fp,"version=%u,",iphdr->ip_v);
        fprintf(fp,"ihl=%u,",iphdr->ip_hl);
        fprintf(fp,"tos=%x,",ntohs(iphdr->ip_tos));
        fprintf(fp,"tot_len=%u,",ntohs(iphdr->ip_len));
        fprintf(fp,"id=%u\n",ntohs(iphdr->ip_id));
        fprintf(fp,"frag_off=%x,%u,",
        (ntohs(iphdr->ip_off)>>13)&0x07,ntohs(iphdr->ip_off)&0x1FFF);
        fprintf(fp,"ttl=%u,",iphdr->ip_ttl);
        fprintf(fp,"protocol=%u",iphdr->ip_p);
        if(iphdr->ip_p<=17){
                fprintf(fp,"(%s),",Proto[iphdr->ip_p]);
        }
        else{
                fprintf(fp,"(undefined),");
        }
        fprintf(fp,"check=%x\n",iphdr->ip_sum);
        fprintf(fp,"SourceAddress=%s,",
             ip_ip2str(iphdr->ip_src.s_addr,buf,sizeof(buf)));
        fprintf(fp,"DesrAddress=%s\n",
             ip_ip2str(iphdr->ip_dst.s_addr,buf,sizeof(buf)));
        if(optionLen>0){
                fprintf(fp,"option:");
                for(i=0;i<optionLen;i++){
                        if(i!=0){
                                fprintf(fp,":%02x",option[i]);
                        }
                        else{
                                fprintf(fp,"%02x",option[i]);
                        }
                }
        }

        return(0);
}

そして現在プログラムを実行した結果が以下のようになっています。

% ./pcap em0
bind: Invalid argument
InitRawSocket:error:em0

pcap.cファイルのInitRawSocket()関数内でsocket()関数を使用している箇所があるのですが、元は第1引数に'PF_PACKET'と指定されていたのですが、FreeBSDでは定義されていなかったため、とりあえず'AF_INET6'に変更しました。ここが原因であるかは不明ですが、もし違っていればご指摘願います。
その他諸々、間違い箇所があれば一緒にご指摘宜しくお願いいたします。

※checksum.cはあまり関係ないかなと思い、省略しています。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

struct ifreq    ifreq;
struct sockaddr_ll      sa;
int soc;
        if(ipOnly){
                if((soc=socket(AF_INET6,SOCK_RAW,ETHERTYPE_IP)) < 0){
                        perror("socket");
                        return(-1);
                }
        }
        else{
                if((soc=socket(AF_INET6,SOCK_RAW,0)) < 0){
                        perror("socket");
                        return(-1);
                }
        }


で「AF_INET6」を使用するのは IPv6 です。
IPv6 を使用するのであれば sockaddr_ll も  sockaddr_in6 になるかと思います。

とりあえずは AF_INET6 は間違いと思われます。

/usr/include/pcap

というディレクトリがありますので、その下の .h を熟読されてはいかがでしょうか。

補足)
下記のページに Linux と BSD の違いについての記載があります。
BSD 系では socket ではなくopen、read、write を使うようです。

BPFとLinuxでのL2インターフェースを扱うネットワークプログラミングでの違いについて

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/22 21:43 編集

    回答ありがとうございます。
    質問なのですが、Linuxで使用される’PF_PACKET’と同じような働きをするものはFreeBSDでは存在しないのでしょうか?
    ディレクトリの方、参考にして見たいと思います!教えていただきありがとうございます。

    キャンセル

  • 2018/01/23 08:30

    参考になりそうなサイトを補足で書いておきました。

    キャンセル

  • 2018/01/23 11:05

    ありがとうございます!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.51%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C

    3684questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • FreeBSD

    79questions

    FreeBSDは、Unix系のオープンソースのOSです。PC/AT互換機用ですが、他のプラットフォームにも移植されています。優れたネットワーク・セキュリティ・ストレージ機能で人気のOSです。ソースコードと共に無償で公開されており、多くの コミュニティによって長年に渡って開発されています。