added my responsibility for the `cpm' port
[unix-history] / sys / netiso / iso_chksum.c
CommitLineData
15637ed4
RG
1/*-
2 * Copyright (c) 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
43371f85 33 * from: @(#)iso_chksum.c 7.5 (Berkeley) 5/6/91
fde1aeb2 34 * $Id: iso_chksum.c,v 1.4 1993/11/25 01:35:58 wollman Exp $
15637ed4
RG
35 */
36
37/***********************************************************
38 Copyright IBM Corporation 1987
39
40 All Rights Reserved
41
42Permission to use, copy, modify, and distribute this software and its
43documentation for any purpose and without fee is hereby granted,
44provided that the above copyright notice appear in all copies and that
45both that copyright notice and this permission notice appear in
46supporting documentation, and that the name of IBM not be
47used in advertising or publicity pertaining to distribution of the
48software without specific, written prior permission.
49
50IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
51ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
52IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
53ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
54WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
55ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
56SOFTWARE.
57
58******************************************************************/
59
60/*
61 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
62 */
43371f85 63
15637ed4 64/*
15637ed4
RG
65 * ISO CHECKSUM
66 *
67 * The checksum generation and check routines are here.
68 * The checksum is 2 bytes such that the sum of all the bytes b(i) == 0
69 * and the sum of i * b(i) == 0.
70 * The whole thing is complicated by the fact that the data are in mbuf
71 * chains.
72 * Furthermore, there is the possibility of wraparound in the running
73 * sums after adding up 4102 octets. In order to avoid doing a mod
74 * operation after EACH add, we have restricted this implementation to
75 * negotiating a maximum of 4096-octets per TPDU (for the transport layer).
76 * The routine iso_check_csum doesn't need to know where the checksum
77 * octets are.
78 * The routine iso_gen_csum takes a pointer to an mbuf chain (logically
79 * a chunk of data), an offset into the chunk at which the 2 octets are to
80 * be stuffed, and the length of the chunk. The 2 octets have to be
81 * logically adjacent, but may be physically located in separate mbufs.
82 */
83
84#ifdef ISO
85#include "argo_debug.h"
86#include "param.h"
5d3c1d60 87#include "systm.h"
15637ed4 88#include "mbuf.h"
fde1aeb2 89#endif /* ISO */
15637ed4
RG
90
91#ifndef MNULL
92#define MNULL (struct mbuf *)0
fde1aeb2 93#endif /* MNULL */
15637ed4
RG
94
95/*
96 * FUNCTION: iso_check_csum
97 *
98 * PURPOSE: To check the checksum of the packet in the mbuf chain (m).
99 * The total length of the packet is (len).
100 * Called from tp_input() and clnp_intr()
101 *
102 * RETURNS: TRUE (something non-zero) if there is a checksum error,
103 * FALSE if there was NO checksum error.
104 *
105 * SIDE EFFECTS: none
106 *
107 * NOTES: It might be possible to gain something by optimizing
108 * this routine (unrolling loops, etc). But it is such
109 * a horrible thing to fiddle with anyway, it probably
110 * isn't worth it.
111 */
112int
113iso_check_csum(m, len)
114 struct mbuf *m;
115 int len;
116{
117 register u_char *p = mtod(m, u_char *);
118 register u_long c0=0, c1=0;
119 register int i=0;
120 int cum = 0; /* cumulative length */
121 int l;
122
123 l = len;
124 len = MIN(m->m_len, len);
125 i = 0;
126
127 IFDEBUG(D_CHKSUM)
128 printf("iso_check_csum: m x%x, l x%x, m->m_len x%x\n", m, l, m->m_len);
129 ENDDEBUG
130
131 while( i<l ) {
132 cum += len;
133 while (i<cum) {
134 c0 = c0 + *(p++);
135 c1 += c0;
136 i++;
137 }
138 if(i < l) {
139 m = m->m_next;
140 IFDEBUG(D_CHKSUM)
141 printf("iso_check_csum: new mbuf\n");
142 if(l-i < m->m_len)
143 printf(
144 "bad mbuf chain in check csum l 0x%x i 0x%x m_data 0x%x",
145 l,i,m->m_data);
146 ENDDEBUG
147 ASSERT( m != MNULL);
148 len = MIN( m->m_len, l-i);
149 p = mtod(m, u_char *);
150 }
151 }
152 if ( ((int)c0 % 255) || ((int)c1 % 255) ) {
153 IFDEBUG(D_CHKSUM)
154 printf("BAD iso_check_csum l 0x%x cum 0x%x len 0x%x, i 0x%x",
155 l, cum, len, i);
156 ENDDEBUG
157 return ((int)c0 % 255)<<8 | ((int)c1 % 255);
158 }
159 return 0;
160}
161
162/*
163 * FUNCTION: iso_gen_csum
164 *
165 * PURPOSE: To generate the checksum of the packet in the mbuf chain (m).
166 * The first of the 2 (logically) adjacent checksum bytes
167 * (x and y) go at offset (n).
168 * (n) is an offset relative to the beginning of the data,
169 * not the beginning of the mbuf.
170 * (l) is the length of the total mbuf chain's data.
171 * Called from tp_emit(), tp_error_emit()
172 * clnp_emit_er(), clnp_forward(), clnp_output().
173 *
174 * RETURNS: Rien
175 *
176 * SIDE EFFECTS: Puts the 2 checksum bytes into the packet.
177 *
178 * NOTES: Ditto the note for iso_check_csum().
179 */
180
181void
182iso_gen_csum(m,n,l)
183 struct mbuf *m;
184 int n; /* offset of 2 checksum bytes */
185 int l;
186{
187 register u_char *p = mtod(m, u_char *);
188 register int c0=0, c1=0;
189 register int i=0;
190 int loc = n++, len=0; /* n is position, loc is offset */
4c45483e
GW
191 u_char *xloc = 0;
192 u_char *yloc = 0;
15637ed4
RG
193 int cum=0; /* cum == cumulative length */
194
195 IFDEBUG(D_CHKSUM)
196 printf("enter gen csum m 0x%x n 0x%x l 0x%x\n",m, n-1 ,l );
197 ENDDEBUG
198
199 while(i < l) {
200 len = MIN(m->m_len, CLBYTES);
201 /* RAH: don't cksum more than l bytes */
202 len = MIN(len, l - i);
203
204 cum +=len;
205 p = mtod(m, u_char *);
206
207 if(loc>=0) {
208 if (loc < len) {
209 xloc = loc + mtod(m, u_char *);
210 IFDEBUG(D_CHKSUM)
211 printf("1: zeroing xloc 0x%x loc 0x%x\n",xloc, loc );
212 ENDDEBUG
213 *xloc = (u_char)0;
214 if (loc+1 < len) {
215 /* both xloc and yloc are in same mbuf */
216 yloc = 1 + xloc;
217 IFDEBUG(D_CHKSUM)
218 printf("2: zeroing yloc 0x%x loc 0x%x\n",yloc, loc );
219 ENDDEBUG
220 *yloc = (u_char)0;
221 } else {
222 /* crosses boundary of mbufs */
223 yloc = mtod(m->m_next, u_char *);
224 IFDEBUG(D_CHKSUM)
225 printf("3: zeroing yloc 0x%x \n",yloc );
226 ENDDEBUG
227 *yloc = (u_char)0;
228 }
229 }
230 loc -= len;
231 }
232
233 while(i < cum) {
234 c0 = (c0 + *p);
235 c1 += c0 ;
236 i++;
237 p++;
238 }
239 m = m->m_next;
240 }
241 IFDEBUG(D_CHKSUM)
242 printf("gen csum final xloc 0x%x yloc 0x%x\n",xloc, yloc );
243 ENDDEBUG
244
245 c1 = (((c0 * (l-n))-c1)%255) ;
246 *xloc = (u_char) ((c1 < 0)? c1+255 : c1);
247
248 c1 = (-(int)(c1+c0))%255;
249 *yloc = (u_char) (c1 < 0? c1 + 255 : c1);
250
251 IFDEBUG(D_CHKSUM)
252 printf("gen csum end \n");
253 ENDDEBUG
254}
255