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