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