The Assimilation Project
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
packetdecoder.c
Go to the documentation of this file.
1 
26 #include <memory.h>
27 #include <projectcommon.h>
28 #include <assimobj.h>
29 #include <generic_tlv_min.h>
30 #include <frameset.h>
31 #include <frametypes.h>
32 #include <signframe.h>
33 #include <cryptframe.h>
34 #include <compressframe.h>
35 #include <tlvhelper.h>
36 #include <packetdecoder.h>
37 #include <intframe.h>
38 #include <addrframe.h>
39 #include <ipportframe.h>
40 #include <signframe.h>
41 #include <cstringframe.h>
42 #include <seqnoframe.h>
43 #include <nvpairframe.h>
44 #include <unknownframe.h>
45 #include <frametypes.h>
51 
52 
53 
54 FSTATIC Frame* _framedata_to_frameobject(PacketDecoder*, gconstpointer, gconstpointer, gconstpointer);
55 FSTATIC FrameSet* _decode_packet_get_frameset_data(gconstpointer, gconstpointer, void const **);
56 FSTATIC Frame* _decode_packet_framedata_to_frameobject(PacketDecoder*, gconstpointer*, gconstpointer*, gpointer*);
57 FSTATIC GSList* _pktdata_to_framesetlist(PacketDecoder*, gconstpointer, gconstpointer);
58 
60 
62 FSTATIC void
64 {
65  PacketDecoder* self = CASTTOCLASS(PacketDecoder, selfobj);
66 
67  FREE(self->_frametypemap); self->_frametypemap = NULL;
68  self->_pfinalize(selfobj);
69 }
70 
71 static FrameTypeToFrame _defaultmap[] = FRAMETYPEMAP;
72 
76 packetdecoder_new(guint objsize, const FrameTypeToFrame* framemap, gint mapsize)
77 {
78  gint j;
79  AssimObj* baseobj;
80  PacketDecoder* self;
81 
82  if (objsize < sizeof(PacketDecoder)) {
83  objsize = sizeof(PacketDecoder);
84  }
85  if (NULL == framemap) {
86  framemap = _defaultmap;
87  mapsize = DIMOF(_defaultmap);
88  }
89 
90  baseobj = assimobj_new(objsize);
91  proj_class_register_subclassed(baseobj, "PacketDecoder");
92  self = CASTTOCLASS(PacketDecoder, baseobj);
93 
94 
95  self->_pfinalize = baseobj->_finalize;
97  self->pktdata_to_framesetlist = _pktdata_to_framesetlist;
98  self->_maxframetype = 0;
99  self->_framemap = framemap;
100  self->_framemaplen = mapsize;
101 
102  for (j=0; j < self->_framemaplen; ++j) {
103  if (self->_framemap[j].frametype > self->_maxframetype) {
104  self->_maxframetype = self->_framemap[j].frametype;
105  }
106  }
107  self->_frametypemap = MALLOC0((self->_maxframetype+1)*sizeof(gpointer));
108  for (j=0; j <= self->_maxframetype; ++j) {
109  self->_frametypemap[j] = unknownframe_tlvconstructor;
110  }
111  for (j=0; j < self->_framemaplen; ++j) {
112  self->_frametypemap[self->_framemap[j].frametype] = self->_framemap[j].constructor;
113  }
114  return self;
115 }
116 
119 FSTATIC Frame*
121  gconstpointer* pktstart,
122  gconstpointer* pktend,
123  gpointer* newpacket)
124 {
126  guint16 frametype = get_generic_tlv_type(*pktstart, *pktend);
127  gpointer newpacketend = NULL;
128  Frame* ret;
129 
130  *newpacket = NULL;
131  // A note: It's easy to get these gpointer* objects confused.
132  // Because they're void**, they can be a bit too flexible ;-)
133  if (frametype <= self->_maxframetype) {
134  ret = self->_frametypemap[frametype](*pktstart, *pktend, newpacket, &newpacketend);
135  }else{
136  ret = unknownframe_tlvconstructor(*pktstart, *pktend, newpacket, &newpacketend);
137  }
138  g_return_val_if_fail(ret != NULL, NULL);
139  if (NULL == *newpacket) {
140  *pktstart = (gconstpointer) ((const guint8*)*pktstart + ret->dataspace(ret));
141  }else{
142  *pktstart = *newpacket;
143  *pktend = newpacketend;
144  }
145  return ret;
146 }
147 
150 _decode_packet_get_frameset_data(gconstpointer vfsstart,
151  gconstpointer vpktend,
152  const void ** fsnext)
153 {
155  const guint8* fsstart = vfsstart;
156  const guint8* pktend = vpktend;
157  gssize bytesleft = pktend - fsstart;
158  guint16 fstype;
159  guint32 fslen;
160  guint16 fsflags;
161  FrameSet* ret;
162 
163  *fsnext = vpktend;
164  if (bytesleft < (gssize)FRAMESET_INITSIZE) {
165  return NULL;
166  }
167  fstype = get_generic_tlv_type(fsstart, pktend);
168  fslen = get_generic_tlv_len(fsstart, pktend);
169  fsflags = tlv_get_guint16(fsstart + GENERICTLV_HDRSZ, pktend);
170  ret = frameset_new(fstype);
171  g_return_val_if_fail(ret != NULL, NULL);
172  frameset_set_flags(ret, fsflags);
173  *fsnext = (gconstpointer) (fsstart + FRAMESET_INITSIZE + fslen);
174  return ret;
175 }
176 
177 
181 GSList*
183  gconstpointer pktstart,
184  gconstpointer pktend)
185 {
186  gconstpointer curframeset = pktstart;
187  GSList* ret = NULL;
188 
189  // Loop over all the FrameSets in the packet we were given.
190  while (curframeset < pktend) {
191  gconstpointer nextframeset = pktend;
192  gconstpointer framestart = ((const guint8*)curframeset + FRAMESET_INITSIZE);
193  gconstpointer curframe;
194  FrameSet* fs = _decode_packet_get_frameset_data(curframeset, pktend, &nextframeset);
195  gconstpointer fsend = nextframeset;
196  gpointer newframestart = NULL;
197 
198  g_return_val_if_fail(fs != NULL, ret);
199 
200  // Construct this FrameSet from the series of frames encoded in the packet.
201  // Note that two special kinds of frames can alter the packet we're examining.
202  // This is explained in more detail inside the loop.
203  curframe = framestart;
204  while (curframe != NULL && curframe < fsend) {
205  Frame* newframe;
206  gpointer newpacket = NULL;
207  // The first special case frame is the compression frame, in which case the
208  // remaining packet is replaced by a new, larger (decompressed) packet.
209  //
210  // The second type is the encryption packet, in which case the remaining
211  // packet is replaced by a new chunk of data which will have different
212  // (decrypted) content, and would normally be expected to be the same size
213  // as the original.
214  //
215  // This means that "decode_packet_framedata_to_frameobject" might replace the
216  // packet data we've been looking at.
217  // (FWIW: It's perfectly OK to have an encryption frame followed by a
218  // compression frame -- both kinds can occur in the same FrameSet).
219  newframe = _decode_packet_framedata_to_frameobject(self, &curframe, &fsend, &newpacket);
220  if (newpacket) {
221  if (newframestart != NULL) {
222  // We did packet replacement more than once...
223  g_free(newframestart);
224  }
225  newframestart = newpacket;
226  }
227  if (NULL == newframe) {
228  UNREF(fs);
229  continue;
230  }
231  frameset_append_frame(fs, newframe);
232  UNREF(newframe);
233  }
234  if (newframestart) {
235  g_free(newframestart); newframestart = NULL;
236  }
237  ret = g_slist_append(ret, fs); fs = NULL;
238  curframeset = nextframeset;
239  }
240  return ret;
241 }
#define MALLOC0(nbytes)
should it just call g_malloc?
Definition: projectcommon.h:25
guint16 frameset_set_flags(FrameSet *fs, guint16 flagbits)
Set (OR in) the given set of FrameSet flags.
Definition: frameset.c:309
Describes interfaces to Signature Frame (Signframe) C-Class - providing digital signatures.
Implements minimal client-oriented Frame and Frameset capabilities.
This is the base Frame class object (in-memory TLV (type, length, value)) for every general component...
Definition: frame.h:43
Describes interfaces to the Unknown Frame (UnknownFrame) C-Class.
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
#define FSTATIC
Definition: projectcommon.h:31
#define GENERICTLV_HDRSZ
Size of Generic TLV header - ((type + length) == 5)
#define FRAMETYPEMAP
Definition: frametypes.h:415
This file defines our base object class: AssimObj.
PacketDecoder * packetdecoder_new(guint objsize, const FrameTypeToFrame *framemap, gint mapsize)
Initialize our frame type map.
Definition: packetdecoder.c:76
guint16 get_generic_tlv_type(gconstpointer tlv_vp, gconstpointer pktend)
Return the 'Type' of the given TLV TLV entry (first two bytes)
int frametype
One of the Defined Frame Formats from frameformats.h.
Definition: packetdecoder.h:38
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
Describes interfaces to C-String Frame (Cstringframe) C-Class It holds conventional zero-terminated b...
FSTATIC void _packetdecoder_finalize(AssimObj *)
Function for finalizing.
Definition: packetdecoder.c:63
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
Describes interfaces to C-String Frame (Compressframe) C-Class It holds conventional zero-terminated ...
#define FREE(m)
Our interface to free.
Definition: projectcommon.h:29
Data structure defining the mapping between frametype integers and corresponding demarshalling module...
Definition: packetdecoder.h:37
guint32 get_generic_tlv_len(gconstpointer tlv_vp, gconstpointer pktend)
Return the 'Length' of the given generic TLV entry (first 3 bytes after type)
FSTATIC GSList * _pktdata_to_framesetlist(PacketDecoder *, gconstpointer, gconstpointer)
Constructs a GSList list of FrameSet class objects from a datagram/packet.
Project common header file.
#define DIMOF(a)
Definition: lldp_min.c:30
Header file defining the data layouts for our Frames.
TLV helper interfaces definitions.
FSTATIC Frame * _decode_packet_framedata_to_frameobject(PacketDecoder *, gconstpointer *, gconstpointer *, gpointer *)
Given a pointer to a TLV entry for the data corresponding to a Frame, construct a corresponding Frame...
Frame * unknownframe_tlvconstructor(gconstpointer tlvstart, gconstpointer pktend, gpointer *ignorednewpkt, gpointer *ignorednewpktend)
Given marshalled data corresponding to an unknown Frame (basic binary frame), return that correspondi...
Definition: unknownframe.c:70
AssimObj * assimobj_new(guint objsize)
Definition: assimobj.c:74
FSTATIC Frame * _framedata_to_frameobject(PacketDecoder *, gconstpointer, gconstpointer, gconstpointer)
void(* _finalize)(AssimObj *)
Free object (private)
Definition: assimobj.h:55
Provides definitions for using our generic TLV capabilities.
Describes interfaces to Address Frame (AddrFrame) C-Class.
gsize(* dataspace)(const Frame *self)
How much space is needed to marshall this Frame?
Definition: frame.h:48
Describes interfaces to Address Frame (IpPortFrame) C-Class.
FrameSet class - used for collecting Frames when not on the wire, and for marshalling/demarshalling t...
Definition: frameset.h:45
Implements the SeqnoFrame class.
#define FRAMESET_INITSIZE
Definition: frameset.h:56
This file defines a few functions and interfaces for unmarshalling packet data into FrameSets...
Describes interfaces to name/value pair Frame (NVpairFrame) C-Class It holds conventional zero-termin...
guint16 tlv_get_guint16(const void *vitem, const void *bufend)
Retrieve an unsigned 16 bit integer from the given location with error checking and without caring ab...
Definition: tlvhelper.c:53
#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
FSTATIC FrameSet * _decode_packet_get_frameset_data(gconstpointer, gconstpointer, void const **)
Construct a basic FrameSet object from the initial marshalled FrameSet data in a packet.
struct _PacketDecoder PacketDecoder
Definition: packetdecoder.h:43