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