xref: /csrg-svn/sys/netiso/iso_chksum.c (revision 36387)
1*36387Ssklower /***********************************************************
2*36387Ssklower 		Copyright IBM Corporation 1987
3*36387Ssklower 
4*36387Ssklower                       All Rights Reserved
5*36387Ssklower 
6*36387Ssklower Permission to use, copy, modify, and distribute this software and its
7*36387Ssklower documentation for any purpose and without fee is hereby granted,
8*36387Ssklower provided that the above copyright notice appear in all copies and that
9*36387Ssklower both that copyright notice and this permission notice appear in
10*36387Ssklower supporting documentation, and that the name of IBM not be
11*36387Ssklower used in advertising or publicity pertaining to distribution of the
12*36387Ssklower software without specific, written prior permission.
13*36387Ssklower 
14*36387Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15*36387Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16*36387Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17*36387Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18*36387Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19*36387Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20*36387Ssklower SOFTWARE.
21*36387Ssklower 
22*36387Ssklower ******************************************************************/
23*36387Ssklower 
24*36387Ssklower /*
25*36387Ssklower  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
26*36387Ssklower  */
27*36387Ssklower /*
28*36387Ssklower  * $Header: iso_chksum.c,v 4.7 88/07/29 15:31:26 nhall Exp $
29*36387Ssklower  * $Source: /usr/argo/sys/netiso/RCS/iso_chksum.c,v $
30*36387Ssklower  *
31*36387Ssklower  * ISO CHECKSUM
32*36387Ssklower  *
33*36387Ssklower  * The checksum generation and check routines are here.
34*36387Ssklower  * The checksum is 2 bytes such that the sum of all the bytes b(i) == 0
35*36387Ssklower  * and the sum of i * b(i) == 0.
36*36387Ssklower  * The whole thing is complicated by the fact that the data are in mbuf
37*36387Ssklower  * chains.
38*36387Ssklower  * Furthermore, there is the possibility of wraparound in the running
39*36387Ssklower  * sums after adding up 4102 octets.  In order to avoid doing a mod
40*36387Ssklower  * operation after EACH add, we have restricted this implementation to
41*36387Ssklower  * negotiating a maximum of 4096-octets per TPDU (for the transport layer).
42*36387Ssklower  * The routine iso_check_csum doesn't need to know where the checksum
43*36387Ssklower  * octets are.
44*36387Ssklower  * The routine iso_gen_csum takes a pointer to an mbuf chain (logically
45*36387Ssklower  * a chunk of data), an offset into the chunk at which the 2 octets are to
46*36387Ssklower  * be stuffed, and the length of the chunk.  The 2 octets have to be
47*36387Ssklower  * logically adjacent, but may be physically located in separate mbufs.
48*36387Ssklower  */
49*36387Ssklower 
50*36387Ssklower #ifndef lint
51*36387Ssklower static char *rcsid = "$Header: iso_chksum.c,v 4.7 88/07/29 15:31:26 nhall Exp $";
52*36387Ssklower #endif
53*36387Ssklower 
54*36387Ssklower #include "../netiso/argo_debug.h"
55*36387Ssklower #include "../h/param.h"
56*36387Ssklower #include "../h/mbuf.h"
57*36387Ssklower 
58*36387Ssklower #ifndef MNULL
59*36387Ssklower #define MNULL (struct mbuf *)0
60*36387Ssklower #endif MNULL
61*36387Ssklower 
62*36387Ssklower /*
63*36387Ssklower  * FUNCTION:	iso_check_csum
64*36387Ssklower  *
65*36387Ssklower  * PURPOSE:		To check the checksum of the packet in the mbuf chain (m).
66*36387Ssklower  * 				The total length of the packet is (len).
67*36387Ssklower  * 				Called from tp_input() and clnp_intr()
68*36387Ssklower  *
69*36387Ssklower  * RETURNS:		 TRUE (something non-zero) if there is a checksum error,
70*36387Ssklower  * 			 	 FALSE if there was NO checksum error.
71*36387Ssklower  *
72*36387Ssklower  * SIDE EFFECTS:  none
73*36387Ssklower  *
74*36387Ssklower  * NOTES:		 It might be possible to gain something by optimizing
75*36387Ssklower  *               this routine (unrolling loops, etc). But it is such
76*36387Ssklower  *				 a horrible thing to fiddle with anyway, it probably
77*36387Ssklower  *				 isn't worth it.
78*36387Ssklower  */
79*36387Ssklower int
80*36387Ssklower iso_check_csum(m, len)
81*36387Ssklower 	struct mbuf *m;
82*36387Ssklower 	int len;
83*36387Ssklower {
84*36387Ssklower 	register u_char *p = mtod(m, u_char *);
85*36387Ssklower 	register u_long c0=0, c1=0;
86*36387Ssklower 	register int i=0;
87*36387Ssklower 	int cum = 0; /* cumulative length */
88*36387Ssklower 	int l;
89*36387Ssklower 
90*36387Ssklower 	l = len;
91*36387Ssklower 	len = MIN(m->m_len, len);
92*36387Ssklower 	i = 0;
93*36387Ssklower 
94*36387Ssklower 	IFDEBUG(D_CHKSUM)
95*36387Ssklower 		printf("iso_check_csum: m x%x, l x%x, m->m_len x%x\n", m, l, m->m_len);
96*36387Ssklower 	ENDDEBUG
97*36387Ssklower 
98*36387Ssklower 	while( i<l ) {
99*36387Ssklower 		cum += len;
100*36387Ssklower 		while (i<cum) {
101*36387Ssklower 			c0 = c0 + *(p++);
102*36387Ssklower 			c1 += c0;
103*36387Ssklower 			i++;
104*36387Ssklower 		}
105*36387Ssklower 		if(i < l) {
106*36387Ssklower 			m = m->m_next;
107*36387Ssklower 			IFDEBUG(D_CHKSUM)
108*36387Ssklower 				printf("iso_check_csum: new mbuf\n");
109*36387Ssklower 				if(l-i < m->m_len)
110*36387Ssklower 					printf(
111*36387Ssklower 					"bad mbuf chain in check csum l 0x%x i 0x%x m_off 0x%x",
112*36387Ssklower 						l,i,m->m_off);
113*36387Ssklower 			ENDDEBUG
114*36387Ssklower 			ASSERT( m != MNULL);
115*36387Ssklower 			len = MIN( m->m_len, l-i);
116*36387Ssklower 			p = mtod(m, u_char *);
117*36387Ssklower 		}
118*36387Ssklower 	}
119*36387Ssklower 	if ( ((int)c0 % 255) || ((int)c1 % 255) ) {
120*36387Ssklower 		IFDEBUG(D_CHKSUM)
121*36387Ssklower 			printf("BAD iso_check_csum l 0x%x cum 0x%x len 0x%x, i 0x%x",
122*36387Ssklower 				l, cum, len, i);
123*36387Ssklower 		ENDDEBUG
124*36387Ssklower 		return ((int)c0 % 255)<<8 | ((int)c1 % 255);
125*36387Ssklower 	}
126*36387Ssklower 	return 0;
127*36387Ssklower }
128*36387Ssklower 
129*36387Ssklower /*
130*36387Ssklower  * FUNCTION:	iso_gen_csum
131*36387Ssklower  *
132*36387Ssklower  * PURPOSE:		To generate the checksum of the packet in the mbuf chain (m).
133*36387Ssklower  * 				The first of the 2 (logically) adjacent checksum bytes
134*36387Ssklower  *				(x and y) go at offset (n).
135*36387Ssklower  * 				(n) is an offset relative to the beginning of the data,
136*36387Ssklower  *				not the beginning of the mbuf.
137*36387Ssklower  * 				(l) is the length of the total mbuf chain's data.
138*36387Ssklower  * 				Called from tp_emit(), tp_error_emit()
139*36387Ssklower  *				clnp_emit_er(), clnp_forward(), clnp_output().
140*36387Ssklower  *
141*36387Ssklower  * RETURNS:		Rien
142*36387Ssklower  *
143*36387Ssklower  * SIDE EFFECTS: Puts the 2 checksum bytes into the packet.
144*36387Ssklower  *
145*36387Ssklower  * NOTES:		Ditto the note for iso_check_csum().
146*36387Ssklower  */
147*36387Ssklower 
148*36387Ssklower void
149*36387Ssklower iso_gen_csum(m,n,l)
150*36387Ssklower 	struct mbuf *m;
151*36387Ssklower 	int n; /* offset of 2 checksum bytes */
152*36387Ssklower 	int l;
153*36387Ssklower {
154*36387Ssklower #ifdef lint
155*36387Ssklower 	register u_char *p = (u_char *)((int)m + m->m_off);
156*36387Ssklower #else
157*36387Ssklower 	register u_char *p = mtod(m, u_char *);
158*36387Ssklower #endif
159*36387Ssklower 	register int c0=0, c1=0;
160*36387Ssklower 	register int i=0;
161*36387Ssklower 	int loc = n++, len=0; /* n is position, loc is offset */
162*36387Ssklower 	u_char *xloc;
163*36387Ssklower 	u_char *yloc;
164*36387Ssklower 	int cum=0;	/* cum == cumulative length */
165*36387Ssklower 
166*36387Ssklower 	IFDEBUG(D_CHKSUM)
167*36387Ssklower 		printf("enter gen csum m 0x%x n 0x%x l 0x%x\n",m, n-1 ,l );
168*36387Ssklower 	ENDDEBUG
169*36387Ssklower 
170*36387Ssklower 	while(i < l) {
171*36387Ssklower 		len = MIN(m->m_len, CLBYTES);
172*36387Ssklower 		/* RAH: don't cksum more than l bytes */
173*36387Ssklower 		len = MIN(len, l);
174*36387Ssklower 
175*36387Ssklower 		cum +=len;
176*36387Ssklower 		p = mtod(m, u_char *);
177*36387Ssklower 
178*36387Ssklower 		if(loc>=0) {
179*36387Ssklower 			if (loc < len) {
180*36387Ssklower 				xloc = ((u_char *)((int)(m) + (m)->m_off + loc));
181*36387Ssklower 				IFDEBUG(D_CHKSUM)
182*36387Ssklower 					printf("1: zeroing xloc 0x%x loc 0x%x\n",xloc, loc );
183*36387Ssklower 				ENDDEBUG
184*36387Ssklower 				*xloc = (u_char)0;
185*36387Ssklower 				if (loc+1 < len) {
186*36387Ssklower 					/* both xloc and yloc are in same mbuf */
187*36387Ssklower 					yloc = ((u_char *)((int)(m) + (m)->m_off + loc + 1));
188*36387Ssklower 					IFDEBUG(D_CHKSUM)
189*36387Ssklower 						printf("2: zeroing yloc 0x%x loc 0x%x\n",yloc, loc );
190*36387Ssklower 					ENDDEBUG
191*36387Ssklower 					*yloc = (u_char)0;
192*36387Ssklower 				} else {
193*36387Ssklower 					/* crosses boundary of mbufs */
194*36387Ssklower 					yloc = ((u_char *)((int)(m->m_next) + (m->m_next)->m_off));
195*36387Ssklower 					IFDEBUG(D_CHKSUM)
196*36387Ssklower 						printf("3: zeroing yloc 0x%x \n",yloc );
197*36387Ssklower 					ENDDEBUG
198*36387Ssklower 					*yloc = (u_char)0;
199*36387Ssklower 				}
200*36387Ssklower 			}
201*36387Ssklower 			loc -= len;
202*36387Ssklower 		}
203*36387Ssklower 
204*36387Ssklower 		while(i < cum) {
205*36387Ssklower 			c0 = (c0 + *p);
206*36387Ssklower 			c1 += c0 ;
207*36387Ssklower 			i++;
208*36387Ssklower 			p++;
209*36387Ssklower 		}
210*36387Ssklower 		m = m->m_next;
211*36387Ssklower 	}
212*36387Ssklower 	IFDEBUG(D_CHKSUM)
213*36387Ssklower 		printf("gen csum final xloc 0x%x yloc 0x%x\n",xloc, yloc );
214*36387Ssklower 	ENDDEBUG
215*36387Ssklower 
216*36387Ssklower 	c1 = (((c0 * (l-n))-c1)%255) ;
217*36387Ssklower 	*xloc = (u_char) ((c1 < 0)? c1+255 : c1);
218*36387Ssklower 
219*36387Ssklower 	c1 = (-(int)(c1+c0))%255;
220*36387Ssklower 	*yloc = (u_char) (c1 < 0? c1 + 255 : c1);
221*36387Ssklower 
222*36387Ssklower 	IFDEBUG(D_CHKSUM)
223*36387Ssklower 		printf("gen csum end \n");
224*36387Ssklower 	ENDDEBUG
225*36387Ssklower }
226*36387Ssklower 
227*36387Ssklower struct mbuf  *
228*36387Ssklower m_append(head, m)
229*36387Ssklower 	struct mbuf *head, *m;
230*36387Ssklower {
231*36387Ssklower 	register struct mbuf *n;
232*36387Ssklower 
233*36387Ssklower 	if (m == 0)
234*36387Ssklower 		return head;
235*36387Ssklower 	if (head == 0)
236*36387Ssklower 		return m;
237*36387Ssklower 	n = head;
238*36387Ssklower 	while (n->m_next)
239*36387Ssklower 		n = n->m_next;
240*36387Ssklower 	n->m_next = m;
241*36387Ssklower 	return head;
242*36387Ssklower }
243*36387Ssklower /*
244*36387Ssklower  * FUNCTION:	m_datalen
245*36387Ssklower  *
246*36387Ssklower  * PURPOSE:		returns length of the mbuf chain.
247*36387Ssklower  * 				used all over the iso code.
248*36387Ssklower  *
249*36387Ssklower  * RETURNS:		integer
250*36387Ssklower  *
251*36387Ssklower  * SIDE EFFECTS: none
252*36387Ssklower  *
253*36387Ssklower  * NOTES:
254*36387Ssklower  */
255*36387Ssklower 
256*36387Ssklower int
257*36387Ssklower m_datalen (morig)
258*36387Ssklower 	struct mbuf *morig;
259*36387Ssklower {
260*36387Ssklower 	int	s = splimp();
261*36387Ssklower 	register struct mbuf *n=morig;
262*36387Ssklower 	register int datalen = 0;
263*36387Ssklower 
264*36387Ssklower 	if( morig == (struct mbuf *)0)
265*36387Ssklower 		return 0;
266*36387Ssklower 	for(;;) {
267*36387Ssklower 		datalen += n->m_len;
268*36387Ssklower 		if (n->m_next == (struct mbuf *)0 ) {
269*36387Ssklower 			break;
270*36387Ssklower 		}
271*36387Ssklower 		n = n->m_next;
272*36387Ssklower 	}
273*36387Ssklower 	splx(s);
274*36387Ssklower 	return datalen;
275*36387Ssklower }
276*36387Ssklower 
277*36387Ssklower int
278*36387Ssklower m_compress(in, out)
279*36387Ssklower 	register struct mbuf *in, **out;
280*36387Ssklower {
281*36387Ssklower 	register 	int datalen = 0;
282*36387Ssklower 	int	s = splimp();
283*36387Ssklower 
284*36387Ssklower 	if( in->m_next == MNULL ) {
285*36387Ssklower 		*out = in;
286*36387Ssklower 		IFDEBUG(D_REQUEST)
287*36387Ssklower 			printf("m_compress returning 0x%x: A\n", in->m_len);
288*36387Ssklower 		ENDDEBUG
289*36387Ssklower 		splx(s);
290*36387Ssklower 		return in->m_len;
291*36387Ssklower 	}
292*36387Ssklower 	MGET((*out), M_DONTWAIT, MT_DATA);
293*36387Ssklower 	if((*out) == MNULL) {
294*36387Ssklower 		*out = in;
295*36387Ssklower 		IFDEBUG(D_REQUEST)
296*36387Ssklower 			printf("m_compress returning -1: B\n");
297*36387Ssklower 		ENDDEBUG
298*36387Ssklower 		splx(s);
299*36387Ssklower 		return -1;
300*36387Ssklower 	}
301*36387Ssklower 	(*out)->m_len = 0;
302*36387Ssklower 	(*out)->m_act = MNULL;
303*36387Ssklower 
304*36387Ssklower 	while (in) {
305*36387Ssklower 		IFDEBUG(D_REQUEST)
306*36387Ssklower 			printf("m_compress in 0x%x *out 0x%x\n", in, *out);
307*36387Ssklower 			printf("m_compress in: len 0x%x, off 0x%x\n", in->m_len, in->m_off);
308*36387Ssklower 			printf("m_compress *out: len 0x%x, off 0x%x\n", (*out)->m_len,
309*36387Ssklower 				(*out)->m_off);
310*36387Ssklower 		ENDDEBUG
311*36387Ssklower 		if ( in->m_off >= MMAXOFF) {
312*36387Ssklower 			ASSERT(in->m_len == 0);
313*36387Ssklower 		}
314*36387Ssklower 		if ( in->m_len == 0) {
315*36387Ssklower 			in = in->m_next;
316*36387Ssklower 			continue;
317*36387Ssklower 		}
318*36387Ssklower 		if ((*out)->m_off < MMAXOFF) {
319*36387Ssklower 			int len;
320*36387Ssklower 
321*36387Ssklower 		    len = MMAXOFF - ((*out)->m_off + (*out)->m_len);
322*36387Ssklower 			len = MIN(len, in->m_len);
323*36387Ssklower 			datalen += len;
324*36387Ssklower 
325*36387Ssklower 			IFDEBUG(D_REQUEST)
326*36387Ssklower 				printf("m_compress copying len %d\n", len);
327*36387Ssklower 			ENDDEBUG
328*36387Ssklower 			bcopy(mtod(in, caddr_t), mtod((*out), caddr_t) + (*out)->m_len, len);
329*36387Ssklower 
330*36387Ssklower 			(*out)->m_len += len;
331*36387Ssklower 			in->m_len -= len;
332*36387Ssklower 			continue;
333*36387Ssklower 		} else {
334*36387Ssklower 			/* (*out) is full */
335*36387Ssklower 			if(( (*out)->m_next = m_get(M_DONTWAIT, MT_DATA) ) == MNULL) {
336*36387Ssklower 				m_freem(*out);
337*36387Ssklower 				*out = in;
338*36387Ssklower 				IFDEBUG(D_REQUEST)
339*36387Ssklower 					printf("m_compress returning -1: B\n");
340*36387Ssklower 				ENDDEBUG
341*36387Ssklower 				splx(s);
342*36387Ssklower 				return -1;
343*36387Ssklower 			}
344*36387Ssklower 			(*out)->m_len = 0;
345*36387Ssklower 			(*out)->m_act = MNULL;
346*36387Ssklower 			*out = (*out)->m_next;
347*36387Ssklower 		}
348*36387Ssklower 	}
349*36387Ssklower 	m_freem(in);
350*36387Ssklower 	IFDEBUG(D_REQUEST)
351*36387Ssklower 		printf("m_compress returning 0x%x: A\n", datalen);
352*36387Ssklower 	ENDDEBUG
353*36387Ssklower 	splx(s);
354*36387Ssklower 	return datalen;
355*36387Ssklower }
356