diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile.am | 14 | ||||
-rw-r--r-- | lib/command.c | 6 | ||||
-rw-r--r-- | lib/if.h | 6 | ||||
-rw-r--r-- | lib/log.c | 81 | ||||
-rw-r--r-- | lib/md5.c | 73 | ||||
-rw-r--r-- | lib/md5.h | 3 | ||||
-rw-r--r-- | lib/paths.c | 65 | ||||
-rw-r--r-- | lib/paths.h | 34 | ||||
-rw-r--r-- | lib/prefix.c | 54 | ||||
-rw-r--r-- | lib/prefix.h | 2 | ||||
-rw-r--r-- | lib/route_types.awk | 187 | ||||
-rwxr-xr-x | lib/route_types.pl | 199 | ||||
-rw-r--r-- | lib/route_types.txt | 17 | ||||
-rw-r--r-- | lib/sockunion.c | 34 | ||||
-rw-r--r-- | lib/sockunion.h | 2 | ||||
-rw-r--r-- | lib/stream.c | 26 | ||||
-rw-r--r-- | lib/stream.h | 4 | ||||
-rw-r--r-- | lib/thread.c | 134 | ||||
-rw-r--r-- | lib/thread.h | 5 | ||||
-rw-r--r-- | lib/vty.c | 1 | ||||
-rw-r--r-- | lib/zclient.c | 3 | ||||
-rw-r--r-- | lib/zclient.h | 3 | ||||
-rw-r--r-- | lib/zebra.h | 19 |
23 files changed, 648 insertions, 324 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index 315e919b..1b4134dc 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,7 +1,7 @@ ## Process this file with automake to produce Makefile.in. INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib @SNMP_INCLUDES@ -DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" +DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" -DPATH_CONFIG=\"$(sysconfdir)\" lib_LTLIBRARIES = libzebra.la libzebra_la_LDFLAGS = -version-info 0:0:0 @@ -12,13 +12,13 @@ libzebra_la_SOURCES = \ sockunion.c prefix.c thread.c if.c memory.c buffer.c table.c hash.c \ filter.c routemap.c distribute.c stream.c str.c log.c plist.c \ zclient.c sockopt.c smux.c md5.c if_rmap.c keychain.c privs.c \ - sigevent.c pqueue.c jhash.c memtypes.c workqueue.c + sigevent.c pqueue.c jhash.c memtypes.c workqueue.c paths.c BUILT_SOURCES = memtypes.h route_types.h libzebra_la_DEPENDENCIES = @LIB_REGEX@ -libzebra_la_LIBADD = @LIB_REGEX@ +libzebra_la_LIBADD = @LIB_REGEX@ @LIBCAP@ pkginclude_HEADERS = \ buffer.h checksum.h command.h filter.h getopt.h hash.h \ @@ -27,12 +27,12 @@ pkginclude_HEADERS = \ str.h stream.h table.h thread.h vector.h version.h vty.h zebra.h \ plist.h zclient.h sockopt.h smux.h md5.h if_rmap.h keychain.h \ privs.h sigevent.h pqueue.h jhash.h zassert.h memtypes.h \ - workqueue.h route_types.h + workqueue.h route_types.h paths.h -EXTRA_DIST = regex.c regex-gnu.h memtypes.awk route_types.awk route_types.txt +EXTRA_DIST = regex.c regex-gnu.h memtypes.awk route_types.pl route_types.txt memtypes.h: $(srcdir)/memtypes.c $(srcdir)/memtypes.awk ($(GAWK) -f $(srcdir)/memtypes.awk $(srcdir)/memtypes.c > $@) -route_types.h: $(srcdir)/route_types.txt $(srcdir)/route_types.awk - ($(GAWK) -f $(srcdir)/route_types.awk $(srcdir)/route_types.txt > $@) +route_types.h: $(srcdir)/route_types.txt $(srcdir)/route_types.pl + @PERL@ $(srcdir)/route_types.pl < $(srcdir)/route_types.txt > $@ diff --git a/lib/command.c b/lib/command.c index 723e5dd4..a080e5e0 100644 --- a/lib/command.c +++ b/lib/command.c @@ -85,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 { @@ -172,6 +172,12 @@ struct connected /* Label for Linux 2.2.X and upper. */ char *label; + + /* scope value, Linux only */ + unsigned scope; + + /* address preference, NetBSD >=4.0 with option IPSRCSEL, in_getifa(9) */ + int preference; }; /* Does the destination field contain a peer address? */ @@ -22,6 +22,8 @@ * 02111-1307, USA. */ +#define QUAGGA_DEFINE_DESC_TABLE + #include <zebra.h> #include "log.h" @@ -759,7 +761,7 @@ lookup (const struct message *mes, int key) { const struct message *pnt; - for (pnt = mes; pnt->key != 0; pnt++) + for (pnt = mes; pnt->str; pnt++) if (pnt->key == key) return pnt->str; @@ -815,29 +817,6 @@ safe_strerror(int errnum) return (s != NULL) ? s : "Unknown error"; } -struct zebra_desc_table -{ - unsigned int type; - const char *string; - char chr; -}; - -#define DESC_ENTRY(T,S,C) [(T)] = { (T), (S), (C) } -static const struct zebra_desc_table route_types[] = { - DESC_ENTRY (ZEBRA_ROUTE_SYSTEM, "system", 'X' ), - DESC_ENTRY (ZEBRA_ROUTE_KERNEL, "kernel", 'K' ), - DESC_ENTRY (ZEBRA_ROUTE_CONNECT, "connected", 'C' ), - DESC_ENTRY (ZEBRA_ROUTE_STATIC, "static", 'S' ), - DESC_ENTRY (ZEBRA_ROUTE_RIP, "rip", 'R' ), - DESC_ENTRY (ZEBRA_ROUTE_RIPNG, "ripng", 'R' ), - DESC_ENTRY (ZEBRA_ROUTE_OSPF, "ospf", 'O' ), - DESC_ENTRY (ZEBRA_ROUTE_OSPF6, "ospf6", 'O' ), - DESC_ENTRY (ZEBRA_ROUTE_ISIS, "isis", 'I' ), - DESC_ENTRY (ZEBRA_ROUTE_BGP, "bgp", 'B' ), - DESC_ENTRY (ZEBRA_ROUTE_HSLS, "hsls", 'H' ), -}; -#undef DESC_ENTRY - #define DESC_ENTRY(T) [(T)] = { (T), (#T), '\0' } static const struct zebra_desc_table command_types[] = { DESC_ENTRY (ZEBRA_INTERFACE_ADD), @@ -927,4 +906,58 @@ proto_name2num(const char *s) return route_types[i].type; return -1; } + #undef RTSIZE + +int +proto_redistnum(int afi, const char *s) +{ + if (! s) + return -1; + + if (afi == AFI_IP) + { + if (strncmp (s, "k", 1) == 0) + return ZEBRA_ROUTE_KERNEL; + else if (strncmp (s, "c", 1) == 0) + return ZEBRA_ROUTE_CONNECT; + else if (strncmp (s, "s", 1) == 0) + return ZEBRA_ROUTE_STATIC; + else if (strncmp (s, "r", 1) == 0) + return ZEBRA_ROUTE_RIP; + 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, "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) + { + if (strncmp (s, "k", 1) == 0) + return ZEBRA_ROUTE_KERNEL; + else if (strncmp (s, "c", 1) == 0) + return ZEBRA_ROUTE_CONNECT; + else if (strncmp (s, "s", 1) == 0) + return ZEBRA_ROUTE_STATIC; + else if (strncmp (s, "r", 1) == 0) + return ZEBRA_ROUTE_RIPNG; + 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, "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; +} @@ -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 */ +} @@ -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/paths.c b/lib/paths.c new file mode 100644 index 00000000..5678b873 --- /dev/null +++ b/lib/paths.c @@ -0,0 +1,65 @@ +/* + * Path helper functions (for namespaces) + * Copyright (C) 2009 David Lamparter + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <zebra.h> +#include <log.h> +#include <paths.h> + +static char *namespace = ""; + +void path_set_namespace(const char *ns) +{ + size_t len; + + if (*namespace) + free(namespace); + if (!ns || !*ns) { + namespace = ""; + return; + } + + len = strlen(ns); + namespace = malloc(len + 2); + if (!namespace) { /* ugh... */ + namespace = ""; + return; + }; + namespace[0] = '/'; + memcpy(namespace + 1, ns, len + 1); +} + +const char *path_state(const char *filename) +{ + static char buf[MAXPATHLEN]; + snprintf(buf, sizeof(buf), "%s%s/%s", + PATH_STATE, namespace, filename); + return buf; +} + +const char *path_config(const char *filename) +{ + static char buf[MAXPATHLEN]; + snprintf(buf, sizeof(buf), "%s%s/%s", + PATH_CONFIG, namespace, filename); + return buf; +} + diff --git a/lib/paths.h b/lib/paths.h new file mode 100644 index 00000000..1f697855 --- /dev/null +++ b/lib/paths.h @@ -0,0 +1,34 @@ +/* + * Path helper functions (for namespaces) + * Copyright (C) 2009 David Lamparter + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ZEBRA_PATHS_H +#define _ZEBRA_PATHS_H + +extern void path_set_namespace(const char *ns); + +/* the following two functions return pointers to a _static_ buffer! + * if you need to keep a reference to the values, do a strdup + */ +extern const char *path_state(const char *filename); +extern const char *path_config(const char *filename); + +#endif /* _ZEBRA_PATHS_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.awk b/lib/route_types.awk deleted file mode 100644 index eb3d382a..00000000 --- a/lib/route_types.awk +++ /dev/null @@ -1,187 +0,0 @@ -# $Id$ -# -# Scan a file of route-type definitions (see eg route_types.txt) and -# generate a corresponding header file with: -# -# - enum of Zserv route-types -# - redistribute strings for the various Quagga daemons -# -# See route_types.txt for the format. -# -# - -BEGIN { - FS="[,]"; - - # globals - exitret = 0; - tcount = 0; - - # formats for output - ## the define format - redist_def_fmt = "#define QUAGGA_REDIST_STR_%s \\\n"; - ## DEFUN/vty route-type argument - redist_str_fmt = "\"(%s)\"\n"; - redist_help_def_fmt = "#define QUAGGA_REDIST_HELP_STR_%s"; - redist_help_str_fmt = " \\\n \"%s\\n\""; - - # header - header = "/* Auto-generated from route_types.txt by " ARGV[0] ". */\n"; - header = header "/* Do not edit! */\n"; - header = header "\n#ifndef _QUAGGA_ROUTE_TYPES_H\n"; - header = header "#define _QUAGGA_ROUTE_TYPES_H\n"; - footer = "#endif /* _QUAGGA_ROUTE_TYPES_H */\n"; - printf ("%s\n", header); -} - -# Chomp comment lines -($0 ~ /^#/) { - next; -} - -# get rid of the commas, leading/trailling whitespace and -# quotes -{ - for (i = 1; i <= NF; i++) { - #print "before:" $i; - $i = gensub(/^[[:blank:]]*(.*)[,]*.*/, "\\1", "g",$i); - $i = gensub(/^["](.*)["]$/, "\\1", "g", $i); - #print "after :" $i; - } -} - -# 7 field format: -# type cname daemon C 4 6 short help -(NF >= 7) { - #print "7", $1, $0; - - if ($1 in types) { - print "error: attempt to redefine", $1; - exitret = 1; - exit exitret; - } - - typesbynum[tcount] = $1; - types[$1,"num"] = tcount++; - types[$1,"cname"] = $2; - types[$1,"daemon"] = $3; - types[$1,"C"] = $4; - types[$1,"4"] = strtonum($5); - types[$1,"6"] = strtonum($6); - types[$1,"shelp"] = $7; - - #print "num :", types[$1,"num"] - #print "cname :", types[$1,"cname"] - #print "daemon:", types[$1,"daemon"]; - #print "char :", types[$1,"C"]; -}; - -# 2 field: type "long description" -(NF == 2) { - #print "2", $1, $2; - - if (!(($1 SUBSEP "num") in types)) { - print "error: type", $1, "must be defined before help str"; - exitret = 2; - exit exitret; - } - - types[$1,"lhelp"] = $2; -} - -END { - if (exitret) - exit exitret; - - # The enums - # not yet... - #printf("enum\n{\n"); - #for (i = 0; i < tcount; i++) { - # type = typesbynum[i]; - # if (type != "" && types[type,"num"] == i) - # printf (" %s,\n", type); - #} - #printf (" ZEBRA_ROUTE_MAX,\n};\n\n"); - - # the redistribute defines - for (i = 0; i < tcount; i++) { - type = typesbynum[i]; - - # must be a type, and must cross-check against recorded type - if (type == "" || types[type,"num"] != i) - continue; - - # ignore route types that can't be redistributed - if (!(types[type,"4"] || types[type,"6"])) - continue; - - # must have a daemon name - if (!((type SUBSEP "daemon") in types)) - continue; - if (!(daemon = types[type,"daemon"])) - continue; - - # might have done this daemon already? - if (daemon in seen_daemons) - continue; - - cname = types[type,"cname"]; - all = all "|" cname; - rstr = ""; - hstr = ""; - - # add it to the others - for (j = 0; j < tcount; j++) { - # ignore self - if (i == j) - continue; - - type2 = typesbynum[j]; - - # type2 must be valid, and self-check. - if (type2 == "" || types[type2,"num"] != j) - continue; - - # ignore different route types for the same daemon - # (eg system/kernel/connected) - if (types[type2,"daemon"] == daemon) - continue; - - if ((types[type2,"4"] && types[type,"4"]) \ - || (types[type2,"6"] && types[type,"6"])) { - - if (rstr == "") - rstr = types[type2,"cname"]; - else - rstr = rstr "|" types[type2,"cname"]; - - if ((type2 SUBSEP "lhelp") in types) - hstr2 = types[type2,"lhelp"]; - else if ((type2 SUBSEP "shelp") in types) - hstr2 = types[type2,"shelp"]; - else - hstr2 = types[type2,"cname"]; - - hstr = hstr sprintf(redist_help_str_fmt, hstr2); - } - } - - # dont double-process daemons. - seen_daemons[daemon] = 1; - - printf("/* %s */\n", daemon); - printf(redist_def_fmt, toupper(daemon)); - printf(redist_str_fmt, rstr); - printf(redist_help_def_fmt, toupper(daemon)); - printf("%s", hstr); - printf("\n\n"); - } - - #printf("#define QUAGGA_REDIST_STR_ALL %s\n",all); - -# for (i = 0; i < lcount; i++) { -# if (mlists[i] != "") -# printf (mlistformat "\n", mlists[i]); -# } - printf (footer); -} diff --git a/lib/route_types.pl b/lib/route_types.pl new file mode 100755 index 00000000..e1595afc --- /dev/null +++ b/lib/route_types.pl @@ -0,0 +1,199 @@ +#!/usr/bin/perl +## +## Scan a file of route-type definitions (see eg route_types.txt) and +## generate a corresponding header file with: +## +## - enum of Zserv route-types +## - redistribute strings for the various Quagga daemons +## +## See route_types.txt for the format. +## +## +## Copyright (C) 2009 David Lamparter. +## This file is part of GNU Zebra. +## +## GNU Zebra is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by the +## Free Software Foundation; either version 2, or (at your option) any +## later version. +## +## GNU Zebra is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with GNU Zebra; see the file COPYING. If not, write to the Free +## Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +## 02111-1307, USA. +## + +use strict; + +# input processing +# +my @protos; +my %protodetail; + +my %daemons; + +while (<STDIN>) { + # skip comments and empty lines + next if (/^\s*(#|$)/); + + # strip whitespace + chomp; + $_ =~ s/^\s*//; + $_ =~ s/\s*$//; + + # match help strings + if (/^(ZEBRA_ROUTE_[^\s]+)\s*,\s*"(.*)"$/) { + $protodetail{$1}->{'longhelp'} = $2; + next; + } + + $_ =~ s/\s*,\s*/,/g; + + # else: 7-field line + my @f = split(/,/, $_); + unless (@f == 7) { + die "invalid input on route_types line $.\n"; + } + + my $proto = $f[0]; + $f[3] = $1 if ($f[3] =~ /^'(.*)'$/); + $f[6] = $1 if ($f[6] =~ /^"(.*)"$/); + + $protodetail{$proto} = { + "number" => scalar @protos, + "type" => $f[0], + "cname" => $f[1], + "daemon" => $f[2], + "char" => $f[3], + "ipv4" => int($f[4]), + "ipv6" => int($f[5]), + "shorthelp" => $f[6], + }; + push @protos, $proto; + $daemons{$f[2]} = { + "ipv4" => int($f[4]), + "ipv6" => int($f[5]) + } unless ($f[2] eq "NULL"); +} + +# output +printf <<EOF, $ARGV[0]; +/* Auto-generated from route_types.txt by %s. */ +/* Do not edit! */ + +#ifndef _QUAGGA_ROUTE_TYPES_H +#define _QUAGGA_ROUTE_TYPES_H + +/* Zebra route's types. */ +EOF + +push @protos, "ZEBRA_ROUTE_MAX"; +my (@protosv4, @protosv6) = ((), ()); +for (my $c = 0; $c < @protos; $c++) { + my $p = $protos[$c]; + printf "#define %-32s %d\n", $p, $c; + push @protosv4, $p if ($protodetail{$p}->{"ipv4"}); + push @protosv6, $p if ($protodetail{$p}->{"ipv6"}); +} +pop @protos; + +sub codelist { + my (@protos) = @_; + my (@lines) = (); + my $str = " \"Codes: "; + for my $p (@protos) { + my $s = sprintf("%s - %s, ", + $protodetail{$p}->{"char"}, + $protodetail{$p}->{"shorthelp"}); + if (length($str . $s) > 70) { + $str =~ s/ $//; + push @lines, $str . "%s\" \\\n"; + $str = " \" "; + } + $str .= $s; + } + $str =~ s/ $//; + push @lines, $str . "%s\" \\\n"; + push @lines, " \" > - selected route, * - FIB route%s%s\", \\\n"; + my @nl = (); + for (my $c = 0; $c < @lines + 1; $c++) { + push @nl, "VTY_NEWLINE" + } + return join("", @lines) ." ". join(", ", @nl); +} + +print "\n"; +printf "#define SHOW_ROUTE_V4_HEADER \\\n%s\n", codelist(@protosv4); +printf "#define SHOW_ROUTE_V6_HEADER \\\n%s\n", codelist(@protosv6); +print "\n"; + +sub collect { + my ($daemon, $ipv4, $ipv6) = @_; + my (@names, @help) = ((), ()); + for my $p (@protos) { + next if ($protodetail{$p}->{"daemon"} eq $daemon && $daemon ne "zebra"); + next unless (($ipv4 && $protodetail{$p}->{"ipv4"}) + || ($ipv6 && $protodetail{$p}->{"ipv6"})); + push @names, $protodetail{$p}->{"cname"}; + push @help, " \"".$protodetail{$p}->{"longhelp"}."\\n\""; + } + return ("\"(" . join("|", @names) . ")\"", join(" \\\n", @help)); +} + +for my $daemon (sort keys %daemons) { + next unless ($daemons{$daemon}->{"ipv4"} || $daemons{$daemon}->{"ipv6"}); + printf "/* %s */\n", $daemon; + if ($daemons{$daemon}->{"ipv4"} && $daemons{$daemon}->{"ipv6"}) { + my ($names, $help) = collect($daemon, 1, 1); + printf "#define QUAGGA_REDIST_STR_%s \\\n %s\n", uc $daemon, $names; + printf "#define QUAGGA_REDIST_HELP_STR_%s \\\n%s\n", uc $daemon, $help; + ($names, $help) = collect($daemon, 1, 0); + printf "#define QUAGGA_IP_REDIST_STR_%s \\\n %s\n", uc $daemon, $names; + printf "#define QUAGGA_IP_REDIST_HELP_STR_%s \\\n%s\n", uc $daemon, $help; + ($names, $help) = collect($daemon, 0, 1); + printf "#define QUAGGA_IP6_REDIST_STR_%s \\\n %s\n", uc $daemon, $names; + printf "#define QUAGGA_IP6_REDIST_HELP_STR_%s \\\n%s\n", uc $daemon, $help; + } else { + my ($names, $help) = collect($daemon, + $daemons{$daemon}->{"ipv4"}, $daemons{$daemon}->{"ipv6"}); + printf "#define QUAGGA_REDIST_STR_%s \\\n %s\n", uc $daemon, $names; + printf "#define QUAGGA_REDIST_HELP_STR_%s \\\n%s\n", uc $daemon, $help; + } + print "\n"; +} + +print <<EOF; + +#ifdef QUAGGA_DEFINE_DESC_TABLE + +struct zebra_desc_table +{ + unsigned int type; + const char *string; + char chr; +}; + +#define DESC_ENTRY(T,S,C) [(T)] = { (T), (S), (C) } +static const struct zebra_desc_table route_types[] = { +EOF + +for (my $c = 0; $c < @protos; $c++) { + my $p = $protos[$c]; + printf " DESC_ENTRY\t(%s\t \"%s\",\t'%s' ),\n", + $p.",", $protodetail{$p}->{"cname"}, $protodetail{$p}->{"char"}; +} + +print <<EOF; +}; +#undef DESC_ENTRY + +#endif /* QUAGGA_DEFINE_DESC_TABLE */ + +#endif /* _QUAGGA_ROUTE_TYPES_H */ +EOF + diff --git a/lib/route_types.txt b/lib/route_types.txt index e99cacde..8111fc56 100644 --- a/lib/route_types.txt +++ b/lib/route_types.txt @@ -42,13 +42,13 @@ ## type cname daemon C 4 6 short help ZEBRA_ROUTE_SYSTEM, system, NULL, 'X', 0, 0, "Reserved" -ZEBRA_ROUTE_KERNEL, kernel, zebra, 'K', 1, 1, NULL -ZEBRA_ROUTE_CONNECT, connected, zebra, 'C', 1, 1, NULL -ZEBRA_ROUTE_STATIC, static, zebra, 'S', 1, 1, NULL +ZEBRA_ROUTE_KERNEL, kernel, zebra, 'K', 1, 1, "kernel route" +ZEBRA_ROUTE_CONNECT, connected, zebra, 'C', 1, 1, "connected" +ZEBRA_ROUTE_STATIC, static, zebra, 'S', 1, 1, "static" ZEBRA_ROUTE_RIP, rip, ripd, 'R', 1, 0, "RIP" ZEBRA_ROUTE_RIPNG, ripng, ripngd, 'R', 0, 1, "RIPng" ZEBRA_ROUTE_OSPF, ospf, ospfd, 'O', 1, 0, "OSPF" -ZEBRA_ROUTE_OSPF6, ospf6, ospf6d, 'O', 0, 1, "OSPF" +ZEBRA_ROUTE_OSPF6, ospf6, ospf6d, 'O', 0, 1, "OSPFv6" ZEBRA_ROUTE_ISIS, isis, isisd, 'I', 1, 1, "IS-IS" ZEBRA_ROUTE_BGP, bgp, bgpd, 'B', 1, 1, "BGP" # HSLS and OLSR both are AFI independent (so: 1, 1), however @@ -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, oslrd, '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" ## help strings ZEBRA_ROUTE_SYSTEM, "Reserved route type, for internal use only" @@ -72,3 +74,6 @@ 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)" + diff --git a/lib/sockunion.c b/lib/sockunion.c index 6a40f332..5de3bcfc 100644 --- a/lib/sockunion.c +++ b/lib/sockunion.c @@ -527,6 +527,40 @@ sockopt_ttl (int family, int sock, int ttl) return 0; } +int +sockopt_v6only (int family, int sock) +{ + int ret, on = 1; + +#ifdef HAVE_IPV6 +#ifdef IPV6_V6ONLY + if (family == AF_INET6) + { + ret = setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, + (void *) &on, sizeof (int)); + if (ret < 0) + { + zlog (NULL, LOG_WARNING, "can't set sockopt IPV6_V6ONLY " + "to socket %d", sock); + return -1; + } + return 0; + } +#endif /* IPV6_V6ONLY */ +#endif /* HAVE_IPV6 */ + 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 96b9a0d4..2e8ce2d0 100644 --- a/lib/sockunion.h +++ b/lib/sockunion.h @@ -99,9 +99,11 @@ extern int sockunion_accept (int sock, union sockunion *); extern int sockunion_stream_socket (union sockunion *); extern int sockopt_reuseaddr (int); extern int sockopt_reuseport (int); +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 b52bc541..a6aed173 100644 --- a/lib/thread.h +++ b/lib/thread.h @@ -53,7 +53,6 @@ struct thread_master struct thread_list background; fd_set readfd; fd_set writefd; - fd_set exceptfd; unsigned long alloc; }; @@ -209,10 +208,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 */ @@ -1816,6 +1816,7 @@ vty_serv_sock_addrinfo (const char *hostname, unsigned short port) if (sock < 0) continue; + sockopt_v6only (ainfo->ai_family, sock); sockopt_reuseaddr (sock); sockopt_reuseport (sock); diff --git a/lib/zclient.c b/lib/zclient.c index d3d53227..0d531ce7 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -32,6 +32,7 @@ #include "zclient.h" #include "memory.h" #include "table.h" +#include "paths.h" /* Zebra client events. */ enum event {ZCLIENT_SCHEDULE, ZCLIENT_READ, ZCLIENT_CONNECT}; @@ -317,7 +318,7 @@ zclient_start (struct zclient *zclient) #ifdef HAVE_TCP_ZEBRA zclient->sock = zclient_socket (); #else - zclient->sock = zclient_socket_un (ZEBRA_SERV_PATH); + zclient->sock = zclient_socket_un (path_state (ZEBRA_SERV_NAME)); #endif /* HAVE_TCP_ZEBRA */ if (zclient->sock < 0) { diff --git a/lib/zclient.h b/lib/zclient.h index 21786ab8..6a63ffa4 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -28,6 +28,9 @@ /* For input/output buffer to zebra. */ #define ZEBRA_MAX_PACKET_SIZ 4096 +/* Name of the zebra API socket */ +#define ZEBRA_SERV_NAME "zserv.api" + /* Zebra header size. */ #define ZEBRA_HEADER_SIZE 6 diff --git a/lib/zebra.h b/lib/zebra.h index 2dc84514..b580934c 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -429,19 +429,8 @@ struct in_pktinfo */ #define ZEBRA_HEADER_MARKER 255 -/* Zebra route's types. */ -#define ZEBRA_ROUTE_SYSTEM 0 -#define ZEBRA_ROUTE_KERNEL 1 -#define ZEBRA_ROUTE_CONNECT 2 -#define ZEBRA_ROUTE_STATIC 3 -#define ZEBRA_ROUTE_RIP 4 -#define ZEBRA_ROUTE_RIPNG 5 -#define ZEBRA_ROUTE_OSPF 6 -#define ZEBRA_ROUTE_OSPF6 7 -#define ZEBRA_ROUTE_ISIS 8 -#define ZEBRA_ROUTE_BGP 9 -#define ZEBRA_ROUTE_HSLS 10 -#define ZEBRA_ROUTE_MAX 11 +/* Zebra route's types are defined in route_types.h */ +#include "route_types.h" /* Note: whenever a new route-type or zserv-command is added the * corresponding {command,route}_types[] table in lib/log.c MUST be @@ -455,6 +444,10 @@ extern char zebra_route_char(unsigned int route_type); * e.g. ZEBRA_INTERFACE_ADD -> "ZEBRA_INTERFACE_ADD" */ /* Map a protocol name to its number. e.g. ZEBRA_ROUTE_BGP->9*/ extern int proto_name2num(const char *s); +/* Map redistribute X argument to protocol number. + * unlike proto_name2num, this accepts shorthands and takes + * an AFI value to restrict input */ +extern int proto_redistnum(int afi, const char *s); extern const char *zserv_command_string (unsigned int command); |