Process LQ_TC messages. Made link quality features configurable. Set
[olsrd.git] / src / cfgparser / olsrd_conf.c
1 /*
2  * OLSR ad-hoc routing table management protocol config parser
3  * Copyright (C) 2004 Andreas T√łnnesen (andreto@olsr.org)
4  *
5  * This file is part of the olsr.org OLSR daemon.
6  *
7  * olsr.org is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * olsr.org is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with olsr.org; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  * 
21  * 
22  * $Id: olsrd_conf.c,v 1.14 2004/11/07 20:09:12 tlopatic Exp $
23  *
24  */
25
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <stdlib.h>
31 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
35
36 #include "olsrd_conf.h"
37
38
39 extern FILE *yyin;
40 extern int yyparse(void);
41
42
43 #ifdef MAKELIB
44
45 /* Build as DLL */
46
47 void __attribute__ ((constructor)) 
48 my_init(void);
49
50 void __attribute__ ((destructor)) 
51 my_fini(void);
52
53
54 /**
55  *Constructor
56  */
57 void
58 my_init()
59 {
60   /* Print plugin info to stdout */
61   printf("olsrd config file parser %s loaded\n", PARSER_VERSION);
62
63   return;
64 }
65
66 /**
67  *Destructor
68  */
69 void
70 my_fini()
71 {
72   printf("See you around!\n");
73   return;
74 }
75
76 #else
77
78 #ifdef MAKEBIN
79
80 /* Build as standalone binary */
81 int 
82 main(int argc, char *argv[])
83 {
84   struct olsrd_config *cnf;
85
86   if(argc == 1)
87     {
88       fprintf(stderr, "Usage: olsrd_cfgparser [filename] -print\n\n");
89       exit(EXIT_FAILURE);
90     }
91
92   if((cnf = olsrd_parse_cnf(argv[1])) != NULL)
93     {
94       if((argc > 2) && (!strcmp(argv[2], "-print")))
95         {
96           olsrd_print_cnf(cnf);  
97           olsrd_write_cnf(cnf, "./out.conf");
98         }
99       else
100         printf("Use -print to view parsed values\n");
101       printf("Configfile parsed OK\n");
102     }
103   else
104     {
105       printf("Failed parsing \"%s\"\n", argv[1]);
106     }
107
108   return 0;
109 }
110
111 #else
112
113 /* Build as part of olsrd */
114
115
116 #endif
117
118 #endif
119
120 struct olsrd_config *
121 olsrd_parse_cnf(char *filename)
122 {
123   struct olsr_if *in;
124
125   cnf = malloc(sizeof(struct olsrd_config));
126   if (cnf == NULL)
127     {
128       fprintf(stderr, "Out of memory %s\n", __func__);
129       return NULL;
130   }
131
132   set_default_cnf(cnf);
133
134   printf("Parsing file: \"%s\"\n", filename);
135
136   yyin = fopen(filename, "r");
137   
138   if (yyin == NULL)
139     {
140       fprintf(stderr, "Cannot open configuration file '%s': %s.\n",
141               filename, strerror(errno));
142       free(cnf);
143       return NULL;
144   }
145
146   current_line = 1;
147
148   if (yyparse() != 0)
149     {
150       fclose(yyin);
151       olsrd_free_cnf(cnf);
152       exit(0);
153     }
154   
155   fclose(yyin);
156
157
158   in = cnf->interfaces;
159
160   while(in)
161     {
162       /* set various stuff */
163       in->index = cnf->ifcnt++;
164       in->configured = OLSR_FALSE;
165       in->interf = NULL;
166       in = in->next;
167     }
168
169
170   return cnf;
171 }
172
173
174 void
175 olsrd_free_cnf(struct olsrd_config *cnf)
176 {
177   struct hna4_entry        *h4d, *h4 = cnf->hna4_entries;
178   struct hna6_entry        *h6d, *h6 = cnf->hna6_entries;
179   struct olsr_if           *ind, *in = cnf->interfaces;
180   struct plugin_entry      *ped, *pe = cnf->plugins;
181   struct if_config_options *iod, *io;
182   
183   while(h4)
184     {
185       h4d = h4;
186       h4 = h4->next;
187       free(h4d);
188     }
189
190   while(h6)
191     {
192       h6d = h6;
193       h6 = h6->next;
194       free(h6d);
195     }
196
197   while(in)
198     {
199       io = in->cnf;
200       while(io)
201         {
202           iod = io;
203           io = io->next;
204           free(iod);
205         }
206       ind = in;
207       in = in->next;
208       free(ind->name);
209       free(ind->config);
210       free(ind);
211     }
212
213   while(pe)
214     {
215       ped = pe;
216       pe = pe->next;
217       free(ped->name);
218       free(ped);
219     }
220
221   return;
222 }
223
224
225
226 struct olsrd_config *
227 olsrd_get_default_cnf()
228 {
229   cnf = malloc(sizeof(struct olsrd_config));
230   if (cnf == NULL)
231     {
232       fprintf(stderr, "Out of memory %s\n", __func__);
233       return NULL;
234   }
235
236   set_default_cnf(cnf);
237
238   return cnf;
239 }
240
241
242
243
244 void
245 set_default_cnf(struct olsrd_config *cnf)
246 {
247     memset(cnf, 0, sizeof(struct olsrd_config));
248     
249     cnf->debug_level = DEF_DEBUGLVL;
250     cnf->ip_version  = AF_INET;
251     cnf->allow_no_interfaces = DEF_ALLOW_NO_INTS;
252     cnf->tos = DEF_TOS;
253     cnf->willingness_auto = DEF_WILL_AUTO;
254     cnf->open_ipc = DEF_OPEN_IPC;
255
256     cnf->use_hysteresis = DEF_USE_HYST;
257     cnf->hysteresis_param.scaling = HYST_SCALING;
258     cnf->hysteresis_param.thr_high = HYST_THRESHOLD_HIGH;
259     cnf->hysteresis_param.thr_low = HYST_THRESHOLD_LOW;
260
261     cnf->pollrate = DEF_POLLRATE;
262
263     cnf->tc_redundancy = TC_REDUNDANCY;
264     cnf->mpr_coverage = MPR_COVERAGE;
265     cnf->lq_level = LQ_LEVEL;
266 }
267
268
269
270
271 struct if_config_options *
272 get_default_if_config()
273 {
274   struct if_config_options *io = malloc(sizeof(struct if_config_options));
275   struct in6_addr in6;
276  
277   memset(io, 0, sizeof(struct if_config_options));
278
279   io->ipv6_addrtype = 1; /* XXX - FixMe */
280
281   if(inet_pton(AF_INET6, OLSR_IPV6_MCAST_SITE_LOCAL, &in6) < 0)
282     {
283       fprintf(stderr, "Failed converting IP address %s\n", OLSR_IPV6_MCAST_SITE_LOCAL);
284       exit(EXIT_FAILURE);
285     }
286   memcpy(&io->ipv6_multi_site.v6, &in6, sizeof(struct in6_addr));
287
288   if(inet_pton(AF_INET6, OLSR_IPV6_MCAST_GLOBAL, &in6) < 0)
289     {
290       fprintf(stderr, "Failed converting IP address %s\n", OLSR_IPV6_MCAST_GLOBAL);
291       exit(EXIT_FAILURE);
292     }
293   memcpy(&io->ipv6_multi_glbl.v6, &in6, sizeof(struct in6_addr));
294
295
296   io->hello_params.emission_interval = HELLO_INTERVAL;
297   io->hello_params.validity_time = NEIGHB_HOLD_TIME;
298   io->tc_params.emission_interval = TC_INTERVAL;
299   io->tc_params.validity_time = TOP_HOLD_TIME;
300   io->mid_params.emission_interval = MID_INTERVAL;
301   io->mid_params.validity_time = MID_HOLD_TIME;
302   io->hna_params.emission_interval = HNA_INTERVAL;
303   io->hna_params.validity_time = HNA_HOLD_TIME;
304
305   return io;
306
307 }
308
309
310
311
312
313 int
314 olsrd_write_cnf(struct olsrd_config *cnf, char *fname)
315 {
316   struct hna4_entry        *h4 = cnf->hna4_entries;
317   struct hna6_entry        *h6 = cnf->hna6_entries;
318   struct olsr_if           *in = cnf->interfaces;
319   struct plugin_entry      *pe = cnf->plugins;
320   struct plugin_param      *pp;
321   char ipv6_buf[100];             /* buffer for IPv6 inet_htop */
322   struct in_addr in4;
323
324   FILE *fd;
325
326   fd = fopen(fname, "w");
327
328   if(fd == NULL)
329     {
330       fprintf(stderr, "Could not open file %s for writing\n%s\n", fname, strerror(errno));
331       return -1;
332     }
333
334   printf("Writing config to file \"%s\".... ", fname);
335
336   fprintf(fd, "#\n# Configuration file for olsr.org olsrd\n# automatically generated by olsrd-cnf %s\n#\n\n\n", PARSER_VERSION);
337
338   /* Debug level */
339   fprintf(fd, "# Debug level(0-9)\n# If set to 0 the daemon runs in the background\n\nDebugLevel\t%d\n\n", cnf->debug_level);
340
341   /* IP version */
342   if(cnf->ip_version == AF_INET6)
343     fprintf(fd, "# IP version to use (4 or 6)\n\nIpVersion\t6\n\n");
344   else
345     fprintf(fd, "# IP version to use (4 or 6)\n\nIpVersion\t4\n\n");
346
347
348   /* HNA IPv4 */
349   fprintf(fd, "# HNA IPv4 routes\n# syntax: netaddr netmask\n# Example Internet gateway:\n# 0.0.0.0 0.0.0.0\n\nHna4\n{\n");
350   while(h4)
351     {
352       in4.s_addr = h4->net.v4;
353       fprintf(fd, "    %s ", inet_ntoa(in4));
354       in4.s_addr = h4->netmask.v4;
355       fprintf(fd, "%s\n", inet_ntoa(in4));
356       h4 = h4->next;
357     }
358   fprintf(fd, "}\n\n");
359
360
361   /* HNA IPv6 */
362   fprintf(fd, "# HNA IPv6 routes\n# syntax: netaddr prefix\n# Example Internet gateway:\nHna6\n{\n");
363   while(h6)
364     {
365       fprintf(fd, "    %s/%d\n", (char *)inet_ntop(AF_INET6, &h6->net.v6, ipv6_buf, sizeof(ipv6_buf)), h6->prefix_len);
366       h6 = h6->next;
367     }
368
369   fprintf(fd, "}\n\n");
370
371   /* No interfaces */
372   fprintf(fd, "# Should olsrd keep on running even if there are\n# no interfaces available? This is a good idea\n# for a PCMCIA/USB hotswap environment.\n# \"yes\" OR \"no\"\n\nAllowNoInt\t");
373   if(cnf->allow_no_interfaces)
374     fprintf(fd, "yes\n\n");
375   else
376     fprintf(fd, "no\n\n");
377
378   /* TOS */
379   fprintf(fd, "# TOS(type of service) value for\n# the IP header of control traffic.\n# default is 16\n\n");
380   fprintf(fd, "TosValue\t%d\n\n", cnf->tos);
381
382   /* Willingness */
383   fprintf(fd, "# The fixed willingness to use(0-7)\n# If not set willingness will be calculated\n# dynammically based on battery/power status\n\n");
384   if(cnf->willingness_auto)
385     fprintf(fd, "#Willingness\t4\n\n");
386   else
387     fprintf(fd, "Willingness%d\n\n", cnf->willingness);
388
389   /* IPC */
390   fprintf(fd, "# Allow processes like the GUI front-end\n# to connect to the daemon. 'yes' or 'no'\n\n");
391   if(cnf->open_ipc)
392     fprintf(fd, "IpcConnect\tyes\n\n");
393   else
394     fprintf(fd, "IpcConnect\tno\n\n");
395
396
397
398   /* Hysteresis */
399   fprintf(fd, "# Wether to use hysteresis or not\n# Hysteresis adds more robustness to the\n# link sensing but delays neighbor registration.\n# Used by default. 'yes' or 'no'\n\n");
400
401   if(cnf->use_hysteresis)
402     {
403       fprintf(fd, "UseHysteresis\tyes\n\n");
404       fprintf(fd, "# Hysteresis parameters\n# Do not alter these unless you know \n# what you are doing!\n# Set to auto by default. Allowed\n# values are floating point values\n# in the interval 0,1\n# THR_LOW must always be lower than\n# THR_HIGH!!\n\n");
405       fprintf(fd, "HystScaling\t%0.2f\n", cnf->hysteresis_param.scaling);
406       fprintf(fd, "HystThrHigh\t%0.2f\n", cnf->hysteresis_param.thr_high);
407       fprintf(fd, "HystThrLow\t%0.2f\n", cnf->hysteresis_param.thr_low);
408     }
409   else
410     fprintf(fd, "UseHysteresis\tno\n\n");
411
412   fprintf(fd, "\n\n");
413
414   /* Pollrate */
415   fprintf(fd, "# Polling rate in seconds(float).\n# Auto uses default value 0.1 sec\n\n");
416   fprintf(fd, "Pollrate\t%0.2f\n", cnf->pollrate);
417
418   /* TC redundancy */
419   fprintf(fd, "# TC redundancy\n# Specifies how much neighbor info should\n# be sent in TC messages\n# Possible values are:\n# 0 - only send MPR selectors\n# 1 - send MPR selectors and MPRs\n# 2 - send all neighbors\n#\n# defaults to 0\n\n");
420   fprintf(fd, "TcRedundancy\t%d\n\n", cnf->tc_redundancy);
421
422   /* MPR coverage */
423   fprintf(fd, "# MPR coverage\n# Specifies how many MPRs a node should\n# try select to reach every 2 hop neighbor\n# Can be set to any integer >0\n# defaults to 1\n\n");
424
425   fprintf(fd, "MprCoverage\t%d\n\n", cnf->mpr_coverage);
426
427   fprintf(fd, "# Link quality level\n# 0 = do not use link quality\n# 1 = use link quality for MPR selection\n# 2 = use link quality for MPR selection and routing\n\n");
428    
429   fprintf(fd, "LinkQualityLevel\t%d\n\n", cnf->lq_level);
430
431   /* Plugins */
432   fprintf(fd, "# Olsrd plugins to load\n# This must be the absolute path to the file\n# or the loader will use the following scheme:\n# - Try the paths in the LD_LIBRARY_PATH \n#   environment variable.\n# - The list of libraries cached in /etc/ld.so.cache\n# - /lib, followed by /usr/lib\n\n");
433   if(pe)
434     {
435       while(pe)
436         {
437           fprintf(fd, "LoadPlugin \"%s\"\n{\n", pe->name);
438           pp = pe->params;
439           while(pp)
440             {
441               fprintf(fd, "    PlParam \"%s\" \"%s\"\n", pp->key, pp->value);
442               pp = pp->next;
443             }
444           fprintf(fd, "}\n");
445           pe = pe->next;
446         }
447     }
448   fprintf(fd, "\n");
449
450   
451   
452
453   /* Interfaces */
454   fprintf(fd, "# Interfaces\n\n");
455   /* Interfaces */
456   if(in)
457     {
458       while(in)
459         {
460           fprintf(fd, "Interface \"%s\"\n{\n", in->name);
461           fprintf(fd, "\n");
462       
463           fprintf(fd, "    # IPv4 broadcast address to use. The\n    # one usefull example would be 255.255.255.255\n    # If not defined the broadcastaddress\n    # every card is configured with is used\n\n");
464
465           if(in->cnf->ipv4_broadcast.v4)
466             {
467               in4.s_addr = in->cnf->ipv4_broadcast.v4;
468               fprintf(fd, "    Ip4Broadcast\t %s\n\n", inet_ntoa(in4));
469             }
470           else
471             {
472               fprintf(fd, "    #Ip4Broadcast\t255.255.255.255\n\n");
473             }
474           
475           
476           fprintf(fd, "    # IPv6 address scope to use.\n    # Must be 'site-local' or 'global'\n\n");
477           if(in->cnf->ipv6_addrtype)
478             fprintf(fd, "    Ip6AddrType \tsite-local\n\n");
479           else
480             fprintf(fd, "    Ip6AddrType \tglobal\n\n");
481           
482           fprintf(fd, "    # IPv6 multicast address to use when\n    # using site-local addresses.\n    # If not defined, ff05::15 is used\n");
483           fprintf(fd, "    Ip6MulticastSite\t%s\n\n", (char *)inet_ntop(AF_INET6, &in->cnf->ipv6_multi_site.v6, ipv6_buf, sizeof(ipv6_buf)));
484           fprintf(fd, "    # IPv6 multicast address to use when\n    # using global addresses\n    # If not defined, ff0e::1 is used\n");
485           fprintf(fd, "    Ip6MulticastGlobal\t%s\n\n", (char *)inet_ntop(AF_INET6, &in->cnf->ipv6_multi_glbl.v6, ipv6_buf, sizeof(ipv6_buf)));
486           
487           
488           
489           fprintf(fd, "    # Emission and validity intervals.\n    # If not defined, RFC proposed values will\n    # in most cases be used.\n\n");
490           
491           
492           if(in->cnf->hello_params.emission_interval != HELLO_INTERVAL)
493             fprintf(fd, "    HelloInterval\t%0.2f\n", in->cnf->hello_params.emission_interval);
494           else
495             fprintf(fd, "    #HelloInterval\t%0.2f\n", in->cnf->hello_params.emission_interval);
496           if(in->cnf->hello_params.validity_time != NEIGHB_HOLD_TIME)
497             fprintf(fd, "    HelloValidityTime\t%0.2f\n", in->cnf->hello_params.validity_time);
498           else
499             fprintf(fd, "    #HelloValidityTime\t%0.2f\n", in->cnf->hello_params.validity_time);
500           if(in->cnf->tc_params.emission_interval != TC_INTERVAL)
501             fprintf(fd, "    TcInterval\t\t%0.2f\n", in->cnf->tc_params.emission_interval);
502           else
503             fprintf(fd, "    #TcInterval\t\t%0.2f\n", in->cnf->tc_params.emission_interval);
504           if(in->cnf->tc_params.validity_time != TOP_HOLD_TIME)
505             fprintf(fd, "    TcValidityTime\t%0.2f\n", in->cnf->tc_params.validity_time);
506           else
507             fprintf(fd, "    #TcValidityTime\t%0.2f\n", in->cnf->tc_params.validity_time);
508           if(in->cnf->mid_params.emission_interval != MID_INTERVAL)
509             fprintf(fd, "    MidInterval\t\t%0.2f\n", in->cnf->mid_params.emission_interval);
510           else
511             fprintf(fd, "    #MidInterval\t%0.2f\n", in->cnf->mid_params.emission_interval);
512           if(in->cnf->mid_params.validity_time != MID_HOLD_TIME)
513             fprintf(fd, "    MidValidityTime\t%0.2f\n", in->cnf->mid_params.validity_time);
514           else
515             fprintf(fd, "    #MidValidityTime\t%0.2f\n", in->cnf->mid_params.validity_time);
516           if(in->cnf->hna_params.emission_interval != HNA_INTERVAL)
517             fprintf(fd, "    HnaInterval\t\t%0.2f\n", in->cnf->hna_params.emission_interval);
518           else
519             fprintf(fd, "    #HnaInterval\t%0.2f\n", in->cnf->hna_params.emission_interval);
520           if(in->cnf->hna_params.validity_time != HNA_HOLD_TIME)
521             fprintf(fd, "    HnaValidityTime\t%0.2f\n", in->cnf->hna_params.validity_time);       
522           else
523             fprintf(fd, "    #HnaValidityTime\t%0.2f\n", in->cnf->hna_params.validity_time);      
524           
525           
526           
527           fprintf(fd, "}\n\n");
528           in = in->next;
529         }
530
531     }
532
533
534   fprintf(fd, "\n# END AUTOGENERATED CONFIG\n");
535
536   fclose(fd);
537   printf("DONE\n");
538
539   return 1;
540 }
541
542
543
544
545
546 void
547 olsrd_print_cnf(struct olsrd_config *cnf)
548 {
549   struct hna4_entry        *h4 = cnf->hna4_entries;
550   struct hna6_entry        *h6 = cnf->hna6_entries;
551   struct olsr_if           *in = cnf->interfaces;
552   struct plugin_entry      *pe = cnf->plugins;
553   char ipv6_buf[100];             /* buffer for IPv6 inet_htop */
554   struct in_addr in4;
555
556   printf(" *** olsrd configuration ***\n");
557
558   printf("Debug Level      : %d\n", cnf->debug_level);
559   printf("IpVersion        : %d\n", cnf->ip_version);
560   if(cnf->allow_no_interfaces)
561     printf("No interfaces    : ALLOWED\n");
562   else
563     printf("No interfaces    : NOT ALLOWED\n");
564   printf("TOS              : 0x%02x\n", cnf->tos);
565   if(cnf->willingness_auto)
566     printf("Willingness      : AUTO\n");
567   else
568     printf("Willingness      : %d\n", cnf->willingness);
569
570   if(cnf->open_ipc)
571     printf("IPC              : ENABLED\n");
572   else
573     printf("IPC              : DISABLED\n");
574
575   printf("Pollrate         : %0.2f\n", cnf->pollrate);
576
577   printf("TC redundancy    : %d\n", cnf->tc_redundancy);
578
579   printf("MPR coverage     : %d\n", cnf->mpr_coverage);
580    
581   printf("LQ level         : %d\n", cnf->lq_level);
582
583   /* Interfaces */
584   if(in)
585     {
586       printf("Interfaces:\n");
587       while(in)
588         {
589           printf(" dev: \"%s\"\n", in->name);
590           
591           if(in->cnf->ipv4_broadcast.v4)
592             {
593               in4.s_addr = in->cnf->ipv4_broadcast.v4;
594               printf("\tIPv4 broadcast        : %s\n", inet_ntoa(in4));
595             }
596           else
597             {
598               printf("\tIPv4 broadcast        : AUTO\n");
599             }
600           
601           if(in->cnf->ipv6_addrtype)
602             printf("\tIPv6 addrtype         : site-local\n");
603           else
604             printf("\tIPv6 addrtype         : global\n");
605           
606           //union olsr_ip_addr       ipv6_multi_site;
607           //union olsr_ip_addr       ipv6_multi_glbl;
608           printf("\tIPv6 multicast site   : %s\n", (char *)inet_ntop(AF_INET6, &in->cnf->ipv6_multi_site.v6, ipv6_buf, sizeof(ipv6_buf)));
609           printf("\tIPv6 multicast global : %s\n", (char *)inet_ntop(AF_INET6, &in->cnf->ipv6_multi_glbl.v6, ipv6_buf, sizeof(ipv6_buf)));
610           
611           printf("\tHELLO emission int    : %0.2f\n", in->cnf->hello_params.emission_interval);
612           printf("\tHELLO validity time   : %0.2f\n", in->cnf->hello_params.validity_time);
613           printf("\tTC emission int       : %0.2f\n", in->cnf->tc_params.emission_interval);
614           printf("\tTC validity time      : %0.2f\n", in->cnf->tc_params.validity_time);
615           printf("\tMID emission int      : %0.2f\n", in->cnf->mid_params.emission_interval);
616           printf("\tMID validity time     : %0.2f\n", in->cnf->mid_params.validity_time);
617           printf("\tHNA emission int      : %0.2f\n", in->cnf->hna_params.emission_interval);
618           printf("\tHNA validity time     : %0.2f\n", in->cnf->hna_params.validity_time);
619           
620           
621           
622           in = in->next;
623
624         }
625     }
626
627
628
629
630   /* Plugins */
631   if(pe)
632     {
633       printf("Plugins:\n");
634
635       while(pe)
636         {
637           printf("\tName: \"%s\"\n", pe->name);
638           pe = pe->next;
639         }
640     }
641
642   /* Hysteresis */
643   if(cnf->use_hysteresis)
644     {
645       printf("Using hysteresis:\n");
646       printf("\tScaling : %0.2f\n", cnf->hysteresis_param.scaling);
647       printf("\tThr high: %0.2f\n", cnf->hysteresis_param.thr_high);
648       printf("\tThr low : %0.2f\n", cnf->hysteresis_param.thr_low);
649     }
650   else
651     printf("Not using hysteresis\n");
652
653   /* HNA IPv4 */
654   if(h4)
655     {
656
657       printf("HNA4 entries:\n");
658       while(h4)
659         {
660           in4.s_addr = h4->net.v4;
661           printf("\t%s/", inet_ntoa(in4));
662           in4.s_addr = h4->netmask.v4;
663           printf("%s\n", inet_ntoa(in4));
664
665           h4 = h4->next;
666         }
667     }
668
669   /* HNA IPv6 */
670   if(h6)
671     {
672       printf("HNA6 entries:\n");
673       while(h6)
674         {
675           printf("\t%s/%d\n", (char *)inet_ntop(AF_INET6, &h6->net.v6, ipv6_buf, sizeof(ipv6_buf)), h6->prefix_len);
676           h6 = h6->next;
677         }
678     }
679 }
680
681