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