The Assimilation Project  based on Assimilation version 0.5.1441048221
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules 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 <cryptcurve25519.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>
46 #include <misc.h>
52 
53 
54 
55 FSTATIC Frame* _framedata_to_frameobject(PacketDecoder*, gpointer, gconstpointer, gconstpointer);
56 FSTATIC FrameSet* _decode_packet_get_frameset_data(gpointer, gconstpointer, gpointer *);
57 FSTATIC Frame* _decode_packet_framedata_to_frameobject(PacketDecoder*, gpointer*, gconstpointer*, gpointer*);
58 FSTATIC GSList* _pktdata_to_framesetlist(PacketDecoder*, gpointer, gconstpointer);
59 
61 
63 FSTATIC void
65 {
66  PacketDecoder* self = CASTTOCLASS(PacketDecoder, selfobj);
67 
68  FREE(self->_frametypemap); self->_frametypemap = NULL;
69  self->_pfinalize(selfobj);
70 }
71 
72 static FrameTypeToFrame _defaultmap[] = FRAMETYPEMAP;
73 
77 packetdecoder_new(guint objsize, const FrameTypeToFrame* framemap, gint mapsize)
78 {
79  gint j;
80  AssimObj* baseobj;
81  PacketDecoder* self;
82 
83  if (objsize < sizeof(PacketDecoder)) {
84  objsize = sizeof(PacketDecoder);
85  }
86  if (NULL == framemap) {
87  framemap = _defaultmap;
88  mapsize = DIMOF(_defaultmap);
89  }
90 
91  baseobj = assimobj_new(objsize);
92  proj_class_register_subclassed(baseobj, "PacketDecoder");
93  self = CASTTOCLASS(PacketDecoder, baseobj);
94 
95 
96  self->_pfinalize = baseobj->_finalize;
98  self->pktdata_to_framesetlist = _pktdata_to_framesetlist;
99  self->_maxframetype = 0;
100  self->_framemap = framemap;
101  self->_framemaplen = mapsize;
102 
103  for (j=0; j < self->_framemaplen; ++j) {
104  if (self->_framemap[j].frametype > self->_maxframetype) {
105  self->_maxframetype = self->_framemap[j].frametype;
106  }
107  }
108  self->_frametypemap = MALLOC0((self->_maxframetype+1)*sizeof(gpointer));
109  for (j=0; j <= self->_maxframetype; ++j) {
110  self->_frametypemap[j] = unknownframe_tlvconstructor;
111  }
112  for (j=0; j < self->_framemaplen; ++j) {
113  self->_frametypemap[self->_framemap[j].frametype] = self->_framemap[j].constructor;
114  }
115  return self;
116 }
117 
120 FSTATIC Frame*
122  gpointer* pktstart,
123  gconstpointer* pktend,
124  gpointer* newpacket)
125 {
127  guint16 frametype = get_generic_tlv_type(*pktstart, *pktend);
128  gpointer newpacketend = NULL;
129  Frame* ret;
130 
131  *newpacket = NULL;
132  // A note: It's easy to get these gpointer* objects confused.
133  // Because they're void**, they can be a bit too flexible ;-)
134  if (frametype <= self->_maxframetype) {
135  ret = self->_frametypemap[frametype](*pktstart, *pktend, newpacket, &newpacketend);
136  }else{
137  ret = unknownframe_tlvconstructor(*pktstart, *pktend, newpacket, &newpacketend);
138  }
139  if (NULL == ret) {
140  return NULL;
141  }
142  g_return_val_if_fail(ret != NULL, NULL);
143  if (NULL == *newpacket) {
144  *pktstart = (gpointer) ((guint8*)*pktstart + ret->dataspace(ret));
145  }else{
146  *pktstart = *newpacket;
147  *pktend = newpacketend;
148  }
149  return ret;
150 }
151 
155  gconstpointer vpktend,
156  gpointer* fsnext)
157 {
159  guint8* fsstart = vfsstart;
160  const guint8* pktend = vpktend;
161  gssize bytesleft = pktend - fsstart;
162  guint16 fstype;
163  guint32 fslen;
164  guint16 fsflags;
165  FrameSet* ret;
166 
167  *fsnext = NULL;
168  if (bytesleft < (gssize)FRAMESET_INITSIZE) {
169  return NULL;
170  }
171  fstype = get_generic_tlv_type(fsstart, pktend);
172  fslen = get_generic_tlv_len(fsstart, pktend);
173  fsflags = tlv_get_guint16(fsstart + GENERICTLV_HDRSZ, pktend);
174  ret = frameset_new(fstype);
175  g_return_val_if_fail(ret != NULL, NULL);
176  frameset_set_flags(ret, fsflags);
177  *fsnext = (gpointer) (fsstart + FRAMESET_INITSIZE + fslen);
178  return ret;
179 }
180 
181 
185 GSList*
187  gpointer pktstart,
188  gconstpointer pktend)
189 {
190  guint8* curframeset = pktstart;
191  GSList* ret = NULL;
192 
193  // Loop over all the FrameSets in the packet we were given.
194  while (curframeset < (guint8*)pktend) {
195  gpointer nextframeset = NULL;
196  gpointer framestart = ((guint8*)curframeset + FRAMESET_INITSIZE);
197  gpointer curframe;
198  FrameSet* fs;
199  gconstpointer fsend = pktend;
200  gpointer newframestart = NULL;
201  gboolean firstframe = TRUE;
202  guint32 framesetlen;
203 
204  // Check the overall frame size
205  framesetlen = get_generic_tlv_len(curframeset, pktend);
206  if (framesetlen > (guint32)((guint8*)pktend-(curframeset+FRAMESET_INITSIZE))) {
207  g_warning("%s.%d: Received frameset length [%d] is invalid - cannot exceed %d"
208  , __FUNCTION__, __LINE__, framesetlen
209  , (int)((guint8*)pktend-(curframeset+FRAMESET_INITSIZE)));
210  goto errout;
211  }
212  fsend = curframeset+framesetlen+FRAMESET_INITSIZE;
213  fs = _decode_packet_get_frameset_data(curframeset, curframeset+framesetlen, &nextframeset);
214  g_return_val_if_fail(fs != NULL, ret);
215  if (!is_valid_generic_tlv_packet(framestart, pktend)) {
216  g_warning("%s.%d: Frameset type %d not a valid TLV frameset"
217  , __FUNCTION__, __LINE__, fs->fstype);
218  UNREF(fs);
219  goto errout;
220  }
221 
222  // Construct this FrameSet from the series of frames encoded in the packet.
223  // Note that two special kinds of frames can alter the packet we're examining.
224  // This is explained in more detail inside the loop.
225  curframe = framestart;
226  while (curframe != NULL && curframe < fsend) {
227  Frame* newframe;
228  gpointer newpacket = NULL;
229  // The first special case frame is the compression frame, in which case the
230  // remaining packet is replaced by a new, larger (decompressed) packet.
231  //
232  // The second type is the encryption packet, in which case the remaining
233  // packet is replaced by a new chunk of data which will have different
234  // (decrypted) content, and would normally be expected to be the same size
235  // as the original.
236  //
237  // This means that "decode_packet_framedata_to_frameobject" might replace the
238  // packet data we've been looking at.
239  // (FWIW: It's perfectly OK to have an encryption frame followed by a
240  // (embedded) compression frame -- both kinds can occur in the same FrameSet).
241  newframe = _decode_packet_framedata_to_frameobject(self, &curframe, &fsend, &newpacket);
242  if (newpacket) {
243  if (newframestart != NULL) {
244  // We did packet replacement more than once...
245  g_free(newframestart);
246  }
247  newframestart = newpacket;
248  }
249  if (NULL == newframe) {
250  UNREF(fs);
251  goto errout;
252  }
253  if (TRUE == firstframe) {
254  if (!OBJ_IS_A(newframe, "SignFrame")) {
255  UNREF(newframe);
256  UNREF(fs);
257  g_warning("%s.%d: First frame NOT a signature frame - [%d] instead"
258  , __FUNCTION__, __LINE__, newframe->type);
259  goto errout;
260  }
261  firstframe = FALSE;
262  }
263  frameset_append_frame(fs, newframe);
264  UNREF(newframe);
265  }
266  if (curframe != fsend) {
267  g_warning("%s.%d: Received %d frameset - length is off by"
268  ": %d instead"
269  , __FUNCTION__, __LINE__, fs->fstype
270  , (int)((guint8*)fsend-((guint8*)curframe)));
271  goto errout;
272  }
273  if (newframestart) {
274  g_free(newframestart); newframestart = NULL;
275  }
276  if (fs) {
277  ret = g_slist_append(ret, fs); fs = NULL;
278  }
279  curframeset = nextframeset;
280  }
281  return ret;
282 errout:
283  g_slist_free_full(ret, assim_g_notify_unref); ret = NULL;
284  return ret;
285 }
#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:319
Defines miscellaneous interfaces.
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.
FSTATIC Frame * _decode_packet_framedata_to_frameobject(PacketDecoder *, gpointer *, gconstpointer *, gpointer *)
Given a pointer to a TLV entry for the data corresponding to a Frame, construct a corresponding Frame...
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:446
This file defines our base object class: AssimObj.
guint16 fstype
Type of frameset.
Definition: frameset.h:52
PacketDecoder * packetdecoder_new(guint objsize, const FrameTypeToFrame *framemap, gint mapsize)
Initialize our frame type map.
Definition: packetdecoder.c:77
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
#define __FUNCTION__
WINEXPORT void assim_g_notify_unref(gpointer assimobj)
Unref for glib notify.
Definition: misc.c:739
FSTATIC GSList * _pktdata_to_framesetlist(PacketDecoder *, gpointer, gconstpointer)
Constructs a GSList list of FrameSet class objects from a datagram/packet.
FSTATIC void _packetdecoder_finalize(AssimObj *)
Function for finalizing.
Definition: packetdecoder.c:64
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 OBJ_IS_A(obj, Cclass)
Definition: proj_classes.h:72
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) Note: return result is ...
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.
gboolean is_valid_generic_tlv_packet(gconstpointer tlv_vp, gconstpointer pktend)
Return TRUE if this is a valid generic TLV packet.
AssimObj * assimobj_new(guint objsize)
Definition: assimobj.c:74
Frame * unknownframe_tlvconstructor(gpointer 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
void(* _finalize)(AssimObj *)
Free object (private)
Definition: assimobj.h:55
guint16 type
Frame Type (see Individual TLV 'Frame' data types and layouts (by TLV type) - frameformats.h )
Definition: frame.h:45
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.
#define g_slist_free_full
Definition: projectcommon.h:73
FrameSet class - used for collecting Frames when not on the wire, and for marshalling/demarshalling t...
Definition: frameset.h:46
FSTATIC Frame * _framedata_to_frameobject(PacketDecoder *, gpointer, gconstpointer, gconstpointer)
FSTATIC FrameSet * _decode_packet_get_frameset_data(gpointer, gconstpointer, gpointer *)
Construct a basic FrameSet object from the initial marshalled FrameSet data in a packet.
Implements the SeqnoFrame class.
#define FRAMESET_INITSIZE
Definition: frameset.h:57
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:55
#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
struct _PacketDecoder PacketDecoder
Definition: packetdecoder.h:43
Describes interfaces to CryptFrame (encryption) C-Class It represents a FrameSet using libsodium (cur...