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  guint16 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 && nextframeset <= pktend, 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 chunk of data.
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 }