]>
git.ipfire.org Git - thirdparty/bird.git/blob - proto/ospf/packet.c
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.
8 * Can be freely distributed and used under the terms of the GNU GPL.
12 #include "nest/password.h"
15 #include "lib/socket.h"
18 ospf_pkt_fill_hdr(struct ospf_iface
*ifa
, void *buf
, u8 h_type
)
20 struct ospf_proto
*p
= ifa
->oa
->po
;
21 struct ospf_packet
*pkt
;
23 pkt
= (struct ospf_packet
*) buf
;
25 pkt
->version
= ospf_get_version(p
);
27 pkt
->length
= htons(ospf_pkt_maxsize(ifa
));
28 pkt
->routerid
= htonl(p
->router_id
);
29 pkt
->areaid
= htonl(ifa
->oa
->areaid
);
31 pkt
->instance_id
= ifa
->instance_id
;
32 pkt
->autype
= ospf_is_v2(p
) ? ifa
->autype
: 0;
35 /* We assume OSPFv2 in ospf_pkt_finalize() */
37 ospf_pkt_finalize2(struct ospf_iface
*ifa
, struct ospf_packet
*pkt
, uint
*plen
)
39 struct ospf_proto
*p
= ifa
->oa
->po
;
40 struct password_item
*pass
= NULL
;
41 union ospf_auth2
*auth
= (void *) (pkt
+ 1);
42 memset(auth
, 0, sizeof(union ospf_auth2
));
44 /* Compatibility note: auth may contain anything if autype is
45 none, but nonzero values do not work with Mikrotik OSPF */
48 pkt
->autype
= ifa
->autype
;
52 case OSPF_AUTH_SIMPLE
:
53 pass
= password_find(ifa
->passwords
, 1);
56 log(L_ERR
"No suitable password found for authentication");
59 strncpy(auth
->password
, pass
->password
, sizeof(auth
->password
));
64 void *body
= (void *) (auth
+ 1);
65 uint blen
= *plen
- sizeof(struct ospf_packet
) - sizeof(union ospf_auth2
);
66 pkt
->checksum
= ipsum_calculate(pkt
, sizeof(struct ospf_packet
), body
, blen
, NULL
);
71 pass
= password_find(ifa
->passwords
, 0);
74 log(L_ERR
"%s: No suitable password found for authentication", p
->p
.name
);
78 /* Perhaps use random value to prevent replay attacks after
79 reboot when system does not have independent RTC? */
82 ifa
->csn
= (u32
) (current_real_time() TO_S
);
83 ifa
->csn_use
= current_time();
86 /* We must have sufficient delay between sending a packet and increasing
87 CSN to prevent reordering of packets (in a network) with different CSNs */
88 if ((current_time() - ifa
->csn_use
) > 1 S
)
91 ifa
->csn_use
= current_time();
93 uint auth_len
= mac_type_length(pass
->alg
);
94 byte
*auth_tail
= ((byte
*) pkt
+ *plen
);
97 ASSERT(*plen
< ifa
->sk
->tbsize
);
100 auth
->c32
.keyid
= pass
->id
;
101 auth
->c32
.len
= auth_len
;
102 auth
->c32
.csn
= htonl(ifa
->csn
);
104 /* Append key for keyed hash, append padding for HMAC (RFC 5709 3.3) */
105 if (pass
->alg
< ALG_HMAC
)
106 strncpy(auth_tail
, pass
->password
, auth_len
);
108 memset32(auth_tail
, HMAC_MAGIC
, auth_len
/ 4);
110 mac_fill(pass
->alg
, pass
->password
, pass
->length
, (byte
*) pkt
, *plen
, auth_tail
);
114 bug("Unknown authentication type");
119 * Return an extra packet size that should be added to a final packet size
122 ospf_pkt_finalize3(struct ospf_iface
*ifa
, struct ospf_packet
*pkt
, uint
*plen
, ip_addr src
)
124 struct ospf_proto
*p
= ifa
->oa
->po
;
125 struct ospf_auth3
*auth
= (void *) ((byte
*) pkt
+ *plen
);
130 if (ifa
->autype
!= OSPF_AUTH_CRYPT
)
133 struct password_item
*pass
= password_find(ifa
->passwords
, 0);
136 log(L_ERR
"%s: No suitable password found for authentication", p
->p
.name
);
140 /* FIXME: Ensure persistence */
143 uint mac_len
= mac_type_length(pass
->alg
);
144 uint auth_len
= sizeof(struct ospf_auth3
) + mac_len
;
147 ASSERT(*plen
< ifa
->sk
->tbsize
);
149 memset(auth
, 0, sizeof(struct ospf_auth3
));
150 auth
->type
= htons(OSPF3_AUTH_HMAC
);
151 auth
->length
= htons(auth_len
);
153 auth
->sa_id
= htons(pass
->id
);
154 put_u64(&auth
->csn
, p
->csn64
);
156 /* Initialize with src IP address padded with HMAC_MAGIC */
157 put_ip6(auth
->data
, ipa_to_ip6(src
));
158 memset32(auth
->data
+ 16, HMAC_MAGIC
, (mac_len
- 16) / 4);
160 /* Attach OSPFv3 Cryptographic Protocol ID to the key */
161 uint pass_len
= pass
->length
+ 2;
162 byte
*pass_key
= alloca(pass_len
);
163 memcpy(pass_key
, pass
->password
, pass
->length
);
164 put_u16(pass_key
+ pass
->length
, OSPF3_CRYPTO_ID
);
166 mac_fill(pass
->alg
, pass_key
, pass_len
, (byte
*) pkt
, *plen
, auth
->data
);
171 ospf_pkt_checkauth2(struct ospf_neighbor
*n
, struct ospf_iface
*ifa
, struct ospf_packet
*pkt
, uint len
)
173 struct ospf_proto
*p
= ifa
->oa
->po
;
174 union ospf_auth2
*auth
= (void *) (pkt
+ 1);
175 struct password_item
*pass
= NULL
;
176 const char *err_dsc
= NULL
;
179 uint plen
= ntohs(pkt
->length
);
180 u8 autype
= pkt
->autype
;
182 if (autype
!= ifa
->autype
)
183 DROP("authentication method mismatch", autype
);
190 case OSPF_AUTH_SIMPLE
:
191 pass
= password_find(ifa
->passwords
, 1);
193 DROP1("no password found");
195 if (!password_verify(pass
, auth
->password
, sizeof(auth
->password
)))
196 DROP("wrong password", pass
->id
);
200 case OSPF_AUTH_CRYPT
:
201 pass
= password_find_by_id(ifa
->passwords
, auth
->c32
.keyid
);
203 DROP("no suitable password found", auth
->c32
.keyid
);
205 uint auth_len
= mac_type_length(pass
->alg
);
207 if (plen
+ auth
->c32
.len
> len
)
208 DROP("packet length mismatch", len
);
210 if (auth
->c32
.len
!= auth_len
)
211 DROP("wrong authentication length", auth
->c32
.len
);
213 u32 rcv_csn
= ntohl(auth
->c32
.csn
);
214 if (n
&& (rcv_csn
< n
->csn
))
215 // DROP("lower sequence number", rcv_csn);
217 /* We want to report both new and old CSN */
218 LOG_PKT_AUTH("Authentication failed for nbr %R on %s - "
219 "lower sequence number (rcv %u, old %u)",
220 n
->rid
, ifa
->ifname
, rcv_csn
, n
->csn
);
224 byte
*auth_tail
= ((byte
*) pkt
) + plen
;
225 byte
*auth_data
= alloca(auth_len
);
226 memcpy(auth_data
, auth_tail
, auth_len
);
228 /* Append key for keyed hash, append padding for HMAC (RFC 5709 3.3) */
229 if (pass
->alg
< ALG_HMAC
)
230 strncpy(auth_tail
, pass
->password
, auth_len
);
232 memset32(auth_tail
, HMAC_MAGIC
, auth_len
/ 4);
234 if (!mac_verify(pass
->alg
, pass
->password
, pass
->length
,
235 (byte
*) pkt
, plen
+ auth_len
, auth_data
))
236 DROP("wrong authentication code", pass
->id
);
244 bug("Unknown authentication type");
248 LOG_PKT_AUTH("Authentication failed for nbr %R on %s - %s (%u)",
249 (n
? n
->rid
: ntohl(pkt
->routerid
)), ifa
->ifname
, err_dsc
, err_val
);
255 ospf_pkt_checkauth3(struct ospf_neighbor
*n
, struct ospf_iface
*ifa
, struct ospf_packet
*pkt
, uint len
, ip_addr src
)
257 struct ospf_proto
*p
= ifa
->oa
->po
;
258 const char *err_dsc
= NULL
;
261 uint plen
= ntohs(pkt
->length
);
262 uint opts
, lls_present
, auth_present
;
265 * When autentication is not enabled, ignore the trailer. This is different
266 * from OSPFv2, but it is necessary in order to support migration modes. Note
267 * that regular authenticated packets do not have valid checksum and will be
268 * dropped by OS on non-authenticated ifaces.
270 if (ifa
->autype
!= OSPF_AUTH_CRYPT
)
276 opts
= ospf_hello3_options(pkt
);
277 lls_present
= opts
& OPT_L_V3
;
278 auth_present
= opts
& OPT_AT
;
282 opts
= ospf_dbdes3_options(pkt
);
283 lls_present
= opts
& OPT_L_V3
;
284 auth_present
= opts
& OPT_AT
;
289 auth_present
= n
->options
& OPT_AT
;
293 DROP1("missing authentication trailer");
297 if ((plen
+ sizeof(struct ospf_lls
)) > len
)
298 DROP("packet length mismatch", len
);
300 struct ospf_lls
*lls
= (void *) ((byte
*) pkt
+ plen
);
301 plen
+= ntohs(lls
->length
);
304 if ((plen
+ sizeof(struct ospf_auth3
)) > len
)
305 DROP("packet length mismatch", len
);
307 struct ospf_auth3
*auth
= (void *) ((byte
*) pkt
+ plen
);
309 uint rcv_auth_type
= ntohs(auth
->type
);
310 if (rcv_auth_type
!= OSPF3_AUTH_HMAC
)
311 DROP("authentication method mismatch", rcv_auth_type
);
313 uint rcv_auth_len
= ntohs(auth
->length
);
314 if (plen
+ rcv_auth_len
> len
)
315 DROP("packet length mismatch", len
);
317 uint rcv_key_id
= ntohs(auth
->sa_id
);
318 struct password_item
*pass
= password_find_by_id(ifa
->passwords
, rcv_key_id
);
320 DROP("no suitable password found", rcv_key_id
);
322 uint mac_len
= mac_type_length(pass
->alg
);
323 if (rcv_auth_len
!= (sizeof(struct ospf_auth3
) + mac_len
))
324 DROP("wrong authentication length", rcv_auth_len
);
326 uint pt
= pkt
->type
- 1;
327 u64 rcv_csn
= get_u64(&auth
->csn
);
328 if (n
&& (rcv_csn
<= n
->csn64
[pt
]))
330 /* We want to report both new and old CSN */
331 LOG_PKT_AUTH("Authentication failed for nbr %R on %s - "
332 "lower sequence number (rcv %u, old %u)",
333 n
->rid
, ifa
->ifname
, (uint
) rcv_csn
, (uint
) n
->csn64
[pt
]);
337 /* Save the received authentication data */
338 byte
*auth_data
= alloca(mac_len
);
339 memcpy(auth_data
, auth
->data
, mac_len
);
341 /* Initialize with src IP address padded with HMAC_MAGIC */
342 put_ip6(auth
->data
, ipa_to_ip6(src
));
343 memset32(auth
->data
+ 16, HMAC_MAGIC
, (mac_len
- 16) / 4);
345 /* Attach OSPFv3 Cryptographic Protocol ID to the key */
346 uint pass_len
= pass
->length
+ 2;
347 byte
*pass_key
= alloca(pass_len
);
348 memcpy(pass_key
, pass
->password
, pass
->length
);
349 put_u16(pass_key
+ pass
->length
, OSPF3_CRYPTO_ID
);
351 if (!mac_verify(pass
->alg
, pass_key
, pass_len
,
352 (byte
*) pkt
, plen
+ rcv_auth_len
, auth_data
))
353 DROP("wrong authentication code", pass
->id
);
356 n
->csn64
[pt
] = rcv_csn
;
361 LOG_PKT_AUTH("Authentication failed for nbr %R on %s - %s (%u)",
362 (n
? n
->rid
: ntohl(pkt
->routerid
)), ifa
->ifname
, err_dsc
, err_val
);
369 * @sk: socket we received the packet.
370 * @len: length of the packet
372 * This is the entry point for messages from neighbors. Many checks (like
373 * authentication, checksums, size) are done before the packet is passed to
374 * non generic functions.
377 ospf_rx_hook(sock
*sk
, uint len
)
379 /* We want just packets from sk->iface. Unfortunately, on BSD we cannot filter
380 out other packets at kernel level and we receive all packets on all sockets */
381 if (sk
->lifindex
!= sk
->iface
->index
)
384 DBG("OSPF: RX hook called (iface %s, src %I, dst %I)\n",
385 sk
->iface
->name
, sk
->faddr
, sk
->laddr
);
387 /* Initially, the packet is associated with the 'master' iface */
388 struct ospf_iface
*ifa
= sk
->data
;
389 struct ospf_proto
*p
= ifa
->oa
->po
;
390 const char *err_dsc
= NULL
;
393 /* Should not happen */
394 if (ifa
->state
<= OSPF_IS_LOOP
)
397 int src_local
, dst_local
, dst_mcast
;
398 src_local
= ipa_in_netX(sk
->faddr
, &ifa
->addr
->prefix
);
399 dst_local
= ipa_equal(sk
->laddr
, ifa
->addr
->ip
);
400 dst_mcast
= ipa_equal(sk
->laddr
, ifa
->all_routers
) || ipa_equal(sk
->laddr
, ifa
->des_routers
);
404 /* First, we eliminate packets with strange address combinations.
405 * In OSPFv2, they might be for other ospf_ifaces (with different IP
406 * prefix) on the same real iface, so we don't log it. We enforce
407 * that (src_local || dst_local), therefore we are eliminating all
410 if (dst_mcast
&& !src_local
)
412 if (!dst_mcast
&& !dst_local
)
415 /* Ignore my own broadcast packets */
416 if (ifa
->cf
->real_bcast
&& ipa_equal(sk
->faddr
, ifa
->addr
->ip
))
421 /* In OSPFv3, src_local and dst_local mean link-local.
422 * RFC 5340 says that local (non-vlink) packets use
423 * link-local src address, but does not enforce it. Strange.
425 if (dst_mcast
&& !src_local
)
426 LOG_PKT_WARN("Multicast packet received from non-link-local %I via %s",
427 sk
->faddr
, ifa
->ifname
);
430 /* Second, we check packet length, checksum, and the protocol version */
431 struct ospf_packet
*pkt
= (void *) sk_rx_buffer(sk
, &len
);
435 DROP("bad IP header", len
);
437 if (len
< sizeof(struct ospf_packet
))
438 DROP("too short", len
);
440 if (pkt
->version
!= ospf_get_version(p
))
441 DROP("version mismatch", pkt
->version
);
443 uint plen
= ntohs(pkt
->length
);
444 if ((plen
< sizeof(struct ospf_packet
)) || ((plen
% 4) != 0))
445 DROP("invalid length", plen
);
447 if (sk
->flags
& SKF_TRUNCATED
)
449 /* If we have dynamic buffers and received truncated message, we expand RX buffer */
451 uint bs
= plen
+ 256;
452 bs
= BIRD_ALIGN(bs
, 1024);
454 if (!ifa
->cf
->rx_buffer
&& (bs
> sk
->rbsize
))
455 sk_set_rbsize(sk
, bs
);
457 DROP("truncated", plen
);
461 DROP("length mismatch", plen
);
463 if (ospf_is_v2(p
) && (pkt
->autype
!= OSPF_AUTH_CRYPT
))
465 uint hlen
= sizeof(struct ospf_packet
) + sizeof(union ospf_auth2
);
466 uint blen
= plen
- hlen
;
467 void *body
= ((void *) pkt
) + hlen
;
469 if (!ipsum_verify(pkt
, sizeof(struct ospf_packet
), body
, blen
, NULL
))
470 DROP("invalid checksum", ntohs(pkt
->checksum
));
473 /* Third, we resolve associated iface and handle vlinks. */
475 u32 areaid
= ntohl(pkt
->areaid
);
476 u32 rid
= ntohl(pkt
->routerid
);
477 u8 instance_id
= pkt
->instance_id
;
479 if (areaid
== ifa
->oa
->areaid
)
481 /* Matching area ID */
483 if (instance_id
!= ifa
->instance_id
)
486 /* It is real iface, source should be local (in OSPFv2) */
487 if (ospf_is_v2(p
) && !src_local
)
488 DROP1("strange source address");
492 else if ((areaid
== 0) && !dst_mcast
)
494 /* Backbone area ID and possible vlink packet */
496 if ((p
->areano
== 1) || !oa_is_ext(ifa
->oa
))
499 struct ospf_iface
*iff
= NULL
;
500 WALK_LIST(iff
, p
->iface_list
)
502 if ((iff
->type
== OSPF_IT_VLINK
) &&
503 (iff
->voa
== ifa
->oa
) &&
504 (iff
->instance_id
== instance_id
) &&
507 /* Vlink should be UP */
508 if (iff
->state
!= OSPF_IS_PTP
)
517 * Cannot find matching vlink. It is either misconfigured vlink; NBMA or
518 * PtMP with misconfigured area ID, or packet for some other instance (that
519 * is possible even if instance_id == ifa->instance_id, because it may be
520 * also vlink packet in the other instance, which is different namespace).
527 /* Non-matching area ID but cannot be vlink packet */
529 if (instance_id
!= ifa
->instance_id
)
532 DROP("area mismatch", areaid
);
537 if (ifa
->stub
) /* This shouldn't happen */
540 if (ipa_equal(sk
->laddr
, ifa
->des_routers
) && (ifa
->sk_dr
== 0))
543 /* TTL check must be done after instance dispatch */
544 if (ifa
->check_ttl
&& (sk
->rcv_ttl
< 255))
545 DROP("wrong TTL", sk
->rcv_ttl
);
547 if (rid
== p
->router_id
)
548 DROP1("my own router ID");
551 DROP1("zero router ID");
553 /* In OSPFv2, neighbors are identified by either IP or Router ID, based on network type */
555 struct ospf_neighbor
*n
;
556 if (ospf_is_v2(p
) && ((t
== OSPF_IT_BCAST
) || (t
== OSPF_IT_NBMA
) || (t
== OSPF_IT_PTMP
)))
557 n
= find_neigh_by_ip(ifa
, sk
->faddr
);
559 n
= find_neigh(ifa
, rid
);
561 if (!n
&& (pkt
->type
!= HELLO_P
))
563 OSPF_TRACE(D_PACKETS
, "Non-HELLO packet received from unknown nbr %R on %s, src %I",
564 rid
, ifa
->ifname
, sk
->faddr
);
568 /* Check packet type here, ospf_pkt_checkauth3() expects valid values */
569 if (pkt
->type
< HELLO_P
|| pkt
->type
> LSACK_P
)
570 DROP("invalid packet type", pkt
->type
);
572 /* ospf_pkt_checkauth() has its own error logging */
574 !ospf_pkt_checkauth2(n
, ifa
, pkt
, len
) :
575 !ospf_pkt_checkauth3(n
, ifa
, pkt
, len
, sk
->faddr
)))
581 ospf_receive_hello(pkt
, ifa
, n
, sk
->faddr
);
585 ospf_receive_dbdes(pkt
, ifa
, n
);
589 ospf_receive_lsreq(pkt
, ifa
, n
);
593 ospf_receive_lsupd(pkt
, ifa
, n
);
597 ospf_receive_lsack(pkt
, ifa
, n
);
603 LOG_PKT("Bad packet from %I via %s - %s (%u)",
604 sk
->faddr
, ifa
->ifname
, err_dsc
, err_val
);
611 ospf_tx_hook(sock * sk)
613 struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
614 // struct proto *p = (struct proto *) (ifa->oa->p);
615 log(L_ERR "OSPF: TX hook called on %s", ifa->ifname);
620 ospf_err_hook(sock
* sk
, int err
)
622 struct ospf_iface
*ifa
= (struct ospf_iface
*) (sk
->data
);
623 struct ospf_proto
*p
= ifa
->oa
->po
;
624 log(L_ERR
"%s: Socket error on %s: %M", p
->p
.name
, ifa
->ifname
, err
);
628 ospf_verr_hook(sock
*sk
, int err
)
630 struct ospf_proto
*p
= (struct ospf_proto
*) (sk
->data
);
631 log(L_ERR
"%s: Vlink socket error: %M", p
->p
.name
, err
);
635 ospf_send_to(struct ospf_iface
*ifa
, ip_addr dst
)
638 struct ospf_packet
*pkt
= (struct ospf_packet
*) sk
->tbuf
;
639 uint plen
= ntohs(pkt
->length
);
641 if (ospf_is_v2(ifa
->oa
->po
))
642 ospf_pkt_finalize2(ifa
, pkt
, &plen
);
644 ospf_pkt_finalize3(ifa
, pkt
, &plen
, sk
->saddr
);
646 int done
= sk_send_to(sk
, plen
, dst
, 0);
648 log(L_WARN
"OSPF: TX queue full on %s", ifa
->ifname
);
652 ospf_send_to_agt(struct ospf_iface
*ifa
, u8 state
)
654 struct ospf_neighbor
*n
;
656 WALK_LIST(n
, ifa
->neigh_list
)
657 if (n
->state
>= state
)
658 ospf_send_to(ifa
, n
->ip
);
662 ospf_send_to_bdr(struct ospf_iface
*ifa
)
664 if (ipa_nonzero2(ifa
->drip
))
665 ospf_send_to(ifa
, ifa
->drip
);
666 if (ipa_nonzero2(ifa
->bdrip
))
667 ospf_send_to(ifa
, ifa
->bdrip
);