I am developing an application (got the code from here) to show the content of network packets in OS X using C and here is my code:
/* open a divert socket */
fd=socket(AF_INET, SOCK_RAW, IPPROTO_DIVERT);
if (fd==-1) {
fprintf(stderr,"We could not open a divert socket\n");
exit(1);
}
bindPort.sin_family=AF_INET;
bindPort.sin_port=htons(5060);
bindPort.sin_addr.s_addr=0;
fprintf(stderr,"Binding a socket\n");
ret=bind(fd, (struct sockaddr *)&bindPort, sizeof(struct sockaddr_in));
if (ret!=0) {
close(fd);
fprintf(stderr, "Error bind(): %s",strerror(ret));
exit(2);
}
/* read data in */
sinlen=sizeof(struct sockaddr_in);
while (1) {
n = (int)recvfrom(fd, packet, 1514, 0, (struct sockaddr*)&sin, (socklen_t*)&sinlen);
hdr = (struct ip *) packet;
fprintf(stdout, "\n{{packet size: [%d]}}\n", htons(hdr->ip_len));fflush(stdout);
printf("The packet looks like this:\n");
for (i = 0; i < 40; i++) {
printf("%02x ", (int)*(packet + i));
if (!((i + 1) % 16))
printf("\n");
};
printf("\n");
printf("Source address: %s\n", inet_ntoa(hdr->ip_src));
printf("Destination address: %s\n", inet_ntoa(hdr->ip_dst));
printf("Receiving IF address: %s\n", inet_ntoa(sin.sin_addr));
printf("Protocol number: %i\n", hdr->ip_p);
}
Before I run the code, I run the following command:
ipfw add divert 5060 all from any to 192.168.1.34
The problem with the code is that it is not reliable. It sometimes works and sometimes does not. I have to reboot the machine and then it works (but only for a few times). Is there any other way to send the packets from kernel space to the user-space? Ultimately, I want to change the packet and re-inject them to the network flow.