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