マイペースなプログラミング日記

DTMやプログラミングにお熱なd-kamiがマイペースに書くブログ

たまには別の言語を使ってみる

最近(というかずっと)Javaばかり使っているので、別の言語を思い出すためにも使ってみた。使ったのはC言語で、作ったのは簡単なEthernet Frameのヘッダをキャプチャするプログラム。動かすためにはroot権限が必要で引数にネットワークインターフェイスを指定する。省略された場合はeth0を使うようにした。無限ループしてるので終了はCtrl+Cで。何か「基礎からわかるTCP/IPネットワーク実験プログラミング」にあったipdumpの超劣化版になったなぁ

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/socket.h>
#include <netinet/if_ether.h>

#define MAX_SIZE 1600

char* mac_ntos(char* str, u_char* addr);

int main(int argc, char** argv){
    char ifname[256];
    int s;

    if(argc == 1)
        strcpy(ifname, "eth0");
    else if(argc == 2)
        strncpy(ifname, *(argv + 1), 256);

    if((s = socket(AF_INET, SOCK_PACKET, htons(ETH_P_ALL))) < 0){
        perror("socket");
        exit(EXIT_FAILURE);
    }

    struct sockaddr sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_family = AF_INET;

    snprintf(sa.sa_data, 256, "%s", ifname);
    if(bind(s, &sa, sizeof(sa)) < 0){
        perror("bind");
        exit(EXIT_FAILURE);
    }

    char buff[MAX_SIZE];
    int length;

    struct ether_header *eth;

    while(1){
        if((length = read(s, buff, MAX_SIZE)) < 0){
            perror("read");
            exit(EXIT_FAILURE);
        }

        eth = (struct ether_header *)buff;

        char shost[18];
        char dhost[18];

        mac_ntos(shost, eth->ether_shost);
        mac_ntos(dhost, eth->ether_dhost);

        printf("Source Mac Address\n%s\n", shost);
        printf("Destination Mac Address\n%s\n", dhost);
        printf("Type\n0x%04x\n", ntohs(eth->ether_type));

        printf("\n");
    }
}

char* mac_ntos(char* str, u_char* addr){
    snprintf(str, 18, "%02x:%02x:%02x:%02x:%02x:%02x",
        addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);

    return str;
}