1 /*
2  * Copyright (c) 2014 CORE Security Technologies
3  *
4  * This software is provided under under a slightly modified version
5  * of the Apache Software License. See the accompanying LICENSE file
6  * for more information.
7  *
8  */
9 
10 #include <pcap.h>
11 #include <Python.h>
12 
13 #include "pcapy.h"
14 #include "pcapobj.h"
15 #include "bpfobj.h"
16 #include "pcapdumper.h"
17 #include "pcap_pkthdr.h"
18 
19 
20 PyObject *PcapError;
21 
22 
23 
24 // module methods
25 
26 static PyObject*
lookupdev(PyObject * self,PyObject * args)27 lookupdev(PyObject* self, PyObject* args)
28 {
29   char errbuff[PCAP_ERRBUF_SIZE];
30   char* dev;
31 
32   dev = pcap_lookupdev(errbuff);
33   if(!dev)
34     {
35       PyErr_SetString(PcapError, errbuff);
36       return NULL;
37     }
38 
39   return Py_BuildValue("u", dev);
40 }
41 
42 static PyObject*
findalldevs(PyObject * self,PyObject * args)43 findalldevs(PyObject *self, PyObject *args)
44 {
45   char errbuff[PCAP_ERRBUF_SIZE];
46   pcap_if_t *devs;
47 
48   int status = pcap_findalldevs(&devs, errbuff);
49   if(status)
50     {
51       PyErr_SetString(PcapError, errbuff);
52       return NULL;
53     }
54 
55   if(devs==NULL)
56     {
57       PyErr_SetString(PcapError, "No valid interfaces to open");
58       return NULL;
59     }
60 
61   pcap_if_t *cursor = devs;
62   PyObject* list = PyList_New(0);
63   while(cursor)
64     {
65       PyList_Append(list, Py_BuildValue("s", cursor->name));
66       cursor = cursor->next;
67     }
68 
69   pcap_freealldevs(devs);
70 
71   return list;
72 }
73 
74 static PyObject*
open_live(PyObject * self,PyObject * args)75 open_live(PyObject *self, PyObject *args)
76 {
77   char errbuff[PCAP_ERRBUF_SIZE];
78   char * device;
79   int  snaplen;
80   int  promisc;
81   int  to_ms;
82 
83   bpf_u_int32 net, mask;
84 
85 
86   if(!PyArg_ParseTuple(args,"siii:open_live",&device,&snaplen,&promisc,&to_ms))
87     return NULL;
88 
89   int status = pcap_lookupnet(device, &net, &mask, errbuff);
90   if(status)
91     {
92       net = 0;
93       mask = 0;
94     }
95 
96   pcap_t* pt;
97 
98   pt = pcap_open_live(device, snaplen, promisc!=0, to_ms, errbuff);
99   if(!pt)
100     {
101       PyErr_SetString(PcapError, errbuff);
102       return NULL;
103     }
104 #ifdef WIN32
105   pcap_setmintocopy(pt, 0);
106 #endif
107 
108   return new_pcapobject( pt, net, mask );
109 }
110 
111 static PyObject*
open_offline(PyObject * self,PyObject * args)112 open_offline(PyObject *self, PyObject *args)
113 {
114   char errbuff[PCAP_ERRBUF_SIZE];
115   char * filename;
116 
117 
118   if(!PyArg_ParseTuple(args,"s",&filename))
119     return NULL;
120 
121   pcap_t* pt;
122 
123   pt = pcap_open_offline(filename, errbuff);
124   if(!pt)
125     {
126       PyErr_SetString(PcapError, errbuff);
127       return NULL;
128     }
129 #ifdef WIN32
130   pcap_setmintocopy(pt, 0);
131 #endif
132 
133   return new_pcapobject( pt );
134 }
135 
136 
137 static PyObject*
bpf_compile(PyObject * self,PyObject * args)138 bpf_compile(PyObject* self, PyObject* args)
139 {
140   int linktype;
141   int  snaplen;
142   char *filter;
143   int optimize;
144   unsigned int netmask;
145 
146   if(!PyArg_ParseTuple(args,
147 		       "iisiI:compile",
148 		       &linktype,
149 		       &snaplen,
150 		       &filter,
151 		       &optimize,
152 		       &netmask))
153     return NULL;
154 
155   pcap_t *pp;
156 
157   pp = pcap_open_dead(linktype, snaplen);
158   if(pp == NULL)
159     return NULL;
160 
161   struct bpf_program bpf;
162   int status = pcap_compile(pp, &bpf, filter, optimize, netmask);
163   pcap_close(pp);
164 
165   if(status)
166     {
167       PyErr_SetString(PcapError, pcap_geterr(pp));
168       return NULL;
169     }
170 
171   return new_bpfobject( bpf );
172 }
173 
174 
175 static PyMethodDef pcap_methods[] = {
176   {"open_live", open_live, METH_VARARGS, "open_live(device, snaplen, promisc, to_ms) opens a pcap device"},
177   {"open_offline", open_offline, METH_VARARGS, "open_offline(filename) opens a pcap formated file"},
178   {"lookupdev", lookupdev, METH_VARARGS, "lookupdev() looks up a pcap device"},
179   {"findalldevs", findalldevs, METH_VARARGS, "findalldevs() lists all available interfaces"},
180   {"compile", bpf_compile, METH_VARARGS, "compile(linktype, snaplen, filter, optimize, netmask) creates a bpfprogram object"},
181   {NULL, NULL}
182 };
183 
184 #if PY_MAJOR_VERSION >= 3
185 PyDoc_STRVAR(pcap_doc,
186 "A wrapper for the Packet Capture (PCAP) library");
187 
188 static struct PyModuleDef pcapy_module = {
189 	PyModuleDef_HEAD_INIT,
190 	"pcapy",      /* m_name */
191 	pcap_doc,     /* m_doc */
192 	-1,           /* m_size */
193 	pcap_methods, /* m_methods */
194 	NULL,         /* m_reload */
195 	NULL,         /* m_traverse */
196 	NULL,         /* m_clear */
197 	NULL,         /* m_free */
198 };
199 #else
200 
201 static char *pcap_doc =
202 "\nA wrapper for the Packet Capture (PCAP) library\n";
203 #endif //PY_MAJOR_VERSION >= 3
204 
205 
206 #if PY_MAJOR_VERSION >= 3
207 PyMODINIT_FUNC
PyInit_pcapy(void)208 PyInit_pcapy(void)
209 #else
210 void
211 initpcapy(void)
212 #endif //PY_MAJOR_VERSION >= 3
213 
214 
215 {
216   PyObject *m, *d;
217 
218 
219 #if PY_MAJOR_VERSION < 3
220   Pcaptype.ob_type = &PyType_Type;
221   Pkthdr_type.ob_type = &PyType_Type;
222   Pdumpertype.ob_type = &PyType_Type;
223 #endif
224 
225 
226 #if PY_MAJOR_VERSION >= 3
227   m = PyModule_Create(&pcapy_module);
228 #else
229   m = Py_InitModule3("pcapy", pcap_methods, pcap_doc);
230 #endif
231 
232   if (PyType_Ready(&BPFProgramType) < 0) {
233     #if PY_MAJOR_VERSION >= 3
234     return NULL;
235     #else
236     return;
237     #endif //PY_MAJOR_VERSION >= 3
238   }
239 
240   PyModule_AddObject(m, "BPFProgram", (PyObject *) &BPFProgramType);
241 
242   /* Direct from pcap's net/bpf.h. */
243   PyModule_AddIntConstant(m, "DLT_NULL", 0);
244   PyModule_AddIntConstant(m, "DLT_EN10MB", 1);
245   PyModule_AddIntConstant(m, "DLT_IEEE802", 6);
246   PyModule_AddIntConstant(m, "DLT_ARCNET", 7);
247   PyModule_AddIntConstant(m, "DLT_SLIP", 8);
248   PyModule_AddIntConstant(m, "DLT_PPP", 9);
249   PyModule_AddIntConstant(m, "DLT_FDDI", 10);
250   PyModule_AddIntConstant(m, "DLT_ATM_RFC1483", 11);
251   PyModule_AddIntConstant(m, "DLT_RAW", 12);
252   PyModule_AddIntConstant(m, "DLT_PPP_SERIAL", 50);
253   PyModule_AddIntConstant(m, "DLT_PPP_ETHER", 51);
254   PyModule_AddIntConstant(m, "DLT_C_HDLC", 104);
255   PyModule_AddIntConstant(m, "DLT_IEEE802_11", 105);
256   PyModule_AddIntConstant(m, "DLT_LOOP", 108);
257   PyModule_AddIntConstant(m, "DLT_LINUX_SLL", 113);
258   PyModule_AddIntConstant(m, "DLT_LTALK", 114);
259 
260   d = PyModule_GetDict(m);
261   PcapError = PyErr_NewException("pcapy.PcapError", NULL, NULL );
262   BPFError = PyErr_NewException("pcapy.BPFError", NULL, NULL );
263   if( PcapError )
264   {
265     PyDict_SetItemString( d, "PcapError", PcapError );
266   }
267 
268   if ( BPFError )
269   {
270     PyDict_SetItemString( d, "BPFError", BPFError );
271   }
272 #if PY_MAJOR_VERSION >= 3
273   return m;
274 #endif  //PY_MAJOR_VERSION >= 3
275 }
276 /* vim: set tabstop=2 shiftwidth=2 expandtab: */
277