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