-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathskel.c
198 lines (174 loc) · 4.13 KB
/
skel.c
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#include "skel.h"
int interfaces[ROUTER_NUM_INTERFACES];
int get_sock(const char *if_name)
{
int res;
int s = socket(AF_PACKET, SOCK_RAW, 768);
DIE(s == -1, "socket");
struct ifreq intf;
strcpy(intf.ifr_name, if_name);
res = ioctl(s, SIOCGIFINDEX, &intf);
DIE(res, "ioctl SIOCGIFINDEX");
struct sockaddr_ll addr;
memset(&addr, 0x00, sizeof(addr));
addr.sll_family = AF_PACKET;
addr.sll_ifindex = intf.ifr_ifindex;
res = bind(s , (struct sockaddr *)&addr , sizeof(addr));
DIE(res == -1, "bind");
return s;
}
packet* socket_receive_message(int sockfd, packet *m)
{
/*
* Note that "buffer" should be at least the MTU size of the
* interface, eg 1500 bytes
* */
m->len = read(sockfd, m->payload, MAX_LEN);
DIE(m->len == -1, "read");
return m;
}
int send_packet(int sockfd, packet *m)
{
/*
* Note that "buffer" should be at least the MTU size of the
* interface, eg 1500 bytes
* */
int ret;
ret = write(interfaces[sockfd], m->payload, m->len);
DIE(ret == -1, "write");
return ret;
}
int get_packet(packet *m) {
int res;
fd_set set;
FD_ZERO(&set);
while (1) {
for (int i = 0; i < ROUTER_NUM_INTERFACES; i++) {
FD_SET(interfaces[i], &set);
}
res = select(interfaces[ROUTER_NUM_INTERFACES - 1] + 1, &set, NULL, NULL, NULL);
DIE(res == -1, "select");
for (int i = 0; i < ROUTER_NUM_INTERFACES; i++) {
if (FD_ISSET(interfaces[i], &set)) {
socket_receive_message(interfaces[i], m);
m->interface = i;
return 0;
}
}
}
return -1;
}
char *get_interface_ip(int interface)
{
struct ifreq ifr;
sprintf(ifr.ifr_name, "r-%u", interface);
ioctl(interfaces[interface], SIOCGIFADDR, &ifr);
return inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr);
}
int get_interface_mac(int interface, uint8_t *mac)
{
struct ifreq ifr;
sprintf(ifr.ifr_name, "r-%u", interface);
ioctl(interfaces[interface], SIOCGIFHWADDR, &ifr);
memcpy(mac, ifr.ifr_addr.sa_data, 6);
return 1;
}
void init()
{
int s0 = get_sock("r-0");
int s1 = get_sock("r-1");
int s2 = get_sock("r-2");
int s3 = get_sock("r-3");
interfaces[0] = s0;
interfaces[1] = s1;
interfaces[2] = s2;
interfaces[3] = s3;
}
static int hex2num(char c)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
return -1;
}
int hex2byte(const char *hex)
{
int a, b;
a = hex2num(*hex++);
if (a < 0)
return -1;
b = hex2num(*hex++);
if (b < 0)
return -1;
return (a << 4) | b;
}
/**
* hwaddr_aton - Convert ASCII string to MAC address (colon-delimited format)
* @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
* @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
* Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
*/
int hwaddr_aton(const char *txt, uint8_t *addr)
{
int i;
for (i = 0; i < 6; i++) {
int a, b;
a = hex2num(*txt++);
if (a < 0)
return -1;
b = hex2num(*txt++);
if (b < 0)
return -1;
*addr++ = (a << 4) | b;
if (i < 5 && *txt++ != ':')
return -1;
}
return 0;
}
uint16_t ip_checksum(void* vdata,size_t length) {
// Cast the data pointer to one that can be indexed.
char* data=(char*)vdata;
// Initialise the accumulator.
uint64_t acc=0xffff;
// Handle any partial block at the start of the data.
unsigned int offset=((uintptr_t)data)&3;
if (offset) {
size_t count=4-offset;
if (count>length) count=length;
uint32_t word=0;
memcpy(offset+(char*)&word,data,count);
acc+=ntohl(word);
data+=count;
length-=count;
}
// Handle any complete 32-bit blocks.
char* data_end=data+(length&~3);
while (data!=data_end) {
uint32_t word;
memcpy(&word,data,4);
acc+=ntohl(word);
data+=4;
}
length&=3;
// Handle any partial block at the end of the data.
if (length) {
uint32_t word=0;
memcpy(&word,data,length);
acc+=ntohl(word);
}
// Handle deferred carries.
acc=(acc&0xffffffff)+(acc>>32);
while (acc>>16) {
acc=(acc&0xffff)+(acc>>16);
}
// If the data began at an odd byte address
// then reverse the byte order to compensate.
if (offset&1) {
acc=((acc&0xff00)>>8)|((acc&0x00ff)<<8);
}
// Return the checksum in network byte order.
return htons(~acc);
}