summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/checksum.c53
-rw-r--r--lib/command.c331
-rw-r--r--lib/if.h1
-rw-r--r--lib/log.c18
-rw-r--r--lib/md5.c73
-rw-r--r--lib/md5.h3
-rw-r--r--lib/prefix.c54
-rw-r--r--lib/prefix.h2
-rw-r--r--lib/route_types.txt8
-rw-r--r--lib/sockunion.c10
-rw-r--r--lib/sockunion.h1
-rw-r--r--lib/stream.c26
-rw-r--r--lib/stream.h4
-rw-r--r--lib/thread.c134
-rw-r--r--lib/thread.h5
15 files changed, 416 insertions, 307 deletions
diff --git a/lib/checksum.c b/lib/checksum.c
index 3ddde815..af4f2550 100644
--- a/lib/checksum.c
+++ b/lib/checksum.c
@@ -14,27 +14,20 @@ in_cksum(void *parg, int nbytes)
{
u_short *ptr = parg;
register long sum; /* assumes long == 32 bits */
- u_short oddbyte;
register u_short answer; /* assumes u_short == 16 bits */
-
+ register int count;
/*
* Our algorithm is simple, using a 32-bit accumulator (sum),
* we add sequential 16-bit words to it, and at the end, fold back
* all the carry bits from the top 16 bits into the lower 16 bits.
*/
-
sum = 0;
- while (nbytes > 1) {
- sum += *ptr++;
- nbytes -= 2;
- }
-
- /* mop up an odd byte, if necessary */
- if (nbytes == 1) {
- oddbyte = 0; /* make sure top half is zero */
- *((u_char *) &oddbyte) = *(u_char *)ptr; /* one byte only */
- sum += oddbyte;
- }
+ count = nbytes >> 1; /* div by 2 */
+ for(ptr--; count; --count)
+ sum += *++ptr;
+
+ if (nbytes & 1) /* Odd */
+ sum += *(u_char *)(++ptr); /* one byte only */
/*
* Add back carry outs from top 16 bits to low 16 bits.
@@ -56,11 +49,8 @@ fletcher_checksum(u_char * buffer, const size_t len, const uint16_t offset)
{
u_int8_t *p;
int x, y, c0, c1;
- u_int16_t checksum;
u_int16_t *csum;
size_t partial_len, i, left = len;
-
- checksum = 0;
assert (offset < len);
@@ -68,47 +58,42 @@ fletcher_checksum(u_char * buffer, const size_t len, const uint16_t offset)
* Zero the csum in the packet.
*/
csum = (u_int16_t *) (buffer + offset);
- *(csum) = 0;
+ *csum = 0;
- p = buffer;
+ p = buffer - 1;
c0 = 0;
c1 = 0;
while (left != 0)
{
partial_len = MIN(left, MODX);
+ left -= partial_len;
- for (i = 0; i < partial_len; i++)
+ do
{
- c0 = c0 + *(p++);
+ c0 = c0 + *(++p);
c1 += c0;
- }
+ } while (--partial_len);
c0 = c0 % 255;
c1 = c1 % 255;
-
- left -= partial_len;
}
-
+
/* The cast is important, to ensure the mod is taken as a signed value. */
x = (int)((len - offset - 1) * c0 - c1) % 255;
if (x <= 0)
x += 255;
y = 510 - c0 - x;
- if (y > 255)
+ if (y > 255)
y -= 255;
-
+
/*
* Now we write this to the packet.
* We could skip this step too, since the checksum returned would
* be stored into the checksum field by the caller.
+ * Checksum is always big endian.
*/
- buffer[offset] = x;
- buffer[offset + 1] = y;
-
- /* Take care of the endian issue */
- checksum = htons((x << 8) | (y & 0xFF));
-
- return checksum;
+ *csum = htons((x << 8) | (y & 0xFF));
+ return *csum;
}
diff --git a/lib/command.c b/lib/command.c
index c432b323..290f1be0 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -32,6 +32,7 @@ Boston, MA 02111-1307, USA. */
#include "vty.h"
#include "command.h"
#include "workqueue.h"
+#include <stdbool.h>
/* Command vector which includes some level of command lists. Normally
each daemon maintains each own cmdvec. */
@@ -84,9 +85,9 @@ static struct cmd_node config_node =
/* Default motd string. */
static const char *default_motd =
"\r\n\
-Hello, this is " QUAGGA_PROGNAME " (version " QUAGGA_VERSION ").\r\n\
-" QUAGGA_COPYRIGHT "\r\n\
-\r\n";
+This is " QUAGGA_PROGNAME " " QUAGGA_VERSION "\r\n\r\n\
+You're using the dn42 branch. Send bug reports to equinox@diac24.net\r\n\
+The 1.1.0 version number is for package management purposes only.\r\n";
static const struct facility_map {
@@ -686,7 +687,8 @@ cmd_filter_by_symbol (char *command, char *symbol)
/* Completion match types. */
enum match_type
{
- no_match,
+no_match = 0,
+any_match,
extend_match,
ipv4_prefix_match,
ipv4_match,
@@ -695,7 +697,7 @@ enum match_type
range_match,
vararg_match,
partly_match,
- exact_match
+exact_match,
};
static enum match_type
@@ -1132,12 +1134,100 @@ cmd_range_match (const char *range, const char *str)
return 1;
}
-/* Make completion match and return match type flag. */
+/* helper to retrieve the 'real' argument string from an optional argument */
+static char *
+cmd_deopt (const char *str)
+{
+/* we've got "[blah]". We want to strip off the []s and redo the
+* match check for "blah"
+*/
+size_t len = strlen (str);
+char *tmp;
+
+if (len < 3)
+return NULL;
+
+/* tmp will hold a string of len-2 chars, so 'len' size is fine */
+tmp = XMALLOC(MTYPE_TMP, len);
+
+memcpy (tmp, (str + 1), len - 2);
+tmp[len - 2] = '\0';
+
+return tmp;
+}
+
+static enum match_type
+cmd_match (const char *str, const char *command,
+enum match_type min, bool recur)
+{
+
+if (recur && CMD_OPTION(str))
+{
+enum match_type ret;
+char *tmp = cmd_deopt (str);
+
+/* this would be a bug in a command, however handle it gracefully
+* as it we only discover it if a user tries to run it
+*/
+if (tmp == NULL)
+return no_match;
+
+ret = cmd_match (tmp, command, min, false);
+
+XFREE (MTYPE_TMP, tmp);
+
+return ret;
+}
+else if (CMD_VARARG (str))
+return vararg_match;
+else if (CMD_RANGE (str))
+{
+if (cmd_range_match (str, command))
+return range_match;
+}
+#ifdef HAVE_IPV6
+else if (CMD_IPV6 (str))
+{
+if (cmd_ipv6_match (command) >= min)
+return ipv6_match;
+}
+else if (CMD_IPV6_PREFIX (str))
+{
+if (cmd_ipv6_prefix_match (command) >= min)
+return ipv6_prefix_match;
+}
+#endif /* HAVE_IPV6 */
+else if (CMD_IPV4 (str))
+{
+if (cmd_ipv4_match (command) >= min)
+return ipv4_match;
+}
+else if (CMD_IPV4_PREFIX (str))
+{
+if (cmd_ipv4_prefix_match (command) >= min)
+return ipv4_prefix_match;
+}
+else if (CMD_VARIABLE (str))
+return extend_match;
+else if (strncmp (command, str, strlen (command)) == 0)
+{
+if (strcmp (command, str) == 0)
+return exact_match;
+else if (partly_match >= min)
+return partly_match;
+}
+
+return no_match;
+}
+
+/* Filter vector at the specified index and by the given command string, to
+* the desired matching level (thus allowing part matches), and return match
+* type flag.
+*/
static enum match_type
-cmd_filter_by_completion (char *command, vector v, unsigned int index)
+cmd_filter (char *command, vector v, unsigned int index, enum match_type level)
{
unsigned int i;
- const char *str;
struct cmd_element *cmd_element;
enum match_type match_type;
vector descvec;
@@ -1160,112 +1250,42 @@ cmd_filter_by_completion (char *command, vector v, unsigned int index)
for (j = 0; j < vector_active (descvec); j++)
if ((desc = vector_slot (descvec, j)))
- {
- str = desc->cmd;
-
- if (CMD_VARARG (str))
- {
- if (match_type < vararg_match)
- match_type = vararg_match;
- matched++;
- }
- else if (CMD_RANGE (str))
- {
- if (cmd_range_match (str, command))
- {
- if (match_type < range_match)
- match_type = range_match;
+ {
+ enum match_type ret;
- matched++;
- }
- }
-#ifdef HAVE_IPV6
- else if (CMD_IPV6 (str))
- {
- if (cmd_ipv6_match (command))
- {
- if (match_type < ipv6_match)
- match_type = ipv6_match;
-
- matched++;
- }
- }
- else if (CMD_IPV6_PREFIX (str))
- {
- if (cmd_ipv6_prefix_match (command))
- {
- if (match_type < ipv6_prefix_match)
- match_type = ipv6_prefix_match;
-
- matched++;
- }
- }
-#endif /* HAVE_IPV6 */
- else if (CMD_IPV4 (str))
- {
- if (cmd_ipv4_match (command))
- {
- if (match_type < ipv4_match)
- match_type = ipv4_match;
+ ret = cmd_match (desc->cmd, command, level, true);
+
+ if (ret != no_match)
+ matched++;
- matched++;
- }
- }
- else if (CMD_IPV4_PREFIX (str))
- {
- if (cmd_ipv4_prefix_match (command))
- {
- if (match_type < ipv4_prefix_match)
- match_type = ipv4_prefix_match;
- matched++;
- }
- }
- else
- /* Check is this point's argument optional ? */
- if (CMD_OPTION (str) || CMD_VARIABLE (str))
- {
- if (match_type < extend_match)
- match_type = extend_match;
- matched++;
- }
- else if (strncmp (command, str, strlen (command)) == 0)
- {
- if (strcmp (command, str) == 0)
- match_type = exact_match;
- else
- {
- if (match_type < partly_match)
- match_type = partly_match;
- }
- matched++;
- }
+ if (match_type < ret)
+ match_type = ret;
}
if (!matched)
vector_slot (v, i) = NULL;
}
}
- return match_type;
-}
-/* Filter vector by command character with index. */
-static enum match_type
-cmd_filter_by_string (char *command, vector v, unsigned int index)
-{
- unsigned int i;
- const char *str;
- struct cmd_element *cmd_element;
- enum match_type match_type;
- vector descvec;
- struct desc *desc;
-
- match_type = no_match;
-
- /* If command and cmd_element string does not match set NULL to vector */
+if (match_type == no_match)
+return no_match;
+
+/* 2nd pass: We now know the 'strongest' match type for the index, so we
+* go again and filter out commands whose argument (at this index) is
+* 'weaker'. E.g., if we have 2 commands:
+*
+* foo bar <1-255>
+* foo bar BLAH
+*
+* and the command string is 'foo bar 10', then we will get here with with
+* 'range_match' being the strongest match. However, if 'BLAH' came
+* earlier, it won't have been filtered out (as a CMD_VARIABLE allows "10").
+*
+* If we don't do a 2nd pass and filter it out, the higher-layers will
+* consider this to be ambiguous.
+*/
for (i = 0; i < vector_active (v); i++)
if ((cmd_element = vector_slot (v, i)) != NULL)
{
- /* If given index is bigger than max string vector of command,
- set NULL */
if (index >= vector_active (cmd_element->strvec))
vector_slot (v, i) = NULL;
else
@@ -1277,81 +1297,19 @@ cmd_filter_by_string (char *command, vector v, unsigned int index)
for (j = 0; j < vector_active (descvec); j++)
if ((desc = vector_slot (descvec, j)))
- {
- str = desc->cmd;
+ {
+ enum match_type ret;
- if (CMD_VARARG (str))
- {
- if (match_type < vararg_match)
- match_type = vararg_match;
- matched++;
- }
- else if (CMD_RANGE (str))
- {
- if (cmd_range_match (str, command))
- {
- if (match_type < range_match)
- match_type = range_match;
- matched++;
- }
- }
-#ifdef HAVE_IPV6
- else if (CMD_IPV6 (str))
- {
- if (cmd_ipv6_match (command) == exact_match)
- {
- if (match_type < ipv6_match)
- match_type = ipv6_match;
- matched++;
- }
- }
- else if (CMD_IPV6_PREFIX (str))
- {
- if (cmd_ipv6_prefix_match (command) == exact_match)
- {
- if (match_type < ipv6_prefix_match)
- match_type = ipv6_prefix_match;
- matched++;
- }
- }
-#endif /* HAVE_IPV6 */
- else if (CMD_IPV4 (str))
- {
- if (cmd_ipv4_match (command) == exact_match)
- {
- if (match_type < ipv4_match)
- match_type = ipv4_match;
- matched++;
- }
- }
- else if (CMD_IPV4_PREFIX (str))
- {
- if (cmd_ipv4_prefix_match (command) == exact_match)
- {
- if (match_type < ipv4_prefix_match)
- match_type = ipv4_prefix_match;
- matched++;
- }
- }
- else if (CMD_OPTION (str) || CMD_VARIABLE (str))
- {
- if (match_type < extend_match)
- match_type = extend_match;
- matched++;
- }
- else
- {
- if (strcmp (command, str) == 0)
- {
- match_type = exact_match;
- matched++;
- }
- }
+ ret = cmd_match (desc->cmd, command, any_match, true);
+
+ if (ret >= match_type)
+ matched++;
}
if (!matched)
vector_slot (v, i) = NULL;
}
}
+
return match_type;
}
@@ -1361,7 +1319,6 @@ is_cmd_ambiguous (char *command, vector v, int index, enum match_type type)
{
unsigned int i;
unsigned int j;
- const char *str = NULL;
struct cmd_element *cmd_element;
const char *matched = NULL;
vector descvec;
@@ -1378,18 +1335,21 @@ is_cmd_ambiguous (char *command, vector v, int index, enum match_type type)
if ((desc = vector_slot (descvec, j)))
{
enum match_type ret;
-
- str = desc->cmd;
+ char *str = desc->cmd;
+ if (CMD_OPTION(str))
+ if ((str = cmd_deopt (str)) == NULL)
+ continue;
+
switch (type)
{
case exact_match:
- if (!(CMD_OPTION (str) || CMD_VARIABLE (str))
+ if (!(CMD_VARIABLE (str))
&& strcmp (command, str) == 0)
match++;
break;
case partly_match:
- if (!(CMD_OPTION (str) || CMD_VARIABLE (str))
+ if (!(CMD_VARIABLE (str))
&& strncmp (command, str, strlen (command)) == 0)
{
if (matched && strcmp (matched, str) != 0)
@@ -1438,13 +1398,16 @@ is_cmd_ambiguous (char *command, vector v, int index, enum match_type type)
}
break;
case extend_match:
- if (CMD_OPTION (str) || CMD_VARIABLE (str))
+ if (CMD_VARIABLE (str))
match++;
break;
case no_match:
default:
break;
}
+
+if (CMD_OPTION(desc->cmd))
+XFREE (MTYPE_TMP, str);
}
if (!match)
vector_slot (v, i) = NULL;
@@ -1614,7 +1577,7 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status)
for (i = 0; i < index; i++)
if ((command = vector_slot (vline, i)))
{
- match = cmd_filter_by_completion (command, cmd_vector, i);
+ match = cmd_filter (command, cmd_vector, i, any_match);
if (match == vararg_match)
{
@@ -1663,7 +1626,7 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status)
/* Make sure that cmd_vector is filtered based on current word */
command = vector_slot (vline, index);
if (command)
- match = cmd_filter_by_completion (command, cmd_vector, index);
+match = cmd_filter (command, cmd_vector, index, any_match);
/* Make description vector. */
for (i = 0; i < vector_active (cmd_vector); i++)
@@ -1817,7 +1780,7 @@ cmd_complete_command_real (vector vline, struct vty *vty, int *status)
int ret;
/* First try completion match, if there is exactly match return 1 */
- match = cmd_filter_by_completion (command, cmd_vector, i);
+ match = cmd_filter (command, cmd_vector, i, any_match);
/* If there is exact match then filter ambiguous match else check
ambiguousness. */
@@ -2026,7 +1989,7 @@ cmd_execute_command_real (vector vline, struct vty *vty,
{
int ret;
- match = cmd_filter_by_completion (command, cmd_vector, index);
+ match = cmd_filter (command, cmd_vector, index, any_match);
if (match == vararg_match)
break;
@@ -2205,8 +2168,8 @@ cmd_execute_command_strict (vector vline, struct vty *vty,
{
int ret;
- match = cmd_filter_by_string (vector_slot (vline, index),
- cmd_vector, index);
+ match = cmd_filter (vector_slot (vline, index), cmd_vector,
+ index, exact_match);
/* If command meets '.VARARG' then finish matching. */
if (match == vararg_match)
diff --git a/lib/if.h b/lib/if.h
index 1b29f470..b28f32b5 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -90,6 +90,7 @@ struct interface
#define ZEBRA_INTERFACE_ACTIVE (1 << 0)
#define ZEBRA_INTERFACE_SUB (1 << 1)
#define ZEBRA_INTERFACE_LINKDETECTION (1 << 2)
+#define ZEBRA_INTERFACE_UNNUMBERED (1 << 3)
/* Interface flags. */
uint64_t flags;
diff --git a/lib/log.c b/lib/log.c
index ea0571c5..cfac61b1 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -927,12 +927,18 @@ proto_redistnum(int afi, const char *s)
return ZEBRA_ROUTE_STATIC;
else if (strncmp (s, "r", 1) == 0)
return ZEBRA_ROUTE_RIP;
- else if (strncmp (s, "o", 1) == 0)
+ else if (strncmp (s, "os", 2) == 0)
return ZEBRA_ROUTE_OSPF;
else if (strncmp (s, "i", 1) == 0)
return ZEBRA_ROUTE_ISIS;
- else if (strncmp (s, "b", 1) == 0)
+ else if (strncmp (s, "bg", 2) == 0)
return ZEBRA_ROUTE_BGP;
+ else if (strncmp (s, "ol", 2) == 0)
+ return ZEBRA_ROUTE_OLSR;
+ else if (strncmp (s, "ba", 2) == 0)
+ return ZEBRA_ROUTE_BATMAN;
+ else if (strncmp (s, "d", 1) == 0)
+ return ZEBRA_ROUTE_DHCP;
}
if (afi == AFI_IP6)
{
@@ -944,12 +950,16 @@ proto_redistnum(int afi, const char *s)
return ZEBRA_ROUTE_STATIC;
else if (strncmp (s, "r", 1) == 0)
return ZEBRA_ROUTE_RIPNG;
- else if (strncmp (s, "o", 1) == 0)
+ else if (strncmp (s, "os", 2) == 0)
return ZEBRA_ROUTE_OSPF6;
else if (strncmp (s, "i", 1) == 0)
return ZEBRA_ROUTE_ISIS;
- else if (strncmp (s, "b", 1) == 0)
+ else if (strncmp (s, "bg", 2) == 0)
return ZEBRA_ROUTE_BGP;
+ else if (strncmp (s, "ol", 2) == 0)
+ return ZEBRA_ROUTE_OLSR;
+ else if (strncmp (s, "ba", 2) == 0)
+ return ZEBRA_ROUTE_BATMAN;
}
return -1;
}
diff --git a/lib/md5.c b/lib/md5.c
index 894de648..2fc36e17 100644
--- a/lib/md5.c
+++ b/lib/md5.c
@@ -298,3 +298,76 @@ static void md5_calc(const uint8_t *b64, md5_ctxt * ctxt)
ctxt->md5_stc += C;
ctxt->md5_std += D;
}
+
+/* From RFC 2104 */
+void
+hmac_md5(text, text_len, key, key_len, digest)
+unsigned char* text; /* pointer to data stream */
+int text_len; /* length of data stream */
+unsigned char* key; /* pointer to authentication key */
+int key_len; /* length of authentication key */
+caddr_t digest; /* caller digest to be filled in */
+
+{
+ MD5_CTX context;
+ unsigned char k_ipad[65]; /* inner padding -
+ * key XORd with ipad
+ */
+ unsigned char k_opad[65]; /* outer padding -
+ * key XORd with opad
+ */
+ unsigned char tk[16];
+ int i;
+ /* if key is longer than 64 bytes reset it to key=MD5(key) */
+ if (key_len > 64) {
+
+ MD5_CTX tctx;
+
+ MD5Init(&tctx);
+ MD5Update(&tctx, key, key_len);
+ MD5Final(tk, &tctx);
+
+ key = tk;
+ key_len = 16;
+ }
+
+ /*
+ * the HMAC_MD5 transform looks like:
+ *
+ * MD5(K XOR opad, MD5(K XOR ipad, text))
+ *
+ * where K is an n byte key
+ * ipad is the byte 0x36 repeated 64 times
+ * opad is the byte 0x5c repeated 64 times
+ * and text is the data being protected
+ */
+
+ /* start out by storing key in pads */
+ bzero( k_ipad, sizeof k_ipad);
+ bzero( k_opad, sizeof k_opad);
+ bcopy( key, k_ipad, key_len);
+ bcopy( key, k_opad, key_len);
+
+ /* XOR key with ipad and opad values */
+ for (i=0; i<64; i++) {
+ k_ipad[i] ^= 0x36;
+ k_opad[i] ^= 0x5c;
+ }
+ /*
+ * perform inner MD5
+ */
+ MD5Init(&context); /* init context for 1st
+ * pass */
+ MD5Update(&context, k_ipad, 64); /* start with inner pad */
+ MD5Update(&context, text, text_len); /* then text of datagram */
+ MD5Final(digest, &context); /* finish up 1st pass */
+ /*
+ * perform outer MD5
+ */
+ MD5Init(&context); /* init context for 2nd
+ * pass */
+ MD5Update(&context, k_opad, 64); /* start with outer pad */
+ MD5Update(&context, digest, 16); /* then results of 1st
+ * hash */
+ MD5Final(digest, &context); /* finish up 2nd pass */
+}
diff --git a/lib/md5.h b/lib/md5.h
index 89b9a320..3ce83a63 100644
--- a/lib/md5.h
+++ b/lib/md5.h
@@ -82,4 +82,7 @@ do { \
md5_result((x), (y)); \
} while (0)
+/* From RFC 2104 */
+void hmac_md5(unsigned char* text, int text_len, unsigned char* key, int key_len, caddr_t digest);
+
#endif /* ! _LIBZEBRA_MD5_H_*/
diff --git a/lib/prefix.c b/lib/prefix.c
index c85e6594..f5de4bde 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -180,6 +180,46 @@ prefix_cmp (const struct prefix *p1, const struct prefix *p2)
return 0;
}
+/*
+ * Count the number of common bits in 2 prefixes. The prefix length is
+ * ignored for this function; the whole prefix is compared. If the prefix
+ * address families don't match, return -1; otherwise the return value is
+ * in range 0 ... maximum prefix length for the address family.
+ */
+int
+prefix_common_bits (const struct prefix *p1, const struct prefix *p2)
+{
+ int pos, bit;
+ int length = 0;
+ u_char xor;
+
+ /* Set both prefix's head pointer. */
+ const u_char *pp1 = (const u_char *)&p1->u.prefix;
+ const u_char *pp2 = (const u_char *)&p2->u.prefix;
+
+ if (p1->family == AF_INET)
+ length = IPV4_MAX_BYTELEN;
+#ifdef HAVE_IPV6
+ if (p1->family == AF_INET6)
+ length = IPV6_MAX_BYTELEN;
+#endif
+ if (p1->family != p2->family || !length)
+ return -1;
+
+ for (pos = 0; pos < length; pos++)
+ if (pp1[pos] != pp2[pos])
+ break;
+ if (pos == length)
+ return pos * 8;
+
+ xor = pp1[pos] ^ pp2[pos];
+ for (bit = 0; bit < 8; bit++)
+ if (xor & (1 << (7 - bit)))
+ break;
+
+ return pos * 8 + bit;
+}
+
/* Return prefix family type string. */
const char *
prefix_family_str (const struct prefix *p)
@@ -569,6 +609,20 @@ sockunion2hostprefix (const union sockunion *su)
return NULL;
}
+void
+prefix2sockunion (const struct prefix *p, union sockunion *su)
+{
+ memset (su, 0, sizeof (*su));
+
+ su->sa.sa_family = p->family;
+ if (p->family == AF_INET)
+ su->sin.sin_addr = p->u.prefix4;
+#ifdef HAVE_IPV6
+ if (p->family == AF_INET6)
+ memcpy (&su->sin6.sin6_addr, &p->u.prefix6, sizeof (struct in6_addr));
+#endif /* HAVE_IPV6 */
+}
+
int
prefix_blen (const struct prefix *p)
{
diff --git a/lib/prefix.h b/lib/prefix.h
index a7598b7e..f6259dee 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -156,12 +156,14 @@ extern int prefix2str (const struct prefix *, char *, int);
extern int prefix_match (const struct prefix *, const struct prefix *);
extern int prefix_same (const struct prefix *, const struct prefix *);
extern int prefix_cmp (const struct prefix *, const struct prefix *);
+extern int prefix_common_bits (const struct prefix *, const struct prefix *);
extern void prefix_copy (struct prefix *dest, const struct prefix *src);
extern void apply_mask (struct prefix *);
extern struct prefix *sockunion2prefix (const union sockunion *dest,
const union sockunion *mask);
extern struct prefix *sockunion2hostprefix (const union sockunion *);
+extern void prefix2sockunion (const struct prefix *, union sockunion *);
extern struct prefix_ipv4 *prefix_ipv4_new (void);
extern void prefix_ipv4_free (struct prefix_ipv4 *);
diff --git a/lib/route_types.txt b/lib/route_types.txt
index d2d4cb6c..dfa34d74 100644
--- a/lib/route_types.txt
+++ b/lib/route_types.txt
@@ -56,8 +56,10 @@ ZEBRA_ROUTE_BGP, bgp, bgpd, 'B', 1, 1, "BGP"
# This at least makes it trivial for users of these protocols
# to 'switch on' redist support (direct numeric entry remaining
# possible).
-ZEBRA_ROUTE_HSLS, hsls, hslsd, 'H', 0, 0, "HSLS"
-ZEBRA_ROUTE_OLSR, olsr, olsrd, 'o', 0, 0, "OLSR"
+ZEBRA_ROUTE_HSLS, hsls, hslsd, 'h', 1, 1, "HSLS"
+ZEBRA_ROUTE_OLSR, olsr, olsrd, 'o', 1, 1, "OLSR"
+ZEBRA_ROUTE_BATMAN, batman, batman, 'b', 1, 1, "BATMAN"
+ZEBRA_ROUTE_DHCP, dhcp, dhcpc, 'D', 1, 0, "DHCP"
ZEBRA_ROUTE_PIM, pim, pimd, 'P', 0, 0, "PIM-SSM"
## help strings
@@ -73,5 +75,7 @@ ZEBRA_ROUTE_ISIS, "Intermediate System to Intermediate System (IS-IS)"
ZEBRA_ROUTE_BGP, "Border Gateway Protocol (BGP)"
ZEBRA_ROUTE_HSLS, "Hazy-Sighted Link State Protocol (HSLS)"
ZEBRA_ROUTE_OLSR, "Optimised Link State Routing (OLSR)"
+ZEBRA_ROUTE_BATMAN, "Better Approach To Mobile Ad-hoc Networking (BATMAN)"
+ZEBRA_ROUTE_DHCP, "Dynamic Host Configuration Protocol (DHCP)"
ZEBRA_ROUTE_PIM, "Protocol Independent Multicast, Source Specific Mode (PIM-SSM)"
diff --git a/lib/sockunion.c b/lib/sockunion.c
index d1f6d80b..5de3bcfc 100644
--- a/lib/sockunion.c
+++ b/lib/sockunion.c
@@ -551,6 +551,16 @@ sockopt_v6only (int family, int sock)
return 0;
}
+int
+sockopt_cork (int sock, int onoff)
+{
+#ifdef TCP_CORK
+ return setsockopt (sock, IPPROTO_TCP, TCP_CORK, &onoff, sizeof(onoff));
+#else
+ return 0;
+#endif
+}
+
/* If same family and same prefix return 1. */
int
sockunion_same (union sockunion *su1, union sockunion *su2)
diff --git a/lib/sockunion.h b/lib/sockunion.h
index db145cf2..2e8ce2d0 100644
--- a/lib/sockunion.h
+++ b/lib/sockunion.h
@@ -103,6 +103,7 @@ extern int sockopt_v6only (int family, int sock);
extern int sockunion_bind (int sock, union sockunion *,
unsigned short, union sockunion *);
extern int sockopt_ttl (int family, int sock, int ttl);
+extern int sockopt_cork (int sock, int onoff);
extern int sockunion_socket (union sockunion *su);
extern const char *inet_sutop (union sockunion *su, char *str);
extern enum connect_result sockunion_connect (int fd, union sockunion *su,
diff --git a/lib/stream.c b/lib/stream.c
index 983330ff..bff74d7b 100644
--- a/lib/stream.c
+++ b/lib/stream.c
@@ -711,32 +711,6 @@ stream_read (struct stream *s, int fd, size_t size)
return nbytes;
}
-/* Read size from fd. */
-int
-stream_read_unblock (struct stream *s, int fd, size_t size)
-{
- int nbytes;
- int val;
-
- STREAM_VERIFY_SANE(s);
-
- if (STREAM_WRITEABLE (s) < size)
- {
- STREAM_BOUND_WARN (s, "put");
- return 0;
- }
-
- val = fcntl (fd, F_GETFL, 0);
- fcntl (fd, F_SETFL, val|O_NONBLOCK);
- nbytes = read (fd, s->data + s->endp, size);
- fcntl (fd, F_SETFL, val);
-
- if (nbytes > 0)
- s->endp += nbytes;
-
- return nbytes;
-}
-
ssize_t
stream_read_try(struct stream *s, int fd, size_t size)
{
diff --git a/lib/stream.h b/lib/stream.h
index 3e4ba7b4..486a3f93 100644
--- a/lib/stream.h
+++ b/lib/stream.h
@@ -181,10 +181,6 @@ extern u_int32_t stream_get_ipv4 (struct stream *);
Use stream_read_try instead. */
extern int stream_read (struct stream *, int, size_t);
-/* Deprecated: all file descriptors should already be non-blocking.
- Will be removed. Use stream_read_try instead. */
-extern int stream_read_unblock (struct stream *, int, size_t);
-
/* Read up to size bytes into the stream.
Return code:
>0: number of bytes read
diff --git a/lib/thread.c b/lib/thread.c
index e89af541..1e714417 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -20,8 +20,9 @@
*/
/* #define DEBUG */
-
+#include <errno.h>
#include <zebra.h>
+#include <sys/times.h>
#include "thread.h"
#include "memory.h"
@@ -31,8 +32,7 @@
#include "sigevent.h"
/* Recent absolute time of day */
-struct timeval recent_time;
-static struct timeval last_recent_time;
+static struct timeval recent_time;
/* Relative time, since startup */
static struct timeval relative_time;
static struct timeval relative_time_base;
@@ -94,54 +94,98 @@ timeval_elapsed (struct timeval a, struct timeval b)
}
#ifndef HAVE_CLOCK_MONOTONIC
+static unsigned long recent_clock_mark; /* Holds value of last call to times(2) */
+static unsigned long last_clock_mark;
+static unsigned long clocks_per_sec, msec_scale, usec_scale;
+
+static unsigned long quagga_times(void)
+{
+#if defined(GNU_LINUX)
+ unsigned long ret;
+
+ errno = 0;
+ ret = times(NULL); /* Linux can handle NULL */
+ /* Workaround broken syscall impl.
+ * A bugfix exists for the kernel, hopefully
+ * it will make it into 2.6.28
+ */
+ if (errno)
+ ret = (unsigned long) (-errno);
+ return ret;
+#else
+ struct tms dummy; /* Only return value is used */
+
+ return times(&dummy);
+#endif
+}
+
static void
quagga_gettimeofday_relative_adjust (void)
{
- struct timeval diff;
- if (timeval_cmp (recent_time, last_recent_time) < 0)
- {
- relative_time.tv_sec++;
- relative_time.tv_usec = 0;
- }
- else
- {
- diff = timeval_subtract (recent_time, last_recent_time);
- relative_time.tv_sec += diff.tv_sec;
- relative_time.tv_usec += diff.tv_usec;
- relative_time = timeval_adjust (relative_time);
- }
- last_recent_time = recent_time;
+ unsigned long diff;
+
+ diff = recent_clock_mark - last_clock_mark;
+ if (!diff)
+ return;
+ /* save mark for next calculation */
+ last_clock_mark = recent_clock_mark;
+
+ relative_time.tv_sec += diff / clocks_per_sec; /* convert to seconds */
+ relative_time.tv_usec += (diff % clocks_per_sec) * usec_scale; /* convert to useconds */
+ relative_time = timeval_adjust (relative_time);
}
#endif /* !HAVE_CLOCK_MONOTONIC */
+static int init_quagga_timers(void)
+{
+ int ret;
+
+ ret = gettimeofday (&recent_time, NULL);
+ relative_time_base = recent_time;
+#if !defined(HAVE_CLOCK_MONOTONIC)
+ clocks_per_sec = sysconf(_SC_CLK_TCK);
+ assert(clocks_per_sec != 0);
+
+ /* Precondition: 1000 % clocks_per_sec == 0 */
+ assert(1000 % clocks_per_sec == 0);
+ msec_scale = 1000 / clocks_per_sec;
+
+ /* Precondition: TIMER_SECOND_MICRO % clocks_per_sec == 0 */
+ assert(TIMER_SECOND_MICRO % clocks_per_sec == 0);
+ usec_scale = TIMER_SECOND_MICRO / clocks_per_sec;
+ recent_clock_mark = quagga_times();
+ last_clock_mark = recent_clock_mark;
+#endif
+ if (ret)
+ return ret;
+ timers_inited = 1;
+ return 0;
+}
+
/* gettimeofday wrapper, to keep recent_time updated */
static int
quagga_gettimeofday (struct timeval *tv)
{
int ret;
-
- assert (tv);
-
- if (!(ret = gettimeofday (&recent_time, NULL)))
- {
- /* init... */
- if (!timers_inited)
- {
- relative_time_base = last_recent_time = recent_time;
- timers_inited = 1;
- }
- /* avoid copy if user passed recent_time pointer.. */
- if (tv != &recent_time)
- *tv = recent_time;
- return 0;
- }
- return ret;
+
+ /* init... */
+ if (!timers_inited)
+ ret = init_quagga_timers();
+ else
+ ret = gettimeofday (&recent_time, NULL);
+ if (ret)
+ return ret;
+
+ /* avoid copy if user passed recent_time pointer.. */
+ if (tv != &recent_time)
+ *tv = recent_time;
+ return 0;
}
static int
quagga_get_relative (struct timeval *tv)
{
- int ret;
+ int ret = 0;
#ifdef HAVE_CLOCK_MONOTONIC
{
@@ -153,8 +197,12 @@ quagga_get_relative (struct timeval *tv)
}
}
#else /* !HAVE_CLOCK_MONOTONIC */
- if (!(ret = quagga_gettimeofday (&recent_time)))
- quagga_gettimeofday_relative_adjust();
+ /* init... */
+ if (!timers_inited)
+ ret = init_quagga_timers();
+
+ recent_clock_mark = quagga_times();
+ quagga_gettimeofday_relative_adjust();
#endif /* HAVE_CLOCK_MONOTONIC */
if (tv)
@@ -910,7 +958,6 @@ thread_fetch (struct thread_master *m, struct thread *fetch)
struct thread *thread;
fd_set readfd;
fd_set writefd;
- fd_set exceptfd;
struct timeval timer_val;
struct timeval timer_val_bg;
struct timeval *timer_wait;
@@ -936,7 +983,6 @@ thread_fetch (struct thread_master *m, struct thread *fetch)
/* Structure copy. */
readfd = m->readfd;
writefd = m->writefd;
- exceptfd = m->exceptfd;
/* Calculate select wait timer if nothing else to do */
quagga_get_relative (NULL);
@@ -947,7 +993,7 @@ thread_fetch (struct thread_master *m, struct thread *fetch)
(!timer_wait || (timeval_cmp (*timer_wait, *timer_wait_bg) > 0)))
timer_wait = timer_wait_bg;
- num = select (FD_SETSIZE, &readfd, &writefd, &exceptfd, timer_wait);
+ num = select (FD_SETSIZE, &readfd, &writefd, NULL, timer_wait);
/* Signals should get quick treatment */
if (num < 0)
@@ -1028,14 +1074,6 @@ thread_getrusage (RUSAGE_T *r)
getrusage(RUSAGE_SELF, &(r->cpu));
#endif
r->real = relative_time;
-
-#ifdef HAVE_CLOCK_MONOTONIC
- /* quagga_get_relative() only updates recent_time if gettimeofday
- * based, not when using CLOCK_MONOTONIC. As we export recent_time
- * and guarantee to update it before threads are run...
- */
- quagga_gettimeofday(&recent_time);
-#endif /* HAVE_CLOCK_MONOTONIC */
}
/* We check thread consumed time. If the system has getrusage, we'll
diff --git a/lib/thread.h b/lib/thread.h
index f3769e25..c0198a36 100644
--- a/lib/thread.h
+++ b/lib/thread.h
@@ -54,7 +54,6 @@ struct thread_master
struct thread_list background;
fd_set readfd;
fd_set writefd;
- fd_set exceptfd;
unsigned long alloc;
};
@@ -216,10 +215,6 @@ extern time_t quagga_time (time_t *);
extern unsigned long thread_consumed_time(RUSAGE_T *after, RUSAGE_T *before,
unsigned long *cpu_time_elapsed);
-/* Global variable containing a recent result from gettimeofday. This can
- be used instead of calling gettimeofday if a recent value is sufficient.
- This is guaranteed to be refreshed before a thread is called. */
-extern struct timeval recent_time;
/* Similar to recent_time, but a monotonically increasing time value */
extern struct timeval recent_relative_time (void);
#endif /* _ZEBRA_THREAD_H */