The Assimilation Project
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pcap_GSource.c
Go to the documentation of this file.
1 
43 #include <memory.h>
44 #include <projectcommon.h>
45 #include <proj_classes.h>
46 #include <pcap_min.h>
47 #include <pcap_GSource.h>
48 #include <intframe.h>
49 #include <addrframe.h>
50 #include <cstringframe.h>
51 #include <frametypes.h>
52 #include <misc.h>
53 
59 
60 FSTATIC gboolean g_source_pcap_prepare(GSource* source, gint* timeout);
61 FSTATIC gboolean g_source_pcap_check(GSource* source);
62 FSTATIC gboolean g_source_pcap_dispatch(GSource* source, GSourceFunc callback, gpointer user_data);
63 FSTATIC void g_source_pcap_finalize(GSource* source);
64 FSTATIC guint64 proj_timeval_to_g_real_time(const struct timeval * tv);
65 
66 static GSourceFuncs g_source_pcap_gsourcefuncs = {
71  NULL,
72  NULL
73 };
74 
75 
85 GSource*
86 g_source_pcap_new(const char * dev,
87  unsigned listenmask,
88  gboolean (*dispatch)(GSource_pcap_t* gsource,
90  pcap_t* capstruct,
91  gconstpointer pkt,
92  gconstpointer pend,
93  const struct pcap_pkthdr* pkthdr,
94  const char * capturedev,
95  gpointer userdata),
96 
97  GDestroyNotify notify,
98  gint priority,
100  gboolean can_recurse,
102  GMainContext* context,
103  gsize objectsize,
104  gpointer userdata
105  )
106 {
107  pcap_t* captureobj;
108  GSource* src;
109  GSource_pcap_t* ret;
110 
111  if (objectsize < sizeof(GSource_pcap_t)) {
112  objectsize = sizeof(GSource_pcap_t);
113  }
114 
115  // Try and create a GSource object for us to eventually return...
116  src = g_source_new(&g_source_pcap_gsourcefuncs, objectsize);
117  g_return_val_if_fail(src != NULL, NULL);
118 
119  proj_class_register_object(src, "GSource");
120  proj_class_register_subclassed(src, "GSource_pcap_t");
121 
122  ret = CASTTOCLASS(GSource_pcap_t, src);
123  // OK, now create the capture object to associate with it
124  if (NULL == (captureobj = create_pcap_listener(dev, FALSE, listenmask, &ret->pcprog))) {
125  // OOPS! Didn't work... Give up.
126  g_source_unref(src);
127  return NULL;
128  }
129  ret->capture = captureobj;
130  ret->capturedev = g_strdup(dev);
131  ret->listenmask = listenmask;
132  ret->dispatch = dispatch;
133 #ifdef _MSC_VER
134  // Probably depends on the version of the API - not just being on Windows...
135  ret->capturefd = pcap_fileno(ret->capture);
136 #else
137  ret->capturefd = pcap_get_selectable_fd(ret->capture);
138 #endif
139  ret->destroynote = notify;
140  ret->gfd.fd = ret->capturefd;
141  ret->gfd.events = G_IO_IN|G_IO_ERR|G_IO_HUP;
142  ret->gfd.revents = 0;
143  ret->userdata = userdata;
144  g_source_add_poll(src, &ret->gfd);
145  g_source_set_priority(src, priority);
146  g_source_set_can_recurse(src, can_recurse);
147  ret->gsourceid = g_source_attach(src, context);
148  if (ret->gsourceid == 0) {
149  g_source_remove_poll(src, &ret->gfd);
150  memset(ret, 0, sizeof(*ret));
151  g_source_unref(src);
152  src = NULL;
153  ret = NULL;
154  }
155  return (GSource*)ret;
156 }
157 
159 gboolean
160 g_source_pcap_prepare(GSource* source,
161  gint* timeout)
162 {
163  // Don't need to do anything prior to a poll(2) call...
164  (void)source;
165  (void)timeout;
166  return FALSE;
167 }
169 gboolean
170 g_source_pcap_check(GSource* src)
171 {
173 
174  // revents: received events...
175  // @todo: should check for errors in revents
176  return 0 != psrc->gfd.revents;
177 }
179 gboolean
181  GSourceFunc callback,
182  gpointer user_data)
183 {
185  const u_char * pkt;
186  struct pcap_pkthdr* hdr;
187  int rc; // Meaning of various rc values:
188  // 1 - read a single packet
189  // 0 - no packets to read at the moment
190  // negative - various kinds of errors
191  (void)callback;
192  (void)user_data;
193  // Process all the packets we can find.
194  while (1 == (rc = pcap_next_ex(psrc->capture, &hdr, &pkt))) {
195  const u_char* pktend = pkt + hdr->caplen;
196  if (!psrc->dispatch(psrc, psrc->capture, pkt, pktend, hdr,
197  psrc->capturedev, psrc->userdata)) {
198  g_source_remove_poll(src, &psrc->gfd);
199  g_source_unref(src);
200  return FALSE;
201  }
202  }
203  // @todo: should check for errors in 'rc'
204  return rc >= 0;
205 }
208 void
210 {
212  if (psrc->destroynote) {
213  psrc->destroynote(psrc);
214  }
215  if (psrc->capture) {
216  close_pcap_listener(psrc->capture, psrc->capturedev, psrc->listenmask);
217  pcap_freecode(&psrc->pcprog);
218  psrc->capture = NULL;
219  g_free(psrc->capturedev);
220  psrc->capturedev = NULL;
221  }
223 }
224 
226 FSTATIC guint64
227 proj_timeval_to_g_real_time(const struct timeval * tv)
228 {
229  guint64 ret;
230  ret = (guint64)tv->tv_sec * (guint64)1000000UL;
231  ret += (guint64)tv->tv_usec;
232  return ret;
233 }
234 
236 FrameSet*
237 construct_pcap_frameset(guint16 framesettype,
238  gconstpointer pkt,
239  gconstpointer pktend,
240  const struct pcap_pkthdr* pkthdr,
241  const char * interfacep)
242 {
244  Frame* pktframe = frame_new(FRAMETYPE_PKTDATA, 0);
247  FrameSet* fs = frameset_new(framesettype);
248  const guint8* bpkt = (const guint8*) pkt;
249  gsize pktlen = ((const guint8*)pktend-bpkt);
250  guint8* cppkt = MALLOC0(pktlen);
251  gchar* sysname;
252 
253  sysname = proj_get_sysname();
254  g_return_val_if_fail(NULL != sysname, NULL);
255  g_return_val_if_fail(fsysname != NULL, NULL);
256  g_return_val_if_fail(timeframe != NULL, NULL);
257  g_return_val_if_fail(pktframe != NULL, NULL);
258  g_return_val_if_fail(intfname != NULL, NULL);
259  g_return_val_if_fail(cppkt != NULL, NULL);
260 
261  // System name
262  fsysname->baseclass.setvalue(&fsysname->baseclass, sysname, strlen(sysname)+1, g_free);
263  frameset_append_frame(fs, &fsysname->baseclass);
264  UNREF2(fsysname);
265 
266  // Interface name
267  intfname->baseclass.setvalue(&intfname->baseclass, g_strdup(interfacep), strlen(interfacep)+1, g_free);
268  frameset_append_frame(fs, &intfname->baseclass);
269  UNREF2(intfname);
270 
271  // Local time stamp
272  timeframe->setint(timeframe, proj_timeval_to_g_real_time(&(pkthdr->ts)));
273  frameset_append_frame(fs, &timeframe->baseclass);
274  UNREF2(timeframe);
275 
276  // Packet data
277  memcpy(cppkt, pkt, pktlen);
278  pktframe->setvalue(pktframe, cppkt, pktlen, g_free);
279  frameset_append_frame(fs, pktframe);
280  UNREF(pktframe);
281 
282  return fs;
283 }
#define MALLOC0(nbytes)
should it just call g_malloc?
Definition: projectcommon.h:25
Defines miscellaneous interfaces.
unsigned listenmask
Protocols selected from Protocols known to (supported by) create_pcap_listener()..
Definition: pcap_GSource.h:45
char * proj_get_sysname(void)
Return a malloced string of the system name.
This is an IntFrame class TLV (type, length, value) frame - representing an integer of some specified...
Definition: intframe.h:39
FSTATIC gboolean g_source_pcap_check(GSource *source)
The GMainLoop check function for libpcap packet capturing.
Definition: pcap_GSource.c:170
void close_pcap_listener(pcap_t *pcapdev, const char *dev, unsigned listenmask)
Close this pcap_listener, and undo listens for multicast addresses.
Definition: pcap_min.c:192
gpointer userdata
Saved user data.
Definition: pcap_GSource.h:47
int capturefd
Underlying file descriptor.
Definition: pcap_GSource.h:43
gint gsourceid
Source ID from g_source_attach()
Definition: pcap_GSource.h:46
GSource * g_source_pcap_new(const char *dev, unsigned listenmask, gboolean(*dispatch)(GSource_pcap_t *gsource, pcap_t *capstruct, gconstpointer pkt, gconstpointer pend, const struct pcap_pkthdr *pkthdr, const char *capturedev, gpointer userdata), GDestroyNotify notify, gint priority, gboolean can_recurse, GMainContext *context, gsize objectsize, gpointer userdata)
Construct new GSource from a newly constructed pcap capture object.
Definition: pcap_GSource.c:86
This is the base Frame class object (in-memory TLV (type, length, value)) for every general component...
Definition: frame.h:43
IntFrame * intframe_new(guint16 frametype, int intbytes)
Construct new IntFrame object.
Definition: intframe.c:181
Describes interfaces to C-String Frame (Cstringframe) C-Class It holds conventional zero-terminated b...
FrameSet * frameset_new(guint16 frameset_type)
Construct a new frameset of the given type.
Definition: frameset.c:110
Simple libpcap interface definitions.
#define FSTATIC
Definition: projectcommon.h:31
#define FRAMETYPE_HOSTNAME
FRAMETYPE_HOSTNAME Frame (frametype 9) Frame subclass - CstringFrame class.
Definition: frametypes.h:192
tuple GSourceFunc
Definition: glib.py:68
GPollFD gfd
Poll/select object for gmainloop.
Definition: pcap_GSource.h:40
gboolean(* dispatch)(GSource_pcap_t *gsource, pcap_t *capstruct, gconstpointer pkt, gconstpointer pend, const struct pcap_pkthdr *pkthdr, const char *capturedev, gpointer userdata)
[in] user dispatch function - we call it when a packet is read
Definition: pcap_GSource.h:49
FrameSet * construct_pcap_frameset(guint16 framesettype, gconstpointer pkt, gconstpointer pktend, const struct pcap_pkthdr *pkthdr, const char *interfacep)
Construct a PCAP capture FrameSet from a PCAP packet.
Definition: pcap_GSource.c:237
Implements the IntFrame class - integers in a frame.
void frameset_append_frame(FrameSet *fs, Frame *f)
Append frame to the front of the end of the frame list.
Definition: frameset.c:143
FSTATIC gboolean g_source_pcap_prepare(GSource *source, gint *timeout)
The GMainLoop prepare function for libpcap packet capturing.
Definition: pcap_GSource.c:160
void proj_class_register_object(gpointer object, const char *static_classname)
Log the creation of a new object, and its association with a given type.
Definition: proj_classes.c:100
Frame * frame_new(guint16 frame_type, gsize framesize)
Construct a new frame - allowing for "derived" frame types...
Definition: frame.c:124
gpointer proj_class_register_subclassed(gpointer object, const char *static_subclassname)
Log the creation of a subclassed object from a superclassed object.
Definition: proj_classes.c:192
#define FRAMETYPE_WALLCLOCK
FRAMETYPE_WALLCLOCK Frame (frametype 7) Frame subclass - IntFrame class.
Definition: frametypes.h:167
This is our CstringFrame class object - used for holding C-style NULL terminated strings.
Definition: cstringframe.h:36
Project common header file.
Header file defining the data layouts for our Frames.
g_main_loop GSource object for creating events from libpcap (pcap_t) objects We manage this with our ...
Definition: pcap_GSource.h:38
pcap_t * create_pcap_listener(const char *dev, gboolean blocking, unsigned listenmask, struct bpf_program *prog)
Set up pcap listener for the given interfaces and protocols.
Definition: pcap_min.c:66
void proj_class_dissociate(gpointer object)
Dissociate an object from the C class system (typically coupled with freeing it). ...
Definition: proj_classes.c:228
Describes interfaces to Address Frame (AddrFrame) C-Class.
FSTATIC void g_source_pcap_finalize(GSource *source)
The GMainLoop finalize function for libpcap packet capturing Called when this object is 'finalized' (...
Definition: pcap_GSource.c:209
Frame baseclass
base Frame class object
Definition: intframe.h:40
void(* setint)(IntFrame *self, guint64 value)
set the integer to the given value
Definition: intframe.h:43
Defines interfaces a project Class system for class hierarchies in 'C'.
GDestroyNotify destroynote
[in] function to call when we're destroyed...
Definition: pcap_GSource.h:57
pcap_t * capture
Pcap capture object.
Definition: pcap_GSource.h:41
FSTATIC guint64 proj_timeval_to_g_real_time(const struct timeval *tv)
Convert struct timeval to g_get_real_time() style value.
Definition: pcap_GSource.c:227
FSTATIC gboolean g_source_pcap_dispatch(GSource *source, GSourceFunc callback, gpointer user_data)
The GMainLoop dispatch function for libpcap packet capturing.
Definition: pcap_GSource.c:180
FrameSet class - used for collecting Frames when not on the wire, and for marshalling/demarshalling t...
Definition: frameset.h:46
libpcap Packet capture Gsource interface description
char * capturedev
Capture device name.
Definition: pcap_GSource.h:44
struct bpf_program pcprog
Pcap program.
Definition: pcap_GSource.h:42
void(* setvalue)(Frame *self, gpointer value, guint32 length, GDestroyNotify valfinal)
member function for setting value
Definition: frame.h:52
#define FRAMETYPE_PKTDATA
FRAMETYPE_PKTDATA Frame (frametype 6) Frame subclass - Frame class.
Definition: frametypes.h:152
#define UNREF2(obj)
Definition: assimobj.h:36
#define CASTTOCLASS(Cclass, obj)
Safely cast 'obj' to C-class 'class' - verifying that it was registerd as being of type class ...
Definition: proj_classes.h:66
#define UNREF(obj)
Definition: assimobj.h:35
WINEXPORT CstringFrame * cstringframe_new(guint16 frame_type, gsize framesize)
Construct a new CstringFrame - allowing for "derived" frame types...
Definition: cstringframe.c:101
struct _GSource_pcap GSource_pcap_t
Definition: pcap_GSource.h:33
#define FRAMETYPE_INTERFACE
FRAMETYPE_INTERFACE Frame (frametype 8) Frame subclass - CstringFrame class.
Definition: frametypes.h:180