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