summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bgpd/ChangeLog30
-rw-r--r--bgpd/bgp_attr.c25
-rw-r--r--bgpd/bgp_attr.h2
-rw-r--r--bgpd/bgp_debug.c7
-rw-r--r--bgpd/bgp_network.c124
-rw-r--r--bgpd/bgp_network.h4
-rw-r--r--bgpd/bgp_open.c3
-rw-r--r--bgpd/bgp_packet.c13
-rw-r--r--bgpd/bgp_vty.c46
-rw-r--r--bgpd/bgpd.c168
-rw-r--r--bgpd/bgpd.h21
-rwxr-xr-xconfigure.ac22
-rw-r--r--isisd/ChangeLog11
-rw-r--r--isisd/isis_flags.c19
-rw-r--r--isisd/isis_flags.h1
-rw-r--r--isisd/isisd.c8
-rw-r--r--lib/ChangeLog32
-rw-r--r--lib/linklist.c20
-rw-r--r--lib/log.c29
-rw-r--r--lib/log.h6
-rw-r--r--lib/memory.c2
-rw-r--r--lib/sockopt.c33
-rw-r--r--lib/sockopt.h28
-rw-r--r--lib/stream.h2
-rw-r--r--ospf6d/ospf6_area.h6
-rw-r--r--ospfd/ospf_opaque.h2
-rw-r--r--ospfd/ospfd.h6
-rw-r--r--ripd/ChangeLog6
-rw-r--r--ripd/rip_interface.c1
-rw-r--r--ripd/ripd.c1
-rw-r--r--solaris/ChangeLog6
-rw-r--r--solaris/Makefile.am2
-rw-r--r--tests/ChangeLog8
-rw-r--r--tests/aspath_test.c18
-rw-r--r--tests/bgp_capability_test.c30
-rw-r--r--zebra/ChangeLog28
-rw-r--r--zebra/ioctl.c26
-rw-r--r--zebra/kernel_socket.c22
-rw-r--r--zebra/rib.h1
-rw-r--r--zebra/zebra_rib.c56
40 files changed, 821 insertions, 54 deletions
diff --git a/bgpd/ChangeLog b/bgpd/ChangeLog
index 3fa3837a..f3b6a8c1 100644
--- a/bgpd/ChangeLog
+++ b/bgpd/ChangeLog
@@ -1,3 +1,33 @@
+2008-03-13 Paul Jakma <paul.jakma@sun.com>
+
+ * (various) Remove 0 entries from struct message's, unneeded due to
+ recent improvements in mes_lookup/LOOKUP.
+
+2008-01-29 Jorge Boncompte <jorge@dti2.net>
+
+ * bgp_network.c: (bgp_socket) IPv4-only version crashes if -l is not
+ used as address will be null.
+
+2007-12-22 Paul Jakma <paul.jakma@sun.com>
+
+ * Fix series of vulnerabilities reported by "Mu Security
+ Research Team", where bgpd can be made to crash by sending
+ malformed packets - requires that bgpd be configured with a
+ session to the peer.
+ * bgp_attr.c: (bgp_attr_as4_path) aspath_parse may fail, only
+ set the attribute flag indicating AS4_PATH if we actually managed
+ to parse one.
+ (bgp_attr_munge_as4_attrs) Assert was too general, it is possible
+ to receive AS4_AGGREGATOR before AGGREGATOR.
+ (bgp_attr_parse) Check that we have actually received the extra
+ byte of header for Extended-Length attributes.
+ * bgp_attr.h: Fix BGP_ATTR_MIN_LEN to account for the length byte.
+ * bgp_open.c: (cap_minsizes) Fix size of CAPABILITY_CODE_RESTART,
+ incorrect -2 left in place from a development version of as4-path
+ patch.
+ * bgp_packet.c: (bgp_route_refresh_receive) ORF length parameter
+ needs to be properly sanity checked.
+
2007-12-18 Denis Ovsienko
* bgp_routemap.c: (no_set_aspath_prepend) This command cancelled
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index b463b3c0..26f62f5a 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -60,7 +60,6 @@ static struct message attr_str [] =
{ BGP_ATTR_AS4_PATH, "AS4_PATH" },
{ BGP_ATTR_AS4_AGGREGATOR, "AS4_AGGREGATOR" },
{ BGP_ATTR_AS_PATHLIMIT, "AS_PATHLIMIT" },
- { 0, NULL }
};
int attr_str_max = sizeof(attr_str)/sizeof(attr_str[0]);
@@ -892,7 +891,8 @@ bgp_attr_as4_path (struct peer *peer, bgp_size_t length,
*as4_path = aspath_parse (peer->ibuf, length, 1);
/* Set aspath attribute flag. */
- attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
+ if (as4_path)
+ attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
return 0;
}
@@ -1126,10 +1126,10 @@ bgp_attr_munge_as4_attrs (struct peer *peer, struct attr *attr,
*/
if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR) ) )
{
- assert (attre);
-
if ( attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
{
+ assert (attre);
+
/* received both.
* if the as_number in aggregator is not AS_TRANS,
* then AS4_AGGREGATOR and AS4_PATH shall be ignored
@@ -1170,7 +1170,7 @@ bgp_attr_munge_as4_attrs (struct peer *peer, struct attr *attr,
zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
" AS4_AGGREGATOR but no AGGREGATOR, will take"
" it as if AGGREGATOR with AS_TRANS had been there", peer->host);
- attre->aggregator_as = as4_aggregator;
+ (attre = bgp_attr_extra_get (attr))->aggregator_as = as4_aggregator;
/* sweep it under the carpet and simulate a "good" AGGREGATOR */
attr->flag |= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR));
}
@@ -1543,6 +1543,21 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
flag = stream_getc (BGP_INPUT (peer));
type = stream_getc (BGP_INPUT (peer));
+ /* Check whether Extended-Length applies and is in bounds */
+ if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)
+ && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1)))
+ {
+ zlog (peer->log, LOG_WARNING,
+ "%s Extended length set, but just %u bytes of attr header",
+ peer->host,
+ (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
+
+ bgp_notify_send (peer,
+ BGP_NOTIFY_UPDATE_ERR,
+ BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
+ return -1;
+ }
+
/* Check extended attribue length bit. */
if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
length = stream_getw (BGP_INPUT (peer));
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index 1af9ce30..e152b9f4 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -44,7 +44,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#define BGP_ATTR_FLAG_EXTLEN 0x10 /* Extended length flag. */
/* BGP attribute header must bigger than 2. */
-#define BGP_ATTR_MIN_LEN 2 /* Attribute flag and type. */
+#define BGP_ATTR_MIN_LEN 3 /* Attribute flag, type length. */
#define BGP_ATTR_DEFAULT_WEIGHT 32768
/* Additional/uncommon BGP attributes.
diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c
index acb1de7f..757b9cf8 100644
--- a/bgpd/bgp_debug.c
+++ b/bgpd/bgp_debug.c
@@ -59,7 +59,6 @@ unsigned long term_bgp_debug_zebra;
/* messages for BGP-4 status */
struct message bgp_status_msg[] =
{
- { 0, "null" },
{ Idle, "Idle" },
{ Connect, "Connect" },
{ Active, "Active" },
@@ -86,7 +85,6 @@ const char *bgp_type_str[] =
/* message for BGP-4 Notify */
struct message bgp_notify_msg[] =
{
- { 0, "" },
{ BGP_NOTIFY_HEADER_ERR, "Message Header Error"},
{ BGP_NOTIFY_OPEN_ERR, "OPEN Message Error"},
{ BGP_NOTIFY_UPDATE_ERR, "UPDATE Message Error"},
@@ -99,7 +97,6 @@ int bgp_notify_msg_max = BGP_NOTIFY_MAX;
struct message bgp_notify_head_msg[] =
{
- { 0, "null"},
{ BGP_NOTIFY_HEADER_NOT_SYNC, "/Connection Not Synchronized"},
{ BGP_NOTIFY_HEADER_BAD_MESLEN, "/Bad Message Length"},
{ BGP_NOTIFY_HEADER_BAD_MESTYPE, "/Bad Message Type"}
@@ -108,7 +105,6 @@ int bgp_notify_head_msg_max = BGP_NOTIFY_HEADER_MAX;
struct message bgp_notify_open_msg[] =
{
- { 0, "null" },
{ BGP_NOTIFY_OPEN_UNSUP_VERSION, "/Unsupported Version Number" },
{ BGP_NOTIFY_OPEN_BAD_PEER_AS, "/Bad Peer AS"},
{ BGP_NOTIFY_OPEN_BAD_BGP_IDENT, "/Bad BGP Identifier"},
@@ -121,7 +117,6 @@ int bgp_notify_open_msg_max = BGP_NOTIFY_OPEN_MAX;
struct message bgp_notify_update_msg[] =
{
- { 0, "null"},
{ BGP_NOTIFY_UPDATE_MAL_ATTR, "/Malformed Attribute List"},
{ BGP_NOTIFY_UPDATE_UNREC_ATTR, "/Unrecognized Well-known Attribute"},
{ BGP_NOTIFY_UPDATE_MISS_ATTR, "/Missing Well-known Attribute"},
@@ -138,7 +133,6 @@ int bgp_notify_update_msg_max = BGP_NOTIFY_UPDATE_MAX;
struct message bgp_notify_cease_msg[] =
{
- { 0, ""},
{ BGP_NOTIFY_CEASE_MAX_PREFIX, "/Maximum Number of Prefixes Reached"},
{ BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN, "/Administratively Shutdown"},
{ BGP_NOTIFY_CEASE_PEER_UNCONFIG, "/Peer Unconfigured"},
@@ -152,7 +146,6 @@ int bgp_notify_cease_msg_max = BGP_NOTIFY_CEASE_MAX;
struct message bgp_notify_capability_msg[] =
{
- { 0, "null" },
{ BGP_NOTIFY_CAPABILITY_INVALID_ACTION, "/Invalid Action Value" },
{ BGP_NOTIFY_CAPABILITY_INVALID_LENGTH, "/Invalid Capability Length"},
{ BGP_NOTIFY_CAPABILITY_MALFORMED_CODE, "/Malformed Capability Value"},
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index 6b8c8a44..4289ce20 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -22,6 +22,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "thread.h"
#include "sockunion.h"
+#include "sockopt.h"
#include "memory.h"
#include "log.h"
#include "if.h"
@@ -38,6 +39,34 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
extern struct zebra_privs_t bgpd_privs;
+#if defined(HAVE_TCP_MD5SIG)
+/*
+ * Set MD5 key for the socket, for the given IPv4 peer address.
+ * If the password is NULL or zero-length, the option will be disabled.
+ */
+int
+bgp_md5_set (int sock, struct sockaddr_in *sin, const char *password)
+{
+ int ret, en;
+
+ if ( bgpd_privs.change (ZPRIVS_RAISE) )
+ zlog_err ("bgp_md5_set: could not raise privs");
+
+ ret = sockopt_tcp_signature (sock, sin, password);
+ en = errno;
+
+ if (bgpd_privs.change (ZPRIVS_LOWER) )
+ zlog_err ("bgp_md5_set: could not lower privs");
+
+ if (ret < 0)
+ zlog (NULL, LOG_WARNING, "can't set TCP_MD5SIG option on socket %d: %s",
+ sock, safe_strerror (en));
+
+ return ret;
+}
+
+#endif /* HAVE_TCP_MD5SIG */
+
/* Accept bgp connection. */
static int
bgp_accept (struct thread *thread)
@@ -238,6 +267,12 @@ bgp_connect (struct peer *peer)
sockopt_reuseaddr (peer->fd);
sockopt_reuseport (peer->fd);
+#ifdef HAVE_TCP_MD5SIG
+ if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSWORD))
+ if (sockunion_family (&peer->su) == AF_INET)
+ bgp_md5_set (peer->fd, &peer->su.sin, peer->password);
+#endif /* HAVE_TCP_MD5SIG */
+
/* Bind socket. */
bgp_bind (peer);
@@ -288,6 +323,10 @@ bgp_socket (struct bgp *bgp, unsigned short port, char *address)
struct addrinfo req;
struct addrinfo *ainfo;
struct addrinfo *ainfo_save;
+#if defined(HAVE_TCP_MD5SIG) && defined(IPV6_V6ONLY)
+ struct sockaddr_in sin;
+ int socklen, on = 1;
+#endif
int sock = 0;
char port_str[BUFSIZ];
@@ -296,7 +335,7 @@ bgp_socket (struct bgp *bgp, unsigned short port, char *address)
req.ai_flags = AI_PASSIVE;
req.ai_family = AF_UNSPEC;
req.ai_socktype = SOCK_STREAM;
- sprintf (port_str, "%d", port);
+ snprintf (port_str, sizeof(port_str), "%d", port);
port_str[sizeof (port_str) - 1] = '\0';
ret = getaddrinfo (address, port_str, &req, &ainfo);
@@ -323,6 +362,21 @@ bgp_socket (struct bgp *bgp, unsigned short port, char *address)
sockopt_reuseaddr (sock);
sockopt_reuseport (sock);
+#if defined(HAVE_TCP_MD5SIG) && defined(IPV6_V6ONLY)
+/* We can not apply MD5SIG to an IPv6 socket. If this is an AF_INET6
+ socket, we'll have to create another socket for IPv4*/
+
+ if (ainfo->ai_family == AF_INET6) {
+/* Mark this one for IPv6 only */
+ ret = setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY,
+ (void *) &on, sizeof (on));
+ if( ret < 0 ) {
+ en = errno;
+ zlog_err ("setsockopt V6ONLY: %s", safe_strerror (en));
+ }
+ }
+#endif
+
if (bgpd_privs.change (ZPRIVS_RAISE) )
zlog_err ("bgp_socket: could not raise privs");
@@ -346,7 +400,65 @@ bgp_socket (struct bgp *bgp, unsigned short port, char *address)
continue;
}
+#if defined(HAVE_TCP_MD5SIG) && defined(IPV6_V6ONLY)
thread_add_read (master, bgp_accept, bgp, sock);
+
+ if (ainfo->ai_family != AF_INET6)
+ continue;
+
+ /* If first socket was an IPv6 socket, we need to create an IPv4
+ socket for use by the TCP_MD5SIG logic. This code is blatently
+ copied and modified from the alternate IPv4 only code from below... */
+
+ sock = socket (AF_INET, SOCK_STREAM, 0);
+ if (sock < 0)
+ {
+ zlog_err ("socket: %s", safe_strerror (errno));
+ continue;
+ }
+
+ sockopt_reuseaddr (sock);
+ sockopt_reuseport (sock);
+
+ memset (&sin, 0, sizeof (struct sockaddr_in));
+
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons (port);
+ socklen = sizeof (struct sockaddr_in);
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
+ sin.sin_len = socklen;
+#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
+
+ if ( bgpd_privs.change (ZPRIVS_RAISE) )
+ zlog_err ("bgp_socket: could not raise privs");
+
+ ret = bind (sock, (struct sockaddr *) &sin, socklen);
+ en = errno;
+ if (bgpd_privs.change (ZPRIVS_LOWER) )
+ zlog_err ("bgp_bind_address: could not lower privs");
+
+ if (ret < 0)
+ {
+ zlog_err ("bind: %s", safe_strerror (en));
+ close(sock);
+ continue;
+ }
+
+ ret = listen (sock, 3);
+ if (ret < 0)
+ {
+ zlog_err ("listen: %s", safe_strerror (errno));
+ close (sock);
+ continue;
+ }
+#endif
+
+#ifdef HAVE_TCP_MD5SIG
+ bm->sock = sock;
+#endif /* HAVE_TCP_MD5SIG */
+
+ thread_add_read (master, bgp_accept, bgp, sock);
+
}
while ((ainfo = ainfo->ai_next) != NULL);
@@ -380,11 +492,10 @@ bgp_socket (struct bgp *bgp, unsigned short port, char *address)
sin.sin_port = htons (port);
socklen = sizeof (struct sockaddr_in);
- ret = inet_aton(address, &sin.sin_addr);
-
- if (ret < 1)
+ if (address && ((ret = inet_aton(address, &sin.sin_addr)) < 1))
{
- zlog_err("bgp_socket: could not parse ip address %s: ", address, safe_strerror (errno));
+ zlog_err("bgp_socket: could not parse ip address %s: %s",
+ address, safe_strerror (errno));
return ret;
}
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
@@ -414,6 +525,9 @@ bgp_socket (struct bgp *bgp, unsigned short port, char *address)
close (sock);
return ret;
}
+#ifdef HAVE_TCP_MD5SIG
+ bm->sock = sock;
+#endif /* HAVE_TCP_MD5SIG */
thread_add_read (bm->master, bgp_accept, bgp, sock);
diff --git a/bgpd/bgp_network.h b/bgpd/bgp_network.h
index b455f574..e7119414 100644
--- a/bgpd/bgp_network.h
+++ b/bgpd/bgp_network.h
@@ -21,6 +21,10 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#ifndef _QUAGGA_BGP_NETWORK_H
#define _QUAGGA_BGP_NETWORK_H
+#if defined(HAVE_TCP_MD5SIG)
+extern int bgp_md5_set (int, struct sockaddr_in *, const char *);
+#endif /* HAVE_TCP_MD5SIG */
+
extern int bgp_socket (struct bgp *, unsigned short, char *);
extern int bgp_connect (struct peer *);
extern void bgp_getsockname (struct peer *);
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index 38431d4c..84d8191e 100644
--- a/bgpd/bgp_open.c
+++ b/bgpd/bgp_open.c
@@ -443,7 +443,6 @@ bgp_capability_as4 (struct peer *peer, struct capability_header *hdr)
static struct message capcode_str[] =
{
- { 0, ""},
{ CAPABILITY_CODE_MP, "MultiProtocol Extensions" },
{ CAPABILITY_CODE_REFRESH, "Route Refresh" },
{ CAPABILITY_CODE_ORF, "Cooperative Route Filtering" },
@@ -461,7 +460,7 @@ static size_t cap_minsizes[] =
[CAPABILITY_CODE_MP] = sizeof (struct capability_mp_data),
[CAPABILITY_CODE_REFRESH] = CAPABILITY_CODE_REFRESH_LEN,
[CAPABILITY_CODE_ORF] = sizeof (struct capability_orf_entry),
- [CAPABILITY_CODE_RESTART] = sizeof (struct capability_gr) - 2,
+ [CAPABILITY_CODE_RESTART] = sizeof (struct capability_gr),
[CAPABILITY_CODE_AS4] = CAPABILITY_CODE_AS4_LEN,
[CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN,
[CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN,
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 2b56259b..e8f77f10 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -1960,11 +1960,14 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
when_to_refresh = stream_getc (s);
end = stream_pnt (s) + (size - 5);
- while (stream_pnt (s) < end)
+ while ((stream_pnt (s) + 2) < end)
{
orf_type = stream_getc (s);
orf_len = stream_getw (s);
-
+
+ /* orf_len in bounds? */
+ if ((stream_pnt (s) + orf_len) > end)
+ break; /* XXX: Notify instead?? */
if (orf_type == ORF_TYPE_PREFIX
|| orf_type == ORF_TYPE_PREFIX_OLD)
{
@@ -1984,6 +1987,12 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
peer->host, orf_type, orf_len);
}
+ /* we're going to read at least 1 byte of common ORF header,
+ * and 7 bytes of ORF Address-filter entry from the stream
+ */
+ if (orf_len < 7)
+ break;
+
/* ORF prefix-list name */
sprintf (name, "%s.%d.%d", peer->host, afi, safi);
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 1481c66d..d42f8121 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -1479,6 +1479,46 @@ ALIAS (no_neighbor_local_as,
"AS number used as local AS\n"
"Do not prepend local-as to updates from ebgp peers\n")
+#ifdef HAVE_TCP_MD5SIG
+DEFUN (neighbor_password,
+ neighbor_password_cmd,
+ NEIGHBOR_CMD2 "password LINE",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Set a password\n"
+ "The password\n")
+{
+ struct peer *peer;
+ int ret;
+
+ peer = peer_and_group_lookup_vty (vty, argv[0]);
+ if (! peer)
+ return CMD_WARNING;
+
+ ret = peer_password_set (peer, argv[1]);
+ return bgp_vty_return (vty, ret);
+}
+
+DEFUN (no_neighbor_password,
+ no_neighbor_password_cmd,
+ NO_NEIGHBOR_CMD2 "password",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Set a password\n")
+{
+ struct peer *peer;
+ int ret;
+
+ peer = peer_and_group_lookup_vty (vty, argv[0]);
+ if (! peer)
+ return CMD_WARNING;
+
+ ret = peer_password_unset (peer);
+ return bgp_vty_return (vty, ret);
+}
+#endif /* HAVE_TCP_MD5SIG */
+
DEFUN (neighbor_activate,
neighbor_activate_cmd,
NEIGHBOR_CMD2 "activate",
@@ -8897,6 +8937,12 @@ bgp_vty_init (void)
install_element (BGP_NODE, &no_neighbor_local_as_val_cmd);
install_element (BGP_NODE, &no_neighbor_local_as_val2_cmd);
+#ifdef HAVE_TCP_MD5SIG
+ /* "neighbor password" commands. */
+ install_element (BGP_NODE, &neighbor_password_cmd);
+ install_element (BGP_NODE, &no_neighbor_password_cmd);
+#endif /* HAVE_TCP_MD5SIG */
+
/* "neighbor activate" commands. */
install_element (BGP_NODE, &neighbor_activate_cmd);
install_element (BGP_IPV4_NODE, &neighbor_activate_cmd);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 128bfef1..c4e54f03 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -788,6 +788,7 @@ peer_new (struct bgp *bgp)
peer->status = Idle;
peer->ostatus = Idle;
peer->weight = 0;
+ peer->password = NULL;
peer->bgp = bgp;
peer = peer_lock (peer); /* initial reference */
@@ -1202,6 +1203,20 @@ peer_delete (struct peer *peer)
peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
bgp_stop (peer);
bgp_fsm_change_status (peer, Deleted);
+
+#ifdef HAVE_TCP_MD5SIG
+ /* Password configuration */
+ if (peer->password)
+ {
+ free (peer->password);
+ peer->password = NULL;
+
+ if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
+ && sockunion_family (&peer->su) == AF_INET)
+ bgp_md5_set (bm->sock, &peer->su.sin, NULL);
+ }
+#endif /* HAVE_TCP_MD5SIG */
+
bgp_timer_set (peer); /* stops all timers for Deleted */
/* Delete from all peer list. */
@@ -1417,6 +1432,27 @@ peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
else
peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
+#ifdef HAVE_TCP_MD5SIG
+ /* password apply */
+ if (CHECK_FLAG (conf->flags, PEER_FLAG_PASSWORD))
+ {
+ if (peer->password)
+ free (peer->password);
+ peer->password = strdup (conf->password);
+
+ if (sockunion_family (&peer->su) == AF_INET)
+ bgp_md5_set (bm->sock, &peer->su.sin, peer->password);
+ }
+ else if (peer->password)
+ {
+ free (peer->password);
+ peer->password = NULL;
+
+ if (sockunion_family (&peer->su) == AF_INET)
+ bgp_md5_set (bm->sock, &peer->su.sin, NULL);
+ }
+#endif /* HAVE_TCP_MD5SIG */
+
/* maximum-prefix */
peer->pmax[afi][safi] = conf->pmax[afi][safi];
peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
@@ -3379,6 +3415,125 @@ peer_local_as_unset (struct peer *peer)
return 0;
}
+#ifdef HAVE_TCP_MD5SIG
+/* Set password for authenticating with the peer. */
+int
+peer_password_set (struct peer *peer, const char *password)
+{
+ struct peer_group *group;
+ struct listnode *nn, *nnode;
+ int len = password ? strlen(password) : 0;
+
+ if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
+ return BGP_ERR_INVALID_VALUE;
+
+ if (peer->password && strcmp (peer->password, password) == 0
+ && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+ return 0;
+
+ SET_FLAG (peer->flags, PEER_FLAG_PASSWORD);
+ if (peer->password)
+ free (peer->password);
+ peer->password = strdup (password);
+
+ if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+ {
+ if (peer->status == Established)
+ bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+ else
+ BGP_EVENT_ADD (peer, BGP_Stop);
+
+ if (sockunion_family (&peer->su) == AF_INET)
+ bgp_md5_set (bm->sock, &peer->su.sin, peer->password);
+ return 0;
+ }
+
+ group = peer->group;
+ /* #42# LIST_LOOP (group->peer, peer, nn) */
+ for (ALL_LIST_ELEMENTS (group->peer, nn, nnode, peer))
+ {
+ if (peer->password && strcmp (peer->password, password) == 0)
+ continue;
+
+ SET_FLAG (peer->flags, PEER_FLAG_PASSWORD);
+ if (peer->password)
+ free (peer->password);
+ peer->password = strdup (password);
+
+ if (peer->status == Established)
+ bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+ else
+ BGP_EVENT_ADD (peer, BGP_Stop);
+
+ if (sockunion_family (&peer->su) == AF_INET)
+ bgp_md5_set (bm->sock, &peer->su.sin, peer->password);
+ }
+
+ return 0;
+}
+
+int
+peer_password_unset (struct peer *peer)
+{
+ struct peer_group *group;
+ struct listnode *nn, *nnode;
+
+ if (! CHECK_FLAG (peer->flags, PEER_FLAG_PASSWORD)
+ && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+ return 0;
+
+ if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+ {
+ if (peer_group_active (peer)
+ && CHECK_FLAG (peer->group->conf->flags, PEER_FLAG_PASSWORD))
+ return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
+
+ if (peer->status == Established)
+ bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+ else
+ BGP_EVENT_ADD (peer, BGP_Stop);
+
+ if (sockunion_family (&peer->su) == AF_INET)
+ bgp_md5_set (bm->sock, &peer->su.sin, NULL);
+
+ UNSET_FLAG (peer->flags, PEER_FLAG_PASSWORD);
+ if (peer->password)
+ free (peer->password);
+ peer->password = NULL;
+
+ return 0;
+ }
+
+ UNSET_FLAG (peer->flags, PEER_FLAG_PASSWORD);
+ if (peer->password)
+ free (peer->password);
+ peer->password = NULL;
+
+ group = peer->group;
+ /* #42# LIST_LOOP (group->peer, peer, nn) */
+ for (ALL_LIST_ELEMENTS (group->peer, nn, nnode, peer))
+ {
+ if (! CHECK_FLAG (peer->flags, PEER_FLAG_PASSWORD))
+ continue;
+
+ if (peer->status == Established)
+ bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+ else
+ BGP_EVENT_ADD (peer, BGP_Stop);
+
+ if (sockunion_family (&peer->su) == AF_INET)
+ bgp_md5_set (bm->sock, &peer->su.sin, NULL);
+
+ UNSET_FLAG (peer->flags, PEER_FLAG_PASSWORD);
+ if (peer->password)
+ free (peer->password);
+ peer->password = NULL;
+ }
+
+ return 0;
+}
+#endif /* HAVE_TCP_MD5SIG */
+
/* Set distribute list to the peer. */
int
peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
@@ -4416,6 +4571,16 @@ bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
+#ifdef HAVE_TCP_MD5SIG
+ /* Password. */
+ if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSWORD))
+ if (! peer_group_active (peer)
+ || ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSWORD)
+ || strcmp (peer->password, g_peer->password) != 0)
+ vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
+ VTY_NEWLINE);
+#endif /* HAVE_TCP_MD5SIG */
+
/* BGP port. */
if (peer->port != BGP_PORT_DEFAULT)
vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
@@ -4951,6 +5116,9 @@ bgp_master_init (void)
bm->port = BGP_PORT_DEFAULT;
bm->master = thread_master_create ();
bm->start_time = time (NULL);
+#ifdef HAVE_TCP_MD5SIG
+ bm->sock = -1;
+#endif /* HAVE_TCP_MD5SIG */
}
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index e9fc410f..ef1f860b 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -56,6 +56,11 @@ struct bgp_master
#define BGP_OPT_NO_FIB (1 << 0)
#define BGP_OPT_MULTIPLE_INSTANCE (1 << 1)
#define BGP_OPT_CONFIG_CISCO (1 << 2)
+
+#ifdef HAVE_TCP_MD5SIG
+ /* bgp receive socket */
+ int sock;
+#endif /* HAVE_TCP_MD5SIG */
};
/* BGP instance structure. */
@@ -358,6 +363,7 @@ struct peer
/* NSF mode (graceful restart) */
u_char nsf[AFI_MAX][SAFI_MAX];
+#define PEER_FLAG_PASSWORD (1 << 9) /* password */
/* Per AF configuration flags. */
u_int32_t af_flags[AFI_MAX][SAFI_MAX];
@@ -379,6 +385,9 @@ struct peer
#define PEER_FLAG_MAX_PREFIX_WARNING (1 << 15) /* maximum prefix warning-only */
#define PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED (1 << 16) /* leave link-local nexthop unchanged */
+ /* MD5 password */
+ char *password;
+
/* default-originate route-map. */
struct
{
@@ -534,6 +543,13 @@ struct peer
#define PEER_RMAP_TYPE_EXPORT (1 << 7) /* neighbor route-map export */
};
+#if defined(HAVE_TCP_MD5SIG)
+
+#define PEER_PASSWORD_MINLEN (1)
+#define PEER_PASSWORD_MAXLEN (80)
+
+#endif /* HAVE_TCP_MD5SIG */
+
/* This structure's member directly points incoming packet data
stream. */
struct bgp_nlri
@@ -924,6 +940,11 @@ extern int peer_route_map_set (struct peer *, afi_t, safi_t, int, const char *);
extern int peer_route_map_unset (struct peer *, afi_t, safi_t, int);
extern int peer_unsuppress_map_set (struct peer *, afi_t, safi_t, const char *);
+#ifdef HAVE_TCP_MD5SIG
+extern int peer_password_set (struct peer *, const char *);
+extern int peer_password_unset (struct peer *);
+#endif /* HAVE_TCP_MD5SIG */
+
extern int peer_unsuppress_map_unset (struct peer *, afi_t, safi_t);
extern int peer_maximum_prefix_set (struct peer *, afi_t, safi_t, u_int32_t, u_char, int, u_int16_t);
diff --git a/configure.ac b/configure.ac
index 09af801d..9f18bd39 100755
--- a/configure.ac
+++ b/configure.ac
@@ -216,6 +216,8 @@ AC_ARG_WITH(libpam,
[ --with-libpam use libpam for PAM support in vtysh])
AC_ARG_ENABLE(tcp-zebra,
[ --enable-tcp-zebra enable TCP/IP socket connection between zebra and protocol daemon])
+AC_ARG_ENABLE(tcp-md5,
+[ --enable-tcp-md5 enable TCP/IP md5 in BGPd])
AC_ARG_ENABLE(opaque-lsa,
[ --enable-opaque-lsa enable OSPF Opaque-LSA with OSPFAPI support (RFC2370)])
AC_ARG_ENABLE(ospfapi,
@@ -286,6 +288,10 @@ if test "${enable_tcp_zebra}" = "yes"; then
AC_DEFINE(HAVE_TCP_ZEBRA,,Use TCP for zebra communication)
fi
+if test "${enable_tcp_md5}" = "yes"; then
+ AC_DEFINE(HAVE_TCP_MD5SIG,1,Enable TCP MD5 Signatures)
+fi
+
if test "${enable_opaque_lsa}" = "yes"; then
AC_DEFINE(HAVE_OPAQUE_LSA,,OSPF Opaque LSA)
fi
@@ -895,6 +901,22 @@ AC_TRY_COMPILE([#ifdef HAVE_SYS_PARAM_H
AC_DEFINE(HAVE_BSD_STRUCT_IP_MREQ_HACK,,[Can pass ifindex in struct ip_mreq])],
AC_MSG_RESULT(no))
+dnl ---------------------------------------------------------------
+dnl figure out how to check link-state
+dnl ---------------------------------------------------------------
+AC_CHECK_HEADER([net/if.h],
+ [AC_CHECK_HEADER( [net/if_media.h],
+ [m4_define([LINK_DETECT_INCLUDES],
+ QUAGGA_INCLUDES
+ [#include <net/if_media.h>
+ ])
+ AC_CHECK_MEMBERS( [struct ifmediareq.ifm_status],
+ AC_DEFINE(HAVE_BSD_LINK_DETECT,,[BSD link-detect]),
+ [], LINK_DETECT_INCLUDES)],
+ [],
+ QUAGGA_INCLUDES)],
+ [], QUAGGA_INCLUDES )
+
dnl -----------------------
dnl check proc file system.
dnl -----------------------
diff --git a/isisd/ChangeLog b/isisd/ChangeLog
index c2482f06..bb77ffea 100644
--- a/isisd/ChangeLog
+++ b/isisd/ChangeLog
@@ -1,3 +1,14 @@
+2008-01-29 James Carlson <james.d.carlson@sun.com>
+
+ * Fix bug #437, assert due to bogus index management
+ * isis_flags.c: (flags_initialize) new
+ * (flags_get_index) fix off by one, leading to list assert
+ on null node data.
+ (flags_free_index) ditto.
+ * isisd.c: (isis_area_create) use flags_initialize
+ (isis_area_destroy) deconfigure circuits when
+ taking down area.
+
2007-07-18 James Carlson <james.d.carlson@sun.com>
* isis_network.c: split up into isis_bpf.c, isis_dlpi.c, and
diff --git a/isisd/isis_flags.c b/isisd/isis_flags.c
index 9c861c94..03c91101 100644
--- a/isisd/isis_flags.c
+++ b/isisd/isis_flags.c
@@ -29,6 +29,13 @@
#include "isisd/isis_common.h"
#include "isisd/isis_flags.h"
+void
+flags_initialize (struct flags *flags)
+{
+ flags->maxindex = 0;
+ flags->free_idcs = NULL;
+}
+
int
flags_get_index (struct flags *flags)
{
@@ -37,14 +44,14 @@ flags_get_index (struct flags *flags)
if (flags->free_idcs == NULL || flags->free_idcs->count == 0)
{
- flags->maxindex++;
- index = flags->maxindex;
+ index = flags->maxindex++;
}
else
{
node = listhead (flags->free_idcs);
index = (int) listgetdata (node);
listnode_delete (flags->free_idcs, (void *) index);
+ index--;
}
return index;
@@ -53,12 +60,18 @@ flags_get_index (struct flags *flags)
void
flags_free_index (struct flags *flags, int index)
{
+ if (index + 1 == flags->maxindex)
+ {
+ flags->maxindex--;
+ return;
+ }
+
if (flags->free_idcs == NULL)
{
flags->free_idcs = list_new ();
}
- listnode_add (flags->free_idcs, (void *) index);
+ listnode_add (flags->free_idcs, (void *) (index + 1));
return;
}
diff --git a/isisd/isis_flags.h b/isisd/isis_flags.h
index f2421f2f..13dd9e14 100644
--- a/isisd/isis_flags.h
+++ b/isisd/isis_flags.h
@@ -28,6 +28,7 @@
* the support will be achived using the newest drafts */
#define ISIS_MAX_CIRCUITS 32 /* = 1024 */ /*FIXME:defined in lsp.h as well */
+void flags_initialize (struct flags *flags);
struct flags *new_flags (int size);
int flags_get_index (struct flags *flags);
void flags_free_index (struct flags *flags, int index);
diff --git a/isisd/isisd.c b/isisd/isisd.c
index 48ea47af..7c669fcb 100644
--- a/isisd/isisd.c
+++ b/isisd/isisd.c
@@ -130,7 +130,7 @@ isis_area_create ()
area->circuit_list = list_new ();
area->area_addrs = list_new ();
THREAD_TIMER_ON (master, area->t_tick, lsp_tick, area, 1);
- area->flags.maxindex = -1;
+ flags_initialize (&area->flags);
/*
* Default values
*/
@@ -215,7 +215,11 @@ isis_area_destroy (struct vty *vty, const char *area_tag)
if (area->circuit_list)
{
for (ALL_LIST_ELEMENTS (area->circuit_list, node, nnode, circuit))
- isis_circuit_del (circuit);
+ {
+ /* The fact that it's in circuit_list means that it was configured */
+ isis_circuit_deconfigure (circuit, area);
+ isis_circuit_del (circuit);
+ }
list_delete (area->circuit_list);
}
diff --git a/lib/ChangeLog b/lib/ChangeLog
index bd66f071..da0fa8ca 100644
--- a/lib/ChangeLog
+++ b/lib/ChangeLog
@@ -1,3 +1,35 @@
+2008-02-28 Paul Jakma <paul.jakma@sun.com>
+
+ * log.c: (mes_lookup) Sowmini Varadhan diagnosed a problem where
+ this function can cause a NULL dereference, on lookups for unknown
+ indices, or messages with NULL strings. Can occur, e.g., debug
+ logging code when processing received messages. Fixed to accept a
+ pointer to a default string to be used if there is no match.
+ * log.h: LOOKUP adjusted to match
+
+2008-02-28 Paul Jakma <paul.jakma@sun.com>
+
+ * linklist.c: This implementation expects that the data pointer not
+ be null, e.g. listgetdata() asserts this. The list add methods
+ don't apply the same sanity check.
+
+ Noted by Jim Carlson in bug #437.
+
+2008-01-11 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
+
+ * zebra.h: Revert previous change, no need to include <net/if_media.h>
+ here.
+
+2008-01-10 Ingo Flaschberger <if@xip.at>
+
+ * zebra.h: If HAVE_BSD_LINK_DETECT is defined, include <net/if_media.h>.
+
+2008-01-08 Pavol Rusnak <prusnak@suse.cz>
+
+ * memory.c: (mtype_memstr) Fix accidental shift past width of type,
+ constant should have been forced to UL, rather than being left to
+ default to int.
+
2007-11-12 Denis Ovsienko
* linklist.c: (listnode_add_after) Don't forget to increment list
diff --git a/lib/linklist.c b/lib/linklist.c
index 983da2d1..a16e9e18 100644
--- a/lib/linklist.c
+++ b/lib/linklist.c
@@ -65,7 +65,9 @@ void
listnode_add (struct list *list, void *val)
{
struct listnode *node;
-
+
+ assert (val != NULL);
+
node = listnode_new ();
node->prev = list->tail;
@@ -91,7 +93,9 @@ listnode_add_sort (struct list *list, void *val)
{
struct listnode *n;
struct listnode *new;
-
+
+ assert (val != NULL);
+
new = listnode_new ();
new->data = val;
@@ -130,7 +134,9 @@ void
listnode_add_after (struct list *list, struct listnode *pp, void *val)
{
struct listnode *nn;
-
+
+ assert (val != NULL);
+
nn = listnode_new ();
nn->data = val;
@@ -266,7 +272,9 @@ void
list_add_node_prev (struct list *list, struct listnode *current, void *val)
{
struct listnode *node;
-
+
+ assert (val != NULL);
+
node = listnode_new ();
node->next = current;
node->data = val;
@@ -287,7 +295,9 @@ void
list_add_node_next (struct list *list, struct listnode *current, void *val)
{
struct listnode *node;
-
+
+ assert (val != NULL);
+
node = listnode_new ();
node->prev = current;
node->data = val;
diff --git a/lib/log.c b/lib/log.c
index ff47cae0..ce00bfbb 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -752,14 +752,24 @@ lookup (struct message *mes, int key)
}
/* Older/faster version of message lookup function, but requires caller to pass
- in the array size (instead of relying on a 0 key to terminate the search). */
+ * in the array size (instead of relying on a 0 key to terminate the search).
+ *
+ * The return value is the message string if found, or the 'none' pointer
+ * provided otherwise.
+ */
const char *
-mes_lookup (struct message *meslist, int max, int index)
+mes_lookup (struct message *meslist, int max, int index, const char *none)
{
+ int pos = index - meslist[0].key;
+
/* first check for best case: index is in range and matches the key
- value in that slot */
- if ((index >= 0) && (index < max) && (meslist[index].key == index))
- return meslist[index].str;
+ * value in that slot.
+ * NB: key numbering might be offset from 0. E.g. protocol constants
+ * often start at 1.
+ */
+ if ((pos >= 0) && (pos < max)
+ && (meslist[pos].key == index))
+ return meslist[pos].str;
/* fall back to linear search */
{
@@ -769,14 +779,17 @@ mes_lookup (struct message *meslist, int max, int index)
{
if (meslist->key == index)
{
+ const char *str = (meslist->str ? meslist->str : none);
+
zlog_debug ("message index %d [%s] found in position %d (max is %d)",
- index, meslist->str, i, max);
- return meslist->str;
+ index, str, i, max);
+ return str;
}
}
}
zlog_err("message index %d not found (max is %d)", index, max);
- return NULL;
+ assert (none);
+ return none;
}
/* Wrapper around strerror to handle case where it returns NULL. */
diff --git a/lib/log.h b/lib/log.h
index da8fbea8..7432b25e 100644
--- a/lib/log.h
+++ b/lib/log.h
@@ -142,10 +142,12 @@ extern int zlog_reset_file (struct zlog *zl);
extern int zlog_rotate (struct zlog *);
/* For hackey massage lookup and check */
-#define LOOKUP(x, y) mes_lookup(x, x ## _max, y)
+#define LOOKUP(x, y) mes_lookup(x, x ## _max, y, "(no item found)")
extern const char *lookup (struct message *, int);
-extern const char *mes_lookup (struct message *meslist, int max, int index);
+extern const char *mes_lookup (struct message *meslist,
+ int max, int index,
+ const char *no_item);
extern const char *zlog_priority[];
extern const char *zlog_proto_names[];
diff --git a/lib/memory.c b/lib/memory.c
index eb670722..9ed5e100 100644
--- a/lib/memory.c
+++ b/lib/memory.c
@@ -501,7 +501,7 @@ mtype_memstr (char *buf, size_t len, unsigned long bytes)
* Just hacked to make it not warn on 'smaller' machines.
* Static compiler analysis should mean no extra code
*/
- if (bytes & (1 << (sizeof (unsigned long) >= 8 ? 39 : 0)))
+ if (bytes & (1UL << (sizeof (unsigned long) >= 8 ? 39 : 0)))
t++;
snprintf (buf, len, "%4d TiB", t);
}
diff --git a/lib/sockopt.c b/lib/sockopt.c
index f8fa946e..985c3a38 100644
--- a/lib/sockopt.c
+++ b/lib/sockopt.c
@@ -480,3 +480,36 @@ sockopt_iphdrincl_swab_systoh (struct ip *iph)
iph->ip_id = ntohs(iph->ip_id);
}
+
+#if defined(HAVE_TCP_MD5SIG)
+int
+sockopt_tcp_signature (int sock, struct sockaddr_in *sin, const char *password)
+{
+ int keylen = password ? strlen(password) : 0;
+
+#if defined(GNU_LINUX)
+
+ struct tcp_md5sig md5sig;
+
+ bzero ((char *)&md5sig, sizeof(md5sig));
+ memcpy (&md5sig.tcpm_addr, sin, sizeof(*sin));
+ md5sig.tcpm_keylen = keylen;
+ if (keylen)
+ memcpy (md5sig.tcpm_key, password, keylen);
+
+ return setsockopt (sock, IPPROTO_TCP, TCP_MD5SIG, &md5sig, sizeof md5sig);
+
+#else /* !GNU_LINUX */
+
+ int enable = keylen ? (TCP_SIG_SPI_BASE + sin->sin_port) : 0;
+
+ /*
+ * XXX Need to do PF_KEY operation here to add/remove an SA entry,
+ * and add/remove an SP entry for this peer's packet flows also.
+ */
+ return setsockopt (sock, IPPROTO_TCP, TCP_MD5SIG, &enable,
+ sizeof(enable));
+
+#endif /* !GNU_LINUX */
+}
+#endif /* HAVE_TCP_MD5SIG */
diff --git a/lib/sockopt.h b/lib/sockopt.h
index ebb71430..158f17ac 100644
--- a/lib/sockopt.h
+++ b/lib/sockopt.h
@@ -98,4 +98,32 @@ extern int getsockopt_ifindex (int, struct msghdr *);
extern void sockopt_iphdrincl_swab_htosys (struct ip *iph);
extern void sockopt_iphdrincl_swab_systoh (struct ip *iph);
+#if defined(HAVE_TCP_MD5SIG)
+
+#if defined(GNU_LINUX) && !defined(TCP_MD5SIG)
+
+/* XXX these will come from <linux/tcp.h> eventually */
+
+#define TCP_MD5SIG 14
+#define TCP_MD5SIG_MAXKEYLEN 80
+
+struct tcp_md5sig {
+ struct sockaddr_storage tcpm_addr; /* address associated */
+ __u16 __tcpm_pad1; /* zero */
+ __u16 tcpm_keylen; /* key length */
+ __u32 __tcpm_pad2; /* zero */
+ __u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN]; /* key (binary) */
+};
+
+#endif /* defined(GNU_LINUX) && !defined(TCP_MD5SIG) */
+
+#if !defined(GNU_LINUX) && !defined(TCP_SIG_SPI_BASE)
+#define TCP_SIG_SPI_BASE 1000 /* XXX this will go away */
+#endif
+
+extern int sockopt_tcp_signature(int sock, struct sockaddr_in *sin,
+ const char *password);
+
+#endif /* HAVE_TCP_MD5SIG */
+
#endif /*_ZEBRA_SOCKOPT_H */
diff --git a/lib/stream.h b/lib/stream.h
index d2d2e401..715a083d 100644
--- a/lib/stream.h
+++ b/lib/stream.h
@@ -137,7 +137,7 @@ struct stream_fifo
*/
extern struct stream *stream_new (size_t);
extern void stream_free (struct stream *);
-extern struct stream * stream_copy (struct stream *new, struct stream *src);
+extern struct stream * stream_copy (struct stream *, struct stream *src);
extern struct stream *stream_dup (struct stream *);
extern size_t stream_resize (struct stream *, size_t);
extern size_t stream_get_getp (struct stream *);
diff --git a/ospf6d/ospf6_area.h b/ospf6d/ospf6_area.h
index dd33ac47..6bf7e0b5 100644
--- a/ospf6d/ospf6_area.h
+++ b/ospf6d/ospf6_area.h
@@ -67,9 +67,9 @@ struct ospf6_area
{
char *name;
struct access_list *list;
- } export;
-#define EXPORT_NAME(A) (A)->export.name
-#define EXPORT_LIST(A) (A)->export.list
+ } _export;
+#define EXPORT_NAME(A) (A)->_export.name
+#define EXPORT_LIST(A) (A)->_export.list
/* Area acceptance list */
struct
diff --git a/ospfd/ospf_opaque.h b/ospfd/ospf_opaque.h
index fc8d6ff6..f49fe460 100644
--- a/ospfd/ospf_opaque.h
+++ b/ospfd/ospf_opaque.h
@@ -141,7 +141,7 @@ extern void ospf_opaque_lsa_dump (struct stream *s, u_int16_t length);
extern void ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi,
int *init_delay);
-extern struct ospf_lsa *ospf_opaque_lsa_install (struct ospf_lsa *new,
+extern struct ospf_lsa *ospf_opaque_lsa_install (struct ospf_lsa *,
int rt_recalc);
extern void ospf_opaque_lsa_refresh (struct ospf_lsa *lsa);
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index 7a0ffcef..b6187111 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -397,9 +397,9 @@ struct ospf_area
{
char *name;
struct access_list *list;
- } export;
-#define EXPORT_NAME(A) (A)->export.name
-#define EXPORT_LIST(A) (A)->export.list
+ } _export;
+#define EXPORT_NAME(A) (A)->_export.name
+#define EXPORT_LIST(A) (A)->_export.list
/* Area acceptance list. */
struct
diff --git a/ripd/ChangeLog b/ripd/ChangeLog
index cb24e269..ecf353d0 100644
--- a/ripd/ChangeLog
+++ b/ripd/ChangeLog
@@ -1,3 +1,9 @@
+2008-03-13 Paul Jakma <paul.jakma@sun.com>
+
+ * ripd.c/rip_interface.c: Remove 0 entries from rip_msg
+ ri_version_msg struct message's, not needed with recent fixes
+ to mes_lookup.
+
2007-04-27 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ripd.c: (rip_vty_out_uptime) Remove unused variable timer_now.
diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c
index c8a1a84f..b6d9240f 100644
--- a/ripd/rip_interface.c
+++ b/ripd/rip_interface.c
@@ -55,7 +55,6 @@ struct message ri_version_msg[] =
{RI_RIP_VERSION_1, "1"},
{RI_RIP_VERSION_2, "2"},
{RI_RIP_VERSION_1_AND_2, "1 2"},
- {0, NULL}
};
extern struct zebra_privs_t ripd_privs;
diff --git a/ripd/ripd.c b/ripd/ripd.c
index 75ac2159..c5e42705 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -84,7 +84,6 @@ struct message rip_msg[] =
{RIP_TRACEOFF, "TRACEOFF"},
{RIP_POLL, "POLL"},
{RIP_POLL_ENTRY, "POLL ENTRY"},
- {0, NULL}
};
/* Utility function to set boradcast option to the socket. */
diff --git a/solaris/ChangeLog b/solaris/ChangeLog
index c6d8b81d..8a2ad7d3 100644
--- a/solaris/ChangeLog
+++ b/solaris/ChangeLog
@@ -1,3 +1,9 @@
+2008-01-13 Paul Jakma <paul.jakma@sun.com>
+
+ * Makefile.am: pkg target should depend on the 'depend.%' files.
+ Crops up now that solaris/ doesn't get descended into by
+ general Quagga build.
+
2007-02-22 Paul Jakma <paul.jakma@sun.com>
* quagga.{xml,init}.in: Add licence boilerplate to ensure
diff --git a/solaris/Makefile.am b/solaris/Makefile.am
index 8cfd1418..674f4ebf 100644
--- a/solaris/Makefile.am
+++ b/solaris/Makefile.am
@@ -97,7 +97,7 @@ quagga.init: $(srcdir)/quagga.init.in Makefile
# construct the pkg
@PACKAGE_TARNAME@-%-$(pkg_name_rev).pkg: prototype.% \
- quagga.init pkginfo.%.full
+ depend.% quagga.init pkginfo.%.full
($(pkg_make) && \
$(pkg_trans) "QUAGGA$*")
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 94f58749..098afb55 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,11 @@
+2008-02-23 Paul Jakma <paul.jakma@sun.com>
+
+ * aspath_test.c: Test for 0-ASN sequences that still have data.
+
+2007-12-22 Paul Jakma <paul.jakma@sun.com>
+
+ * bgp_capability_test.c: Test for empty capabilities.
+
2007-09-27 Paul Jakma <paul.jakma@sun.com>
* aspath_test.c: Test dupe-weeding from sets.
diff --git a/tests/aspath_test.c b/tests/aspath_test.c
index c12d07a5..fb504f31 100644
--- a/tests/aspath_test.c
+++ b/tests/aspath_test.c
@@ -402,6 +402,24 @@ static struct test_segment {
"8466 3 52737 4096 3456 {7099,8153}",
6, 0, NOT_ALL_PRIVATE, 4096, 4, 8466 },
},
+ { /* 25 */
+ "zero-size overflow",
+ "#ASNs = 0, data = seq(8466 3 52737 4096 3456)",
+ { 0x2,0x0, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x0d,0x80 },
+ 12,
+ { "", "",
+ 0, 0, 0, 0, 0, 0 },
+ },
+ { /* 26 */
+ "zero-size overflow + valid segment",
+ "seq(#AS=0:8466 3 52737),seq(4096 3456)",
+ { 0x2,0x0, 0x21,0x12, 0x00,0x03, 0xce,0x01,
+ 0x2,0x2, 0x10,0x00, 0x0d,0x80 },
+ 14
+ ,
+ { "", "",
+ 0, 0, 0, 0, 0, 0 },
+ },
{ NULL, NULL, {0}, 0, { NULL, 0, 0 } }
};
diff --git a/tests/bgp_capability_test.c b/tests/bgp_capability_test.c
index 6771b579..0dbf4fb9 100644
--- a/tests/bgp_capability_test.c
+++ b/tests/bgp_capability_test.c
@@ -362,6 +362,36 @@ static struct test_segment misc_segments[] =
},
15, SHOULD_ERR,
},
+ { "GR-empty",
+ "GR capability, but empty.",
+ { /* hdr */ 0x40, 0x0,
+ },
+ 2, SHOULD_ERR,
+ },
+ { "MP-empty",
+ "MP capability, but empty.",
+ { /* hdr */ 0x1, 0x0,
+ },
+ 2, SHOULD_ERR,
+ },
+ { "ORF-empty",
+ "ORF capability, but empty.",
+ { /* hdr */ 0x3, 0x0,
+ },
+ 2, SHOULD_ERR,
+ },
+ { "AS4-empty",
+ "AS4 capability, but empty.",
+ { /* hdr */ 0x41, 0x0,
+ },
+ 2, SHOULD_ERR,
+ },
+ { "dyn-empty",
+ "Dynamic capability, but empty.",
+ { /* hdr */ 0x42, 0x0,
+ },
+ 2, SHOULD_PARSE,
+ },
{ "dyn-old",
"Dynamic capability (deprecated version)",
{ CAPABILITY_CODE_DYNAMIC, 0x0 },
diff --git a/zebra/ChangeLog b/zebra/ChangeLog
index 3ce7b9ea..d9cae283 100644
--- a/zebra/ChangeLog
+++ b/zebra/ChangeLog
@@ -1,3 +1,31 @@
+2008-02-26 Denis Ovsienko
+ * zebra_rib.[ch]: (rib_lookup_and_pushup) New function, which makes sure,
+ that if_set_prefix() has nothing in its way of assigning an address.
+ * ioctl.c: (if_set_prefix) Use rib_lookup_and_pushup() to resolve
+ bug #326.
+
+2008-01-11 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
+
+ * ioctl.c: If HAVE_BSD_LINK_DETECT is defined, include <net/if_media.h>
+ (if_get_flags) Remove debug messages about BSD link state.
+ * kernel_socket.c: (bsd_linkdetect_translate) If link state
+ is unknown, we should set the IFF_RUNNING flag.
+
+2008-01-10 Ingo Flaschberger <if@xip.at>
+
+ * ioctl.c: (if_get_flags) If HAVE_BSD_LINK_DETECT, use the SIOCGIFMEDIA
+ ioctl to ascertain link state.
+ * kernel_socket.c: (bsd_linkdetect_translate) New function to
+ map the ifm_data.ifi_link_state value into the IFF_RUNNING flag.
+ (ifm_read) Call bsd_linkdetect_translate to fix the IFF_RUNNING
+ flag before calling if_flags_update.
+
+2008-01-08 Michael Larson <mike@vyatta.com>
+
+ * zebra_rib.c: (nexthop_active_check) Replace if_is_up with
+ if_is_operative to solve problems with static interface
+ routes not behaving properly with link-detect.
+
2007-11-12 Denis Ovsienko
* connected.c: (connected_up_ipv4, connected_down_ipv4,
diff --git a/zebra/ioctl.c b/zebra/ioctl.c
index c9ec8d57..d536771a 100644
--- a/zebra/ioctl.c
+++ b/zebra/ioctl.c
@@ -33,6 +33,10 @@
#include "zebra/rt.h"
#include "zebra/interface.h"
+#ifdef HAVE_BSD_LINK_DETECT
+#include <net/if_media.h>
+#endif /* HAVE_BSD_LINK_DETECT*/
+
extern struct zebra_privs_t zserv_privs;
/* clear and set interface name string */
@@ -192,6 +196,7 @@ if_set_prefix (struct interface *ifp, struct connected *ifc)
struct prefix_ipv4 *p;
p = (struct prefix_ipv4 *) ifc->address;
+ rib_lookup_and_pushup (p);
memset (&addreq, 0, sizeof addreq);
strncpy ((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name);
@@ -344,6 +349,9 @@ if_get_flags (struct interface *ifp)
{
int ret;
struct ifreq ifreq;
+#ifdef HAVE_BSD_LINK_DETECT
+ struct ifmediareq ifmr;
+#endif /* HAVE_BSD_LINK_DETECT */
ifreq_set_name (&ifreq, ifp);
@@ -353,6 +361,24 @@ if_get_flags (struct interface *ifp)
zlog_err("if_ioctl(SIOCGIFFLAGS) failed: %s", safe_strerror(errno));
return;
}
+#ifdef HAVE_BSD_LINK_DETECT /* Detect BSD link-state at start-up */
+ (void) memset(&ifmr, 0, sizeof(ifmr));
+ strncpy (&ifmr.ifm_name, ifp->name, IFNAMSIZ);
+ if (if_ioctl(SIOCGIFMEDIA, (caddr_t) &ifmr) < 0)
+ {
+ zlog_err("if_ioctl(SIOCGIFMEDIA) failed: %s", safe_strerror(errno));
+ return;
+ }
+ if (ifmr.ifm_status & IFM_AVALID) /* Link state is valid */
+ {
+ if (ifmr.ifm_status & IFM_ACTIVE)
+ SET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
+ else
+ UNSET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
+ }
+ else /* Force always up */
+ SET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
+#endif /* HAVE_BSD_LINK_DETECT */
if_flags_update (ifp, (ifreq.ifr_flags & 0x0000ffff));
}
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index a91d76f5..2e04b031 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -295,6 +295,19 @@ ifan_read (struct if_announcemsghdr *ifan)
}
#endif /* RTM_IFANNOUNCE */
+#ifdef HAVE_BSD_LINK_DETECT
+/* BSD link detect translation */
+static void
+bsd_linkdetect_translate (struct if_msghdr *ifm)
+{
+ if ((ifm->ifm_data.ifi_link_state >= LINK_STATE_UP) ||
+ (ifm->ifm_data.ifi_link_state == LINK_STATE_UNKNOWN))
+ SET_FLAG(ifm->ifm_flags, IFF_RUNNING);
+ else
+ UNSET_FLAG(ifm->ifm_flags, IFF_RUNNING);
+}
+#endif /* HAVE_BSD_LINK_DETECT */
+
/*
* Handle struct if_msghdr obtained from reading routing socket or
* sysctl (from interface_list). There may or may not be sockaddrs
@@ -426,6 +439,11 @@ ifm_read (struct if_msghdr *ifm)
* structure with ifindex IFINDEX_INTERNAL.
*/
ifp->ifindex = ifm->ifm_index;
+
+#ifdef HAVE_BSD_LINK_DETECT /* translate BSD kernel msg for link-state */
+ bsd_linkdetect_translate(ifm);
+#endif /* HAVE_BSD_LINK_DETECT */
+
if_flags_update (ifp, ifm->ifm_flags);
#if defined(__bsdi__)
if_kvm_get_mtu (ifp);
@@ -453,6 +471,10 @@ ifm_read (struct if_msghdr *ifm)
return -1;
}
+#ifdef HAVE_BSD_LINK_DETECT /* translate BSD kernel msg for link-state */
+ bsd_linkdetect_translate(ifm);
+#endif /* HAVE_BSD_LINK_DETECT */
+
/* update flags and handle operative->inoperative transition, if any */
if_flags_update (ifp, ifm->ifm_flags);
diff --git a/zebra/rib.h b/zebra/rib.h
index 796a30eb..9621f2c8 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -212,6 +212,7 @@ extern struct nexthop *nexthop_blackhole_add (struct rib *);
extern struct nexthop *nexthop_ipv4_add (struct rib *, struct in_addr *,
struct in_addr *);
extern void rib_lookup_and_dump (struct prefix_ipv4 *);
+extern void rib_lookup_and_pushup (struct prefix_ipv4 *);
extern void rib_dump (const char *, const struct prefix_ipv4 *, const struct rib *);
extern int rib_lookup_ipv4_route (struct prefix_ipv4 *, union sockunion *);
#define ZEBRA_RIB_LOOKUP_ERROR -1
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 5de320d9..7a6c7050 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -1657,6 +1657,62 @@ void rib_lookup_and_dump (struct prefix_ipv4 * p)
}
}
+/* Check if requested address assignment will fail due to another
+ * route being installed by zebra in FIB already. Take necessary
+ * actions, if needed: remove such a route from FIB and deSELECT
+ * corresponding RIB entry. Then put affected RN into RIBQ head.
+ */
+void rib_lookup_and_pushup (struct prefix_ipv4 * p)
+{
+ struct route_table *table;
+ struct route_node *rn;
+ struct rib *rib;
+ unsigned changed = 0;
+
+ if (NULL == (table = vrf_table (AFI_IP, SAFI_UNICAST, 0)))
+ {
+ zlog_err ("%s: vrf_table() returned NULL", __func__);
+ return;
+ }
+
+ /* No matches would be the simplest case. */
+ if (NULL == (rn = route_node_lookup (table, (struct prefix *) p)))
+ return;
+
+ /* Unlock node. */
+ route_unlock_node (rn);
+
+ /* Check all RIB entries. In case any changes have to be done, requeue
+ * the RN into RIBQ head. If the routing message about the new connected
+ * route (generated by the IP address we are going to assign very soon)
+ * comes before the RIBQ is processed, the new RIB entry will join
+ * RIBQ record already on head. This is necessary for proper revalidation
+ * of the rest of the RIB.
+ */
+ for (rib = rn->info; rib; rib = rib->next)
+ {
+ if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) &&
+ ! RIB_SYSTEM_ROUTE (rib))
+ {
+ changed = 1;
+ if (IS_ZEBRA_DEBUG_RIB)
+ {
+ char buf[INET_ADDRSTRLEN];
+ inet_ntop (rn->p.family, &p->prefix, buf, INET_ADDRSTRLEN);
+ zlog_debug ("%s: freeing way for connected prefix %s/%d", __func__, buf, p->prefixlen);
+ rib_dump (__func__, (struct prefix_ipv4 *)&rn->p, rib);
+ }
+ rib_uninstall (rn, rib);
+ }
+ }
+ if (changed)
+ {
+ work_queue_aim_head (zebrad.ribq, 1);
+ rib_queue_add (&zebrad, rn);
+ work_queue_aim_head (zebrad.ribq, 0);
+ }
+}
+
int
rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)
{