components/quagga/patches/65-isisd-iso-checksum.patch
author Brian Utterback <Brian.Utterback@Oracle.COM>
Mon, 18 Jul 2011 12:08:25 -0700
changeset 417 7c10b5cba79b
child 641 719d637aca9f
permissions -rw-r--r--
7066915 Move Quagga to Userland PSARC 2008/038 Move quagga files from /usr/sfw to /usr 6636788 quagga files should move from /usr/sfw 6610234 Pre-quagga start/stop scripts in /usr/sfw/sbin (bgpdstart,ospfdstart,etc..) should be removed 7064040 quagga smf start method no longer needs to worry about upgrade from SUNWzerbra 7027236 ospfd should allow the -a option to be set in smf 7066821 quaggaadm usage message gives program name as quaggaadm_usage instead of quaggaadm. 6933282 quagga manual pages need to be adjusted for the new IPS package names. 6615038 quaagadm: there is no usage info for the -e option 7002951 quagga pkg should deliver headers to allow users to build OSPF-API client programs

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>