2

I am trying to pipe the output of xz to a custom python script:

xz -cd file.pcap.xz | myscripy.py

However, I get an error when the script attempts to run this line:

  #!/usr/bin/env python2.7
from __future__ import print_function

import pcap
import io
STDIN_ALIAS = '/proc/self/fd/0' 

pcap.pcap(io.open(STDIN_ALIAS, 'r'))

and received an error

    pcap.pcap(io.open(STDIN_ALIAS, 'r'))
  File "pcap.pyx", line 196, in pcap.pcap.__init__
TypeError: expected string or Unicode object, _io.TextIOWrapper found

I am on Ubuntu 18.04 and running under python 2.7.

Ilia
  • 534
  • 3
  • 21
  • Given the traceback, this must be [`pypcap` version 1.1.5](https://github.com/pynetwork/pypcap), as corroborated by the [available Ubuntu package for 18.04](https://packages.ubuntu.com/bionic/python-pypcap) – Martijn Pieters Jan 03 '19 at 13:02

3 Answers3

3

You can't use Python to pass in packets from a file to pcap.pcap(). The pypcap library you are using is a thin wrapper around the pcap_open_offline() and pcap_create() C functions, and offers no facilities for passing in a Python file object. This wrapper only accepts a filename or a network interface name, nothing else.

The pcap_open_offline() function does accept - as an alias for stdin, so just pass that in directly:

import pcap

sniffer = pcap.pcap('-')
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
0

The error message already tell you what happened. You need a string to the pcap() function, not a file object. To fix this, try

pcap.pcap(io.open(STDIN_ALIAS, 'r').read())

But I am not sure this will work as your file might be binary instead of text. In such case, you may want to open with 'rb' instead of 'r' flag, and do some conversion afterwards (especially if you use Python 3 instead of Python 2.7).

I see another issue: your code is not portable as it depends on this:

STDIN_ALIAS = '/proc/self/fd/0' 

A pythonic way to read the stdin is the follows (see Reading binary data from stdin)

import sys
string = sys.stdin.read()
adrtam
  • 6,991
  • 2
  • 12
  • 27
  • i tried `pcap.pcap(io.open(STDIN_ALIAS, 'r').read())` it gave an error : `UnicodeDecodeError: 'utf8' codec can't decode byte 0xb2 in position 2: invalid start byte' i tried `pcap.pcap(io.open(STDIN_ALIAS, 'rb').read())` it gave an error : `OSError: M<��: You don't have permission to capture on that device (socket: Operation not permitted)` – Ilia Jan 03 '19 at 09:47
  • 1
    You can't pass packets to the `pcap.pcap()` class; it only accepts a filename or a network interface. Luckily, the filename `-` is accepted to refer to stdin. – Martijn Pieters Jan 04 '19 at 11:29
-1

Have you tried upgrading PyPcap to work on Python 3? This could help, since Unicode handling is a lot cleaner and less prone to surprises on Python 3. The appropriate package is available, at least on Debian (and probably derived distros as well). Look for: python3-pypcap.

Isac Casapu
  • 1,163
  • 13
  • 21
  • cant find them via apt-get – Ilia Jan 03 '19 at 09:15
  • 1
    This isn't a Unicode issue, as pcap simply can't be passed an open file object, not via the Python wrapper at any rate. This applies to both Python 2 and Python 3, the library is the same. – Martijn Pieters Jan 04 '19 at 11:25