27#include "NetSim_utility.h"
29#include "../Firewall/Firewall.h"
34 ptrIP_ROUTINGTABLE table;
39#define MATCH_ALLOC() (ptrMATCH)list_alloc(sizeof(MATCH),offsetof(MATCH,ele))
41static void print_match_table(ptrMATCH match, NETSIM_ID d, NETSIM_IPAddress dest, NETSIM_IPAddress src)
43 static FILE* fp = NULL;
44#ifdef PRINT_MATCH_TABLE
47 fp = fopen(
"MatchTable.csv",
"w");
48 fprintf(fp,
"Dest,Gateway,Ifcount,Iflist,\n");
54 fprintf(fp,
" Device %d, dest = %s, Src = %s\n", d, dest->str_ip, src->str_ip);
58 fprintf(fp,
"%s,%s,%d,",
59 match->table->networkDestination->str_ip,
60 match->table->gateway?match->table->gateway->str_ip:
"EMPTY",
61 match->table->interfaceCount);
62 for (i = 0; i < match->table->interfaceCount; i++)
63 fprintf(fp,
"%s,", match->table->Interface[i]->str_ip);
65 match = LIST_NEXT(match);
72static void free_match_table(ptrMATCH l)
78static int match_check(ptrMATCH m1, ptrMATCH m2)
80 if (m2->bitsCount > m1->bitsCount)
82 if (m2->bitsCount == m1->bitsCount)
84 if (m2->metric < m1->metric)
90static void add_to_match_list(ptrMATCH* l, ptrMATCH c)
92 LIST_ADD(l, c, match_check);
95static UINT get_bit_match_count(NETSIM_IPAddress ip1)
99 IP_TO_BINARY(ip1, b1);
101 UINT l = (UINT)strlen(b1);
103 for (i = 0; i < l; i++)
111static ptrMATCH get_match_table(ptrIP_ROUTINGTABLE table, NETSIM_IPAddress dest,
bool isStatic)
115 NETSIM_IPAddress network1;
116 NETSIM_IPAddress network2;
120 bool isC = (isStatic && table->type == RoutingType_STATIC) || (!isStatic);
123 table = LIST_NEXT(table);
127 if (!IP_COMPARE(dest, table->networkDestination) && ICMP_CHECKSTATE(dest))
131 c->bitsCount = dest->type == 4 ? 32 : 128;
132 if (table->Metric <= 0)
135 c->metric = table->Metric;
136 add_to_match_list(&l, c);
138 else if (dest->type == table->networkDestination->type)
140 network1 = IP_NETWORK_ADDRESS(dest, table->netMask, table->prefix_len);
141 network2 = IP_NETWORK_ADDRESS(table->networkDestination, table->netMask, table->prefix_len);
142 if (!IP_COMPARE(network1, network2))
144 if (ICMP_CHECKSTATE(table->gateway))
148 c->bitsCount = dest->type == 4 ? get_bit_match_count(table->netMask) : table->prefix_len;
149 c->metric = table->Metric;
150 add_to_match_list(&l, c);
154 table = LIST_NEXT(table);
160void free_ip_route(ptrIP_FORWARD_ROUTE route)
162 if (route == NULL)
return;
163 free(route->interfaceId);
164 free(route->nextHop);
165 free(route->nextHopId);
166 free(route->gateway);
170static void update_route_entry(ptrMATCH match, ptrIP_FORWARD_ROUTE route,NETSIM_IPAddress dest)
176 ptrIP_ROUTINGTABLE table = match->table;
178 route->count = table->interfaceCount;
180 route->nextHop = calloc(table->interfaceCount,
sizeof* route->nextHop);
181 route->gateway = calloc(table->interfaceCount,
sizeof* route->gateway);
182 route->interfaceId = calloc(table->interfaceCount,
sizeof* route->interfaceId);
183 route->nextHopId = calloc(table->interfaceCount,
sizeof* route->nextHopId);
185 for (i = 0; i < table->interfaceCount; i++)
188 route->nextHop[i] = table->gateway;
190 route->nextHop[i] = dest;
192 route->gateway[i] = table->Interface[i];
194 route->interfaceId[i] = table->nInterfaceId[i];
196 if (!table->nGatewayId && table->gateway)
197 table->nGatewayId = fn_NetSim_Stack_GetDeviceId_asIP(table->gateway, &in);
199 if (table->nGatewayId)
200 route->nextHopId[i] = table->nGatewayId;
202 route->nextHopId[i] = 0;
207static ptrMATCH choose_match_for_reserved_address(ptrMATCH match,
208 NETSIM_IPAddress dest,
209 NETSIM_IPAddress src)
211 bool isResevedAddr = is_reserved_multicast_address(dest);
217 if (isCorrectRoute(&match->table, dest, src))
219 match = LIST_NEXT(match);
224static void multicast_update_route_entry(ptrMATCH match,
225 ptrIP_FORWARD_ROUTE route,
226 NETSIM_IPAddress dest,
227 NETSIM_IPAddress src)
233 match = choose_match_for_reserved_address(match, dest, src);
236 ptrIP_ROUTINGTABLE table = match->table;
238 route->count = table->interfaceCount;
240 route->nextHop = calloc(table->interfaceCount,
sizeof* route->nextHop);
241 route->gateway = calloc(table->interfaceCount,
sizeof* route->gateway);
242 route->interfaceId = calloc(table->interfaceCount,
sizeof* route->interfaceId);
243 route->nextHopId = calloc(table->interfaceCount,
sizeof* route->nextHopId);
245 for (i = 0, c = 0; i < table->interfaceCount; i++, c++)
247 if (table->nInterfaceId[i] == pstruEventDetails->nInterfaceId)
255 route->nextHop[c] = table->gateway;
257 route->nextHop[c] = dest;
259 route->gateway[c] = table->Interface[i];
261 route->interfaceId[c] = table->nInterfaceId[i];
263 if (!table->nGatewayId && table->gateway)
264 table->nGatewayId = fn_NetSim_Stack_GetDeviceId_asIP(table->gateway, &in);
266 if (table->nGatewayId)
267 route->nextHopId[c] = table->nGatewayId;
269 route->nextHopId[c] = 0;
274static void route_onlink(NETSIM_ID d,
275 NETSIM_IPAddress src,
276 NETSIM_IPAddress dest,
277 ptrIP_FORWARD_ROUTE route)
281 for (i = 0; i < DEVICE(d)->nNumOfInterface; i++)
283 if (IP_IS_IN_SAME_NETWORK(src,
284 DEVICE_NWADDRESS(d, i + 1),
285 DEVICE_INTERFACE(d, i + 1)->szSubnetMask,
286 DEVICE_INTERFACE(d, i + 1)->prefix_len))
291 route->gateway = realloc(route->gateway, route->count *
sizeof* route->gateway);
292 route->interfaceId = realloc(route->interfaceId, route->count *
sizeof* route->interfaceId);
293 route->nextHop = realloc(route->nextHop, route->count *
sizeof* route->nextHop);
294 route->nextHopId = realloc(route->nextHopId, route->count *
sizeof* route->nextHopId);
298 route->gateway = calloc(1, route->count *
sizeof* route->gateway);
299 route->interfaceId = calloc(1, route->count *
sizeof* route->interfaceId);
300 route->nextHop = calloc(1, route->count *
sizeof* route->nextHop);
301 route->nextHopId = calloc(1, route->count *
sizeof* route->nextHopId);
303 route->gateway[c] = DEVICE_NWADDRESS(d, i + 1);
304 route->interfaceId[c] = i + 1;
305 route->nextHop[c] = dest;
306 route->nextHopId[c] = 0;
312static bool check_my_ip(NETSIM_ID d, NETSIM_IPAddress ip)
315 for (i = 0; i < DEVICE(d)->nNumOfInterface; i++)
316 if (!IP_COMPARE(DEVICE_NWADDRESS(d, i + 1), ip))
321static ptrIP_FORWARD_ROUTE route_unicast(NetSim_PACKET* packet,
324 ptrIP_ROUTINGTABLE routingTable = IP_TABLE_GET(dev);
325 NETSIM_IPAddress dest = packet->pstruNetworkData->szDestIP;
327 ptrMATCH match = get_match_table(routingTable, dest,
false);
329 ptrMATCH store = match;
331 ptrIP_FORWARD_ROUTE route = (ptrIP_FORWARD_ROUTE)calloc(1,
sizeof* route);
333 update_route_entry(match, route, dest);
335 free_match_table(store);
339 free_ip_route(route);
346static ptrIP_FORWARD_ROUTE route_multicast(NetSim_PACKET* packet,
349 ptrIP_ROUTINGTABLE routingTable = IP_TABLE_GET(dev);
350 NETSIM_IPAddress dest = packet->pstruNetworkData->szDestIP;
351 NETSIM_IPAddress src = packet->pstruNetworkData->szSourceIP;
353 ptrMATCH match = get_match_table(routingTable, dest,
false);
354#ifdef PRINT_MATCH_TABLE
355 print_match_table(match, dev, dest, src);
357 ptrMATCH store = match;
359 ptrIP_FORWARD_ROUTE route = (ptrIP_FORWARD_ROUTE)calloc(1,
sizeof* route);
361 multicast_update_route_entry(match, route, dest, src);
363 free_match_table(store);
374ptrIP_FORWARD_ROUTE fn_NetSim_IP_RoutePacket(NetSim_PACKET* packet,
377 NETSIM_IPAddress dest = packet->pstruNetworkData->szDestIP;
379 if (isMulticastIP(dest))
380 return route_multicast(packet, dev);
382 return route_unicast(packet, dev);
385static void change_table(NETSIM_ID d, ptrIP_ROUTINGTABLE table,
386 NETSIM_IPAddress gateway, NETSIM_ID in, UINT metric)
389 bool isfound =
false;
390 for (i = 0; i < table->interfaceCount; i++)
392 if (in == table->nInterfaceId[i])
400 table->gateway = gateway;
401 table->Metric = metric;
405 table->Interface = realloc(table->Interface, (table->interfaceCount + 1) *
sizeof* table->Interface);
406 table->nInterfaceId = realloc(table->nInterfaceId, (table->interfaceCount + 1) *
sizeof* table->Interface);
407 table->nInterfaceId[table->interfaceCount] = in;
408 table->Interface[table->interfaceCount] = DEVICE_NWADDRESS(d, in);
409 table->gateway = gateway;
410 table->Metric = metric;
411 table->interfaceCount++;
415static void add_table(NETSIM_ID d, NETSIM_IPAddress dest, NETSIM_IPAddress mask,
416 NETSIM_IPAddress gateway, NETSIM_ID in, UINT metric)
418 iptable_add(IP_WRAPPER_GET(d), dest, mask, 0, gateway, 1, &DEVICE_NWADDRESS(d, in), &in, metric,
"STATIC");
421#define display_error(error, line, file) fnNetSimError("Invalid line in route file %s at line %d: %s", file, line, error)
423void configure_static_ip_route(NETSIM_ID d,
char* file)
426 NETSIM_ID nDevId = 0;
431 sprintf(input,
"%s%s%s", pszIOPath, pathSeperator, file);
432 FILE* fp = fopen(input,
"r");
436 fnNetSimError(
"Unable to open routing file %s", input);
440 while (fgets(input, BUFSIZ, fp))
445 if (*temp ==
'#' || !*temp)
448 char* f = find_word(&temp);
449 if (_stricmp(f,
"route"))
451 display_error(
"Not start with route", file, line);
455 f = find_word(&temp);
456 if (_stricmp(f,
"add"))
458 display_error(
"Second word is not add", file, line);
462 f = find_word(&temp);
463 NETSIM_IPAddress dest = STR_TO_IP4(f);
465 f = find_word(&temp);
466 if (_stricmp(f,
"mask"))
468 display_error(
"Fourth word is not mask", file, line);
472 f = find_word(&temp);
473 NETSIM_IPAddress mask = STR_TO_IP4(f);
475 f = find_word(&temp);
476 NETSIM_IPAddress gateway = STR_TO_IP4(f);
478 f = find_word(&temp);
479 if (_stricmp(f,
"metric"))
481 display_error(
"Seventh word is not metric", file, line);
485 f = find_word(&temp);
486 UINT metric = atoi(f);
488 f = find_word(&temp);
489 if (_stricmp(f,
"IF"))
491 display_error(
"Ninth word is not if", file, line);
495 f = find_word(&temp);
496 NETSIM_ID in = atoi(f);
497 in = fn_NetSim_GetInterfaceIdByConfigId(d, in);
499 ptrIP_ROUTINGTABLE table = iptable_check(PIP_TABLE_GET(d), dest, mask);
501 change_table(d, table, gateway, in, metric);
503 add_table(d, dest, mask, gateway, in, metric);
508static ptrIP_FORWARD_ROUTE static_route_unicast(NetSim_PACKET* packet,
511 ptrIP_ROUTINGTABLE routingTable = IP_TABLE_GET(dev);
512 NETSIM_IPAddress dest = packet->pstruNetworkData->szDestIP;
514 ptrMATCH match = get_match_table(routingTable, dest,
true);
516 ptrMATCH store = match;
518 ptrIP_FORWARD_ROUTE route = (ptrIP_FORWARD_ROUTE)calloc(1,
sizeof* route);
520 update_route_entry(match, route, dest);
522 free_match_table(store);
533static ptrIP_FORWARD_ROUTE static_route_multicast(NetSim_PACKET* packet,
536 ptrIP_ROUTINGTABLE routingTable = IP_TABLE_GET(dev);
537 NETSIM_IPAddress dest = packet->pstruNetworkData->szDestIP;
538 NETSIM_IPAddress src = packet->pstruNetworkData->szSourceIP;
540 ptrMATCH match = get_match_table(routingTable, dest,
true);
541#ifdef PRINT_MATCH_TABLE
542 print_match_table(match, dev, dest, src);
544 ptrMATCH store = match;
546 ptrIP_FORWARD_ROUTE route = (ptrIP_FORWARD_ROUTE)calloc(1,
sizeof* route);
548 multicast_update_route_entry(match, route, dest, src);
550 free_match_table(store);
561ptrIP_FORWARD_ROUTE fn_NetSim_IP_RoutePacketViaStaticEntry(NetSim_PACKET* packet, NETSIM_ID dev)
563 NETSIM_IPAddress dest = packet->pstruNetworkData->szDestIP;
565 if (isMulticastIP(dest))
566 return static_route_multicast(packet, dev);
568 return static_route_unicast(packet, dev);
571void pass_to_lower_layer(NetSim_PACKET* packet, ptrIP_FORWARD_ROUTE route, UINT c)
573 NetSim_EVENTDETAILS pevent;
574 memset(&pevent, 0,
sizeof pevent);
578 d = pstruEventDetails->nDeviceId;
581 packet->pstruNetworkData->szNextHopIp = route->nextHop[c];
582 packet->pstruNetworkData->szGatewayIP = route->gateway[c];
583 n = route->nextHopId[c];
584 i = route->interfaceId[c];
588 if (!packet->pstruNetworkData->szGatewayIP)
589 packet->pstruNetworkData->szGatewayIP = fn_NetSim_Stack_GetFirstIPAddressAsId(d, 4);
591 if (!pstruEventDetails->nInterfaceId)
592 i = fn_NetSim_Stack_GetInterfaceIdFromIP(d,
593 packet->pstruNetworkData->szGatewayIP);
595 i = pstruEventDetails->nInterfaceId;
598 n = fn_NetSim_Stack_GetDeviceId_asIP(packet->pstruNetworkData->szNextHopIp,
604 if (fn_NetSim_NETWORK_Firewall(d, i, packet, ACLTYPE_OUTBOUND) == ACLACTION_DENY)
606 ipMetrics[d - 1]->nFirewallBlocked++;
607 fn_NetSim_Packet_FreePacket(packet);
608 pstruEventDetails->pPacket = NULL;
612 if (!IP_COMPARE(packet->pstruNetworkData->szGatewayIP, packet->pstruNetworkData->szNextHopIp))
614 fnNetSimError(
"Gateway IP and next hop IP are same. IP address=%s\n",
615 packet->pstruNetworkData->szGatewayIP->str_ip);
618 packet->pstruNetworkData->dOverhead += IPV4_HEADER_SIZE;
619 packet->pstruNetworkData->dPacketSize = packet->pstruNetworkData->dOverhead +
620 packet->pstruNetworkData->dPayload;
624 packet->pstruNetworkData->dEndTime = pstruEventDetails->dEventTime;
625 packet->pstruNetworkData->nNetworkProtocol = DEVICE_INTERFACE(d, i)->nProtocolId;
626 packet->nTransmitterId = d;
627 packet->nReceiverId = n;
629 if (DEVICE_INTERFACE(d, i)->nLocalNetworkProtocol == PROTOCOL_VPN)
630 fn_NetSim_IP_VPN_Run();
632 if (pstruEventDetails->pPacket == NULL)
636 ipMetrics[d - 1]->nPacketSent++;
638 ip_write_to_pcap(packet, d, i, pstruEventDetails->dEventTime);
640 if (!DEVICE_INTERFACE(d, i)->nLocalNetworkProtocol)
642 packet->pstruMacData->szSourceMac = (fn_NetSim_Stack_GetMacAddressFromIP(packet->pstruNetworkData->szGatewayIP));
643 NETSIM_IPAddress szDestIPaddr = packet->pstruNetworkData->szNextHopIp;
644 if (isBroadcastIP(szDestIPaddr))
645 packet->pstruMacData->szDestMac = BROADCAST_MAC;
646 else if (isMulticastIP(szDestIPaddr))
647 packet->pstruMacData->szDestMac = multicastIP_to_Mac(szDestIPaddr);
649 packet->pstruMacData->szDestMac = fn_NetSim_Stack_GetMacAddressFromIP(szDestIPaddr);
652 IP_DEVVAR* ipVar = GET_IP_DEVVAR(d);
653 memset(&pevent, 0,
sizeof pevent);
654 pevent.dEventTime = pstruEventDetails->dEventTime + ipVar->processingDelay;
655 pevent.dPacketSize = packet->pstruNetworkData->dPacketSize;
656 if (packet->pstruAppData)
658 pevent.nApplicationId = packet->pstruAppData->nApplicationId;
659 pevent.nSegmentId = packet->pstruAppData->nSegmentId;
661 pevent.nDeviceId = d;
662 pevent.nDeviceType = DEVICE_TYPE(d);
663 pevent.nEventType = TIMER_EVENT;
664 pevent.nInterfaceId = i;
665 pevent.nPacketId = packet->nPacketId;
666 pevent.nProtocolId = DEVICE_INTERFACE(d, i)->nProtocolId;
667 pevent.nSubEventType = EVENT_IP_PROCESSING_DELAY;
668 pevent.pPacket = packet;
669 fnpAddEvent(&pevent);