1 /* $NetBSD: iso_snpac.c,v 1.52 2008/11/07 00:20:18 dyoung Exp $ */
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * @(#)iso_snpac.c 8.4 (Berkeley) 5/2/95
34 /***********************************************************
35 Copyright IBM Corporation 1987
39 Permission to use, copy, modify, and distribute this software and its
40 documentation for any purpose and without fee is hereby granted,
41 provided that the above copyright notice appear in all copies and that
42 both that copyright notice and this permission notice appear in
43 supporting documentation, and that the name of IBM not be
44 used in advertising or publicity pertaining to distribution of the
45 software without specific, written prior permission.
47 IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
48 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
49 IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
50 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
51 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
52 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
55 ******************************************************************/
58 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
61 #include <sys/cdefs.h>
62 __KERNEL_RCSID(0, "$NetBSD: iso_snpac.c,v 1.52 2008/11/07 00:20:18 dyoung Exp $");
67 #include <sys/param.h>
68 #include <sys/systm.h>
69 #include <sys/kernel.h>
71 #include <sys/domain.h>
72 #include <sys/protosw.h>
73 #include <sys/socket.h>
74 #include <sys/socketvar.h>
75 #include <sys/errno.h>
76 #include <sys/ioctl.h>
77 #include <sys/syslog.h>
79 #include <sys/kauth.h>
82 #include <net/if_dl.h>
83 #include <net/route.h>
85 #include <net/if_ether.h>
87 #include <netinet/in.h>
89 #include <netiso/iso.h>
90 #include <netiso/iso_var.h>
91 #include <netiso/iso_snpac.h>
92 #include <netiso/clnp.h>
93 #include <netiso/clnp_stat.h>
94 #include <netiso/esis.h>
95 #include <netiso/argo_debug.h>
97 int iso_systype
= SNPA_ES
; /* default to be an ES */
99 LIST_HEAD(, llinfo_llc
) llinfo_llc
;
101 struct callout snpac_age_ch
;
103 struct sockaddr_iso blank_siso
= {
104 .siso_len
= sizeof(blank_siso
),
105 .siso_family
= AF_ISO
,
107 static struct sockaddr_iso
109 .siso_len
= sizeof(dst
),
110 .siso_family
= AF_ISO
,
113 .siso_len
= sizeof(gte
),
114 .siso_family
= AF_ISO
,
118 .siso_len
= sizeof(src
),
119 .siso_family
= AF_ISO
,
123 .siso_len
= sizeof(msk
),
124 .siso_family
= AF_ISO
,
130 #define zsi blank_siso
131 #define zero_isoa zsi.siso_addr
132 #define zap_isoaddr(a, b) {memset(&a.siso_addr, 0, sizeof(*r)); r = b; \
133 memmove(&a.siso_addr, r, 1 + (r)->isoa_len);}
134 #define S(x) ((struct sockaddr *)&(x))
136 static struct sockaddr_dl gte_dl
;
138 static void snpac_fixdstandmask (int);
141 * We only keep track of a single IS at a time.
143 struct rtentry
*known_is
;
146 * Addresses taken from NBS agreements, December 1987.
148 * These addresses assume on-the-wire transmission of least significant
149 * bit first. This is the method used by 802.3. When these
150 * addresses are passed to the token ring driver, (802.5), they
151 * must be bit-swapped because 802.5 transmission order is MSb first.
153 * Furthermore, according to IBM Austin, these addresses are not
154 * true token ring multicast addresses. More work is necessary
155 * to get multicast to work right on token ring.
157 * Currently, the token ring driver does not handle multicast, so
158 * these addresses are converted into the broadcast address in
159 * lan_output() That means that if these multicast addresses change
160 * the token ring driver must be altered.
162 const char all_es_snpa
[] = {0x09, 0x00, 0x2b, 0x00, 0x00, 0x04};
163 const char all_is_snpa
[] = {0x09, 0x00, 0x2b, 0x00, 0x00, 0x05};
164 const char all_l1is_snpa
[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x14};
165 const char all_l2is_snpa
[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x15};
168 struct sockaddr_iso siso
;
169 struct sockaddr_dl sdl
;
174 * FUNCTION: llc_rtrequest
176 * PURPOSE: Manage routing table entries specific to LLC for ISO.
178 * NOTES: This does a lot of obscure magic;
181 llc_rtrequest(int req
, struct rtentry
*rt
, const struct rt_addrinfo
*info
)
183 union sockunion
*gate
= (union sockunion
*) rt
->rt_gateway
;
184 struct llinfo_llc
*lc
= (struct llinfo_llc
*) rt
->rt_llinfo
;
185 struct ifnet
*ifp
= rt
->rt_ifp
;
186 int addrlen
= ifp
->if_addrlen
;
187 #define LLC_SIZE 3 /* XXXXXX do this right later */
190 if (argo_debug
[D_SNPA
]) {
191 printf("llc_rtrequest(%d, %p, %p)\n", req
, rt
, info
);
194 if (rt
->rt_flags
& RTF_GATEWAY
)
200 * Case 1: This route may come from a route to iface with mask
201 * or from a default route.
203 if (rt
->rt_flags
& RTF_CLONING
) {
206 struct sockaddr_dl sdl
;
207 struct sockaddr_storage ss
;
210 iso_setmcasts(ifp
, req
);
211 sockaddr_dl_init(&u
.sdl
, sizeof(u
.ss
),
212 ifp
->if_index
, ifp
->if_type
,
213 NULL
, strlen(ifp
->if_xname
),
214 NULL
, ifp
->if_addrlen
);
215 rt_setgate(rt
, &u
.sa
);
219 return; /* happens on a route change */
223 * Case 2: This route may come from cloning, or a manual route
224 * add with a LL address.
226 if (gate
->sdl
.sdl_family
!= AF_LINK
) {
227 log(LOG_DEBUG
, "llc_rtrequest: got non-link non-gateway route\n");
230 R_Malloc(lc
, struct llinfo_llc
*, sizeof(*lc
));
231 rt
->rt_llinfo
= (void *) lc
;
233 log(LOG_DEBUG
, "llc_rtrequest: malloc failed\n");
236 memset(lc
, 0, sizeof(*lc
));
238 rt
->rt_flags
|= RTF_LLINFO
;
239 LIST_INSERT_HEAD(&llinfo_llc
, lc
, lc_list
);
240 if (gate
->sdl
.sdl_alen
== sizeof(struct esis_req
)
242 gate
->sdl
.sdl_alen
-= sizeof(struct esis_req
);
243 (void)memcpy(&lc
->lc_er
,
244 (const char *)CLLADDR(&gate
->sdl
) +
245 addrlen
, sizeof(lc
->lc_er
));
246 } else if (gate
->sdl
.sdl_alen
== addrlen
)
247 lc
->lc_flags
= (SNPA_ES
| SNPA_VALID
| SNPA_PERM
);
250 if (rt
->rt_flags
& RTF_CLONING
)
251 iso_setmcasts(ifp
, req
);
254 LIST_REMOVE(lc
, lc_list
);
257 rt
->rt_flags
&= ~RTF_LLINFO
;
260 if (rt
->rt_rmx
.rmx_mtu
== 0) {
261 rt
->rt_rmx
.rmx_mtu
= rt
->rt_ifp
->if_mtu
- LLC_SIZE
;
266 * FUNCTION: iso_setmcasts
268 * PURPOSE: Enable/Disable ESIS/ISIS multicast reception on
271 * NOTES: This also does a lot of obscure magic;
274 iso_setmcasts(struct ifnet
*ifp
, int req
)
276 static const char * const addrlist
[] =
277 {all_es_snpa
, all_is_snpa
, all_l1is_snpa
, all_l2is_snpa
, 0};
279 const char *const *cpp
;
281 (void)memset(&ifr
, 0, sizeof(ifr
));
282 for (cpp
= addrlist
; *cpp
; cpp
++) {
283 (void)memcpy(ifr
.ifr_addr
.sa_data
, *cpp
, 6);
284 if (req
== RTM_ADD
&&
285 (*ifp
->if_ioctl
)(ifp
, SIOCADDMULTI
, &ifr
) != 0)
286 printf("iso_setmcasts: %s unable to add mcast\n",
288 else if (req
== RTM_DELETE
&&
289 (*ifp
->if_ioctl
)(ifp
, SIOCDELMULTI
, &ifr
) != 0)
290 printf("iso_setmcasts: %s unable to delete mcast\n",
296 * FUNCTION: iso_snparesolve
298 * PURPOSE: Resolve an iso address into snpa address
300 * RETURNS: 0 if addr is resolved
301 * errno if addr is unknown
305 * NOTES: Now that we have folded the snpa cache into the routing
306 * table, we know there is no snpa address known for this
307 * destination. If we know of a default IS, then the
308 * address of the IS is returned. If no IS is known,
309 * then return the multi-cast address for "all ES" for
312 * NB: the last case described above constitutes the
313 * query configuration function 9542, sec 6.5
314 * A mechanism is needed to prevent this function from
315 * being invoked if the system is an IS.
319 struct ifnet
*ifp
, /* outgoing interface */
320 const struct sockaddr_iso
*dest
, /* destination */
321 void * snpa
, /* RESULT: snpa to be used */
322 int *snpa_len
) /* RESULT: length of snpa */
324 struct llinfo_llc
*sc
; /* ptr to snpa table entry */
325 const char *found_snpa
;
329 * This hack allows us to send esis packets that have the destination
330 * snpa addresss embedded in the destination nsap address
332 if (dest
->siso_data
[0] == AFI_SNA
) {
334 * This is a subnetwork address. Return it immediately
337 if (argo_debug
[D_SNPA
]) {
338 printf("iso_snparesolve: return SN address\n");
341 addrlen
= dest
->siso_nlen
- 1; /* subtract size of AFI */
342 found_snpa
= (const char *)dest
->siso_data
+ 1;
344 * If we are an IS, we can't do much with the packet; Check
345 * if we know about an IS.
347 } else if (iso_systype
!= SNPA_IS
&& known_is
!= 0 &&
348 (sc
= (struct llinfo_llc
*) known_is
->rt_llinfo
) &&
349 (sc
->lc_flags
& SNPA_VALID
)) {
350 const struct sockaddr_dl
*sdl
= satocsdl(known_is
->rt_gateway
);
351 found_snpa
= CLLADDR(sdl
);
352 addrlen
= sdl
->sdl_alen
;
353 } else if (ifp
->if_flags
& IFF_BROADCAST
) {
355 * no IS, no match. Return "all es" multicast address for
356 * this interface, as per Query Configuration Function (9542
359 * Note: there is a potential problem here. If the destination
360 * is on the subnet and it does not respond with a ESH, but
361 * does send back a TP CC, a connection could be established
362 * where we always transmit the CLNP packet to "all es"
364 addrlen
= ifp
->if_addrlen
;
365 found_snpa
= (const char *) all_es_snpa
;
367 return (ENETUNREACH
);
368 memcpy(snpa
, found_snpa
, *snpa_len
= addrlen
);
374 * FUNCTION: snpac_free
376 * PURPOSE: free an entry in the iso address map table
382 * NOTES: If there is a route entry associated with cache
383 * entry, then delete that as well
387 struct llinfo_llc
*lc
) /* entry to free */
389 struct rtentry
*rt
= lc
->lc_rt
;
393 if (rt
&& (rt
->rt_flags
& RTF_UP
) &&
394 (rt
->rt_flags
& (RTF_DYNAMIC
| RTF_MODIFIED
))) {
396 rtrequest(RTM_DELETE
, rt_getkey(rt
), rt
->rt_gateway
,
397 rt_mask(rt
), rt
->rt_flags
, NULL
);
403 * FUNCTION: snpac_add
405 * PURPOSE: Add an entry to the snpa cache
411 * NOTES: If entry already exists, then update holding time.
415 struct ifnet
*ifp
, /* interface info is related to */
416 struct iso_addr
*nsap
, /* nsap to add */
417 void * snpa
, /* translation */
418 int type
, /* SNPA_IS or SNPA_ES */
419 u_short ht
, /* holding time (in seconds) */
420 int nsellength
) /* nsaps may differ only in trailing
423 struct llinfo_llc
*lc
;
425 struct rtentry
*mrt
= 0;
426 struct iso_addr
*r
; /* for zap_isoaddr macro */
427 int snpalen
= min(ifp
->if_addrlen
, MAX_SNPALEN
);
428 int new_entry
= 0, index
= ifp
->if_index
, iftype
= ifp
->if_type
;
431 if (argo_debug
[D_SNPA
]) {
432 printf("snpac_add(%p, %p, %p, %x, %x, %x)\n",
433 ifp
, nsap
, snpa
, type
, ht
, nsellength
);
436 zap_isoaddr(dst
, nsap
);
437 rt
= rtalloc1(sisotosa(&dst
), 0);
439 if (argo_debug
[D_SNPA
]) {
440 printf("snpac_add: rtalloc1 returns %p\n", rt
);
444 struct sockaddr
*netmask
;
448 netmask
= sisotosa(&msk
);
450 snpac_fixdstandmask(nsellength
);
453 flags
= RTF_UP
| RTF_HOST
;
456 sockaddr_dl_init(>e_dl
, sizeof(gte_dl
), index
, iftype
,
457 NULL
, 0, snpa
, snpalen
);
459 if (rtrequest(RTM_ADD
, sisotosa(&dst
), S(gte_dl
), netmask
,
460 flags
, &mrt
) || mrt
== 0)
465 struct sockaddr_dl
*sdl
= satosdl(rt
->rt_gateway
);
467 if ((rt
->rt_flags
& RTF_LLINFO
) == 0)
469 if (nsellength
&& (rt
->rt_flags
& RTF_HOST
)) {
470 if (rt
->rt_refcnt
== 0) {
471 rtrequest(RTM_DELETE
, sisotosa(&dst
),
472 NULL
, NULL
, 0, NULL
);
476 static struct iso_addr nsap2
;
479 cp
= nsap2
.isoa_genaddr
+ nsap
->isoa_len
- nsellength
;
480 while (cp
< (char *) (1 + &nsap2
))
482 (void) snpac_add(ifp
, &nsap2
, snpa
, type
, ht
, nsellength
);
485 if (sdl
->sdl_family
!= AF_LINK
|| sdl
->sdl_alen
== 0) {
486 int old_sdl_len
= sdl
->sdl_len
;
487 if (old_sdl_len
< sizeof(*sdl
)) {
488 log(LOG_DEBUG
, "snpac_add: cant make room for lladdr\n");
491 sockaddr_dl_init(sdl
, sdl
->sdl_len
, index
, iftype
,
492 NULL
, 0, snpa
, snpalen
);
496 if ((lc
= (struct llinfo_llc
*) rt
->rt_llinfo
) == 0)
497 panic("snpac_rtrequest");
498 rt
->rt_rmx
.rmx_expire
= ht
+ time_second
;
499 lc
->lc_flags
= SNPA_VALID
| type
;
500 if ((type
& SNPA_IS
) && !(iso_systype
& SNPA_IS
))
506 snpac_fixdstandmask(int nsellength
)
508 char *cp
= msk
.siso_data
, *cplim
;
510 cplim
= cp
+ (dst
.siso_nlen
-= nsellength
);
511 msk
.siso_len
= cplim
- (char *) &msk
;
515 while (cp
< (char *) msk
.siso_pad
)
517 for (cp
= dst
.siso_data
+ dst
.siso_nlen
; cp
< (char *) dst
.siso_pad
;)
522 * FUNCTION: snpac_ioctl
524 * PURPOSE: Set/Get the system type and esis parameters
526 * RETURNS: 0 on success, or unix error code
535 u_long cmd
, /* ioctl to process */
536 void *data
, /* data for the cmd */
539 struct systype_req
*rq
= (struct systype_req
*) data
;
542 if (argo_debug
[D_IOCTL
]) {
543 if (cmd
== SIOCSSTYPE
)
544 printf("snpac_ioctl: cmd set, type x%x, ht %d, ct %d\n",
545 rq
->sr_type
, rq
->sr_holdt
, rq
->sr_configt
);
547 printf("snpac_ioctl: cmd get\n");
551 if (cmd
== SIOCSSTYPE
) {
557 error
= kauth_authorize_network(l
->l_cred
,
558 KAUTH_NETWORK_SOCKET
,
559 KAUTH_REQ_NETWORK_SOCKET_SETPRIV
, so
,
560 KAUTH_ARG(cmd
), NULL
);
564 if ((rq
->sr_type
& (SNPA_ES
| SNPA_IS
)) == (SNPA_ES
| SNPA_IS
))
566 if (rq
->sr_type
& SNPA_ES
) {
567 iso_systype
= SNPA_ES
;
568 } else if (rq
->sr_type
& SNPA_IS
) {
569 iso_systype
= SNPA_IS
;
573 esis_holding_time
= rq
->sr_holdt
;
574 esis_config_time
= rq
->sr_configt
;
575 if (esis_esconfig_time
!= rq
->sr_esconfigt
) {
576 callout_stop(&esis_config_ch
);
577 esis_esconfig_time
= rq
->sr_esconfigt
;
580 } else if (cmd
== SIOCGSTYPE
) {
581 rq
->sr_type
= iso_systype
;
582 rq
->sr_holdt
= esis_holding_time
;
583 rq
->sr_configt
= esis_config_time
;
584 rq
->sr_esconfigt
= esis_esconfig_time
;
592 * FUNCTION: snpac_logdefis
594 * PURPOSE: Mark the IS passed as the default IS
603 snpac_logdefis(struct rtentry
*sc
)
607 if (known_is
== sc
|| !(sc
->rt_flags
& RTF_HOST
))
614 rt
= rtalloc1((struct sockaddr
*) & zsi
, 0);
616 rtrequest(RTM_ADD
, sisotosa(&zsi
), rt_getkey(sc
),
617 sisotosa(&zmk
), RTF_DYNAMIC
| RTF_GATEWAY
, NULL
);
619 if ((rt
->rt_flags
& RTF_DYNAMIC
) &&
620 (rt
->rt_flags
& RTF_GATEWAY
) && rt_mask(rt
)->sa_len
== 0)
621 rt_setgate(rt
, rt_getkey(sc
));
626 * FUNCTION: snpac_age
628 * PURPOSE: Time out snpac entries
634 * NOTES: When encountering an entry for the first time, snpac_age
635 * may delete up to SNPAC_AGE too many seconds. Ie.
636 * if the entry is added a moment before snpac_age is
637 * called, the entry will immediately have SNPAC_AGE
638 * seconds taken off the holding time, even though
639 * it has only been held a brief moment.
641 * The proper way to do this is set an expiry timeval
642 * equal to current time + holding time. Then snpac_age
643 * would time out entries where expiry date is older
644 * than the current time.
650 struct llinfo_llc
*lc
, *nlc
;
653 callout_reset(&snpac_age_ch
, SNPAC_AGE
* hz
, snpac_age
, NULL
);
655 for (lc
= llinfo_llc
.lh_first
; lc
!= 0; lc
= nlc
) {
656 nlc
= lc
->lc_list
.le_next
;
657 if (lc
->lc_flags
& SNPA_VALID
) {
659 if (rt
->rt_rmx
.rmx_expire
&&
660 rt
->rt_rmx
.rmx_expire
< time_second
)
667 * FUNCTION: snpac_ownmulti
669 * PURPOSE: Determine if the snpa address is a multicast address
670 * of the same type as the system.
672 * RETURNS: true or false
676 * NOTES: Used by interface drivers when not in eavesdrop mode
677 * as interm kludge until
678 * real multicast addresses can be configured
681 snpac_ownmulti(void *snpa
, u_int len
)
683 return (((iso_systype
& SNPA_ES
) &&
684 (!memcmp(snpa
, all_es_snpa
, len
))) ||
685 ((iso_systype
& SNPA_IS
) &&
686 (!memcmp(snpa
, all_is_snpa
, len
))));
690 * FUNCTION: snpac_flushifp
692 * PURPOSE: Flush entries associated with specific ifp
701 snpac_flushifp(struct ifnet
*ifp
)
703 struct llinfo_llc
*lc
;
705 for (lc
= llinfo_llc
.lh_first
; lc
!= 0; lc
= lc
->lc_list
.le_next
) {
706 if (lc
->lc_rt
->rt_ifp
== ifp
&& (lc
->lc_flags
& SNPA_VALID
))
712 * FUNCTION: snpac_rtrequest
714 * PURPOSE: Make a routing request
720 * NOTES: In the future, this should make a request of a user
721 * level routing daemon.
724 snpac_rtrequest(int req
, struct iso_addr
*host
, struct iso_addr
*gateway
,
725 struct iso_addr
*netmask
, int flags
, struct rtentry
**ret_nrt
)
730 if (argo_debug
[D_SNPA
]) {
731 printf("snpac_rtrequest: ");
734 else if (req
== RTM_DELETE
)
737 printf("unknown command");
738 printf(" dst: %s\n", clnp_iso_addrp(host
));
739 printf("\tgateway: %s\n", clnp_iso_addrp(gateway
));
744 zap_isoaddr(dst
, host
);
745 zap_isoaddr(gte
, gateway
);
747 zap_isoaddr(msk
, netmask
);
749 msk
.siso_len
= msk
.siso_pad
- (u_char
*) & msk
;
751 rtrequest(req
, sisotosa(&dst
), sisotosa(>e
),
752 (netmask
? sisotosa(&msk
) : (struct sockaddr
*) 0), flags
, ret_nrt
);
756 * FUNCTION: snpac_addrt
758 * PURPOSE: Associate a routing entry with an snpac entry
764 * NOTES: If a cache entry exists for gateway, then
765 * make a routing entry (host, gateway) and associate
768 * If a route already exists and is different, first delete
771 * This could be made more efficient by checking
772 * the existing route before adding a new one.
775 snpac_addrt(struct ifnet
*ifp
, struct iso_addr
*host
,
776 struct iso_addr
*gateway
, struct iso_addr
*netmask
)
780 zap_isoaddr(dst
, host
);
781 zap_isoaddr(gte
, gateway
);
783 zap_isoaddr(msk
, netmask
);
785 msk
.siso_len
= msk
.siso_pad
- (u_char
*) & msk
;
786 rtredirect(sisotosa(&dst
), sisotosa(>e
), sisotosa(&msk
),
787 RTF_DONE
, sisotosa(>e
), 0);
789 rtredirect(sisotosa(&dst
), sisotosa(>e
), (struct sockaddr
*) 0,
790 RTF_DONE
| RTF_HOST
, sisotosa(>e
), 0);