add _SSIZE_T_
[unix-history] / usr / src / sys / netiso / clnp_subr.c
CommitLineData
7bcd1bb8
KB
1/*-
2 * Copyright (c) 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 *
7 * @(#)clnp_subr.c 7.13 (Berkeley) %G%
8 */
9
e832ea14
KS
10/***********************************************************
11 Copyright IBM Corporation 1987
12
13 All Rights Reserved
14
15Permission to use, copy, modify, and distribute this software and its
16documentation for any purpose and without fee is hereby granted,
17provided that the above copyright notice appear in all copies and that
18both that copyright notice and this permission notice appear in
19supporting documentation, and that the name of IBM not be
20used in advertising or publicity pertaining to distribution of the
21software without specific, written prior permission.
22
23IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
29SOFTWARE.
30
31******************************************************************/
32
33/*
34 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
35 */
ede75751
KS
36/* $Header: /var/src/sys/netiso/RCS/clnp_subr.c,v 5.1 89/02/09 16:20:46 hagens Exp $ */
37/* $Source: /var/src/sys/netiso/RCS/clnp_subr.c,v $ */
e832ea14
KS
38
39#ifdef ISO
40
a50e2bc0
KS
41#include "types.h"
42#include "param.h"
43#include "mbuf.h"
44#include "domain.h"
45#include "protosw.h"
46#include "socket.h"
47#include "socketvar.h"
48#include "errno.h"
49#include "time.h"
e832ea14
KS
50
51#include "../net/if.h"
52#include "../net/route.h"
d910a5d6 53#include "../net/if_dl.h"
e832ea14 54
a50e2bc0
KS
55#include "iso.h"
56#include "iso_var.h"
57#include "iso_pcb.h"
58#include "iso_snpac.h"
59#include "clnp.h"
60#include "clnp_stat.h"
61#include "argo_debug.h"
e832ea14
KS
62
63/*
64 * FUNCTION: clnp_data_ck
65 *
66 * PURPOSE: Check that the amount of data in the mbuf chain is
67 * at least as much as the clnp header would have us
68 * expect. Trim mbufs if longer than expected, drop
69 * packet if shorter than expected.
70 *
71 * RETURNS: success - ptr to mbuf chain
72 * failure - 0
73 *
74 * SIDE EFFECTS:
75 *
76 * NOTES:
77 */
78struct mbuf *
79clnp_data_ck(m, length)
80register struct mbuf *m; /* ptr to mbuf chain containing hdr & data */
81int length; /* length (in bytes) of packet */
82 {
83 register int len; /* length of data */
84 register struct mbuf *mhead; /* ptr to head of chain */
85
86 len = -length;
87 mhead = m;
88 for (;;) {
89 len += m->m_len;
90 if (m->m_next == 0)
91 break;
92 m = m->m_next;
93 }
94 if (len != 0) {
95 if (len < 0) {
96 INCSTAT(cns_toosmall);
97 clnp_discard(mhead, GEN_INCOMPLETE);
98 return 0;
99 }
100 if (len <= m->m_len)
101 m->m_len -= len;
102 else
103 m_adj(mhead, -len);
104 }
105 return mhead;
106}
107
f943ee68 108#ifdef notdef
e832ea14
KS
109/*
110 * FUNCTION: clnp_extract_addr
111 *
112 * PURPOSE: Extract the source and destination address from the
113 * supplied buffer. Place them in the supplied address buffers.
114 * If insufficient data is supplied, then fail.
115 *
116 * RETURNS: success - Address of first byte in the packet past
117 * the address part.
118 * failure - 0
119 *
120 * SIDE EFFECTS:
121 *
122 * NOTES:
123 */
124caddr_t
125clnp_extract_addr(bufp, buflen, srcp, destp)
126caddr_t bufp; /* ptr to buffer containing addresses */
127int buflen; /* length of buffer */
128register struct iso_addr *srcp; /* ptr to source address buffer */
129register struct iso_addr *destp; /* ptr to destination address buffer */
130 {
131 int len; /* argument to bcopy */
132
133 /*
134 * check that we have enough data. Plus1 is for length octet
135 */
136 if ((u_char)*bufp + 1 > buflen) {
137 return((caddr_t)0);
138 }
139 len = destp->isoa_len = (u_char)*bufp++;
140 (void) bcopy(bufp, (caddr_t)destp, len);
141 buflen -= len;
142 bufp += len;
143
144 /*
145 * check that we have enough data. Plus1 is for length octet
146 */
147 if ((u_char)*bufp + 1 > buflen) {
148 return((caddr_t)0);
149 }
150 len = srcp->isoa_len = (u_char)* bufp++;
151 (void) bcopy(bufp, (caddr_t)srcp, len);
152 bufp += len;
153
154 /*
155 * Insure that the addresses make sense
156 */
157 if (iso_ck_addr(srcp) && iso_ck_addr(destp))
158 return bufp;
159 else
160 return (caddr_t) 0;
161}
f943ee68 162#endif notdef
e832ea14
KS
163
164/*
165 * FUNCTION: clnp_ours
166 *
167 * PURPOSE: Decide whether the supplied packet is destined for
168 * us, or that it should be forwarded on.
169 *
170 * RETURNS: packet is for us - 1
171 * packet is not for us - 0
172 *
173 * SIDE EFFECTS:
174 *
175 * NOTES:
176 */
177clnp_ours(dst)
178register struct iso_addr *dst; /* ptr to destination address */
179{
180 register struct iso_ifaddr *ia; /* scan through interface addresses */
181
182 for (ia = iso_ifaddr; ia; ia = ia->ia_next) {
183 IFDEBUG(D_ROUTE)
128a1a78 184 printf("clnp_ours: ia_sis x%x, dst x%x\n", &ia->ia_addr,
e832ea14
KS
185 dst);
186 ENDDEBUG
128a1a78
KS
187 /*
188 * XXX Warning:
189 * We are overloading siso_tlen in the if's address, as an nsel length.
190 */
c2bb180a 191 if (dst->isoa_len == ia->ia_addr.siso_nlen &&
128a1a78 192 bcmp((caddr_t)ia->ia_addr.siso_addr.isoa_genaddr,
c2bb180a
KS
193 (caddr_t)dst->isoa_genaddr,
194 ia->ia_addr.siso_nlen - ia->ia_addr.siso_tlen) == 0)
128a1a78 195 return 1;
e832ea14
KS
196 }
197 return 0;
198}
199
ede75751
KS
200/* Dec bit set if ifp qlen is greater than congest_threshold */
201int congest_threshold = 0;
202
e832ea14
KS
203/*
204 * FUNCTION: clnp_forward
205 *
206 * PURPOSE: Forward the datagram passed
207 * clnpintr guarantees that the header will be
208 * contigious (a cluster mbuf will be used if necessary).
209 *
210 * If oidx is NULL, no options are present.
211 *
212 * RETURNS: nothing
213 *
214 * SIDE EFFECTS:
215 *
216 * NOTES:
217 */
218clnp_forward(m, len, dst, oidx, seg_off, inbound_shp)
219struct mbuf *m; /* pkt to forward */
220int len; /* length of pkt */
221struct iso_addr *dst; /* destination address */
222struct clnp_optidx *oidx; /* option index */
223int seg_off;/* offset of segmentation part */
224struct snpa_hdr *inbound_shp; /* subnetwork header of inbound packet */
225{
226 struct clnp_fixed *clnp; /* ptr to fixed part of header */
227 int error; /* return value of route function */
228 struct sockaddr *next_hop; /* next hop for dgram */
229 struct ifnet *ifp; /* ptr to outgoing interface */
a50e2bc0 230 struct iso_ifaddr *ia = 0;/* ptr to iso name for ifp */
fa350669 231 struct route_iso route; /* filled in by clnp_route */
e832ea14
KS
232 extern int iso_systype;
233
234 clnp = mtod(m, struct clnp_fixed *);
235 bzero((caddr_t)&route, sizeof(route)); /* MUST be done before "bad:" */
236
237 /*
238 * Don't forward multicast or broadcast packets
239 */
240 if ((inbound_shp) && (IS_MULTICAST(inbound_shp->snh_dhost))) {
241 IFDEBUG(D_FORWARD)
242 printf("clnp_forward: dropping multicast packet\n");
243 ENDDEBUG
a50e2bc0 244 clnp->cnf_type &= ~CNF_ERR_OK; /* so we don't generate an ER */
e832ea14 245 clnp_discard(m, 0);
a9a44513 246 INCSTAT(cns_cantforward);
e832ea14
KS
247 goto done;
248 }
249
250 IFDEBUG(D_FORWARD)
251 printf("clnp_forward: %d bytes, to %s, options x%x\n", len,
252 clnp_iso_addrp(dst), oidx);
253 ENDDEBUG
254
255 /*
256 * Decrement ttl, and if zero drop datagram
257 * Can't compare ttl as less than zero 'cause its a unsigned
258 */
259 if ((clnp->cnf_ttl == 0) || (--clnp->cnf_ttl == 0)) {
260 IFDEBUG(D_FORWARD)
261 printf("clnp_forward: discarding datagram because ttl is zero\n");
262 ENDDEBUG
263 INCSTAT(cns_ttlexpired);
264 clnp_discard(m, TTL_EXPTRANSIT);
265 goto done;
266 }
e832ea14
KS
267 /*
268 * Route packet; special case for source rt
269 */
270 if CLNPSRCRT_VALID(oidx) {
271 /*
272 * Update src route first
273 */
274 clnp_update_srcrt(m, oidx);
a50e2bc0 275 error = clnp_srcroute(m, oidx, &route, &next_hop, &ia, dst);
e832ea14 276 } else {
a50e2bc0 277 error = clnp_route(dst, &route, 0, &next_hop, &ia);
e832ea14 278 }
a50e2bc0 279 if (error || ia == 0) {
e832ea14
KS
280 IFDEBUG(D_FORWARD)
281 printf("clnp_forward: can't route packet (errno %d)\n", error);
282 ENDDEBUG
283 clnp_discard(m, ADDR_DESTUNREACH);
a9a44513 284 INCSTAT(cns_cantforward);
e832ea14
KS
285 goto done;
286 }
a50e2bc0 287 ifp = ia->ia_ifp;
e832ea14
KS
288
289 IFDEBUG(D_FORWARD)
290 printf("clnp_forward: packet routed to %s\n",
291 clnp_iso_addrp(&((struct sockaddr_iso *)next_hop)->siso_addr));
292 ENDDEBUG
293
294 INCSTAT(cns_forward);
295
296 /*
297 * If we are an intermediate system and
298 * we are routing outbound on the same ifp that the packet
299 * arrived upon, and we know the next hop snpa,
300 * then generate a redirect request
301 */
302 if ((iso_systype & SNPA_IS) && (inbound_shp) &&
c2bb180a
KS
303 (ifp == inbound_shp->snh_ifp))
304 esis_rdoutput(inbound_shp, m, oidx, dst, route.ro_rt);
e832ea14
KS
305 /*
306 * If options are present, update them
307 */
308 if (oidx) {
a50e2bc0 309 struct iso_addr *mysrc = &ia->ia_addr.siso_addr;
e832ea14
KS
310 if (mysrc == NULL) {
311 clnp_discard(m, ADDR_DESTUNREACH);
a9a44513
KS
312 INCSTAT(cns_cantforward);
313 clnp_stat.cns_forward--;
e832ea14
KS
314 goto done;
315 } else {
ede75751
KS
316 (void) clnp_dooptions(m, oidx, ifp, mysrc);
317 }
318 }
319
320#ifdef DECBIT
321 if (ifp->if_snd.ifq_len > congest_threshold) {
322 /*
323 * Congestion! Set the Dec Bit and thank Dave Oran
324 */
325 IFDEBUG(D_FORWARD)
326 printf("clnp_forward: congestion experienced\n");
327 ENDDEBUG
328 if ((oidx) && (oidx->cni_qos_formatp)) {
329 caddr_t qosp = CLNP_OFFTOOPT(m, oidx->cni_qos_formatp);
330 u_char qos = *qosp;
331 IFDEBUG(D_FORWARD)
332 printf("clnp_forward: setting congestion bit (qos x%x)\n", qos);
333 ENDDEBUG
334 if ((qos & CLNPOVAL_GLOBAL) == CLNPOVAL_GLOBAL) {
335 qos |= CLNPOVAL_CONGESTED;
336 INCSTAT(cns_congest_set);
337 *qosp = qos;
338 }
e832ea14
KS
339 }
340 }
ede75751 341#endif DECBIT
e832ea14
KS
342
343 /*
344 * Dispatch the datagram if it is small enough, otherwise fragment
345 */
f943ee68 346 if (len <= SN_MTU(ifp, route.ro_rt)) {
e832ea14 347 iso_gen_csum(m, CLNP_CKSUM_OFF, (int)clnp->cnf_hdr_len);
a544c9af 348 (void) (*ifp->if_output)(ifp, m, next_hop, route.ro_rt);
e832ea14 349 } else {
a544c9af 350 (void) clnp_fragment(ifp, m, next_hop, len, seg_off, /* flags */0, route.ro_rt);
e832ea14
KS
351 }
352
353done:
354 /*
355 * Free route
356 */
357 if (route.ro_rt != NULL) {
358 RTFREE(route.ro_rt);
359 }
360}
361
f943ee68 362#ifdef notdef
e832ea14
KS
363/*
364 * FUNCTION: clnp_insert_addr
365 *
366 * PURPOSE: Insert the address part into a clnp datagram.
367 *
368 * RETURNS: Address of first byte after address part in datagram.
369 *
370 * SIDE EFFECTS:
371 *
372 * NOTES: Assume that there is enough space for the address part.
373 */
374caddr_t
375clnp_insert_addr(bufp, srcp, dstp)
376caddr_t bufp; /* address of where addr part goes */
377register struct iso_addr *srcp; /* ptr to src addr */
378register struct iso_addr *dstp; /* ptr to dst addr */
379{
380 *bufp++ = dstp->isoa_len;
381 (void) bcopy((caddr_t)dstp, bufp, dstp->isoa_len);
382 bufp += dstp->isoa_len;
383
384 *bufp++ = srcp->isoa_len;
385 (void) bcopy((caddr_t)srcp, bufp, srcp->isoa_len);
386 bufp += srcp->isoa_len;
387
388 return bufp;
389}
390
f943ee68 391#endif notdef
e832ea14
KS
392
393/*
394 * FUNCTION: clnp_route
395 *
396 * PURPOSE: Route a clnp datagram to the first hop toward its
397 * destination. In many cases, the first hop will be
398 * the destination. The address of a route
399 * is specified. If a routing entry is present in
400 * that route, and it is still up to the same destination,
401 * then no further action is necessary. Otherwise, a
402 * new routing entry will be allocated.
403 *
404 * RETURNS: route found - 0
405 * unix error code
406 *
407 * SIDE EFFECTS:
408 *
409 * NOTES: It is up to the caller to free the routing entry
410 * allocated in route.
411 */
a50e2bc0
KS
412clnp_route(dst, ro, flags, first_hop, ifa)
413 struct iso_addr *dst; /* ptr to datagram destination */
414 register struct route_iso *ro; /* existing route structure */
415 int flags; /* flags for routing */
416 struct sockaddr **first_hop; /* result: fill in with ptr to firsthop */
417 struct iso_ifaddr **ifa; /* result: fill in with ptr to interface */
e832ea14 418{
a50e2bc0 419 if (flags & SO_DONTROUTE) {
a50e2bc0
KS
420 struct iso_ifaddr *ia;
421
8f7b4417
KS
422 if (ro->ro_rt) {
423 RTFREE(ro->ro_rt);
424 ro->ro_rt = 0;
425 }
426 bzero((caddr_t)&ro->ro_dst, sizeof(ro->ro_dst));
427 bcopy((caddr_t)dst, (caddr_t)&ro->ro_dst.siso_addr,
a50e2bc0 428 1 + (unsigned)dst->isoa_len);
8f7b4417
KS
429 ro->ro_dst.siso_family = AF_ISO;
430 ro->ro_dst.siso_len = sizeof(ro->ro_dst);
431 ia = iso_localifa(&ro->ro_dst);
a50e2bc0
KS
432 if (ia == 0)
433 return EADDRNOTAVAIL;
434 if (ifa)
8f7b4417
KS
435 *ifa = ia;
436 if (first_hop)
437 *first_hop = (struct sockaddr *)&ro->ro_dst;
a50e2bc0
KS
438 return 0;
439 }
e832ea14
KS
440 /*
441 * If there is a cached route, check that it is still up and to
442 * the same destination. If not, free it and try again.
443 */
444 if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
a50e2bc0 445 (Bcmp(ro->ro_dst.siso_data, dst->isoa_genaddr, dst->isoa_len)))) {
e832ea14
KS
446 IFDEBUG(D_ROUTE)
447 printf("clnp_route: freeing old route: ro->ro_rt 0x%x\n",
448 ro->ro_rt);
449 printf("clnp_route: old route refcnt: 0x%x\n",
450 ro->ro_rt->rt_refcnt);
451 ENDDEBUG
452
453 /* free old route entry */
454 RTFREE(ro->ro_rt);
455 ro->ro_rt = (struct rtentry *)0;
456 } else {
457 IFDEBUG(D_ROUTE)
458 printf("clnp_route: OK route exists\n");
459 ENDDEBUG
460 }
461
462 if (ro->ro_rt == 0) {
463 /* set up new route structure */
a50e2bc0
KS
464 bzero((caddr_t)&ro->ro_dst, sizeof(ro->ro_dst));
465 ro->ro_dst.siso_len = sizeof(ro->ro_dst);
466 ro->ro_dst.siso_family = AF_ISO;
467 Bcopy(dst, &ro->ro_dst.siso_addr, 1 + dst->isoa_len);
e832ea14
KS
468 /* allocate new route */
469 IFDEBUG(D_ROUTE)
470 printf("clnp_route: allocating new route to %s\n",
471 clnp_iso_addrp(dst));
472 ENDDEBUG
a50e2bc0 473 rtalloc((struct route *)ro);
e832ea14 474 }
a50e2bc0 475 if (ro->ro_rt == 0)
e832ea14 476 return(ENETUNREACH); /* rtalloc failed */
e832ea14 477 ro->ro_rt->rt_use++;
a50e2bc0
KS
478 if (ifa)
479 if ((*ifa = (struct iso_ifaddr *)ro->ro_rt->rt_ifa) == 0)
480 panic("clnp_route");
481 if (first_hop) {
a544c9af 482 if (ro->ro_rt->rt_flags & RTF_GATEWAY)
a50e2bc0
KS
483 *first_hop = ro->ro_rt->rt_gateway;
484 else
485 *first_hop = (struct sockaddr *)&ro->ro_dst;
486 }
e832ea14
KS
487 return(0);
488}
489
490/*
491 * FUNCTION: clnp_srcroute
492 *
493 * PURPOSE: Source route the datagram. If complete source
494 * routing is specified but not possible, then
495 * return an error. If src routing is terminated, then
496 * try routing on destination.
497 * Usage of first_hop,
498 * ifp, and error return is identical to clnp_route.
499 *
500 * RETURNS: 0 or unix error code
501 *
502 * SIDE EFFECTS:
503 *
504 * NOTES: Remember that option index pointers are really
505 * offsets from the beginning of the mbuf.
506 */
c2bb180a 507clnp_srcroute(options, oidx, ro, first_hop, ifa, final_dst)
e832ea14
KS
508struct mbuf *options; /* ptr to options */
509struct clnp_optidx *oidx; /* index to options */
c2bb180a 510struct route_iso *ro; /* route structure */
e832ea14 511struct sockaddr **first_hop; /* RETURN: fill in with ptr to firsthop */
a50e2bc0 512struct iso_ifaddr **ifa; /* RETURN: fill in with ptr to interface */
e832ea14
KS
513struct iso_addr *final_dst; /* final destination */
514{
515 struct iso_addr dst; /* first hop specified by src rt */
516 int error = 0; /* return code */
517
518 /*
519 * Check if we have run out of routes
520 * If so, then try to route on destination.
521 */
522 if CLNPSRCRT_TERM(oidx, options) {
523 dst.isoa_len = final_dst->isoa_len;
a50e2bc0 524 bcopy(final_dst->isoa_genaddr, dst.isoa_genaddr, dst.isoa_len);
e832ea14
KS
525 } else {
526 /*
527 * setup dst based on src rt specified
528 */
529 dst.isoa_len = CLNPSRCRT_CLEN(oidx, options);
a50e2bc0 530 bcopy(CLNPSRCRT_CADDR(oidx, options), dst.isoa_genaddr, dst.isoa_len);
e832ea14
KS
531 }
532
533 /*
534 * try to route it
535 */
c2bb180a 536 error = clnp_route(&dst, ro, 0, first_hop, ifa);
e832ea14
KS
537 if (error != 0)
538 return error;
539
540 /*
541 * If complete src rt, first hop must be equal to dst
542 */
543 if ((CLNPSRCRT_TYPE(oidx, options) == CLNPOVAL_COMPRT) &&
544 (!iso_addrmatch1(&(*(struct sockaddr_iso **)first_hop)->siso_addr,&dst))){
545 IFDEBUG(D_OPTIONS)
546 printf("clnp_srcroute: complete src route failed\n");
547 ENDDEBUG
548 return EHOSTUNREACH; /* RAH? would like ESRCRTFAILED */
549 }
550
551 return error;
552}
553
f943ee68
KS
554/*
555 * FUNCTION: clnp_badmtu
556 *
557 * PURPOSE: print notice of route with mtu not initialized.
558 *
559 * RETURNS: mtu of ifp.
560 *
561 * SIDE EFFECTS: prints notice, slows down system.
562 */
563clnp_badmtu(ifp, rt, line, file)
564struct ifnet *ifp; /* outgoing interface */
565struct rtentry *rt; /* dst route */
566int line; /* where the dirty deed occured */
567char *file; /* where the dirty deed occured */
568{
569 printf("sending on route %x with no mtu, line %s of file %s\n",
570 rt, line, file);
571#ifdef ARGO_DEBUG
572 printf("route dst is");
573 dump_isoaddr(rt_key(rt));
574#endif
575 return ifp->if_mtu;
576}
577
e832ea14
KS
578/*
579 * FUNCTION: clnp_ypocb - backwards bcopy
580 *
581 * PURPOSE: bcopy starting at end of src rather than beginning.
582 *
583 * RETURNS: none
584 *
585 * SIDE EFFECTS:
586 *
587 * NOTES: No attempt has been made to make this efficient
588 */
589clnp_ypocb(from, to, len)
590caddr_t from; /* src buffer */
591caddr_t to; /* dst buffer */
592u_int len; /* number of bytes */
593{
594 while (len--)
595 *(to + len) = *(from + len);
596}
e832ea14 597#endif ISO