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