1
我有看似簡單的任務,即打印有關通過特定以太網接口的幀的非常基本的信息。我有一個插座定義爲解析以太網幀和數據類型
if ((sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) return __LINE__;
strcpy(ifr.ifr_name, argv[1]);
if (ioctl(sd, SIOCGIFFLAGS, &ifr) == -1) return __LINE__;
ifr.ifr_flags |= IFF_PROMISC;
if (ioctl(sd, SIOCSIFFLAGS, &ifr) == -1) return __LINE__;
if (ioctl(sd, SIOCGIFINDEX, &ifr) == -1) return __LINE__;
我環路我的輸入,像這樣
while (active) {
FD_SET(sd, &fds);
FD_SET(STDIN_FILENO, &fds);
if ((rv = select(sd + 1, &fds, NULL, NULL, &tv)) < 0)
active = 0;
if (FD_ISSET(sd, &fds)) input(sd, buf);
這是我有問題。我定義了以太網標題中的每個幀被鑄造成與struct
struct ethheader {
unsigned char dsta[6];
unsigned char srca[6];
uint16_t type;
};
並輸出信息等
void input(int sd, char *buf) {
int i;
char *p = buf;
struct ethheader *eth = (struct ethheader*)buf;
int len = read(sd, buf, BUF_SIZ);
if (len < sizeof(struct ethheader)) {
printf("smaller than an ethernet frame\n");
return;
} else {
char dst[18];
char src[18];
for (i = 0; i < 6; i++) {
sprintf(dst + i * 3, "%02x:", eth->dsta[i]);
sprintf(src + i * 3, "%02x:", eth->srca[i]);
}
dst[17] = '\0';
src[17] = '\0';
printf("dst: %s src: %s ", dst, src);
switch (eth->type) {
case 0x0800:
printf("IPv4\n");
break;
case 0x0842:
printf("ARP\n");
break;
case 0x86DD:
printf("IPv6\n");
break;
default:
printf("unknown\n");
break;
}
}
}
我接收指示我正確打印的MAC地址的輸出,我不正確檢測的協議。我很確定這個bug處理的是左值字節大小還是endian order-ness;或兩者。在這一點上,我不得不在此問一問,我可以如何更好地定義我的struct
的值,以及爲什麼我的協議switch
被破壞?
行,所以讀了一些意見之後,我能夠正確讀取以太網類型:
struct ethheader {
unsigned char dsta[6];
unsigned char srca[6];
unsigned char type[2];
};
int type = (eth->type[0] << 8) + eth->type[1];
我二次的問題是:我怎樣才能更好地定義這些struct
s的更便攜的類型;或者我很好,unsigned char
?
使用正確的序列化技術做的工作,不容易出錯和非便攜式鑄造。 – Olaf
@Olaf你會詳細解釋一下嗎? – motoku
對不起,沒有。使用搜索引擎確實是一項現在可以推測的技能。我已經給你一個關鍵字。 – Olaf