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