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