7072c527b7761047e0280f01c49ad7d4476c109d
[olsrd.git] / src / cfgparser / oparse.y
1 %{
2
3 /*
4  * The olsr.org Optimized Link-State Routing daemon (olsrd)
5  *
6  * (c) by the OLSR project
7  *
8  * See our Git repository to find out who worked on this file
9  * and thus is a copyright holder on it.
10  *
11  * All rights reserved.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  *
17  * * Redistributions of source code must retain the above copyright
18  *   notice, this list of conditions and the following disclaimer.
19  * * Redistributions in binary form must reproduce the above copyright
20  *   notice, this list of conditions and the following disclaimer in
21  *   the documentation and/or other materials provided with the
22  *   distribution.
23  * * Neither the name of olsr.org, olsrd nor the names of its
24  *   contributors may be used to endorse or promote products derived
25  *   from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
30  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
31  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
32  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
33  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
34  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
35  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38  * POSSIBILITY OF SUCH DAMAGE.
39  *
40  * Visit http://www.olsr.org for more information.
41  *
42  * If you find this software useful feel free to make a donation
43  * to the project. For more information see the website or contact
44  * the copyright holders.
45  *
46  */
47
48 #include "olsrd_conf.h"
49 #include "defs.h"
50 #include "ipcalc.h"
51 #include "net_olsr.h"
52 #include "link_set.h"
53 #include "olsr.h"
54 #include "egressTypes.h"
55 #include "gateway.h"
56
57 #include <stddef.h>
58 #include <stdio.h>
59 #include <stdlib.h>
60 #include <sys/types.h>
61 #include <sys/socket.h>
62 #include <netinet/in.h>
63 #include <arpa/inet.h>
64 #include <string.h>
65 #include <ctype.h>
66
67 #define PARSER_DEBUG 1
68
69 #if defined PARSER_DEBUG && PARSER_DEBUG
70 #define PARSER_DEBUG_PRINTF(x, args...)   printf(x, ##args)
71 #else
72 #define PARSER_DEBUG_PRINTF(x, args...)   do { } while (0)
73 #endif
74
75 #define SET_IFS_CONF(ifs, ifcnt, field, value) do { \
76         for (; ifcnt>0; ifs=ifs->next, ifcnt--) { \
77     ifs->cnfi->field = (value); \
78     ifs->cnf->field = (value); \
79         } \
80 } while (0)
81
82 #define YYSTYPE struct conf_token *
83
84 void yyerror(const char *);
85 int yylex(void);
86
87 static int ifs_in_curr_cfg = 0;
88
89 static int add_ipv6_addr(YYSTYPE ipaddr_arg, YYSTYPE prefixlen_arg);
90
91 static int lq_mult_helper(YYSTYPE ip_addr_arg, YYSTYPE mult_arg)
92 {
93   union olsr_ip_addr addr;
94   int i;
95   struct olsr_if *walker;
96
97 #if defined PARSER_DEBUG && PARSER_DEBUG > 0
98   printf("\tLinkQualityMult %s %0.2f\n",
99          (ip_addr_arg != NULL) ? ip_addr_arg->string : "any",
100          (double)mult_arg->floating);
101 #endif
102
103   memset(&addr, 0, sizeof(addr));
104
105   if (ip_addr_arg != NULL &&
106      inet_pton(olsr_cnf->ip_version, ip_addr_arg->string, &addr) <= 0) {
107     fprintf(stderr, "Cannot parse IP address %s.\n", ip_addr_arg->string);
108     return -1;
109   }
110
111   walker = olsr_cnf->interfaces;
112
113   for (i = 0; i < ifs_in_curr_cfg; i++) {
114     struct olsr_lq_mult *mult = malloc(sizeof(*mult));
115     if (mult == NULL) {
116       fprintf(stderr, "Out of memory (LQ multiplier).\n");
117       return -1;
118     }
119
120     mult->addr = addr;
121     mult->value = (uint32_t)(mult_arg->floating * LINK_LOSS_MULTIPLIER);
122
123     mult->next = walker->cnf->lq_mult;
124     walker->cnfi->lq_mult = walker->cnf->lq_mult = mult;
125     walker->cnf->orig_lq_mult_cnt++;
126     walker->cnfi->orig_lq_mult_cnt=walker->cnf->orig_lq_mult_cnt;
127
128     walker = walker->next;
129   }
130
131   if (ip_addr_arg != NULL) {
132     free(ip_addr_arg->string);
133     free(ip_addr_arg);
134   }
135
136   free(mult_arg);
137
138   return 0;
139 }
140
141 static int add_ipv6_addr(YYSTYPE ipaddr_arg, YYSTYPE prefixlen_arg)
142 {
143   union olsr_ip_addr ipaddr;
144   PARSER_DEBUG_PRINTF("HNA IPv6 entry: %s/%d\n", ipaddr_arg->string, prefixlen_arg->integer);
145
146   if (olsr_cnf->ip_version != AF_INET6) {
147     fprintf(stderr, "IPv6 addresses can only be used if \"IpVersion\" == 6, skipping HNA6.\n");
148     olsr_startup_sleep(3);
149   }
150         else {
151           if(inet_pton(AF_INET6, ipaddr_arg->string, &ipaddr) <= 0) {
152       fprintf(stderr, "ihna6entry: Failed converting IP address %s\n", ipaddr_arg->string);
153       return 1;
154     }
155
156                 if (prefixlen_arg->integer > 128) {
157                         fprintf(stderr, "ihna6entry: Illegal IPv6 prefix length %d\n", prefixlen_arg->integer);
158                         return 1;
159                 }
160
161                 /* Queue */
162                 ip_prefix_list_add(&olsr_cnf->hna_entries, &ipaddr, prefixlen_arg->integer);
163         }
164   free(ipaddr_arg->string);
165   free(ipaddr_arg);
166   free(prefixlen_arg);
167
168   return 0;
169 }
170
171 %}
172
173 %token TOK_SLASH
174 %token TOK_OPEN
175 %token TOK_CLOSE
176
177 %token TOK_STRING
178 %token TOK_INTEGER
179 %token TOK_FLOAT
180 %token TOK_BOOLEAN
181
182 %token TOK_IPV6TYPE
183
184 %token TOK_DEBUGLEVEL
185 %token TOK_IPVERSION
186 %token TOK_HNA4
187 %token TOK_HNA6
188 %token TOK_PLUGIN
189 %token TOK_INTERFACE_DEFAULTS
190 %token TOK_INTERFACE
191 %token TOK_NOINT
192 %token TOK_TOS
193 %token TOK_OLSRPORT
194 %token TOK_RTPROTO
195 %token TOK_RTTABLE
196 %token TOK_RTTABLE_DEFAULT
197 %token TOK_RTTABLE_TUNNEL
198 %token TOK_RTTABLE_PRIORITY
199 %token TOK_RTTABLE_DEFAULTOLSR_PRIORITY
200 %token TOK_RTTABLE_TUNNEL_PRIORITY
201 %token TOK_RTTABLE_DEFAULT_PRIORITY
202 %token TOK_WILLINGNESS
203 %token TOK_IPCCON
204 %token TOK_FIBMETRIC
205 %token TOK_FIBMETRICDEFAULT
206 %token TOK_USEHYST
207 %token TOK_HYSTSCALE
208 %token TOK_HYSTUPPER
209 %token TOK_HYSTLOWER
210 %token TOK_POLLRATE
211 %token TOK_NICCHGSPOLLRT
212 %token TOK_TCREDUNDANCY
213 %token TOK_MPRCOVERAGE
214 %token TOK_LQ_LEVEL
215 %token TOK_LQ_FISH
216 %token TOK_LQ_AGING
217 %token TOK_LQ_PLUGIN
218 %token TOK_LQ_NAT_THRESH
219 %token TOK_LQ_MULT
220 %token TOK_CLEAR_SCREEN
221 %token TOK_PLPARAM
222 %token TOK_MIN_TC_VTIME
223 %token TOK_LOCK_FILE
224 %token TOK_USE_NIIT
225 %token TOK_SMART_GW
226 %token TOK_SMART_GW_ALWAYS_REMOVE_SERVER_TUNNEL
227 %token TOK_SMART_GW_USE_COUNT
228 %token TOK_SMART_GW_TAKEDOWN_PERCENTAGE
229 %token TOK_SMART_GW_INSTANCE_ID
230 %token TOK_SMART_GW_POLICYROUTING_SCRIPT
231 %token TOK_SMART_GW_EGRESS_IFS
232 %token TOK_SMART_GW_EGRESS_FILE
233 %token TOK_SMART_GW_EGRESS_FILE_PERIOD
234 %token TOK_SMART_GW_STATUS_FILE
235 %token TOK_SMART_GW_OFFSET_TABLES
236 %token TOK_SMART_GW_OFFSET_RULES
237 %token TOK_SMART_GW_ALLOW_NAT
238 %token TOK_SMART_GW_PERIOD
239 %token TOK_SMART_GW_STABLECOUNT
240 %token TOK_SMART_GW_THRESH
241 %token TOK_SMART_GW_WEIGHT_EXITLINK_UP
242 %token TOK_SMART_GW_WEIGHT_EXITLINK_DOWN
243 %token TOK_SMART_GW_WEIGHT_ETX
244 %token TOK_SMART_GW_DIVIDER_ETX
245 %token TOK_SMART_GW_MAX_COST_MAX_ETX
246 %token TOK_SMART_GW_UPLINK
247 %token TOK_SMART_GW_UPLINK_NAT
248 %token TOK_SMART_GW_SPEED
249 %token TOK_SMART_GW_PREFIX
250 %token TOK_SRC_IP_ROUTES
251 %token TOK_MAIN_IP
252 %token TOK_SET_IPFORWARD
253
254 %token TOK_HOSTLABEL
255 %token TOK_NETLABEL
256 %token TOK_MAXIPC
257
258 %token TOK_IFMODE
259 %token TOK_IPV4MULTICAST
260 %token TOK_IP4BROADCAST
261 %token TOK_IPV4BROADCAST
262 %token TOK_IPV6MULTICAST
263 %token TOK_IPV4SRC
264 %token TOK_IPV6SRC
265 %token TOK_IFWEIGHT
266 %token TOK_HELLOINT
267 %token TOK_HELLOVAL
268 %token TOK_TCINT
269 %token TOK_TCVAL
270 %token TOK_MIDINT
271 %token TOK_MIDVAL
272 %token TOK_HNAINT
273 %token TOK_HNAVAL
274 %token TOK_AUTODETCHG
275
276 %token TOK_IPV4_ADDR
277 %token TOK_IPV6_ADDR
278 %token TOK_DEFAULT
279 %token TOK_AUTO
280 %token TOK_NONE
281
282 %token TOK_COMMENT
283
284 %%
285
286 conf:
287           | conf block
288           | conf stmt
289 ;
290
291 stmt:       idebug
292           | iipversion
293           | fibmetric
294           | afibmetricdefault
295           | bnoint
296           | atos
297           | aolsrport
298           | irtproto
299           | irttable
300           | irttable_default
301           | irttable_tunnel
302           | irttable_priority
303           | irttable_defaultolsr_priority
304           | irttable_tunnel_priority
305           | irttable_default_priority
306           | awillingness
307           | busehyst
308           | fhystscale
309           | fhystupper
310           | fhystlower
311           | fpollrate
312           | fnicchgspollrt
313           | atcredundancy
314           | amprcoverage
315           | alq_level
316           | alq_plugin
317           | alq_fish
318           | anat_thresh
319           | alq_aging
320           | bclear_screen
321           | vcomment
322           | amin_tc_vtime
323           | alock_file
324           | suse_niit
325           | bsmart_gw
326           | bsmart_gw_always_remove_server_tunnel
327           | ismart_gw_use_count
328           | ismart_gw_takedown_percentage
329           | ssmart_gw_instance_id
330           | ssmart_gw_policyrouting_script
331           | ssmart_gw_egress_file
332           | ismart_gw_egress_file_period
333           | ssmart_gw_status_file
334           | ismart_gw_offset_tables
335           | ismart_gw_offset_rules
336           | bsmart_gw_allow_nat
337           | ismart_gw_period
338           | asmart_gw_stablecount
339           | asmart_gw_thresh
340           | asmart_gw_weight_exitlink_up
341           | asmart_gw_weight_exitlink_down
342           | asmart_gw_weight_etx
343           | asmart_gw_divider_etx
344           | ssmart_gw_uplink
345           | bsmart_gw_uplink_nat
346           | ismart_gw_speed
347           | ismart_gw_prefix
348           | bsrc_ip_routes
349           | amain_ip
350           | bset_ipforward
351           | ssgw_egress_ifs
352 ;
353
354 block:      TOK_HNA4 hna4body
355           | TOK_HNA6 hna6body
356           | TOK_IPCCON ipcbody
357           | ifdblock ifdbody
358           | ifblock ifbody
359           | plblock plbody
360 ;
361
362 hna4body:       TOK_OPEN hna4stmts TOK_CLOSE
363 ;
364
365 hna4stmts: | hna4stmts hna4stmt
366 ;
367
368 hna4stmt:  vcomment
369          | ihna4entry
370 ;
371
372 hna6body:       TOK_OPEN hna6stmts TOK_CLOSE
373 ;
374
375 hna6stmts: | hna6stmts hna6stmt
376 ;
377
378 hna6stmt:  vcomment
379          | ihna6entry
380 ;
381
382 ipcbody:    TOK_OPEN ipcstmts TOK_CLOSE
383 ;
384
385 ipcstmts: | ipcstmts ipcstmt
386 ;
387
388 ipcstmt:  vcomment
389           | imaxipc
390           | ipchost
391           | ipcnet
392 ;
393
394 ifblock:   ifstart ifnicks
395 ;
396
397 ifnicks:   | ifnicks ifnick
398 ;
399
400 ifbody:     TOK_OPEN ifstmts TOK_CLOSE
401 ;
402
403 ifdbody:     TOK_OPEN ifstmts TOK_CLOSE
404 {
405   struct olsr_if *in = olsr_cnf->interfaces;
406   printf("\nInterface Defaults");
407   /*remove Interface Defaults from Interface list as they are no interface!*/
408   olsr_cnf->interfaces = in->next;
409   ifs_in_curr_cfg=0;
410   /*free interface but keep its config intact?*/
411   free(in->cnfi);
412   free(in);
413
414 }
415 ;
416
417 ifstmts:   | ifstmts ifstmt
418 ;
419
420 ifstmt:      vcomment
421              | iifweight
422              | isetifmode
423              | TOK_IP4BROADCAST isetipv4mc
424              | TOK_IPV4BROADCAST isetipv4mc
425              | TOK_IPV4MULTICAST isetipv4mc
426              | isetipv6mc
427              | isetipv4src
428              | isetipv6src
429              | isethelloint
430              | isethelloval
431              | isettcint
432              | isettcval
433              | isetmidint
434              | isetmidval
435              | isethnaint
436              | isethnaval
437              | isetautodetchg
438              | isetlqmult
439 ;
440
441 plbody:     TOK_OPEN plstmts TOK_CLOSE
442 ;
443
444 plstmts:   | plstmts plstmt
445 ;
446
447 plstmt:     plparam
448           | vcomment
449 ;
450
451 ifdblock: TOK_INTERFACE_DEFAULTS
452 {
453   struct olsr_if *in = malloc(sizeof(*in));
454
455   if (in == NULL) {
456     fprintf(stderr, "Out of memory(ADD IF)\n");
457     YYABORT;
458   }
459
460   in->cnf = get_default_if_config();
461   in->cnfi = get_default_if_config();
462
463   if (in->cnf == NULL || in->cnfi == NULL) {
464     fprintf(stderr, "Out of memory(ADD DEFIFRULE)\n");
465     if (in->cnf) {
466       free(in->cnf);
467     }
468     if (in->cnfi) {
469       free(in->cnfi);
470     }
471     free(in);
472     YYABORT;
473   }
474
475   //should not need a name any more, as we free it on "}" again
476   //in->name = strdup(interface_defaults_name);
477
478   olsr_cnf->interface_defaults = in->cnf;
479
480   /* Queue */
481   in->next = olsr_cnf->interfaces;
482   olsr_cnf->interfaces = in;
483   ifs_in_curr_cfg=1;
484   
485   fflush(stdout);
486 }
487 ;
488
489 imaxipc: TOK_MAXIPC TOK_INTEGER
490 {
491   olsr_cnf->ipc_connections = $2->integer;
492   free($2);
493 }
494 ;
495
496 ipchost: TOK_HOSTLABEL TOK_IPV4_ADDR
497 {
498   union olsr_ip_addr ipaddr;
499   PARSER_DEBUG_PRINTF("\tIPC host: %s\n", $2->string);
500   
501   if (inet_pton(AF_INET, $2->string, &ipaddr.v4) == 0) {
502     fprintf(stderr, "Failed converting IP address IPC %s\n", $2->string);
503     YYABORT;
504   }
505
506   ip_prefix_list_add(&olsr_cnf->ipc_nets, &ipaddr, olsr_cnf->maxplen);
507
508   free($2->string);
509   free($2);
510 }
511 ;
512
513 ipcnet: TOK_NETLABEL TOK_IPV4_ADDR TOK_IPV4_ADDR
514 {
515   union olsr_ip_addr ipaddr, netmask;
516
517   PARSER_DEBUG_PRINTF("\tIPC net: %s/%s\n", $2->string, $3->string);
518   
519   if (inet_pton(AF_INET, $2->string, &ipaddr.v4) == 0) {
520     fprintf(stderr, "Failed converting IP net IPC %s\n", $2->string);
521     YYABORT;
522   }
523
524   if (inet_pton(AF_INET, $3->string, &netmask.v4) == 0) {
525     fprintf(stderr, "Failed converting IP mask IPC %s\n", $3->string);
526     YYABORT;
527   }
528
529   ip_prefix_list_add(&olsr_cnf->ipc_nets, &ipaddr, olsr_netmask_to_prefix(&netmask));
530
531   free($2->string);
532   free($2);
533   free($3->string);
534   free($3);
535 }
536         |       TOK_NETLABEL TOK_IPV4_ADDR TOK_SLASH TOK_INTEGER
537 {
538   union olsr_ip_addr ipaddr;
539
540   PARSER_DEBUG_PRINTF("\tIPC net: %s/%s\n", $2->string, $3->string);
541   
542   if (inet_pton(AF_INET, $2->string, &ipaddr.v4) == 0) {
543     fprintf(stderr, "Failed converting IP net IPC %s\n", $2->string);
544     YYABORT;
545   }
546
547   if ($4->integer > olsr_cnf->maxplen) {
548     fprintf(stderr, "ipcnet: Prefix len %u > %d is not allowed!\n", $4->integer, olsr_cnf->maxplen);
549     YYABORT;
550   }
551
552   ip_prefix_list_add(&olsr_cnf->ipc_nets, &ipaddr, $4->integer);
553
554   free($2->string);
555   free($2);
556   free($4);
557 }
558 ;
559
560 iifweight:       TOK_IFWEIGHT TOK_INTEGER
561 {
562   int ifcnt = ifs_in_curr_cfg;
563   struct olsr_if *ifs = olsr_cnf->interfaces;
564
565   PARSER_DEBUG_PRINTF("Fixed willingness: %d\n", $2->integer);
566
567   while (ifcnt) {
568     ifs->cnf->weight.value = $2->integer;
569     ifs->cnf->weight.fixed = true;
570     ifs->cnfi->weight.value = $2->integer;
571     ifs->cnfi->weight.fixed = true;
572
573     ifs = ifs->next;
574     ifcnt--;
575   }
576
577   free($2);
578 }
579 ;
580
581 isetifmode: TOK_IFMODE TOK_STRING
582 {
583   int ifcnt = ifs_in_curr_cfg;
584   struct olsr_if *ifs = olsr_cnf->interfaces;
585         int mode = (strcmp($2->string, "ether") == 0)?IF_MODE_ETHER:IF_MODE_MESH;
586
587   PARSER_DEBUG_PRINTF("\tMode: %s\n", $2->string);
588
589         SET_IFS_CONF(ifs, ifcnt, mode, mode);
590         
591   free($2->string);
592   free($2);
593 }
594 ;
595
596 /* called if prepended with TOK_IPV4MULTICAST TOK_IP4BROADCAST TOK_IPV4BROADCAST */
597 isetipv4mc: TOK_IPV4_ADDR
598 {
599   struct in_addr in;
600   int ifcnt = ifs_in_curr_cfg;
601   struct olsr_if *ifs = olsr_cnf->interfaces;
602
603   PARSER_DEBUG_PRINTF("\tIPv4 broadcast: %s\n", $1->string);
604
605   if (inet_pton(AF_INET, $1->string, &in) == 0) {
606     fprintf(stderr, "isetipv4br: Failed converting IP address %s\n", $1->string);
607     YYABORT;
608   }
609
610         SET_IFS_CONF(ifs, ifcnt, ipv4_multicast.v4, in);
611
612   free($1->string);
613   free($1);
614 }
615 ;
616
617 isetipv6mc: TOK_IPV6MULTICAST TOK_IPV6_ADDR
618 {
619   struct in6_addr in6;
620   int ifcnt = ifs_in_curr_cfg;
621   struct olsr_if *ifs = olsr_cnf->interfaces;
622
623   PARSER_DEBUG_PRINTF("\tIPv6 multicast: %s\n", $2->string);
624
625   if (inet_pton(AF_INET6, $2->string, &in6) <= 0) {
626     fprintf(stderr, "isetipv6mc: Failed converting IP address %s\n", $2->string);
627     YYABORT;
628   }
629
630         SET_IFS_CONF(ifs, ifcnt, ipv6_multicast.v6, in6);
631
632   free($2->string);
633   free($2);
634 }
635 ;
636
637 isetipv4src: TOK_IPV4SRC TOK_IPV4_ADDR
638 {
639   struct in_addr in;
640   int ifcnt = ifs_in_curr_cfg;
641   struct olsr_if *ifs = olsr_cnf->interfaces;
642
643   PARSER_DEBUG_PRINTF("\tIPv4 src: %s\n", $2->string);
644
645   if (inet_pton(AF_INET, $2->string, &in) == 0) {
646     fprintf(stderr, "isetipv4src: Failed converting IP address %s\n", $2->string);
647     YYABORT;
648   }
649
650         SET_IFS_CONF(ifs, ifcnt, ipv4_src.v4, in);
651
652   free($2->string);
653   free($2);
654 }
655 ;
656
657 isetipv6src: TOK_IPV6SRC TOK_IPV6_ADDR TOK_SLASH TOK_INTEGER
658 {
659   struct olsr_ip_prefix pr6;
660   int ifcnt = ifs_in_curr_cfg;
661   struct olsr_if *ifs = olsr_cnf->interfaces;
662
663   PARSER_DEBUG_PRINTF("\tIPv6 src prefix: %s/%d\n", $2->string, $4->integer);
664
665   if (inet_pton(AF_INET6, $2->string, &pr6.prefix.v6) <= 0) {
666     fprintf(stderr, "isetipv6src: Failed converting IP address %s\n", $2->string);
667     YYABORT;
668   }
669   if ($4->integer > 128) {
670     fprintf(stderr, "isetipv6src: Illegal Prefixlength %d\n", $4->integer);
671     YYABORT;
672   }
673   pr6.prefix_len = $4->integer;
674
675         SET_IFS_CONF(ifs, ifcnt, ipv6_src, pr6);
676
677   free($2->string);
678   free($2);
679 }
680         | TOK_IPV6SRC TOK_IPV6_ADDR
681 {
682   struct olsr_ip_prefix pr6;
683   int ifcnt = ifs_in_curr_cfg;
684   struct olsr_if *ifs = olsr_cnf->interfaces;
685
686   PARSER_DEBUG_PRINTF("\tIPv6 src prefix: %s/%d\n", $2->string, 128);
687
688   if (inet_pton(AF_INET6, $2->string, &pr6.prefix.v6) <= 0) {
689     fprintf(stderr, "isetipv6src: Failed converting IP address %s\n", $2->string);
690     YYABORT;
691   }
692   pr6.prefix_len = 128;
693
694   SET_IFS_CONF(ifs, ifcnt, ipv6_src, pr6);
695
696   free($2->string);
697   free($2);
698 }
699 ;
700
701 isethelloint: TOK_HELLOINT TOK_FLOAT
702 {
703   int ifcnt = ifs_in_curr_cfg;
704   struct olsr_if *ifs = olsr_cnf->interfaces;
705
706   PARSER_DEBUG_PRINTF("\tHELLO interval: %0.2f\n", (double)$2->floating);
707
708         SET_IFS_CONF(ifs, ifcnt, hello_params.emission_interval, $2->floating);
709
710   free($2);
711 }
712 ;
713 isethelloval: TOK_HELLOVAL TOK_FLOAT
714 {
715   int ifcnt = ifs_in_curr_cfg;
716   struct olsr_if *ifs = olsr_cnf->interfaces;
717
718   PARSER_DEBUG_PRINTF("\tHELLO validity: %0.2f\n", (double)$2->floating);
719
720         SET_IFS_CONF(ifs, ifcnt, hello_params.validity_time, $2->floating);
721
722   free($2);
723 }
724 ;
725 isettcint: TOK_TCINT TOK_FLOAT
726 {
727   int ifcnt = ifs_in_curr_cfg;
728   struct olsr_if *ifs = olsr_cnf->interfaces;
729
730   PARSER_DEBUG_PRINTF("\tTC interval: %0.2f\n", (double)$2->floating);
731
732         SET_IFS_CONF(ifs, ifcnt, tc_params.emission_interval, $2->floating);
733
734   free($2);
735 }
736 ;
737 isettcval: TOK_TCVAL TOK_FLOAT
738 {
739   int ifcnt = ifs_in_curr_cfg;
740   struct olsr_if *ifs = olsr_cnf->interfaces;
741   
742   PARSER_DEBUG_PRINTF("\tTC validity: %0.2f\n", (double)$2->floating);
743   
744  SET_IFS_CONF(ifs, ifcnt, tc_params.validity_time, $2->floating);
745
746   free($2);
747 }
748 ;
749 isetmidint: TOK_MIDINT TOK_FLOAT
750 {
751   int ifcnt = ifs_in_curr_cfg;
752   struct olsr_if *ifs = olsr_cnf->interfaces;
753
754
755   PARSER_DEBUG_PRINTF("\tMID interval: %0.2f\n", (double)$2->floating);
756   
757   SET_IFS_CONF(ifs, ifcnt, mid_params.emission_interval, $2->floating);
758
759   free($2);
760 }
761 ;
762 isetmidval: TOK_MIDVAL TOK_FLOAT
763 {
764   int ifcnt = ifs_in_curr_cfg;
765   struct olsr_if *ifs = olsr_cnf->interfaces;
766
767   PARSER_DEBUG_PRINTF("\tMID validity: %0.2f\n", (double)$2->floating);
768   
769   SET_IFS_CONF(ifs, ifcnt, mid_params.validity_time, $2->floating);
770
771   free($2);
772 }
773 ;
774 isethnaint: TOK_HNAINT TOK_FLOAT
775 {
776   int ifcnt = ifs_in_curr_cfg;
777   struct olsr_if *ifs = olsr_cnf->interfaces;
778   
779   PARSER_DEBUG_PRINTF("\tHNA interval: %0.2f\n", (double)$2->floating);
780
781   SET_IFS_CONF(ifs, ifcnt, hna_params.emission_interval, $2->floating);
782
783   free($2);
784 }
785 ;
786 isethnaval: TOK_HNAVAL TOK_FLOAT
787 {
788   int ifcnt = ifs_in_curr_cfg;
789   struct olsr_if *ifs = olsr_cnf->interfaces;
790
791   PARSER_DEBUG_PRINTF("\tHNA validity: %0.2f\n", (double)$2->floating);
792
793   SET_IFS_CONF(ifs, ifcnt, hna_params.validity_time, $2->floating);
794
795   free($2);
796 }
797 ;
798 isetautodetchg: TOK_AUTODETCHG TOK_BOOLEAN
799 {
800   int ifcnt = ifs_in_curr_cfg;
801   struct olsr_if *ifs = olsr_cnf->interfaces;
802
803   PARSER_DEBUG_PRINTF("\tAutodetect changes: %s\n", $2->boolean ? "YES" : "NO");
804
805   SET_IFS_CONF(ifs, ifcnt, autodetect_chg, $2->boolean);
806
807   free($2);
808 }
809 ;
810
811 isetlqmult: TOK_LQ_MULT TOK_DEFAULT TOK_FLOAT
812 {
813   if (lq_mult_helper($2, $3) < 0) {
814     YYABORT;
815   }
816 }
817
818           | TOK_LQ_MULT TOK_IPV4_ADDR TOK_FLOAT
819 {
820   if (lq_mult_helper($2, $3) < 0) {
821     YYABORT;
822   }
823 }
824
825           | TOK_LQ_MULT TOK_IPV6_ADDR TOK_FLOAT
826 {
827   if (lq_mult_helper($2, $3) < 0) {
828     YYABORT;
829   }
830 }
831 ;
832
833 idebug:       TOK_DEBUGLEVEL TOK_INTEGER
834 {
835   olsr_cnf->debug_level = $2->integer;
836   PARSER_DEBUG_PRINTF("Debug level: %d\n", olsr_cnf->debug_level);
837   free($2);
838 }
839 ;
840
841
842 iipversion:    TOK_IPVERSION TOK_INTEGER
843 {
844   if ($2->integer == 4) {
845     olsr_cnf->ip_version = AF_INET;
846     olsr_cnf->ipsize = sizeof(struct in_addr);
847     olsr_cnf->maxplen = 32;
848   } else if ($2->integer == 6) {
849     olsr_cnf->ip_version = AF_INET6;
850     olsr_cnf->ipsize = sizeof(struct in6_addr);
851     olsr_cnf->maxplen = 128;
852   } else {
853     fprintf(stderr, "IPversion must be 4 or 6!\n");
854     YYABORT;
855   }
856
857   PARSER_DEBUG_PRINTF("IpVersion: %d\n", $2->integer);
858   free($2);
859 }
860 ;
861
862 fibmetric:    TOK_FIBMETRIC TOK_STRING
863 {
864   int i;
865   PARSER_DEBUG_PRINTF("FIBMetric: %s\n", $2->string);
866   for (i=0; i<FIBM_CNT; i++) {
867     if (strcmp($2->string, FIB_METRIC_TXT[i]) == 0) {
868       olsr_cnf->fib_metric = i;
869       break;
870     }
871   }
872   if (i == FIBM_CNT) {
873     fprintf(stderr, "Bad FIBMetric value: %s\n", $2->string);
874     YYABORT;
875   }
876   free($1);
877   free($2->string);
878   free($2);
879 }
880 ;
881
882 afibmetricdefault: TOK_FIBMETRICDEFAULT TOK_INTEGER
883 {
884   PARSER_DEBUG_PRINTF("FIBMetricDefault: %d\n", $2->integer);
885   olsr_cnf->fib_metric_default = $2->integer;
886   free($2);
887 }
888 ;
889
890 ihna4entry:     TOK_IPV4_ADDR TOK_IPV4_ADDR
891 {
892   union olsr_ip_addr ipaddr, netmask;
893
894   if (olsr_cnf->ip_version == AF_INET6) {
895     fprintf(stderr, "IPv4 addresses can only be used if \"IpVersion\" == 4, skipping HNA.\n");
896     olsr_startup_sleep(3);
897   }
898   else {
899     PARSER_DEBUG_PRINTF("HNA IPv4 entry: %s/%s\n", $1->string, $2->string);
900
901     if (inet_pton(AF_INET, $1->string, &ipaddr.v4) <= 0) {
902       fprintf(stderr, "ihna4entry: Failed converting IP address %s\n", $1->string);
903       YYABORT;
904     }
905     if (inet_pton(AF_INET, $2->string, &netmask.v4) <= 0) {
906       fprintf(stderr, "ihna4entry: Failed converting IP address %s\n", $1->string);
907       YYABORT;
908     }
909
910     /* check that the given IP address is actually a network address */
911     if ((ipaddr.v4.s_addr & ~netmask.v4.s_addr) != 0) {
912       fprintf(stderr, "ihna4entry: The ipaddress \"%s\" is not a network address!\n", $1->string);
913       YYABORT;
914     }
915
916     /* Queue */
917     ip_prefix_list_add(&olsr_cnf->hna_entries, &ipaddr, olsr_netmask_to_prefix(&netmask));
918   }
919   free($1->string);
920   free($1);
921   free($2->string);
922   free($2);
923 }
924         |       TOK_IPV4_ADDR TOK_SLASH TOK_INTEGER
925 {
926   union olsr_ip_addr ipaddr, netmask;
927
928   if (olsr_cnf->ip_version == AF_INET6) {
929     fprintf(stderr, "IPv4 addresses can only be used if \"IpVersion\" == 4, skipping HNA.\n");
930     olsr_startup_sleep(3);
931   }
932   else {
933     PARSER_DEBUG_PRINTF("HNA IPv4 entry: %s/%d\n", $1->string, $3->integer);
934
935     if (inet_pton(AF_INET, $1->string, &ipaddr.v4) <= 0) {
936       fprintf(stderr, "ihna4entry: Failed converting IP address %s\n", $1->string);
937       YYABORT;
938     }
939     if ($3->integer > olsr_cnf->maxplen) {
940       fprintf(stderr, "ihna4entry: Prefix len %u > %d is not allowed!\n", $3->integer, olsr_cnf->maxplen);
941       YYABORT;
942     }
943
944     /* check that the given IP address is actually a network address */
945     olsr_prefix_to_netmask(&netmask, $3->integer);
946     if ((ipaddr.v4.s_addr & ~netmask.v4.s_addr) != 0) {
947       fprintf(stderr, "ihna4entry: The ipaddress \"%s\" is not a network address!\n", $1->string);
948       YYABORT;
949     }
950
951     /* Queue */
952     ip_prefix_list_add(&olsr_cnf->hna_entries, &ipaddr, $3->integer);
953   }
954   free($1->string);
955   free($1);
956   free($3);
957 }
958 ;
959
960 ihna6entry:     TOK_IPV6_ADDR TOK_INTEGER
961 {
962   if (add_ipv6_addr($1, $2)) {
963     YYABORT;
964   }
965 }
966         |       TOK_IPV6_ADDR TOK_SLASH TOK_INTEGER
967 {
968   if (add_ipv6_addr($1, $3)) {
969     YYABORT;
970   }
971 }
972 ;
973
974 ifstart: TOK_INTERFACE
975 {
976   PARSER_DEBUG_PRINTF("setting ifs_in_curr_cfg = 0\n");
977   ifs_in_curr_cfg = 0;
978 }
979 ;
980
981 ifnick: TOK_STRING
982 {
983   struct olsr_if *in, *last;
984   in = olsr_cnf->interfaces;
985   last = NULL;
986   while (in != NULL) {
987     if (strcmp(in->name, $1->string) == 0) {
988       free ($1->string);
989       break;
990     }
991     last = in;
992     in = in->next;
993   }
994
995   if (in != NULL) {
996     /* remove old interface from list to add it later at the beginning */
997     if (last) {
998       last->next = in->next;
999     }
1000     else {
1001       olsr_cnf->interfaces = in->next;
1002     }
1003   }
1004   else {
1005     in = malloc(sizeof(*in));
1006     if (in == NULL) {
1007       fprintf(stderr, "Out of memory(ADD IF)\n");
1008       YYABORT;
1009     }
1010     memset(in, 0, sizeof(*in));
1011
1012     in->cnf = malloc(sizeof(*in->cnf));
1013     if (in->cnf == NULL) {
1014       fprintf(stderr, "Out of memory(ADD IFRULE)\n");
1015       free(in);
1016       YYABORT;
1017     }
1018     memset(in->cnf, 0x00, sizeof(*in->cnf));
1019
1020     in->cnfi = malloc(sizeof(*in->cnfi));
1021     if (in->cnfi == NULL) {
1022       fprintf(stderr, "Out of memory(ADD IFRULE)\n");
1023       free (in->cnf);
1024       free(in);
1025       YYABORT;
1026     }
1027     memset(in->cnfi, 0xFF, sizeof(*in->cnfi));
1028     in->cnfi->orig_lq_mult_cnt=0;
1029
1030     in->name = $1->string;
1031   }
1032   /* Queue */
1033   in->next = olsr_cnf->interfaces;
1034   olsr_cnf->interfaces = in;
1035   ifs_in_curr_cfg++;
1036   free($1);
1037 }
1038 ;
1039
1040 bnoint: TOK_NOINT TOK_BOOLEAN
1041 {
1042   PARSER_DEBUG_PRINTF("Noint set to %d\n", $2->boolean);
1043   olsr_cnf->allow_no_interfaces = $2->boolean;
1044   free($2);
1045 }
1046 ;
1047
1048 atos: TOK_TOS TOK_INTEGER
1049 {
1050   PARSER_DEBUG_PRINTF("TOS: %d\n", $2->integer);
1051   olsr_cnf->tos = $2->integer;
1052   free($2);
1053
1054 }
1055 ;
1056
1057 aolsrport: TOK_OLSRPORT TOK_INTEGER
1058 {
1059   PARSER_DEBUG_PRINTF("OlsrPort: %d\n", $2->integer);
1060   olsr_cnf->olsrport = $2->integer;
1061   free($2);
1062 }
1063 ;
1064
1065 irtproto: TOK_RTPROTO TOK_INTEGER
1066 {
1067   PARSER_DEBUG_PRINTF("RtProto: %d\n", $2->integer);
1068   olsr_cnf->rt_proto = $2->integer;
1069   free($2);
1070 }
1071 ;
1072
1073 irttable: TOK_RTTABLE TOK_INTEGER
1074 {
1075   PARSER_DEBUG_PRINTF("RtTable: %d\n", $2->integer);
1076   olsr_cnf->rt_table = $2->integer;
1077   free($2);
1078 }
1079        | TOK_RTTABLE TOK_AUTO
1080 {
1081   PARSER_DEBUG_PRINTF("RtTable: auto\n");
1082   olsr_cnf->rt_table = DEF_RT_AUTO;
1083   free($2);
1084 }
1085 ;
1086
1087 irttable_default: TOK_RTTABLE_DEFAULT TOK_INTEGER
1088 {
1089   PARSER_DEBUG_PRINTF("RtTableDefault: %d\n", $2->integer);
1090   olsr_cnf->rt_table_default = $2->integer;
1091   free($2);
1092 }
1093        | TOK_RTTABLE_DEFAULT TOK_AUTO
1094 {
1095   PARSER_DEBUG_PRINTF("RtTableDefault: auto\n");
1096   olsr_cnf->rt_table_default = DEF_RT_AUTO;
1097   free($2);
1098 }
1099 ;
1100
1101 irttable_tunnel: TOK_RTTABLE_TUNNEL TOK_INTEGER
1102 {
1103   PARSER_DEBUG_PRINTF("RtTableTunnel: %d\n", $2->integer);
1104   olsr_cnf->rt_table_tunnel = $2->integer;
1105   free($2);
1106 }
1107        | TOK_RTTABLE_TUNNEL TOK_AUTO
1108 {
1109   PARSER_DEBUG_PRINTF("RtTableTunnel: auto\n");
1110   olsr_cnf->rt_table_tunnel = DEF_RT_AUTO;
1111   free($2);
1112 }
1113 ;
1114
1115 irttable_priority: TOK_RTTABLE_PRIORITY TOK_INTEGER
1116 {
1117   PARSER_DEBUG_PRINTF("RtTablePriority: %d\n", $2->integer);
1118   olsr_cnf->rt_table_pri = $2->integer;
1119   free($2);
1120 }
1121         | TOK_RTTABLE_PRIORITY TOK_AUTO
1122 {
1123   PARSER_DEBUG_PRINTF("RtTablePriority: auto\n");
1124   olsr_cnf->rt_table_pri = DEF_RT_AUTO;
1125   free($2);
1126 }
1127         | TOK_RTTABLE_PRIORITY TOK_NONE
1128 {
1129   PARSER_DEBUG_PRINTF("RtTablePriority: none\n");
1130   olsr_cnf->rt_table_pri = DEF_RT_NONE;
1131   free($2);
1132 }
1133 ;
1134
1135 irttable_default_priority: TOK_RTTABLE_DEFAULT_PRIORITY TOK_INTEGER
1136 {
1137   PARSER_DEBUG_PRINTF("RtTableDefaultPriority: %d\n", $2->integer);
1138   olsr_cnf->rt_table_default_pri = $2->integer;
1139   free($2);
1140 }
1141         | TOK_RTTABLE_DEFAULT_PRIORITY TOK_AUTO
1142 {
1143   PARSER_DEBUG_PRINTF("RtTableDefaultPriority: auto\n");
1144   olsr_cnf->rt_table_default_pri = DEF_RT_AUTO;
1145   free($2);
1146 }
1147         | TOK_RTTABLE_DEFAULT_PRIORITY TOK_NONE
1148 {
1149   PARSER_DEBUG_PRINTF("RtTableDefaultPriority: none\n");
1150   olsr_cnf->rt_table_default_pri = DEF_RT_NONE;
1151   free($2);
1152 }
1153 ;
1154
1155 irttable_tunnel_priority: TOK_RTTABLE_TUNNEL_PRIORITY TOK_INTEGER
1156 {
1157   PARSER_DEBUG_PRINTF("RtTableTunnelPriority: %d\n", $2->integer);
1158   olsr_cnf->rt_table_tunnel_pri = $2->integer;
1159   free($2);
1160 }
1161         | TOK_RTTABLE_TUNNEL_PRIORITY TOK_AUTO
1162 {
1163   PARSER_DEBUG_PRINTF("RtTableTunnelPriority: auto\n");
1164   olsr_cnf->rt_table_tunnel_pri = DEF_RT_AUTO;
1165   free($2);
1166 }
1167         | TOK_RTTABLE_TUNNEL_PRIORITY TOK_NONE
1168 {
1169   PARSER_DEBUG_PRINTF("RtTableTunnelPriority: none\n");
1170   olsr_cnf->rt_table_tunnel_pri = DEF_RT_NONE;
1171   free($2);
1172 }
1173 ;
1174
1175 irttable_defaultolsr_priority: TOK_RTTABLE_DEFAULTOLSR_PRIORITY TOK_INTEGER
1176 {
1177   PARSER_DEBUG_PRINTF("RtTableDefaultOlsrPriority: %d\n", $2->integer);
1178   olsr_cnf->rt_table_defaultolsr_pri = $2->integer;
1179   free($2);
1180 }
1181         | TOK_RTTABLE_DEFAULTOLSR_PRIORITY TOK_AUTO
1182 {
1183   PARSER_DEBUG_PRINTF("RtTableDefaultOlsrPriority: auto\n");
1184   olsr_cnf->rt_table_defaultolsr_pri = DEF_RT_AUTO;
1185   free($2);
1186 }
1187         | TOK_RTTABLE_DEFAULTOLSR_PRIORITY TOK_NONE
1188 {
1189   PARSER_DEBUG_PRINTF("RtTableDefaultOlsrPriority: none\n");
1190   olsr_cnf->rt_table_defaultolsr_pri = DEF_RT_NONE;
1191   free($2);
1192 }
1193 ;
1194
1195 awillingness: TOK_WILLINGNESS TOK_INTEGER
1196 {
1197   PARSER_DEBUG_PRINTF("Willingness: %d\n", $2->integer);
1198   olsr_cnf->willingness_auto = false;
1199   olsr_cnf->willingness = $2->integer;
1200   free($2);
1201 }
1202 ;
1203
1204 busehyst: TOK_USEHYST TOK_BOOLEAN
1205 {
1206   olsr_cnf->use_hysteresis = $2->boolean;
1207   PARSER_DEBUG_PRINTF("Hysteresis %s\n", olsr_cnf->use_hysteresis ? "enabled" : "disabled");
1208   free($2);
1209 }
1210 ;
1211
1212 fhystscale: TOK_HYSTSCALE TOK_FLOAT
1213 {
1214   olsr_cnf->hysteresis_param.scaling = $2->floating;
1215   PARSER_DEBUG_PRINTF("Hysteresis Scaling: %0.2f\n", (double)$2->floating);
1216   free($2);
1217 }
1218 ;
1219
1220 fhystupper: TOK_HYSTUPPER TOK_FLOAT
1221 {
1222   olsr_cnf->hysteresis_param.thr_high = $2->floating;
1223   PARSER_DEBUG_PRINTF("Hysteresis UpperThr: %0.2f\n", (double)$2->floating);
1224   free($2);
1225 }
1226 ;
1227
1228 fhystlower: TOK_HYSTLOWER TOK_FLOAT
1229 {
1230   olsr_cnf->hysteresis_param.thr_low = $2->floating;
1231   PARSER_DEBUG_PRINTF("Hysteresis LowerThr: %0.2f\n", (double)$2->floating);
1232   free($2);
1233 }
1234 ;
1235
1236 fpollrate: TOK_POLLRATE TOK_FLOAT
1237 {
1238   PARSER_DEBUG_PRINTF("Pollrate %0.2f\n", (double)$2->floating);
1239   olsr_cnf->pollrate = $2->floating;
1240   free($2);
1241 }
1242 ;
1243
1244 fnicchgspollrt: TOK_NICCHGSPOLLRT TOK_FLOAT
1245 {
1246   PARSER_DEBUG_PRINTF("NIC Changes Pollrate %0.2f\n", (double)$2->floating);
1247   olsr_cnf->nic_chgs_pollrate = $2->floating;
1248   free($2);
1249 }
1250 ;
1251
1252 atcredundancy: TOK_TCREDUNDANCY TOK_INTEGER
1253 {
1254   PARSER_DEBUG_PRINTF("TC redundancy %d\n", $2->integer);
1255   olsr_cnf->tc_redundancy = $2->integer;
1256   free($2);
1257 }
1258 ;
1259
1260 amprcoverage: TOK_MPRCOVERAGE TOK_INTEGER
1261 {
1262   PARSER_DEBUG_PRINTF("MPR coverage %d\n", $2->integer);
1263   olsr_cnf->mpr_coverage = $2->integer;
1264   free($2);
1265 }
1266 ;
1267
1268 alq_level: TOK_LQ_LEVEL TOK_INTEGER
1269 {
1270   PARSER_DEBUG_PRINTF("Link quality level %d\n", $2->integer);
1271   olsr_cnf->lq_level = $2->integer;
1272   free($2);
1273 }
1274 ;
1275
1276 alq_fish: TOK_LQ_FISH TOK_INTEGER
1277 {
1278   PARSER_DEBUG_PRINTF("Link quality fish eye %d\n", $2->integer);
1279   olsr_cnf->lq_fish = $2->integer;
1280   free($2);
1281 }
1282 ;
1283
1284 alq_aging: TOK_LQ_AGING TOK_FLOAT
1285 {
1286   PARSER_DEBUG_PRINTF("Link quality aging factor %f\n", (double)$2->floating);
1287   olsr_cnf->lq_aging = $2->floating;
1288   free($2);
1289 }
1290 ;
1291
1292 amin_tc_vtime: TOK_MIN_TC_VTIME TOK_FLOAT
1293 {
1294   PARSER_DEBUG_PRINTF("Minimum TC validity time %f\n", (double)$2->floating);
1295   olsr_cnf->min_tc_vtime = $2->floating;
1296   free($2);
1297 }
1298 ;
1299
1300 alock_file: TOK_LOCK_FILE TOK_STRING
1301 {
1302   PARSER_DEBUG_PRINTF("Lock file %s\n", $2->string);
1303   if (olsr_cnf->lock_file) free(olsr_cnf->lock_file);
1304   olsr_cnf->lock_file = $2->string;
1305   free($2);
1306 }
1307 ;
1308 alq_plugin: TOK_LQ_PLUGIN TOK_STRING
1309 {
1310   if (olsr_cnf->lq_algorithm) free(olsr_cnf->lq_algorithm);
1311   olsr_cnf->lq_algorithm = $2->string;
1312   PARSER_DEBUG_PRINTF("LQ Algorithm: %s\n", $2->string);
1313   free($2);
1314 }
1315 ;
1316
1317 anat_thresh: TOK_LQ_NAT_THRESH TOK_FLOAT
1318 {
1319   PARSER_DEBUG_PRINTF("NAT threshold %0.2f\n", (double)$2->floating);
1320   olsr_cnf->lq_nat_thresh = $2->floating;
1321   free($2);
1322 }
1323 ;
1324
1325 bclear_screen: TOK_CLEAR_SCREEN TOK_BOOLEAN
1326 {
1327   PARSER_DEBUG_PRINTF("Clear screen %s\n", $2->boolean ? "enabled" : "disabled");
1328   olsr_cnf->clear_screen = $2->boolean;
1329   free($2);
1330 }
1331 ;
1332
1333 suse_niit: TOK_USE_NIIT TOK_BOOLEAN
1334 {
1335   PARSER_DEBUG_PRINTF("Use NIIT ip translation: %s\n", $2->boolean ? "enabled" : "disabled");
1336   olsr_cnf->use_niit = $2->boolean;
1337   free($2);
1338 }
1339 ;
1340
1341 bsmart_gw: TOK_SMART_GW TOK_BOOLEAN
1342 {
1343         PARSER_DEBUG_PRINTF("Smart gateway system: %s\n", $2->boolean ? "enabled" : "disabled");
1344         olsr_cnf->smart_gw_active = $2->boolean;
1345         free($2);
1346 }
1347 ;
1348
1349 bsmart_gw_always_remove_server_tunnel: TOK_SMART_GW_ALWAYS_REMOVE_SERVER_TUNNEL TOK_BOOLEAN
1350 {
1351         PARSER_DEBUG_PRINTF("Smart gateway always remove server tunnel: %s\n", $2->boolean ? "enabled" : "disabled");
1352         olsr_cnf->smart_gw_always_remove_server_tunnel = $2->boolean;
1353         free($2);
1354 }
1355 ;
1356
1357 ismart_gw_use_count: TOK_SMART_GW_USE_COUNT TOK_INTEGER
1358 {
1359   PARSER_DEBUG_PRINTF("Smart gateway use count: %d\n", $2->integer);
1360   olsr_cnf->smart_gw_use_count = $2->integer;
1361   free($2);
1362 }
1363 ;
1364
1365 ismart_gw_takedown_percentage: TOK_SMART_GW_TAKEDOWN_PERCENTAGE TOK_INTEGER
1366 {
1367   PARSER_DEBUG_PRINTF("Smart gateway takedown percentage: %d\n", $2->integer);
1368   olsr_cnf->smart_gw_takedown_percentage = $2->integer;
1369   free($2);
1370 }
1371 ;
1372
1373 ssmart_gw_instance_id: TOK_SMART_GW_INSTANCE_ID TOK_STRING
1374 {
1375   PARSER_DEBUG_PRINTF("Smart gateway instance id: %s\n", $2->string);
1376   if (olsr_cnf->smart_gw_instance_id) free(olsr_cnf->smart_gw_instance_id);
1377   olsr_cnf->smart_gw_instance_id = $2->string;
1378   free($2);
1379 }
1380 ;
1381
1382 ssmart_gw_policyrouting_script: TOK_SMART_GW_POLICYROUTING_SCRIPT TOK_STRING
1383 {
1384   PARSER_DEBUG_PRINTF("Smart gateway policy routing script: %s\n", $2->string);
1385   if (olsr_cnf->smart_gw_policyrouting_script) free(olsr_cnf->smart_gw_policyrouting_script);
1386   olsr_cnf->smart_gw_policyrouting_script = $2->string;
1387   free($2);
1388 }
1389 ;
1390
1391 ssgw_egress_ifs:   TOK_SMART_GW_EGRESS_IFS sgw_egress_ifs
1392 ;
1393
1394 sgw_egress_ifs:   | sgw_egress_ifs sgw_egress_if
1395 ;
1396
1397 sgw_egress_if: TOK_STRING
1398 {
1399   struct sgw_egress_if *in, *previous, *last;
1400   char * str = $1->string;
1401   char *end;
1402
1403   /* Trim leading space */
1404   while(isspace(*str)) {
1405     str++;
1406   }
1407
1408   /* Trim trailing space */
1409   end = &str[strlen(str) - 1];
1410   while((end > str) && isspace(*end)) {
1411     end--;
1412   }
1413
1414   /* Write new null terminator */
1415   end[1] = '\0';
1416
1417   if(*str == '\0') {
1418     PARSER_DEBUG_PRINTF("Smart gateway egress interface: <empty> (skipped)\n");
1419   } else {
1420     PARSER_DEBUG_PRINTF("Smart gateway egress interface: %s\n", str);
1421
1422     in = olsr_cnf->smart_gw_egress_interfaces;
1423     previous = NULL;
1424     while (in != NULL) {
1425       if (strcmp(in->name, str) == 0) {
1426         free ($1->string);
1427         break;
1428       }
1429       previous = in;
1430       in = in->next;
1431     }
1432
1433     if (in != NULL) {
1434       /* remove old interface from list to add it later at the end */
1435       if (previous) {
1436         previous->next = in->next;
1437       }
1438       else {
1439         olsr_cnf->smart_gw_egress_interfaces = in->next;
1440       }
1441       in->next = NULL;
1442     }
1443     else {
1444       /* interface in not in the list: create a new entry to add it later at the end */
1445       in = malloc(sizeof(*in));
1446       if (in == NULL) {
1447         fprintf(stderr, "Out of memory(ADD IF)\n");
1448         YYABORT;
1449       }
1450       memset(in, 0, sizeof(*in));
1451
1452       in->name = str;
1453     }
1454
1455     last = olsr_cnf->smart_gw_egress_interfaces;
1456     while (last && last->next) {
1457       last = last->next;
1458     }
1459
1460     /* Add to the end of the list */
1461     if (!last) {
1462       olsr_cnf->smart_gw_egress_interfaces = in;
1463     } else {
1464       last->next = in;
1465     }
1466     free($1);
1467   }
1468 }
1469 ;
1470
1471 ssmart_gw_egress_file: TOK_SMART_GW_EGRESS_FILE TOK_STRING
1472 {
1473   PARSER_DEBUG_PRINTF("Smart gateway egress file: %s\n", $2->string);
1474   if (olsr_cnf->smart_gw_egress_file) free(olsr_cnf->smart_gw_egress_file);
1475   olsr_cnf->smart_gw_egress_file = $2->string;
1476   free($2);
1477 }
1478 ;
1479
1480 ismart_gw_egress_file_period: TOK_SMART_GW_EGRESS_FILE_PERIOD TOK_INTEGER
1481 {
1482   PARSER_DEBUG_PRINTF("Smart gateway egress file period: %d\n", $2->integer);
1483   olsr_cnf->smart_gw_egress_file_period = $2->integer;
1484   free($2);
1485 }
1486 ;
1487
1488 ssmart_gw_status_file: TOK_SMART_GW_STATUS_FILE TOK_STRING
1489 {
1490   PARSER_DEBUG_PRINTF("Smart gateway status file: %s\n", $2->string);
1491   if (olsr_cnf->smart_gw_status_file) free(olsr_cnf->smart_gw_status_file);
1492   olsr_cnf->smart_gw_status_file = $2->string;
1493   free($2);
1494 }
1495 ;
1496
1497 ismart_gw_offset_tables: TOK_SMART_GW_OFFSET_TABLES TOK_INTEGER
1498 {
1499   PARSER_DEBUG_PRINTF("Smart gateway tables offset: %d\n", $2->integer);
1500   olsr_cnf->smart_gw_offset_tables = $2->integer;
1501   free($2);
1502 }
1503 ;
1504
1505 ismart_gw_offset_rules: TOK_SMART_GW_OFFSET_RULES TOK_INTEGER
1506 {
1507   PARSER_DEBUG_PRINTF("Smart gateway rules offset: %d\n", $2->integer);
1508   olsr_cnf->smart_gw_offset_rules = $2->integer;
1509   free($2);
1510 }
1511 ;
1512
1513 bsmart_gw_allow_nat: TOK_SMART_GW_ALLOW_NAT TOK_BOOLEAN
1514 {
1515         PARSER_DEBUG_PRINTF("Smart gateway allow client nat: %s\n", $2->boolean ? "yes" : "no");
1516         olsr_cnf->smart_gw_allow_nat = $2->boolean;
1517         free($2);
1518 }
1519 ;
1520
1521 ismart_gw_period: TOK_SMART_GW_PERIOD TOK_INTEGER
1522 {
1523   PARSER_DEBUG_PRINTF("Smart gateway period: %d\n", $2->integer);
1524   olsr_cnf->smart_gw_period = $2->integer;
1525   free($2);
1526 }
1527 ;
1528
1529 asmart_gw_stablecount: TOK_SMART_GW_STABLECOUNT TOK_INTEGER
1530 {
1531   PARSER_DEBUG_PRINTF("Smart gateway stablecount: %d\n", $2->integer);
1532   olsr_cnf->smart_gw_stablecount = $2->integer;
1533   free($2);
1534 }
1535 ;
1536
1537 asmart_gw_thresh: TOK_SMART_GW_THRESH TOK_INTEGER
1538 {
1539   PARSER_DEBUG_PRINTF("Smart gateway threshold: %d\n", $2->integer);
1540   olsr_cnf->smart_gw_thresh = $2->integer;
1541   free($2);
1542 }
1543 ;
1544
1545 asmart_gw_weight_exitlink_up: TOK_SMART_GW_WEIGHT_EXITLINK_UP TOK_INTEGER
1546 {
1547   PARSER_DEBUG_PRINTF("Smart gateway exitlink uplink weight: %d\n", $2->integer);
1548   olsr_cnf->smart_gw_weight_exitlink_up = $2->integer;
1549   free($2);
1550 }
1551 ;
1552
1553 asmart_gw_weight_exitlink_down: TOK_SMART_GW_WEIGHT_EXITLINK_DOWN TOK_INTEGER
1554 {
1555   PARSER_DEBUG_PRINTF("Smart gateway exitlink downlink weight: %d\n", $2->integer);
1556   olsr_cnf->smart_gw_weight_exitlink_down = $2->integer;
1557   free($2);
1558 }
1559 ;
1560
1561 asmart_gw_weight_etx: TOK_SMART_GW_WEIGHT_ETX TOK_INTEGER
1562 {
1563   PARSER_DEBUG_PRINTF("Smart gateway ETX weight: %d\n", $2->integer);
1564   olsr_cnf->smart_gw_weight_etx = $2->integer;
1565   free($2);
1566 }
1567 ;
1568
1569 asmart_gw_divider_etx: TOK_SMART_GW_DIVIDER_ETX TOK_INTEGER
1570 {
1571   PARSER_DEBUG_PRINTF("Smart gateway ETX divider: %d\n", $2->integer);
1572   olsr_cnf->smart_gw_divider_etx = $2->integer;
1573   free($2);
1574 }
1575 ;
1576
1577 asmart_gw_divider_etx: TOK_SMART_GW_MAX_COST_MAX_ETX TOK_INTEGER
1578 {
1579   PARSER_DEBUG_PRINTF("Smart gateway max cost max ETX: %d\n", $2->integer);
1580   olsr_cnf->smart_gw_path_max_cost_etx_max = $2->integer;
1581   free($2);
1582 }
1583 ;
1584
1585 ssmart_gw_uplink: TOK_SMART_GW_UPLINK TOK_STRING
1586 {
1587         PARSER_DEBUG_PRINTF("Smart gateway uplink: %s\n", $2->string);
1588         if (strcasecmp($2->string, GW_UPLINK_TXT[GW_UPLINK_NONE]) == 0) {
1589                 olsr_cnf->smart_gw_type = GW_UPLINK_NONE;
1590         }
1591         else if (strcasecmp($2->string, GW_UPLINK_TXT[GW_UPLINK_IPV4]) == 0) {
1592                 olsr_cnf->smart_gw_type = GW_UPLINK_IPV4;
1593         }
1594         else if (strcasecmp($2->string, GW_UPLINK_TXT[GW_UPLINK_IPV6]) == 0) {
1595                 olsr_cnf->smart_gw_type = GW_UPLINK_IPV6;
1596         }
1597         else if (strcasecmp($2->string, GW_UPLINK_TXT[GW_UPLINK_IPV46]) == 0) {
1598                 olsr_cnf->smart_gw_type = GW_UPLINK_IPV46;
1599         }
1600         else {
1601                 fprintf(stderr, "Bad gateway uplink type: %s\n", $2->string);
1602                 YYABORT;
1603         }
1604         free($2);
1605 }
1606 ;
1607
1608 ismart_gw_speed: TOK_SMART_GW_SPEED TOK_INTEGER TOK_INTEGER
1609 {
1610         PARSER_DEBUG_PRINTF("Smart gateway speed: %u uplink/%u downlink kbit/s\n", $2->integer, $3->integer);
1611         smartgw_set_uplink(olsr_cnf, $2->integer);
1612         smartgw_set_downlink(olsr_cnf, $3->integer);
1613         free($2);
1614         free($3);
1615 }
1616 ;
1617
1618 bsmart_gw_uplink_nat: TOK_SMART_GW_UPLINK_NAT TOK_BOOLEAN
1619 {
1620         PARSER_DEBUG_PRINTF("Smart gateway uplink nat: %s\n", $2->boolean ? "yes" : "no");
1621         olsr_cnf->smart_gw_uplink_nat = $2->boolean;
1622         free($2);
1623 }
1624 ;
1625
1626 ismart_gw_prefix: TOK_SMART_GW_PREFIX TOK_IPV6_ADDR TOK_INTEGER
1627 {
1628   PARSER_DEBUG_PRINTF("Smart gateway prefix: %s %u\n", $2->string, $3->integer);
1629         if (inet_pton(olsr_cnf->ip_version, $2->string, &olsr_cnf->smart_gw_prefix.prefix) == 0) {
1630           fprintf(stderr, "Bad IP part of gateway prefix: %s\n", $2->string);
1631     YYABORT;
1632   }
1633         olsr_cnf->smart_gw_prefix.prefix_len = (uint8_t)$3->integer;
1634         
1635         free($2);
1636         free($3);
1637 }
1638         |       TOK_SMART_GW_PREFIX TOK_IPV6_ADDR TOK_SLASH TOK_INTEGER
1639 {
1640         PARSER_DEBUG_PRINTF("Smart gateway prefix: %s %u\n", $2->string, $4->integer);
1641         if (inet_pton(olsr_cnf->ip_version, $2->string, &olsr_cnf->smart_gw_prefix.prefix) == 0) {
1642           fprintf(stderr, "Bad IP part of gateway prefix: %s\n", $2->string);
1643     YYABORT;
1644   }
1645         olsr_cnf->smart_gw_prefix.prefix_len = (uint8_t)$4->integer;
1646         
1647         free($2);
1648         free($4);
1649 }
1650 ;
1651
1652 bsrc_ip_routes: TOK_SRC_IP_ROUTES TOK_BOOLEAN
1653 {
1654         PARSER_DEBUG_PRINTF("Use originator for routes src-ip: %s\n", $2->boolean ? "yes" : "no");
1655         if (olsr_cnf->ip_version != AF_INET) {
1656           fprintf(stderr, "Source ip routes not possible with IPV6\n");
1657           YYABORT;
1658         }
1659         else olsr_cnf->use_src_ip_routes = $2->boolean;
1660         free($2);
1661 }
1662 ;
1663
1664 amain_ip: TOK_MAIN_IP TOK_IPV4_ADDR
1665 {
1666   PARSER_DEBUG_PRINTF("Fixed Main IP: %s\n", $2->string);
1667   
1668   if (olsr_cnf->ip_version != AF_INET
1669       || inet_pton(olsr_cnf->ip_version, $2->string, &olsr_cnf->main_addr) != 1) {
1670     fprintf(stderr, "Bad main IP: %s\n", $2->string);
1671     YYABORT;
1672   }
1673   else olsr_cnf->unicast_src_ip = olsr_cnf->main_addr;
1674   free($2);
1675 }
1676         |       TOK_MAIN_IP TOK_IPV6_ADDR
1677 {
1678   PARSER_DEBUG_PRINTF("Fixed Main IP: %s\n", $2->string);
1679   
1680   if (olsr_cnf->ip_version != AF_INET6
1681       || inet_pton(olsr_cnf->ip_version, $2->string, &olsr_cnf->main_addr) != 1) {
1682     fprintf(stderr, "Bad main IP: %s\n", $2->string);
1683     YYABORT;
1684   }
1685   free($2);
1686 }
1687 ;
1688
1689 bset_ipforward: TOK_SET_IPFORWARD TOK_BOOLEAN
1690 {
1691   PARSER_DEBUG_PRINTF("Set IP-Forward procfile variable: %s\n", $2->boolean ? "yes" : "no");
1692   olsr_cnf->set_ip_forward = $2->boolean;
1693   free($2);
1694 }
1695 ;
1696
1697
1698 plblock: TOK_PLUGIN TOK_STRING
1699 {
1700   struct plugin_entry *pe, *last;
1701   
1702   pe = olsr_cnf->plugins;
1703   last = NULL;
1704   while (pe != NULL) {
1705     if (strcmp(pe->name, $2->string) == 0) {
1706       free ($2->string);
1707       break;
1708     }
1709     last = pe;
1710     pe = pe->next;
1711   }
1712
1713   if (pe != NULL) {
1714     /* remove old plugin from list to add it later at the beginning */
1715     if (last) {
1716       last->next = pe->next;
1717     }
1718     else {
1719       olsr_cnf->plugins = pe->next;
1720     }
1721   }
1722   else {
1723     pe = malloc(sizeof(*pe));
1724
1725     if (pe == NULL) {
1726       fprintf(stderr, "Out of memory(ADD PL)\n");
1727       YYABORT;
1728     }
1729
1730     pe->name = $2->string;
1731     pe->params = NULL;
1732
1733     PARSER_DEBUG_PRINTF("Plugin: %s\n", $2->string);
1734   }
1735   
1736   /* Queue */
1737   pe->next = olsr_cnf->plugins;
1738   olsr_cnf->plugins = pe;
1739
1740   free($2);
1741 }
1742 ;
1743
1744 plparam: TOK_PLPARAM TOK_STRING TOK_STRING
1745 {
1746   struct plugin_param *pp = malloc(sizeof(*pp));
1747   char *p;
1748   
1749   if (pp == NULL) {
1750     fprintf(stderr, "Out of memory(ADD PP)\n");
1751     YYABORT;
1752   }
1753   
1754   PARSER_DEBUG_PRINTF("Plugin param key:\"%s\" val: \"%s\"\n", $2->string, $3->string);
1755   
1756   pp->key = $2->string;
1757   pp->value = $3->string;
1758
1759   /* Lower-case the key */
1760   for (p = pp->key; *p; p++) {
1761     *p = tolower(*p);
1762   }
1763
1764   /* Queue */
1765   pp->next = olsr_cnf->plugins->params;
1766   olsr_cnf->plugins->params = pp;
1767
1768   free($2);
1769   free($3);
1770 }
1771 ;
1772
1773 vcomment:       TOK_COMMENT
1774 {
1775     //PARSER_DEBUG_PRINTF("Comment\n");
1776 }
1777 ;
1778
1779
1780
1781 %%
1782
1783 void yyerror (const char *string)
1784 {
1785   fprintf(stderr, "Config line %d: %s\n", current_line, string);
1786 }