February 14, 2014

Linux AF_PACKET raw socket incoming and outgoing

In Linux, one use socket(family, type, protocol) to create a socket.  Some tips about raw socket:

1. To capture packets with Ethernet header, use family AF_PACKET

2. PF_PACKET is the same as AF_PACKET. Actually PF_* is the same as AF_*. AF_ prefix is the new way of calling them. (Address Family)

3. When using PF_PACKET,  type can either be SOCK_RAW or SOCK_DGRAM

4. protocol can be ETH_P_IP, ETH_P_ALL, etc. The complete list is under Linux source tree include/uapi/linux/if_ether.h

5. IMPORTANT ETH_P_ALL captures all incoming and outgoing packets. Other protocols only capture incoming packets. (See this question: http://stackoverflow.com/questions/20864962/does-capturing-outgoing-frames-using-linux-raw-socket-requires-eth-p-all)

Also remember to bind the raw socket to the particular network interface. Man 7 af_packet for details.


  1. I am unable to intercept the outgoing packet despite using ETH_P_ALL. Can you suggest the exact steps here, please?

    This is my code:

    if ((raw_sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) {
    fprintf(stderr, "Socket error!\n");

    strncpy(interface_request.ifr_name, dev, IFNAMSIZ);

    /* get the current lags the device */
    if (ioctl(sock_fd, SIOCGIFFLAGS, &interface_request) == -1) {
    fprintf(stderr, "Unable to get the interface index!\n");
    return DR_IOCTL_FAILED;

    /* set the old flags with promiscuous mode */
    interface_request.ifr_flags |= IFF_PROMISC;
    if (ioctl(sock_fd, SIOCSIFFLAGS, &interface_request) == -1) {
    fprintf(stderr, "Unable to set the promiscuous mode!\n");
    return DR_IOCTL_FAILED;

    if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof opt)
    == -1) {
    fprintf(stderr, "Unable to set the reuse address!\n");

    /* configure the device */
    if (ioctl(sock_fd, SIOCGIFINDEX, &interface_request) == -1) {
    fprintf(stderr, "Unable to get the interface index!\n");
    return DR_IOCTL_FAILED;
    interface_idx = interface_request.ifr_ifindex;
    fprintf(stderr, "Index: %d\n", interface_idx);

    sock_addr.sll_family = AF_PACKET;
    //sock_addr.sll_protocol = htons(0x800);
    sock_addr.sll_protocol = htons(ETH_P_ALL);
    sock_addr.sll_ifindex = interface_idx;

    if (bind(sock_fd, (struct sockaddr*) &sock_addr, sizeof(sock_addr)) < 0) {
    printf("Unable to bind!");
    return DR_BIND_FAILED;

  2. I suggest you ask on the stackoverflow page. I think you will get more help there.