]>
git.ipfire.org Git - thirdparty/bird.git/blob - proto/ospf/packet.c
4 * (c) 1999--2005 Ondrej Filip <feela@network.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
10 #include "nest/password.h"
14 ospf_pkt_fill_hdr(struct ospf_iface
*ifa
, void *buf
, u8 h_type
)
16 struct proto_ospf
*po
= ifa
->oa
->po
;
17 struct ospf_packet
*pkt
;
19 pkt
= (struct ospf_packet
*) buf
;
21 pkt
->version
= OSPF_VERSION
;
25 pkt
->routerid
= htonl(po
->router_id
);
26 pkt
->areaid
= htonl(ifa
->oa
->areaid
);
29 pkt
->instance_id
= ifa
->instance_id
;
33 pkt
->autype
= htons(ifa
->autype
);
40 ospf_pkt_maxsize(struct ospf_iface
*ifa
)
42 unsigned headers
= SIZE_OF_IP_HEADER
;
45 if (ifa
->autype
== OSPF_AUTH_CRYPT
)
46 headers
+= OSPF_AUTH_CRYPT_SIZE
;
49 return ifa
->tx_length
- headers
;
55 ospf_pkt_finalize(struct ospf_iface
*ifa
, struct ospf_packet
*pkt
)
57 struct password_item
*passwd
= NULL
;
59 struct MD5Context ctxt
;
60 char password
[OSPF_AUTH_CRYPT_SIZE
];
63 pkt
->autype
= htons(ifa
->autype
);
64 bzero(&pkt
->u
, sizeof(union ospf_auth
));
66 /* Compatibility note: pkt->u may contain anything if autype is
67 none, but nonzero values do not work with Mikrotik OSPF */
71 case OSPF_AUTH_SIMPLE
:
72 passwd
= password_find(ifa
->passwords
, 1);
75 log( L_ERR
"No suitable password found for authentication" );
78 password_cpy(pkt
->u
.password
, passwd
->password
, sizeof(union ospf_auth
));
80 pkt
->checksum
= ipsum_calculate(pkt
, sizeof(struct ospf_packet
) -
81 sizeof(union ospf_auth
), (pkt
+ 1),
83 sizeof(struct ospf_packet
), NULL
);
86 passwd
= password_find(ifa
->passwords
, 0);
89 log( L_ERR
"No suitable password found for authentication" );
93 /* Perhaps use random value to prevent replay attacks after
94 reboot when system does not have independent RTC? */
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)
108 pkt
->u
.md5
.keyid
= passwd
->id
;
109 pkt
->u
.md5
.len
= OSPF_AUTH_CRYPT_SIZE
;
111 pkt
->u
.md5
.csn
= htonl(ifa
->csn
);
112 tail
= ((void *)pkt
) + ntohs(pkt
->length
);
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
);
120 bug("Unknown authentication type");
125 ospf_pkt_checkauth(struct ospf_neighbor
*n
, struct ospf_iface
*ifa
, struct ospf_packet
*pkt
, int size
)
127 struct proto_ospf
*po
= ifa
->oa
->po
;
128 struct proto
*p
= &po
->proto
;
129 struct password_item
*pass
= NULL
, *ptmp
;
131 char md5sum
[OSPF_AUTH_CRYPT_SIZE
];
132 char password
[OSPF_AUTH_CRYPT_SIZE
];
133 struct MD5Context ctxt
;
136 if (pkt
->autype
!= htons(ifa
->autype
))
138 OSPF_TRACE(D_PACKETS
, "OSPF_auth: Method differs (%d)", ntohs(pkt
->autype
));
147 case OSPF_AUTH_SIMPLE
:
148 pass
= password_find(ifa
->passwords
, 1);
151 OSPF_TRACE(D_PACKETS
, "OSPF_auth: no password found");
154 password_cpy(password
, pass
->password
, sizeof(union ospf_auth
));
156 if (memcmp(pkt
->u
.password
, password
, sizeof(union ospf_auth
)))
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
);
166 case OSPF_AUTH_CRYPT
:
167 if (pkt
->u
.md5
.len
!= OSPF_AUTH_CRYPT_SIZE
)
169 OSPF_TRACE(D_PACKETS
, "OSPF_auth: wrong size of md5 digest");
173 if (ntohs(pkt
->length
) + OSPF_AUTH_CRYPT_SIZE
> size
)
175 OSPF_TRACE(D_PACKETS
, "OSPF_auth: size mismatch (%d vs %d)",
176 ntohs(pkt
->length
) + OSPF_AUTH_CRYPT_SIZE
, size
);
180 tail
= ((void *)pkt
) + ntohs(pkt
->length
);
184 WALK_LIST(ptmp
, *(ifa
->passwords
))
186 if (pkt
->u
.md5
.keyid
!= ptmp
->id
) continue;
187 if ((ptmp
->accfrom
> now_real
) || (ptmp
->accto
< now_real
)) continue;
195 OSPF_TRACE(D_PACKETS
, "OSPF_auth: no suitable md5 password found");
201 u32 rcv_csn
= ntohl(pkt
->u
.md5
.csn
);
204 OSPF_TRACE(D_PACKETS
, "OSPF_auth: lower sequence number (rcv %d, old %d)", rcv_csn
, n
->csn
);
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
))
218 OSPF_TRACE(D_PACKETS
, "OSPF_auth: wrong md5 digest");
224 OSPF_TRACE(D_PACKETS
, "OSPF_auth: unknown auth type");
231 /* OSPFv3 authentication not yet supported */
234 ospf_pkt_finalize(struct ospf_iface
*ifa
, struct ospf_packet
*pkt
)
238 ospf_pkt_checkauth(struct ospf_neighbor
*n
, struct ospf_iface
*ifa
, struct ospf_packet
*pkt
, int size
)
246 * @sk: socket we received the packet.
247 * @size: size of the packet
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.
254 ospf_rx_hook(sock
*sk
, int size
)
256 char *mesg
= "OSPF: Bad packet from ";
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
)
264 DBG("OSPF: RX hook called (iface %s, src %I, dst %I)\n",
265 sk
->ifname
, sk
->faddr
, sk
->laddr
);
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;
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
);
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
284 if (dst_mcast
&& !src_local
)
286 if (!dst_mcast
&& !dst_local
)
289 /* Ignore my own broadcast packets */
290 if (ifa
->cf
->real_bcast
&& ipa_equal(sk
->faddr
, ifa
->addr
->ip
))
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.
298 if (dst_mcast
&& !src_local
)
299 log(L_WARN
"OSPF: Received multicast packet from %I (not link-local)", sk
->faddr
);
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
);
307 log(L_ERR
"%s%I - bad IP header", mesg
, sk
->faddr
);
311 if (ifa
->check_ttl
&& (sk
->ttl
< 255))
313 log(L_ERR
"%s%I - TTL %d (< 255)", mesg
, sk
->faddr
, sk
->ttl
);
317 if ((unsigned) size
< sizeof(struct ospf_packet
))
319 log(L_ERR
"%s%I - too short (%u bytes)", mesg
, sk
->faddr
, size
);
323 uint plen
= ntohs(ps
->length
);
324 if ((plen
< sizeof(struct ospf_packet
)) || ((plen
% 4) != 0))
326 log(L_ERR
"%s%I - invalid length (%u)", mesg
, sk
->faddr
, plen
);
330 if (sk
->flags
& SKF_TRUNCATED
)
332 log(L_WARN
"%s%I - too large (%d/%d)", mesg
, sk
->faddr
, plen
, size
);
334 /* If we have dynamic buffers and received truncated message, we expand RX buffer */
336 uint bs
= plen
+ 256;
337 bs
= BIRD_ALIGN(bs
, 1024);
339 if (!ifa
->cf
->rx_buffer
&& (bs
> sk
->rbsize
))
340 sk_set_rbsize(sk
, bs
);
347 log(L_ERR
"%s%I - size field does not match (%d/%d)", mesg
, sk
->faddr
, plen
, size
);
351 if (ps
->version
!= OSPF_VERSION
)
353 log(L_ERR
"%s%I - version %u", mesg
, sk
->faddr
, ps
->version
);
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
)))
362 log(L_ERR
"%s%I - bad checksum", mesg
, sk
->faddr
);
368 /* Third, we resolve associated iface and handle vlinks. */
370 u32 areaid
= ntohl(ps
->areaid
);
371 u32 rid
= ntohl(ps
->routerid
);
373 if ((areaid
== ifa
->oa
->areaid
)
375 && (ps
->instance_id
== ifa
->instance_id
)
379 /* It is real iface, source should be local (in OSPFv2) */
385 else if (dst_mcast
|| (areaid
!= 0))
387 /* Obvious mismatch */
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
);
400 struct ospf_iface
*iff
= NULL
;
402 WALK_LIST(iff
, po
->iface_list
)
404 if ((iff
->type
== OSPF_IT_VLINK
) &&
405 (iff
->voa
== ifa
->oa
) &&
407 (iff
->instance_id
== ps
->instance_id
) &&
411 /* Vlink should be UP */
412 if (iff
->state
!= OSPF_IS_PTP
)
421 log(L_WARN
"OSPF: Received packet for unknown vlink (ID %R, IP %I)", rid
, sk
->faddr
);
427 if (ifa
->stub
) /* This shouldn't happen */
430 if (ipa_equal(sk
->laddr
, AllDRouters
) && (ifa
->sk_dr
== 0))
433 if (rid
== po
->router_id
)
435 log(L_ERR
"%s%I - received my own router ID!", mesg
, sk
->faddr
);
441 log(L_ERR
"%s%I - router id = 0.0.0.0", mesg
, sk
->faddr
);
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
);
451 n
= find_neigh(ifa
, rid
);
453 struct ospf_neighbor
*n
= find_neigh(ifa
, rid
);
456 if(!n
&& (ps
->type
!= HELLO_P
))
458 log(L_WARN
"OSPF: Received non-hello packet from unknown neighbor (src %I, iface %s)",
459 sk
->faddr
, ifa
->ifname
);
463 if (!ospf_pkt_checkauth(n
, ifa
, ps
, size
))
465 log(L_ERR
"%s%I - authentication failed", mesg
, sk
->faddr
);
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],
474 DBG("%s: received size: %u\n",p->name,size);
480 DBG("%s: Hello received.\n", p
->name
);
481 ospf_hello_receive(ps
, ifa
, n
, sk
->faddr
);
484 DBG("%s: Database description received.\n", p
->name
);
485 ospf_dbdes_receive(ps
, ifa
, n
);
488 DBG("%s: Link state request received.\n", p
->name
);
489 ospf_lsreq_receive(ps
, ifa
, n
);
492 DBG("%s: Link state update received.\n", p
->name
);
493 ospf_lsupd_receive(ps
, ifa
, n
);
496 DBG("%s: Link state ack received.\n", p
->name
);
497 ospf_lsack_receive(ps
, ifa
, n
);
500 log(L_ERR
"%s%I - wrong type %u", mesg
, sk
->faddr
, ps
->type
);
508 ospf_tx_hook(sock * sk)
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);
517 ospf_err_hook(sock
* sk
, int err
)
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
);
525 ospf_verr_hook(sock
*sk
, int err
)
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
);
533 ospf_send_to_agt(struct ospf_iface
*ifa
, u8 state
)
535 struct ospf_neighbor
*n
;
537 WALK_LIST(n
, ifa
->neigh_list
)
538 if (n
->state
>= state
)
539 ospf_send_to(ifa
, n
->ip
);
543 ospf_send_to_bdr(struct ospf_iface
*ifa
)
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
);
552 ospf_send_to(struct ospf_iface
*ifa
, ip_addr dst
)
555 struct ospf_packet
*pkt
= (struct ospf_packet
*) sk
->tbuf
;
556 int len
= ntohs(pkt
->length
);
559 if (ifa
->autype
== OSPF_AUTH_CRYPT
)
560 len
+= OSPF_AUTH_CRYPT_SIZE
;
563 ospf_pkt_finalize(ifa
, pkt
);
565 int done
= sk_send_to(sk
, len
, dst
, 0);
567 log(L_WARN
"OSPF: TX queue full on %s", ifa
->ifname
);