1 /*
2  *	BIRD -- OSPF
3  *
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.
7  *
8  *	Can be freely distributed and used under the terms of the GNU GPL.
9  */
10 
11 #include "ospf.h"
12 #include "nest/password.h"
13 #include "lib/md5.h"
14 #include "lib/mac.h"
15 #include "lib/socket.h"
16 
17 const char * const ospf_pkt_names[] = {
18   [HELLO_P]	= "HELLO",
19   [DBDES_P]	= "DBDES",
20   [LSREQ_P]	= "LSREQ",
21   [LSUPD_P]	= "LSUPD",
22   [LSACK_P]	= "LSACK",
23 };
24 
25 void
ospf_pkt_fill_hdr(struct ospf_iface * ifa,void * buf,u8 h_type)26 ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
27 {
28   struct ospf_proto *p = ifa->oa->po;
29   struct ospf_packet *pkt;
30 
31   pkt = (struct ospf_packet *) buf;
32 
33   pkt->version = ospf_get_version(p);
34   pkt->type = h_type;
35   pkt->length = htons(ospf_pkt_maxsize(ifa));
36   pkt->routerid = htonl(p->router_id);
37   pkt->areaid = htonl(ifa->oa->areaid);
38   pkt->checksum = 0;
39   pkt->instance_id = ifa->instance_id;
40   pkt->autype = ospf_is_v2(p) ? ifa->autype : 0;
41 }
42 
43 /* We assume OSPFv2 in ospf_pkt_finalize() */
44 static void
ospf_pkt_finalize2(struct ospf_iface * ifa,struct ospf_packet * pkt,uint * plen)45 ospf_pkt_finalize2(struct ospf_iface *ifa, struct ospf_packet *pkt, uint *plen)
46 {
47   struct ospf_proto *p = ifa->oa->po;
48   struct password_item *pass = NULL;
49   union ospf_auth2 *auth = (void *) (pkt + 1);
50   memset(auth, 0, sizeof(union ospf_auth2));
51 
52   /* Compatibility note: auth may contain anything if autype is
53      none, but nonzero values do not work with Mikrotik OSPF */
54 
55   pkt->checksum = 0;
56   pkt->autype = ifa->autype;
57 
58   switch (ifa->autype)
59   {
60   case OSPF_AUTH_SIMPLE:
61     pass = password_find(ifa->passwords, 1);
62     if (!pass)
63     {
64       log(L_ERR "No suitable password found for authentication");
65       return;
66     }
67     strncpy(auth->password, pass->password, sizeof(auth->password));
68     /* fallthrough */
69 
70   case OSPF_AUTH_NONE:
71     {
72       void *body = (void *) (auth + 1);
73       uint blen = *plen - sizeof(struct ospf_packet) - sizeof(union ospf_auth2);
74       pkt->checksum = ipsum_calculate(pkt, sizeof(struct ospf_packet), body, blen, NULL);
75     }
76     break;
77 
78   case OSPF_AUTH_CRYPT:
79     pass = password_find(ifa->passwords, 0);
80     if (!pass)
81     {
82       log(L_ERR "%s: No suitable password found for authentication", p->p.name);
83       return;
84     }
85 
86     /* Perhaps use random value to prevent replay attacks after
87        reboot when system does not have independent RTC? */
88     if (!ifa->csn)
89     {
90       ifa->csn = (u32) (current_real_time() TO_S);
91       ifa->csn_use = current_time();
92     }
93 
94     /* We must have sufficient delay between sending a packet and increasing
95        CSN to prevent reordering of packets (in a network) with different CSNs */
96     if ((current_time() - ifa->csn_use) > 1 S)
97       ifa->csn++;
98 
99     ifa->csn_use = current_time();
100 
101     uint auth_len = mac_type_length(pass->alg);
102     byte *auth_tail = ((byte *) pkt + *plen);
103     *plen += auth_len;
104 
105     ASSERT(*plen < ifa->sk->tbsize);
106 
107     auth->c32.zero = 0;
108     auth->c32.keyid = pass->id;
109     auth->c32.len = auth_len;
110     auth->c32.csn = htonl(ifa->csn);
111 
112     /* Append key for keyed hash, append padding for HMAC (RFC 5709 3.3) */
113     if (pass->alg < ALG_HMAC)
114       strncpy(auth_tail, pass->password, auth_len);
115     else
116       memset32(auth_tail, HMAC_MAGIC, auth_len / 4);
117 
118     mac_fill(pass->alg, pass->password, pass->length, (byte *) pkt, *plen, auth_tail);
119     break;
120 
121   default:
122     bug("Unknown authentication type");
123   }
124 }
125 
126 /*
127  * Return an extra packet size that should be added to a final packet size
128  */
129 static void
ospf_pkt_finalize3(struct ospf_iface * ifa,struct ospf_packet * pkt,uint * plen,ip_addr src)130 ospf_pkt_finalize3(struct ospf_iface *ifa, struct ospf_packet *pkt, uint *plen, ip_addr src)
131 {
132   struct ospf_proto *p = ifa->oa->po;
133   struct ospf_auth3 *auth = (void *) ((byte *) pkt + *plen);
134 
135   pkt->checksum = 0;
136   pkt->autype = 0;
137 
138   if (ifa->autype != OSPF_AUTH_CRYPT)
139     return;
140 
141   struct password_item *pass = password_find(ifa->passwords, 0);
142   if (!pass)
143   {
144     log(L_ERR "%s: No suitable password found for authentication", p->p.name);
145     return;
146   }
147 
148   /* FIXME: Ensure persistence */
149   p->csn64++;
150 
151   uint mac_len = mac_type_length(pass->alg);
152   uint auth_len = sizeof(struct ospf_auth3) + mac_len;
153   *plen += auth_len;
154 
155   ASSERT(*plen < ifa->sk->tbsize);
156 
157   memset(auth, 0, sizeof(struct ospf_auth3));
158   auth->type = htons(OSPF3_AUTH_HMAC);
159   auth->length = htons(auth_len);
160   auth->reserved = 0;
161   auth->sa_id = htons(pass->id);
162   put_u64(&auth->csn, p->csn64);
163 
164   /* Initialize with src IP address padded with HMAC_MAGIC */
165   put_ip6(auth->data, ipa_to_ip6(src));
166   memset32(auth->data + 16, HMAC_MAGIC, (mac_len - 16) / 4);
167 
168   /* Attach OSPFv3 Cryptographic Protocol ID to the key */
169   uint pass_len = pass->length + 2;
170   byte *pass_key = alloca(pass_len);
171   memcpy(pass_key, pass->password, pass->length);
172   put_u16(pass_key + pass->length, OSPF3_CRYPTO_ID);
173 
174   mac_fill(pass->alg, pass_key, pass_len, (byte *) pkt, *plen, auth->data);
175 }
176 
177 
178 static int
ospf_pkt_checkauth2(struct ospf_neighbor * n,struct ospf_iface * ifa,struct ospf_packet * pkt,uint len)179 ospf_pkt_checkauth2(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, uint len)
180 {
181   struct ospf_proto *p = ifa->oa->po;
182   union ospf_auth2 *auth = (void *) (pkt + 1);
183   struct password_item *pass = NULL;
184   const char *err_dsc = NULL;
185   uint err_val = 0;
186 
187   uint plen = ntohs(pkt->length);
188   u8 autype = pkt->autype;
189 
190   if (autype != ifa->autype)
191     DROP("authentication method mismatch", autype);
192 
193   switch (autype)
194   {
195   case OSPF_AUTH_NONE:
196     return 1;
197 
198   case OSPF_AUTH_SIMPLE:
199     pass = password_find(ifa->passwords, 1);
200     if (!pass)
201       DROP1("no password found");
202 
203     if (!password_verify(pass, auth->password, sizeof(auth->password)))
204       DROP("wrong password", pass->id);
205 
206     return 1;
207 
208   case OSPF_AUTH_CRYPT:
209     pass = password_find_by_id(ifa->passwords, auth->c32.keyid);
210     if (!pass)
211       DROP("no suitable password found", auth->c32.keyid);
212 
213     uint auth_len = mac_type_length(pass->alg);
214 
215     if (plen + auth->c32.len > len)
216       DROP("packet length mismatch", len);
217 
218     if (auth->c32.len != auth_len)
219       DROP("wrong authentication length", auth->c32.len);
220 
221     u32 rcv_csn = ntohl(auth->c32.csn);
222     if (n && (rcv_csn < n->csn))
223       // DROP("lower sequence number", rcv_csn);
224     {
225       /* We want to report both new and old CSN */
226       LOG_PKT_AUTH("Authentication failed for nbr %R on %s - "
227 		   "lower sequence number (rcv %u, old %u)",
228 		   n->rid, ifa->ifname, rcv_csn, n->csn);
229       return 0;
230     }
231 
232     byte *auth_tail = ((byte *) pkt) + plen;
233     byte *auth_data = alloca(auth_len);
234     memcpy(auth_data, auth_tail, auth_len);
235 
236     /* Append key for keyed hash, append padding for HMAC (RFC 5709 3.3) */
237     if (pass->alg < ALG_HMAC)
238       strncpy(auth_tail, pass->password, auth_len);
239     else
240       memset32(auth_tail, HMAC_MAGIC, auth_len / 4);
241 
242     if (!mac_verify(pass->alg, pass->password, pass->length,
243 		    (byte *) pkt, plen + auth_len, auth_data))
244       DROP("wrong authentication code", pass->id);
245 
246     if (n)
247       n->csn = rcv_csn;
248 
249     return 1;
250 
251   default:
252     bug("Unknown authentication type");
253   }
254 
255 drop:
256   LOG_PKT_AUTH("Authentication failed for nbr %R on %s - %s (%u)",
257 	       (n ? n->rid : ntohl(pkt->routerid)), ifa->ifname, err_dsc, err_val);
258 
259   return 0;
260 }
261 
262 static int
ospf_pkt_checkauth3(struct ospf_neighbor * n,struct ospf_iface * ifa,struct ospf_packet * pkt,uint len,ip_addr src)263 ospf_pkt_checkauth3(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, uint len, ip_addr src)
264 {
265   struct ospf_proto *p = ifa->oa->po;
266   const char *err_dsc = NULL;
267   uint err_val = 0;
268 
269   uint plen = ntohs(pkt->length);
270   uint opts, lls_present, auth_present;
271 
272   /*
273    * When autentication is not enabled, ignore the trailer. This is different
274    * from OSPFv2, but it is necessary in order to support migration modes. Note
275    * that regular authenticated packets do not have valid checksum and will be
276    * dropped by OS on non-authenticated ifaces.
277    */
278   if (ifa->autype != OSPF_AUTH_CRYPT)
279     return 1;
280 
281   switch(pkt->type)
282   {
283   case HELLO_P:
284     opts = ospf_hello3_options(pkt);
285     lls_present = opts & OPT_L_V3;
286     auth_present = opts & OPT_AT;
287     break;
288 
289   case DBDES_P:
290     opts = ospf_dbdes3_options(pkt);
291     lls_present = opts & OPT_L_V3;
292     auth_present = opts & OPT_AT;
293     break;
294 
295   default:
296     lls_present = 0;
297     auth_present = n->options & OPT_AT;
298   }
299 
300   if (!auth_present)
301     DROP1("missing authentication trailer");
302 
303   if (lls_present)
304   {
305     if ((plen + sizeof(struct ospf_lls)) > len)
306       DROP("packet length mismatch", len);
307 
308     struct ospf_lls *lls = (void *) ((byte *) pkt + plen);
309     plen += ntohs(lls->length);
310   }
311 
312   if ((plen + sizeof(struct ospf_auth3)) > len)
313     DROP("packet length mismatch", len);
314 
315   struct ospf_auth3 *auth = (void *) ((byte *) pkt + plen);
316 
317   uint rcv_auth_type = ntohs(auth->type);
318   if (rcv_auth_type != OSPF3_AUTH_HMAC)
319     DROP("authentication method mismatch", rcv_auth_type);
320 
321   uint rcv_auth_len = ntohs(auth->length);
322   if (plen + rcv_auth_len > len)
323     DROP("packet length mismatch", len);
324 
325   uint rcv_key_id = ntohs(auth->sa_id);
326   struct password_item *pass = password_find_by_id(ifa->passwords, rcv_key_id);
327   if (!pass)
328     DROP("no suitable password found", rcv_key_id);
329 
330   uint mac_len = mac_type_length(pass->alg);
331   if (rcv_auth_len != (sizeof(struct ospf_auth3) + mac_len))
332     DROP("wrong authentication length", rcv_auth_len);
333 
334   uint pt = pkt->type - 1;
335   u64 rcv_csn = get_u64(&auth->csn);
336   if (n && (rcv_csn <= n->csn64[pt]))
337   {
338     /* We want to report both new and old CSN */
339     LOG_PKT_AUTH("Authentication failed for nbr %R on %s - "
340 		 "lower sequence number (rcv %u, old %u)",
341 		 n->rid, ifa->ifname, (uint) rcv_csn, (uint) n->csn64[pt]);
342     return 0;
343   }
344 
345   /* Save the received authentication data */
346   byte *auth_data = alloca(mac_len);
347   memcpy(auth_data, auth->data, mac_len);
348 
349   /* Initialize with src IP address padded with HMAC_MAGIC */
350   put_ip6(auth->data, ipa_to_ip6(src));
351   memset32(auth->data + 16, HMAC_MAGIC, (mac_len - 16) / 4);
352 
353   /* Attach OSPFv3 Cryptographic Protocol ID to the key */
354   uint pass_len = pass->length + 2;
355   byte *pass_key = alloca(pass_len);
356   memcpy(pass_key, pass->password, pass->length);
357   put_u16(pass_key + pass->length, OSPF3_CRYPTO_ID);
358 
359   if (!mac_verify(pass->alg, pass_key, pass_len,
360 		  (byte *) pkt, plen + rcv_auth_len, auth_data))
361     DROP("wrong authentication code", pass->id);
362 
363   if (n)
364     n->csn64[pt] = rcv_csn;
365 
366   return 1;
367 
368 drop:
369   LOG_PKT_AUTH("Authentication failed for nbr %R on %s - %s (%u)",
370 	       (n ? n->rid : ntohl(pkt->routerid)), ifa->ifname, err_dsc, err_val);
371 
372   return 0;
373 }
374 
375 /**
376  * ospf_rx_hook
377  * @sk: socket we received the packet.
378  * @len: length of the packet
379  *
380  * This is the entry point for messages from neighbors. Many checks (like
381  * authentication, checksums, size) are done before the packet is passed to
382  * non generic functions.
383  */
384 int
ospf_rx_hook(sock * sk,uint len)385 ospf_rx_hook(sock *sk, uint len)
386 {
387   /* We want just packets from sk->iface. Unfortunately, on BSD we cannot filter
388      out other packets at kernel level and we receive all packets on all sockets */
389   if (sk->lifindex != sk->iface->index)
390     return 1;
391 
392   DBG("OSPF: RX hook called (iface %s, src %I, dst %I)\n",
393       sk->iface->name, sk->faddr, sk->laddr);
394 
395   /* Initially, the packet is associated with the 'master' iface */
396   struct ospf_iface *ifa = sk->data;
397   struct ospf_proto *p = ifa->oa->po;
398   const char *err_dsc = NULL;
399   uint err_val = 0;
400 
401   /* Should not happen */
402   if (ifa->state <= OSPF_IS_LOOP)
403     return 1;
404 
405   int src_local, dst_local, dst_mcast;
406   src_local = ipa_in_netX(sk->faddr, &ifa->addr->prefix);
407   dst_local = ipa_equal(sk->laddr, ifa->addr->ip);
408   dst_mcast = ipa_equal(sk->laddr, ifa->all_routers) || ipa_equal(sk->laddr, ifa->des_routers);
409 
410   if (ospf_is_v2(p))
411   {
412     /* First, we eliminate packets with strange address combinations.
413      * In OSPFv2, they might be for other ospf_ifaces (with different IP
414      * prefix) on the same real iface, so we don't log it. We enforce
415      * that (src_local || dst_local), therefore we are eliminating all
416      * such cases.
417      */
418     if (dst_mcast && !src_local)
419       return 1;
420     if (!dst_mcast && !dst_local)
421       return 1;
422 
423     /* Ignore my own broadcast packets */
424     if (ifa->cf->real_bcast && ipa_equal(sk->faddr, ifa->addr->ip))
425       return 1;
426   }
427   else
428   {
429     /* In OSPFv3, src_local and dst_local mean link-local.
430      * RFC 5340 says that local (non-vlink) packets use
431      * link-local src address, but does not enforce it. Strange.
432      */
433     if (dst_mcast && !src_local)
434       LOG_PKT_WARN("Multicast packet received from non-link-local %I via %s",
435 		   sk->faddr, ifa->ifname);
436   }
437 
438   /* Second, we check packet length, checksum, and the protocol version */
439   struct ospf_packet *pkt = (void *) sk_rx_buffer(sk, &len);
440 
441 
442   if (pkt == NULL)
443     DROP("bad IP header", len);
444 
445   if (len < sizeof(struct ospf_packet))
446     DROP("too short", len);
447 
448   if (pkt->version != ospf_get_version(p))
449     DROP("version mismatch", pkt->version);
450 
451   uint plen = ntohs(pkt->length);
452   uint hlen = sizeof(struct ospf_packet) + (ospf_is_v2(p) ? sizeof(union ospf_auth2) : 0);
453   if ((plen < hlen) || ((plen % 4) != 0))
454     DROP("invalid length", plen);
455 
456   if (sk->flags & SKF_TRUNCATED)
457   {
458     /* If we have dynamic buffers and received truncated message, we expand RX buffer */
459 
460     uint bs = plen + 256;
461     bs = BIRD_ALIGN(bs, 1024);
462 
463     if (!ifa->cf->rx_buffer && (bs > sk->rbsize))
464       sk_set_rbsize(sk, bs);
465 
466     DROP("truncated", plen);
467   }
468 
469   if (plen > len)
470     DROP("length mismatch", plen);
471 
472   if (ospf_is_v2(p) && (pkt->autype != OSPF_AUTH_CRYPT))
473   {
474     void *body = ((void *) pkt) + hlen;
475     uint blen = plen - hlen;
476 
477     if (!ipsum_verify(pkt, sizeof(struct ospf_packet), body, blen, NULL))
478       DROP("invalid checksum", ntohs(pkt->checksum));
479   }
480 
481   /* Third, we resolve associated iface and handle vlinks. */
482 
483   u32 areaid = ntohl(pkt->areaid);
484   u32 rid = ntohl(pkt->routerid);
485   u8 instance_id = pkt->instance_id;
486 
487   if (areaid == ifa->oa->areaid)
488   {
489     /* Matching area ID */
490 
491     if (instance_id != ifa->instance_id)
492       return 1;
493 
494     /* It is real iface, source should be local (in OSPFv2) */
495     if (ospf_is_v2(p) && !src_local)
496       DROP1("strange source address");
497 
498     goto found;
499   }
500   else if ((areaid == 0) && !dst_mcast)
501   {
502     /* Backbone area ID and possible vlink packet */
503 
504     if ((p->areano == 1) || !oa_is_ext(ifa->oa))
505       return 1;
506 
507     struct ospf_iface *iff = NULL;
508     WALK_LIST(iff, p->iface_list)
509     {
510       if ((iff->type == OSPF_IT_VLINK) &&
511 	  (iff->voa == ifa->oa) &&
512 	  (iff->instance_id == instance_id) &&
513 	  (iff->vid == rid))
514       {
515 	/* Vlink should be UP */
516 	if (iff->state != OSPF_IS_PTP)
517 	  return 1;
518 
519 	ifa = iff;
520 	goto found;
521       }
522     }
523 
524     /*
525      * Cannot find matching vlink. It is either misconfigured vlink; NBMA or
526      * PtMP with misconfigured area ID, or packet for some other instance (that
527      * is possible even if instance_id == ifa->instance_id, because it may be
528      * also vlink packet in the other instance, which is different namespace).
529      */
530 
531     return 1;
532   }
533   else
534   {
535     /* Non-matching area ID but cannot be vlink packet */
536 
537     if (instance_id != ifa->instance_id)
538       return 1;
539 
540     DROP("area mismatch", areaid);
541   }
542 
543 
544 found:
545   if (ifa->stub)	    /* This shouldn't happen */
546     return 1;
547 
548   if (ipa_equal(sk->laddr, ifa->des_routers) && (ifa->sk_dr == 0))
549     return 1;
550 
551   /* TTL check must be done after instance dispatch */
552   if (ifa->check_ttl && (sk->rcv_ttl < 255))
553     DROP("wrong TTL", sk->rcv_ttl);
554 
555   if (rid == p->router_id)
556     DROP1("my own router ID");
557 
558   if (rid == 0)
559     DROP1("zero router ID");
560 
561   /* Check packet type here, ospf_pkt_checkauth3() expects valid values */
562   if (pkt->type < HELLO_P || pkt->type > LSACK_P)
563     DROP("invalid packet type", pkt->type);
564 
565   /* In OSPFv2, neighbors are identified by either IP or Router ID, based on network type */
566   uint t = ifa->type;
567   struct ospf_neighbor *n;
568   if (ospf_is_v2(p) && ((t == OSPF_IT_BCAST) || (t == OSPF_IT_NBMA) || (t == OSPF_IT_PTMP)))
569     n = find_neigh_by_ip(ifa, sk->faddr);
570   else
571     n = find_neigh(ifa, rid);
572 
573   if (!n && (pkt->type != HELLO_P))
574   {
575     OSPF_TRACE(D_PACKETS, "Non-HELLO packet received from unknown nbr %R on %s, src %I",
576 	       rid, ifa->ifname, sk->faddr);
577     return 1;
578   }
579 
580   /* We need to ignore out-of-state packets before ospf_pkt_checkauth3() */
581   if ((pkt->type > DBDES_P) && (n->state < NEIGHBOR_EXCHANGE))
582   {
583     OSPF_TRACE(D_PACKETS, "%s packet ignored - lesser state than Exchange",
584 	       ospf_pkt_names[pkt->type]);
585     return 1;
586   }
587 
588   /* ospf_pkt_checkauthX() has its own error logging */
589   if ((ospf_is_v2(p) ?
590        !ospf_pkt_checkauth2(n, ifa, pkt, len) :
591        !ospf_pkt_checkauth3(n, ifa, pkt, len, sk->faddr)))
592     return 1;
593 
594   switch (pkt->type)
595   {
596   case HELLO_P:
597     ospf_receive_hello(pkt, ifa, n, sk->faddr);
598     break;
599 
600   case DBDES_P:
601     ospf_receive_dbdes(pkt, ifa, n);
602     break;
603 
604   case LSREQ_P:
605     ospf_receive_lsreq(pkt, ifa, n);
606     break;
607 
608   case LSUPD_P:
609     ospf_receive_lsupd(pkt, ifa, n);
610     break;
611 
612   case LSACK_P:
613     ospf_receive_lsack(pkt, ifa, n);
614     break;
615   };
616   return 1;
617 
618 drop:
619   LOG_PKT("Bad packet from %I via %s - %s (%u)",
620 	  sk->faddr, ifa->ifname, err_dsc, err_val);
621 
622   return 1;
623 }
624 
625 /*
626 void
627 ospf_tx_hook(sock * sk)
628 {
629   struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
630 //  struct proto *p = (struct proto *) (ifa->oa->p);
631   log(L_ERR "OSPF: TX hook called on %s", ifa->ifname);
632 }
633 */
634 
635 void
ospf_err_hook(sock * sk,int err)636 ospf_err_hook(sock * sk, int err)
637 {
638   struct ospf_iface *ifa = (struct ospf_iface *) (sk->data);
639   struct ospf_proto *p = ifa->oa->po;
640   log(L_ERR "%s: Socket error on %s: %M", p->p.name, ifa->ifname, err);
641 }
642 
643 void
ospf_verr_hook(sock * sk,int err)644 ospf_verr_hook(sock *sk, int err)
645 {
646   struct ospf_proto *p = (struct ospf_proto *) (sk->data);
647   log(L_ERR "%s: Vlink socket error: %M", p->p.name, err);
648 }
649 
650 void
ospf_send_to(struct ospf_iface * ifa,ip_addr dst)651 ospf_send_to(struct ospf_iface *ifa, ip_addr dst)
652 {
653   sock *sk = ifa->sk;
654   struct ospf_packet *pkt = (struct ospf_packet *) sk->tbuf;
655   uint plen = ntohs(pkt->length);
656 
657   if (ospf_is_v2(ifa->oa->po))
658     ospf_pkt_finalize2(ifa, pkt, &plen);
659   else
660     ospf_pkt_finalize3(ifa, pkt, &plen, sk->saddr);
661 
662   int done = sk_send_to(sk, plen, dst, 0);
663   if (!done)
664     log(L_WARN "OSPF: TX queue full on %s", ifa->ifname);
665 }
666 
667 void
ospf_send_to_agt(struct ospf_iface * ifa,u8 state)668 ospf_send_to_agt(struct ospf_iface *ifa, u8 state)
669 {
670   struct ospf_neighbor *n;
671 
672   WALK_LIST(n, ifa->neigh_list)
673     if (n->state >= state)
674       ospf_send_to(ifa, n->ip);
675 }
676 
677 void
ospf_send_to_bdr(struct ospf_iface * ifa)678 ospf_send_to_bdr(struct ospf_iface *ifa)
679 {
680   if (ipa_nonzero2(ifa->drip))
681     ospf_send_to(ifa, ifa->drip);
682   if (ipa_nonzero2(ifa->bdrip))
683     ospf_send_to(ifa, ifa->bdrip);
684 }
685