Module Name:    src
Committed By:   kefren
Date:           Thu Dec 30 11:29:22 UTC 2010

Modified Files:
        src/usr.sbin/ldpd: Makefile TODO label.c ldp.h ldp_command.c ldp_peer.c
            ldpd.8 main.c socketops.c
Added Files:
        src/usr.sbin/ldpd: conffile.c conffile.h

Log Message:
* add config file so one can control id, timers and label assignment and
  use neighbour specific options - XXX: needs documentation
* add peer authentication using TCP_MD5SIG. Interoperability tested with
  Cisco IOS
* use SLIST_FOREACH_SAFE when deleting labels instead of re-looping.


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/usr.sbin/ldpd/Makefile src/usr.sbin/ldpd/label.c \
    src/usr.sbin/ldpd/ldp_command.c src/usr.sbin/ldpd/ldp_peer.c \
    src/usr.sbin/ldpd/ldpd.8 src/usr.sbin/ldpd/main.c \
    src/usr.sbin/ldpd/socketops.c
cvs rdiff -u -r1.1 -r1.2 src/usr.sbin/ldpd/TODO src/usr.sbin/ldpd/ldp.h
cvs rdiff -u -r0 -r1.1 src/usr.sbin/ldpd/conffile.c \
    src/usr.sbin/ldpd/conffile.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.sbin/ldpd/Makefile
diff -u src/usr.sbin/ldpd/Makefile:1.2 src/usr.sbin/ldpd/Makefile:1.3
--- src/usr.sbin/ldpd/Makefile:1.2	Sat Dec 18 04:25:37 2010
+++ src/usr.sbin/ldpd/Makefile	Thu Dec 30 11:29:21 2010
@@ -1,11 +1,12 @@
-# $NetBSD: Makefile,v 1.2 2010/12/18 04:25:37 joerg Exp $
+# $NetBSD: Makefile,v 1.3 2010/12/30 11:29:21 kefren Exp $
 
 .include <bsd.own.mk>
 
 PROG=   ldpd
 MAN=    ldpd.8
 
-SRCS=   fsm.c \
+SRCS=   conffile.c \
+	fsm.c \
 	label.c \
 	ldp_command.c \
 	ldp_errors.c \
Index: src/usr.sbin/ldpd/label.c
diff -u src/usr.sbin/ldpd/label.c:1.2 src/usr.sbin/ldpd/label.c:1.3
--- src/usr.sbin/ldpd/label.c:1.2	Thu Dec  9 00:10:59 2010
+++ src/usr.sbin/ldpd/label.c	Thu Dec 30 11:29:21 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: label.c,v 1.2 2010/12/09 00:10:59 christos Exp $ */
+/* $NetBSD: label.c,v 1.3 2010/12/30 11:29:21 kefren Exp $ */
 
 /*-
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -41,6 +41,8 @@
 #include "label.h"
 #include "ldp_errors.h"
 
+int	min_label = MIN_LABEL, max_label = MAX_LABEL;
+
 void 
 label_init()
 {
@@ -146,7 +148,7 @@
 	l->label = 0;
 
 	/* Deletes pure MPLS route */
