diff options
author | sommerfe <none@none> | 2006-06-22 12:52:27 -0700 |
---|---|---|
committer | sommerfe <none@none> | 2006-06-22 12:52:27 -0700 |
commit | 5d0bc3ededb82d77f7c33d8f58e517a837ba5140 (patch) | |
tree | f3b0f2cc21773e13d562f20191626012f1201473 /usr/src | |
parent | abf8481b415d552f9b7ab854dd6032fd972a49ac (diff) | |
download | illumos-joyent-5d0bc3ededb82d77f7c33d8f58e517a837ba5140.tar.gz |
PSARC 2006/073 PF_ROUTE: Include interface name with RTM_NEWADDR/RTM_DELADDR
PSARC 2006/084 SO_ALLZONES
4963315 Should make IKE work for non-global zones
4984263 in.iked removes server entities when unnumbered interfaces go away
5024997 system daemons need a way to receive packets from all zones
6218993 PF_ROUTE: RTM_NEWADDR/RTM_DELADDR should include interface name via RTA_IFP
6422023 sctp doesn't need shadow copies of conn_t socket option bits
6426542 Comment about ipp_use_min_mtu got lost and wandered into conn_t
6430869 in.iked should ignore loopback addresses, not loopback interfaces
6438186 SCTP handling of getsockopt( .. SO_MAC_EXEMPT) is oddly inconsistent with TCP, UDP
Diffstat (limited to 'usr/src')
21 files changed, 177 insertions, 104 deletions
diff --git a/usr/src/cmd/mdb/common/modules/sctp/sctp.c b/usr/src/cmd/mdb/common/modules/sctp/sctp.c index 83904321bb..c40d3249e1 100644 --- a/usr/src/cmd/mdb/common/modules/sctp/sctp.c +++ b/usr/src/cmd/mdb/common/modules/sctp/sctp.c @@ -540,13 +540,8 @@ show_sctp_flags(sctp_t *sctp) mdb_printf("\tunderstands_asconf\t%d\n", sctp->sctp_understands_asconf); mdb_printf("\tdebug\t\t\t%d\n", sctp->sctp_debug); - mdb_printf("\tdontroute\t\t%d\n", sctp->sctp_dontroute); - mdb_printf("\tbroadcast\t\t%d\n", sctp->sctp_broadcast); - - mdb_printf("\tuseloopback\t\t%d\n", sctp->sctp_useloopback); mdb_printf("\tcchunk_pend\t\t%d\n", sctp->sctp_cchunk_pend); mdb_printf("\tdgram_errind\t\t%d\n", sctp->sctp_dgram_errind); - mdb_printf("\treuseaddr\t\t%d\n", sctp->sctp_reuseaddr); mdb_printf("\tlinger\t\t\t%d\n", sctp->sctp_linger); if (sctp->sctp_lingering) @@ -572,8 +567,8 @@ show_sctp_flags(sctp_t *sctp) mdb_printf("\tprsctp_aware\t\t%d\n", sctp->sctp_prsctp_aware); mdb_printf("\tlinklocal\t\t%d\n", sctp->sctp_linklocal); - mdb_printf("\tmac_exempt\t\t%d\n", sctp->sctp_mac_exempt); mdb_printf("\trexmitting\t\t%d\n", sctp->sctp_rexmitting); + mdb_printf("\tzero_win_probe\t\t%d\n", sctp->sctp_zero_win_probe); mdb_printf("\trecvsndrcvinfo\t\t%d\n", sctp->sctp_recvsndrcvinfo); mdb_printf("\trecvassocevnt\t\t%d\n", sctp->sctp_recvassocevnt); diff --git a/usr/src/cmd/ptools/pfiles/pfiles.c b/usr/src/cmd/ptools/pfiles/pfiles.c index 634736cf7b..80fdaa3e46 100644 --- a/usr/src/cmd/ptools/pfiles/pfiles.c +++ b/usr/src/cmd/ptools/pfiles/pfiles.c @@ -544,11 +544,12 @@ show_sockopts(struct ps_prochandle *Pr, int fd) { SO_DONTROUTE, "SO_DONTROUTE," }, { SO_BROADCAST, "SO_BROADCAST," }, { SO_OOBINLINE, "SO_OOBINLINE," }, - { SO_DGRAM_ERRIND, "SO_DGRAM_ERRIND,"} + { SO_DGRAM_ERRIND, "SO_DGRAM_ERRIND,"}, + { SO_ALLZONES, "SO_ALLZONES," }, }; struct linger l; - buf[0] = ','; + buf[0] = '!'; /* sentinel value, never printed */ buf[1] = '\0'; for (i = 0; i < sizeof (boolopts) / sizeof (boolopts[0]); i++) { @@ -588,7 +589,7 @@ show_sockopts(struct ps_prochandle *Pr, int fd) } } - buf[strlen(buf) - 1] = '\0'; + buf[strlen(buf) - 1] = '\0'; /* overwrites sentinel if no options */ if (buf[1] != '\0') (void) printf("\t%s\n", buf+1); } diff --git a/usr/src/cmd/truss/print.c b/usr/src/cmd/truss/print.c index 7ab35fd3b5..d8fc6fc08a 100644 --- a/usr/src/cmd/truss/print.c +++ b/usr/src/cmd/truss/print.c @@ -1758,6 +1758,7 @@ sol_optname(private_t *pri, long val) case SO_ERROR: return ("SO_ERROR"); case SO_TYPE: return ("SO_TYPE"); case SO_PROTOTYPE: return ("SO_PROTOTYPE"); + case SO_ALLZONES: return ("SO_ALLZONES"); default: (void) snprintf(pri->code_buf, CBSIZE, "0x%lx", val); diff --git a/usr/src/uts/common/inet/ip/icmp.c b/usr/src/uts/common/inet/ip/icmp.c index df8c33bb4b..d79cfce076 100644 --- a/usr/src/uts/common/inet/ip/icmp.c +++ b/usr/src/uts/common/inet/ip/icmp.c @@ -1567,12 +1567,13 @@ icmp_opt_get(queue_t *q, int level, int name, uchar_t *ptr) *i1 = icmp->icmp_mac_exempt; break; /* - * Following three not meaningful for icmp + * Following four not meaningful for icmp * Action is same as "default" to which we fallthrough * so we keep them in comments. * case SO_LINGER: * case SO_KEEPALIVE: * case SO_OOBINLINE: + * case SO_ALLZONES: */ default: return (-1); @@ -2024,6 +2025,13 @@ icmp_opt_set(queue_t *q, uint_t optset_context, int level, int name, if (!checkonly) icmp->icmp_dgram_errind = onoff; break; + case SO_ALLZONES: + /* + * "soft" error (negative) + * option not handled at this level + * Note: Do not modify *outlenp + */ + return (-EINVAL); case SO_TIMESTAMP: if (!checkonly) { icmp->icmp_timestamp = onoff; diff --git a/usr/src/uts/common/inet/ip/icmp_opt_data.c b/usr/src/uts/common/inet/ip/icmp_opt_data.c index 515880c03d..41d3278422 100644 --- a/usr/src/uts/common/inet/ip/icmp_opt_data.c +++ b/usr/src/uts/common/inet/ip/icmp_opt_data.c @@ -88,7 +88,10 @@ opdes_t icmp_opt_arr[] = { { SO_TIMESTAMP, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int), 0 }, { SO_MAC_EXEMPT, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int), - 0 }, + 0 }, + +{ SO_ALLZONES, SOL_SOCKET, OA_R, OA_RW, OP_CONFIG, OP_PASSNEXT, sizeof (int), + 0 }, { IP_OPTIONS, IPPROTO_IP, OA_RW, OA_RW, OP_NP, (OP_PASSNEXT|OP_VARLEN|OP_NODEFAULT), diff --git a/usr/src/uts/common/inet/ip/ip.c b/usr/src/uts/common/inet/ip/ip.c index 3f59b430a5..7ba17444f3 100644 --- a/usr/src/uts/common/inet/ip/ip.c +++ b/usr/src/uts/common/inet/ip/ip.c @@ -4245,7 +4245,7 @@ ip_bind_laddr(conn_t *connp, mblk_t *mp, ipaddr_t src_addr, uint16_t lport, src_ire = NULL; ipif = NULL; - zoneid = connp->conn_zoneid; + zoneid = IPCL_ZONEID(connp); if (src_addr) { src_ire = ire_route_lookup(src_addr, 0, 0, 0, @@ -4431,7 +4431,7 @@ ip_bind_connected(conn_t *connp, mblk_t *mp, ipaddr_t *src_addrp, policy_mp = mp->b_cont; } - zoneid = connp->conn_zoneid; + zoneid = IPCL_ZONEID(connp); if (CLASSD(dst_addr)) { /* Pick up an IRE_BROADCAST */ @@ -6353,7 +6353,8 @@ ip_fanout_udp(queue_t *q, mblk_t *mp, ill_t *ill, ipha_t *ipha, */ while ((connp != NULL) && (!IPCL_UDP_MATCH(connp, dstport, dst, - srcport, src) || connp->conn_zoneid != zoneid)) { + srcport, src) || + (connp->conn_zoneid != zoneid && !connp->conn_allzones))) { connp = connp->conn_next; } @@ -6499,7 +6500,7 @@ notfound: if (!broadcast && !CLASSD(dst)) { while (connp != NULL) { if (IPCL_UDP_MATCH_V6(connp, dstport, ipv6_all_zeros, - srcport, v6src) && connp->conn_zoneid == zoneid && + srcport, v6src) && IPCL_ZONE_MATCH(connp, zoneid) && conn_wantpacket(connp, ill, ipha, flags, zoneid) && !connp->conn_ipv6_v6only) break; @@ -9666,16 +9667,17 @@ ip_opt_set_ipif(conn_t *connp, ipaddr_t addr, boolean_t checkonly, int option, ipif_t *ipif = NULL; int error; ill_t *ill; + int zoneid; ip2dbg(("ip_opt_set_ipif: ipaddr %X\n", addr)); if (addr != INADDR_ANY || checkonly) { ASSERT(connp != NULL); + zoneid = IPCL_ZONEID(connp); if (option == IP_NEXTHOP) { - ipif = - ipif_lookup_onlink_addr(addr, connp->conn_zoneid); + ipif = ipif_lookup_onlink_addr(addr, zoneid); } else { - ipif = ipif_lookup_addr(addr, NULL, connp->conn_zoneid, + ipif = ipif_lookup_addr(addr, NULL, zoneid, CONNP_TO_WQ(connp), first_mp, ip_restart_optmgmt, &error); } @@ -10057,6 +10059,17 @@ ip_opt_set(queue_t *q, uint_t optset_context, int level, int name, mutex_exit(&connp->conn_lock); } break; /* goto sizeof (int) option return */ + case SO_ALLZONES: + if (!checkonly) { + mutex_enter(&connp->conn_lock); + if (IPCL_IS_BOUND(connp)) { + mutex_exit(&connp->conn_lock); + return (EINVAL); + } + connp->conn_allzones = *i1 != 0 ? 1 : 0; + mutex_exit(&connp->conn_lock); + } + break; /* goto sizeof (int) option return */ case SO_ANON_MLP: if (!checkonly) { mutex_enter(&connp->conn_lock); @@ -26384,7 +26397,7 @@ conn_wantpacket(conn_t *connp, ill_t *ill, ipha_t *ipha, int fanout_flags, } if (!CLASSD(dst)) { - if (connp->conn_zoneid == zoneid) + if (IPCL_ZONE_MATCH(connp, zoneid)) return (B_TRUE); /* * The conn is in a different zone; we need to check that this diff --git a/usr/src/uts/common/inet/ip/ip_multi.c b/usr/src/uts/common/inet/ip/ip_multi.c index 3586b89d24..d95b8fdaf3 100644 --- a/usr/src/uts/common/inet/ip/ip_multi.c +++ b/usr/src/uts/common/inet/ip/ip_multi.c @@ -1858,13 +1858,15 @@ ip_opt_check(conn_t *connp, ipaddr_t group, ipaddr_t src, ipaddr_t ifaddr, { ipif_t *ipif; int err = 0; - zoneid_t zoneid = connp->conn_zoneid; + zoneid_t zoneid; if (!CLASSD(group) || CLASSD(src)) { return (EINVAL); } *ipifpp = NULL; + zoneid = IPCL_ZONEID(connp); + ASSERT(!(ifaddr != INADDR_ANY && ifindexp != NULL && *ifindexp != 0)); if (ifaddr != INADDR_ANY) { ipif = ipif_lookup_addr(ifaddr, NULL, zoneid, diff --git a/usr/src/uts/common/inet/ip/ip_opt_data.c b/usr/src/uts/common/inet/ip/ip_opt_data.c index 6f9f7c0f0e..86e146a5b6 100644 --- a/usr/src/uts/common/inet/ip/ip_opt_data.c +++ b/usr/src/uts/common/inet/ip/ip_opt_data.c @@ -66,6 +66,10 @@ opdes_t ip_opt_arr[] = { { SO_MAC_EXEMPT, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int), 0 }, +{ SO_ALLZONES, SOL_SOCKET, OA_R, OA_RW, OP_CONFIG, OP_PASSNEXT, sizeof (int), + 0 }, + + { IP_OPTIONS, IPPROTO_IP, OA_RW, OA_RW, OP_NP, (OP_PASSNEXT|OP_VARLEN|OP_NODEFAULT), 40, -1 /* not initialized */ }, { T_IP_OPTIONS, IPPROTO_IP, OA_RW, OA_RW, OP_NP, diff --git a/usr/src/uts/common/inet/ip/ip_rts.c b/usr/src/uts/common/inet/ip/ip_rts.c index 9312ee37c2..7a78143e6c 100644 --- a/usr/src/uts/common/inet/ip/ip_rts.c +++ b/usr/src/uts/common/inet/ip/ip_rts.c @@ -1805,7 +1805,7 @@ ip_rts_newaddrmsg(int cmd, int error, const ipif_t *ipif) (cmd == RTM_DELETE && pass == 2)) { ncmd = ((cmd == RTM_ADD) ? RTM_NEWADDR : RTM_DELADDR); - rtm_addrs = (RTA_IFA | RTA_NETMASK | RTA_BRD); + rtm_addrs = (RTA_IFA | RTA_NETMASK | RTA_BRD | RTA_IFP); mp = rts_alloc_msg(ncmd, rtm_addrs, af, 0); if (mp == NULL) continue; @@ -1813,7 +1813,7 @@ ip_rts_newaddrmsg(int cmd, int error, const ipif_t *ipif) case AF_INET: rts_fill_msg(ncmd, rtm_addrs, 0, ipif->ipif_net_mask, 0, ipif->ipif_lcl_addr, - ipif->ipif_pp_dst_addr, 0, NULL, mp, + ipif->ipif_pp_dst_addr, 0, ipif, mp, 0, NULL); break; case AF_INET6: @@ -1821,7 +1821,7 @@ ip_rts_newaddrmsg(int cmd, int error, const ipif_t *ipif) &ipv6_all_zeros, &ipif->ipif_v6net_mask, &ipv6_all_zeros, &ipif->ipif_v6lcl_addr, &ipif->ipif_v6pp_dst_addr, &ipv6_all_zeros, - NULL, mp, 0, NULL); + ipif, mp, 0, NULL); break; } ifam = (ifa_msghdr_t *)mp->b_rptr; diff --git a/usr/src/uts/common/inet/ip/ipclassifier.c b/usr/src/uts/common/inet/ip/ipclassifier.c index 9983068c64..74bc792c80 100644 --- a/usr/src/uts/common/inet/ip/ipclassifier.c +++ b/usr/src/uts/common/inet/ip/ipclassifier.c @@ -1362,8 +1362,7 @@ ipcl_classify_v4(mblk_t *mp, uint8_t protocol, uint_t hdr_len, zoneid_t zoneid) for (connp = bind_connfp->connf_head; connp != NULL; connp = connp->conn_next) { if (IPCL_BIND_MATCH(connp, protocol, ipha->ipha_dst, - lport) && - (connp->conn_zoneid == zoneid || + lport) && (IPCL_ZONE_MATCH(connp, zoneid) || (unlabeled && connp->conn_mac_exempt))) break; } @@ -1432,7 +1431,7 @@ ipcl_classify_v4(mblk_t *mp, uint8_t protocol, uint_t hdr_len, zoneid_t zoneid) connp = connp->conn_next) { if (IPCL_UDP_MATCH(connp, lport, ipha->ipha_dst, fport, ipha->ipha_src) && - (connp->conn_zoneid == zoneid || + (IPCL_ZONE_MATCH(connp, zoneid) || (unlabeled && connp->conn_mac_exempt))) break; } @@ -1546,7 +1545,7 @@ ipcl_classify_v6(mblk_t *mp, uint8_t protocol, uint_t hdr_len, zoneid_t zoneid) connp = connp->conn_next) { if (IPCL_BIND_MATCH_V6(connp, protocol, ip6h->ip6_dst, lport) && - (connp->conn_zoneid == zoneid || + (IPCL_ZONE_MATCH(connp, zoneid) || (unlabeled && connp->conn_mac_exempt))) break; } @@ -1617,7 +1616,7 @@ ipcl_classify_v6(mblk_t *mp, uint8_t protocol, uint_t hdr_len, zoneid_t zoneid) connp = connp->conn_next) { if (IPCL_UDP_MATCH_V6(connp, lport, ip6h->ip6_dst, fport, ip6h->ip6_src) && - (connp->conn_zoneid == zoneid || + (IPCL_ZONE_MATCH(connp, zoneid) || (unlabeled && connp->conn_mac_exempt))) break; } @@ -1755,7 +1754,7 @@ ipcl_classify_raw(mblk_t *mp, uint8_t protocol, zoneid_t zoneid, } } - if (connp->conn_zoneid == zoneid || + if (IPCL_ZONE_MATCH(connp, zoneid) || (unlabeled && connp->conn_mac_exempt)) break; } @@ -1784,7 +1783,7 @@ ipcl_classify_raw(mblk_t *mp, uint8_t protocol, zoneid_t zoneid, connp = connp->conn_next) { /* We don't allow v4 fallback for v6 raw socket. */ if ((af == (connp->conn_af_isv6 ? IPV4_VERSION : - IPV6_VERSION)) || (connp->conn_zoneid != zoneid)) { + IPV6_VERSION)) || !IPCL_ZONE_MATCH(connp, zoneid)) { continue; } if (af == IPV4_VERSION) { @@ -2163,7 +2162,7 @@ ipcl_lookup_listener_v4(uint16_t lport, ipaddr_t laddr, zoneid_t zoneid) connp = connp->conn_next) { tcp = connp->conn_tcp; if (IPCL_BIND_MATCH(connp, IPPROTO_TCP, laddr, lport) && - connp->conn_zoneid == zoneid && + IPCL_ZONE_MATCH(connp, zoneid) && (tcp->tcp_listener == NULL)) { CONN_INC_REF(connp); mutex_exit(&bind_connfp->connf_lock); @@ -2201,7 +2200,7 @@ ipcl_lookup_listener_v6(uint16_t lport, in6_addr_t *laddr, uint_t ifindex, connp = connp->conn_next) { tcp = connp->conn_tcp; if (IPCL_BIND_MATCH_V6(connp, IPPROTO_TCP, *laddr, lport) && - connp->conn_zoneid == zoneid && + IPCL_ZONE_MATCH(connp, zoneid) && (tcp->tcp_bound_if == 0 || tcp->tcp_bound_if == ifindex) && tcp->tcp_listener == NULL) { diff --git a/usr/src/uts/common/inet/ipclassifier.h b/usr/src/uts/common/inet/ipclassifier.h index e11e1caf77..f424dbe78d 100644 --- a/usr/src/uts/common/inet/ipclassifier.h +++ b/usr/src/uts/common/inet/ipclassifier.h @@ -165,18 +165,13 @@ struct conn_s { conn_pathmtu_valid : 1, /* The cached mtu is valid. */ conn_ipv6_dontfrag : 1, /* IPV6_DONTFRAG */ - /* - * This option can take on values in [-1, 1] so we store it - * +1. Manifest constants IPV6_USE_MIN_MTU_* describe these - * values. - */ conn_fully_bound : 1, /* Fully bound connection */ conn_recvif : 1, /* IP_RECVIF option */ conn_recvslla : 1, /* IP_RECVSLLA option */ conn_mdt_ok : 1, /* MDT is permitted */ conn_nexthop_set : 1, - pad_to_bit_31 : 1; + conn_allzones : 1; /* SO_ALLZONES */ tcp_t *conn_tcp; /* Pointer to the tcp struct */ struct udp_s *conn_udp; /* Pointer to the udp struct */ @@ -332,12 +327,28 @@ struct connf_s { } \ } +/* + * For use with subsystems within ip which use ALL_ZONES as a wildcard + */ +#define IPCL_ZONEID(connp) \ + ((connp)->conn_allzones ? ALL_ZONES : (connp)->conn_zoneid) + +/* + * For matching between a conn_t and a zoneid. + */ +#define IPCL_ZONE_MATCH(connp, zoneid) \ + (((connp)->conn_allzones) || \ + ((zoneid) == ALL_ZONES) || \ + (connp)->conn_zoneid == (zoneid)) + + #define _IPCL_V4_MATCH(v6addr, v4addr) \ (V4_PART_OF_V6((v6addr)) == (v4addr) && IN6_IS_ADDR_V4MAPPED(&(v6addr))) #define _IPCL_V4_MATCH_ANY(addr) \ (IN6_IS_ADDR_V4MAPPED_ANY(&(addr)) || IN6_IS_ADDR_UNSPECIFIED(&(addr))) + /* * IPCL_PROTO_MATCH() only matches conns with the specified zoneid, while * IPCL_PROTO_MATCH_V6() can match other conns in the multicast case, see @@ -347,12 +358,12 @@ struct connf_s { fanout_flags, zoneid) \ ((((connp)->conn_src == INADDR_ANY) || \ (((connp)->conn_src == ((ipha)->ipha_dst)) && \ - (((connp)->conn_rem == INADDR_ANY) || \ + (((connp)->conn_rem == INADDR_ANY) || \ ((connp)->conn_rem == ((ipha)->ipha_src))))) && \ - ((zoneid) == ALL_ZONES || (connp)->conn_zoneid == (zoneid)) && \ - (conn_wantpacket((connp), (ill), (ipha), \ - (fanout_flags), (zoneid)) || ((protocol) == IPPROTO_PIM) || \ - ((protocol) == IPPROTO_RSVP))) + IPCL_ZONE_MATCH(connp, zoneid) && \ + (conn_wantpacket((connp), (ill), (ipha), (fanout_flags), \ + (zoneid)) || ((protocol) == IPPROTO_PIM) || \ + ((protocol) == IPPROTO_RSVP))) #define IPCL_PROTO_MATCH_V6(connp, protocol, ip6h, ill, \ fanout_flags, zoneid) \ diff --git a/usr/src/uts/common/inet/sctp/sctp.c b/usr/src/uts/common/inet/sctp/sctp.c index cc9c1345ad..f42afa0d2c 100644 --- a/usr/src/uts/common/inet/sctp/sctp.c +++ b/usr/src/uts/common/inet/sctp/sctp.c @@ -239,7 +239,10 @@ sctp_create_eager(sctp_t *psctp) if (getpflags(NET_MAC_AWARE, credp) != 0) connp->conn_mac_exempt = B_TRUE; } - connp->conn_zoneid = psctp->sctp_zoneid; + + connp->conn_allzones = pconnp->conn_allzones; + connp->conn_zoneid = pconnp->conn_zoneid; + sctp->sctp_mss = psctp->sctp_mss; sctp->sctp_detached = B_TRUE; /* @@ -853,6 +856,7 @@ sctp_init_values(sctp_t *sctp, sctp_t *psctp, int sleep) { int err; int cnt; + conn_t *connp, *pconnp; ASSERT((sctp->sctp_family == AF_INET && sctp->sctp_ipversion == IPV4_VERSION) || @@ -954,16 +958,22 @@ sctp_init_values(sctp_t *sctp, sctp_t *psctp, int sleep) /* xxx should be a better way to copy these flags xxx */ sctp->sctp_debug = psctp->sctp_debug; - sctp->sctp_dontroute = psctp->sctp_dontroute; - sctp->sctp_useloopback = psctp->sctp_useloopback; - sctp->sctp_broadcast = psctp->sctp_broadcast; - sctp->sctp_reuseaddr = psctp->sctp_reuseaddr; sctp->sctp_bound_to_all = psctp->sctp_bound_to_all; sctp->sctp_cansleep = psctp->sctp_cansleep; sctp->sctp_send_adaption = psctp->sctp_send_adaption; sctp->sctp_ndelay = psctp->sctp_ndelay; sctp->sctp_events = psctp->sctp_events; sctp->sctp_ipv6_recvancillary = psctp->sctp_ipv6_recvancillary; + + /* Copy IP-layer options */ + connp = sctp->sctp_connp; + pconnp = psctp->sctp_connp; + + connp->conn_broadcast = pconnp->conn_broadcast; + connp->conn_loopback = pconnp->conn_loopback; + connp->conn_dontroute = pconnp->conn_dontroute; + connp->conn_reuseaddr = pconnp->conn_reuseaddr; + } else { /* * Initialize the header template @@ -1369,6 +1379,7 @@ sctp_create(void *sctp_ulpd, sctp_t *parent, int family, int flags, */ sctp->sctp_lport = psctp->sctp_lport; sctp->sctp_state = SCTPS_BOUND; + sctp->sctp_allzones = psctp->sctp_allzones; sctp->sctp_zoneid = psctp->sctp_zoneid; WAKE_SCTP(psctp); } else { diff --git a/usr/src/uts/common/inet/sctp/sctp_addr.c b/usr/src/uts/common/inet/sctp/sctp_addr.c index 089ac791a8..a4bef74443 100644 --- a/usr/src/uts/common/inet/sctp/sctp_addr.c +++ b/usr/src/uts/common/inet/sctp/sctp_addr.c @@ -50,7 +50,7 @@ static void sctp_ipif_inactive(sctp_ipif_t *); static sctp_ipif_t *sctp_lookup_ipif_addr(in6_addr_t *, boolean_t, - zoneid_t zoneid, uint_t); + sctp_t *, uint_t); static int sctp_get_all_ipifs(sctp_t *, int); int sctp_valid_addr_list(sctp_t *, const void *, uint32_t, uchar_t *, size_t); @@ -94,6 +94,9 @@ void sctp_saddr_fini(); ((!(ipif)->sctp_ipif_isv6 && !((supp_af) & PARM_SUPP_V4)) || \ ((ipif)->sctp_ipif_isv6 && !((supp_af) & PARM_SUPP_V6))) +#define SCTP_IPIF_ZONE_MATCH(sctp, ipif) \ + IPCL_ZONE_MATCH((sctp)->sctp_connp, (ipif)->sctp_ipif_zoneid) + #define SCTP_ILL_HASH_FN(index) ((index) % SCTP_ILL_HASH) #define SCTP_IPIF_HASH_FN(seqid) ((seqid) % SCTP_IPIF_HASH) #define SCTP_ILL_TO_PHYINDEX(ill) ((ill)->ill_phyint->phyint_ifindex) @@ -167,14 +170,14 @@ sctp_ipif_inactive(sctp_ipif_t *sctp_ipif) * Called with no locks held. */ static sctp_ipif_t * -sctp_lookup_ipif_addr(in6_addr_t *addr, boolean_t refhold, zoneid_t zoneid, +sctp_lookup_ipif_addr(in6_addr_t *addr, boolean_t refhold, sctp_t *sctp, uint_t ifindex) { int i; int j; sctp_ipif_t *sctp_ipif; - ASSERT(zoneid != ALL_ZONES); + ASSERT(sctp->sctp_zoneid != ALL_ZONES); rw_enter(&sctp_g_ipifs_lock, RW_READER); for (i = 0; i < SCTP_IPIF_HASH; i++) { if (sctp_g_ipifs[i].ipif_count == 0) @@ -182,8 +185,7 @@ sctp_lookup_ipif_addr(in6_addr_t *addr, boolean_t refhold, zoneid_t zoneid, sctp_ipif = list_head(&sctp_g_ipifs[i].sctp_ipif_list); for (j = 0; j < sctp_g_ipifs[i].ipif_count; j++) { rw_enter(&sctp_ipif->sctp_ipif_lock, RW_READER); - if ((zoneid == sctp_ipif->sctp_ipif_zoneid || - sctp_ipif->sctp_ipif_zoneid == ALL_ZONES) && + if (SCTP_IPIF_ZONE_MATCH(sctp, sctp_ipif) && SCTP_IPIF_USABLE(sctp_ipif->sctp_ipif_state) && (ifindex == 0 || ifindex == sctp_ipif->sctp_ipif_ill->sctp_ill_index) && @@ -226,8 +228,7 @@ sctp_get_all_ipifs(sctp_t *sctp, int sleep) rw_enter(&sctp_ipif->sctp_ipif_lock, RW_READER); if (SCTP_IPIF_DISCARD(sctp_ipif->sctp_ipif_flags) || !SCTP_IPIF_USABLE(sctp_ipif->sctp_ipif_state) || - (sctp_ipif->sctp_ipif_zoneid != ALL_ZONES && - sctp_ipif->sctp_ipif_zoneid != sctp->sctp_zoneid) || + !SCTP_IPIF_ZONE_MATCH(sctp, sctp_ipif) || (sctp->sctp_ipversion == IPV4_VERSION && sctp_ipif->sctp_ipif_isv6) || (sctp->sctp_connp->conn_ipv6_v6only && @@ -359,8 +360,8 @@ sctp_valid_addr_list(sctp_t *sctp, const void *addrs, uint32_t addrcnt, goto free_ret; } if (lookup_saddr) { - ipif = sctp_lookup_ipif_addr(&addr, B_TRUE, - sctp->sctp_zoneid, ifindex); + ipif = sctp_lookup_ipif_addr(&addr, B_TRUE, sctp, + ifindex); if (ipif == NULL) { /* Address not in the list */ err = EINVAL; @@ -974,8 +975,8 @@ sctp_del_saddr_list(sctp_t *sctp, const void *addrs, int addcnt, ifindex = sin6->sin6_scope_id; break; } - sctp_ipif = sctp_lookup_ipif_addr(&addr, B_FALSE, - sctp->sctp_zoneid, ifindex); + sctp_ipif = sctp_lookup_ipif_addr(&addr, B_FALSE, sctp, + ifindex); ASSERT(sctp_ipif != NULL); sctp_ipif_hash_remove(sctp, sctp_ipif); } @@ -1000,8 +1001,7 @@ sctp_saddr_lookup(sctp_t *sctp, in6_addr_t *addr, uint_t ifindex) sctp_saddr_ipif_t *saddr_ipifs; sctp_ipif_t *sctp_ipif; - sctp_ipif = sctp_lookup_ipif_addr(addr, B_FALSE, sctp->sctp_zoneid, - ifindex); + sctp_ipif = sctp_lookup_ipif_addr(addr, B_FALSE, sctp, ifindex); if (sctp_ipif == NULL) return (NULL); @@ -1015,8 +1015,7 @@ sctp_saddr_add_addr(sctp_t *sctp, in6_addr_t *addr, uint_t ifindex) { sctp_ipif_t *sctp_ipif; - sctp_ipif = sctp_lookup_ipif_addr(addr, B_TRUE, sctp->sctp_zoneid, - ifindex); + sctp_ipif = sctp_lookup_ipif_addr(addr, B_TRUE, sctp, ifindex); if (sctp_ipif == NULL) return (EINVAL); @@ -1447,7 +1446,7 @@ get_all_addrs: !SCTP_IPIF_USABLE(sctp_ipif->sctp_ipif_state) || SCTP_IS_IPIF_LOOPBACK(sctp_ipif) || SCTP_IS_IPIF_LINKLOCAL(sctp_ipif) || - sctp_ipif->sctp_ipif_zoneid != sctp->sctp_zoneid || + !SCTP_IPIF_ZONE_MATCH(sctp, sctp_ipif) || (sctp->sctp_ipversion == IPV4_VERSION && sctp_ipif->sctp_ipif_isv6) || (sctp->sctp_connp->conn_ipv6_v6only && diff --git a/usr/src/uts/common/inet/sctp/sctp_hash.c b/usr/src/uts/common/inet/sctp/sctp_hash.c index 2efd771f9e..ff21e9c950 100644 --- a/usr/src/uts/common/inet/sctp/sctp_hash.c +++ b/usr/src/uts/common/inet/sctp/sctp_hash.c @@ -286,8 +286,8 @@ sctp_conn_match(in6_addr_t *faddr, in6_addr_t *laddr, uint32_t ports, mutex_enter(&tf->tf_lock); for (sctp = tf->tf_sctp; sctp; sctp = sctp->sctp_conn_hash_next) { - if (ports != sctp->sctp_ports || (zoneid != ALL_ZONES && - zoneid != sctp->sctp_zoneid)) { + if (ports != sctp->sctp_ports || + !IPCL_ZONE_MATCH(sctp->sctp_connp, zoneid)) { continue; } @@ -337,8 +337,8 @@ listen_match(in6_addr_t *laddr, uint32_t ports, uint_t ipif_seqid, mutex_enter(&tf->tf_lock); for (sctp = tf->tf_sctp; sctp; sctp = sctp->sctp_listen_hash_next) { - if (lport != sctp->sctp_lport || (zoneid != ALL_ZONES && - zoneid != sctp->sctp_zoneid)) { + if (lport != sctp->sctp_lport || + !IPCL_ZONE_MATCH(sctp->sctp_connp, zoneid)) { continue; } diff --git a/usr/src/uts/common/inet/sctp/sctp_impl.h b/usr/src/uts/common/inet/sctp/sctp_impl.h index fbc157f682..fd934ab482 100644 --- a/usr/src/uts/common/inet/sctp/sctp_impl.h +++ b/usr/src/uts/common/inet/sctp/sctp_impl.h @@ -633,7 +633,10 @@ typedef struct sctp_s { conn_t *sctp_connp; /* conn_t stuff */ #define sctp_zoneid sctp_connp->conn_zoneid +#define sctp_allzones sctp_connp->conn_allzones +#define sctp_mac_exempt sctp_connp->conn_mac_exempt #define sctp_credp sctp_connp->conn_cred +#define sctp_reuseaddr sctp_connp->conn_reuseaddr /* Peer address tracking */ sctp_faddr_t *sctp_lastfaddr; /* last faddr in list */ @@ -743,13 +746,8 @@ typedef struct sctp_s { sctp_understands_asconf : 1, /* Peer handles ASCONF chunks */ sctp_debug : 1, /* SO_DEBUG "socket" option. */ - sctp_dontroute : 1, /* SO_DONTROUTE "socket" option. */ - sctp_broadcast : 1, /* SO_BROADCAST "socket" option. */ - - sctp_useloopback : 1, /* SO_USELOOPBACK "socket" option. */ sctp_cchunk_pend : 1, /* Control chunk in flight. */ sctp_dgram_errind : 1, /* SO_DGRAM_ERRIND option */ - sctp_reuseaddr : 1, /* SO_REUSEADDR "socket" option. */ sctp_linger : 1, /* SO_LINGER turned on */ sctp_lingering : 1, /* Lingering in close */ @@ -773,11 +771,10 @@ typedef struct sctp_s { sctp_prsctp_aware : 1, /* is peer PR-SCTP aware? */ sctp_linklocal : 1, /* is linklocal assoc. */ - sctp_mac_exempt : 1, /* SO_MAC_EXEMPT */ sctp_rexmitting : 1, /* SCTP is retransmitting */ sctp_zero_win_probe : 1, /* doing zero win probe */ - sctp_dummy : 3; + sctp_dummy : 8; } sctp_bits; struct { uint32_t @@ -795,12 +792,8 @@ typedef struct sctp_s { #define sctp_priv_stream sctp_bits.sctp_priv_stream #define sctp_understands_asconf sctp_bits.sctp_understands_asconf #define sctp_debug sctp_bits.sctp_debug -#define sctp_dontroute sctp_bits.sctp_dontroute -#define sctp_broadcast sctp_bits.sctp_broadcast -#define sctp_useloopback sctp_bits.sctp_useloopback #define sctp_cchunk_pend sctp_bits.sctp_cchunk_pend #define sctp_dgram_errind sctp_bits.sctp_dgram_errind -#define sctp_reuseaddr sctp_bits.sctp_reuseaddr #define sctp_linger sctp_bits.sctp_linger #define sctp_lingering sctp_bits.sctp_lingering #define sctp_loopback sctp_bits.sctp_loopback @@ -819,7 +812,6 @@ typedef struct sctp_s { #define sctp_chk_fast_rexmit sctp_bits.sctp_chk_fast_rexmit #define sctp_prsctp_aware sctp_bits.sctp_prsctp_aware #define sctp_linklocal sctp_bits.sctp_linklocal -#define sctp_mac_exempt sctp_bits.sctp_mac_exempt #define sctp_rexmitting sctp_bits.sctp_rexmitting #define sctp_zero_win_probe sctp_bits.sctp_zero_win_probe diff --git a/usr/src/uts/common/inet/sctp/sctp_opt_data.c b/usr/src/uts/common/inet/sctp/sctp_opt_data.c index 89ffd6ae60..c670fecbb9 100644 --- a/usr/src/uts/common/inet/sctp/sctp_opt_data.c +++ b/usr/src/uts/common/inet/sctp/sctp_opt_data.c @@ -701,16 +701,16 @@ sctp_get_opt(sctp_t *sctp, int level, int name, void *ptr, socklen_t *optlen) *i1 = sctp->sctp_debug ? SO_DEBUG : 0; break; case SO_DONTROUTE: - *i1 = sctp->sctp_dontroute ? SO_DONTROUTE : 0; + *i1 = connp->conn_dontroute ? SO_DONTROUTE : 0; break; case SO_USELOOPBACK: - *i1 = sctp->sctp_useloopback ? SO_USELOOPBACK : 0; + *i1 = connp->conn_loopback ? SO_USELOOPBACK : 0; break; case SO_BROADCAST: - *i1 = sctp->sctp_broadcast ? SO_BROADCAST : 0; + *i1 = connp->conn_broadcast ? SO_BROADCAST : 0; break; case SO_REUSEADDR: - *i1 = sctp->sctp_reuseaddr ? SO_REUSEADDR : 0; + *i1 = connp->conn_reuseaddr ? SO_REUSEADDR : 0; break; case SO_DGRAM_ERRIND: *i1 = sctp->sctp_dgram_errind ? SO_DGRAM_ERRIND : 0; @@ -721,8 +721,11 @@ sctp_get_opt(sctp_t *sctp, int level, int name, void *ptr, socklen_t *optlen) case SO_RCVBUF: *i1 = sctp->sctp_rwnd; break; + case SO_ALLZONES: + *i1 = connp->conn_allzones; + break; case SO_MAC_EXEMPT: - *i1 = sctp->sctp_mac_exempt ? SO_MAC_EXEMPT : 0; + *i1 = connp->conn_mac_exempt; break; default: retval = EINVAL; @@ -1160,22 +1163,17 @@ sctp_set_opt(sctp_t *sctp, int level, int name, const void *invalp, case SO_DONTROUTE: /* * SO_DONTROUTE, SO_USELOOPBACK and SO_BROADCAST are - * only of interest to IP. We track them here only so - * that we can report their current value. + * only of interest to IP. */ - sctp->sctp_dontroute = onoff; connp->conn_dontroute = onoff; break; case SO_USELOOPBACK: - sctp->sctp_useloopback = onoff; connp->conn_loopback = onoff; break; case SO_BROADCAST: - sctp->sctp_broadcast = onoff; connp->conn_broadcast = onoff; break; case SO_REUSEADDR: - sctp->sctp_reuseaddr = onoff; connp->conn_reuseaddr = onoff; break; case SO_DGRAM_ERRIND: @@ -1220,14 +1218,28 @@ sctp_set_opt(sctp_t *sctp, int level, int name, const void *invalp, * and sctp_opt_get ? */ break; + case SO_ALLZONES: + if (secpolicy_net(sctp->sctp_credp, OP_CONFIG, + B_TRUE)) { + retval = EACCES; + break; + } + if (sctp->sctp_state >= SCTPS_BOUND) { + retval = EINVAL; + break; + } + sctp->sctp_allzones = onoff; + break; case SO_MAC_EXEMPT: - if (secpolicy_net_mac_aware(sctp->sctp_credp) != 0 || - sctp->sctp_state >= SCTPS_BOUND) { + if (secpolicy_net_mac_aware(sctp->sctp_credp) != 0) { retval = EACCES; - } else { - sctp->sctp_mac_exempt = onoff; - connp->conn_mac_exempt = onoff; + break; + } + if (sctp->sctp_state >= SCTPS_BOUND) { + retval = EINVAL; + break; } + connp->conn_mac_exempt = onoff; break; default: retval = EINVAL; diff --git a/usr/src/uts/common/inet/tcp/tcp.c b/usr/src/uts/common/inet/tcp/tcp.c index 17a35961d8..5ae25e49d5 100644 --- a/usr/src/uts/common/inet/tcp/tcp.c +++ b/usr/src/uts/common/inet/tcp/tcp.c @@ -3511,7 +3511,7 @@ tcp_bindi(tcp_t *tcp, in_port_t port, const in6_addr_t *laddr, * privilege as being in all zones, as there's * otherwise no way to identify the right receiver. */ - if (lconnp->conn_zoneid != zoneid && + if (!IPCL_ZONE_MATCH(ltcp->tcp_connp, zoneid) && !lconnp->conn_mac_exempt && !connp->conn_mac_exempt) continue; @@ -5341,7 +5341,7 @@ tcp_update_label(tcp_t *tcp, const cred_t *cr) * reference is dropped by the squeue framework. * * 3) The ref on listener placed in 1 above is dropped in tcp_accept_finish - * + * * The reference must be released by the same entity that added the reference * In the above scheme, the eager is the entity that adds and releases the * references. Note that tcp_accept_finish executes in the squeue of the eager @@ -5373,10 +5373,10 @@ tcp_update_label(tcp_t *tcp, const cred_t *cr) * based on the ref placed on eager before sending T_conn_ind. * The only entity that can negate this refhold is a listener close * which is mutually exclusive with an active acceptor stream. - * + * * Eager's reference on the listener * =================================== - * + * * If the accept happens (even on a closed eager) the eager drops its * reference on the listener at the start of tcp_accept_finish. If the * eager is killed due to an incoming RST before the T_conn_ind is sent up, @@ -9587,6 +9587,9 @@ tcp_opt_get(queue_t *q, int level, int name, uchar_t *ptr) *i1 = tcp->tcp_snd_zcopy_on ? SO_SND_COPYAVOID : 0; break; + case SO_ALLZONES: + *i1 = connp->conn_allzones ? 1 : 0; + break; case SO_ANON_MLP: *i1 = connp->conn_anon_mlp; break; @@ -10072,6 +10075,9 @@ tcp_opt_set(queue_t *q, uint_t optset_context, int level, int name, tcp->tcp_snd_zcopy_aware = 1; } break; + case SO_ALLZONES: + /* Handled at the IP level */ + return (-EINVAL); case SO_ANON_MLP: if (!checkonly) { mutex_enter(&connp->conn_lock); @@ -22613,7 +22619,7 @@ tcp_reserved_port_add(int size, in_port_t *lo_port, in_port_t *hi_port) mutex_enter(&tbf->tf_lock); for (tcp = tbf->tf_tcp; tcp != NULL; tcp = tcp->tcp_bind_hash) { - if (zoneid == tcp->tcp_connp->conn_zoneid && + if (IPCL_ZONE_MATCH(tcp->tcp_connp, zoneid) && net_port == tcp->tcp_lport) { /* * A port is already bound. Search again diff --git a/usr/src/uts/common/inet/tcp/tcp_opt_data.c b/usr/src/uts/common/inet/tcp/tcp_opt_data.c index 2f4139405a..350ff7ec30 100644 --- a/usr/src/uts/common/inet/tcp/tcp_opt_data.c +++ b/usr/src/uts/common/inet/tcp/tcp_opt_data.c @@ -75,9 +75,11 @@ opdes_t tcp_opt_arr[] = { }, { SO_SND_COPYAVOID, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 }, { SO_ANON_MLP, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int), - 0 }, + 0 }, { SO_MAC_EXEMPT, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int), - 0 }, + 0 }, +{ SO_ALLZONES, SOL_SOCKET, OA_R, OA_RW, OP_CONFIG, OP_PASSNEXT, sizeof (int), + 0 }, { TCP_NODELAY, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int), 0 }, { TCP_MAXSEG, IPPROTO_TCP, OA_R, OA_R, OP_NP, OP_PASSNEXT, sizeof (uint_t), diff --git a/usr/src/uts/common/inet/udp/udp.c b/usr/src/uts/common/inet/udp/udp.c index 2c8a401c05..c2213c446b 100644 --- a/usr/src/uts/common/inet/udp/udp.c +++ b/usr/src/uts/common/inet/udp/udp.c @@ -3104,13 +3104,16 @@ udp_opt_get(queue_t *q, t_scalar_t level, t_scalar_t name, uchar_t *ptr) break; /* goto sizeof (int) option return */ case SO_TIMESTAMP: *i1 = udp->udp_timestamp; - break; + break; /* goto sizeof (int) option return */ case SO_ANON_MLP: *i1 = udp->udp_anon_mlp; break; /* goto sizeof (int) option return */ case SO_MAC_EXEMPT: *i1 = udp->udp_mac_exempt; break; /* goto sizeof (int) option return */ + case SO_ALLZONES: + *i1 = connp->conn_allzones; + break; /* goto sizeof (int) option return */ default: return (-1); } @@ -3477,6 +3480,13 @@ udp_opt_set(queue_t *q, uint_t optset_context, int level, if (!checkonly) udp->udp_recvucred = onoff; break; + case SO_ALLZONES: + /* + * "soft" error (negative) + * option not handled at this level + * Do not modify *outlenp. + */ + return (-EINVAL); case SO_TIMESTAMP: if (!checkonly) udp->udp_timestamp = onoff; diff --git a/usr/src/uts/common/inet/udp/udp_opt_data.c b/usr/src/uts/common/inet/udp/udp_opt_data.c index 58836f3cb1..0ac5bb9a62 100644 --- a/usr/src/uts/common/inet/udp/udp_opt_data.c +++ b/usr/src/uts/common/inet/udp/udp_opt_data.c @@ -71,6 +71,8 @@ opdes_t udp_opt_arr[] = { 0 }, { SO_RECVUCRED, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int), 0 }, +{ SO_ALLZONES, SOL_SOCKET, OA_R, OA_RW, OP_CONFIG, OP_PASSNEXT, sizeof (int), + 0 }, { SO_TIMESTAMP, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int), 0 }, { SO_ANON_MLP, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int), diff --git a/usr/src/uts/common/sys/socket.h b/usr/src/uts/common/sys/socket.h index a43edfd1ce..2d6b58d8c3 100644 --- a/usr/src/uts/common/sys/socket.h +++ b/usr/src/uts/common/sys/socket.h @@ -153,6 +153,8 @@ typedef void *_RESTRICT_KYWD Psocklen_t; #define SO_TIMESTAMP 0x1013 /* socket-level timestamp option */ #define SCM_TIMESTAMP SO_TIMESTAMP /* socket control message timestamp */ +#define SO_ALLZONES 0x1014 /* bind in all zones */ + #ifdef _KERNEL #define SO_SRCADDR 0x2001 /* Internal: AF_UNIX source address */ #define SO_FILEP 0x2002 /* Internal: AF_UNIX file pointer */ |