conffile.c revision 1.4
1/* $NetBSD: conffile.c,v 1.4 2012/11/12 18:39:00 kefren 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, no_default_route, loop_detection; 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 *); 64static int Fnodefault(char*); 65static int Floopdetection(char*); 66 67struct conf_func { 68 char com[64]; 69 int (* func)(char *); 70}; 71 72struct conf_func main_commands[] = { 73 { "hello-time", Fhellotime }, 74 { "keepalive-time", Fkeepalive }, 75 { "holddown-time", Fholddown }, 76 { "command-port", Fport }, 77 { "min-label", Fminlabel }, 78 { "max-label", Fmaxlabel }, 79 { "LDP-ID", Fldpid }, 80 { "neighbor", Fneighbour }, 81 { "neighbour", Fneighbour }, 82 { "no-default-route", Fnodefault }, 83 { "loop-detection", Floopdetection }, 84 { "", NULL }, 85}; 86 87/* 88 * Parses config file 89 */ 90int 91conf_parsefile(char *fname) 92{ 93 int i; 94 char buf[LINEMAXSIZE + 1]; 95 96 SLIST_INIT(&conei_head); 97 conf_ldp_id.s_addr = 0; 98 99 confh = open(fname, O_RDONLY, 0); 100 101 if (confh == -1) 102 return E_CONF_IO; 103 104 for (i = 1; conf_readline(buf, sizeof(buf)) >= 0; i++) 105 if (conf_dispatch(buf) != 0) { 106 close(confh); 107 return i; 108 } 109 110 close(confh); 111 return 0; 112} 113 114/* 115 * Reads a line from config file 116 */ 117int 118conf_readline(char *buf, size_t bufsize) 119{ 120 size_t i; 121 122 for (i = 0; i < bufsize; i++) { 123 if (read(confh, &buf[i], 1) != 1) { 124 if (i == 0) 125 return E_CONF_IO; 126 break; 127 } 128 if (buf[i] == '\n') 129 break; 130 if (i == 0 && isspace((unsigned char)buf[i]) != 0) { 131 i--; 132 continue; 133 } 134 } 135 if (i == bufsize) 136 return E_CONF_MEM; 137 buf[i] = '\0'; 138 return i; 139} 140 141/* 142 * Looks for a matching command on a line 143 */ 144int 145conf_dispatch(char *line) 146{ 147 int i, last_match = -1, matched = 0; 148 char *command, *nline = line; 149 150 if (strlen(line) == 0 || line[0] == '#') 151 return E_CONF_OK; 152 command = NextCommand(nline); 153 for (i = 0; main_commands[i].func != NULL; i++) 154 if (strncasecmp(main_commands[i].com, command, 155 strlen(command)) == 0) { 156 matched++; 157 last_match = i; 158 } 159 if (matched == 0) 160 return E_CONF_NOMATCH; 161 else if (matched > 1) 162 return E_CONF_AMBIGUOUS; 163 164 if (checkeol(nline) != 0) 165 return E_CONF_PARAM; 166 return main_commands[last_match].func(nline); 167} 168 169/* 170 * Checks if a line is terminated or else if it contains 171 * a start block bracket. If it's semicolon terminated 172 * then trim it. 173 */ 174int 175checkeol(char *line) 176{ 177 size_t len = strlen(line); 178 if (len > 0 && line[len - 1] == ';') { 179 line[len - 1] = '\0'; 180 return 0; 181 } 182 for (size_t i = 0; i < len; i++) 183 if (line[i] == '{') 184 return 0; 185 return -1; 186} 187 188/* 189 * Sets hello time 190 */ 191int 192Fhellotime(char *line) 193{ 194 int ht = atoi(line); 195 if (ht <= 0) 196 return E_CONF_PARAM; 197 ldp_hello_time = ht; 198 return 0; 199} 200 201/* 202 * Sets command port 203 */ 204int 205Fport(char *line) 206{ 207 int cp = atoi(line); 208 if (cp <= 0 || cp > 65535) 209 return E_CONF_PARAM; 210 command_port = cp; 211 return 0; 212} 213 214/* 215 * Sets neighbour keepalive 216 */ 217int 218Fkeepalive(char *line) 219{ 220 int kt = atoi(line); 221 if (kt <= 0) 222 return E_CONF_PARAM; 223 ldp_keepalive_time = kt; 224 return 0; 225} 226 227/* 228 * Sets neighbour holddown timer 229 */ 230int 231Fholddown(char *line) 232{ 233 int hdt = atoi(line); 234 if (hdt <= 0) 235 return E_CONF_PARAM; 236 ldp_holddown_time = hdt; 237 return 0; 238} 239 240int 241Fminlabel(char *line) 242{ 243 int ml = atoi(line); 244 if (ml <= 0) 245 return E_CONF_PARAM; 246 min_label = ml; 247 return 0; 248} 249 250int 251Fmaxlabel(char *line) 252{ 253 int ml = atoi(line); 254 if (ml <= 0) 255 return E_CONF_PARAM; 256 max_label = ml; 257 return 0; 258} 259 260int 261Fldpid(char *line) 262{ 263 if (inet_pton(AF_INET, line, &conf_ldp_id) != 1) 264 return E_CONF_PARAM; 265 return 0; 266} 267 268int 269Fneighbour(char *line) 270{ 271 char *peer; 272 struct conf_neighbour *nei; 273 struct in_addr ad; 274 char buf[1024]; 275 276 peer = NextCommand(line); 277 if (inet_pton(AF_INET, peer, &ad) != 1) 278 return E_CONF_PARAM; 279 280 nei = calloc(1, sizeof(*nei)); 281 if (nei == NULL) 282 return E_CONF_MEM; 283 nei->address.s_addr = ad.s_addr; 284 SLIST_INSERT_HEAD(&conei_head, nei, neilist); 285 286 while (conf_readline(buf, sizeof(buf)) >= 0) { 287 if (buf[0] == '}') 288 return 0; 289 if (Gneighbour(nei, buf) == -1) 290 return -1; 291 } 292 return -1; 293} 294 295/* 296 * neighbour { } sub-commands 297 */ 298int 299Gneighbour(struct conf_neighbour *nei, char *line) 300{ 301 if (strncasecmp("authenticate", line, 12) == 0) { 302 nei->authenticate = 1; 303 return 0; 304 } 305 return -1; 306} 307 308int 309Fnodefault(char *line) 310{ 311 int nd = atoi(line); 312 if (nd < 0) 313 return E_CONF_PARAM; 314 no_default_route = nd; 315 return 0; 316} 317 318int 319Floopdetection(char *line) 320{ 321 int loopd = atoi(line); 322 if (loopd < 0) 323 return E_CONF_PARAM; 324 loop_detection = loopd; 325 return 0; 326} 327