3

I am trying to achieve this goal on Linux (not sure if it is possible and how if so): I need to write a program to intercept all IP packets on an interface, and deliver this packet to a specific set of user-space programs. By intercept I mean, an IP packet is captured by my program (maybe a kernel module or a special user-space program), then this packet does not go through IP stack anymore. For example, let's say the OS is running a lot of processes (either in kernel-space or user-space), A, B, C, D..., etc. If an IP packet is received at an interface, say eth2, I only want A,B sees this packet, and all other processes do even know the existence of this packet. Can someone put me into the right direction? Thanks a lot!

user2975098
  • 115
  • 1
  • 7

1 Answers1

3

What I suggest is that you re-examine if it's really necessary to intercept packets in the way you describe. This sounds like you have not completely understood, as pointed above, how networking works.

First of all unless your programs somehow magically manage to read raw network packets instead of using standard sockets, they're not receiving traffic destined to each other anyway. Each socket has a port associated with it and only one process can bind onto same port in the same host (the socket actually being nothing more than a pair of a port and a host address).

In case you're actually reading raw network packets in your programs and this is necessary, you most likely should not be running them on the same host. Instead use virtualization to put programs which aren't allowed to see packets destined to each other in different virtual hosts and thus separate them completely instead of using a rather complex programmatic solution.

If everything else fails, you might want to take a good look at libpcap which allows you to capture network packets, even from several programs simultaneously. Albeit you'd have to run those as root but that's necessary anyway for being able to put a network interface into promiscuous mode and so on and so fort. Here is a simple example for reading little something from the network, you can find plenty more from libpcap homepage and associated

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

/* IP header (from tcpdump examples) */
struct sniff_ip {
    u_char ip_vhl;          /* version << 4 | header length >> 2 */
    u_char ip_tos;          /* type of service */
    u_short ip_len;         /* total length */
    u_short ip_id;          /* identification */
    u_short ip_off;         /* fragment offset field */
    u_char ip_ttl;          /* time to live */
    u_char ip_p;            /* protocol */
    u_short ip_sum;         /* checksum */
    struct in_addr ip_src, ip_dst;  /* source and dest address */
};

/* callback function for pcap_loop */
void cllbck(u_char * args,
        const struct pcap_pkthdr *hdr, const u_char * pkt)
{
    const struct sniff_ip *ip = (struct sniff_ip *) (pkt + 14);

    fprintf(stderr, "Sniffed a packet with length %d.\n", hdr->len);
    fprintf(stderr, "IP version %d.\n", ip->ip_vhl >> 4);
}

int main(int argc, char *argv[])
{
    char *dev;                  /* device name */
    char errbuf[PCAP_ERRBUF_SIZE];      /* buffer for libpcap errmsgs */
    pcap_t *cap;                /* libpcap capture session */
    char *filt = "host 127.0.0.1";      /* capture filter */
    struct bpf_program fp;      /* compiled filter */
    struct pcap_pkthdr hdr;     /* packet header from libpcap */
    const u_char *pkt;          /* packet from libpcap */

    dev = strdup(argv[1]);
    if (dev == NULL) {
        fprintf(stderr, "Invalid device.\n");
        return 2;
    }

    /* open the device for live capture */
    cap = pcap_open_live(dev, BUFSIZ, 1, 1000, errbuf);
    if (cap == NULL) {
        fprintf(stderr, "Opening device `%s´ failed: %s\n", dev, errbuf);
        return 2;
    }

    /* compile the capture filter */
    if (pcap_compile(cap, &fp, filt, 0, PCAP_NETMASK_UNKNOWN) < 0) {
        fprintf(stderr, "Failed to parse filter `%s´: %s\n",
                filt, pcap_geterr(cap));
        return 2;
    }
    /* set the filter active for this session */
    if (pcap_setfilter(cap, &fp) == -1) {
        fprintf(stderr, "Couldn't install filter %s: %s\n",
                filt, pcap_geterr(cap));
        return 2;
    }

    /* pcap close will loop until an error if 2nd arg is < 0 */
    pcap_loop(cap, -1, cllbck, NULL);

    /* end session, pcap_loop has exited ie. an error has occurred */
    pcap_close(cap);

    return 0;
}

/* end of file */