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