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