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