-1

I would like to sniff packets on a particular Ethernet interface using python.

These packets are received from an FPGA and do not contain any of the usual IP headers. The only header info is the Ethernet header.

I have the following python code which reads raw packets, It's from an example I modified from here.

from socket import *

interface = "em3"

# Create socket connection
sock = socket(AF_PACKET, SOCK_RAW, htons(0x0003))
sock.bind((interface, 0)) #port number

data = sock.recv(1024)

print(data)

sock.close()

I understand that when TCP/UDP sockets are created, port numbers are reserved for use by a specific service. However, I don't know what port number to use for my application. How do I know what port number to use?

Why I'm asking:

I'm asking because the above code doesn't receive any packets from the FPGA, even though when I use tshark (sudo tshark -i em3 -w output.bin) I get two. My interface is in promiscuous mode, and now I'm checking if my port number and protocol types are correct.

stanri
  • 2,922
  • 3
  • 25
  • 43
  • If the ethernet frames do not contain IP packets (no IP headers as you claim), there will be no TCP/UDP either since TCP and UDP segments are encapsulated in IP packets. – Ron Maupin Sep 14 '15 at 17:30
  • @RonMaupin You're right - my issue is that I still need to specify a port number when I bind the interface to the socket in any case. I don't know if the port number is irrelevant (because no IP headers) or if I am binding the interface to the socket in the wrong way. – stanri Sep 14 '15 at 17:33
  • If you are skipping TCP/IP, you need to create your own protocol stack. It sounds like you are trying to use the TCP/IP protocol stack without wanting the the protocol stack. It is possible to create and use your own protocol stack, but it is non-trivial. – Ron Maupin Sep 14 '15 at 17:36
  • have you tried sniffing with wireshark. If you know the ip of your FPGA you can inspect what and on what port it sends/recieves. – RickyA Sep 14 '15 at 17:38
  • @RickyA tshark is the console version of wireshark (it has the same backend) and I receive 2 packets (as expected) using it. – stanri Sep 14 '15 at 17:39
  • @RonMaupin My intention is to dump the raw packets received from em3 in Python. I don't need any of the features in the TCP/IP stack. – stanri Sep 14 '15 at 17:40
  • @RickyA Also, the FPGA doesn't have an IP address, since there isn't a TCP/IP stack. – stanri Sep 14 '15 at 17:44
  • Port numbers, etc. are features of the TCP/IP stack. Needing to bind to a socket means that you are using the TCP/IP stack. You can snoop on all traffic, but to limit it to your specific non-TCP/IP traffic, you will need to create your own protocols. – Ron Maupin Sep 14 '15 at 17:46
  • @RonMaupin Okay, so then I'm doing it wrong. How do I snoop the interface of interest without binding it to a socket? Should I not use sockets at all? What other options are there? – stanri Sep 14 '15 at 17:50
  • What OS are you using? – Robᵩ Sep 14 '15 at 17:52
  • @Robᵩ I'm using CentOS release 6.6 (Final) – stanri Sep 14 '15 at 17:53
  • possible duplicate of [How to bind a Raw Socket to a specific port?](http://stackoverflow.com/questions/4988027/how-to-bind-a-raw-socket-to-a-specific-port) – Barmar Sep 14 '15 at 18:01
  • @Barmar, this is not a duplicate of the one you linked since the answer to that one involved IP. The Op here doesn't want to involve IP. This question needs its own protocol stack to bypass the TCP/IP protocol stack. – Ron Maupin Sep 14 '15 at 19:13
  • @RonMaupin The answer explained that you can't bind to a specific port, the only thing you can bind a raw socket to is a specific IP. Since the questions are the same, so are the answers. – Barmar Sep 15 '15 at 03:29
  • @Barmar, my point is that the OP doesn't want to use IP, so binding to IP is out. He needs his own protocol stack instead of TCP/IP. – Ron Maupin Sep 15 '15 at 03:30
  • No, he just needs to use a raw socket, parse the header, and match the port number. – Barmar Sep 15 '15 at 03:32
  • @Barmar, the raw socket will use IP. The OP specifically says that there will be no IP header in the layer-2 frame. There are layer-2 protocols that don't use IP, and there are other layer-3 protocols besides IP. These don't have IP sockets, and not all have any sort of socket. Ethernet does not always equal IP. – Ron Maupin Sep 15 '15 at 03:37
  • I see, I didn't understand the question. I don't know why he would ask about a port number when he's not using a protocol that has port numbers. – Barmar Sep 15 '15 at 03:40
  • Here's a page with a demonstration program that reads raw ethernet frames: https://gist.github.com/austinmarton/2862515 – Barmar Sep 15 '15 at 03:42
  • @Barmar, you should post an answer which contains the relevant information and link. The OP is looking to get raw ethernet frames to decode. – Ron Maupin Sep 15 '15 at 03:46
  • I frequently complain when other people post link-only answers, I'm not going to do it myself! – Barmar Sep 15 '15 at 03:47
  • @Barmar, I did it for you. – Ron Maupin Sep 15 '15 at 04:03

2 Answers2

1

austinmarton on GitHub has some code to Receive raw Ethernet frames in Linux. This is not my code, so don't ak me any questions about it, and your mileage may vary. Thanks to @Barmar for the link.

/*
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 */

#include <arpa/inet.h>
#include <linux/if_packet.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/ether.h>

#define DEST_MAC0   0x00
#define DEST_MAC1   0x00
#define DEST_MAC2   0x00
#define DEST_MAC3   0x00
#define DEST_MAC4   0x00
#define DEST_MAC5   0x00

#define ETHER_TYPE  0x0800

#define DEFAULT_IF  "eth0"
#define BUF_SIZ     1024

int main(int argc, char *argv[])
{
    char sender[INET6_ADDRSTRLEN];
    int sockfd, ret, i;
    int sockopt;
    ssize_t numbytes;
    struct ifreq ifopts;    /* set promiscuous mode */
    struct ifreq if_ip; /* get ip addr */
    struct sockaddr_storage their_addr;
    uint8_t buf[BUF_SIZ];
    char ifName[IFNAMSIZ];

    /* Get interface name */
    if (argc > 1)
        strcpy(ifName, argv[1]);
    else
        strcpy(ifName, DEFAULT_IF);

    /* Header structures */
    struct ether_header *eh = (struct ether_header *) buf;
    struct iphdr *iph = (struct iphdr *) (buf + sizeof(struct ether_header));
    struct udphdr *udph = (struct udphdr *) (buf + sizeof(struct iphdr) + sizeof(struct ether_header));

    memset(&if_ip, 0, sizeof(struct ifreq));

    /* Open PF_PACKET socket, listening for EtherType ETHER_TYPE */
    if ((sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETHER_TYPE))) == -1) {
        perror("listener: socket"); 
        return -1;
    }

    /* Set interface to promiscuous mode - do we need to do this every time? */
    strncpy(ifopts.ifr_name, ifName, IFNAMSIZ-1);
    ioctl(sockfd, SIOCGIFFLAGS, &ifopts);
    ifopts.ifr_flags |= IFF_PROMISC;
    ioctl(sockfd, SIOCSIFFLAGS, &ifopts);
    /* Allow the socket to be reused - incase connection is closed prematurely */
    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof sockopt) == -1) {
        perror("setsockopt");
        close(sockfd);
        exit(EXIT_FAILURE);
    }
    /* Bind to device */
    if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, ifName, IFNAMSIZ-1) == -1)  {
        perror("SO_BINDTODEVICE");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

repeat: printf("listener: Waiting to recvfrom...\n");
    numbytes = recvfrom(sockfd, buf, BUF_SIZ, 0, NULL, NULL);
    printf("listener: got packet %lu bytes\n", numbytes);

    /* Check the packet is for me */
    if (eh->ether_dhost[0] == DEST_MAC0 &&
            eh->ether_dhost[1] == DEST_MAC1 &&
            eh->ether_dhost[2] == DEST_MAC2 &&
            eh->ether_dhost[3] == DEST_MAC3 &&
            eh->ether_dhost[4] == DEST_MAC4 &&
            eh->ether_dhost[5] == DEST_MAC5) {
        printf("Correct destination MAC address\n");
    } else {
        printf("Wrong destination MAC: %x:%x:%x:%x:%x:%x\n",
                        eh->ether_dhost[0],
                        eh->ether_dhost[1],
                        eh->ether_dhost[2],
                        eh->ether_dhost[3],
                        eh->ether_dhost[4],
                        eh->ether_dhost[5]);
        ret = -1;
        goto done;
    }

    /* Get source IP */
    ((struct sockaddr_in *)&their_addr)->sin_addr.s_addr = iph->saddr;
    inet_ntop(AF_INET, &((struct sockaddr_in*)&their_addr)->sin_addr, sender, sizeof sender);

    /* Look up my device IP addr if possible */
    strncpy(if_ip.ifr_name, ifName, IFNAMSIZ-1);
    if (ioctl(sockfd, SIOCGIFADDR, &if_ip) >= 0) { /* if we can't check then don't */
        printf("Source IP: %s\n My IP: %s\n", sender, 
                inet_ntoa(((struct sockaddr_in *)&if_ip.ifr_addr)->sin_addr));
        /* ignore if I sent it */
        if (strcmp(sender, inet_ntoa(((struct sockaddr_in *)&if_ip.ifr_addr)->sin_addr)) == 0)  {
            printf("but I sent it :(\n");
            ret = -1;
            goto done;
        }
    }

    /* UDP payload length */
    ret = ntohs(udph->len) - sizeof(struct udphdr);

    /* Print packet */
    printf("\tData:");
    for (i=0; i<numbytes; i++) printf("%02x:", buf[i]);
    printf("\n");

done:   goto repeat;

    close(sockfd);
    return ret;
}
Ron Maupin
  • 6,180
  • 4
  • 29
  • 36
0

socket probably not going to work here, since it will use TCP/IP

you can try to use the scapy package to sniff packet from that interface. check this:

http://www.secdev.org/projects/scapy/doc/usage.html#sniffing

DorElias
  • 2,243
  • 15
  • 18