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) 1988, 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  *      @(#)rtsock.c    8.5 (Berkeley) 11/2/94 
  58 #include <sys/param.h> 
  59 #include <sys/systm.h> 
  60 #include <sys/kernel.h> 
  61 #include <sys/sysctl.h> 
  63 #include <sys/malloc.h> 
  65 #include <sys/socket.h> 
  66 #include <sys/socketvar.h> 
  67 #include <sys/domain.h> 
  68 #include <sys/protosw.h> 
  71 #include <net/route.h> 
  72 #include <net/raw_cb.h> 
  74 MALLOC_DEFINE(M_RTABLE
, "routetbl", "routing tables"); 
  76 static struct   sockaddr route_dst 
= { 2, PF_ROUTE
, }; 
  77 static struct   sockaddr route_src 
= { 2, PF_ROUTE
, }; 
  78 static struct   sockaddr sa_zero   
= { sizeof(sa_zero
), AF_INET
, }; 
  79 static struct   sockproto route_proto 
= { PF_ROUTE
, }; 
  87         struct sysctl_req 
*w_req
; 
  91                 rt_msg1 
__P((int, struct rt_addrinfo 
*)); 
  92 static int      rt_msg2 
__P((int, 
  93                     struct rt_addrinfo 
*, caddr_t
, struct walkarg 
*)); 
  94 static int      rt_xaddrs 
__P((caddr_t
, caddr_t
, struct rt_addrinfo 
*)); 
  95 static int      sysctl_dumpentry 
__P((struct radix_node 
*rn
, void *vw
)); 
  96 static int      sysctl_iflist 
__P((int af
, struct walkarg 
*w
)); 
  97 static int       route_output 
__P((struct mbuf 
*, struct socket 
*)); 
  98 static void      rt_setmetrics 
__P((u_long
, struct rt_metrics 
*, struct rt_metrics 
*)); 
  99 static void     rt_setif 
__P((struct rtentry 
*, struct sockaddr 
*, struct sockaddr 
*, 
 102 /* Sleazy use of local variables throughout file, warning!!!! */ 
 103 #define dst     info.rti_info[RTAX_DST] 
 104 #define gate    info.rti_info[RTAX_GATEWAY] 
 105 #define netmask info.rti_info[RTAX_NETMASK] 
 106 #define genmask info.rti_info[RTAX_GENMASK] 
 107 #define ifpaddr info.rti_info[RTAX_IFP] 
 108 #define ifaaddr info.rti_info[RTAX_IFA] 
 109 #define brdaddr info.rti_info[RTAX_BRD] 
 112  * It really doesn't make any sense at all for this code to share much 
 113  * with raw_usrreq.c, since its functionality is so restricted.  XXX 
 116 rts_abort(struct socket 
*so
) 
 120         error 
= raw_usrreqs
.pru_abort(so
); 
 125 /* pru_accept is EOPNOTSUPP */ 
 128 rts_attach(struct socket 
*so
, int proto
, struct proc 
*p
) 
 133         if (sotorawcb(so
) != 0) 
 134                 return EISCONN
; /* XXX panic? */ 
 135         MALLOC(rp
, struct rawcb 
*, sizeof *rp
, M_PCB
, M_WAITOK
); /* XXX */ 
 138         bzero(rp
, sizeof *rp
); 
 141          * The splnet() is necessary to block protocols from sending 
 142          * error notifications (like RTM_REDIRECT or RTM_LOSING) while 
 143          * this PCB is extant but incompletely initialized. 
 144          * Probably we should try to do more of this work beforehand and 
 148         so
->so_pcb 
= (caddr_t
)rp
; 
 149         error 
= raw_usrreqs
.pru_attach(so
, proto
, p
); 
 156         switch(rp
->rcb_proto
.sp_protocol
) { 
 161                 route_cb
.ip6_count
++; 
 164                 route_cb
.ipx_count
++; 
 170                 route_cb
.iso_count
++; 
 173         rp
->rcb_faddr 
= &route_src
; 
 174         route_cb
.any_count
++; 
 176         so
->so_options 
|= SO_USELOOPBACK
; 
 182 rts_bind(struct socket 
*so
, struct sockaddr 
*nam
, struct proc 
*p
) 
 186         error 
= raw_usrreqs
.pru_bind(so
, nam
, p
); /* xxx just EINVAL */ 
 192 rts_connect(struct socket 
*so
, struct sockaddr 
*nam
, struct proc 
*p
) 
 196         error 
= raw_usrreqs
.pru_connect(so
, nam
, p
); /* XXX just EINVAL */ 
 201 /* pru_connect2 is EOPNOTSUPP */ 
 202 /* pru_control is EOPNOTSUPP */ 
 205 rts_detach(struct socket 
*so
) 
 207         struct rawcb 
*rp 
= sotorawcb(so
); 
 212                 switch(rp
->rcb_proto
.sp_protocol
) { 
 217                         route_cb
.ip6_count
--; 
 220                         route_cb
.ipx_count
--; 
 226                         route_cb
.iso_count
--; 
 229                 route_cb
.any_count
--; 
 231         error 
= raw_usrreqs
.pru_detach(so
); 
 237 rts_disconnect(struct socket 
*so
) 
 241         error 
= raw_usrreqs
.pru_disconnect(so
); 
 246 /* pru_listen is EOPNOTSUPP */ 
 249 rts_peeraddr(struct socket 
*so
, struct sockaddr 
**nam
) 
 253         error 
= raw_usrreqs
.pru_peeraddr(so
, nam
); 
 258 /* pru_rcvd is EOPNOTSUPP */ 
 259 /* pru_rcvoob is EOPNOTSUPP */ 
 262 rts_send(struct socket 
*so
, int flags
, struct mbuf 
*m
, struct sockaddr 
*nam
, 
 263          struct mbuf 
*control
, struct proc 
*p
) 
 267         error 
= raw_usrreqs
.pru_send(so
, flags
, m
, nam
, control
, p
); 
 272 /* pru_sense is null */ 
 275 rts_shutdown(struct socket 
*so
) 
 279         error 
= raw_usrreqs
.pru_shutdown(so
); 
 285 rts_sockaddr(struct socket 
*so
, struct sockaddr 
**nam
) 
 289         error 
= raw_usrreqs
.pru_sockaddr(so
, nam
); 
 294 static struct pr_usrreqs route_usrreqs 
= { 
 295         rts_abort
, pru_accept_notsupp
, rts_attach
, rts_bind
, rts_connect
, 
 296         pru_connect2_notsupp
, pru_control_notsupp
, rts_detach
, rts_disconnect
, 
 297         pru_listen_notsupp
, rts_peeraddr
, pru_rcvd_notsupp
, pru_rcvoob_notsupp
, 
 298         rts_send
, pru_sense_null
, rts_shutdown
, rts_sockaddr
, 
 299         sosend
, soreceive
, sopoll
 
 305         register struct mbuf 
*m
; 
 308         register struct rt_msghdr 
*rtm 
= 0; 
 309         register struct rtentry 
*rt 
= 0; 
 310         struct rtentry 
*saved_nrt 
= 0; 
 311         struct radix_node_head 
*rnh
; 
 312         struct rt_addrinfo info
; 
 314         struct ifnet 
*ifp 
= 0; 
 315         struct ifaddr 
*ifa 
= 0; 
 316         struct proc  
*curproc 
= current_proc(); 
 318 #define senderr(e) { error = e; goto flush;} 
 319         if (m 
== 0 || ((m
->m_len 
< sizeof(long)) && 
 320                        (m 
= m_pullup(m
, sizeof(long))) == 0)) 
 322         if ((m
->m_flags 
& M_PKTHDR
) == 0) 
 323                 panic("route_output"); 
 324         len 
= m
->m_pkthdr
.len
; 
 325         if (len 
< sizeof(*rtm
) || 
 326             len 
!= mtod(m
, struct rt_msghdr 
*)->rtm_msglen
) { 
 330         R_Malloc(rtm
, struct rt_msghdr 
*, len
); 
 335         m_copydata(m
, 0, len
, (caddr_t
)rtm
); 
 336         if (rtm
->rtm_version 
!= RTM_VERSION
) { 
 338                 senderr(EPROTONOSUPPORT
); 
 340         rtm
->rtm_pid 
= curproc
->p_pid
; 
 341         info
.rti_addrs 
= rtm
->rtm_addrs
; 
 342         if (rt_xaddrs((caddr_t
)(rtm 
+ 1), len 
+ (caddr_t
)rtm
, &info
)) { 
 346         if (dst 
== 0 || (dst
->sa_family 
>= AF_MAX
) 
 347             || (gate 
!= 0 && (gate
->sa_family 
>= AF_MAX
))) 
 350                 struct radix_node 
*t
; 
 351                 t 
= rn_addmask((caddr_t
)genmask
, 0, 1); 
 352                 if (t 
&& Bcmp(genmask
, t
->rn_key
, *(u_char 
*)genmask
) == 0) 
 353                         genmask 
= (struct sockaddr 
*)(t
->rn_key
); 
 357         switch (rtm
->rtm_type
) { 
 362                 error 
= rtrequest(RTM_ADD
, dst
, gate
, netmask
, 
 363                                         rtm
->rtm_flags
, &saved_nrt
); 
 364                 if (error 
== 0 && saved_nrt
) { 
 366                      * If the route request specified an interface with 
 367                      * IFA and/or IFP, we set the requested interface on 
 368                      * the route with rt_setif.  It would be much better 
 369                      * to do this inside rtrequest, but that would 
 370                      * require passing the desired interface, in some 
 371                      * form, to rtrequest.  Since rtrequest is called in 
 372                      * so many places (roughly 40 in our source), adding 
 373                      * a parameter is to much for us to swallow; this is 
 374                      * something for the FreeBSD developers to tackle. 
 375                      * Instead, we let rtrequest compute whatever 
 376                      * interface it wants, then come in behind it and 
 377                      * stick in the interface that we really want.  This 
 378                      * works reasonably well except when rtrequest can't 
 379                      * figure out what interface to use (with 
 380                      * ifa_withroute) and returns ENETUNREACH.  Ideally 
 381                      * it shouldn't matter if rtrequest can't figure out 
 382                      * the interface if we're going to explicitly set it 
 383                      * ourselves anyway.  But practically we can't 
 384                      * recover here because rtrequest will not do any of 
 385                      * the work necessary to add the route if it can't 
 386                      * find an interface.  As long as there is a default 
 387                      * route that leads to some interface, rtrequest will 
 388                      * find an interface, so this problem should be 
 389                      * rarely encountered. 
 393                         rt_setif(saved_nrt
, ifpaddr
, ifaaddr
, gate
); 
 394                         rt_setmetrics(rtm
->rtm_inits
, 
 395                                 &rtm
->rtm_rmx
, &saved_nrt
->rt_rmx
); 
 396                         saved_nrt
->rt_rmx
.rmx_locks 
&= ~(rtm
->rtm_inits
); 
 397                         saved_nrt
->rt_rmx
.rmx_locks 
|= 
 398                                 (rtm
->rtm_inits 
& rtm
->rtm_rmx
.rmx_locks
); 
 399                         saved_nrt
->rt_refcnt
--; 
 400                         saved_nrt
->rt_genmask 
= genmask
; 
 405                 error 
= rtrequest(RTM_DELETE
, dst
, gate
, netmask
, 
 406                                 rtm
->rtm_flags
, &saved_nrt
); 
 408                         if ((rt 
= saved_nrt
)) 
 417                 if ((rnh 
= rt_tables
[dst
->sa_family
]) == 0) { 
 418                         senderr(EAFNOSUPPORT
); 
 419                 } else if (rt 
= (struct rtentry 
*) 
 420                                 rnh
->rnh_lookup(dst
, netmask
, rnh
)) 
 424                 switch(rtm
->rtm_type
) { 
 429                         gate 
= rt
->rt_gateway
; 
 430                         netmask 
= rt_mask(rt
); 
 431                         genmask 
= rt
->rt_genmask
; 
 432                         if (rtm
->rtm_addrs 
& (RTA_IFP 
| RTA_IFA
)) { 
 435                                         ifpaddr 
= ifp
->if_addrhead
.tqh_first
->ifa_addr
; 
 436                                         ifaaddr 
= rt
->rt_ifa
->ifa_addr
; 
 437                                         rtm
->rtm_index 
= ifp
->if_index
; 
 443                         len 
= rt_msg2(rtm
->rtm_type
, &info
, (caddr_t
)0, 
 444                                 (struct walkarg 
*)0); 
 445                         if (len 
> rtm
->rtm_msglen
) { 
 446                                 struct rt_msghdr 
*new_rtm
; 
 447                                 R_Malloc(new_rtm
, struct rt_msghdr 
*, len
); 
 450                                 Bcopy(rtm
, new_rtm
, rtm
->rtm_msglen
); 
 451                                 Free(rtm
); rtm 
= new_rtm
; 
 453                         (void)rt_msg2(rtm
->rtm_type
, &info
, (caddr_t
)rtm
, 
 454                                 (struct walkarg 
*)0); 
 455                         rtm
->rtm_flags 
= rt
->rt_flags
; 
 456                         rtm
->rtm_rmx 
= rt
->rt_rmx
; 
 457                         rtm
->rtm_addrs 
= info
.rti_addrs
; 
 461                         if (gate 
&& (error 
= rt_setgate(rt
, rt_key(rt
), gate
))) 
 465                          * If they tried to change things but didn't specify 
 466                          * the required gateway, then just use the old one. 
 467                          * This can happen if the user tries to change the 
 468                          * flags on the default route without changing the 
 469                          * default gateway.  Changing flags still doesn't work. 
 471                         if ((rt
->rt_flags 
& RTF_GATEWAY
) && !gate
) 
 472                                 gate 
= rt
->rt_gateway
; 
 474                         rt_setif(rt
, ifpaddr
, ifaaddr
, gate
); 
 476                         rt_setmetrics(rtm
->rtm_inits
, &rtm
->rtm_rmx
, 
 479                                 rt
->rt_genmask 
= genmask
; 
 484                         rt
->rt_rmx
.rmx_locks 
&= ~(rtm
->rtm_inits
); 
 485                         rt
->rt_rmx
.rmx_locks 
|= 
 486                                 (rtm
->rtm_inits 
& rtm
->rtm_rmx
.rmx_locks
); 
 498                         rtm
->rtm_errno 
= error
; 
 500                         rtm
->rtm_flags 
|= RTF_DONE
; 
 505         register struct rawcb 
*rp 
= 0; 
 507          * Check to see if we don't want our own messages. 
 509         if ((so
->so_options 
& SO_USELOOPBACK
) == 0) { 
 510                 if (route_cb
.any_count 
<= 1) { 
 516                 /* There is another listener, so construct message */ 
 520                 m_copyback(m
, 0, rtm
->rtm_msglen
, (caddr_t
)rtm
); 
 524                 rp
->rcb_proto
.sp_family 
= 0; /* Avoid us */ 
 526                 route_proto
.sp_protocol 
= dst
->sa_family
; 
 527         raw_input(m
, &route_proto
, &route_src
, &route_dst
); 
 529                 rp
->rcb_proto
.sp_family 
= PF_ROUTE
; 
 535 rt_setmetrics(which
, in
, out
) 
 537         register struct rt_metrics 
*in
, *out
; 
 539 #define metric(f, e) if (which & (f)) out->e = in->e; 
 540         metric(RTV_RPIPE
, rmx_recvpipe
); 
 541         metric(RTV_SPIPE
, rmx_sendpipe
); 
 542         metric(RTV_SSTHRESH
, rmx_ssthresh
); 
 543         metric(RTV_RTT
, rmx_rtt
); 
 544         metric(RTV_RTTVAR
, rmx_rttvar
); 
 545         metric(RTV_HOPCOUNT
, rmx_hopcount
); 
 546         metric(RTV_MTU
, rmx_mtu
); 
 547         metric(RTV_EXPIRE
, rmx_expire
); 
 552  * Set route's interface given ifpaddr, ifaaddr, and gateway. 
 555 rt_setif(rt
, Ifpaddr
, Ifaaddr
, Gate
) 
 557         struct sockaddr 
*Ifpaddr
, *Ifaaddr
, *Gate
; 
 559         struct ifaddr 
*ifa 
= 0; 
 560         struct ifnet  
*ifp 
= 0; 
 562         /* new gateway could require new ifaddr, ifp; 
 563            flags may also be different; ifp may be specified 
 564            by ll sockaddr when protocol address is ambiguous */ 
 565         if (Ifpaddr 
&& (ifa 
= ifa_ifwithnet(Ifpaddr
)) && 
 566             (ifp 
= ifa
->ifa_ifp
) && (Ifaaddr 
|| Gate
)) 
 567                 ifa 
= ifaof_ifpforaddr(Ifaaddr 
? Ifaaddr 
: Gate
, 
 569         else if (Ifpaddr 
&& (ifp 
= if_withname(Ifpaddr
)) ) { 
 570                 ifa 
= Gate 
? ifaof_ifpforaddr(Gate
, ifp
) : 
 571                                 TAILQ_FIRST(&ifp
->if_addrhead
); 
 573         else if ((Ifaaddr 
&& (ifa 
= ifa_ifwithaddr(Ifaaddr
))) || 
 574                  (Gate 
&& (ifa 
= ifa_ifwithroute(rt
->rt_flags
, 
 578                 register struct ifaddr 
*oifa 
= rt
->rt_ifa
; 
 580                     if (oifa 
&& oifa
->ifa_rtrequest
) 
 581                         oifa
->ifa_rtrequest(RTM_DELETE
, 
 587                     rt
->rt_rmx
.rmx_mtu 
= ifp
->if_mtu
; 
 588                     if (rt
->rt_ifa 
&& rt
->rt_ifa
->ifa_rtrequest
) 
 589                         rt
->rt_ifa
->ifa_rtrequest(RTM_ADD
, rt
, Gate
); 
 595         /* XXX: to reset gateway to correct value, at RTM_CHANGE */ 
 596         if (rt
->rt_ifa 
&& rt
->rt_ifa
->ifa_rtrequest
) 
 597                 rt
->rt_ifa
->ifa_rtrequest(RTM_ADD
, rt
, Gate
); 
 602         ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 
 603 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 
 607  * Extract the addresses of the passed sockaddrs. 
 608  * Do a little sanity checking so as to avoid bad memory references. 
 609  * This data is derived straight from userland. 
 612 rt_xaddrs(cp
, cplim
, rtinfo
) 
 613         register caddr_t cp
, cplim
; 
 614         register struct rt_addrinfo 
*rtinfo
; 
 616         register struct sockaddr 
*sa
; 
 619         bzero(rtinfo
->rti_info
, sizeof(rtinfo
->rti_info
)); 
 620         for (i 
= 0; (i 
< RTAX_MAX
) && (cp 
< cplim
); i
++) { 
 621                 if ((rtinfo
->rti_addrs 
& (1 << i
)) == 0) 
 623                 sa 
= (struct sockaddr 
*)cp
; 
 627                 if ( (cp 
+ sa
->sa_len
) > cplim 
) { 
 632                  * there are no more.. quit now 
 633                  * If there are more bits, they are in error. 
 634                  * I've seen this. route(1) can evidently generate these.  
 635                  * This causes kernel to core dump. 
 636                  * for compatibility, If we see this, point to a safe address. 
 638                 if (sa
->sa_len 
== 0) { 
 639                         rtinfo
->rti_info
[i
] = &sa_zero
; 
 640                         return (0); /* should be EINVAL but for compat */ 
 644                 rtinfo
->rti_info
[i
] = sa
; 
 651 rt_msg1(type
, rtinfo
) 
 653         register struct rt_addrinfo 
*rtinfo
; 
 655         register struct rt_msghdr 
*rtm
; 
 656         register struct mbuf 
*m
; 
 658         register struct sockaddr 
*sa
; 
 661         m 
= m_gethdr(M_DONTWAIT
, MT_DATA
); 
 668                 len 
= sizeof(struct ifa_msghdr
); 
 673                 len 
= sizeof(struct ifma_msghdr
); 
 677                 len 
= sizeof(struct if_msghdr
); 
 681                 len 
= sizeof(struct rt_msghdr
); 
 685         m
->m_pkthdr
.len 
= m
->m_len 
= len
; 
 686         m
->m_pkthdr
.rcvif 
= 0; 
 687         rtm 
= mtod(m
, struct rt_msghdr 
*); 
 688         bzero((caddr_t
)rtm
, len
); 
 689         for (i 
= 0; i 
< RTAX_MAX
; i
++) { 
 690                 if ((sa 
= rtinfo
->rti_info
[i
]) == NULL
) 
 692                 rtinfo
->rti_addrs 
|= (1 << i
); 
 693                 dlen 
= ROUNDUP(sa
->sa_len
); 
 694                 m_copyback(m
, len
, dlen
, (caddr_t
)sa
); 
 697         if (m
->m_pkthdr
.len 
!= len
) { 
 701         rtm
->rtm_msglen 
= len
; 
 702         rtm
->rtm_version 
= RTM_VERSION
; 
 703         rtm
->rtm_type 
= type
; 
 708 rt_msg2(type
, rtinfo
, cp
, w
) 
 710         register struct rt_addrinfo 
*rtinfo
; 
 715         int len
, dlen
, second_time 
= 0; 
 718         rtinfo
->rti_addrs 
= 0; 
 724                 len 
= sizeof(struct ifa_msghdr
); 
 728                 len 
= sizeof(struct if_msghdr
); 
 732                 len 
= sizeof(struct rt_msghdr
); 
 737         for (i 
= 0; i 
< RTAX_MAX
; i
++) { 
 738                 register struct sockaddr 
*sa
; 
 740                 if ((sa 
= rtinfo
->rti_info
[i
]) == 0) 
 742                 rtinfo
->rti_addrs 
|= (1 << i
); 
 743                 dlen 
= ROUNDUP(sa
->sa_len
); 
 745                         bcopy((caddr_t
)sa
, cp
, (unsigned)dlen
); 
 750         if (cp 
== 0 && w 
!= NULL 
&& !second_time
) { 
 751                 register struct walkarg 
*rw 
= w
; 
 754                         if (rw
->w_tmemsize 
< len
) { 
 756                                         FREE(rw
->w_tmem
, M_RTABLE
); 
 757                                 rw
->w_tmem 
= (caddr_t
) 
 758                                         _MALLOC(len
, M_RTABLE
, M_NOWAIT
); 
 760                                         rw
->w_tmemsize 
= len
; 
 770                 register struct rt_msghdr 
*rtm 
= (struct rt_msghdr 
*)cp0
; 
 772                 rtm
->rtm_version 
= RTM_VERSION
; 
 773                 rtm
->rtm_type 
= type
; 
 774                 rtm
->rtm_msglen 
= len
; 
 780  * This routine is called to generate a message from the routing 
 781  * socket indicating that a redirect has occured, a routing lookup 
 782  * has failed, or that a protocol has detected timeouts to a particular 
 786 rt_missmsg(type
, rtinfo
, flags
, error
) 
 787         int type
, flags
, error
; 
 788         register struct rt_addrinfo 
*rtinfo
; 
 790         register struct rt_msghdr 
*rtm
; 
 791         register struct mbuf 
*m
; 
 792         struct sockaddr 
*sa 
= rtinfo
->rti_info
[RTAX_DST
]; 
 794         if (route_cb
.any_count 
== 0) 
 796         m 
= rt_msg1(type
, rtinfo
); 
 799         rtm 
= mtod(m
, struct rt_msghdr 
*); 
 800         rtm
->rtm_flags 
= RTF_DONE 
| flags
; 
 801         rtm
->rtm_errno 
= error
; 
 802         rtm
->rtm_addrs 
= rtinfo
->rti_addrs
; 
 803         route_proto
.sp_protocol 
= sa 
? sa
->sa_family 
: 0; 
 804         raw_input(m
, &route_proto
, &route_src
, &route_dst
); 
 808  * This routine is called to generate a message from the routing 
 809  * socket indicating that the status of a network interface has changed. 
 813         register struct ifnet 
*ifp
; 
 815         register struct if_msghdr 
*ifm
; 
 817         struct rt_addrinfo info
; 
 819         if (route_cb
.any_count 
== 0) 
 821         bzero((caddr_t
)&info
, sizeof(info
)); 
 822         m 
= rt_msg1(RTM_IFINFO
, &info
); 
 825         ifm 
= mtod(m
, struct if_msghdr 
*); 
 826         ifm
->ifm_index 
= ifp
->if_index
; 
 827         ifm
->ifm_flags 
= (u_short
)ifp
->if_flags
; 
 828         ifm
->ifm_data 
= ifp
->if_data
; 
 830         route_proto
.sp_protocol 
= 0; 
 831         raw_input(m
, &route_proto
, &route_src
, &route_dst
); 
 835  * This is called to generate messages from the routing socket 
 836  * indicating a network interface has had addresses associated with it. 
 837  * if we ever reverse the logic and replace messages TO the routing 
 838  * socket indicate a request to configure interfaces, then it will 
 839  * be unnecessary as the routing socket will automatically generate 
 843 rt_newaddrmsg(cmd
, ifa
, error
, rt
) 
 845         register struct ifaddr 
*ifa
; 
 846         register struct rtentry 
*rt
; 
 848         struct rt_addrinfo info
; 
 849         struct sockaddr 
*sa 
= 0; 
 852         struct ifnet 
*ifp 
= ifa
->ifa_ifp
; 
 854         if (route_cb
.any_count 
== 0) 
 856         for (pass 
= 1; pass 
< 3; pass
++) { 
 857                 bzero((caddr_t
)&info
, sizeof(info
)); 
 858                 if ((cmd 
== RTM_ADD 
&& pass 
== 1) || 
 859                     (cmd 
== RTM_DELETE 
&& pass 
== 2)) { 
 860                         register struct ifa_msghdr 
*ifam
; 
 861                         int ncmd 
= cmd 
== RTM_ADD 
? RTM_NEWADDR 
: RTM_DELADDR
; 
 863                         ifaaddr 
= sa 
= ifa
->ifa_addr
; 
 864                         ifpaddr 
= ifp
->if_addrhead
.tqh_first
->ifa_addr
; 
 865                         netmask 
= ifa
->ifa_netmask
; 
 866                         brdaddr 
= ifa
->ifa_dstaddr
; 
 867                         if ((m 
= rt_msg1(ncmd
, &info
)) == NULL
) 
 869                         ifam 
= mtod(m
, struct ifa_msghdr 
*); 
 870                         ifam
->ifam_index 
= ifp
->if_index
; 
 871                         ifam
->ifam_metric 
= ifa
->ifa_metric
; 
 872                         ifam
->ifam_flags 
= ifa
->ifa_flags
; 
 873                         ifam
->ifam_addrs 
= info
.rti_addrs
; 
 875                 if ((cmd 
== RTM_ADD 
&& pass 
== 2) || 
 876                     (cmd 
== RTM_DELETE 
&& pass 
== 1)) { 
 877                         register struct rt_msghdr 
*rtm
; 
 881                         netmask 
= rt_mask(rt
); 
 882                         dst 
= sa 
= rt_key(rt
); 
 883                         gate 
= rt
->rt_gateway
; 
 884                         if ((m 
= rt_msg1(cmd
, &info
)) == NULL
) 
 886                         rtm 
= mtod(m
, struct rt_msghdr 
*); 
 887                         rtm
->rtm_index 
= ifp
->if_index
; 
 888                         rtm
->rtm_flags 
|= rt
->rt_flags
; 
 889                         rtm
->rtm_errno 
= error
; 
 890                         rtm
->rtm_addrs 
= info
.rti_addrs
; 
 892                 route_proto
.sp_protocol 
= sa 
? sa
->sa_family 
: 0; 
 893                 raw_input(m
, &route_proto
, &route_src
, &route_dst
); 
 898  * This is the analogue to the rt_newaddrmsg which performs the same 
 899  * function but for multicast group memberhips.  This is easier since 
 900  * there is no route state to worry about. 
 903 rt_newmaddrmsg(cmd
, ifma
) 
 905         struct ifmultiaddr 
*ifma
; 
 907         struct rt_addrinfo info
; 
 909         struct ifnet 
*ifp 
= ifma
->ifma_ifp
; 
 910         struct ifma_msghdr 
*ifmam
; 
 912         if (route_cb
.any_count 
== 0) 
 915         bzero((caddr_t
)&info
, sizeof(info
)); 
 916         ifaaddr 
= ifma
->ifma_addr
; 
 917         ifpaddr 
= ifp
->if_addrhead
.tqh_first
->ifa_addr
; 
 919          * If a link-layer address is present, present it as a ``gateway'' 
 920          * (similarly to how ARP entries, e.g., are presented). 
 922         gate 
= ifma
->ifma_lladdr
; 
 923         if ((m 
= rt_msg1(cmd
, &info
)) == NULL
) 
 925         ifmam 
= mtod(m
, struct ifma_msghdr 
*); 
 926         ifmam
->ifmam_index 
= ifp
->if_index
; 
 927         ifmam
->ifmam_addrs 
= info
.rti_addrs
; 
 928         route_proto
.sp_protocol 
= ifma
->ifma_addr
->sa_family
; 
 929         raw_input(m
, &route_proto
, &route_src
, &route_dst
); 
 933  * This is used in dumping the kernel table via sysctl(). 
 936 sysctl_dumpentry(rn
, vw
) 
 937         struct radix_node 
*rn
; 
 940         register struct walkarg 
*w 
= vw
; 
 941         register struct rtentry 
*rt 
= (struct rtentry 
*)rn
; 
 943         struct rt_addrinfo info
; 
 945         if (w
->w_op 
== NET_RT_FLAGS 
&& !(rt
->rt_flags 
& w
->w_arg
)) 
 947         bzero((caddr_t
)&info
, sizeof(info
)); 
 949         gate 
= rt
->rt_gateway
; 
 950         netmask 
= rt_mask(rt
); 
 951         genmask 
= rt
->rt_genmask
; 
 952         size 
= rt_msg2(RTM_GET
, &info
, 0, w
); 
 953         if (w
->w_req 
&& w
->w_tmem
) { 
 954                 register struct rt_msghdr 
*rtm 
= (struct rt_msghdr 
*)w
->w_tmem
; 
 956                 rtm
->rtm_flags 
= rt
->rt_flags
; 
 957                 rtm
->rtm_use 
= rt
->rt_use
; 
 958                 rtm
->rtm_rmx 
= rt
->rt_rmx
; 
 959                 rtm
->rtm_index 
= rt
->rt_ifp
->if_index
; 
 960                 rtm
->rtm_errno 
= rtm
->rtm_pid 
= rtm
->rtm_seq 
= 0; 
 961                 rtm
->rtm_addrs 
= info
.rti_addrs
; 
 962                 error 
= SYSCTL_OUT(w
->w_req
, (caddr_t
)rtm
, size
); 
 971         register struct walkarg 
*w
; 
 973         register struct ifnet 
*ifp
; 
 974         register struct ifaddr 
*ifa
; 
 975         struct  rt_addrinfo info
; 
 978         bzero((caddr_t
)&info
, sizeof(info
)); 
 979         for (ifp 
= ifnet
.tqh_first
; ifp
; ifp 
= ifp
->if_link
.tqe_next
) { 
 980                 if (w
->w_arg 
&& w
->w_arg 
!= ifp
->if_index
) 
 982                 ifa 
= ifp
->if_addrhead
.tqh_first
; 
 983                 ifpaddr 
= ifa
->ifa_addr
; 
 984                 len 
= rt_msg2(RTM_IFINFO
, &info
, (caddr_t
)0, w
); 
 986                 if (w
->w_req 
&& w
->w_tmem
) { 
 987                         register struct if_msghdr 
*ifm
; 
 989                         ifm 
= (struct if_msghdr 
*)w
->w_tmem
; 
 990                         ifm
->ifm_index 
= ifp
->if_index
; 
 991                         ifm
->ifm_flags 
= (u_short
)ifp
->if_flags
; 
 992                         ifm
->ifm_data 
= ifp
->if_data
; 
 993                         ifm
->ifm_addrs 
= info
.rti_addrs
; 
 994                         error 
= SYSCTL_OUT(w
->w_req
,(caddr_t
)ifm
, len
); 
 998                 while ((ifa 
= ifa
->ifa_link
.tqe_next
) != 0) { 
 999                         if (af 
&& af 
!= ifa
->ifa_addr
->sa_family
) 
1001                         ifaaddr 
= ifa
->ifa_addr
; 
1002                         netmask 
= ifa
->ifa_netmask
; 
1003                         brdaddr 
= ifa
->ifa_dstaddr
; 
1004                         len 
= rt_msg2(RTM_NEWADDR
, &info
, 0, w
); 
1005                         if (w
->w_req 
&& w
->w_tmem
) { 
1006                                 register struct ifa_msghdr 
*ifam
; 
1008                                 ifam 
= (struct ifa_msghdr 
*)w
->w_tmem
; 
1009                                 ifam
->ifam_index 
= ifa
->ifa_ifp
->if_index
; 
1010                                 ifam
->ifam_flags 
= ifa
->ifa_flags
; 
1011                                 ifam
->ifam_metric 
= ifa
->ifa_metric
; 
1012                                 ifam
->ifam_addrs 
= info
.rti_addrs
; 
1013                                 error 
= SYSCTL_OUT(w
->w_req
, w
->w_tmem
, len
); 
1018                 ifaaddr 
= netmask 
= brdaddr 
= 0; 
1025 sysctl_rtsock SYSCTL_HANDLER_ARGS
 
1027         int     *name 
= (int *)arg1
; 
1028         u_int   namelen 
= arg2
; 
1029         register struct radix_node_head 
*rnh
; 
1030         int     i
, s
, error 
= EINVAL
; 
1041         Bzero(&w
, sizeof(w
)); 
1051                 for (i 
= 1; i 
<= AF_MAX
; i
++) 
1052                         if ((rnh 
= rt_tables
[i
]) && (af 
== 0 || af 
== i
) && 
1053                             (error 
= rnh
->rnh_walktree(rnh
, 
1054                                                         sysctl_dumpentry
, &w
))) 
1059                 error 
= sysctl_iflist(af
, &w
); 
1063                 FREE(w
.w_tmem
, M_RTABLE
); 
1067 SYSCTL_NODE(_net
, PF_ROUTE
, routetable
, CTLFLAG_RD
, sysctl_rtsock
, ""); 
1072  * Definitions of protocols supported in the ROUTE domain. 
1075 struct domain routedomain
;              /* or at least forward */ 
1078 static struct protosw routesw
[] = { 
1079 { SOCK_RAW
,     &routedomain
,   0,              PR_ATOMIC
|PR_ADDR
, 
1080   0,    route_output
,   raw_ctlinput
,   0, 
1083   0, &route_usrreqs
, 0, 0 
1087 struct domain routedomain 
= 
1088     { PF_ROUTE
, "route", route_init
, 0, 0, 
1094 #include <net/rtsock_mip.c>