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