eonrtrequest should return void
[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 *
e05094a6 7 * @(#)iso_snpac.c 7.22 (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
e05094a6 225 if (ether_delmulti(&ifr, (struct arpcom *)ifp) == ENETRESET)
0f9efb57
KS
226 doreset++;
227 }
e05094a6
KS
228 if (doreset) {
229 if (ifp->if_reset)
230 (*ifp->if_reset)(ifp->if_unit);
231 else
232 printf("iso_setmcasts: %s%d needs reseting to receive iso mcasts\n",
233 ifp->if_name, ifp->if_unit);
234 }
0f9efb57 235}
600d71da
KS
236/*
237 * FUNCTION: iso_snparesolve
238 *
239 * PURPOSE: Resolve an iso address into snpa address
240 *
241 * RETURNS: 0 if addr is resolved
242 * errno if addr is unknown
243 *
244 * SIDE EFFECTS:
245 *
d910a5d6
KS
246 * NOTES: Now that we have folded the snpa cache into the routing
247 * table, we know there is no snpa address known for this
248 * destination. If we know of a default IS, then the address
249 * of the IS is returned. If no IS is known, then return the
250 * multi-cast address for "all ES" for this interface.
600d71da
KS
251 *
252 * NB: the last case described above constitutes the
253 * query configuration function 9542, sec 6.5
254 * A mechanism is needed to prevent this function from
255 * being invoked if the system is an IS.
256 */
a50e2bc0 257iso_snparesolve(ifp, dest, snpa, snpa_len)
d910a5d6
KS
258struct ifnet *ifp; /* outgoing interface */
259struct sockaddr_iso *dest; /* destination */
260caddr_t snpa; /* RESULT: snpa to be used */
261int *snpa_len; /* RESULT: length of snpa */
600d71da 262{
d910a5d6
KS
263 struct llinfo_llc *sc; /* ptr to snpa table entry */
264 caddr_t found_snpa;
265 int addrlen;
600d71da
KS
266
267 /*
268 * This hack allows us to send esis packets that have the destination snpa
269 * addresss embedded in the destination nsap address
270 */
d910a5d6 271 if (dest->siso_data[0] == AFI_SNA) {
600d71da
KS
272 /*
273 * This is a subnetwork address. Return it immediately
274 */
275 IFDEBUG(D_SNPA)
276 printf("iso_snparesolve: return SN address\n");
277 ENDDEBUG
d910a5d6
KS
278 addrlen = dest->siso_nlen - 1; /* subtract size of AFI */
279 found_snpa = (caddr_t) dest->siso_data + 1;
600d71da 280 /*
d910a5d6
KS
281 * If we are an IS, we can't do much with the packet;
282 * Check if we know about an IS.
600d71da 283 */
d910a5d6
KS
284 } else if (iso_systype != SNPA_IS && known_is != 0 &&
285 (sc = (struct llinfo_llc *)known_is->rt_llinfo) &&
286 (sc->lc_flags & SNPA_VALID)) {
287 register struct sockaddr_dl *sdl =
288 (struct sockaddr_dl *)(known_is->rt_gateway);
289 found_snpa = LLADDR(sdl);
290 addrlen = sdl->sdl_alen;
291 } else if (ifp->if_flags & IFF_BROADCAST) {
292 /*
293 * no IS, no match. Return "all es" multicast address for this
294 * interface, as per Query Configuration Function (9542 sec 6.5)
295 *
296 * Note: there is a potential problem here. If the destination
297 * is on the subnet and it does not respond with a ESH, but
298 * does send back a TP CC, a connection could be established
299 * where we always transmit the CLNP packet to "all es"
600d71da 300 */
d910a5d6
KS
301 addrlen = ifp->if_addrlen;
302 found_snpa = (caddr_t)all_es_snpa;
303 } else
304 return (ENETUNREACH);
305 bcopy(found_snpa, snpa, *snpa_len = addrlen);
600d71da 306 return (0);
600d71da
KS
307}
308
600d71da 309
600d71da
KS
310/*
311 * FUNCTION: snpac_free
312 *
313 * PURPOSE: free an entry in the iso address map table
314 *
315 * RETURNS: nothing
316 *
317 * SIDE EFFECTS:
318 *
319 * NOTES: If there is a route entry associated with cache
320 * entry, then delete that as well
321 */
d910a5d6
KS
322snpac_free(lc)
323register struct llinfo_llc *lc; /* entry to free */
600d71da 324{
d910a5d6 325 register struct rtentry *rt = lc->lc_rt;
a50e2bc0 326 register struct iso_addr *r;
600d71da 327
d910a5d6
KS
328 if (known_is == rt)
329 known_is = 0;
330 if (rt && (rt->rt_flags & RTF_UP) &&
331 (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED))) {
a50e2bc0
KS
332 RTFREE(rt);
333 rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt),
334 rt->rt_flags, (struct rtentry **)0);
a50e2bc0 335 RTFREE(rt);
600d71da 336 }
600d71da
KS
337}
338
339/*
340 * FUNCTION: snpac_add
341 *
342 * PURPOSE: Add an entry to the snpa cache
343 *
344 * RETURNS:
345 *
346 * SIDE EFFECTS:
347 *
348 * NOTES: If entry already exists, then update holding time.
349 */
c2bb180a 350snpac_add(ifp, nsap, snpa, type, ht, nsellength)
600d71da
KS
351struct ifnet *ifp; /* interface info is related to */
352struct iso_addr *nsap; /* nsap to add */
353caddr_t snpa; /* translation */
600d71da 354char type; /* SNPA_IS or SNPA_ES */
a50e2bc0 355u_short ht; /* holding time (in seconds) */
c2bb180a 356int nsellength; /* nsaps may differ only in trailing bytes */
600d71da 357{
d910a5d6 358 register struct llinfo_llc *lc;
c2bb180a
KS
359 register struct rtentry *rt;
360 struct rtentry *mrt = 0;
d910a5d6
KS
361 register struct iso_addr *r; /* for zap_isoaddr macro */
362 int snpalen = min(ifp->if_addrlen, MAX_SNPALEN);
02863b0e 363 int new_entry = 0, index = ifp->if_index, iftype = ifp->if_type;
d910a5d6 364
c2bb180a
KS
365 IFDEBUG(D_SNPA)
366 printf("snpac_add(%x, %x, %x, %x, %x, %x)\n",
367 ifp, nsap, snpa, type, ht, nsellength);
368 ENDDEBUG
d910a5d6
KS
369 zap_isoaddr(dst, nsap);
370 rt = rtalloc1(S(dst), 0);
c2bb180a
KS
371 IFDEBUG(D_SNPA)
372 printf("snpac_add: rtalloc1 returns %x\n", rt);
373 ENDDEBUG
d910a5d6 374 if (rt == 0) {
c2bb180a
KS
375 struct sockaddr *netmask;
376 int flags;
377 add:
378 if (nsellength) {
379 netmask = S(msk); flags = RTF_UP;
380 snpac_fixdstandmask(nsellength);
381 } else {
382 netmask = 0; flags = RTF_UP | RTF_HOST;
383 }
d910a5d6
KS
384 new_entry = 1;
385 zap_linkaddr((&gte_dl), snpa, snpalen, index);
02863b0e 386 gte_dl.sdl_type = iftype;
c2bb180a
KS
387 if (rtrequest(RTM_ADD, S(dst), S(gte_dl), netmask, flags, &mrt) ||
388 mrt == 0)
d910a5d6 389 return (0);
c2bb180a
KS
390 rt = mrt;
391 rt->rt_refcnt--;
d910a5d6
KS
392 } else {
393 register struct sockaddr_dl *sdl = (struct sockaddr_dl *)rt->rt_gateway;
c2bb180a
KS
394 rt->rt_refcnt--;
395 if ((rt->rt_flags & RTF_LLINFO) == 0)
396 goto add;
397 if (nsellength && (rt->rt_flags & RTF_HOST)) {
398 if (rt->rt_refcnt == 0) {
399 rtrequest(RTM_DELETE, S(dst), (struct sockaddr *)0,
400 (struct sockaddr *)0, 0, (struct rtentry *)0);
401 rt = 0;
402 goto add;
403 } else {
404 static struct iso_addr nsap2; register char *cp;
405 nsap2 = *nsap;
406 cp = nsap2.isoa_genaddr + nsap->isoa_len - nsellength;
407 while (cp < (char *)(1 + &nsap2))
408 *cp++ = 0;
409 (void) snpac_add(ifp, &nsap2, snpa, type, ht, nsellength);
410 }
411 }
d910a5d6
KS
412 if (sdl->sdl_family != AF_LINK || sdl->sdl_alen == 0) {
413 int old_sdl_len = sdl->sdl_len;
c2bb180a 414 if (old_sdl_len < sizeof(*sdl)) {
67bd0c50 415 log(LOG_DEBUG, "snpac_add: cant make room for lladdr\n");
d910a5d6 416 return (0);
c2bb180a 417 }
d910a5d6
KS
418 zap_linkaddr(sdl, snpa, snpalen, index);
419 sdl->sdl_len = old_sdl_len;
02863b0e 420 sdl->sdl_type = iftype;
d910a5d6
KS
421 new_entry = 1;
422 }
600d71da 423 }
c2bb180a
KS
424 if ((lc = (struct llinfo_llc *)rt->rt_llinfo) == 0)
425 panic("snpac_rtrequest");
cf9fbd7a 426 rt->rt_rmx.rmx_expire = ht + time.tv_sec;
d910a5d6 427 lc->lc_flags = SNPA_VALID | type;
1351f49f 428 if ((type & SNPA_IS) && !(iso_systype & SNPA_IS))
d910a5d6 429 snpac_logdefis(rt);
c2bb180a
KS
430 return (new_entry);
431}
432
cf9fbd7a
KS
433static void
434snpac_fixdstandmask(nsellength)
c2bb180a
KS
435{
436 register char *cp = msk.siso_data, *cplim;
437
438 cplim = cp + (dst.siso_nlen -= nsellength);
439 msk.siso_len = cplim - (char *)&msk;
440 msk.siso_nlen = 0;
441 while (cp < cplim)
442 *cp++ = -1;
443 while (cp < (char *)msk.siso_pad)
444 *cp++ = 0;
445 for (cp = dst.siso_data + dst.siso_nlen; cp < (char *)dst.siso_pad; )
446 *cp++ = 0;
600d71da
KS
447}
448
449/*
450 * FUNCTION: snpac_ioctl
451 *
600d71da
KS
452 * PURPOSE: Set/Get the system type and esis parameters
453 *
454 * RETURNS: 0 on success, or unix error code
455 *
456 * SIDE EFFECTS:
457 *
458 * NOTES:
459 */
cf9fbd7a
KS
460snpac_ioctl (so, cmd, data)
461struct socket *so;
600d71da
KS
462int cmd; /* ioctl to process */
463caddr_t data; /* data for the cmd */
464{
465 register struct systype_req *rq = (struct systype_req *)data;
600d71da 466
c2bb180a 467 IFDEBUG(D_IOCTL)
600d71da 468 if (cmd == SIOCSSTYPE)
d910a5d6 469 printf("snpac_ioctl: cmd set, type x%x, ht %d, ct %d\n",
600d71da
KS
470 rq->sr_type, rq->sr_holdt, rq->sr_configt);
471 else
d910a5d6 472 printf("snpac_ioctl: cmd get\n");
600d71da
KS
473 ENDDEBUG
474
475 if (cmd == SIOCSSTYPE) {
cf9fbd7a
KS
476 if ((so->so_state & SS_PRIV) == 0)
477 return (EPERM);
600d71da
KS
478 if ((rq->sr_type & (SNPA_ES|SNPA_IS)) == (SNPA_ES|SNPA_IS))
479 return(EINVAL);
480 if (rq->sr_type & SNPA_ES) {
481 iso_systype = SNPA_ES;
482 } else if (rq->sr_type & SNPA_IS) {
483 iso_systype = SNPA_IS;
484 } else {
485 return(EINVAL);
486 }
487 esis_holding_time = rq->sr_holdt;
488 esis_config_time = rq->sr_configt;
d12b96b5
KS
489 if (esis_esconfig_time != rq->sr_esconfigt) {
490 untimeout(esis_config, (caddr_t)0);
491 esis_esconfig_time = rq->sr_esconfigt;
492 esis_config();
493 }
600d71da
KS
494 } else if (cmd == SIOCGSTYPE) {
495 rq->sr_type = iso_systype;
496 rq->sr_holdt = esis_holding_time;
497 rq->sr_configt = esis_config_time;
d12b96b5 498 rq->sr_esconfigt = esis_esconfig_time;
600d71da 499 } else {
d910a5d6 500 return (EINVAL);
600d71da 501 }
d910a5d6 502 return (0);
600d71da
KS
503}
504
505/*
506 * FUNCTION: snpac_logdefis
507 *
508 * PURPOSE: Mark the IS passed as the default IS
509 *
510 * RETURNS: nothing
511 *
512 * SIDE EFFECTS:
513 *
514 * NOTES:
515 */
516snpac_logdefis(sc)
d910a5d6 517register struct rtentry *sc;
600d71da 518{
a50e2bc0 519 register struct iso_addr *r;
d910a5d6 520 register struct sockaddr_dl *sdl = (struct sockaddr_dl *)sc->rt_gateway;
1351f49f
KS
521 register struct rtentry *rt;
522
523 if (known_is == sc || !(sc->rt_flags & RTF_HOST))
a50e2bc0 524 return;
1351f49f
KS
525 if (known_is) {
526 RTFREE(known_is);
a50e2bc0 527 }
1351f49f
KS
528 known_is = sc;
529 sc->rt_refcnt++;
530 rt = rtalloc1((struct sockaddr *)&zsi, 0);
531 if (rt == 0)
532 rtrequest(RTM_ADD, S(zsi), rt_key(sc), S(zmk),
533 RTF_DYNAMIC|RTF_GATEWAY, 0);
534 else {
535 if ((rt->rt_flags & RTF_DYNAMIC) &&
536 (rt->rt_flags & RTF_GATEWAY) && rt_mask(rt)->sa_len == 0)
537 rt_setgate(rt, rt_key(rt), rt_key(sc));
600d71da 538 }
600d71da
KS
539}
540
541/*
542 * FUNCTION: snpac_age
543 *
544 * PURPOSE: Time out snpac entries
545 *
546 * RETURNS:
547 *
548 * SIDE EFFECTS:
549 *
550 * NOTES: When encountering an entry for the first time, snpac_age
551 * may delete up to SNPAC_AGE too many seconds. Ie.
552 * if the entry is added a moment before snpac_age is
553 * called, the entry will immediately have SNPAC_AGE
554 * seconds taken off the holding time, even though
555 * it has only been held a brief moment.
556 *
557 * The proper way to do this is set an expiry timeval
558 * equal to current time + holding time. Then snpac_age
559 * would time out entries where expiry date is older
560 * than the current time.
561 */
562snpac_age()
563{
cf9fbd7a
KS
564 register struct llinfo_llc *lc, *nlc;
565 register struct rtentry *rt;
600d71da
KS
566
567 timeout(snpac_age, (caddr_t)0, SNPAC_AGE * hz);
568
cf9fbd7a
KS
569 for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = nlc) {
570 nlc = lc->lc_next;
1351f49f 571 if (lc->lc_flags & SNPA_VALID) {
cf9fbd7a
KS
572 rt = lc->lc_rt;
573 if (rt->rt_rmx.rmx_expire && rt->rt_rmx.rmx_expire < time.tv_sec)
d910a5d6 574 snpac_free(lc);
600d71da
KS
575 }
576 }
577}
578
579/*
580 * FUNCTION: snpac_ownmulti
581 *
582 * PURPOSE: Determine if the snpa address is a multicast address
583 * of the same type as the system.
584 *
585 * RETURNS: true or false
586 *
587 * SIDE EFFECTS:
588 *
589 * NOTES: Used by interface drivers when not in eavesdrop mode
590 * as interm kludge until
591 * real multicast addresses can be configured
592 */
593snpac_ownmulti(snpa, len)
d910a5d6
KS
594caddr_t snpa;
595u_int len;
600d71da 596{
a50e2bc0 597 return (((iso_systype & SNPA_ES) &&
d910a5d6 598 (!bcmp(snpa, (caddr_t)all_es_snpa, len))) ||
a50e2bc0 599 ((iso_systype & SNPA_IS) &&
d910a5d6 600 (!bcmp(snpa, (caddr_t)all_is_snpa, len))));
600d71da
KS
601}
602
603/*
604 * FUNCTION: snpac_flushifp
605 *
606 * PURPOSE: Flush entries associated with specific ifp
607 *
608 * RETURNS: nothing
609 *
610 * SIDE EFFECTS:
611 *
612 * NOTES:
613 */
614snpac_flushifp(ifp)
615struct ifnet *ifp;
616{
d910a5d6 617 register struct llinfo_llc *lc;
600d71da 618
d910a5d6
KS
619 for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = lc->lc_next) {
620 if (lc->lc_rt->rt_ifp == ifp && (lc->lc_flags & SNPA_VALID))
621 snpac_free(lc);
600d71da
KS
622 }
623}
624
625/*
626 * FUNCTION: snpac_rtrequest
627 *
628 * PURPOSE: Make a routing request
629 *
630 * RETURNS: nothing
631 *
632 * SIDE EFFECTS:
633 *
634 * NOTES: In the future, this should make a request of a user
635 * level routing daemon.
636 */
a50e2bc0 637snpac_rtrequest(req, host, gateway, netmask, flags, ret_nrt)
600d71da 638int req;
a50e2bc0 639struct iso_addr *host;
600d71da 640struct iso_addr *gateway;
a50e2bc0 641struct iso_addr *netmask;
600d71da 642short flags;
a50e2bc0 643struct rtentry **ret_nrt;
600d71da 644{
a50e2bc0 645 register struct iso_addr *r;
600d71da
KS
646
647 IFDEBUG(D_SNPA)
648 printf("snpac_rtrequest: ");
a50e2bc0 649 if (req == RTM_ADD)
600d71da 650 printf("add");
a50e2bc0 651 else if (req == RTM_DELETE)
600d71da
KS
652 printf("delete");
653 else
654 printf("unknown command");
a50e2bc0 655 printf(" dst: %s\n", clnp_iso_addrp(host));
600d71da
KS
656 printf("\tgateway: %s\n", clnp_iso_addrp(gateway));
657 ENDDEBUG
658
600d71da 659
a50e2bc0
KS
660 zap_isoaddr(dst, host);
661 zap_isoaddr(gte, gateway);
c2bb180a
KS
662 if (netmask) {
663 zap_isoaddr(msk, netmask);
664 msk.siso_nlen = 0;
665 msk.siso_len = msk.siso_pad - (u_char *)&msk;
666 }
600d71da 667
a50e2bc0
KS
668 rtrequest(req, S(dst), S(gte), (netmask ? S(msk) : (struct sockaddr *)0),
669 flags, ret_nrt);
670}
600d71da
KS
671
672/*
673 * FUNCTION: snpac_addrt
674 *
675 * PURPOSE: Associate a routing entry with an snpac entry
676 *
677 * RETURNS: nothing
678 *
679 * SIDE EFFECTS:
680 *
681 * NOTES: If a cache entry exists for gateway, then
682 * make a routing entry (host, gateway) and associate
683 * with gateway.
684 *
685 * If a route already exists and is different, first delete
686 * it.
687 *
688 * This could be made more efficient by checking
689 * the existing route before adding a new one.
690 */
af8f5eff
KS
691snpac_addrt(ifp, host, gateway, netmask)
692struct ifnet *ifp;
693struct iso_addr *host, *gateway, *netmask;
600d71da 694{
a50e2bc0 695 register struct iso_addr *r;
600d71da 696
d910a5d6
KS
697 zap_isoaddr(dst, host);
698 zap_isoaddr(gte, gateway);
d910a5d6 699 if (netmask) {
c2bb180a
KS
700 zap_isoaddr(msk, netmask);
701 msk.siso_nlen = 0;
702 msk.siso_len = msk.siso_pad - (u_char *)&msk;
d910a5d6
KS
703 rtredirect(S(dst), S(gte), S(msk), RTF_DONE, S(gte), 0);
704 } else
705 rtredirect(S(dst), S(gte), (struct sockaddr *)0,
706 RTF_DONE | RTF_HOST, S(gte), 0);
600d71da
KS
707}
708#endif ISO