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 "prefix.h"
27
28#include "pimd.h"
29#include "pim_int.h"
30#include "pim_tlv.h"
31#include "pim_str.h"
32#include "pim_msg.h"
33
34uint8_t *pim_tlv_append_uint16(uint8_t *buf,
35			       const uint8_t *buf_pastend,
36			       uint16_t option_type,
37			       uint16_t option_value)
38{
39  uint16_t option_len = 2;
40
41  if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend) {
42    zlog_warn("%s: buffer overflow: left=%zd needed=%d",
43	      __PRETTY_FUNCTION__,
44	      buf_pastend - buf, PIM_TLV_OPTION_SIZE(option_len));
45    return 0;
46  }
47
48  *(uint16_t *) buf = htons(option_type);
49  buf += 2;
50  *(uint16_t *) buf = htons(option_len);
51  buf += 2;
52  *(uint16_t *) buf = htons(option_value);
53  buf += option_len;
54
55  return buf;
56}
57
58uint8_t *pim_tlv_append_2uint16(uint8_t *buf,
59				const uint8_t *buf_pastend,
60				uint16_t option_type,
61				uint16_t option_value1,
62				uint16_t option_value2)
63{
64  uint16_t option_len = 4;
65
66  if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend) {
67    zlog_warn("%s: buffer overflow: left=%zd needed=%d",
68	      __PRETTY_FUNCTION__,
69	      buf_pastend - buf, PIM_TLV_OPTION_SIZE(option_len));
70    return 0;
71  }
72
73  *(uint16_t *) buf = htons(option_type);
74  buf += 2;
75  *(uint16_t *) buf = htons(option_len);
76  buf += 2;
77  *(uint16_t *) buf = htons(option_value1);
78  buf += 2;
79  *(uint16_t *) buf = htons(option_value2);
80  buf += 2;
81
82  return buf;
83}
84
85uint8_t *pim_tlv_append_uint32(uint8_t *buf,
86			       const uint8_t *buf_pastend,
87			       uint16_t option_type,
88			       uint32_t option_value)
89{
90  uint16_t option_len = 4;
91
92  if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend) {
93    zlog_warn("%s: buffer overflow: left=%zd needed=%d",
94	      __PRETTY_FUNCTION__,
95	      buf_pastend - buf, PIM_TLV_OPTION_SIZE(option_len));
96    return 0;
97  }
98
99  *(uint16_t *) buf = htons(option_type);
100  buf += 2;
101  *(uint16_t *) buf = htons(option_len);
102  buf += 2;
103  pim_write_uint32(buf, option_value);
104  buf += option_len;
105
106  return buf;
107}
108
109#define ucast_ipv4_encoding_len (2 + sizeof(struct in_addr))
110
111uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf,
112				       const uint8_t *buf_pastend,
113				       struct list *ifconnected)
114{
115  struct listnode *node;
116  uint16_t option_len = 0;
117
118  uint8_t *curr;
119
120  node = listhead(ifconnected);
121
122  /* Empty address list ? */
123  if (!node) {
124    return buf;
125  }
126
127  /* Skip first address (primary) */
128  node = listnextnode(node);
129
130  /* Scan secondary address list */
131  curr = buf + 4; /* skip T and L */
132  for (; node; node = listnextnode(node)) {
133    struct connected *ifc = listgetdata(node);
134    struct prefix *p = ifc->address;
135
136    if (p->family != AF_INET)
137      continue;
138
139    if ((curr + ucast_ipv4_encoding_len) > buf_pastend) {
140      zlog_warn("%s: buffer overflow: left=%zd needed=%zu",
141		__PRETTY_FUNCTION__,
142		buf_pastend - curr, ucast_ipv4_encoding_len);
143      return 0;
144    }
145
146    /* Write encoded unicast IPv4 address */
147    *(uint8_t *) curr = PIM_MSG_ADDRESS_FAMILY_IPV4; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */
148    ++curr;
149    *(uint8_t *) curr = 0; /* ucast IPv4 native encoding type (RFC 4601: 4.9.1) */
150    ++curr;
151    memcpy(curr, &p->u.prefix4, sizeof(struct in_addr));
152    curr += sizeof(struct in_addr);
153
154    option_len += ucast_ipv4_encoding_len;
155  }
156
157  if (PIM_DEBUG_PIM_TRACE) {
158    zlog_warn("%s: number of encoded secondary unicast IPv4 addresses: %zu",
159	      __PRETTY_FUNCTION__,
160	      option_len / ucast_ipv4_encoding_len);
161  }
162
163  if (option_len < 1) {
164    /* Empty secondary unicast IPv4 address list */
165    return buf;
166  }
167
168  /*
169   * Write T and L
170   */
171  *(uint16_t *) buf       = htons(PIM_MSG_OPTION_TYPE_ADDRESS_LIST);
172  *(uint16_t *) (buf + 2) = htons(option_len);
173
174  return curr;
175}
176
177static int check_tlv_length(const char *label, const char *tlv_name,
178			    const char *ifname, struct in_addr src_addr,
179			    int correct_len, int option_len)
180{
181  if (option_len != correct_len) {
182    char src_str[100];
183    pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
184    zlog_warn("%s: PIM hello %s TLV with incorrect value size=%d correct=%d from %s on interface %s",
185	      label, tlv_name,
186	      option_len, correct_len,
187	      src_str, ifname);
188    return -1;
189  }
190
191  return 0;
192}
193
194static void check_tlv_redefinition_uint16(const char *label, const char *tlv_name,
195					  const char *ifname, struct in_addr src_addr,
196					  pim_hello_options options,
197					  pim_hello_options opt_mask,
198					  uint16_t new, uint16_t old)
199{
200  if (PIM_OPTION_IS_SET(options, opt_mask)) {
201    char src_str[100];
202    pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
203    zlog_warn("%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s",
204	      label, tlv_name,
205	      new, old,
206	      src_str, ifname);
207  }
208}
209
210static void check_tlv_redefinition_uint32(const char *label, const char *tlv_name,
211					  const char *ifname, struct in_addr src_addr,
212					  pim_hello_options options,
213					  pim_hello_options opt_mask,
214					  uint32_t new, uint32_t old)
215{
216  if (PIM_OPTION_IS_SET(options, opt_mask)) {
217    char src_str[100];
218    pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
219    zlog_warn("%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s",
220	      label, tlv_name,
221	      new, old,
222	      src_str, ifname);
223  }
224}
225
226static void check_tlv_redefinition_uint32_hex(const char *label, const char *tlv_name,
227					      const char *ifname, struct in_addr src_addr,
228					      pim_hello_options options,
229					      pim_hello_options opt_mask,
230					      uint32_t new, uint32_t old)
231{
232  if (PIM_OPTION_IS_SET(options, opt_mask)) {
233    char src_str[100];
234    pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
235    zlog_warn("%s: PIM hello TLV redefined %s=%08x old=%08x from %s on interface %s",
236	      label, tlv_name,
237	      new, old,
238	      src_str, ifname);
239  }
240}
241
242int pim_tlv_parse_holdtime(const char *ifname, struct in_addr src_addr,
243			   pim_hello_options *hello_options,
244			   uint16_t *hello_option_holdtime,
245			   uint16_t option_len,
246			   const uint8_t *tlv_curr)
247{
248  const char *label = "holdtime";
249
250  if (check_tlv_length(__PRETTY_FUNCTION__, label,
251		       ifname, src_addr,
252		       sizeof(uint16_t), option_len)) {
253    return -1;
254  }
255
256  check_tlv_redefinition_uint16(__PRETTY_FUNCTION__, label,
257				ifname, src_addr,
258				*hello_options, PIM_OPTION_MASK_HOLDTIME,
259				PIM_TLV_GET_HOLDTIME(tlv_curr),
260				*hello_option_holdtime);
261
262  PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_HOLDTIME);
263
264  *hello_option_holdtime = PIM_TLV_GET_HOLDTIME(tlv_curr);
265
266  return 0;
267}
268
269int pim_tlv_parse_lan_prune_delay(const char *ifname, struct in_addr src_addr,
270				  pim_hello_options *hello_options,
271				  uint16_t *hello_option_propagation_delay,
272				  uint16_t *hello_option_override_interval,
273				  uint16_t option_len,
274				  const uint8_t *tlv_curr)
275{
276  if (check_tlv_length(__PRETTY_FUNCTION__, "lan_prune_delay",
277		       ifname, src_addr,
278		       sizeof(uint32_t), option_len)) {
279    return -1;
280  }
281
282  check_tlv_redefinition_uint16(__PRETTY_FUNCTION__, "propagation_delay",
283				ifname, src_addr,
284				*hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY,
285				PIM_TLV_GET_PROPAGATION_DELAY(tlv_curr),
286				*hello_option_propagation_delay);
287
288  PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY);
289
290  *hello_option_propagation_delay = PIM_TLV_GET_PROPAGATION_DELAY(tlv_curr);
291  if (PIM_TLV_GET_CAN_DISABLE_JOIN_SUPPRESSION(tlv_curr)) {
292    PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION);
293  }
294  else {
295    PIM_OPTION_UNSET(*hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION);
296  }
297  ++tlv_curr;
298  ++tlv_curr;
299  *hello_option_override_interval = PIM_TLV_GET_OVERRIDE_INTERVAL(tlv_curr);
300
301  return 0;
302}
303
304int pim_tlv_parse_dr_priority(const char *ifname, struct in_addr src_addr,
305			      pim_hello_options *hello_options,
306			      uint32_t *hello_option_dr_priority,
307			      uint16_t option_len,
308			      const uint8_t *tlv_curr)
309{
310  const char *label = "dr_priority";
311
312  if (check_tlv_length(__PRETTY_FUNCTION__, label,
313		       ifname, src_addr,
314		       sizeof(uint32_t), option_len)) {
315    return -1;
316  }
317
318  check_tlv_redefinition_uint32(__PRETTY_FUNCTION__, label,
319				ifname, src_addr,
320				*hello_options, PIM_OPTION_MASK_DR_PRIORITY,
321				PIM_TLV_GET_DR_PRIORITY(tlv_curr),
322				*hello_option_dr_priority);
323
324  PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_DR_PRIORITY);
325
326  *hello_option_dr_priority = PIM_TLV_GET_DR_PRIORITY(tlv_curr);
327
328  return 0;
329}
330
331int pim_tlv_parse_generation_id(const char *ifname, struct in_addr src_addr,
332				pim_hello_options *hello_options,
333				uint32_t *hello_option_generation_id,
334				uint16_t option_len,
335				const uint8_t *tlv_curr)
336{
337  const char *label = "generation_id";
338
339  if (check_tlv_length(__PRETTY_FUNCTION__, label,
340		       ifname, src_addr,
341		       sizeof(uint32_t), option_len)) {
342    return -1;
343  }
344
345  check_tlv_redefinition_uint32_hex(__PRETTY_FUNCTION__, label,
346				    ifname, src_addr,
347				    *hello_options, PIM_OPTION_MASK_GENERATION_ID,
348				    PIM_TLV_GET_GENERATION_ID(tlv_curr),
349				    *hello_option_generation_id);
350
351  PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_GENERATION_ID);
352
353  *hello_option_generation_id = PIM_TLV_GET_GENERATION_ID(tlv_curr);
354
355  return 0;
356}
357
358int pim_parse_addr_ucast(const char *ifname, struct in_addr src_addr,
359			 struct prefix *p,
360			 const uint8_t *buf,
361			 int buf_size)
362{
363  const int ucast_encoding_min_len = 3; /* 1 family + 1 type + 1 addr */
364  const uint8_t *addr;
365  const uint8_t *pastend;
366  int family;
367  int type;
368
369  if (buf_size < ucast_encoding_min_len) {
370    char src_str[100];
371    pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
372    zlog_warn("%s: unicast address encoding overflow: left=%d needed=%d from %s on %s",
373	      __PRETTY_FUNCTION__,
374	      buf_size, ucast_encoding_min_len,
375	      src_str, ifname);
376    return -1;
377  }
378
379  addr = buf;
380  pastend = buf + buf_size;
381
382  family = *addr++;
383  type = *addr++;
384
385  switch (family) {
386  case PIM_MSG_ADDRESS_FAMILY_IPV4:
387    if (type) {
388      char src_str[100];
389      pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
390      zlog_warn("%s: unknown unicast address encoding type=%d from %s on %s",
391		__PRETTY_FUNCTION__,
392		type, src_str, ifname);
393      return -2;
394    }
395
396    if ((addr + sizeof(struct in_addr)) > pastend) {
397      char src_str[100];
398      pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
399      zlog_warn("%s: IPv4 unicast address overflow: left=%zd needed=%zu from %s on %s",
400		__PRETTY_FUNCTION__,
401		pastend - addr, sizeof(struct in_addr),
402		src_str, ifname);
403      return -3;
404    }
405
406    p->family = AF_INET; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */
407    memcpy(&p->u.prefix4, addr, sizeof(struct in_addr));
408
409    addr += sizeof(struct in_addr);
410
411    break;
412  default:
413    {
414      char src_str[100];
415      pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
416      zlog_warn("%s: unknown unicast address encoding family=%d from %s on %s",
417		__PRETTY_FUNCTION__,
418		family, src_str, ifname);
419      return -4;
420    }
421  }
422
423  return addr - buf;
424}
425
426int pim_parse_addr_group(const char *ifname, struct in_addr src_addr,
427			 struct prefix *p,
428			 const uint8_t *buf,
429			 int buf_size)
430{
431  const int grp_encoding_min_len = 4; /* 1 family + 1 type + 1 reserved + 1 addr */
432  const uint8_t *addr;
433  const uint8_t *pastend;
434  int family;
435  int type;
436  int mask_len;
437
438  if (buf_size < grp_encoding_min_len) {
439    char src_str[100];
440    pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
441    zlog_warn("%s: group address encoding overflow: left=%d needed=%d from %s on %s",
442	      __PRETTY_FUNCTION__,
443	      buf_size, grp_encoding_min_len,
444	      src_str, ifname);
445    return -1;
446  }
447
448  addr = buf;
449  pastend = buf + buf_size;
450
451  family = *addr++;
452  type = *addr++;
453  //++addr;
454  ++addr; /* skip b_reserved_z fields */
455  mask_len = *addr++;
456
457  switch (family) {
458  case PIM_MSG_ADDRESS_FAMILY_IPV4:
459    if (type) {
460      char src_str[100];
461      pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
462      zlog_warn("%s: unknown group address encoding type=%d from %s on %s",
463		__PRETTY_FUNCTION__,
464		type, src_str, ifname);
465      return -2;
466    }
467
468    if ((addr + sizeof(struct in_addr)) > pastend) {
469      char src_str[100];
470      pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
471      zlog_warn("%s: IPv4 group address overflow: left=%zd needed=%zu from %s on %s",
472		__PRETTY_FUNCTION__,
473		pastend - addr, sizeof(struct in_addr),
474		src_str, ifname);
475      return -3;
476    }
477
478    p->family = AF_INET; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */
479    memcpy(&p->u.prefix4, addr, sizeof(struct in_addr));
480    p->prefixlen = mask_len;
481
482    addr += sizeof(struct in_addr);
483
484    break;
485  default:
486    {
487      char src_str[100];
488      pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
489      zlog_warn("%s: unknown group address encoding family=%d from %s on %s",
490		__PRETTY_FUNCTION__,
491		family, src_str, ifname);
492      return -4;
493    }
494  }
495
496  return addr - buf;
497}
498
499int pim_parse_addr_source(const char *ifname,
500			  struct in_addr src_addr,
501			  struct prefix *p,
502			  uint8_t *flags,
503			  const uint8_t *buf,
504			  int buf_size)
505{
506  const int src_encoding_min_len = 4; /* 1 family + 1 type + 1 reserved + 1 addr */
507  const uint8_t *addr;
508  const uint8_t *pastend;
509  int family;
510  int type;
511  int mask_len;
512
513  if (buf_size < src_encoding_min_len) {
514    char src_str[100];
515    pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
516    zlog_warn("%s: source address encoding overflow: left=%d needed=%d from %s on %s",
517	      __PRETTY_FUNCTION__,
518	      buf_size, src_encoding_min_len,
519	      src_str, ifname);
520    return -1;
521  }
522
523  addr = buf;
524  pastend = buf + buf_size;
525
526  family = *addr++;
527  type = *addr++;
528  *flags = *addr++;
529  mask_len = *addr++;
530
531  switch (family) {
532  case PIM_MSG_ADDRESS_FAMILY_IPV4:
533    if (type) {
534      char src_str[100];
535      pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
536      zlog_warn("%s: unknown source address encoding type=%d from %s on %s: %02x%02x%02x%02x%02x%02x%02x%02x",
537		__PRETTY_FUNCTION__,
538		type, src_str, ifname,
539		buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
540      return -2;
541    }
542
543    if ((addr + sizeof(struct in_addr)) > pastend) {
544      char src_str[100];
545      pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
546      zlog_warn("%s: IPv4 source address overflow: left=%zd needed=%zu from %s on %s",
547		__PRETTY_FUNCTION__,
548		pastend - addr, sizeof(struct in_addr),
549		src_str, ifname);
550      return -3;
551    }
552
553    p->family = AF_INET; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */
554    memcpy(&p->u.prefix4, addr, sizeof(struct in_addr));
555    p->prefixlen = mask_len;
556
557    /*
558       RFC 4601: 4.9.1  Encoded Source and Group Address Formats
559
560       Encoded-Source Address
561
562       The mask length MUST be equal to the mask length in bits for
563       the given Address Family and Encoding Type (32 for IPv4 native
564       and 128 for IPv6 native).  A router SHOULD ignore any messages
565       received with any other mask length.
566    */
567    if (p->prefixlen != 32) {
568      char src_str[100];
569      pim_inet4_dump("<src?>", p->u.prefix4, src_str, sizeof(src_str));
570      zlog_warn("%s: IPv4 bad source address mask: %s/%d",
571		__PRETTY_FUNCTION__, src_str, p->prefixlen);
572      return -4;
573    }
574
575    addr += sizeof(struct in_addr);
576
577    break;
578  default:
579    {
580      char src_str[100];
581      pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
582      zlog_warn("%s: unknown source address encoding family=%d from %s on %s: %02x%02x%02x%02x%02x%02x%02x%02x",
583		__PRETTY_FUNCTION__,
584		family, src_str, ifname,
585		buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
586      return -5;
587    }
588  }
589
590  return addr - buf;
591}
592
593#define FREE_ADDR_LIST(hello_option_addr_list) \
594{ \
595  if (hello_option_addr_list) { \
596    list_delete(hello_option_addr_list); \
597    hello_option_addr_list = 0; \
598  } \
599}
600
601int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr,
602			    pim_hello_options *hello_options,
603			    struct list **hello_option_addr_list,
604			    uint16_t option_len,
605			    const uint8_t *tlv_curr)
606{
607  const uint8_t *addr;
608  const uint8_t *pastend;
609
610  zassert(hello_option_addr_list);
611
612  /*
613    Scan addr list
614   */
615  addr = tlv_curr;
616  pastend = tlv_curr + option_len;
617  while (addr < pastend) {
618    struct prefix tmp;
619    int addr_offset;
620
621    /*
622      Parse ucast addr
623     */
624    addr_offset = pim_parse_addr_ucast(ifname, src_addr, &tmp,
625				       addr, pastend - addr);
626    if (addr_offset < 1) {
627      char src_str[100];
628      pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
629      zlog_warn("%s: pim_parse_addr_ucast() failure: from %s on %s",
630		__PRETTY_FUNCTION__,
631		src_str, ifname);
632      FREE_ADDR_LIST(*hello_option_addr_list);
633      return -1;
634    }
635    addr += addr_offset;
636
637    /*
638      Debug
639     */
640    if (PIM_DEBUG_PIM_TRACE) {
641      switch (tmp.family) {
642      case AF_INET:
643	{
644	  char addr_str[100];
645	  char src_str[100];
646	  pim_inet4_dump("<addr?>", tmp.u.prefix4, addr_str, sizeof(addr_str));
647	  pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
648	  zlog_debug("%s: PIM hello TLV option: list_old_size=%d IPv4 address %s from %s on %s",
649		     __PRETTY_FUNCTION__,
650		     *hello_option_addr_list ?
651		     ((int) listcount(*hello_option_addr_list)) : -1,
652		     addr_str, src_str, ifname);
653	}
654	break;
655      default:
656	{
657	  char src_str[100];
658	  pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
659	  zlog_debug("%s: PIM hello TLV option: list_old_size=%d UNKNOWN address family from %s on %s",
660		     __PRETTY_FUNCTION__,
661		     *hello_option_addr_list ?
662		     ((int) listcount(*hello_option_addr_list)) : -1,
663		     src_str, ifname);
664	}
665      }
666    }
667
668    /*
669      Exclude neighbor's primary address if incorrectly included in
670      the secondary address list
671     */
672    if (tmp.family == AF_INET) {
673      if (tmp.u.prefix4.s_addr == src_addr.s_addr) {
674	  char src_str[100];
675	  pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
676	  zlog_warn("%s: ignoring primary address in secondary list from %s on %s",
677		    __PRETTY_FUNCTION__,
678		    src_str, ifname);
679	  continue;
680      }
681    }
682
683    /*
684      Allocate list if needed
685     */
686    if (!*hello_option_addr_list) {
687      *hello_option_addr_list = list_new();
688      if (!*hello_option_addr_list) {
689	zlog_err("%s %s: failure: hello_option_addr_list=list_new()",
690		 __FILE__, __PRETTY_FUNCTION__);
691	return -2;
692      }
693      (*hello_option_addr_list)->del = (void (*)(void *)) prefix_free;
694    }
695
696    /*
697      Attach addr to list
698     */
699    {
700      struct prefix *p;
701      p = prefix_new();
702      if (!p) {
703	zlog_err("%s %s: failure: prefix_new()",
704		 __FILE__, __PRETTY_FUNCTION__);
705	FREE_ADDR_LIST(*hello_option_addr_list);
706	return -3;
707      }
708      p->family = tmp.family;
709      p->u.prefix4 = tmp.u.prefix4;
710      listnode_add(*hello_option_addr_list, p);
711    }
712
713  } /* while (addr < pastend) */
714
715  /*
716    Mark hello option
717   */
718  PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_ADDRESS_LIST);
719
720  return 0;
721}
722