Strange RAW Socket on Mac OS X
Asked Answered
M

2

14

When i run a simple packet sniffer coded in C on my Mac OS X, i got no output at all, this is a strange thing! can someone help me to understand what going on.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(void) {
   int i, recv_length, sockfd;

   u_char buffer[9000];

   if ((sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP)) == -1) {
        printf("Socket failed!!\n");

        return -1;
   }

   for(i=0; i < 3; i++) {
      recv_length = recv(sockfd, buffer, 8000, 0);
      printf("Got some bytes : %d\n", recv_length);
   }

   return 0;
}

I compile it and run it on my box and nothing is going:

MacOsxBox:Desktop evariste$sudo ./simpleSniffer

Thanks for your help.

Marceline answered 29/7, 2011 at 20:23 Comment(1)
You may have better luck using libpcap for this instead of trying to open a raw socket directly.Cuspid
I
18

This will not work on *BSD (including OSX/Darwin). See the investigation here for more details:

b. FreeBSD
**********

FreeBSD takes another approach. It *never* passes TCP or UDP packets to raw
sockets. Such packets need to be read directly at the datalink layer by using
libraries like libpcap or the bpf API. It also *never* passes any fragmented 
datagram. Each datagram has to be completeley reassembled before it is passed
to a raw socket.
FreeBSD passes to a raw socket:
    a) every IP datagram with a protocol field that is not registered in
    the kernel
    b) all IGMP packets after kernel finishes processing them
    c) all ICMP packets (except echo request, timestamp request and address
    mask request) after kernel finishes processes them

Moral of the story: use libpcap for this. It will make your life much easier. (If you use MacPorts, do sudo port install libpcap.)

Imphal answered 30/7, 2011 at 1:53 Comment(4)
Thanks for this answer. For the lpcap i used it before and it works fine. I was just investigating why this simple raw socket work on linux and not on Mac OS X and now i got the confirmation. Thanks.Marceline
Why is the moral to use libpcap? There are some great examples out there (if you'll keep digging, you'll find at least some) that explain how to use Berkeley Packet Filters etc.: vankuik.nl bastion.rieck.ru Actually, I prefer to use BPF over libpcap. You don't need to learn the API; instead, you can proceed as one normally would.Yanez
This is a good point; perhaps my conclusion was too strongly-worded. I recommended using libpcap since it's generally available on all platforms and would make your code more portable. But if you want to go low-level for performance reasons or otherwise, I say go for it!Imphal
"But if you want to go low-level" Note that, in this case, "go low-level" means "use BPF directly rather than having libpcap do it for you"; the mechanism libpcap uses on macOS, the *BSDs, AIX, and Solaris 11 is BPF.Partisan
S
0

I run it and get:

# ./a.out
Got some bytes : 176
Got some bytes : 168
Got some bytes : 168
# 

I'm guessing it's going to be something really odd, like you don't have permission to open a socket and stderr is redirected oddly.

I'd suggest the good old-fashioned wolf-trap debugging:

   printf("I got ti 1\n");
   if ((sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP)) == -1) {
        printf("Socket failed!!\n");

        return -1;
   }
   printf("I got to 2\n");
   for(i=0; i < 3; i++) {
      printf("About to read socket.\n");
      recv_length = recv(sockfd, buffer, 8000, 0);
      printf("Got some bytes : %d\n", recv_length);
   }
   printf("Past the for loop.\n");

...and see what it says.

Schoolteacher answered 29/7, 2011 at 22:14 Comment(1)
Thanks Charlie, do you run it on MacOsX or Linux (cause on linux it's OK). It seems that it stopps on the while loop! i added the old printf debug to the code (thanks :-) and got just : About to read socket. Strange thing on this mac box i have all permissions on the desktop.Marceline

© 2022 - 2024 — McMap. All rights reserved.