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