embox

Форк
0
/
ip_options.c 
242 строки · 5.3 Кб
1
/*
2
 * @file
3
 * @brief IP options processing module
4
 *
5
 * @date 14.04.10
6
 * @author Roman Kolobov
7
 */
8

9
#include <net/l3/ipv4/ip_options.h>
10
#include <net/skbuff.h>
11
#include <net/l3/ipv4/ip.h>
12
#include <net/l3/icmpv4.h>
13
#include <net/inetdevice.h>
14
#include <net/socket/inet_sock.h>
15

16
int ip_options_compile(sk_buff_t *skb, ip_options_t *opt) {
17
	struct iphdr *iph;
18

19
	uint8_t * endopts;
20

21
	/* curropt points to current option in question
22
	 * optsfault points to first problem occurred in options
23
	 */
24
	uint8_t *curropt;
25
	int curroptlen;
26

27
	uint8_t *optsfault = NULL;
28
	_Bool secappeared = false;
29
	_Bool sidappeared = false;
30
	unsigned int* timestamp = NULL;
31

32
	iph = ip_hdr(skb);
33
	curropt	= (unsigned char*) iph + IP_MIN_HEADER_SIZE;
34
	endopts = curropt + opt->optlen;
35

36
	for (; curropt < endopts; ) {
37
		switch (*curropt) {
38
		case IPOPT_END:
39
			for (++curropt ; curropt < endopts; ++curropt) {
40
				if (IPOPT_END != *curropt) {
41
					*curropt = IPOPT_END;
42
					opt->is_changed = 1;
43
				}
44
			}
45
			goto end;
46
		case IPOPT_NOOP:
47
			continue;
48
		}
49

50
		curroptlen = curropt[1];
51
		if ((curroptlen < 2) || (curroptlen > (endopts - curropt))) {
52
			optsfault = curropt + 1;
53
			goto error;
54
		}
55

56
		switch(*curropt) {
57
		case IPOPT_SEC:
58
			if (secappeared) {
59
				optsfault = curropt;
60
				goto error;
61
			}
62
			if (curroptlen != 11) {
63
				optsfault = curropt + 1;
64
				goto error;
65
			}
66
			secappeared = true;
67
			memcpy(&opt->__data, curropt, 12);
68
			break;
69
		case IPOPT_LSRR:
70
		case IPOPT_SSRR:
71
			if (opt->srr) {
72
				optsfault = curropt;
73
				goto error;
74
			}
75
			if (curroptlen < 3) {
76
				optsfault = curropt + 1;
77
				goto error;
78
			}
79
			if (curropt[2] < 4) {
80
				optsfault = curropt + 2;
81
				goto error;
82
			}
83
			opt->srr = (unsigned char) (curropt - (unsigned char*) iph);
84
			opt->is_strictroute = (*curropt == IPOPT_SSRR);
85
			break;
86
		case IPOPT_RR:
87
			if (opt->rr) {
88
				optsfault = curropt;
89
				goto error;
90
			}
91
			if (curroptlen < 3) {
92
				optsfault = curropt + 1;
93
				goto error;
94
			}
95
			if (curropt[2] < 4) {
96
				optsfault = curropt + 2;
97
				goto error;
98
			}
99
			if (curropt[2] <= curroptlen) {
100
				if (curropt[2] + 3 > curroptlen) {
101
					optsfault = curropt + 2;
102
					goto error;
103
				}
104
				//TODO ask whether ...->ifa_address is a correct transmitter (i.e. our) address
105
				*(in_addr_t *)(curropt + curropt[2] - 1) = inetdev_get_by_dev(skb->dev)->ifa_address;
106
				curropt[2] += 4;
107
				opt->is_changed = 1;
108
				opt->rr_needaddr = 1;
109
			}
110
			opt->rr = (unsigned char) (curropt - (unsigned char*) iph);
111
			break;
112
		case IPOPT_SID:
113
			if (sidappeared) {
114
				optsfault = curropt;
115
				goto error;
116
			}
117
			if (curropt[1] != 4) {
118
				optsfault = curropt + 1;
119
				goto error;
120
			}
121
			sidappeared = true;
122
		case IPOPT_TIMESTAMP:
123
			if (opt->ts) {
124
				optsfault = curropt;
125
				goto error;
126
			}
127
			if (curroptlen < 4) {
128
				optsfault = curropt + 1;
129
				goto error;
130
			}
131
			if (curropt[2] < 5) {
132
				optsfault = curropt + 2;
133
				goto error;
134
			}
135
			if (curropt[2] <= curroptlen) {
136
				if (curropt[2] + 3 > curroptlen) {
137
					optsfault = curropt + 2;
138
					goto error;
139
				}
140
				switch(curropt[3]&0x0F) {
141
				case IPOPT_TS_TSONLY:
142
					opt->ts = (unsigned char) (curropt - (unsigned char*) iph);
143
					opt->ts_needtime = 1;
144
					timestamp = (unsigned int*)(&curropt[curropt[2]-1]);
145
					curropt[2] += 4;
146
					break;
147
				case IPOPT_TS_TSANDADDR:
148
					if (curropt[2] + 7 > curroptlen)
149
					{
150
						optsfault = curropt + 2;
151
						goto error;
152
					}
153
					*(in_addr_t *)(curropt + curropt[2] - 1) = inetdev_get_by_dev(skb->dev)->ifa_address;
154
					timestamp = (unsigned int*)(&curropt[curropt[2]+3]);
155
					opt->ts = (unsigned char) (curropt - (unsigned char*) iph);
156
					opt->ts_needaddr = 1;
157
					opt->ts_needtime = 1;
158
					curropt[2] += 8;
159
					break;
160
				case IPOPT_TS_PRESPEC:
161
					if (curropt[2] + 7 > curroptlen)
162
					{
163
						optsfault = curropt + 2;
164
						goto error;
165
					}
166
					opt->ts = (unsigned char) (curropt - (unsigned char*) iph);
167
					//TODO i still don't understand meaning of this option
168
					break;
169
				default:
170
					optsfault = curropt + 3;
171
					goto error;
172
				}
173
				if (timestamp) {
174
					//TODO get timestamp and record, gettimeofday seems to be unimplemented
175
					opt->is_changed = 1;
176
				}
177
			}
178
			else {
179
				unsigned short tsoverflow = curropt[3] >> 4;
180

181
				if (0xFF == tsoverflow) {
182
					optsfault = curropt + 3;
183
					goto error;
184
				}
185
				curropt[3] &= 0x0F;
186
				curropt[3] |= (++tsoverflow) << 4;
187
				opt->is_changed = 1;
188
				opt->ts = (unsigned char) (curropt - (unsigned char*) iph);
189
			}
190
			break;
191
		// TODO case IPOPT_CIPSO - don't still know what to do here
192
		case IPOPT_RA:
193
			opt->router_alert = curropt[3];
194
			break;
195
		default:
196
			optsfault = curropt;
197
			goto error;
198
		}
199

200
		curropt += curroptlen;
201

202
	}
203

204
end:
205
	if (!optsfault)
206
	{
207
		return 0;
208
	}
209

210
error:
211
	curroptlen = (int) (optsfault - (unsigned char*) iph);
212
	icmp_discard(skb, ICMP_PARAM_PROB, ICMP_PTR_ERROR,
213
			(uint8_t)curroptlen);
214
	//TODO : is it an adequate return value? maybe -EINVAL will suit better?
215
	return -1;
216

217
}
218

219
int ip_options_handle_srr(sk_buff_t *skb)
220
{
221
	ip_options_t *opt = (ip_options_t*)(skb->cb);
222
//	iphdr_t *iph = ip_hdr(skb);
223

224
	if (!opt->srr) {
225
		return 0;
226
	}
227

228
	//TODO search for addresses consequently, try to route
229

230
	return 0;
231
}
232

233
uint16_t skb_get_secure_level(struct sk_buff *skb) {
234
	uint16_t level;
235
	ip_options_t *opt;
236

237
	opt = (ip_options_t *)skb->cb;
238

239
	memcpy(&level, &opt->__data + 2, sizeof(level));
240

241
	return ntohs(level);
242
}
243

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.