--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/quagga/patches/65-isisd-iso-checksum.patch Mon Jul 18 12:08:25 2011 -0700
@@ -0,0 +1,676 @@
+diff -ur quagga-0.99.8/ChangeLog quagga-unified-checksum/ChangeLog
+--- ChangeLog
++++ ChangeLog
+@@ -1,3 +1,18 @@
++2008-06-25 Jingjing Duan <[email protected]>
++ * lib/checksum.[ch]: Add a consolidated checksum function to be
++ used by both OSPF and IS-IS. The consolidated version also fixes
++ the checksum byte-order checksum on big-endian architectures.
++ * isisd/iso_checksum.[ch]: Remove the old checksum implementation
++ and use the consolidated version.
++ * isisd/isis_dlpi.c: Change ioctl from PFIOCSETF (transparent mode)
++ to I_STR (non-transparent mode). The old code resulted in no
++ filtering at all.
++ * isisd/isis_dlpi.c: (open_dlpi_dev) Clearview-UV device nodes are
++ under /dev/net, try opening there before attempting style 1 or 2
++ names.
++ * ospfd/ospf_lsa.c: Remove the old checksum implementation and
++ use the consolidated version.
++
+ 2007-08-07 James Carlson <[email protected]>
+
+ * configure.ac: Added support for separate link-layer access
+diff -ur quagga-0.99.8/isisd/isis_dlpi.c quagga-unified-checksum/isisd/isis_dlpi.c
+--- isisd/isis_dlpi.c
++++ isisd/isis_dlpi.c
+@@ -42,8 +42,6 @@
+ #include "isisd/isis_circuit.h"
+ #include "isisd/isis_flags.h"
+ #include "isisd/isisd.h"
+-#include "isisd/isis_constants.h"
+-#include "isisd/isis_circuit.h"
+ #include "isisd/isis_network.h"
+
+ #include "privs.h"
+@@ -315,13 +313,24 @@
+ circuit->interface->name);
+ return ISIS_WARNING;
+ }
++
++ /* Try the vanity node first, if permitted */
++ if (getenv("DLPI_DEVONLY") == NULL)
++ {
++ (void) snprintf (devpath, sizeof(devpath), "/dev/net/%s",
++ circuit->interface->name);
++ fd = dlpiopen (devpath, &acklen);
++ }
++
++ /* Now try as an ordinary Style 1 node */
++ if (fd == -1)
++ {
++ (void) snprintf (devpath, sizeof (devpath), "/dev/%s",
++ circuit->interface->name);
++ unit = -1;
++ fd = dlpiopen (devpath, &acklen);
++ }
+
+- /* Try first as Style 1 */
+- (void) snprintf(devpath, sizeof (devpath), "/dev/%s",
+- circuit->interface->name);
+- unit = -1;
+- fd = dlpiopen (devpath, &acklen);
+-
+ /* If that fails, try again as Style 2 */
+ if (fd == -1)
+ {
+@@ -452,11 +461,19 @@
+ if (ioctl (fd, I_PUSH, "pfmod") == 0)
+ {
+ struct packetfilt pfil;
++ struct strioctl sioc;
+
+ pfil.Pf_Priority = 0;
+ pfil.Pf_FilterLen = sizeof (pf_filter) / sizeof (u_short);
+ memcpy (pfil.Pf_Filter, pf_filter, sizeof (pf_filter));
+- ioctl (fd, PFIOCSETF, &pfil);
++ /* pfmod does not support transparent ioctls */
++ sioc.ic_cmd = PFIOCSETF;
++ sioc.ic_timout = 5;
++ sioc.ic_len = sizeof (struct packetfilt);
++ sioc.ic_dp = (char *)&pfil;
++ if (ioctl (fd, I_STR, &sioc) == -1)
++ zlog_warn("%s: could not perform PF_IOCSETF on %s",
++ __func__, circuit->interface->name);
+ }
+
+ circuit->fd = fd;
+diff -ur quagga-0.99.8/isisd/isis_lsp.c quagga-unified-checksum/isisd/isis_lsp.c
+--- isisd/isis_lsp.c
++++ isisd/isis_lsp.c
+@@ -33,6 +33,7 @@
+ #include "command.h"
+ #include "hash.h"
+ #include "if.h"
++#include "checksum.h"
+
+ #include "isisd/dict.h"
+ #include "isisd/isis_constants.h"
+@@ -45,7 +46,6 @@
+ #include "isisd/isis_dynhn.h"
+ #include "isisd/isis_misc.h"
+ #include "isisd/isis_flags.h"
+-#include "isisd/iso_checksum.h"
+ #include "isisd/isis_csm.h"
+ #include "isisd/isis_adjacency.h"
+ #include "isisd/isis_spf.h"
+@@ -314,7 +314,7 @@
+ newseq = seq_num++;
+
+ lsp->lsp_header->seq_num = htonl (newseq);
+- iso_csum_create (STREAM_DATA (lsp->pdu) + 12,
++ fletcher_checksum (STREAM_DATA (lsp->pdu) + 12,
+ ntohs (lsp->lsp_header->pdu_len) - 12, 12);
+
+ return;
+@@ -1803,7 +1803,7 @@
+ tlv_add_is_neighs (lsp->tlv_data.es_neighs, lsp->pdu);
+
+ lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu));
+- iso_csum_create (STREAM_DATA (lsp->pdu) + 12,
++ fletcher_checksum (STREAM_DATA (lsp->pdu) + 12,
+ ntohs (lsp->lsp_header->pdu_len) - 12, 12);
+
+ list_delete (adj_list);
+@@ -2071,7 +2071,7 @@
+ lsp->lsp_header->pdu_len =
+ htons (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
+ lsp->purged = 0;
+- iso_csum_create (STREAM_DATA (lsp->pdu) + 12,
++ fletcher_checksum (STREAM_DATA (lsp->pdu) + 12,
+ ntohs (lsp->lsp_header->pdu_len) - 12, 12);
+ ISIS_FLAGS_SET_ALL (lsp->SRMflags);
+ }
+diff -ur quagga-0.99.8/isisd/isis_pdu.c quagga-unified-checksum/isisd/isis_pdu.c
+--- isisd/isis_pdu.c
++++ isisd/isis_pdu.c
+@@ -32,6 +32,7 @@
+ #include "hash.c"
+ #include "prefix.h"
+ #include "if.h"
++#include "checksum.h"
+
+ #include "isisd/dict.h"
+ #include "isisd/include-netbsd/iso.h"
+@@ -1121,7 +1122,7 @@
+ if (isis->debugs & DEBUG_UPDATE_PACKETS)
+ zlog_debug ("LSP LEN: %d",
+ ntohs (lsp->lsp_header->pdu_len));
+- iso_csum_create (STREAM_DATA (lsp->pdu) + 12,
++ fletcher_checksum (STREAM_DATA (lsp->pdu) + 12,
+ ntohs (lsp->lsp_header->pdu_len) - 12, 12);
+ ISIS_FLAGS_SET_ALL (lsp->SRMflags);
+ if (isis->debugs & DEBUG_UPDATE_PACKETS)
+@@ -1164,7 +1165,7 @@
+ /* 7.3.16.1 */
+ lsp->lsp_header->seq_num = htonl (ntohl (hdr->seq_num) + 1);
+
+- iso_csum_create (STREAM_DATA (lsp->pdu) + 12,
++ fletcher_checksum (STREAM_DATA (lsp->pdu) + 12,
+ ntohs (lsp->lsp_header->pdu_len) - 12, 12);
+
+ ISIS_FLAGS_SET_ALL (lsp->SRMflags);
+diff -ur quagga-0.99.8/isisd/iso_checksum.c quagga-unified-checksum/isisd/iso_checksum.c
+--- isisd/iso_checksum.c
++++ isisd/iso_checksum.c
+@@ -23,6 +23,7 @@
+
+ #include <zebra.h>
+ #include "iso_checksum.h"
++#include "checksum.h"
+
+ /*
+ * Calculations of the OSI checksum.
+@@ -47,14 +48,10 @@
+ int
+ iso_csum_verify (u_char * buffer, int len, uint16_t * csum)
+ {
+- u_int8_t *p;
++ u_int16_t checksum;
+ u_int32_t c0;
+ u_int32_t c1;
+- u_int16_t checksum;
+- int i, partial_len;
+
+- p = buffer;
+- checksum = 0;
+ c0 = *csum & 0xff00;
+ c1 = *csum & 0x00ff;
+
+@@ -70,124 +69,8 @@
+ if (c0 == 0 || c1 == 0)
+ return 1;
+
+- /*
+- * Otherwise initialize to zero and calculate...
+- */
+- 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;
+-
++ checksum = fletcher_checksum(buffer, len, (u_char *)csum - buffer);
++ if (checksum == *csum)
++ return 0;
+ return 1;
+ }
+-
+-/*
+- * Creates the checksum. *csum points to the position of the checksum in the
+- * PDU.
+- * Based on Annex C.4 of ISO/IEC 8473
+- */
+-#define FIXED_CODE
+-u_int16_t
+-iso_csum_create (u_char * buffer, int len, u_int16_t n)
+-{
+-
+- u_int8_t *p;
+- int x;
+- int y;
+- u_int32_t mul;
+- u_int32_t c0;
+- u_int32_t c1;
+- u_int16_t checksum;
+- u_int16_t *csum;
+- int i, init_len, partial_len;
+-
+- checksum = 0;
+-
+- /*
+- * Zero the csum in the packet.
+- */
+- csum = (u_int16_t *) (buffer + n);
+- *(csum) = checksum;
+-
+- p = buffer;
+- c0 = 0;
+- c1 = 0;
+- init_len = len;
+-
+- while (len != 0)
+- {
+- 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;
+- }
+-
+- mul = (init_len - n)*(c0);
+-
+-#ifdef FIXED_CODE
+- 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;
+-
+- checksum = (y << 8) | (x & 0xFF);
+-
+-#else
+- x = mul - c0 - c1;
+- x %= 255;
+-
+- y = c1 - mul - 1;
+- y %= 255;
+-
+- if (x == 0)
+- x = 255;
+- if (y == 0)
+- y = 255;
+-
+- checksum = ((y << 8) | x);
+-#endif
+-
+- /*
+- * Now we write this to the packet
+- */
+- *(csum) = checksum;
+-
+- /* return the checksum for user usage */
+- return checksum;
+-}
+diff -ur quagga-0.99.8/isisd/iso_checksum.h quagga-unified-checksum/isisd/iso_checksum.h
+--- isisd/iso_checksum.h
++++ isisd/iso_checksum.h
+@@ -24,6 +24,5 @@
+ #define _ZEBRA_ISO_CSUM_H
+
+ int iso_csum_verify (u_char * buffer, int len, uint16_t * csum);
+-u_int16_t iso_csum_create (u_char * buffer, int len, u_int16_t n);
+
+ #endif /* _ZEBRA_ISO_CSUM_H */
+diff -ur quagga-0.99.8/lib/checksum.c quagga-unified-checksum/lib/checksum.c
+--- lib/checksum.c
++++ lib/checksum.c
+@@ -45,3 +45,82 @@
+ answer = ~sum; /* ones-complement, then truncate to 16 bits */
+ return(answer);
+ }
++
++/* Fletcher Checksum -- Refer to RFC1008. */
++#define MODX 4102 /* 5802 should be fine */
++
++/* 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)
++{
++ u_int8_t *p;
++ int x;
++ int y;
++ u_int32_t mul;
++ u_int32_t c0;
++ u_int32_t c1;
++ u_int16_t checksum;
++ u_int16_t *csum;
++ int i, init_len, partial_len;
++
++ checksum = 0;
++
++ /*
++ * Zero the csum in the packet.
++ */
++ csum = (u_int16_t *) (buffer + offset);
++ *(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;
++ }
++
++ 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;
++
++ /*
++ * 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.
++ */
++ buffer[offset] = x;
++ buffer[offset + 1] = y;
++
++ /* Take care of the endian issue */
++ checksum = htons((x << 8) | (y & 0xFF));
++
++ return checksum;
++}
+diff -ur quagga-0.99.8/lib/checksum.h quagga-unified-checksum/lib/checksum.h
+--- lib/checksum.h
++++ lib/checksum.h
+@@ -1 +1,2 @@
+ extern int in_cksum(void *, int);
++extern u_int16_t fletcher_checksum(u_char * buffer, int len, u_int16_t offset);
+diff -ur quagga-0.99.8/ospfd/ospf_lsa.c quagga-unified-checksum/ospfd/ospf_lsa.c
+--- ospfd/ospf_lsa.c
++++ ospfd/ospf_lsa.c
+@@ -32,6 +32,7 @@
+ #include "thread.h"
+ #include "hash.h"
+ #include "sockunion.h" /* for inet_aton() */
++#include "checksum.h"
+
+ #include "ospfd/ospfd.h"
+ #include "ospfd/ospf_interface.h"
+@@ -172,46 +173,22 @@
+
+
+ /* Fletcher Checksum -- Refer to RFC1008. */
+-#define MODX 4102
+-#define LSA_CHECKSUM_OFFSET 15
+
++/* All the offsets are zero-based. The offsets in the RFC1008 are
++ one-based. */
+ u_int16_t
+ ospf_lsa_checksum (struct lsa_header *lsa)
+ {
+- u_char *sp, *ep, *p, *q;
+- int c0 = 0, c1 = 0;
+- int x, y;
+- u_int16_t length;
+-
+- lsa->checksum = 0;
+- length = ntohs (lsa->length) - 2;
+- sp = (u_char *) &lsa->options;
+-
+- for (ep = sp + length; 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;
+- }
++ u_char *buffer = (u_char *) &lsa->options;
++ int options_offset = buffer - (u_char *) &lsa->ls_age; /* should be 2 */
+
+- x = (((int)length - LSA_CHECKSUM_OFFSET) * c0 - c1) % 255;
+- if (x <= 0)
+- x += 255;
+- y = 510 - c0 - x;
+- if (y > 255)
+- y -= 255;
++ /* Skip the AGE field */
++ u_int16_t len = ntohs(lsa->length) - options_offset;
+
+- /* take care endian issue. */
+- lsa->checksum = htons ((x << 8) + y);
++ /* Checksum offset starts from "options" field, not the beginning of the
++ lsa_header struct. The offset is 14, rather than 16. */
+
+- return (lsa->checksum);
++ return fletcher_checksum(buffer, len, (u_char *) &lsa->checksum - buffer);
+ }
+
+
+diff -ur quagga-0.99.8/solaris/quagga.init.in quagga-unified-checksum/solaris/quagga.init.in
+--- solaris/quagga.init.in
++++ solaris/quagga.init.in
+@@ -134,7 +134,7 @@
+ case "${DAEMON}" in
+ bgpd)
+ ;;
+- zebra | ospfd | ospf6d | ripd | ripngd )
++ zebra | ospfd | ospf6d | ripd | ripngd | isisd)
+ quagga_is_globalzone || exit $SMF_EXIT_OK
+ ;;
+ *)
+@@ -168,7 +168,7 @@
+ eval exec $DAEMON_PATH/$DAEMON $DAEMON_ARGS --pid_file ${PIDFILE} &
+ }
+
+-stop () {
++daemonstop () {
+ if [ -f "${PIDFILE}" ]; then
+ /usr/bin/kill -TERM `/usr/bin/cat "${PIDFILE}"`
+ fi
+@@ -179,7 +179,7 @@
+ start
+ ;;
+ 'stop')
+- stop
++ daemonstop
+ ;;
+
+ *)
+diff -ur quagga-0.99.8/solaris/quagga.xml.in quagga-unified-checksum/solaris/quagga.xml.in
+--- solaris/quagga.xml.in
++++ solaris/quagga.xml.in
+@@ -187,7 +187,7 @@
+ <service_fmri value='svc:/network/routing-setup' />
+ </dependency>
+
+- <!-- ensure that restart of zebra is propogated to daemon -->
++ <!-- ensure that restart of zebra is propagated to daemon -->
+ <dependency
+ name='zebra'
+ grouping='optional_all'
+@@ -818,6 +818,148 @@
+ <manpage title='bgpd' section='1M'
+ manpath='@mandir@' />
+ <doc_link name='quagga.net'
++ uri='http://www.quagga.net/' />
++ </documentation>
++ </template>
++ </instance>
++ <stability value='Unstable' />
++</service>
++
++<service
++ name='network/routing/isis'
++ type='service'
++ version='1'>
++
++ <instance name='quagga' enabled='false'>
++
++ <dependency name='fs'
++ grouping='require_all'
++ restart_on='none'
++ type='service'>
++ <service_fmri
++ value='svc:/system/filesystem/usr:default' />
++ </dependency>
++
++ <dependency
++ name='ipv6-forwarding'
++ grouping='optional_all'
++ restart_on='refresh'
++ type='service'>
++ <service_fmri value='svc:/network/ipv6-forwarding' />
++ </dependency>
++
++ <dependency
++ name='ipv4-forwarding'
++ grouping='optional_all'
++ restart_on='refresh'
++ type='service'>
++ <service_fmri value='svc:/network/ipv4-forwarding' />
++ </dependency>
++
++ <!-- do not not run unless routing-setup has run -->
++ <dependency
++ name='network_routing_setup'
++ grouping='require_all'
++ restart_on='refresh'
++ type='service'>
++ <service_fmri value='svc:/network/routing-setup' />
++ </dependency>
++
++ <!-- ensure that restart of zebra is propogated to daemon -->
++ <dependency
++ name='zebra'
++ grouping='optional_all'
++ restart_on='restart'
++ type='service'>
++ <service_fmri value='svc:/network/routing/zebra:quagga' />
++ </dependency>
++
++ <exec_method
++ type='method'
++ name='start'
++ exec='/lib/svc/method/quagga isisd'
++ timeout_seconds='60'>
++ <method_context>
++ <method_credential
++ user='root' group='root'/>
++ </method_context>
++ </exec_method>
++
++ <!-- isisd can take a long time to shutdown, due to graceful
++ shutdown
++ -->
++ <exec_method
++ type='method'
++ name='stop'
++ exec=':kill'
++ timeout_seconds='60'>
++ </exec_method>
++
++ <property_group name='startd'
++ type='framework'>
++ <!-- sub-process core dumps shouldn't restart session -->
++ <propval name='ignore_error'
++ type='astring' value='core,signal' />
++ </property_group>
++
++ <!-- Properties in this group are used by routeadm (1M) -->
++ <property_group name='routeadm' type='application'>
++ <stability value='Unstable' />
++ <!-- Identifies service as a routing service -->
++ <propval name='daemon' type='astring'
++ value='@sbindir@/isisd' />
++ <propval name='value_authorization' type='astring'
++ value='solaris.smf.value.routing' />
++ <property name='protocol' type='astring'>
++ <astring_list>
++ <value_node value='ipv4'/>
++ <value_node value='ipv6'/>
++ </astring_list>
++ </property>
++ </property_group>
++
++ <!-- Properties in this group are modifiable via routeadm (1M) -->
++ <property_group name='routing' type='application'>
++ <propval name='value_authorization' type='astring'
++ value='solaris.smf.value.routing' />
++
++ <!-- Options common to Quagga daemons -->
++ <!-- The config file to use, if not the default -->
++ <propval name='config_file' type='astring' value=''/>
++ <!-- The vty_port to listen on if not the default.
++ 0 to disable -->
++ <propval name='vty_port' type='integer' value='0' />
++ <!-- The address to bind the VTY interface to, if not any. -->
++ <propval name='vty_address' type='astring' value='' />
++ <!-- The user to switch to after startup, if not the default -->
++ <propval name='user' type='astring' value='' />
++ <!-- The group to switch to, if not the default.
++ If user is specified, this defaults to a group with
++ same name as user -->
++ <propval name='group' type='astring' value='' />
++ <!-- The pidfile to use, if not the default of
++ @quagga_statedir@ -->
++ <propval name='pid_file' type='astring' value='' />
++ </property_group>
++
++ <property_group name='general' type='framework'>
++ <!-- to start stop routing services -->
++ <propval name='action_authorization' type='astring'
++ value='solaris.smf.manage.routing' />
++ <propval name='value_authorization' type='astring'
++ value='solaris.smf.manage.routing' />
++ </property_group>
++
++ <template>
++ <common_name>
++ <loctext xml:lang='C'>
++ Quagga: isisd, IS-IS routing protocol daemon.
++ </loctext>
++ </common_name>
++ <documentation>
++ <manpage title='isisd' section='1M'
++ manpath='@mandir@' />
++ <doc_link name='quagga.net'
+ uri='http://www.quagga.net/' />
+ </documentation>
+ </template>