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