Import Upstream version 1.2.2
[quagga-debian.git] / pimd / pim_pim.c
1 /*
2   PIM for Quagga
3   Copyright (C) 2008  Everton da Silva Marques
4
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 2 of the License, or
8   (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful, but
11   WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   General Public License for more details.
14   
15   You should have received a copy of the GNU General Public License
16   along with this program; see the file COPYING; if not, write to the
17   Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
18   MA 02110-1301 USA
19   
20   $QuaggaId: $Format:%an, %ai, %h$ $
21 */
22
23 #include <zebra.h>
24
25 #include "log.h"
26 #include "thread.h"
27 #include "memory.h"
28
29 #include "pimd.h"
30 #include "pim_pim.h"
31 #include "pim_time.h"
32 #include "pim_iface.h"
33 #include "pim_sock.h"
34 #include "pim_str.h"
35 #include "pim_util.h"
36 #include "pim_tlv.h"
37 #include "pim_neighbor.h"
38 #include "pim_hello.h"
39 #include "pim_join.h"
40 #include "pim_assert.h"
41 #include "pim_msg.h"
42
43 static int on_pim_hello_send(struct thread *t);
44 static int pim_hello_send(struct interface *ifp,
45                           uint16_t holdtime);
46
47 static void sock_close(struct interface *ifp)
48 {
49   struct pim_interface *pim_ifp = ifp->info;
50
51   if (PIM_DEBUG_PIM_TRACE) {
52     if (pim_ifp->t_pim_sock_read) {
53       zlog_debug("Cancelling READ event for PIM socket fd=%d on interface %s",
54                  pim_ifp->pim_sock_fd,
55                  ifp->name);
56     }
57   }
58   THREAD_OFF(pim_ifp->t_pim_sock_read);
59
60   if (PIM_DEBUG_PIM_TRACE) {
61     if (pim_ifp->t_pim_hello_timer) {
62       zlog_debug("Cancelling PIM hello timer for interface %s",
63                  ifp->name);
64     }
65   }
66   THREAD_OFF(pim_ifp->t_pim_hello_timer);
67
68   if (PIM_DEBUG_PIM_TRACE) {
69     zlog_debug("Deleting PIM socket fd=%d on interface %s",
70                pim_ifp->pim_sock_fd, ifp->name);
71   }
72
73   if (close(pim_ifp->pim_sock_fd)) {
74     zlog_warn("Failure closing PIM socket fd=%d on interface %s: errno=%d: %s",
75               pim_ifp->pim_sock_fd, ifp->name,
76               errno, safe_strerror(errno));
77   }
78   
79   pim_ifp->pim_sock_fd = -1;
80   pim_ifp->pim_sock_creation = 0;
81
82   zassert(pim_ifp->pim_sock_fd < 0);
83   zassert(!pim_ifp->t_pim_sock_read);
84   zassert(!pim_ifp->t_pim_hello_timer);
85   zassert(!pim_ifp->pim_sock_creation);
86 }
87
88 void pim_sock_delete(struct interface *ifp, const char *delete_message)
89 {
90   zlog_info("PIM INTERFACE DOWN: on interface %s: %s",
91             ifp->name, delete_message);
92
93   if (!ifp->info) {
94     zlog_err("%s: %s: but PIM not enabled on interface %s (!)",
95              __PRETTY_FUNCTION__, delete_message, ifp->name);
96     return;
97   }
98
99   /*
100     RFC 4601: 4.3.1.  Sending Hello Messages
101     
102     Before an interface goes down or changes primary IP address, a Hello
103     message with a zero HoldTime should be sent immediately (with the
104     old IP address if the IP address changed).
105   */
106   pim_hello_send(ifp, 0 /* zero-sec holdtime */);
107
108   pim_neighbor_delete_all(ifp, delete_message);
109
110   sock_close(ifp);
111 }
112
113 int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len)
114 {
115   struct ip *ip_hdr;
116   size_t ip_hlen; /* ip header length in bytes */
117   char src_str[100];
118   char dst_str[100];
119   uint8_t *pim_msg;
120   int pim_msg_len;
121   uint8_t pim_version;
122   uint8_t pim_type;
123   uint16_t pim_checksum; /* received checksum */
124   uint16_t checksum;     /* computed checksum */
125   struct pim_neighbor *neigh;
126
127   if (!ifp->info) {
128     zlog_warn("%s: PIM not enabled on interface %s",
129               __PRETTY_FUNCTION__, ifp->name);
130     return -1;
131   }
132     
133   if (len < sizeof(*ip_hdr)) {
134     zlog_warn("PIM packet size=%zu shorter than minimum=%zu",
135               len, sizeof(*ip_hdr));
136     return -1;
137   }
138
139   ip_hdr = (struct ip *) buf;
140
141   pim_inet4_dump("<src?>", ip_hdr->ip_src, src_str, sizeof(src_str));
142   pim_inet4_dump("<dst?>", ip_hdr->ip_dst, dst_str, sizeof(dst_str));
143
144   ip_hlen = ip_hdr->ip_hl << 2; /* ip_hl gives length in 4-byte words */
145
146   if (PIM_DEBUG_PIM_PACKETS) {
147     zlog_debug("Recv IP packet from %s to %s on %s: size=%zu ip_header_size=%zu ip_proto=%d",
148                src_str, dst_str, ifp->name, len, ip_hlen, ip_hdr->ip_p);
149   }
150
151   if (ip_hdr->ip_p != PIM_IP_PROTO_PIM) {
152     zlog_warn("IP packet protocol=%d is not PIM=%d",
153               ip_hdr->ip_p, PIM_IP_PROTO_PIM);
154     return -1;
155   }
156
157   if (ip_hlen < PIM_IP_HEADER_MIN_LEN) {
158     zlog_warn("IP packet header size=%zu shorter than minimum=%d",
159               ip_hlen, PIM_IP_HEADER_MIN_LEN);
160     return -1;
161   }
162   if (ip_hlen > PIM_IP_HEADER_MAX_LEN) {
163     zlog_warn("IP packet header size=%zu greater than maximum=%d",
164               ip_hlen, PIM_IP_HEADER_MAX_LEN);
165     return -1;
166   }
167
168   pim_msg = buf + ip_hlen;
169   pim_msg_len = len - ip_hlen;
170
171   if (PIM_DEBUG_PIM_PACKETDUMP_RECV) {
172     pim_pkt_dump(__PRETTY_FUNCTION__, pim_msg, pim_msg_len);
173   }
174
175   if (pim_msg_len < PIM_PIM_MIN_LEN) {
176     zlog_warn("PIM message size=%d shorter than minimum=%d",
177               pim_msg_len, PIM_PIM_MIN_LEN);
178     return -1;
179   }
180
181   pim_version = PIM_MSG_HDR_GET_VERSION(pim_msg);
182   pim_type    = PIM_MSG_HDR_GET_TYPE(pim_msg);
183
184   if (pim_version != PIM_PROTO_VERSION) {
185     zlog_warn("Ignoring PIM pkt from %s with unsupported version: %d",
186               ifp->name, pim_version);
187     return -1;
188   }
189
190   /* save received checksum */
191   pim_checksum = PIM_MSG_HDR_GET_CHECKSUM(pim_msg);
192
193   /* for computing checksum */
194   *(uint16_t *) PIM_MSG_HDR_OFFSET_CHECKSUM(pim_msg) = 0;
195
196   checksum = in_cksum(pim_msg, pim_msg_len);
197   if (checksum != pim_checksum) {
198     zlog_warn("Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x",
199               ifp->name, pim_checksum, checksum);
200     return -1;
201   }
202
203   if (PIM_DEBUG_PIM_PACKETS) {
204     zlog_debug("Recv PIM packet from %s to %s on %s: ttl=%d pim_version=%d pim_type=%d pim_msg_size=%d checksum=%x",
205                src_str, dst_str, ifp->name, ip_hdr->ip_ttl,
206                pim_version, pim_type, pim_msg_len, checksum);
207   }
208
209   if (pim_type == PIM_MSG_TYPE_REGISTER  ||
210       pim_type == PIM_MSG_TYPE_REG_STOP  ||
211       pim_type == PIM_MSG_TYPE_BOOTSTRAP ||
212       pim_type == PIM_MSG_TYPE_GRAFT     ||
213       pim_type == PIM_MSG_TYPE_GRAFT_ACK ||
214       pim_type == PIM_MSG_TYPE_CANDIDATE)
215     {
216       if (PIM_DEBUG_PIM_PACKETS) {
217         zlog_debug("Recv PIM packet type %d which is not currently understood",
218                    pim_type);
219       }
220       return -1;
221     }
222
223   if (pim_type == PIM_MSG_TYPE_HELLO) {
224     int result = pim_hello_recv(ifp,
225                  ip_hdr->ip_src,
226                  pim_msg + PIM_MSG_HEADER_LEN,
227                  pim_msg_len - PIM_MSG_HEADER_LEN);
228     return result;
229   }
230
231   neigh = pim_neighbor_find(ifp, ip_hdr->ip_src);
232   if (!neigh) {
233     zlog_warn("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s",
234               __FILE__, __PRETTY_FUNCTION__,
235               pim_type, src_str, ifp->name);
236     return -1;
237   }
238
239   switch (pim_type) {
240   case PIM_MSG_TYPE_JOIN_PRUNE:
241     return pim_joinprune_recv(ifp, neigh,
242                               ip_hdr->ip_src,
243                               pim_msg + PIM_MSG_HEADER_LEN,
244                               pim_msg_len - PIM_MSG_HEADER_LEN);
245   case PIM_MSG_TYPE_ASSERT:
246     return pim_assert_recv(ifp, neigh,
247                            ip_hdr->ip_src,
248                            pim_msg + PIM_MSG_HEADER_LEN,
249                            pim_msg_len - PIM_MSG_HEADER_LEN);
250   default:
251     zlog_warn("%s %s: unsupported PIM message type=%d from %s on %s",
252               __FILE__, __PRETTY_FUNCTION__,
253               pim_type, src_str, ifp->name);
254   }
255
256   return -1;
257 }
258
259 static void pim_sock_read_on(struct interface *ifp);
260
261 static int pim_sock_read(struct thread *t)
262 {
263   struct interface *ifp;
264   struct pim_interface *pim_ifp;
265   int fd;
266   struct sockaddr_in from;
267   struct sockaddr_in to;
268   socklen_t fromlen = sizeof(from);
269   socklen_t tolen = sizeof(to);
270   uint8_t buf[PIM_PIM_BUFSIZE_READ];
271   int len;
272   ifindex_t ifindex = -1;
273   int result = -1; /* defaults to bad */
274
275   zassert(t);
276
277   ifp = THREAD_ARG(t);
278   zassert(ifp);
279
280   fd = THREAD_FD(t);
281
282   pim_ifp = ifp->info;
283   zassert(pim_ifp);
284
285   zassert(fd == pim_ifp->pim_sock_fd);
286
287   len = pim_socket_recvfromto(fd, buf, sizeof(buf),
288                               &from, &fromlen,
289                               &to, &tolen,
290                               &ifindex);
291   if (len < 0) {
292     zlog_warn("Failure receiving IP PIM packet on fd=%d: errno=%d: %s",
293               fd, errno, safe_strerror(errno));
294     goto done;
295   }
296
297   if (PIM_DEBUG_PIM_PACKETS) {
298     char from_str[100];
299     char to_str[100];
300     
301     if (!inet_ntop(AF_INET, &from.sin_addr, from_str, sizeof(from_str)))
302       sprintf(from_str, "<from?>");
303     if (!inet_ntop(AF_INET, &to.sin_addr, to_str, sizeof(to_str)))
304       sprintf(to_str, "<to?>");
305     
306     zlog_debug("Recv IP PIM pkt size=%d from %s to %s on fd=%d on ifindex=%d (sock_ifindex=%d)",
307                len, from_str, to_str, fd, ifindex, ifp->ifindex);
308   }
309
310   if (PIM_DEBUG_PIM_PACKETDUMP_RECV) {
311     pim_pkt_dump(__PRETTY_FUNCTION__, buf, len);
312   }
313
314 #ifdef PIM_CHECK_RECV_IFINDEX_SANITY
315   /* ifindex sanity check */
316   if (ifindex != (int) ifp->ifindex) {
317     char from_str[100];
318     char to_str[100];
319     struct interface *recv_ifp;
320
321     if (!inet_ntop(AF_INET, &from.sin_addr, from_str , sizeof(from_str)))
322       sprintf(from_str, "<from?>");
323     if (!inet_ntop(AF_INET, &to.sin_addr, to_str , sizeof(to_str)))
324       sprintf(to_str, "<to?>");
325
326     recv_ifp = if_lookup_by_index(ifindex);
327     if (recv_ifp) {
328       zassert(ifindex == (int) recv_ifp->ifindex);
329     }
330
331 #ifdef PIM_REPORT_RECV_IFINDEX_MISMATCH
332     zlog_warn("Interface mismatch: recv PIM pkt from %s to %s on fd=%d: recv_ifindex=%d (%s) sock_ifindex=%d (%s)",
333               from_str, to_str, fd,
334               ifindex, recv_ifp ? recv_ifp->name : "<if-notfound>",
335               ifp->ifindex, ifp->name);
336 #endif
337     goto done;
338   }
339 #endif
340
341   int fail = pim_pim_packet(ifp, buf, len);
342   if (fail) {
343     zlog_warn("%s: pim_pim_packet() return=%d",
344               __PRETTY_FUNCTION__, fail);
345     goto done;
346   }
347
348   result = 0; /* good */
349
350  done:
351   pim_sock_read_on(ifp);
352
353   if (result) {
354     ++pim_ifp->pim_ifstat_hello_recvfail;
355   }
356
357   return result;
358 }
359
360 static void pim_sock_read_on(struct interface *ifp)
361 {
362   struct pim_interface *pim_ifp;
363
364   zassert(ifp);
365   zassert(ifp->info);
366
367   pim_ifp = ifp->info;
368
369   if (PIM_DEBUG_PIM_TRACE) {
370     zlog_debug("Scheduling READ event on PIM socket fd=%d",
371                pim_ifp->pim_sock_fd);
372   }
373   pim_ifp->t_pim_sock_read = 0;
374   zassert(!pim_ifp->t_pim_sock_read);
375   THREAD_READ_ON(master, pim_ifp->t_pim_sock_read, pim_sock_read, ifp,
376                  pim_ifp->pim_sock_fd);
377 }
378
379 static int pim_sock_open(struct in_addr ifaddr, ifindex_t ifindex)
380 {
381   int fd;
382
383   fd = pim_socket_mcast(IPPROTO_PIM, ifaddr, 0 /* loop=false */);
384   if (fd < 0)
385     return -1;
386
387   if (pim_socket_join(fd, qpim_all_pim_routers_addr, ifaddr, ifindex)) {
388     close(fd);
389     return -2;
390   }
391
392   return fd;
393 }
394
395 void pim_ifstat_reset(struct interface *ifp)
396 {
397   struct pim_interface *pim_ifp;
398
399   zassert(ifp);
400
401   pim_ifp = ifp->info;
402   if (!pim_ifp) {
403     return;
404   }
405
406   pim_ifp->pim_ifstat_start          = pim_time_monotonic_sec();
407   pim_ifp->pim_ifstat_hello_sent     = 0;
408   pim_ifp->pim_ifstat_hello_sendfail = 0;
409   pim_ifp->pim_ifstat_hello_recv     = 0;
410   pim_ifp->pim_ifstat_hello_recvfail = 0;
411 }
412
413 void pim_sock_reset(struct interface *ifp)
414 {
415   struct pim_interface *pim_ifp;
416
417   zassert(ifp);
418   zassert(ifp->info);
419
420   pim_ifp = ifp->info;
421
422   pim_ifp->primary_address = pim_find_primary_addr(ifp);
423
424   pim_ifp->pim_sock_fd       = -1;
425   pim_ifp->pim_sock_creation = 0;
426   pim_ifp->t_pim_sock_read   = 0;
427
428   pim_ifp->t_pim_hello_timer          = 0;
429   pim_ifp->pim_hello_period           = PIM_DEFAULT_HELLO_PERIOD;
430   pim_ifp->pim_default_holdtime       = -1; /* unset: means 3.5 * pim_hello_period */
431   pim_ifp->pim_triggered_hello_delay  = PIM_DEFAULT_TRIGGERED_HELLO_DELAY;
432   pim_ifp->pim_dr_priority            = PIM_DEFAULT_DR_PRIORITY;
433   pim_ifp->pim_propagation_delay_msec = PIM_DEFAULT_PROPAGATION_DELAY_MSEC;
434   pim_ifp->pim_override_interval_msec = PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC;
435   if (PIM_DEFAULT_CAN_DISABLE_JOIN_SUPPRESSION) {
436     PIM_IF_DO_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options);
437   }
438   else {
439     PIM_IF_DONT_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options);
440   }
441
442   /* neighbors without lan_delay */
443   pim_ifp->pim_number_of_nonlandelay_neighbors = 0;
444   pim_ifp->pim_neighbors_highest_propagation_delay_msec = 0;
445   pim_ifp->pim_neighbors_highest_override_interval_msec = 0;
446
447   /* DR Election */
448   pim_ifp->pim_dr_election_last          = 0; /* timestamp */
449   pim_ifp->pim_dr_election_count         = 0;
450   pim_ifp->pim_dr_election_changes       = 0;
451   pim_ifp->pim_dr_num_nondrpri_neighbors = 0; /* neighbors without dr_pri */
452   pim_ifp->pim_dr_addr                   = pim_ifp->primary_address;
453
454   pim_ifstat_reset(ifp);
455 }
456
457 int pim_msg_send(int fd,
458                  struct in_addr dst,
459                  uint8_t *pim_msg,
460                  int pim_msg_size,
461                  const char *ifname)
462 {
463   ssize_t            sent;
464   struct sockaddr_in to;
465   socklen_t          tolen;
466
467   if (PIM_DEBUG_PIM_PACKETS) {
468     char dst_str[100];
469     pim_inet4_dump("<dst?>", dst, dst_str, sizeof(dst_str));
470     zlog_debug("%s: to %s on %s: msg_size=%d checksum=%x",
471                __PRETTY_FUNCTION__,
472                dst_str, ifname, pim_msg_size,
473                *(uint16_t *) PIM_MSG_HDR_OFFSET_CHECKSUM(pim_msg));
474   }
475
476   memset(&to, 0, sizeof(to));
477   to.sin_family = AF_INET;
478   to.sin_addr = dst;
479   tolen = sizeof(to);
480
481   if (PIM_DEBUG_PIM_PACKETDUMP_SEND) {
482     pim_pkt_dump(__PRETTY_FUNCTION__, pim_msg, pim_msg_size);
483   }
484
485   sent = sendto(fd, pim_msg, pim_msg_size, MSG_DONTWAIT,
486                 (struct sockaddr *)&to, tolen);
487   if (sent != (ssize_t) pim_msg_size) {
488     int e = errno;
489     char dst_str[100];
490     pim_inet4_dump("<dst?>", dst, dst_str, sizeof(dst_str));
491     if (sent < 0) {
492       zlog_warn("%s: sendto() failure to %s on %s: fd=%d msg_size=%d: errno=%d: %s",
493                 __PRETTY_FUNCTION__,
494                 dst_str, ifname, fd, pim_msg_size,
495                 e, safe_strerror(e));
496     }
497     else {
498       zlog_warn("%s: sendto() partial to %s on %s: fd=%d msg_size=%d: sent=%zd",
499                 __PRETTY_FUNCTION__,
500                 dst_str, ifname, fd,
501                 pim_msg_size, sent);
502     }
503     return -1;
504   }
505
506   return 0;
507 }
508
509 static int hello_send(struct interface *ifp,
510                       uint16_t holdtime)
511 {
512   uint8_t pim_msg[PIM_PIM_BUFSIZE_WRITE];
513   struct pim_interface *pim_ifp;
514   int pim_tlv_size;
515   int pim_msg_size;
516
517   pim_ifp = ifp->info;
518
519   if (PIM_DEBUG_PIM_HELLO) {
520     char dst_str[100];
521     pim_inet4_dump("<dst?>", qpim_all_pim_routers_addr, dst_str, sizeof(dst_str));
522     zlog_debug("%s: to %s on %s: holdt=%u prop_d=%u overr_i=%u dis_join_supp=%d dr_prio=%u gen_id=%08x addrs=%d",
523                __PRETTY_FUNCTION__,
524                dst_str, ifp->name,
525                holdtime,
526                pim_ifp->pim_propagation_delay_msec, pim_ifp->pim_override_interval_msec,
527                PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options),
528                pim_ifp->pim_dr_priority, pim_ifp->pim_generation_id,
529                listcount(ifp->connected));
530   }
531
532   pim_tlv_size = pim_hello_build_tlv(ifp->name,
533                                      pim_msg + PIM_PIM_MIN_LEN,
534                                      sizeof(pim_msg) - PIM_PIM_MIN_LEN,
535                                      holdtime,
536                                      pim_ifp->pim_dr_priority,
537                                      pim_ifp->pim_generation_id,
538                                      pim_ifp->pim_propagation_delay_msec,
539                                      pim_ifp->pim_override_interval_msec,
540                                      PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options),
541                                      ifp->connected);
542   if (pim_tlv_size < 0) {
543     return -1;
544   }
545
546   pim_msg_size = pim_tlv_size + PIM_PIM_MIN_LEN;
547
548   zassert(pim_msg_size >= PIM_PIM_MIN_LEN);
549   zassert(pim_msg_size <= PIM_PIM_BUFSIZE_WRITE);
550
551   pim_msg_build_header(pim_msg, pim_msg_size,
552                        PIM_MSG_TYPE_HELLO);
553
554   if (pim_msg_send(pim_ifp->pim_sock_fd,
555                    qpim_all_pim_routers_addr,
556                    pim_msg,
557                    pim_msg_size,
558                    ifp->name)) {
559     if (PIM_DEBUG_PIM_HELLO) {
560       zlog_debug("%s: could not send PIM message on interface %s",
561                  __PRETTY_FUNCTION__, ifp->name);
562     }
563     return -2;
564   }
565
566   return 0;
567 }
568
569 static int pim_hello_send(struct interface *ifp,
570                           uint16_t holdtime)
571 {
572   struct pim_interface *pim_ifp;
573
574   zassert(ifp);
575   pim_ifp = ifp->info;
576   zassert(pim_ifp);
577
578   if (hello_send(ifp, holdtime)) {
579     ++pim_ifp->pim_ifstat_hello_sendfail;
580
581     if (PIM_DEBUG_PIM_HELLO) {
582       zlog_warn("Could not send PIM hello on interface %s",
583                 ifp->name);
584     }
585     return -1;
586   }
587
588   ++pim_ifp->pim_ifstat_hello_sent;
589
590   return 0;
591 }
592
593 static void hello_resched(struct interface *ifp)
594 {
595   struct pim_interface *pim_ifp;
596
597   zassert(ifp);
598   pim_ifp = ifp->info;
599   zassert(pim_ifp);
600
601   if (PIM_DEBUG_PIM_HELLO) {
602     zlog_debug("Rescheduling %d sec hello on interface %s",
603                pim_ifp->pim_hello_period, ifp->name);
604   }
605   THREAD_OFF(pim_ifp->t_pim_hello_timer);
606   THREAD_TIMER_ON(master, pim_ifp->t_pim_hello_timer,
607                   on_pim_hello_send,
608                   ifp, pim_ifp->pim_hello_period);
609 }
610
611 /*
612   Periodic hello timer
613  */
614 static int on_pim_hello_send(struct thread *t)
615 {
616   struct pim_interface *pim_ifp;
617   struct interface *ifp;
618
619   zassert(t);
620   ifp = THREAD_ARG(t);
621   zassert(ifp);
622
623   pim_ifp = ifp->info;
624
625   /*
626    * Schedule next hello
627    */
628   pim_ifp->t_pim_hello_timer = 0;
629   hello_resched(ifp);
630
631   /*
632    * Send hello
633    */
634   return pim_hello_send(ifp, PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
635 }
636
637 /*
638   RFC 4601: 4.3.1.  Sending Hello Messages
639
640   Thus, if a router needs to send a Join/Prune or Assert message on an
641   interface on which it has not yet sent a Hello message with the
642   currently configured IP address, then it MUST immediately send the
643   relevant Hello message without waiting for the Hello Timer to
644   expire, followed by the Join/Prune or Assert message.
645  */
646 void pim_hello_restart_now(struct interface *ifp)
647 {
648   struct pim_interface *pim_ifp;
649
650   zassert(ifp);
651   pim_ifp = ifp->info;
652   zassert(pim_ifp);
653
654   /*
655    * Reset next hello timer
656    */
657   hello_resched(ifp);
658
659   /*
660    * Immediately send hello
661    */
662   pim_hello_send(ifp, PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
663 }
664
665 /*
666   RFC 4601: 4.3.1.  Sending Hello Messages
667
668   To allow new or rebooting routers to learn of PIM neighbors quickly,
669   when a Hello message is received from a new neighbor, or a Hello
670   message with a new GenID is received from an existing neighbor, a
671   new Hello message should be sent on this interface after a
672   randomized delay between 0 and Triggered_Hello_Delay.
673  */
674 void pim_hello_restart_triggered(struct interface *ifp)
675 {
676   struct pim_interface *pim_ifp;
677   int triggered_hello_delay_msec;
678   int random_msec;
679
680   zassert(ifp);
681   pim_ifp = ifp->info;
682   zassert(pim_ifp);
683
684   triggered_hello_delay_msec = 1000 * pim_ifp->pim_triggered_hello_delay;
685
686   if (pim_ifp->t_pim_hello_timer) {
687     long remain_msec = pim_time_timer_remain_msec(pim_ifp->t_pim_hello_timer);
688     if (remain_msec <= triggered_hello_delay_msec) {
689       /* Rescheduling hello would increase the delay, then it's faster
690          to just wait for the scheduled periodic hello. */
691       return;
692     }
693
694     THREAD_OFF(pim_ifp->t_pim_hello_timer);
695     pim_ifp->t_pim_hello_timer = 0;
696   }
697   zassert(!pim_ifp->t_pim_hello_timer);
698
699   random_msec = random() % (triggered_hello_delay_msec + 1);
700
701   if (PIM_DEBUG_PIM_HELLO) {
702     zlog_debug("Scheduling %d msec triggered hello on interface %s",
703                random_msec, ifp->name);
704   }
705
706   THREAD_TIMER_MSEC_ON(master, pim_ifp->t_pim_hello_timer,
707                        on_pim_hello_send,
708                        ifp, random_msec);
709 }
710
711 int pim_sock_add(struct interface *ifp)
712 {
713   struct pim_interface *pim_ifp;
714   struct in_addr ifaddr;
715   uint32_t old_genid;
716
717   pim_ifp = ifp->info;
718   zassert(pim_ifp);
719
720   if (pim_ifp->pim_sock_fd >= 0) {
721     zlog_warn("Can't recreate existing PIM socket fd=%d for interface %s",
722               pim_ifp->pim_sock_fd, ifp->name);
723     return -1;
724   }
725
726   ifaddr = pim_ifp->primary_address;
727
728   pim_ifp->pim_sock_fd = pim_sock_open(ifaddr, ifp->ifindex);
729   if (pim_ifp->pim_sock_fd < 0) {
730     zlog_warn("Could not open PIM socket on interface %s",
731               ifp->name);
732     return -2;
733   }
734
735   pim_ifp->t_pim_sock_read   = 0;
736   pim_ifp->pim_sock_creation = pim_time_monotonic_sec();
737
738   /*
739    * Just ensure that the new generation id
740    * actually chooses something different.
741    * Actually ran across a case where this
742    * happened, pre-switch to random().
743    * While this is unlikely to happen now
744    * let's make sure it doesn't.
745    */
746   old_genid = pim_ifp->pim_generation_id;
747
748   while (old_genid == pim_ifp->pim_generation_id)
749     pim_ifp->pim_generation_id = random();
750
751   zlog_info("PIM INTERFACE UP: on interface %s ifindex=%d",
752             ifp->name, ifp->ifindex);
753
754   /*
755    * Start receiving PIM messages
756    */
757   pim_sock_read_on(ifp);
758
759   /*
760    * Start sending PIM hello's
761    */
762   pim_hello_restart_triggered(ifp);
763
764   return 0;
765 }