]>
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"
16 ospf_pkt_fill_hdr(struct ospf_iface
*ifa
, void *buf
, u8 h_type
)
18 struct ospf_proto
*p
= ifa
->oa
->po
;
19 struct ospf_packet
*pkt
;
21 pkt
= (struct ospf_packet
*) buf
;
23 pkt
->version
= ospf_get_version(p
);
25 pkt
->length
= htons(ospf_pkt_maxsize(ifa
));
26 pkt
->routerid
= htonl(p
->router_id
);
27 pkt
->areaid
= htonl(ifa
->oa
->areaid
);
29 pkt
->instance_id
= ifa
->instance_id
;
30 pkt
->autype
= ifa
->autype
;
34 ospf_pkt_maxsize(struct ospf_iface
*ifa
)
36 uint headers
= SIZE_OF_IP_HEADER
;
38 /* Relevant just for OSPFv2 */
39 if (ifa
->autype
== OSPF_AUTH_CRYPT
)
40 headers
+= OSPF_AUTH_CRYPT_SIZE
;
42 return ifa
->tx_length
- headers
;
45 /* We assume OSPFv2 in ospf_pkt_finalize() */
47 ospf_pkt_finalize(struct ospf_iface
*ifa
, struct ospf_packet
*pkt
)
49 struct password_item
*passwd
= NULL
;
50 union ospf_auth
*auth
= (void *) (pkt
+ 1);
51 uint plen
= ntohs(pkt
->length
);
54 pkt
->autype
= ifa
->autype
;
55 bzero(auth
, sizeof(union ospf_auth
));
57 /* Compatibility note: auth may contain anything if autype is
58 none, but nonzero values do not work with Mikrotik OSPF */
62 case OSPF_AUTH_SIMPLE
:
63 passwd
= password_find(ifa
->passwords
, 1);
66 log(L_ERR
"No suitable password found for authentication");
69 password_cpy(auth
->password
, passwd
->password
, sizeof(union ospf_auth
));
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
);
80 passwd
= password_find(ifa
->passwords
, 0);
83 log(L_ERR
"No suitable password found for authentication");
87 /* Perhaps use random value to prevent replay attacks after
88 reboot when system does not have independent RTC? */
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)
103 auth
->md5
.keyid
= passwd
->id
;
104 auth
->md5
.len
= OSPF_AUTH_CRYPT_SIZE
;
105 auth
->md5
.csn
= htonl(ifa
->csn
);
107 void *tail
= ((void *) pkt
) + plen
;
108 char password
[OSPF_AUTH_CRYPT_SIZE
];
109 password_cpy(password
, passwd
->password
, OSPF_AUTH_CRYPT_SIZE
);
111 struct MD5Context ctxt
;
113 MD5Update(&ctxt
, (char *) pkt
, plen
);
114 MD5Update(&ctxt
, password
, OSPF_AUTH_CRYPT_SIZE
);
115 MD5Final(tail
, &ctxt
);
119 bug("Unknown authentication type");
123 /* We assume OSPFv2 in ospf_pkt_checkauth() */
125 ospf_pkt_checkauth(struct ospf_neighbor
*n
, struct ospf_iface
*ifa
, struct ospf_packet
*pkt
, int size
)
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
];
132 uint plen
= ntohs(pkt
->length
);
133 u8 autype
= pkt
->autype
;
135 if (autype
!= ifa
->autype
)
137 OSPF_TRACE(D_PACKETS
, "OSPF_auth: Method differs (%d)", autype
);
146 case OSPF_AUTH_SIMPLE
:
147 pass
= password_find(ifa
->passwords
, 1);
150 OSPF_TRACE(D_PACKETS
, "OSPF_auth: no password found");
154 password_cpy(password
, pass
->password
, sizeof(union ospf_auth
));
155 if (memcmp(auth
->password
, password
, sizeof(union ospf_auth
)))
157 OSPF_TRACE(D_PACKETS
, "OSPF_auth: different passwords");
162 case OSPF_AUTH_CRYPT
:
163 if (auth
->md5
.len
!= OSPF_AUTH_CRYPT_SIZE
)
165 OSPF_TRACE(D_PACKETS
, "OSPF_auth: wrong size of md5 digest");
169 if (plen
+ OSPF_AUTH_CRYPT_SIZE
> size
)
171 OSPF_TRACE(D_PACKETS
, "OSPF_auth: size mismatch (%d vs %d)",
172 plen
+ OSPF_AUTH_CRYPT_SIZE
, size
);
178 u32 rcv_csn
= ntohl(auth
->md5
.csn
);
181 OSPF_TRACE(D_PACKETS
, "OSPF_auth: lower sequence number (rcv %d, old %d)", rcv_csn
, n
->csn
);
190 WALK_LIST(ptmp
, *(ifa
->passwords
))
192 if (auth
->md5
.keyid
!= ptmp
->id
) continue;
193 if ((ptmp
->accfrom
> now_real
) || (ptmp
->accto
< now_real
)) continue;
201 OSPF_TRACE(D_PACKETS
, "OSPF_auth: no suitable md5 password found");
205 void *tail
= ((void *) pkt
) + plen
;
206 char md5sum
[OSPF_AUTH_CRYPT_SIZE
];
207 password_cpy(password
, pass
->password
, OSPF_AUTH_CRYPT_SIZE
);
209 struct MD5Context ctxt
;
211 MD5Update(&ctxt
, (char *) pkt
, plen
);
212 MD5Update(&ctxt
, password
, OSPF_AUTH_CRYPT_SIZE
);
213 MD5Final(md5sum
, &ctxt
);
215 if (memcmp(md5sum
, tail
, OSPF_AUTH_CRYPT_SIZE
))
217 OSPF_TRACE(D_PACKETS
, "OSPF_auth: wrong md5 digest");
223 OSPF_TRACE(D_PACKETS
, "OSPF_auth: unknown auth type");
231 * @sk: socket we received the packet.
232 * @size: size of the packet
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.
239 ospf_rx_hook(sock
*sk
, int size
)
241 char *mesg
= "OSPF: Bad packet from ";
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
)
249 DBG("OSPF: RX hook called (iface %s, src %I, dst %I)\n",
250 sk
->ifname
, sk
->faddr
, sk
->laddr
);
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
;
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
);
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
269 if (dst_mcast
&& !src_local
)
271 if (!dst_mcast
&& !dst_local
)
274 /* Ignore my own broadcast packets */
275 if (ifa
->cf
->real_bcast
&& ipa_equal(sk
->faddr
, ifa
->addr
->ip
))
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.
284 if (dst_mcast
&& !src_local
)
285 log(L_WARN
"OSPF: Received multicast packet from %I (not link-local)", sk
->faddr
);
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
);
293 log(L_ERR
"%s%I - bad IP header", mesg
, sk
->faddr
);
297 if (ifa
->check_ttl
&& (sk
->rcv_ttl
< 255))
299 log(L_ERR
"%s%I - TTL %d (< 255)", mesg
, sk
->faddr
, sk
->rcv_ttl
);
303 if ((uint
) size
< sizeof(struct ospf_packet
))
305 log(L_ERR
"%s%I - too short (%u bytes)", mesg
, sk
->faddr
, size
);
309 uint plen
= ntohs(pkt
->length
);
310 if ((plen
< sizeof(struct ospf_packet
)) || ((plen
% 4) != 0))
312 log(L_ERR
"%s%I - invalid length (%u)", mesg
, sk
->faddr
, plen
);
316 if (sk
->flags
& SKF_TRUNCATED
)
318 log(L_WARN
"%s%I - too large (%d/%d)", mesg
, sk
->faddr
, plen
, size
);
320 /* If we have dynamic buffers and received truncated message, we expand RX buffer */
322 uint bs
= plen
+ 256;
323 bs
= BIRD_ALIGN(bs
, 1024);
325 if (!ifa
->cf
->rx_buffer
&& (bs
> sk
->rbsize
))
326 sk_set_rbsize(sk
, bs
);
333 log(L_ERR
"%s%I - size field does not match (%d/%d)", mesg
, sk
->faddr
, plen
, size
);
337 if (pkt
->version
!= ospf_get_version(p
))
339 log(L_ERR
"%s%I - version %u", mesg
, sk
->faddr
, pkt
->version
);
343 if (ospf_is_v2(p
) && (pkt
->autype
!= OSPF_AUTH_CRYPT
))
345 uint hlen
= sizeof(struct ospf_packet
) + sizeof(union ospf_auth
);
346 uint blen
= plen
- hlen
;
347 void *body
= ((void *) pkt
) + hlen
;
349 if (! ipsum_verify(pkt
, sizeof(struct ospf_packet
), body
, blen
, NULL
))
351 log(L_ERR
"%s%I - bad checksum", mesg
, sk
->faddr
);
356 /* Third, we resolve associated iface and handle vlinks. */
358 u32 areaid
= ntohl(pkt
->areaid
);
359 u32 rid
= ntohl(pkt
->routerid
);
360 u8 instance_id
= pkt
->instance_id
;
362 if (areaid
== ifa
->oa
->areaid
)
364 /* Matching area ID */
366 if (instance_id
!= ifa
->instance_id
)
369 /* It is real iface, source should be local (in OSPFv2) */
370 if (ospf_is_v2(p
) && !src_local
)
372 log(L_ERR
"%s%I - strange source address for %s", mesg
, sk
->faddr
, ifa
->ifname
);
378 else if ((areaid
== 0) && !dst_mcast
)
380 /* Backbone area ID and possible vlink packet */
382 if ((p
->areano
== 1) || !oa_is_ext(ifa
->oa
))
385 struct ospf_iface
*iff
= NULL
;
386 WALK_LIST(iff
, p
->iface_list
)
388 if ((iff
->type
== OSPF_IT_VLINK
) &&
389 (iff
->voa
== ifa
->oa
) &&
390 (iff
->instance_id
== instance_id
) &&
393 /* Vlink should be UP */
394 if (iff
->state
!= OSPF_IS_PTP
)
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).
413 /* Non-matching area ID but cannot be vlink packet */
415 if (instance_id
!= ifa
->instance_id
)
418 log(L_ERR
"%s%I - area does not match (%R vs %R)",
419 mesg
, sk
->faddr
, areaid
, ifa
->oa
->areaid
);
425 if (ifa
->stub
) /* This shouldn't happen */
428 if (ipa_equal(sk
->laddr
, ifa
->des_routers
) && (ifa
->sk_dr
== 0))
431 if (rid
== p
->router_id
)
433 log(L_ERR
"%s%I - received my own router ID!", mesg
, sk
->faddr
);
439 log(L_ERR
"%s%I - router id = 0.0.0.0", mesg
, sk
->faddr
);
443 /* In OSPFv2, neighbors are identified by either IP or Router ID, base on network 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
);
449 n
= find_neigh(ifa
, rid
);
451 if (!n
&& (pkt
->type
!= HELLO_P
))
453 log(L_WARN
"OSPF: Received non-hello packet from unknown neighbor (src %I, iface %s)",
454 sk
->faddr
, ifa
->ifname
);
458 if (ospf_is_v2(p
) && !ospf_pkt_checkauth(n
, ifa
, pkt
, size
))
460 log(L_ERR
"%s%I - authentication failed", mesg
, sk
->faddr
);
467 ospf_receive_hello(pkt
, ifa
, n
, sk
->faddr
);
471 ospf_receive_dbdes(pkt
, ifa
, n
);
475 ospf_receive_lsreq(pkt
, ifa
, n
);
479 ospf_receive_lsupd(pkt
, ifa
, n
);
483 ospf_receive_lsack(pkt
, ifa
, n
);
487 log(L_ERR
"%s%I - wrong type %u", mesg
, sk
->faddr
, pkt
->type
);
495 ospf_tx_hook(sock * sk)
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);
504 ospf_err_hook(sock
* sk
, int err
)
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
);
512 ospf_verr_hook(sock
*sk
, int err
)
514 struct ospf_proto
*p
= (struct ospf_proto
*) (sk
->data
);
515 log(L_ERR
"%s: Vlink socket error: %M", p
->p
.name
, err
);
519 ospf_send_to(struct ospf_iface
*ifa
, ip_addr dst
)
522 struct ospf_packet
*pkt
= (struct ospf_packet
*) sk
->tbuf
;
523 int plen
= ntohs(pkt
->length
);
525 if (ospf_is_v2(ifa
->oa
->po
))
527 if (ifa
->autype
== OSPF_AUTH_CRYPT
)
528 plen
+= OSPF_AUTH_CRYPT_SIZE
;
530 ospf_pkt_finalize(ifa
, pkt
);
533 int done
= sk_send_to(sk
, plen
, dst
, 0);
535 log(L_WARN
"OSPF: TX queue full on %s", ifa
->ifname
);
539 ospf_send_to_agt(struct ospf_iface
*ifa
, u8 state
)
541 struct ospf_neighbor
*n
;
543 WALK_LIST(n
, ifa
->neigh_list
)
544 if (n
->state
>= state
)
545 ospf_send_to(ifa
, n
->ip
);
549 ospf_send_to_bdr(struct ospf_iface
*ifa
)
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
);