conffile.c revision 1.2
1/* $NetBSD: conffile.c,v 1.2 2010/12/30 21:26:00 christos Exp $ */ 2 3/* 4 * Copyright (c) 2010 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Mihai Chelaru <kefren@NetBSD.org> 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <arpa/inet.h> 33#include <netinet/in.h> 34 35#include <ctype.h> 36#include <fcntl.h> 37#include <stdlib.h> 38#include <string.h> 39#include <unistd.h> 40 41#include "conffile.h" 42#include "ldp_errors.h" 43 44#define NextCommand(x) strsep(&x, " ") 45#define LINEMAXSIZE 1024 46 47extern int ldp_hello_time, ldp_keepalive_time, ldp_holddown_time, command_port, 48 min_label, max_label; 49int confh; 50struct in_addr conf_ldp_id; 51 52static int conf_dispatch(char*); 53static int conf_readline(char*, size_t); 54static int checkeol(char*); 55static int Fhellotime(char*); 56static int Fport(char*); 57static int Fholddown(char*); 58static int Fkeepalive(char*); 59static int Fmaxlabel(char*); 60static int Fminlabel(char*); 61static int Fldpid(char*); 62static int Fneighbour(char*); 63static int Gneighbour(struct conf_neighbour *, char *); 64 65struct conf_func { 66 char com[64]; 67 int (* func)(char *); 68}; 69 70struct conf_func main_commands[] = { 71 { "hello-time", Fhellotime }, 72 { "keepalive-time", Fkeepalive }, 73 { "holddown-time", Fholddown }, 74 { "command-port", Fport }, 75 { "min-label", Fminlabel }, 76 { "max-label", Fmaxlabel }, 77 { "LDP-ID", Fldpid }, 78 { "neighbor", Fneighbour }, 79 { "neighbour", Fneighbour }, 80 { "", NULL }, 81}; 82 83/* 84 * Parses config file 85 */ 86int 87conf_parsefile(char *fname) 88{ 89 int i; 90 char buf[LINEMAXSIZE + 1]; 91 92 SLIST_INIT(&conei_head); 93 conf_ldp_id.s_addr = 0; 94 95 confh = open(fname, O_RDONLY, 0); 96 97 if (confh == -1) 98 return E_CONF_IO; 99 100 for (i = 1; conf_readline(buf, sizeof(buf)) >= 0; i++) 101 if (conf_dispatch(buf) != 0) { 102 close(confh); 103 return i; 104 } 105 106 close(confh); 107 return 0; 108} 109 110/* 111 * Reads a line from config file 112 */ 113int 114conf_readline(char *buf, size_t bufsize) 115{ 116 size_t i; 117 118 for (i = 0; i < bufsize; i++) { 119 if (read(confh, &buf[i], 1) != 1) { 120 if (i == 0) 121 return E_CONF_IO; 122 break; 123 } 124 if (buf[i] == '\n') 125 break; 126 if (i == 0 && isspace((unsigned char)buf[i]) != 0) { 127 i--; 128 continue; 129 } 130 } 131 if (i == bufsize) 132 return E_CONF_MEM; 133 buf[i] = '\0'; 134 return i; 135} 136 137/* 138 * Looks for a matching command on a line 139 */ 140int 141conf_dispatch(char *line) 142{ 143 int i, last_match = -1, matched = 0; 144 char *command, *nline = line; 145 146 if (strlen(line) == 0 || line[0] == '#') 147 return E_CONF_OK; 148 command = NextCommand(nline); 149 for (i = 0; main_commands[i].func != NULL; i++) 150 if (strncasecmp(main_commands[i].com, command, 151 strlen(command)) == 0) { 152 matched++; 153 last_match = i; 154 } 155 if (matched == 0) 156 return E_CONF_NOMATCH; 157 else if (matched > 1) 158 return E_CONF_AMBIGUOUS; 159 160 if (checkeol(nline) != 0) 161 return E_CONF_PARAM; 162 return main_commands[last_match].func(nline); 163} 164 165/* 166 * Checks if a line is terminated or else if it contains 167 * a start block bracket. If it's semicolon terminated 168 * then trim it. 169 */ 170int 171checkeol(char *line) 172{ 173 size_t len = strlen(line); 174 if (len > 0 && line[len - 1] == ';') { 175 line[len - 1] = '\0'; 176 return 0; 177 } 178 for (size_t i = 0; i < len; i++) 179 if (line[i] == '{') 180 return 0; 181 return -1; 182} 183 184/* 185 * Sets hello time 186 */ 187int 188Fhellotime(char *line) 189{ 190 int ht = atoi(line); 191 if (ht <= 0) 192 return E_CONF_PARAM; 193 ldp_hello_time = ht; 194 return 0; 195} 196 197/* 198 * Sets command port 199 */ 200int 201Fport(char *line) 202{ 203 int cp = atoi(line); 204 if (cp <= 0 || cp > 65535) 205 return E_CONF_PARAM; 206 command_port = cp; 207 return 0; 208} 209 210/* 211 * Sets neighbour keepalive 212 */ 213int 214Fkeepalive(char *line) 215{ 216 int kt = atoi(line); 217 if (kt <= 0) 218 return E_CONF_PARAM; 219 ldp_keepalive_time = kt; 220 return 0; 221} 222 223/* 224 * Sets neighbour holddown timer 225 */ 226int 227Fholddown(char *line) 228{ 229 int hdt = atoi(line); 230 if (hdt <= 0) 231 return E_CONF_PARAM; 232 ldp_holddown_time = hdt; 233 return 0; 234} 235 236int 237Fminlabel(char *line) 238{ 239 int ml = atoi(line); 240 if (ml <= 0) 241 return E_CONF_PARAM; 242 min_label = ml; 243 return 0; 244} 245 246int 247Fmaxlabel(char *line) 248{ 249 int ml = atoi(line); 250 if (ml <= 0) 251 return E_CONF_PARAM; 252 max_label = ml; 253 return 0; 254} 255 256int 257Fldpid(char *line) 258{ 259 if (inet_pton(AF_INET, line, &conf_ldp_id) != 1) 260 return E_CONF_PARAM; 261 return 0; 262} 263 264int 265Fneighbour(char *line) 266{ 267 char *peer; 268 struct conf_neighbour *nei; 269 struct in_addr ad; 270 char buf[1024]; 271 272 peer = NextCommand(line); 273 if (inet_pton(AF_INET, peer, &ad) != 1) 274 return E_CONF_PARAM; 275 276 nei = calloc(1, sizeof(*nei)); 277 if (nei == NULL) 278 return E_CONF_MEM; 279 nei->address.s_addr = ad.s_addr; 280 SLIST_INSERT_HEAD(&conei_head, nei, neilist); 281 282 while (conf_readline(buf, sizeof(buf)) >= 0) { 283 if (buf[0] == '}') 284 return 0; 285 if (Gneighbour(nei, buf) == -1) 286 return -1; 287 } 288 return -1; 289} 290 291/* 292 * neighbour { } sub-commands 293 */ 294int 295Gneighbour(struct conf_neighbour *nei, char *line) 296{ 297 if (strncasecmp("authenticate", line, 12) == 0) { 298 nei->authenticate = 1; 299 return 0; 300 } 301 return -1; 302} 303