xref: /csrg-svn/sys/netiso/iso_chksum.c (revision 37469)
136387Ssklower /***********************************************************
236387Ssklower 		Copyright IBM Corporation 1987
336387Ssklower 
436387Ssklower                       All Rights Reserved
536387Ssklower 
636387Ssklower Permission to use, copy, modify, and distribute this software and its
736387Ssklower documentation for any purpose and without fee is hereby granted,
836387Ssklower provided that the above copyright notice appear in all copies and that
936387Ssklower both that copyright notice and this permission notice appear in
1036387Ssklower supporting documentation, and that the name of IBM not be
1136387Ssklower used in advertising or publicity pertaining to distribution of the
1236387Ssklower software without specific, written prior permission.
1336387Ssklower 
1436387Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
1536387Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
1636387Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
1736387Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
1836387Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
1936387Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2036387Ssklower SOFTWARE.
2136387Ssklower 
2236387Ssklower ******************************************************************/
2336387Ssklower 
2436387Ssklower /*
2536387Ssklower  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
2636387Ssklower  */
2736387Ssklower /*
2836387Ssklower  * $Header: iso_chksum.c,v 4.7 88/07/29 15:31:26 nhall Exp $
2936387Ssklower  * $Source: /usr/argo/sys/netiso/RCS/iso_chksum.c,v $
3036387Ssklower  *
3136387Ssklower  * ISO CHECKSUM
3236387Ssklower  *
3336387Ssklower  * The checksum generation and check routines are here.
3436387Ssklower  * The checksum is 2 bytes such that the sum of all the bytes b(i) == 0
3536387Ssklower  * and the sum of i * b(i) == 0.
3636387Ssklower  * The whole thing is complicated by the fact that the data are in mbuf
3736387Ssklower  * chains.
3836387Ssklower  * Furthermore, there is the possibility of wraparound in the running
3936387Ssklower  * sums after adding up 4102 octets.  In order to avoid doing a mod
4036387Ssklower  * operation after EACH add, we have restricted this implementation to
4136387Ssklower  * negotiating a maximum of 4096-octets per TPDU (for the transport layer).
4236387Ssklower  * The routine iso_check_csum doesn't need to know where the checksum
4336387Ssklower  * octets are.
4436387Ssklower  * The routine iso_gen_csum takes a pointer to an mbuf chain (logically
4536387Ssklower  * a chunk of data), an offset into the chunk at which the 2 octets are to
4636387Ssklower  * be stuffed, and the length of the chunk.  The 2 octets have to be
4736387Ssklower  * logically adjacent, but may be physically located in separate mbufs.
4836387Ssklower  */
4936387Ssklower 
50*37469Ssklower #ifdef ISO
5136387Ssklower #ifndef lint
5236387Ssklower static char *rcsid = "$Header: iso_chksum.c,v 4.7 88/07/29 15:31:26 nhall Exp $";
5336387Ssklower #endif
5436387Ssklower 
55*37469Ssklower #include "argo_debug.h"
56*37469Ssklower #include "param.h"
57*37469Ssklower #include "mbuf.h"
58*37469Ssklower #endif ISO
5936387Ssklower 
6036387Ssklower #ifndef MNULL
6136387Ssklower #define MNULL (struct mbuf *)0
6236387Ssklower #endif MNULL
6336387Ssklower 
6436387Ssklower /*
6536387Ssklower  * FUNCTION:	iso_check_csum
6636387Ssklower  *
6736387Ssklower  * PURPOSE:		To check the checksum of the packet in the mbuf chain (m).
6836387Ssklower  * 				The total length of the packet is (len).
6936387Ssklower  * 				Called from tp_input() and clnp_intr()
7036387Ssklower  *
7136387Ssklower  * RETURNS:		 TRUE (something non-zero) if there is a checksum error,
7236387Ssklower  * 			 	 FALSE if there was NO checksum error.
7336387Ssklower  *
7436387Ssklower  * SIDE EFFECTS:  none
7536387Ssklower  *
7636387Ssklower  * NOTES:		 It might be possible to gain something by optimizing
7736387Ssklower  *               this routine (unrolling loops, etc). But it is such
7836387Ssklower  *				 a horrible thing to fiddle with anyway, it probably
7936387Ssklower  *				 isn't worth it.
8036387Ssklower  */
8136387Ssklower int
8236387Ssklower iso_check_csum(m, len)
8336387Ssklower 	struct mbuf *m;
8436387Ssklower 	int len;
8536387Ssklower {
8636387Ssklower 	register u_char *p = mtod(m, u_char *);
8736387Ssklower 	register u_long c0=0, c1=0;
8836387Ssklower 	register int i=0;
8936387Ssklower 	int cum = 0; /* cumulative length */
9036387Ssklower 	int l;
9136387Ssklower 
9236387Ssklower 	l = len;
9336387Ssklower 	len = MIN(m->m_len, len);
9436387Ssklower 	i = 0;
9536387Ssklower 
9636387Ssklower 	IFDEBUG(D_CHKSUM)
9736387Ssklower 		printf("iso_check_csum: m x%x, l x%x, m->m_len x%x\n", m, l, m->m_len);
9836387Ssklower 	ENDDEBUG
9936387Ssklower 
10036387Ssklower 	while( i<l ) {
10136387Ssklower 		cum += len;
10236387Ssklower 		while (i<cum) {
10336387Ssklower 			c0 = c0 + *(p++);
10436387Ssklower 			c1 += c0;
10536387Ssklower 			i++;
10636387Ssklower 		}
10736387Ssklower 		if(i < l) {
10836387Ssklower 			m = m->m_next;
10936387Ssklower 			IFDEBUG(D_CHKSUM)
11036387Ssklower 				printf("iso_check_csum: new mbuf\n");
11136387Ssklower 				if(l-i < m->m_len)
11236387Ssklower 					printf(
113*37469Ssklower 					"bad mbuf chain in check csum l 0x%x i 0x%x m_data 0x%x",
114*37469Ssklower 						l,i,m->m_data);
11536387Ssklower 			ENDDEBUG
11636387Ssklower 			ASSERT( m != MNULL);
11736387Ssklower 			len = MIN( m->m_len, l-i);
11836387Ssklower 			p = mtod(m, u_char *);
11936387Ssklower 		}
12036387Ssklower 	}
12136387Ssklower 	if ( ((int)c0 % 255) || ((int)c1 % 255) ) {
12236387Ssklower 		IFDEBUG(D_CHKSUM)
12336387Ssklower 			printf("BAD iso_check_csum l 0x%x cum 0x%x len 0x%x, i 0x%x",
12436387Ssklower 				l, cum, len, i);
12536387Ssklower 		ENDDEBUG
12636387Ssklower 		return ((int)c0 % 255)<<8 | ((int)c1 % 255);
12736387Ssklower 	}
12836387Ssklower 	return 0;
12936387Ssklower }
13036387Ssklower 
13136387Ssklower /*
13236387Ssklower  * FUNCTION:	iso_gen_csum
13336387Ssklower  *
13436387Ssklower  * PURPOSE:		To generate the checksum of the packet in the mbuf chain (m).
13536387Ssklower  * 				The first of the 2 (logically) adjacent checksum bytes
13636387Ssklower  *				(x and y) go at offset (n).
13736387Ssklower  * 				(n) is an offset relative to the beginning of the data,
13836387Ssklower  *				not the beginning of the mbuf.
13936387Ssklower  * 				(l) is the length of the total mbuf chain's data.
14036387Ssklower  * 				Called from tp_emit(), tp_error_emit()
14136387Ssklower  *				clnp_emit_er(), clnp_forward(), clnp_output().
14236387Ssklower  *
14336387Ssklower  * RETURNS:		Rien
14436387Ssklower  *
14536387Ssklower  * SIDE EFFECTS: Puts the 2 checksum bytes into the packet.
14636387Ssklower  *
14736387Ssklower  * NOTES:		Ditto the note for iso_check_csum().
14836387Ssklower  */
14936387Ssklower 
15036387Ssklower void
15136387Ssklower iso_gen_csum(m,n,l)
15236387Ssklower 	struct mbuf *m;
15336387Ssklower 	int n; /* offset of 2 checksum bytes */
15436387Ssklower 	int l;
15536387Ssklower {
15636387Ssklower 	register u_char *p = mtod(m, u_char *);
15736387Ssklower 	register int c0=0, c1=0;
15836387Ssklower 	register int i=0;
15936387Ssklower 	int loc = n++, len=0; /* n is position, loc is offset */
16036387Ssklower 	u_char *xloc;
16136387Ssklower 	u_char *yloc;
16236387Ssklower 	int cum=0;	/* cum == cumulative length */
16336387Ssklower 
16436387Ssklower 	IFDEBUG(D_CHKSUM)
16536387Ssklower 		printf("enter gen csum m 0x%x n 0x%x l 0x%x\n",m, n-1 ,l );
16636387Ssklower 	ENDDEBUG
16736387Ssklower 
16836387Ssklower 	while(i < l) {
16936387Ssklower 		len = MIN(m->m_len, CLBYTES);
17036387Ssklower 		/* RAH: don't cksum more than l bytes */
17136387Ssklower 		len = MIN(len, l);
17236387Ssklower 
17336387Ssklower 		cum +=len;
17436387Ssklower 		p = mtod(m, u_char *);
17536387Ssklower 
17636387Ssklower 		if(loc>=0) {
17736387Ssklower 			if (loc < len) {
178*37469Ssklower 				xloc = loc + mtod(m, u_char *);
17936387Ssklower 				IFDEBUG(D_CHKSUM)
18036387Ssklower 					printf("1: zeroing xloc 0x%x loc 0x%x\n",xloc, loc );
18136387Ssklower 				ENDDEBUG
18236387Ssklower 				*xloc = (u_char)0;
18336387Ssklower 				if (loc+1 < len) {
18436387Ssklower 					/* both xloc and yloc are in same mbuf */
185*37469Ssklower 					yloc = 1  + xloc;
18636387Ssklower 					IFDEBUG(D_CHKSUM)
18736387Ssklower 						printf("2: zeroing yloc 0x%x loc 0x%x\n",yloc, loc );
18836387Ssklower 					ENDDEBUG
18936387Ssklower 					*yloc = (u_char)0;
19036387Ssklower 				} else {
19136387Ssklower 					/* crosses boundary of mbufs */
192*37469Ssklower 					yloc = mtod(m->m_next, u_char *);
19336387Ssklower 					IFDEBUG(D_CHKSUM)
19436387Ssklower 						printf("3: zeroing yloc 0x%x \n",yloc );
19536387Ssklower 					ENDDEBUG
19636387Ssklower 					*yloc = (u_char)0;
19736387Ssklower 				}
19836387Ssklower 			}
19936387Ssklower 			loc -= len;
20036387Ssklower 		}
20136387Ssklower 
20236387Ssklower 		while(i < cum) {
20336387Ssklower 			c0 = (c0 + *p);
20436387Ssklower 			c1 += c0 ;
20536387Ssklower 			i++;
20636387Ssklower 			p++;
20736387Ssklower 		}
20836387Ssklower 		m = m->m_next;
20936387Ssklower 	}
21036387Ssklower 	IFDEBUG(D_CHKSUM)
21136387Ssklower 		printf("gen csum final xloc 0x%x yloc 0x%x\n",xloc, yloc );
21236387Ssklower 	ENDDEBUG
21336387Ssklower 
21436387Ssklower 	c1 = (((c0 * (l-n))-c1)%255) ;
21536387Ssklower 	*xloc = (u_char) ((c1 < 0)? c1+255 : c1);
21636387Ssklower 
21736387Ssklower 	c1 = (-(int)(c1+c0))%255;
21836387Ssklower 	*yloc = (u_char) (c1 < 0? c1 + 255 : c1);
21936387Ssklower 
22036387Ssklower 	IFDEBUG(D_CHKSUM)
22136387Ssklower 		printf("gen csum end \n");
22236387Ssklower 	ENDDEBUG
22336387Ssklower }
22436387Ssklower 
22536387Ssklower struct mbuf  *
22636387Ssklower m_append(head, m)
22736387Ssklower 	struct mbuf *head, *m;
22836387Ssklower {
22936387Ssklower 	register struct mbuf *n;
23036387Ssklower 
23136387Ssklower 	if (m == 0)
23236387Ssklower 		return head;
23336387Ssklower 	if (head == 0)
23436387Ssklower 		return m;
23536387Ssklower 	n = head;
23636387Ssklower 	while (n->m_next)
23736387Ssklower 		n = n->m_next;
23836387Ssklower 	n->m_next = m;
23936387Ssklower 	return head;
24036387Ssklower }
24136387Ssklower /*
24236387Ssklower  * FUNCTION:	m_datalen
24336387Ssklower  *
24436387Ssklower  * PURPOSE:		returns length of the mbuf chain.
24536387Ssklower  * 				used all over the iso code.
24636387Ssklower  *
24736387Ssklower  * RETURNS:		integer
24836387Ssklower  *
24936387Ssklower  * SIDE EFFECTS: none
25036387Ssklower  *
25136387Ssklower  * NOTES:
25236387Ssklower  */
25336387Ssklower 
25436387Ssklower int
25536387Ssklower m_datalen (morig)
25636387Ssklower 	struct mbuf *morig;
25736387Ssklower {
25836387Ssklower 	int	s = splimp();
25936387Ssklower 	register struct mbuf *n=morig;
26036387Ssklower 	register int datalen = 0;
26136387Ssklower 
26236387Ssklower 	if( morig == (struct mbuf *)0)
26336387Ssklower 		return 0;
26436387Ssklower 	for(;;) {
26536387Ssklower 		datalen += n->m_len;
26636387Ssklower 		if (n->m_next == (struct mbuf *)0 ) {
26736387Ssklower 			break;
26836387Ssklower 		}
26936387Ssklower 		n = n->m_next;
27036387Ssklower 	}
27136387Ssklower 	splx(s);
27236387Ssklower 	return datalen;
27336387Ssklower }
27436387Ssklower 
27536387Ssklower int
27636387Ssklower m_compress(in, out)
27736387Ssklower 	register struct mbuf *in, **out;
27836387Ssklower {
27936387Ssklower 	register 	int datalen = 0;
28036387Ssklower 	int	s = splimp();
28136387Ssklower 
28236387Ssklower 	if( in->m_next == MNULL ) {
28336387Ssklower 		*out = in;
28436387Ssklower 		IFDEBUG(D_REQUEST)
28536387Ssklower 			printf("m_compress returning 0x%x: A\n", in->m_len);
28636387Ssklower 		ENDDEBUG
28736387Ssklower 		splx(s);
28836387Ssklower 		return in->m_len;
28936387Ssklower 	}
29036387Ssklower 	MGET((*out), M_DONTWAIT, MT_DATA);
29136387Ssklower 	if((*out) == MNULL) {
29236387Ssklower 		*out = in;
29336387Ssklower 		IFDEBUG(D_REQUEST)
29436387Ssklower 			printf("m_compress returning -1: B\n");
29536387Ssklower 		ENDDEBUG
29636387Ssklower 		splx(s);
29736387Ssklower 		return -1;
29836387Ssklower 	}
29936387Ssklower 	(*out)->m_len = 0;
30036387Ssklower 	(*out)->m_act = MNULL;
30136387Ssklower 
30236387Ssklower 	while (in) {
30336387Ssklower 		IFDEBUG(D_REQUEST)
30436387Ssklower 			printf("m_compress in 0x%x *out 0x%x\n", in, *out);
305*37469Ssklower 			printf("m_compress in: len 0x%x, off 0x%x\n", in->m_len, in->m_data);
30636387Ssklower 			printf("m_compress *out: len 0x%x, off 0x%x\n", (*out)->m_len,
307*37469Ssklower 				(*out)->m_data);
30836387Ssklower 		ENDDEBUG
309*37469Ssklower 		if (in->m_flags & M_EXT) {
31036387Ssklower 			ASSERT(in->m_len == 0);
31136387Ssklower 		}
31236387Ssklower 		if ( in->m_len == 0) {
31336387Ssklower 			in = in->m_next;
31436387Ssklower 			continue;
31536387Ssklower 		}
316*37469Ssklower 		if (((*out)->m_flags & M_EXT) == 0) {
31736387Ssklower 			int len;
31836387Ssklower 
319*37469Ssklower 			len = M_TRAILINGSPACE(*out);
32036387Ssklower 			len = MIN(len, in->m_len);
32136387Ssklower 			datalen += len;
32236387Ssklower 
32336387Ssklower 			IFDEBUG(D_REQUEST)
32436387Ssklower 				printf("m_compress copying len %d\n", len);
32536387Ssklower 			ENDDEBUG
326*37469Ssklower 			bcopy(mtod(in, caddr_t), mtod((*out), caddr_t) + (*out)->m_len,
327*37469Ssklower 						(unsigned)len);
32836387Ssklower 
32936387Ssklower 			(*out)->m_len += len;
33036387Ssklower 			in->m_len -= len;
33136387Ssklower 			continue;
33236387Ssklower 		} else {
33336387Ssklower 			/* (*out) is full */
33436387Ssklower 			if(( (*out)->m_next = m_get(M_DONTWAIT, MT_DATA) ) == MNULL) {
33536387Ssklower 				m_freem(*out);
33636387Ssklower 				*out = in;
33736387Ssklower 				IFDEBUG(D_REQUEST)
33836387Ssklower 					printf("m_compress returning -1: B\n");
33936387Ssklower 				ENDDEBUG
34036387Ssklower 				splx(s);
34136387Ssklower 				return -1;
34236387Ssklower 			}
34336387Ssklower 			(*out)->m_len = 0;
34436387Ssklower 			(*out)->m_act = MNULL;
34536387Ssklower 			*out = (*out)->m_next;
34636387Ssklower 		}
34736387Ssklower 	}
34836387Ssklower 	m_freem(in);
34936387Ssklower 	IFDEBUG(D_REQUEST)
35036387Ssklower 		printf("m_compress returning 0x%x: A\n", datalen);
35136387Ssklower 	ENDDEBUG
35236387Ssklower 	splx(s);
35336387Ssklower 	return datalen;
35436387Ssklower }
355