]> git.ipfire.org Git - thirdparty/bird.git/blob - proto/ospf/packet.c
Temporary integrated OSPF commit.
[thirdparty/bird.git] / proto / ospf / packet.c
1 /*
2 * BIRD -- OSPF
3 *
4 * (c) 1999--2005 Ondrej Filip <feela@network.cz>
5 * (c) 2009--2014 Ondrej Zajicek <santiago@crfreenet.org>
6 * (c) 2009--2014 CZ.NIC z.s.p.o.
7 *
8 * Can be freely distributed and used under the terms of the GNU GPL.
9 */
10
11 #include "ospf.h"
12 #include "nest/password.h"
13 #include "lib/md5.h"
14
15 void
16 ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
17 {
18 struct ospf_proto *p = ifa->oa->po;
19 struct ospf_packet *pkt;
20
21 pkt = (struct ospf_packet *) buf;
22
23 pkt->version = ospf_get_version(p);
24 pkt->type = h_type;
25 pkt->length = htons(ospf_pkt_maxsize(ifa));
26 pkt->routerid = htonl(p->router_id);
27 pkt->areaid = htonl(ifa->oa->areaid);
28 pkt->checksum = 0;
29 pkt->instance_id = ifa->instance_id;
30 pkt->autype = ifa->autype;
31 }
32
33 uint
34 ospf_pkt_maxsize(struct ospf_iface *ifa)
35 {
36 uint headers = SIZE_OF_IP_HEADER;
37
38 /* Relevant just for OSPFv2 */
39 if (ifa->autype == OSPF_AUTH_CRYPT)
40 headers += OSPF_AUTH_CRYPT_SIZE;
41
42 return ifa->tx_length - headers;
43 }
44
45 /* We assume OSPFv2 in ospf_pkt_finalize() */
46 static void
47 ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
48 {
49 struct password_item *passwd = NULL;
50 union ospf_auth *auth = (void *) (pkt + 1);
51 uint plen = ntohs(pkt->length);
52
53 pkt->checksum = 0;
54 pkt->autype = ifa->autype;
55 bzero(auth, sizeof(union ospf_auth));
56
57 /* Compatibility note: auth may contain anything if autype is
58 none, but nonzero values do not work with Mikrotik OSPF */
59
60 switch (ifa->autype)
61 {
62 case OSPF_AUTH_SIMPLE:
63 passwd = password_find(ifa->passwords, 1);
64 if (!passwd)
65 {
66 log(L_ERR "No suitable password found for authentication");
67 return;
68 }
69 password_cpy(auth->password, passwd->password, sizeof(union ospf_auth));
70
71 case OSPF_AUTH_NONE:
72 {
73 void *body = (void *) (auth + 1);
74 uint blen = plen - sizeof(struct ospf_packet) - sizeof(union ospf_auth);
75 pkt->checksum = ipsum_calculate(pkt, sizeof(struct ospf_packet), body, blen, NULL);
76 }
77 break;
78
79 case OSPF_AUTH_CRYPT:
80 passwd = password_find(ifa->passwords, 0);
81 if (!passwd)
82 {
83 log(L_ERR "No suitable password found for authentication");
84 return;
85 }
86
87 /* Perhaps use random value to prevent replay attacks after
88 reboot when system does not have independent RTC? */
89 if (!ifa->csn)
90 {
91 ifa->csn = (u32) now;
92 ifa->csn_use = now;
93 }
94
95 /* We must have sufficient delay between sending a packet and increasing
96 CSN to prevent reordering of packets (in a network) with different CSNs */
97 if ((now - ifa->csn_use) > 1)
98 ifa->csn++;
99
100 ifa->csn_use = now;
101
102 auth->md5.zero = 0;
103 auth->md5.keyid = passwd->id;
104 auth->md5.len = OSPF_AUTH_CRYPT_SIZE;
105 auth->md5.csn = htonl(ifa->csn);
106
107 void *tail = ((void *) pkt) + plen;
108 char password[OSPF_AUTH_CRYPT_SIZE];
109 password_cpy(password, passwd->password, OSPF_AUTH_CRYPT_SIZE);
110
111 struct MD5Context ctxt;
112 MD5Init(&ctxt);
113 MD5Update(&ctxt, (char *) pkt, plen);
114 MD5Update(&ctxt, password, OSPF_AUTH_CRYPT_SIZE);
115 MD5Final(tail, &ctxt);
116 break;
117
118 default:
119 bug("Unknown authentication type");
120 }
121 }
122
123 /* We assume OSPFv2 in ospf_pkt_checkauth() */
124 static int
125 ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, int size)
126 {
127 struct ospf_proto *p = ifa->oa->po;
128 union ospf_auth *auth = (void *) (pkt + 1);
129 struct password_item *pass = NULL, *ptmp;
130 char password[OSPF_AUTH_CRYPT_SIZE];
131
132 uint plen = ntohs(pkt->length);
133 u8 autype = pkt->autype;
134
135 if (autype != ifa->autype)
136 {
137 OSPF_TRACE(D_PACKETS, "OSPF_auth: Method differs (%d)", autype);
138 return 0;
139 }
140
141 switch (autype)
142 {
143 case OSPF_AUTH_NONE:
144 return 1;
145
146 case OSPF_AUTH_SIMPLE:
147 pass = password_find(ifa->passwords, 1);
148 if (!pass)
149 {
150 OSPF_TRACE(D_PACKETS, "OSPF_auth: no password found");
151 return 0;
152 }
153
154 password_cpy(password, pass->password, sizeof(union ospf_auth));
155 if (memcmp(auth->password, password, sizeof(union ospf_auth)))
156 {
157 OSPF_TRACE(D_PACKETS, "OSPF_auth: different passwords");
158 return 0;
159 }
160 return 1;
161
162 case OSPF_AUTH_CRYPT:
163 if (auth->md5.len != OSPF_AUTH_CRYPT_SIZE)
164 {
165 OSPF_TRACE(D_PACKETS, "OSPF_auth: wrong size of md5 digest");
166 return 0;
167 }
168
169 if (plen + OSPF_AUTH_CRYPT_SIZE > size)
170 {
171 OSPF_TRACE(D_PACKETS, "OSPF_auth: size mismatch (%d vs %d)",
172 plen + OSPF_AUTH_CRYPT_SIZE, size);
173 return 0;
174 }
175
176 if (n)
177 {
178 u32 rcv_csn = ntohl(auth->md5.csn);
179 if(rcv_csn < n->csn)
180 {
181 OSPF_TRACE(D_PACKETS, "OSPF_auth: lower sequence number (rcv %d, old %d)", rcv_csn, n->csn);
182 return 0;
183 }
184
185 n->csn = rcv_csn;
186 }
187
188 if (ifa->passwords)
189 {
190 WALK_LIST(ptmp, *(ifa->passwords))
191 {
192 if (auth->md5.keyid != ptmp->id) continue;
193 if ((ptmp->accfrom > now_real) || (ptmp->accto < now_real)) continue;
194 pass = ptmp;
195 break;
196 }
197 }
198
199 if (!pass)
200 {
201 OSPF_TRACE(D_PACKETS, "OSPF_auth: no suitable md5 password found");
202 return 0;
203 }
204
205 void *tail = ((void *) pkt) + plen;
206 char md5sum[OSPF_AUTH_CRYPT_SIZE];
207 password_cpy(password, pass->password, OSPF_AUTH_CRYPT_SIZE);
208
209 struct MD5Context ctxt;
210 MD5Init(&ctxt);
211 MD5Update(&ctxt, (char *) pkt, plen);
212 MD5Update(&ctxt, password, OSPF_AUTH_CRYPT_SIZE);
213 MD5Final(md5sum, &ctxt);
214
215 if (memcmp(md5sum, tail, OSPF_AUTH_CRYPT_SIZE))
216 {
217 OSPF_TRACE(D_PACKETS, "OSPF_auth: wrong md5 digest");
218 return 0;
219 }
220 return 1;
221
222 default:
223 OSPF_TRACE(D_PACKETS, "OSPF_auth: unknown auth type");
224 return 0;
225 }
226 }
227
228
229 /**
230 * ospf_rx_hook
231 * @sk: socket we received the packet.
232 * @size: size of the packet
233 *
234 * This is the entry point for messages from neighbors. Many checks (like
235 * authentication, checksums, size) are done before the packet is passed to
236 * non generic functions.
237 */
238 int
239 ospf_rx_hook(sock *sk, int size)
240 {
241 char *mesg = "OSPF: Bad packet from ";
242
243 /* We want just packets from sk->iface. Unfortunately, on BSD we
244 cannot filter out other packets at kernel level and we receive
245 all packets on all sockets */
246 if (sk->lifindex != sk->iface->index)
247 return 1;
248
249 DBG("OSPF: RX hook called (iface %s, src %I, dst %I)\n",
250 sk->ifname, sk->faddr, sk->laddr);
251
252 /* Initially, the packet is associated with the 'master' iface */
253 struct ospf_iface *ifa = sk->data;
254 struct ospf_proto *p = ifa->oa->po;
255
256 int src_local, dst_local, dst_mcast;
257 src_local = ipa_in_net(sk->faddr, ifa->addr->prefix, ifa->addr->pxlen);
258 dst_local = ipa_equal(sk->laddr, ifa->addr->ip);
259 dst_mcast = ipa_equal(sk->laddr, ifa->all_routers) || ipa_equal(sk->laddr, ifa->des_routers);
260
261 if (ospf_is_v2(p))
262 {
263 /* First, we eliminate packets with strange address combinations.
264 * In OSPFv2, they might be for other ospf_ifaces (with different IP
265 * prefix) on the same real iface, so we don't log it. We enforce
266 * that (src_local || dst_local), therefore we are eliminating all
267 * such cases.
268 */
269 if (dst_mcast && !src_local)
270 return 1;
271 if (!dst_mcast && !dst_local)
272 return 1;
273
274 /* Ignore my own broadcast packets */
275 if (ifa->cf->real_bcast && ipa_equal(sk->faddr, ifa->addr->ip))
276 return 1;
277 }
278 else
279 {
280 /* In OSPFv3, src_local and dst_local mean link-local.
281 * RFC 5340 says that local (non-vlink) packets use
282 * link-local src address, but does not enforce it. Strange.
283 */
284 if (dst_mcast && !src_local)
285 log(L_WARN "OSPF: Received multicast packet from %I (not link-local)", sk->faddr);
286 }
287
288 /* Second, we check packet size, checksum, and the protocol version */
289 struct ospf_packet *pkt = (struct ospf_packet *) ip_skip_header(sk->rbuf, &size);
290
291 if (pkt == NULL)
292 {
293 log(L_ERR "%s%I - bad IP header", mesg, sk->faddr);
294 return 1;
295 }
296
297 if (ifa->check_ttl && (sk->rcv_ttl < 255))
298 {
299 log(L_ERR "%s%I - TTL %d (< 255)", mesg, sk->faddr, sk->rcv_ttl);
300 return 1;
301 }
302
303 if ((uint) size < sizeof(struct ospf_packet))
304 {
305 log(L_ERR "%s%I - too short (%u bytes)", mesg, sk->faddr, size);
306 return 1;
307 }
308
309 uint plen = ntohs(pkt->length);
310 if ((plen < sizeof(struct ospf_packet)) || ((plen % 4) != 0))
311 {
312 log(L_ERR "%s%I - invalid length (%u)", mesg, sk->faddr, plen);
313 return 1;
314 }
315
316 if (sk->flags & SKF_TRUNCATED)
317 {
318 log(L_WARN "%s%I - too large (%d/%d)", mesg, sk->faddr, plen, size);
319
320 /* If we have dynamic buffers and received truncated message, we expand RX buffer */
321
322 uint bs = plen + 256;
323 bs = BIRD_ALIGN(bs, 1024);
324
325 if (!ifa->cf->rx_buffer && (bs > sk->rbsize))
326 sk_set_rbsize(sk, bs);
327
328 return 1;
329 }
330
331 if (plen > size)
332 {
333 log(L_ERR "%s%I - size field does not match (%d/%d)", mesg, sk->faddr, plen, size);
334 return 1;
335 }
336
337 if (pkt->version != ospf_get_version(p))
338 {
339 log(L_ERR "%s%I - version %u", mesg, sk->faddr, pkt->version);
340 return 1;
341 }
342
343 if (ospf_is_v2(p) && (pkt->autype != OSPF_AUTH_CRYPT))
344 {
345 uint hlen = sizeof(struct ospf_packet) + sizeof(union ospf_auth);
346 uint blen = plen - hlen;
347 void *body = ((void *) pkt) + hlen;
348
349 if (! ipsum_verify(pkt, sizeof(struct ospf_packet), body, blen, NULL))
350 {
351 log(L_ERR "%s%I - bad checksum", mesg, sk->faddr);
352 return 1;
353 }
354 }
355
356 /* Third, we resolve associated iface and handle vlinks. */
357
358 u32 areaid = ntohl(pkt->areaid);
359 u32 rid = ntohl(pkt->routerid);
360 u8 instance_id = pkt->instance_id;
361
362 if (areaid == ifa->oa->areaid)
363 {
364 /* Matching area ID */
365
366 if (instance_id != ifa->instance_id)
367 return 1;
368
369 /* It is real iface, source should be local (in OSPFv2) */
370 if (ospf_is_v2(p) && !src_local)
371 {
372 log(L_ERR "%s%I - strange source address for %s", mesg, sk->faddr, ifa->ifname);
373 return 1;
374 }
375
376 goto found;
377 }
378 else if ((areaid == 0) && !dst_mcast)
379 {
380 /* Backbone area ID and possible vlink packet */
381
382 if ((p->areano == 1) || !oa_is_ext(ifa->oa))
383 return 1;
384
385 struct ospf_iface *iff = NULL;
386 WALK_LIST(iff, p->iface_list)
387 {
388 if ((iff->type == OSPF_IT_VLINK) &&
389 (iff->voa == ifa->oa) &&
390 (iff->instance_id == instance_id) &&
391 (iff->vid == rid))
392 {
393 /* Vlink should be UP */
394 if (iff->state != OSPF_IS_PTP)
395 return 1;
396
397 ifa = iff;
398 goto found;
399 }
400 }
401
402 /*
403 * Cannot find matching vlink. It is either misconfigured vlink; NBMA or
404 * PtMP with misconfigured area ID, or packet for some other instance (that
405 * is possible even if instance_id == ifa->instance_id, because it may be
406 * also vlink packet in the other instance, which is different namespace).
407 */
408
409 return 1;
410 }
411 else
412 {
413 /* Non-matching area ID but cannot be vlink packet */
414
415 if (instance_id != ifa->instance_id)
416 return 1;
417
418 log(L_ERR "%s%I - area does not match (%R vs %R)",
419 mesg, sk->faddr, areaid, ifa->oa->areaid);
420 return 1;
421 }
422
423
424 found:
425 if (ifa->stub) /* This shouldn't happen */
426 return 1;
427
428 if (ipa_equal(sk->laddr, ifa->des_routers) && (ifa->sk_dr == 0))
429 return 1;
430
431 if (rid == p->router_id)
432 {
433 log(L_ERR "%s%I - received my own router ID!", mesg, sk->faddr);
434 return 1;
435 }
436
437 if (rid == 0)
438 {
439 log(L_ERR "%s%I - router id = 0.0.0.0", mesg, sk->faddr);
440 return 1;
441 }
442
443 /* In OSPFv2, neighbors are identified by either IP or Router ID, base on network type */
444 uint t = ifa->type;
445 struct ospf_neighbor *n;
446 if (ospf_is_v2(p) && ((t == OSPF_IT_BCAST) || (t == OSPF_IT_NBMA) || (t == OSPF_IT_PTMP)))
447 n = find_neigh_by_ip(ifa, sk->faddr);
448 else
449 n = find_neigh(ifa, rid);
450
451 if (!n && (pkt->type != HELLO_P))
452 {
453 log(L_WARN "OSPF: Received non-hello packet from unknown neighbor (src %I, iface %s)",
454 sk->faddr, ifa->ifname);
455 return 1;
456 }
457
458 if (ospf_is_v2(p) && !ospf_pkt_checkauth(n, ifa, pkt, size))
459 {
460 log(L_ERR "%s%I - authentication failed", mesg, sk->faddr);
461 return 1;
462 }
463
464 switch (pkt->type)
465 {
466 case HELLO_P:
467 ospf_receive_hello(pkt, ifa, n, sk->faddr);
468 break;
469
470 case DBDES_P:
471 ospf_receive_dbdes(pkt, ifa, n);
472 break;
473
474 case LSREQ_P:
475 ospf_receive_lsreq(pkt, ifa, n);
476 break;
477
478 case LSUPD_P:
479 ospf_receive_lsupd(pkt, ifa, n);
480 break;
481
482 case LSACK_P:
483 ospf_receive_lsack(pkt, ifa, n);
484 break;
485
486 default:
487 log(L_ERR "%s%I - wrong type %u", mesg, sk->faddr, pkt->type);
488 return 1;
489 };
490 return 1;
491 }
492
493 /*
494 void
495 ospf_tx_hook(sock * sk)
496 {
497 struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
498 // struct proto *p = (struct proto *) (ifa->oa->p);
499 log(L_ERR "OSPF: TX hook called on %s", ifa->ifname);
500 }
501 */
502
503 void
504 ospf_err_hook(sock * sk, int err)
505 {
506 struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
507 struct ospf_proto *p = ifa->oa->po;
508 log(L_ERR "%s: Socket error on %s: %M", p->p.name, ifa->ifname, err);
509 }
510
511 void
512 ospf_verr_hook(sock *sk, int err)
513 {
514 struct ospf_proto *p = (struct ospf_proto *) (sk->data);
515 log(L_ERR "%s: Vlink socket error: %M", p->p.name, err);
516 }
517
518 void
519 ospf_send_to(struct ospf_iface *ifa, ip_addr dst)
520 {
521 sock *sk = ifa->sk;
522 struct ospf_packet *pkt = (struct ospf_packet *) sk->tbuf;
523 int plen = ntohs(pkt->length);
524
525 if (ospf_is_v2(ifa->oa->po))
526 {
527 if (ifa->autype == OSPF_AUTH_CRYPT)
528 plen += OSPF_AUTH_CRYPT_SIZE;
529
530 ospf_pkt_finalize(ifa, pkt);
531 }
532
533 int done = sk_send_to(sk, plen, dst, 0);
534 if (!done)
535 log(L_WARN "OSPF: TX queue full on %s", ifa->ifname);
536 }
537
538 void
539 ospf_send_to_agt(struct ospf_iface *ifa, u8 state)
540 {
541 struct ospf_neighbor *n;
542
543 WALK_LIST(n, ifa->neigh_list)
544 if (n->state >= state)
545 ospf_send_to(ifa, n->ip);
546 }
547
548 void
549 ospf_send_to_bdr(struct ospf_iface *ifa)
550 {
551 if (ipa_nonzero(ifa->drip))
552 ospf_send_to(ifa, ifa->drip);
553 if (ipa_nonzero(ifa->bdrip))
554 ospf_send_to(ifa, ifa->bdrip);
555 }