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