../machine => machine
[unix-history] / usr / src / sys / netiso / iso_snpac.c
CommitLineData
600d71da
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: iso_snpac.c,v 1.8 88/09/19 13:51:36 hagens Exp $ */
28/* $Source: /usr/argo/sys/netiso/RCS/iso_snpac.c,v $ */
29
30#ifndef lint
31static char *rcsid = "$Header: iso_snpac.c,v 1.8 88/09/19 13:51:36 hagens Exp $";
32#endif lint
33
34#ifdef ISO
35
a50e2bc0
KS
36#include "types.h"
37#include "param.h"
38#include "mbuf.h"
39#include "domain.h"
40#include "protosw.h"
41#include "socket.h"
42#include "socketvar.h"
43#include "errno.h"
44#include "ioctl.h"
45#include "time.h"
46#include "kernel.h"
600d71da
KS
47
48#include "../net/if.h"
49#include "../net/route.h"
50
a50e2bc0
KS
51#include "iso.h"
52#include "iso_var.h"
53#include "iso_snpac.h"
54#include "clnp.h"
55#include "clnp_stat.h"
56#include "argo_debug.h"
57#include "esis.h"
600d71da
KS
58
59#define SNPAC_BSIZ 20 /* bucket size */
60#define SNPAC_NB 13 /* number of buckets */
61#define SNPAC_SIZE (SNPAC_BSIZ * SNPAC_NB)
62struct snpa_cache iso_snpac[SNPAC_SIZE];
a50e2bc0 63u_int iso_snpac_size = SNPAC_SIZE;/* for iso_map command */
600d71da 64int iso_systype = SNPA_ES; /* default to be an ES */
a50e2bc0
KS
65
66struct sockaddr_iso blank_siso = {sizeof(blank_siso), AF_ISO};
67extern u_long iso_hashchar();
68static struct sockaddr_iso
69 dst = {sizeof(dst), AF_ISO},
70 gte = {sizeof(dst), AF_ISO},
71 src = {sizeof(dst), AF_ISO},
72 msk = {sizeof(dst), AF_ISO},
73 zmk = {1};
74#define zsi blank_siso
75#define zero_isoa zsi.siso_addr
76#define zap_isoaddr(a, b) (bzero((caddr_t)&a.siso_addr, sizeof(*r)), \
77 ((r = b) && bcopy((caddr_t)r, (caddr_t)&a.siso_addr, 1 + (r)->isoa_len)))
78#define S(x) ((struct sockaddr *)&(x))
600d71da
KS
79
80#define SNPAC_HASH(addr) \
a50e2bc0 81 (((u_long) iso_hashchar((caddr_t)addr, (int)addr->isoa_len)) % SNPAC_NB)
600d71da
KS
82
83#define SNPAC_LOOK(sc,addr) { \
84 register n; \
85 sc = &iso_snpac[SNPAC_HASH(addr) * SNPAC_BSIZ]; \
86 for (n = 0 ; n < SNPAC_BSIZ ; n++,sc++) \
87 if ((sc->sc_flags & SNPA_VALID) && \
88 (iso_addrmatch1(&sc->sc_nsap, addr))) \
89 break; \
90 if (n >= SNPAC_BSIZ) \
91 sc = 0; \
92}
93
94struct snpa_cache *snpac_new();
95
96/*
97 * We only keep track of a single IS at a time.
98 */
99struct snpa_cache *known_is;
100
101/*
102 * Addresses taken from NBS agreements, December 1987.
103 *
104 * These addresses assume on-the-wire transmission of least significant
105 * bit first. This is the method used by 802.3. When these
106 * addresses are passed to the token ring driver, (802.5), they
107 * must be bit-swaped because 802.5 transmission order is MSb first.
108 *
109 * Furthermore, according to IBM Austin, these addresses are not
110 * true token ring multicast addresses. More work is necessary
111 * to get multicast to work right on token ring.
112 *
113 * Currently, the token ring driver does not handle multicast, so
114 * these addresses are converted into the broadcast address in
115 * lan_output() That means that if these multicast addresses change
116 * the token ring driver must be altered.
117 */
118struct snpa_cache all_es = {
119 { { 0x0 }, /* sc_nsap */
120 6, /* sc_len */
121 { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x04 }, /* sc_snpa */
122 SNPA_VALID, /* sc_flags */
123 0 } /* sc_ht */
124};
125struct snpa_cache all_is = {
126 { { 0x0 }, /* sc_nsap */
127 6, /* sc_len */
128 { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x05 }, /* sc_snpa */
129 SNPA_VALID, /* sc_flags */
130 0 } /* sc_ht */
131};
132
133
134/*
135 * FUNCTION: iso_snparesolve
136 *
137 * PURPOSE: Resolve an iso address into snpa address
138 *
139 * RETURNS: 0 if addr is resolved
140 * errno if addr is unknown
141 *
142 * SIDE EFFECTS:
143 *
144 * NOTES: If an entry is found that matches the address, that
145 * snpa is returned. If no entry is found, but an IS is
146 * known, then the address of the IS is returned. If
147 * neither an address is found that matches or an IS is
148 * known, then the multi-cast address for "all ES" for
149 * this interface is returned.
150 *
151 * NB: the last case described above constitutes the
152 * query configuration function 9542, sec 6.5
153 * A mechanism is needed to prevent this function from
154 * being invoked if the system is an IS.
155 */
a50e2bc0 156iso_snparesolve(ifp, dest, snpa, snpa_len)
600d71da 157struct ifnet *ifp; /* outgoing interface */
a50e2bc0 158struct sockaddr_iso *dest; /* destination */
600d71da
KS
159char *snpa; /* RESULT: snpa to be used */
160int *snpa_len; /* RESULT: length of snpa */
161{
162 extern struct ifnet loif; /* loopback interface */
163 struct snpa_cache *sc; /* ptr to snpa table entry */
164 struct iso_addr *destiso; /* destination iso addr */
600d71da 165
a50e2bc0 166 destiso = &dest->siso_addr;
600d71da
KS
167
168 /*
169 * This hack allows us to send esis packets that have the destination snpa
170 * addresss embedded in the destination nsap address
171 */
a50e2bc0 172 if (destiso->isoa_genaddr[0] == AFI_SNA) {
600d71da
KS
173 /*
174 * This is a subnetwork address. Return it immediately
175 */
176 IFDEBUG(D_SNPA)
177 printf("iso_snparesolve: return SN address\n");
178 ENDDEBUG
179
180 *snpa_len = destiso->isoa_len - 1; /* subtract size of AFI */
a50e2bc0
KS
181 bcopy((caddr_t) destiso->isoa_genaddr + 1, (caddr_t)snpa,
182 (unsigned)*snpa_len);
600d71da
KS
183 return (0);
184 }
185
186 IFDEBUG(D_SNPA)
187 printf("iso_snparesolve: resolving %s\n", clnp_iso_addrp(destiso));
188 ENDDEBUG
189
190 /*
191 * packet is not for us, check cache for an entry
192 */
600d71da
KS
193 SNPAC_LOOK(sc, destiso);
194 if (sc == 0) { /* not found */
195 /* If we are an IS, we can't do much with the packet */
196 if (iso_systype == SNPA_IS)
197 goto bad;
198
199 /*
200 * Check if we know about an IS
201 */
202 if ((known_is) && (known_is->sc_flags & SNPA_VALID)) {
203 sc = known_is;
204 } else if (ifp->if_flags & IFF_BROADCAST) {
205 /*
206 * no IS, no match. Return "all es" multicast address for this
207 * interface, as per Query Configuration Function (9542 sec 6.5)
208 *
209 * Note: there is a potential problem here. If the destination
210 * is on the subnet and it does not respond with a ESH, but
211 * does send back a TP CC, a connection could be established
212 * where we always transmit the CLNP packet to "all es"
213 */
214 sc = &all_es;
215 } else {
216 goto bad;
217 }
218 }
219
220 bcopy((caddr_t)sc->sc_snpa, (caddr_t)snpa, sc->sc_len);
221 *snpa_len = sc->sc_len;
600d71da
KS
222 return (0);
223
224bad:
600d71da
KS
225 return(ENETUNREACH);
226}
227
228
229/*
230 * FUNCTION: snpac_look
231 *
232 * PURPOSE: Look up an entry in the snpa cache
233 *
234 * RETURNS: Pointer to snpa_cache structure, or null
235 *
236 * SIDE EFFECTS:
237 *
238 * NOTES: This is simply SNPAC_LOOK as a procedure.
239 */
240struct snpa_cache *
241snpac_look(isoa)
242struct iso_addr *isoa; /* destination nsap */
243{
244 struct snpa_cache *sc;
245 int s = splimp();
246
247 SNPAC_LOOK(sc, isoa);
248
249 splx(s);
250 return(sc);
251}
252
253/*
254 * FUNCTION: iso_8208snparesolve
255 *
256 * PURPOSE: Find the X.121 address that corresponds to an NSAP addr
257 *
258 * RETURNS: 0 or unix errno
259 *
260 * SIDE EFFECTS:
261 *
262 * NOTES: This ought to invoke the 8208 ES-IS function
263 */
a50e2bc0
KS
264iso_8208snparesolve(dest, snpa, snpa_len)
265struct sockaddr_iso *dest; /* destination */
600d71da
KS
266char *snpa; /* RESULT: snpa to be used */
267int *snpa_len; /* RESULT: length of snpa */
268{
269 struct snpa_cache *sc; /* ptr to snpa table entry */
270 struct iso_addr *destiso; /* destination iso addr */
271 int s;
272 int err = 0;
273
a50e2bc0 274 destiso = &dest->siso_addr;
600d71da
KS
275
276 s = splimp();
277 SNPAC_LOOK(sc, destiso);
278 if (sc) {
279 bcopy((caddr_t)sc->sc_snpa, (caddr_t)snpa, sc->sc_len);
280 *snpa_len = sc->sc_len;
281 } else {
282 err = ENETUNREACH;
283 }
284 splx(s);
285 return (err);
286}
287
288/*
289 * FUNCTION: iso_8208snpaadd
290 *
291 * PURPOSE: Add an entry to the snpa cache
292 *
293 * RETURNS:
294 *
295 * SIDE EFFECTS:
296 *
297 * NOTES: used by cons
298 */
299iso_8208snpaadd(ifp, nsap, snpa, snpalen, ht)
300struct ifnet *ifp; /* interface info is related to */
301struct iso_addr *nsap; /* nsap to add */
302caddr_t snpa; /* translation */
303int snpalen; /* length in bytes */
304short ht; /* holding time (in seconds) */
305{
a50e2bc0 306 snpac_add(ifp, nsap, snpa, snpalen, SNPA_ES, (u_short)ht);
600d71da
KS
307}
308
309/*
310 * FUNCTION: iso_8208snpadelete
311 *
312 * PURPOSE: Delete an entry from the snpa cache
313 *
314 * RETURNS: nothing
315 *
316 * SIDE EFFECTS:
317 *
318 * NOTES: used by CONS
319 */
320iso_8208snpadelete(nsap)
321struct iso_addr *nsap;
322{
323 struct snpa_cache *sc = snpac_look(nsap);
324
325 if (sc != NULL)
326 snpac_free(sc);
327}
328
329/*
330 * FUNCTION: snpac_new
331 *
332 * PURPOSE: create a new entry in the iso address to ethernet
333 * address table
334 *
335 * RETURNS: pointer to newest entry
336 *
337 * SIDE EFFECTS: times out old entries if no new entries are found
338 *
339 * NOTES: If the bucket is full, then timeout the oldest entry
340 * (ie. the one with the youngest holding time)
341 */
342struct snpa_cache *
343snpac_new(isoa)
344struct iso_addr *isoa; /* iso address to enter into table */
345{
346 register struct snpa_cache *sc;
347 register int n;
348 int smallest_ht = 1000000;
349 struct snpa_cache *maybe;
350
351 sc = &iso_snpac[SNPAC_HASH(isoa) * SNPAC_BSIZ];
352 for (n = 0 ; n < SNPAC_BSIZ ; n++,sc++) {
353
354 IFDEBUG (D_IOCTL)
355 printf("snpac_new: sc x%x ", sc);
356
357 if (sc->sc_flags & SNPA_VALID) {
358 int i;
359
360 printf("(valid) %s ", clnp_iso_addrp(&sc->sc_nsap));
361 for (i=0; i<sc->sc_len; i++)
362 printf("%x%c", sc->sc_snpa[i], i < (sc->sc_len-1) ? ':'
363 : '\n');
364 } else {
365 printf("invalid\n");
366 }
367 ENDDEBUG
368
369 if (sc->sc_flags & SNPA_VALID) {
370 if (sc->sc_ht < smallest_ht) {
371 smallest_ht = sc->sc_ht;
372 maybe = sc;
373 }
374 } else {
375 return sc; /* found unused slot */
376 }
377 }
378 snpac_free(maybe);
379 return maybe;
380}
600d71da
KS
381/*
382 * FUNCTION: snpac_free
383 *
384 * PURPOSE: free an entry in the iso address map table
385 *
386 * RETURNS: nothing
387 *
388 * SIDE EFFECTS:
389 *
390 * NOTES: If there is a route entry associated with cache
391 * entry, then delete that as well
392 */
393snpac_free(sc)
394register struct snpa_cache *sc; /* entry to free */
395{
a50e2bc0
KS
396 register struct rtentry *rt;
397 register struct iso_addr *r;
600d71da
KS
398
399 if (known_is == sc) {
600d71da
KS
400 known_is = NULL;
401 }
a50e2bc0
KS
402 if (sc->sc_rt) {
403 zap_isoaddr(dst, (&(sc->sc_da)));
404 rt = rtalloc1((struct sockaddr *)&dst, 0);
405 if ((sc->sc_rt == rt) && (rt->rt_flags & RTF_UP)
406 && (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED))) {
407 RTFREE(rt);
408 rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt),
409 rt->rt_flags, (struct rtentry **)0);
410 }
411 RTFREE(rt);
600d71da
KS
412 }
413 bzero((caddr_t)sc, sizeof(struct snpa_cache));
600d71da
KS
414}
415
416/*
417 * FUNCTION: snpac_add
418 *
419 * PURPOSE: Add an entry to the snpa cache
420 *
421 * RETURNS:
422 *
423 * SIDE EFFECTS:
424 *
425 * NOTES: If entry already exists, then update holding time.
426 */
427snpac_add(ifp, nsap, snpa, snpalen, type, ht)
428struct ifnet *ifp; /* interface info is related to */
429struct iso_addr *nsap; /* nsap to add */
430caddr_t snpa; /* translation */
a50e2bc0 431int snpalen; /* translation length */
600d71da 432char type; /* SNPA_IS or SNPA_ES */
a50e2bc0 433u_short ht; /* holding time (in seconds) */
600d71da
KS
434{
435 struct snpa_cache *sc;
600d71da
KS
436
437 SNPAC_LOOK(sc, nsap);
438 if (sc == NULL) {
439 sc = snpac_new(nsap);
440 sc->sc_nsap = *nsap;
441 }
442
443 sc->sc_ht = ht;
444
445 sc->sc_len = min(snpalen, MAX_SNPALEN);
a50e2bc0 446 bcopy(snpa, (caddr_t)sc->sc_snpa, sc->sc_len);
600d71da
KS
447 sc->sc_flags = SNPA_VALID | type;
448 sc->sc_ifp = ifp;
449
450 if (type & SNPA_IS)
451 snpac_logdefis(sc);
600d71da
KS
452}
453
454/*
455 * FUNCTION: snpac_ioctl
456 *
457 * PURPOSE: handle ioctls to change the iso address map
458 *
459 * RETURNS: unix error code
460 *
461 * SIDE EFFECTS: changes the snpa_cache table declared above.
462 *
463 * NOTES:
464 */
465snpac_ioctl(cmd, data)
466int cmd; /* ioctl to process */
467caddr_t data; /* data for the cmd */
468{
469 register struct snpa_req *rq = (struct snpa_req *)data;
470 register struct snpa_cache *sc;
471 register struct iso_addr *isoa;
472 int s;
a50e2bc0 473 char *type;
600d71da 474
a50e2bc0
KS
475 switch(cmd) {
476 case SIOCSISOMAP: type = "set"; break;
477 case SIOCDISOMAP: type = "delete"; break;
478 case SIOCGISOMAP: type = "get"; break;
479 default: return(snpac_systype(cmd, data));
480 }
600d71da
KS
481
482 /* sanity check */
483 if (rq->sr_len > MAX_SNPALEN)
484 return(EINVAL);
485
486 IFDEBUG (D_IOCTL)
487 int i;
488
a50e2bc0 489 printf("snpac_ioctl: %s %s to ", type, clnp_iso_addrp(isoa));
600d71da
KS
490 for (i=0; i<rq->sr_len; i++)
491 printf("%x%c", rq->sr_snpa[i], i < (rq->sr_len-1) ? ':' : '\n');
492 ENDDEBUG
493
a50e2bc0
KS
494 /* look up this address in table */
495 isoa = &rq->sr_isoa;
496
600d71da
KS
497 SNPAC_LOOK(sc, isoa);
498 if (sc == NULL) { /* not found */
499 if (cmd != SIOCSISOMAP)
500 return(ENXIO);
501 }
502
503 switch(cmd) {
504 case SIOCSISOMAP: /* set entry */
a50e2bc0
KS
505 snpac_add((struct ifnet *)NULL, isoa, (caddr_t)rq->sr_snpa,
506 (int)rq->sr_len,
507 (char)(rq->sr_flags & (SNPA_ES|SNPA_IS|SNPA_PERM)),
508 rq->sr_ht);
600d71da
KS
509 break;
510
511 case SIOCDISOMAP: /* delete entry */
512 snpac_free(sc);
513 break;
514
515 case SIOCGISOMAP: /* get entry */
a50e2bc0 516 bcopy((caddr_t)&sc->sc_sr, (caddr_t)rq, sizeof(struct snpa_req));
600d71da
KS
517 break;
518 }
600d71da
KS
519 return(0);
520}
521
522/*
523 * FUNCTION: iso_tryloopback
524 *
525 * PURPOSE: Attempt to use the software loopback interface for pkt
526 *
527 * RETURNS: 0 if packet was sent successfully
528 * errno if there was a problem sending the packet
529 * Ie. the return value of looutput
530 * -1 if software loopback is not appropriate
531 *
532 * SIDE EFFECTS:
533 *
534 * NOTES:
535 */
a50e2bc0 536iso_tryloopback(m, dest)
600d71da 537struct mbuf *m; /* pkt */
a50e2bc0 538struct sockaddr_iso *dest; /* destination */
600d71da
KS
539{
540 struct iso_addr *destiso; /* destination iso addr */
541
a50e2bc0 542 destiso = &dest->siso_addr;
600d71da
KS
543
544 if (clnp_ours(destiso)) {
545 IFDEBUG(D_SNPA)
546 printf("iso_tryloopback: local destination\n");
547 ENDDEBUG
548 if (loif.if_flags & IFF_UP) {
549 IFDEBUG(D_SNPA)
550 printf("iso_tryloopback: calling looutput\n");
551 ENDDEBUG
a50e2bc0 552 return (looutput(&loif, m, (struct sockaddr *)dest));
600d71da
KS
553 }
554 }
555 return (-1);
556}
557
558/*
559 * FUNCTION: snpac_systype
560 *
561 * PURPOSE: Set/Get the system type and esis parameters
562 *
563 * RETURNS: 0 on success, or unix error code
564 *
565 * SIDE EFFECTS:
566 *
567 * NOTES:
568 */
569snpac_systype (cmd, data)
570int cmd; /* ioctl to process */
571caddr_t data; /* data for the cmd */
572{
573 register struct systype_req *rq = (struct systype_req *)data;
574 extern short esis_holding_time, esis_config_time;
575
576 IFDEBUG (D_IOCTL)
577 if (cmd == SIOCSSTYPE)
578 printf("snpac_systype: cmd set, type x%x, ht %d, ct %d\n",
579 rq->sr_type, rq->sr_holdt, rq->sr_configt);
580 else
581 printf("snpac_systype: cmd get\n");
582 ENDDEBUG
583
584 if (cmd == SIOCSSTYPE) {
585 if (!suser())
586 return(EACCES);
587 if ((rq->sr_type & (SNPA_ES|SNPA_IS)) == (SNPA_ES|SNPA_IS))
588 return(EINVAL);
589 if (rq->sr_type & SNPA_ES) {
590 iso_systype = SNPA_ES;
591 } else if (rq->sr_type & SNPA_IS) {
592 iso_systype = SNPA_IS;
593 } else {
594 return(EINVAL);
595 }
596 esis_holding_time = rq->sr_holdt;
597 esis_config_time = rq->sr_configt;
598 } else if (cmd == SIOCGSTYPE) {
599 rq->sr_type = iso_systype;
600 rq->sr_holdt = esis_holding_time;
601 rq->sr_configt = esis_config_time;
602 } else {
603 return(EINVAL);
604 }
605 return(0);
606}
607
608/*
609 * FUNCTION: snpac_logdefis
610 *
611 * PURPOSE: Mark the IS passed as the default IS
612 *
613 * RETURNS: nothing
614 *
615 * SIDE EFFECTS:
616 *
617 * NOTES:
618 */
619snpac_logdefis(sc)
a50e2bc0 620register struct snpa_cache *sc;
600d71da 621{
a50e2bc0
KS
622 register struct iso_addr *r;
623 register struct rtentry *rt = rtalloc1((struct sockaddr *)&zsi, 0);
624 if (known_is == 0)
625 known_is = sc;
626 if (known_is != sc) {
627 if (known_is->sc_rt) {
628 rtfree(known_is->sc_rt);
629 known_is->sc_rt = 0;
630 }
631 known_is = sc;
632 }
633 if (rt == 0) {
634 zap_isoaddr(dst, &(sc->sc_nsap));
635 rtrequest(RTM_ADD, S(zsi), S(dst), S(zmk),
636 RTF_DYNAMIC|RTF_GATEWAY, &sc->sc_rt);
637 return;
638 }
639 if (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED)) {
640 ((struct sockaddr_iso *)rt->rt_gateway)->siso_addr = sc->sc_nsap;
641 known_is = sc;
642 sc->sc_rt = rt;
600d71da 643 }
600d71da
KS
644}
645
646/*
647 * FUNCTION: snpac_age
648 *
649 * PURPOSE: Time out snpac entries
650 *
651 * RETURNS:
652 *
653 * SIDE EFFECTS:
654 *
655 * NOTES: When encountering an entry for the first time, snpac_age
656 * may delete up to SNPAC_AGE too many seconds. Ie.
657 * if the entry is added a moment before snpac_age is
658 * called, the entry will immediately have SNPAC_AGE
659 * seconds taken off the holding time, even though
660 * it has only been held a brief moment.
661 *
662 * The proper way to do this is set an expiry timeval
663 * equal to current time + holding time. Then snpac_age
664 * would time out entries where expiry date is older
665 * than the current time.
666 */
667snpac_age()
668{
669 register struct snpa_cache *sc;
670 register int i;
671
672 timeout(snpac_age, (caddr_t)0, SNPAC_AGE * hz);
673
674 sc = &iso_snpac[0];
675 for (i=0; i<SNPAC_SIZE; i++, sc++) {
676 if (((sc->sc_flags & SNPA_PERM) == 0) && (sc->sc_flags & SNPA_VALID)) {
677 sc->sc_ht -= SNPAC_AGE;
678 if (sc->sc_ht > 0)
679 continue;
680 else
681 snpac_free(sc);
682 }
683 }
684}
685
686/*
687 * FUNCTION: snpac_ownmulti
688 *
689 * PURPOSE: Determine if the snpa address is a multicast address
690 * of the same type as the system.
691 *
692 * RETURNS: true or false
693 *
694 * SIDE EFFECTS:
695 *
696 * NOTES: Used by interface drivers when not in eavesdrop mode
697 * as interm kludge until
698 * real multicast addresses can be configured
699 */
700snpac_ownmulti(snpa, len)
701char *snpa;
702int len;
703{
a50e2bc0
KS
704 return (((iso_systype & SNPA_ES) &&
705 (!bcmp((caddr_t)snpa, (caddr_t)all_es.sc_snpa, (unsigned)len))) ||
706 ((iso_systype & SNPA_IS) &&
707 (!bcmp((caddr_t)snpa, (caddr_t)all_is.sc_snpa, (unsigned)len))));
600d71da
KS
708}
709
710/*
711 * FUNCTION: snpac_flushifp
712 *
713 * PURPOSE: Flush entries associated with specific ifp
714 *
715 * RETURNS: nothing
716 *
717 * SIDE EFFECTS:
718 *
719 * NOTES:
720 */
721snpac_flushifp(ifp)
722struct ifnet *ifp;
723{
724 register struct snpa_cache *sc;
725 register int i;
726
727 sc = &iso_snpac[0];
728 for (i=0; i<SNPAC_SIZE; i++, sc++) {
729 if ((sc->sc_ifp == ifp) && (sc->sc_flags & SNPA_VALID)) {
730 snpac_free(sc);
731 }
732 }
733}
734
735/*
736 * FUNCTION: snpac_rtrequest
737 *
738 * PURPOSE: Make a routing request
739 *
740 * RETURNS: nothing
741 *
742 * SIDE EFFECTS:
743 *
744 * NOTES: In the future, this should make a request of a user
745 * level routing daemon.
746 */
a50e2bc0 747snpac_rtrequest(req, host, gateway, netmask, flags, ret_nrt)
600d71da 748int req;
a50e2bc0 749struct iso_addr *host;
600d71da 750struct iso_addr *gateway;
a50e2bc0 751struct iso_addr *netmask;
600d71da 752short flags;
a50e2bc0 753struct rtentry **ret_nrt;
600d71da 754{
a50e2bc0 755 register struct iso_addr *r;
600d71da
KS
756
757 IFDEBUG(D_SNPA)
758 printf("snpac_rtrequest: ");
a50e2bc0 759 if (req == RTM_ADD)
600d71da 760 printf("add");
a50e2bc0 761 else if (req == RTM_DELETE)
600d71da
KS
762 printf("delete");
763 else
764 printf("unknown command");
a50e2bc0 765 printf(" dst: %s\n", clnp_iso_addrp(host));
600d71da
KS
766 printf("\tgateway: %s\n", clnp_iso_addrp(gateway));
767 ENDDEBUG
768
600d71da 769
a50e2bc0
KS
770 zap_isoaddr(dst, host);
771 zap_isoaddr(gte, gateway);
772 zap_isoaddr(msk, netmask);
600d71da 773
a50e2bc0
KS
774 rtrequest(req, S(dst), S(gte), (netmask ? S(msk) : (struct sockaddr *)0),
775 flags, ret_nrt);
776}
600d71da
KS
777
778/*
779 * FUNCTION: snpac_addrt
780 *
781 * PURPOSE: Associate a routing entry with an snpac entry
782 *
783 * RETURNS: nothing
784 *
785 * SIDE EFFECTS:
786 *
787 * NOTES: If a cache entry exists for gateway, then
788 * make a routing entry (host, gateway) and associate
789 * with gateway.
790 *
791 * If a route already exists and is different, first delete
792 * it.
793 *
794 * This could be made more efficient by checking
795 * the existing route before adding a new one.
796 */
a50e2bc0
KS
797snpac_addrt(host, gateway, source, netmask)
798struct iso_addr *host, *gateway, *source, *netmask;
600d71da 799{
a50e2bc0
KS
800 register struct snpa_cache *sc;
801 register struct iso_addr *r;
600d71da 802
600d71da
KS
803 SNPAC_LOOK(sc, gateway);
804 if (sc != NULL) {
a50e2bc0
KS
805 bcopy((caddr_t)host, (caddr_t)&sc->sc_da, sizeof(struct iso_addr));
806 zap_isoaddr(dst, host);
807 zap_isoaddr(gte, gateway);
808 zap_isoaddr(src, source);
809 zap_isoaddr(msk, netmask);
810 if (netmask) {
811 rtredirect(S(dst), S(gte), S(msk), RTF_DONE, S(src), &sc->sc_rt);
812 } else
813 rtredirect(S(dst), S(gte), (struct sockaddr *)0,
814 RTF_DONE | RTF_HOST, S(src), &sc->sc_rt);
600d71da 815 }
600d71da
KS
816}
817#endif ISO