-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrouter.c
More file actions
110 lines (91 loc) · 3.17 KB
/
Copy pathrouter.c
File metadata and controls
110 lines (91 loc) · 3.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include "queue.h"
#include "lib.h"
#include "protocols.h"
#include "router.h"
#include "arp.h"
#include "icmp.h"
#include "trie.h"
#include "utils.h"
#include <stdbool.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
struct arp_queue packets_arp_queue;
struct arp_table arp_tbl;
void handle_ip_packet(struct ether_header *eth_hdr, char *frame, int len_frame, int interface) {
printf("[LOG] Received an IPv4 packet\n");
struct iphdr *ip_hdr = (struct iphdr *)(frame + sizeof(struct ether_header));
// compare checksums
uint16_t received_check = ip_hdr->check;
received_check = ntohs(received_check);
ip_hdr->check = 0;
uint16_t new_check = checksum((uint16_t*)ip_hdr, sizeof(struct iphdr));
if (received_check != new_check) {
// drop the packet
printf("[LOG] Bad checksum\n");
return;
}
if (am_i_destination_ip(interface, ip_hdr)) {
printf("[LOG] Packet destination IP it's me, sending echo reply\n");
handle_icmp(frame, len_frame, 0, 0, interface);
return;
}
int rc = update_ttl(frame, len_frame, interface);
if (rc)
return; // the packet has been dropped and a reply has been sent
// search for the next hoop
struct route_table_entry *next_hoop = search_next_hoop(ip_hdr->daddr);
if (next_hoop == NULL) {
printf("[LOG] Destination unreachable\n");
handle_icmp(frame, len_frame, HOST_UNREC_TYPE, 0, interface);
return;
}
// modify the existing packet to send it forward
update_checksum(ip_hdr);
struct arp_entry *arp_dest = find_mac_address_in_arp(next_hoop->next_hop);
if (arp_dest == NULL) {
// it means there's no entry in the arp table for the ip to send to
printf("[LOG] No entry in the ARP table found, creating ARP request\n");
struct arp_queue_entry entry = create_arp_queue_entry(frame, len_frame, *next_hoop);
arp_enq(entry);
generate_arp_request(next_hoop->next_hop, next_hoop->interface);
return;
}
// replace the data in old ethernet header
eth_hdr->ether_type = htons(IP_TYPE);
get_interface_mac(interface, eth_hdr->ether_shost);
memcpy(eth_hdr->ether_dhost, arp_dest->mac, MAC_ADR_SIZE_BYTES);
// send forward the packet
send_to_link(next_hoop->interface, frame, len_frame);
}
int main(int argc, char *argv[])
{
setvbuf(stdout, NULL, _IONBF, 0);
char buf[MAX_PACKET_LEN];
// Do not modify this line
init(argc - 2, argv + 2);
init_rtable_trie(argv[1]);
init_arp_table();
init_arp_queue();
while (1) {
int interface;
size_t len;
interface = recv_from_any_link(buf, &len);
DIE(interface < 0, "recv_from_any_links");
struct ether_header *eth_hdr = (struct ether_header *) buf;
convert_to_host_eth_header(eth_hdr);
if (am_i_destination_mac(eth_hdr, interface) == 0) {
printf("[LOG] received a frame which is not for me\n");
continue; // drop the eth frame, it's not for me
}
printf("[LOG] Received a frame\n");
if (eth_hdr->ether_type == ARP_TYPE)
handle_arp_packet(eth_hdr, buf, interface);
else
handle_ip_packet(eth_hdr, buf, len, interface);
/* Note that packets received are in network order,
any header field which has more than 1 byte will need to be conerted to
host order. For example, ntohs(eth_hdr->ether_type). The oposite is needed when
sending a packet on the link, */
}
}