Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Capturing injected packets not working on Linux #1208

Open
amurzeau opened this issue Jul 24, 2023 · 2 comments
Open

Capturing injected packets not working on Linux #1208

amurzeau opened this issue Jul 24, 2023 · 2 comments
Labels

Comments

@amurzeau
Copy link

Hi,

I've found that on Linux, sent packets using pcap_sendpacket or pcap_inject are not captured by pcap_dispatch (using the same pcap instance).

I think I got the same as this older issue: #400

I encountered it while testing a Windows application that use Winpcap under wine (which implements winpcap using libpcap).

Is there a way to still enable that ?

As an alternative, opening a different pcap handle works, one handle to send packets and another different handle to receive packet.
This way, sent packets are captured by pcap_dispatch.
Maybe that's the way to go then ?

Thanks !

@infrastation
Copy link
Member

Does this reproduce without Wine?

@amurzeau
Copy link
Author

Hi,

Sorry the delay.
I've tested on Linux without Wine and I reproduce the behavior.
pcap_dispatch does not receive packets sent by pcap_inject on the same pcap_t handle.

But when using a different handle for pcap_dispatch and pcap_inject, pcap_dispatch receive injected packets.

See bellow for a test application
// This is an example program from the website www.microhowto.info
// © 2012 Graham Shaw
// Copying and distribution of this software, with or without modification,
// is permitted in any medium without royalty.
// This software is offered as-is, without any warranty.

// Purpose: to construct an ARP request and write it to an Ethernet interface
// using libpcap.
//
// See: "Send an arbitrary Ethernet frame using libpcap"
// http://www.microhowto.info/howto/send_an_arbitrary_ethernet_frame_using_libpcap.html


// Compile with gcc send_arp.c -o send_arp -lpcap

// Uncomment this to test pcap_inject using the same libpcap instance as pcap_dispatch
#define TEST_SINGLE_PCAP_INSTANCE

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pcap.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <netinet/if_ether.h>
#include <sys/ioctl.h>
#include <unistd.h>


struct frame_t {
    struct ether_header eth_header;
};

struct ether_header frame;
pcap_t* pcap;
pcap_t* pcap2;

void handler(u_char *user, const struct pcap_pkthdr *header, const u_char *data)
{
    // Write the Ethernet frame to the interface.
    const struct ether_header *data_eth = (struct ether_header*) data;
    pcap_inject(pcap2,&frame,sizeof(frame));
    printf("received packet with size: %d, ether_type: 0x%x\n", header->caplen, data_eth->ether_type);
}

int main(int argc,const char* argv[]) {
    // Get interface name and target IP address from command line.
    if (argc<2) {
        fprintf(stderr,"Usage: send_arp <interface>\nExample: send_arp eth0\n");
        exit(1);
    }
    const char* if_name=argv[1];

    const unsigned char source_mac_addr[]={0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
    const unsigned char destination_mac_addr[]={0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
    memcpy(frame.ether_shost,source_mac_addr,sizeof(frame.ether_shost));
    memcpy(frame.ether_dhost,destination_mac_addr,sizeof(frame.ether_dhost));
    frame.ether_type = 0x1234;

    // Open a PCAP packet capture descriptor for the specified interface.
    char pcap_errbuf[PCAP_ERRBUF_SIZE];
    pcap_errbuf[0]='\0';

    pcap=pcap_open_live(if_name,1514,1,1,pcap_errbuf);

#ifndef TEST_SINGLE_PCAP_INSTANCE
    // If not testing single pcap instance, use a second instance for the pcap_inject call
    pcap2=pcap_open_live(if_name,1514,1,1,pcap_errbuf);
#else
    pcap2 = pcap;
#endif

    if (pcap_errbuf[0]!='\0') {
        fprintf(stderr,"%s\n",pcap_errbuf);
    }
    if (!pcap) {
        exit(1);
    }

    // Write the Ethernet frame to the interface.
    if (pcap_inject(pcap2,&frame,sizeof(frame))==-1) {
        pcap_perror(pcap,0);
        pcap_close(pcap);
        exit(1);
    }

    while(1)
	pcap_dispatch(pcap, -1, handler, NULL);

    if (pcap_errbuf[0]!='\0') {
        fprintf(stderr,"%s\n",pcap_errbuf);
    }
    // Close the PCAP descriptor.
    pcap_close(pcap);
    return 0;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

2 participants