Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / netiso / iso_snpac.c
blob52a89fc4f2469151546dd3bec6b269f95cc3743a
1 /* $NetBSD: iso_snpac.c,v 1.52 2008/11/07 00:20:18 dyoung Exp $ */
3 /*-
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
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.
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.
31 * @(#)iso_snpac.c 8.4 (Berkeley) 5/2/95
34 /***********************************************************
35 Copyright IBM Corporation 1987
37 All Rights Reserved
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.
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.
55 ******************************************************************/
58 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
61 #include <sys/cdefs.h>
62 __KERNEL_RCSID(0, "$NetBSD: iso_snpac.c,v 1.52 2008/11/07 00:20:18 dyoung Exp $");
64 #include "opt_iso.h"
65 #ifdef ISO
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 #include <sys/kauth.h>
81 #include <net/if.h>
82 #include <net/if_dl.h>
83 #include <net/route.h>
85 #include <net/if_ether.h>
87 #include <netinet/in.h>
89 #include <netiso/iso.h>
90 #include <netiso/iso_var.h>
91 #include <netiso/iso_snpac.h>
92 #include <netiso/clnp.h>
93 #include <netiso/clnp_stat.h>
94 #include <netiso/esis.h>
95 #include <netiso/argo_debug.h>
97 int iso_systype = SNPA_ES; /* default to be an ES */
99 LIST_HEAD(, llinfo_llc) llinfo_llc;
101 struct callout snpac_age_ch;
103 struct sockaddr_iso blank_siso = {
104 .siso_len = sizeof(blank_siso),
105 .siso_family = AF_ISO,
107 static struct sockaddr_iso
108 dst = {
109 .siso_len = sizeof(dst),
110 .siso_family = AF_ISO,
112 gte = {
113 .siso_len = sizeof(gte),
114 .siso_family = AF_ISO,
116 #if 0
117 src = {
118 .siso_len = sizeof(src),
119 .siso_family = AF_ISO,
121 #endif
122 msk = {
123 .siso_len = sizeof(msk),
124 .siso_family = AF_ISO,
126 zmk = {
127 .siso_len = 0,
130 #define zsi blank_siso
131 #define zero_isoa zsi.siso_addr
132 #define zap_isoaddr(a, b) {memset(&a.siso_addr, 0, sizeof(*r)); r = b; \
133 memmove(&a.siso_addr, r, 1 + (r)->isoa_len);}
134 #define S(x) ((struct sockaddr *)&(x))
136 static struct sockaddr_dl gte_dl;
138 static void snpac_fixdstandmask (int);
141 * We only keep track of a single IS at a time.
143 struct rtentry *known_is;
146 * Addresses taken from NBS agreements, December 1987.
148 * These addresses assume on-the-wire transmission of least significant
149 * bit first. This is the method used by 802.3. When these
150 * addresses are passed to the token ring driver, (802.5), they
151 * must be bit-swapped because 802.5 transmission order is MSb first.
153 * Furthermore, according to IBM Austin, these addresses are not
154 * true token ring multicast addresses. More work is necessary
155 * to get multicast to work right on token ring.
157 * Currently, the token ring driver does not handle multicast, so
158 * these addresses are converted into the broadcast address in
159 * lan_output() That means that if these multicast addresses change
160 * the token ring driver must be altered.
162 const char all_es_snpa[] = {0x09, 0x00, 0x2b, 0x00, 0x00, 0x04};
163 const char all_is_snpa[] = {0x09, 0x00, 0x2b, 0x00, 0x00, 0x05};
164 const char all_l1is_snpa[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x14};
165 const char all_l2is_snpa[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x15};
167 union sockunion {
168 struct sockaddr_iso siso;
169 struct sockaddr_dl sdl;
170 struct sockaddr sa;
174 * FUNCTION: llc_rtrequest
176 * PURPOSE: Manage routing table entries specific to LLC for ISO.
178 * NOTES: This does a lot of obscure magic;
180 void
181 llc_rtrequest(int req, struct rtentry *rt, const struct rt_addrinfo *info)
183 union sockunion *gate = (union sockunion *) rt->rt_gateway;
184 struct llinfo_llc *lc = (struct llinfo_llc *) rt->rt_llinfo;
185 struct ifnet *ifp = rt->rt_ifp;
186 int addrlen = ifp->if_addrlen;
187 #define LLC_SIZE 3 /* XXXXXX do this right later */
189 #ifdef ARGO_DEBUG
190 if (argo_debug[D_SNPA]) {
191 printf("llc_rtrequest(%d, %p, %p)\n", req, rt, info);
193 #endif
194 if (rt->rt_flags & RTF_GATEWAY)
195 return;
196 else
197 switch (req) {
198 case RTM_ADD:
200 * Case 1: This route may come from a route to iface with mask
201 * or from a default route.
203 if (rt->rt_flags & RTF_CLONING) {
204 union {
205 struct sockaddr sa;
206 struct sockaddr_dl sdl;
207 struct sockaddr_storage ss;
208 } u;
210 iso_setmcasts(ifp, req);
211 sockaddr_dl_init(&u.sdl, sizeof(u.ss),
212 ifp->if_index, ifp->if_type,
213 NULL, strlen(ifp->if_xname),
214 NULL, ifp->if_addrlen);
215 rt_setgate(rt, &u.sa);
216 return;
218 if (lc != 0)
219 return; /* happens on a route change */
220 /* FALLTHROUGH */
221 case RTM_RESOLVE:
223 * Case 2: This route may come from cloning, or a manual route
224 * add with a LL address.
226 if (gate->sdl.sdl_family != AF_LINK) {
227 log(LOG_DEBUG, "llc_rtrequest: got non-link non-gateway route\n");
228 break;
230 R_Malloc(lc, struct llinfo_llc *, sizeof(*lc));
231 rt->rt_llinfo = (void *) lc;
232 if (lc == 0) {
233 log(LOG_DEBUG, "llc_rtrequest: malloc failed\n");
234 break;
236 memset(lc, 0, sizeof(*lc));
237 lc->lc_rt = rt;
238 rt->rt_flags |= RTF_LLINFO;
239 LIST_INSERT_HEAD(&llinfo_llc, lc, lc_list);
240 if (gate->sdl.sdl_alen == sizeof(struct esis_req)
241 + addrlen) {
242 gate->sdl.sdl_alen -= sizeof(struct esis_req);
243 (void)memcpy(&lc->lc_er,
244 (const char *)CLLADDR(&gate->sdl) +
245 addrlen, sizeof(lc->lc_er));
246 } else if (gate->sdl.sdl_alen == addrlen)
247 lc->lc_flags = (SNPA_ES | SNPA_VALID | SNPA_PERM);
248 break;
249 case RTM_DELETE:
250 if (rt->rt_flags & RTF_CLONING)
251 iso_setmcasts(ifp, req);
252 if (lc == 0)
253 return;
254 LIST_REMOVE(lc, lc_list);
255 Free(lc);
256 rt->rt_llinfo = 0;
257 rt->rt_flags &= ~RTF_LLINFO;
258 break;
260 if (rt->rt_rmx.rmx_mtu == 0) {
261 rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu - LLC_SIZE;
266 * FUNCTION: iso_setmcasts
268 * PURPOSE: Enable/Disable ESIS/ISIS multicast reception on
269 * interfaces.
271 * NOTES: This also does a lot of obscure magic;
273 void
274 iso_setmcasts(struct ifnet *ifp, int req)
276 static const char * const addrlist[] =
277 {all_es_snpa, all_is_snpa, all_l1is_snpa, all_l2is_snpa, 0};
278 struct ifreq ifr;
279 const char *const *cpp;
281 (void)memset(&ifr, 0, sizeof(ifr));
282 for (cpp = addrlist; *cpp; cpp++) {
283 (void)memcpy(ifr.ifr_addr.sa_data, *cpp, 6);
284 if (req == RTM_ADD &&
285 (*ifp->if_ioctl)(ifp, SIOCADDMULTI, &ifr) != 0)
286 printf("iso_setmcasts: %s unable to add mcast\n",
287 ifp->if_xname);
288 else if (req == RTM_DELETE &&
289 (*ifp->if_ioctl)(ifp, SIOCDELMULTI, &ifr) != 0)
290 printf("iso_setmcasts: %s unable to delete mcast\n",
291 ifp->if_xname);
296 * FUNCTION: iso_snparesolve
298 * PURPOSE: Resolve an iso address into snpa address
300 * RETURNS: 0 if addr is resolved
301 * errno if addr is unknown
303 * SIDE EFFECTS:
305 * NOTES: Now that we have folded the snpa cache into the routing
306 * table, we know there is no snpa address known for this
307 * destination. If we know of a default IS, then the
308 * address of the IS is returned. If no IS is known,
309 * then return the multi-cast address for "all ES" for
310 * this interface.
312 * NB: the last case described above constitutes the
313 * query configuration function 9542, sec 6.5
314 * A mechanism is needed to prevent this function from
315 * being invoked if the system is an IS.
318 iso_snparesolve(
319 struct ifnet *ifp, /* outgoing interface */
320 const struct sockaddr_iso *dest, /* destination */
321 void * snpa, /* RESULT: snpa to be used */
322 int *snpa_len) /* RESULT: length of snpa */
324 struct llinfo_llc *sc; /* ptr to snpa table entry */
325 const char *found_snpa;
326 int addrlen;
329 * This hack allows us to send esis packets that have the destination
330 * snpa addresss embedded in the destination nsap address
332 if (dest->siso_data[0] == AFI_SNA) {
334 * This is a subnetwork address. Return it immediately
336 #ifdef ARGO_DEBUG
337 if (argo_debug[D_SNPA]) {
338 printf("iso_snparesolve: return SN address\n");
340 #endif
341 addrlen = dest->siso_nlen - 1; /* subtract size of AFI */
342 found_snpa = (const char *)dest->siso_data + 1;
344 * If we are an IS, we can't do much with the packet; Check
345 * if we know about an IS.
347 } else if (iso_systype != SNPA_IS && known_is != 0 &&
348 (sc = (struct llinfo_llc *) known_is->rt_llinfo) &&
349 (sc->lc_flags & SNPA_VALID)) {
350 const struct sockaddr_dl *sdl = satocsdl(known_is->rt_gateway);
351 found_snpa = CLLADDR(sdl);
352 addrlen = sdl->sdl_alen;
353 } else if (ifp->if_flags & IFF_BROADCAST) {
355 * no IS, no match. Return "all es" multicast address for
356 * this interface, as per Query Configuration Function (9542
357 * sec 6.5)
359 * Note: there is a potential problem here. If the destination
360 * is on the subnet and it does not respond with a ESH, but
361 * does send back a TP CC, a connection could be established
362 * where we always transmit the CLNP packet to "all es"
364 addrlen = ifp->if_addrlen;
365 found_snpa = (const char *) all_es_snpa;
366 } else
367 return (ENETUNREACH);
368 memcpy(snpa, found_snpa, *snpa_len = addrlen);
369 return (0);
374 * FUNCTION: snpac_free
376 * PURPOSE: free an entry in the iso address map table
378 * RETURNS: nothing
380 * SIDE EFFECTS:
382 * NOTES: If there is a route entry associated with cache
383 * entry, then delete that as well
385 void
386 snpac_free(
387 struct llinfo_llc *lc) /* entry to free */
389 struct rtentry *rt = lc->lc_rt;
391 if (known_is == rt)
392 known_is = 0;
393 if (rt && (rt->rt_flags & RTF_UP) &&
394 (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED))) {
395 RTFREE(rt);
396 rtrequest(RTM_DELETE, rt_getkey(rt), rt->rt_gateway,
397 rt_mask(rt), rt->rt_flags, NULL);
398 RTFREE(rt);
403 * FUNCTION: snpac_add
405 * PURPOSE: Add an entry to the snpa cache
407 * RETURNS:
409 * SIDE EFFECTS:
411 * NOTES: If entry already exists, then update holding time.
414 snpac_add(
415 struct ifnet *ifp, /* interface info is related to */
416 struct iso_addr *nsap, /* nsap to add */
417 void * snpa, /* translation */
418 int type, /* SNPA_IS or SNPA_ES */
419 u_short ht, /* holding time (in seconds) */
420 int nsellength) /* nsaps may differ only in trailing
421 * bytes */
423 struct llinfo_llc *lc;
424 struct rtentry *rt;
425 struct rtentry *mrt = 0;
426 struct iso_addr *r; /* for zap_isoaddr macro */
427 int snpalen = min(ifp->if_addrlen, MAX_SNPALEN);
428 int new_entry = 0, index = ifp->if_index, iftype = ifp->if_type;
430 #ifdef ARGO_DEBUG
431 if (argo_debug[D_SNPA]) {
432 printf("snpac_add(%p, %p, %p, %x, %x, %x)\n",
433 ifp, nsap, snpa, type, ht, nsellength);
435 #endif
436 zap_isoaddr(dst, nsap);
437 rt = rtalloc1(sisotosa(&dst), 0);
438 #ifdef ARGO_DEBUG
439 if (argo_debug[D_SNPA]) {
440 printf("snpac_add: rtalloc1 returns %p\n", rt);
442 #endif
443 if (rt == 0) {
444 struct sockaddr *netmask;
445 int flags;
446 add:
447 if (nsellength) {
448 netmask = sisotosa(&msk);
449 flags = RTF_UP;
450 snpac_fixdstandmask(nsellength);
451 } else {
452 netmask = 0;
453 flags = RTF_UP | RTF_HOST;
455 new_entry = 1;
456 sockaddr_dl_init(&gte_dl, sizeof(gte_dl), index, iftype,
457 NULL, 0, snpa, snpalen);
459 if (rtrequest(RTM_ADD, sisotosa(&dst), S(gte_dl), netmask,
460 flags, &mrt) || mrt == 0)
461 return (0);
462 rt = mrt;
463 rt->rt_refcnt--;
464 } else {
465 struct sockaddr_dl *sdl = satosdl(rt->rt_gateway);
466 rt->rt_refcnt--;
467 if ((rt->rt_flags & RTF_LLINFO) == 0)
468 goto add;
469 if (nsellength && (rt->rt_flags & RTF_HOST)) {
470 if (rt->rt_refcnt == 0) {
471 rtrequest(RTM_DELETE, sisotosa(&dst),
472 NULL, NULL, 0, NULL);
473 rt = 0;
474 goto add;
475 } else {
476 static struct iso_addr nsap2;
477 char *cp;
478 nsap2 = *nsap;
479 cp = nsap2.isoa_genaddr + nsap->isoa_len - nsellength;
480 while (cp < (char *) (1 + &nsap2))
481 *cp++ = 0;
482 (void) snpac_add(ifp, &nsap2, snpa, type, ht, nsellength);
485 if (sdl->sdl_family != AF_LINK || sdl->sdl_alen == 0) {
486 int old_sdl_len = sdl->sdl_len;
487 if (old_sdl_len < sizeof(*sdl)) {
488 log(LOG_DEBUG, "snpac_add: cant make room for lladdr\n");
489 return (0);
491 sockaddr_dl_init(sdl, sdl->sdl_len, index, iftype,
492 NULL, 0, snpa, snpalen);
493 new_entry = 1;
496 if ((lc = (struct llinfo_llc *) rt->rt_llinfo) == 0)
497 panic("snpac_rtrequest");
498 rt->rt_rmx.rmx_expire = ht + time_second;
499 lc->lc_flags = SNPA_VALID | type;
500 if ((type & SNPA_IS) && !(iso_systype & SNPA_IS))
501 snpac_logdefis(rt);
502 return (new_entry);
505 static void
506 snpac_fixdstandmask(int nsellength)
508 char *cp = msk.siso_data, *cplim;
510 cplim = cp + (dst.siso_nlen -= nsellength);
511 msk.siso_len = cplim - (char *) &msk;
512 msk.siso_nlen = 0;
513 while (cp < cplim)
514 *cp++ = -1;
515 while (cp < (char *) msk.siso_pad)
516 *cp++ = 0;
517 for (cp = dst.siso_data + dst.siso_nlen; cp < (char *) dst.siso_pad;)
518 *cp++ = 0;
522 * FUNCTION: snpac_ioctl
524 * PURPOSE: Set/Get the system type and esis parameters
526 * RETURNS: 0 on success, or unix error code
528 * SIDE EFFECTS:
530 * NOTES:
533 snpac_ioctl(
534 struct socket *so,
535 u_long cmd, /* ioctl to process */
536 void *data, /* data for the cmd */
537 struct lwp *l)
539 struct systype_req *rq = (struct systype_req *) data;
541 #ifdef ARGO_DEBUG
542 if (argo_debug[D_IOCTL]) {
543 if (cmd == SIOCSSTYPE)
544 printf("snpac_ioctl: cmd set, type x%x, ht %d, ct %d\n",
545 rq->sr_type, rq->sr_holdt, rq->sr_configt);
546 else
547 printf("snpac_ioctl: cmd get\n");
549 #endif
551 if (cmd == SIOCSSTYPE) {
552 int error;
554 if (l == NULL)
555 error = EACCES;
556 else
557 error = kauth_authorize_network(l->l_cred,
558 KAUTH_NETWORK_SOCKET,
559 KAUTH_REQ_NETWORK_SOCKET_SETPRIV, so,
560 KAUTH_ARG(cmd), NULL);
562 if (error)
563 return (error);
564 if ((rq->sr_type & (SNPA_ES | SNPA_IS)) == (SNPA_ES | SNPA_IS))
565 return (EINVAL);
566 if (rq->sr_type & SNPA_ES) {
567 iso_systype = SNPA_ES;
568 } else if (rq->sr_type & SNPA_IS) {
569 iso_systype = SNPA_IS;
570 } else {
571 return (EINVAL);
573 esis_holding_time = rq->sr_holdt;
574 esis_config_time = rq->sr_configt;
575 if (esis_esconfig_time != rq->sr_esconfigt) {
576 callout_stop(&esis_config_ch);
577 esis_esconfig_time = rq->sr_esconfigt;
578 esis_config(NULL);
580 } else if (cmd == SIOCGSTYPE) {
581 rq->sr_type = iso_systype;
582 rq->sr_holdt = esis_holding_time;
583 rq->sr_configt = esis_config_time;
584 rq->sr_esconfigt = esis_esconfig_time;
585 } else {
586 return (EINVAL);
588 return (0);
592 * FUNCTION: snpac_logdefis
594 * PURPOSE: Mark the IS passed as the default IS
596 * RETURNS: nothing
598 * SIDE EFFECTS:
600 * NOTES:
602 void
603 snpac_logdefis(struct rtentry *sc)
605 struct rtentry *rt;
607 if (known_is == sc || !(sc->rt_flags & RTF_HOST))
608 return;
609 if (known_is) {
610 RTFREE(known_is);
612 known_is = sc;
613 sc->rt_refcnt++;
614 rt = rtalloc1((struct sockaddr *) & zsi, 0);
615 if (rt == 0) {
616 rtrequest(RTM_ADD, sisotosa(&zsi), rt_getkey(sc),
617 sisotosa(&zmk), RTF_DYNAMIC | RTF_GATEWAY, NULL);
618 } else {
619 if ((rt->rt_flags & RTF_DYNAMIC) &&
620 (rt->rt_flags & RTF_GATEWAY) && rt_mask(rt)->sa_len == 0)
621 rt_setgate(rt, rt_getkey(sc));
626 * FUNCTION: snpac_age
628 * PURPOSE: Time out snpac entries
630 * RETURNS:
632 * SIDE EFFECTS:
634 * NOTES: When encountering an entry for the first time, snpac_age
635 * may delete up to SNPAC_AGE too many seconds. Ie.
636 * if the entry is added a moment before snpac_age is
637 * called, the entry will immediately have SNPAC_AGE
638 * seconds taken off the holding time, even though
639 * it has only been held a brief moment.
641 * The proper way to do this is set an expiry timeval
642 * equal to current time + holding time. Then snpac_age
643 * would time out entries where expiry date is older
644 * than the current time.
646 /*ARGSUSED*/
647 void
648 snpac_age(void *v)
650 struct llinfo_llc *lc, *nlc;
651 struct rtentry *rt;
653 callout_reset(&snpac_age_ch, SNPAC_AGE * hz, snpac_age, NULL);
655 for (lc = llinfo_llc.lh_first; lc != 0; lc = nlc) {
656 nlc = lc->lc_list.le_next;
657 if (lc->lc_flags & SNPA_VALID) {
658 rt = lc->lc_rt;
659 if (rt->rt_rmx.rmx_expire &&
660 rt->rt_rmx.rmx_expire < time_second)
661 snpac_free(lc);
667 * FUNCTION: snpac_ownmulti
669 * PURPOSE: Determine if the snpa address is a multicast address
670 * of the same type as the system.
672 * RETURNS: true or false
674 * SIDE EFFECTS:
676 * NOTES: Used by interface drivers when not in eavesdrop mode
677 * as interm kludge until
678 * real multicast addresses can be configured
681 snpac_ownmulti(void *snpa, u_int len)
683 return (((iso_systype & SNPA_ES) &&
684 (!memcmp(snpa, all_es_snpa, len))) ||
685 ((iso_systype & SNPA_IS) &&
686 (!memcmp(snpa, all_is_snpa, len))));
690 * FUNCTION: snpac_flushifp
692 * PURPOSE: Flush entries associated with specific ifp
694 * RETURNS: nothing
696 * SIDE EFFECTS:
698 * NOTES:
700 void
701 snpac_flushifp(struct ifnet *ifp)
703 struct llinfo_llc *lc;
705 for (lc = llinfo_llc.lh_first; lc != 0; lc = lc->lc_list.le_next) {
706 if (lc->lc_rt->rt_ifp == ifp && (lc->lc_flags & SNPA_VALID))
707 snpac_free(lc);
712 * FUNCTION: snpac_rtrequest
714 * PURPOSE: Make a routing request
716 * RETURNS: nothing
718 * SIDE EFFECTS:
720 * NOTES: In the future, this should make a request of a user
721 * level routing daemon.
723 void
724 snpac_rtrequest(int req, struct iso_addr *host, struct iso_addr *gateway,
725 struct iso_addr *netmask, int flags, struct rtentry **ret_nrt)
727 struct iso_addr *r;
729 #ifdef ARGO_DEBUG
730 if (argo_debug[D_SNPA]) {
731 printf("snpac_rtrequest: ");
732 if (req == RTM_ADD)
733 printf("add");
734 else if (req == RTM_DELETE)
735 printf("delete");
736 else
737 printf("unknown command");
738 printf(" dst: %s\n", clnp_iso_addrp(host));
739 printf("\tgateway: %s\n", clnp_iso_addrp(gateway));
741 #endif
744 zap_isoaddr(dst, host);
745 zap_isoaddr(gte, gateway);
746 if (netmask) {
747 zap_isoaddr(msk, netmask);
748 msk.siso_nlen = 0;
749 msk.siso_len = msk.siso_pad - (u_char *) & msk;
751 rtrequest(req, sisotosa(&dst), sisotosa(&gte),
752 (netmask ? sisotosa(&msk) : (struct sockaddr *) 0), flags, ret_nrt);
756 * FUNCTION: snpac_addrt
758 * PURPOSE: Associate a routing entry with an snpac entry
760 * RETURNS: nothing
762 * SIDE EFFECTS:
764 * NOTES: If a cache entry exists for gateway, then
765 * make a routing entry (host, gateway) and associate
766 * with gateway.
768 * If a route already exists and is different, first delete
769 * it.
771 * This could be made more efficient by checking
772 * the existing route before adding a new one.
774 void
775 snpac_addrt(struct ifnet *ifp, struct iso_addr *host,
776 struct iso_addr *gateway, struct iso_addr *netmask)
778 struct iso_addr *r;
780 zap_isoaddr(dst, host);
781 zap_isoaddr(gte, gateway);
782 if (netmask) {
783 zap_isoaddr(msk, netmask);
784 msk.siso_nlen = 0;
785 msk.siso_len = msk.siso_pad - (u_char *) & msk;
786 rtredirect(sisotosa(&dst), sisotosa(&gte), sisotosa(&msk),
787 RTF_DONE, sisotosa(&gte), 0);
788 } else
789 rtredirect(sisotosa(&dst), sisotosa(&gte), (struct sockaddr *) 0,
790 RTF_DONE | RTF_HOST, sisotosa(&gte), 0);
792 #endif /* ISO */