]>
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 mtu
= (ifa
->type
== OSPF_IT_VLINK
) ? OSPF_VLINK_MTU
: ifa
->iface
->mtu
;
43 unsigned headers
= SIZE_OF_IP_HEADER
;
46 if (ifa
->autype
== OSPF_AUTH_CRYPT
)
47 headers
+= OSPF_AUTH_CRYPT_SIZE
;
56 ospf_pkt_finalize(struct ospf_iface
*ifa
, struct ospf_packet
*pkt
)
58 struct password_item
*passwd
= NULL
;
60 struct MD5Context ctxt
;
61 char password
[OSPF_AUTH_CRYPT_SIZE
];
64 pkt
->autype
= htons(ifa
->autype
);
65 bzero(&pkt
->u
, sizeof(union ospf_auth
));
67 /* Compatibility note: pkt->u may contain anything if autype is
68 none, but nonzero values do not work with Mikrotik OSPF */
72 case OSPF_AUTH_SIMPLE
:
73 passwd
= password_find(ifa
->passwords
, 1);
76 log( L_ERR
"No suitable password found for authentication" );
79 password_cpy(pkt
->u
.password
, passwd
->password
, sizeof(union ospf_auth
));
81 pkt
->checksum
= ipsum_calculate(pkt
, sizeof(struct ospf_packet
) -
82 sizeof(union ospf_auth
), (pkt
+ 1),
84 sizeof(struct ospf_packet
), NULL
);
87 passwd
= password_find(ifa
->passwords
, 0);
90 log( L_ERR
"No suitable password found for authentication" );
94 /* Perhaps use random value to prevent replay attacks after
95 reboot when system does not have independent RTC? */
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)
109 pkt
->u
.md5
.keyid
= passwd
->id
;
110 pkt
->u
.md5
.len
= OSPF_AUTH_CRYPT_SIZE
;
112 pkt
->u
.md5
.csn
= htonl(ifa
->csn
);
113 tail
= ((void *)pkt
) + ntohs(pkt
->length
);
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
);
121 bug("Unknown authentication type");
126 ospf_pkt_checkauth(struct ospf_neighbor
*n
, struct ospf_iface
*ifa
, struct ospf_packet
*pkt
, int size
)
128 struct proto_ospf
*po
= ifa
->oa
->po
;
129 struct proto
*p
= &po
->proto
;
130 struct password_item
*pass
= NULL
, *ptmp
;
132 char md5sum
[OSPF_AUTH_CRYPT_SIZE
];
133 char password
[OSPF_AUTH_CRYPT_SIZE
];
134 struct MD5Context ctxt
;
137 if (pkt
->autype
!= htons(ifa
->autype
))
139 OSPF_TRACE(D_PACKETS
, "OSPF_auth: Method differs (%d)", ntohs(pkt
->autype
));
148 case OSPF_AUTH_SIMPLE
:
149 pass
= password_find(ifa
->passwords
, 1);
152 OSPF_TRACE(D_PACKETS
, "OSPF_auth: no password found");
155 password_cpy(password
, pass
->password
, sizeof(union ospf_auth
));
157 if (memcmp(pkt
->u
.password
, password
, sizeof(union ospf_auth
)))
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
);
167 case OSPF_AUTH_CRYPT
:
168 if (pkt
->u
.md5
.len
!= OSPF_AUTH_CRYPT_SIZE
)
170 OSPF_TRACE(D_PACKETS
, "OSPF_auth: wrong size of md5 digest");
174 if (ntohs(pkt
->length
) + OSPF_AUTH_CRYPT_SIZE
> size
)
176 OSPF_TRACE(D_PACKETS
, "OSPF_auth: size mismatch (%d vs %d)",
177 ntohs(pkt
->length
) + OSPF_AUTH_CRYPT_SIZE
, size
);
181 tail
= ((void *)pkt
) + ntohs(pkt
->length
);
185 WALK_LIST(ptmp
, *(ifa
->passwords
))
187 if (pkt
->u
.md5
.keyid
!= ptmp
->id
) continue;
188 if ((ptmp
->accfrom
> now_real
) || (ptmp
->accto
< now_real
)) continue;
196 OSPF_TRACE(D_PACKETS
, "OSPF_auth: no suitable md5 password found");
202 u32 rcv_csn
= ntohl(pkt
->u
.md5
.csn
);
205 OSPF_TRACE(D_PACKETS
, "OSPF_auth: lower sequence number (rcv %d, old %d)", rcv_csn
, n
->csn
);
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
))
219 OSPF_TRACE(D_PACKETS
, "OSPF_auth: wrong md5 digest");
225 OSPF_TRACE(D_PACKETS
, "OSPF_auth: unknown auth type");
232 /* OSPFv3 authentication not yet supported */
235 ospf_pkt_finalize(struct ospf_iface
*ifa
, struct ospf_packet
*pkt
)
239 ospf_pkt_checkauth(struct ospf_neighbor
*n
, struct ospf_iface
*ifa
, struct ospf_packet
*pkt
, int size
)
247 * @sk: socket we received the packet.
248 * @size: size of the packet
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.
255 ospf_rx_hook(sock
*sk
, int size
)
257 char *mesg
= "OSPF: Bad packet from ";
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
)
265 DBG("OSPF: RX hook called (iface %s, src %I, dst %I)\n",
266 sk
->iface
->name
, sk
->faddr
, sk
->laddr
);
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;
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
);
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
285 if (dst_mcast
&& !src_local
)
287 if (!dst_mcast
&& !dst_local
)
290 /* Ignore my own broadcast packets */
291 if (ifa
->cf
->real_bcast
&& ipa_equal(sk
->faddr
, ifa
->addr
->ip
))
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.
299 if (dst_mcast
&& !src_local
)
300 log(L_WARN
"OSPF: Received multicast packet from %I (not link-local)", sk
->faddr
);
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
);
308 log(L_ERR
"%s%I - bad IP header", mesg
, sk
->faddr
);
312 if ((unsigned) size
< sizeof(struct ospf_packet
))
314 log(L_ERR
"%s%I - too short (%u bytes)", mesg
, sk
->faddr
, size
);
318 int osize
= ntohs(ps
->length
);
319 if ((unsigned) osize
< sizeof(struct ospf_packet
))
321 log(L_ERR
"%s%I - too low value in size field (%u bytes)", mesg
, sk
->faddr
, osize
);
325 if ((osize
> size
) || ((osize
% 4) != 0))
327 log(L_ERR
"%s%I - size field does not match (%d/%d)", mesg
, sk
->faddr
, osize
, size
);
331 if ((unsigned) size
> sk
->rbsize
)
333 log(L_ERR
"%s%I - too large (%d vs %d)", mesg
, sk
->faddr
, size
, sk
->rbsize
);
337 if (ps
->version
!= OSPF_VERSION
)
339 log(L_ERR
"%s%I - version %u", mesg
, sk
->faddr
, ps
->version
);
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
)))
348 log(L_ERR
"%s%I - bad checksum", mesg
, sk
->faddr
);
354 /* Third, we resolve associated iface and handle vlinks. */
356 u32 areaid
= ntohl(ps
->areaid
);
357 u32 rid
= ntohl(ps
->routerid
);
359 if ((areaid
== ifa
->oa
->areaid
)
361 && (ps
->instance_id
== ifa
->instance_id
)
365 /* It is real iface, source should be local (in OSPFv2) */
371 else if (dst_mcast
|| (areaid
!= 0))
373 /* Obvious mismatch */
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
);
386 struct ospf_iface
*iff
= NULL
;
388 WALK_LIST(iff
, po
->iface_list
)
390 if ((iff
->type
== OSPF_IT_VLINK
) &&
391 (iff
->voa
== ifa
->oa
) &&
393 (iff
->instance_id
== ps
->instance_id
) &&
397 /* Vlink should be UP */
398 if (iff
->state
!= OSPF_IS_PTP
)
407 log(L_WARN
"OSPF: Received packet for unknown vlink (ID %R, IP %I)", rid
, sk
->faddr
);
413 if (ifa
->stub
) /* This shouldn't happen */
416 if (ipa_equal(sk
->laddr
, AllDRouters
) && (ifa
->sk_dr
== 0))
419 if (rid
== po
->router_id
)
421 log(L_ERR
"%s%I - received my own router ID!", mesg
, sk
->faddr
);
427 log(L_ERR
"%s%I - router id = 0.0.0.0", mesg
, sk
->faddr
);
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
);
437 n
= find_neigh(ifa
, rid
);
439 struct ospf_neighbor
*n
= find_neigh(ifa
, rid
);
442 if(!n
&& (ps
->type
!= HELLO_P
))
444 log(L_WARN
"OSPF: Received non-hello packet from unknown neighbor (src %I, iface %s)",
445 sk
->faddr
, ifa
->iface
->name
);
449 if (!ospf_pkt_checkauth(n
, ifa
, ps
, size
))
451 log(L_ERR
"%s%I - authentication failed", mesg
, sk
->faddr
);
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],
460 DBG("%s: received size: %u\n",p->name,size);
466 DBG("%s: Hello received.\n", p
->name
);
467 ospf_hello_receive(ps
, ifa
, n
, sk
->faddr
);
470 DBG("%s: Database description received.\n", p
->name
);
471 ospf_dbdes_receive(ps
, ifa
, n
);
474 DBG("%s: Link state request received.\n", p
->name
);
475 ospf_lsreq_receive(ps
, ifa
, n
);
478 DBG("%s: Link state update received.\n", p
->name
);
479 ospf_lsupd_receive(ps
, ifa
, n
);
482 DBG("%s: Link state ack received.\n", p
->name
);
483 ospf_lsack_receive(ps
, ifa
, n
);
486 log(L_ERR
"%s%I - wrong type %u", mesg
, sk
->faddr
, ps
->type
);
493 ospf_tx_hook(sock
* sk
)
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
);
501 ospf_err_hook(sock
* sk
, int err
)
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
);
509 ospf_send_to_agt(struct ospf_iface
*ifa
, u8 state
)
511 struct ospf_neighbor
*n
;
513 WALK_LIST(n
, ifa
->neigh_list
)
514 if (n
->state
>= state
)
515 ospf_send_to(ifa
, n
->ip
);
519 ospf_send_to_bdr(struct ospf_iface
*ifa
)
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
);
528 ospf_send_to(struct ospf_iface
*ifa
, ip_addr dst
)
531 struct ospf_packet
*pkt
= (struct ospf_packet
*) sk
->tbuf
;
532 int len
= ntohs(pkt
->length
);
535 if (ifa
->autype
== OSPF_AUTH_CRYPT
)
536 len
+= OSPF_AUTH_CRYPT_SIZE
;
539 ospf_pkt_finalize(ifa
, pkt
);
540 if (sk
->tbuf
!= sk
->tpos
)
541 log(L_ERR
"Aiee, old packet was overwritten in TX buffer");
543 sk_send_to(sk
, len
, dst
, 0);