iof-bird-daemon / proto / babel / packets.c @ 8b58f565
History | View | Annotate | Download (33.6 KB)
1 | 937e75d8 | Ondrej Zajicek (work) | /*
|
---|---|---|---|
2 | * BIRD -- The Babel protocol
|
||
3 | *
|
||
4 | * Copyright (c) 2015--2016 Toke Hoiland-Jorgensen
|
||
5 | *
|
||
6 | * Can be freely distributed and used under the terms of the GNU GPL.
|
||
7 | *
|
||
8 | * This file contains the packet and TLV handling code for the protocol.
|
||
9 | */
|
||
10 | |||
11 | #include "babel.h" |
||
12 | |||
13 | |||
14 | struct babel_pkt_header {
|
||
15 | u8 magic; |
||
16 | u8 version; |
||
17 | u16 length; |
||
18 | } PACKED; |
||
19 | |||
20 | struct babel_tlv {
|
||
21 | u8 type; |
||
22 | u8 length; |
||
23 | u8 value[0];
|
||
24 | } PACKED; |
||
25 | |||
26 | struct babel_tlv_ack_req {
|
||
27 | u8 type; |
||
28 | u8 length; |
||
29 | u16 reserved; |
||
30 | u16 nonce; |
||
31 | u16 interval; |
||
32 | } PACKED; |
||
33 | |||
34 | struct babel_tlv_ack {
|
||
35 | u8 type; |
||
36 | u8 length; |
||
37 | u16 nonce; |
||
38 | } PACKED; |
||
39 | |||
40 | struct babel_tlv_hello {
|
||
41 | u8 type; |
||
42 | u8 length; |
||
43 | u16 reserved; |
||
44 | u16 seqno; |
||
45 | u16 interval; |
||
46 | } PACKED; |
||
47 | |||
48 | struct babel_tlv_ihu {
|
||
49 | u8 type; |
||
50 | u8 length; |
||
51 | u8 ae; |
||
52 | u8 reserved; |
||
53 | u16 rxcost; |
||
54 | u16 interval; |
||
55 | u8 addr[0];
|
||
56 | } PACKED; |
||
57 | |||
58 | struct babel_tlv_router_id {
|
||
59 | u8 type; |
||
60 | u8 length; |
||
61 | u16 reserved; |
||
62 | u64 router_id; |
||
63 | } PACKED; |
||
64 | |||
65 | struct babel_tlv_next_hop {
|
||
66 | u8 type; |
||
67 | u8 length; |
||
68 | u8 ae; |
||
69 | u8 reserved; |
||
70 | u8 addr[0];
|
||
71 | } PACKED; |
||
72 | |||
73 | struct babel_tlv_update {
|
||
74 | u8 type; |
||
75 | u8 length; |
||
76 | u8 ae; |
||
77 | u8 flags; |
||
78 | u8 plen; |
||
79 | u8 omitted; |
||
80 | u16 interval; |
||
81 | u16 seqno; |
||
82 | u16 metric; |
||
83 | u8 addr[0];
|
||
84 | } PACKED; |
||
85 | |||
86 | struct babel_tlv_route_request {
|
||
87 | u8 type; |
||
88 | u8 length; |
||
89 | u8 ae; |
||
90 | u8 plen; |
||
91 | u8 addr[0];
|
||
92 | } PACKED; |
||
93 | |||
94 | struct babel_tlv_seqno_request {
|
||
95 | u8 type; |
||
96 | u8 length; |
||
97 | u8 ae; |
||
98 | u8 plen; |
||
99 | u16 seqno; |
||
100 | u8 hop_count; |
||
101 | u8 reserved; |
||
102 | u64 router_id; |
||
103 | u8 addr[0];
|
||
104 | } PACKED; |
||
105 | |||
106 | |||
107 | #define BABEL_FLAG_DEF_PREFIX 0x80 |
||
108 | #define BABEL_FLAG_ROUTER_ID 0x40 |
||
109 | |||
110 | |||
111 | struct babel_parse_state {
|
||
112 | struct babel_proto *proto;
|
||
113 | struct babel_iface *ifa;
|
||
114 | ip_addr saddr; |
||
115 | 4324025f | Ondrej Zajicek (work) | ip_addr next_hop_ip4; |
116 | ip_addr next_hop_ip6; |
||
117 | 937e75d8 | Ondrej Zajicek (work) | u64 router_id; /* Router ID used in subsequent updates */
|
118 | u8 def_ip6_prefix[16]; /* Implicit IPv6 prefix in network order */ |
||
119 | u8 def_ip4_prefix[4]; /* Implicit IPv4 prefix in network order */ |
||
120 | u8 router_id_seen; /* router_id field is valid */
|
||
121 | u8 def_ip6_prefix_seen; /* def_ip6_prefix is valid */
|
||
122 | u8 def_ip4_prefix_seen; /* def_ip4_prefix is valid */
|
||
123 | 145ebfa1 | Ondrej Zajicek (work) | u8 current_tlv_endpos; /* End of self-terminating TLVs (offset from start) */
|
124 | 937e75d8 | Ondrej Zajicek (work) | }; |
125 | |||
126 | enum parse_result {
|
||
127 | PARSE_SUCCESS, |
||
128 | PARSE_ERROR, |
||
129 | PARSE_IGNORE, |
||
130 | }; |
||
131 | |||
132 | struct babel_write_state {
|
||
133 | u64 router_id; |
||
134 | u8 router_id_seen; |
||
135 | 4324025f | Ondrej Zajicek (work) | ip_addr next_hop_ip4; |
136 | ip_addr next_hop_ip6; |
||
137 | b3c6273e | Ondrej Zajicek (work) | u8 def_ip6_prefix[16]; /* Implicit IPv6 prefix in network order */ |
138 | u8 def_ip6_pxlen; |
||
139 | 937e75d8 | Ondrej Zajicek (work) | }; |
140 | |||
141 | |||
142 | #define DROP(DSC,VAL) do { err_dsc = DSC; err_val = VAL; goto drop; } while(0) |
||
143 | #define DROP1(DSC) do { err_dsc = DSC; goto drop; } while(0) |
||
144 | #define LOG_PKT(msg, args...) \
|
||
145 | log_rl(&p->log_pkt_tbf, L_REMOTE "%s: " msg, p->p.name, args)
|
||
146 | |||
147 | #define FIRST_TLV(p) ((struct babel_tlv *) (((struct babel_pkt_header *) p) + 1)) |
||
148 | #define NEXT_TLV(t) ((struct babel_tlv *) (((byte *) t) + TLV_LENGTH(t))) |
||
149 | #define TLV_LENGTH(t) (t->type == BABEL_TLV_PAD1 ? 1 : t->length + sizeof(struct babel_tlv)) |
||
150 | #define TLV_OPT_LENGTH(t) (t->length + sizeof(struct babel_tlv) - sizeof(*t)) |
||
151 | #define TLV_HDR(tlv,t,l) ({ tlv->type = t; tlv->length = l - sizeof(struct babel_tlv); }) |
||
152 | #define TLV_HDR0(tlv,t) TLV_HDR(tlv, t, tlv_data[t].min_length)
|
||
153 | |||
154 | 5e8df049 | Ondrej Zajicek (work) | #define NET_SIZE(n) BYTES(net_pxlen(n))
|
155 | |||
156 | b3c6273e | Ondrej Zajicek (work) | static inline uint |
157 | bytes_equal(u8 *b1, u8 *b2, uint maxlen) |
||
158 | { |
||
159 | uint i; |
||
160 | for (i = 0; (i < maxlen) && (*b1 == *b2); i++, b1++, b2++) |
||
161 | ; |
||
162 | return i;
|
||
163 | } |
||
164 | 937e75d8 | Ondrej Zajicek (work) | |
165 | 8b58f565 | Ondrej Zajicek (work) | static inline uint |
166 | 937e75d8 | Ondrej Zajicek (work) | get_time16(const void *p) |
167 | { |
||
168 | 8b58f565 | Ondrej Zajicek (work) | uint v = get_u16(p) * BABEL_TIME_UNITS; |
169 | return MAX(BABEL_MIN_INTERVAL, v);
|
||
170 | 937e75d8 | Ondrej Zajicek (work) | } |
171 | |||
172 | static inline void |
||
173 | 8b58f565 | Ondrej Zajicek (work) | put_time16(void *p, uint v)
|
174 | 937e75d8 | Ondrej Zajicek (work) | { |
175 | 8b58f565 | Ondrej Zajicek (work) | put_u16(p, v / BABEL_TIME_UNITS); |
176 | 937e75d8 | Ondrej Zajicek (work) | } |
177 | |||
178 | 5e8df049 | Ondrej Zajicek (work) | static inline void |
179 | 4324025f | Ondrej Zajicek (work) | read_ip4_px(net_addr *n, const void *p, uint plen) |
180 | { |
||
181 | ip4_addr addr = {0};
|
||
182 | memcpy(&addr, p, BYTES(plen)); |
||
183 | net_fill_ip4(n, ip4_ntoh(addr), plen); |
||
184 | } |
||
185 | |||
186 | static inline void |
||
187 | put_ip4_px(void *p, net_addr *n)
|
||
188 | { |
||
189 | ip4_addr addr = ip4_hton(net4_prefix(n)); |
||
190 | memcpy(p, &addr, NET_SIZE(n)); |
||
191 | } |
||
192 | |||
193 | static inline void |
||
194 | 5e8df049 | Ondrej Zajicek (work) | read_ip6_px(net_addr *n, const void *p, uint plen) |
195 | 937e75d8 | Ondrej Zajicek (work) | { |
196 | ip6_addr addr = IPA_NONE; |
||
197 | 3e236955 | Jan Moskyto Matejka | memcpy(&addr, p, BYTES(plen)); |
198 | 5e8df049 | Ondrej Zajicek (work) | net_fill_ip6(n, ip6_ntoh(addr), plen); |
199 | 937e75d8 | Ondrej Zajicek (work) | } |
200 | |||
201 | static inline void |
||
202 | 5e8df049 | Ondrej Zajicek (work) | put_ip6_px(void *p, net_addr *n)
|
203 | 937e75d8 | Ondrej Zajicek (work) | { |
204 | 5e8df049 | Ondrej Zajicek (work) | ip6_addr addr = ip6_hton(net6_prefix(n)); |
205 | memcpy(p, &addr, NET_SIZE(n)); |
||
206 | 937e75d8 | Ondrej Zajicek (work) | } |
207 | |||
208 | static inline ip6_addr |
||
209 | get_ip6_ll(const void *p) |
||
210 | { |
||
211 | return ip6_build(0xfe800000, 0, get_u32(p+0), get_u32(p+4)); |
||
212 | } |
||
213 | |||
214 | static inline void |
||
215 | put_ip6_ll(void *p, ip6_addr addr)
|
||
216 | { |
||
217 | put_u32(p+0, _I2(addr));
|
||
218 | put_u32(p+4, _I3(addr));
|
||
219 | } |
||
220 | |||
221 | |||
222 | /*
|
||
223 | * TLV read/write functions
|
||
224 | */
|
||
225 | |||
226 | static int babel_read_ack_req(struct babel_tlv *hdr, union babel_msg *msg, struct babel_parse_state *state); |
||
227 | static int babel_read_hello(struct babel_tlv *hdr, union babel_msg *msg, struct babel_parse_state *state); |
||
228 | static int babel_read_ihu(struct babel_tlv *hdr, union babel_msg *msg, struct babel_parse_state *state); |
||
229 | static int babel_read_router_id(struct babel_tlv *hdr, union babel_msg *msg, struct babel_parse_state *state); |
||
230 | static int babel_read_next_hop(struct babel_tlv *hdr, union babel_msg *msg, struct babel_parse_state *state); |
||
231 | static int babel_read_update(struct babel_tlv *hdr, union babel_msg *msg, struct babel_parse_state *state); |
||
232 | static int babel_read_route_request(struct babel_tlv *hdr, union babel_msg *msg, struct babel_parse_state *state); |
||
233 | static int babel_read_seqno_request(struct babel_tlv *hdr, union babel_msg *msg, struct babel_parse_state *state); |
||
234 | |||
235 | 3e236955 | Jan Moskyto Matejka | static uint babel_write_ack(struct babel_tlv *hdr, union babel_msg *msg, struct babel_write_state *state, uint max_len); |
236 | static uint babel_write_hello(struct babel_tlv *hdr, union babel_msg *msg, struct babel_write_state *state, uint max_len); |
||
237 | static uint babel_write_ihu(struct babel_tlv *hdr, union babel_msg *msg, struct babel_write_state *state, uint max_len); |
||
238 | static uint babel_write_update(struct babel_tlv *hdr, union babel_msg *msg, struct babel_write_state *state, uint max_len); |
||
239 | static uint babel_write_route_request(struct babel_tlv *hdr, union babel_msg *msg, struct babel_write_state *state, uint max_len); |
||
240 | static uint babel_write_seqno_request(struct babel_tlv *hdr, union babel_msg *msg, struct babel_write_state *state, uint max_len); |
||
241 | 937e75d8 | Ondrej Zajicek (work) | |
242 | struct babel_tlv_data {
|
||
243 | u8 min_length; |
||
244 | int (*read_tlv)(struct babel_tlv *hdr, union babel_msg *m, struct babel_parse_state *state); |
||
245 | 3e236955 | Jan Moskyto Matejka | uint (*write_tlv)(struct babel_tlv *hdr, union babel_msg *m, struct babel_write_state *state, uint max_len); |
246 | 937e75d8 | Ondrej Zajicek (work) | void (*handle_tlv)(union babel_msg *m, struct babel_iface *ifa); |
247 | }; |
||
248 | |||
249 | 3e236955 | Jan Moskyto Matejka | static const struct babel_tlv_data tlv_data[BABEL_TLV_MAX] = { |
250 | 937e75d8 | Ondrej Zajicek (work) | [BABEL_TLV_ACK_REQ] = { |
251 | sizeof(struct babel_tlv_ack_req), |
||
252 | babel_read_ack_req, |
||
253 | NULL,
|
||
254 | babel_handle_ack_req |
||
255 | }, |
||
256 | [BABEL_TLV_ACK] = { |
||
257 | sizeof(struct babel_tlv_ack), |
||
258 | NULL,
|
||
259 | babel_write_ack, |
||
260 | NULL
|
||
261 | }, |
||
262 | [BABEL_TLV_HELLO] = { |
||
263 | sizeof(struct babel_tlv_hello), |
||
264 | babel_read_hello, |
||
265 | babel_write_hello, |
||
266 | babel_handle_hello |
||
267 | }, |
||
268 | [BABEL_TLV_IHU] = { |
||
269 | sizeof(struct babel_tlv_ihu), |
||
270 | babel_read_ihu, |
||
271 | babel_write_ihu, |
||
272 | babel_handle_ihu |
||
273 | }, |
||
274 | [BABEL_TLV_ROUTER_ID] = { |
||
275 | sizeof(struct babel_tlv_router_id), |
||
276 | babel_read_router_id, |
||
277 | NULL,
|
||
278 | NULL
|
||
279 | }, |
||
280 | [BABEL_TLV_NEXT_HOP] = { |
||
281 | sizeof(struct babel_tlv_next_hop), |
||
282 | babel_read_next_hop, |
||
283 | NULL,
|
||
284 | NULL
|
||
285 | }, |
||
286 | [BABEL_TLV_UPDATE] = { |
||
287 | sizeof(struct babel_tlv_update), |
||
288 | babel_read_update, |
||
289 | babel_write_update, |
||
290 | babel_handle_update |
||
291 | }, |
||
292 | [BABEL_TLV_ROUTE_REQUEST] = { |
||
293 | sizeof(struct babel_tlv_route_request), |
||
294 | babel_read_route_request, |
||
295 | babel_write_route_request, |
||
296 | babel_handle_route_request |
||
297 | }, |
||
298 | [BABEL_TLV_SEQNO_REQUEST] = { |
||
299 | sizeof(struct babel_tlv_seqno_request), |
||
300 | babel_read_seqno_request, |
||
301 | babel_write_seqno_request, |
||
302 | babel_handle_seqno_request |
||
303 | }, |
||
304 | }; |
||
305 | |||
306 | static int |
||
307 | babel_read_ack_req(struct babel_tlv *hdr, union babel_msg *m, |
||
308 | struct babel_parse_state *state)
|
||
309 | { |
||
310 | struct babel_tlv_ack_req *tlv = (void *) hdr; |
||
311 | struct babel_msg_ack_req *msg = &m->ack_req;
|
||
312 | |||
313 | msg->type = BABEL_TLV_ACK_REQ; |
||
314 | msg->nonce = get_u16(&tlv->nonce); |
||
315 | msg->interval = get_time16(&tlv->interval); |
||
316 | msg->sender = state->saddr; |
||
317 | |||
318 | if (!msg->interval)
|
||
319 | return PARSE_ERROR;
|
||
320 | |||
321 | return PARSE_SUCCESS;
|
||
322 | } |
||
323 | |||
324 | 3e236955 | Jan Moskyto Matejka | static uint
|
325 | 937e75d8 | Ondrej Zajicek (work) | babel_write_ack(struct babel_tlv *hdr, union babel_msg *m, |
326 | 3e236955 | Jan Moskyto Matejka | struct babel_write_state *state UNUSED, uint max_len UNUSED)
|
327 | 937e75d8 | Ondrej Zajicek (work) | { |
328 | struct babel_tlv_ack *tlv = (void *) hdr; |
||
329 | struct babel_msg_ack *msg = &m->ack;
|
||
330 | |||
331 | TLV_HDR0(tlv, BABEL_TLV_ACK); |
||
332 | put_u16(&tlv->nonce, msg->nonce); |
||
333 | |||
334 | return sizeof(struct babel_tlv_ack); |
||
335 | } |
||
336 | |||
337 | static int |
||
338 | babel_read_hello(struct babel_tlv *hdr, union babel_msg *m, |
||
339 | struct babel_parse_state *state)
|
||
340 | { |
||
341 | struct babel_tlv_hello *tlv = (void *) hdr; |
||
342 | struct babel_msg_hello *msg = &m->hello;
|
||
343 | |||
344 | msg->type = BABEL_TLV_HELLO; |
||
345 | msg->seqno = get_u16(&tlv->seqno); |
||
346 | msg->interval = get_time16(&tlv->interval); |
||
347 | msg->sender = state->saddr; |
||
348 | |||
349 | return PARSE_SUCCESS;
|
||
350 | } |
||
351 | |||
352 | 3e236955 | Jan Moskyto Matejka | static uint
|
353 | 937e75d8 | Ondrej Zajicek (work) | babel_write_hello(struct babel_tlv *hdr, union babel_msg *m, |
354 | 3e236955 | Jan Moskyto Matejka | struct babel_write_state *state UNUSED, uint max_len UNUSED)
|
355 | 937e75d8 | Ondrej Zajicek (work) | { |
356 | struct babel_tlv_hello *tlv = (void *) hdr; |
||
357 | struct babel_msg_hello *msg = &m->hello;
|
||
358 | |||
359 | TLV_HDR0(tlv, BABEL_TLV_HELLO); |
||
360 | put_u16(&tlv->seqno, msg->seqno); |
||
361 | put_time16(&tlv->interval, msg->interval); |
||
362 | |||
363 | return sizeof(struct babel_tlv_hello); |
||
364 | } |
||
365 | |||
366 | static int |
||
367 | babel_read_ihu(struct babel_tlv *hdr, union babel_msg *m, |
||
368 | struct babel_parse_state *state)
|
||
369 | { |
||
370 | struct babel_tlv_ihu *tlv = (void *) hdr; |
||
371 | struct babel_msg_ihu *msg = &m->ihu;
|
||
372 | |||
373 | msg->type = BABEL_TLV_IHU; |
||
374 | msg->ae = tlv->ae; |
||
375 | msg->rxcost = get_u16(&tlv->rxcost); |
||
376 | msg->interval = get_time16(&tlv->interval); |
||
377 | msg->addr = IPA_NONE; |
||
378 | msg->sender = state->saddr; |
||
379 | |||
380 | if (msg->ae >= BABEL_AE_MAX)
|
||
381 | return PARSE_IGNORE;
|
||
382 | |||
383 | 145ebfa1 | Ondrej Zajicek (work) | /*
|
384 | * We only actually read link-local IPs. In every other case, the addr field
|
||
385 | * will be 0 but validation will succeed. The handler takes care of these
|
||
386 | * cases. We handle them here anyway because we need the length for parsing
|
||
387 | * subtlvs.
|
||
388 | */
|
||
389 | switch (msg->ae)
|
||
390 | 937e75d8 | Ondrej Zajicek (work) | { |
391 | 145ebfa1 | Ondrej Zajicek (work) | case BABEL_AE_IP4:
|
392 | if (TLV_OPT_LENGTH(tlv) < 4) |
||
393 | return PARSE_ERROR;
|
||
394 | state->current_tlv_endpos += 4;
|
||
395 | break;
|
||
396 | |||
397 | case BABEL_AE_IP6:
|
||
398 | if (TLV_OPT_LENGTH(tlv) < 16) |
||
399 | return PARSE_ERROR;
|
||
400 | state->current_tlv_endpos += 16;
|
||
401 | break;
|
||
402 | |||
403 | case BABEL_AE_IP6_LL:
|
||
404 | 937e75d8 | Ondrej Zajicek (work) | if (TLV_OPT_LENGTH(tlv) < 8) |
405 | return PARSE_ERROR;
|
||
406 | |||
407 | msg->addr = ipa_from_ip6(get_ip6_ll(&tlv->addr)); |
||
408 | 145ebfa1 | Ondrej Zajicek (work) | state->current_tlv_endpos += 8;
|
409 | break;
|
||
410 | 937e75d8 | Ondrej Zajicek (work) | } |
411 | |||
412 | return PARSE_SUCCESS;
|
||
413 | } |
||
414 | |||
415 | 3e236955 | Jan Moskyto Matejka | static uint
|
416 | 937e75d8 | Ondrej Zajicek (work) | babel_write_ihu(struct babel_tlv *hdr, union babel_msg *m, |
417 | 3e236955 | Jan Moskyto Matejka | struct babel_write_state *state UNUSED, uint max_len)
|
418 | 937e75d8 | Ondrej Zajicek (work) | { |
419 | struct babel_tlv_ihu *tlv = (void *) hdr; |
||
420 | struct babel_msg_ihu *msg = &m->ihu;
|
||
421 | |||
422 | if (ipa_is_link_local(msg->addr) && max_len < sizeof(struct babel_tlv_ihu) + 8) |
||
423 | return 0; |
||
424 | |||
425 | TLV_HDR0(tlv, BABEL_TLV_IHU); |
||
426 | put_u16(&tlv->rxcost, msg->rxcost); |
||
427 | put_time16(&tlv->interval, msg->interval); |
||
428 | |||
429 | if (!ipa_is_link_local(msg->addr))
|
||
430 | { |
||
431 | tlv->ae = BABEL_AE_WILDCARD; |
||
432 | return sizeof(struct babel_tlv_ihu); |
||
433 | } |
||
434 | put_ip6_ll(&tlv->addr, msg->addr); |
||
435 | tlv->ae = BABEL_AE_IP6_LL; |
||
436 | hdr->length += 8;
|
||
437 | return sizeof(struct babel_tlv_ihu) + 8; |
||
438 | } |
||
439 | |||
440 | static int |
||
441 | babel_read_router_id(struct babel_tlv *hdr, union babel_msg *m UNUSED, |
||
442 | struct babel_parse_state *state)
|
||
443 | { |
||
444 | struct babel_tlv_router_id *tlv = (void *) hdr; |
||
445 | |||
446 | state->router_id = get_u64(&tlv->router_id); |
||
447 | state->router_id_seen = 1;
|
||
448 | |||
449 | return PARSE_IGNORE;
|
||
450 | } |
||
451 | |||
452 | /* This is called directly from babel_write_update() */
|
||
453 | 3e236955 | Jan Moskyto Matejka | static uint
|
454 | 937e75d8 | Ondrej Zajicek (work) | babel_write_router_id(struct babel_tlv *hdr, u64 router_id,
|
455 | 3e236955 | Jan Moskyto Matejka | struct babel_write_state *state, uint max_len UNUSED)
|
456 | 937e75d8 | Ondrej Zajicek (work) | { |
457 | struct babel_tlv_router_id *tlv = (void *) hdr; |
||
458 | |||
459 | /* We still assume that first min_length bytes are available and zeroed */
|
||
460 | |||
461 | TLV_HDR0(tlv, BABEL_TLV_ROUTER_ID); |
||
462 | put_u64(&tlv->router_id, router_id); |
||
463 | |||
464 | state->router_id = router_id; |
||
465 | state->router_id_seen = 1;
|
||
466 | |||
467 | return sizeof(struct babel_tlv_router_id); |
||
468 | } |
||
469 | |||
470 | static int |
||
471 | babel_read_next_hop(struct babel_tlv *hdr, union babel_msg *m UNUSED, |
||
472 | struct babel_parse_state *state)
|
||
473 | { |
||
474 | struct babel_tlv_next_hop *tlv = (void *) hdr; |
||
475 | |||
476 | switch (tlv->ae)
|
||
477 | { |
||
478 | case BABEL_AE_WILDCARD:
|
||
479 | return PARSE_ERROR;
|
||
480 | |||
481 | case BABEL_AE_IP4:
|
||
482 | 4324025f | Ondrej Zajicek (work) | if (TLV_OPT_LENGTH(tlv) < sizeof(ip4_addr)) |
483 | return PARSE_ERROR;
|
||
484 | |||
485 | state->next_hop_ip4 = ipa_from_ip4(get_ip4(&tlv->addr)); |
||
486 | 145ebfa1 | Ondrej Zajicek (work) | state->current_tlv_endpos += sizeof(ip4_addr);
|
487 | 937e75d8 | Ondrej Zajicek (work) | return PARSE_IGNORE;
|
488 | |||
489 | case BABEL_AE_IP6:
|
||
490 | if (TLV_OPT_LENGTH(tlv) < sizeof(ip6_addr)) |
||
491 | return PARSE_ERROR;
|
||
492 | |||
493 | 4324025f | Ondrej Zajicek (work) | state->next_hop_ip6 = ipa_from_ip6(get_ip6(&tlv->addr)); |
494 | 145ebfa1 | Ondrej Zajicek (work) | state->current_tlv_endpos += sizeof(ip6_addr);
|
495 | 937e75d8 | Ondrej Zajicek (work) | return PARSE_IGNORE;
|
496 | |||
497 | case BABEL_AE_IP6_LL:
|
||
498 | if (TLV_OPT_LENGTH(tlv) < 8) |
||
499 | return PARSE_ERROR;
|
||
500 | |||
501 | 4324025f | Ondrej Zajicek (work) | state->next_hop_ip6 = ipa_from_ip6(get_ip6_ll(&tlv->addr)); |
502 | 145ebfa1 | Ondrej Zajicek (work) | state->current_tlv_endpos += 8;
|
503 | 937e75d8 | Ondrej Zajicek (work) | return PARSE_IGNORE;
|
504 | |||
505 | default:
|
||
506 | return PARSE_IGNORE;
|
||
507 | } |
||
508 | |||
509 | return PARSE_IGNORE;
|
||
510 | } |
||
511 | |||
512 | 4324025f | Ondrej Zajicek (work) | /* This is called directly from babel_write_update() and returns -1 if a next
|
513 | hop should be written but there is not enough space. */
|
||
514 | static int |
||
515 | babel_write_next_hop(struct babel_tlv *hdr, ip_addr addr,
|
||
516 | struct babel_write_state *state, uint max_len)
|
||
517 | { |
||
518 | struct babel_tlv_next_hop *tlv = (void *) hdr; |
||
519 | |||
520 | if (ipa_zero(addr))
|
||
521 | { |
||
522 | /* Should not happen */
|
||
523 | return 0; |
||
524 | } |
||
525 | else if (ipa_is_ip4(addr) && !ipa_equal(addr, state->next_hop_ip4)) |
||
526 | { |
||
527 | uint len = sizeof(struct babel_tlv_next_hop) + sizeof(ip4_addr); |
||
528 | if (len > max_len)
|
||
529 | return -1; |
||
530 | |||
531 | TLV_HDR(tlv, BABEL_TLV_NEXT_HOP, len); |
||
532 | |||
533 | tlv->ae = BABEL_AE_IP4; |
||
534 | put_ip4(&tlv->addr, ipa_to_ip4(addr)); |
||
535 | state->next_hop_ip4 = addr; |
||
536 | |||
537 | return len;
|
||
538 | } |
||
539 | else if (ipa_is_ip6(addr) && !ipa_equal(addr, state->next_hop_ip6)) |
||
540 | { |
||
541 | uint len = sizeof(struct babel_tlv_next_hop) + sizeof(ip6_addr); |
||
542 | if (len > max_len)
|
||
543 | return -1; |
||
544 | |||
545 | TLV_HDR(tlv, BABEL_TLV_NEXT_HOP, len); |
||
546 | |||
547 | tlv->ae = BABEL_AE_IP6; |
||
548 | put_ip6(&tlv->addr, ipa_to_ip6(addr)); |
||
549 | state->next_hop_ip6 = addr; |
||
550 | |||
551 | return len;
|
||
552 | } |
||
553 | |||
554 | return 0; |
||
555 | } |
||
556 | |||
557 | 937e75d8 | Ondrej Zajicek (work) | static int |
558 | babel_read_update(struct babel_tlv *hdr, union babel_msg *m, |
||
559 | struct babel_parse_state *state)
|
||
560 | { |
||
561 | struct babel_tlv_update *tlv = (void *) hdr; |
||
562 | struct babel_msg_update *msg = &m->update;
|
||
563 | |||
564 | msg->type = BABEL_TLV_UPDATE; |
||
565 | msg->interval = get_time16(&tlv->interval); |
||
566 | msg->seqno = get_u16(&tlv->seqno); |
||
567 | msg->metric = get_u16(&tlv->metric); |
||
568 | |||
569 | /* Length of received prefix data without omitted part */
|
||
570 | 3e236955 | Jan Moskyto Matejka | int len = BYTES(tlv->plen) - (int) tlv->omitted; |
571 | 937e75d8 | Ondrej Zajicek (work) | u8 buf[16] = {};
|
572 | |||
573 | 3e236955 | Jan Moskyto Matejka | if ((len < 0) || ((uint) len > TLV_OPT_LENGTH(tlv))) |
574 | 937e75d8 | Ondrej Zajicek (work) | return PARSE_ERROR;
|
575 | |||
576 | switch (tlv->ae)
|
||
577 | { |
||
578 | case BABEL_AE_WILDCARD:
|
||
579 | if (tlv->plen > 0) |
||
580 | return PARSE_ERROR;
|
||
581 | |||
582 | 5e8df049 | Ondrej Zajicek (work) | if (msg->metric != 65535) |
583 | return PARSE_ERROR;
|
||
584 | |||
585 | 5d6ca220 | Ondrej Zajicek (work) | msg->wildcard = 1;
|
586 | 937e75d8 | Ondrej Zajicek (work) | break;
|
587 | |||
588 | case BABEL_AE_IP4:
|
||
589 | 4324025f | Ondrej Zajicek (work) | if (tlv->plen > IP4_MAX_PREFIX_LENGTH)
|
590 | return PARSE_ERROR;
|
||
591 | |||
592 | /* Cannot omit data if there is no saved prefix */
|
||
593 | if (tlv->omitted && !state->def_ip4_prefix_seen)
|
||
594 | return PARSE_ERROR;
|
||
595 | |||
596 | /* Need next hop for v4 routes */
|
||
597 | if (ipa_zero(state->next_hop_ip4))
|
||
598 | return PARSE_ERROR;
|
||
599 | |||
600 | /* Merge saved prefix and received prefix parts */
|
||
601 | memcpy(buf, state->def_ip4_prefix, tlv->omitted); |
||
602 | memcpy(buf + tlv->omitted, tlv->addr, len); |
||
603 | |||
604 | ip4_addr prefix4 = get_ip4(buf); |
||
605 | net_fill_ip4(&msg->net, prefix4, tlv->plen); |
||
606 | |||
607 | if (tlv->flags & BABEL_FLAG_DEF_PREFIX)
|
||
608 | { |
||
609 | put_ip4(state->def_ip4_prefix, prefix4); |
||
610 | state->def_ip4_prefix_seen = 1;
|
||
611 | } |
||
612 | |||
613 | msg->next_hop = state->next_hop_ip4; |
||
614 | |||
615 | break;
|
||
616 | 937e75d8 | Ondrej Zajicek (work) | |
617 | case BABEL_AE_IP6:
|
||
618 | 5e8df049 | Ondrej Zajicek (work) | if (tlv->plen > IP6_MAX_PREFIX_LENGTH)
|
619 | 937e75d8 | Ondrej Zajicek (work) | return PARSE_ERROR;
|
620 | |||
621 | /* Cannot omit data if there is no saved prefix */
|
||
622 | if (tlv->omitted && !state->def_ip6_prefix_seen)
|
||
623 | return PARSE_ERROR;
|
||
624 | |||
625 | /* Merge saved prefix and received prefix parts */
|
||
626 | memcpy(buf, state->def_ip6_prefix, tlv->omitted); |
||
627 | memcpy(buf + tlv->omitted, tlv->addr, len); |
||
628 | |||
629 | 4324025f | Ondrej Zajicek (work) | ip6_addr prefix6 = get_ip6(buf); |
630 | net_fill_ip6(&msg->net, prefix6, tlv->plen); |
||
631 | 937e75d8 | Ondrej Zajicek (work) | |
632 | if (tlv->flags & BABEL_FLAG_DEF_PREFIX)
|
||
633 | { |
||
634 | 4324025f | Ondrej Zajicek (work) | put_ip6(state->def_ip6_prefix, prefix6); |
635 | 937e75d8 | Ondrej Zajicek (work) | state->def_ip6_prefix_seen = 1;
|
636 | } |
||
637 | |||
638 | if (tlv->flags & BABEL_FLAG_ROUTER_ID)
|
||
639 | { |
||
640 | 4324025f | Ondrej Zajicek (work) | state->router_id = ((u64) _I2(prefix6)) << 32 | _I3(prefix6);
|
641 | 937e75d8 | Ondrej Zajicek (work) | state->router_id_seen = 1;
|
642 | } |
||
643 | 4324025f | Ondrej Zajicek (work) | |
644 | msg->next_hop = state->next_hop_ip6; |
||
645 | |||
646 | 937e75d8 | Ondrej Zajicek (work) | break;
|
647 | |||
648 | case BABEL_AE_IP6_LL:
|
||
649 | /* ??? */
|
||
650 | return PARSE_IGNORE;
|
||
651 | |||
652 | default:
|
||
653 | return PARSE_IGNORE;
|
||
654 | } |
||
655 | |||
656 | ecae2f43 | Ondrej Zajicek (work) | /* Update must have Router ID, unless it is retraction */
|
657 | if (!state->router_id_seen && (msg->metric != BABEL_INFINITY))
|
||
658 | 937e75d8 | Ondrej Zajicek (work) | { |
659 | DBG("Babel: No router ID seen before update\n");
|
||
660 | return PARSE_ERROR;
|
||
661 | } |
||
662 | |||
663 | msg->router_id = state->router_id; |
||
664 | msg->sender = state->saddr; |
||
665 | 145ebfa1 | Ondrej Zajicek (work) | state->current_tlv_endpos += len; |
666 | 937e75d8 | Ondrej Zajicek (work) | |
667 | return PARSE_SUCCESS;
|
||
668 | } |
||
669 | |||
670 | 3e236955 | Jan Moskyto Matejka | static uint
|
671 | 937e75d8 | Ondrej Zajicek (work) | babel_write_update(struct babel_tlv *hdr, union babel_msg *m, |
672 | 3e236955 | Jan Moskyto Matejka | struct babel_write_state *state, uint max_len)
|
673 | 937e75d8 | Ondrej Zajicek (work) | { |
674 | struct babel_msg_update *msg = &m->update;
|
||
675 | 3e236955 | Jan Moskyto Matejka | uint len0 = 0;
|
676 | 937e75d8 | Ondrej Zajicek (work) | |
677 | /*
|
||
678 | * When needed, we write Router-ID TLV before Update TLV and return size of
|
||
679 | * both of them. There is enough space for the Router-ID TLV, because
|
||
680 | * sizeof(struct babel_tlv_router_id) == sizeof(struct babel_tlv_update).
|
||
681 | 5d6ca220 | Ondrej Zajicek (work) | *
|
682 | 4324025f | Ondrej Zajicek (work) | * Router ID is not used for retractions, so do not use it in such case.
|
683 | 937e75d8 | Ondrej Zajicek (work) | */
|
684 | 5d6ca220 | Ondrej Zajicek (work) | if ((msg->metric < BABEL_INFINITY) &&
|
685 | (!state->router_id_seen || (msg->router_id != state->router_id))) |
||
686 | 937e75d8 | Ondrej Zajicek (work) | { |
687 | len0 = babel_write_router_id(hdr, msg->router_id, state, max_len); |
||
688 | 4324025f | Ondrej Zajicek (work) | hdr = NEXT_TLV(hdr); |
689 | 937e75d8 | Ondrej Zajicek (work) | } |
690 | |||
691 | 4324025f | Ondrej Zajicek (work) | /*
|
692 | * We also may add Next Hop TLV for regular updates. It may fail for not
|
||
693 | * enough space or it may be unnecessary as the next hop is the same as the
|
||
694 | * last one already announced. So we handle all three cases.
|
||
695 | */
|
||
696 | if (msg->metric < BABEL_INFINITY)
|
||
697 | { |
||
698 | int l = babel_write_next_hop(hdr, msg->next_hop, state, max_len - len0);
|
||
699 | if (l < 0) |
||
700 | return 0; |
||
701 | |||
702 | if (l)
|
||
703 | { |
||
704 | len0 += l; |
||
705 | hdr = NEXT_TLV(hdr); |
||
706 | } |
||
707 | } |
||
708 | |||
709 | struct babel_tlv_update *tlv = (void *) hdr; |
||
710 | 5e8df049 | Ondrej Zajicek (work) | uint len = sizeof(struct babel_tlv_update) + NET_SIZE(&msg->net); |
711 | 937e75d8 | Ondrej Zajicek (work) | |
712 | if (len0 + len > max_len)
|
||
713 | return 0; |
||
714 | |||
715 | memset(tlv, 0, sizeof(struct babel_tlv_update)); |
||
716 | TLV_HDR(tlv, BABEL_TLV_UPDATE, len); |
||
717 | 5d6ca220 | Ondrej Zajicek (work) | |
718 | if (msg->wildcard)
|
||
719 | { |
||
720 | tlv->ae = BABEL_AE_WILDCARD; |
||
721 | tlv->plen = 0;
|
||
722 | } |
||
723 | 4324025f | Ondrej Zajicek (work) | else if (msg->net.type == NET_IP4) |
724 | { |
||
725 | tlv->ae = BABEL_AE_IP4; |
||
726 | tlv->plen = net4_pxlen(&msg->net); |
||
727 | put_ip4_px(tlv->addr, &msg->net); |
||
728 | } |
||
729 | 5d6ca220 | Ondrej Zajicek (work) | else
|
730 | { |
||
731 | tlv->ae = BABEL_AE_IP6; |
||
732 | 5e8df049 | Ondrej Zajicek (work) | tlv->plen = net6_pxlen(&msg->net); |
733 | b3c6273e | Ondrej Zajicek (work) | |
734 | /* Address compression - omit initial matching bytes */
|
||
735 | u8 buf[16], omit;
|
||
736 | put_ip6(buf, net6_prefix(&msg->net)); |
||
737 | omit = bytes_equal(buf, state->def_ip6_prefix, |
||
738 | MIN(tlv->plen, state->def_ip6_pxlen) / 8);
|
||
739 | |||
740 | if (omit > 0) |
||
741 | { |
||
742 | memcpy(tlv->addr, buf + omit, NET_SIZE(&msg->net) - omit); |
||
743 | |||
744 | tlv->omitted = omit; |
||
745 | tlv->length -= omit; |
||
746 | len -= omit; |
||
747 | } |
||
748 | else
|
||
749 | { |
||
750 | put_ip6_px(tlv->addr, &msg->net); |
||
751 | tlv->flags |= BABEL_FLAG_DEF_PREFIX; |
||
752 | |||
753 | put_ip6(state->def_ip6_prefix, net6_prefix(&msg->net)); |
||
754 | state->def_ip6_pxlen = tlv->plen; |
||
755 | } |
||
756 | 5d6ca220 | Ondrej Zajicek (work) | } |
757 | |||
758 | 937e75d8 | Ondrej Zajicek (work) | put_time16(&tlv->interval, msg->interval); |
759 | put_u16(&tlv->seqno, msg->seqno); |
||
760 | put_u16(&tlv->metric, msg->metric); |
||
761 | |||
762 | return len0 + len;
|
||
763 | } |
||
764 | |||
765 | static int |
||
766 | babel_read_route_request(struct babel_tlv *hdr, union babel_msg *m, |
||
767 | 3e236955 | Jan Moskyto Matejka | struct babel_parse_state *state UNUSED)
|
768 | 937e75d8 | Ondrej Zajicek (work) | { |
769 | struct babel_tlv_route_request *tlv = (void *) hdr; |
||
770 | struct babel_msg_route_request *msg = &m->route_request;
|
||
771 | |||
772 | msg->type = BABEL_TLV_ROUTE_REQUEST; |
||
773 | |||
774 | switch (tlv->ae)
|
||
775 | { |
||
776 | case BABEL_AE_WILDCARD:
|
||
777 | /* Wildcard requests must have plen 0 */
|
||
778 | if (tlv->plen > 0) |
||
779 | return PARSE_ERROR;
|
||
780 | |||
781 | msg->full = 1;
|
||
782 | return PARSE_SUCCESS;
|
||
783 | |||
784 | case BABEL_AE_IP4:
|
||
785 | 4324025f | Ondrej Zajicek (work) | if (tlv->plen > IP4_MAX_PREFIX_LENGTH)
|
786 | return PARSE_ERROR;
|
||
787 | |||
788 | if (TLV_OPT_LENGTH(tlv) < BYTES(tlv->plen))
|
||
789 | return PARSE_ERROR;
|
||
790 | |||
791 | read_ip4_px(&msg->net, tlv->addr, tlv->plen); |
||
792 | 145ebfa1 | Ondrej Zajicek (work) | state->current_tlv_endpos += BYTES(tlv->plen); |
793 | 4324025f | Ondrej Zajicek (work) | return PARSE_SUCCESS;
|
794 | 937e75d8 | Ondrej Zajicek (work) | |
795 | case BABEL_AE_IP6:
|
||
796 | 5e8df049 | Ondrej Zajicek (work) | if (tlv->plen > IP6_MAX_PREFIX_LENGTH)
|
797 | 937e75d8 | Ondrej Zajicek (work) | return PARSE_ERROR;
|
798 | |||
799 | 3e236955 | Jan Moskyto Matejka | if (TLV_OPT_LENGTH(tlv) < BYTES(tlv->plen))
|
800 | 937e75d8 | Ondrej Zajicek (work) | return PARSE_ERROR;
|
801 | |||
802 | 5e8df049 | Ondrej Zajicek (work) | read_ip6_px(&msg->net, tlv->addr, tlv->plen); |
803 | 145ebfa1 | Ondrej Zajicek (work) | state->current_tlv_endpos += BYTES(tlv->plen); |
804 | 937e75d8 | Ondrej Zajicek (work) | return PARSE_SUCCESS;
|
805 | |||
806 | case BABEL_AE_IP6_LL:
|
||
807 | return PARSE_ERROR;
|
||
808 | |||
809 | default:
|
||
810 | return PARSE_IGNORE;
|
||
811 | } |
||
812 | |||
813 | return PARSE_IGNORE;
|
||
814 | } |
||
815 | |||
816 | 3e236955 | Jan Moskyto Matejka | static uint
|
817 | 937e75d8 | Ondrej Zajicek (work) | babel_write_route_request(struct babel_tlv *hdr, union babel_msg *m, |
818 | 3e236955 | Jan Moskyto Matejka | struct babel_write_state *state UNUSED, uint max_len)
|
819 | 937e75d8 | Ondrej Zajicek (work) | { |
820 | struct babel_tlv_route_request *tlv = (void *) hdr; |
||
821 | struct babel_msg_route_request *msg = &m->route_request;
|
||
822 | |||
823 | 5e8df049 | Ondrej Zajicek (work) | uint len = sizeof(struct babel_tlv_route_request) + NET_SIZE(&msg->net); |
824 | 937e75d8 | Ondrej Zajicek (work) | |
825 | if (len > max_len)
|
||
826 | return 0; |
||
827 | |||
828 | TLV_HDR(tlv, BABEL_TLV_ROUTE_REQUEST, len); |
||
829 | |||
830 | if (msg->full)
|
||
831 | { |
||
832 | tlv->ae = BABEL_AE_WILDCARD; |
||
833 | tlv->plen = 0;
|
||
834 | } |
||
835 | 4324025f | Ondrej Zajicek (work) | else if (msg->net.type == NET_IP4) |
836 | { |
||
837 | tlv->ae = BABEL_AE_IP4; |
||
838 | tlv->plen = net4_pxlen(&msg->net); |
||
839 | put_ip4_px(tlv->addr, &msg->net); |
||
840 | } |
||
841 | 937e75d8 | Ondrej Zajicek (work) | else
|
842 | { |
||
843 | tlv->ae = BABEL_AE_IP6; |
||
844 | 5e8df049 | Ondrej Zajicek (work) | tlv->plen = net6_pxlen(&msg->net); |
845 | put_ip6_px(tlv->addr, &msg->net); |
||
846 | 937e75d8 | Ondrej Zajicek (work) | } |
847 | |||
848 | return len;
|
||
849 | } |
||
850 | |||
851 | static int |
||
852 | babel_read_seqno_request(struct babel_tlv *hdr, union babel_msg *m, |
||
853 | struct babel_parse_state *state)
|
||
854 | { |
||
855 | struct babel_tlv_seqno_request *tlv = (void *) hdr; |
||
856 | struct babel_msg_seqno_request *msg = &m->seqno_request;
|
||
857 | |||
858 | msg->type = BABEL_TLV_SEQNO_REQUEST; |
||
859 | msg->seqno = get_u16(&tlv->seqno); |
||
860 | msg->hop_count = tlv->hop_count; |
||
861 | msg->router_id = get_u64(&tlv->router_id); |
||
862 | msg->sender = state->saddr; |
||
863 | |||
864 | if (tlv->hop_count == 0) |
||
865 | return PARSE_ERROR;
|
||
866 | |||
867 | switch (tlv->ae)
|
||
868 | { |
||
869 | case BABEL_AE_WILDCARD:
|
||
870 | return PARSE_ERROR;
|
||
871 | |||
872 | case BABEL_AE_IP4:
|
||
873 | 4324025f | Ondrej Zajicek (work) | if (tlv->plen > IP4_MAX_PREFIX_LENGTH)
|
874 | return PARSE_ERROR;
|
||
875 | |||
876 | if (TLV_OPT_LENGTH(tlv) < BYTES(tlv->plen))
|
||
877 | return PARSE_ERROR;
|
||
878 | |||
879 | read_ip4_px(&msg->net, tlv->addr, tlv->plen); |
||
880 | 145ebfa1 | Ondrej Zajicek (work) | state->current_tlv_endpos += BYTES(tlv->plen); |
881 | 4324025f | Ondrej Zajicek (work) | return PARSE_SUCCESS;
|
882 | 937e75d8 | Ondrej Zajicek (work) | |
883 | case BABEL_AE_IP6:
|
||
884 | 5e8df049 | Ondrej Zajicek (work) | if (tlv->plen > IP6_MAX_PREFIX_LENGTH)
|
885 | 937e75d8 | Ondrej Zajicek (work) | return PARSE_ERROR;
|
886 | |||
887 | 3e236955 | Jan Moskyto Matejka | if (TLV_OPT_LENGTH(tlv) < BYTES(tlv->plen))
|
888 | 937e75d8 | Ondrej Zajicek (work) | return PARSE_ERROR;
|
889 | |||
890 | 5e8df049 | Ondrej Zajicek (work) | read_ip6_px(&msg->net, tlv->addr, tlv->plen); |
891 | 145ebfa1 | Ondrej Zajicek (work) | state->current_tlv_endpos += BYTES(tlv->plen); |
892 | 937e75d8 | Ondrej Zajicek (work) | return PARSE_SUCCESS;
|
893 | |||
894 | case BABEL_AE_IP6_LL:
|
||
895 | return PARSE_ERROR;
|
||
896 | |||
897 | default:
|
||
898 | return PARSE_IGNORE;
|
||
899 | } |
||
900 | |||
901 | return PARSE_IGNORE;
|
||
902 | } |
||
903 | |||
904 | 3e236955 | Jan Moskyto Matejka | static uint
|
905 | 937e75d8 | Ondrej Zajicek (work) | babel_write_seqno_request(struct babel_tlv *hdr, union babel_msg *m, |
906 | 3e236955 | Jan Moskyto Matejka | struct babel_write_state *state UNUSED, uint max_len)
|
907 | 937e75d8 | Ondrej Zajicek (work) | { |
908 | struct babel_tlv_seqno_request *tlv = (void *) hdr; |
||
909 | struct babel_msg_seqno_request *msg = &m->seqno_request;
|
||
910 | |||
911 | 5e8df049 | Ondrej Zajicek (work) | uint len = sizeof(struct babel_tlv_seqno_request) + NET_SIZE(&msg->net); |
912 | 937e75d8 | Ondrej Zajicek (work) | |
913 | if (len > max_len)
|
||
914 | return 0; |
||
915 | |||
916 | TLV_HDR(tlv, BABEL_TLV_SEQNO_REQUEST, len); |
||
917 | 4324025f | Ondrej Zajicek (work) | |
918 | if (msg->net.type == NET_IP4)
|
||
919 | { |
||
920 | tlv->ae = BABEL_AE_IP4; |
||
921 | tlv->plen = net4_pxlen(&msg->net); |
||
922 | put_ip4_px(tlv->addr, &msg->net); |
||
923 | } |
||
924 | else
|
||
925 | { |
||
926 | tlv->ae = BABEL_AE_IP6; |
||
927 | tlv->plen = net6_pxlen(&msg->net); |
||
928 | put_ip6_px(tlv->addr, &msg->net); |
||
929 | } |
||
930 | |||
931 | 937e75d8 | Ondrej Zajicek (work) | put_u16(&tlv->seqno, msg->seqno); |
932 | tlv->hop_count = msg->hop_count; |
||
933 | put_u64(&tlv->router_id, msg->router_id); |
||
934 | |||
935 | return len;
|
||
936 | } |
||
937 | |||
938 | static inline int |
||
939 | 145ebfa1 | Ondrej Zajicek (work) | babel_read_subtlvs(struct babel_tlv *hdr,
|
940 | union babel_msg *msg UNUSED,
|
||
941 | struct babel_parse_state *state)
|
||
942 | { |
||
943 | struct babel_tlv *tlv;
|
||
944 | |||
945 | for (tlv = (void *) hdr + state->current_tlv_endpos; |
||
946 | 5220cb63 | Ondrej Zajicek (work) | (void *) tlv < (void *) hdr + TLV_LENGTH(hdr); |
947 | 145ebfa1 | Ondrej Zajicek (work) | tlv = NEXT_TLV(tlv)) |
948 | { |
||
949 | /*
|
||
950 | * The subtlv type space is non-contiguous (due to the mandatory bit), so
|
||
951 | * use a switch for dispatch instead of the mapping array we use for TLVs
|
||
952 | */
|
||
953 | switch (tlv->type)
|
||
954 | { |
||
955 | case BABEL_SUBTLV_PAD1:
|
||
956 | case BABEL_SUBTLV_PADN:
|
||
957 | /* FIXME: Framing errors in PADN are silently ignored, see babel_process_packet() */
|
||
958 | break;
|
||
959 | |||
960 | default:
|
||
961 | /* Unknown mandatory subtlv; PARSE_IGNORE ignores the whole TLV */
|
||
962 | if (tlv->type > 128) |
||
963 | { |
||
964 | DBG("Babel: Mandatory subtlv %d found; skipping TLV\n", tlv->type);
|
||
965 | return PARSE_IGNORE;
|
||
966 | } |
||
967 | break;
|
||
968 | } |
||
969 | } |
||
970 | |||
971 | return PARSE_SUCCESS;
|
||
972 | } |
||
973 | |||
974 | static inline int |
||
975 | 937e75d8 | Ondrej Zajicek (work) | babel_read_tlv(struct babel_tlv *hdr,
|
976 | union babel_msg *msg,
|
||
977 | struct babel_parse_state *state)
|
||
978 | { |
||
979 | if ((hdr->type <= BABEL_TLV_PADN) ||
|
||
980 | (hdr->type >= BABEL_TLV_MAX) || |
||
981 | !tlv_data[hdr->type].read_tlv) |
||
982 | return PARSE_IGNORE;
|
||
983 | |||
984 | if (TLV_LENGTH(hdr) < tlv_data[hdr->type].min_length)
|
||
985 | return PARSE_ERROR;
|
||
986 | |||
987 | 145ebfa1 | Ondrej Zajicek (work) | state->current_tlv_endpos = tlv_data[hdr->type].min_length; |
988 | 937e75d8 | Ondrej Zajicek (work) | memset(msg, 0, sizeof(*msg)); |
989 | 145ebfa1 | Ondrej Zajicek (work) | |
990 | int res = tlv_data[hdr->type].read_tlv(hdr, msg, state);
|
||
991 | if (res != PARSE_SUCCESS)
|
||
992 | return res;
|
||
993 | |||
994 | return babel_read_subtlvs(hdr, msg, state);
|
||
995 | 937e75d8 | Ondrej Zajicek (work) | } |
996 | |||
997 | 3e236955 | Jan Moskyto Matejka | static uint
|
998 | 937e75d8 | Ondrej Zajicek (work) | babel_write_tlv(struct babel_tlv *hdr,
|
999 | union babel_msg *msg,
|
||
1000 | struct babel_write_state *state,
|
||
1001 | 3e236955 | Jan Moskyto Matejka | uint max_len) |
1002 | 937e75d8 | Ondrej Zajicek (work) | { |
1003 | if ((msg->type <= BABEL_TLV_PADN) ||
|
||
1004 | (msg->type >= BABEL_TLV_MAX) || |
||
1005 | !tlv_data[msg->type].write_tlv) |
||
1006 | return 0; |
||
1007 | |||
1008 | if (tlv_data[msg->type].min_length > max_len)
|
||
1009 | return 0; |
||
1010 | |||
1011 | memset(hdr, 0, tlv_data[msg->type].min_length);
|
||
1012 | return tlv_data[msg->type].write_tlv(hdr, msg, state, max_len);
|
||
1013 | } |
||
1014 | |||
1015 | |||
1016 | /*
|
||
1017 | * Packet RX/TX functions
|
||
1018 | */
|
||
1019 | |||
1020 | static int |
||
1021 | babel_send_to(struct babel_iface *ifa, ip_addr dest)
|
||
1022 | { |
||
1023 | sock *sk = ifa->sk; |
||
1024 | struct babel_pkt_header *hdr = (void *) sk->tbuf; |
||
1025 | int len = get_u16(&hdr->length) + sizeof(struct babel_pkt_header); |
||
1026 | |||
1027 | DBG("Babel: Sending %d bytes to %I\n", len, dest);
|
||
1028 | return sk_send_to(sk, len, dest, 0); |
||
1029 | } |
||
1030 | |||
1031 | /**
|
||
1032 | * babel_write_queue - Write a TLV queue to a transmission buffer
|
||
1033 | * @ifa: Interface holding the transmission buffer
|
||
1034 | * @queue: TLV queue to write (containing internal-format TLVs)
|
||
1035 | *
|
||
1036 | * This function writes a packet to the interface transmission buffer with as
|
||
1037 | * many TLVs from the &queue as will fit in the buffer. It returns the number of
|
||
1038 | * bytes written (NOT counting the packet header). The function is called by
|
||
1039 | * babel_send_queue() and babel_send_unicast() to construct packets for
|
||
1040 | * transmission, and uses per-TLV helper functions to convert the
|
||
1041 | * internal-format TLVs to their wire representations.
|
||
1042 | *
|
||
1043 | * The TLVs in the queue are freed after they are written to the buffer.
|
||
1044 | */
|
||
1045 | 3e236955 | Jan Moskyto Matejka | static uint
|
1046 | 937e75d8 | Ondrej Zajicek (work) | babel_write_queue(struct babel_iface *ifa, list *queue)
|
1047 | { |
||
1048 | struct babel_proto *p = ifa->proto;
|
||
1049 | 4324025f | Ondrej Zajicek (work) | struct babel_write_state state = { .next_hop_ip6 = ifa->addr };
|
1050 | 937e75d8 | Ondrej Zajicek (work) | |
1051 | if (EMPTY_LIST(*queue))
|
||
1052 | return 0; |
||
1053 | |||
1054 | byte *pos = ifa->sk->tbuf; |
||
1055 | byte *end = pos + ifa->tx_length; |
||
1056 | |||
1057 | struct babel_pkt_header *pkt = (void *) pos; |
||
1058 | pkt->magic = BABEL_MAGIC; |
||
1059 | pkt->version = BABEL_VERSION; |
||
1060 | pkt->length = 0;
|
||
1061 | pos += sizeof(struct babel_pkt_header); |
||
1062 | |||
1063 | struct babel_msg_node *msg;
|
||
1064 | WALK_LIST_FIRST(msg, *queue) |
||
1065 | { |
||
1066 | 3e236955 | Jan Moskyto Matejka | if (pos >= end)
|
1067 | break;
|
||
1068 | |||
1069 | 937e75d8 | Ondrej Zajicek (work) | int len = babel_write_tlv((struct babel_tlv *) pos, &msg->msg, &state, end - pos); |
1070 | |||
1071 | if (!len)
|
||
1072 | break;
|
||
1073 | |||
1074 | pos += len; |
||
1075 | rem_node(NODE msg); |
||
1076 | sl_free(p->msg_slab, msg); |
||
1077 | } |
||
1078 | |||
1079 | 3e236955 | Jan Moskyto Matejka | uint plen = pos - (byte *) pkt; |
1080 | 937e75d8 | Ondrej Zajicek (work) | put_u16(&pkt->length, plen - sizeof(struct babel_pkt_header)); |
1081 | |||
1082 | return plen;
|
||
1083 | } |
||
1084 | |||
1085 | void
|
||
1086 | babel_send_queue(void *arg)
|
||
1087 | { |
||
1088 | struct babel_iface *ifa = arg;
|
||
1089 | while ((babel_write_queue(ifa, &ifa->msg_queue) > 0) && |
||
1090 | (babel_send_to(ifa, IP6_BABEL_ROUTERS) > 0));
|
||
1091 | } |
||
1092 | |||
1093 | static inline void |
||
1094 | babel_kick_queue(struct babel_iface *ifa)
|
||
1095 | { |
||
1096 | /*
|
||
1097 | * Only schedule send event if there is not already data in the socket buffer.
|
||
1098 | * Otherwise we may overwrite the data already in the buffer.
|
||
1099 | */
|
||
1100 | |||
1101 | if ((ifa->sk->tpos == ifa->sk->tbuf) && !ev_active(ifa->send_event))
|
||
1102 | ev_schedule(ifa->send_event); |
||
1103 | } |
||
1104 | |||
1105 | /**
|
||
1106 | * babel_send_unicast - send a single TLV via unicast to a destination
|
||
1107 | * @msg: TLV to send
|
||
1108 | * @ifa: Interface to send via
|
||
1109 | * @dest: Destination of the TLV
|
||
1110 | *
|
||
1111 | * This function is used to send a single TLV via unicast to a designated
|
||
1112 | * receiver. This is used for replying to certain incoming requests, and for
|
||
1113 | * sending unicast requests to refresh routes before they expire.
|
||
1114 | */
|
||
1115 | void
|
||
1116 | babel_send_unicast(union babel_msg *msg, struct babel_iface *ifa, ip_addr dest) |
||
1117 | { |
||
1118 | struct babel_proto *p = ifa->proto;
|
||
1119 | struct babel_msg_node *msgn = sl_alloc(p->msg_slab);
|
||
1120 | list queue; |
||
1121 | |||
1122 | msgn->msg = *msg; |
||
1123 | init_list(&queue); |
||
1124 | add_tail(&queue, NODE msgn); |
||
1125 | babel_write_queue(ifa, &queue); |
||
1126 | babel_send_to(ifa, dest); |
||
1127 | |||
1128 | /* We could overwrite waiting packet here, we may have to kick TX queue */
|
||
1129 | if (!EMPTY_LIST(ifa->msg_queue))
|
||
1130 | babel_kick_queue(ifa); |
||
1131 | } |
||
1132 | |||
1133 | /**
|
||
1134 | * babel_enqueue - enqueue a TLV for transmission on an interface
|
||
1135 | * @msg: TLV to enqueue (in internal TLV format)
|
||
1136 | * @ifa: Interface to enqueue to
|
||
1137 | *
|
||
1138 | * This function is called to enqueue a TLV for subsequent transmission on an
|
||
1139 | * interface. The transmission event is triggered whenever a TLV is enqueued;
|
||
1140 | * this ensures that TLVs will be transmitted in a timely manner, but that TLVs
|
||
1141 | * which are enqueued in rapid succession can be transmitted together in one
|
||
1142 | * packet.
|
||
1143 | */
|
||
1144 | void
|
||
1145 | babel_enqueue(union babel_msg *msg, struct babel_iface *ifa) |
||
1146 | { |
||
1147 | struct babel_proto *p = ifa->proto;
|
||
1148 | struct babel_msg_node *msgn = sl_alloc(p->msg_slab);
|
||
1149 | msgn->msg = *msg; |
||
1150 | add_tail(&ifa->msg_queue, NODE msgn); |
||
1151 | babel_kick_queue(ifa); |
||
1152 | } |
||
1153 | |||
1154 | /**
|
||
1155 | * babel_process_packet - process incoming data packet
|
||
1156 | * @pkt: Pointer to the packet data
|
||
1157 | * @len: Length of received packet
|
||
1158 | * @saddr: Address of packet sender
|
||
1159 | * @ifa: Interface packet was received on.
|
||
1160 | *
|
||
1161 | * This function is the main processing hook of incoming Babel packets. It
|
||
1162 | * checks that the packet header is well-formed, then processes the TLVs
|
||
1163 | * contained in the packet. This is done in two passes: First all TLVs are
|
||
1164 | * parsed into the internal TLV format. If a TLV parser fails, processing of the
|
||
1165 | * rest of the packet is aborted.
|
||
1166 | *
|
||
1167 | * After the parsing step, the TLV handlers are called for each parsed TLV in
|
||
1168 | * order.
|
||
1169 | */
|
||
1170 | static void |
||
1171 | babel_process_packet(struct babel_pkt_header *pkt, int len, |
||
1172 | ip_addr saddr, struct babel_iface *ifa)
|
||
1173 | { |
||
1174 | struct babel_proto *p = ifa->proto;
|
||
1175 | struct babel_tlv *tlv;
|
||
1176 | struct babel_msg_node *msg;
|
||
1177 | list msgs; |
||
1178 | int res;
|
||
1179 | |||
1180 | int plen = sizeof(struct babel_pkt_header) + get_u16(&pkt->length); |
||
1181 | byte *pos; |
||
1182 | byte *end = (byte *)pkt + plen; |
||
1183 | |||
1184 | struct babel_parse_state state = {
|
||
1185 | 4324025f | Ondrej Zajicek (work) | .proto = p, |
1186 | .ifa = ifa, |
||
1187 | .saddr = saddr, |
||
1188 | .next_hop_ip6 = saddr, |
||
1189 | 937e75d8 | Ondrej Zajicek (work) | }; |
1190 | |||
1191 | if ((pkt->magic != BABEL_MAGIC) || (pkt->version != BABEL_VERSION))
|
||
1192 | { |
||
1193 | TRACE(D_PACKETS, "Strange packet from %I via %s - magic %d version %d",
|
||
1194 | saddr, ifa->iface->name, pkt->magic, pkt->version); |
||
1195 | return;
|
||
1196 | } |
||
1197 | |||
1198 | if (plen > len)
|
||
1199 | { |
||
1200 | LOG_PKT("Bad packet from %I via %s - %s (%u)",
|
||
1201 | saddr, ifa->iface->name, "length mismatch", plen);
|
||
1202 | return;
|
||
1203 | } |
||
1204 | |||
1205 | TRACE(D_PACKETS, "Packet received from %I via %s",
|
||
1206 | saddr, ifa->iface->name); |
||
1207 | |||
1208 | init_list(&msgs); |
||
1209 | |||
1210 | /* First pass through the packet TLV by TLV, parsing each into internal data
|
||
1211 | structures. */
|
||
1212 | for (tlv = FIRST_TLV(pkt);
|
||
1213 | (byte *)tlv < end; |
||
1214 | tlv = NEXT_TLV(tlv)) |
||
1215 | { |
||
1216 | /* Ugly special case */
|
||
1217 | if (tlv->type == BABEL_TLV_PAD1)
|
||
1218 | continue;
|
||
1219 | |||
1220 | /* The end of the common TLV header */
|
||
1221 | pos = (byte *)tlv + sizeof(struct babel_tlv); |
||
1222 | if ((pos > end) || (pos + tlv->length > end))
|
||
1223 | { |
||
1224 | LOG_PKT("Bad TLV from %I via %s type %d pos %d - framing error",
|
||
1225 | saddr, ifa->iface->name, tlv->type, (byte *)tlv - (byte *)pkt); |
||
1226 | break;
|
||
1227 | } |
||
1228 | |||
1229 | msg = sl_alloc(p->msg_slab); |
||
1230 | res = babel_read_tlv(tlv, &msg->msg, &state); |
||
1231 | if (res == PARSE_SUCCESS)
|
||
1232 | { |
||
1233 | add_tail(&msgs, NODE msg); |
||
1234 | } |
||
1235 | else if (res == PARSE_IGNORE) |
||
1236 | { |
||
1237 | DBG("Babel: Ignoring TLV of type %d\n", tlv->type);
|
||
1238 | sl_free(p->msg_slab, msg); |
||
1239 | } |
||
1240 | else /* PARSE_ERROR */ |
||
1241 | { |
||
1242 | LOG_PKT("Bad TLV from %I via %s type %d pos %d - parse error",
|
||
1243 | saddr, ifa->iface->name, tlv->type, (byte *)tlv - (byte *)pkt); |
||
1244 | sl_free(p->msg_slab, msg); |
||
1245 | break;
|
||
1246 | } |
||
1247 | } |
||
1248 | |||
1249 | /* Parsing done, handle all parsed TLVs */
|
||
1250 | WALK_LIST_FIRST(msg, msgs) |
||
1251 | { |
||
1252 | if (tlv_data[msg->msg.type].handle_tlv)
|
||
1253 | tlv_data[msg->msg.type].handle_tlv(&msg->msg, ifa); |
||
1254 | rem_node(NODE msg); |
||
1255 | sl_free(p->msg_slab, msg); |
||
1256 | } |
||
1257 | } |
||
1258 | |||
1259 | static void |
||
1260 | babel_err_hook(sock *sk, int err)
|
||
1261 | { |
||
1262 | struct babel_iface *ifa = sk->data;
|
||
1263 | struct babel_proto *p = ifa->proto;
|
||
1264 | |||
1265 | log(L_ERR "%s: Socket error on %s: %M", p->p.name, ifa->iface->name, err);
|
||
1266 | /* FIXME: Drop queued TLVs here? */
|
||
1267 | } |
||
1268 | |||
1269 | |||
1270 | static void |
||
1271 | babel_tx_hook(sock *sk) |
||
1272 | { |
||
1273 | struct babel_iface *ifa = sk->data;
|
||
1274 | |||
1275 | DBG("Babel: TX hook called (iface %s, src %I, dst %I)\n",
|
||
1276 | sk->iface->name, sk->saddr, sk->daddr); |
||
1277 | |||
1278 | babel_send_queue(ifa); |
||
1279 | } |
||
1280 | |||
1281 | |||
1282 | static int |
||
1283 | 3e236955 | Jan Moskyto Matejka | babel_rx_hook(sock *sk, uint len) |
1284 | 937e75d8 | Ondrej Zajicek (work) | { |
1285 | struct babel_iface *ifa = sk->data;
|
||
1286 | struct babel_proto *p = ifa->proto;
|
||
1287 | const char *err_dsc = NULL; |
||
1288 | uint err_val = 0;
|
||
1289 | |||
1290 | if (sk->lifindex != ifa->iface->index)
|
||
1291 | return 1; |
||
1292 | |||
1293 | DBG("Babel: RX hook called (iface %s, src %I, dst %I)\n",
|
||
1294 | sk->iface->name, sk->faddr, sk->laddr); |
||
1295 | |||
1296 | /* Silently ignore my own packets */
|
||
1297 | 153f02da | Ondrej Zajicek (work) | if (ipa_equal(sk->faddr, sk->saddr))
|
1298 | 937e75d8 | Ondrej Zajicek (work) | return 1; |
1299 | |||
1300 | if (!ipa_is_link_local(sk->faddr))
|
||
1301 | DROP1("wrong src address");
|
||
1302 | |||
1303 | if (sk->fport != ifa->cf->port)
|
||
1304 | DROP("wrong src port", sk->fport);
|
||
1305 | |||
1306 | if (len < sizeof(struct babel_pkt_header)) |
||
1307 | DROP("too short", len);
|
||
1308 | |||
1309 | if (sk->flags & SKF_TRUNCATED)
|
||
1310 | DROP("truncated", len);
|
||
1311 | |||
1312 | babel_process_packet((struct babel_pkt_header *) sk->rbuf, len, sk->faddr, ifa);
|
||
1313 | return 1; |
||
1314 | |||
1315 | drop:
|
||
1316 | LOG_PKT("Bad packet from %I via %s - %s (%u)",
|
||
1317 | sk->faddr, sk->iface->name, err_dsc, err_val); |
||
1318 | return 1; |
||
1319 | } |
||
1320 | |||
1321 | int
|
||
1322 | babel_open_socket(struct babel_iface *ifa)
|
||
1323 | { |
||
1324 | struct babel_proto *p = ifa->proto;
|
||
1325 | |||
1326 | sock *sk; |
||
1327 | sk = sk_new(ifa->pool); |
||
1328 | sk->type = SK_UDP; |
||
1329 | sk->sport = ifa->cf->port; |
||
1330 | sk->dport = ifa->cf->port; |
||
1331 | sk->iface = ifa->iface; |
||
1332 | 153f02da | Ondrej Zajicek (work) | sk->saddr = ifa->addr; |
1333 | 937e75d8 | Ondrej Zajicek (work) | |
1334 | sk->rx_hook = babel_rx_hook; |
||
1335 | sk->tx_hook = babel_tx_hook; |
||
1336 | sk->err_hook = babel_err_hook; |
||
1337 | sk->data = ifa; |
||
1338 | |||
1339 | sk->tos = ifa->cf->tx_tos; |
||
1340 | sk->priority = ifa->cf->tx_priority; |
||
1341 | sk->ttl = 1;
|
||
1342 | sk->flags = SKF_LADDR_RX; |
||
1343 | |||
1344 | if (sk_open(sk) < 0) |
||
1345 | goto err;
|
||
1346 | |||
1347 | if (sk_setup_multicast(sk) < 0) |
||
1348 | goto err;
|
||
1349 | |||
1350 | if (sk_join_group(sk, IP6_BABEL_ROUTERS) < 0) |
||
1351 | goto err;
|
||
1352 | |||
1353 | ifa->sk = sk; |
||
1354 | return 1; |
||
1355 | |||
1356 | err:
|
||
1357 | sk_log_error(sk, p->p.name); |
||
1358 | rfree(sk); |
||
1359 | return 0; |
||
1360 | } |