The Assimilation Project
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ipportframe.c
Go to the documentation of this file.
1 
28 #include <string.h>
29 #include <projectcommon.h>
30 #include <frameset.h>
31 #include <ipportframe.h>
32 #include <frametypes.h>
33 #include <generic_tlv_min.h>
34 #include <tlvhelper.h>
35 #include <address_family_numbers.h>
36 
37 FSTATIC gboolean _ipportframe_default_isvalid(const Frame *, gconstpointer, gconstpointer);
38 FSTATIC void _ipportframe_setaddr(IpPortFrame* self, guint16 frametype, guint16 port, gconstpointer addr, gsize addrlen);
42 FSTATIC IpPortFrame* ipportframe_new(guint16 frame_type, gsize framesize);
43 FSTATIC gchar* _ipportframe_toString(gconstpointer aself);
45 
63 #define TLVOVERHEAD (sizeof(guint16)+sizeof(guint16))
64 #define TLVIPV4SIZE (TLVOVERHEAD+4)
65 #define TLVIPV6SIZE (TLVOVERHEAD+16)
66 
67 
74 FSTATIC gboolean
76  gconstpointer tlvptr,
77  gconstpointer pktend)
78 {
79  guint16 address_family = 0;
80  guint16 portnumber;
81  const guint16* int16ptr;
82  guint16 pktsize;
83 
84  if (tlvptr == NULL) {
85  // Validate the local copy instead of the TLV version.
86  tlvptr = self->value;
87  g_return_val_if_fail(tlvptr != NULL, FALSE);
88  pktend = (const guint8*)tlvptr + self->length;
89  int16ptr = (const guint16*)self->value;
90  pktsize = self->length;
91  }else{
92  pktsize = get_generic_tlv_len(tlvptr, pktend);
93  int16ptr = (const guint16*)get_generic_tlv_value(tlvptr, pktend);
94  }
95 
96  if (pktsize < TLVIPV4SIZE || int16ptr == NULL) {
97  return FALSE;
98  }
99 
100  // First field -- port number: 16-bit unsigned integer - network byte order
101  portnumber = tlv_get_guint16(int16ptr, pktend);
102  if (portnumber == 0) {
103  g_warning("%s.%d: Port is zero", __FUNCTION__, __LINE__);
104  return FALSE;
105  }
106 
107  // Second field -- address family: 16-bit unsigned integer - network byte order
108  address_family = tlv_get_guint16(int16ptr+1, pktend);
109 
110  switch(address_family) {
111  case ADDR_FAMILY_IPV4: // IPv4
112  return (TLVIPV4SIZE == pktsize);
113 
114  case ADDR_FAMILY_IPV6: // IPv6
115  return (TLVIPV6SIZE == pktsize);
116 
117  default:
118  break;
119 
120  }
121  return FALSE;
122 }
123 
124 FSTATIC void
125 _ipportframe_setaddr(IpPortFrame* f, //<[in/out] Frame to set the address type for
126  guint16 addrtype, //<[in] IANA address type
127  guint16 port, //<[in] port
128  gconstpointer addr,//<[in] Address blob
129  gsize addrlen) //<[in] size of address
130 {
131  gsize blobsize = addrlen + (2*sizeof(guint16));
132  guint8* blob = MALLOC(blobsize);
133  guint8* blobend = blob + blobsize;
134 
135  g_return_if_fail(blob != NULL);
136 
137  if (f->baseclass.value != NULL) {
138  FREE(f->baseclass.value);
139  f->baseclass.value = NULL;
140  }
141 
142  tlv_set_guint16(blob, port, blobend);
143  tlv_set_guint16(blob+sizeof(guint16), addrtype, blobend);
144  memcpy(blob+sizeof(guint16)+sizeof(guint16), addr, addrlen);
145  f->baseclass.length = blobsize;
146  f->baseclass.value = blob;
147  f->port = port;
148  f->_addr = netaddr_new(0, 0, addrtype, addr, addrlen);
149  f->_addr->setport(f->_addr, port);
150 }
151 
152 
155 {
156  return self->_addr;
157 }
158 
159 
161 FSTATIC void
163 {
164  IpPortFrame* self = CASTTOCLASS(IpPortFrame, obj);
165  if (self->_addr) {
166  UNREF(self->_addr);
167  }
168  if (self->baseclass.value) {
169  FREE(self->baseclass.value);
170  self->baseclass.value = NULL;
171  }
172  self->_basefinal(CASTTOCLASS(AssimObj, self)); self = NULL;
173 }
174 
178 ipportframe_new(guint16 frame_type,
179  gsize framesize)
180 {
181  IpPortFrame* aframe;
182 
183  if (framesize < sizeof(IpPortFrame)){
184  framesize = sizeof(IpPortFrame);
185  }
186 
187  aframe = NEWSUBCLASS(IpPortFrame, frame_new(frame_type, framesize));
189 
191  aframe->_basefinal = aframe->baseclass.baseclass._finalize;
194  return aframe;
195 }
196 
199 ipportframe_ipv4_new(guint16 frame_type,
200  guint16 port,
202  gconstpointer addr)
203 {
204  IpPortFrame* ret;
205  g_return_val_if_fail(addr != NULL, NULL);
206  if (port == 0) {
207  return NULL;
208  }
209  ret = ipportframe_new(frame_type, 0);
210  g_return_val_if_fail(ret != NULL, NULL);
211  _ipportframe_setaddr(ret, ADDR_FAMILY_IPV4, port, addr, 4);
212  return ret;
213 }
214 
217 ipportframe_ipv6_new(guint16 frame_type,
218  guint16 port,
219  gconstpointer addr)
220 {
221  IpPortFrame* ret;
222  g_return_val_if_fail(addr != NULL, NULL);
223  if (port == 0) {
224  return NULL;
225  }
226  ret = ipportframe_new(frame_type, 0);
227  g_return_val_if_fail(ret != NULL, NULL);
228  _ipportframe_setaddr(ret, ADDR_FAMILY_IPV6, port, addr, 16);
229  return ret;
230 }
231 
234 ipportframe_netaddr_new(guint16 frame_type, NetAddr* addr)
235 {
236  guint16 port = addr->port(addr);
237  gpointer body = addr->_addrbody;
238 
239  if (port == 0) {
240  return NULL;
241  }
242 
243  switch(addr->addrtype(addr)) {
244  case ADDR_FAMILY_IPV4:
245  return ipportframe_ipv4_new(frame_type, port, body);
246  break;
247  case ADDR_FAMILY_IPV6:
248  return ipportframe_ipv6_new(frame_type, port, body);
249  break;
250  }
251  return NULL;
252 }
253 
254 
259 ipportframe_tlvconstructor(gconstpointer tlvstart,
260  gconstpointer pktend,
261  gpointer* ignorednewpkt,
262  gpointer* ignoredpktend)
263 
264 {
265  guint16 frametype = get_generic_tlv_type(tlvstart, pktend);
266  guint16 framelength = get_generic_tlv_len(tlvstart, pktend);
267  const guint8* framevalue = get_generic_tlv_value(tlvstart, pktend);
268  IpPortFrame * ret;
269  guint16 addr_family;
270  guint16 port;
271 
272 // +-------------+----------------+-------------+---------------+--------------------+
273 // | frametype | f_length | Port Number | Address Type | address-data |
274 // | 16 bits) | (24-bits) | 2 bytes | 2 bytes | (f_length-4 bytes) |
275 // +-------------+----------------+-------------+---------------+--------------------+
276  (void)ignorednewpkt; (void)ignoredpktend;
277  port = tlv_get_guint16(framevalue, pktend);
278  if (port == 0) {
279  return NULL;
280  }
281 
282  addr_family = tlv_get_guint16(framevalue+sizeof(guint16), pktend);
283 
284  switch (addr_family) {
285  case ADDR_FAMILY_IPV4:
286  g_return_val_if_fail(framelength == TLVIPV4SIZE, NULL);
287  break;
288  case ADDR_FAMILY_IPV6:
289  g_return_val_if_fail(framelength == TLVIPV6SIZE, NULL);
290  break;
291  default:
292  g_return_val_if_reached(NULL);
293  break;
294  }
295 
296  ret = ipportframe_new(frametype, 0);
297  ret->baseclass.length = framelength;
298  _ipportframe_setaddr(ret, addr_family, port, framevalue+TLVOVERHEAD
299  , framelength-TLVOVERHEAD);
300  if (!_ipportframe_default_isvalid(&ret->baseclass, tlvstart, pktend)) {
301  UNREF2(ret);
302  g_return_val_if_reached(NULL);
303  }
304  return &ret->baseclass;
305 }
307 FSTATIC gchar*
308 _ipportframe_toString(gconstpointer aself)
309 {
310  const IpPortFrame* self = CASTTOCONSTCLASS(IpPortFrame, aself);
311  char * selfstr = self->_addr->baseclass.toString(&self->_addr->baseclass);
312  char * ret;
313 
314  ret = g_strdup_printf("IpPortFrame(%d, %s)", self->baseclass.type, selfstr);
315  g_free(selfstr);
316  return ret;
317 }