149268Sbostic /*-
2*63222Sbostic * Copyright (c) 1991, 1993
3*63222Sbostic * The Regents of the University of California. All rights reserved.
449268Sbostic *
549268Sbostic * %sccs.include.redist.c%
649268Sbostic *
7*63222Sbostic * @(#)iso_chksum.c 8.1 (Berkeley) 06/10/93
849268Sbostic */
949268Sbostic
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
6056533Sbostic #include <netiso/argo_debug.h>
6156533Sbostic #include <sys/param.h>
6256533Sbostic #include <sys/systm.h>
6356533Sbostic #include <sys/mbuf.h>
6460359Sbostic #endif /* ISO */
6536387Ssklower
6636387Ssklower #ifndef MNULL
6736387Ssklower #define MNULL (struct mbuf *)0
6860359Sbostic #endif /* MNULL */
6936387Ssklower
7036387Ssklower /*
7136387Ssklower * FUNCTION: iso_check_csum
7236387Ssklower *
7336387Ssklower * PURPOSE: To check the checksum of the packet in the mbuf chain (m).
7436387Ssklower * The total length of the packet is (len).
7536387Ssklower * Called from tp_input() and clnp_intr()
7636387Ssklower *
7736387Ssklower * RETURNS: TRUE (something non-zero) if there is a checksum error,
7836387Ssklower * FALSE if there was NO checksum error.
7936387Ssklower *
8036387Ssklower * SIDE EFFECTS: none
8136387Ssklower *
8236387Ssklower * NOTES: It might be possible to gain something by optimizing
8336387Ssklower * this routine (unrolling loops, etc). But it is such
8436387Ssklower * a horrible thing to fiddle with anyway, it probably
8536387Ssklower * isn't worth it.
8636387Ssklower */
8736387Ssklower int
iso_check_csum(m,len)8836387Ssklower iso_check_csum(m, len)
8936387Ssklower struct mbuf *m;
9036387Ssklower int len;
9136387Ssklower {
9236387Ssklower register u_char *p = mtod(m, u_char *);
9336387Ssklower register u_long c0=0, c1=0;
9436387Ssklower register int i=0;
9536387Ssklower int cum = 0; /* cumulative length */
9636387Ssklower int l;
9736387Ssklower
9836387Ssklower l = len;
9956310Smckusick len = min(m->m_len, len);
10036387Ssklower i = 0;
10136387Ssklower
10236387Ssklower IFDEBUG(D_CHKSUM)
10336387Ssklower printf("iso_check_csum: m x%x, l x%x, m->m_len x%x\n", m, l, m->m_len);
10436387Ssklower ENDDEBUG
10536387Ssklower
10636387Ssklower while( i<l ) {
10736387Ssklower cum += len;
10836387Ssklower while (i<cum) {
10936387Ssklower c0 = c0 + *(p++);
11036387Ssklower c1 += c0;
11136387Ssklower i++;
11236387Ssklower }
11336387Ssklower if(i < l) {
11436387Ssklower m = m->m_next;
11536387Ssklower IFDEBUG(D_CHKSUM)
11636387Ssklower printf("iso_check_csum: new mbuf\n");
11736387Ssklower if(l-i < m->m_len)
11836387Ssklower printf(
11937469Ssklower "bad mbuf chain in check csum l 0x%x i 0x%x m_data 0x%x",
12037469Ssklower l,i,m->m_data);
12136387Ssklower ENDDEBUG
12236387Ssklower ASSERT( m != MNULL);
12356310Smckusick len = min( m->m_len, l-i);
12436387Ssklower p = mtod(m, u_char *);
12536387Ssklower }
12636387Ssklower }
12736387Ssklower if ( ((int)c0 % 255) || ((int)c1 % 255) ) {
12836387Ssklower IFDEBUG(D_CHKSUM)
12936387Ssklower printf("BAD iso_check_csum l 0x%x cum 0x%x len 0x%x, i 0x%x",
13036387Ssklower l, cum, len, i);
13136387Ssklower ENDDEBUG
13236387Ssklower return ((int)c0 % 255)<<8 | ((int)c1 % 255);
13336387Ssklower }
13436387Ssklower return 0;
13536387Ssklower }
13636387Ssklower
13736387Ssklower /*
13836387Ssklower * FUNCTION: iso_gen_csum
13936387Ssklower *
14036387Ssklower * PURPOSE: To generate the checksum of the packet in the mbuf chain (m).
14136387Ssklower * The first of the 2 (logically) adjacent checksum bytes
14236387Ssklower * (x and y) go at offset (n).
14336387Ssklower * (n) is an offset relative to the beginning of the data,
14436387Ssklower * not the beginning of the mbuf.
14536387Ssklower * (l) is the length of the total mbuf chain's data.
14636387Ssklower * Called from tp_emit(), tp_error_emit()
14736387Ssklower * clnp_emit_er(), clnp_forward(), clnp_output().
14836387Ssklower *
14936387Ssklower * RETURNS: Rien
15036387Ssklower *
15136387Ssklower * SIDE EFFECTS: Puts the 2 checksum bytes into the packet.
15236387Ssklower *
15336387Ssklower * NOTES: Ditto the note for iso_check_csum().
15436387Ssklower */
15536387Ssklower
15636387Ssklower void
iso_gen_csum(m,n,l)15736387Ssklower iso_gen_csum(m,n,l)
15836387Ssklower struct mbuf *m;
15936387Ssklower int n; /* offset of 2 checksum bytes */
16036387Ssklower int l;
16136387Ssklower {
16236387Ssklower register u_char *p = mtod(m, u_char *);
16336387Ssklower register int c0=0, c1=0;
16436387Ssklower register int i=0;
16536387Ssklower int loc = n++, len=0; /* n is position, loc is offset */
16636387Ssklower u_char *xloc;
16736387Ssklower u_char *yloc;
16836387Ssklower int cum=0; /* cum == cumulative length */
16936387Ssklower
17036387Ssklower IFDEBUG(D_CHKSUM)
17136387Ssklower printf("enter gen csum m 0x%x n 0x%x l 0x%x\n",m, n-1 ,l );
17236387Ssklower ENDDEBUG
17336387Ssklower
17436387Ssklower while(i < l) {
17556310Smckusick len = min(m->m_len, CLBYTES);
17636387Ssklower /* RAH: don't cksum more than l bytes */
17756310Smckusick len = min(len, l - i);
17836387Ssklower
17936387Ssklower cum +=len;
18036387Ssklower p = mtod(m, u_char *);
18136387Ssklower
18236387Ssklower if(loc>=0) {
18336387Ssklower if (loc < len) {
18437469Ssklower xloc = loc + mtod(m, u_char *);
18536387Ssklower IFDEBUG(D_CHKSUM)
18636387Ssklower printf("1: zeroing xloc 0x%x loc 0x%x\n",xloc, loc );
18736387Ssklower ENDDEBUG
18836387Ssklower *xloc = (u_char)0;
18936387Ssklower if (loc+1 < len) {
19036387Ssklower /* both xloc and yloc are in same mbuf */
19137469Ssklower yloc = 1 + xloc;
19236387Ssklower IFDEBUG(D_CHKSUM)
19336387Ssklower printf("2: zeroing yloc 0x%x loc 0x%x\n",yloc, loc );
19436387Ssklower ENDDEBUG
19536387Ssklower *yloc = (u_char)0;
19636387Ssklower } else {
19736387Ssklower /* crosses boundary of mbufs */
19837469Ssklower yloc = mtod(m->m_next, u_char *);
19936387Ssklower IFDEBUG(D_CHKSUM)
20036387Ssklower printf("3: zeroing yloc 0x%x \n",yloc );
20136387Ssklower ENDDEBUG
20236387Ssklower *yloc = (u_char)0;
20336387Ssklower }
20436387Ssklower }
20536387Ssklower loc -= len;
20636387Ssklower }
20736387Ssklower
20836387Ssklower while(i < cum) {
20936387Ssklower c0 = (c0 + *p);
21036387Ssklower c1 += c0 ;
21136387Ssklower i++;
21236387Ssklower p++;
21336387Ssklower }
21436387Ssklower m = m->m_next;
21536387Ssklower }
21636387Ssklower IFDEBUG(D_CHKSUM)
21736387Ssklower printf("gen csum final xloc 0x%x yloc 0x%x\n",xloc, yloc );
21836387Ssklower ENDDEBUG
21936387Ssklower
22036387Ssklower c1 = (((c0 * (l-n))-c1)%255) ;
22136387Ssklower *xloc = (u_char) ((c1 < 0)? c1+255 : c1);
22236387Ssklower
22336387Ssklower c1 = (-(int)(c1+c0))%255;
22436387Ssklower *yloc = (u_char) (c1 < 0? c1 + 255 : c1);
22536387Ssklower
22636387Ssklower IFDEBUG(D_CHKSUM)
22736387Ssklower printf("gen csum end \n");
22836387Ssklower ENDDEBUG
22936387Ssklower }
23036387Ssklower
23136387Ssklower /*
23236387Ssklower * FUNCTION: m_datalen
23336387Ssklower *
23436387Ssklower * PURPOSE: returns length of the mbuf chain.
23536387Ssklower * used all over the iso code.
23636387Ssklower *
23736387Ssklower * RETURNS: integer
23836387Ssklower *
23936387Ssklower * SIDE EFFECTS: none
24036387Ssklower *
24136387Ssklower * NOTES:
24236387Ssklower */
24336387Ssklower
24436387Ssklower int
m_datalen(m)24550900Ssklower m_datalen (m)
24650900Ssklower register struct mbuf *m;
24736387Ssklower {
24850900Ssklower register int datalen;
24936387Ssklower
25050900Ssklower for (datalen = 0; m; m = m->m_next)
25150900Ssklower datalen += m->m_len;
25236387Ssklower return datalen;
25336387Ssklower }
25436387Ssklower
25536387Ssklower int
m_compress(in,out)25636387Ssklower m_compress(in, out)
25736387Ssklower register struct mbuf *in, **out;
25836387Ssklower {
25936387Ssklower register int datalen = 0;
26036387Ssklower int s = splimp();
26136387Ssklower
26236387Ssklower if( in->m_next == MNULL ) {
26336387Ssklower *out = in;
26436387Ssklower IFDEBUG(D_REQUEST)
26536387Ssklower printf("m_compress returning 0x%x: A\n", in->m_len);
26636387Ssklower ENDDEBUG
26736387Ssklower splx(s);
26836387Ssklower return in->m_len;
26936387Ssklower }
27036387Ssklower MGET((*out), M_DONTWAIT, MT_DATA);
27136387Ssklower if((*out) == MNULL) {
27236387Ssklower *out = in;
27336387Ssklower IFDEBUG(D_REQUEST)
27436387Ssklower printf("m_compress returning -1: B\n");
27536387Ssklower ENDDEBUG
27636387Ssklower splx(s);
27736387Ssklower return -1;
27836387Ssklower }
27936387Ssklower (*out)->m_len = 0;
28036387Ssklower (*out)->m_act = MNULL;
28136387Ssklower
28236387Ssklower while (in) {
28336387Ssklower IFDEBUG(D_REQUEST)
28436387Ssklower printf("m_compress in 0x%x *out 0x%x\n", in, *out);
28537469Ssklower printf("m_compress in: len 0x%x, off 0x%x\n", in->m_len, in->m_data);
28636387Ssklower printf("m_compress *out: len 0x%x, off 0x%x\n", (*out)->m_len,
28737469Ssklower (*out)->m_data);
28836387Ssklower ENDDEBUG
28937469Ssklower if (in->m_flags & M_EXT) {
29036387Ssklower ASSERT(in->m_len == 0);
29136387Ssklower }
29236387Ssklower if ( in->m_len == 0) {
29336387Ssklower in = in->m_next;
29436387Ssklower continue;
29536387Ssklower }
29637469Ssklower if (((*out)->m_flags & M_EXT) == 0) {
29736387Ssklower int len;
29836387Ssklower
29937469Ssklower len = M_TRAILINGSPACE(*out);
30056310Smckusick len = min(len, in->m_len);
30136387Ssklower datalen += len;
30236387Ssklower
30336387Ssklower IFDEBUG(D_REQUEST)
30436387Ssklower printf("m_compress copying len %d\n", len);
30536387Ssklower ENDDEBUG
30637469Ssklower bcopy(mtod(in, caddr_t), mtod((*out), caddr_t) + (*out)->m_len,
30737469Ssklower (unsigned)len);
30836387Ssklower
30936387Ssklower (*out)->m_len += len;
31036387Ssklower in->m_len -= len;
31136387Ssklower continue;
31236387Ssklower } else {
31336387Ssklower /* (*out) is full */
31436387Ssklower if(( (*out)->m_next = m_get(M_DONTWAIT, MT_DATA) ) == MNULL) {
31536387Ssklower m_freem(*out);
31636387Ssklower *out = in;
31736387Ssklower IFDEBUG(D_REQUEST)
31836387Ssklower printf("m_compress returning -1: B\n");
31936387Ssklower ENDDEBUG
32036387Ssklower splx(s);
32136387Ssklower return -1;
32236387Ssklower }
32336387Ssklower (*out)->m_len = 0;
32436387Ssklower (*out)->m_act = MNULL;
32536387Ssklower *out = (*out)->m_next;
32636387Ssklower }
32736387Ssklower }
32836387Ssklower m_freem(in);
32936387Ssklower IFDEBUG(D_REQUEST)
33036387Ssklower printf("m_compress returning 0x%x: A\n", datalen);
33136387Ssklower ENDDEBUG
33236387Ssklower splx(s);
33336387Ssklower return datalen;
33436387Ssklower }
335