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