-	if (oldbinding >= MIN_LABEL) {
+	if (oldbinding >= min_label) {
 		u = make_mpls_union(oldbinding);
 		delete_route(u, NULL, FREESO);
 	}
@@ -189,22 +191,15 @@
 void 
 del_all_peer_labels(struct ldp_peer * p, int readd)
 {
-	struct label   *l;
-	int		do_remove = 1;
+	struct label   *l, *lnext;
 
-	while(do_remove == 1) {
-		do_remove = 0;
-		SLIST_FOREACH(l, &label_head, labels) {
-			if(l->p != p)
-				continue;
-			label_reattach_route(l, readd);
-			label_del(l);
-			/* remove must not interact with foreach */
-			SLIST_REMOVE(&label_head, l, label, labels);
-			do_remove = 1;
-			break;		/* XXX: suboptimal */
-		}
-	} // while
+	SLIST_FOREACH_SAFE(l, &label_head, labels, lnext) {
+		if(l->p != p)
+			continue;
+		label_reattach_route(l, readd);
+		label_del(l);
+		SLIST_REMOVE(&label_head, l, label, labels);
+	}
 }
 
 /*
@@ -251,11 +246,11 @@
 get_free_local_label()
 {
 	struct label *l;
-	uint32_t lbl;
+	int lbl;
  
-	for (lbl = MIN_LABEL; lbl <= MAX_LABEL; lbl++) {
+	for (lbl = min_label; lbl <= max_label; lbl++) {
 		SLIST_FOREACH(l, &label_head, labels)
-			if ((uint32_t)l->binding == lbl)
+			if (l->binding == lbl)
 				break;
 		if (l == NULL)
 			return lbl;
Index: src/usr.sbin/ldpd/ldp_command.c
diff -u src/usr.sbin/ldpd/ldp_command.c:1.2 src/usr.sbin/ldpd/ldp_command.c:1.3
--- src/usr.sbin/ldpd/ldp_command.c:1.2	Tue Dec 14 21:32:43 2010
+++ src/usr.sbin/ldpd/ldp_command.c	Thu Dec 30 11:29:21 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: ldp_command.c,v 1.2 2010/12/14 21:32:43 christos Exp $ */
+/* $NetBSD: ldp_command.c,v 1.3 2010/12/30 11:29:21 kefren Exp $ */
 
 /*-
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -51,7 +51,8 @@
 #include "socketops.h"
 
 struct com_sock csockets[MAX_COMMAND_SOCKETS];
-extern int ldp_hello_time, debug_f, warn_f;
+extern int ldp_hello_time, ldp_keepalive_time, ldp_holddown_time,
+	min_label, max_label, debug_f, warn_f;
 
 #define	writestr(soc, str) write(soc, str, strlen(str))
 
@@ -62,7 +63,7 @@
 static void	echo_on(int s);
 static void	echo_off(int s);
 
-struct com_func main_commands[] = {
+static struct com_func main_commands[] = {
 	{ "show", show_func },
 	{ "set", set_func },
 	{ "quit", exit_func },
@@ -70,7 +71,7 @@
 	{ "", NULL }
 };
 
-struct com_func show_commands[] = {
+static struct com_func show_commands[] = {
 	{ "neighbours", show_neighbours },
 	{ "bindings", show_bindings },
 	{ "debug", show_debug },
@@ -494,10 +495,10 @@
 		my_ldp_id,
 		LDP_VERSION,
 		ldp_hello_time,
-		LDP_KEEPALIVE_TIME,
-		LDP_HOLDTIME,
-		MIN_LABEL,
-		MAX_LABEL);
+		ldp_keepalive_time,
+		ldp_holddown_time,
+		min_label,
+		max_label);
 	writestr(s, sendspace);
 	return 1;
 }
Index: src/usr.sbin/ldpd/ldp_peer.c
diff -u src/usr.sbin/ldpd/ldp_peer.c:1.2 src/usr.sbin/ldpd/ldp_peer.c:1.3
--- src/usr.sbin/ldpd/ldp_peer.c:1.2	Thu Dec  9 00:10:59 2010
+++ src/usr.sbin/ldpd/ldp_peer.c	Thu Dec 30 11:29:21 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: ldp_peer.c,v 1.2 2010/12/09 00:10:59 christos Exp $ */
+/* $NetBSD: ldp_peer.c,v 1.3 2010/12/30 11:29:21 kefren Exp $ */
 
 /*-
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -32,6 +32,7 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
+#include <netinet/tcp.h>
 #include <netmpls/mpls.h>
 #include <arpa/inet.h>
 
@@ -40,6 +41,8 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <errno.h>
+
+#include "conffile.h"
 #include "socketops.h"
 #include "ldp_errors.h"
 #include "ldp.h"
@@ -48,6 +51,8 @@
 #include "notifications.h"
 #include "ldp_peer.h"
 
+extern int ldp_holddown_time;
+
 struct in_addr *myaddresses;
 
 void 
@@ -66,8 +71,9 @@
 	     struct in_addr * tradd, uint16_t holdtime, int soc)
 {
 	struct ldp_peer *p;
-	int             s = soc;
+	int s = soc;
 	struct sockaddr_in sa;
+	struct conf_neighbour *cn;
 
 	if (s < 1) {
 		s = socket(PF_INET, SOCK_STREAM, 0);
@@ -86,11 +92,22 @@
 		set_ttl(s);
 	}
 
+	/* MD5 authentication needed ? */
+	SLIST_FOREACH(cn, &conei_head, neilist)
+		if (cn->authenticate != 0 && (a->s_addr == cn->address.s_addr ||
+		    (tradd && tradd->s_addr == cn->address.s_addr))) {
+			if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG, &(int){1},
+			    sizeof(int)) != 0)
+				fatalp("setsockopt TCP_MD5SIG: %s\n",
+				    strerror(errno));
+			break;
+		}
+
 	/* Set the peer in CONNECTING/CONNECTED state */
 	p = calloc(1, sizeof(*p));
 
 	if (!p) {
-		fatalp("ldp_peer_new: malloc problem\n");
+		fatalp("ldp_peer_new: calloc problem\n");
 		return NULL;
 	}
 
