summaryrefslogtreecommitdiffstats
path: root/extra/quagga
diff options
context:
space:
mode:
authorNatanael Copa <ncopa@alpinelinux.org>2009-02-19 12:41:00 +0000
committerNatanael Copa <ncopa@alpinelinux.org>2009-02-19 12:41:00 +0000
commit70a0197eae565fd71db2592a66f7b6f4abcb34e8 (patch)
tree826175695b4be139e4c4d5abf6337ea6ad8ce1ba /extra/quagga
parentce6f3d73f192aea7f12243f16da92e0029ee6079 (diff)
downloadaports-70a0197eae565fd71db2592a66f7b6f4abcb34e8.tar.bz2
aports-70a0197eae565fd71db2592a66f7b6f4abcb34e8.tar.xz
extra/quagga: new aport
A free routing daemon replacing Zebra supporting RIP, OSPF and BGP http://quagga.net/
Diffstat (limited to 'extra/quagga')
-rw-r--r--extra/quagga/APKBUILD81
-rw-r--r--extra/quagga/bgpd.initd33
-rw-r--r--extra/quagga/ospf6d.initd33
-rw-r--r--extra/quagga/ospfd.initd33
-rw-r--r--extra/quagga/quagga-0.99.11-checksum.patch654
-rw-r--r--extra/quagga/quagga-0.99.11-del-routes.patch44
-rw-r--r--extra/quagga/quagga-0.99.11-ipv6-only.patch29
-rw-r--r--extra/quagga/quagga-0.99.11-ipv6.patch19
-rw-r--r--extra/quagga/quagga-0.99.11-link-libcap.patch24
-rw-r--r--extra/quagga/quagga-0.99.11-zombie.patch29
-rw-r--r--extra/quagga/quagga.install13
-rw-r--r--extra/quagga/ripd.initd33
-rw-r--r--extra/quagga/ripngd.initd33
-rw-r--r--extra/quagga/zebra.confd7
-rw-r--r--extra/quagga/zebra.initd41
15 files changed, 1106 insertions, 0 deletions
diff --git a/extra/quagga/APKBUILD b/extra/quagga/APKBUILD
new file mode 100644
index 00000000..04f33d40
--- /dev/null
+++ b/extra/quagga/APKBUILD
@@ -0,0 +1,81 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=quagga
+pkgver=0.99.11
+pkgrel=4
+pkgdesc="A free routing daemon replacing Zebra supporting RIP, OSPF and BGP."
+url="http://quagga.net/"
+license="GPL-2"
+depends="uclibc readline ncurses"
+makedepends="readline-dev ncurses-dev
+ autoconf automake libtool"
+install=quagga.install
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://www.quagga.net/download/$pkgname-$pkgver.tar.gz
+ $pkgname-0.99.11-link-libcap.patch
+ $pkgname-0.99.11-ipv6.patch
+ $pkgname-0.99.11-checksum.patch
+ $pkgname-0.99.11-ipv6-only.patch
+ $pkgname-0.99.11-del-routes.patch
+ $pkgname-0.99.11-zombie.patch
+ bgpd.initd
+ ospf6d.initd
+ ospfd.initd
+ ripd.initd
+ ripngd.initd
+ zebra.initd
+ zebra.confd
+ $install
+ "
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ for i in ../*.patch; do
+ msg "Applying $i..."
+ patch -p1 < $i || return 1
+ done
+
+ msg "Running autotools..."
+ aclocal || return 1
+ autoconf || return 1
+ automake || return 1
+ libtoolize || return 1
+
+ ./configure --prefix=/usr \
+ --disable-static \
+ --enable-ipv6 \
+ --enable-ospf6d \
+ --enable-rtadv \
+ --enable-user=quagga \
+ --enable-group=quagga \
+ --enable-vty-group=quagga \
+ --enable-vtysh \
+ --sysconfdir=/etc/quagga \
+ --enable-exampledir=/usr/share/doc/quagga/ \
+ --localstatedir=/var/run/quagga \
+ || return 1
+
+# --with-cflags="${CFLAGS}" \
+ make || return 1
+ make DESTDIR="$pkgdir" install
+
+ install -d "$pkgdir"/var/run/quagga
+ for i in zebra ripd ospfd bgpd ripngd ospf6d; do
+ install -Dm755 "$srcdir"/$i.initd "$pkgdir"/etc/init.d/$i
+ done
+ install -Dm644 "$srcdir/zebra.confd" "$pkgdir"/etc/conf.d/zebra
+}
+md5sums="903e40c744730ad4d62bee872eeb813b quagga-0.99.11.tar.gz
+8f99d41a8ed79e51704e8f655d255f29 quagga-0.99.11-link-libcap.patch
+d73000d128eaf20a17ffb15b5ca1805a quagga-0.99.11-ipv6.patch
+7e1c0152d4733b713613e10df207e3a9 quagga-0.99.11-checksum.patch
+44c517e988273e0e5076d24f3959a125 quagga-0.99.11-ipv6-only.patch
+1cbcf60a637b2577dee4d6df711e1247 quagga-0.99.11-del-routes.patch
+ce345725f2e7240cebe0fd5ac2b2fc48 quagga-0.99.11-zombie.patch
+cc109a746273bc0d6aee9d758e7524ab bgpd.initd
+44547b687343ebfed7524cebc5626067 ospf6d.initd
+89b0cf4e70172bfcd195b2869cae28da ospfd.initd
+39b8cb21b55de53af38c94c2f5d85917 ripd.initd
+120ab1b53975ec86e78266f31e935ab6 ripngd.initd
+6d51e9fca8d206a6d9d1d9fde793b48f zebra.initd
+c38e884372406e9e59616e436cd26388 zebra.confd
+6d2ca71d32ed9d9517f7779986db91da quagga.install"
diff --git a/extra/quagga/bgpd.initd b/extra/quagga/bgpd.initd
new file mode 100644
index 00000000..b6104235
--- /dev/null
+++ b/extra/quagga/bgpd.initd
@@ -0,0 +1,33 @@
+#!/sbin/runscript
+# Copyright 1999-2003 DataCore GmbH, Amir Guindehi
+# Distributed under the terms of the GNU General Public License, v2 or later
+# $Header: /var/cvsroot/gentoo-x86/net-misc/quagga/files/bgpd.init,v 1.1 2005/09/14 11:11:08 mrness Exp $
+
+depend() {
+ need net zebra
+}
+
+checkconfig() {
+ if [ ! -e /etc/quagga/bgpd.conf ] ; then
+ eerror "You need to create /etc/quagga/bgpd.conf first."
+ eerror "An example can be found in /etc/quagga/samples/bgpd.conf.sample"
+ return 1
+ fi
+}
+
+start() {
+ checkconfig || return 1
+ ebegin "Starting bgpd"
+ start-stop-daemon --start --quiet --exec /usr/sbin/bgpd \
+ -- -d -f /etc/quagga/bgpd.conf \
+ --pid_file /var/run/quagga/bgpd.pid
+ result=$?
+ eend $result
+}
+
+stop() {
+ ebegin "Stopping bgpd"
+ start-stop-daemon --stop --quiet --pidfile /var/run/quagga/bgpd.pid
+ result=$?
+ eend $result
+}
diff --git a/extra/quagga/ospf6d.initd b/extra/quagga/ospf6d.initd
new file mode 100644
index 00000000..6edafe5f
--- /dev/null
+++ b/extra/quagga/ospf6d.initd
@@ -0,0 +1,33 @@
+#!/sbin/runscript
+# Copyright 1999-2003 DataCore GmbH, Amir Guindehi
+# Distributed under the terms of the GNU General Public License, v2 or later
+# $Header: /var/cvsroot/gentoo-x86/net-misc/quagga/files/ospf6d.init,v 1.1 2005/09/14 11:11:08 mrness Exp $
+
+depend() {
+ need net zebra
+}
+
+checkconfig() {
+ if [ ! -e /etc/quagga/ospf6d.conf ] ; then
+ eerror "You need to create /etc/quagga/ospf6d.conf first."
+ eerror "An example can be found in /etc/quagga/samples/ospf6d.conf.sample"
+ return 1
+ fi
+}
+
+start() {
+ checkconfig || return 1
+ ebegin "Starting ospf6d"
+ start-stop-daemon --start --quiet --exec /usr/sbin/ospf6d \
+ -- -d -f /etc/quagga/ospf6d.conf \
+ --pid_file /var/run/quagga/ospf6d.pid
+ result=$?
+ eend $result
+}
+
+stop() {
+ ebegin "Stopping ospf6d"
+ start-stop-daemon --stop --quiet --pidfile /var/run/quagga/ospf6d.pid
+ result=$?
+ eend $result
+}
diff --git a/extra/quagga/ospfd.initd b/extra/quagga/ospfd.initd
new file mode 100644
index 00000000..f67ca2c1
--- /dev/null
+++ b/extra/quagga/ospfd.initd
@@ -0,0 +1,33 @@
+#!/sbin/runscript
+# Copyright 1999-2003 DataCore GmbH, Amir Guindehi
+# Distributed under the terms of the GNU General Public License, v2 or later
+# $Header: /var/cvsroot/gentoo-x86/net-misc/quagga/files/ospfd.init,v 1.1 2005/09/14 11:11:08 mrness Exp $
+
+depend() {
+ need net zebra
+}
+
+checkconfig() {
+ if [ ! -e /etc/quagga/ospfd.conf ] ; then
+ eerror "You need to create /etc/quagga/ospfd.conf first."
+ eerror "An example can be found in /etc/quagga/samples/ospfd.conf.sample"
+ return 1
+ fi
+}
+
+start() {
+ checkconfig || return 1
+ ebegin "Starting ospfd"
+ start-stop-daemon --start --quiet --exec /usr/sbin/ospfd \
+ -- -d -f /etc/quagga/ospfd.conf \
+ --pid_file /var/run/quagga/ospfd.pid
+ result=$?
+ eend $result
+}
+
+stop() {
+ ebegin "Stopping ospfd"
+ start-stop-daemon --stop --quiet --pidfile /var/run/quagga/ospfd.pid
+ result=$?
+ eend $result
+}
diff --git a/extra/quagga/quagga-0.99.11-checksum.patch b/extra/quagga/quagga-0.99.11-checksum.patch
new file mode 100644
index 00000000..c8480ac5
--- /dev/null
+++ b/extra/quagga/quagga-0.99.11-checksum.patch
@@ -0,0 +1,654 @@
+From: Paul Jakma <paul.jakma@sun.com>
+Date: Sun, 16 Nov 2008 18:34:19 +0000 (+0000)
+Subject: [lib] Switch Fletcher checksum back to old ospfd version
+X-Git-Url: http://code.quagga.net/cgi-bin/gitweb.cgi?p=quagga.git;a=commitdiff_plain;h=5d4b8cf2faba9f5386810a7c70837e5b7fae3572
+
+[lib] Switch Fletcher checksum back to old ospfd version
+
+* lib/checksum.c: (fletcher_checksum) Switch the second phase of the checksum
+ back to the old ospfd logic.
+
+ The isisd-derived version:
+
+ a) is very hard to follow
+ b) had some kind of subtle bug that caused it be wrong when c0=0 and c1=254
+ (potentially fixable by doing the mods before adjusting x and y)
+
+ Additionally:
+
+ - explicitely cast expressions using non-internal variables to int, to ensure
+ the result is signed.
+ - defensively change the length argument to 'size_t', to ensure the code
+ works with that argument being unsigned..
+
+ Thanks to Joakim Tjernlund for the investigative work into this bug.
+
+* tests/test-checksum.c: new file to exercise the checksum code.
+---
+
+diff --git a/lib/checksum.c b/lib/checksum.c
+index 88ec72a..f6d74d3 100644
+--- a/lib/checksum.c
++++ b/lib/checksum.c
+@@ -52,34 +52,31 @@ in_cksum(void *parg, int nbytes)
+ /* To be consistent, offset is 0-based index, rather than the 1-based
+ index required in the specification ISO 8473, Annex C.1 */
+ u_int16_t
+-fletcher_checksum(u_char * buffer, int len, u_int16_t offset)
++fletcher_checksum(u_char * buffer, const size_t len, const uint16_t offset)
+ {
+ u_int8_t *p;
+- int x;
+- int y;
+- u_int32_t mul;
+- u_int32_t c0;
+- u_int32_t c1;
++ int x, y, c0, c1;
+ u_int16_t checksum;
+ u_int16_t *csum;
+- int i, init_len, partial_len;
+-
++ size_t partial_len, i, left = len;
++
+ checksum = 0;
+
++ assert (offset < len);
++
+ /*
+ * Zero the csum in the packet.
+ */
+ csum = (u_int16_t *) (buffer + offset);
+- *(csum) = checksum;
++ *(csum) = 0;
+
+ p = buffer;
+ c0 = 0;
+ c1 = 0;
+- init_len = len;
+
+- while (len != 0)
++ while (left != 0)
+ {
+- partial_len = MIN(len, MODX);
++ partial_len = MIN(left, MODX);
+
+ for (i = 0; i < partial_len; i++)
+ {
+@@ -90,27 +87,18 @@ fletcher_checksum(u_char * buffer, int len, u_int16_t offset)
+ c0 = c0 % 255;
+ c1 = c1 % 255;
+
+- len -= partial_len;
++ left -= partial_len;
+ }
+-
+- mul = (init_len - offset)*(c0);
+-
+- x = mul - c0 - c1;
+- y = c1 - mul - 1;
+-
+- if (y > 0)
+- y++;
+- if (x < 0)
+- x--;
+-
+- x %= 255;
+- y %= 255;
+-
+- if (x == 0)
+- x = 255;
+- if (y == 0)
+- y = 1;
+-
++
++ /* 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)
++ y -= 255;
++
+ /*
+ * Now we write this to the packet.
+ * We could skip this step too, since the checksum returned would
+diff --git a/lib/checksum.h b/lib/checksum.h
+index d3ce930..da1d3cb 100644
+--- a/lib/checksum.h
++++ b/lib/checksum.h
+@@ -1,2 +1,2 @@
+ extern int in_cksum(void *, int);
+-extern u_int16_t fletcher_checksum(u_char * buffer, int len, u_int16_t offset);
++extern u_int16_t fletcher_checksum(u_char *, const size_t len, const uint16_t offset);
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index c93fa08..4ab507b 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -6,7 +6,7 @@ AM_LDFLAGS = $(PILDFLAGS)
+
+ noinst_PROGRAMS = testsig testbuffer testmemory heavy heavywq heavythread \
+ aspathtest testprivs teststream testbgpcap ecommtest \
+- testbgpmpattr
++ testbgpmpattr testchecksum
+
+ testsig_SOURCES = test-sig.c
+ testbuffer_SOURCES = test-buffer.c
+@@ -20,6 +20,7 @@ aspathtest_SOURCES = aspath_test.c
+ testbgpcap_SOURCES = bgp_capability_test.c
+ ecommtest_SOURCES = ecommunity_test.c
+ testbgpmpattr_SOURCES = bgp_mp_attr_test.c
++testchecksum_SOURCES = test-checksum.c
+
+ testsig_LDADD = ../lib/libzebra.la @LIBCAP@
+ testbuffer_LDADD = ../lib/libzebra.la @LIBCAP@
+@@ -33,3 +34,4 @@ aspathtest_LDADD = ../lib/libzebra.la @LIBCAP@ -lm ../bgpd/libbgp.a
+ testbgpcap_LDADD = ../lib/libzebra.la @LIBCAP@ -lm ../bgpd/libbgp.a
+ ecommtest_LDADD = ../lib/libzebra.la @LIBCAP@ -lm ../bgpd/libbgp.a
+ testbgpmpattr_LDADD = ../lib/libzebra.la @LIBCAP@ -lm ../bgpd/libbgp.a
++testchecksum_LDADD = ../lib/libzebra.la @LIBCAP@
+diff --git a/tests/test-checksum.c b/tests/test-checksum.c
+new file mode 100644
+index 0000000..d218840
+--- /dev/null
++++ b/tests/test-checksum.c
+@@ -0,0 +1,499 @@
++#include <zebra.h>
++#include <stdlib.h>
++#include <time.h>
++
++#include "checksum.h"
++
++struct thread_master *master;
++
++struct acc_vals {
++ int c0;
++ int c1;
++};
++
++struct csum_vals {
++ struct acc_vals a;
++ int x;
++ int y;
++};
++
++static struct csum_vals ospfd_vals, isisd_vals;
++
++typedef size_t testsz_t;
++typedef uint16_t testoff_t;
++
++/* Fletcher Checksum -- Refer to RFC1008. */
++#define MODX 4102
++
++/* Accumulator phase of checksum */
++static
++struct acc_vals
++accumulate (u_char *buffer, testsz_t len, testoff_t off)
++{
++ u_int8_t *p;
++ u_int16_t *csum;
++ int i, init_len, partial_len;
++ struct acc_vals ret;
++
++ csum = (u_int16_t *) (buffer + off);
++ *(csum) = 0;
++
++ p = buffer;
++ ret.c0 = 0;
++ ret.c1 = 0;
++ init_len = len;
++
++ while (len != 0)
++ {
++ partial_len = MIN(len, MODX);
++
++ for (i = 0; i < partial_len; i++)
++ {
++ ret.c0 = ret.c0 + *(p++);
++ ret.c1 += ret.c0;
++ }
++
++ ret.c0 = ret.c0 % 255;
++ ret.c1 = ret.c1 % 255;
++
++ len -= partial_len;
++ }
++ return ret;
++}
++
++/* The final reduction phase.
++ * This one should be the original ospfd version
++ */
++static u_int16_t
++reduce_ospfd (struct csum_vals *vals, testsz_t len, testoff_t off)
++{
++#define x vals->x
++#define y vals->y
++#define c0 vals->a.c0
++#define c1 vals->a.c1
++
++ x = ((len - off - 1) * c0 - c1) % 255;
++
++ if (x <= 0)
++ x += 255;
++ y = 510 - c0 - x;
++ if (y > 255)
++ y -= 255;
++
++ /* take care endian issue. */
++ return htons ((x << 8) + y);
++#undef x
++#undef y
++#undef c0
++#undef c1
++}
++
++/* slightly different concatenation */
++static u_int16_t
++reduce_ospfd1 (struct csum_vals *vals, testsz_t len, testoff_t off)
++{
++#define x vals->x
++#define y vals->y
++#define c0 vals->a.c0
++#define c1 vals->a.c1
++
++ x = ((len - off - 1) * c0 - c1) % 255;
++ if (x <= 0)
++ x += 255;
++ y = 510 - c0 - x;
++ if (y > 255)
++ y -= 255;
++
++ /* take care endian issue. */
++ return htons ((x << 8) | (y & 0xff));
++#undef x
++#undef y
++#undef c0
++#undef c1
++}
++
++/* original isisd version */
++static u_int16_t
++reduce_isisd (struct csum_vals *vals, testsz_t len, testoff_t off)
++{
++#define x vals->x
++#define y vals->y
++#define c0 vals->a.c0
++#define c1 vals->a.c1
++ u_int32_t mul;
++
++ mul = (len - off)*(c0);
++ x = mul - c0 - c1;
++ y = c1 - mul - 1;
++
++ if (y > 0)
++ y++;
++ if (x < 0)
++ x--;
++
++ x %= 255;
++ y %= 255;
++
++ if (x == 0)
++ x = 255;
++ if (y == 0)
++ y = 1;
++
++ return htons ((x << 8) | (y & 0xff));
++
++#undef x
++#undef y
++#undef c0
++#undef c1
++}
++
++/* Is the -1 in y wrong perhaps? */
++static u_int16_t
++reduce_isisd_yfix (struct csum_vals *vals, testsz_t len, testoff_t off)
++{
++#define x vals->x
++#define y vals->y
++#define c0 vals->a.c0
++#define c1 vals->a.c1
++ u_int32_t mul;
++
++ mul = (len - off)*(c0);
++ x = mul - c0 - c1;
++ y = c1 - mul;
++
++ if (y > 0)
++ y++;
++ if (x < 0)
++ x--;
++
++ x %= 255;
++ y %= 255;
++
++ if (x == 0)
++ x = 255;
++ if (y == 0)
++ y = 1;
++
++ return htons ((x << 8) | (y & 0xff));
++
++#undef x
++#undef y
++#undef c0
++#undef c1
++}
++
++/* Move the mods yp */
++static u_int16_t
++reduce_isisd_mod (struct csum_vals *vals, testsz_t len, testoff_t off)
++{
++#define x vals->x
++#define y vals->y
++#define c0 vals->a.c0
++#define c1 vals->a.c1
++ u_int32_t mul;
++
++ mul = (len - off)*(c0);
++ x = mul - c1 - c0;
++ y = c1 - mul - 1;
++
++ x %= 255;
++ y %= 255;
++
++ if (y > 0)
++ y++;
++ if (x < 0)
++ x--;
++
++ if (x == 0)
++ x = 255;
++ if (y == 0)
++ y = 1;
++
++ return htons ((x << 8) | (y & 0xff));
++
++#undef x
++#undef y
++#undef c0
++#undef c1
++}
++
++/* Move the mods up + fix y */
++static u_int16_t
++reduce_isisd_mody (struct csum_vals *vals, testsz_t len, testoff_t off)
++{
++#define x vals->x
++#define y vals->y
++#define c0 vals->a.c0
++#define c1 vals->a.c1
++ u_int32_t mul;
++
++ mul = (len - off)*(c0);
++ x = mul - c0 - c1;
++ y = c1 - mul;
++
++ x %= 255;
++ y %= 255;
++
++ if (y > 0)
++ y++;
++ if (x < 0)
++ x--;
++
++ if (x == 0)
++ x = 255;
++ if (y == 0)
++ y = 1;
++
++ return htons ((x << 8) | (y & 0xff));
++
++#undef x
++#undef y
++#undef c0
++#undef c1
++}
++
++struct reductions_t {
++ const char *name;
++ u_int16_t (*f) (struct csum_vals *, testsz_t, testoff_t);
++} reducts[] = {
++ { .name = "ospfd", .f = reduce_ospfd },
++ { .name = "ospfd-1", .f = reduce_ospfd1 },
++ { .name = "isisd", .f = reduce_isisd },
++ { .name = "isisd-yfix", .f = reduce_isisd_yfix },
++ { .name = "isisd-mod", .f = reduce_isisd_mod },
++ { .name = "isisd-mody", .f = reduce_isisd_mody },
++ { NULL, NULL },
++};
++
++/* The original ospfd checksum */
++static u_int16_t
++ospfd_checksum (u_char *buffer, testsz_t len, testoff_t off)
++{
++ u_char *sp, *ep, *p, *q;
++ int c0 = 0, c1 = 0;
++ int x, y;
++ u_int16_t checksum, *csum;
++
++ csum = (u_int16_t *) (buffer + off);
++ *(csum) = 0;
++
++ sp = buffer;
++
++ for (ep = sp + len; sp < ep; sp = q)
++ {
++ q = sp + MODX;
++ if (q > ep)
++ q = ep;
++ for (p = sp; p < q; p++)
++ {
++ c0 += *p;
++ c1 += c0;
++ }
++ c0 %= 255;
++ c1 %= 255;
++ }
++
++ ospfd_vals.a.c0 = c0;
++ ospfd_vals.a.c1 = c1;
++
++ //printf ("%s: len %u, off %u, c0 %d, c1 %d\n",
++ // __func__, len, off, c0, c1);
++
++ x = ((int)(len - off - 1) * (int)c0 - (int)c1) % 255;
++
++ if (x <= 0)
++ x += 255;
++ y = 510 - c0 - x;
++ if (y > 255)
++ y -= 255;
++
++ ospfd_vals.x = x;
++ ospfd_vals.y = y;
++
++ buffer[off] = x;
++ buffer[off + 1] = y;
++
++ /* take care endian issue. */
++ checksum = htons ((x << 8) | (y & 0xff));
++
++ return (checksum);
++}
++
++/* the original, broken isisd checksum */
++static u_int16_t
++iso_csum_create (u_char * buffer, testsz_t len, testoff_t off)
++{
++
++ u_int8_t *p;
++ int x;
++ int y;
++ u_int32_t mul;
++ u_int32_t c0;
++ u_int32_t c1;
++ u_int16_t checksum, *csum;
++ int i, init_len, partial_len;
++
++ checksum = 0;
++
++ csum = (u_int16_t *) (buffer + off);
++ *(csum) = checksum;
++
++ p = buffer;
++ c0 = 0;
++ c1 = 0;
++ init_len = len;
++
++ while (len != 0)
++ {
++ partial_len = MIN(len, MODX);
++
++ for (i = 0; i < partial_len; i++)
++ {
++ c0 = c0 + *(p++);
++ c1 += c0;
++ }
++
++ c0 = c0 % 255;
++ c1 = c1 % 255;
++
++ len -= partial_len;
++ }
++
++ isisd_vals.a.c0 = c0;
++ isisd_vals.a.c1 = c1;
++
++ mul = (init_len - off) * c0;
++
++ x = mul - c1 - c0;
++ y = c1 - mul - 1;
++
++ if (y > 0)
++ y++;
++ if (x < 0)
++ x--;
++
++ x %= 255;
++ y %= 255;
++
++ if (x == 0)
++ x = 255;
++ if (y == 0)
++ y = 1;
++
++ isisd_vals.x = x;
++ isisd_vals.y = y;
++
++ checksum = htons((x << 8) | (y & 0xFF));
++
++ *(csum) = checksum;
++
++ /* return the checksum for user usage */
++ return checksum;
++}
++
++static int
++verify (u_char * buffer, testsz_t len)
++{
++ u_int8_t *p;
++ u_int32_t c0;
++ u_int32_t c1;
++ u_int16_t checksum;
++ int i, partial_len;
++
++ p = buffer;
++ checksum = 0;
++
++ c0 = 0;
++ c1 = 0;
++
++ while (len)
++ {
++ partial_len = MIN(len, 5803);
++
++ for (i = 0; i < partial_len; i++)
++ {
++ c0 = c0 + *(p++);
++ c1 += c0;
++ }
++ c0 = c0 % 255;
++ c1 = c1 % 255;
++
++ len -= partial_len;
++ }
++
++ if (c0 == 0 && c1 == 0)
++ return 0;
++
++ return 1;
++}
++
++int
++main(int argc, char **argv)
++{
++/* 60017 65629 702179 */
++#define MAXDATALEN 60017
++#define BUFSIZE MAXDATALEN + sizeof(u_int16_t)
++ u_char buffer[BUFSIZE];
++ int exercise = 0;
++#define EXERCISESTEP 257
++
++ srandom (time (NULL));
++
++ while (1) {
++ u_int16_t ospfd, isisd, lib;
++
++ exercise += EXERCISESTEP;
++ exercise %= MAXDATALEN;
++
++ for (int i = 0; i < exercise; i += sizeof (long int)) {
++ long int rand = random ();
++
++ for (int j = sizeof (long int); j > 0; j--)
++ buffer[i + (sizeof (long int) - j)] = (rand >> (j * 8)) & 0xff;
++ }
++
++ ospfd = ospfd_checksum (buffer, exercise + sizeof(u_int16_t), exercise);
++ if (verify (buffer, exercise + sizeof(u_int16_t)))
++ printf ("verify: ospfd failed\n");
++ isisd = iso_csum_create (buffer, exercise + sizeof(u_int16_t), exercise);
++ if (verify (buffer, exercise + sizeof(u_int16_t)))
++ printf ("verify: isisd failed\n");
++ lib = fletcher_checksum (buffer, exercise + sizeof(u_int16_t), exercise);
++ if (verify (buffer, exercise + sizeof(u_int16_t)))
++ printf ("verify: lib failed\n");
++
++ if (ospfd != lib) {
++ printf ("Mismatch in values at size %u\n"
++ "ospfd: 0x%04x\tc0: %d\tc1: %d\tx: %d\ty: %d\n"
++ "isisd: 0x%04x\tc0: %d\tc1: %d\tx: %d\ty: %d\n"
++ "lib: 0x%04x\n",
++ exercise,
++ ospfd, ospfd_vals.a.c0, ospfd_vals.a.c1, ospfd_vals.x, ospfd_vals.y,
++ isisd, isisd_vals.a.c0, isisd_vals.a.c1, isisd_vals.x, isisd_vals.y,
++ lib
++ );
++
++ /* Investigate reduction phase discrepencies */
++ if (ospfd_vals.a.c0 == isisd_vals.a.c0
++ && ospfd_vals.a.c1 == isisd_vals.a.c1) {
++ printf ("\n");
++ for (int i = 0; reducts[i].name != NULL; i++) {
++ ospfd = reducts[i].f (&ospfd_vals,
++ exercise + sizeof (u_int16_t),
++ exercise);
++ printf ("%20s: x: %02x, y %02x, checksum 0x%04x\n",
++ reducts[i].name, ospfd_vals.x & 0xff, ospfd_vals.y & 0xff, ospfd);
++ }
++ }
++
++ printf ("\n u_char testdata [] = {\n ");
++ for (int i = 0; i < exercise; i++) {
++ printf ("0x%02x,%s",
++ buffer[i],
++ (i + 1) % 8 ? " " : "\n ");
++ }
++ printf ("\n}\n");
++ exit (1);
++ }
++ }
++}
diff --git a/extra/quagga/quagga-0.99.11-del-routes.patch b/extra/quagga/quagga-0.99.11-del-routes.patch
new file mode 100644
index 00000000..72ee8992
--- /dev/null
+++ b/extra/quagga/quagga-0.99.11-del-routes.patch
@@ -0,0 +1,44 @@
+From http://lists.quagga.net/pipermail/quagga-dev/2009-January/006362.html
+
+If there are two paralell PtP links to the same router:
+ C * 192.168.101.112/32 is directly connected, p1-4-19-4-20
+ C>* 192.168.101.112/32 is directly connected, p1-4-17-4-18
+and the cable is to one of the ppp links is pulled, Zebra
+deletes both routes instead of just the one that got yanked.
+This fixes it to only delete the route to the interface that
+got yanked.
+---
+This fix was suggested by lsorense at csclub.uwaterloo.ca (Lennart Sorensen)
+who had a similar problem. See [quagga-dev 6355]
+
+ zebra/zebra_rib.c | 9 ++++++++-
+ 1 files changed, 8 insertions(+), 1 deletions(-)
+
+diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
+index 90db932..7a37387 100644
+--- a/zebra/zebra_rib.c
++++ b/zebra/zebra_rib.c
+@@ -1896,6 +1896,13 @@ rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
+ inet_ntoa (*gate),
+ ifindex);
+
++ if (IS_ZEBRA_DEBUG_KERNEL && !gate)
++ zlog_debug ("rib_delete_ipv4(): route delete %s/%d directly, %s ifindex %d",
++ inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
++ p->prefixlen,
++ ifindex2ifname(ifindex),
++ ifindex);
++
+ /* Lookup route node. */
+ rn = route_node_lookup (table, (struct prefix *) p);
+ if (! rn)
+@@ -1942,7 +1949,7 @@ rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
+ break;
+ }
+ /* Make sure that the route found has the same gateway. */
+- else if (gate == NULL ||
++ else if (gate != NULL &&
+ ((nexthop = rib->nexthop) &&
+ (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) ||
+ IPV4_ADDR_SAME (&nexthop->rgate.ipv4, gate))))
+
diff --git a/extra/quagga/quagga-0.99.11-ipv6-only.patch b/extra/quagga/quagga-0.99.11-ipv6-only.patch
new file mode 100644
index 00000000..53636d6b
--- /dev/null
+++ b/extra/quagga/quagga-0.99.11-ipv6-only.patch
@@ -0,0 +1,29 @@
+On Linux the default behaviour of getaddrinfo is to provide both IPV4 and IPV6
+addresses if available. But the default behaviour of binding to an IPV6 address
+is to handle both the native IPV6 address and IPV4 to IPV6 mapped addresses.
+Without this patch what happens is:
+ 1. First address is IPV6, bind succeeds.
+ 2. Second address is IPV4, bind fails (port already used by IPV6)
+ 3. incoming connections come in on IPV6 listen socket, as IPV4 mapped
+ addresses then BGP gets confused because of client with unexpected address.
+
+The fix is to force IPV6 socket as IPV6 only.
+
+--- a/bgpd/bgp_network.c 2008-08-27 17:59:20.000000000 -0700
++++ b/bgpd/bgp_network.c 2008-08-27 18:02:46.000000000 -0700
+@@ -412,6 +412,15 @@ bgp_socket (struct bgp *bgp, unsigned sh
+ setsockopt_ipv4_tos (sock, IPTOS_PREC_INTERNETCONTROL);
+ #endif
+
++#ifdef IPV6_V6ONLY
++ /* Want only IPV6 on ipv6 socket (not mapped addresses) */
++ if (ainfo->ai_family == AF_INET6) {
++ int on = 1;
++ setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY,
++ (void *) &on, sizeof (on));
++ }
++#endif
++
+ if (bgpd_privs.change (ZPRIVS_RAISE) )
+ zlog_err ("bgp_socket: could not raise privs");
+
diff --git a/extra/quagga/quagga-0.99.11-ipv6.patch b/extra/quagga/quagga-0.99.11-ipv6.patch
new file mode 100644
index 00000000..b7b0b3d2
--- /dev/null
+++ b/extra/quagga/quagga-0.99.11-ipv6.patch
@@ -0,0 +1,19 @@
+diff -Nru quagga-0.99.11.orig/lib/sockopt.c quagga-0.99.11/lib/sockopt.c
+--- quagga-0.99.11.orig/lib/sockopt.c 2008-09-05 14:27:26.000000000 +0000
++++ quagga-0.99.11/lib/sockopt.c 2008-10-13 21:46:13.000000000 +0000
+@@ -530,6 +530,7 @@
+ return -1;
+ };
+
++#ifdef HAVE_IPV6
+ /* If this does not work, then all users of this sockopt will need to
+ * differentiate between IPv4 and IPv6, and keep seperate sockets for
+ * each.
+@@ -546,6 +547,7 @@
+ su2->sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
+ memcpy (&su2->sin6.sin6_addr.s6_addr32[3], &su->sin.sin_addr, 4);
+ }
++#endif /* HAVE_IPV6 */
+ }
+
+ memset (&md5sig, 0, sizeof (md5sig));
diff --git a/extra/quagga/quagga-0.99.11-link-libcap.patch b/extra/quagga/quagga-0.99.11-link-libcap.patch
new file mode 100644
index 00000000..2c1b868d
--- /dev/null
+++ b/extra/quagga/quagga-0.99.11-link-libcap.patch
@@ -0,0 +1,24 @@
+diff -ur quagga-0.99.11.orig/lib/Makefile.am quagga-0.99.11/lib/Makefile.am
+--- quagga-0.99.11.orig/lib/Makefile.am 2008-09-24 15:22:43.000000000 +0000
++++ quagga-0.99.11/lib/Makefile.am 2008-10-09 20:29:17.000000000 +0000
+@@ -18,7 +18,7 @@
+
+ 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 \
+diff -ur quagga-0.99.11.orig/zebra/Makefile.am quagga-0.99.11/zebra/Makefile.am
+--- quagga-0.99.11.orig/zebra/Makefile.am 2008-09-05 14:27:26.000000000 +0000
++++ quagga-0.99.11/zebra/Makefile.am 2008-10-09 20:29:17.000000000 +0000
+@@ -39,7 +39,7 @@
+ connected.h ioctl.h rib.h rt.h zserv.h redistribute.h debug.h rtadv.h \
+ interface.h ipforward.h irdp.h router-id.h kernel_socket.h
+
+-zebra_LDADD = $(otherobj) $(LIBCAP) $(LIB_IPV6) ../lib/libzebra.la
++zebra_LDADD = $(otherobj) ../lib/libzebra.la $(LIBCAP) $(LIB_IPV6)
+
+ testzebra_LDADD = $(LIBCAP) $(LIB_IPV6) ../lib/libzebra.la
+
diff --git a/extra/quagga/quagga-0.99.11-zombie.patch b/extra/quagga/quagga-0.99.11-zombie.patch
new file mode 100644
index 00000000..ad562df0
--- /dev/null
+++ b/extra/quagga/quagga-0.99.11-zombie.patch
@@ -0,0 +1,29 @@
+
+Currently, when accepting the connection, it can be left as zombie,
+when the peer just initiates a connection, but never sends data (and
+the TCP connection end packets are lost). This happens because for
+accepted connections a temporary new peer entry is created until OPEN
+message is exchanged, and this temporary peer entry does not get the
+hold time parameter set at all.
+
+Signed-off-by: Timo Teras <timo.teras@iki.fi>
+---
+ bgpd/bgp_network.c | 2 ++
+ 1 files changed, 2 insertions(+), 0 deletions(-)
+
+diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
+index 5dbd487..9a4c36d 100644
+--- a/bgpd/bgp_network.c
++++ b/bgpd/bgp_network.c
+@@ -185,6 +185,8 @@ bgp_accept (struct thread *thread)
+ peer->fd = bgp_sock;
+ peer->status = Active;
+ peer->local_id = peer1->local_id;
++ peer->v_holdtime = peer1->v_holdtime;
++ peer->v_keepalive = peer1->v_keepalive;
+
+ /* Make peer's address string. */
+ sockunion2str (&su, buf, SU_ADDRSTRLEN);
+--
+1.5.6.3
+
diff --git a/extra/quagga/quagga.install b/extra/quagga/quagga.install
new file mode 100644
index 00000000..a69fe81a
--- /dev/null
+++ b/extra/quagga/quagga.install
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+case "$1" in
+ pre_install)
+ adduser -H -h /var/empty -s /bin/false -D quagga 2>/dev/null
+ mkdir -p var/empty
+ chown root:root var/empty
+ chown quagga:quagga /var/run/quagga
+ ;;
+esac
+exit 0
+
+
diff --git a/extra/quagga/ripd.initd b/extra/quagga/ripd.initd
new file mode 100644
index 00000000..987d6ec4
--- /dev/null
+++ b/extra/quagga/ripd.initd
@@ -0,0 +1,33 @@
+#!/sbin/runscript
+# Copyright 1999-2003 DataCore GmbH, Amir Guindehi
+# Distributed under the terms of the GNU General Public License, v2 or later
+# $Header: /var/cvsroot/gentoo-x86/net-misc/quagga/files/ripd.init,v 1.1 2005/09/14 11:11:08 mrness Exp $
+
+depend() {
+ need net zebra
+}
+
+checkconfig() {
+ if [ ! -e /etc/quagga/ripd.conf ] ; then
+ eerror "You need to create /etc/quagga/ripd.conf first."
+ eerror "An example can be found in /etc/quagga/samples/ripd.conf.sample"
+ return 1
+ fi
+}
+
+start() {
+ checkconfig || return 1
+ ebegin "Starting ripd"
+ start-stop-daemon --start --quiet --exec /usr/sbin/ripd \
+ -- -d -f /etc/quagga/ripd.conf \
+ --pid_file /var/run/quagga/ripd.pid
+ result=$?
+ eend $result
+}
+
+stop() {
+ ebegin "Stopping ripd"
+ start-stop-daemon --stop --quiet --pidfile /var/run/quagga/ripd.pid
+ result=$?
+ eend $result
+}
diff --git a/extra/quagga/ripngd.initd b/extra/quagga/ripngd.initd
new file mode 100644
index 00000000..9bf2ff2a
--- /dev/null
+++ b/extra/quagga/ripngd.initd
@@ -0,0 +1,33 @@
+#!/sbin/runscript
+# Copyright 1999-2003 DataCore GmbH, Amir Guindehi
+# Distributed under the terms of the GNU General Public License, v2 or later
+# $Header: /var/cvsroot/gentoo-x86/net-misc/quagga/files/ripngd.init,v 1.1 2005/09/14 11:11:08 mrness Exp $
+
+depend() {
+ need net zebra
+}
+
+checkconfig() {
+ if [ ! -e /etc/quagga/ripngd.conf ] ; then
+ eerror "You need to create /etc/quagga/ripngd.conf first."
+ eerror "An example can be found in /etc/quagga/samples/ripngd.conf.sample"
+ return 1
+ fi
+}
+
+start() {
+ checkconfig || return 1
+ ebegin "Starting ripngd"
+ start-stop-daemon --start --quiet --exec /usr/sbin/ripngd \
+ -- -d -f /etc/quagga/ripngd.conf \
+ --pid_file /var/run/quagga/ripngd.pid
+ result=$?
+ eend $result
+}
+
+stop() {
+ ebegin "Stopping ripngd"
+ start-stop-daemon --stop --quiet --pidfile /var/run/quagga/ripngd.pid
+ result=$?
+ eend $result
+}
diff --git a/extra/quagga/zebra.confd b/extra/quagga/zebra.confd
new file mode 100644
index 00000000..a5256acd
--- /dev/null
+++ b/extra/quagga/zebra.confd
@@ -0,0 +1,7 @@
+# Additional command-line parameters to run zebra with:
+# -k, --keep_kernel Don't delete old routes which installed by zebra.
+# -l, --log_mode number Set verbose log mode flag
+# -A, --vty_addr addr Set vty's bind address
+# -P, --vty_port port Set vty's port number
+# -r, --retain When program terminates, retain added route by zebra.
+ZEBRA_OPTS="-l 255"
diff --git a/extra/quagga/zebra.initd b/extra/quagga/zebra.initd
new file mode 100644
index 00000000..5ca8ef58
--- /dev/null
+++ b/extra/quagga/zebra.initd
@@ -0,0 +1,41 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License, v2 or later
+# $Header: /var/cvsroot/gentoo-x86/net-misc/quagga/files/zebra.init,v 1.2 2007/02/25 09:57:18 mrness Exp $
+
+depend() {
+ need net
+}
+
+checkconfig() {
+ if [ ! -e /etc/quagga/zebra.conf ] ; then
+ eerror "You need to create /etc/quagga/zebra.conf first."
+ eerror "An example can be found in /etc/quagga/samples/zebra.conf.sample"
+ return 1
+ fi
+}
+
+cleanup() {
+ ebegin "Cleaning up stale zebra routes..."
+ ip route flush proto zebra
+ eend $?
+}
+
+start() {
+ checkconfig || return 1
+ cleanup
+
+ ebegin "Starting zebra"
+ start-stop-daemon --start --quiet --exec /usr/sbin/zebra \
+ -- -d -f /etc/quagga/zebra.conf ${ZEBRA_OPTS} \
+ --pid_file /var/run/quagga/zebra.pid
+ result=$?
+ eend $result
+}
+
+stop() {
+ ebegin "Stopping zebra"
+ start-stop-daemon --stop --quiet --pidfile /var/run/quagga/zebra.pid
+ result=$?
+ eend $result
+}