ラベル BPF (Berkeley Packet Filter) の投稿を表示しています。 すべての投稿を表示
ラベル BPF (Berkeley Packet Filter) の投稿を表示しています。 すべての投稿を表示

2011年7月29日金曜日

イメージを描画する(11.3)

bpf のフィルタを設定したい。そこで bpf(4) を見ます。オペコード、アキュームレータ、インデックスレジスタ... アセンブリ言語?疑似マシンへの命令は僕には難しすぎます。そんな僕のために libpcap は疑似マシン命令を手軽にコンパイルしてくれるということなので頼ります。

/*事前に/dev/bpf* はオープンされていて、ネットワークインターフェイス(struct ifreq ifr)がアタッチされている。*/

    char errorBuffer[PCAP_ERRBUF_SIZE];
    bpf_u_int32 mask;
    bpf_u_int32 net;

    if ((pcap_lookupnet(ifr.ifr_name, &net, &mask, errorBuffer)) == -1 ) {
        fprintf(stderr,"pcap_lookupnet:%s",errorBuffer);
        net = 0;
        mask = 0;
    }

    u_int dataLinkType;
    u_int bufferLength;

    ioctl(bpf, BIOCGDLT, &dataLinkType);
    ioctl(bpf, BIOCGBLEN, &bufferLength);

    pcap_t *tmpHandle = pcap_open_dead(dataLinkType, bufferLength);

    if (!tmpHandle) {
        fprintf(stderr,"pcap_open_dead:NULL");
    }

    struct bpf_program *bpfProgram = (struct bpf_program *)malloc(sizeof(struct bpf_program));
    const char *filterExpression = "ether proto \\ip";
    int optimize = 0;

    if (pcap_compile(tmpHandle,
                     bpfProgram,
                     filterExpression,
                     optimize,
                     mask) == -1 ) {
        fprintf(stderr,"pcap_compile:%s",pcap_geterr(tmpHandle));
    }

    pcap_close(tmpHandle);
    
    ioctl(bpf, BIOCSETF, bpfProgram);
    
    pcap_freecode(bpfProgram);

2011年7月15日金曜日

イメージを描画する(11.2)

インターフェイスと bpf デバイスファイルのアタッチ

めも
///// bpf デバイスファイルのオープン /////
    NSArray *devices;
    NSString *deviceFile = @"/dev/bpf";
    int bpf;

    [deviceFile completePathIntoString:nil
                         caseSensitive:YES
                      matchesIntoArray:&devices
                           filterTypes:nil];
      
    for (NSString *device in devices) {
        bpf = open([device UTF8String],O_RDONLY,0);
        
        if (bpf != -1 ) {
            break;
        }
    }

// 使用するネットワークインターフェイスを用意する e.g "en0"
    struct ifreq ifr;
    bzero(ifr.ifr_name, sizeof(char) * IFNAMSIZ);
    strncpy(ifr.ifr_name, argv[1], IFNAMSIZ);

// デバイスファイルとネットワークインターフェイスを接続、設定する
    u_int isImmediately = 1;
    u_int isIO = 0;             // Input only;
    u_int bufferLength = (u_int)([[NSString stringWithCString:argv[2]
                                            encoding:NSUTF8StringEncoding] intValue]

    ioctl(bpf, BIOCSBLEN, &bufferLength); // 長さ
    ioctl(bpf, BIOCSETIF, &ifr);  // 接続
    ioctl(bpf, BIOCIMMEDIATE, &isImmediately); // すぐに書出す
    ioctl(bpf, BIOCSSEESENT, &isIO); // インプットのみ
あとは read(2) でデバイスファイルから読込む。
また読込みは bpf(4) Mac OS X Man page より bpf_hdr について。
The following structure is prepended to each packet returned by read(2):
"以下の構造体(bpf_hdr)はread(2) によって戻される各パケットの先頭に追加されます。"

Additionally, individual packets are padded so that each starts on a word boundary.  This requires that an application has some knowledge of how to get from packet to packet.  The macro BPF_WORDALIGN is defined in to facilitate this process.  It rounds up its argument to the nearest word aligned value (where a word is BPF_ALIGNMENT bytes wide).
p = (char *)p + BPF_WORDALIGN(p->bh_hdrlen + p->bh_caplen)

考え中。

// kernel -> bpf デバイスファイルへのデータコピーの状態
        struct bpf_stat status;
        ioctl(bpf, BIOCGSTATS,&status);
        NSLog(@"receive:%d, drop:%d",status.bs_recv, status.bs_drop);

bs_drop: パケットトラフィックがついていっていないとカーネルがドロップする。その数。