|
|
1.1 root 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:
62: Permission to use, copy, modify, and distribute this software and its
63: documentation for any purpose and without fee is hereby granted,
64: provided that the above copyright notice appear in all copies and that
65: both that copyright notice and this permission notice appear in
66: supporting documentation, and that the name of IBM not be
67: used in advertising or publicity pertaining to distribution of the
68: software without specific, written prior permission.
69:
70: IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
71: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
72: IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
73: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
74: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
75: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
76: SOFTWARE.
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:
110: int iso_systype = SNPA_ES; /* default to be an ES */
111: extern short esis_holding_time, esis_config_time, esis_esconfig_time;
112: extern struct timeval time;
113: extern void esis_config();
114: extern int hz;
115: static void snpac_fixdstandmask();
116:
117: struct sockaddr_iso blank_siso = {sizeof(blank_siso), AF_ISO};
118: extern u_long iso_hashchar();
119: static 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:
131: static struct sockaddr_dl blank_dl = {sizeof(blank_dl), AF_LINK};
132: static 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: */
139: struct 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: */
158: char all_es_snpa[] = { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x04 };
159: char all_is_snpa[] = { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x05 };
160: char all_l1is_snpa[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x14};
161: char all_l2is_snpa[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x15};
162:
163: union 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: */
176: llc_rtrequest(req, rt, sa)
177: int req;
178: register struct rtentry *rt;
179: struct 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: */
255: iso_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: */
304: iso_snparesolve(ifp, dest, snpa, snpa_len)
305: struct ifnet *ifp; /* outgoing interface */
306: struct sockaddr_iso *dest; /* destination */
307: caddr_t snpa; /* RESULT: snpa to be used */
308: int *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: */
369: snpac_free(lc)
370: register 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: */
397: snpac_add(ifp, nsap, snpa, type, ht, nsellength)
398: struct ifnet *ifp; /* interface info is related to */
399: struct iso_addr *nsap; /* nsap to add */
400: caddr_t snpa; /* translation */
401: char type; /* SNPA_IS or SNPA_ES */
402: u_short ht; /* holding time (in seconds) */
403: int 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((>e_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:
480: static void
481: snpac_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: */
507: snpac_ioctl (so, cmd, data)
508: struct socket *so;
509: int cmd; /* ioctl to process */
510: caddr_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: */
563: snpac_logdefis(sc)
564: register 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: */
609: void
610: snpac_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: */
641: snpac_ownmulti(snpa, len)
642: caddr_t snpa;
643: u_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: */
662: snpac_flushifp(ifp)
663: struct 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: */
685: snpac_rtrequest(req, host, gateway, netmask, flags, ret_nrt)
686: int req;
687: struct iso_addr *host;
688: struct iso_addr *gateway;
689: struct iso_addr *netmask;
690: short flags;
691: struct 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: */
739: snpac_addrt(ifp, host, gateway, netmask)
740: struct ifnet *ifp;
741: struct 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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.