我一直在用C编写一些套接字代码.我需要修改数据包头并控制它们的发送方式,所以我采用了原始套接字方法.但是,我写的代码不能在BSD系统上编译(Mac OS X/Darwin,FreeBSD等)
我已经对此进行了大量研究,并发现BSD系统无法像Linux(甚至Windows)那样处理原始套接字.从我读过的内容来看,似乎我需要使用bpf(berkley数据包过滤器),但我无法弄清楚bpf是如何工作的,或者我将如何使用原始套接字.
如果有人能对这一点有所了解,我会非常兴奋:D
PS我甚至会对一些显示如何在BSD环境中处理原始套接字的源代码感到满意.它不一定是指导或解释.我只想看看它是如何工作的.
使用原始套接字并不难,但它不是完全可移植的.例如,无论是在BSD还是在Linux中,您都可以发送任何您想要的内容,但在BSD中,您无法接收任何具有处理程序的内容(如TCP
和UDP
).
这是一个发送一个示例程序SYN
.
#include#include #include #include #include #include #include #include #include #include int main(int argc, char *argv[]) { int s, rc; struct protoent *p; struct sockaddr_in sin; struct tcphdr tcp; if (argc != 2) errx(EX_USAGE, "%s addr", argv[0]); memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = 0; /* Parse command line address. */ if (inet_pton(AF_INET, argv[1], &sin.sin_addr) <= 0) err(EX_USAGE, "Parse address"); /* Look up tcp although it's 6. */ p = getprotobyname("tcp"); if (p == NULL) err(EX_UNAVAILABLE, "getprotobyname"); /* Make a new shiny (Firefly) socket. */ s = socket(AF_INET, SOCK_RAW, p->p_proto); if (s < 0) err(EX_OSERR, "socket"); memset(&tcp, 0, sizeof(tcp)); /* Fill in some random stuff. */ tcp.th_sport = htons(4567); tcp.th_dport = htons(80); tcp.th_seq = 4; /* Chosen by fair dice roll. */ tcp.th_ack = 0; tcp.th_off = 5; tcp.th_flags = TH_SYN; tcp.th_win = htonl(65535); rc = sendto(s, &tcp, sizeof(tcp), 0, (struct sockaddr *)&sin, sizeof(sin)); printf("Wrote %d bytes\n", rc); return 0; }
当然,可以使用更多特定于BSD的解决方案.例如,您可以使用它divert(4)
来拦截数据包,因为它们遍历您的系统并更改它们.