The Assimilation Project
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
frameset.c
Go to the documentation of this file.
1 
51 #include <string.h>
52 #include <projectcommon.h>
53 #include <frameset.h>
54 #include <frametypes.h>
55 #include <compressframe.h>
56 #include <generic_tlv_min.h>
57 #include <tlvhelper.h>
58 FSTATIC void _frameset_indir_finalize(void* f);
60 FSTATIC char * _frameset_toString(gconstpointer);
61 
63 
70 
72 
74 FSTATIC void
76 {
77  Frame* frame = CASTTOCLASS(Frame, f);
78  UNREF(frame);
79 }
80 
82 FSTATIC void
84 {
85  FrameSet* fs = CASTTOCLASS(FrameSet, obj);
86  g_return_if_fail(NULL != fs);
89  if (fs->framelist) {
90  // Would rather use g_slist_free_full() - but it's too new to be widely deployed...
91  while (NULL != fs->framelist) {
93  fs->framelist->data = NULL;
94  fs->framelist = g_slist_delete_link(fs->framelist, fs->framelist);
95  }
96  }
97  if (fs->packet) {
98  FREE(fs->packet);
99  fs->packet = NULL;
100  fs->pktend = NULL;
101  }
102  memset(fs, 0x0, sizeof(*fs));
103  FREECLASSOBJ(fs);
104 }
105 
106 
107 
109 FrameSet*
110 frameset_new(guint16 frameset_type)
111 {
112  AssimObj* obj = assimobj_new(sizeof(FrameSet));
113  FrameSet* s = NEWSUBCLASS(FrameSet, obj);
114 
116  g_return_val_if_fail(s != NULL, NULL);
117  s->fstype = frameset_type;
118  s->framelist = NULL;
119  s->packet = NULL;
120  s->pktend = NULL;
121  s->fsflags = 0;
125  return s;
126 }
127 
128 #define SPECIALFRAME(ftype) ((FRAMETYPE_COMPRESS == (ftype)) || (FRAMETYPE_CRYPTCURVE28819 == (ftype)) || (FRAMETYPE_SIG == (ftype)))
129 
131 void
133  Frame* f)
134 {
135  g_return_if_fail(NULL != fs && NULL != f);
136  REF(f);
137 
138  fs->framelist = g_slist_prepend(fs->framelist, f);
139 }
140 
142 void
144  Frame* f)
145 {
146  g_return_if_fail(NULL != fs && NULL != f);
147  REF(f);
148  fs->framelist = g_slist_append(fs->framelist, f);
149 }
150 
158 void
160  SignFrame* sigframe,
161  CryptFrame* cryptframe,
162  CompressFrame* compressframe)
164 {
167  GSList* curframe; // Current frame as we marshall packet...
168  int curpktoffset; // Current offset as we marshall packet...
169  guint8* curpktpos=NULL; // Current position within packet..
170  gsize pktsize;
171  gsize fssize = FRAMESET_INITSIZE; // "frameset" overhead size
172  g_return_if_fail(NULL != fs);
173  g_return_if_fail(NULL != sigframe);
174  // g_return_if_fail(NULL != fs->framelist); // Is an empty frame list OK?
175 
176  /*
177  * The general method we employ here is to:
178  * 1. Free the current packet, if any
179  * 2. Remove current Framelist signature, compression, and encryption frames (if any).
180  * 3. Prepend a compression Frame if compm != NULL
181  * 4. Prepend an encryption Frame if cryptm != NULL
182  * 5. Prepend a signature Frame (sigm may not be NULL).
183  * 6. Figure out how much space we think we need to malloc for the packet using Frames.
184  * 7. Malloc enough space.
185  * 8. Populate all the frames into this new packet in reverse order.
186  */
187 
188  // Free current packet, if any...
189  if (fs->packet) {
190  FREE(fs->packet);
191  fs->packet = NULL;
192  fs->pktend = NULL;
193  }
194  // Remove any current signature, compression, or encryption frames...
195  // (this method only works if they're first, and all together - but that's OK)
196  while (fs->framelist) {
197  Frame* item = CASTTOCLASS(Frame, fs->framelist->data);
198  g_return_if_fail(NULL != item);
199  switch (item->type) {
200  case FRAMETYPE_SIG:
202  case FRAMETYPE_COMPRESS:
203  UNREF(item);
204  fs->framelist->data = NULL;
205  fs->framelist = g_slist_delete_link(fs->framelist, fs->framelist);
206  continue;
207  }
208  break;
209  }
230  if (NULL != compressframe) {
231  gsize estsize = FRAMESET_INITSIZE;
232  for (curframe=fs->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
233  Frame* frame = CASTTOCLASS(Frame, curframe->data);
234  estsize += frame->dataspace(frame);
235  }
236  if (estsize > compressframe->compression_threshold) {
237  CompressFrame* newframe
238  = compressframe_new(compressframe->baseclass.type, compressframe->compression_method);
239  frameset_prepend_frame(fs, &newframe->baseclass);
240  UNREF2(newframe);
241  }
242  }
243  if (NULL != cryptframe) {
244  frameset_prepend_frame(fs, &cryptframe->baseclass);
245  }
246  // "sigframe" cannot be NULL (see check above)
247  frameset_prepend_frame(fs, CASTTOCLASS(Frame, sigframe));
248 
249  // Reverse list...
250  fs->framelist = g_slist_reverse(fs->framelist);
251 
252  // Add "end" frame to the "end" - if not already present...
253  if (CASTTOCLASS(Frame, fs->framelist->data)->type != FRAMETYPE_END) {
254  Frame* endframe = frame_new(FRAMETYPE_END, 0);
255  g_return_if_fail(NULL != endframe);
256  frameset_prepend_frame(fs, endframe);
257  UNREF(endframe);
258  }
259 
260  pktsize = fssize;
261  for (curframe=fs->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
262  Frame* frame = CASTTOCLASS(Frame, curframe->data);
263  pktsize += frame->dataspace(frame);
264  }
265  fs->packet = MALLOC0(pktsize);
266  fs->pktend = ((guint8*)fs->packet + pktsize);
267  g_return_if_fail(fs->packet != NULL);
268 
269  curpktoffset = pktsize;
270 
271  // Marshall out all our data - in reverse order...
272  // WATCH OUT: compression and encryption can replace or modify our packet(!)
273  for (curframe=fs->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
274  Frame* frame = CASTTOCLASS(Frame, curframe->data);
275 
276  // frame->dataspace() may change after calling updatedata()
277  curpktoffset = curpktoffset - frame->dataspace(frame);
278  g_return_if_fail(curpktoffset >= 0);
279  curpktpos = (guint8*)fs->packet + curpktoffset;
280  set_generic_tlv_type(curpktpos, frame->type, fs->pktend);
281  set_generic_tlv_len(curpktpos, frame->length, fs->pktend);
282  frame->updatedata(frame, curpktpos, fs->pktend, fs);
283  // updatedata() can change fs->packet and fs->pktend
284  curpktpos = (guint8*)fs->packet + curpktoffset;
285  if (!frame->isvalid(frame, curpktpos, fs->pktend)) {
286  g_error("Generated %s frame is not valid(!) (length=%"G_GSIZE_FORMAT")"
287  , proj_class_classname(frame), (gsize)frame->length);
288  }
289  }
290  g_return_if_fail(curpktpos == (((guint8*)fs->packet)+fssize));
291  // Reverse list - putting it back in the right order
292  fs->framelist = g_slist_reverse(fs->framelist);
293  // Write out the initial FrameSet header.
294  set_generic_tlv_type(fs->packet, fs->fstype, ((guint8*)fs->packet)+fssize);
295  set_generic_tlv_len(fs->packet, pktsize-fssize, ((guint8*)fs->packet)+fssize);
296  tlv_set_guint16(((guint8*)fs->packet)+GENERICTLV_HDRSZ, fs->fsflags, ((guint8*)fs->packet)+fssize);
297 }
298 
300 guint16
302 {
303  g_return_val_if_fail(NULL != fs, 0xffff);
304  return fs->fsflags;
305 }
306 
308 guint16
310  guint16 flagbits)
311 {
312  g_return_val_if_fail(NULL != fs, 0xffff);
313  fs->fsflags |= flagbits;
314  return fs->fsflags;
315 }
316 
318 guint16
320  guint16 flagbits)
321 {
322  g_return_val_if_fail(NULL != fs, 0xffff);
323  g_return_val_if_fail(flagbits != 0x0000, fs->fsflags);
324  fs->fsflags &= ~flagbits;
325  return fs->fsflags;
326 }
327 
330 gpointer
332  Frame* f,
333  gpointer curpktpos)
334 {
335  guint8 * curpos = curpktpos;
336  guint8 * endpos = fs->pktend;
337 
338  g_return_val_if_fail(fs != NULL && f != NULL && fs->packet != NULL && curpktpos != NULL, NULL);
339  g_return_val_if_fail((curpos + f->dataspace(f)) <= endpos, NULL);
340 
341  tlv_set_guint16(curpos, f->type, fs->pktend);
342  curpos += 2; // sizeof(guint16)
343  tlv_set_guint24(curpos, f->length, fs->pktend);
344  curpos += 3; // 3 byte integer for length
345  if (f->length > 0) {
346  // Zero-length frames are just fine.
347  memcpy(curpos, f->value, f->length);
348  }
349  curpos += f->length;
350  return (gpointer)curpos;
351 }
352 
354 void
356 {
357  GSList* curframe;
358  g_debug("BEGIN Dumping FrameSet:");
359  for (curframe=fs->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
360  Frame* frame = CASTTOCLASS(Frame, curframe->data);
361  frame->dump(frame, ".... ");
362  }
363  g_debug("END FrameSet dump");
364 }
365 
368 {
369  GSList* curframe;
370  if (self->_seqframe) {
371  return self->_seqframe;
372  }
373  for (curframe=self->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
374  Frame* frame = CASTTOCLASS(Frame, curframe->data);
375  DEBUGMSG4("%s: LOOKING AT FRAME TYPE %d (but want sequence number)", __FUNCTION__, frame->type);
376  if (frame->type == FRAMETYPE_REQID) {
377  self->_seqframe = CASTTOCLASS(SeqnoFrame, frame);
378  return self->_seqframe;
379  }
380  }
381  return NULL;
382 }
383 
384 FSTATIC char *
385 _frameset_toString(gconstpointer vself)
386 {
387  GString* gsret = NULL;
388  char* ret = NULL;
389  const FrameSet* self = CASTTOCONSTCLASS(FrameSet, vself);
390  GSList* curframe;
391  const char * comma = "";
392 
393  g_return_val_if_fail(self != NULL, NULL);
394  gsret = g_string_new("");
395  g_string_append_printf(gsret, "FrameSet(fstype=%d, [", self->fstype);
396 
397  for (curframe=self->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
398  Frame* frame = CASTTOCLASS(Frame, curframe->data);
399  char* fstr;
400  g_return_val_if_fail(frame != NULL, NULL);
401  fstr = frame->baseclass.toString(&frame->baseclass);
402  g_string_append_printf(gsret, "%s[%s]", comma, fstr);
403  comma = ", ";
404  g_free(fstr); fstr = NULL;
405  }
406  g_string_append_printf(gsret, "])");
407  ret = gsret->str;
408  g_string_free(gsret, FALSE);
409  return ret;
410 }
411 
412 
414 WINEXPORT const char *
416 {
417  gpointer maybecrypt;
418  CryptFrame* cryptframe;
419 
420  // If we have an encryption frame it *must* be the second frame
421  // (the first frame is frame 0, and the second is frame 1)
422  maybecrypt = g_slist_nth_data(self->framelist, 1);
423  if (!OBJ_IS_A(maybecrypt, "CryptFrame")) {
424  return NULL;
425  }
426  cryptframe = CASTTOCLASS(CryptFrame, maybecrypt);
427  return cryptframe->sender_key_id;
428 }
429 
431 WINEXPORT const char *
433 {
435 }
436 
#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
void frameset_dump(const FrameSet *fs)
Dump out a FrameSet.
Definition: frameset.c:355
AssimObj baseclass
Definition: frameset.h:47
guint32 length
Frame Length.
Definition: frame.h:46
guint16 frameset_get_flags(FrameSet *fs)
Return the flags currently set on this FrameSet.
Definition: frameset.c:301
FSTATIC void _frameset_finalize(AssimObj *self)
static: finalize (free) frameset and all its constituent frames...
Definition: frameset.c:83
guint16 frameset_clear_flags(FrameSet *fs, guint16 flagbits)
Clear the given set of FrameSet flags (& ~flagbits)
Definition: frameset.c:319
#define DEBUGMSG4(...)
Definition: proj_classes.h:92
AssimObj baseclass
Base object class for our Class system.
Definition: frame.h:44
char * sender_key_id
Definition: cryptframe.h:55
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
SeqnoFrame *(* getseqno)(FrameSet *)
Return the sequence number for this frameset (if any)
Definition: frameset.h:55
FSTATIC char * _frameset_toString(gconstpointer)
Definition: frameset.c:385
FrameSet * frameset_new(guint16 frameset_type)
Construct a new frameset of the given type.
Definition: frameset.c:110
The SignFrame class object - implements digital signatures for FrameSets.
Definition: signframe.h:47
WINEXPORT const char * frameset_sender_identity(const FrameSet *self)
Return the identity of this Frameset's CryptFrame sender – NULL if None or Unknown.
Definition: frameset.c:432
gpointer pktend
Last byte past the end of the packet.
Definition: frameset.h:51
gpointer frame_append_to_frameset_packet(FrameSet *fs, Frame *f, gpointer curpktpos)
Append the given Frame to a FrameSet packet.
Definition: frameset.c:331
#define WINEXPORT
Definition: projectcommon.h:45
#define FSTATIC
Definition: projectcommon.h:31
#define GENERICTLV_HDRSZ
Size of Generic TLV header - ((type + length) == 5)
gpointer value
Frame Value (pointer)
Definition: frame.h:47
void(* dump)(const Frame *self, const char *prefix)
member function for dumping Frame
Definition: frame.h:56
guint32 compression_threshold
Definition: compressframe.h:43
FSTATIC void _frameset_indir_finalize(void *f)
static: finalize (free) frame
Definition: frameset.c:75
#define FREECLASSOBJ(obj)
Free a C-class object.
Definition: proj_classes.h:76
guint16 fstype
Type of frameset.
Definition: frameset.h:52
void tlv_set_guint24(void *vitem, guint32 item, const void *bufend)
Set an unsigned 24 bit (3-byte) integer to the given location with error checking and without caring ...
Definition: tlvhelper.c:146
void tlv_set_guint16(void *vitem, guint16 item, const void *bufend)
Set an unsigned 16 bit integer to the given location with error checking and without caring about byt...
Definition: tlvhelper.c:68
#define BINDDEBUG(Cclass)
BINDDEBUG is for telling the class system where the debug variable for this class is - put it in the ...
Definition: proj_classes.h:82
WINEXPORT const char * cryptframe_whois_key_id(const char *key_id)
Return the identity associated with the given key id.
Definition: cryptframe.c:346
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__
CompressFrame * compressframe_new(guint16 frame_type, guint16 compression_method)
This is our CompressFrame class object - used for representing a compression method.
Definition: compressframe.h:41
Frame * frame_new(guint16 frame_type, gsize framesize)
Construct a new frame - allowing for "derived" frame types...
Definition: frame.c:124
#define OBJ_IS_A(obj, Cclass)
Definition: proj_classes.h:72
gboolean(* isvalid)(const Frame *self, gconstpointer tlvptr, gconstpointer pktend)
TRUE if TLV data looks valid...
Definition: frame.h:50
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
#define REF(obj)
Definition: assimobj.h:39
gpointer packet
Pointer to packet (when constructed)
Definition: frameset.h:50
#define CASTTOCONSTCLASS(Cclass, obj)
Safely cast 'obj' to const C-class 'class' - verifying that it was registered as being of type class ...
Definition: proj_classes.h:71
void set_generic_tlv_type(gpointer tlv_vp, guint16 newtype, gconstpointer pktend)
Set the 'Type' of the given TLV TLV entry (first two bytes)
Project common header file.
WINEXPORT const char * frameset_sender_key_id(const FrameSet *self)
Return the key_id of this Frameset's CryptFrame sender – NULL if None.
Definition: frameset.c:415
Header file defining the data layouts for our Frames.
TLV helper interfaces definitions.
Frame baseclass
Definition: cryptframe.h:54
guint8 compression_method
Definition: compressframe.h:45
guint16 fsflags
Flags for frameset.
Definition: frameset.h:53
AssimObj * assimobj_new(guint objsize)
Definition: assimobj.c:74
const char * proj_class_classname(gconstpointer object)
Return the class name of one of our managed objects.
Definition: proj_classes.c:324
void set_generic_tlv_len(gpointer tlv_vp, guint32 newsize, gconstpointer pktend)
Set the 'Length' of the given generic TLV entry (first 3 bytes after type)
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.
GSList * framelist
List of frames in this FrameSet.
Definition: frameset.h:48
gsize(* dataspace)(const Frame *self)
How much space is needed to marshall this Frame?
Definition: frame.h:48
void frameset_prepend_frame(FrameSet *fs, Frame *f)
Prepend frame to the front of the frame list.
Definition: frameset.c:132
void frameset_construct_packet(FrameSet *fs, SignFrame *sigframe, CryptFrame *cryptframe, CompressFrame *compressframe)
Construct packet to go correspond to this frameset.
Definition: frameset.c:159
#define FRAMETYPE_END
FRAMETYPE_END Frame (frametype 0) Frame subclass - Frame class.
Definition: frametypes.h:63
void(* updatedata)(Frame *self, gpointer tlvptr, gconstpointer pktend, FrameSet *fs)
Update packet data.
Definition: frame.h:49
FrameSet class - used for collecting Frames when not on the wire, and for marshalling/demarshalling t...
Definition: frameset.h:46
gchar *(* toString)(gconstpointer)
Produce malloc-ed string representation.
Definition: assimobj.h:58
#define FRAMETYPE_SIG
FRAMETYPE_SIG Frame (frametype 1) Frame subclass - SignFrame class.
Definition: frametypes.h:82
#define DEBUGDECLARATIONS
Definition: proj_classes.h:79
FSTATIC SeqnoFrame * _frameset_getseqno(FrameSet *self)
Definition: frameset.c:367
This is our CryptFrame class object - representing an encryption method.
Definition: cryptframe.h:53
#define FRAMESET_INITSIZE
Definition: frameset.h:57
#define UNREF2(obj)
Definition: assimobj.h:36
#define FRAMETYPE_COMPRESS
FRAMETYPE_COMPRESS Frame (frametype 3) Frame subclass - CompressFrame class.
Definition: frametypes.h:122
#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
#define NEWSUBCLASS(Cclass, obj)
Definition: proj_classes.h:67
This is an SeqnoFrame class TLV (type, length, value) frame.
Definition: seqnoframe.h:43
#define FRAMETYPE_REQID
FRAMETYPE_REQID Frame (frametype 4) Frame subclass - SeqnoFrame class.
Definition: frametypes.h:138
#define FRAMETYPE_CRYPTCURVE25519
FRAMETYPE_CRYPTCURVE25519 Frame (frametype 2) Frame subclass - CryptCurve25519 class.
Definition: frametypes.h:104