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