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--debian/control3
-rwxr-xr-xdebian/rules3
-rw-r--r--debian/vyatta-quagga.preinst6
-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/smux.c25
-rw-r--r--lib/smux.h2
-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--vtysh/vtysh_main.c1
-rw-r--r--watchlink/Makefile.am8
-rw-r--r--watchlink/netlink_event.cc335
-rw-r--r--watchlink/netlink_event.hh274
-rw-r--r--watchlink/netlink_linkstatus.cc318
-rw-r--r--watchlink/netlink_linkstatus.hh56
-rw-r--r--watchlink/netlink_listener.cc271
-rw-r--r--watchlink/netlink_listener.hh50
-rw-r--r--watchlink/netlink_send.cc318
-rw-r--r--watchlink/netlink_send.hh39
-rw-r--r--watchlink/netlink_utils.cc59
-rw-r--r--watchlink/netlink_utils.hh20
-rw-r--r--watchlink/rl_str_proc.cc90
-rw-r--r--watchlink/rl_str_proc.hh32
-rw-r--r--watchlink/watchlink.cc293
-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
60 files changed, 849 insertions, 2229 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/debian/control b/debian/control
index bfd9db1e..26491df3 100644
--- a/debian/control
+++ b/debian/control
@@ -12,7 +12,8 @@ Build-Depends: debhelper (>= 5),
imagemagick,
ghostscript | gs-gpl,
groff,
- po-debconf
+ po-debconf,
+ libsnmp-dev
Standards-Version: 3.7.2
Vcs-Git: http://suva.vyatta.git/quagga.git
diff --git a/debian/rules b/debian/rules
index ba47d987..e89dc246 100755
--- a/debian/rules
+++ b/debian/rules
@@ -18,6 +18,7 @@ PACKAGE=vyatta-quagga
PKGDIR=$(CURDIR)/debian/$(PACKAGE)
BUILD_STAMP=debian/build-stamp
CFLAGS = -Wall -g
+WANT_SNMP=1
ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
CFLAGS += -O0
@@ -107,7 +108,7 @@ install: build
install -D --mode=0644 debian/lintian $(PKGDIR)/usr/share/lintian/overrides/$(PACKAGE)
ifeq ($(WANT_SNMP), 1)
- install -D --mode=0644 zebra/GNOME-PRODUCT-ZEBRA-MIB $(PKGDIR)/usr/share/snmp/mibs
+ install -D --mode=0644 zebra/GNOME-PRODUCT-ZEBRA-MIB $(PKGDIR)/usr/share/snmp/mibs/GNOME-PRODUCT-ZEBRA-MIB.txt
endif
diff --git a/debian/vyatta-quagga.preinst b/debian/vyatta-quagga.preinst
index 4222ef3b..af61947a 100644
--- a/debian/vyatta-quagga.preinst
+++ b/debian/vyatta-quagga.preinst
@@ -71,6 +71,12 @@ if [ "$1" = "install" ]; then
EOF
fi
done
+
+
+ echo "smux peer .1.3.6.1.4.1.3317.1.2.5" >> $ETC_DIR/ospfd.conf
+ echo "smux peer .1.3.6.1.4.1.3317.1.2.2" >> $ETC_DIR/bgpd.conf
+ echo "smux peer .1.3.6.1.4.1.3317.1.2.3" >> $ETC_DIR/ripd.conf
+
if [ ! -e $ETC_DIR/vtysh.conf ] ; then
touch $ETC_DIR/vtysh.conf
chown quagga:quaggavty $ETC_DIR/vtysh.conf
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/smux.c b/lib/smux.c
index 6285c94d..c5159dd9 100644
--- a/lib/smux.c
+++ b/lib/smux.c
@@ -226,7 +226,8 @@ smux_socket ()
}
freeaddrinfo(res0);
if (sock < 0)
- zlog_warn ("Can't connect to SNMP agent with SMUX");
+ if (debug_smux)
+ zlog_debug ("Can't connect to SNMP agent with SMUX");
#else
sock = socket (AF_INET, SOCK_STREAM, 0);
if (sock < 0)
@@ -257,7 +258,8 @@ smux_socket ()
{
close (sock);
smux_sock = -1;
- zlog_warn ("Can't connect to SNMP agent with SMUX");
+ if (debug_smux)
+ zlog_debug ("Can't connect to SNMP agent with SMUX");
return -1;
}
#endif
@@ -1179,7 +1181,10 @@ smux_connect (struct thread *t)
int ret;
if (debug_smux)
- zlog_debug ("SMUX connect try %d", fail + 1);
+ {
+ fail = fail + 1;
+ zlog_debug ("SMUX connect try %d", fail);
+ }
/* Clear thread poner of myself. */
smux_connect_thread = NULL;
@@ -1188,8 +1193,10 @@ smux_connect (struct thread *t)
smux_sock = smux_socket ();
if (smux_sock < 0)
{
- if (++fail < SMUX_MAX_FAILURE)
- smux_event (SMUX_CONNECT, 0);
+ if (debug_smux)
+ zlog_debug ("SMUX socket/connection creation error");
+ // if (++fail < SMUX_MAX_FAILURE)
+ smux_event (SMUX_CONNECT, 0);
return 0;
}
@@ -1200,8 +1207,8 @@ smux_connect (struct thread *t)
zlog_warn ("SMUX open message send failed: %s", safe_strerror (errno));
close (smux_sock);
smux_sock = -1;
- if (++fail < SMUX_MAX_FAILURE)
- smux_event (SMUX_CONNECT, 0);
+ // if (++fail < SMUX_MAX_FAILURE)
+ smux_event (SMUX_CONNECT, 0);
return -1;
}
@@ -1212,8 +1219,8 @@ smux_connect (struct thread *t)
zlog_warn ("SMUX register message send failed: %s", safe_strerror (errno));
close (smux_sock);
smux_sock = -1;
- if (++fail < SMUX_MAX_FAILURE)
- smux_event (SMUX_CONNECT, 0);
+ // if (++fail < SMUX_MAX_FAILURE)
+ smux_event (SMUX_CONNECT, 0);
return -1;
}
diff --git a/lib/smux.h b/lib/smux.h
index 79d23e70..11f02e9e 100644
--- a/lib/smux.h
+++ b/lib/smux.h
@@ -39,7 +39,7 @@
#define SMUX_SET (ASN_CONTEXT | ASN_CONSTRUCTOR | 3)
#define SMUX_TRAP (ASN_CONTEXT | ASN_CONSTRUCTOR | 4)
-#define SMUX_MAX_FAILURE 3
+// #define SMUX_MAX_FAILURE 3
/* Structures here are mostly compatible with UCD SNMP 4.1.1 */
#define MATCH_FAILED (-1)
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/vtysh/vtysh_main.c b/vtysh/vtysh_main.c
index 51f376c7..d655e073 100644
--- a/vtysh/vtysh_main.c
+++ b/vtysh/vtysh_main.c
@@ -259,6 +259,7 @@ main (int argc, char **argv, char **env)
/* Initialize user input buffer. */
line_read = NULL;
+ setlinebuf(stdout);
/* Signal and others. */
vtysh_signal_init ();
diff --git a/watchlink/Makefile.am b/watchlink/Makefile.am
deleted file mode 100644
index 798275e5..00000000
--- a/watchlink/Makefile.am
+++ /dev/null
@@ -1,8 +0,0 @@
-## Process this file with automake to produce Makefile.in.
-
-INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib
-DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
-
-sbin_PROGRAMS = watchlink
-
-watchlink_SOURCES = watchlink.cc netlink_utils.cc netlink_send.cc netlink_listener.cc netlink_event.cc netlink_linkstatus.cc rl_str_proc.cc
diff --git a/watchlink/netlink_event.cc b/watchlink/netlink_event.cc
deleted file mode 100644
index 7bda70bb..00000000
--- a/watchlink/netlink_event.cc
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * Module: netlink_event.cc
- *
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- */
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <linux/rtnetlink.h>
-#include <net/if.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <syslog.h>
-
-#include <iostream>
-#include <string>
-#include "netlink_event.hh"
-
-using namespace std;
-
-/**
- *
- *
- **/
-NetlinkEvent::NetlinkEvent(int type,
- std::string iface,
- int mtu,
- unsigned char *mac,
- bool enabled,
- bool running,
- IPv4 local,
- IPv4 addr,
- IPv4 broadcast,
- int mask_len,
- int index) :
- _type(type),
- _iface(iface),
- _vif(false),
- _mtu(mtu),
- _enabled(enabled),
- _running(running),
- _local(local),
- _addr(addr),
- _broadcast(broadcast),
- _mask_len(mask_len),
- _index(index)
-{
- memcpy(_mac, mac, 6);
- if (_iface.find(".") != string::npos) {
- _vif = true;
- }
-}
-
-/**
- *
- *
- **/
-NetlinkEvent::~NetlinkEvent()
-{
-}
-
-/**
- *
- *
- **/
-void
-NetlinkEvent::log()
-{
- syslog(LOG_USER | LOG_INFO, "NetlinkEvent::log(): type: %d, iface: %s, mtu: %d, local: %s, addr: %s, bc: %s, mask: %d, index: %d", _type, _iface.c_str(), _mtu, _local.str().c_str(), _addr.str().c_str(), _broadcast.str().c_str(), _mask_len, _index);
-}
-
-/**
- *
- *
- **/
-NetlinkEventManager::NetlinkEventManager(bool debug) :
- _debug(debug)
-{
-
-}
-
-/**
- *
- *
- *
- **/
-NetlinkEventManager::~NetlinkEventManager()
-{
-}
-
-/**
- *
- *
- *
- **/
-void
-NetlinkEventManager::process(unsigned char* pkt, int size)
-{
- if (size <= 0) {
- return;
- }
-
- size_t ps = size_t(size);
-
- const struct nlmsghdr* mh;
- for (mh = reinterpret_cast<const struct nlmsghdr*>(pkt);
- NLMSG_OK(mh, ps);
- mh = NLMSG_NEXT(const_cast<struct nlmsghdr*>(mh), ps)) {
- parse_msg(mh);
- }
-}
-
-/**
- *
- *
- **/
-bool
-NetlinkEventManager::pop(NetlinkEvent &e)
-{
- char buf[20];
- sprintf(buf, "%d", _coll.size());
-
- NLEventIter iter = _coll.begin();
- if (iter != _coll.end()) {
- e = *iter;
- _coll.erase(iter);
- return true;
- }
- return false;
-}
-
-/**
- *
- *
- *
- **/
-void
-NetlinkEventManager::parse_msg(const struct nlmsghdr *nlHdr)
-{
- bool enabled;
- bool running;
- string iface;
- int mtu = -1;
- int index = -1;
- unsigned char mac[6];
- IPv4 addr, local, broadcast;
- int mask_len = -1;
-
- bzero(mac, 6);
-
- struct ifinfomsg* ifInfo = (struct ifinfomsg *)NLMSG_DATA(nlHdr);
-
- //link state flag
- enabled = ifInfo->ifi_flags & IFF_UP;
- running = enabled && (ifInfo->ifi_flags & IFF_RUNNING);
- index = ifInfo->ifi_index;
-
- struct rtattr* rtAttr = (struct rtattr *)IFLA_RTA(ifInfo);
- int rtLen = IFLA_PAYLOAD(nlHdr);
-
- switch (nlHdr->nlmsg_type) {
- case RTM_NEWLINK:
- case RTM_DELLINK:
- case RTM_NEWADDR:
- case RTM_DELADDR:
- for(;RTA_OK(rtAttr,rtLen);rtAttr = RTA_NEXT(rtAttr,rtLen)){
- if (nlHdr->nlmsg_type == RTM_NEWLINK ||
- nlHdr->nlmsg_type == RTM_DELLINK) {
- switch(rtAttr->rta_type) {
- case IFLA_IFNAME:
- iface = string((char*)RTA_DATA(rtAttr));
- break;
- case IFLA_ADDRESS:
- memcpy(mac, RTA_DATA(rtAttr), 6);
- break;
- case IFLA_MTU:
- mtu = *((unsigned int *)RTA_DATA(rtAttr));
- break;
- default:
- break;
- }
- }
- else if (nlHdr->nlmsg_type == RTM_NEWADDR ||
- nlHdr->nlmsg_type == RTM_DELADDR) {
- uint32_t address;
- struct ifaddrmsg *ifAddrs;
- ifAddrs = (struct ifaddrmsg *)NLMSG_DATA(nlHdr);
- mask_len = ifAddrs->ifa_prefixlen;
-
- switch(rtAttr->rta_type) {
- case IFA_LOCAL:
- address = *(uint32_t *)RTA_DATA(rtAttr);
- local = IPv4(address);
- break;
- case IFA_ADDRESS:
- address = *(uint32_t *)RTA_DATA(rtAttr);
- addr = IPv4(address);
- break;
- case IFA_LABEL:
- iface = string((char*)RTA_DATA(rtAttr));
- break;
- case IFA_BROADCAST:
- address = *(uint32_t *)RTA_DATA(rtAttr);
- broadcast = IPv4(address);
- break;
- default:
- break;
- }
- }
- }
- {
- NetlinkEvent e(nlHdr->nlmsg_type,
- iface,
- mtu,
- mac,
- enabled,
- running,
- local,
- addr,
- broadcast,
- mask_len,
- index);
-
- e.set_ifinfomsg(ifInfo);
-
- if (_debug) {
- e.log();
- }
- _coll.push_back(e);
- }
- break;
- case NLMSG_ERROR: {
- struct nlmsgerr *err = (struct nlmsgerr*) NLMSG_DATA(nlHdr);
- //drop down to info as this can be caused on startup by downed interfaces that are requested for dump, or attempting to remove routes on downed interface after startup (if they have already been removed).
- syslog(LOG_INFO,"netlink message of type ERROR received: %s",strerror(-err->error));
- // cerr << "netlink message of type ERROR received: " ;
- // cerr << string(strerror(-err->error)) << endl;
- }
- break;
- case NLMSG_DONE:
- // if (_debug) {
- // cout << "netlink message of type DONE received" << endl;
- // }
- break;
- case NLMSG_NOOP:
- syslog(LOG_INFO,"netlink message of type NOOP received");
- break;
- default:
- syslog(LOG_INFO,"unknown netlink message type received");
- break;
- }
-}
-
-
-/**
- *
- *
- *
- **/
-typedef struct {
- unsigned int iff_flag;
- char *name;
-} iff_flags_name;
-
-
-string
-NetlinkEvent::get_ifinfomsg()
-{
- string ret;
- char buf[40];
-
- sprintf(buf, "%u", _ifinfo.ifi_family);
- ret = "ifi_family: " + string(buf) + ", ";
- sprintf(buf, "%u", _ifinfo.ifi_type);
- ret += "ifi_type: " + string(buf) + ", ";
- sprintf(buf, "%d", _ifinfo.ifi_index);
- ret += "ifi_index: " + string(buf) + ", ";
- sprintf(buf, "%u", _ifinfo.ifi_flags);
- ret += "ifi_flags: " + string(buf) + ", ";
- sprintf(buf, "%u", _ifinfo.ifi_change);
- ret += "ifi_change: " + string(buf);
- return ret;
-}
-
-/*
-string
-NetlinkEvent::operator<<(const ostream &o)
-{
- UNUSED(o);
- return ("");
-}
-*/
-std::ostream & operator <<(std::ostream & Stream, const NetlinkEvent & instance)
-{
- // Stream << ... fields from instance
- const NetlinkEvent foo = instance;
- return Stream;
-}
-
-
-/* from quagga prefix.c */
-/* Apply mask to IPv4 prefix. */
-/* Maskbit. */
-static u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
- 0xf8, 0xfc, 0xfe, 0xff};
-
-
-uint32_t
-apply_mask_ipv4 (const uint32_t p, const unsigned char m)
-{
- uint32_t val(p);
- u_char *pnt = (u_char *) &val;
- int index;
- int offset;
-
- index = m / 8;
- if (index < 4) {
- offset = m % 8;
-
- pnt[index] &= maskbit[offset];
- index++;
-
- while (index < 4) {
- pnt[index++] = 0;
- }
- }
- return val;
-}
-
-
-
diff --git a/watchlink/netlink_event.hh b/watchlink/netlink_event.hh
deleted file mode 100644
index 76ccefa6..00000000
--- a/watchlink/netlink_event.hh
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * Module: netlink_event.hh
- *
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- */
-#ifndef __NETLINK_EVENT_HH__
-#define __NETLINK_EVENT_HH__
-
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <net/if.h>
-
-#include <string>
-#include <vector>
-#include <ostream>
-#include <linux/rtnetlink.h>
-
-uint32_t
-apply_mask_ipv4 (const uint32_t p, const unsigned char m);
-
-
-class Mac
-{
-public:
- Mac() {}
-private:
- unsigned char _addr[6];
-};
-
-class IPv4
-{
-public:
- IPv4() : _addr(-1) {}
- IPv4(uint32_t addr) : _addr(addr) {}
- virtual ~IPv4() {}
-
- uint32_t
- get() {return _addr;}
-
- virtual
- std::string
- str()
- {
- in_addr addr;
- addr.s_addr = _addr;
- char* buf = inet_ntoa(addr);
- return std::string(buf);
- }
-
-protected:
- uint32_t _addr;
-};
-
-
-class IPv4net : protected IPv4
-{
-public:
- IPv4net() : IPv4(-1),_mask_length(32) {}
- IPv4net(uint32_t addr, char mask_len) : IPv4(addr),_mask_length(mask_len) {}
- IPv4net(std::string &net) {
- int pos = net.find("/");
- if (pos == std::string::npos) {
- pos = net.length();
- _mask_length = 32;
- }
- else {
- uint32_t m_val = strtoul(net.substr(pos+1,net.length()-1).c_str(),NULL,10);
- if (m_val > 32) {
- m_val = 32;
- }
- _mask_length = m_val;
- }
- uint32_t a_val = inet_addr(net.substr(0,pos).c_str());
- if (a_val == INADDR_NONE) {
- this->_addr = 0;
- return;
- }
- this->_addr = apply_mask_ipv4(a_val,_mask_length);
- }
-
- uint32_t
- get_addr() {return get();}
-
- char
- get_mask_length() {return _mask_length;}
-
- bool
- contains(IPv4 &addr) {
- //check if addr is within specified addr range
- return (apply_mask_ipv4(addr.get(),_mask_length) == _addr);
- }
-
- bool
- contains(IPv4 addr) {
- //check if addr is within specified addr range
- return (apply_mask_ipv4(addr.get(),_mask_length) == _addr);
- }
-
- std::string
- str()
- {
- in_addr addr;
- addr.s_addr = _addr;
- char *buf = inet_ntoa(addr);
-
- std::string tmp(buf);
-
- char buf2[80];
- sprintf(buf2,"%d",_mask_length);
- tmp += std::string("/") + buf2;
- return tmp;
- }
-
-private:
- char _mask_length;
-};
-
-
-/**
- *
- *
- **/
-class NetlinkEvent
-{
-public:
- NetlinkEvent(int type,
- std::string iface,
- int mtu,
- unsigned char *mac,
- bool enabled,
- bool running,
- IPv4 local,
- IPv4 addr,
- IPv4 broadcast,
- int mask_len,
- int index);
-
- NetlinkEvent() :
- _type(-1),
- _mtu(-1),
- _enabled(false),
- _running(false),
- _mask_len(-1),
- _index(-1) {}
-
- ~NetlinkEvent();
-
-
- std::string
- get_iface() const {return _iface;}
-
- int
- get_mtu() const {return _mtu;}
-
- std::string
- get_mac_str() const {
- char buf[18];
- sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
- _mac[0], _mac[1], _mac[2],
- _mac[3], _mac[4], _mac[5]
- );
- return std::string(buf);
- }
-
- int
- get_type() const {return _type;}
- /*
- unsigned char*
- get_mac() const {
- return _mac;
- }
- */
-
- int
- get_ifi_type() const {return _ifinfo.ifi_type;}
-
- bool
- get_enabled() const {return _enabled;}
-
- bool
- get_running() const {return _running;}
-
- IPv4
- get_local_addr() const {return _local;}
-
- IPv4
- get_addr() const {return _addr;}
-
- IPv4
- get_broadcast() const {return _broadcast;}
-
- int
- get_mask_len() const {return _mask_len;}
-
- bool
- is_link_up() const {return _enabled;}
-
- int
- get_index() const {return _index;}
-
- bool
- is_vif() const {return _vif;}
-
- void
- log();
-
- void
- set_ifinfomsg(ifinfomsg *ifinfo) {_ifinfo = *ifinfo;}
-
- std::string
- get_ifinfomsg();
-
-private:
- int _type;
- std::string _iface;
- bool _vif;
- int _mtu;
- unsigned char _mac[6];
- bool _enabled;
- bool _running;
- IPv4 _local;
- IPv4 _addr;
- IPv4 _broadcast;
- int _mask_len;
- int _index;
-
- //debug
- struct ifinfomsg _ifinfo;
-};
-
-
-
-/**
- *
- *
- **/
-class NetlinkEventManager
-{
-public:
- typedef std::vector<NetlinkEvent> NLEventColl;
- typedef std::vector<NetlinkEvent>::iterator NLEventIter;
-
-public: //methods
- friend std::ostream & operator<< (std::ostream &, const NetlinkEvent &);
-
- NetlinkEventManager(bool debug);
-
- ~NetlinkEventManager();
-
- void
- process(unsigned char *pkt, int size);
-
- bool
- pop(NetlinkEvent &e);
-
-
-
-private: //methods
- void
- parse_msg(const struct nlmsghdr*);
-
-private: //variables
- NLEventColl _coll;
- bool _debug;
-};
-
-
-
-
-#endif // __NETLINK_EVENT_HH__
diff --git a/watchlink/netlink_linkstatus.cc b/watchlink/netlink_linkstatus.cc
deleted file mode 100644
index 9dd26fbd..00000000
--- a/watchlink/netlink_linkstatus.cc
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Module: netlink_linkstatus.cc
- *
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- */
-#include <stdio.h>
-#include <sys/socket.h>
-#include <sys/file.h>
-#include <iostream>
-#include <string>
-#include <syslog.h>
-#include <errno.h>
-
-#include "rl_str_proc.hh"
-#include "netlink_send.hh"
-#include "netlink_event.hh"
-#include "netlink_utils.hh"
-#include "netlink_linkstatus.hh"
-
-
-using namespace std;
-
-/**
- *
- *
- **/
-NetlinkLinkStatus::NetlinkLinkStatus(int send_sock, const string &link_dir, bool debug) :
- _nl_send(debug),
- _send_sock(send_sock),
- _link_dir(link_dir),
- _debug(debug)
-{
- if (_send_sock < 0) {
- syslog(LOG_ERR,"NetlinkListStatus::NetlinkLinkStatus(), send sock is bad value");
- cerr << "NetlinkListStatus::NetlinkLinkStatus(), send sock is bad value" << endl;
- }
-
- if (_link_dir.empty()) {
- syslog(LOG_ERR,"NetlinkListStatus::NetlinkLinkStatus(), no link status directory specified");
- cerr << "NetlinkListStatus::NetlinkLinkStatus(), no link status directory specified" << endl;
- }
-}
-
-/**
- *
- *
- **/
-NetlinkLinkStatus::~NetlinkLinkStatus()
-{
-}
-
-/**
- *
- *
- **/
-void
-NetlinkLinkStatus::process(const NetlinkEvent &event)
-{
- bool state_event = false;
-
- IfaceStateIter iter = _iface_state_coll.find(event.get_index());
- if (iter == _iface_state_coll.end()) {
- if (event.get_type() == RTM_NEWLINK || event.get_type() == RTM_DELLINK) {
- //start maintaining state information here.
- _iface_state_coll.insert(pair<int,bool>(event.get_index(),event.get_running()));
-
- //let's clean up directory here!
- char buf[40];
- sprintf(buf,"%d",event.get_index());
- string file = _link_dir + "/" + buf;
- unlink(file.c_str());
- }
- return;
- }
-
- bool running_old = iter->second;
- bool running_new = event.get_running();
-
- //capture link status on link messages only
- if (event.get_type() == RTM_NEWLINK ||
- event.get_type() == RTM_DELLINK) {
- // _iface_state_coll.insert(pair<int,bool>(event.get_index(),event.get_running()));
- _iface_state_coll[event.get_index()] = event.get_running();
- if (running_old != running_new) {
- state_event = true;
- }
- }
-
- //is this a transition from up->down, or down->up?
- if (state_event) {
- if (running_new) {
- process_going_up(event);
- }
- else {
- process_going_down(event);
- }
- }
- else {
- if (running_old) {
- process_up(event);
- }
- else {
- process_down(event);
- }
- }
-}
-
-/**
- *
- * file is in the format of IFINDEX,IP,MASK
- *
- **/
-int
-NetlinkLinkStatus::process_up(const NetlinkEvent &event)
-{
- if (_debug) {
- cout << "NetlinkLinkStatus::process_up(): " << event.get_iface() << endl;
- }
- //can't think of anything that needs to go here yet.
- return 0;
-}
-
-/**
- *
- *
- **/
-int
-NetlinkLinkStatus::process_going_up(const NetlinkEvent &event)
-{
- if (_debug) {
- cout << "NetlinkLinkStatus::process_going_up(): " << event.get_iface() << endl;
- }
- syslog(LOG_INFO,"Interface is now active: %s",event.get_iface().c_str());
-
- //check for link status file, otherwise return
- char buf[40];
- sprintf(buf,"%d",event.get_index());
- string file = _link_dir + "/" + buf;
- FILE *fp = fopen(file.c_str(), "r");
- if (fp == NULL) {
- syslog(LOG_INFO,"NetlinkLinkStatus::process_going_up(), failed to open state file: %s",
- strerror(errno));
- // cerr << "NetlinkLinkStatus::process_going_up(), failed to open state file" << endl;
- return -1; //means we are still up, ignore...
- }
-
- if (flock(fileno(fp), LOCK_SH)) {
- syslog(LOG_INFO, "NetlinkLinkStatus::process_going_up() failed to acquire lock: %s",
- strerror(errno));
- fclose(fp);
- return -1;
- }
-
- char str[1025];
- while (fgets(str, 1024, fp)) {
- string line(str);
-
- StrProc tokens(line, ",");
- if (tokens.size() != 4) {
- syslog(LOG_INFO,"NetlinkLinkStatus::process_up(), failure to parse link status file, exiting(): %s, size: %d", line.c_str(), tokens.size());
- // cerr << "NetlinkLinkStatus::process_up(), failure to parse link status file, exiting(): " << line << ", size: " << tokens.size() << endl;
- fclose(fp);
- return -1;
- }
-
- int ifindex = strtoul(tokens.get(0).c_str(),NULL,10);
- uint32_t local_addr = strtoul(tokens.get(1).c_str(),NULL,10);
- uint32_t addr = strtoul(tokens.get(2).c_str(),NULL,10);
- int mask_len = strtoul(tokens.get(3).c_str(),NULL,10);
-
-
- bool err = _nl_send.send_set(_send_sock, ifindex, local_addr, addr, mask_len, RTM_NEWADDR);
- if (err) {
- syslog(LOG_INFO,"NetlinkLinkStatus::process_up(), failure in setting interface back to up");
- }
- /*
- bool err = _nl_send.send_set_route(_send_sock, ifindex, local_addr, local_addr, 32, RTM_NEWROUTE, RT_TABLE_LOCAL, RTN_LOCAL, RT_SCOPE_HOST);
- if (err) {
- syslog(LOG_INFO,"NetlinkLinkStatus::process_up(), failure in setting interface back to up");
- }
- //COMPUTE FIRST ADDRESS
- uint32_t first_addr = ipv4_first_addr(local_addr, mask_len);
- err = _nl_send.send_set_route(_send_sock, ifindex, local_addr, first_addr, 32, RTM_NEWROUTE, RT_TABLE_LOCAL, RTN_BROADCAST, RT_SCOPE_LINK);
- if (err) {
- syslog(LOG_INFO,"NetlinkLinkStatus::process_up(), failure in setting interface back to up");
- }
- //COMPUTE LAST ADDRESS
- uint32_t last_addr = ipv4_broadcast_addr(local_addr, mask_len);
- err = _nl_send.send_set_route(_send_sock, ifindex, local_addr, last_addr, 32, RTM_NEWROUTE, RT_TABLE_LOCAL, RTN_BROADCAST, RT_SCOPE_LINK);
- if (err) {
- syslog(LOG_INFO,"NetlinkLinkStatus::process_up(), failure in setting interface back to up");
- }
-
- //reinsert addresses to interface
- err = _nl_send.send_set_route(_send_sock, ifindex, local_addr, first_addr, mask_len, RTM_NEWROUTE, RT_TABLE_MAIN, RTN_UNICAST, RT_SCOPE_LINK);
- if (err) {
- syslog(LOG_INFO,"NetlinkLinkStatus::process_up(), failure in setting interface back to up");
- }
- */
- }
-
- fclose(fp);
-
- //remove file
- unlink(file.c_str());
-
- return 0;
-}
-
-/**
- * send an ip flush command and capture all the rtm_deladdr messages to the file...
- *
- **/
-int
-NetlinkLinkStatus::process_down(const NetlinkEvent &event)
-{
- if (_debug) {
- cout << "NetlinkLinkStatus::process_down(): " << event.get_iface() << endl;
- }
-
- if (event.get_type() != RTM_NEWADDR) {
- return 0;
- }
-
- if (event.get_index() < 0 || event.get_local_addr().get() == 0 || event.get_mask_len() < 1) {
- return 0;
- }
-
- if (_debug) {
- cout << "netlinkLinkStatus::process_down(), processing valid request" << endl;
- }
-
- //append to file...
- char buf[40];
- sprintf(buf,"%d",event.get_index());
- string file = _link_dir + "/" + buf;
- FILE *fp = fopen(file.c_str(), "a");
- if (fp == NULL) {
- syslog(LOG_INFO,"NetlinkLinkStatus::process_down(), failed to open state file");
- // cerr << "NetlinkLinkStatus::process_down(), failed to open state file" << endl;
- return -1;
- }
-
- if (flock(fileno(fp), LOCK_EX)) {
- syslog(LOG_INFO, "NetlinkLinkStatus::process_down() failed to acquire lock: %s",
- strerror(errno));
- fclose(fp);
- return -1;
- }
-
- int ifindex = event.get_index();
- uint32_t local_addr = event.get_local_addr().get();
- int mask_len = event.get_mask_len();
-
- //create file on system
- //CRAJ--NEED TO HAVE THIS BE FROM A COLLECTION??? DEPENDS ON FORMAT OF NETLINK MSG
- sprintf(buf,"%d",ifindex);
- string line = string(buf) + ",";
- sprintf(buf,"%d",local_addr);
- line += string(buf) + ",";
- sprintf(buf,"%d",event.get_addr().get());
- line += string(buf) + ",";
- sprintf(buf,"%d",mask_len);
- line += string(buf) + "\n";
-
- fputs(line.c_str(),fp);
-
- bool err = _nl_send.send_set(_send_sock, ifindex, event.get_local_addr().get(), event.get_addr().get(), mask_len, RTM_DELADDR);
- if (err) {
- syslog(LOG_INFO,"NetlinkLinkStatus::process_down(), failure in setting interface down");
- }
-
- /*
- uint32_t first_addr = ipv4_first_addr(local_addr, mask_len);
- //reinsert addresses to interface
- bool err = _nl_send.send_set_route(_send_sock, ifindex, local_addr, first_addr, mask_len, RTM_DELROUTE, RT_TABLE_MAIN, -1,-1);
- if (err) {
- syslog(LOG_INFO,"NetlinkLinkStatus::process_down(), failure in setting interface down");
- }
-
- uint32_t last_addr = ipv4_broadcast_addr(local_addr, mask_len);
- err = _nl_send.send_set_route(_send_sock, ifindex, local_addr, last_addr, 32, RTM_DELROUTE, RT_TABLE_LOCAL, -1,-1);
- if (err) {
- syslog(LOG_INFO,"NetlinkLinkStatus::process_down(), failure in setting interface down");
- }
-
- err = _nl_send.send_set_route(_send_sock, ifindex, first_addr, first_addr, 32, RTM_DELROUTE, RT_TABLE_LOCAL, -1,-1);
- if (err) {
- syslog(LOG_INFO,"NetlinkLinkStatus::process_down(), failure in setting interface down");
- }
-
- err = _nl_send.send_set_route(_send_sock, ifindex, local_addr, local_addr, 32, RTM_DELROUTE, RT_TABLE_LOCAL, -1,-1);
- if (err) {
- syslog(LOG_INFO,"NetlinkLinkStatus::process_down(), failure in setting interface down");
- }
- */
- fclose(fp);
-
- return 0;
-}
-
-int
-NetlinkLinkStatus::process_going_down(const NetlinkEvent &event)
-{
- if (_debug) {
- cout << "NetlinkLinkStatus::process_going_down(): " << event.get_iface() << "(" << event.get_index() << ")" << endl;
- }
- syslog(LOG_INFO,"Interface is now inactive: %s",event.get_iface().c_str());
-
- //pull interface addresses
- if (_nl_send.send_get(_send_sock, RTM_GETADDR, event.get_index())) {
- return -1;
- }
- return 0;
-}
diff --git a/watchlink/netlink_linkstatus.hh b/watchlink/netlink_linkstatus.hh
deleted file mode 100644
index b4eebbce..00000000
--- a/watchlink/netlink_linkstatus.hh
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Module: netlink_linkstatus.hh
- *
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- */
-#ifndef __NETLINK_LINKSTATUS_HH__
-#define __NETLINK_LINKSTATUS_HH__
-
-#include <string>
-#include <map>
-#include "netlink_event.hh"
-#include "netlink_send.hh"
-
-class NetlinkLinkStatus
-{
-public:
- typedef std::map<int,bool> IfaceStateColl;
- typedef std::map<int,bool>::iterator IfaceStateIter;
-
-public:
- NetlinkLinkStatus(int send_sock, const std::string &link_dir, bool debug);
- ~NetlinkLinkStatus();
-
- void
- process(const NetlinkEvent &event);
-
-private:
- int
- process_up(const NetlinkEvent &event);
-
- int
- process_down(const NetlinkEvent &event);
-
- int
- process_going_up(const NetlinkEvent &event);
-
- int
- process_going_down(const NetlinkEvent &event);
-
-
-private:
- NetlinkSend _nl_send;
- int _send_sock;
- std::string _link_dir;
- bool _debug;
-
- //keeps track of down messages where we've issued a
- //request for addresses but haven't received msg yet.
- IfaceStateColl _iface_state_coll;
-
-};
-
-#endif //__NETLINK_LINKSTATUS_HH__
diff --git a/watchlink/netlink_listener.cc b/watchlink/netlink_listener.cc
deleted file mode 100644
index be17fc76..00000000
--- a/watchlink/netlink_listener.cc
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Module: netlink_listener.cc
- *
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- */
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <linux/rtnetlink.h>
-#include <syslog.h>
-
-#include <map>
-#include <vector>
-#include <string>
-#include <iostream>
-
-#include "netlink_event.hh"
-#include "netlink_listener.hh"
-
-
-using namespace std;
-
-
-#define SO_RCV_BUF_SIZE_MAX (256*1024) // Desired socket buffer size
-#define SO_RCV_BUF_SIZE_MIN (48*1024) // Min. socket buffer size
-#define NLSOCK_BYTES (8*1024)
-
-/**
- *
- *
- **/
-NetlinkListener::NetlinkListener(bool debug) :
- _fd(-1),
- _is_multipart_message_read(false),
- _nl_event_mgr(debug)
-{
-
-}
-
-/**
- *
- *
- **/
-NetlinkListener::~NetlinkListener()
-{
- close(_fd);
-}
-
-/**
- *
- *
- **/
-int
-NetlinkListener::init()
-{
- struct sockaddr_nl snl;
- socklen_t snl_len;
-
- if (_fd >= 0) {
- syslog(LOG_ERR,"socket cannot be initialized");
- cerr << "socket cannot be initialized" << endl;
- return _fd;
- }
-
- _fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
- if (_fd < 0) {
- syslog(LOG_ERR,"Could not open netlink socket: %s",strerror(errno));
- cerr << string("Could not open netlink socket: ") << strerror(errno) << endl;
- return _fd;
- }
-
- comm_sock_set_rcvbuf(_fd, SO_RCV_BUF_SIZE_MAX, SO_RCV_BUF_SIZE_MIN);
-
- memset(&snl, 0, sizeof(snl));
- snl.nl_family = AF_NETLINK;
- snl.nl_pid = getpid(); // Let the kernel assign the pid to the socket
- snl.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;//_nl_groups;
- if (bind(_fd, reinterpret_cast<struct sockaddr*>(&snl), sizeof(snl)) < 0) {
- syslog(LOG_ERR,"bind(AF_NETLINK) failed: ",strerror(errno));
- cerr << string("bind(AF_NETLINK) failed: ") << strerror(errno) << endl;
- close(_fd);
- _fd = -1;
- return _fd;
- }
-
- snl_len = sizeof(snl);
- if (getsockname(_fd, reinterpret_cast<struct sockaddr*>(&snl), &snl_len) < 0) {
- syslog(LOG_ERR,"getsockname(AF_NETLINK) failed: ",strerror(errno));
- cerr << string("getsockname(AF_NETLINK) failed: ") << strerror(errno) << endl;
- close(_fd);
- _fd = -1;
- return _fd;
- }
- if (snl_len != sizeof(snl)) {
- syslog(LOG_ERR,"Wrong address length of AF_NETLINK socket: ");
- cerr << string("Wrong address length of AF_NETLINK socket: ") << endl;
- close(_fd);
- _fd = -1;
- return _fd;
- }
- if (snl.nl_family != AF_NETLINK) {
- syslog(LOG_ERR,"wrong address family of AF_NETLINK socket: ");;
- cerr << string("Wrong address family of AF_NETLINK socket: ") << endl;
- close(_fd);
- _fd = -1;
- return _fd;
- }
- return _fd;
-}
-
-/**
- *
- *
- **/
-bool
-NetlinkListener::process(NetlinkEvent &e, multimap<string,IPv4net> filter)
-{
- bool state = process(e);
- //is this a non-ethernet msg?
- if ((e.get_type() == RTM_DELLINK || e.get_type() == RTM_NEWLINK) && e.get_ifi_type() != 1/*ARPHRD_ETHER*/) {
- e = NetlinkEvent();
- state = false;
- }
- else {
- multimap<string,IPv4net>::iterator iter = filter.begin();
- while (iter != filter.end()) {
- if (iter->first == e.get_iface() || iter->first == "*") { //found interface exclusion
- if (iter->second.contains(e.get_local_addr())) {
- e = NetlinkEvent();
- state = false;
- break;
- }
- }
- ++iter;
- }
- }
-
-
- return state;
-}
-
-/**
- *
- *
- **/
-bool
-NetlinkListener::process(NetlinkEvent &e)
-{
- if (_fd <= 0) {
- return false;
- }
-
- vector<uint8_t> message;
- vector<uint8_t> buffer(NLSOCK_BYTES);
- size_t last_mh_off = 0;
- size_t off = 0;
- ssize_t got = -1;
-
- char buf[20];
-
- for ( ; ; ) {
- //don't block on recv
- do {
- got = recv(_fd, &buffer[0], buffer.size(), MSG_DONTWAIT | MSG_PEEK);
- if ((got < 0) && (errno == EINTR))
- continue; // XXX: the receive was interrupted by a signal
- if ((got < 0) || (got < (ssize_t)buffer.size()))
- break; // The buffer is big enough
- buffer.resize(buffer.size() + NLSOCK_BYTES);
- } while (true);
-
- got = recv(_fd, &buffer[0], buffer.size(),
- MSG_DONTWAIT);
- // got = read(_fd, &buffer[0], buffer.size());
- if (got < 0) {
- if (errno == EINTR)
- continue;
- // cerr << "Netlink socket read error: " << endl;
- break;
- }
-
- message.resize(message.size() + got);
- memcpy(&message[off], &buffer[0], got);
- off += got;
-
- if ((off - last_mh_off) < (ssize_t)sizeof(struct nlmsghdr)) {
- syslog(LOG_ERR,"Netlink socket recvfrom failed: message truncated: ");
- cerr << string("Netlink socket recvfrom failed: message truncated: ") << endl;
- break;
- }
-
- //
- // If this is a multipart message, it must be terminated by NLMSG_DONE
- //
- // NEED to revisit the MULTI part message--does not operate correctly right now.
- //
-
- bool is_end_of_message = false;
- size_t new_size = off - last_mh_off;
- const struct nlmsghdr* mh;
- for (mh = reinterpret_cast<const struct nlmsghdr*>(&buffer[last_mh_off]);
- NLMSG_OK(mh, new_size);
- mh = NLMSG_NEXT(const_cast<struct nlmsghdr*>(mh), new_size)) {
- if ((mh->nlmsg_flags & NLM_F_MULTI)
- || _is_multipart_message_read) {
- sprintf(buf, "%d", mh->nlmsg_type);
- is_end_of_message = false;
- if (mh->nlmsg_type == NLMSG_DONE) {
- is_end_of_message = true;
- }
- }
- }
- last_mh_off = reinterpret_cast<size_t>(mh) - reinterpret_cast<size_t>(&buffer[0]);
- if (is_end_of_message) {
- break;
- }
- }
-
- _nl_event_mgr.process(&message[0], off);
- return _nl_event_mgr.pop(e);
-}
-
-/**
- *
- *
- **/
-int
-NetlinkListener::comm_sock_set_rcvbuf(int sock, int desired_bufsize, int min_bufsize)
-{
- int delta = desired_bufsize / 2;
-
- /*
- * Set the socket buffer size. If we can't set it as large as we
- * want, search around to try to find the highest acceptable
- * value. The highest acceptable value being smaller than
- * minsize is a fatal error.
- */
- if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
- &desired_bufsize,
- sizeof(desired_bufsize)) < 0) {
- desired_bufsize -= delta;
- while (1) {
- if (delta > 1)
- delta /= 2;
-
- if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
- &desired_bufsize,
- sizeof(desired_bufsize)) < 0) {
- desired_bufsize -= delta;
- if (desired_bufsize <= 0)
- break;
- } else {
- if (delta < 1024)
- break;
- desired_bufsize += delta;
- }
- }
- if (desired_bufsize < min_bufsize) {
- syslog(LOG_ERR,"Cannot set receiving buffer size of socket");
- cerr << "Cannot set receiving buffer size of socket" << endl;
- return -1;
- }
- }
-
- return (desired_bufsize);
-}
-
diff --git a/watchlink/netlink_listener.hh b/watchlink/netlink_listener.hh
deleted file mode 100644
index b74589a8..00000000
--- a/watchlink/netlink_listener.hh
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Module: netlink_listener.hh
- *
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- */
-#ifndef __NETLINK_LISTENER_HH__
-#define __NETLINK_LISTENER_HH__
-
-#include "netlink_event.hh"
-#include <map>
-#include <string>
-
-class NetlinkListener
-{
-public: //methods
- NetlinkListener(bool debug);
- ~NetlinkListener();
-
- /*
- * returns socket fd
- */
- int
- init();
-
- bool
- process(NetlinkEvent &e);
-
- bool
- process(NetlinkEvent &e, std::multimap<std::string,IPv4net> filter);
-
- int
- get_sock() {return _fd;}
-
- void
- set_multipart(bool state) {_is_multipart_message_read = state;}
-
-private: //methods
-int
-comm_sock_set_rcvbuf(int sock, int desired_bufsize, int min_bufsize);
-
-private: //vraiables
- int _fd;
- bool _is_multipart_message_read;
- NetlinkEventManager _nl_event_mgr;
-};
-
-#endif //__NETLINK_LISTENER_HH__
diff --git a/watchlink/netlink_send.cc b/watchlink/netlink_send.cc
deleted file mode 100644
index 3824c2ef..00000000
--- a/watchlink/netlink_send.cc
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Module: netlink_send.cc
- *
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- */
-#include <errno.h>
-#include <arpa/inet.h>
-#include <linux/types.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-#include <syslog.h>
-
-#include <vector>
-#include <string>
-#include <iostream>
-
-#include "netlink_utils.hh"
-#include "netlink_send.hh"
-
-using namespace std;
-
-
-/**
- *
- *
- **/
-NetlinkSend::NetlinkSend(bool debug) : _debug(debug)
-{
-}
-
-
-/**
- *
- *
- **/
-NetlinkSend::~NetlinkSend()
-{
-}
-
-/**
- *
- *
- **/
-int
-NetlinkSend::send_set(int sock, int ifindex, uint32_t local_addr, uint32_t addr, int mask_len, int type)
-{
- int ret;
- struct sockaddr_nl snl;
- struct {
- struct nlmsghdr n;
- struct ifaddrmsg ifa;
- char buf[256];
- } req;
-
- /* Check netlink socket. */
- if (sock < 0) {
- syslog(LOG_ERR,"sock is not active, exiting");
- cerr << "sock is not active, exiting" << endl;
- return -1;
- }
-
- if (_debug) {
- struct in_addr in;
- in.s_addr = local_addr;
- char *lbuf = inet_ntoa(in);
-
- in.s_addr = addr;
- char *buf = inet_ntoa(in);
-
- char sbuf[1024];
- sprintf(sbuf, "NetlinkSend::send_set(): %d, %s/%d, to this address: %s, on interface: %d",type,buf,mask_len,lbuf,ifindex);
- cout << sbuf << endl;
-
- syslog(LOG_INFO,sbuf);
- }
-
- memset(&req, 0, sizeof(req));
-
- req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
- req.n.nlmsg_flags = NLM_F_REQUEST;
- req.n.nlmsg_pid = getpid();
- req.n.nlmsg_type = type;
- req.n.nlmsg_seq = time(NULL);
- req.ifa.ifa_family = AF_INET;
- req.ifa.ifa_index = ifindex;
- req.ifa.ifa_prefixlen = mask_len;
-
- // addr = htonl( addr );
- addattr_l(&req.n, sizeof(req), IFA_LOCAL, &local_addr, sizeof(local_addr) );
-
- in_addr_t broadcast_addr = ipv4_broadcast_addr(local_addr,mask_len);
- addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &broadcast_addr, sizeof(broadcast_addr) );
-
- if (addr != -1 && local_addr != addr) {
- addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &addr, sizeof(addr) );
- }
-
- memset(&snl, 0, sizeof(snl));
- snl.nl_family = AF_NETLINK;
-
- ret = sendto (sock, (void*) &req, sizeof req, 0,
- (struct sockaddr*) &snl, sizeof snl);
- if (ret < 0) {
- syslog(LOG_ERR,"netlink_send failed on send: %d, %d",ret,errno);
- cerr << "netlink_send failed on send: " << ret << ", " << errno << endl;
- return -1;
- }
- return 0;
-}
-
-/**
- *
- *
- **/
-int
-NetlinkSend::send_set_route(int sock, int ifindex, uint32_t local_addr, uint32_t dst_addr, int mask_len, int type, int table, int rtn_type, int rt_scope)
-{
- int ret;
- struct sockaddr_nl snl;
- struct {
- struct nlmsghdr n;
- struct rtmsg rt_message;
- char buf[8192];
- } req;
- req.rt_message.rtm_table = 0;
- req.rt_message.rtm_protocol = 0;
- req.rt_message.rtm_scope = 0;
- req.rt_message.rtm_type = 0;
- req.rt_message.rtm_src_len = 0;
- req.rt_message.rtm_dst_len = 0;
- req.rt_message.rtm_tos = 0;
-
- memset(&snl, 0, sizeof(snl));
- snl.nl_family = AF_NETLINK;
-
- /* Check netlink socket. */
- if (sock < 0) {
- syslog(LOG_ERR,"sock is not active, exiting");
- cerr << "sock is not active, exiting" << endl;
- return -1;
- }
-
- if (_debug) {
- struct in_addr in;
- in.s_addr = local_addr;
- char *lbuf = inet_ntoa(in);
-
- in.s_addr = dst_addr;
- char *buf = inet_ntoa(in);
-
- char sbuf[1024];
- sprintf(sbuf, "NetlinkSend::send_set_route(): %d, %s/%d, to this address: %s, on interface: %d, for this table: ",type,buf,mask_len,lbuf,ifindex,table);
- cout << sbuf << endl;
-
- syslog(LOG_INFO,sbuf);
- }
-
- memset(&req, 0, sizeof(req));
-
- req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
- if (type == RTM_NEWROUTE) {
- req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL;
- }
- else {
- req.n.nlmsg_flags = NLM_F_REQUEST;
- }
- req.n.nlmsg_pid = getpid();
- req.n.nlmsg_type = type;
- req.n.nlmsg_seq = time(NULL);
-
- req.rt_message.rtm_family = AF_INET;
- req.rt_message.rtm_dst_len = mask_len;
- req.rt_message.rtm_table = table;
- if (type == RTM_NEWROUTE) {
- req.rt_message.rtm_protocol = RTPROT_KERNEL;
- if (rt_scope != -1) {
- req.rt_message.rtm_scope = rt_scope;//RT_SCOPE_HOST; //will need to pass this in to get RT_SCOPE_HOST
- }
- if (rtn_type != -1) {
- req.rt_message.rtm_type = rtn_type;//RTN_LOCAL;
- }
- }
- else {
- req.rt_message.rtm_scope = RT_SCOPE_NOWHERE;
- req.rt_message.rtm_type = RTN_UNSPEC;
- }
-
- addattr_l(&req.n, sizeof(req), RTA_PREFSRC, &local_addr, sizeof(local_addr));
- addattr_l(&req.n, sizeof(req), RTA_DST, &dst_addr, sizeof(dst_addr));
- addattr32(&req.n, sizeof(req), RTA_OIF, ifindex);
-
- if (_debug) {
- cout << "NetlinkSend::send_set_route():" << endl;
- cout << " interface: " << ifindex << endl;
- cout << " type: " << string(req.n.nlmsg_type == RTM_NEWROUTE ? string("RTM_NEWROUTE") : string("RTM_DELROUTE")) << endl;
- cout << " flags: " << req.n.nlmsg_flags << endl;
- cout << " protocol: " << int(req.rt_message.rtm_protocol) << endl;
- cout << " scope: " << int(req.rt_message.rtm_scope) << endl;
- cout << " addr(s): " << local_addr << ", " << dst_addr << ", " << mask_len << ", " << int(req.rt_message.rtm_dst_len) << endl;
- cout << endl;
- }
-
- ret = sendto (sock, (void*) &req, sizeof req, 0,
- (struct sockaddr*) &snl, sizeof snl);
- if (ret < 0) {
- syslog(LOG_ERR,"netlink_send_route failed on send: %d, %d",ret,errno);
- cerr << "netlink_send_route failed on send: " << ret << ", " << errno << endl;
- return -1;
- }
- return 0;
-}
-
-/**
- *
- *
- **/
-int
-NetlinkSend::send_get(int sock, int type, int ifindex)
-{
- int ret;
- struct sockaddr_nl snl;
- struct {
- struct nlmsghdr n;
- struct ifaddrmsg ifa;
- char buf[256];
- } req;
-
- /* Check netlink socket. */
- if (sock < 0) {
- syslog(LOG_ERR,"sock is not active, exiting");
- cerr << "sock is not active, exiting" << endl;
- return -1;
- }
-
- if (_debug) {
- char sbuf[1024];
- sprintf(sbuf,"NetlinkSend::send_get(): type: %d, ifindex: %d",type,ifindex);
- cout << sbuf << endl;
- syslog(LOG_INFO,sbuf);
- }
-
- memset(&req, 0, sizeof(req));
-
- req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
- if (ifindex > -1) {
- req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH;
- }
- else {
- req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
- }
- req.n.nlmsg_pid = getpid();
- req.n.nlmsg_type = type;
- req.n.nlmsg_seq = time(NULL);
- req.ifa.ifa_family = AF_INET;
- if (ifindex > -1) {
- req.ifa.ifa_index = ifindex;
- }
-
- /*
- note bug right now in that all interfaces are provided back when a specific index is requested
- */
- memset(&snl, 0, sizeof(snl));
- snl.nl_family = AF_NETLINK;
-
- ret = sendto (sock, (void*) &req, sizeof req, 0,
- (struct sockaddr*) &snl, sizeof snl);
- if (ret < 0) {
- syslog(LOG_ERR,"netlink_send failed on send: %d, %d",ret,errno);
- cerr << "netlink_send failed on send: " << ret << ", " << errno << endl;
- return -1;
- }
- return 0;
-}
-
-/**
- *
- *
- **/
-int
-NetlinkSend::addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen)
-{
- int len = RTA_LENGTH(alen);
- struct rtattr *rta;
-
- if ((int)NLMSG_ALIGN(n->nlmsg_len) + len > maxlen)
- return -1;
- rta = (struct rtattr*)(((char*)n) + NLMSG_ALIGN(n->nlmsg_len));
- rta->rta_type = type;
- rta->rta_len = len;
- memcpy(RTA_DATA(rta), data, alen);
- n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;
- return 0;
-}
-
-int
-NetlinkSend::addattr32(struct nlmsghdr *n, int maxlen, int type, int data)
-{
- int len;
- struct rtattr *rta;
-
- len = RTA_LENGTH (4);
-
- if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
- return -1;
-
- rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len));
- rta->rta_type = type;
- rta->rta_len = len;
- memcpy (RTA_DATA (rta), &data, 4);
- n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
-
- return 0;
-}
diff --git a/watchlink/netlink_send.hh b/watchlink/netlink_send.hh
deleted file mode 100644
index 3e13e5c8..00000000
--- a/watchlink/netlink_send.hh
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Module: netlink_send.hh
- *
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- */
-#ifndef __NETLINK_SEND_HH__
-#define __NETLINK_SEND_HH__
-
-class NetlinkSend
-{
-public:
- NetlinkSend(bool debug);
- ~NetlinkSend();
-
- int
- send_get(int sock, int type, int ifindex = -1);
-
- int
- send_set(int sock, int ifindex, uint32_t local_addr, uint32_t addr, int mask_len, int type);
-
- int
- send_set_route(int sock, int ifindex, uint32_t local_addr, uint32_t dst_addr, int mask_len, int type, int table, int rtn_type, int rt_scope);
-
-private:
- int
- addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen);
-
- int
- addattr32(struct nlmsghdr *n, int maxlen, int type, int data);
-
-private:
- bool _debug;
-
-};
-
-#endif //__NETLINK_SEND_HH__
diff --git a/watchlink/netlink_utils.cc b/watchlink/netlink_utils.cc
deleted file mode 100644
index 18a4b3ff..00000000
--- a/watchlink/netlink_utils.cc
+++ /dev/null
@@ -1,59 +0,0 @@
-#include <errno.h>
-#include <string.h>
-#include <arpa/inet.h>
-#include <linux/types.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <linux/rtnetlink.h>
-#include <syslog.h>
-
-#include "netlink_utils.hh"
-
-
-/* Maskbit. */
-static u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
- 0xf8, 0xfc, 0xfe, 0xff};
-
-/* Convert masklen into IP address's netmask. */
-void
-masklen2ip (int masklen, struct in_addr *netmask)
-{
- u_char *pnt;
- int bit;
- int offset;
-
- memset (netmask, 0, sizeof (struct in_addr));
- pnt = (unsigned char *) netmask;
-
- offset = masklen / 8;
- bit = masklen % 8;
-
- while (offset--)
- *pnt++ = 0xff;
-
- if (bit)
- *pnt = maskbit[bit];
-}
-
-
-in_addr_t
-ipv4_broadcast_addr (in_addr_t hostaddr, int masklen)
-{
- struct in_addr mask;
-
- masklen2ip (masklen, &mask);
- return (masklen != 32-1) ?
- /* normal case */
- (hostaddr | ~mask.s_addr) :
- /* special case for /31 */
- (hostaddr ^ ~mask.s_addr);
-}
-
-in_addr_t
-ipv4_first_addr (in_addr_t hostaddr, int masklen)
-{
- struct in_addr mask;
- masklen2ip (masklen, &mask);
- return (hostaddr & mask.s_addr);
-}
-
diff --git a/watchlink/netlink_utils.hh b/watchlink/netlink_utils.hh
deleted file mode 100644
index a1be920a..00000000
--- a/watchlink/netlink_utils.hh
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef __NETLINK_UTILS_HH__
-#define __NETLINK_UTILS_HH__
-
-#include <arpa/inet.h>
-#include <linux/types.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-
-in_addr_t
-ipv4_broadcast_addr (in_addr_t hostaddr, int masklen);
-
-void
-masklen2ip (int masklen, struct in_addr *netmask);
-
-in_addr_t
-ipv4_first_addr (in_addr_t hostaddr, int masklen);
-
-
-#endif //__NETLINK_UTILS_HH__
diff --git a/watchlink/rl_str_proc.cc b/watchlink/rl_str_proc.cc
deleted file mode 100644
index e3c67e82..00000000
--- a/watchlink/rl_str_proc.cc
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Module: rl_str_proc.cc
- *
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- */
-#include "rl_str_proc.hh"
-
-using namespace std;
-
-/**
- *
- **/
-StrProc::StrProc(const string &in_str, const string &token)
-{
- string tmp = in_str;
-
- //convert tabs to spaces
- uint32_t pos = 0;
- string tabtospace = " ";
- string::iterator iter = tmp.begin();
- while ((pos = tmp.find("\t", pos)) != string::npos) {
- tmp.replace(pos, 1, tabtospace);
- pos += tabtospace.length();
- }
-
- //remove the cr
- pos = tmp.find("\n");
- if (pos != string::npos) {
- tmp.replace(pos, 1, "");
- }
-
- //now handle the case of the multiple length token
- //note that we are using the '~' as a token internally
- uint32_t start = 0, end;
- while ((start = tmp.find(token, start)) != string::npos) {
- tmp.replace(start, token.length(), "~");
- }
-
-
- while ((start = tmp.find_first_not_of("~")) != string::npos) {
- tmp = tmp.substr(start, tmp.length() - start);
- end = tmp.find_first_of("~");
- _str_coll.push_back(tmp.substr(0, end));
- tmp = tmp.substr(end+1, tmp.length() - end-1);
- if (end == string::npos) {
- break;
- }
- }
-}
-
-/**
- *
- **/
-string
-StrProc::get(int i)
-{
- if (uint32_t(i) >= _str_coll.size()) {
- return string("");
- }
- return _str_coll[i];
-}
-
-/**
- *
- **/
-string
-StrProc::get(int start, int end)
-{
- if (uint32_t(start) >= _str_coll.size()) {
- return string("");
- }
-
- string tmp;
- for (int i = start; (i < end) && (uint32_t(i) < _str_coll.size()); ++i) {
- tmp += _str_coll[i] + " ";
- }
- return tmp.substr(0,tmp.length()-1);
-}
-
-/**
- *
- **/
-vector<string>
-StrProc::get()
-{
- return _str_coll;
-}
diff --git a/watchlink/rl_str_proc.hh b/watchlink/rl_str_proc.hh
deleted file mode 100644
index ad7d897f..00000000
--- a/watchlink/rl_str_proc.hh
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Module: rl_str_proc.hh
- *
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- */
-#ifndef __RL_STR_PROC_HH__
-#define __RL_STR_PROC_HH__
-
-#include <vector>
-#include <string>
-
-class StrProc
-{
-public:
- StrProc(const std::string &in, const std::string &token);
-
- std::string get(int i);
-
- std::string get(int start, int end);
-
- std::vector<std::string> get();
-
- int size() {return _str_coll.size();}
-
-private:
- std::vector<std::string> _str_coll;
-};
-
-#endif //__RL_STR_PROC_HH__
diff --git a/watchlink/watchlink.cc b/watchlink/watchlink.cc
deleted file mode 100644
index 0cc8f232..00000000
--- a/watchlink/watchlink.cc
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Module: watchlink.cc
- *
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- */
-#include <unistd.h>
-#include <iostream>
-#include <stdio.h>
-#include <string>
-#include <map>
-#include <fcntl.h>
-#include <syslog.h>
-#include <errno.h>
-
-#include <linux/types.h>
-#include <sys/socket.h>
-#include <signal.h>
-#include <linux/rtnetlink.h>
-#include "rl_str_proc.hh"
-#include "netlink_send.hh"
-#include "netlink_listener.hh"
-#include "netlink_linkstatus.hh"
-#include "netlink_event.hh"
-
-using namespace std;
-
-
-void print_netlink(NetlinkEvent &nl_event);
-pid_t pid_output (const char *path);
-
-struct option longopts[] =
-{
- { 0 }
-};
-
-multimap<string,IPv4net> g_exclude;
-string g_link_dir = "/var/linkstatus";
-
-/**
- *
- *
- **/
-void
-usage()
-{
- fprintf(stdout, "-s start with sending netlink request\n");
- fprintf(stdout, "-l specify directory for link status. default /var/linkstatus\n");
- fprintf(stdout, "-i specify location of pid directory\n");
- fprintf(stdout, "-p print netlink messages\n");
- fprintf(stdout, "-d run as a daemon\n");
- fprintf(stdout, "-v debug to stdout\n");
- fprintf(stdout, "-h help message\n");
-}
-
-/**
- *
- *
- **/
-multimap<string,IPv4net>
-load_exclusion_file(const string &link_dir)
-{
- multimap<string,IPv4net> coll;
-
- string file = link_dir + "/exclude";
- FILE *fp = fopen(file.c_str(), "r");
- if (fp == NULL) {
- syslog(LOG_INFO,"load_exclusion_file(), failed to open state file");
- // cerr << "load_exclusion_file(), failed to open state file" << endl;
- return coll; //means we are still up, ignore...
- }
-
- char str[1025];
- while (fgets(str, 1024, fp)) {
- string line(str);
-
- //strip out comments
- int pos = line.find("#");
- line = line.substr(0,pos);
-
- StrProc tokens(line, " ");
- if (tokens.size() == 1) {
- string any("0/0");
- coll.insert(pair<string,IPv4net>(tokens.get(0),IPv4net(any)));
- }
- else if (tokens.size() == 2) {
- string net(tokens.get(1));
- coll.insert(pair<string,IPv4net>(tokens.get(0),IPv4net(net)));
- }
- }
- fclose(fp);
- return coll;
-}
-
-/**
- *
- *
- **/
-static void
-sig_user(int signo)
-{
- //reload interface exclusion list
- g_exclude = load_exclusion_file(g_link_dir);
-}
-
-
-/**
- *
- *
- **/
-int
-main(int argc, char* const argv[])
-{
- int ch;
- bool send_request = false;
- bool debug = false;
- bool daemon = false;
- string pid_path;
- bool print_nl_msg = false;
-
- if (debug) {
- cout << "starting..." << endl;
- }
-
- while ((ch = getopt_long(argc, argv, "sl:i:dvhp",longopts,0)) != -1) {
- switch (ch) {
- case 's':
- send_request = true;
- break;
- case 'l':
- g_link_dir = optarg;
- break;
- case 'i':
- pid_path = optarg;
- break;
- case 'd':
- daemon = true;
- break;
- case 'v':
- debug = true;
- break;
- case 'p':
- print_nl_msg = true;
- break;
- case 'h':
- usage();
- exit(0);
- }
- }
-
- NetlinkSend nl_send(debug);
- NetlinkListener nl_listener(debug);
-
- //add check here to ensure only one watchlink process
-
- if (daemon) {
- if (fork() != 0) {
- exit(0);
- }
- }
-
- if (pid_path.empty() == false) {
- pid_output(pid_path.c_str());
- }
-
- //load interface exclusion list
- g_exclude = load_exclusion_file(g_link_dir);
-
- signal(SIGUSR1, sig_user);
-
- int sock = nl_listener.init();
- if (sock <= 0) {
- syslog(LOG_ERR, "watchlink(), netlink listener failed in initialization. exiting..");
- cerr << "watchlink(), netlink listener failed in initialization. exiting.." << endl;
- exit(1);
- }
-
- if (send_request) {
- if (debug) {
- cout << "sending initial netlink request" << endl;
- }
- nl_listener.set_multipart(true);
- if (nl_send.send_get(sock, RTM_GETLINK) != 0) {
- syslog(LOG_ERR,"watchlink(), error sending, exiting..");
- cerr << "watchlink(), error sending. exiting.." << endl;
- exit(1);
- }
- }
-
- NetlinkLinkStatus nl_ls(sock, g_link_dir, debug);
-
- while (true) {
- NetlinkEvent nl_event;
- if (nl_listener.process(nl_event, g_exclude) == true) {
- if (send_request) {
- if (nl_send.send_get(sock, RTM_GETADDR) != 0) {
- syslog(LOG_ERR,"watchlink(), error sending. exiting..");
- cerr << "watchlink(), error sending. exiting.." << endl;
- exit(1);
- }
- send_request = false;
- }
- else {
- nl_listener.set_multipart(false);
- }
-
- nl_ls.process(nl_event);
-
- if (debug) {
- cout << " ifinfomsg: " << nl_event.get_ifinfomsg() << endl;
- }
- if (print_nl_msg) {
- print_netlink(nl_event);
- }
-
- }
- else {
- // cout << "didn't receive a message, sleeping for 1 second" << endl;
- sleep(1);
- }
- }
-
- exit(0);
-}
-
-
-/**
- *
- *
- **/
-void
-print_netlink(NetlinkEvent &nl_event)
-{
- char buf[20];
- sprintf(buf, "%d", nl_event.get_index());
- cout << "results for " << nl_event.get_iface() << "(" << string(buf) << ")" << endl;
- cout << " running: " << string(nl_event.get_running() ? "yes" : "no") << endl;
- cout << " enabled: " << string(nl_event.get_enabled() ? "yes" : "no") << endl;
- if (nl_event.get_type() == RTM_DELLINK ||
- nl_event.get_type() == RTM_NEWLINK) {
- cout << " type: " << string(nl_event.get_type()==RTM_DELLINK?"DELLINK":"NEWLINK") << endl;
- cout << " state: " << string(nl_event.is_link_up()?"UP":"DOWN") << endl;
- sprintf(buf, "%d", nl_event.get_mtu());
- cout << " mtu: " << string(buf) << endl;
- cout << " mac: " << nl_event.get_mac_str() << endl;
- cout << " alternate mac: " << nl_event.get_mac_str() << endl;
- }
- else if (nl_event.get_type() == RTM_DELADDR ||
- nl_event.get_type() == RTM_NEWADDR) {
- cout << " type: " << string(nl_event.get_type()==RTM_DELADDR?"DELADDR":"NEWADDR") << endl;
- cout << " local addr: " << nl_event.get_local_addr().str().c_str() << endl;
- cout << " addr: " << nl_event.get_addr().str().c_str() << endl;
- cout << " broadcast: " << nl_event.get_broadcast().str().c_str() << endl;
- char buf[20];
- sprintf(buf, "%d", nl_event.get_mask_len());
- cout << " mask length: " << string(buf) << endl;
- }
- cout << endl;
-
-}
-
-/**
- *
- *below borrowed from quagga library.
- **/
-#define PIDFILE_MASK 0644
-pid_t
-pid_output (const char *path)
-{
- FILE *fp;
- pid_t pid;
- mode_t oldumask;
-
- pid = getpid();
-
- oldumask = umask(0777 & ~PIDFILE_MASK);
- fp = fopen (path, "w");
- if (fp != NULL)
- {
- fprintf (fp, "%d\n", (int) pid);
- fclose (fp);
- umask(oldumask);
- return pid;
- }
- /* XXX Why do we continue instead of exiting? This seems incompatible
- with the behavior of the fcntl version below. */
- syslog(LOG_ERR,"Can't fopen pid lock file %s, continuing",
- path);
- umask(oldumask);
- return -1;
-}
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 27cd4fa9..24975f71 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)
{