Module Name: src
Committed By: kefren
Date: Mon Nov 12 18:39:01 UTC 2012
Modified Files:
src/usr.sbin/ldpd: Makefile conffile.c fsm.c ldp.h ldp_peer.c
ldp_peer.h ldpd.8 main.c notifications.h socketops.c socketops.h
tlv.h tlv_stack.c
Log Message:
* add initial IPv6 support - still incomplete at this moment, but it sends
out there IPv6 hellos. Interoperability not yet tested.
* sync man page with reality
To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/usr.sbin/ldpd/Makefile \
src/usr.sbin/ldpd/conffile.c src/usr.sbin/ldpd/ldp.h \
src/usr.sbin/ldpd/ldp_peer.c
cvs rdiff -u -r1.5 -r1.6 src/usr.sbin/ldpd/fsm.c src/usr.sbin/ldpd/ldpd.8
cvs rdiff -u -r1.1 -r1.2 src/usr.sbin/ldpd/ldp_peer.h \
src/usr.sbin/ldpd/notifications.h src/usr.sbin/ldpd/tlv.h
cvs rdiff -u -r1.6 -r1.7 src/usr.sbin/ldpd/main.c
cvs rdiff -u -r1.11 -r1.12 src/usr.sbin/ldpd/socketops.c
cvs rdiff -u -r1.2 -r1.3 src/usr.sbin/ldpd/socketops.h
cvs rdiff -u -r1.4 -r1.5 src/usr.sbin/ldpd/tlv_stack.c
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.3 src/usr.sbin/ldpd/Makefile:1.4
--- src/usr.sbin/ldpd/Makefile:1.3 Thu Dec 30 11:29:21 2010
+++ src/usr.sbin/ldpd/Makefile Mon Nov 12 18:39:00 2012
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.3 2010/12/30 11:29:21 kefren Exp $
+# $NetBSD: Makefile,v 1.4 2012/11/12 18:39:00 kefren Exp $
.include <bsd.own.mk>
@@ -22,4 +22,8 @@ SRCS= conffile.c \
LDADD+= -lcrypt
+.if (${USE_INET6} != "no")
+CPPFLAGS+=-DINET6
+.endif
+
.include <bsd.prog.mk>
Index: src/usr.sbin/ldpd/conffile.c
diff -u src/usr.sbin/ldpd/conffile.c:1.3 src/usr.sbin/ldpd/conffile.c:1.4
--- src/usr.sbin/ldpd/conffile.c:1.3 Tue Jun 14 11:28:51 2011
+++ src/usr.sbin/ldpd/conffile.c Mon Nov 12 18:39:00 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: conffile.c,v 1.3 2011/06/14 11:28:51 kefren Exp $ */
+/* $NetBSD: conffile.c,v 1.4 2012/11/12 18:39:00 kefren Exp $ */
/*
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -45,7 +45,7 @@
#define LINEMAXSIZE 1024
extern int ldp_hello_time, ldp_keepalive_time, ldp_holddown_time, command_port,
- min_label, max_label, no_default_route;
+ min_label, max_label, no_default_route, loop_detection;
int confh;
struct in_addr conf_ldp_id;
@@ -62,6 +62,7 @@ static int Fldpid(char*);
static int Fneighbour(char*);
static int Gneighbour(struct conf_neighbour *, char *);
static int Fnodefault(char*);
+static int Floopdetection(char*);
struct conf_func {
char com[64];
@@ -79,6 +80,7 @@ struct conf_func main_commands[] = {
{ "neighbor", Fneighbour },
{ "neighbour", Fneighbour },
{ "no-default-route", Fnodefault },
+ { "loop-detection", Floopdetection },
{ "", NULL },
};
@@ -312,3 +314,13 @@ Fnodefault(char *line)
no_default_route = nd;
return 0;
}
+
+int
+Floopdetection(char *line)
+{
+ int loopd = atoi(line);
+ if (loopd < 0)
+ return E_CONF_PARAM;
+ loop_detection = loopd;
+ return 0;
+}
Index: src/usr.sbin/ldpd/ldp.h
diff -u src/usr.sbin/ldpd/ldp.h:1.3 src/usr.sbin/ldpd/ldp.h:1.4
--- src/usr.sbin/ldpd/ldp.h:1.3 Thu Jun 16 14:48:30 2011
+++ src/usr.sbin/ldpd/ldp.h Mon Nov 12 18:39:00 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: ldp.h,v 1.3 2011/06/16 14:48:30 kefren Exp $ */
+/* $NetBSD: ldp.h,v 1.4 2012/11/12 18:39:00 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -36,10 +36,11 @@
#include <netinet/in.h>
#define ALL_ROUTERS "224.0.0.2"
+#define ALL_ROUTERS6 "FF02::2"
#define LDP_PORT 646
#define LDP_COMMAND_PORT 2626
-#define LDPD_VER "0.3.0"
+#define LDPD_VER "0.4.0"
#define CONFFILE "/etc/ldpd.conf"
Index: src/usr.sbin/ldpd/ldp_peer.c
diff -u src/usr.sbin/ldpd/ldp_peer.c:1.3 src/usr.sbin/ldpd/ldp_peer.c:1.4
--- src/usr.sbin/ldpd/ldp_peer.c:1.3 Thu Dec 30 11:29:21 2010
+++ src/usr.sbin/ldpd/ldp_peer.c Mon Nov 12 18:39:00 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: ldp_peer.c,v 1.3 2010/12/30 11:29:21 kefren Exp $ */
+/* $NetBSD: ldp_peer.c,v 1.4 2012/11/12 18:39:00 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -68,7 +68,8 @@ ldp_peer_init(void)
*/
struct ldp_peer *
ldp_peer_new(struct in_addr * ldp_id, struct in_addr * a,
- struct in_addr * tradd, uint16_t holdtime, int soc)
+ struct in_addr * tradd, struct in6_addr * tradd6,
+ uint16_t holdtime, int soc)
{
struct ldp_peer *p;
int s = soc;
Index: src/usr.sbin/ldpd/fsm.c
diff -u src/usr.sbin/ldpd/fsm.c:1.5 src/usr.sbin/ldpd/fsm.c:1.6
--- src/usr.sbin/ldpd/fsm.c:1.5 Thu Jun 16 14:48:30 2011
+++ src/usr.sbin/ldpd/fsm.c Mon Nov 12 18:39:00 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: fsm.c,v 1.5 2011/06/16 14:48:30 kefren Exp $ */
+/* $NetBSD: fsm.c,v 1.6 2012/11/12 18:39:00 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -56,6 +56,7 @@ run_ldp_hello(struct ldp_pdu * pduid, st
{
struct ldp_peer *peer = NULL;
struct in_addr peer_addr;
+ struct in6_addr peer_addr6;
struct transport_address_tlv *trtlv;
struct hello_info *hi;
@@ -113,16 +114,20 @@ run_ldp_hello(struct ldp_pdu * pduid, st
if (trtlv->type == TLV_IPV4_TRANSPORT)
memcpy(&peer_addr, &trtlv->address,
sizeof(struct in_addr));
+ else if (trtlv->type == TLV_IPV6_TRANSPORT)
+ memcpy(&peer_addr6, &trtlv->address,
+ sizeof(struct in6_addr));
} else
trtlv = NULL;
/*
- * RFC says: If A1 > A2, LSR1 plays the active role;
+ * RFC 5036 2.5.2: If A1 > A2, LSR1 plays the active role;
* otherwise it is passive.
*/
if (ntohl(peer_addr.s_addr) < ntohl(ladd->s_addr)) {
-#define TRADDR (trtlv && trtlv->type == TLV_IPV4_TRANSPORT) ? &peer_addr : NULL
+#define TR_INET4_ADDR (trtlv && trtlv->type == TLV_IPV4_TRANSPORT) ? &peer_addr : NULL
+#define TR_INET6_ADDR NULL
peer = ldp_peer_new(&pduid->ldp_id, padd,
- TRADDR, ht->ch.holdtime, 0);
+ TR_INET4_ADDR, TR_INET6_ADDR, ht->ch.holdtime, 0);
if (!peer)
return;
if (peer && peer->state == LDP_PEER_CONNECTED)
Index: src/usr.sbin/ldpd/ldpd.8
diff -u src/usr.sbin/ldpd/ldpd.8:1.5 src/usr.sbin/ldpd/ldpd.8:1.6
--- src/usr.sbin/ldpd/ldpd.8:1.5 Thu Jul 7 05:20:16 2011
+++ src/usr.sbin/ldpd/ldpd.8 Mon Nov 12 18:39:00 2012
@@ -1,4 +1,4 @@
-.\" $NetBSD: ldpd.8,v 1.5 2011/07/07 05:20:16 kefren Exp $
+.\" $NetBSD: ldpd.8,v 1.6 2012/11/12 18:39:00 kefren Exp $
.\"
.\" Copyright (c) 2010 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -38,35 +38,40 @@
.Sh DESCRIPTION
.Nm
is a utility used to automatically distribute labels between two MPLS LSRs
-almost conforming to RFC3036.
-Right now it is in BETA stage and many features
-are not implemented or may not work.
-As a security measure you SHOULD filter the LDP well-known (646)
+almost conforming to RFC5036.
+Right now some features requested by RFC5036 are not fully implemented.
+For more information please consult the
+.Sx BUGS
+section. As a security measure you SHOULD filter the LDP well-known (646)
TCP and UDP ports using your favourite packet filter before starting
.Nm .
-Also this is the current measure used to filter neighbours.
-You should see some logs reported via
+This is the current way used to filter neighbours and to protect the
+system of external attacks like route injections.
+.Pp
+.Nm
+logs information using the
.Xr syslog 3
interface.
-.Pp
You can increase the log verbosity using the
.Fl W
and
.Fl D
flags.
-Also you can telnet to the control port (default: 2626) and use
-this interface in order to get informations about protocol, neighbours
-etc. but also to set runtime parameters.
-The required password is the same as the root password.
+.Pp
+Administrators can use
+.Xr telnet 1
+to connect to the control port (default: 2626) and use
+this interface in order to get informations about protocol status,
+neighbours et cetera but also to set runtime parameters.
+The password required for connecting is the same as the root password.
.Pp
.Nm
computes existing routes and tries to match them on MPLS labels
announced by other LDP peers.
-This means that
-.Dq normal
+This means that usual IP
routes will be changed into tagged routes, and MPLS routing table
will be populated.
-It will also announce its mappings to its peers.
+Any change in MPLS topology will also be announced to LDP neighbors.
.Nm
will listen on a route socket and compute the necessary changes in
order to change untagged routes into tagged routes.
@@ -86,6 +91,8 @@ for configuration file format.
Enable debug mode.
.It Fl d
Don't use route interception code.
+.Nm
+will not make any changes to routing table if started with this option.
.It Fl f
Run in foreground.
Use STDOUT for warning and debug messages.
@@ -99,8 +106,8 @@ Enable output of warning messages.
.Sh SEE ALSO
.Rs
.%R RFC
-.%N 3036
-.%D January 2001
+.%N 5036
+.%D October 2007
.%T LDP Specification
.Re
.Rs
Index: src/usr.sbin/ldpd/ldp_peer.h
diff -u src/usr.sbin/ldpd/ldp_peer.h:1.1 src/usr.sbin/ldpd/ldp_peer.h:1.2
--- src/usr.sbin/ldpd/ldp_peer.h:1.1 Wed Dec 8 07:20:14 2010
+++ src/usr.sbin/ldpd/ldp_peer.h Mon Nov 12 18:39:00 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: ldp_peer.h,v 1.1 2010/12/08 07:20:14 kefren Exp $ */
+/* $NetBSD: ldp_peer.h,v 1.2 2012/11/12 18:39:00 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -86,7 +86,7 @@ struct peer_map {
void ldp_peer_init(void);
struct ldp_peer * ldp_peer_new(struct in_addr *, struct in_addr *,
- struct in_addr *, uint16_t, int);
+ struct in_addr *, struct in6_addr *, uint16_t, int);
void ldp_peer_holddown(struct ldp_peer *);
void ldp_peer_delete(struct ldp_peer *);
struct ldp_peer * get_ldp_peer(struct in_addr *);
Index: src/usr.sbin/ldpd/notifications.h
diff -u src/usr.sbin/ldpd/notifications.h:1.1 src/usr.sbin/ldpd/notifications.h:1.2
--- src/usr.sbin/ldpd/notifications.h:1.1 Wed Dec 8 07:20:15 2010
+++ src/usr.sbin/ldpd/notifications.h Mon Nov 12 18:39:00 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: notifications.h,v 1.1 2010/12/08 07:20:15 kefren Exp $ */
+/* $NetBSD: notifications.h,v 1.2 2012/11/12 18:39:00 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
#ifndef _NOTIFICATIONS_H_
#define _NOTIFICATIONS_H_
-/* Notifications codes RFC3036 2.9 */
+/* Notifications codes from RFC5036 3.9 - Status code summary */
#define NOTIF_SUCCESS 0x00000000
#define NOTIF_BAD_LDP_ID 0x00000001
#define NOTIF_BAD_LDP_VER 0x00000002
Index: src/usr.sbin/ldpd/tlv.h
diff -u src/usr.sbin/ldpd/tlv.h:1.1 src/usr.sbin/ldpd/tlv.h:1.2
--- src/usr.sbin/ldpd/tlv.h:1.1 Wed Dec 8 07:20:15 2010
+++ src/usr.sbin/ldpd/tlv.h Mon Nov 12 18:39:00 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: tlv.h,v 1.1 2010/12/08 07:20:15 kefren Exp $ */
+/* $NetBSD: tlv.h,v 1.2 2012/11/12 18:39:00 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -91,7 +91,10 @@ struct hello_tlv {
struct transport_address_tlv {
uint16_t type;
uint16_t length;
- struct in_addr address;
+ union {
+ struct in_addr ip4addr;
+ struct in6_addr ip6addr;
+ } address;
} __packed;
Index: src/usr.sbin/ldpd/main.c
diff -u src/usr.sbin/ldpd/main.c:1.6 src/usr.sbin/ldpd/main.c:1.7
--- src/usr.sbin/ldpd/main.c:1.6 Sat Jul 2 18:17:12 2011
+++ src/usr.sbin/ldpd/main.c Mon Nov 12 18:39:00 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: main.c,v 1.6 2011/07/02 18:17:12 kefren Exp $ */
+/* $NetBSD: main.c,v 1.7 2012/11/12 18:39:00 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -139,7 +139,7 @@ main(int argc, char *argv[])
fatalp("Cannot create command socket\n");
return EXIT_FAILURE;
}
- if (create_hello_socket() < 1) {
+ if (create_hello_sockets() != 0) {
fatalp("Cannot create hello socket\n");
return EXIT_FAILURE;
}
Index: src/usr.sbin/ldpd/socketops.c
diff -u src/usr.sbin/ldpd/socketops.c:1.11 src/usr.sbin/ldpd/socketops.c:1.12
--- src/usr.sbin/ldpd/socketops.c:1.11 Wed Aug 31 13:32:38 2011
+++ src/usr.sbin/ldpd/socketops.c Mon Nov 12 18:39:00 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: socketops.c,v 1.11 2011/08/31 13:32:38 joerg Exp $ */
+/* $NetBSD: socketops.c,v 1.12 2012/11/12 18:39:00 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -60,12 +60,15 @@
#include "ldp_errors.h"
#include "socketops.h"
-int ls; /* TCP listening socket on port 646 */
-int route_socket; /* used to see when a route is added/deleted */
-int hello_socket; /* hello multicast listener - transmitter */
-int command_socket; /* Listening socket for interface command */
-int current_msg_id = 0x233;
-int command_port = LDP_COMMAND_PORT;
+int ls; /* TCP listening socket on port 646 */
+int route_socket; /* used to see when a route is added/deleted */
+int hello_socket; /* hello RX/TX multicast sockets */
+#ifdef INET6
+int hello6_socket; /* same as above */
+#endif
+int command_socket; /* Listening socket for interface command */
+int current_msg_id = 0x233;
+int command_port = LDP_COMMAND_PORT;
extern int replay_index;
extern struct rt_msg replay_rt[REPLAY_MAX];
extern struct com_sock csockets[MAX_COMMAND_SOCKETS];
@@ -74,70 +77,141 @@ int ldp_hello_time = LDP_HELLO_TIME;
int ldp_keepalive_time = LDP_KEEPALIVE_TIME;
int ldp_holddown_time = LDP_HOLDTIME;
int no_default_route = 1;
+int loop_detection = 0;
void recv_pdu(int);
void send_hello_alarm(int);
__dead static void bail_out(int);
+static int bind_socket(int s, uint8_t stype);
+static int set_mcast_ttl(int, int);
+static int set_tos(int);
+static int socket_reuse_port(int);
static int get_local_addr(struct sockaddr_dl *, struct in_addr *);
int
-create_hello_socket()
+create_hello_sockets()
{
struct ip_mreq mcast_addr;
- int s = socket(PF_INET, SOCK_DGRAM, 17);
+ int s;
+#ifdef INET6
+ struct ipv6_mreq mcast_addr6;
+ int s6;
+#endif
+ s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (s < 0)
return s;
+#ifdef INET6
+ s6 = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ if (s6 < 0) {
+ close(s);
+ return s6;
+ }
+#endif
/*
- * RFC3036 specifies we should listen to all subnet routers multicast
+ * RFC5036 specifies we should listen to all subnet routers multicast
* group
*/
- mcast_addr.imr_multiaddr.s_addr = inet_addr(ALL_ROUTERS);
+ assert(inet_pton(AF_INET, ALL_ROUTERS, &mcast_addr.imr_multiaddr) == 1);
mcast_addr.imr_interface.s_addr = htonl(INADDR_ANY);
- socket_reuse_port(s);
+#ifdef INET6
+ assert(inet_pton(AF_INET6, ALL_ROUTERS6,
+ &mcast_addr6.ipv6mr_multiaddr) == 1);
+ /*
+ * XXXXX: kefren. This should be 0, else I should create a socket
+ * for every interface. Need to investigate why is not working
+ * as documented in ip6(4)
+ */
+ mcast_addr6.ipv6mr_interface = 1;
+#endif
+
+ if (socket_reuse_port(s) < 0)
+ goto chs_error;
+#ifdef INET6
+ if (socket_reuse_port(s6) < 0)
+ goto chs_error;
+#endif
+
/* Bind it to port 646 on specific address */
- if (bind_socket(s, htonl(INADDR_ANY)) == -1) {
- warnp("Cannot bind hello socket\n");
- close(s);
- return -1;
+ if (bind_socket(s, 4) == -1) {
+ warnp("Cannot bind INET hello socket\n");
+ goto chs_error;
+ }
+#ifdef INET6
+ if (bind_socket(s6, 6) == -1) {
+ fatalp("Cannot bind INET6 hello socket\n");
+ goto chs_error;
}
+#endif
+
/* We don't need to receive back our messages */
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &(uint8_t){0},
sizeof(uint8_t)) == -1) {
- fatalp("setsockopt: %s", strerror(errno));
- close(s);
- return -1;
+ fatalp("INET setsockopt IP_MCAST_LOOP: %s\n", strerror(errno));
+ goto chs_error;
+ }
+#ifdef INET6
+ if (setsockopt(s6, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &(uint32_t){0},
+ sizeof(uint32_t)) == -1) {
+ fatalp("INET6 setsocketopt IP_MCAST_LOOP: %s\n",
+ strerror(errno));
+ goto chs_error;
}
+#endif
+
/* Finally join the group */
if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mcast_addr,
sizeof(mcast_addr)) == -1) {
- fatalp("setsockopt: %s", strerror(errno));
- close(s);
- return -1;
+ fatalp("setsockopt ADD_MEMBER: %s\n", strerror(errno));
+ goto chs_error;
}
- /* TTL:1, TOS: 0xc0 */
- if (set_mcast_ttl(s) == -1) {
- close(s);
- return -1;
+#ifdef INET6
+ if (setsockopt(s6, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&mcast_addr6,
+ sizeof(mcast_addr6)) == -1) {
+ fatalp("INET6 setsockopt JOIN: %s\n", strerror(errno));
+ goto chs_error;
}
+#endif
+ /* TTL:1, TOS: 0xc0 */
+ if (set_mcast_ttl(s, 4) == -1)
+ goto chs_error;
+#ifdef INET6
+ if (set_mcast_ttl(s6, 6) == -1)
+ goto chs_error;
+#endif
if (set_tos(s) == -1) {
fatalp("set_tos: %s", strerror(errno));
- close(s);
- return -1;
+ goto chs_error;
}
+
+ /* we need to get the input interface for message processing */
if (setsockopt(s, IPPROTO_IP, IP_RECVIF, &(uint32_t){1}, sizeof(uint32_t)) == -1) {
fatalp("Cannot set IP_RECVIF\n");
- close(s);
- return -1;
+ goto chs_error;
}
+#ifdef INET6
+ if (setsockopt(s6, IPPROTO_IPV6, IPV6_RECVPKTINFO, &(uint32_t){1}, sizeof(uint32_t)) == -1)
+ goto chs_error;
+#endif
+
hello_socket = s;
- return hello_socket;
+#ifdef INET6
+ hello6_socket = s6;
+#endif
+
+ return 0;
+chs_error:
+ close(s);
+#ifdef INET6
+ close(s6);
+#endif
+ return -1;
}
/* Sets the TTL to 1 as we don't want to transmit outside this subnet */
-int
+int
set_ttl(int s)
{
int ret;
@@ -148,18 +222,21 @@ set_ttl(int s)
}
/* Sets multicast TTL to 1 */
-int
-set_mcast_ttl(int s)
+static int
+set_mcast_ttl(int s, int stype)
{
int ret;
- if ((ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &(int){1},
+
+ assert(stype == 4 || stype == 6);
+ if ((ret = setsockopt(s, stype == 4 ? IPPROTO_IP : IPPROTO_IPV6,
+ stype == 4 ? IP_MULTICAST_TTL : IPV6_MULTICAST_HOPS, &(int){1},
sizeof(int))) == -1)
fatalp("set_mcast_ttl: %s", strerror(errno));
return ret;
}
/* Sets TOS to 0xc0 aka IP Precedence 6 */
-int
+static int
set_tos(int s)
{
int ret;
@@ -169,10 +246,10 @@ set_tos(int s)
return ret;
}
-int
+static int
socket_reuse_port(int s)
{
- int ret;
+ int ret;
if ((ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &(int){1},
sizeof(int))) == -1)
fatalp("socket_reuse_port: %s", strerror(errno));
@@ -180,24 +257,38 @@ socket_reuse_port(int s)
}
/* binds an UDP socket */
-int
-bind_socket(int s, uint32_t addr)
+static int
+bind_socket(int s, uint8_t stype)
{
- struct sockaddr_in sa;
+ struct sockaddr sa;
- sa.sin_len = sizeof(sa);
- sa.sin_family = AF_INET;
- sa.sin_port = htons(LDP_PORT);
- sa.sin_addr.s_addr = addr;
- if (bind(s, (struct sockaddr *) (&sa), sizeof(sa))) {
- fatalp("bind_socket: %s", strerror(errno));
+ assert (stype == 4 || stype == 6);
+
+ if (stype == 4) {
+ struct sockaddr_in *sa_inet = (struct sockaddr_in *)(&sa);
+ sa_inet->sin_len = sizeof(*sa_inet);
+ sa_inet->sin_family = AF_INET;
+ sa_inet->sin_addr.s_addr = INADDR_ANY;
+ sa_inet->sin_port = htons(LDP_PORT);
+ }
+#ifdef INET6
+ else if (stype == 6) {
+ struct sockaddr_in6 *sa_inet6 = (struct sockaddr_in6 *)(&sa);
+ sa_inet6->sin6_len = sizeof(*sa_inet6);
+ sa_inet6->sin6_family = AF_INET6;
+ sa_inet6->sin6_addr = in6addr_any;
+ sa_inet6->sin6_port = htons(LDP_PORT);
+ }
+#endif
+ if (bind(s, &sa, sa.sa_len)) {
+ fatalp("bind_socket: %s\n", strerror(errno));
return -1;
}
return 0;
}
/* Create / bind the TCP socket */
-int
+int
create_listening_socket(void)
{
struct sockaddr_in sa;
@@ -208,7 +299,7 @@ create_listening_socket(void)
sa.sin_port = htons(LDP_PORT);
sa.sin_addr.s_addr = htonl(INADDR_ANY);
- s = socket(PF_INET, SOCK_STREAM, 6);
+ s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s < 0)
return s;
if (bind(s, (struct sockaddr *) & sa, sizeof(sa))) {
@@ -242,20 +333,27 @@ send_hello(void)
struct transport_address_tlv *trtlv;
void *v;
struct sockaddr_in sadest; /* Destination ALL_ROUTERS */
- int sb = 0; /* sent bytes */
+ ssize_t sb = 0; /* sent bytes */
struct ifaddrs *ifa, *ifb;
struct sockaddr_in *if_sa;
+#ifdef INET6
+ struct sockaddr_in6 sadest6;
+ struct sockaddr_in6 *if_sa6;
+#endif
char lastifname[20];
-#define HELLO_MSG_SIZE (sizeof(struct ldp_pdu) + /* PDU */ \
+#define BASIC_HELLO_MSG_SIZE (sizeof(struct ldp_pdu) + /* PDU */ \
TLV_TYPE_LENGTH + MSGID_SIZE + /* Hello TLV */ \
/* Common Hello TLV */ \
- sizeof(struct common_hello_tlv) + \
- /* IPv4 Transport Address */ \
- sizeof(struct transport_address_tlv))
+ sizeof(struct common_hello_tlv))
+#define GENERAL_HELLO_MSG_SIZE BASIC_HELLO_MSG_SIZE + \
+ /* Transport Address */ \
+ sizeof(struct transport_address_tlv)
+#define IPV4_HELLO_MSG_SIZE BASIC_HELLO_MSG_SIZE + 4 + sizeof(struct in_addr)
+#define IPV6_HELLO_MSG_SIZE BASIC_HELLO_MSG_SIZE + 4 + sizeof(struct in6_addr)
- if ((v = calloc(1, HELLO_MSG_SIZE)) == NULL) {
- fatalp("malloc problem in send_hello()\n");
+ if ((v = calloc(1, GENERAL_HELLO_MSG_SIZE)) == NULL) {
+ fatalp("alloc problem in send_hello()\n");
return;
}
@@ -266,17 +364,18 @@ send_hello(void)
/* Prepare PDU envelope */
spdu->version = htons(LDP_VERSION);
- spdu->length = htons(HELLO_MSG_SIZE - PDU_VER_LENGTH);
+ spdu->length = htons(IPV4_HELLO_MSG_SIZE - PDU_VER_LENGTH);
inet_aton(LDP_ID, &spdu->ldp_id);
/* Prepare Hello TLV */
t->type = htons(LDP_HELLO);
t->length = htons(MSGID_SIZE +
sizeof(struct common_hello_tlv) +
- sizeof(struct transport_address_tlv));
+ IPV4_HELLO_MSG_SIZE - BASIC_HELLO_MSG_SIZE);
/*
+ * kefren:
* I used ID 0 instead of htonl(get_message_id()) because I've
- * seen hellos from a cisco router doing the same thing
+ * seen hellos from Cisco routers doing the same thing
*/
t->messageid = 0;
@@ -287,7 +386,7 @@ send_hello(void)
cht->res = 0;
/*
- * Prepare Transport Address TLV RFC3036 says: "If this optional TLV
+ * Prepare Transport Address TLV RFC5036 says: "If this optional TLV
* is not present the IPv4 source address for the UDP packet carrying
* the Hello should be used." But we send it because everybody seems
* to do so
@@ -309,6 +408,7 @@ send_hello(void)
}
lastifname[0] = '\0';
+ /* Loop all interfaces in order to send IPv4 hellos */
for (ifb = ifa; ifb; ifb = ifb->ifa_next) {
if_sa = (struct sockaddr_in *) ifb->ifa_addr;
if (if_sa->sin_family != AF_INET)
@@ -316,7 +416,8 @@ send_hello(void)
if (ntohl(if_sa->sin_addr.s_addr) >> 24 == IN_LOOPBACKNET ||
ntohl(if_sa->sin_addr.s_addr) >> 24 == 0)
continue;
- /* Send only once per interface, using master address */
+
+ /* Send only once per interface, using primary address */
if (strcmp(ifb->ifa_name, lastifname) == 0)
continue;
debugp("Sending hello on %s\n", ifb->ifa_name);
@@ -325,22 +426,80 @@ send_hello(void)
warnp("setsockopt failed: %s\n", strerror(errno));
continue;
}
- trtlv->address.s_addr = if_sa->sin_addr.s_addr;
+ trtlv->address.ip4addr.s_addr = if_sa->sin_addr.s_addr;
strlcpy(lastifname, ifb->ifa_name, sizeof(lastifname));
/* Send to the wire */
- sb = sendto(hello_socket, v, HELLO_MSG_SIZE,
+ sb = sendto(hello_socket, v, IPV4_HELLO_MSG_SIZE,
0, (struct sockaddr *) & sadest, sizeof(sadest));
- if (sb < (int)HELLO_MSG_SIZE)
+ if (sb < (ssize_t)(IPV4_HELLO_MSG_SIZE))
fatalp("send: %s", strerror(errno));
else
- debugp("Send %d bytes (PDU: %d, Hello TLV: %d, CH: %d)\n",
- sb, (int) (sizeof(struct ldp_pdu) - PDU_VER_LENGTH),
- (int) (TLV_TYPE_LENGTH + MSGID_SIZE),
- (int) (sizeof(struct common_hello_tlv)));
+ debugp("Sent (IP4) %lu bytes on %s"
+ "(PDU: %d, Hello TLV: %d, CH: %d, TR: %d)\n",
+ sb, ifb->ifa_name,
+ ntohs(spdu->length), ntohs(t->length),
+ ntohs(cht->length), ntohs(trtlv->length));
+ }
+#ifdef INET6
+ /* Let's do the same thing for IPv6 */
+ lastifname[0]='\0';
+
+ /* Adjust lengths */
+ spdu->length = htons(IPV6_HELLO_MSG_SIZE - PDU_VER_LENGTH);
+ t->length = htons(MSGID_SIZE +
+ sizeof(struct common_hello_tlv) +
+ IPV6_HELLO_MSG_SIZE - BASIC_HELLO_MSG_SIZE);
+ trtlv->length = htons(sizeof(struct in6_addr));
+ trtlv->type = htons(TLV_IPV6_TRANSPORT);
+
+ /* Prepare destination sockaddr */
+ memset(&sadest6, 0, sizeof(sadest6));
+ sadest6.sin6_len = sizeof(sadest6);
+ sadest6.sin6_family = AF_INET6;
+ sadest6.sin6_port = htons(LDP_PORT);
+ assert(inet_pton(AF_INET6, ALL_ROUTERS6, &sadest6.sin6_addr) == 1);
+
+ for (ifb = ifa; ifb; ifb = ifb->ifa_next) {
+ unsigned int if_index;
+ if_sa6 = (struct sockaddr_in6 *) ifb->ifa_addr;
+ if (if_sa6->sin6_family != AF_INET6)
+ continue;
+ if (IN6_IS_ADDR_LOOPBACK(&if_sa6->sin6_addr))
+ continue;
+
+ /* Send only once per interface, using primary address */
+ if (strcmp(ifb->ifa_name, lastifname) == 0)
+ continue;
+ if_index = if_nametoindex(ifb->ifa_name);
+ if (if_index == 0)
+ continue;
+ if (setsockopt(hello6_socket, IPPROTO_IPV6, IPV6_MULTICAST_IF,
+ &if_index, sizeof(int)) == -1) {
+ warnp("setsockopt6 failed in sendhello(): %s\n",
+ strerror(errno));
+ continue;
+ }
+ memcpy(&trtlv->address.ip6addr, &if_sa6->sin6_addr,
+ sizeof(struct in6_addr));
+
+ strlcpy(lastifname, ifb->ifa_name, sizeof(lastifname));
+
+ /* Put it on the wire */
+ sb = sendto(hello6_socket, v, IPV6_HELLO_MSG_SIZE,
+ 0, (struct sockaddr *)&sadest6, sizeof(sadest6));
+ if (sb < (ssize_t)(IPV6_HELLO_MSG_SIZE))
+ fatalp("send6 on %s: %s", ifb->ifa_name, strerror(errno));
+ else
+ debugp("Sent (IPv6) %lu bytes on %s"
+ "(PDU: %d, Hello TLV: %d, CH: %d TR: %d)\n",
+ sb, ifb->ifa_name,
+ htons(spdu->length), htons(t->length),
+ htons(cht->length), htons(trtlv->length));
}
+#endif
freeifaddrs(ifa);
free(v);
}
@@ -714,8 +873,8 @@ new_peer_connection()
close(s);
return;
}
- /* XXX: sa.sin_addr ain't peer LDP ID ... */
- ldp_peer_new(&sa.sin_addr, &sa.sin_addr, NULL, ldp_holddown_time, s);
+ /* XXX: sa.sin_addr is not peer LDP ID ... */
+ ldp_peer_new(&sa.sin_addr, &sa.sin_addr, NULL, NULL, ldp_holddown_time, s);
}
@@ -940,7 +1099,7 @@ recv_session_pdu(struct ldp_peer * p)
break;
case LDP_LABEL_ABORT:
/* XXX: For now I pretend I can process everything
- * RFC 3036, Section 3.5.9.1
+ * RFC 5036, Section 3.5.9.1
* If an LSR receives a Label Abort Request Message after it
* has responded to the Label Request in question with a Label
* Mapping message or a Notification message, it ignores the
Index: src/usr.sbin/ldpd/socketops.h
diff -u src/usr.sbin/ldpd/socketops.h:1.2 src/usr.sbin/ldpd/socketops.h:1.3
--- src/usr.sbin/ldpd/socketops.h:1.2 Tue Jun 14 11:28:51 2011
+++ src/usr.sbin/ldpd/socketops.h Mon Nov 12 18:39:00 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: socketops.h,v 1.2 2011/06/14 11:28:51 kefren Exp $ */
+/* $NetBSD: socketops.h,v 1.3 2012/11/12 18:39:00 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -42,11 +42,7 @@
#define LDP_AF_INET6 2
int set_ttl(int);
-int set_mcast_ttl(int);
-int set_tos(int);
-int socket_reuse_port(int);
-int bind_socket(int, uint32_t);
-int create_hello_socket(void);
+int create_hello_sockets(void);
int create_listening_socket(void);
void send_hello(void);
int get_message_id(void);
Index: src/usr.sbin/ldpd/tlv_stack.c
diff -u src/usr.sbin/ldpd/tlv_stack.c:1.4 src/usr.sbin/ldpd/tlv_stack.c:1.5
--- src/usr.sbin/ldpd/tlv_stack.c:1.4 Wed Jun 15 18:16:48 2011
+++ src/usr.sbin/ldpd/tlv_stack.c Mon Nov 12 18:39:00 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: tlv_stack.c,v 1.4 2011/06/15 18:16:48 kefren Exp $ */
+/* $NetBSD: tlv_stack.c,v 1.5 2012/11/12 18:39:00 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -253,8 +253,8 @@ send_label_tlv(struct ldp_peer * peer, s
/* Now let's do the even a dirtier job: PREFIX TLV */
p = (struct prefix_tlv *) & fec[1];
- /* Cisco and Juniper don't support FEC type HOST
- * so everything is FEC_PREFIX..
+ /*
+ * RFC5036 obsoletes FEC_HOST
*
* if (prefixlen == 32) p->type = FEC_HOST; else
*/
@@ -344,7 +344,8 @@ send_withdraw_tlv(struct ldp_peer * peer
/* Now the even dirtier job: PREFIX TLV */
p = (struct prefix_tlv *) & fec[1];
- /* See above comment
+ /*
+ * RFC5036 obsoletes FEC_HOST
*
* if (prefixlen == 32) p->type = FEC_HOST; else
*/