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