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