Python-based Socket program accept by libPcap(C-based)
Question: Dear all:

I use **python-based socket client** to send string data (i.e log data).

On the other hand, I use **libpcap to sniff string data on the server side**.

# But I got an error on the client side when I send string data to the server
side at the second time.

The error like below:

    
    
    Traceback (most recent call last):
      File "./udp_client_not_sendback.py", line 21, in <module>
        s.sendall(data) #Send UDP data
      File "/usr/lib/python2.7/socket.py", line 224, in meth
        return getattr(self._sock,name)(*args)
    socket.error: [Errno 111] Connection refused
    

And below are my codes on the client and server side:

_**Client side(Python)_**

    
    
    import socket, sys
    
    host = sys.argv[1] #Server IP Address
    
    textport = sys.argv[2] #Server Binding Port
    
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #socket
    
    try:
        port = int(textport)
    except ValueError:
        port = socket.getservbyname(textport, 'udp')
    
    s.connect((host, port)) #connect
    
    while(1):
        print "Enter data to transmit:"
    
        data = sys.stdin.readline().strip() #UDP data
    
        s.sendall(data) #Send UDP data
    

_**Server side(C libpcap)_**

    
    
        pcap_handler_func(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
        {
        char timebuf[64];
        char addrstr[64];
        struct ether_header *ethhdr = (struct ether_header *)bytes;
        struct iphdr *ipv4h;
        struct ip6_hdr *ipv6h;
    
        memset(timebuf, 0, sizeof(timebuf));
        if (ctime_r(&h->ts.tv_sec, timebuf) == NULL) {
        return;
        }
        timebuf[strlen(timebuf) - 1] = '\0';
        printf("%s, caplen:%d, len:%d, ", timebuf, h->caplen, h->len);
        ipv4h = (struct iphdr *)(bytes + sizeof(struct ether_header));
        inet_ntop(AF_INET, &ipv4h->saddr, addrstr, sizeof(addrstr));
        printf("src[%s]\n", addrstr);
    
        return;
        }
    
        int main()
        {
        pcap_t *p;
        char errbuf[PCAP_ERRBUF_SIZE];
        char cmdstr[] = "udp";
        struct bpf_program bpfprog;
    
        p = pcap_open_live("eth1", 65536, 1, 10, errbuf);
    
        //Filter
        if (pcap_setfilter(p, &bpfprog) < 0) {
        fprintf(stderr, "%s\n", pcap_geterr(p));
        return 1;
        }
    
        //Packet action
        if (pcap_loop(p, -1, pcap_handler_func, NULL) < 0) {
        fprintf(stderr, "%s\n", pcap_geterr(p));
        pcap_close(p);
        return 1;
        }
    
        pcap_close(p);
        return 0;
        }
    

I think the problem is I don't bind the socket on the server side and I just
use pcap to capture the string data.

So at the second time it happened the socket error on the client side.

Anyone can give me some suggestion to overcome this problem?

Thanks a lot for your helping.


Answer: libpcap, and the capture mechanisms it uses, are **_NOT_** intended for use
when writing TCP/UDP/IP servers! They're intended to 1) allow passive capture
of packets and (in some cases and with newer versions of libpcap) injection of
packets and 2) user-mode implementation of protocols that run atop the link
layer and that don't have an implementation in the OS kernel.

If you have a process running on some machine, listening for packets using
libpcap, that will **_NOT_** create a socket on that machine to receive
packets sent to some particular TCP or UDP port.

The first time your program tries to send a packet to the UDP port in
question, the machine to which you're sending it probably sees that it's being
sent to a UDP port on which no socket is listening, and sends back an ICMP
Port Unreachable message. The send call has already been done; UDP is a
connectionless protocol with no reliable delivery guarantees, so a UDP send
does _NOT_ wait for a reply of any sort - if the packet made it out onto the
wire, that's considered "success", as no other checks for successful delivery
can be made at the UDP level.

However, as you connected the socket in the client program, the client
machine's ICMP implementation, if it sees the ICMP Port Unreachable message,
will set an indicator on the socket to tell the program that the _previous_
UDP packet couldn't be delivered (as there was nothing to which to deliver
it). A receive attempt on that socket - or, it appears, a subsequent attempt
to send a packet on that socket - will return the "connection refused" error
as an indication that the _previously-sent_ packet couldn't be delivered. It
will also mean that the second attempt to send the packet won't actually send
the packet; you'd have to make _another_ attempt, which will, I think, succeed
in sending the packet, although it will again get an ICMP Port Unreachable if
there's no program listening for that UDP port on the server.

So _that's_ why you saw the first packet, but not the second, in your sniffer
(**_NOT_** server!) application using libpcap.

So millimoose is 100% correct when he/she says "there has to be an actual
server running on the server side". Write one - using regular sockets, not
libpcap and whatever mechanism it might use (AF_PACKET sockets on Linux, BPF
devices on *BSD and OS X, etc.), and run it on the server machine. You can
_also_ run your libpcap-based _sniffer_ program, or some other sniffer program
such as tcpdump or {Wireshark, TShark}, at the same time to see what's going
on the wire.

