1  | 
     | 
     | 
    /*	$OpenBSD: conf.y,v 1.19 2017/04/09 02:40:24 jsg Exp $	*/  | 
    
    
    2  | 
     | 
     | 
     | 
    
    
    3  | 
     | 
     | 
    /*  | 
    
    
    4  | 
     | 
     | 
     * Copyright (c) 2005 Håkan Olsson.  All rights reserved.  | 
    
    
    5  | 
     | 
     | 
     *  | 
    
    
    6  | 
     | 
     | 
     * Redistribution and use in source and binary forms, with or without  | 
    
    
    7  | 
     | 
     | 
     * modification, are permitted provided that the following conditions  | 
    
    
    8  | 
     | 
     | 
     * are met:  | 
    
    
    9  | 
     | 
     | 
     *  | 
    
    
    10  | 
     | 
     | 
     * 1. Redistributions of source code must retain the above copyright  | 
    
    
    11  | 
     | 
     | 
     *    notice, this list of conditions and the following disclaimer.  | 
    
    
    12  | 
     | 
     | 
     * 2. Redistributions in binary form must reproduce the above copyright  | 
    
    
    13  | 
     | 
     | 
     *    notice, this list of conditions and the following disclaimer in the  | 
    
    
    14  | 
     | 
     | 
     *    documentation and/or other materials provided with the distribution.  | 
    
    
    15  | 
     | 
     | 
     *  | 
    
    
    16  | 
     | 
     | 
     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR  | 
    
    
    17  | 
     | 
     | 
     * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES  | 
    
    
    18  | 
     | 
     | 
     * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  | 
    
    
    19  | 
     | 
     | 
     * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,  | 
    
    
    20  | 
     | 
     | 
     * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT  | 
    
    
    21  | 
     | 
     | 
     * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,  | 
    
    
    22  | 
     | 
     | 
     * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY  | 
    
    
    23  | 
     | 
     | 
     * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT  | 
    
    
    24  | 
     | 
     | 
     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF  | 
    
    
    25  | 
     | 
     | 
     * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  | 
    
    
    26  | 
     | 
     | 
     */  | 
    
    
    27  | 
     | 
     | 
     | 
    
    
    28  | 
     | 
     | 
    /* Definitions */  | 
    
    
    29  | 
     | 
     | 
    %{ | 
    
    
    30  | 
     | 
     | 
    #include <sys/types.h>  | 
    
    
    31  | 
     | 
     | 
    #include <sys/stat.h>  | 
    
    
    32  | 
     | 
     | 
    #include <sys/socket.h>  | 
    
    
    33  | 
     | 
     | 
    #include <ctype.h>  | 
    
    
    34  | 
     | 
     | 
    #include <fcntl.h>  | 
    
    
    35  | 
     | 
     | 
    #include <stdio.h>  | 
    
    
    36  | 
     | 
     | 
    #include <stdlib.h>  | 
    
    
    37  | 
     | 
     | 
    #include <string.h>  | 
    
    
    38  | 
     | 
     | 
    #include <unistd.h>  | 
    
    
    39  | 
     | 
     | 
    #include <pwd.h>  | 
    
    
    40  | 
     | 
     | 
     | 
    
    
    41  | 
     | 
     | 
    #include "sasyncd.h"  | 
    
    
    42  | 
     | 
     | 
    #include "net.h"  | 
    
    
    43  | 
     | 
     | 
     | 
    
    
    44  | 
     | 
     | 
    /* Global configuration context.  */  | 
    
    
    45  | 
     | 
     | 
    struct cfgstate	cfgstate;  | 
    
    
    46  | 
     | 
     | 
     | 
    
    
    47  | 
     | 
     | 
    /* Local variables */  | 
    
    
    48  | 
     | 
     | 
    int	conflen = 0;  | 
    
    
    49  | 
     | 
     | 
    char	*confbuf, *confptr;  | 
    
    
    50  | 
     | 
     | 
     | 
    
    
    51  | 
     | 
     | 
    int	yyparse(void);  | 
    
    
    52  | 
     | 
     | 
    int	yylex(void);  | 
    
    
    53  | 
     | 
     | 
    void	yyerror(const char *);  | 
    
    
    54  | 
     | 
     | 
    unsigned char x2i(unsigned char *);  | 
    
    
    55  | 
     | 
     | 
    %}  | 
    
    
    56  | 
     | 
     | 
     | 
    
    
    57  | 
     | 
     | 
    %union { | 
    
    
    58  | 
     | 
     | 
    	char	*string;  | 
    
    
    59  | 
     | 
     | 
    	int	 val;  | 
    
    
    60  | 
     | 
     | 
    	struct { | 
    
    
    61  | 
     | 
     | 
    		unsigned char	*data;  | 
    
    
    62  | 
     | 
     | 
    		int	 len;  | 
    
    
    63  | 
     | 
     | 
    	} hex;  | 
    
    
    64  | 
     | 
     | 
    }  | 
    
    
    65  | 
     | 
     | 
     | 
    
    
    66  | 
     | 
     | 
    %token MODE INTERFACE INTERVAL LISTEN ON PORT PEER SHAREDKEY  | 
    
    
    67  | 
     | 
     | 
    %token Y_SLAVE Y_MASTER INET INET6 FLUSHMODE STARTUP NEVER SYNC  | 
    
    
    68  | 
     | 
     | 
    %token GROUP SKIPSLAVE CONTROL  | 
    
    
    69  | 
     | 
     | 
    %token <string> STRING  | 
    
    
    70  | 
     | 
     | 
    %token <hex>	HEX  | 
    
    
    71  | 
     | 
     | 
    %token <val>	VALUE  | 
    
    
    72  | 
     | 
     | 
    %type  <val>	af port mode flushmode ctlmode  | 
    
    
    73  | 
     | 
     | 
     | 
    
    
    74  | 
     | 
     | 
    %%  | 
    
    
    75  | 
     | 
     | 
    /* Rules */  | 
    
    
    76  | 
     | 
     | 
     | 
    
    
    77  | 
     | 
     | 
    settings	: /* empty */  | 
    
    
    78  | 
     | 
     | 
    		| settings setting  | 
    
    
    79  | 
     | 
     | 
    		;  | 
    
    
    80  | 
     | 
     | 
     | 
    
    
    81  | 
     | 
     | 
    af		: /* empty */		{ $$ = AF_UNSPEC; } | 
    
    
    82  | 
     | 
     | 
    		| INET			{ $$ = AF_INET; } | 
    
    
    83  | 
     | 
     | 
    		| INET6			{ $$ = AF_INET6; } | 
    
    
    84  | 
     | 
     | 
    		;  | 
    
    
    85  | 
     | 
     | 
     | 
    
    
    86  | 
     | 
     | 
    port		: /* empty */		{ $$ = SASYNCD_DEFAULT_PORT; } | 
    
    
    87  | 
     | 
     | 
    		| PORT VALUE		{ $$ = $2; } | 
    
    
    88  | 
     | 
     | 
    		;  | 
    
    
    89  | 
     | 
     | 
     | 
    
    
    90  | 
     | 
     | 
    mode		: Y_MASTER		{ $$ = MASTER; } | 
    
    
    91  | 
     | 
     | 
    		| Y_SLAVE		{ $$ = SLAVE; } | 
    
    
    92  | 
     | 
     | 
    		;  | 
    
    
    93  | 
     | 
     | 
     | 
    
    
    94  | 
     | 
     | 
    modes		: SKIPSLAVE  | 
    
    
    95  | 
     | 
     | 
    		{ | 
    
    
    96  | 
     | 
     | 
    			cfgstate.flags |= SKIP_LOCAL_SAS;  | 
    
    
    97  | 
     | 
     | 
    			log_msg(2, "config: not syncing SA to peers");  | 
    
    
    98  | 
     | 
     | 
    		}  | 
    
    
    99  | 
     | 
     | 
    		| mode  | 
    
    
    100  | 
     | 
     | 
    		{ | 
    
    
    101  | 
     | 
     | 
    			const char *m[] = CARPSTATES;  | 
    
    
    102  | 
     | 
     | 
    			cfgstate.lockedstate = $1;  | 
    
    
    103  | 
     | 
     | 
    			log_msg(2, "config: mode set to %s", m[$1]);  | 
    
    
    104  | 
     | 
     | 
    		}  | 
    
    
    105  | 
     | 
     | 
    		;  | 
    
    
    106  | 
     | 
     | 
     | 
    
    
    107  | 
     | 
     | 
    flushmode	: STARTUP		{ $$ = FM_STARTUP; } | 
    
    
    108  | 
     | 
     | 
    		| NEVER			{ $$ = FM_NEVER; } | 
    
    
    109  | 
     | 
     | 
    		| SYNC			{ $$ = FM_SYNC; } | 
    
    
    110  | 
     | 
     | 
    		;  | 
    
    
    111  | 
     | 
     | 
     | 
    
    
    112  | 
     | 
     | 
    key		: STRING  | 
    
    
    113  | 
     | 
     | 
    		{ | 
    
    
    114  | 
     | 
     | 
    			if (cfgstate.sharedkey)  | 
    
    
    115  | 
     | 
     | 
    				free(cfgstate.sharedkey);  | 
    
    
    116  | 
     | 
     | 
    			cfgstate.sharedkey = $1;  | 
    
    
    117  | 
     | 
     | 
    			cfgstate.sharedkey_len = strlen($1) * 8;  | 
    
    
    118  | 
     | 
     | 
    			log_msg(2, "config: shared ascii key");  | 
    
    
    119  | 
     | 
     | 
    		}  | 
    
    
    120  | 
     | 
     | 
    		| HEX  | 
    
    
    121  | 
     | 
     | 
    		{ | 
    
    
    122  | 
     | 
     | 
    			if (cfgstate.sharedkey)  | 
    
    
    123  | 
     | 
     | 
    				free(cfgstate.sharedkey);  | 
    
    
    124  | 
     | 
     | 
    			cfgstate.sharedkey = $1.data;  | 
    
    
    125  | 
     | 
     | 
    			cfgstate.sharedkey_len = $1.len * 8;  | 
    
    
    126  | 
     | 
     | 
    			log_msg(2, "config: %d byte shared hex key", $1.len);  | 
    
    
    127  | 
     | 
     | 
    		}  | 
    
    
    128  | 
     | 
     | 
     | 
    
    
    129  | 
     | 
     | 
    ctlmode		: STRING  | 
    
    
    130  | 
     | 
     | 
    		{ | 
    
    
    131  | 
     | 
     | 
    			/* Compare strings to avoid keywords for daemons */  | 
    
    
    132  | 
     | 
     | 
    			if (strcmp("isakmpd", $1) == 0) | 
    
    
    133  | 
     | 
     | 
    				$$ = CTL_ISAKMPD;  | 
    
    
    134  | 
     | 
     | 
    			else if (strcmp("iked", $1) == 0) | 
    
    
    135  | 
     | 
     | 
    				$$ = CTL_IKED;  | 
    
    
    136  | 
     | 
     | 
    			else if (strcmp("all", $1) == 0) | 
    
    
    137  | 
     | 
     | 
    				$$ = CTL_MASK;  | 
    
    
    138  | 
     | 
     | 
    			else if (strcmp("none", $1) == 0) | 
    
    
    139  | 
     | 
     | 
    				$$ = CTL_NONE;  | 
    
    
    140  | 
     | 
     | 
    			else { | 
    
    
    141  | 
     | 
     | 
    				log_err("config: invalid control mode"); | 
    
    
    142  | 
     | 
     | 
    				free($1);  | 
    
    
    143  | 
     | 
     | 
    				YYERROR;  | 
    
    
    144  | 
     | 
     | 
    			}  | 
    
    
    145  | 
     | 
     | 
    			log_msg(2, "config: control mode set to %s", $1);  | 
    
    
    146  | 
     | 
     | 
    			free($1);  | 
    
    
    147  | 
     | 
     | 
    		}  | 
    
    
    148  | 
     | 
     | 
    		;  | 
    
    
    149  | 
     | 
     | 
     | 
    
    
    150  | 
     | 
     | 
    setting		: INTERFACE STRING  | 
    
    
    151  | 
     | 
     | 
    		{ | 
    
    
    152  | 
     | 
     | 
    			if (cfgstate.carp_ifname)  | 
    
    
    153  | 
     | 
     | 
    				free(cfgstate.carp_ifname);  | 
    
    
    154  | 
     | 
     | 
    			cfgstate.carp_ifname = $2;  | 
    
    
    155  | 
     | 
     | 
    			log_msg(2, "config: interface %s",  | 
    
    
    156  | 
     | 
     | 
    			    cfgstate.carp_ifname);  | 
    
    
    157  | 
     | 
     | 
    		}  | 
    
    
    158  | 
     | 
     | 
    		| GROUP STRING  | 
    
    
    159  | 
     | 
     | 
    		{ | 
    
    
    160  | 
     | 
     | 
    			if (cfgstate.carp_ifgroup)  | 
    
    
    161  | 
     | 
     | 
    				free(cfgstate.carp_ifgroup);  | 
    
    
    162  | 
     | 
     | 
    			cfgstate.carp_ifgroup = $2;  | 
    
    
    163  | 
     | 
     | 
    			log_msg(2, "config: group %s",  | 
    
    
    164  | 
     | 
     | 
    			    cfgstate.carp_ifgroup);  | 
    
    
    165  | 
     | 
     | 
    		}  | 
    
    
    166  | 
     | 
     | 
    		| FLUSHMODE flushmode  | 
    
    
    167  | 
     | 
     | 
    		{ | 
    
    
    168  | 
     | 
     | 
    			const char *fm[] = { "STARTUP", "NEVER", "SYNC" }; | 
    
    
    169  | 
     | 
     | 
    			cfgstate.flags |= $2;  | 
    
    
    170  | 
     | 
     | 
    			log_msg(2, "config: flush mode set to %s", fm[$2]);  | 
    
    
    171  | 
     | 
     | 
    		}  | 
    
    
    172  | 
     | 
     | 
    		| PEER STRING  | 
    
    
    173  | 
     | 
     | 
    		{ | 
    
    
    174  | 
     | 
     | 
    			struct syncpeer	*peer;  | 
    
    
    175  | 
     | 
     | 
    			int		 duplicate = 0;  | 
    
    
    176  | 
     | 
     | 
     | 
    
    
    177  | 
     | 
     | 
    			for (peer = LIST_FIRST(&cfgstate.peerlist); peer;  | 
    
    
    178  | 
     | 
     | 
    			     peer = LIST_NEXT(peer, link))  | 
    
    
    179  | 
     | 
     | 
    				if (strcmp($2, peer->name) == 0) { | 
    
    
    180  | 
     | 
     | 
    					duplicate++;  | 
    
    
    181  | 
     | 
     | 
    					break;  | 
    
    
    182  | 
     | 
     | 
    				}  | 
    
    
    183  | 
     | 
     | 
    			if (duplicate)  | 
    
    
    184  | 
     | 
     | 
    				free($2);  | 
    
    
    185  | 
     | 
     | 
    			else { | 
    
    
    186  | 
     | 
     | 
    				peer = calloc(1, sizeof *peer);  | 
    
    
    187  | 
     | 
     | 
    				if (!peer) { | 
    
    
    188  | 
     | 
     | 
    					log_err("config: calloc(1, %lu) " | 
    
    
    189  | 
     | 
     | 
    					    "failed", sizeof *peer);  | 
    
    
    190  | 
     | 
     | 
    					free($2);  | 
    
    
    191  | 
     | 
     | 
    					YYERROR;  | 
    
    
    192  | 
     | 
     | 
    				}  | 
    
    
    193  | 
     | 
     | 
    				peer->name = $2;  | 
    
    
    194  | 
     | 
     | 
    			}  | 
    
    
    195  | 
     | 
     | 
    			LIST_INSERT_HEAD(&cfgstate.peerlist, peer, link);  | 
    
    
    196  | 
     | 
     | 
    			cfgstate.peercnt++;  | 
    
    
    197  | 
     | 
     | 
    			log_msg(2, "config: add peer %s", peer->name);  | 
    
    
    198  | 
     | 
     | 
    		}  | 
    
    
    199  | 
     | 
     | 
    		| LISTEN ON STRING af port  | 
    
    
    200  | 
     | 
     | 
    		{ | 
    
    
    201  | 
     | 
     | 
    			char pstr[20];  | 
    
    
    202  | 
     | 
     | 
     | 
    
    
    203  | 
     | 
     | 
    			if (cfgstate.listen_on)  | 
    
    
    204  | 
     | 
     | 
    				free(cfgstate.listen_on);  | 
    
    
    205  | 
     | 
     | 
    			cfgstate.listen_on = $3;  | 
    
    
    206  | 
     | 
     | 
    			cfgstate.listen_family = $4;  | 
    
    
    207  | 
     | 
     | 
    			cfgstate.listen_port = $5;  | 
    
    
    208  | 
     | 
     | 
    			if ($5 < 1 || $5 > IPPORT_HILASTAUTO) { | 
    
    
    209  | 
     | 
     | 
    				cfgstate.listen_port = SASYNCD_DEFAULT_PORT;  | 
    
    
    210  | 
     | 
     | 
    				log_msg(0, "config: bad port, listen-port "  | 
    
    
    211  | 
     | 
     | 
    				    "reset to %u", SASYNCD_DEFAULT_PORT);  | 
    
    
    212  | 
     | 
     | 
    			}  | 
    
    
    213  | 
     | 
     | 
    			if ($5 != SASYNCD_DEFAULT_PORT)  | 
    
    
    214  | 
     | 
     | 
    				snprintf(pstr, sizeof pstr, "port %d",$5);  | 
    
    
    215  | 
     | 
     | 
    			log_msg(2, "config: listen on %s %s%s",  | 
    
    
    216  | 
     | 
     | 
    			    cfgstate.listen_on, $4 == AF_INET6 ? "(IPv6) " :  | 
    
    
    217  | 
     | 
     | 
    			    ($4 == AF_INET ? "(IPv4) " : ""),  | 
    
    
    218  | 
     | 
     | 
    			    $5 != SASYNCD_DEFAULT_PORT ? pstr : "");  | 
    
    
    219  | 
     | 
     | 
    		}  | 
    
    
    220  | 
     | 
     | 
    		| MODE modes  | 
    
    
    221  | 
     | 
     | 
    		| SHAREDKEY key  | 
    
    
    222  | 
     | 
     | 
    		{ | 
    
    
    223  | 
     | 
     | 
    			int bits;  | 
    
    
    224  | 
     | 
     | 
     | 
    
    
    225  | 
     | 
     | 
    			bits = cfgstate.sharedkey_len;  | 
    
    
    226  | 
     | 
     | 
    			if (bits != 128 && bits != 192 && bits != 256) { | 
    
    
    227  | 
     | 
     | 
    				log_err("config: bad shared key length %d, " | 
    
    
    228  | 
     | 
     | 
    				    "should be 128, 192 or 256 bits\n", bits);  | 
    
    
    229  | 
     | 
     | 
    				YYERROR;  | 
    
    
    230  | 
     | 
     | 
    			}  | 
    
    
    231  | 
     | 
     | 
    			log_msg(2, "config: shared key set");  | 
    
    
    232  | 
     | 
     | 
    		}  | 
    
    
    233  | 
     | 
     | 
    		| CONTROL ctlmode  | 
    
    
    234  | 
     | 
     | 
    		{ | 
    
    
    235  | 
     | 
     | 
    			cfgstate.flags &= ~CTL_MASK;  | 
    
    
    236  | 
     | 
     | 
    			cfgstate.flags |= $2;  | 
    
    
    237  | 
     | 
     | 
    		}  | 
    
    
    238  | 
     | 
     | 
    		;  | 
    
    
    239  | 
     | 
     | 
     | 
    
    
    240  | 
     | 
     | 
    %%  | 
    
    
    241  | 
     | 
     | 
    /* Program */  | 
    
    
    242  | 
     | 
     | 
     | 
    
    
    243  | 
     | 
     | 
    struct keyword { | 
    
    
    244  | 
     | 
     | 
    	char *name;  | 
    
    
    245  | 
     | 
     | 
    	int   value;  | 
    
    
    246  | 
     | 
     | 
    };  | 
    
    
    247  | 
     | 
     | 
     | 
    
    
    248  | 
     | 
     | 
    static int  | 
    
    
    249  | 
     | 
     | 
    match_cmp(const void *a, const void *b)  | 
    
    
    250  | 
     | 
     | 
    { | 
    
    
    251  | 
     | 
     | 
    	return strcmp(a, ((const struct keyword *)b)->name);  | 
    
    
    252  | 
     | 
     | 
    }  | 
    
    
    253  | 
     | 
     | 
     | 
    
    
    254  | 
     | 
     | 
    static int  | 
    
    
    255  | 
     | 
     | 
    match(char *token)  | 
    
    
    256  | 
     | 
     | 
    { | 
    
    
    257  | 
     | 
     | 
    	/* Sorted */  | 
    
    
    258  | 
     | 
     | 
    	static const struct keyword keywords[] = { | 
    
    
    259  | 
     | 
     | 
    		{ "control", CONTROL }, | 
    
    
    260  | 
     | 
     | 
    		{ "flushmode", FLUSHMODE }, | 
    
    
    261  | 
     | 
     | 
    		{ "group", GROUP }, | 
    
    
    262  | 
     | 
     | 
    		{ "inet", INET }, | 
    
    
    263  | 
     | 
     | 
    		{ "inet6", INET6 }, | 
    
    
    264  | 
     | 
     | 
    		{ "interface", INTERFACE }, | 
    
    
    265  | 
     | 
     | 
    		{ "listen", LISTEN }, | 
    
    
    266  | 
     | 
     | 
    		{ "master", Y_MASTER }, | 
    
    
    267  | 
     | 
     | 
    		{ "mode", MODE }, | 
    
    
    268  | 
     | 
     | 
    		{ "never", NEVER }, | 
    
    
    269  | 
     | 
     | 
    		{ "on", ON }, | 
    
    
    270  | 
     | 
     | 
    		{ "peer", PEER }, | 
    
    
    271  | 
     | 
     | 
    		{ "port", PORT }, | 
    
    
    272  | 
     | 
     | 
    		{ "sharedkey", SHAREDKEY }, | 
    
    
    273  | 
     | 
     | 
    		{ "skipslave", SKIPSLAVE }, | 
    
    
    274  | 
     | 
     | 
    		{ "slave", Y_SLAVE }, | 
    
    
    275  | 
     | 
     | 
    		{ "startup", STARTUP }, | 
    
    
    276  | 
     | 
     | 
    		{ "sync", SYNC }, | 
    
    
    277  | 
     | 
     | 
    	};  | 
    
    
    278  | 
     | 
     | 
    	const struct keyword *k;  | 
    
    
    279  | 
     | 
     | 
     | 
    
    
    280  | 
     | 
     | 
    	k = bsearch(token, keywords, sizeof keywords / sizeof keywords[0],  | 
    
    
    281  | 
     | 
     | 
    	    sizeof keywords[0], match_cmp);  | 
    
    
    282  | 
     | 
     | 
     | 
    
    
    283  | 
     | 
     | 
    	return k ? k->value : STRING;  | 
    
    
    284  | 
     | 
     | 
    }  | 
    
    
    285  | 
     | 
     | 
     | 
    
    
    286  | 
     | 
     | 
    int  | 
    
    
    287  | 
     | 
     | 
    yylex(void)  | 
    
    
    288  | 
     | 
     | 
    { | 
    
    
    289  | 
     | 
     | 
    	char *p;  | 
    
    
    290  | 
     | 
     | 
    	int v, i, len;  | 
    
    
    291  | 
     | 
     | 
     | 
    
    
    292  | 
     | 
     | 
    	/* Locate next token */  | 
    
    
    293  | 
     | 
     | 
    	if (!confptr)  | 
    
    
    294  | 
     | 
     | 
    		confptr = confbuf;  | 
    
    
    295  | 
     | 
     | 
    	else { | 
    
    
    296  | 
     | 
     | 
    		for (p = confptr; p < confbuf + conflen && *p; p++)  | 
    
    
    297  | 
     | 
     | 
    			;  | 
    
    
    298  | 
     | 
     | 
    		if (p == confbuf + conflen)  | 
    
    
    299  | 
     | 
     | 
    			return 0;  | 
    
    
    300  | 
     | 
     | 
    		p++;  | 
    
    
    301  | 
     | 
     | 
    		if (!*p)  | 
    
    
    302  | 
     | 
     | 
    			return 0;  | 
    
    
    303  | 
     | 
     | 
    		confptr = p;  | 
    
    
    304  | 
     | 
     | 
    	}  | 
    
    
    305  | 
     | 
     | 
     | 
    
    
    306  | 
     | 
     | 
    	/* Hex token? */  | 
    
    
    307  | 
     | 
     | 
    	p = confptr;  | 
    
    
    308  | 
     | 
     | 
    	if (!strncmp(p, "0x", 2)) { | 
    
    
    309  | 
     | 
     | 
    		for (p = confptr + 2; *p; p++)  | 
    
    
    310  | 
     | 
     | 
    			if (!isxdigit(*p))  | 
    
    
    311  | 
     | 
     | 
    				goto is_string;  | 
    
    
    312  | 
     | 
     | 
    		p = confptr + 2;  | 
    
    
    313  | 
     | 
     | 
    		len = strlen(p) / 2;  | 
    
    
    314  | 
     | 
     | 
    		if ((yylval.hex.data = calloc(len, sizeof(unsigned char)))  | 
    
    
    315  | 
     | 
     | 
    		    == NULL) { | 
    
    
    316  | 
     | 
     | 
    			log_err("yylex: calloc()"); | 
    
    
    317  | 
     | 
     | 
    			exit(1);  | 
    
    
    318  | 
     | 
     | 
    		}  | 
    
    
    319  | 
     | 
     | 
    		for (i = 0; i < len; i++)  | 
    
    
    320  | 
     | 
     | 
    			yylval.hex.data[i] = x2i(p + 2 * i);  | 
    
    
    321  | 
     | 
     | 
    		yylval.hex.len = len;  | 
    
    
    322  | 
     | 
     | 
    		return HEX;  | 
    
    
    323  | 
     | 
     | 
    	}  | 
    
    
    324  | 
     | 
     | 
     | 
    
    
    325  | 
     | 
     | 
    	/* Numerical token? */  | 
    
    
    326  | 
     | 
     | 
    	if (isdigit(*confptr)) { | 
    
    
    327  | 
     | 
     | 
    		for (p = confptr; *p; p++)  | 
    
    
    328  | 
     | 
     | 
    			if (*p == '.') /* IP address, or bad input */  | 
    
    
    329  | 
     | 
     | 
    				goto is_string;  | 
    
    
    330  | 
     | 
     | 
    		v = (int)strtol(confptr, (char **)NULL, 10);  | 
    
    
    331  | 
     | 
     | 
    		yylval.val = v;  | 
    
    
    332  | 
     | 
     | 
    		return VALUE;  | 
    
    
    333  | 
     | 
     | 
    	}  | 
    
    
    334  | 
     | 
     | 
     | 
    
    
    335  | 
     | 
     | 
      is_string:  | 
    
    
    336  | 
     | 
     | 
    	v = match(confptr);  | 
    
    
    337  | 
     | 
     | 
    	if (v == STRING) { | 
    
    
    338  | 
     | 
     | 
    		yylval.string = strdup(confptr);  | 
    
    
    339  | 
     | 
     | 
    		if (!yylval.string) { | 
    
    
    340  | 
     | 
     | 
    			log_err("yylex: strdup()"); | 
    
    
    341  | 
     | 
     | 
    			exit(1);  | 
    
    
    342  | 
     | 
     | 
    		}  | 
    
    
    343  | 
     | 
     | 
    	}  | 
    
    
    344  | 
     | 
     | 
    	return v;  | 
    
    
    345  | 
     | 
     | 
    }  | 
    
    
    346  | 
     | 
     | 
     | 
    
    
    347  | 
     | 
     | 
    int  | 
    
    
    348  | 
     | 
     | 
    conf_parse_file(char *cfgfile)  | 
    
    
    349  | 
     | 
     | 
    { | 
    
    
    350  | 
     | 
     | 
    	struct stat	st;  | 
    
    
    351  | 
     | 
     | 
    	int		fd, r;  | 
    
    
    352  | 
     | 
     | 
    	char		*buf, *s, *d;  | 
    
    
    353  | 
     | 
     | 
    	struct passwd	*pw;  | 
    
    
    354  | 
     | 
     | 
     | 
    
    
    355  | 
     | 
     | 
    	if (stat(cfgfile, &st) != 0)  | 
    
    
    356  | 
     | 
     | 
    		goto bad;  | 
    
    
    357  | 
     | 
     | 
     | 
    
    
    358  | 
     | 
     | 
    	pw = getpwnam(SASYNCD_USER);  | 
    
    
    359  | 
     | 
     | 
    	if (pw == NULL) { | 
    
    
    360  | 
     | 
     | 
    		log_err("getpwnam(%s) failed", SASYNCD_USER); | 
    
    
    361  | 
     | 
     | 
    		return 1;  | 
    
    
    362  | 
     | 
     | 
    	}  | 
    
    
    363  | 
     | 
     | 
     | 
    
    
    364  | 
     | 
     | 
    	/* Valid file? */  | 
    
    
    365  | 
     | 
     | 
    	if ((st.st_uid && st.st_uid != pw->pw_uid) ||  | 
    
    
    366  | 
     | 
     | 
    	    ((st.st_mode & S_IFMT) != S_IFREG) ||  | 
    
    
    367  | 
     | 
     | 
    	    ((st.st_mode & (S_IRWXG | S_IRWXO)) != 0)) { | 
    
    
    368  | 
     | 
     | 
    		log_msg(0, "configuration file has bad owner, type or mode");  | 
    
    
    369  | 
     | 
     | 
    		goto bad;  | 
    
    
    370  | 
     | 
     | 
    	}  | 
    
    
    371  | 
     | 
     | 
     | 
    
    
    372  | 
     | 
     | 
    	fd = open(cfgfile, O_RDONLY, 0);  | 
    
    
    373  | 
     | 
     | 
    	if (fd < 0)  | 
    
    
    374  | 
     | 
     | 
    		goto bad;  | 
    
    
    375  | 
     | 
     | 
     | 
    
    
    376  | 
     | 
     | 
    	conflen = st.st_size;  | 
    
    
    377  | 
     | 
     | 
    	buf = malloc(conflen + 1);  | 
    
    
    378  | 
     | 
     | 
    	if (!buf) { | 
    
    
    379  | 
     | 
     | 
    		log_err("malloc(%d) failed", conflen + 1); | 
    
    
    380  | 
     | 
     | 
    		close(fd);  | 
    
    
    381  | 
     | 
     | 
    		return 1;  | 
    
    
    382  | 
     | 
     | 
    	}  | 
    
    
    383  | 
     | 
     | 
     | 
    
    
    384  | 
     | 
     | 
    	if (read(fd, buf, conflen) != conflen) { | 
    
    
    385  | 
     | 
     | 
    		log_err("read() failed"); | 
    
    
    386  | 
     | 
     | 
    		free(buf);  | 
    
    
    387  | 
     | 
     | 
    		close(fd);  | 
    
    
    388  | 
     | 
     | 
    		return 1;  | 
    
    
    389  | 
     | 
     | 
    	}  | 
    
    
    390  | 
     | 
     | 
    	close(fd);  | 
    
    
    391  | 
     | 
     | 
     | 
    
    
    392  | 
     | 
     | 
    	/* Prepare the buffer somewhat in the way of strsep() */  | 
    
    
    393  | 
     | 
     | 
    	buf[conflen] = (char)0;  | 
    
    
    394  | 
     | 
     | 
    	for (s = buf, d = s; s < buf + conflen && *s; s++) { | 
    
    
    395  | 
     | 
     | 
    		if (isspace(*s) && isspace(*(s+1)))  | 
    
    
    396  | 
     | 
     | 
    			continue;  | 
    
    
    397  | 
     | 
     | 
    		if (*s == '#') { | 
    
    
    398  | 
     | 
     | 
    			while (*s != '\n' && s < buf + conflen)  | 
    
    
    399  | 
     | 
     | 
    				s++;  | 
    
    
    400  | 
     | 
     | 
    			continue;  | 
    
    
    401  | 
     | 
     | 
    		}  | 
    
    
    402  | 
     | 
     | 
    		if (d == buf && isspace(*s))  | 
    
    
    403  | 
     | 
     | 
    			continue;  | 
    
    
    404  | 
     | 
     | 
    		*d++ = *s;  | 
    
    
    405  | 
     | 
     | 
    	}  | 
    
    
    406  | 
     | 
     | 
    	*d = (char)0;  | 
    
    
    407  | 
     | 
     | 
    	for (s = buf; s <= d; s++)  | 
    
    
    408  | 
     | 
     | 
    		if (isspace(*s))  | 
    
    
    409  | 
     | 
     | 
    			*s = (char)0;  | 
    
    
    410  | 
     | 
     | 
     | 
    
    
    411  | 
     | 
     | 
    	confbuf = buf;  | 
    
    
    412  | 
     | 
     | 
    	confptr = NULL;  | 
    
    
    413  | 
     | 
     | 
    	r = yyparse();  | 
    
    
    414  | 
     | 
     | 
    	free(buf);  | 
    
    
    415  | 
     | 
     | 
     | 
    
    
    416  | 
     | 
     | 
    	if (!cfgstate.carp_ifgroup)  | 
    
    
    417  | 
     | 
     | 
    		cfgstate.carp_ifgroup = strdup("carp"); | 
    
    
    418  | 
     | 
     | 
     | 
    
    
    419  | 
     | 
     | 
    	return r;  | 
    
    
    420  | 
     | 
     | 
     | 
    
    
    421  | 
     | 
     | 
      bad:  | 
    
    
    422  | 
     | 
     | 
    	log_msg(0, "failed to open \"%s\"", cfgfile);  | 
    
    
    423  | 
     | 
     | 
    	return 1;  | 
    
    
    424  | 
     | 
     | 
    }  | 
    
    
    425  | 
     | 
     | 
     | 
    
    
    426  | 
     | 
     | 
    unsigned char  | 
    
    
    427  | 
     | 
     | 
    x2i(unsigned char *s)  | 
    
    
    428  | 
     | 
     | 
    { | 
    
    
    429  | 
     | 
     | 
            char    ss[3];  | 
    
    
    430  | 
     | 
     | 
     | 
    
    
    431  | 
     | 
     | 
            ss[0] = s[0];  | 
    
    
    432  | 
     | 
     | 
            ss[1] = s[1];  | 
    
    
    433  | 
     | 
     | 
            ss[2] = 0;  | 
    
    
    434  | 
     | 
     | 
     | 
    
    
    435  | 
     | 
     | 
            return ((unsigned char)strtoul(ss, NULL, 16));  | 
    
    
    436  | 
     | 
     | 
    }  | 
    
    
    437  | 
     | 
     | 
     | 
    
    
    438  | 
     | 
     | 
    void  | 
    
    
    439  | 
     | 
     | 
    yyerror(const char *s)  | 
    
    
    440  | 
     | 
     | 
    { | 
    
    
    441  | 
     | 
     | 
    	fprintf(stderr, "config: %s\n", s);  | 
    
    
    442  | 
     | 
     | 
    }  |