wisconsin fixes
[unix-history] / usr / src / sys / netiso / clnp_input.c
CommitLineData
3652553f
KS
1/***********************************************************
2 Copyright IBM Corporation 1987
3
4 All Rights Reserved
5
6Permission to use, copy, modify, and distribute this software and its
7documentation for any purpose and without fee is hereby granted,
8provided that the above copyright notice appear in all copies and that
9both that copyright notice and this permission notice appear in
10supporting documentation, and that the name of IBM not be
11used in advertising or publicity pertaining to distribution of the
12software without specific, written prior permission.
13
14IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20SOFTWARE.
21
22******************************************************************/
23
24/*
25 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
26 */
27/* $Header: clnp_input.c,v 4.4 88/09/08 08:38:15 hagens Exp $ */
28/* $Source: /usr/argo/sys/netiso/RCS/clnp_input.c,v $ */
29
30#ifndef lint
31static char *rcsid = "$Header: clnp_input.c,v 4.4 88/09/08 08:38:15 hagens Exp $";
32#endif lint
33
34#include "../h/types.h"
35#include "../h/param.h"
36#include "../h/mbuf.h"
37#include "../h/domain.h"
38#include "../h/protosw.h"
39#include "../h/socket.h"
40#include "../h/socketvar.h"
41#include "../h/errno.h"
42#include "../h/time.h"
43
44#include "../net/if.h"
45#include "../net/route.h"
46
47#include "../netiso/iso.h"
48#include "../netiso/iso_var.h"
49#include "../netiso/iso_snpac.h"
50#include "../netiso/clnp.h"
51#include "../netiso/clnl.h"
52#include "../netiso/esis.h"
53#include "../netiso/clnp_stat.h"
54#include "../netiso/argo_debug.h"
55
56#ifdef ISO
57u_char clnp_protox[ISOPROTO_MAX];
58struct clnl_protosw clnl_protox[256];
59int clnpqmaxlen = IFQ_MAXLEN; /* RAH? why is this a variable */
60struct mbuf *clnp_data_ck();
61
62int clnp_input();
63
64int esis_input();
65
66#ifdef ISO_X25ESIS
67int x25esis_input();
68#endif ISO_X25ESIS
69
70/*
71 * FUNCTION: clnp_init
72 *
73 * PURPOSE: clnp initialization. Fill in clnp switch tables.
74 *
75 * RETURNS: none
76 *
77 * SIDE EFFECTS: fills in clnp_protox table with correct offsets into
78 * the isosw table.
79 *
80 * NOTES:
81 */
82clnp_init()
83{
84 register struct protosw *pr;
85
86 /*
87 * CLNP protox initialization
88 */
89 if ((pr = pffindproto(PF_ISO, ISOPROTO_RAW, SOCK_RAW)) == 0)
90 printf("clnl_init: no raw CLNP\n");
91 else
92 clnp_protox[ISOPROTO_RAW] = pr - isosw;
93
94 if ((pr = pffindproto(PF_ISO, ISOPROTO_TP, SOCK_SEQPACKET)) == 0)
95 printf("clnl_init: no tp/clnp\n");
96 else
97 clnp_protox[ISOPROTO_TP] = pr - isosw;
98
99 /*
100 * CLNL protox initialization
101 */
102 clnl_protox[ISO8473_CLNP].clnl_input = clnp_input;
103
104 clnlintrq.ifq_maxlen = clnpqmaxlen;
105}
106
107/*
108 * FUNCTION: clnlintr
109 *
110 * PURPOSE: Process a packet on the clnl input queue
111 *
112 * RETURNS: nothing.
113 *
114 * SIDE EFFECTS:
115 *
116 * NOTES:
117 */
118clnlintr()
119{
120 register struct mbuf *m; /* ptr to first mbuf of pkt */
121 register struct clnl_fixed *clnl; /* ptr to fixed part of clnl hdr */
122 struct ifnet *ifp; /* ptr to interface pkt arrived on */
123 int s; /* save and restore priority */
124 struct clnl_protosw *clnlsw;/* ptr to protocol switch */
125 struct snpa_hdr sh; /* subnetwork hdr */
126
127 /*
128 * Get next datagram off clnl input queue
129 */
130next:
131 s = splimp();
132
133 IF_DEQUEUESNPAHDR(&clnlintrq, m, sh);
134
135 IFDEBUG(D_INPUT)
136 int i;
137 printf("clnlintr: src:");
138 for (i=0; i<6; i++)
139 printf("%x%c", sh.snh_shost[i] & 0xff, (i<5) ? ':' : ' ');
140 printf(" dst:");
141 for (i=0; i<6; i++)
142 printf("%x%c", sh.snh_dhost[i] & 0xff, (i<5) ? ':' : ' ');
143 printf("\n");
144 ENDDEBUG
145
146 splx(s);
147 if (m == 0) /* nothing to do */
148 return;
149
150 /*
151 * Get the fixed part of the clnl header into the first mbuf.
152 * Drop the packet if this fails.
153 * Do not call m_pullup if we have a cluster mbuf or the
154 * data is not there.
155 */
156 if ((IS_CLUSTER(m) || (m->m_len < sizeof(struct clnl_fixed))) &&
157 ((m = m_pullup(m, sizeof(struct clnl_fixed))) == 0)) {
158 INCSTAT(cns_toosmall); /* TODO: use clnl stats */
159 goto next; /* m_pullup discards mbuf */
160 }
161
162 clnl = mtod(m, struct clnl_fixed *);
163
164 /*
165 * Drop packet if the length of the header is not reasonable.
166 */
167 if ((clnl->cnf_hdr_len < CLNP_HDR_MIN) ||
168 (clnl->cnf_hdr_len > CLNP_HDR_MAX)) {
169 INCSTAT(cns_badhlen); /* TODO: use clnl stats */
170 m_freem(m);
171 goto next;
172 }
173
174 /*
175 * If the header is not contained in this mbuf, make it so.
176 * Drop packet if this fails.
177 * Note: m_pullup will allocate a cluster mbuf if necessary
178 */
179 if (clnl->cnf_hdr_len > m->m_len) {
180 if ((m = m_pullup(m, clnl->cnf_hdr_len)) == 0) {
181 INCSTAT(cns_badhlen); /* TODO: use clnl stats */
182 goto next; /* m_pullup discards mbuf */
183 }
184 clnl = mtod(m, struct clnl_fixed *);
185 }
186
187 clnlsw = &clnl_protox[clnl->cnf_proto_id];
188
189
190 if (clnlsw->clnl_input)
191 (*clnlsw->clnl_input) (m, &sh);
192 else
193 m_freem(m);
194
195 goto next;
196}
197
198/*
199 * FUNCTION: clnp_input
200 *
201 * PURPOSE: process an incoming clnp packet
202 *
203 * RETURNS: nothing
204 *
205 * SIDE EFFECTS: increments fields of clnp_stat structure.
206 *
207 * NOTES:
208 * TODO: I would like to make seg_part a pointer into the mbuf, but
209 * will it be correctly aligned?
210 */
211int clnp_input(m, shp)
212struct mbuf *m; /* ptr to first mbuf of pkt */
213struct snpa_hdr *shp; /* subnetwork header */
214{
215 register struct clnp_fixed *clnp; /* ptr to fixed part of header */
216 struct iso_addr src; /* source address of pkt */
217 struct iso_addr dst; /* destination address of pkt */
218 caddr_t hoff; /* current offset in packet */
219 caddr_t hend; /* address of end of header info */
220 struct clnp_segment seg_part; /* segment part of hdr */
221 int seg_off=0; /* offset of segment part of hdr */
222 int seg_len;/* length of packet data&hdr in bytes */
223 struct clnp_optidx oidx, *oidxp = NULL; /* option index */
224 extern int iso_systype; /* used by ESIS config resp */
225
226 IFDEBUG(D_INPUT)
227 printf(
228 "clnp_input: proccessing dg; First mbuf m_len %d, m_type x%x, data:\n",
229 m->m_len, m->m_type);
230 ENDDEBUG
231 IFDEBUG(D_DUMPIN)
232 printf("clnp_input: first mbuf:\n");
233 dump_buf(mtod(m, caddr_t), m->m_len);
234 ENDDEBUG
235
236 /*
237 * If no iso addresses have been set, there is nothing
238 * to do with the packet.
239 */
240 if (iso_ifaddr == NULL) {
241 clnp_discard(m, ADDR_DESTUNREACH);
242 return;
243 }
244
245 INCSTAT(cns_total);
246 clnp = mtod(m, struct clnp_fixed *);
247
248 /*
249 * Compute checksum (if necessary) and drop packet if
250 * checksum does not match
251 */
252 if (CKSUM_REQUIRED(clnp) && iso_check_csum(m, clnp->cnf_hdr_len)) {
253 INCSTAT(cns_badcsum);
254 clnp_discard(m, GEN_BADCSUM);
255 return;
256 }
257
258 if (clnp->cnf_vers != ISO8473_V1) {
259 INCSTAT(cns_badvers);
260 clnp_discard(m, DISC_UNSUPPVERS);
261 return;
262 }
263
264
265 /* check mbuf data length: clnp_data_ck will free mbuf upon error */
266 CTOH(clnp->cnf_seglen_msb, clnp->cnf_seglen_lsb, seg_len);
267 if ((m = clnp_data_ck(m, seg_len)) == 0)
268 return;
269
270 clnp = mtod(m, struct clnp_fixed *);
271 hend = (caddr_t)clnp + clnp->cnf_hdr_len;
272
273 /*
274 * extract the source and destination address
275 * drop packet on failure
276 */
277 bzero((caddr_t)&src, sizeof(src));
278 bzero((caddr_t)&dst, sizeof(dst));
279
280 hoff = (caddr_t)clnp + sizeof(struct clnp_fixed);
281 CLNP_EXTRACT_ADDR(dst, hoff, hend);
282 if (hoff == (caddr_t)0) {
283 INCSTAT(cns_badaddr);
284 clnp_discard(m, GEN_INCOMPLETE);
285 return;
286 }
287 CLNP_EXTRACT_ADDR(src, hoff, hend);
288 if (hoff == (caddr_t)0) {
289 INCSTAT(cns_badaddr);
290 clnp_discard(m, GEN_INCOMPLETE);
291 return;
292 }
293
294 IFDEBUG(D_INPUT)
295 printf("clnp_input: from %s", clnp_iso_addrp(&src));
296 printf(" to %s\n", clnp_iso_addrp(&dst));
297 ENDDEBUG
298
299 /*
300 * extract the segmentation information, if it is present.
301 * drop packet on failure
302 */
303 if ((clnp->cnf_type != CLNP_ER) && (clnp->cnf_seg_ok)) {
304 if (hoff + sizeof(struct clnp_segment) > hend) {
305 INCSTAT(cns_noseg);
306 clnp_discard(m, GEN_INCOMPLETE);
307 return;
308 } else {
309 (void) bcopy(hoff, (caddr_t)&seg_part, sizeof(struct clnp_segment));
310 /* make sure segmentation fields are in host order */
311 seg_part.cng_id = ntohs(seg_part.cng_id);
312 seg_part.cng_off = ntohs(seg_part.cng_off);
313 seg_part.cng_tot_len = ntohs(seg_part.cng_tot_len);
314 seg_off = hoff - (caddr_t)clnp;
315 hoff += sizeof(struct clnp_segment);
316 }
317 }
318
319 /*
320 * process options if present. If clnp_opt_sanity returns
321 * false (indicating an error was found in the options) or
322 * an unsupported option was found
323 * then drop packet and emit an ER.
324 */
325 if (hoff < hend) {
326 int errcode;
327
328 oidxp = &oidx;
329 errcode = clnp_opt_sanity(m, hoff, hend-hoff, oidxp);
330
331 /* we do not support security */
332 if ((errcode == 0) && (oidxp->cni_securep))
333 errcode = DISC_UNSUPPSECURE;
334
335 /* the er option is valid with ER pdus only */
336 if ((errcode == 0) && (oidxp->cni_er_reason != ER_INVALREAS) &&
337 (clnp->cnf_type != CLNP_ER))
338 errcode = DISC_UNSUPPOPT;
339
340 if (errcode != 0) {
341 clnp_discard(m, (char)errcode);
342 IFDEBUG(D_INPUT)
343 printf("clnp_input: dropped (err x%x) due to bad options\n",
344 errcode);
345 ENDDEBUG
346 return;
347 }
348 }
349
350 /*
351 * check if this packet is for us. if not, then forward
352 */
353 if (clnp_ours(&dst) == 0) {
354 IFDEBUG(D_INPUT)
355 printf("clnp_input: forwarding packet not for us\n");
356 ENDDEBUG
357 clnp_forward(m, seg_len, &dst, oidxp, seg_off, shp);
358 return;
359 }
360
361 /*
362 * ESIS Configuration Response Function
363 *
364 * If the packet received was sent to the multicast address
365 * all end systems, then send an esh to the source
366 */
367 if ((IS_MULTICAST(shp->snh_dhost)) && (iso_systype == SNPA_ES)) {
368 extern short esis_holding_time;
369
370 esis_shoutput(shp->snh_ifp, ESIS_ESH, esis_holding_time,
371 shp->snh_shost, 6);
372 }
373
374 /*
375 * If this is a fragment, then try to reassemble it. If clnp_reass
376 * returns non NULL, the packet has been reassembled, and should
377 * be give to TP. Otherwise the fragment has been delt with
378 * by the reassembly code (either stored or deleted). In either case
379 * we should have nothing more to do with it.
380 */
381 if ((clnp->cnf_type != CLNP_ER) && (clnp->cnf_seg_ok) &&
382 (seg_len != seg_part.cng_tot_len)) {
383 struct mbuf *m0;
384
385 if ((m0 = clnp_reass(m, &src, &dst, &seg_part)) != NULL) {
386 m = m0;
387 clnp = mtod(m, struct clnp_fixed *);
388 } else {
389 return;
390 }
391 }
392
393 /*
394 * give the packet to the higher layer
395 * TODO: how do we tell TP that congestion bit is on in QOS option?
396 *
397 * Note: the total length of packet
398 * is the total length field of the segmentation part,
399 * or, if absent, the segment length field of the
400 * header.
401 */
402 switch (clnp->cnf_type) {
403 case CLNP_ER:
404 /*
405 * This ER must have the er option.
406 * If the option is not present, discard datagram.
407 */
408 if (oidxp == NULL || oidxp->cni_er_reason == ER_INVALREAS) {
409 clnp_discard(m, GEN_HDRSYNTAX);
410 } else {
411 clnp_er_input(m, &src, oidxp->cni_er_reason);
412 }
413 break;
414
415 case CLNP_DT:
416 (*isosw[clnp_protox[ISOPROTO_TP]].pr_input)(m, &src, &dst,
417 clnp->cnf_hdr_len);
418 break;
419
420 case CLNP_RAW:
421 case CLNP_ECR:
422 IFDEBUG(D_INPUT)
423 printf("clnp_input: raw input of %d bytes\n",
424 clnp->cnf_seg_ok ? seg_part.cng_tot_len : seg_len);
425 ENDDEBUG
426 (*isosw[clnp_protox[ISOPROTO_RAW]].pr_input)(m, &src, &dst,
427 clnp->cnf_hdr_len);
428 break;
429
430 case CLNP_EC:
431 IFDEBUG(D_INPUT)
432 printf("clnp_input: echoing packet\n");
433 ENDDEBUG
434 /*
435 * Switch the source and destination address,
436 */
437 hoff = (caddr_t)clnp + sizeof(struct clnp_fixed);
438 CLNP_INSERT_ADDR(hoff, &src);
439 CLNP_INSERT_ADDR(hoff, &dst);
440 clnp->cnf_type = CLNP_ECR;
441
442 /*
443 * Forward back to sender
444 */
445 clnp_forward(m, clnp->cnf_seg_ok ? seg_part.cng_tot_len : seg_len,
446 &src, oidxp, seg_off, shp);
447 break;
448
449 default:
450 printf("clnp_input: unknown clnp pkt type %d\n", clnp->cnf_type);
451 clnp_discard(m, GEN_HDRSYNTAX);
452 break;
453 }
454}
455
456int clnp_ctlinput()
457{
458}
459
460#endif ISO