1 /* $NetBSD: iso_snpac.c,v 1.30 2003/10/30 01:43:10 simonb 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.30 2003/10/30 01:43:10 simonb 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 __P((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 char all_es_snpa[] = {0x09, 0x00, 0x2b, 0x00, 0x00, 0x04};
148 char all_is_snpa[] = {0x09, 0x00, 0x2b, 0x00, 0x00, 0x05};
149 char all_l1is_snpa[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x14};
150 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(req, rt, info)
167 int req;
168 struct rtentry *rt;
169 struct rt_addrinfo *info;
170 {
171 union sockunion *gate = (union sockunion *) rt->rt_gateway;
172 struct llinfo_llc *lc = (struct llinfo_llc *) rt->rt_llinfo;
173 struct ifnet *ifp = rt->rt_ifp;
174 int addrlen = ifp->if_addrlen;
175 #define LLC_SIZE 3 /* XXXXXX do this right later */
176
177 #ifdef ARGO_DEBUG
178 if (argo_debug[D_SNPA]) {
179 printf("llc_rtrequest(%d, %p, %p)\n", req, rt, info);
180 }
181 #endif
182 if (rt->rt_flags & RTF_GATEWAY)
183 return;
184 else
185 switch (req) {
186 case RTM_ADD:
187 /*
188 * Case 1: This route may come from a route to iface with mask
189 * or from a default route.
190 */
191 if (rt->rt_flags & RTF_CLONING) {
192 iso_setmcasts(ifp, req);
193 rt_setgate(rt, rt_key(rt),
194 (struct sockaddr *) & blank_dl);
195 return;
196 }
197 if (lc != 0)
198 return; /* happens on a route change */
199 /* FALLTHROUGH */
200 case RTM_RESOLVE:
201 /*
202 * Case 2: This route may come from cloning, or a manual route
203 * add with a LL address.
204 */
205 if (gate->sdl.sdl_family != AF_LINK) {
206 log(LOG_DEBUG, "llc_rtrequest: got non-link non-gateway route\n");
207 break;
208 }
209 R_Malloc(lc, struct llinfo_llc *, sizeof(*lc));
210 rt->rt_llinfo = (caddr_t) lc;
211 if (lc == 0) {
212 log(LOG_DEBUG, "llc_rtrequest: malloc failed\n");
213 break;
214 }
215 Bzero(lc, sizeof(*lc));
216 lc->lc_rt = rt;
217 rt->rt_flags |= RTF_LLINFO;
218 LIST_INSERT_HEAD(&llinfo_llc, lc, lc_list);
219 if (gate->sdl.sdl_alen == sizeof(struct esis_req) + addrlen) {
220 gate->sdl.sdl_alen -= sizeof(struct esis_req);
221 bcopy(addrlen + LLADDR(&gate->sdl),
222 (caddr_t) & lc->lc_er, sizeof(lc->lc_er));
223 } else if (gate->sdl.sdl_alen == addrlen)
224 lc->lc_flags = (SNPA_ES | SNPA_VALID | SNPA_PERM);
225 break;
226 case RTM_DELETE:
227 if (rt->rt_flags & RTF_CLONING)
228 iso_setmcasts(ifp, req);
229 if (lc == 0)
230 return;
231 LIST_REMOVE(lc, lc_list);
232 Free(lc);
233 rt->rt_llinfo = 0;
234 rt->rt_flags &= ~RTF_LLINFO;
235 break;
236 }
237 if (rt->rt_rmx.rmx_mtu == 0) {
238 rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu - LLC_SIZE;
239 }
240 }
241
242 /*
243 * FUNCTION: iso_setmcasts
244 *
245 * PURPOSE: Enable/Disable ESIS/ISIS multicast reception on
246 * interfaces.
247 *
248 * NOTES: This also does a lot of obscure magic;
249 */
250 void
251 iso_setmcasts(ifp, req)
252 struct ifnet *ifp;
253 int req;
254 {
255 static char *addrlist[] =
256 {all_es_snpa, all_is_snpa, all_l1is_snpa, all_l2is_snpa, 0};
257 struct ifreq ifr;
258 caddr_t *cpp;
259
260 bzero((caddr_t) & ifr, sizeof(ifr));
261 for (cpp = (caddr_t *) addrlist; *cpp; cpp++) {
262 bcopy(*cpp, (caddr_t) ifr.ifr_addr.sa_data, 6);
263 if (req == RTM_ADD && (ifp->if_ioctl == 0 ||
264 (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr) != 0))
265 printf("iso_setmcasts: %s unable to add mcast\n",
266 ifp->if_xname);
267 else if (req == RTM_DELETE && (ifp->if_ioctl == 0 ||
268 (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr) != 0))
269 printf("iso_setmcasts: %s unable to delete mcast\n",
270 ifp->if_xname);
271 }
272 }
273
274 /*
275 * FUNCTION: iso_snparesolve
276 *
277 * PURPOSE: Resolve an iso address into snpa address
278 *
279 * RETURNS: 0 if addr is resolved
280 * errno if addr is unknown
281 *
282 * SIDE EFFECTS:
283 *
284 * NOTES: Now that we have folded the snpa cache into the routing
285 * table, we know there is no snpa address known for this
286 * destination. If we know of a default IS, then the
287 * address of the IS is returned. If no IS is known,
288 * then return the multi-cast address for "all ES" for
289 * this interface.
290 *
291 * NB: the last case described above constitutes the
292 * query configuration function 9542, sec 6.5
293 * A mechanism is needed to prevent this function from
294 * being invoked if the system is an IS.
295 */
296 int
297 iso_snparesolve(ifp, dest, snpa, snpa_len)
298 struct ifnet *ifp; /* outgoing interface */
299 struct sockaddr_iso *dest; /* destination */
300 caddr_t snpa; /* RESULT: snpa to be used */
301 int *snpa_len; /* RESULT: length of snpa */
302 {
303 struct llinfo_llc *sc; /* ptr to snpa table entry */
304 caddr_t found_snpa;
305 int addrlen;
306
307 /*
308 * This hack allows us to send esis packets that have the destination
309 * snpa addresss embedded in the destination nsap address
310 */
311 if (dest->siso_data[0] == AFI_SNA) {
312 /*
313 * This is a subnetwork address. Return it immediately
314 */
315 #ifdef ARGO_DEBUG
316 if (argo_debug[D_SNPA]) {
317 printf("iso_snparesolve: return SN address\n");
318 }
319 #endif
320 addrlen = dest->siso_nlen - 1; /* subtract size of AFI */
321 found_snpa = (caddr_t) dest->siso_data + 1;
322 /*
323 * If we are an IS, we can't do much with the packet; Check
324 * if we know about an IS.
325 */
326 } else if (iso_systype != SNPA_IS && known_is != 0 &&
327 (sc = (struct llinfo_llc *) known_is->rt_llinfo) &&
328 (sc->lc_flags & SNPA_VALID)) {
329 struct sockaddr_dl *sdl =
330 (struct sockaddr_dl *) (known_is->rt_gateway);
331 found_snpa = LLADDR(sdl);
332 addrlen = sdl->sdl_alen;
333 } else if (ifp->if_flags & IFF_BROADCAST) {
334 /*
335 * no IS, no match. Return "all es" multicast address for
336 * this interface, as per Query Configuration Function (9542
337 * sec 6.5)
338 *
339 * Note: there is a potential problem here. If the destination
340 * is on the subnet and it does not respond with a ESH, but
341 * does send back a TP CC, a connection could be established
342 * where we always transmit the CLNP packet to "all es"
343 */
344 addrlen = ifp->if_addrlen;
345 found_snpa = (caddr_t) all_es_snpa;
346 } else
347 return (ENETUNREACH);
348 bcopy(found_snpa, snpa, *snpa_len = addrlen);
349 return (0);
350 }
351
352
353 /*
354 * FUNCTION: snpac_free
355 *
356 * PURPOSE: free an entry in the iso address map table
357 *
358 * RETURNS: nothing
359 *
360 * SIDE EFFECTS:
361 *
362 * NOTES: If there is a route entry associated with cache
363 * entry, then delete that as well
364 */
365 void
366 snpac_free(lc)
367 struct llinfo_llc *lc; /* entry to free */
368 {
369 struct rtentry *rt = lc->lc_rt;
370
371 if (known_is == rt)
372 known_is = 0;
373 if (rt && (rt->rt_flags & RTF_UP) &&
374 (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED))) {
375 RTFREE(rt);
376 rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt),
377 rt->rt_flags, (struct rtentry **) 0);
378 RTFREE(rt);
379 }
380 }
381
382 /*
383 * FUNCTION: snpac_add
384 *
385 * PURPOSE: Add an entry to the snpa cache
386 *
387 * RETURNS:
388 *
389 * SIDE EFFECTS:
390 *
391 * NOTES: If entry already exists, then update holding time.
392 */
393 int
394 snpac_add(ifp, nsap, snpa, type, ht, nsellength)
395 struct ifnet *ifp; /* interface info is related to */
396 struct iso_addr *nsap; /* nsap to add */
397 caddr_t snpa; /* translation */
398 char type; /* SNPA_IS or SNPA_ES */
399 u_short ht; /* holding time (in seconds) */
400 int nsellength; /* nsaps may differ only in trailing
401 * bytes */
402 {
403 struct llinfo_llc *lc;
404 struct rtentry *rt;
405 struct rtentry *mrt = 0;
406 struct iso_addr *r; /* for zap_isoaddr macro */
407 int snpalen = min(ifp->if_addrlen, MAX_SNPALEN);
408 int new_entry = 0, index = ifp->if_index, iftype = ifp->if_type;
409
410 #ifdef ARGO_DEBUG
411 if (argo_debug[D_SNPA]) {
412 printf("snpac_add(%p, %p, %p, %x, %x, %x)\n",
413 ifp, nsap, snpa, type, ht, nsellength);
414 }
415 #endif
416 zap_isoaddr(dst, nsap);
417 rt = rtalloc1(sisotosa(&dst), 0);
418 #ifdef ARGO_DEBUG
419 if (argo_debug[D_SNPA]) {
420 printf("snpac_add: rtalloc1 returns %p\n", rt);
421 }
422 #endif
423 if (rt == 0) {
424 struct sockaddr *netmask;
425 int flags;
426 add:
427 if (nsellength) {
428 netmask = sisotosa(&msk);
429 flags = RTF_UP;
430 snpac_fixdstandmask(nsellength);
431 } else {
432 netmask = 0;
433 flags = RTF_UP | RTF_HOST;
434 }
435 new_entry = 1;
436 zap_linkaddr((>e_dl), snpa, snpalen, index);
437 gte_dl.sdl_type = iftype;
438 if (rtrequest(RTM_ADD, sisotosa(&dst), S(gte_dl), netmask,
439 flags, &mrt) || mrt == 0)
440 return (0);
441 rt = mrt;
442 rt->rt_refcnt--;
443 } else {
444 struct sockaddr_dl *sdl = (struct sockaddr_dl *) rt->rt_gateway;
445 rt->rt_refcnt--;
446 if ((rt->rt_flags & RTF_LLINFO) == 0)
447 goto add;
448 if (nsellength && (rt->rt_flags & RTF_HOST)) {
449 if (rt->rt_refcnt == 0) {
450 rtrequest(RTM_DELETE, sisotosa(&dst),
451 (struct sockaddr *) 0, (struct sockaddr *) 0,
452 0, (struct rtentry **) 0);
453 rt = 0;
454 goto add;
455 } else {
456 static struct iso_addr nsap2;
457 char *cp;
458 nsap2 = *nsap;
459 cp = nsap2.isoa_genaddr + nsap->isoa_len - nsellength;
460 while (cp < (char *) (1 + &nsap2))
461 *cp++ = 0;
462 (void) snpac_add(ifp, &nsap2, snpa, type, ht, nsellength);
463 }
464 }
465 if (sdl->sdl_family != AF_LINK || sdl->sdl_alen == 0) {
466 int old_sdl_len = sdl->sdl_len;
467 if (old_sdl_len < sizeof(*sdl)) {
468 log(LOG_DEBUG, "snpac_add: cant make room for lladdr\n");
469 return (0);
470 }
471 zap_linkaddr(sdl, snpa, snpalen, index);
472 sdl->sdl_len = old_sdl_len;
473 sdl->sdl_type = iftype;
474 new_entry = 1;
475 }
476 }
477 if ((lc = (struct llinfo_llc *) rt->rt_llinfo) == 0)
478 panic("snpac_rtrequest");
479 rt->rt_rmx.rmx_expire = ht + time.tv_sec;
480 lc->lc_flags = SNPA_VALID | type;
481 if ((type & SNPA_IS) && !(iso_systype & SNPA_IS))
482 snpac_logdefis(rt);
483 return (new_entry);
484 }
485
486 static void
487 snpac_fixdstandmask(nsellength)
488 int nsellength;
489 {
490 char *cp = msk.siso_data, *cplim;
491
492 cplim = cp + (dst.siso_nlen -= nsellength);
493 msk.siso_len = cplim - (char *) &msk;
494 msk.siso_nlen = 0;
495 while (cp < cplim)
496 *cp++ = -1;
497 while (cp < (char *) msk.siso_pad)
498 *cp++ = 0;
499 for (cp = dst.siso_data + dst.siso_nlen; cp < (char *) dst.siso_pad;)
500 *cp++ = 0;
501 }
502
503 /*
504 * FUNCTION: snpac_ioctl
505 *
506 * PURPOSE: Set/Get the system type and esis parameters
507 *
508 * RETURNS: 0 on success, or unix error code
509 *
510 * SIDE EFFECTS:
511 *
512 * NOTES:
513 */
514 int
515 snpac_ioctl(so, cmd, data, p)
516 struct socket *so;
517 u_long cmd; /* ioctl to process */
518 caddr_t data; /* data for the cmd */
519 struct proc *p;
520 {
521 struct systype_req *rq = (struct systype_req *) data;
522
523 #ifdef ARGO_DEBUG
524 if (argo_debug[D_IOCTL]) {
525 if (cmd == SIOCSSTYPE)
526 printf("snpac_ioctl: cmd set, type x%x, ht %d, ct %d\n",
527 rq->sr_type, rq->sr_holdt, rq->sr_configt);
528 else
529 printf("snpac_ioctl: cmd get\n");
530 }
531 #endif
532
533 if (cmd == SIOCSSTYPE) {
534 if (p == 0 || suser(p->p_ucred, &p->p_acflag))
535 return (EPERM);
536 if ((rq->sr_type & (SNPA_ES | SNPA_IS)) == (SNPA_ES | SNPA_IS))
537 return (EINVAL);
538 if (rq->sr_type & SNPA_ES) {
539 iso_systype = SNPA_ES;
540 } else if (rq->sr_type & SNPA_IS) {
541 iso_systype = SNPA_IS;
542 } else {
543 return (EINVAL);
544 }
545 esis_holding_time = rq->sr_holdt;
546 esis_config_time = rq->sr_configt;
547 if (esis_esconfig_time != rq->sr_esconfigt) {
548 callout_stop(&esis_config_ch);
549 esis_esconfig_time = rq->sr_esconfigt;
550 esis_config(NULL);
551 }
552 } else if (cmd == SIOCGSTYPE) {
553 rq->sr_type = iso_systype;
554 rq->sr_holdt = esis_holding_time;
555 rq->sr_configt = esis_config_time;
556 rq->sr_esconfigt = esis_esconfig_time;
557 } else {
558 return (EINVAL);
559 }
560 return (0);
561 }
562
563 /*
564 * FUNCTION: snpac_logdefis
565 *
566 * PURPOSE: Mark the IS passed as the default IS
567 *
568 * RETURNS: nothing
569 *
570 * SIDE EFFECTS:
571 *
572 * NOTES:
573 */
574 void
575 snpac_logdefis(sc)
576 struct rtentry *sc;
577 {
578 struct rtentry *rt;
579
580 if (known_is == sc || !(sc->rt_flags & RTF_HOST))
581 return;
582 if (known_is) {
583 RTFREE(known_is);
584 }
585 known_is = sc;
586 sc->rt_refcnt++;
587 rt = rtalloc1((struct sockaddr *) & zsi, 0);
588 if (rt == 0)
589 rtrequest(RTM_ADD, sisotosa(&zsi), rt_key(sc), sisotosa(&zmk),
590 RTF_DYNAMIC | RTF_GATEWAY, 0);
591 else {
592 if ((rt->rt_flags & RTF_DYNAMIC) &&
593 (rt->rt_flags & RTF_GATEWAY) && rt_mask(rt)->sa_len == 0)
594 rt_setgate(rt, rt_key(rt), rt_key(sc));
595 }
596 }
597
598 /*
599 * FUNCTION: snpac_age
600 *
601 * PURPOSE: Time out snpac entries
602 *
603 * RETURNS:
604 *
605 * SIDE EFFECTS:
606 *
607 * NOTES: When encountering an entry for the first time, snpac_age
608 * may delete up to SNPAC_AGE too many seconds. Ie.
609 * if the entry is added a moment before snpac_age is
610 * called, the entry will immediately have SNPAC_AGE
611 * seconds taken off the holding time, even though
612 * it has only been held a brief moment.
613 *
614 * The proper way to do this is set an expiry timeval
615 * equal to current time + holding time. Then snpac_age
616 * would time out entries where expiry date is older
617 * than the current time.
618 */
619 /*ARGSUSED*/
620 void
621 snpac_age(v)
622 void *v;
623 {
624 struct llinfo_llc *lc, *nlc;
625 struct rtentry *rt;
626
627 callout_reset(&snpac_age_ch, SNPAC_AGE * hz, snpac_age, NULL);
628
629 for (lc = llinfo_llc.lh_first; lc != 0; lc = nlc) {
630 nlc = lc->lc_list.le_next;
631 if (lc->lc_flags & SNPA_VALID) {
632 rt = lc->lc_rt;
633 if (rt->rt_rmx.rmx_expire && rt->rt_rmx.rmx_expire < time.tv_sec)
634 snpac_free(lc);
635 }
636 }
637 }
638
639 /*
640 * FUNCTION: snpac_ownmulti
641 *
642 * PURPOSE: Determine if the snpa address is a multicast address
643 * of the same type as the system.
644 *
645 * RETURNS: true or false
646 *
647 * SIDE EFFECTS:
648 *
649 * NOTES: Used by interface drivers when not in eavesdrop mode
650 * as interm kludge until
651 * real multicast addresses can be configured
652 */
653 int
654 snpac_ownmulti(snpa, len)
655 caddr_t snpa;
656 u_int len;
657 {
658 return (((iso_systype & SNPA_ES) &&
659 (!bcmp(snpa, (caddr_t) all_es_snpa, len))) ||
660 ((iso_systype & SNPA_IS) &&
661 (!bcmp(snpa, (caddr_t) all_is_snpa, len))));
662 }
663
664 /*
665 * FUNCTION: snpac_flushifp
666 *
667 * PURPOSE: Flush entries associated with specific ifp
668 *
669 * RETURNS: nothing
670 *
671 * SIDE EFFECTS:
672 *
673 * NOTES:
674 */
675 void
676 snpac_flushifp(ifp)
677 struct ifnet *ifp;
678 {
679 struct llinfo_llc *lc;
680
681 for (lc = llinfo_llc.lh_first; lc != 0; lc = lc->lc_list.le_next) {
682 if (lc->lc_rt->rt_ifp == ifp && (lc->lc_flags & SNPA_VALID))
683 snpac_free(lc);
684 }
685 }
686
687 /*
688 * FUNCTION: snpac_rtrequest
689 *
690 * PURPOSE: Make a routing request
691 *
692 * RETURNS: nothing
693 *
694 * SIDE EFFECTS:
695 *
696 * NOTES: In the future, this should make a request of a user
697 * level routing daemon.
698 */
699 void
700 snpac_rtrequest(req, host, gateway, netmask, flags, ret_nrt)
701 int req;
702 struct iso_addr *host;
703 struct iso_addr *gateway;
704 struct iso_addr *netmask;
705 short flags;
706 struct rtentry **ret_nrt;
707 {
708 struct iso_addr *r;
709
710 #ifdef ARGO_DEBUG
711 if (argo_debug[D_SNPA]) {
712 printf("snpac_rtrequest: ");
713 if (req == RTM_ADD)
714 printf("add");
715 else if (req == RTM_DELETE)
716 printf("delete");
717 else
718 printf("unknown command");
719 printf(" dst: %s\n", clnp_iso_addrp(host));
720 printf("\tgateway: %s\n", clnp_iso_addrp(gateway));
721 }
722 #endif
723
724
725 zap_isoaddr(dst, host);
726 zap_isoaddr(gte, gateway);
727 if (netmask) {
728 zap_isoaddr(msk, netmask);
729 msk.siso_nlen = 0;
730 msk.siso_len = msk.siso_pad - (u_char *) & msk;
731 }
732 rtrequest(req, sisotosa(&dst), sisotosa(>e),
733 (netmask ? sisotosa(&msk) : (struct sockaddr *) 0), flags, ret_nrt);
734 }
735
736 /*
737 * FUNCTION: snpac_addrt
738 *
739 * PURPOSE: Associate a routing entry with an snpac entry
740 *
741 * RETURNS: nothing
742 *
743 * SIDE EFFECTS:
744 *
745 * NOTES: If a cache entry exists for gateway, then
746 * make a routing entry (host, gateway) and associate
747 * with gateway.
748 *
749 * If a route already exists and is different, first delete
750 * it.
751 *
752 * This could be made more efficient by checking
753 * the existing route before adding a new one.
754 */
755 void
756 snpac_addrt(ifp, host, gateway, netmask)
757 struct ifnet *ifp;
758 struct iso_addr *host, *gateway, *netmask;
759 {
760 struct iso_addr *r;
761
762 zap_isoaddr(dst, host);
763 zap_isoaddr(gte, gateway);
764 if (netmask) {
765 zap_isoaddr(msk, netmask);
766 msk.siso_nlen = 0;
767 msk.siso_len = msk.siso_pad - (u_char *) & msk;
768 rtredirect(sisotosa(&dst), sisotosa(>e), sisotosa(&msk),
769 RTF_DONE, sisotosa(>e), 0);
770 } else
771 rtredirect(sisotosa(&dst), sisotosa(>e), (struct sockaddr *) 0,
772 RTF_DONE | RTF_HOST, sisotosa(>e), 0);
773 }
774 #endif /* ISO */
Cache object: af9f47bcea35da9f022b2ce772dff1e6
|