]> git.saurik.com Git - apple/xnu.git/blame_incremental - bsd/netiso/iso_snpac.c
xnu-201.42.3.tar.gz
[apple/xnu.git] / bsd / netiso / iso_snpac.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*-
23 * Copyright (c) 1991, 1993
24 * The Regents of the University of California. All rights reserved.
25 *
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions
28 * are met:
29 * 1. Redistributions of source code must retain the above copyright
30 * notice, this list of conditions and the following disclaimer.
31 * 2. Redistributions in binary form must reproduce the above copyright
32 * notice, this list of conditions and the following disclaimer in the
33 * documentation and/or other materials provided with the distribution.
34 * 3. All advertising materials mentioning features or use of this software
35 * must display the following acknowledgement:
36 * This product includes software developed by the University of
37 * California, Berkeley and its contributors.
38 * 4. Neither the name of the University nor the names of its contributors
39 * may be used to endorse or promote products derived from this software
40 * without specific prior written permission.
41 *
42 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52 * SUCH DAMAGE.
53 *
54 * @(#)iso_snpac.c 8.1 (Berkeley) 6/10/93
55 */
56
57/***********************************************************
58 Copyright IBM Corporation 1987
59
60 All Rights Reserved
61
62Permission to use, copy, modify, and distribute this software and its
63documentation for any purpose and without fee is hereby granted,
64provided that the above copyright notice appear in all copies and that
65both that copyright notice and this permission notice appear in
66supporting documentation, and that the name of IBM not be
67used in advertising or publicity pertaining to distribution of the
68software without specific, written prior permission.
69
70IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
71ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
72IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
73ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
74WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
75ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
76SOFTWARE.
77
78******************************************************************/
79
80/*
81 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
82 */
83
84#include <sys/param.h>
85#include <sys/systm.h>
86
87#if ISO
88#include <sys/mbuf.h>
89#include <sys/domain.h>
90#include <sys/protosw.h>
91#include <sys/socket.h>
92#include <sys/socketvar.h>
93#include <sys/errno.h>
94#include <sys/ioctl.h>
95#include <sys/syslog.h>
96#include <sys/malloc.h>
97
98#include <net/if.h>
99#include <net/if_dl.h>
100#include <net/route.h>
101
102#include <netiso/iso.h>
103#include <netiso/iso_var.h>
104#include <netiso/iso_snpac.h>
105#include <netiso/clnp.h>
106#include <netiso/clnp_stat.h>
107#include <netiso/esis.h>
108#include <netiso/argo_debug.h>
109
110int iso_systype = SNPA_ES; /* default to be an ES */
111extern short esis_holding_time, esis_config_time, esis_esconfig_time;
112extern struct timeval time;
113extern void esis_config();
114extern int hz;
115static void snpac_fixdstandmask();
116
117struct sockaddr_iso blank_siso = {sizeof(blank_siso), AF_ISO};
118extern u_long iso_hashchar();
119static struct sockaddr_iso
120 dst = {sizeof(dst), AF_ISO},
121 gte = {sizeof(dst), AF_ISO},
122 src = {sizeof(dst), AF_ISO},
123 msk = {sizeof(dst), AF_ISO},
124 zmk = {0};
125#define zsi blank_siso
126#define zero_isoa zsi.siso_addr
127#define zap_isoaddr(a, b) {Bzero(&a.siso_addr, sizeof(*r)); r = b; \
128 Bcopy(r, &a.siso_addr, 1 + (r)->isoa_len);}
129#define S(x) ((struct sockaddr *)&(x))
130
131static struct sockaddr_dl blank_dl = {sizeof(blank_dl), AF_LINK};
132static struct sockaddr_dl gte_dl;
133#define zap_linkaddr(a, b, c, i) \
134 (*a = blank_dl, bcopy(b, a->sdl_data, a->sdl_alen = c), a->sdl_index = i)
135
136/*
137 * We only keep track of a single IS at a time.
138 */
139struct rtentry *known_is;
140
141/*
142 * Addresses taken from NBS agreements, December 1987.
143 *
144 * These addresses assume on-the-wire transmission of least significant
145 * bit first. This is the method used by 802.3. When these
146 * addresses are passed to the token ring driver, (802.5), they
147 * must be bit-swaped because 802.5 transmission order is MSb first.
148 *
149 * Furthermore, according to IBM Austin, these addresses are not
150 * true token ring multicast addresses. More work is necessary
151 * to get multicast to work right on token ring.
152 *
153 * Currently, the token ring driver does not handle multicast, so
154 * these addresses are converted into the broadcast address in
155 * lan_output() That means that if these multicast addresses change
156 * the token ring driver must be altered.
157 */
158char all_es_snpa[] = { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x04 };
159char all_is_snpa[] = { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x05 };
160char all_l1is_snpa[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x14};
161char all_l2is_snpa[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x15};
162
163union sockunion {
164 struct sockaddr_iso siso;
165 struct sockaddr_dl sdl;
166 struct sockaddr sa;
167};
168
169/*
170 * FUNCTION: llc_rtrequest
171 *
172 * PURPOSE: Manage routing table entries specific to LLC for ISO.
173 *
174 * NOTES: This does a lot of obscure magic;
175 */
176llc_rtrequest(req, rt, sa)
177int req;
178register struct rtentry *rt;
179struct sockaddr *sa;
180{
181 register union sockunion *gate = (union sockunion *)rt->rt_gateway;
182 register struct llinfo_llc *lc = (struct llinfo_llc *)rt->rt_llinfo, *lc2;
183 struct rtentry *rt2;
184 struct ifnet *ifp = rt->rt_ifp;
185 int addrlen = ifp->if_addrlen;
186#define LLC_SIZE 3 /* XXXXXX do this right later */
187
188 IFDEBUG (D_SNPA)
189 printf("llc_rtrequest(%d, %x, %x)\n", req, rt, sa);
190 ENDDEBUG
191 if (rt->rt_flags & RTF_GATEWAY)
192 return;
193 else switch (req) {
194 case RTM_ADD:
195 /*
196 * Case 1: This route may come from a route to iface with mask
197 * or from a default route.
198 */
199 if (rt->rt_flags & RTF_CLONING) {
200 iso_setmcasts(ifp, req);
201 rt_setgate(rt, rt_key(rt), &blank_dl);
202 return;
203 }
204 if (lc != 0)
205 return; /* happens on a route change */
206 /* FALLTHROUGH */
207 case RTM_RESOLVE:
208 /*
209 * Case 2: This route may come from cloning, or a manual route
210 * add with a LL address.
211 */
212 if (gate->sdl.sdl_family != AF_LINK) {
213 log(LOG_DEBUG, "llc_rtrequest: got non-link non-gateway route\n");
214 break;
215 }
216 R_Malloc(lc, struct llinfo_llc *, sizeof (*lc));
217 rt->rt_llinfo = (caddr_t)lc;
218 if (lc == 0) {
219 log(LOG_DEBUG, "llc_rtrequest: malloc failed\n");
220 break;
221 }
222 Bzero(lc, sizeof(*lc));
223 lc->lc_rt = rt;
224 rt->rt_flags |= RTF_LLINFO;
225 insque(lc, &llinfo_llc);
226 if (gate->sdl.sdl_alen == sizeof(struct esis_req) + addrlen) {
227 gate->sdl.sdl_alen -= sizeof(struct esis_req);
228 bcopy(addrlen + LLADDR(&gate->sdl),
229 (caddr_t)&lc->lc_er, sizeof(lc->lc_er));
230 } else if (gate->sdl.sdl_alen == addrlen)
231 lc->lc_flags = (SNPA_ES | SNPA_VALID | SNPA_PERM);
232 break;
233 case RTM_DELETE:
234 if (rt->rt_flags & RTF_CLONING)
235 iso_setmcasts(ifp, req);
236 if (lc == 0)
237 return;
238 remque(lc);
239 Free(lc);
240 rt->rt_llinfo = 0;
241 rt->rt_flags &= ~RTF_LLINFO;
242 break;
243 }
244 if (rt->rt_rmx.rmx_mtu == 0) {
245 rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu - LLC_SIZE;
246 }
247}
248/*
249 * FUNCTION: iso_setmcasts
250 *
251 * PURPOSE: Enable/Disable ESIS/ISIS multicast reception on interfaces.
252 *
253 * NOTES: This also does a lot of obscure magic;
254 */
255iso_setmcasts(ifp, req)
256 struct ifnet *ifp;
257 int req;
258{
259 static char *addrlist[] =
260 { all_es_snpa, all_is_snpa, all_l1is_snpa, all_l2is_snpa, 0};
261 struct ifreq ifr;
262 register caddr_t *cpp;
263 int doreset = 0;
264
265 bzero((caddr_t)&ifr, sizeof(ifr));
266 for (cpp = (caddr_t *)addrlist; *cpp; cpp++) {
267 bcopy(*cpp, (caddr_t)ifr.ifr_addr.sa_data, 6);
268 if (req == RTM_ADD)
269 if (ether_addmulti(&ifr, (struct arpcom *)ifp) == ENETRESET)
270 doreset++;
271 else
272 if (ether_delmulti(&ifr, (struct arpcom *)ifp) == ENETRESET)
273 doreset++;
274 }
275 if (doreset) {
276 if (ifp->if_reset)
277 (*ifp->if_reset)(ifp->if_unit);
278 else
279 printf("iso_setmcasts: %s%d needs reseting to receive iso mcasts\n",
280 ifp->if_name, ifp->if_unit);
281 }
282}
283/*
284 * FUNCTION: iso_snparesolve
285 *
286 * PURPOSE: Resolve an iso address into snpa address
287 *
288 * RETURNS: 0 if addr is resolved
289 * errno if addr is unknown
290 *
291 * SIDE EFFECTS:
292 *
293 * NOTES: Now that we have folded the snpa cache into the routing
294 * table, we know there is no snpa address known for this
295 * destination. If we know of a default IS, then the address
296 * of the IS is returned. If no IS is known, then return the
297 * multi-cast address for "all ES" for this interface.
298 *
299 * NB: the last case described above constitutes the
300 * query configuration function 9542, sec 6.5
301 * A mechanism is needed to prevent this function from
302 * being invoked if the system is an IS.
303 */
304iso_snparesolve(ifp, dest, snpa, snpa_len)
305struct ifnet *ifp; /* outgoing interface */
306struct sockaddr_iso *dest; /* destination */
307caddr_t snpa; /* RESULT: snpa to be used */
308int *snpa_len; /* RESULT: length of snpa */
309{
310 struct llinfo_llc *sc; /* ptr to snpa table entry */
311 caddr_t found_snpa;
312 int addrlen;
313
314 /*
315 * This hack allows us to send esis packets that have the destination snpa
316 * addresss embedded in the destination nsap address
317 */
318 if (dest->siso_data[0] == AFI_SNA) {
319 /*
320 * This is a subnetwork address. Return it immediately
321 */
322 IFDEBUG(D_SNPA)
323 printf("iso_snparesolve: return SN address\n");
324 ENDDEBUG
325 addrlen = dest->siso_nlen - 1; /* subtract size of AFI */
326 found_snpa = (caddr_t) dest->siso_data + 1;
327 /*
328 * If we are an IS, we can't do much with the packet;
329 * Check if we know about an IS.
330 */
331 } else if (iso_systype != SNPA_IS && known_is != 0 &&
332 (sc = (struct llinfo_llc *)known_is->rt_llinfo) &&
333 (sc->lc_flags & SNPA_VALID)) {
334 register struct sockaddr_dl *sdl =
335 (struct sockaddr_dl *)(known_is->rt_gateway);
336 found_snpa = LLADDR(sdl);
337 addrlen = sdl->sdl_alen;
338 } else if (ifp->if_flags & IFF_BROADCAST) {
339 /*
340 * no IS, no match. Return "all es" multicast address for this
341 * interface, as per Query Configuration Function (9542 sec 6.5)
342 *
343 * Note: there is a potential problem here. If the destination
344 * is on the subnet and it does not respond with a ESH, but
345 * does send back a TP CC, a connection could be established
346 * where we always transmit the CLNP packet to "all es"
347 */
348 addrlen = ifp->if_addrlen;
349 found_snpa = (caddr_t)all_es_snpa;
350 } else
351 return (ENETUNREACH);
352 bcopy(found_snpa, snpa, *snpa_len = addrlen);
353 return (0);
354}
355
356
357/*
358 * FUNCTION: snpac_free
359 *
360 * PURPOSE: free an entry in the iso address map table
361 *
362 * RETURNS: nothing
363 *
364 * SIDE EFFECTS:
365 *
366 * NOTES: If there is a route entry associated with cache
367 * entry, then delete that as well
368 */
369snpac_free(lc)
370register struct llinfo_llc *lc; /* entry to free */
371{
372 register struct rtentry *rt = lc->lc_rt;
373 register struct iso_addr *r;
374
375 if (known_is == rt)
376 known_is = 0;
377 if (rt && (rt->rt_flags & RTF_UP) &&
378 (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED))) {
379 RTFREE(rt);
380 rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt),
381 rt->rt_flags, (struct rtentry **)0);
382 RTFREE(rt);
383 }
384}
385
386/*
387 * FUNCTION: snpac_add
388 *
389 * PURPOSE: Add an entry to the snpa cache
390 *
391 * RETURNS:
392 *
393 * SIDE EFFECTS:
394 *
395 * NOTES: If entry already exists, then update holding time.
396 */
397snpac_add(ifp, nsap, snpa, type, ht, nsellength)
398struct ifnet *ifp; /* interface info is related to */
399struct iso_addr *nsap; /* nsap to add */
400caddr_t snpa; /* translation */
401char type; /* SNPA_IS or SNPA_ES */
402u_short ht; /* holding time (in seconds) */
403int nsellength; /* nsaps may differ only in trailing bytes */
404{
405 register struct llinfo_llc *lc;
406 register struct rtentry *rt;
407 struct rtentry *mrt = 0;
408 register struct iso_addr *r; /* for zap_isoaddr macro */
409 int snpalen = min(ifp->if_addrlen, MAX_SNPALEN);
410 int new_entry = 0, index = ifp->if_index, iftype = ifp->if_type;
411
412 IFDEBUG(D_SNPA)
413 printf("snpac_add(%x, %x, %x, %x, %x, %x)\n",
414 ifp, nsap, snpa, type, ht, nsellength);
415 ENDDEBUG
416 zap_isoaddr(dst, nsap);
417 rt = rtalloc1(S(dst), 0);
418 IFDEBUG(D_SNPA)
419 printf("snpac_add: rtalloc1 returns %x\n", rt);
420 ENDDEBUG
421 if (rt == 0) {
422 struct sockaddr *netmask;
423 int flags;
424 add:
425 if (nsellength) {
426 netmask = S(msk); flags = RTF_UP;
427 snpac_fixdstandmask(nsellength);
428 } else {
429 netmask = 0; flags = RTF_UP | RTF_HOST;
430 }
431 new_entry = 1;
432 zap_linkaddr((&gte_dl), snpa, snpalen, index);
433 gte_dl.sdl_type = iftype;
434 if (rtrequest(RTM_ADD, S(dst), S(gte_dl), netmask, flags, &mrt) ||
435 mrt == 0)
436 return (0);
437 rt = mrt;
438 rt->rt_refcnt--;
439 } else {
440 register struct sockaddr_dl *sdl = (struct sockaddr_dl *)rt->rt_gateway;
441 rt->rt_refcnt--;
442 if ((rt->rt_flags & RTF_LLINFO) == 0)
443 goto add;
444 if (nsellength && (rt->rt_flags & RTF_HOST)) {
445 if (rt->rt_refcnt == 0) {
446 rtrequest(RTM_DELETE, S(dst), (struct sockaddr *)0,
447 (struct sockaddr *)0, 0, (struct rtentry *)0);
448 rt = 0;
449 goto add;
450 } else {
451 static struct iso_addr nsap2; register char *cp;
452 nsap2 = *nsap;
453 cp = nsap2.isoa_genaddr + nsap->isoa_len - nsellength;
454 while (cp < (char *)(1 + &nsap2))
455 *cp++ = 0;
456 (void) snpac_add(ifp, &nsap2, snpa, type, ht, nsellength);
457 }
458 }
459 if (sdl->sdl_family != AF_LINK || sdl->sdl_alen == 0) {
460 int old_sdl_len = sdl->sdl_len;
461 if (old_sdl_len < sizeof(*sdl)) {
462 log(LOG_DEBUG, "snpac_add: cant make room for lladdr\n");
463 return (0);
464 }
465 zap_linkaddr(sdl, snpa, snpalen, index);
466 sdl->sdl_len = old_sdl_len;
467 sdl->sdl_type = iftype;
468 new_entry = 1;
469 }
470 }
471 if ((lc = (struct llinfo_llc *)rt->rt_llinfo) == 0)
472 panic("snpac_rtrequest");
473 rt->rt_rmx.rmx_expire = ht + time.tv_sec;
474 lc->lc_flags = SNPA_VALID | type;
475 if ((type & SNPA_IS) && !(iso_systype & SNPA_IS))
476 snpac_logdefis(rt);
477 return (new_entry);
478}
479
480static void
481snpac_fixdstandmask(nsellength)
482{
483 register char *cp = msk.siso_data, *cplim;
484
485 cplim = cp + (dst.siso_nlen -= nsellength);
486 msk.siso_len = cplim - (char *)&msk;
487 msk.siso_nlen = 0;
488 while (cp < cplim)
489 *cp++ = -1;
490 while (cp < (char *)msk.siso_pad)
491 *cp++ = 0;
492 for (cp = dst.siso_data + dst.siso_nlen; cp < (char *)dst.siso_pad; )
493 *cp++ = 0;
494}
495
496/*
497 * FUNCTION: snpac_ioctl
498 *
499 * PURPOSE: Set/Get the system type and esis parameters
500 *
501 * RETURNS: 0 on success, or unix error code
502 *
503 * SIDE EFFECTS:
504 *
505 * NOTES:
506 */
507snpac_ioctl (so, cmd, data)
508struct socket *so;
509int cmd; /* ioctl to process */
510caddr_t data; /* data for the cmd */
511{
512 register struct systype_req *rq = (struct systype_req *)data;
513
514 IFDEBUG(D_IOCTL)
515 if (cmd == SIOCSSTYPE)
516 printf("snpac_ioctl: cmd set, type x%x, ht %d, ct %d\n",
517 rq->sr_type, rq->sr_holdt, rq->sr_configt);
518 else
519 printf("snpac_ioctl: cmd get\n");
520 ENDDEBUG
521
522 if (cmd == SIOCSSTYPE) {
523 if ((so->so_state & SS_PRIV) == 0)
524 return (EPERM);
525 if ((rq->sr_type & (SNPA_ES|SNPA_IS)) == (SNPA_ES|SNPA_IS))
526 return(EINVAL);
527 if (rq->sr_type & SNPA_ES) {
528 iso_systype = SNPA_ES;
529 } else if (rq->sr_type & SNPA_IS) {
530 iso_systype = SNPA_IS;
531 } else {
532 return(EINVAL);
533 }
534 esis_holding_time = rq->sr_holdt;
535 esis_config_time = rq->sr_configt;
536 if (esis_esconfig_time != rq->sr_esconfigt) {
537 untimeout(esis_config, (caddr_t)0);
538 esis_esconfig_time = rq->sr_esconfigt;
539 esis_config();
540 }
541 } else if (cmd == SIOCGSTYPE) {
542 rq->sr_type = iso_systype;
543 rq->sr_holdt = esis_holding_time;
544 rq->sr_configt = esis_config_time;
545 rq->sr_esconfigt = esis_esconfig_time;
546 } else {
547 return (EINVAL);
548 }
549 return (0);
550}
551
552/*
553 * FUNCTION: snpac_logdefis
554 *
555 * PURPOSE: Mark the IS passed as the default IS
556 *
557 * RETURNS: nothing
558 *
559 * SIDE EFFECTS:
560 *
561 * NOTES:
562 */
563snpac_logdefis(sc)
564register struct rtentry *sc;
565{
566 register struct iso_addr *r;
567 register struct sockaddr_dl *sdl = (struct sockaddr_dl *)sc->rt_gateway;
568 register struct rtentry *rt;
569
570 if (known_is == sc || !(sc->rt_flags & RTF_HOST))
571 return;
572 if (known_is) {
573 RTFREE(known_is);
574 }
575 known_is = sc;
576 RTHOLD(sc);
577 rt = rtalloc1((struct sockaddr *)&zsi, 0);
578 if (rt == 0)
579 rtrequest(RTM_ADD, S(zsi), rt_key(sc), S(zmk),
580 RTF_DYNAMIC|RTF_GATEWAY, 0);
581 else {
582 if ((rt->rt_flags & RTF_DYNAMIC) &&
583 (rt->rt_flags & RTF_GATEWAY) && rt_mask(rt)->sa_len == 0)
584 rt_setgate(rt, rt_key(rt), rt_key(sc));
585 }
586}
587
588/*
589 * FUNCTION: snpac_age
590 *
591 * PURPOSE: Time out snpac entries
592 *
593 * RETURNS:
594 *
595 * SIDE EFFECTS:
596 *
597 * NOTES: When encountering an entry for the first time, snpac_age
598 * may delete up to SNPAC_AGE too many seconds. Ie.
599 * if the entry is added a moment before snpac_age is
600 * called, the entry will immediately have SNPAC_AGE
601 * seconds taken off the holding time, even though
602 * it has only been held a brief moment.
603 *
604 * The proper way to do this is set an expiry timeval
605 * equal to current time + holding time. Then snpac_age
606 * would time out entries where expiry date is older
607 * than the current time.
608 */
609void
610snpac_age()
611{
612 register struct llinfo_llc *lc, *nlc;
613 register struct rtentry *rt;
614
615 timeout(snpac_age, (caddr_t)0, SNPAC_AGE * hz);
616
617 for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = nlc) {
618 nlc = lc->lc_next;
619 if (lc->lc_flags & SNPA_VALID) {
620 rt = lc->lc_rt;
621 if (rt->rt_rmx.rmx_expire && rt->rt_rmx.rmx_expire < time.tv_sec)
622 snpac_free(lc);
623 }
624 }
625}
626
627/*
628 * FUNCTION: snpac_ownmulti
629 *
630 * PURPOSE: Determine if the snpa address is a multicast address
631 * of the same type as the system.
632 *
633 * RETURNS: true or false
634 *
635 * SIDE EFFECTS:
636 *
637 * NOTES: Used by interface drivers when not in eavesdrop mode
638 * as interm kludge until
639 * real multicast addresses can be configured
640 */
641snpac_ownmulti(snpa, len)
642caddr_t snpa;
643u_int len;
644{
645 return (((iso_systype & SNPA_ES) &&
646 (!bcmp(snpa, (caddr_t)all_es_snpa, len))) ||
647 ((iso_systype & SNPA_IS) &&
648 (!bcmp(snpa, (caddr_t)all_is_snpa, len))));
649}
650
651/*
652 * FUNCTION: snpac_flushifp
653 *
654 * PURPOSE: Flush entries associated with specific ifp
655 *
656 * RETURNS: nothing
657 *
658 * SIDE EFFECTS:
659 *
660 * NOTES:
661 */
662snpac_flushifp(ifp)
663struct ifnet *ifp;
664{
665 register struct llinfo_llc *lc;
666
667 for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = lc->lc_next) {
668 if (lc->lc_rt->rt_ifp == ifp && (lc->lc_flags & SNPA_VALID))
669 snpac_free(lc);
670 }
671}
672
673/*
674 * FUNCTION: snpac_rtrequest
675 *
676 * PURPOSE: Make a routing request
677 *
678 * RETURNS: nothing
679 *
680 * SIDE EFFECTS:
681 *
682 * NOTES: In the future, this should make a request of a user
683 * level routing daemon.
684 */
685snpac_rtrequest(req, host, gateway, netmask, flags, ret_nrt)
686int req;
687struct iso_addr *host;
688struct iso_addr *gateway;
689struct iso_addr *netmask;
690short flags;
691struct rtentry **ret_nrt;
692{
693 register struct iso_addr *r;
694
695 IFDEBUG(D_SNPA)
696 printf("snpac_rtrequest: ");
697 if (req == RTM_ADD)
698 printf("add");
699 else if (req == RTM_DELETE)
700 printf("delete");
701 else
702 printf("unknown command");
703 printf(" dst: %s\n", clnp_iso_addrp(host));
704 printf("\tgateway: %s\n", clnp_iso_addrp(gateway));
705 ENDDEBUG
706
707
708 zap_isoaddr(dst, host);
709 zap_isoaddr(gte, gateway);
710 if (netmask) {
711 zap_isoaddr(msk, netmask);
712 msk.siso_nlen = 0;
713 msk.siso_len = msk.siso_pad - (u_char *)&msk;
714 }
715
716 rtrequest(req, S(dst), S(gte), (netmask ? S(msk) : (struct sockaddr *)0),
717 flags, ret_nrt);
718}
719
720/*
721 * FUNCTION: snpac_addrt
722 *
723 * PURPOSE: Associate a routing entry with an snpac entry
724 *
725 * RETURNS: nothing
726 *
727 * SIDE EFFECTS:
728 *
729 * NOTES: If a cache entry exists for gateway, then
730 * make a routing entry (host, gateway) and associate
731 * with gateway.
732 *
733 * If a route already exists and is different, first delete
734 * it.
735 *
736 * This could be made more efficient by checking
737 * the existing route before adding a new one.
738 */
739snpac_addrt(ifp, host, gateway, netmask)
740struct ifnet *ifp;
741struct iso_addr *host, *gateway, *netmask;
742{
743 register struct iso_addr *r;
744
745 zap_isoaddr(dst, host);
746 zap_isoaddr(gte, gateway);
747 if (netmask) {
748 zap_isoaddr(msk, netmask);
749 msk.siso_nlen = 0;
750 msk.siso_len = msk.siso_pad - (u_char *)&msk;
751 rtredirect(S(dst), S(gte), S(msk), RTF_DONE, S(gte), 0);
752 } else
753 rtredirect(S(dst), S(gte), (struct sockaddr *)0,
754 RTF_DONE | RTF_HOST, S(gte), 0);
755}
756#endif /* ISO */