@@ -103,7 +120,7 @@
 	else
 		memcpy(&p->transport_address, a,
 		    sizeof(struct in_addr));
-	p->holdtime = holdtime > LDP_HOLDTIME ? holdtime : LDP_HOLDTIME;
+	p->holdtime = holdtime > ldp_holddown_time ? holdtime : ldp_holddown_time;
 	p->socket = s;
 	if (soc < 1) {
 		p->state = LDP_PEER_CONNECTING;
@@ -141,7 +158,7 @@
 	if (p->state == LDP_PEER_ESTABLISHED)
 		mpls_delete_ldp_peer(p);
 	p->state = LDP_PEER_HOLDDOWN;
-	p->timeout = LDP_HOLDTIME;
+	p->timeout = ldp_holddown_time;
 	shutdown(p->socket, SHUT_RDWR);
 	ldp_peer_delete_all_mappings(p);
 	del_all_ifaddr(p);
Index: src/usr.sbin/ldpd/ldpd.8
diff -u src/usr.sbin/ldpd/ldpd.8:1.2 src/usr.sbin/ldpd/ldpd.8:1.3
--- src/usr.sbin/ldpd/ldpd.8:1.2	Wed Dec  8 09:43:22 2010
+++ src/usr.sbin/ldpd/ldpd.8	Thu Dec 30 11:29:21 2010
@@ -1,4 +1,4 @@
-.\" $NetBSD: ldpd.8,v 1.2 2010/12/08 09:43:22 wiz Exp $
+.\" $NetBSD: ldpd.8,v 1.3 2010/12/30 11:29:21 kefren Exp $
 .\"
 .\" Copyright (c) 2010 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -32,6 +32,7 @@
 .Nd Label Distribution Protocol Daemon
 .Sh SYNOPSIS
 .Nm
+.Op Fl c Ar config_file
 .Op Fl DdfhW
 .Op Fl p Ar port
 .Sh DESCRIPTION
@@ -74,6 +75,8 @@
 .Pp
 The options are as follows:
 .Bl -tag -width 15n
+.It Fl c Ar config_file
+Specifies a path to the config file. Default: /etc/ldpd.conf
 .It Fl D
 Enable debug mode.
 .It Fl d
Index: src/usr.sbin/ldpd/main.c
diff -u src/usr.sbin/ldpd/main.c:1.2 src/usr.sbin/ldpd/main.c:1.3
--- src/usr.sbin/ldpd/main.c:1.2	Wed Dec  8 09:43:28 2010
+++ src/usr.sbin/ldpd/main.c	Thu Dec 30 11:29:21 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: main.c,v 1.2 2010/12/08 09:43:28 wiz Exp $ */
+/* $NetBSD: main.c,v 1.3 2010/12/30 11:29:21 kefren Exp $ */
 
 /*-
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -48,15 +48,17 @@
 #include "fsm.h"
 #include "ldp_errors.h"
 #include "mpls_interface.h"
+#include "conffile.h"
 
-extern int      ls;		/* TCP listening socket */
-extern int	dont_catch;
-extern int	command_port;
-extern int	command_socket;
+extern int ls;		/* TCP listening socket */
+extern int dont_catch;
+extern int command_port;
+extern int command_socket;
 
-extern int	debug_f, warn_f, syslog_f;
+extern int debug_f, warn_f, syslog_f;
 
-extern	struct sockaddr	mplssockaddr;
+extern struct sockaddr mplssockaddr;
+extern struct in_addr conf_ldp_id;
 
 void print_usage(char *myself)
 {
@@ -66,10 +68,15 @@
 int 
 main(int argc, char *argv[])
 {
-	int ch, forkres, dontfork = 0;
+	int ch, forkres, dontfork = 0, cpf;
+	char conffile[PATH_MAX + 1];
 
-	while((ch = getopt(argc, argv, "dDfhp:W")) != -1)
+	strlcpy(conffile, CONFFILE, sizeof(conffile));
+	while((ch = getopt(argc, argv, "c:dDfhp:W")) != -1)
 		switch(ch) {
+		case 'c':
+			strlcpy(conffile, optarg, sizeof(conffile));
+			break;
 		case 'D':
 			debug_f = 1;
 			break;
@@ -98,10 +105,23 @@
 		fatalp("You have to run this as ROOT\n");
 		return -1;
 	}
+
+	cpf = conf_parsefile(conffile);
+	if (cpf < 0 && strcmp(conffile, CONFFILE)) {
+		fatalp("Cannot parse config file: %s\n", conffile);
+		return -1;
+	} else if (cpf > 0) {
+		fatalp("Cannot parse line %d in config file\n", cpf);
+		return -1;
+	}
+
 	if (set_my_ldp_id()) {
 		fatalp("Cannot set LDP ID\n");
 		return -1;
 	}
+	if (conf_ldp_id.s_addr != 0)
+		strlcpy(my_ldp_id, inet_ntoa(conf_ldp_id), INET_ADDRSTRLEN);
+
 	if (mplssockaddr.sa_len == 0) {
 		fatalp("You need one mpls interface up and an IP "
 		    "address set for it\n");
Index: src/usr.sbin/ldpd/socketops.c
diff -u src/usr.sbin/ldpd/socketops.c:1.2 src/usr.sbin/ldpd/socketops.c:1.3
--- src/usr.sbin/ldpd/socketops.c:1.2	Thu Dec  9 00:10:59 2010
+++ src/usr.sbin/ldpd/socketops.c	Thu Dec 30 11:29:21 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: socketops.c,v 1.2 2010/12/09 00:10:59 christos Exp $ */
+/* $NetBSD: socketops.c,v 1.3 2010/12/30 11:29:21 kefren Exp $ */
 
 /*-
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -70,6 +70,8 @@
 extern struct com_sock	csockets[MAX_COMMAND_SOCKETS];
 
 int	ldp_hello_time = LDP_HELLO_TIME;
+int	ldp_keepalive_time = LDP_KEEPALIVE_TIME;
+int	ldp_holddown_time = LDP_HOLDTIME;
 
 void	recv_pdu(int);
 void	send_hello_alarm(int);
@@ -279,7 +281,7 @@
 	/* Prepare Common Hello attributes */
 	cht->type = htons(TLV_COMMON_HELLO);
 	cht->length = htons(sizeof(cht->holdtime) + sizeof(cht->res));
-	cht->holdtime = htons(LDP_HOLDTIME);
+	cht->holdtime = htons(ldp_holddown_time);
 	cht->res = 0;
 
 	/*
@@ -456,7 +458,7 @@
 send_hello_alarm(int unused)
 {
 	struct ldp_peer *p;
-	struct hello_info *hi;
+	struct hello_info *hi, *hinext;
 	time_t          t = time(NULL);
 	int             olderrno = errno;
 
@@ -489,7 +491,7 @@
 			}	/* switch */
 
 	/* send keepalives */
-	if (!(t % LDP_KEEPALIVE_TIME)) {
+	if (!(t % ldp_keepalive_time)) {
 		SLIST_FOREACH(p, &ldp_peer_head, peers)	
 		    if (p->state == LDP_PEER_ESTABLISHED) {
 			debugp("Sending KeepAlive to %s\n",
@@ -503,12 +505,9 @@
 		hi->keepalive--;
 
 	/* Check hello keepalives */
-check_hello:
-	SLIST_FOREACH(hi, &hello_info_head, infos)
-		if (hi->keepalive < 1) {
+	SLIST_FOREACH_SAFE(hi, &hello_info_head, infos, hinext)
+		if (hi->keepalive < 1)
 			SLIST_REMOVE(&hello_info_head, hi, hello_info, infos);
-			goto check_hello;
-		}
 
 	/* Set the alarm again and bail out */
 	alarm(1);
@@ -707,7 +706,7 @@
 		return;
 	}
 	/* XXX: sa.sin_addr ain't peer LDP ID ... */
-	ldp_peer_new(&sa.sin_addr, &sa.sin_addr, NULL, LDP_HOLDTIME, s);
+	ldp_peer_new(&sa.sin_addr, &sa.sin_addr, NULL, ldp_holddown_time, s);
 
 }
 
@@ -722,7 +721,7 @@
 	ti.cs_type = htons(TLV_COMMON_SESSION);
 	ti.cs_len = htons(CS_LEN);
 	ti.cs_version = htons(LDP_VERSION);
-	ti.cs_keepalive = htons(2 * LDP_KEEPALIVE_TIME);
+	ti.cs_keepalive = htons(2 * ldp_keepalive_time);
 	ti.cs_adpvlim = 0;
 	ti.cs_maxpdulen = htons(MAX_PDU_SIZE);
 	ti.cs_peeraddress.s_addr = p->ldp_id.s_addr;

Index: src/usr.sbin/ldpd/TODO
diff -u src/usr.sbin/ldpd/TODO:1.1 src/usr.sbin/ldpd/TODO:1.2
--- src/usr.sbin/ldpd/TODO:1.1	Wed Dec  8 07:20:14 2010
+++ src/usr.sbin/ldpd/TODO	Thu Dec 30 11:29:21 2010
@@ -1,4 +1,4 @@
-# $NetBSD: TODO,v 1.1 2010/12/08 07:20:14 kefren Exp $
+# $NetBSD: TODO,v 1.2 2010/12/30 11:29:21 kefren Exp $
 
 TODO
 ====
@@ -7,6 +7,5 @@
 * document better Label Distribution (downstream on demand or
   unsolicited downstream), distribution control (independent or
   ordered) and retention mode (liberal or conservative) - kefren
-* config/options file
 * future: IPv6 support. Have no infrastructure to test right
   now - kefren
Index: src/usr.sbin/ldpd/ldp.h
diff -u src/usr.sbin/ldpd/ldp.h:1.1 src/usr.sbin/ldpd/ldp.h:1.2
--- src/usr.sbin/ldpd/ldp.h:1.1	Wed Dec  8 07:20:14 2010
+++ src/usr.sbin/ldpd/ldp.h	Thu Dec 30 11:29:21 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: ldp.h,v 1.1 2010/12/08 07:20:14 kefren Exp $ */
+/* $NetBSD: ldp.h,v 1.2 2010/12/30 11:29:21 kefren Exp $ */
 
 /*-
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -41,6 +41,8 @@
 
 #define	LDPD_VER		"0.3.0"
 
+#define CONFFILE		"/etc/ldpd.conf"
+
 extern char     my_ldp_id[20];
 
 #define LDP_ID my_ldp_id

Added files:

Index: src/usr.sbin/ldpd/conffile.c
diff -u /dev/null src/usr.sbin/ldpd/conffile.c:1.1
--- /dev/null	Thu Dec 30 11:29:22 2010
+++ src/usr.sbin/ldpd/conffile.c	Thu Dec 30 11:29:21 2010
@@ -0,0 +1,299 @@
+/* $NetBSD: conffile.c,v 1.1 2010/12/30 11:29:21 kefren Exp $ */
+
+/*
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Mihai Chelaru <kef...@netbsd.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "conffile.h"
+#include "ldp_errors.h"
+
+#define NextCommand(x) strsep(&x, " ")
+#define LINEMAXSIZE 1024
+
+extern int ldp_hello_time, ldp_keepalive_time, ldp_holddown_time, command_port,
+	min_label, max_label;
+int confh;
+struct in_addr conf_ldp_id;
+
+static int conf_dispatch(char*);
+static int conf_readline(char*, int);
+static int checkeol(char*);
+static int Fhellotime(char*);
+static int Fport(char*);
+static int Fholddown(char*);
+static int Fkeepalive(char*);
+static int Fmaxlabel(char*);
+static int Fminlabel(char*);
+static int Fldpid(char*);
+static int Fneighbour(char*);
+static int Gneighbour(struct conf_neighbour *, char *);
+
+struct conf_func {
+	char com[64];
+	int (* func)(char *);
+};
+
+struct conf_func main_commands[] = {
+	{ "hello-time", Fhellotime },
+	{ "keepalive-time", Fkeepalive },
+	{ "holddown-time", Fholddown },
+	{ "command-port", Fport },
+	{ "min-label", Fminlabel },
+	{ "max-label", Fmaxlabel },
+	{ "LDP-ID", Fldpid },
+	{ "neighbor", Fneighbour },
+	{ "neighbour", Fneighbour },
+	{ "", NULL },
+};
+
+/*
+ * Parses config file
+ */
+int
+conf_parsefile(char *fname)
+{
+	int i;
+	char buf[LINEMAXSIZE + 1];
+
+	SLIST_INIT(&conei_head);
+	conf_ldp_id.s_addr = 0;
+
+	confh = open(fname, O_RDONLY, 0);
+
+	if (confh == -1)
+		return E_CONF_IO;
+
+	for (i = 1; conf_readline(buf, sizeof(buf)) >= 0; i++)
+		if (conf_dispatch(buf) != 0) {
+			close(confh);
+			return i;
+		}
+
+	close(confh);
+	return 0;
+}
+
+/*
+ * Reads a line from config file
+ */
+int
+conf_readline(char *buf, int bufsize)
+{
+	int i;
+
+	for (i = 0; i < bufsize; i++) {
+		if (read(confh, &buf[i], 1) != 1) {
+			if (i == 0)
+				return E_CONF_IO;
+			break;
+		}
+		if (buf[i] == '\n')
+			break;
+		if (i == 0 && isspace((int)buf[i]) != 0) {
+			i--;
+			continue;
+		}
+	}
+	if (i == bufsize)
+		return E_CONF_MEM;
+	buf[i] = '\0';
+	return i;
+}
+
+/*
+ * Looks for a matching command on a line
+ */
+int
+conf_dispatch(char *line)
+{
+	int i, last_match = -1, matched = 0;
+	char *command, *nline = line;
+
+	if (strlen(line) == 0 || line[0] == '#')
+		return E_CONF_OK;
+	command = NextCommand(nline);
+	for (i = 0; main_commands[i].func != NULL; i++)
+		if (strncasecmp(main_commands[i].com, command,
+		    strlen(command)) == 0) {
+			matched++;
+			last_match = i;
+		}
+	if (matched == 0)
+		return E_CONF_NOMATCH;
+	else if (matched > 1)
+		return E_CONF_AMBIGUOUS;
+
+	if (checkeol(nline) != 0)
+		return E_CONF_PARAM;
+	return main_commands[last_match].func(nline);
+}
+
+/*
+ * Checks if a line is terminated or else if it contains
+ * a start block bracket. If it's semicolon terminated
+ * then trim it.
+ */
+int
+checkeol(char *line)
+{
+	if (line[strlen(line) - 1] == ';') {
+		line[strlen(line) - 1] = '\0';
+		return 0;
+	}
+	for (uint i = 0; i < strlen(line); i++)
+		if (line[i] == '{')
+			return 0;
+	return -1;
+}
+
+/*
+ * Sets hello time
+ */
+int
+Fhellotime(char *line)
+{
+	int ht = atoi(line);
+	if (ht <= 0)
+		return E_CONF_PARAM;
+	ldp_hello_time = ht;
+	return 0;
+}
+
+/*
+ * Sets command port
+ */
+int
+Fport(char *line)
+{
+	int cp = atoi(line);
+	if (cp <= 0 || cp > 65535)
+		return E_CONF_PARAM;
+	command_port = cp;
+	return 0;
+}
+
+/*
+ * Sets neighbour keepalive
+ */
+int
+Fkeepalive(char *line)
+{
+	int kt = atoi(line);
+	if (kt <= 0)
+		return E_CONF_PARAM;
+	ldp_keepalive_time = kt;
+	return 0;
+}
+
+/*
+ * Sets neighbour holddown timer
+ */
+int
+Fholddown(char *line)
+{
+	int hdt = atoi(line);
+	if (hdt <= 0)
+		return E_CONF_PARAM;
+	ldp_holddown_time = hdt;
+	return 0;
+}
+
+int
+Fminlabel(char *line)
+{
+	int ml = atoi(line);
+	if (ml <= 0)
+		return E_CONF_PARAM;
+	min_label = ml;
+	return 0;
+}
+
+int
+Fmaxlabel(char *line)
+{
+	int ml = atoi(line);
+	if (ml <= 0)
+		return E_CONF_PARAM;
+	max_label = ml;
+	return 0;
+}
+
+int
+Fldpid(char *line)
+{
+	if (inet_pton(AF_INET, line, &conf_ldp_id) != 1)
+		return E_CONF_PARAM;
+	return 0;
+}
+
+int
+Fneighbour(char *line)
+{
+	char *peer;
+	struct conf_neighbour *nei;
+	struct in_addr ad;
+	char buf[1024];
+
+	peer = NextCommand(line);
+	if (inet_pton(AF_INET, peer, &ad) != 1)
+		return E_CONF_PARAM;
+
+	nei = calloc(1, sizeof(*nei));
+	nei->address.s_addr = ad.s_addr;
+	SLIST_INSERT_HEAD(&conei_head, nei, neilist);
+
+	while(conf_readline(buf, sizeof(buf)) >= 0) {
+		if (buf[0] == '}')
+			return 0;
+		if (Gneighbour(nei, buf) == -1)
+			return -1;
+	}
+	return -1;
+}
+
+/*
+ * neighbour { } sub-commands
+ */
+int
+Gneighbour(struct conf_neighbour *nei, char *line)
+{
+	if (strncasecmp("authenticate", line, 12) == 0) {
+		nei->authenticate = 1;
+		return 0;
+	}
+	return -1;
+}
Index: src/usr.sbin/ldpd/conffile.h
diff -u /dev/null src/usr.sbin/ldpd/conffile.h:1.1
--- /dev/null	Thu Dec 30 11:29:22 2010
+++ src/usr.sbin/ldpd/conffile.h	Thu Dec 30 11:29:21 2010
@@ -0,0 +1,56 @@
+/* $NetBSD: conffile.h,v 1.1 2010/12/30 11:29:21 kefren Exp $ */
+
+/*
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Mihai Chelaru <kef...@netbsd.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CONFFILE_H
+#define __CONFFILE_H
+
+#include <netinet/in.h>
+#include <sys/queue.h>
+
+#define E_CONF_OK 0
+#define	E_CONF_NOMATCH -1
+#define E_CONF_AMBIGUOUS -2
+#define E_CONF_IO -3
+#define E_CONF_MEM -4
+#define E_CONF_GENERIC -5
+#define E_CONF_PARAM -6
+
+struct conf_neighbour {
+	struct in_addr address;
+	int authenticate;	/* RFC 2385 */
+	SLIST_ENTRY(conf_neighbour) neilist;
+};
+SLIST_HEAD(,conf_neighbour) conei_head;
+
+
+int conf_parsefile(char *fname);
+
+#endif

Reply via email to