NetSim Source Code Help v14.4
All 13 Components
 
Loading...
Searching...
No Matches
RPL_Message.c
1/************************************************************************************
2* Copyright (C) 2023 *
3* TETCOS, Bangalore. India *
4* *
5* Tetcos owns the intellectual property rights in the Product and its content. *
6* The copying, redistribution, reselling or publication of any or all of the *
7* Product or its content without express prior written consent of Tetcos is *
8* prohibited. Ownership and / or any other right relating to the software and all *
9* intellectual property rights therein shall remain at all times with Tetcos. *
10* *
11* Author: Shashi Kant Suman *
12* *
13* ---------------------------------------------------------------------------------*/
14#include "main.h"
15#include "RPL.h"
16#include "RPL_Message.h"
17
18//Function definition
19static void rpl_dodag_config_option_destroy(PRPL_DODAG_CONFIG_OPTION opt);
20static PRPL_DODAG_CONFIG_OPTION rpl_dodag_config_option_copy(PRPL_DODAG_CONFIG_OPTION opt);
21static PRPL_TARGET_OPTION rpl_rpl_target_option_copy(PRPL_TARGET_OPTION target);
22static void rpl_rpl_target_option_destroy(PRPL_TARGET_OPTION target);
23
24static double get_rpl_packet_size_fixed(RPL_CTRL_MSG_CODE code)
25{
26 switch (code)
27 {
28 case Destination_Advertisement_Object:
29 return RPL_CTRL_MSG_SIZE_FIXED + RPL_DAO_BASE_SIZE;
30 break;
31 case Destination_Advertisement_Object_Acknowledgment:
32 return RPL_CTRL_MSG_SIZE_FIXED + RPL_DAOACK_BASE_SIZE;
33 break;
34 case DODAG_Information_Object:
35 return RPL_CTRL_MSG_SIZE_FIXED + RPL_DIO_BASE_SIZE;
36 break;
37 case DODAG_Information_Solicitation:
38 return RPL_CTRL_MSG_SIZE_FIXED + RPL_DIS_BASE_SIZE;
39 break;
40 default:
41 fnNetSimError("Unknow rpl msg code %d in %s\n", code, __FUNCTION__);
42 return 0;
43 break;
44 }
45}
46
47static void set_option_in_msg(NetSim_PACKET* packet, RPL_OPTION_TYPE type, void* option)
48{
49 PRPL_CTRL_MSG msg = GET_PRPL_CTRL_MSG(packet);
50 if (msg->option_count)
51 msg->options = (PRPL_OPTION*)realloc(msg->options, (msg->option_count + 1) * sizeof* msg->options);
52 else
53 msg->options = (PRPL_OPTION*)calloc(1, sizeof* msg->options);
54 msg->options[msg->option_count] = (PRPL_OPTION)calloc(1, sizeof* msg->options[msg->option_count]);
55 msg->options[msg->option_count]->option = option;
56 msg->options[msg->option_count]->type = type;
57 msg->option_count++;
58}
59
60void* get_option_from_msg(PRPL_CTRL_MSG msg, RPL_OPTION_TYPE type)
61{
62 UINT i;
63 if (!msg)
64 return NULL;
65 for (i = 0; i < msg->option_count; i++)
66 {
67 if (msg->options[i]->type == type)
68 return msg->options[i]->option;
69 }
70 return NULL;
71}
72
73void** get_all_option_from_msg(PRPL_CTRL_MSG msg, RPL_OPTION_TYPE type, UINT* count)
74{
75 UINT i;
76 UINT c=0;
77 void** ret=NULL;
78 if (!msg)
79 {
80 *count = 0;
81 return NULL;
82 }
83 for (i = 0; i < msg->option_count; i++)
84 {
85 if (msg->options[i]->type == type)
86 {
87 ret = (void**)realloc(ret, (c + 1) * sizeof(void*));
88 ret[c] = msg->options[i]->option;
89 c++;
90 }
91 }
92 *count = c;
93 return ret;
94}
95
96void rpl_option_destroy(PRPL_OPTION option)
97{
98 switch (option->type)
99 {
100 case RPLOPTION_DODAGConfiguration:
101 rpl_dodag_config_option_destroy(option->option);
102 break;
103 case RPLOPTION_RPLTARGET:
104 rpl_rpl_target_option_destroy(option->option);
105 break;
106 default:
107 fnNetSimError("Unknown option %d in %s\n",
108 option->type, __FUNCTION__);
109 break;
110 }
111 free(option);
112}
113
114PRPL_OPTION rpl_option_copy(PRPL_OPTION option)
115{
116 PRPL_OPTION ret = (PRPL_OPTION)calloc(1, sizeof* ret);
117 memcpy(ret, option, sizeof* ret);
118
119 switch (option->type)
120 {
121 case RPLOPTION_DODAGConfiguration:
122 ret->option = rpl_dodag_config_option_copy(option->option);
123 break;
124 case RPLOPTION_RPLTARGET:
125 ret->option = rpl_rpl_target_option_copy(option->option);
126 break;
127 default:
128 fnNetSimError("Unknown option %d in %s\n",
129 option->type, __FUNCTION__);
130 break;
131 }
132
133 return ret;
134}
135
136static PRPL_CTRL_MSG get_icmp_rpl_msg(RPL_CTRL_MSG_CODE code)
137{
138 PRPL_CTRL_MSG msg = (PRPL_CTRL_MSG)calloc(1, sizeof* msg);
139 msg->Type = ICMP_TYPE_RPL;
140 msg->Code = code;
141 return msg;
142}
143
144static void rpl_get_packet_type_sz(char* str, RPL_CTRL_MSG_CODE code)
145{
146 switch (code)
147 {
148 case Consistency_Check:
149 strcpy(str, "Consistency_check");
150 break;
151 case Destination_Advertisement_Object:
152 strcpy(str, "DAO");
153 break;
154 case Destination_Advertisement_Object_Acknowledgment:
155 strcpy(str, "DAO-ACK");
156 break;
157 case DODAG_Information_Object:
158 strcpy(str, "DIO");
159 break;
160 case DODAG_Information_Solicitation:
161 strcpy(str, "DIS");
162 break;
163 }
164}
165
166static NetSim_PACKET* create_rpl_ctrl_msg(RPL_CTRL_MSG_CODE code,
167 double time,
168 NETSIM_ID src,
169 NETSIM_ID dest)
170{
171 NetSim_PACKET* packet = fn_NetSim_Packet_CreatePacket(NETWORK_LAYER);
172 packet->nPacketType = PacketType_Control;
173 packet->pstruNetworkData->dArrivalTime = time;
174 packet->pstruNetworkData->dOverhead = get_rpl_packet_size_fixed(code);
175 packet->pstruNetworkData->nRoutingProtocol = NW_PROTOCOL_RPL;
176 packet->pstruNetworkData->szSourceIP = IP_COPY(DEVICE_NWADDRESS(src, 1));
177 packet->pstruNetworkData->szGatewayIP = IP_COPY(DEVICE_NWADDRESS(src, 1));
178 if (dest)
179 packet->pstruNetworkData->szDestIP = IP_COPY(DEVICE_NWADDRESS(dest, 1));
180 else
181 packet->pstruNetworkData->szDestIP = GET_BROADCAST_IP(6);
182 packet->pstruNetworkData->nTTL = MAX_TTL;
183 packet->dEventTime = time;
184 packet->nControlDataType = GET_RPL_CTRL_PACKET_TYPE(code);
185 packet->nSourceId = src;
186 add_dest_to_packet(packet, dest);
187 packet->nTransmitterId = src;
188
189 rpl_get_packet_type_sz(packet->szPacketType, code);
190
191 packet->pstruNetworkData->Packet_RoutingProtocol = get_icmp_rpl_msg(code);
192 return packet;
193}
194
195//DIO
196static PRPL_DIO_BASE create_dio_base()
197{
198 PRPL_DIO_BASE b = (PRPL_DIO_BASE)calloc(1, sizeof* b);
199 b->Prf = RPL_DEFAULT_DAG_PREF;
200 b->Rank = INFINITE_RANK;
201 b->MOP = RPL_DEFAULT_MOP;
202 return b;
203}
204
205static PRPL_DODAG_CONFIG_OPTION create_dodag_config_option()
206{
207 PRPL_DODAG_CONFIG_OPTION o = (PRPL_DODAG_CONFIG_OPTION)calloc(1, sizeof* o);
208 o->Type = 0x04;
209 o->OptLength = 14;
210 return o;
211}
212
213static void rpl_dodag_config_option_destroy(PRPL_DODAG_CONFIG_OPTION opt)
214{
215 free(opt);
216}
217
218static PRPL_DODAG_CONFIG_OPTION rpl_dodag_config_option_copy(PRPL_DODAG_CONFIG_OPTION opt)
219{
220 PRPL_DODAG_CONFIG_OPTION ret = (PRPL_DODAG_CONFIG_OPTION)calloc(1, sizeof* ret);
221 memcpy(ret, opt, sizeof* ret);
222 return ret;
223}
224
225NetSim_PACKET* create_root_dio_message(NETSIM_ID ndevId, double time, bool include_dodag_config, bool include_seq_num)
226{
227 PRPL_NODE r = GET_RPL_NODE(ndevId);
228
229 NetSim_PACKET* packet = create_rpl_ctrl_msg(DODAG_Information_Object, time, ndevId, 0);
230 PRPL_DIO_BASE diobase = create_dio_base();
231 SET_BASE_IN_MSG(packet, diobase);
232
233 if (r->root_info->dodag_id != NULL)
234 diobase->DODAGID = IP_COPY(r->root_info->dodag_id);
235 else
236 diobase->DODAGID = IP_COPY(DEVICE_NWADDRESS(ndevId,1));
237
238 diobase->Prf = r->root_info->dodag_pref;
239 diobase->Rank = RPL_RANK_ROOT;
240 diobase->G = r->root_info->grounded;
241
242 if (include_seq_num)
243 diobase->DTSN = seq_num_mapping_get(diobase->DODAGID)->seq_num;
244 else
245 diobase->DTSN = 0;
246 diobase->RPLInstanceID = r->RPLInstanceId;
247
248 if (include_dodag_config)
249 {
250 PRPL_DODAG_CONFIG_OPTION opt = create_dodag_config_option();
251 set_option_in_msg(packet, RPLOPTION_DODAGConfiguration ,opt);
252
253 opt->DIOIntDoubl = r->root_info->dio_interval_doublings;
254 opt->DIOIntMin = r->root_info->dio_interval_min;
255 opt->DIORedun = r->root_info->dio_redundancy_constant;
256 opt->MaxRankIncrease = r->root_info->max_rank_inc;
257 opt->MinHopRankIncrease = r->root_info->min_hop_rank_inc;
258 }
259
260 return packet;
261}
262
263static NetSim_PACKET* create_joined_dio_message(NETSIM_ID ndevId, double time, bool include_dodag_config)
264{
265 PRPL_NODE r = GET_RPL_NODE(ndevId);
266
267 NetSim_PACKET* packet = create_rpl_ctrl_msg(DODAG_Information_Object, time, ndevId, 0);
268 PRPL_DIO_BASE diobase = create_dio_base();
269 SET_BASE_IN_MSG(packet, diobase);
270
271 diobase->DODAGID = r->joined_dodag->dodag_id;
272 diobase->Prf = r->joined_dodag->dodag_pref;
273 diobase->Rank = r->joined_dodag->rank;
274 diobase->G = r->joined_dodag->grounded;
275 diobase->DTSN = r->joined_dodag->seq_num;
276 diobase->RPLInstanceID = r->RPLInstanceId;
277
278 if (include_dodag_config)
279 {
280 PRPL_DODAG_CONFIG_OPTION opt = create_dodag_config_option();
281 set_option_in_msg(packet, RPLOPTION_DODAGConfiguration, opt);
282
283 opt->DIOIntDoubl = r->joined_dodag->dio_interval_doublings;
284 opt->DIOIntMin = r->joined_dodag->dio_interval_min;
285 opt->DIORedun = r->joined_dodag->dio_redundancy_constant;
286 opt->MaxRankIncrease = r->joined_dodag->max_rank_inc;
287 opt->MinHopRankIncrease = r->joined_dodag->min_hop_rank_inc;
288 }
289
290 return packet;
291}
292
293NetSim_PACKET* create_current_dio_message(NETSIM_ID ndevId, double time, bool include_dodag_config)
294{
295 PRPL_NODE r = GET_RPL_NODE(ndevId);
296 if (rpl_node_is_joined(r))
297 {
298 return create_joined_dio_message(ndevId, time, include_dodag_config);
299 }
300 else if (rpl_node_is_root(r))
301 {
302 return create_root_dio_message(ndevId, time, include_dodag_config, TRUE);
303 }
304 else if (rpl_node_is_poisoning(r))
305 {
306 return create_joined_dio_message(ndevId, time, include_dodag_config);
307 }
308 else
309 {
310 return NULL;
311 }
312}
313
314PRPL_CTRL_MSG rpl_dio_pdu_duplicate(PRPL_CTRL_MSG dio)
315{
316 PRPL_CTRL_MSG new_dio = (PRPL_CTRL_MSG)calloc(1, sizeof* new_dio);
317 memcpy(new_dio, dio, sizeof* new_dio);
318
319 PRPL_DIO_BASE new_base = (PRPL_DIO_BASE)calloc(1, sizeof* new_base);
320 new_dio->Base = new_base;
321 memcpy(new_base, dio->Base, sizeof* new_base);
322
323 new_dio->options = (PRPL_OPTION*)calloc(dio->option_count, sizeof* new_dio->options);
324 UINT i;
325 for (i = 0; i < dio->option_count; i++)
326 {
327 new_dio->options[i] = (PRPL_OPTION)calloc(1, sizeof* new_dio->options[i]);
328 new_dio->options[i]->type = dio->options[i]->type;
329 switch (new_dio->options[i]->type)
330 {
331 case RPLOPTION_DODAGConfiguration:
332 new_dio->options[i]->option = calloc(1, sizeof(RPL_DODAG_CONFIG_OPTION));
333 memcpy(new_dio->options[i]->option, dio->options[i]->option, sizeof(RPL_DODAG_CONFIG_OPTION));
334 break;
335 default:
336 fnNetSimError("Unknown option %d in %s\n", new_dio->options[i]->type, __FUNCTION__);
337 break;
338 }
339 }
340 return new_dio;
341}
342
343void rpl_dio_pdu_free(PRPL_CTRL_MSG dio)
344{
345 if (!dio)
346 return;
347 IP_FREE(((PRPL_DIO_BASE)dio->Base)->DODAGID);
348 free((PRPL_DIO_BASE)dio->Base);
349 UINT i;
350 for (i = 0; i < dio->option_count; i++)
351 {
352 free((PRPL_DODAG_CONFIG_OPTION)dio->options[i]->option);
353 free(dio->options[i]);
354 }
355 free(dio->options);
356 free(dio);
357}
358
359//DAO
360static PRPL_DAO_BASE create_dao_base(PRPL_NODE rpl)
361{
362 PRPL_DAO_BASE b = (PRPL_DAO_BASE)calloc(1, sizeof* b);
363 b->RPLInstanceID = rpl->RPLInstanceId;
364 b->D = false; //No local RPL Instance
365 b->K = true;
366 b->DAOSequence = ++rpl->DaoSequence;
367 return b;
368}
369
370NetSim_PACKET* create_dao_message(NETSIM_ID ndevid, double time,NETSIM_ID parent)
371{
372 PRPL_NODE rpl = GET_RPL_NODE(ndevid);
373 NetSim_PACKET* packet = create_rpl_ctrl_msg(Destination_Advertisement_Object, time, ndevid, parent);
374 PRPL_DAO_BASE dao = create_dao_base(rpl);
375 SET_BASE_IN_MSG(packet, dao);
376 return packet;
377}
378
379void create_and_add_rpl_target_option(NetSim_PACKET* dao_pdu, UINT8 prefix_len, NETSIM_IPAddress dest)
380{
381 PRPL_TARGET_OPTION target = (PRPL_TARGET_OPTION)calloc(1, sizeof* target);
382 target->Type = RPLOPTION_RPLTARGET;
383 target->Option_Length = 18;
384 target->Prefix_Length = prefix_len;
385 target->Traget_Prefix = IP_COPY(dest);
386 set_option_in_msg(dao_pdu, RPLOPTION_RPLTARGET, target);
387}
388
389static PRPL_TARGET_OPTION rpl_rpl_target_option_copy(PRPL_TARGET_OPTION target)
390{
391 PRPL_TARGET_OPTION ret = (PRPL_TARGET_OPTION)calloc(1, sizeof* ret);
392 memcpy(ret, target, sizeof* ret);
393 return ret;
394}
395
396static void rpl_rpl_target_option_destroy(PRPL_TARGET_OPTION target)
397{
398 free(target);
399}
400
401//DIS
402static PRPL_DIS_BASE create_dis_base(PRPL_NODE rpl)
403{
404 PRPL_DIS_BASE b = (PRPL_DIS_BASE)calloc(1, sizeof* b);
405 return b;
406}
407
408NetSim_PACKET* create_dis_message(NETSIM_ID ndevid, double time)
409{
410 PRPL_NODE rpl = GET_RPL_NODE(ndevid);
411 NetSim_PACKET* packet = create_rpl_ctrl_msg(DODAG_Information_Solicitation, time, ndevid, 0);
412 PRPL_DIS_BASE dis = create_dis_base(rpl);
413 SET_BASE_IN_MSG(packet, dis);
414 return packet;
415}
416
417// Message Processing
418void rpl_node_send_msg(NETSIM_ID ndevid, NetSim_PACKET* packet)
419{
420 NetSim_EVENTDETAILS pevent;
421 memset(&pevent, 0, sizeof pevent);
422 pevent.dEventTime = pstruEventDetails->dEventTime;
423 pevent.dPacketSize = fnGetPacketSize(packet);
424 pevent.nDeviceId = ndevid;
425 pevent.nDeviceType = DEVICE_TYPE(ndevid);
426 pevent.nEventType = NETWORK_OUT_EVENT;
427 pevent.nPacketId = packet->nPacketId;
428 pevent.nProtocolId = NW_PROTOCOL_IPV6;
429 pevent.pPacket = packet;
430 fnpAddEvent(&pevent);
431}
432
433void rpl_process_ctrl_msg()
434{
435 switch (pstruEventDetails->pPacket->nControlDataType % 100)
436 {
437 case DODAG_Information_Object:
438 rpl_process_dio_msg();
439 break;
440 case Destination_Advertisement_Object:
441 rpl_process_dao_msg();
442 break;
443 case DODAG_Information_Solicitation:
444 rpl_process_dis_msg();
445 break;
446 default:
447 fnNetSimError("Unknown rpl ctrl msg %d in %s",
448 pstruEventDetails->pPacket->nControlDataType,
449 __FUNCTION__);
450 break;
451 }
452}