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