This commit was generated by cvs2svn to track changes on a CVS vendor
[unix-history] / sys / netiso / iso_snpac.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_snpac.c 7.14 (Berkeley) 6/27/91
4c45483e 34 * $Id: iso_snpac.c,v 1.3 1993/11/07 17:49:46 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 */
15637ed4
RG
63
64#ifdef ISO
65
66#include "types.h"
67#include "param.h"
68#include "systm.h"
4c45483e 69#include "kernel.h"
15637ed4
RG
70#include "mbuf.h"
71#include "domain.h"
72#include "protosw.h"
73#include "socket.h"
74#include "socketvar.h"
75#include "errno.h"
76#include "ioctl.h"
77#include "syslog.h"
78
79#include "../net/if.h"
80#include "../net/if_dl.h"
81#include "../net/route.h"
82
83#include "iso.h"
84#include "iso_var.h"
85#include "iso_snpac.h"
86#include "clnp.h"
87#include "clnp_stat.h"
88#include "esis.h"
89#include "argo_debug.h"
90
4c45483e
GW
91static void snpac_logdefis(struct rtentry *);
92
8ace4366
GW
93struct llinfo_llc llinfo_llc;
94
4c45483e 95int iso_systype = SNPA_ES; /* default to be an ES */
15637ed4 96extern short esis_holding_time, esis_config_time, esis_esconfig_time;
4c45483e 97extern int esis_config();
15637ed4
RG
98static void snpac_fixdstandmask();
99
100struct sockaddr_iso blank_siso = {sizeof(blank_siso), AF_ISO};
101extern u_long iso_hashchar();
102static struct sockaddr_iso
103 dst = {sizeof(dst), AF_ISO},
104 gte = {sizeof(dst), AF_ISO},
105 src = {sizeof(dst), AF_ISO},
106 msk = {sizeof(dst), AF_ISO},
107 zmk = {1};
108#define zsi blank_siso
109#define zero_isoa zsi.siso_addr
110#define zap_isoaddr(a, b) {Bzero(&a.siso_addr, sizeof(*r)); r = b; \
111 Bcopy(r, &a.siso_addr, 1 + (r)->isoa_len);}
112#define S(x) ((struct sockaddr *)&(x))
113
114static struct sockaddr_dl blank_dl = {sizeof(blank_dl), AF_LINK};
115static struct sockaddr_dl gte_dl;
116#define zap_linkaddr(a, b, c, i) \
117 (*a = blank_dl, bcopy(b, a->sdl_data, a->sdl_alen = c), a->sdl_index = i)
118
119/*
120 * We only keep track of a single IS at a time.
121 */
122struct rtentry *known_is;
123
124/*
125 * Addresses taken from NBS agreements, December 1987.
126 *
127 * These addresses assume on-the-wire transmission of least significant
128 * bit first. This is the method used by 802.3. When these
129 * addresses are passed to the token ring driver, (802.5), they
130 * must be bit-swaped because 802.5 transmission order is MSb first.
131 *
132 * Furthermore, according to IBM Austin, these addresses are not
133 * true token ring multicast addresses. More work is necessary
134 * to get multicast to work right on token ring.
135 *
136 * Currently, the token ring driver does not handle multicast, so
137 * these addresses are converted into the broadcast address in
138 * lan_output() That means that if these multicast addresses change
139 * the token ring driver must be altered.
140 */
141char all_es_snpa[] = { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x04 };
142char all_is_snpa[] = { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x05 };
143char all_l1is_snpa[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x14};
144char all_l2is_snpa[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x15};
145
146union sockunion {
147 struct sockaddr_iso siso;
148 struct sockaddr_dl sdl;
149 struct sockaddr sa;
150};
151
152/*
153 * FUNCTION: llc_rtrequest
154 *
155 * PURPOSE: Manage routing table entries specific to LLC for ISO.
156 *
157 * NOTES: This does a lot of obscure magic;
158 */
4c45483e 159void
15637ed4 160llc_rtrequest(req, rt, sa)
4c45483e
GW
161 int req;
162 register struct rtentry *rt;
163 struct sockaddr *sa;
15637ed4
RG
164{
165 register union sockunion *gate = (union sockunion *)rt->rt_gateway;
166 register struct llinfo_llc *lc = (struct llinfo_llc *)rt->rt_llinfo, *lc2;
167 struct rtentry *rt2;
168 struct ifnet *ifp = rt->rt_ifp;
169 int addrlen = ifp->if_addrlen;
170 static struct rtentry *recursing = 0;
171#define LLC_SIZE 3 /* XXXXXX do this right later */
172
173 IFDEBUG (D_SNPA)
174 printf("llc_rtrequest(%d, %x, %x)\n", req, rt, sa);
175 ENDDEBUG
176 if (rt->rt_flags & RTF_GATEWAY) {
177 if (recursing) {
178 log(LOG_DEBUG, "llc_rtrequest: gateway route points to same type %x %x\n",
179 recursing, rt);
180 } else switch (req) {
181 case RTM_RESOLVE:
182 case RTM_ADD:
183 recursing = rt;
184 rt->rt_llinfo = (caddr_t)rtalloc1(&gate->sa, 1);
185 recursing = 0;
186 if (rt->rt_rmx.rmx_mtu == 0) {
187 rt->rt_rmx.rmx_mtu =
188 ((rt2 = (struct rtentry *)rt->rt_llinfo) &&
189 (rt2->rt_rmx.rmx_mtu)) ?
190 rt2->rt_rmx.rmx_mtu :
191 rt->rt_ifp->if_mtu - LLC_SIZE;
192 }
193 return;
194
195 case RTM_DELETE:
196 if (lc)
197 RTFREE((struct rtentry *)lc);
198 rt->rt_llinfo = 0;
199 }
200 } else switch (req) {
201 case RTM_ADD:
202 /*
203 * Case 1: This route may come from a route to iface with mask
204 * or from a default route.
205 */
206 if (rt->rt_flags & RTF_CLONING) {
207 register struct ifaddr *ifa;
208 register struct sockaddr *sa;
4c45483e 209 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
15637ed4
RG
210 if ((sa = ifa->ifa_addr)->sa_family == AF_LINK) {
211 if (sa->sa_len > gate->sa.sa_len)
212 log(LOG_DEBUG, "llc_rtrequest: cloning address too small\n");
213 else {
214 Bcopy(sa, gate, gate->sa.sa_len);
215 gate->sdl.sdl_alen = 0;
216 }
217 break;
218 }
219 if (ifa == 0)
220 log(LOG_DEBUG, "llc_rtrequest: can't find LL ifaddr for iface\n");
221 break;
222 }
223 /* FALLTHROUGH */
224 case RTM_RESOLVE:
225 /*
226 * Case 2: This route may come from cloning, or a manual route
227 * add with a LL address.
228 */
229 if (gate->sdl.sdl_family != AF_LINK) {
230 log(LOG_DEBUG, "llc_rtrequest: got non-link non-gateway route\n");
231 break;
232 }
233 if (lc != 0)
234 return; /* happens on a route change */
235 R_Malloc(lc, struct llinfo_llc *, sizeof (*lc));
236 rt->rt_llinfo = (caddr_t)lc;
237 if (lc == 0) {
238 log(LOG_DEBUG, "llc_rtrequest: malloc failed\n");
239 break;
240 }
241 Bzero(lc, sizeof(*lc));
242 lc->lc_rt = rt;
243 rt->rt_flags |= RTF_LLINFO;
244 insque(lc, &llinfo_llc);
245 if (gate->sdl.sdl_alen == sizeof(struct esis_req) + addrlen) {
246 gate->sdl.sdl_alen -= sizeof(struct esis_req);
247 bcopy(addrlen + LLADDR(&gate->sdl),
248 (caddr_t)&lc->lc_er, sizeof(lc->lc_er));
249 } else if (gate->sdl.sdl_alen == addrlen)
250 lc->lc_flags = (SNPA_ES | SNPA_VALID | SNPA_PERM);
251 break;
252 case RTM_DELETE:
253 if (lc == 0 || (rt->rt_flags & RTF_CLONING))
254 return;
255 remque(lc);
256 Free(lc);
257 rt->rt_llinfo = 0;
258 rt->rt_flags &= ~RTF_LLINFO;
259 break;
260 }
261 if (rt->rt_rmx.rmx_mtu == 0) {
262 rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu - LLC_SIZE;
263 }
264}
265/*
266 * FUNCTION: iso_snparesolve
267 *
268 * PURPOSE: Resolve an iso address into snpa address
269 *
270 * RETURNS: 0 if addr is resolved
271 * errno if addr is unknown
272 *
273 * SIDE EFFECTS:
274 *
275 * NOTES: Now that we have folded the snpa cache into the routing
276 * table, we know there is no snpa address known for this
277 * destination. If we know of a default IS, then the address
278 * of the IS is returned. If no IS is known, then return the
279 * multi-cast address for "all ES" for this interface.
280 *
281 * NB: the last case described above constitutes the
282 * query configuration function 9542, sec 6.5
283 * A mechanism is needed to prevent this function from
284 * being invoked if the system is an IS.
285 */
4c45483e 286int
15637ed4
RG
287iso_snparesolve(ifp, dest, snpa, snpa_len)
288struct ifnet *ifp; /* outgoing interface */
289struct sockaddr_iso *dest; /* destination */
290caddr_t snpa; /* RESULT: snpa to be used */
291int *snpa_len; /* RESULT: length of snpa */
292{
293 struct llinfo_llc *sc; /* ptr to snpa table entry */
294 caddr_t found_snpa;
295 int addrlen;
296
297 /*
298 * This hack allows us to send esis packets that have the destination snpa
299 * addresss embedded in the destination nsap address
300 */
301 if (dest->siso_data[0] == AFI_SNA) {
302 /*
303 * This is a subnetwork address. Return it immediately
304 */
305 IFDEBUG(D_SNPA)
306 printf("iso_snparesolve: return SN address\n");
307 ENDDEBUG
308 addrlen = dest->siso_nlen - 1; /* subtract size of AFI */
309 found_snpa = (caddr_t) dest->siso_data + 1;
310 /*
311 * If we are an IS, we can't do much with the packet;
312 * Check if we know about an IS.
313 */
314 } else if (iso_systype != SNPA_IS && known_is != 0 &&
315 (sc = (struct llinfo_llc *)known_is->rt_llinfo) &&
316 (sc->lc_flags & SNPA_VALID)) {
317 register struct sockaddr_dl *sdl =
318 (struct sockaddr_dl *)(known_is->rt_gateway);
319 found_snpa = LLADDR(sdl);
320 addrlen = sdl->sdl_alen;
321 } else if (ifp->if_flags & IFF_BROADCAST) {
322 /*
323 * no IS, no match. Return "all es" multicast address for this
324 * interface, as per Query Configuration Function (9542 sec 6.5)
325 *
326 * Note: there is a potential problem here. If the destination
327 * is on the subnet and it does not respond with a ESH, but
328 * does send back a TP CC, a connection could be established
329 * where we always transmit the CLNP packet to "all es"
330 */
331 addrlen = ifp->if_addrlen;
332 found_snpa = (caddr_t)all_es_snpa;
333 } else
334 return (ENETUNREACH);
335 bcopy(found_snpa, snpa, *snpa_len = addrlen);
336 return (0);
337}
338
339
340/*
341 * FUNCTION: snpac_free
342 *
343 * PURPOSE: free an entry in the iso address map table
344 *
345 * RETURNS: nothing
346 *
347 * SIDE EFFECTS:
348 *
349 * NOTES: If there is a route entry associated with cache
350 * entry, then delete that as well
351 */
4c45483e 352void
15637ed4
RG
353snpac_free(lc)
354register struct llinfo_llc *lc; /* entry to free */
355{
356 register struct rtentry *rt = lc->lc_rt;
357 register struct iso_addr *r;
358
359 if (known_is == rt)
360 known_is = 0;
361 if (rt && (rt->rt_flags & RTF_UP) &&
362 (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED))) {
363 RTFREE(rt);
364 rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt),
365 rt->rt_flags, (struct rtentry **)0);
366 RTFREE(rt);
367 }
368}
369
370/*
371 * FUNCTION: snpac_add
372 *
373 * PURPOSE: Add an entry to the snpa cache
374 *
375 * RETURNS:
376 *
377 * SIDE EFFECTS:
378 *
379 * NOTES: If entry already exists, then update holding time.
380 */
4c45483e 381int
15637ed4
RG
382snpac_add(ifp, nsap, snpa, type, ht, nsellength)
383struct ifnet *ifp; /* interface info is related to */
384struct iso_addr *nsap; /* nsap to add */
385caddr_t snpa; /* translation */
386char type; /* SNPA_IS or SNPA_ES */
387u_short ht; /* holding time (in seconds) */
388int nsellength; /* nsaps may differ only in trailing bytes */
389{
390 register struct llinfo_llc *lc;
391 register struct rtentry *rt;
392 struct rtentry *mrt = 0;
393 register struct iso_addr *r; /* for zap_isoaddr macro */
394 int snpalen = min(ifp->if_addrlen, MAX_SNPALEN);
395 int new_entry = 0, index = ifp->if_index;
396
397 IFDEBUG(D_SNPA)
398 printf("snpac_add(%x, %x, %x, %x, %x, %x)\n",
399 ifp, nsap, snpa, type, ht, nsellength);
400 ENDDEBUG
401 zap_isoaddr(dst, nsap);
402 rt = rtalloc1(S(dst), 0);
403 IFDEBUG(D_SNPA)
404 printf("snpac_add: rtalloc1 returns %x\n", rt);
405 ENDDEBUG
406 if (rt == 0) {
407 struct sockaddr *netmask;
408 int flags;
409 add:
410 if (nsellength) {
411 netmask = S(msk); flags = RTF_UP;
412 snpac_fixdstandmask(nsellength);
413 } else {
414 netmask = 0; flags = RTF_UP | RTF_HOST;
415 }
416 new_entry = 1;
417 zap_linkaddr((&gte_dl), snpa, snpalen, index);
418 if (rtrequest(RTM_ADD, S(dst), S(gte_dl), netmask, flags, &mrt) ||
419 mrt == 0)
420 return (0);
421 rt = mrt;
422 rt->rt_refcnt--;
423 } else {
424 register struct sockaddr_dl *sdl = (struct sockaddr_dl *)rt->rt_gateway;
425 rt->rt_refcnt--;
426 if ((rt->rt_flags & RTF_LLINFO) == 0)
427 goto add;
428 if (nsellength && (rt->rt_flags & RTF_HOST)) {
429 if (rt->rt_refcnt == 0) {
430 rtrequest(RTM_DELETE, S(dst), (struct sockaddr *)0,
431 (struct sockaddr *)0, 0, (struct rtentry *)0);
432 rt = 0;
433 goto add;
434 } else {
435 static struct iso_addr nsap2; register char *cp;
436 nsap2 = *nsap;
437 cp = nsap2.isoa_genaddr + nsap->isoa_len - nsellength;
438 while (cp < (char *)(1 + &nsap2))
439 *cp++ = 0;
440 (void) snpac_add(ifp, &nsap2, snpa, type, ht, nsellength);
441 }
442 }
443 if (sdl->sdl_family != AF_LINK || sdl->sdl_alen == 0) {
444 int old_sdl_len = sdl->sdl_len;
445 if (old_sdl_len < sizeof(*sdl)) {
446 log(LOG_DEBUG, "snpac_add: cant make room for lladdr\n");
447 return (0);
448 }
449 zap_linkaddr(sdl, snpa, snpalen, index);
450 sdl->sdl_len = old_sdl_len;
451 new_entry = 1;
452 }
453 }
454 if ((lc = (struct llinfo_llc *)rt->rt_llinfo) == 0)
455 panic("snpac_rtrequest");
456 rt->rt_rmx.rmx_expire = ht + time.tv_sec;
457 lc->lc_flags = SNPA_VALID | type;
458 if (type & SNPA_IS)
459 snpac_logdefis(rt);
460 return (new_entry);
461}
462
463static void
464snpac_fixdstandmask(nsellength)
4c45483e 465 int nsellength;
15637ed4
RG
466{
467 register char *cp = msk.siso_data, *cplim;
468
469 cplim = cp + (dst.siso_nlen -= nsellength);
470 msk.siso_len = cplim - (char *)&msk;
471 msk.siso_nlen = 0;
472 while (cp < cplim)
473 *cp++ = -1;
474 while (cp < (char *)msk.siso_pad)
475 *cp++ = 0;
476 for (cp = dst.siso_data + dst.siso_nlen; cp < (char *)dst.siso_pad; )
477 *cp++ = 0;
478}
479
480/*
481 * FUNCTION: snpac_ioctl
482 *
483 * PURPOSE: Set/Get the system type and esis parameters
484 *
485 * RETURNS: 0 on success, or unix error code
486 *
487 * SIDE EFFECTS:
488 *
489 * NOTES:
490 */
4c45483e 491int
15637ed4
RG
492snpac_ioctl (so, cmd, data)
493struct socket *so;
494int cmd; /* ioctl to process */
495caddr_t data; /* data for the cmd */
496{
497 register struct systype_req *rq = (struct systype_req *)data;
498
499 IFDEBUG(D_IOCTL)
500 if (cmd == SIOCSSTYPE)
501 printf("snpac_ioctl: cmd set, type x%x, ht %d, ct %d\n",
502 rq->sr_type, rq->sr_holdt, rq->sr_configt);
503 else
504 printf("snpac_ioctl: cmd get\n");
505 ENDDEBUG
506
507 if (cmd == SIOCSSTYPE) {
508 if ((so->so_state & SS_PRIV) == 0)
509 return (EPERM);
510 if ((rq->sr_type & (SNPA_ES|SNPA_IS)) == (SNPA_ES|SNPA_IS))
511 return(EINVAL);
512 if (rq->sr_type & SNPA_ES) {
513 iso_systype = SNPA_ES;
514 } else if (rq->sr_type & SNPA_IS) {
515 iso_systype = SNPA_IS;
516 } else {
517 return(EINVAL);
518 }
519 esis_holding_time = rq->sr_holdt;
520 esis_config_time = rq->sr_configt;
521 if (esis_esconfig_time != rq->sr_esconfigt) {
522 untimeout(esis_config, (caddr_t)0);
523 esis_esconfig_time = rq->sr_esconfigt;
524 esis_config();
525 }
526 } else if (cmd == SIOCGSTYPE) {
527 rq->sr_type = iso_systype;
528 rq->sr_holdt = esis_holding_time;
529 rq->sr_configt = esis_config_time;
530 rq->sr_esconfigt = esis_esconfig_time;
531 } else {
532 return (EINVAL);
533 }
534 return (0);
535}
536
537/*
538 * FUNCTION: snpac_logdefis
539 *
540 * PURPOSE: Mark the IS passed as the default IS
541 *
542 * RETURNS: nothing
543 *
544 * SIDE EFFECTS:
545 *
546 * NOTES:
547 */
4c45483e 548static void
15637ed4 549snpac_logdefis(sc)
4c45483e 550 register struct rtentry *sc;
15637ed4
RG
551{
552 register struct iso_addr *r;
553 register struct sockaddr_dl *sdl = (struct sockaddr_dl *)sc->rt_gateway;
554 register struct rtentry *rt = rtalloc1((struct sockaddr *)&zsi, 0);
555
556 zap_linkaddr((&gte_dl), LLADDR(sdl), sdl->sdl_alen, sdl->sdl_index);
557 if (known_is == 0)
558 known_is = sc;
559 if (known_is != sc) {
560 rtfree(known_is);
561 known_is = sc;
562 }
563 if (rt == 0) {
564 rtrequest(RTM_ADD, S(zsi), S(gte_dl), S(zmk),
565 RTF_DYNAMIC|RTF_GATEWAY|RTF_CLONING, 0);
566 return;
567 }
568 rt->rt_refcnt--;
569 if (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED)) {
570 *((struct sockaddr_dl *)rt->rt_gateway) = gte_dl;
571 }
572}
573
574/*
575 * FUNCTION: snpac_age
576 *
577 * PURPOSE: Time out snpac entries
578 *
579 * RETURNS:
580 *
581 * SIDE EFFECTS:
582 *
583 * NOTES: When encountering an entry for the first time, snpac_age
584 * may delete up to SNPAC_AGE too many seconds. Ie.
585 * if the entry is added a moment before snpac_age is
586 * called, the entry will immediately have SNPAC_AGE
587 * seconds taken off the holding time, even though
588 * it has only been held a brief moment.
589 *
590 * The proper way to do this is set an expiry timeval
591 * equal to current time + holding time. Then snpac_age
592 * would time out entries where expiry date is older
593 * than the current time.
594 */
4c45483e 595void
15637ed4
RG
596snpac_age()
597{
598 register struct llinfo_llc *lc, *nlc;
599 register struct rtentry *rt;
600
601 timeout(snpac_age, (caddr_t)0, SNPAC_AGE * hz);
602
603 for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = nlc) {
604 nlc = lc->lc_next;
605 if (((lc->lc_flags & SNPA_PERM) == 0) && (lc->lc_flags & SNPA_VALID)) {
606 rt = lc->lc_rt;
607 if (rt->rt_rmx.rmx_expire && rt->rt_rmx.rmx_expire < time.tv_sec)
608 snpac_free(lc);
609 else
610 continue;
611 }
612 }
613}
614
615/*
616 * FUNCTION: snpac_ownmulti
617 *
618 * PURPOSE: Determine if the snpa address is a multicast address
619 * of the same type as the system.
620 *
621 * RETURNS: true or false
622 *
623 * SIDE EFFECTS:
624 *
625 * NOTES: Used by interface drivers when not in eavesdrop mode
626 * as interm kludge until
627 * real multicast addresses can be configured
628 */
4c45483e 629int
15637ed4
RG
630snpac_ownmulti(snpa, len)
631caddr_t snpa;
632u_int len;
633{
634 return (((iso_systype & SNPA_ES) &&
635 (!bcmp(snpa, (caddr_t)all_es_snpa, len))) ||
636 ((iso_systype & SNPA_IS) &&
637 (!bcmp(snpa, (caddr_t)all_is_snpa, len))));
638}
639
640/*
641 * FUNCTION: snpac_flushifp
642 *
643 * PURPOSE: Flush entries associated with specific ifp
644 *
645 * RETURNS: nothing
646 *
647 * SIDE EFFECTS:
648 *
649 * NOTES:
650 */
4c45483e 651void
15637ed4
RG
652snpac_flushifp(ifp)
653struct ifnet *ifp;
654{
655 register struct llinfo_llc *lc;
656
657 for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = lc->lc_next) {
658 if (lc->lc_rt->rt_ifp == ifp && (lc->lc_flags & SNPA_VALID))
659 snpac_free(lc);
660 }
661}
662
663/*
664 * FUNCTION: snpac_rtrequest
665 *
666 * PURPOSE: Make a routing request
667 *
668 * RETURNS: nothing
669 *
670 * SIDE EFFECTS:
671 *
672 * NOTES: In the future, this should make a request of a user
673 * level routing daemon.
674 */
4c45483e 675void
15637ed4
RG
676snpac_rtrequest(req, host, gateway, netmask, flags, ret_nrt)
677int req;
678struct iso_addr *host;
679struct iso_addr *gateway;
680struct iso_addr *netmask;
681short flags;
682struct rtentry **ret_nrt;
683{
684 register struct iso_addr *r;
685
686 IFDEBUG(D_SNPA)
687 printf("snpac_rtrequest: ");
688 if (req == RTM_ADD)
689 printf("add");
690 else if (req == RTM_DELETE)
691 printf("delete");
692 else
693 printf("unknown command");
694 printf(" dst: %s\n", clnp_iso_addrp(host));
695 printf("\tgateway: %s\n", clnp_iso_addrp(gateway));
696 ENDDEBUG
697
698
699 zap_isoaddr(dst, host);
700 zap_isoaddr(gte, gateway);
701 if (netmask) {
702 zap_isoaddr(msk, netmask);
703 msk.siso_nlen = 0;
704 msk.siso_len = msk.siso_pad - (u_char *)&msk;
705 }
706
707 rtrequest(req, S(dst), S(gte), (netmask ? S(msk) : (struct sockaddr *)0),
708 flags, ret_nrt);
709}
710
711/*
712 * FUNCTION: snpac_addrt
713 *
714 * PURPOSE: Associate a routing entry with an snpac entry
715 *
716 * RETURNS: nothing
717 *
718 * SIDE EFFECTS:
719 *
720 * NOTES: If a cache entry exists for gateway, then
721 * make a routing entry (host, gateway) and associate
722 * with gateway.
723 *
724 * If a route already exists and is different, first delete
725 * it.
726 *
727 * This could be made more efficient by checking
728 * the existing route before adding a new one.
729 */
4c45483e 730void
15637ed4
RG
731snpac_addrt(ifp, host, gateway, netmask)
732struct ifnet *ifp;
733struct iso_addr *host, *gateway, *netmask;
734{
735 register struct iso_addr *r;
736
737 zap_isoaddr(dst, host);
738 zap_isoaddr(gte, gateway);
739 if (netmask) {
740 zap_isoaddr(msk, netmask);
741 msk.siso_nlen = 0;
742 msk.siso_len = msk.siso_pad - (u_char *)&msk;
743 rtredirect(S(dst), S(gte), S(msk), RTF_DONE, S(gte), 0);
744 } else
745 rtredirect(S(dst), S(gte), (struct sockaddr *)0,
746 RTF_DONE | RTF_HOST, S(gte), 0);
747}
748#endif ISO