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 
262 {
263  guint16 frametype = get_generic_tlv_type(tlvstart, pktend);
264  guint16 framelength = get_generic_tlv_len(tlvstart, pktend);
265  const guint8* framevalue = get_generic_tlv_value(tlvstart, pktend);
266  IpPortFrame * ret;
267  guint16 addr_family;
268  guint16 port;
269 
270 // +-------------+----------------+-------------+---------------+--------------------+
271 // | frametype | f_length | Port Number | Address Type | address-data |
272 // | 16 bits) | (16-bits) | 2 bytes | 2 bytes | (f_length-4 bytes) |
273 // +-------------+----------------+-------------+---------------+--------------------+
274  port = tlv_get_guint16(framevalue, pktend);
275  if (port == 0) {
276  return NULL;
277  }
278 
279  addr_family = tlv_get_guint16(framevalue+sizeof(guint16), pktend);
280 
281  switch (addr_family) {
282  case ADDR_FAMILY_IPV4:
283  g_return_val_if_fail(framelength == TLVIPV4SIZE, NULL);
284  break;
285  case ADDR_FAMILY_IPV6:
286  g_return_val_if_fail(framelength == TLVIPV6SIZE, NULL);
287  break;
288  default:
289  g_return_val_if_reached(NULL);
290  break;
291  }
292 
293  ret = ipportframe_new(frametype, 0);
294  ret->baseclass.length = framelength;
295  _ipportframe_setaddr(ret, addr_family, port, framevalue+TLVOVERHEAD
296  , framelength-TLVOVERHEAD);
297  if (!_ipportframe_default_isvalid(&ret->baseclass, tlvstart, pktend)) {
298  UNREF2(ret);
299  g_return_val_if_reached(NULL);
300  }
301  return &ret->baseclass;
302 }
304 FSTATIC gchar*
305 _ipportframe_toString(gconstpointer aself)
306 {
307  const IpPortFrame* self = CASTTOCONSTCLASS(IpPortFrame, aself);
308  char * selfstr = self->_addr->baseclass.toString(&self->_addr->baseclass);
309  char * ret;
310 
311  ret = g_strdup_printf("IpPortFrame(%d, %s)", self->baseclass.type, selfstr);
312  g_free(selfstr);
313  return ret;
314 }