]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netiso/iso_snpac.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1991, 1993
24 * The Regents of the University of California. All rights reserved.
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions
29 * 1. Redistributions of source code must retain the above copyright
30 * notice, this list of conditions and the following disclaimer.
31 * 2. Redistributions in binary form must reproduce the above copyright
32 * notice, this list of conditions and the following disclaimer in the
33 * documentation and/or other materials provided with the distribution.
34 * 3. All advertising materials mentioning features or use of this software
35 * must display the following acknowledgement:
36 * This product includes software developed by the University of
37 * California, Berkeley and its contributors.
38 * 4. Neither the name of the University nor the names of its contributors
39 * may be used to endorse or promote products derived from this software
40 * without specific prior written permission.
42 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * @(#)iso_snpac.c 8.1 (Berkeley) 6/10/93
57 /***********************************************************
58 Copyright IBM Corporation 1987
62 Permission to use, copy, modify, and distribute this software and its
63 documentation for any purpose and without fee is hereby granted,
64 provided that the above copyright notice appear in all copies and that
65 both that copyright notice and this permission notice appear in
66 supporting documentation, and that the name of IBM not be
67 used in advertising or publicity pertaining to distribution of the
68 software without specific, written prior permission.
70 IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
71 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
72 IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
73 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
74 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
75 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
78 ******************************************************************/
81 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
84 #include <sys/param.h>
85 #include <sys/systm.h>
89 #include <sys/domain.h>
90 #include <sys/protosw.h>
91 #include <sys/socket.h>
92 #include <sys/socketvar.h>
93 #include <sys/errno.h>
94 #include <sys/ioctl.h>
95 #include <sys/syslog.h>
96 #include <sys/malloc.h>
99 #include <net/if_dl.h>
100 #include <net/route.h>
102 #include <netiso/iso.h>
103 #include <netiso/iso_var.h>
104 #include <netiso/iso_snpac.h>
105 #include <netiso/clnp.h>
106 #include <netiso/clnp_stat.h>
107 #include <netiso/esis.h>
108 #include <netiso/argo_debug.h>
110 int iso_systype
= SNPA_ES
; /* default to be an ES */
111 extern short esis_holding_time
, esis_config_time
, esis_esconfig_time
;
112 extern struct timeval time
;
113 extern void esis_config();
115 static void snpac_fixdstandmask();
117 struct sockaddr_iso blank_siso
= {sizeof(blank_siso
), AF_ISO
};
118 extern u_long
iso_hashchar();
119 static struct sockaddr_iso
120 dst
= {sizeof(dst
), AF_ISO
},
121 gte
= {sizeof(dst
), AF_ISO
},
122 src
= {sizeof(dst
), AF_ISO
},
123 msk
= {sizeof(dst
), AF_ISO
},
125 #define zsi blank_siso
126 #define zero_isoa zsi.siso_addr
127 #define zap_isoaddr(a, b) {Bzero(&a.siso_addr, sizeof(*r)); r = b; \
128 Bcopy(r, &a.siso_addr, 1 + (r)->isoa_len);}
129 #define S(x) ((struct sockaddr *)&(x))
131 static struct sockaddr_dl blank_dl
= {sizeof(blank_dl
), AF_LINK
};
132 static struct sockaddr_dl gte_dl
;
133 #define zap_linkaddr(a, b, c, i) \
134 (*a = blank_dl, bcopy(b, a->sdl_data, a->sdl_alen = c), a->sdl_index = i)
137 * We only keep track of a single IS at a time.
139 struct rtentry
*known_is
;
142 * Addresses taken from NBS agreements, December 1987.
144 * These addresses assume on-the-wire transmission of least significant
145 * bit first. This is the method used by 802.3. When these
146 * addresses are passed to the token ring driver, (802.5), they
147 * must be bit-swaped because 802.5 transmission order is MSb first.
149 * Furthermore, according to IBM Austin, these addresses are not
150 * true token ring multicast addresses. More work is necessary
151 * to get multicast to work right on token ring.
153 * Currently, the token ring driver does not handle multicast, so
154 * these addresses are converted into the broadcast address in
155 * lan_output() That means that if these multicast addresses change
156 * the token ring driver must be altered.
158 char all_es_snpa
[] = { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x04 };
159 char all_is_snpa
[] = { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x05 };
160 char all_l1is_snpa
[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x14};
161 char all_l2is_snpa
[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x15};
164 struct sockaddr_iso siso
;
165 struct sockaddr_dl sdl
;
170 * FUNCTION: llc_rtrequest
172 * PURPOSE: Manage routing table entries specific to LLC for ISO.
174 * NOTES: This does a lot of obscure magic;
176 llc_rtrequest(req
, rt
, sa
)
178 register struct rtentry
*rt
;
181 register union sockunion
*gate
= (union sockunion
*)rt
->rt_gateway
;
182 register struct llinfo_llc
*lc
= (struct llinfo_llc
*)rt
->rt_llinfo
, *lc2
;
184 struct ifnet
*ifp
= rt
->rt_ifp
;
185 int addrlen
= ifp
->if_addrlen
;
186 #define LLC_SIZE 3 /* XXXXXX do this right later */
189 printf("llc_rtrequest(%d, %x, %x)\n", req
, rt
, sa
);
191 if (rt
->rt_flags
& RTF_GATEWAY
)
196 * Case 1: This route may come from a route to iface with mask
197 * or from a default route.
199 if (rt
->rt_flags
& RTF_CLONING
) {
200 iso_setmcasts(ifp
, req
);
201 rt_setgate(rt
, rt_key(rt
), &blank_dl
);
205 return; /* happens on a route change */
209 * Case 2: This route may come from cloning, or a manual route
210 * add with a LL address.
212 if (gate
->sdl
.sdl_family
!= AF_LINK
) {
213 log(LOG_DEBUG
, "llc_rtrequest: got non-link non-gateway route\n");
216 R_Malloc(lc
, struct llinfo_llc
*, sizeof (*lc
));
217 rt
->rt_llinfo
= (caddr_t
)lc
;
219 log(LOG_DEBUG
, "llc_rtrequest: malloc failed\n");
222 Bzero(lc
, sizeof(*lc
));
224 rt
->rt_flags
|= RTF_LLINFO
;
225 insque(lc
, &llinfo_llc
);
226 if (gate
->sdl
.sdl_alen
== sizeof(struct esis_req
) + addrlen
) {
227 gate
->sdl
.sdl_alen
-= sizeof(struct esis_req
);
228 bcopy(addrlen
+ LLADDR(&gate
->sdl
),
229 (caddr_t
)&lc
->lc_er
, sizeof(lc
->lc_er
));
230 } else if (gate
->sdl
.sdl_alen
== addrlen
)
231 lc
->lc_flags
= (SNPA_ES
| SNPA_VALID
| SNPA_PERM
);
234 if (rt
->rt_flags
& RTF_CLONING
)
235 iso_setmcasts(ifp
, req
);
241 rt
->rt_flags
&= ~RTF_LLINFO
;
244 if (rt
->rt_rmx
.rmx_mtu
== 0) {
245 rt
->rt_rmx
.rmx_mtu
= rt
->rt_ifp
->if_mtu
- LLC_SIZE
;
249 * FUNCTION: iso_setmcasts
251 * PURPOSE: Enable/Disable ESIS/ISIS multicast reception on interfaces.
253 * NOTES: This also does a lot of obscure magic;
255 iso_setmcasts(ifp
, req
)
259 static char *addrlist
[] =
260 { all_es_snpa
, all_is_snpa
, all_l1is_snpa
, all_l2is_snpa
, 0};
262 register caddr_t
*cpp
;
265 bzero((caddr_t
)&ifr
, sizeof(ifr
));
266 for (cpp
= (caddr_t
*)addrlist
; *cpp
; cpp
++) {
267 bcopy(*cpp
, (caddr_t
)ifr
.ifr_addr
.sa_data
, 6);
269 if (ether_addmulti(&ifr
, (struct arpcom
*)ifp
) == ENETRESET
)
272 if (ether_delmulti(&ifr
, (struct arpcom
*)ifp
) == ENETRESET
)
277 (*ifp
->if_reset
)(ifp
->if_unit
);
279 printf("iso_setmcasts: %s%d needs reseting to receive iso mcasts\n",
280 ifp
->if_name
, ifp
->if_unit
);
284 * FUNCTION: iso_snparesolve
286 * PURPOSE: Resolve an iso address into snpa address
288 * RETURNS: 0 if addr is resolved
289 * errno if addr is unknown
293 * NOTES: Now that we have folded the snpa cache into the routing
294 * table, we know there is no snpa address known for this
295 * destination. If we know of a default IS, then the address
296 * of the IS is returned. If no IS is known, then return the
297 * multi-cast address for "all ES" for this interface.
299 * NB: the last case described above constitutes the
300 * query configuration function 9542, sec 6.5
301 * A mechanism is needed to prevent this function from
302 * being invoked if the system is an IS.
304 iso_snparesolve(ifp
, dest
, snpa
, snpa_len
)
305 struct ifnet
*ifp
; /* outgoing interface */
306 struct sockaddr_iso
*dest
; /* destination */
307 caddr_t snpa
; /* RESULT: snpa to be used */
308 int *snpa_len
; /* RESULT: length of snpa */
310 struct llinfo_llc
*sc
; /* ptr to snpa table entry */
315 * This hack allows us to send esis packets that have the destination snpa
316 * addresss embedded in the destination nsap address
318 if (dest
->siso_data
[0] == AFI_SNA
) {
320 * This is a subnetwork address. Return it immediately
323 printf("iso_snparesolve: return SN address\n");
325 addrlen
= dest
->siso_nlen
- 1; /* subtract size of AFI */
326 found_snpa
= (caddr_t
) dest
->siso_data
+ 1;
328 * If we are an IS, we can't do much with the packet;
329 * Check if we know about an IS.
331 } else if (iso_systype
!= SNPA_IS
&& known_is
!= 0 &&
332 (sc
= (struct llinfo_llc
*)known_is
->rt_llinfo
) &&
333 (sc
->lc_flags
& SNPA_VALID
)) {
334 register struct sockaddr_dl
*sdl
=
335 (struct sockaddr_dl
*)(known_is
->rt_gateway
);
336 found_snpa
= LLADDR(sdl
);
337 addrlen
= sdl
->sdl_alen
;
338 } else if (ifp
->if_flags
& IFF_BROADCAST
) {
340 * no IS, no match. Return "all es" multicast address for this
341 * interface, as per Query Configuration Function (9542 sec 6.5)
343 * Note: there is a potential problem here. If the destination
344 * is on the subnet and it does not respond with a ESH, but
345 * does send back a TP CC, a connection could be established
346 * where we always transmit the CLNP packet to "all es"
348 addrlen
= ifp
->if_addrlen
;
349 found_snpa
= (caddr_t
)all_es_snpa
;
351 return (ENETUNREACH
);
352 bcopy(found_snpa
, snpa
, *snpa_len
= addrlen
);
358 * FUNCTION: snpac_free
360 * PURPOSE: free an entry in the iso address map table
366 * NOTES: If there is a route entry associated with cache
367 * entry, then delete that as well
370 register struct llinfo_llc
*lc
; /* entry to free */
372 register struct rtentry
*rt
= lc
->lc_rt
;
373 register struct iso_addr
*r
;
377 if (rt
&& (rt
->rt_flags
& RTF_UP
) &&
378 (rt
->rt_flags
& (RTF_DYNAMIC
| RTF_MODIFIED
))) {
380 rtrequest(RTM_DELETE
, rt_key(rt
), rt
->rt_gateway
, rt_mask(rt
),
381 rt
->rt_flags
, (struct rtentry
**)0);
387 * FUNCTION: snpac_add
389 * PURPOSE: Add an entry to the snpa cache
395 * NOTES: If entry already exists, then update holding time.
397 snpac_add(ifp
, nsap
, snpa
, type
, ht
, nsellength
)
398 struct ifnet
*ifp
; /* interface info is related to */
399 struct iso_addr
*nsap
; /* nsap to add */
400 caddr_t snpa
; /* translation */
401 char type
; /* SNPA_IS or SNPA_ES */
402 u_short ht
; /* holding time (in seconds) */
403 int nsellength
; /* nsaps may differ only in trailing bytes */
405 register struct llinfo_llc
*lc
;
406 register struct rtentry
*rt
;
407 struct rtentry
*mrt
= 0;
408 register struct iso_addr
*r
; /* for zap_isoaddr macro */
409 int snpalen
= min(ifp
->if_addrlen
, MAX_SNPALEN
);
410 int new_entry
= 0, index
= ifp
->if_index
, iftype
= ifp
->if_type
;
413 printf("snpac_add(%x, %x, %x, %x, %x, %x)\n",
414 ifp
, nsap
, snpa
, type
, ht
, nsellength
);
416 zap_isoaddr(dst
, nsap
);
417 rt
= rtalloc1(S(dst
), 0);
419 printf("snpac_add: rtalloc1 returns %x\n", rt
);
422 struct sockaddr
*netmask
;
426 netmask
= S(msk
); flags
= RTF_UP
;
427 snpac_fixdstandmask(nsellength
);
429 netmask
= 0; flags
= RTF_UP
| RTF_HOST
;
432 zap_linkaddr((>e_dl
), snpa
, snpalen
, index
);
433 gte_dl
.sdl_type
= iftype
;
434 if (rtrequest(RTM_ADD
, S(dst
), S(gte_dl
), netmask
, flags
, &mrt
) ||
440 register struct sockaddr_dl
*sdl
= (struct sockaddr_dl
*)rt
->rt_gateway
;
442 if ((rt
->rt_flags
& RTF_LLINFO
) == 0)
444 if (nsellength
&& (rt
->rt_flags
& RTF_HOST
)) {
445 if (rt
->rt_refcnt
== 0) {
446 rtrequest(RTM_DELETE
, S(dst
), (struct sockaddr
*)0,
447 (struct sockaddr
*)0, 0, (struct rtentry
*)0);
451 static struct iso_addr nsap2
; register char *cp
;
453 cp
= nsap2
.isoa_genaddr
+ nsap
->isoa_len
- nsellength
;
454 while (cp
< (char *)(1 + &nsap2
))
456 (void) snpac_add(ifp
, &nsap2
, snpa
, type
, ht
, nsellength
);
459 if (sdl
->sdl_family
!= AF_LINK
|| sdl
->sdl_alen
== 0) {
460 int old_sdl_len
= sdl
->sdl_len
;
461 if (old_sdl_len
< sizeof(*sdl
)) {
462 log(LOG_DEBUG
, "snpac_add: cant make room for lladdr\n");
465 zap_linkaddr(sdl
, snpa
, snpalen
, index
);
466 sdl
->sdl_len
= old_sdl_len
;
467 sdl
->sdl_type
= iftype
;
471 if ((lc
= (struct llinfo_llc
*)rt
->rt_llinfo
) == 0)
472 panic("snpac_rtrequest");
473 rt
->rt_rmx
.rmx_expire
= ht
+ time
.tv_sec
;
474 lc
->lc_flags
= SNPA_VALID
| type
;
475 if ((type
& SNPA_IS
) && !(iso_systype
& SNPA_IS
))
481 snpac_fixdstandmask(nsellength
)
483 register char *cp
= msk
.siso_data
, *cplim
;
485 cplim
= cp
+ (dst
.siso_nlen
-= nsellength
);
486 msk
.siso_len
= cplim
- (char *)&msk
;
490 while (cp
< (char *)msk
.siso_pad
)
492 for (cp
= dst
.siso_data
+ dst
.siso_nlen
; cp
< (char *)dst
.siso_pad
; )
497 * FUNCTION: snpac_ioctl
499 * PURPOSE: Set/Get the system type and esis parameters
501 * RETURNS: 0 on success, or unix error code
507 snpac_ioctl (so
, cmd
, data
)
509 int cmd
; /* ioctl to process */
510 caddr_t data
; /* data for the cmd */
512 register struct systype_req
*rq
= (struct systype_req
*)data
;
515 if (cmd
== SIOCSSTYPE
)
516 printf("snpac_ioctl: cmd set, type x%x, ht %d, ct %d\n",
517 rq
->sr_type
, rq
->sr_holdt
, rq
->sr_configt
);
519 printf("snpac_ioctl: cmd get\n");
522 if (cmd
== SIOCSSTYPE
) {
523 if ((so
->so_state
& SS_PRIV
) == 0)
525 if ((rq
->sr_type
& (SNPA_ES
|SNPA_IS
)) == (SNPA_ES
|SNPA_IS
))
527 if (rq
->sr_type
& SNPA_ES
) {
528 iso_systype
= SNPA_ES
;
529 } else if (rq
->sr_type
& SNPA_IS
) {
530 iso_systype
= SNPA_IS
;
534 esis_holding_time
= rq
->sr_holdt
;
535 esis_config_time
= rq
->sr_configt
;
536 if (esis_esconfig_time
!= rq
->sr_esconfigt
) {
537 untimeout(esis_config
, (caddr_t
)0);
538 esis_esconfig_time
= rq
->sr_esconfigt
;
541 } else if (cmd
== SIOCGSTYPE
) {
542 rq
->sr_type
= iso_systype
;
543 rq
->sr_holdt
= esis_holding_time
;
544 rq
->sr_configt
= esis_config_time
;
545 rq
->sr_esconfigt
= esis_esconfig_time
;
553 * FUNCTION: snpac_logdefis
555 * PURPOSE: Mark the IS passed as the default IS
564 register struct rtentry
*sc
;
566 register struct iso_addr
*r
;
567 register struct sockaddr_dl
*sdl
= (struct sockaddr_dl
*)sc
->rt_gateway
;
568 register struct rtentry
*rt
;
570 if (known_is
== sc
|| !(sc
->rt_flags
& RTF_HOST
))
577 rt
= rtalloc1((struct sockaddr
*)&zsi
, 0);
579 rtrequest(RTM_ADD
, S(zsi
), rt_key(sc
), S(zmk
),
580 RTF_DYNAMIC
|RTF_GATEWAY
, 0);
582 if ((rt
->rt_flags
& RTF_DYNAMIC
) &&
583 (rt
->rt_flags
& RTF_GATEWAY
) && rt_mask(rt
)->sa_len
== 0)
584 rt_setgate(rt
, rt_key(rt
), rt_key(sc
));
589 * FUNCTION: snpac_age
591 * PURPOSE: Time out snpac entries
597 * NOTES: When encountering an entry for the first time, snpac_age
598 * may delete up to SNPAC_AGE too many seconds. Ie.
599 * if the entry is added a moment before snpac_age is
600 * called, the entry will immediately have SNPAC_AGE
601 * seconds taken off the holding time, even though
602 * it has only been held a brief moment.
604 * The proper way to do this is set an expiry timeval
605 * equal to current time + holding time. Then snpac_age
606 * would time out entries where expiry date is older
607 * than the current time.
612 register struct llinfo_llc
*lc
, *nlc
;
613 register struct rtentry
*rt
;
615 timeout(snpac_age
, (caddr_t
)0, SNPAC_AGE
* hz
);
617 for (lc
= llinfo_llc
.lc_next
; lc
!= & llinfo_llc
; lc
= nlc
) {
619 if (lc
->lc_flags
& SNPA_VALID
) {
621 if (rt
->rt_rmx
.rmx_expire
&& rt
->rt_rmx
.rmx_expire
< time
.tv_sec
)
628 * FUNCTION: snpac_ownmulti
630 * PURPOSE: Determine if the snpa address is a multicast address
631 * of the same type as the system.
633 * RETURNS: true or false
637 * NOTES: Used by interface drivers when not in eavesdrop mode
638 * as interm kludge until
639 * real multicast addresses can be configured
641 snpac_ownmulti(snpa
, len
)
645 return (((iso_systype
& SNPA_ES
) &&
646 (!bcmp(snpa
, (caddr_t
)all_es_snpa
, len
))) ||
647 ((iso_systype
& SNPA_IS
) &&
648 (!bcmp(snpa
, (caddr_t
)all_is_snpa
, len
))));
652 * FUNCTION: snpac_flushifp
654 * PURPOSE: Flush entries associated with specific ifp
665 register struct llinfo_llc
*lc
;
667 for (lc
= llinfo_llc
.lc_next
; lc
!= & llinfo_llc
; lc
= lc
->lc_next
) {
668 if (lc
->lc_rt
->rt_ifp
== ifp
&& (lc
->lc_flags
& SNPA_VALID
))
674 * FUNCTION: snpac_rtrequest
676 * PURPOSE: Make a routing request
682 * NOTES: In the future, this should make a request of a user
683 * level routing daemon.
685 snpac_rtrequest(req
, host
, gateway
, netmask
, flags
, ret_nrt
)
687 struct iso_addr
*host
;
688 struct iso_addr
*gateway
;
689 struct iso_addr
*netmask
;
691 struct rtentry
**ret_nrt
;
693 register struct iso_addr
*r
;
696 printf("snpac_rtrequest: ");
699 else if (req
== RTM_DELETE
)
702 printf("unknown command");
703 printf(" dst: %s\n", clnp_iso_addrp(host
));
704 printf("\tgateway: %s\n", clnp_iso_addrp(gateway
));
708 zap_isoaddr(dst
, host
);
709 zap_isoaddr(gte
, gateway
);
711 zap_isoaddr(msk
, netmask
);
713 msk
.siso_len
= msk
.siso_pad
- (u_char
*)&msk
;
716 rtrequest(req
, S(dst
), S(gte
), (netmask
? S(msk
) : (struct sockaddr
*)0),
721 * FUNCTION: snpac_addrt
723 * PURPOSE: Associate a routing entry with an snpac entry
729 * NOTES: If a cache entry exists for gateway, then
730 * make a routing entry (host, gateway) and associate
733 * If a route already exists and is different, first delete
736 * This could be made more efficient by checking
737 * the existing route before adding a new one.
739 snpac_addrt(ifp
, host
, gateway
, netmask
)
741 struct iso_addr
*host
, *gateway
, *netmask
;
743 register struct iso_addr
*r
;
745 zap_isoaddr(dst
, host
);
746 zap_isoaddr(gte
, gateway
);
748 zap_isoaddr(msk
, netmask
);
750 msk
.siso_len
= msk
.siso_pad
- (u_char
*)&msk
;
751 rtredirect(S(dst
), S(gte
), S(msk
), RTF_DONE
, S(gte
), 0);
753 rtredirect(S(dst
), S(gte
), (struct sockaddr
*)0,
754 RTF_DONE
| RTF_HOST
, S(gte
), 0);