1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3*0Sstevel@tonic-gate * Use is subject to license terms. 4*0Sstevel@tonic-gate */ 5*0Sstevel@tonic-gate 6*0Sstevel@tonic-gate /* 7*0Sstevel@tonic-gate * Copyright (c) 1988, 1991, 1993 8*0Sstevel@tonic-gate * The Regents of the University of California. All rights reserved. 9*0Sstevel@tonic-gate * 10*0Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 11*0Sstevel@tonic-gate * modification, are permitted provided that the following conditions 12*0Sstevel@tonic-gate * are met: 13*0Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 14*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 15*0Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 16*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 17*0Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 18*0Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 19*0Sstevel@tonic-gate * must display the following acknowledgement: 20*0Sstevel@tonic-gate * This product includes software developed by the University of 21*0Sstevel@tonic-gate * California, Berkeley and its contributors. 22*0Sstevel@tonic-gate * 4. Neither the name of the University nor the names of its contributors 23*0Sstevel@tonic-gate * may be used to endorse or promote products derived from this software 24*0Sstevel@tonic-gate * without specific prior written permission. 25*0Sstevel@tonic-gate * 26*0Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27*0Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28*0Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29*0Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30*0Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31*0Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32*0Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33*0Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34*0Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35*0Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36*0Sstevel@tonic-gate * SUCH DAMAGE. 37*0Sstevel@tonic-gate * 38*0Sstevel@tonic-gate * @(#)rtsock.c 8.6 (Berkeley) 2/11/95 39*0Sstevel@tonic-gate */ 40*0Sstevel@tonic-gate 41*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate /* 44*0Sstevel@tonic-gate * This file contains routines that processes routing socket requests. 45*0Sstevel@tonic-gate */ 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate #include <sys/types.h> 48*0Sstevel@tonic-gate #include <sys/stream.h> 49*0Sstevel@tonic-gate #include <sys/stropts.h> 50*0Sstevel@tonic-gate #include <sys/strlog.h> 51*0Sstevel@tonic-gate #include <sys/dlpi.h> 52*0Sstevel@tonic-gate #include <sys/ddi.h> 53*0Sstevel@tonic-gate #include <sys/cmn_err.h> 54*0Sstevel@tonic-gate #include <sys/debug.h> 55*0Sstevel@tonic-gate #include <sys/policy.h> 56*0Sstevel@tonic-gate #include <sys/zone.h> 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate #include <sys/systm.h> 59*0Sstevel@tonic-gate #include <sys/param.h> 60*0Sstevel@tonic-gate #include <sys/socket.h> 61*0Sstevel@tonic-gate #define _SUN_TPI_VERSION 2 62*0Sstevel@tonic-gate #include <sys/tihdr.h> 63*0Sstevel@tonic-gate #include <sys/strsun.h> 64*0Sstevel@tonic-gate #include <net/if.h> 65*0Sstevel@tonic-gate #include <net/route.h> 66*0Sstevel@tonic-gate #include <netinet/in.h> 67*0Sstevel@tonic-gate #include <net/if_dl.h> 68*0Sstevel@tonic-gate #include <netinet/ip6.h> 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate #include <inet/common.h> 71*0Sstevel@tonic-gate #include <inet/mi.h> 72*0Sstevel@tonic-gate #include <inet/ip.h> 73*0Sstevel@tonic-gate #include <inet/ip6.h> 74*0Sstevel@tonic-gate #include <inet/ip_if.h> 75*0Sstevel@tonic-gate #include <inet/ip_ire.h> 76*0Sstevel@tonic-gate #include <inet/ip_rts.h> 77*0Sstevel@tonic-gate #include <inet/ip_multi.h> 78*0Sstevel@tonic-gate 79*0Sstevel@tonic-gate #include <inet/ipclassifier.h> 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate #define RTS_MSG_SIZE(type, rtm_addrs, af) \ 82*0Sstevel@tonic-gate (rts_data_msg_size(rtm_addrs, af) + rts_header_msg_size(type)) 83*0Sstevel@tonic-gate 84*0Sstevel@tonic-gate static size_t rts_copyfromsockaddr(struct sockaddr *sa, in6_addr_t *addrp); 85*0Sstevel@tonic-gate static void rts_fill_msg(int type, int rtm_addrs, ipaddr_t dst, 86*0Sstevel@tonic-gate ipaddr_t mask, ipaddr_t gateway, ipaddr_t src_addr, ipaddr_t brd_addr, 87*0Sstevel@tonic-gate ipaddr_t author, ipif_t *ipif, mblk_t *mp); 88*0Sstevel@tonic-gate static int rts_getaddrs(rt_msghdr_t *rtm, in6_addr_t *dst_addrp, 89*0Sstevel@tonic-gate in6_addr_t *gw_addrp, in6_addr_t *net_maskp, in6_addr_t *authorp, 90*0Sstevel@tonic-gate in6_addr_t *if_addrp, in6_addr_t *src_addrp, ushort_t *indexp, 91*0Sstevel@tonic-gate ushort_t *src_indexp, sa_family_t *afp); 92*0Sstevel@tonic-gate static void rts_getifdata(if_data_t *if_data, ipif_t *ipif); 93*0Sstevel@tonic-gate static int rts_getmetrics(ire_t *ire, rt_metrics_t *metrics); 94*0Sstevel@tonic-gate static mblk_t *rts_rtmget(mblk_t *mp, ire_t *ire, ire_t *sire, 95*0Sstevel@tonic-gate sa_family_t af); 96*0Sstevel@tonic-gate static void rts_setmetrics(ire_t *ire, uint_t which, rt_metrics_t *metrics); 97*0Sstevel@tonic-gate static void ip_rts_request_retry(ipsq_t *, queue_t *q, mblk_t *mp, void *); 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate /* 100*0Sstevel@tonic-gate * Send the ack to all the routing queues. In case of the originating queue, 101*0Sstevel@tonic-gate * send it only if the loopback is set. 102*0Sstevel@tonic-gate * 103*0Sstevel@tonic-gate * Messages are sent upstream only on routing sockets that did not specify an 104*0Sstevel@tonic-gate * address family when they were created or when the address family matches the 105*0Sstevel@tonic-gate * one specified by the caller. 106*0Sstevel@tonic-gate * 107*0Sstevel@tonic-gate */ 108*0Sstevel@tonic-gate void 109*0Sstevel@tonic-gate rts_queue_input(mblk_t *mp, queue_t *q, sa_family_t af) 110*0Sstevel@tonic-gate { 111*0Sstevel@tonic-gate mblk_t *mp1; 112*0Sstevel@tonic-gate int checkqfull; 113*0Sstevel@tonic-gate conn_t *connp, *next_connp; 114*0Sstevel@tonic-gate 115*0Sstevel@tonic-gate mutex_enter(&rts_clients.connf_lock); 116*0Sstevel@tonic-gate connp = rts_clients.connf_head; 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gate while (connp != NULL) { 119*0Sstevel@tonic-gate /* 120*0Sstevel@tonic-gate * If there was a family specified when this routing socket was 121*0Sstevel@tonic-gate * created and it doesn't match the family of the message to 122*0Sstevel@tonic-gate * copy, then continue. 123*0Sstevel@tonic-gate */ 124*0Sstevel@tonic-gate if ((connp->conn_proto != AF_UNSPEC) && 125*0Sstevel@tonic-gate (connp->conn_proto != af)) { 126*0Sstevel@tonic-gate connp = connp->conn_next; 127*0Sstevel@tonic-gate continue; 128*0Sstevel@tonic-gate } 129*0Sstevel@tonic-gate /* 130*0Sstevel@tonic-gate * For the originating queue, we only copy the message upstream 131*0Sstevel@tonic-gate * if loopback is set. For others reading on the routing 132*0Sstevel@tonic-gate * socket, we check if there is room upstream for a copy of the 133*0Sstevel@tonic-gate * message. 134*0Sstevel@tonic-gate */ 135*0Sstevel@tonic-gate if ((q != NULL) && (CONNP_TO_RQ(connp) == RD(q))) { 136*0Sstevel@tonic-gate if (connp->conn_loopback == 0) { 137*0Sstevel@tonic-gate connp = connp->conn_next; 138*0Sstevel@tonic-gate continue; 139*0Sstevel@tonic-gate } 140*0Sstevel@tonic-gate checkqfull = B_FALSE; 141*0Sstevel@tonic-gate } else { 142*0Sstevel@tonic-gate checkqfull = B_TRUE; 143*0Sstevel@tonic-gate } 144*0Sstevel@tonic-gate CONN_INC_REF(connp); 145*0Sstevel@tonic-gate mutex_exit(&rts_clients.connf_lock); 146*0Sstevel@tonic-gate if (!checkqfull || canputnext(CONNP_TO_RQ(connp))) { 147*0Sstevel@tonic-gate mp1 = dupmsg(mp); 148*0Sstevel@tonic-gate if (mp1 == NULL) 149*0Sstevel@tonic-gate mp1 = copymsg(mp); 150*0Sstevel@tonic-gate if (mp1 != NULL) 151*0Sstevel@tonic-gate putnext(CONNP_TO_RQ(connp), mp1); 152*0Sstevel@tonic-gate } 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate mutex_enter(&rts_clients.connf_lock); 155*0Sstevel@tonic-gate /* Follow the next pointer before releasing the conn. */ 156*0Sstevel@tonic-gate next_connp = connp->conn_next; 157*0Sstevel@tonic-gate CONN_DEC_REF(connp); 158*0Sstevel@tonic-gate connp = next_connp; 159*0Sstevel@tonic-gate } 160*0Sstevel@tonic-gate mutex_exit(&rts_clients.connf_lock); 161*0Sstevel@tonic-gate freemsg(mp); 162*0Sstevel@tonic-gate } 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate /* 165*0Sstevel@tonic-gate * Takes an ire and sends an ack to all the routing sockets. This 166*0Sstevel@tonic-gate * routine is used 167*0Sstevel@tonic-gate * - when a route is created/deleted through the ioctl interface. 168*0Sstevel@tonic-gate * - when ire_expire deletes a stale redirect 169*0Sstevel@tonic-gate */ 170*0Sstevel@tonic-gate void 171*0Sstevel@tonic-gate ip_rts_rtmsg(int type, ire_t *ire, int error) 172*0Sstevel@tonic-gate { 173*0Sstevel@tonic-gate mblk_t *mp; 174*0Sstevel@tonic-gate rt_msghdr_t *rtm; 175*0Sstevel@tonic-gate int rtm_addrs = (RTA_DST | RTA_NETMASK | RTA_GATEWAY); 176*0Sstevel@tonic-gate sa_family_t af; 177*0Sstevel@tonic-gate in6_addr_t gw_addr_v6; 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate if (ire == NULL) 180*0Sstevel@tonic-gate return; 181*0Sstevel@tonic-gate ASSERT(ire->ire_ipversion == IPV4_VERSION || 182*0Sstevel@tonic-gate ire->ire_ipversion == IPV6_VERSION); 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate if (ire->ire_flags & RTF_SETSRC) 185*0Sstevel@tonic-gate rtm_addrs |= RTA_SRC; 186*0Sstevel@tonic-gate 187*0Sstevel@tonic-gate switch (ire->ire_ipversion) { 188*0Sstevel@tonic-gate case IPV4_VERSION: 189*0Sstevel@tonic-gate af = AF_INET; 190*0Sstevel@tonic-gate mp = rts_alloc_msg(type, rtm_addrs, af); 191*0Sstevel@tonic-gate if (mp == NULL) 192*0Sstevel@tonic-gate return; 193*0Sstevel@tonic-gate rts_fill_msg(type, rtm_addrs, ire->ire_addr, ire->ire_mask, 194*0Sstevel@tonic-gate ire->ire_gateway_addr, ire->ire_src_addr, 0, 0, NULL, mp); 195*0Sstevel@tonic-gate break; 196*0Sstevel@tonic-gate case IPV6_VERSION: 197*0Sstevel@tonic-gate af = AF_INET6; 198*0Sstevel@tonic-gate mp = rts_alloc_msg(type, rtm_addrs, af); 199*0Sstevel@tonic-gate if (mp == NULL) 200*0Sstevel@tonic-gate return; 201*0Sstevel@tonic-gate mutex_enter(&ire->ire_lock); 202*0Sstevel@tonic-gate gw_addr_v6 = ire->ire_gateway_addr_v6; 203*0Sstevel@tonic-gate mutex_exit(&ire->ire_lock); 204*0Sstevel@tonic-gate rts_fill_msg_v6(type, rtm_addrs, &ire->ire_addr_v6, 205*0Sstevel@tonic-gate &ire->ire_mask_v6, &gw_addr_v6, 206*0Sstevel@tonic-gate &ire->ire_src_addr_v6, &ipv6_all_zeros, &ipv6_all_zeros, 207*0Sstevel@tonic-gate NULL, mp); 208*0Sstevel@tonic-gate break; 209*0Sstevel@tonic-gate } 210*0Sstevel@tonic-gate rtm = (rt_msghdr_t *)mp->b_rptr; 211*0Sstevel@tonic-gate mp->b_wptr = (uchar_t *)&mp->b_rptr[rtm->rtm_msglen]; 212*0Sstevel@tonic-gate rtm->rtm_addrs = rtm_addrs; 213*0Sstevel@tonic-gate rtm->rtm_flags = ire->ire_flags; 214*0Sstevel@tonic-gate if (error != 0) 215*0Sstevel@tonic-gate rtm->rtm_errno = error; 216*0Sstevel@tonic-gate else 217*0Sstevel@tonic-gate rtm->rtm_flags |= RTF_DONE; 218*0Sstevel@tonic-gate rts_queue_input(mp, NULL, af); 219*0Sstevel@tonic-gate } 220*0Sstevel@tonic-gate 221*0Sstevel@tonic-gate /* ARGSUSED */ 222*0Sstevel@tonic-gate static void 223*0Sstevel@tonic-gate ip_rts_request_retry(ipsq_t *dummy_sq, queue_t *q, mblk_t *mp, void *dummy) 224*0Sstevel@tonic-gate { 225*0Sstevel@tonic-gate (void) ip_rts_request(q, mp, DB_CRED(mp)); 226*0Sstevel@tonic-gate } 227*0Sstevel@tonic-gate 228*0Sstevel@tonic-gate /* 229*0Sstevel@tonic-gate * Processes requests received on a routing socket. It extracts all the 230*0Sstevel@tonic-gate * arguments and calls the appropriate function to process the request. 231*0Sstevel@tonic-gate * 232*0Sstevel@tonic-gate * RTA_SRC bit flag requests are sent by mipagent and 'route -setsrc'. 233*0Sstevel@tonic-gate * RTA_SRCIFP bit flag requests are sent by mipagent only. 234*0Sstevel@tonic-gate * 235*0Sstevel@tonic-gate * In general, this function does not consume the message supplied but rather 236*0Sstevel@tonic-gate * sends the message upstream with an appropriate UNIX errno. 237*0Sstevel@tonic-gate * 238*0Sstevel@tonic-gate * We may need to restart this operation if the ipif cannot be looked up 239*0Sstevel@tonic-gate * due to an exclusive operation that is currently in progress. The restart 240*0Sstevel@tonic-gate * entry point is ip_rts_request_retry. While the request is enqueud in the 241*0Sstevel@tonic-gate * ipsq the ioctl could be aborted and the conn close. To ensure that we don't 242*0Sstevel@tonic-gate * have stale conn pointers, ip_wput_ioctl does a conn refhold. This is 243*0Sstevel@tonic-gate * released at the completion of the rts ioctl at the end of this function 244*0Sstevel@tonic-gate * by calling CONN_OPER_PENDING_DONE or when the ioctl is aborted and 245*0Sstevel@tonic-gate * conn close occurs in conn_ioctl_cleanup. 246*0Sstevel@tonic-gate */ 247*0Sstevel@tonic-gate int 248*0Sstevel@tonic-gate ip_rts_request(queue_t *q, mblk_t *mp, cred_t *ioc_cr) 249*0Sstevel@tonic-gate { 250*0Sstevel@tonic-gate rt_msghdr_t *rtm = NULL; 251*0Sstevel@tonic-gate in6_addr_t dst_addr_v6; 252*0Sstevel@tonic-gate in6_addr_t src_addr_v6; 253*0Sstevel@tonic-gate in6_addr_t gw_addr_v6; 254*0Sstevel@tonic-gate in6_addr_t net_mask_v6; 255*0Sstevel@tonic-gate in6_addr_t author_v6; 256*0Sstevel@tonic-gate in6_addr_t if_addr_v6; 257*0Sstevel@tonic-gate mblk_t *mp1, *ioc_mp = mp; 258*0Sstevel@tonic-gate ire_t *ire = NULL; 259*0Sstevel@tonic-gate ire_t *sire = NULL; 260*0Sstevel@tonic-gate int error = 0; 261*0Sstevel@tonic-gate int match_flags = MATCH_IRE_DSTONLY; 262*0Sstevel@tonic-gate int found_addrs; 263*0Sstevel@tonic-gate sa_family_t af; 264*0Sstevel@tonic-gate ipaddr_t dst_addr; 265*0Sstevel@tonic-gate ipaddr_t gw_addr; 266*0Sstevel@tonic-gate ipaddr_t src_addr; 267*0Sstevel@tonic-gate ipaddr_t net_mask; 268*0Sstevel@tonic-gate ushort_t index; 269*0Sstevel@tonic-gate ushort_t src_index; 270*0Sstevel@tonic-gate ipif_t *ipif = NULL; 271*0Sstevel@tonic-gate ipif_t *src_ipif = NULL; 272*0Sstevel@tonic-gate ipif_t *tmp_ipif = NULL; 273*0Sstevel@tonic-gate IOCP iocp = (IOCP)mp->b_rptr; 274*0Sstevel@tonic-gate conn_t *connp; 275*0Sstevel@tonic-gate 276*0Sstevel@tonic-gate ip1dbg(("ip_rts_request: mp is %x\n", DB_TYPE(mp))); 277*0Sstevel@tonic-gate 278*0Sstevel@tonic-gate ASSERT(CONN_Q(q)); 279*0Sstevel@tonic-gate connp = Q_TO_CONN(q); 280*0Sstevel@tonic-gate 281*0Sstevel@tonic-gate ASSERT(mp->b_cont != NULL); 282*0Sstevel@tonic-gate /* ioc_mp holds mp */ 283*0Sstevel@tonic-gate mp = mp->b_cont; 284*0Sstevel@tonic-gate 285*0Sstevel@tonic-gate /* 286*0Sstevel@tonic-gate * The Routing Socket data starts on 287*0Sstevel@tonic-gate * next block. If there is no next block 288*0Sstevel@tonic-gate * this is an indication from routing module 289*0Sstevel@tonic-gate * that it is a routing socket stream queue. 290*0Sstevel@tonic-gate */ 291*0Sstevel@tonic-gate if (mp->b_cont != NULL) { 292*0Sstevel@tonic-gate mp1 = dupmsg(mp->b_cont); 293*0Sstevel@tonic-gate if (mp1 == NULL) { 294*0Sstevel@tonic-gate freemsg(mp); 295*0Sstevel@tonic-gate error = ENOBUFS; 296*0Sstevel@tonic-gate goto done; 297*0Sstevel@tonic-gate } 298*0Sstevel@tonic-gate mp = mp1; 299*0Sstevel@tonic-gate } else { 300*0Sstevel@tonic-gate /* 301*0Sstevel@tonic-gate * This is a message from RTS module 302*0Sstevel@tonic-gate * indicating that this is a Routing Socket 303*0Sstevel@tonic-gate * Stream. Insert this conn_t in routing 304*0Sstevel@tonic-gate * socket client list. 305*0Sstevel@tonic-gate */ 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate connp->conn_loopback = 1; 308*0Sstevel@tonic-gate ipcl_hash_insert_wildcard(&rts_clients, connp); 309*0Sstevel@tonic-gate 310*0Sstevel@tonic-gate goto done; 311*0Sstevel@tonic-gate } 312*0Sstevel@tonic-gate if (mp->b_cont != NULL && !pullupmsg(mp, -1)) { 313*0Sstevel@tonic-gate freemsg(mp); 314*0Sstevel@tonic-gate error = EINVAL; 315*0Sstevel@tonic-gate goto done; 316*0Sstevel@tonic-gate } 317*0Sstevel@tonic-gate if ((mp->b_wptr - mp->b_rptr) < sizeof (rt_msghdr_t)) { 318*0Sstevel@tonic-gate freemsg(mp); 319*0Sstevel@tonic-gate error = EINVAL; 320*0Sstevel@tonic-gate goto done; 321*0Sstevel@tonic-gate } 322*0Sstevel@tonic-gate 323*0Sstevel@tonic-gate /* 324*0Sstevel@tonic-gate * Check the routing message for basic consistency including the 325*0Sstevel@tonic-gate * version number and that the number of octets written is the same 326*0Sstevel@tonic-gate * as specified by the rtm_msglen field. 327*0Sstevel@tonic-gate * 328*0Sstevel@tonic-gate * At this point, an error can be delivered back via rtm_errno. 329*0Sstevel@tonic-gate */ 330*0Sstevel@tonic-gate rtm = (rt_msghdr_t *)mp->b_rptr; 331*0Sstevel@tonic-gate if ((mp->b_wptr - mp->b_rptr) != rtm->rtm_msglen) { 332*0Sstevel@tonic-gate error = EINVAL; 333*0Sstevel@tonic-gate goto done; 334*0Sstevel@tonic-gate } 335*0Sstevel@tonic-gate if (rtm->rtm_version != RTM_VERSION) { 336*0Sstevel@tonic-gate error = EPROTONOSUPPORT; 337*0Sstevel@tonic-gate goto done; 338*0Sstevel@tonic-gate } 339*0Sstevel@tonic-gate 340*0Sstevel@tonic-gate /* Only allow RTM_GET or RTM_RESOLVE for unprivileged process */ 341*0Sstevel@tonic-gate if (rtm->rtm_type != RTM_GET && 342*0Sstevel@tonic-gate rtm->rtm_type != RTM_RESOLVE && 343*0Sstevel@tonic-gate (ioc_cr == NULL || 344*0Sstevel@tonic-gate secpolicy_net_config(ioc_cr, B_FALSE) != 0)) { 345*0Sstevel@tonic-gate error = EPERM; 346*0Sstevel@tonic-gate goto done; 347*0Sstevel@tonic-gate } 348*0Sstevel@tonic-gate 349*0Sstevel@tonic-gate found_addrs = rts_getaddrs(rtm, &dst_addr_v6, &gw_addr_v6, &net_mask_v6, 350*0Sstevel@tonic-gate &author_v6, &if_addr_v6, &src_addr_v6, &index, &src_index, &af); 351*0Sstevel@tonic-gate if ((found_addrs & RTA_DST) == 0) { 352*0Sstevel@tonic-gate error = EINVAL; 353*0Sstevel@tonic-gate goto done; 354*0Sstevel@tonic-gate } 355*0Sstevel@tonic-gate 356*0Sstevel@tonic-gate /* 357*0Sstevel@tonic-gate * Based on the address family of the destination address, determine 358*0Sstevel@tonic-gate * the destination, gateway and netmask and return the appropriate error 359*0Sstevel@tonic-gate * if an unknown address family was specified (following the errno 360*0Sstevel@tonic-gate * values that 4.4BSD-Lite2 returns.) 361*0Sstevel@tonic-gate */ 362*0Sstevel@tonic-gate switch (af) { 363*0Sstevel@tonic-gate case AF_INET: 364*0Sstevel@tonic-gate /* 365*0Sstevel@tonic-gate * RTA_SRCIFP is supported for interface route only. 366*0Sstevel@tonic-gate * Thus a gateway route with srcifindex is rejected, 367*0Sstevel@tonic-gate * except if it's a request to add reverse tunnel 368*0Sstevel@tonic-gate * route. 369*0Sstevel@tonic-gate */ 370*0Sstevel@tonic-gate if ((rtm->rtm_flags & RTF_GATEWAY) && 371*0Sstevel@tonic-gate (found_addrs & RTA_SRCIFP) && 372*0Sstevel@tonic-gate !(found_addrs & RTA_SRC)) { 373*0Sstevel@tonic-gate error = EINVAL; 374*0Sstevel@tonic-gate goto done; 375*0Sstevel@tonic-gate } 376*0Sstevel@tonic-gate IN6_V4MAPPED_TO_IPADDR(&dst_addr_v6, dst_addr); 377*0Sstevel@tonic-gate IN6_V4MAPPED_TO_IPADDR(&src_addr_v6, src_addr); 378*0Sstevel@tonic-gate IN6_V4MAPPED_TO_IPADDR(&gw_addr_v6, gw_addr); 379*0Sstevel@tonic-gate if (((found_addrs & RTA_NETMASK) == 0) || 380*0Sstevel@tonic-gate (rtm->rtm_flags & RTF_HOST)) 381*0Sstevel@tonic-gate net_mask = IP_HOST_MASK; 382*0Sstevel@tonic-gate else 383*0Sstevel@tonic-gate IN6_V4MAPPED_TO_IPADDR(&net_mask_v6, net_mask); 384*0Sstevel@tonic-gate break; 385*0Sstevel@tonic-gate case AF_INET6: 386*0Sstevel@tonic-gate /* 387*0Sstevel@tonic-gate * RTA_SRCIFP is not a valid flag for IPv6 routes. 388*0Sstevel@tonic-gate */ 389*0Sstevel@tonic-gate if (found_addrs & RTA_SRCIFP) { 390*0Sstevel@tonic-gate error = EINVAL; 391*0Sstevel@tonic-gate goto done; 392*0Sstevel@tonic-gate } 393*0Sstevel@tonic-gate if (((found_addrs & RTA_NETMASK) == 0) || 394*0Sstevel@tonic-gate (rtm->rtm_flags & RTF_HOST)) 395*0Sstevel@tonic-gate net_mask_v6 = ipv6_all_ones; 396*0Sstevel@tonic-gate break; 397*0Sstevel@tonic-gate default: 398*0Sstevel@tonic-gate /* 399*0Sstevel@tonic-gate * These errno values are meant to be compatible with 400*0Sstevel@tonic-gate * 4.4BSD-Lite2 for the given message types. 401*0Sstevel@tonic-gate */ 402*0Sstevel@tonic-gate switch (rtm->rtm_type) { 403*0Sstevel@tonic-gate case RTM_ADD: 404*0Sstevel@tonic-gate case RTM_DELETE: 405*0Sstevel@tonic-gate error = ESRCH; 406*0Sstevel@tonic-gate goto done; 407*0Sstevel@tonic-gate case RTM_GET: 408*0Sstevel@tonic-gate case RTM_CHANGE: 409*0Sstevel@tonic-gate error = EAFNOSUPPORT; 410*0Sstevel@tonic-gate goto done; 411*0Sstevel@tonic-gate default: 412*0Sstevel@tonic-gate error = EOPNOTSUPP; 413*0Sstevel@tonic-gate goto done; 414*0Sstevel@tonic-gate } 415*0Sstevel@tonic-gate } 416*0Sstevel@tonic-gate 417*0Sstevel@tonic-gate /* 418*0Sstevel@tonic-gate * At this point, the address family must be something known. 419*0Sstevel@tonic-gate */ 420*0Sstevel@tonic-gate ASSERT(af == AF_INET || af == AF_INET6); 421*0Sstevel@tonic-gate 422*0Sstevel@tonic-gate if (index != 0) { 423*0Sstevel@tonic-gate ill_t *ill; 424*0Sstevel@tonic-gate 425*0Sstevel@tonic-gate /* 426*0Sstevel@tonic-gate * IPC must be refheld somewhere in ip_wput_nondata or 427*0Sstevel@tonic-gate * ip_wput_ioctl etc... and cleaned up if ioctl is killed. 428*0Sstevel@tonic-gate * If ILL_CHANGING the request is queued in the ipsq. 429*0Sstevel@tonic-gate */ 430*0Sstevel@tonic-gate ill = ill_lookup_on_ifindex(index, af == AF_INET6, 431*0Sstevel@tonic-gate CONNP_TO_WQ(connp), ioc_mp, ip_rts_request_retry, &error); 432*0Sstevel@tonic-gate if (ill == NULL) { 433*0Sstevel@tonic-gate if (error != EINPROGRESS) 434*0Sstevel@tonic-gate error = EINVAL; 435*0Sstevel@tonic-gate goto done; 436*0Sstevel@tonic-gate } 437*0Sstevel@tonic-gate 438*0Sstevel@tonic-gate ipif = ipif_get_next_ipif(NULL, ill); 439*0Sstevel@tonic-gate ill_refrele(ill); 440*0Sstevel@tonic-gate /* 441*0Sstevel@tonic-gate * If this is replacement ipif, prevent a route from 442*0Sstevel@tonic-gate * being added. 443*0Sstevel@tonic-gate */ 444*0Sstevel@tonic-gate if (ipif != NULL && ipif->ipif_replace_zero) { 445*0Sstevel@tonic-gate error = ENETDOWN; 446*0Sstevel@tonic-gate goto done; 447*0Sstevel@tonic-gate } 448*0Sstevel@tonic-gate match_flags |= MATCH_IRE_ILL; 449*0Sstevel@tonic-gate } 450*0Sstevel@tonic-gate 451*0Sstevel@tonic-gate /* RTA_SRCIFP is unsupported on AF_INET6. */ 452*0Sstevel@tonic-gate if (af == AF_INET && src_index != 0) { 453*0Sstevel@tonic-gate ill_t *ill; 454*0Sstevel@tonic-gate 455*0Sstevel@tonic-gate /* If ILL_CHANGING the request is queued in the ipsq. */ 456*0Sstevel@tonic-gate ill = ill_lookup_on_ifindex(src_index, B_FALSE, 457*0Sstevel@tonic-gate CONNP_TO_WQ(connp), ioc_mp, ip_rts_request_retry, &error); 458*0Sstevel@tonic-gate if (ill == NULL) { 459*0Sstevel@tonic-gate if (error != EINPROGRESS) 460*0Sstevel@tonic-gate error = EINVAL; 461*0Sstevel@tonic-gate goto done; 462*0Sstevel@tonic-gate } 463*0Sstevel@tonic-gate 464*0Sstevel@tonic-gate src_ipif = ipif_get_next_ipif(NULL, ill); 465*0Sstevel@tonic-gate ill_refrele(ill); 466*0Sstevel@tonic-gate } 467*0Sstevel@tonic-gate /* 468*0Sstevel@tonic-gate * If a netmask was supplied in the message, then subsequent route 469*0Sstevel@tonic-gate * lookups will attempt to match on the netmask as well. 470*0Sstevel@tonic-gate */ 471*0Sstevel@tonic-gate if ((found_addrs & RTA_NETMASK) != 0) 472*0Sstevel@tonic-gate match_flags |= MATCH_IRE_MASK; 473*0Sstevel@tonic-gate 474*0Sstevel@tonic-gate switch (rtm->rtm_type) { 475*0Sstevel@tonic-gate case RTM_ADD: 476*0Sstevel@tonic-gate /* if we are adding a route, gateway is a must */ 477*0Sstevel@tonic-gate if ((found_addrs & RTA_GATEWAY) == 0) { 478*0Sstevel@tonic-gate error = EINVAL; 479*0Sstevel@tonic-gate goto done; 480*0Sstevel@tonic-gate } 481*0Sstevel@tonic-gate 482*0Sstevel@tonic-gate /* Multirouting does not support net routes. */ 483*0Sstevel@tonic-gate if ((rtm->rtm_flags & (RTF_MULTIRT | RTF_HOST)) == 484*0Sstevel@tonic-gate RTF_MULTIRT) { 485*0Sstevel@tonic-gate error = EADDRNOTAVAIL; 486*0Sstevel@tonic-gate goto done; 487*0Sstevel@tonic-gate } 488*0Sstevel@tonic-gate 489*0Sstevel@tonic-gate /* 490*0Sstevel@tonic-gate * Multirouting and user-specified source addresses 491*0Sstevel@tonic-gate * do not support interface based routing. 492*0Sstevel@tonic-gate * Assigning a source address to an interface based 493*0Sstevel@tonic-gate * route is achievable by plumbing a new ipif and 494*0Sstevel@tonic-gate * setting up the interface route via this ipif, 495*0Sstevel@tonic-gate * though. 496*0Sstevel@tonic-gate */ 497*0Sstevel@tonic-gate if (rtm->rtm_flags & (RTF_MULTIRT | RTF_SETSRC)) { 498*0Sstevel@tonic-gate if ((rtm->rtm_flags & RTF_GATEWAY) == 0) { 499*0Sstevel@tonic-gate error = EADDRNOTAVAIL; 500*0Sstevel@tonic-gate goto done; 501*0Sstevel@tonic-gate } 502*0Sstevel@tonic-gate } 503*0Sstevel@tonic-gate 504*0Sstevel@tonic-gate switch (af) { 505*0Sstevel@tonic-gate case AF_INET: 506*0Sstevel@tonic-gate if (src_addr != INADDR_ANY) { 507*0Sstevel@tonic-gate /* 508*0Sstevel@tonic-gate * If there is a source address, but 509*0Sstevel@tonic-gate * no RTF_SETSRC modifier, setup a MobileIP 510*0Sstevel@tonic-gate * reverse tunnel. 511*0Sstevel@tonic-gate */ 512*0Sstevel@tonic-gate if ((rtm->rtm_flags & RTF_SETSRC) == 0) { 513*0Sstevel@tonic-gate error = ip_mrtun_rt_add(src_addr, 514*0Sstevel@tonic-gate rtm->rtm_flags, ipif, 515*0Sstevel@tonic-gate src_ipif, &ire, CONNP_TO_WQ(connp), 516*0Sstevel@tonic-gate ioc_mp, ip_rts_request_retry); 517*0Sstevel@tonic-gate break; 518*0Sstevel@tonic-gate } 519*0Sstevel@tonic-gate /* 520*0Sstevel@tonic-gate * The RTF_SETSRC flag is present, check that 521*0Sstevel@tonic-gate * the supplied src address is not the loopback 522*0Sstevel@tonic-gate * address. This would produce martian packets. 523*0Sstevel@tonic-gate */ 524*0Sstevel@tonic-gate if (src_addr == htonl(INADDR_LOOPBACK)) { 525*0Sstevel@tonic-gate error = EINVAL; 526*0Sstevel@tonic-gate goto done; 527*0Sstevel@tonic-gate } 528*0Sstevel@tonic-gate /* 529*0Sstevel@tonic-gate * Also check that the supplied address is a 530*0Sstevel@tonic-gate * valid, local one. 531*0Sstevel@tonic-gate */ 532*0Sstevel@tonic-gate tmp_ipif = ipif_lookup_addr(src_addr, NULL, 533*0Sstevel@tonic-gate ALL_ZONES, CONNP_TO_WQ(connp), ioc_mp, 534*0Sstevel@tonic-gate ip_rts_request_retry, &error); 535*0Sstevel@tonic-gate if (tmp_ipif == NULL) { 536*0Sstevel@tonic-gate if (error != EINPROGRESS) 537*0Sstevel@tonic-gate error = EADDRNOTAVAIL; 538*0Sstevel@tonic-gate goto done; 539*0Sstevel@tonic-gate } 540*0Sstevel@tonic-gate if (!(tmp_ipif->ipif_flags & IPIF_UP) || 541*0Sstevel@tonic-gate (tmp_ipif->ipif_flags & 542*0Sstevel@tonic-gate (IPIF_NOLOCAL | IPIF_ANYCAST))) { 543*0Sstevel@tonic-gate error = EINVAL; 544*0Sstevel@tonic-gate goto done; 545*0Sstevel@tonic-gate } 546*0Sstevel@tonic-gate } else { 547*0Sstevel@tonic-gate /* 548*0Sstevel@tonic-gate * The RTF_SETSRC modifier must be associated 549*0Sstevel@tonic-gate * to a non-null source address. 550*0Sstevel@tonic-gate */ 551*0Sstevel@tonic-gate if (rtm->rtm_flags & RTF_SETSRC) { 552*0Sstevel@tonic-gate error = EINVAL; 553*0Sstevel@tonic-gate goto done; 554*0Sstevel@tonic-gate } 555*0Sstevel@tonic-gate } 556*0Sstevel@tonic-gate 557*0Sstevel@tonic-gate error = ip_rt_add(dst_addr, net_mask, 558*0Sstevel@tonic-gate gw_addr, src_addr, 559*0Sstevel@tonic-gate rtm->rtm_flags, ipif, src_ipif, &ire, B_FALSE, 560*0Sstevel@tonic-gate CONNP_TO_WQ(connp), ioc_mp, ip_rts_request_retry); 561*0Sstevel@tonic-gate if (ipif != NULL) 562*0Sstevel@tonic-gate ASSERT(!MUTEX_HELD(&ipif->ipif_ill->ill_lock)); 563*0Sstevel@tonic-gate break; 564*0Sstevel@tonic-gate case AF_INET6: 565*0Sstevel@tonic-gate if (!IN6_IS_ADDR_UNSPECIFIED(&src_addr_v6)) { 566*0Sstevel@tonic-gate /* 567*0Sstevel@tonic-gate * If there is a source address, but 568*0Sstevel@tonic-gate * no RTF_SETSRC modifier, reject, as 569*0Sstevel@tonic-gate * MobileIP IPv6 reverse tunnels are 570*0Sstevel@tonic-gate * not supported. 571*0Sstevel@tonic-gate */ 572*0Sstevel@tonic-gate if ((rtm->rtm_flags & RTF_SETSRC) == 0) { 573*0Sstevel@tonic-gate error = EINVAL; 574*0Sstevel@tonic-gate goto done; 575*0Sstevel@tonic-gate } 576*0Sstevel@tonic-gate /* 577*0Sstevel@tonic-gate * The RTF_SETSRC flag is present, check that 578*0Sstevel@tonic-gate * the supplied src address is not the loopback 579*0Sstevel@tonic-gate * address. This would produce martian packets. 580*0Sstevel@tonic-gate */ 581*0Sstevel@tonic-gate if (IN6_IS_ADDR_LOOPBACK(&src_addr_v6)) { 582*0Sstevel@tonic-gate error = EINVAL; 583*0Sstevel@tonic-gate goto done; 584*0Sstevel@tonic-gate } 585*0Sstevel@tonic-gate /* 586*0Sstevel@tonic-gate * Also check that the supplied address is a 587*0Sstevel@tonic-gate * valid, local one. 588*0Sstevel@tonic-gate */ 589*0Sstevel@tonic-gate tmp_ipif = ipif_lookup_addr_v6(&src_addr_v6, 590*0Sstevel@tonic-gate NULL, ALL_ZONES, CONNP_TO_WQ(connp), ioc_mp, 591*0Sstevel@tonic-gate ip_rts_request_retry, &error); 592*0Sstevel@tonic-gate if (tmp_ipif == NULL) { 593*0Sstevel@tonic-gate if (error != EINPROGRESS) 594*0Sstevel@tonic-gate error = EADDRNOTAVAIL; 595*0Sstevel@tonic-gate goto done; 596*0Sstevel@tonic-gate } 597*0Sstevel@tonic-gate 598*0Sstevel@tonic-gate if (!(tmp_ipif->ipif_flags & IPIF_UP) || 599*0Sstevel@tonic-gate (tmp_ipif->ipif_flags & 600*0Sstevel@tonic-gate (IPIF_NOLOCAL | IPIF_ANYCAST))) { 601*0Sstevel@tonic-gate error = EINVAL; 602*0Sstevel@tonic-gate goto done; 603*0Sstevel@tonic-gate } 604*0Sstevel@tonic-gate 605*0Sstevel@tonic-gate error = ip_rt_add_v6(&dst_addr_v6, &net_mask_v6, 606*0Sstevel@tonic-gate &gw_addr_v6, &src_addr_v6, rtm->rtm_flags, 607*0Sstevel@tonic-gate ipif, &ire, CONNP_TO_WQ(connp), ioc_mp, 608*0Sstevel@tonic-gate ip_rts_request_retry); 609*0Sstevel@tonic-gate break; 610*0Sstevel@tonic-gate } 611*0Sstevel@tonic-gate /* 612*0Sstevel@tonic-gate * The RTF_SETSRC modifier must be associated 613*0Sstevel@tonic-gate * to a non-null source address. 614*0Sstevel@tonic-gate */ 615*0Sstevel@tonic-gate if (rtm->rtm_flags & RTF_SETSRC) { 616*0Sstevel@tonic-gate error = EINVAL; 617*0Sstevel@tonic-gate goto done; 618*0Sstevel@tonic-gate } 619*0Sstevel@tonic-gate error = ip_rt_add_v6(&dst_addr_v6, &net_mask_v6, 620*0Sstevel@tonic-gate &gw_addr_v6, NULL, rtm->rtm_flags, 621*0Sstevel@tonic-gate ipif, &ire, CONNP_TO_WQ(connp), ioc_mp, 622*0Sstevel@tonic-gate ip_rts_request_retry); 623*0Sstevel@tonic-gate if (ipif != NULL) 624*0Sstevel@tonic-gate ASSERT(!MUTEX_HELD(&ipif->ipif_ill->ill_lock)); 625*0Sstevel@tonic-gate break; 626*0Sstevel@tonic-gate } 627*0Sstevel@tonic-gate if (error != 0) 628*0Sstevel@tonic-gate goto done; 629*0Sstevel@tonic-gate ASSERT(ire != NULL); 630*0Sstevel@tonic-gate rts_setmetrics(ire, rtm->rtm_inits, &rtm->rtm_rmx); 631*0Sstevel@tonic-gate break; 632*0Sstevel@tonic-gate case RTM_DELETE: 633*0Sstevel@tonic-gate /* if we are deleting a route, gateway is a must */ 634*0Sstevel@tonic-gate if ((found_addrs & RTA_GATEWAY) == 0) { 635*0Sstevel@tonic-gate error = EINVAL; 636*0Sstevel@tonic-gate goto done; 637*0Sstevel@tonic-gate } 638*0Sstevel@tonic-gate /* 639*0Sstevel@tonic-gate * The RTF_SETSRC modifier does not make sense 640*0Sstevel@tonic-gate * when deleting a route. 641*0Sstevel@tonic-gate */ 642*0Sstevel@tonic-gate if (rtm->rtm_flags & RTF_SETSRC) { 643*0Sstevel@tonic-gate error = EINVAL; 644*0Sstevel@tonic-gate goto done; 645*0Sstevel@tonic-gate } 646*0Sstevel@tonic-gate 647*0Sstevel@tonic-gate switch (af) { 648*0Sstevel@tonic-gate case AF_INET: 649*0Sstevel@tonic-gate /* 650*0Sstevel@tonic-gate * If there is a source address, delete 651*0Sstevel@tonic-gate * a MobileIP reverse tunnel. 652*0Sstevel@tonic-gate */ 653*0Sstevel@tonic-gate if (src_addr != INADDR_ANY) { 654*0Sstevel@tonic-gate error = ip_mrtun_rt_delete(src_addr, 655*0Sstevel@tonic-gate src_ipif); 656*0Sstevel@tonic-gate break; 657*0Sstevel@tonic-gate } 658*0Sstevel@tonic-gate error = ip_rt_delete(dst_addr, net_mask, gw_addr, 659*0Sstevel@tonic-gate found_addrs, rtm->rtm_flags, ipif, src_ipif, 660*0Sstevel@tonic-gate B_FALSE, CONNP_TO_WQ(connp), ioc_mp, 661*0Sstevel@tonic-gate ip_rts_request_retry); 662*0Sstevel@tonic-gate break; 663*0Sstevel@tonic-gate case AF_INET6: 664*0Sstevel@tonic-gate error = ip_rt_delete_v6(&dst_addr_v6, &net_mask_v6, 665*0Sstevel@tonic-gate &gw_addr_v6, found_addrs, rtm->rtm_flags, ipif, 666*0Sstevel@tonic-gate CONNP_TO_WQ(connp), ioc_mp, ip_rts_request_retry); 667*0Sstevel@tonic-gate break; 668*0Sstevel@tonic-gate } 669*0Sstevel@tonic-gate break; 670*0Sstevel@tonic-gate case RTM_GET: 671*0Sstevel@tonic-gate case RTM_CHANGE: 672*0Sstevel@tonic-gate /* 673*0Sstevel@tonic-gate * In the case of RTM_GET, the forwarding table should be 674*0Sstevel@tonic-gate * searched recursively with default being matched if the 675*0Sstevel@tonic-gate * specific route doesn't exist. Also, if a gateway was 676*0Sstevel@tonic-gate * specified then the gateway address must also be matched. 677*0Sstevel@tonic-gate * 678*0Sstevel@tonic-gate * In the case of RTM_CHANGE, the gateway address (if supplied) 679*0Sstevel@tonic-gate * is the new gateway address so matching on the gateway address 680*0Sstevel@tonic-gate * is not done. This can lead to ambiguity when looking up the 681*0Sstevel@tonic-gate * route to change as usually only the destination (and netmask, 682*0Sstevel@tonic-gate * if supplied) is used for the lookup. However if a RTA_IFP 683*0Sstevel@tonic-gate * sockaddr is also supplied, it can disambiguate which route to 684*0Sstevel@tonic-gate * change provided the ambigous routes are tied to distinct 685*0Sstevel@tonic-gate * ill's (or interface indices). If the routes are not tied to 686*0Sstevel@tonic-gate * any particular interfaces (for example, with traditional 687*0Sstevel@tonic-gate * gateway routes), then a RTA_IFP sockaddr will be of no use as 688*0Sstevel@tonic-gate * it won't match any such routes. 689*0Sstevel@tonic-gate * RTA_SRC is not supported for RTM_GET and RTM_CHANGE, 690*0Sstevel@tonic-gate * except when RTM_CHANGE is combined to RTF_SETSRC. 691*0Sstevel@tonic-gate */ 692*0Sstevel@tonic-gate if (((found_addrs & RTA_SRC) != 0) && 693*0Sstevel@tonic-gate ((rtm->rtm_type == RTM_GET) || 694*0Sstevel@tonic-gate !(rtm->rtm_flags & RTF_SETSRC))) { 695*0Sstevel@tonic-gate error = EOPNOTSUPP; 696*0Sstevel@tonic-gate goto done; 697*0Sstevel@tonic-gate } 698*0Sstevel@tonic-gate 699*0Sstevel@tonic-gate if (rtm->rtm_type == RTM_GET) { 700*0Sstevel@tonic-gate match_flags |= 701*0Sstevel@tonic-gate (MATCH_IRE_DEFAULT | MATCH_IRE_RECURSIVE); 702*0Sstevel@tonic-gate if ((found_addrs & RTA_GATEWAY) != 0) 703*0Sstevel@tonic-gate match_flags |= MATCH_IRE_GW; 704*0Sstevel@tonic-gate } 705*0Sstevel@tonic-gate if (rtm->rtm_type == RTM_CHANGE) { 706*0Sstevel@tonic-gate if ((found_addrs & RTA_GATEWAY) && 707*0Sstevel@tonic-gate (rtm->rtm_flags & RTF_SETSRC)) { 708*0Sstevel@tonic-gate /* 709*0Sstevel@tonic-gate * Do not want to change the gateway, 710*0Sstevel@tonic-gate * but rather the source address. 711*0Sstevel@tonic-gate */ 712*0Sstevel@tonic-gate match_flags |= MATCH_IRE_GW; 713*0Sstevel@tonic-gate } 714*0Sstevel@tonic-gate } 715*0Sstevel@tonic-gate 716*0Sstevel@tonic-gate /* 717*0Sstevel@tonic-gate * If the netmask is all ones (either as supplied or as derived 718*0Sstevel@tonic-gate * above), then first check for an IRE_LOOPBACK or 719*0Sstevel@tonic-gate * IRE_LOCAL entry. 720*0Sstevel@tonic-gate * 721*0Sstevel@tonic-gate * If we didn't check for or find an IRE_LOOPBACK or IRE_LOCAL 722*0Sstevel@tonic-gate * entry, then look in the forwarding table. 723*0Sstevel@tonic-gate */ 724*0Sstevel@tonic-gate switch (af) { 725*0Sstevel@tonic-gate case AF_INET: 726*0Sstevel@tonic-gate if (net_mask == IP_HOST_MASK) { 727*0Sstevel@tonic-gate ire = ire_ctable_lookup(dst_addr, gw_addr, 728*0Sstevel@tonic-gate IRE_LOCAL | IRE_LOOPBACK, NULL, ALL_ZONES, 729*0Sstevel@tonic-gate MATCH_IRE_TYPE | MATCH_IRE_GW); 730*0Sstevel@tonic-gate } 731*0Sstevel@tonic-gate if (ire == NULL) { 732*0Sstevel@tonic-gate ire = ire_ftable_lookup(dst_addr, net_mask, 733*0Sstevel@tonic-gate gw_addr, 0, ipif, &sire, ALL_ZONES, 0, 734*0Sstevel@tonic-gate match_flags); 735*0Sstevel@tonic-gate } 736*0Sstevel@tonic-gate break; 737*0Sstevel@tonic-gate case AF_INET6: 738*0Sstevel@tonic-gate if (IN6_ARE_ADDR_EQUAL(&net_mask_v6, &ipv6_all_ones)) { 739*0Sstevel@tonic-gate ire = ire_ctable_lookup_v6(&dst_addr_v6, 740*0Sstevel@tonic-gate &gw_addr_v6, IRE_LOCAL | IRE_LOOPBACK, NULL, 741*0Sstevel@tonic-gate ALL_ZONES, MATCH_IRE_TYPE | MATCH_IRE_GW); 742*0Sstevel@tonic-gate } 743*0Sstevel@tonic-gate if (ire == NULL) { 744*0Sstevel@tonic-gate ire = ire_ftable_lookup_v6(&dst_addr_v6, 745*0Sstevel@tonic-gate &net_mask_v6, &gw_addr_v6, 0, ipif, &sire, 746*0Sstevel@tonic-gate ALL_ZONES, 0, match_flags); 747*0Sstevel@tonic-gate } 748*0Sstevel@tonic-gate break; 749*0Sstevel@tonic-gate } 750*0Sstevel@tonic-gate 751*0Sstevel@tonic-gate if (ire == NULL) { 752*0Sstevel@tonic-gate error = ESRCH; 753*0Sstevel@tonic-gate goto done; 754*0Sstevel@tonic-gate } 755*0Sstevel@tonic-gate /* we know the IRE before we come here */ 756*0Sstevel@tonic-gate switch (rtm->rtm_type) { 757*0Sstevel@tonic-gate case RTM_GET: 758*0Sstevel@tonic-gate mp1 = rts_rtmget(mp, ire, sire, af); 759*0Sstevel@tonic-gate if (mp1 == NULL) { 760*0Sstevel@tonic-gate error = ENOBUFS; 761*0Sstevel@tonic-gate goto done; 762*0Sstevel@tonic-gate } 763*0Sstevel@tonic-gate freemsg(mp); 764*0Sstevel@tonic-gate mp = mp1; 765*0Sstevel@tonic-gate rtm = (rt_msghdr_t *)mp->b_rptr; 766*0Sstevel@tonic-gate break; 767*0Sstevel@tonic-gate case RTM_CHANGE: 768*0Sstevel@tonic-gate /* 769*0Sstevel@tonic-gate * Do not allow to the multirouting state of a route 770*0Sstevel@tonic-gate * to be changed. This aims to prevent undesirable 771*0Sstevel@tonic-gate * stages where both multirt and non-multirt routes 772*0Sstevel@tonic-gate * for the same destination are declared. 773*0Sstevel@tonic-gate */ 774*0Sstevel@tonic-gate if ((ire->ire_flags & RTF_MULTIRT) != 775*0Sstevel@tonic-gate (rtm->rtm_flags & RTF_MULTIRT)) { 776*0Sstevel@tonic-gate error = EINVAL; 777*0Sstevel@tonic-gate goto done; 778*0Sstevel@tonic-gate } 779*0Sstevel@tonic-gate /* 780*0Sstevel@tonic-gate * Note that we do not need to do 781*0Sstevel@tonic-gate * ire_flush_cache_*(IRE_FLUSH_ADD) as a change 782*0Sstevel@tonic-gate * in metrics or gateway will not affect existing 783*0Sstevel@tonic-gate * routes since it does not create a more specific 784*0Sstevel@tonic-gate * route. 785*0Sstevel@tonic-gate */ 786*0Sstevel@tonic-gate switch (af) { 787*0Sstevel@tonic-gate case AF_INET: 788*0Sstevel@tonic-gate ire_flush_cache_v4(ire, IRE_FLUSH_DELETE); 789*0Sstevel@tonic-gate if ((found_addrs & RTA_GATEWAY) != 0 && 790*0Sstevel@tonic-gate (ire->ire_gateway_addr != gw_addr)) { 791*0Sstevel@tonic-gate ire->ire_gateway_addr = gw_addr; 792*0Sstevel@tonic-gate } 793*0Sstevel@tonic-gate if ((found_addrs & RTA_SRC) != 0 && 794*0Sstevel@tonic-gate (rtm->rtm_flags & RTF_SETSRC) != 0 && 795*0Sstevel@tonic-gate (ire->ire_src_addr != src_addr)) { 796*0Sstevel@tonic-gate 797*0Sstevel@tonic-gate if (src_addr != INADDR_ANY) { 798*0Sstevel@tonic-gate /* 799*0Sstevel@tonic-gate * The RTF_SETSRC flag is 800*0Sstevel@tonic-gate * present, check that the 801*0Sstevel@tonic-gate * supplied src address is not 802*0Sstevel@tonic-gate * the loopback address. This 803*0Sstevel@tonic-gate * would produce martian 804*0Sstevel@tonic-gate * packets. 805*0Sstevel@tonic-gate */ 806*0Sstevel@tonic-gate if (src_addr == 807*0Sstevel@tonic-gate htonl(INADDR_LOOPBACK)) { 808*0Sstevel@tonic-gate error = EINVAL; 809*0Sstevel@tonic-gate goto done; 810*0Sstevel@tonic-gate } 811*0Sstevel@tonic-gate /* 812*0Sstevel@tonic-gate * Also check that the the 813*0Sstevel@tonic-gate * supplied addr is a valid 814*0Sstevel@tonic-gate * local address. 815*0Sstevel@tonic-gate */ 816*0Sstevel@tonic-gate tmp_ipif = ipif_lookup_addr( 817*0Sstevel@tonic-gate src_addr, NULL, ALL_ZONES, 818*0Sstevel@tonic-gate CONNP_TO_WQ(connp), ioc_mp, 819*0Sstevel@tonic-gate ip_rts_request_retry, 820*0Sstevel@tonic-gate &error); 821*0Sstevel@tonic-gate if (tmp_ipif == NULL) { 822*0Sstevel@tonic-gate error = (error == 823*0Sstevel@tonic-gate EINPROGRESS) ? 824*0Sstevel@tonic-gate error : 825*0Sstevel@tonic-gate EADDRNOTAVAIL; 826*0Sstevel@tonic-gate goto done; 827*0Sstevel@tonic-gate } 828*0Sstevel@tonic-gate 829*0Sstevel@tonic-gate if (!(tmp_ipif->ipif_flags & 830*0Sstevel@tonic-gate IPIF_UP) || 831*0Sstevel@tonic-gate (tmp_ipif->ipif_flags & 832*0Sstevel@tonic-gate (IPIF_NOLOCAL | 833*0Sstevel@tonic-gate IPIF_ANYCAST))) { 834*0Sstevel@tonic-gate error = EINVAL; 835*0Sstevel@tonic-gate goto done; 836*0Sstevel@tonic-gate } 837*0Sstevel@tonic-gate ire->ire_flags |= RTF_SETSRC; 838*0Sstevel@tonic-gate } else { 839*0Sstevel@tonic-gate ire->ire_flags &= ~RTF_SETSRC; 840*0Sstevel@tonic-gate } 841*0Sstevel@tonic-gate ire->ire_src_addr = src_addr; 842*0Sstevel@tonic-gate } 843*0Sstevel@tonic-gate break; 844*0Sstevel@tonic-gate case AF_INET6: 845*0Sstevel@tonic-gate ire_flush_cache_v6(ire, IRE_FLUSH_DELETE); 846*0Sstevel@tonic-gate mutex_enter(&ire->ire_lock); 847*0Sstevel@tonic-gate if ((found_addrs & RTA_GATEWAY) != 0 && 848*0Sstevel@tonic-gate !IN6_ARE_ADDR_EQUAL( 849*0Sstevel@tonic-gate &ire->ire_gateway_addr_v6, &gw_addr_v6)) { 850*0Sstevel@tonic-gate ire->ire_gateway_addr_v6 = gw_addr_v6; 851*0Sstevel@tonic-gate } 852*0Sstevel@tonic-gate if ((found_addrs & RTA_SRC) != 0 && 853*0Sstevel@tonic-gate (rtm->rtm_flags & RTF_SETSRC) != 0 && 854*0Sstevel@tonic-gate !IN6_ARE_ADDR_EQUAL( 855*0Sstevel@tonic-gate &ire->ire_src_addr_v6, &src_addr_v6)) { 856*0Sstevel@tonic-gate 857*0Sstevel@tonic-gate if (!IN6_IS_ADDR_UNSPECIFIED( 858*0Sstevel@tonic-gate &src_addr_v6)) { 859*0Sstevel@tonic-gate /* 860*0Sstevel@tonic-gate * The RTF_SETSRC flag is 861*0Sstevel@tonic-gate * present, check that the 862*0Sstevel@tonic-gate * supplied src address is not 863*0Sstevel@tonic-gate * the loopback address. This 864*0Sstevel@tonic-gate * would produce martian 865*0Sstevel@tonic-gate * packets. 866*0Sstevel@tonic-gate */ 867*0Sstevel@tonic-gate if (IN6_IS_ADDR_LOOPBACK( 868*0Sstevel@tonic-gate &src_addr_v6)) { 869*0Sstevel@tonic-gate mutex_exit( 870*0Sstevel@tonic-gate &ire->ire_lock); 871*0Sstevel@tonic-gate error = EINVAL; 872*0Sstevel@tonic-gate goto done; 873*0Sstevel@tonic-gate } 874*0Sstevel@tonic-gate /* 875*0Sstevel@tonic-gate * Also check that the the 876*0Sstevel@tonic-gate * supplied addr is a valid 877*0Sstevel@tonic-gate * local address. 878*0Sstevel@tonic-gate */ 879*0Sstevel@tonic-gate tmp_ipif = ipif_lookup_addr_v6( 880*0Sstevel@tonic-gate &src_addr_v6, NULL, 881*0Sstevel@tonic-gate ALL_ZONES, 882*0Sstevel@tonic-gate CONNP_TO_WQ(connp), ioc_mp, 883*0Sstevel@tonic-gate ip_rts_request_retry, 884*0Sstevel@tonic-gate &error); 885*0Sstevel@tonic-gate if (tmp_ipif == NULL) { 886*0Sstevel@tonic-gate mutex_exit( 887*0Sstevel@tonic-gate &ire->ire_lock); 888*0Sstevel@tonic-gate error = (error == 889*0Sstevel@tonic-gate EINPROGRESS) ? 890*0Sstevel@tonic-gate error : 891*0Sstevel@tonic-gate EADDRNOTAVAIL; 892*0Sstevel@tonic-gate goto done; 893*0Sstevel@tonic-gate } 894*0Sstevel@tonic-gate if (!(tmp_ipif->ipif_flags & 895*0Sstevel@tonic-gate IPIF_UP) || 896*0Sstevel@tonic-gate (tmp_ipif->ipif_flags & 897*0Sstevel@tonic-gate (IPIF_NOLOCAL | 898*0Sstevel@tonic-gate IPIF_ANYCAST))) { 899*0Sstevel@tonic-gate mutex_exit( 900*0Sstevel@tonic-gate &ire->ire_lock); 901*0Sstevel@tonic-gate error = EINVAL; 902*0Sstevel@tonic-gate goto done; 903*0Sstevel@tonic-gate } 904*0Sstevel@tonic-gate ire->ire_flags |= RTF_SETSRC; 905*0Sstevel@tonic-gate } else { 906*0Sstevel@tonic-gate ire->ire_flags &= ~RTF_SETSRC; 907*0Sstevel@tonic-gate } 908*0Sstevel@tonic-gate ire->ire_src_addr_v6 = src_addr_v6; 909*0Sstevel@tonic-gate } 910*0Sstevel@tonic-gate mutex_exit(&ire->ire_lock); 911*0Sstevel@tonic-gate break; 912*0Sstevel@tonic-gate } 913*0Sstevel@tonic-gate rts_setmetrics(ire, rtm->rtm_inits, &rtm->rtm_rmx); 914*0Sstevel@tonic-gate break; 915*0Sstevel@tonic-gate } 916*0Sstevel@tonic-gate break; 917*0Sstevel@tonic-gate default: 918*0Sstevel@tonic-gate error = EOPNOTSUPP; 919*0Sstevel@tonic-gate break; 920*0Sstevel@tonic-gate } 921*0Sstevel@tonic-gate done: 922*0Sstevel@tonic-gate if (ire != NULL) 923*0Sstevel@tonic-gate ire_refrele(ire); 924*0Sstevel@tonic-gate if (sire != NULL) 925*0Sstevel@tonic-gate ire_refrele(sire); 926*0Sstevel@tonic-gate if (ipif != NULL) 927*0Sstevel@tonic-gate ipif_refrele(ipif); 928*0Sstevel@tonic-gate if (src_ipif != NULL) 929*0Sstevel@tonic-gate ipif_refrele(src_ipif); 930*0Sstevel@tonic-gate if (tmp_ipif != NULL) 931*0Sstevel@tonic-gate ipif_refrele(tmp_ipif); 932*0Sstevel@tonic-gate 933*0Sstevel@tonic-gate if (error == EINPROGRESS) 934*0Sstevel@tonic-gate return (error); 935*0Sstevel@tonic-gate if (rtm != NULL) { 936*0Sstevel@tonic-gate ASSERT(mp->b_wptr <= mp->b_datap->db_lim); 937*0Sstevel@tonic-gate if (error != 0) { 938*0Sstevel@tonic-gate rtm->rtm_errno = error; 939*0Sstevel@tonic-gate /* Send error ACK */ 940*0Sstevel@tonic-gate ip1dbg(("ip_rts_request: error %d\n", error)); 941*0Sstevel@tonic-gate } else { 942*0Sstevel@tonic-gate rtm->rtm_flags |= RTF_DONE; 943*0Sstevel@tonic-gate /* OK ACK already set up by caller except this */ 944*0Sstevel@tonic-gate ip2dbg(("ip_rts_request: OK ACK\n")); 945*0Sstevel@tonic-gate } 946*0Sstevel@tonic-gate rts_queue_input(mp, q, af); 947*0Sstevel@tonic-gate } 948*0Sstevel@tonic-gate iocp->ioc_error = error; 949*0Sstevel@tonic-gate ioc_mp->b_datap->db_type = M_IOCACK; 950*0Sstevel@tonic-gate if (iocp->ioc_error != 0) 951*0Sstevel@tonic-gate iocp->ioc_count = 0; 952*0Sstevel@tonic-gate qreply(q, ioc_mp); 953*0Sstevel@tonic-gate /* conn was refheld in ip_wput_ioctl. */ 954*0Sstevel@tonic-gate CONN_OPER_PENDING_DONE(connp); 955*0Sstevel@tonic-gate 956*0Sstevel@tonic-gate return (error); 957*0Sstevel@tonic-gate } 958*0Sstevel@tonic-gate 959*0Sstevel@tonic-gate /* 960*0Sstevel@tonic-gate * Build a reply to the RTM_GET request contained in the given message block 961*0Sstevel@tonic-gate * using the retrieved IRE of the destination address, the parent IRE (if it 962*0Sstevel@tonic-gate * exists) and the address family. 963*0Sstevel@tonic-gate * 964*0Sstevel@tonic-gate * Returns a pointer to a message block containing the reply if successful, 965*0Sstevel@tonic-gate * otherwise NULL is returned. 966*0Sstevel@tonic-gate */ 967*0Sstevel@tonic-gate mblk_t * 968*0Sstevel@tonic-gate rts_rtmget(mblk_t *mp, ire_t *ire, ire_t *sire, sa_family_t af) 969*0Sstevel@tonic-gate { 970*0Sstevel@tonic-gate rt_msghdr_t *rtm; 971*0Sstevel@tonic-gate rt_msghdr_t *new_rtm; 972*0Sstevel@tonic-gate mblk_t *new_mp; 973*0Sstevel@tonic-gate int rtm_addrs; 974*0Sstevel@tonic-gate int rtm_flags; 975*0Sstevel@tonic-gate in6_addr_t gw_addr_v6; 976*0Sstevel@tonic-gate 977*0Sstevel@tonic-gate ASSERT(ire->ire_ipif != NULL); 978*0Sstevel@tonic-gate rtm = (rt_msghdr_t *)mp->b_rptr; 979*0Sstevel@tonic-gate 980*0Sstevel@tonic-gate /* 981*0Sstevel@tonic-gate * Always return RTA_DST, RTA_GATEWAY and RTA_NETMASK. 982*0Sstevel@tonic-gate * 983*0Sstevel@tonic-gate * The 4.4BSD-Lite2 code (net/rtsock.c) returns both 984*0Sstevel@tonic-gate * RTA_IFP and RTA_IFA if either is defined, and also 985*0Sstevel@tonic-gate * returns RTA_BRD if the appropriate interface is 986*0Sstevel@tonic-gate * point-to-point. 987*0Sstevel@tonic-gate */ 988*0Sstevel@tonic-gate rtm_addrs = (RTA_DST | RTA_GATEWAY | RTA_NETMASK); 989*0Sstevel@tonic-gate if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) { 990*0Sstevel@tonic-gate rtm_addrs |= (RTA_IFP | RTA_IFA); 991*0Sstevel@tonic-gate if (ire->ire_ipif->ipif_flags & IPIF_POINTOPOINT) 992*0Sstevel@tonic-gate rtm_addrs |= RTA_BRD; 993*0Sstevel@tonic-gate } 994*0Sstevel@tonic-gate 995*0Sstevel@tonic-gate new_mp = rts_alloc_msg(RTM_GET, rtm_addrs, af); 996*0Sstevel@tonic-gate if (new_mp == NULL) 997*0Sstevel@tonic-gate return (NULL); 998*0Sstevel@tonic-gate 999*0Sstevel@tonic-gate /* 1000*0Sstevel@tonic-gate * We set the destination address, gateway address, 1001*0Sstevel@tonic-gate * netmask and flags in the RTM_GET response depending 1002*0Sstevel@tonic-gate * on whether we found a parent IRE or not. 1003*0Sstevel@tonic-gate * In particular, if we did find a parent IRE during the 1004*0Sstevel@tonic-gate * recursive search, use that IRE's gateway address. 1005*0Sstevel@tonic-gate * Otherwise, we use the IRE's source address for the 1006*0Sstevel@tonic-gate * gateway address. 1007*0Sstevel@tonic-gate */ 1008*0Sstevel@tonic-gate ASSERT(af == AF_INET || af == AF_INET6); 1009*0Sstevel@tonic-gate switch (af) { 1010*0Sstevel@tonic-gate case AF_INET: 1011*0Sstevel@tonic-gate if (sire == NULL) { 1012*0Sstevel@tonic-gate rtm_flags = ire->ire_flags; 1013*0Sstevel@tonic-gate rts_fill_msg(RTM_GET, rtm_addrs, ire->ire_addr, 1014*0Sstevel@tonic-gate ire->ire_mask, ire->ire_src_addr, ire->ire_src_addr, 1015*0Sstevel@tonic-gate ire->ire_ipif->ipif_pp_dst_addr, 0, ire->ire_ipif, 1016*0Sstevel@tonic-gate new_mp); 1017*0Sstevel@tonic-gate } else { 1018*0Sstevel@tonic-gate if (sire->ire_flags & RTF_SETSRC) 1019*0Sstevel@tonic-gate rtm_addrs |= RTA_SRC; 1020*0Sstevel@tonic-gate 1021*0Sstevel@tonic-gate rtm_flags = sire->ire_flags; 1022*0Sstevel@tonic-gate rts_fill_msg(RTM_GET, rtm_addrs, sire->ire_addr, 1023*0Sstevel@tonic-gate sire->ire_mask, sire->ire_gateway_addr, 1024*0Sstevel@tonic-gate (sire->ire_flags & RTF_SETSRC) ? 1025*0Sstevel@tonic-gate sire->ire_src_addr : ire->ire_src_addr, 1026*0Sstevel@tonic-gate ire->ire_ipif->ipif_pp_dst_addr, 1027*0Sstevel@tonic-gate 0, ire->ire_ipif, new_mp); 1028*0Sstevel@tonic-gate } 1029*0Sstevel@tonic-gate break; 1030*0Sstevel@tonic-gate case AF_INET6: 1031*0Sstevel@tonic-gate if (sire == NULL) { 1032*0Sstevel@tonic-gate rtm_flags = ire->ire_flags; 1033*0Sstevel@tonic-gate rts_fill_msg_v6(RTM_GET, rtm_addrs, &ire->ire_addr_v6, 1034*0Sstevel@tonic-gate &ire->ire_mask_v6, &ire->ire_src_addr_v6, 1035*0Sstevel@tonic-gate &ire->ire_src_addr_v6, 1036*0Sstevel@tonic-gate &ire->ire_ipif->ipif_v6pp_dst_addr, 1037*0Sstevel@tonic-gate &ipv6_all_zeros, ire->ire_ipif, new_mp); 1038*0Sstevel@tonic-gate } else { 1039*0Sstevel@tonic-gate if (sire->ire_flags & RTF_SETSRC) 1040*0Sstevel@tonic-gate rtm_addrs |= RTA_SRC; 1041*0Sstevel@tonic-gate 1042*0Sstevel@tonic-gate rtm_flags = sire->ire_flags; 1043*0Sstevel@tonic-gate mutex_enter(&sire->ire_lock); 1044*0Sstevel@tonic-gate gw_addr_v6 = sire->ire_gateway_addr_v6; 1045*0Sstevel@tonic-gate mutex_exit(&sire->ire_lock); 1046*0Sstevel@tonic-gate rts_fill_msg_v6(RTM_GET, rtm_addrs, &sire->ire_addr_v6, 1047*0Sstevel@tonic-gate &sire->ire_mask_v6, &gw_addr_v6, 1048*0Sstevel@tonic-gate (sire->ire_flags & RTF_SETSRC) ? 1049*0Sstevel@tonic-gate &sire->ire_src_addr_v6 : &ire->ire_src_addr_v6, 1050*0Sstevel@tonic-gate &ire->ire_ipif->ipif_v6pp_dst_addr, &ipv6_all_zeros, 1051*0Sstevel@tonic-gate ire->ire_ipif, new_mp); 1052*0Sstevel@tonic-gate } 1053*0Sstevel@tonic-gate break; 1054*0Sstevel@tonic-gate } 1055*0Sstevel@tonic-gate new_rtm = (rt_msghdr_t *)new_mp->b_rptr; 1056*0Sstevel@tonic-gate 1057*0Sstevel@tonic-gate /* 1058*0Sstevel@tonic-gate * The rtm_msglen, rtm_version and rtm_type fields in 1059*0Sstevel@tonic-gate * RTM_GET response are filled in by rts_fill_msg. 1060*0Sstevel@tonic-gate * 1061*0Sstevel@tonic-gate * rtm_addrs and rtm_flags are filled in based on what 1062*0Sstevel@tonic-gate * was requested and the state of the IREs looked up 1063*0Sstevel@tonic-gate * above. 1064*0Sstevel@tonic-gate * 1065*0Sstevel@tonic-gate * rtm_inits and rtm_rmx are filled in with metrics 1066*0Sstevel@tonic-gate * based on whether a parent IRE was found or not. 1067*0Sstevel@tonic-gate * 1068*0Sstevel@tonic-gate * TODO: rtm_index and rtm_use should probably be 1069*0Sstevel@tonic-gate * filled in with something resonable here and not just 1070*0Sstevel@tonic-gate * copied from the request. 1071*0Sstevel@tonic-gate */ 1072*0Sstevel@tonic-gate new_rtm->rtm_index = rtm->rtm_index; 1073*0Sstevel@tonic-gate new_rtm->rtm_pid = rtm->rtm_pid; 1074*0Sstevel@tonic-gate new_rtm->rtm_seq = rtm->rtm_seq; 1075*0Sstevel@tonic-gate new_rtm->rtm_use = rtm->rtm_use; 1076*0Sstevel@tonic-gate new_rtm->rtm_addrs = rtm_addrs; 1077*0Sstevel@tonic-gate new_rtm->rtm_flags = rtm_flags; 1078*0Sstevel@tonic-gate if (sire == NULL) 1079*0Sstevel@tonic-gate new_rtm->rtm_inits = rts_getmetrics(ire, &new_rtm->rtm_rmx); 1080*0Sstevel@tonic-gate else 1081*0Sstevel@tonic-gate new_rtm->rtm_inits = rts_getmetrics(sire, &new_rtm->rtm_rmx); 1082*0Sstevel@tonic-gate return (new_mp); 1083*0Sstevel@tonic-gate } 1084*0Sstevel@tonic-gate 1085*0Sstevel@tonic-gate /* 1086*0Sstevel@tonic-gate * Fill the given if_data_t with interface statistics. 1087*0Sstevel@tonic-gate */ 1088*0Sstevel@tonic-gate static void 1089*0Sstevel@tonic-gate rts_getifdata(if_data_t *if_data, ipif_t *ipif) 1090*0Sstevel@tonic-gate { 1091*0Sstevel@tonic-gate if_data->ifi_type = ipif->ipif_type; /* ethernet, tokenring, etc */ 1092*0Sstevel@tonic-gate if_data->ifi_addrlen = 0; /* media address length */ 1093*0Sstevel@tonic-gate if_data->ifi_hdrlen = 0; /* media header length */ 1094*0Sstevel@tonic-gate if_data->ifi_mtu = ipif->ipif_mtu; /* maximum transmission unit */ 1095*0Sstevel@tonic-gate if_data->ifi_metric = ipif->ipif_metric; /* metric (external only) */ 1096*0Sstevel@tonic-gate if_data->ifi_baudrate = 0; /* linespeed */ 1097*0Sstevel@tonic-gate 1098*0Sstevel@tonic-gate if_data->ifi_ipackets = 0; /* packets received on if */ 1099*0Sstevel@tonic-gate if_data->ifi_ierrors = 0; /* input errors on interface */ 1100*0Sstevel@tonic-gate if_data->ifi_opackets = 0; /* packets sent on interface */ 1101*0Sstevel@tonic-gate if_data->ifi_oerrors = 0; /* output errors on if */ 1102*0Sstevel@tonic-gate if_data->ifi_collisions = 0; /* collisions on csma if */ 1103*0Sstevel@tonic-gate if_data->ifi_ibytes = 0; /* total number received */ 1104*0Sstevel@tonic-gate if_data->ifi_obytes = 0; /* total number sent */ 1105*0Sstevel@tonic-gate if_data->ifi_imcasts = 0; /* multicast packets received */ 1106*0Sstevel@tonic-gate if_data->ifi_omcasts = 0; /* multicast packets sent */ 1107*0Sstevel@tonic-gate if_data->ifi_iqdrops = 0; /* dropped on input */ 1108*0Sstevel@tonic-gate if_data->ifi_noproto = 0; /* destined for unsupported */ 1109*0Sstevel@tonic-gate /* protocol. */ 1110*0Sstevel@tonic-gate } 1111*0Sstevel@tonic-gate 1112*0Sstevel@tonic-gate /* 1113*0Sstevel@tonic-gate * Set the metrics on a forwarding table route. 1114*0Sstevel@tonic-gate */ 1115*0Sstevel@tonic-gate static void 1116*0Sstevel@tonic-gate rts_setmetrics(ire_t *ire, uint_t which, rt_metrics_t *metrics) 1117*0Sstevel@tonic-gate { 1118*0Sstevel@tonic-gate clock_t rtt; 1119*0Sstevel@tonic-gate clock_t rtt_sd; 1120*0Sstevel@tonic-gate ipif_t *ipif; 1121*0Sstevel@tonic-gate ifrt_t *ifrt; 1122*0Sstevel@tonic-gate mblk_t *mp; 1123*0Sstevel@tonic-gate in6_addr_t gw_addr_v6; 1124*0Sstevel@tonic-gate 1125*0Sstevel@tonic-gate /* 1126*0Sstevel@tonic-gate * Bypass obtaining the lock and searching ipif_saved_ire_mp in the 1127*0Sstevel@tonic-gate * common case of no metrics. 1128*0Sstevel@tonic-gate */ 1129*0Sstevel@tonic-gate if (which == 0) 1130*0Sstevel@tonic-gate return; 1131*0Sstevel@tonic-gate ire->ire_uinfo.iulp_set = B_TRUE; 1132*0Sstevel@tonic-gate 1133*0Sstevel@tonic-gate /* 1134*0Sstevel@tonic-gate * iulp_rtt and iulp_rtt_sd are in milliseconds, but 4.4BSD-Lite2's 1135*0Sstevel@tonic-gate * <net/route.h> says: rmx_rtt and rmx_rttvar are stored as 1136*0Sstevel@tonic-gate * microseconds. 1137*0Sstevel@tonic-gate */ 1138*0Sstevel@tonic-gate if (which & RTV_RTT) 1139*0Sstevel@tonic-gate rtt = metrics->rmx_rtt / 1000; 1140*0Sstevel@tonic-gate if (which & RTV_RTTVAR) 1141*0Sstevel@tonic-gate rtt_sd = metrics->rmx_rttvar / 1000; 1142*0Sstevel@tonic-gate 1143*0Sstevel@tonic-gate /* 1144*0Sstevel@tonic-gate * Update the metrics in the IRE itself. 1145*0Sstevel@tonic-gate */ 1146*0Sstevel@tonic-gate mutex_enter(&ire->ire_lock); 1147*0Sstevel@tonic-gate if (which & RTV_MTU) 1148*0Sstevel@tonic-gate ire->ire_max_frag = metrics->rmx_mtu; 1149*0Sstevel@tonic-gate if (which & RTV_RTT) 1150*0Sstevel@tonic-gate ire->ire_uinfo.iulp_rtt = rtt; 1151*0Sstevel@tonic-gate if (which & RTV_SSTHRESH) 1152*0Sstevel@tonic-gate ire->ire_uinfo.iulp_ssthresh = metrics->rmx_ssthresh; 1153*0Sstevel@tonic-gate if (which & RTV_RTTVAR) 1154*0Sstevel@tonic-gate ire->ire_uinfo.iulp_rtt_sd = rtt_sd; 1155*0Sstevel@tonic-gate if (which & RTV_SPIPE) 1156*0Sstevel@tonic-gate ire->ire_uinfo.iulp_spipe = metrics->rmx_sendpipe; 1157*0Sstevel@tonic-gate if (which & RTV_RPIPE) 1158*0Sstevel@tonic-gate ire->ire_uinfo.iulp_rpipe = metrics->rmx_recvpipe; 1159*0Sstevel@tonic-gate mutex_exit(&ire->ire_lock); 1160*0Sstevel@tonic-gate 1161*0Sstevel@tonic-gate /* 1162*0Sstevel@tonic-gate * Search through the ifrt_t chain hanging off the IPIF in order to 1163*0Sstevel@tonic-gate * reflect the metric change there. 1164*0Sstevel@tonic-gate */ 1165*0Sstevel@tonic-gate ipif = ire->ire_ipif; 1166*0Sstevel@tonic-gate if (ipif == NULL) 1167*0Sstevel@tonic-gate return; 1168*0Sstevel@tonic-gate ASSERT((ipif->ipif_isv6 && ire->ire_ipversion == IPV6_VERSION) || 1169*0Sstevel@tonic-gate ((!ipif->ipif_isv6 && ire->ire_ipversion == IPV4_VERSION))); 1170*0Sstevel@tonic-gate if (ipif->ipif_isv6) { 1171*0Sstevel@tonic-gate mutex_enter(&ire->ire_lock); 1172*0Sstevel@tonic-gate gw_addr_v6 = ire->ire_gateway_addr_v6; 1173*0Sstevel@tonic-gate mutex_exit(&ire->ire_lock); 1174*0Sstevel@tonic-gate } 1175*0Sstevel@tonic-gate mutex_enter(&ipif->ipif_saved_ire_lock); 1176*0Sstevel@tonic-gate for (mp = ipif->ipif_saved_ire_mp; mp != NULL; mp = mp->b_cont) { 1177*0Sstevel@tonic-gate /* 1178*0Sstevel@tonic-gate * On a given ipif, the triple of address, gateway and mask is 1179*0Sstevel@tonic-gate * unique for each saved IRE (in the case of ordinary interface 1180*0Sstevel@tonic-gate * routes, the gateway address is all-zeroes). 1181*0Sstevel@tonic-gate */ 1182*0Sstevel@tonic-gate ifrt = (ifrt_t *)mp->b_rptr; 1183*0Sstevel@tonic-gate if (ipif->ipif_isv6) { 1184*0Sstevel@tonic-gate if (!IN6_ARE_ADDR_EQUAL(&ifrt->ifrt_v6addr, 1185*0Sstevel@tonic-gate &ire->ire_addr_v6) || 1186*0Sstevel@tonic-gate !IN6_ARE_ADDR_EQUAL(&ifrt->ifrt_v6gateway_addr, 1187*0Sstevel@tonic-gate &gw_addr_v6) || 1188*0Sstevel@tonic-gate !IN6_ARE_ADDR_EQUAL(&ifrt->ifrt_v6mask, 1189*0Sstevel@tonic-gate &ire->ire_mask_v6)) 1190*0Sstevel@tonic-gate continue; 1191*0Sstevel@tonic-gate } else { 1192*0Sstevel@tonic-gate if (ifrt->ifrt_addr != ire->ire_addr || 1193*0Sstevel@tonic-gate ifrt->ifrt_gateway_addr != ire->ire_gateway_addr || 1194*0Sstevel@tonic-gate ifrt->ifrt_mask != ire->ire_mask) 1195*0Sstevel@tonic-gate continue; 1196*0Sstevel@tonic-gate } 1197*0Sstevel@tonic-gate if (which & RTV_MTU) 1198*0Sstevel@tonic-gate ifrt->ifrt_max_frag = metrics->rmx_mtu; 1199*0Sstevel@tonic-gate if (which & RTV_RTT) 1200*0Sstevel@tonic-gate ifrt->ifrt_iulp_info.iulp_rtt = rtt; 1201*0Sstevel@tonic-gate if (which & RTV_SSTHRESH) { 1202*0Sstevel@tonic-gate ifrt->ifrt_iulp_info.iulp_ssthresh = 1203*0Sstevel@tonic-gate metrics->rmx_ssthresh; 1204*0Sstevel@tonic-gate } 1205*0Sstevel@tonic-gate if (which & RTV_RTTVAR) 1206*0Sstevel@tonic-gate ifrt->ifrt_iulp_info.iulp_rtt_sd = metrics->rmx_rttvar; 1207*0Sstevel@tonic-gate if (which & RTV_SPIPE) 1208*0Sstevel@tonic-gate ifrt->ifrt_iulp_info.iulp_spipe = metrics->rmx_sendpipe; 1209*0Sstevel@tonic-gate if (which & RTV_RPIPE) 1210*0Sstevel@tonic-gate ifrt->ifrt_iulp_info.iulp_rpipe = metrics->rmx_recvpipe; 1211*0Sstevel@tonic-gate break; 1212*0Sstevel@tonic-gate } 1213*0Sstevel@tonic-gate mutex_exit(&ipif->ipif_saved_ire_lock); 1214*0Sstevel@tonic-gate } 1215*0Sstevel@tonic-gate 1216*0Sstevel@tonic-gate /* 1217*0Sstevel@tonic-gate * Get the metrics from a forwarding table route. 1218*0Sstevel@tonic-gate */ 1219*0Sstevel@tonic-gate static int 1220*0Sstevel@tonic-gate rts_getmetrics(ire_t *ire, rt_metrics_t *metrics) 1221*0Sstevel@tonic-gate { 1222*0Sstevel@tonic-gate int metrics_set = 0; 1223*0Sstevel@tonic-gate 1224*0Sstevel@tonic-gate bzero(metrics, sizeof (rt_metrics_t)); 1225*0Sstevel@tonic-gate /* 1226*0Sstevel@tonic-gate * iulp_rtt and iulp_rtt_sd are in milliseconds, but 4.4BSD-Lite2's 1227*0Sstevel@tonic-gate * <net/route.h> says: rmx_rtt and rmx_rttvar are stored as 1228*0Sstevel@tonic-gate * microseconds. 1229*0Sstevel@tonic-gate */ 1230*0Sstevel@tonic-gate metrics->rmx_rtt = ire->ire_uinfo.iulp_rtt * 1000; 1231*0Sstevel@tonic-gate metrics_set |= RTV_RTT; 1232*0Sstevel@tonic-gate metrics->rmx_mtu = ire->ire_max_frag; 1233*0Sstevel@tonic-gate metrics_set |= RTV_MTU; 1234*0Sstevel@tonic-gate metrics->rmx_ssthresh = ire->ire_uinfo.iulp_ssthresh; 1235*0Sstevel@tonic-gate metrics_set |= RTV_SSTHRESH; 1236*0Sstevel@tonic-gate metrics->rmx_rttvar = ire->ire_uinfo.iulp_rtt_sd * 1000; 1237*0Sstevel@tonic-gate metrics_set |= RTV_RTTVAR; 1238*0Sstevel@tonic-gate metrics->rmx_sendpipe = ire->ire_uinfo.iulp_spipe; 1239*0Sstevel@tonic-gate metrics_set |= RTV_SPIPE; 1240*0Sstevel@tonic-gate metrics->rmx_recvpipe = ire->ire_uinfo.iulp_rpipe; 1241*0Sstevel@tonic-gate metrics_set |= RTV_RPIPE; 1242*0Sstevel@tonic-gate return (metrics_set); 1243*0Sstevel@tonic-gate } 1244*0Sstevel@tonic-gate 1245*0Sstevel@tonic-gate /* 1246*0Sstevel@tonic-gate * Takes a pointer to a routing message and extracts necessary info by looking 1247*0Sstevel@tonic-gate * at the rtm->rtm_addrs bits and store the requested sockaddrs in the pointers 1248*0Sstevel@tonic-gate * passed (all of which must be valid). 1249*0Sstevel@tonic-gate * 1250*0Sstevel@tonic-gate * The bitmask of sockaddrs actually found in the message is returned, or zero 1251*0Sstevel@tonic-gate * is returned in the case of an error. 1252*0Sstevel@tonic-gate */ 1253*0Sstevel@tonic-gate static int 1254*0Sstevel@tonic-gate rts_getaddrs(rt_msghdr_t *rtm, in6_addr_t *dst_addrp, in6_addr_t *gw_addrp, 1255*0Sstevel@tonic-gate in6_addr_t *net_maskp, in6_addr_t *authorp, in6_addr_t *if_addrp, 1256*0Sstevel@tonic-gate in6_addr_t *in_src_addrp, ushort_t *indexp, ushort_t *src_indexp, 1257*0Sstevel@tonic-gate sa_family_t *afp) 1258*0Sstevel@tonic-gate { 1259*0Sstevel@tonic-gate struct sockaddr *sa; 1260*0Sstevel@tonic-gate int i; 1261*0Sstevel@tonic-gate int addr_bits; 1262*0Sstevel@tonic-gate int length; 1263*0Sstevel@tonic-gate int found_addrs = 0; 1264*0Sstevel@tonic-gate caddr_t cp; 1265*0Sstevel@tonic-gate size_t size; 1266*0Sstevel@tonic-gate struct sockaddr_dl *sdl; 1267*0Sstevel@tonic-gate 1268*0Sstevel@tonic-gate *dst_addrp = ipv6_all_zeros; 1269*0Sstevel@tonic-gate *gw_addrp = ipv6_all_zeros; 1270*0Sstevel@tonic-gate *net_maskp = ipv6_all_zeros; 1271*0Sstevel@tonic-gate *authorp = ipv6_all_zeros; 1272*0Sstevel@tonic-gate *if_addrp = ipv6_all_zeros; 1273*0Sstevel@tonic-gate *in_src_addrp = ipv6_all_zeros; 1274*0Sstevel@tonic-gate *indexp = 0; 1275*0Sstevel@tonic-gate *src_indexp = 0; 1276*0Sstevel@tonic-gate *afp = AF_UNSPEC; 1277*0Sstevel@tonic-gate 1278*0Sstevel@tonic-gate /* 1279*0Sstevel@tonic-gate * At present we handle only RTA_DST, RTA_GATEWAY, RTA_NETMASK, RTA_IFP, 1280*0Sstevel@tonic-gate * RTA_IFA and RTA_AUTHOR. The rest will be added as we need them. 1281*0Sstevel@tonic-gate */ 1282*0Sstevel@tonic-gate cp = (caddr_t)&rtm[1]; 1283*0Sstevel@tonic-gate length = rtm->rtm_msglen; 1284*0Sstevel@tonic-gate for (i = 0; (i < RTA_NUMBITS) && ((cp - (caddr_t)rtm) < length); i++) { 1285*0Sstevel@tonic-gate /* 1286*0Sstevel@tonic-gate * The address family we are working with starts out as 1287*0Sstevel@tonic-gate * AF_UNSPEC, but is set to the one specified with the 1288*0Sstevel@tonic-gate * destination address. 1289*0Sstevel@tonic-gate * 1290*0Sstevel@tonic-gate * If the "working" address family that has been set to 1291*0Sstevel@tonic-gate * something other than AF_UNSPEC, then the address family of 1292*0Sstevel@tonic-gate * subsequent sockaddrs must either be AF_UNSPEC (for 1293*0Sstevel@tonic-gate * compatibility with older programs) or must be the same as our 1294*0Sstevel@tonic-gate * "working" one. 1295*0Sstevel@tonic-gate * 1296*0Sstevel@tonic-gate * This code assumes that RTA_DST (1) comes first in the loop. 1297*0Sstevel@tonic-gate */ 1298*0Sstevel@tonic-gate sa = (struct sockaddr *)cp; 1299*0Sstevel@tonic-gate addr_bits = (rtm->rtm_addrs & (1 << i)); 1300*0Sstevel@tonic-gate if (addr_bits == 0) 1301*0Sstevel@tonic-gate continue; 1302*0Sstevel@tonic-gate switch (addr_bits) { 1303*0Sstevel@tonic-gate case RTA_DST: 1304*0Sstevel@tonic-gate size = rts_copyfromsockaddr(sa, dst_addrp); 1305*0Sstevel@tonic-gate *afp = sa->sa_family; 1306*0Sstevel@tonic-gate break; 1307*0Sstevel@tonic-gate case RTA_GATEWAY: 1308*0Sstevel@tonic-gate if (sa->sa_family != *afp && sa->sa_family != AF_UNSPEC) 1309*0Sstevel@tonic-gate return (0); 1310*0Sstevel@tonic-gate size = rts_copyfromsockaddr(sa, gw_addrp); 1311*0Sstevel@tonic-gate break; 1312*0Sstevel@tonic-gate case RTA_NETMASK: 1313*0Sstevel@tonic-gate if (sa->sa_family != *afp && sa->sa_family != AF_UNSPEC) 1314*0Sstevel@tonic-gate return (0); 1315*0Sstevel@tonic-gate size = rts_copyfromsockaddr(sa, net_maskp); 1316*0Sstevel@tonic-gate break; 1317*0Sstevel@tonic-gate case RTA_IFP: 1318*0Sstevel@tonic-gate if (sa->sa_family != AF_LINK && 1319*0Sstevel@tonic-gate sa->sa_family != AF_UNSPEC) 1320*0Sstevel@tonic-gate return (0); 1321*0Sstevel@tonic-gate sdl = (struct sockaddr_dl *)cp; 1322*0Sstevel@tonic-gate *indexp = sdl->sdl_index; 1323*0Sstevel@tonic-gate size = sizeof (struct sockaddr_dl); 1324*0Sstevel@tonic-gate break; 1325*0Sstevel@tonic-gate case RTA_SRC: 1326*0Sstevel@tonic-gate /* Source address of the incoming packet */ 1327*0Sstevel@tonic-gate size = rts_copyfromsockaddr(sa, in_src_addrp); 1328*0Sstevel@tonic-gate *afp = sa->sa_family; 1329*0Sstevel@tonic-gate break; 1330*0Sstevel@tonic-gate case RTA_SRCIFP: 1331*0Sstevel@tonic-gate /* Return incoming interface index pointer */ 1332*0Sstevel@tonic-gate if (sa->sa_family != AF_LINK && 1333*0Sstevel@tonic-gate sa->sa_family != AF_UNSPEC) 1334*0Sstevel@tonic-gate return (0); 1335*0Sstevel@tonic-gate sdl = (struct sockaddr_dl *)cp; 1336*0Sstevel@tonic-gate *src_indexp = sdl->sdl_index; 1337*0Sstevel@tonic-gate size = sizeof (struct sockaddr_dl); 1338*0Sstevel@tonic-gate break; 1339*0Sstevel@tonic-gate case RTA_IFA: 1340*0Sstevel@tonic-gate if (sa->sa_family != *afp && sa->sa_family != AF_UNSPEC) 1341*0Sstevel@tonic-gate return (0); 1342*0Sstevel@tonic-gate size = rts_copyfromsockaddr(sa, if_addrp); 1343*0Sstevel@tonic-gate break; 1344*0Sstevel@tonic-gate case RTA_AUTHOR: 1345*0Sstevel@tonic-gate if (sa->sa_family != *afp && sa->sa_family != AF_UNSPEC) 1346*0Sstevel@tonic-gate return (0); 1347*0Sstevel@tonic-gate size = rts_copyfromsockaddr(sa, authorp); 1348*0Sstevel@tonic-gate break; 1349*0Sstevel@tonic-gate default: 1350*0Sstevel@tonic-gate return (0); 1351*0Sstevel@tonic-gate } 1352*0Sstevel@tonic-gate if (size == 0) 1353*0Sstevel@tonic-gate return (0); 1354*0Sstevel@tonic-gate cp += size; 1355*0Sstevel@tonic-gate found_addrs |= addr_bits; 1356*0Sstevel@tonic-gate } 1357*0Sstevel@tonic-gate return (found_addrs); 1358*0Sstevel@tonic-gate } 1359*0Sstevel@tonic-gate 1360*0Sstevel@tonic-gate /* 1361*0Sstevel@tonic-gate * Fills the message with the given info. 1362*0Sstevel@tonic-gate */ 1363*0Sstevel@tonic-gate static void 1364*0Sstevel@tonic-gate rts_fill_msg(int type, int rtm_addrs, ipaddr_t dst, ipaddr_t mask, 1365*0Sstevel@tonic-gate ipaddr_t gateway, ipaddr_t src_addr, ipaddr_t brd_addr, ipaddr_t author, 1366*0Sstevel@tonic-gate ipif_t *ipif, mblk_t *mp) 1367*0Sstevel@tonic-gate { 1368*0Sstevel@tonic-gate rt_msghdr_t *rtm; 1369*0Sstevel@tonic-gate sin_t *sin; 1370*0Sstevel@tonic-gate size_t data_size, header_size; 1371*0Sstevel@tonic-gate uchar_t *cp; 1372*0Sstevel@tonic-gate int i; 1373*0Sstevel@tonic-gate 1374*0Sstevel@tonic-gate ASSERT(mp != NULL); 1375*0Sstevel@tonic-gate /* 1376*0Sstevel@tonic-gate * First find the type of the message 1377*0Sstevel@tonic-gate * and its length. 1378*0Sstevel@tonic-gate */ 1379*0Sstevel@tonic-gate header_size = rts_header_msg_size(type); 1380*0Sstevel@tonic-gate /* 1381*0Sstevel@tonic-gate * Now find the size of the data 1382*0Sstevel@tonic-gate * that follows the message header. 1383*0Sstevel@tonic-gate */ 1384*0Sstevel@tonic-gate data_size = rts_data_msg_size(rtm_addrs, AF_INET); 1385*0Sstevel@tonic-gate 1386*0Sstevel@tonic-gate rtm = (rt_msghdr_t *)mp->b_rptr; 1387*0Sstevel@tonic-gate mp->b_wptr = &mp->b_rptr[header_size]; 1388*0Sstevel@tonic-gate cp = mp->b_wptr; 1389*0Sstevel@tonic-gate bzero(cp, data_size); 1390*0Sstevel@tonic-gate for (i = 0; i < RTA_NUMBITS; i++) { 1391*0Sstevel@tonic-gate sin = (sin_t *)cp; 1392*0Sstevel@tonic-gate switch (rtm_addrs & (1 << i)) { 1393*0Sstevel@tonic-gate case RTA_DST: 1394*0Sstevel@tonic-gate sin->sin_addr.s_addr = dst; 1395*0Sstevel@tonic-gate sin->sin_family = AF_INET; 1396*0Sstevel@tonic-gate cp += sizeof (sin_t); 1397*0Sstevel@tonic-gate break; 1398*0Sstevel@tonic-gate case RTA_GATEWAY: 1399*0Sstevel@tonic-gate sin->sin_addr.s_addr = gateway; 1400*0Sstevel@tonic-gate sin->sin_family = AF_INET; 1401*0Sstevel@tonic-gate cp += sizeof (sin_t); 1402*0Sstevel@tonic-gate break; 1403*0Sstevel@tonic-gate case RTA_NETMASK: 1404*0Sstevel@tonic-gate sin->sin_addr.s_addr = mask; 1405*0Sstevel@tonic-gate sin->sin_family = AF_INET; 1406*0Sstevel@tonic-gate cp += sizeof (sin_t); 1407*0Sstevel@tonic-gate break; 1408*0Sstevel@tonic-gate case RTA_IFP: 1409*0Sstevel@tonic-gate cp += ill_dls_info((struct sockaddr_dl *)cp, ipif); 1410*0Sstevel@tonic-gate break; 1411*0Sstevel@tonic-gate case RTA_SRCIFP: 1412*0Sstevel@tonic-gate /* 1413*0Sstevel@tonic-gate * RTA_SRCIFP is not yet supported 1414*0Sstevel@tonic-gate * for RTM_GET and RTM_CHANGE 1415*0Sstevel@tonic-gate */ 1416*0Sstevel@tonic-gate break; 1417*0Sstevel@tonic-gate case RTA_IFA: 1418*0Sstevel@tonic-gate case RTA_SRC: 1419*0Sstevel@tonic-gate sin->sin_addr.s_addr = src_addr; 1420*0Sstevel@tonic-gate sin->sin_family = AF_INET; 1421*0Sstevel@tonic-gate cp += sizeof (sin_t); 1422*0Sstevel@tonic-gate break; 1423*0Sstevel@tonic-gate case RTA_AUTHOR: 1424*0Sstevel@tonic-gate sin->sin_addr.s_addr = author; 1425*0Sstevel@tonic-gate sin->sin_family = AF_INET; 1426*0Sstevel@tonic-gate cp += sizeof (sin_t); 1427*0Sstevel@tonic-gate break; 1428*0Sstevel@tonic-gate case RTA_BRD: 1429*0Sstevel@tonic-gate /* 1430*0Sstevel@tonic-gate * RTA_BRD is used typically to specify a point-to-point 1431*0Sstevel@tonic-gate * destination address. 1432*0Sstevel@tonic-gate */ 1433*0Sstevel@tonic-gate sin->sin_addr.s_addr = brd_addr; 1434*0Sstevel@tonic-gate sin->sin_family = AF_INET; 1435*0Sstevel@tonic-gate cp += sizeof (sin_t); 1436*0Sstevel@tonic-gate break; 1437*0Sstevel@tonic-gate } 1438*0Sstevel@tonic-gate } 1439*0Sstevel@tonic-gate mp->b_wptr = cp; 1440*0Sstevel@tonic-gate mp->b_cont = NULL; 1441*0Sstevel@tonic-gate /* 1442*0Sstevel@tonic-gate * set the fields that are common to 1443*0Sstevel@tonic-gate * to different messages. 1444*0Sstevel@tonic-gate */ 1445*0Sstevel@tonic-gate rtm->rtm_msglen = (short)(header_size + data_size); 1446*0Sstevel@tonic-gate rtm->rtm_version = RTM_VERSION; 1447*0Sstevel@tonic-gate rtm->rtm_type = (uchar_t)type; 1448*0Sstevel@tonic-gate } 1449*0Sstevel@tonic-gate 1450*0Sstevel@tonic-gate /* 1451*0Sstevel@tonic-gate * Allocates and initializes a routing socket message. 1452*0Sstevel@tonic-gate */ 1453*0Sstevel@tonic-gate mblk_t * 1454*0Sstevel@tonic-gate rts_alloc_msg(int type, int rtm_addrs, sa_family_t af) 1455*0Sstevel@tonic-gate { 1456*0Sstevel@tonic-gate size_t length; 1457*0Sstevel@tonic-gate mblk_t *mp; 1458*0Sstevel@tonic-gate 1459*0Sstevel@tonic-gate length = RTS_MSG_SIZE(type, rtm_addrs, af); 1460*0Sstevel@tonic-gate mp = allocb(length, BPRI_MED); 1461*0Sstevel@tonic-gate if (mp == NULL) 1462*0Sstevel@tonic-gate return (mp); 1463*0Sstevel@tonic-gate bzero(mp->b_rptr, length); 1464*0Sstevel@tonic-gate return (mp); 1465*0Sstevel@tonic-gate } 1466*0Sstevel@tonic-gate 1467*0Sstevel@tonic-gate /* 1468*0Sstevel@tonic-gate * Returns the size of the routing 1469*0Sstevel@tonic-gate * socket message header size. 1470*0Sstevel@tonic-gate */ 1471*0Sstevel@tonic-gate size_t 1472*0Sstevel@tonic-gate rts_header_msg_size(int type) 1473*0Sstevel@tonic-gate { 1474*0Sstevel@tonic-gate switch (type) { 1475*0Sstevel@tonic-gate case RTM_DELADDR: 1476*0Sstevel@tonic-gate case RTM_NEWADDR: 1477*0Sstevel@tonic-gate return (sizeof (ifa_msghdr_t)); 1478*0Sstevel@tonic-gate case RTM_IFINFO: 1479*0Sstevel@tonic-gate return (sizeof (if_msghdr_t)); 1480*0Sstevel@tonic-gate default: 1481*0Sstevel@tonic-gate return (sizeof (rt_msghdr_t)); 1482*0Sstevel@tonic-gate } 1483*0Sstevel@tonic-gate } 1484*0Sstevel@tonic-gate 1485*0Sstevel@tonic-gate /* 1486*0Sstevel@tonic-gate * Returns the size of the message needed with the given rtm_addrs and family. 1487*0Sstevel@tonic-gate * 1488*0Sstevel@tonic-gate * It is assumed that all of the sockaddrs (with the exception of RTA_IFP) are 1489*0Sstevel@tonic-gate * of the same family (currently either AF_INET or AF_INET6). 1490*0Sstevel@tonic-gate */ 1491*0Sstevel@tonic-gate size_t 1492*0Sstevel@tonic-gate rts_data_msg_size(int rtm_addrs, sa_family_t af) 1493*0Sstevel@tonic-gate { 1494*0Sstevel@tonic-gate int i; 1495*0Sstevel@tonic-gate size_t length = 0; 1496*0Sstevel@tonic-gate 1497*0Sstevel@tonic-gate for (i = 0; i < RTA_NUMBITS; i++) { 1498*0Sstevel@tonic-gate switch (rtm_addrs & (1 << i)) { 1499*0Sstevel@tonic-gate case RTA_IFP: 1500*0Sstevel@tonic-gate length += sizeof (struct sockaddr_dl); 1501*0Sstevel@tonic-gate break; 1502*0Sstevel@tonic-gate case RTA_DST: 1503*0Sstevel@tonic-gate case RTA_GATEWAY: 1504*0Sstevel@tonic-gate case RTA_NETMASK: 1505*0Sstevel@tonic-gate case RTA_SRC: 1506*0Sstevel@tonic-gate case RTA_SRCIFP: 1507*0Sstevel@tonic-gate case RTA_IFA: 1508*0Sstevel@tonic-gate case RTA_AUTHOR: 1509*0Sstevel@tonic-gate case RTA_BRD: 1510*0Sstevel@tonic-gate ASSERT(af == AF_INET || af == AF_INET6); 1511*0Sstevel@tonic-gate switch (af) { 1512*0Sstevel@tonic-gate case AF_INET: 1513*0Sstevel@tonic-gate length += sizeof (sin_t); 1514*0Sstevel@tonic-gate break; 1515*0Sstevel@tonic-gate case AF_INET6: 1516*0Sstevel@tonic-gate length += sizeof (sin6_t); 1517*0Sstevel@tonic-gate break; 1518*0Sstevel@tonic-gate } 1519*0Sstevel@tonic-gate break; 1520*0Sstevel@tonic-gate } 1521*0Sstevel@tonic-gate } 1522*0Sstevel@tonic-gate return (length); 1523*0Sstevel@tonic-gate } 1524*0Sstevel@tonic-gate 1525*0Sstevel@tonic-gate /* 1526*0Sstevel@tonic-gate * This routine is called to generate a message to the routing 1527*0Sstevel@tonic-gate * socket indicating that a redirect has occured, a routing lookup 1528*0Sstevel@tonic-gate * has failed, or that a protocol has detected timeouts to a particular 1529*0Sstevel@tonic-gate * destination. This routine is called for message types RTM_LOSING, 1530*0Sstevel@tonic-gate * RTM_REDIRECT, and RTM_MISS. 1531*0Sstevel@tonic-gate */ 1532*0Sstevel@tonic-gate void 1533*0Sstevel@tonic-gate ip_rts_change(int type, ipaddr_t dst_addr, ipaddr_t gw_addr, ipaddr_t net_mask, 1534*0Sstevel@tonic-gate ipaddr_t source, ipaddr_t author, int flags, int error, int rtm_addrs) 1535*0Sstevel@tonic-gate { 1536*0Sstevel@tonic-gate rt_msghdr_t *rtm; 1537*0Sstevel@tonic-gate mblk_t *mp; 1538*0Sstevel@tonic-gate 1539*0Sstevel@tonic-gate if (rtm_addrs == 0) 1540*0Sstevel@tonic-gate return; 1541*0Sstevel@tonic-gate mp = rts_alloc_msg(type, rtm_addrs, AF_INET); 1542*0Sstevel@tonic-gate if (mp == NULL) 1543*0Sstevel@tonic-gate return; 1544*0Sstevel@tonic-gate rts_fill_msg(type, rtm_addrs, dst_addr, net_mask, gw_addr, source, 0, 1545*0Sstevel@tonic-gate author, NULL, mp); 1546*0Sstevel@tonic-gate rtm = (rt_msghdr_t *)mp->b_rptr; 1547*0Sstevel@tonic-gate rtm->rtm_flags = flags; 1548*0Sstevel@tonic-gate rtm->rtm_errno = error; 1549*0Sstevel@tonic-gate rtm->rtm_flags |= RTF_DONE; 1550*0Sstevel@tonic-gate rtm->rtm_addrs = rtm_addrs; 1551*0Sstevel@tonic-gate rts_queue_input(mp, NULL, AF_INET); 1552*0Sstevel@tonic-gate } 1553*0Sstevel@tonic-gate 1554*0Sstevel@tonic-gate /* 1555*0Sstevel@tonic-gate * This routine is called to generate a message to the routing 1556*0Sstevel@tonic-gate * socket indicating that the status of a network interface has changed. 1557*0Sstevel@tonic-gate * Message type generated RTM_IFINFO. 1558*0Sstevel@tonic-gate */ 1559*0Sstevel@tonic-gate void 1560*0Sstevel@tonic-gate ip_rts_ifmsg(ipif_t *ipif) 1561*0Sstevel@tonic-gate { 1562*0Sstevel@tonic-gate if_msghdr_t *ifm; 1563*0Sstevel@tonic-gate mblk_t *mp; 1564*0Sstevel@tonic-gate sa_family_t af; 1565*0Sstevel@tonic-gate 1566*0Sstevel@tonic-gate /* 1567*0Sstevel@tonic-gate * This message should be generated only 1568*0Sstevel@tonic-gate * when the physical device is changing 1569*0Sstevel@tonic-gate * state. 1570*0Sstevel@tonic-gate */ 1571*0Sstevel@tonic-gate if (ipif->ipif_id != 0) 1572*0Sstevel@tonic-gate return; 1573*0Sstevel@tonic-gate if (ipif->ipif_isv6) { 1574*0Sstevel@tonic-gate af = AF_INET6; 1575*0Sstevel@tonic-gate mp = rts_alloc_msg(RTM_IFINFO, RTA_IFP, af); 1576*0Sstevel@tonic-gate if (mp == NULL) 1577*0Sstevel@tonic-gate return; 1578*0Sstevel@tonic-gate rts_fill_msg_v6(RTM_IFINFO, RTA_IFP, &ipv6_all_zeros, 1579*0Sstevel@tonic-gate &ipv6_all_zeros, &ipv6_all_zeros, &ipv6_all_zeros, 1580*0Sstevel@tonic-gate &ipv6_all_zeros, &ipv6_all_zeros, ipif, mp); 1581*0Sstevel@tonic-gate } else { 1582*0Sstevel@tonic-gate af = AF_INET; 1583*0Sstevel@tonic-gate mp = rts_alloc_msg(RTM_IFINFO, RTA_IFP, af); 1584*0Sstevel@tonic-gate if (mp == NULL) 1585*0Sstevel@tonic-gate return; 1586*0Sstevel@tonic-gate rts_fill_msg(RTM_IFINFO, RTA_IFP, 0, 0, 0, 0, 0, 0, ipif, mp); 1587*0Sstevel@tonic-gate } 1588*0Sstevel@tonic-gate ifm = (if_msghdr_t *)mp->b_rptr; 1589*0Sstevel@tonic-gate ifm->ifm_index = ipif->ipif_ill->ill_phyint->phyint_ifindex; 1590*0Sstevel@tonic-gate ifm->ifm_flags = ipif->ipif_flags | ipif->ipif_ill->ill_flags | 1591*0Sstevel@tonic-gate ipif->ipif_ill->ill_phyint->phyint_flags; 1592*0Sstevel@tonic-gate rts_getifdata(&ifm->ifm_data, ipif); 1593*0Sstevel@tonic-gate ifm->ifm_addrs = RTA_IFP; 1594*0Sstevel@tonic-gate rts_queue_input(mp, NULL, af); 1595*0Sstevel@tonic-gate } 1596*0Sstevel@tonic-gate 1597*0Sstevel@tonic-gate /* 1598*0Sstevel@tonic-gate * This is called to generate messages to the routing socket 1599*0Sstevel@tonic-gate * indicating a network interface has had addresses associated with it. 1600*0Sstevel@tonic-gate * The structure of the code is based on the 4.4BSD-Lite2 <net/rtsock.c>. 1601*0Sstevel@tonic-gate */ 1602*0Sstevel@tonic-gate void 1603*0Sstevel@tonic-gate ip_rts_newaddrmsg(int cmd, int error, ipif_t *ipif) 1604*0Sstevel@tonic-gate { 1605*0Sstevel@tonic-gate int pass; 1606*0Sstevel@tonic-gate int ncmd; 1607*0Sstevel@tonic-gate int rtm_addrs; 1608*0Sstevel@tonic-gate mblk_t *mp; 1609*0Sstevel@tonic-gate ifa_msghdr_t *ifam; 1610*0Sstevel@tonic-gate rt_msghdr_t *rtm; 1611*0Sstevel@tonic-gate sa_family_t af; 1612*0Sstevel@tonic-gate 1613*0Sstevel@tonic-gate if (ipif->ipif_isv6) 1614*0Sstevel@tonic-gate af = AF_INET6; 1615*0Sstevel@tonic-gate else 1616*0Sstevel@tonic-gate af = AF_INET; 1617*0Sstevel@tonic-gate /* 1618*0Sstevel@tonic-gate * If the request is DELETE, send RTM_DELETE and RTM_DELADDR. 1619*0Sstevel@tonic-gate * if the request is ADD, send RTM_NEWADDR and RTM_ADD. 1620*0Sstevel@tonic-gate */ 1621*0Sstevel@tonic-gate for (pass = 1; pass < 3; pass++) { 1622*0Sstevel@tonic-gate if ((cmd == RTM_ADD && pass == 1) || 1623*0Sstevel@tonic-gate (cmd == RTM_DELETE && pass == 2)) { 1624*0Sstevel@tonic-gate ncmd = ((cmd == RTM_ADD) ? RTM_NEWADDR : RTM_DELADDR); 1625*0Sstevel@tonic-gate 1626*0Sstevel@tonic-gate rtm_addrs = (RTA_IFA | RTA_NETMASK | RTA_BRD); 1627*0Sstevel@tonic-gate mp = rts_alloc_msg(ncmd, rtm_addrs, af); 1628*0Sstevel@tonic-gate if (mp == NULL) 1629*0Sstevel@tonic-gate continue; 1630*0Sstevel@tonic-gate switch (af) { 1631*0Sstevel@tonic-gate case AF_INET: 1632*0Sstevel@tonic-gate rts_fill_msg(ncmd, rtm_addrs, 0, 1633*0Sstevel@tonic-gate ipif->ipif_net_mask, 0, ipif->ipif_lcl_addr, 1634*0Sstevel@tonic-gate ipif->ipif_pp_dst_addr, 0, NULL, mp); 1635*0Sstevel@tonic-gate break; 1636*0Sstevel@tonic-gate case AF_INET6: 1637*0Sstevel@tonic-gate rts_fill_msg_v6(ncmd, rtm_addrs, 1638*0Sstevel@tonic-gate &ipv6_all_zeros, &ipif->ipif_v6net_mask, 1639*0Sstevel@tonic-gate &ipv6_all_zeros, &ipif->ipif_v6lcl_addr, 1640*0Sstevel@tonic-gate &ipif->ipif_v6pp_dst_addr, &ipv6_all_zeros, 1641*0Sstevel@tonic-gate NULL, mp); 1642*0Sstevel@tonic-gate break; 1643*0Sstevel@tonic-gate } 1644*0Sstevel@tonic-gate ifam = (ifa_msghdr_t *)mp->b_rptr; 1645*0Sstevel@tonic-gate ifam->ifam_index = 1646*0Sstevel@tonic-gate ipif->ipif_ill->ill_phyint->phyint_ifindex; 1647*0Sstevel@tonic-gate ifam->ifam_metric = ipif->ipif_metric; 1648*0Sstevel@tonic-gate ifam->ifam_flags = ((cmd == RTM_ADD) ? RTF_UP : 0); 1649*0Sstevel@tonic-gate ifam->ifam_addrs = rtm_addrs; 1650*0Sstevel@tonic-gate rts_queue_input(mp, NULL, af); 1651*0Sstevel@tonic-gate } 1652*0Sstevel@tonic-gate if ((cmd == RTM_ADD && pass == 2) || 1653*0Sstevel@tonic-gate (cmd == RTM_DELETE && pass == 1)) { 1654*0Sstevel@tonic-gate rtm_addrs = (RTA_DST | RTA_NETMASK); 1655*0Sstevel@tonic-gate mp = rts_alloc_msg(cmd, rtm_addrs, af); 1656*0Sstevel@tonic-gate if (mp == NULL) 1657*0Sstevel@tonic-gate continue; 1658*0Sstevel@tonic-gate switch (af) { 1659*0Sstevel@tonic-gate case AF_INET: 1660*0Sstevel@tonic-gate rts_fill_msg(cmd, rtm_addrs, 1661*0Sstevel@tonic-gate ipif->ipif_lcl_addr, ipif->ipif_net_mask, 0, 1662*0Sstevel@tonic-gate 0, 0, 0, NULL, mp); 1663*0Sstevel@tonic-gate break; 1664*0Sstevel@tonic-gate case AF_INET6: 1665*0Sstevel@tonic-gate rts_fill_msg_v6(cmd, rtm_addrs, 1666*0Sstevel@tonic-gate &ipif->ipif_v6lcl_addr, 1667*0Sstevel@tonic-gate &ipif->ipif_v6net_mask, &ipv6_all_zeros, 1668*0Sstevel@tonic-gate &ipv6_all_zeros, &ipv6_all_zeros, 1669*0Sstevel@tonic-gate &ipv6_all_zeros, NULL, mp); 1670*0Sstevel@tonic-gate break; 1671*0Sstevel@tonic-gate } 1672*0Sstevel@tonic-gate rtm = (rt_msghdr_t *)mp->b_rptr; 1673*0Sstevel@tonic-gate rtm->rtm_index = 1674*0Sstevel@tonic-gate ipif->ipif_ill->ill_phyint->phyint_ifindex; 1675*0Sstevel@tonic-gate rtm->rtm_flags = ((cmd == RTM_ADD) ? RTF_UP : 0); 1676*0Sstevel@tonic-gate rtm->rtm_errno = error; 1677*0Sstevel@tonic-gate if (error == 0) 1678*0Sstevel@tonic-gate rtm->rtm_flags |= RTF_DONE; 1679*0Sstevel@tonic-gate rtm->rtm_addrs = rtm_addrs; 1680*0Sstevel@tonic-gate rts_queue_input(mp, NULL, af); 1681*0Sstevel@tonic-gate } 1682*0Sstevel@tonic-gate } 1683*0Sstevel@tonic-gate } 1684*0Sstevel@tonic-gate 1685*0Sstevel@tonic-gate /* 1686*0Sstevel@tonic-gate * Based on the address family specified in a sockaddr, copy the address field 1687*0Sstevel@tonic-gate * into an in6_addr_t. 1688*0Sstevel@tonic-gate * 1689*0Sstevel@tonic-gate * In the case of AF_UNSPEC, we assume the family is actually AF_INET for 1690*0Sstevel@tonic-gate * compatibility with programs that leave the family cleared in the sockaddr. 1691*0Sstevel@tonic-gate * Callers of rts_copyfromsockaddr should check the family themselves if they 1692*0Sstevel@tonic-gate * wish to verify its value. 1693*0Sstevel@tonic-gate * 1694*0Sstevel@tonic-gate * In the case of AF_INET6, a check is made to ensure that address is not an 1695*0Sstevel@tonic-gate * IPv4-mapped address. 1696*0Sstevel@tonic-gate */ 1697*0Sstevel@tonic-gate size_t 1698*0Sstevel@tonic-gate rts_copyfromsockaddr(struct sockaddr *sa, in6_addr_t *addrp) 1699*0Sstevel@tonic-gate { 1700*0Sstevel@tonic-gate switch (sa->sa_family) { 1701*0Sstevel@tonic-gate case AF_INET: 1702*0Sstevel@tonic-gate case AF_UNSPEC: 1703*0Sstevel@tonic-gate IN6_IPADDR_TO_V4MAPPED(((sin_t *)sa)->sin_addr.s_addr, addrp); 1704*0Sstevel@tonic-gate return (sizeof (sin_t)); 1705*0Sstevel@tonic-gate case AF_INET6: 1706*0Sstevel@tonic-gate *addrp = ((sin6_t *)sa)->sin6_addr; 1707*0Sstevel@tonic-gate if (IN6_IS_ADDR_V4MAPPED(addrp)) 1708*0Sstevel@tonic-gate return (0); 1709*0Sstevel@tonic-gate return (sizeof (sin6_t)); 1710*0Sstevel@tonic-gate default: 1711*0Sstevel@tonic-gate return (0); 1712*0Sstevel@tonic-gate } 1713*0Sstevel@tonic-gate } 1714