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