summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvi117747 <none@none>2007-01-30 00:04:35 -0800
committervi117747 <none@none>2007-01-30 00:04:35 -0800
commite35d2278fa5447def80bb5a191ce0f1c6b6836de (patch)
treeeff5d8c8c47d17a8d4f9319983624a79bf60f8f3
parent691b55abbc2aa71b47338f7971838df72745f2da (diff)
downloadillumos-gate-e35d2278fa5447def80bb5a191ce0f1c6b6836de.tar.gz
6473179 SCTP assoc. should be resilient to addrs. being un-plumbed and re-plumbed on a diff. interface
-rw-r--r--usr/src/uts/common/inet/ip/ip.c27
-rw-r--r--usr/src/uts/common/inet/ip/ip6.c13
-rw-r--r--usr/src/uts/common/inet/ip/ip_if.c39
-rw-r--r--usr/src/uts/common/inet/ip/sadb.c4
-rw-r--r--usr/src/uts/common/inet/sctp/sctp_addr.c584
-rw-r--r--usr/src/uts/common/inet/sctp/sctp_addr.h10
-rw-r--r--usr/src/uts/common/inet/sctp/sctp_common.c6
-rw-r--r--usr/src/uts/common/inet/sctp/sctp_cookie.c10
-rw-r--r--usr/src/uts/common/inet/sctp/sctp_hash.c64
-rw-r--r--usr/src/uts/common/inet/sctp/sctp_impl.h4
-rw-r--r--usr/src/uts/common/inet/sctp/sctp_input.c7
-rw-r--r--usr/src/uts/common/inet/sctp_ip.h11
12 files changed, 511 insertions, 268 deletions
diff --git a/usr/src/uts/common/inet/ip/ip.c b/usr/src/uts/common/inet/ip/ip.c
index 83e13a8bd1..83b9fcd4a4 100644
--- a/usr/src/uts/common/inet/ip/ip.c
+++ b/usr/src/uts/common/inet/ip/ip.c
@@ -2137,7 +2137,7 @@ icmp_get_nexthop_addr(ipha_t *ipha, ill_t *ill, zoneid_t zoneid, mblk_t *mp)
((uint16_t *)&ports)[1] = up[0];
connp = sctp_find_conn(&map_src, &map_dst, ports,
- 0, zoneid, ipst->ips_netstack->netstack_sctp);
+ zoneid, ipst->ips_netstack->netstack_sctp);
if (connp == NULL) {
connp = ipcl_classify_raw(mp, IPPROTO_SCTP,
zoneid, ports, ipha, ipst);
@@ -2562,7 +2562,7 @@ icmp_inbound_error_fanout(queue_t *q, ill_t *ill, mblk_t *mp,
/* Have to change db_type after any pullupmsg */
DB_TYPE(mp) = M_CTL;
ip_fanout_sctp(first_mp, recv_ill, &ripha, ports, 0,
- mctl_present, ip_policy, 0, zoneid);
+ mctl_present, ip_policy, zoneid);
return;
case IPPROTO_ESP:
@@ -13624,7 +13624,6 @@ ip_sctp_input(mblk_t *mp, ipha_t *ipha, ill_t *recv_ill, boolean_t mctl_present,
uint32_t pktsum;
uint32_t calcsum;
uint32_t ports;
- uint_t ipif_seqid;
in6_addr_t map_src, map_dst;
ill_t *ill = (ill_t *)q->q_ptr;
ip_stack_t *ipst;
@@ -13720,12 +13719,11 @@ find_sctp_client:
/* get the ports */
ports = *(uint32_t *)&sctph->sh_sport;
- ipif_seqid = ire->ire_ipif->ipif_seqid;
IRE_REFRELE(ire);
IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst, &map_dst);
IN6_IPADDR_TO_V4MAPPED(ipha->ipha_src, &map_src);
- if ((connp = sctp_fanout(&map_src, &map_dst, ports, ipif_seqid, zoneid,
- mp, sctps)) == NULL) {
+ if ((connp = sctp_fanout(&map_src, &map_dst, ports, zoneid, mp,
+ sctps)) == NULL) {
/* Check for raw socket or OOTB handling */
goto no_conn;
}
@@ -13737,7 +13735,7 @@ find_sctp_client:
no_conn:
ip_fanout_sctp_raw(first_mp, recv_ill, ipha, B_TRUE,
- ports, mctl_present, flags, B_TRUE, ipif_seqid, zoneid);
+ ports, mctl_present, flags, B_TRUE, zoneid);
return;
ipoptions:
@@ -16333,8 +16331,13 @@ ip_rput_dlpi_writer(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
ASSERT(ill->ill_ipif->ipif_id == 0);
if (ipif != NULL &&
- IN6_IS_ADDR_UNSPECIFIED(&ipif->ipif_v6lcl_addr))
+ IN6_IS_ADDR_UNSPECIFIED(&ipif->ipif_v6lcl_addr)) {
+ in6_addr_t ov6addr;
+
+ ov6addr = ipif->ipif_v6lcl_addr;
(void) ipif_setlinklocal(ipif);
+ sctp_update_ipif_addr(ipif, ov6addr);
+ }
break;
}
case DL_OK_ACK:
@@ -25389,8 +25392,7 @@ ip_wput_local(queue_t *q, ill_t *ill, ipha_t *ipha, mblk_t *mp, ire_t *ire,
bcopy(rptr + IPH_HDR_LENGTH(ipha), &ports, sizeof (ports));
ip_fanout_sctp(first_mp, ill, ipha, ports,
fanout_flags | IP_FF_SEND_ICMP | IP_FF_HDR_COMPLETE |
- IP_FF_IPINFO,
- mctl_present, B_FALSE, 0, zoneid);
+ IP_FF_IPINFO, mctl_present, B_FALSE, zoneid);
return;
}
@@ -29770,7 +29772,7 @@ icmp_kstat_update(kstat_t *kp, int rw)
void
ip_fanout_sctp_raw(mblk_t *mp, ill_t *recv_ill, ipha_t *ipha, boolean_t isv4,
uint32_t ports, boolean_t mctl_present, uint_t flags, boolean_t ip_policy,
- uint_t ipif_seqid, zoneid_t zoneid)
+ zoneid_t zoneid)
{
conn_t *connp;
queue_t *rq;
@@ -29792,8 +29794,7 @@ ip_fanout_sctp_raw(mblk_t *mp, ill_t *recv_ill, ipha_t *ipha, boolean_t isv4,
connp = ipcl_classify_raw(mp, IPPROTO_SCTP, zoneid, ports, ipha, ipst);
if (connp == NULL) {
- sctp_ootb_input(first_mp, recv_ill, ipif_seqid, zoneid,
- mctl_present);
+ sctp_ootb_input(first_mp, recv_ill, zoneid, mctl_present);
return;
}
rq = connp->conn_rq;
diff --git a/usr/src/uts/common/inet/ip/ip6.c b/usr/src/uts/common/inet/ip/ip6.c
index 49938b8eac..2bbf82030f 100644
--- a/usr/src/uts/common/inet/ip/ip6.c
+++ b/usr/src/uts/common/inet/ip/ip6.c
@@ -952,7 +952,7 @@ icmp_inbound_error_fanout_v6(queue_t *q, mblk_t *mp, ip6_t *ip6h,
((uint16_t *)&ports)[0] = up[1];
((uint16_t *)&ports)[1] = up[0];
ip_fanout_sctp(mp, ill, (ipha_t *)ip6h, ports, 0, mctl_present,
- IP6_NO_IPPOLICY, 0, zoneid);
+ IP6_NO_IPPOLICY, zoneid);
return;
case IPPROTO_ESP:
case IPPROTO_AH: {
@@ -7266,7 +7266,6 @@ ip_rput_data_v6(queue_t *q, ill_t *inill, mblk_t *mp, ip6_t *ip6h,
conn_t *connp;
ilm_t *ilm;
uint32_t ports;
- uint_t ipif_id = 0;
zoneid_t zoneid = GLOBAL_ZONEID;
uint16_t hck_flags, reass_hck_flags;
uint32_t reass_sum;
@@ -7504,7 +7503,6 @@ ip_rput_data_v6(queue_t *q, ill_t *inill, mblk_t *mp, ip6_t *ip6h,
ALL_ZONES, ipst);
return;
}
- ipif_id = ire->ire_ipif->ipif_seqid;
/* we have a matching IRE */
if (ire->ire_stq != NULL) {
ill_group_t *ill_group;
@@ -7925,12 +7923,12 @@ tcp_fanout:
sctph->sh_chksum = pktsum;
ports = *(uint32_t *)(mp->b_rptr + hdr_len);
if ((connp = sctp_fanout(&ip6h->ip6_src, &ip6h->ip6_dst,
- ports, ipif_id, zoneid, mp, sctps)) == NULL) {
+ ports, zoneid, mp, sctps)) == NULL) {
ip_fanout_sctp_raw(first_mp, ill,
(ipha_t *)ip6h, B_FALSE, ports,
mctl_present,
(flags|IP_FF_SEND_ICMP|IP_FF_IPINFO),
- B_TRUE, ipif_id, zoneid);
+ B_TRUE, zoneid);
return;
}
BUMP_MIB(ill->ill_ip_mib, ipIfStatsHCInDelivers);
@@ -10732,13 +10730,10 @@ ip_wput_local_v6(queue_t *q, ill_t *ill, ip6_t *ip6h, mblk_t *first_mp,
case IPPROTO_SCTP:
{
- uint_t ipif_seqid = ire->ire_ipif->ipif_seqid;
-
ports = *(uint32_t *)(mp->b_rptr + hdr_length);
ip_fanout_sctp(mp, ill, (ipha_t *)ip6h, ports,
fanout_flags|IP_FF_SEND_ICMP|IP_FF_IPINFO,
- mctl_present, IP6_NO_IPPOLICY, ipif_seqid,
- ire->ire_zoneid);
+ mctl_present, IP6_NO_IPPOLICY, ire->ire_zoneid);
return;
}
case IPPROTO_ICMPV6: {
diff --git a/usr/src/uts/common/inet/ip/ip_if.c b/usr/src/uts/common/inet/ip/ip_if.c
index a7aac93eda..4f0694b33b 100644
--- a/usr/src/uts/common/inet/ip/ip_if.c
+++ b/usr/src/uts/common/inet/ip/ip_if.c
@@ -5029,6 +5029,7 @@ ill_lookup_on_name(char *name, boolean_t do_alloc, boolean_t isv6,
kstat_named_t *kn;
boolean_t isloopback;
ipsq_t *old_ipsq;
+ in6_addr_t ov6addr;
isloopback = mi_strcmp(name, ipif_loopback_name) == 0;
@@ -5126,6 +5127,7 @@ ill_lookup_on_name(char *name, boolean_t do_alloc, boolean_t isv6,
ill->ill_flags = ILLF_MULTICAST;
+ ov6addr = ipif->ipif_v6lcl_addr;
/* Set up default loopback address and mask. */
if (!isv6) {
ipaddr_t inaddr_loopback = htonl(INADDR_LOOPBACK);
@@ -5164,8 +5166,13 @@ ill_lookup_on_name(char *name, boolean_t do_alloc, boolean_t isv6,
/* Let SCTP know so that it can add this to its list */
sctp_update_ill(ill, SCTP_ILL_INSERT);
- /* Let SCTP know about this IPIF, so that it can add it to its list */
- sctp_update_ipif(ipif, SCTP_IPIF_INSERT);
+ /*
+ * We have already assigned ipif_v6lcl_addr above, but we need to
+ * call sctp_update_ipif_addr() after SCTP_ILL_INSERT, which
+ * requires to be after ill_glist_insert() since we need the
+ * ill_index set. Pass on ipv6_loopback as the old address.
+ */
+ sctp_update_ipif_addr(ipif, ov6addr);
/*
* If the ipsq was changed in ill_phyint_reinit free the old ipsq.
@@ -11391,6 +11398,7 @@ ip_sioctl_addr_tail(ipif_t *ipif, sin_t *sin, queue_t *q, mblk_t *mp,
boolean_t need_up)
{
in6_addr_t v6addr;
+ in6_addr_t ov6addr;
ipaddr_t addr;
sin6_t *sin6;
int sinlen;
@@ -11421,7 +11429,9 @@ ip_sioctl_addr_tail(ipif_t *ipif, sin_t *sin, queue_t *q, mblk_t *mp,
sinlen = sizeof (struct sockaddr_in);
}
mutex_enter(&ill->ill_lock);
+ ov6addr = ipif->ipif_v6lcl_addr;
ipif->ipif_v6lcl_addr = v6addr;
+ sctp_update_ipif_addr(ipif, ov6addr);
if (ipif->ipif_flags & (IPIF_ANYCAST | IPIF_NOLOCAL)) {
ipif->ipif_v6src_addr = ipv6_all_zeros;
} else {
@@ -11536,12 +11546,6 @@ ip_sioctl_addr_tail(ipif_t *ipif, sin_t *sin, queue_t *q, mblk_t *mp,
* ip_rput_dlpi when we see the DL_BIND_ACK.
*/
err = ipif_up(ipif, q, mp);
- } else {
- /*
- * Update the IPIF list in SCTP, ipif_up_done() will do it
- * if need_up is true.
- */
- sctp_update_ipif(ipif, SCTP_IPIF_UPDATE);
}
if (need_dl_down)
@@ -12347,9 +12351,13 @@ ip_sioctl_flags_tail(ipif_t *ipif, uint64_t flags, queue_t *q, mblk_t *mp,
if (((turn_on | turn_off) & (PHYI_FAILED|PHYI_STANDBY|PHYI_OFFLINE)))
ip_redo_nomination(phyi);
- if (set_linklocal)
- (void) ipif_setlinklocal(ipif);
+ if (set_linklocal) {
+ in6_addr_t ov6addr;
+ ov6addr = ipif->ipif_v6lcl_addr;
+ (void) ipif_setlinklocal(ipif);
+ sctp_update_ipif_addr(ipif, ov6addr);
+ }
if (zero_source)
ipif->ipif_v6src_addr = ipv6_all_zeros;
else
@@ -12382,6 +12390,8 @@ ip_sioctl_flags_tail(ipif_t *ipif, uint64_t flags, queue_t *q, mblk_t *mp,
ip_rts_ifmsg(ipif);
}
}
+ /* Update the flags in SCTP's IPIF list */
+ sctp_update_ipif(ipif, SCTP_IPIF_UPDATE);
return (err);
}
@@ -13645,11 +13655,9 @@ ipif_allocate(ill_t *ill, int id, uint_t ire_type, boolean_t initialize)
id = ipif->ipif_id;
ASSERT(id >= 0);
- if (ill->ill_name[0] != '\0') {
+ if (ill->ill_name[0] != '\0')
ipif_assign_seqid(ipif);
- if (ill->ill_phyint->phyint_ifindex != 0)
- sctp_update_ipif(ipif, SCTP_IPIF_INSERT);
- }
+
/*
* Keep a copy of original id in ipif_orig_ipifid. Failback
* will attempt to restore the original id. The SIOCSLIFOINDEX
@@ -23267,9 +23275,6 @@ ipif_set_values(queue_t *q, mblk_t *mp, char *interf_name, uint_t *new_ppa_ptr)
/* Let SCTP know about this ILL */
sctp_update_ill(ill, SCTP_ILL_INSERT);
- /* and also about the first ipif */
- sctp_update_ipif(ipif, SCTP_IPIF_INSERT);
-
ipsq = ipsq_try_enter(NULL, ill, q, mp, ip_reprocess_ioctl, NEW_OP,
B_TRUE);
diff --git a/usr/src/uts/common/inet/ip/sadb.c b/usr/src/uts/common/inet/ip/sadb.c
index 70d1f1f23d..51e6be5278 100644
--- a/usr/src/uts/common/inet/ip/sadb.c
+++ b/usr/src/uts/common/inet/ip/sadb.c
@@ -5681,11 +5681,11 @@ ipsec_sctp_pol(ipsec_selector_t *sel, ipsec_policy_t **ppp,
IN6_IPADDR_TO_V4MAPPED(sel->ips_remote_addr_v4, &dst);
IN6_IPADDR_TO_V4MAPPED(sel->ips_local_addr_v4, &src);
- connp = sctp_find_conn(&dst, &src, ports, 0, ALL_ZONES,
+ connp = sctp_find_conn(&dst, &src, ports, ALL_ZONES,
ipst->ips_netstack->netstack_sctp);
} else {
connp = sctp_find_conn(&sel->ips_remote_addr_v6,
- &sel->ips_local_addr_v6, ports, 0, ALL_ZONES,
+ &sel->ips_local_addr_v6, ports, ALL_ZONES,
ipst->ips_netstack->netstack_sctp);
}
if (connp == NULL)
diff --git a/usr/src/uts/common/inet/sctp/sctp_addr.c b/usr/src/uts/common/inet/sctp/sctp_addr.c
index 946d85b3b1..d181162fd3 100644
--- a/usr/src/uts/common/inet/sctp/sctp_addr.c
+++ b/usr/src/uts/common/inet/sctp/sctp_addr.c
@@ -50,13 +50,13 @@
static void sctp_ipif_inactive(sctp_ipif_t *);
static sctp_ipif_t *sctp_lookup_ipif_addr(in6_addr_t *, boolean_t,
- sctp_t *, uint_t);
+ zoneid_t, boolean_t, uint_t, uint_t, boolean_t,
+ sctp_stack_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);
-sctp_saddr_ipif_t *sctp_ipif_lookup(sctp_t *, uint_t);
static int sctp_ipif_hash_insert(sctp_t *, sctp_ipif_t *, int,
- boolean_t dontsrc);
+ boolean_t, boolean_t);
static void sctp_ipif_hash_remove(sctp_t *, sctp_ipif_t *);
static int sctp_compare_ipif_list(sctp_ipif_hash_t *,
sctp_ipif_hash_t *);
@@ -76,6 +76,19 @@ int sctp_getmyaddrs(void *, void *, int *);
void sctp_saddr_init(sctp_stack_t *);
void sctp_saddr_fini(sctp_stack_t *);
+#define SCTP_ADDR4_HASH(addr) \
+ (((addr) ^ ((addr) >> 8) ^ ((addr) >> 16) ^ ((addr) >> 24)) & \
+ (SCTP_IPIF_HASH - 1))
+
+#define SCTP_ADDR6_HASH(addr) \
+ (((addr).s6_addr32[3] ^ \
+ (((addr).s6_addr32[3] ^ (addr).s6_addr32[2]) >> 12)) & \
+ (SCTP_IPIF_HASH - 1))
+
+#define SCTP_IPIF_ADDR_HASH(addr, isv6) \
+ ((isv6) ? SCTP_ADDR6_HASH((addr)) : \
+ SCTP_ADDR4_HASH((addr)._S6_un._S6_u32[3]))
+
#define SCTP_IPIF_USABLE(sctp_ipif_state) \
((sctp_ipif_state) == SCTP_IPIFS_UP || \
(sctp_ipif_state) == SCTP_IPIFS_DOWN)
@@ -98,27 +111,21 @@ void sctp_saddr_fini(sctp_stack_t *);
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)
/*
- *
- *
* SCTP Interface list manipulation functions, locking used.
- *
- *
*/
/*
* Delete an SCTP IPIF from the list if the refcount goes to 0 and it is
* marked as condemned. Also, check if the ILL needs to go away.
- * Called with no locks held.
*/
static void
sctp_ipif_inactive(sctp_ipif_t *sctp_ipif)
{
sctp_ill_t *sctp_ill;
- uint_t ipif_index;
+ uint_t hindex;
uint_t ill_index;
sctp_stack_t *sctps = sctp_ipif->sctp_ipif_ill->
sctp_ill_netstack->netstack_sctp;
@@ -126,7 +133,9 @@ sctp_ipif_inactive(sctp_ipif_t *sctp_ipif)
rw_enter(&sctps->sctps_g_ills_lock, RW_READER);
rw_enter(&sctps->sctps_g_ipifs_lock, RW_WRITER);
- ipif_index = SCTP_IPIF_HASH_FN(sctp_ipif->sctp_ipif_id);
+ hindex = SCTP_IPIF_ADDR_HASH(sctp_ipif->sctp_ipif_saddr,
+ sctp_ipif->sctp_ipif_isv6);
+
sctp_ill = sctp_ipif->sctp_ipif_ill;
ASSERT(sctp_ill != NULL);
ill_index = SCTP_ILL_HASH_FN(sctp_ill->sctp_ill_index);
@@ -136,9 +145,9 @@ sctp_ipif_inactive(sctp_ipif_t *sctp_ipif)
rw_exit(&sctps->sctps_g_ills_lock);
return;
}
- list_remove(&sctps->sctps_g_ipifs[ipif_index].sctp_ipif_list,
+ list_remove(&sctps->sctps_g_ipifs[hindex].sctp_ipif_list,
sctp_ipif);
- sctps->sctps_g_ipifs[ipif_index].ipif_count--;
+ sctps->sctps_g_ipifs[hindex].ipif_count--;
sctps->sctps_g_ipifs_count--;
rw_destroy(&sctp_ipif->sctp_ipif_lock);
kmem_free(sctp_ipif, sizeof (sctp_ipif_t));
@@ -163,41 +172,67 @@ sctp_ipif_inactive(sctp_ipif_t *sctp_ipif)
/*
* Lookup an SCTP IPIF given an IP address. Increments sctp_ipif refcnt.
- * Called with no locks held.
+ * We are either looking for a IPIF with the given address before
+ * inserting it into the global list or looking for an IPIF for an
+ * address given an SCTP. In the former case we always check the zoneid,
+ * but for the latter case, check_zid could be B_FALSE if the connp
+ * for the sctp has conn_all_zones set. When looking for an address we
+ * give preference to one that is up, so even though we may find one that
+ * is not up we keep looking if there is one up, we hold the down addr
+ * in backup_ipif in case we don't find one that is up - i.e. we return
+ * the backup_ipif in that case. Note that if we are looking for. If we
+ * are specifically looking for an up address, then usable will be set
+ * to true.
*/
static sctp_ipif_t *
-sctp_lookup_ipif_addr(in6_addr_t *addr, boolean_t refhold, sctp_t *sctp,
- uint_t ifindex)
+sctp_lookup_ipif_addr(in6_addr_t *addr, boolean_t refhold, zoneid_t zoneid,
+ boolean_t check_zid, uint_t ifindex, uint_t seqid, boolean_t usable,
+ sctp_stack_t *sctps)
{
- int i;
int j;
sctp_ipif_t *sctp_ipif;
- sctp_stack_t *sctps = sctp->sctp_sctps;
+ sctp_ipif_t *backup_ipif = NULL;
+ int hindex;
+
+ hindex = SCTP_IPIF_ADDR_HASH(*addr, !IN6_IS_ADDR_V4MAPPED(addr));
- ASSERT(sctp->sctp_zoneid != ALL_ZONES);
rw_enter(&sctps->sctps_g_ipifs_lock, RW_READER);
- for (i = 0; i < SCTP_IPIF_HASH; i++) {
- if (sctps->sctps_g_ipifs[i].ipif_count == 0)
- continue;
- sctp_ipif = list_head(&sctps->sctps_g_ipifs[i].sctp_ipif_list);
- for (j = 0; j < sctps->sctps_g_ipifs[i].ipif_count; j++) {
- rw_enter(&sctp_ipif->sctp_ipif_lock, RW_READER);
- 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) &&
- IN6_ARE_ADDR_EQUAL(&sctp_ipif->sctp_ipif_saddr,
- addr)) {
+ if (sctps->sctps_g_ipifs[hindex].ipif_count == 0) {
+ rw_exit(&sctps->sctps_g_ipifs_lock);
+ return (NULL);
+ }
+ sctp_ipif = list_head(&sctps->sctps_g_ipifs[hindex].sctp_ipif_list);
+ for (j = 0; j < sctps->sctps_g_ipifs[hindex].ipif_count; j++) {
+ rw_enter(&sctp_ipif->sctp_ipif_lock, RW_READER);
+ if ((!check_zid ||
+ (sctp_ipif->sctp_ipif_zoneid == ALL_ZONES ||
+ zoneid == sctp_ipif->sctp_ipif_zoneid)) &&
+ (ifindex == 0 || ifindex ==
+ sctp_ipif->sctp_ipif_ill->sctp_ill_index) &&
+ ((seqid != 0 && seqid == sctp_ipif->sctp_ipif_id) ||
+ (IN6_ARE_ADDR_EQUAL(&sctp_ipif->sctp_ipif_saddr,
+ addr)))) {
+ if (!usable || sctp_ipif->sctp_ipif_state ==
+ SCTP_IPIFS_UP) {
rw_exit(&sctp_ipif->sctp_ipif_lock);
if (refhold)
SCTP_IPIF_REFHOLD(sctp_ipif);
rw_exit(&sctps->sctps_g_ipifs_lock);
return (sctp_ipif);
+ } else if (sctp_ipif->sctp_ipif_state ==
+ SCTP_IPIFS_DOWN && backup_ipif == NULL) {
+ backup_ipif = sctp_ipif;
}
- rw_exit(&sctp_ipif->sctp_ipif_lock);
- sctp_ipif = list_next(
- &sctps->sctps_g_ipifs[i].sctp_ipif_list, sctp_ipif);
}
+ rw_exit(&sctp_ipif->sctp_ipif_lock);
+ sctp_ipif = list_next(
+ &sctps->sctps_g_ipifs[hindex].sctp_ipif_list, sctp_ipif);
+ }
+ if (backup_ipif != NULL) {
+ if (refhold)
+ SCTP_IPIF_REFHOLD(backup_ipif);
+ rw_exit(&sctps->sctps_g_ipifs_lock);
+ return (backup_ipif);
}
rw_exit(&sctps->sctps_g_ipifs_lock);
return (NULL);
@@ -240,8 +275,8 @@ sctp_get_all_ipifs(sctp_t *sctp, int sleep)
rw_exit(&sctp_ipif->sctp_ipif_lock);
SCTP_IPIF_REFHOLD(sctp_ipif);
error = sctp_ipif_hash_insert(sctp, sctp_ipif, sleep,
- B_FALSE);
- if (error != 0)
+ B_FALSE, B_FALSE);
+ if (error != 0 && error != EALREADY)
goto free_stuff;
sctp_ipif = list_next(
&sctps->sctps_g_ipifs[i].sctp_ipif_list,
@@ -360,8 +395,9 @@ 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,
- ifindex);
+ ipif = sctp_lookup_ipif_addr(&addr, B_TRUE,
+ sctp->sctp_zoneid, !sctp->sctp_connp->conn_allzones,
+ ifindex, 0, B_TRUE, sctp->sctp_sctps);
if (ipif == NULL) {
/* Address not in the list */
err = EINVAL;
@@ -382,7 +418,7 @@ sctp_valid_addr_list(sctp_t *sctp, const void *addrs, uint32_t addrcnt,
* get the ASCONF ACK for this address.
*/
err = sctp_ipif_hash_insert(sctp, ipif, KM_SLEEP,
- check_addrs ? B_TRUE : B_FALSE);
+ check_addrs ? B_TRUE : B_FALSE, B_FALSE);
if (err != 0) {
SCTP_IPIF_REFRELE(ipif);
if (check_addrs && err == EALREADY)
@@ -426,39 +462,35 @@ free_ret:
return (err);
}
-sctp_saddr_ipif_t *
-sctp_ipif_lookup(sctp_t *sctp, uint_t ipif_index)
-{
- int cnt;
- int seqid = SCTP_IPIF_HASH_FN(ipif_index);
- sctp_saddr_ipif_t *ipif_obj;
-
- if (sctp->sctp_saddrs[seqid].ipif_count == 0)
- return (NULL);
-
- ipif_obj = list_head(&sctp->sctp_saddrs[seqid].sctp_ipif_list);
- for (cnt = 0; cnt < sctp->sctp_saddrs[seqid].ipif_count; cnt++) {
- if (ipif_obj->saddr_ipifp->sctp_ipif_id == ipif_index)
- return (ipif_obj);
- ipif_obj = list_next(&sctp->sctp_saddrs[seqid].sctp_ipif_list,
- ipif_obj);
- }
- return (NULL);
-}
-
static int
sctp_ipif_hash_insert(sctp_t *sctp, sctp_ipif_t *ipif, int sleep,
- boolean_t dontsrc)
+ boolean_t dontsrc, boolean_t allow_dup)
{
int cnt;
sctp_saddr_ipif_t *ipif_obj;
- int seqid = SCTP_IPIF_HASH_FN(ipif->sctp_ipif_id);
-
- ipif_obj = list_head(&sctp->sctp_saddrs[seqid].sctp_ipif_list);
- for (cnt = 0; cnt < sctp->sctp_saddrs[seqid].ipif_count; cnt++) {
- if (ipif_obj->saddr_ipifp->sctp_ipif_id == ipif->sctp_ipif_id)
- return (EALREADY);
- ipif_obj = list_next(&sctp->sctp_saddrs[seqid].sctp_ipif_list,
+ int hindex;
+
+ hindex = SCTP_IPIF_ADDR_HASH(ipif->sctp_ipif_saddr,
+ ipif->sctp_ipif_isv6);
+ ipif_obj = list_head(&sctp->sctp_saddrs[hindex].sctp_ipif_list);
+ for (cnt = 0; cnt < sctp->sctp_saddrs[hindex].ipif_count; cnt++) {
+ if (IN6_ARE_ADDR_EQUAL(&ipif_obj->saddr_ipifp->sctp_ipif_saddr,
+ &ipif->sctp_ipif_saddr)) {
+ if (ipif->sctp_ipif_id !=
+ ipif_obj->saddr_ipifp->sctp_ipif_id &&
+ ipif_obj->saddr_ipifp->sctp_ipif_state ==
+ SCTP_IPIFS_DOWN && ipif->sctp_ipif_state ==
+ SCTP_IPIFS_UP) {
+ SCTP_IPIF_REFRELE(ipif_obj->saddr_ipifp);
+ ipif_obj->saddr_ipifp = ipif;
+ ipif_obj->saddr_ipif_dontsrc = dontsrc ? 1 : 0;
+ return (0);
+ } else if (!allow_dup || ipif->sctp_ipif_id ==
+ ipif_obj->saddr_ipifp->sctp_ipif_id) {
+ return (EALREADY);
+ }
+ }
+ ipif_obj = list_next(&sctp->sctp_saddrs[hindex].sctp_ipif_list,
ipif_obj);
}
ipif_obj = kmem_zalloc(sizeof (sctp_saddr_ipif_t), sleep);
@@ -468,8 +500,8 @@ sctp_ipif_hash_insert(sctp_t *sctp, sctp_ipif_t *ipif, int sleep,
}
ipif_obj->saddr_ipifp = ipif;
ipif_obj->saddr_ipif_dontsrc = dontsrc ? 1 : 0;
- list_insert_tail(&sctp->sctp_saddrs[seqid].sctp_ipif_list, ipif_obj);
- sctp->sctp_saddrs[seqid].ipif_count++;
+ list_insert_tail(&sctp->sctp_saddrs[hindex].sctp_ipif_list, ipif_obj);
+ sctp->sctp_saddrs[hindex].ipif_count++;
sctp->sctp_nsaddrs++;
return (0);
}
@@ -479,20 +511,23 @@ sctp_ipif_hash_remove(sctp_t *sctp, sctp_ipif_t *ipif)
{
int cnt;
sctp_saddr_ipif_t *ipif_obj;
- int seqid = SCTP_IPIF_HASH_FN(ipif->sctp_ipif_id);
-
- ipif_obj = list_head(&sctp->sctp_saddrs[seqid].sctp_ipif_list);
- for (cnt = 0; cnt < sctp->sctp_saddrs[seqid].ipif_count; cnt++) {
- if (ipif_obj->saddr_ipifp->sctp_ipif_id == ipif->sctp_ipif_id) {
- list_remove(&sctp->sctp_saddrs[seqid].sctp_ipif_list,
+ int hindex;
+
+ hindex = SCTP_IPIF_ADDR_HASH(ipif->sctp_ipif_saddr,
+ ipif->sctp_ipif_isv6);
+ ipif_obj = list_head(&sctp->sctp_saddrs[hindex].sctp_ipif_list);
+ for (cnt = 0; cnt < sctp->sctp_saddrs[hindex].ipif_count; cnt++) {
+ if (IN6_ARE_ADDR_EQUAL(&ipif_obj->saddr_ipifp->sctp_ipif_saddr,
+ &ipif->sctp_ipif_saddr)) {
+ list_remove(&sctp->sctp_saddrs[hindex].sctp_ipif_list,
ipif_obj);
+ sctp->sctp_saddrs[hindex].ipif_count--;
sctp->sctp_nsaddrs--;
- sctp->sctp_saddrs[seqid].ipif_count--;
SCTP_IPIF_REFRELE(ipif_obj->saddr_ipifp);
kmem_free(ipif_obj, sizeof (sctp_saddr_ipif_t));
break;
}
- ipif_obj = list_next(&sctp->sctp_saddrs[seqid].sctp_ipif_list,
+ ipif_obj = list_next(&sctp->sctp_saddrs[hindex].sctp_ipif_list,
ipif_obj);
}
}
@@ -510,8 +545,9 @@ sctp_compare_ipif_list(sctp_ipif_hash_t *list1, sctp_ipif_hash_t *list2)
for (i = 0; i < list1->ipif_count; i++) {
obj2 = list_head(&list2->sctp_ipif_list);
for (j = 0; j < list2->ipif_count; j++) {
- if (obj1->saddr_ipifp->sctp_ipif_id ==
- obj2->saddr_ipifp->sctp_ipif_id) {
+ if (IN6_ARE_ADDR_EQUAL(
+ &obj1->saddr_ipifp->sctp_ipif_saddr,
+ &obj2->saddr_ipifp->sctp_ipif_saddr)) {
overlap++;
break;
}
@@ -559,7 +595,8 @@ sctp_copy_ipifs(sctp_ipif_hash_t *list1, sctp_t *sctp2, int sleep)
for (i = 0; i < list1->ipif_count; i++) {
SCTP_IPIF_REFHOLD(obj->saddr_ipifp);
error = sctp_ipif_hash_insert(sctp2, obj->saddr_ipifp, sleep,
- B_FALSE);
+ B_FALSE, B_FALSE);
+ ASSERT(error != EALREADY);
if (error != 0)
return (error);
obj = list_next(&list1->sctp_ipif_list, obj);
@@ -628,8 +665,6 @@ sctp_update_ill(ill_t *ill, int op)
netstack_t *ns = ill->ill_ipst->ips_netstack;
sctp_stack_t *sctps = ns->netstack_sctp;
- ip2dbg(("sctp_update_ill: %s\n", ill->ill_name));
-
rw_enter(&sctps->sctps_g_ills_lock, RW_WRITER);
index = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(ill));
@@ -657,8 +692,8 @@ sctp_update_ill(ill_t *ill, int op)
rw_exit(&sctps->sctps_g_ills_lock);
return;
}
- sctp_ill->sctp_ill_name =
- kmem_zalloc(ill->ill_name_length, KM_NOSLEEP);
+ sctp_ill->sctp_ill_name = kmem_zalloc(ill->ill_name_length,
+ KM_NOSLEEP);
if (sctp_ill->sctp_ill_name == NULL) {
ip1dbg(("sctp_ill_insert: mem error..\n"));
kmem_free(sctp_ill, sizeof (sctp_ill_t));
@@ -708,7 +743,7 @@ sctp_move_ipif(ipif_t *ipif, ill_t *f_ill, ill_t *t_ill)
sctp_ill_t *fsctp_ill = NULL;
sctp_ill_t *tsctp_ill = NULL;
sctp_ipif_t *sctp_ipif;
- uint_t index;
+ uint_t hindex;
int i;
netstack_t *ns = ipif->ipif_ill->ill_ipst->ips_netstack;
sctp_stack_t *sctps = ns->netstack_sctp;
@@ -716,31 +751,32 @@ sctp_move_ipif(ipif_t *ipif, ill_t *f_ill, ill_t *t_ill)
rw_enter(&sctps->sctps_g_ills_lock, RW_READER);
rw_enter(&sctps->sctps_g_ipifs_lock, RW_READER);
- index = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(f_ill));
- fsctp_ill = list_head(&sctps->sctps_g_ills[index].sctp_ill_list);
- for (i = 0; i < sctps->sctps_g_ills[index].ill_count; i++) {
+ hindex = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(f_ill));
+ fsctp_ill = list_head(&sctps->sctps_g_ills[hindex].sctp_ill_list);
+ for (i = 0; i < sctps->sctps_g_ills[hindex].ill_count; i++) {
if (fsctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(f_ill))
break;
- fsctp_ill = list_next(&sctps->sctps_g_ills[index].sctp_ill_list,
- fsctp_ill);
+ fsctp_ill = list_next(
+ &sctps->sctps_g_ills[hindex].sctp_ill_list, fsctp_ill);
}
- index = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(t_ill));
- tsctp_ill = list_head(&sctps->sctps_g_ills[index].sctp_ill_list);
- for (i = 0; i < sctps->sctps_g_ills[index].ill_count; i++) {
+ hindex = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(t_ill));
+ tsctp_ill = list_head(&sctps->sctps_g_ills[hindex].sctp_ill_list);
+ for (i = 0; i < sctps->sctps_g_ills[hindex].ill_count; i++) {
if (tsctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(t_ill))
break;
- tsctp_ill = list_next(&sctps->sctps_g_ills[index].sctp_ill_list,
- tsctp_ill);
+ tsctp_ill = list_next(
+ &sctps->sctps_g_ills[hindex].sctp_ill_list, tsctp_ill);
}
- index = SCTP_IPIF_HASH_FN(ipif->ipif_seqid);
- sctp_ipif = list_head(&sctps->sctps_g_ipifs[index].sctp_ipif_list);
- for (i = 0; i < sctps->sctps_g_ipifs[index].ipif_count; i++) {
+ hindex = SCTP_IPIF_ADDR_HASH(ipif->ipif_v6lcl_addr,
+ ipif->ipif_ill->ill_isv6);
+ sctp_ipif = list_head(&sctps->sctps_g_ipifs[hindex].sctp_ipif_list);
+ for (i = 0; i < sctps->sctps_g_ipifs[hindex].ipif_count; i++) {
if (sctp_ipif->sctp_ipif_id == ipif->ipif_seqid)
break;
sctp_ipif = list_next(
- &sctps->sctps_g_ipifs[index].sctp_ipif_list, sctp_ipif);
+ &sctps->sctps_g_ipifs[hindex].sctp_ipif_list, sctp_ipif);
}
/* Should be an ASSERT? */
if (fsctp_ill == NULL || tsctp_ill == NULL || sctp_ipif == NULL) {
@@ -760,6 +796,246 @@ sctp_move_ipif(ipif_t *ipif, ill_t *f_ill, ill_t *t_ill)
rw_exit(&sctps->sctps_g_ills_lock);
}
+/*
+ * Walk the list of SCTPs and find each that has oipif in it's saddr list, and
+ * if so replace it with nipif.
+ */
+void
+sctp_update_saddrs(sctp_ipif_t *oipif, sctp_ipif_t *nipif, int idx,
+ sctp_stack_t *sctps)
+{
+ sctp_t *sctp;
+ sctp_t *sctp_prev = NULL;
+ sctp_saddr_ipif_t *sobj;
+ int count;
+
+ sctp = sctps->sctps_gsctp;
+ mutex_enter(&sctps->sctps_g_lock);
+ while (sctp != NULL && oipif->sctp_ipif_refcnt > 0) {
+ mutex_enter(&sctp->sctp_reflock);
+ if (sctp->sctp_condemned ||
+ sctp->sctp_saddrs[idx].ipif_count <= 0) {
+ mutex_exit(&sctp->sctp_reflock);
+ sctp = list_next(&sctps->sctps_g_list, sctp);
+ continue;
+ }
+ sctp->sctp_refcnt++;
+ mutex_exit(&sctp->sctp_reflock);
+ mutex_exit(&sctps->sctps_g_lock);
+ if (sctp_prev != NULL)
+ SCTP_REFRELE(sctp_prev);
+
+ RUN_SCTP(sctp);
+ sobj = list_head(&sctp->sctp_saddrs[idx].sctp_ipif_list);
+ for (count = 0; count <
+ sctp->sctp_saddrs[idx].ipif_count; count++) {
+ if (sobj->saddr_ipifp == oipif) {
+ SCTP_IPIF_REFHOLD(nipif);
+ sobj->saddr_ipifp = nipif;
+ ASSERT(oipif->sctp_ipif_refcnt > 0);
+ /* We have the writer lock */
+ oipif->sctp_ipif_refcnt--;
+ /*
+ * Can't have more than one referring
+ * to the same sctp_ipif.
+ */
+ break;
+ }
+ sobj = list_next(&sctp->sctp_saddrs[idx].sctp_ipif_list,
+ sobj);
+ }
+ WAKE_SCTP(sctp);
+ sctp_prev = sctp;
+ mutex_enter(&sctps->sctps_g_lock);
+ sctp = list_next(&sctps->sctps_g_list, sctp);
+ }
+ mutex_exit(&sctps->sctps_g_lock);
+ if (sctp_prev != NULL)
+ SCTP_REFRELE(sctp_prev);
+}
+
+/*
+ * Given an ipif, walk the hash list in the global ipif table and for
+ * any other SCTP ipif with the same address and non-zero reference, walk
+ * the SCTP list and update the saddr list, if required, to point to the
+ * new SCTP ipif.
+ */
+void
+sctp_chk_and_updt_saddr(int hindex, sctp_ipif_t *ipif, sctp_stack_t *sctps)
+{
+ int cnt;
+ sctp_ipif_t *sipif;
+
+ ASSERT(sctps->sctps_g_ipifs[hindex].ipif_count > 0);
+ ASSERT(ipif->sctp_ipif_state == SCTP_IPIFS_UP);
+
+ sipif = list_head(&sctps->sctps_g_ipifs[hindex].sctp_ipif_list);
+ for (cnt = 0; cnt < sctps->sctps_g_ipifs[hindex].ipif_count; cnt++) {
+ rw_enter(&sipif->sctp_ipif_lock, RW_WRITER);
+ if (sipif->sctp_ipif_id != ipif->sctp_ipif_id &&
+ IN6_ARE_ADDR_EQUAL(&sipif->sctp_ipif_saddr,
+ &ipif->sctp_ipif_saddr) && sipif->sctp_ipif_refcnt > 0) {
+ /*
+ * There can only be one address up at any time
+ * and we are here because ipif has been brought
+ * up.
+ */
+ ASSERT(sipif->sctp_ipif_state != SCTP_IPIFS_UP);
+ /*
+ * Someone has a reference to this we need to update to
+ * point to the new sipif.
+ */
+ sctp_update_saddrs(sipif, ipif, hindex, sctps);
+ }
+ rw_exit(&sipif->sctp_ipif_lock);
+ sipif = list_next(&sctps->sctps_g_ipifs[hindex].sctp_ipif_list,
+ sipif);
+ }
+}
+
+/*
+ * Insert a new SCTP ipif using 'ipif'. v6addr is the address that existed
+ * prior to the current address in 'ipif'. Only when an existing address
+ * is changed on an IPIF, will v6addr be specified. If the IPIF already
+ * exists in the global SCTP ipif table, then we either removed it, if
+ * it doesn't have any existing reference, or mark it condemned otherwise.
+ * If an address is being brought up (IPIF_UP), then we need to scan
+ * the SCTP list to check if there is any SCTP that points to the *same*
+ * address on a different SCTP ipif and update in that case.
+ */
+void
+sctp_update_ipif_addr(ipif_t *ipif, in6_addr_t v6addr)
+{
+ ill_t *ill = ipif->ipif_ill;
+ int i;
+ sctp_ill_t *sctp_ill;
+ sctp_ill_t *osctp_ill;
+ sctp_ipif_t *sctp_ipif = NULL;
+ sctp_ipif_t *osctp_ipif = NULL;
+ uint_t ill_index;
+ int hindex;
+ sctp_stack_t *sctps;
+
+
+ sctps = ipif->ipif_ill->ill_ipst->ips_netstack->netstack_sctp;
+
+ /* Index for new address */
+ hindex = SCTP_IPIF_ADDR_HASH(ipif->ipif_v6lcl_addr, ill->ill_isv6);
+
+ /*
+ * The address on this IPIF is changing, we need to look for
+ * this old address and mark it condemned, before creating
+ * one for the new address.
+ */
+ osctp_ipif = sctp_lookup_ipif_addr(&v6addr, B_FALSE,
+ ipif->ipif_zoneid, B_TRUE, SCTP_ILL_TO_PHYINDEX(ill),
+ ipif->ipif_seqid, B_FALSE, sctps);
+
+ rw_enter(&sctps->sctps_g_ills_lock, RW_READER);
+ rw_enter(&sctps->sctps_g_ipifs_lock, RW_WRITER);
+
+ ill_index = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(ill));
+ sctp_ill = list_head(&sctps->sctps_g_ills[ill_index].sctp_ill_list);
+ for (i = 0; i < sctps->sctps_g_ills[ill_index].ill_count; i++) {
+ if (sctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(ill))
+ break;
+ sctp_ill = list_next(
+ &sctps->sctps_g_ills[ill_index].sctp_ill_list, sctp_ill);
+ }
+
+ if (sctp_ill == NULL) {
+ ip1dbg(("sctp_ipif_insert: ill not found ..\n"));
+ rw_exit(&sctps->sctps_g_ipifs_lock);
+ rw_exit(&sctps->sctps_g_ills_lock);
+ }
+
+ if (osctp_ipif != NULL) {
+
+ /* The address is the same? */
+ if (IN6_ARE_ADDR_EQUAL(&ipif->ipif_v6lcl_addr, &v6addr)) {
+ boolean_t chk_n_updt = B_FALSE;
+
+ rw_downgrade(&sctps->sctps_g_ipifs_lock);
+ rw_enter(&osctp_ipif->sctp_ipif_lock, RW_WRITER);
+ if (ipif->ipif_flags & IPIF_UP &&
+ osctp_ipif->sctp_ipif_state != SCTP_IPIFS_UP) {
+ osctp_ipif->sctp_ipif_state = SCTP_IPIFS_UP;
+ chk_n_updt = B_TRUE;
+ } else {
+ osctp_ipif->sctp_ipif_state = SCTP_IPIFS_DOWN;
+ }
+ osctp_ipif->sctp_ipif_flags = ipif->ipif_flags;
+ rw_exit(&osctp_ipif->sctp_ipif_lock);
+ if (chk_n_updt) {
+ sctp_chk_and_updt_saddr(hindex, osctp_ipif,
+ sctps);
+ }
+ rw_exit(&sctps->sctps_g_ipifs_lock);
+ rw_exit(&sctps->sctps_g_ills_lock);
+ return;
+ }
+ /*
+ * We are effectively removing this address from the ILL.
+ */
+ if (osctp_ipif->sctp_ipif_refcnt != 0) {
+ osctp_ipif->sctp_ipif_state = SCTP_IPIFS_CONDEMNED;
+ } else {
+ list_t *ipif_list;
+ int ohindex;
+
+ osctp_ill = osctp_ipif->sctp_ipif_ill;
+ /* hash index for the old one */
+ ohindex = SCTP_IPIF_ADDR_HASH(
+ osctp_ipif->sctp_ipif_saddr,
+ osctp_ipif->sctp_ipif_isv6);
+
+ ipif_list =
+ &sctps->sctps_g_ipifs[ohindex].sctp_ipif_list;
+
+ list_remove(ipif_list, (void *)osctp_ipif);
+ sctps->sctps_g_ipifs[ohindex].ipif_count--;
+ sctps->sctps_g_ipifs_count--;
+ rw_destroy(&osctp_ipif->sctp_ipif_lock);
+ kmem_free(osctp_ipif, sizeof (sctp_ipif_t));
+ (void) atomic_add_32_nv(&osctp_ill->sctp_ill_ipifcnt,
+ -1);
+ }
+ }
+
+ sctp_ipif = kmem_zalloc(sizeof (sctp_ipif_t), KM_NOSLEEP);
+ /* Try again? */
+ if (sctp_ipif == NULL) {
+ ip1dbg(("sctp_ipif_insert: mem failure..\n"));
+ rw_exit(&sctps->sctps_g_ipifs_lock);
+ rw_exit(&sctps->sctps_g_ills_lock);
+ return;
+ }
+ sctps->sctps_g_ipifs_count++;
+ rw_init(&sctp_ipif->sctp_ipif_lock, NULL, RW_DEFAULT, NULL);
+ sctp_ipif->sctp_ipif_saddr = ipif->ipif_v6lcl_addr;
+ sctp_ipif->sctp_ipif_ill = sctp_ill;
+ sctp_ipif->sctp_ipif_isv6 = ill->ill_isv6;
+ sctp_ipif->sctp_ipif_zoneid = ipif->ipif_zoneid;
+ sctp_ipif->sctp_ipif_id = ipif->ipif_seqid;
+ if (ipif->ipif_flags & IPIF_UP)
+ sctp_ipif->sctp_ipif_state = SCTP_IPIFS_UP;
+ else
+ sctp_ipif->sctp_ipif_state = SCTP_IPIFS_DOWN;
+ sctp_ipif->sctp_ipif_flags = ipif->ipif_flags;
+ /*
+ * We add it to the head so that it is quicker to find good/recent
+ * additions.
+ */
+ list_insert_head(&sctps->sctps_g_ipifs[hindex].sctp_ipif_list,
+ (void *)sctp_ipif);
+ sctps->sctps_g_ipifs[hindex].ipif_count++;
+ atomic_add_32(&sctp_ill->sctp_ill_ipifcnt, 1);
+ if (sctp_ipif->sctp_ipif_state == SCTP_IPIFS_UP)
+ sctp_chk_and_updt_saddr(hindex, sctp_ipif, sctps);
+ rw_exit(&sctps->sctps_g_ipifs_lock);
+ rw_exit(&sctps->sctps_g_ills_lock);
+}
+
/* Insert, Remove, Mark up or Mark down the ipif */
void
sctp_update_ipif(ipif_t *ipif, int op)
@@ -769,7 +1045,7 @@ sctp_update_ipif(ipif_t *ipif, int op)
sctp_ill_t *sctp_ill;
sctp_ipif_t *sctp_ipif;
uint_t ill_index;
- uint_t ipif_index;
+ uint_t hindex;
netstack_t *ns = ipif->ipif_ill->ill_ipst->ips_netstack;
sctp_stack_t *sctps = ns->netstack_sctp;
@@ -792,66 +1068,34 @@ sctp_update_ipif(ipif_t *ipif, int op)
return;
}
- ipif_index = SCTP_IPIF_HASH_FN(ipif->ipif_seqid);
- sctp_ipif = list_head(&sctps->sctps_g_ipifs[ipif_index].sctp_ipif_list);
- for (i = 0; i < sctps->sctps_g_ipifs[ipif_index].ipif_count; i++) {
- if (sctp_ipif->sctp_ipif_id == ipif->ipif_seqid)
+ hindex = SCTP_IPIF_ADDR_HASH(ipif->ipif_v6lcl_addr,
+ ipif->ipif_ill->ill_isv6);
+ sctp_ipif = list_head(&sctps->sctps_g_ipifs[hindex].sctp_ipif_list);
+ for (i = 0; i < sctps->sctps_g_ipifs[hindex].ipif_count; i++) {
+ if (sctp_ipif->sctp_ipif_id == ipif->ipif_seqid) {
+ ASSERT(IN6_ARE_ADDR_EQUAL(&sctp_ipif->sctp_ipif_saddr,
+ &ipif->ipif_v6lcl_addr));
break;
+ }
sctp_ipif = list_next(
- &sctps->sctps_g_ipifs[ipif_index].sctp_ipif_list,
+ &sctps->sctps_g_ipifs[hindex].sctp_ipif_list,
sctp_ipif);
}
- if (op != SCTP_IPIF_INSERT && sctp_ipif == NULL) {
+ if (sctp_ipif == NULL) {
ip1dbg(("sctp_update_ipif: null sctp_ipif for %d\n", op));
rw_exit(&sctps->sctps_g_ipifs_lock);
rw_exit(&sctps->sctps_g_ills_lock);
return;
}
-#ifdef DEBUG
- if (sctp_ipif != NULL)
- ASSERT(sctp_ill == sctp_ipif->sctp_ipif_ill);
-#endif
+ ASSERT(sctp_ill == sctp_ipif->sctp_ipif_ill);
switch (op) {
- case SCTP_IPIF_INSERT:
- if (sctp_ipif != NULL) {
- if (sctp_ipif->sctp_ipif_state == SCTP_IPIFS_CONDEMNED)
- sctp_ipif->sctp_ipif_state = SCTP_IPIFS_INVALID;
- rw_exit(&sctps->sctps_g_ipifs_lock);
- rw_exit(&sctps->sctps_g_ills_lock);
- return;
- }
- sctp_ipif = kmem_zalloc(sizeof (sctp_ipif_t), KM_NOSLEEP);
- /* Try again? */
- if (sctp_ipif == NULL) {
- ip1dbg(("sctp_ipif_insert: mem failure..\n"));
- rw_exit(&sctps->sctps_g_ipifs_lock);
- rw_exit(&sctps->sctps_g_ills_lock);
- return;
- }
- sctp_ipif->sctp_ipif_id = ipif->ipif_seqid;
- sctp_ipif->sctp_ipif_ill = sctp_ill;
- sctp_ipif->sctp_ipif_state = SCTP_IPIFS_INVALID;
- sctp_ipif->sctp_ipif_mtu = ipif->ipif_mtu;
- sctp_ipif->sctp_ipif_zoneid = ipif->ipif_zoneid;
- sctp_ipif->sctp_ipif_isv6 = ill->ill_isv6;
- sctp_ipif->sctp_ipif_flags = ipif->ipif_flags;
- rw_init(&sctp_ipif->sctp_ipif_lock, NULL, RW_DEFAULT, NULL);
- list_insert_tail(
- &sctps->sctps_g_ipifs[ipif_index].sctp_ipif_list,
- (void *)sctp_ipif);
- sctps->sctps_g_ipifs[ipif_index].ipif_count++;
- sctps->sctps_g_ipifs_count++;
- atomic_add_32(&sctp_ill->sctp_ill_ipifcnt, 1);
-
- break;
-
case SCTP_IPIF_REMOVE:
{
list_t *ipif_list;
list_t *ill_list;
ill_list = &sctps->sctps_g_ills[ill_index].sctp_ill_list;
- ipif_list = &sctps->sctps_g_ipifs[ipif_index].sctp_ipif_list;
+ ipif_list = &sctps->sctps_g_ipifs[hindex].sctp_ipif_list;
if (sctp_ipif->sctp_ipif_refcnt != 0) {
sctp_ipif->sctp_ipif_state = SCTP_IPIFS_CONDEMNED;
rw_exit(&sctps->sctps_g_ipifs_lock);
@@ -859,7 +1103,7 @@ sctp_update_ipif(ipif_t *ipif, int op)
return;
}
list_remove(ipif_list, (void *)sctp_ipif);
- sctps->sctps_g_ipifs[ipif_index].ipif_count--;
+ sctps->sctps_g_ipifs[hindex].ipif_count--;
sctps->sctps_g_ipifs_count--;
rw_destroy(&sctp_ipif->sctp_ipif_lock);
kmem_free(sctp_ipif, sizeof (sctp_ipif_t));
@@ -884,10 +1128,11 @@ sctp_update_ipif(ipif_t *ipif, int op)
rw_downgrade(&sctps->sctps_g_ipifs_lock);
rw_enter(&sctp_ipif->sctp_ipif_lock, RW_WRITER);
sctp_ipif->sctp_ipif_state = SCTP_IPIFS_UP;
- sctp_ipif->sctp_ipif_saddr = ipif->ipif_v6lcl_addr;
- sctp_ipif->sctp_ipif_flags = ipif->ipif_flags;
sctp_ipif->sctp_ipif_mtu = ipif->ipif_mtu;
+ sctp_ipif->sctp_ipif_flags = ipif->ipif_flags;
rw_exit(&sctp_ipif->sctp_ipif_lock);
+ sctp_chk_and_updt_saddr(hindex, sctp_ipif,
+ ipif->ipif_ill->ill_ipst->ips_netstack->netstack_sctp);
break;
@@ -896,7 +1141,6 @@ sctp_update_ipif(ipif_t *ipif, int op)
rw_downgrade(&sctps->sctps_g_ipifs_lock);
rw_enter(&sctp_ipif->sctp_ipif_lock, RW_WRITER);
sctp_ipif->sctp_ipif_mtu = ipif->ipif_mtu;
- sctp_ipif->sctp_ipif_saddr = ipif->ipif_v6lcl_addr;
sctp_ipif->sctp_ipif_zoneid = ipif->ipif_zoneid;
sctp_ipif->sctp_ipif_flags = ipif->ipif_flags;
rw_exit(&sctp_ipif->sctp_ipif_lock);
@@ -908,6 +1152,8 @@ sctp_update_ipif(ipif_t *ipif, int op)
rw_downgrade(&sctps->sctps_g_ipifs_lock);
rw_enter(&sctp_ipif->sctp_ipif_lock, RW_WRITER);
sctp_ipif->sctp_ipif_state = SCTP_IPIFS_DOWN;
+ sctp_ipif->sctp_ipif_mtu = ipif->ipif_mtu;
+ sctp_ipif->sctp_ipif_flags = ipif->ipif_flags;
rw_exit(&sctp_ipif->sctp_ipif_lock);
break;
@@ -917,12 +1163,8 @@ sctp_update_ipif(ipif_t *ipif, int op)
}
/*
- *
- *
* SCTP source address list manipulaton, locking not used (except for
* sctp locking by the caller.
- *
- *
*/
/* Remove a specific saddr from the list */
@@ -984,8 +1226,9 @@ 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,
- ifindex);
+ sctp_ipif = sctp_lookup_ipif_addr(&addr, B_FALSE,
+ sctp->sctp_zoneid, !sctp->sctp_connp->conn_allzones,
+ ifindex, 0, B_TRUE, sctp->sctp_sctps);
ASSERT(sctp_ipif != NULL);
sctp_ipif_hash_remove(sctp, sctp_ipif);
}
@@ -1007,15 +1250,31 @@ sctp_del_saddr_list(sctp_t *sctp, const void *addrs, int addcnt,
sctp_saddr_ipif_t *
sctp_saddr_lookup(sctp_t *sctp, in6_addr_t *addr, uint_t ifindex)
{
- sctp_saddr_ipif_t *saddr_ipifs;
+ int cnt;
+ sctp_saddr_ipif_t *ipif_obj;
+ int hindex;
sctp_ipif_t *sctp_ipif;
- sctp_ipif = sctp_lookup_ipif_addr(addr, B_FALSE, sctp, ifindex);
- if (sctp_ipif == NULL)
+ hindex = SCTP_IPIF_ADDR_HASH(*addr, !IN6_IS_ADDR_V4MAPPED(addr));
+ if (sctp->sctp_saddrs[hindex].ipif_count == 0)
return (NULL);
- saddr_ipifs = sctp_ipif_lookup(sctp, sctp_ipif->sctp_ipif_id);
- return (saddr_ipifs);
+ ipif_obj = list_head(&sctp->sctp_saddrs[hindex].sctp_ipif_list);
+ for (cnt = 0; cnt < sctp->sctp_saddrs[hindex].ipif_count; cnt++) {
+ sctp_ipif = ipif_obj->saddr_ipifp;
+ /*
+ * Zone check shouldn't be needed.
+ */
+ if (IN6_ARE_ADDR_EQUAL(addr, &sctp_ipif->sctp_ipif_saddr) &&
+ (ifindex == 0 ||
+ ifindex == sctp_ipif->sctp_ipif_ill->sctp_ill_index) &&
+ SCTP_IPIF_USABLE(sctp_ipif->sctp_ipif_state)) {
+ return (ipif_obj);
+ }
+ ipif_obj = list_next(&sctp->sctp_saddrs[hindex].sctp_ipif_list,
+ ipif_obj);
+ }
+ return (NULL);
}
/* Given an address, add it to the source address list */
@@ -1024,11 +1283,14 @@ 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, ifindex);
+ sctp_ipif = sctp_lookup_ipif_addr(addr, B_TRUE, sctp->sctp_zoneid,
+ !sctp->sctp_connp->conn_allzones, ifindex, 0, B_TRUE,
+ sctp->sctp_sctps);
if (sctp_ipif == NULL)
return (EINVAL);
- if (sctp_ipif_hash_insert(sctp, sctp_ipif, KM_NOSLEEP, B_FALSE) != 0) {
+ if (sctp_ipif_hash_insert(sctp, sctp_ipif, KM_NOSLEEP, B_FALSE,
+ B_FALSE) != 0) {
SCTP_IPIF_REFRELE(sctp_ipif);
return (EINVAL);
}
diff --git a/usr/src/uts/common/inet/sctp/sctp_addr.h b/usr/src/uts/common/inet/sctp/sctp_addr.h
index 4e1eaf78e2..2625b2e06a 100644
--- a/usr/src/uts/common/inet/sctp/sctp_addr.h
+++ b/usr/src/uts/common/inet/sctp/sctp_addr.h
@@ -132,13 +132,18 @@ typedef struct sctp_ill_hash_s {
#define SCTP_IPIF_REFHOLD(sctp_ipif) { \
atomic_add_32(&(sctp_ipif)->sctp_ipif_refcnt, 1); \
- ASSERT((sctp_ipif)->sctp_ipif_refcnt != 0); \
}
#define SCTP_IPIF_REFRELE(sctp_ipif) { \
+ rw_enter(&(sctp_ipif)->sctp_ipif_lock, RW_WRITER); \
ASSERT((sctp_ipif)->sctp_ipif_refcnt != 0); \
- if (atomic_add_32_nv(&(sctp_ipif)->sctp_ipif_refcnt, -1) == 0) \
+ if (--(sctp_ipif)->sctp_ipif_refcnt == 0 && \
+ (sctp_ipif)->sctp_ipif_state == SCTP_IPIFS_CONDEMNED) { \
+ rw_exit(&(sctp_ipif)->sctp_ipif_lock); \
sctp_ipif_inactive(sctp_ipif); \
+ } else { \
+ rw_exit(&(sctp_ipif)->sctp_ipif_lock); \
+ } \
}
/* Address set comparison results. */
@@ -164,7 +169,6 @@ extern void sctp_del_saddr(sctp_t *, sctp_saddr_ipif_t *);
extern void sctp_free_saddrs(sctp_t *);
extern void sctp_saddr_init(sctp_stack_t *);
extern void sctp_saddr_fini(sctp_stack_t *);
-extern sctp_saddr_ipif_t *sctp_ipif_lookup(sctp_t *, uint_t);
extern int sctp_getmyaddrs(void *, void *, int *);
extern int sctp_saddr_add_addr(sctp_t *, in6_addr_t *, uint_t);
extern void sctp_check_saddr(sctp_t *, int, boolean_t);
diff --git a/usr/src/uts/common/inet/sctp/sctp_common.c b/usr/src/uts/common/inet/sctp/sctp_common.c
index 101cd49ecc..2930c15337 100644
--- a/usr/src/uts/common/inet/sctp/sctp_common.c
+++ b/usr/src/uts/common/inet/sctp/sctp_common.c
@@ -90,7 +90,6 @@ sctp_get_ire(sctp_t *sctp, sctp_faddr_t *fp)
ipaddr_t addr4;
in6_addr_t laddr;
sctp_saddr_ipif_t *sp;
- uint_t ipif_seqid;
int hdrlen;
ts_label_t *tsl;
sctp_stack_t *sctps = sctp->sctp_sctps;
@@ -151,7 +150,6 @@ sctp_get_ire(sctp_t *sctp, sctp_faddr_t *fp)
goto check_current;
}
- ipif_seqid = ire->ire_ipif->ipif_seqid;
dprint(2, ("ire2faddr: got ire for %x:%x:%x:%x, ",
SCTP_PRINTADDR(fp->faddr)));
if (fp->isv4) {
@@ -162,8 +160,8 @@ sctp_get_ire(sctp_t *sctp, sctp_faddr_t *fp)
}
/* Make sure the laddr is part of this association */
- if ((sp = sctp_ipif_lookup(sctp, ipif_seqid)) != NULL &&
- !sp->saddr_ipif_dontsrc) {
+ if ((sp = sctp_saddr_lookup(sctp, &ire->ire_ipif->ipif_v6lcl_addr,
+ 0)) != NULL && !sp->saddr_ipif_dontsrc) {
if (sp->saddr_ipif_unconfirmed == 1)
sp->saddr_ipif_unconfirmed = 0;
fp->saddr = laddr;
diff --git a/usr/src/uts/common/inet/sctp/sctp_cookie.c b/usr/src/uts/common/inet/sctp/sctp_cookie.c
index dcb94c2ccd..036f069257 100644
--- a/usr/src/uts/common/inet/sctp/sctp_cookie.c
+++ b/usr/src/uts/common/inet/sctp/sctp_cookie.c
@@ -1319,7 +1319,7 @@ sctp_process_cookie(sctp_t *sctp, sctp_chunk_hdr_t *ch, mblk_t *cmp,
*/
sctp_t *
sctp_addrlist2sctp(mblk_t *mp, sctp_hdr_t *sctph, sctp_chunk_hdr_t *ich,
- uint_t ipif_seqid, zoneid_t zoneid, sctp_stack_t *sctps)
+ zoneid_t zoneid, sctp_stack_t *sctps)
{
int isv4;
ipha_t *iph;
@@ -1366,8 +1366,8 @@ sctp_addrlist2sctp(mblk_t *mp, sctp_hdr_t *sctph, sctp_chunk_hdr_t *ich,
IN6_INADDR_TO_V4MAPPED((struct in_addr *)(ph + 1),
&src);
- sctp = sctp_conn_match(&src, &dst, ports, ipif_seqid,
- zoneid, sctps);
+ sctp = sctp_conn_match(&src, &dst, ports, zoneid,
+ sctps);
dprint(1,
("sctp_addrlist2sctp: src=%x:%x:%x:%x, sctp=%p\n",
@@ -1379,8 +1379,8 @@ sctp_addrlist2sctp(mblk_t *mp, sctp_hdr_t *sctph, sctp_chunk_hdr_t *ich,
}
} else if (ph->sph_type == PARM_ADDR6) {
src = *(in6_addr_t *)(ph + 1);
- sctp = sctp_conn_match(&src, &dst, ports, ipif_seqid,
- zoneid, sctps);
+ sctp = sctp_conn_match(&src, &dst, ports, zoneid,
+ sctps);
dprint(1,
("sctp_addrlist2sctp: src=%x:%x:%x:%x, sctp=%p\n",
diff --git a/usr/src/uts/common/inet/sctp/sctp_hash.c b/usr/src/uts/common/inet/sctp/sctp_hash.c
index f6b3666da5..9c55d72193 100644
--- a/usr/src/uts/common/inet/sctp/sctp_hash.c
+++ b/usr/src/uts/common/inet/sctp/sctp_hash.c
@@ -312,7 +312,7 @@ cl_sctp_walk_list_stack(int (*cl_callback)(cl_sctp_info_t *, void *),
sctp_t *
sctp_conn_match(in6_addr_t *faddr, in6_addr_t *laddr, uint32_t ports,
- uint_t ipif_seqid, zoneid_t zoneid, sctp_stack_t *sctps)
+ zoneid_t zoneid, sctp_stack_t *sctps)
{
sctp_tf_t *tf;
sctp_t *sctp;
@@ -334,24 +334,16 @@ sctp_conn_match(in6_addr_t *faddr, in6_addr_t *laddr, uint32_t ports,
}
}
- if (!fp) {
- /* no faddr match; keep looking */
+ /* no faddr match; keep looking */
+ if (fp == NULL)
continue;
- }
/* check for laddr match */
- if (ipif_seqid == 0) {
- if (sctp_saddr_lookup(sctp, laddr, 0) != NULL) {
- SCTP_REFHOLD(sctp);
- goto done;
- }
- } else {
- if (sctp_ipif_lookup(sctp, ipif_seqid) != NULL) {
- SCTP_REFHOLD(sctp);
- goto done;
- }
- /* no match; continue to the next in the chain */
+ if (sctp_saddr_lookup(sctp, laddr, 0) != NULL) {
+ SCTP_REFHOLD(sctp);
+ goto done;
}
+ /* no match; continue to the next in the chain */
}
done:
@@ -360,8 +352,8 @@ done:
}
static sctp_t *
-listen_match(in6_addr_t *laddr, uint32_t ports, uint_t ipif_seqid,
- zoneid_t zoneid, sctp_stack_t *sctps)
+listen_match(in6_addr_t *laddr, uint32_t ports, zoneid_t zoneid,
+ sctp_stack_t *sctps)
{
sctp_t *sctp;
sctp_tf_t *tf;
@@ -378,16 +370,9 @@ listen_match(in6_addr_t *laddr, uint32_t ports, uint_t ipif_seqid,
continue;
}
- if (ipif_seqid == 0) {
- if (sctp_saddr_lookup(sctp, laddr, 0) != NULL) {
- SCTP_REFHOLD(sctp);
- goto done;
- }
- } else {
- if (sctp_ipif_lookup(sctp, ipif_seqid) != NULL) {
- SCTP_REFHOLD(sctp);
- goto done;
- }
+ if (sctp_saddr_lookup(sctp, laddr, 0) != NULL) {
+ SCTP_REFHOLD(sctp);
+ goto done;
}
/* no match; continue to the next in the chain */
}
@@ -400,31 +385,27 @@ done:
/* called by ipsec_sctp_pol */
conn_t *
sctp_find_conn(in6_addr_t *src, in6_addr_t *dst, uint32_t ports,
- uint_t ipif_seqid, zoneid_t zoneid, sctp_stack_t *sctps)
+ zoneid_t zoneid, sctp_stack_t *sctps)
{
sctp_t *sctp;
- if ((sctp = sctp_conn_match(src, dst, ports, ipif_seqid,
- zoneid, sctps)) == NULL) {
+ if ((sctp = sctp_conn_match(src, dst, ports, zoneid, sctps)) == NULL) {
/* Not in conn fanout; check listen fanout */
- if ((sctp = listen_match(dst, ports, ipif_seqid,
- zoneid, sctps)) == NULL) {
+ if ((sctp = listen_match(dst, ports, zoneid, sctps)) == NULL)
return (NULL);
- }
}
return (sctp->sctp_connp);
}
conn_t *
sctp_fanout(in6_addr_t *src, in6_addr_t *dst, uint32_t ports,
- uint_t ipif_seqid, zoneid_t zoneid, mblk_t *mp, sctp_stack_t *sctps)
+ zoneid_t zoneid, mblk_t *mp, sctp_stack_t *sctps)
{
sctp_t *sctp;
boolean_t shared_addr;
- if ((sctp = sctp_conn_match(src, dst, ports, ipif_seqid,
- zoneid, sctps)) == NULL) {
+ if ((sctp = sctp_conn_match(src, dst, ports, zoneid, sctps)) == NULL) {
shared_addr = (zoneid == ALL_ZONES);
if (shared_addr) {
/*
@@ -445,10 +426,8 @@ sctp_fanout(in6_addr_t *src, in6_addr_t *dst, uint32_t ports,
return (NULL);
}
/* Not in conn fanout; check listen fanout */
- if ((sctp = listen_match(dst, ports, ipif_seqid,
- zoneid, sctps)) == NULL) {
+ if ((sctp = listen_match(dst, ports, zoneid, sctps)) == NULL)
return (NULL);
- }
/*
* On systems running trusted extensions, check if dst
* should accept the packet. "IPV6_VERSION" indicates
@@ -478,7 +457,7 @@ sctp_fanout(in6_addr_t *src, in6_addr_t *dst, uint32_t ports,
void
ip_fanout_sctp(mblk_t *mp, ill_t *recv_ill, ipha_t *ipha,
uint32_t ports, uint_t flags, boolean_t mctl_present, boolean_t ip_policy,
- uint_t ipif_seqid, zoneid_t zoneid)
+ zoneid_t zoneid)
{
sctp_t *sctp;
boolean_t isv4;
@@ -522,11 +501,10 @@ ip_fanout_sctp(mblk_t *mp, ill_t *recv_ill, ipha_t *ipha,
dst = &map_dst;
isv4 = B_TRUE;
}
- connp = sctp_find_conn(src, dst, ports, ipif_seqid, zoneid, sctps);
+ connp = sctp_find_conn(src, dst, ports, zoneid, sctps);
if (connp == NULL) {
ip_fanout_sctp_raw(first_mp, recv_ill, ipha, isv4,
- ports, mctl_present, flags, ip_policy,
- ipif_seqid, zoneid);
+ ports, mctl_present, flags, ip_policy, zoneid);
return;
}
sctp = CONN2SCTP(connp);
diff --git a/usr/src/uts/common/inet/sctp/sctp_impl.h b/usr/src/uts/common/inet/sctp/sctp_impl.h
index e405703a29..453f911f5f 100644
--- a/usr/src/uts/common/inet/sctp/sctp_impl.h
+++ b/usr/src/uts/common/inet/sctp/sctp_impl.h
@@ -925,7 +925,7 @@ extern mblk_t *sctp_add_proto_hdr(sctp_t *, sctp_faddr_t *, mblk_t *, int,
int *);
extern void sctp_addr_req(sctp_t *, mblk_t *);
extern sctp_t *sctp_addrlist2sctp(mblk_t *, sctp_hdr_t *, sctp_chunk_hdr_t *,
- uint_t, zoneid_t, sctp_stack_t *);
+ zoneid_t, sctp_stack_t *);
extern void sctp_add_hdr(sctp_t *, uchar_t *, size_t);
extern void sctp_check_adv_ack_pt(sctp_t *, mblk_t *, mblk_t *);
extern void sctp_assoc_event(sctp_t *, uint16_t, uint16_t,
@@ -947,7 +947,7 @@ extern int sctp_compare_faddrsets(sctp_faddr_t *, sctp_faddr_t *);
extern void sctp_congest_reset(sctp_t *);
extern void sctp_conn_hash_insert(sctp_tf_t *, sctp_t *, int);
extern void sctp_conn_hash_remove(sctp_t *);
-extern sctp_t *sctp_conn_match(in6_addr_t *, in6_addr_t *, uint32_t, uint_t,
+extern sctp_t *sctp_conn_match(in6_addr_t *, in6_addr_t *, uint32_t,
zoneid_t, sctp_stack_t *);
extern sctp_t *sctp_conn_request(sctp_t *, mblk_t *, uint_t, uint_t,
sctp_init_chunk_t *, mblk_t *);
diff --git a/usr/src/uts/common/inet/sctp/sctp_input.c b/usr/src/uts/common/inet/sctp/sctp_input.c
index 4169486856..0b15712122 100644
--- a/usr/src/uts/common/inet/sctp/sctp_input.c
+++ b/usr/src/uts/common/inet/sctp/sctp_input.c
@@ -3183,8 +3183,8 @@ sctp_check_in_policy(mblk_t *mp, mblk_t *ipsec_mp)
/* Handle out-of-the-blue packets */
void
-sctp_ootb_input(mblk_t *mp, ill_t *recv_ill, uint_t ipif_seqid,
- zoneid_t zoneid, boolean_t mctl_present)
+sctp_ootb_input(mblk_t *mp, ill_t *recv_ill, zoneid_t zoneid,
+ boolean_t mctl_present)
{
sctp_t *sctp;
sctp_chunk_hdr_t *ch;
@@ -3272,8 +3272,7 @@ sctp_ootb_input(mblk_t *mp, ill_t *recv_ill, uint_t ipif_seqid,
break;
case CHUNK_INIT_ACK:
/* check for changed src addr */
- sctp = sctp_addrlist2sctp(mp, sctph, ch, ipif_seqid, zoneid,
- sctps);
+ sctp = sctp_addrlist2sctp(mp, sctph, ch, zoneid, sctps);
if (sctp != NULL) {
/* success; proceed to normal path */
mutex_enter(&sctp->sctp_lock);
diff --git a/usr/src/uts/common/inet/sctp_ip.h b/usr/src/uts/common/inet/sctp_ip.h
index 89b5730f90..567a600671 100644
--- a/usr/src/uts/common/inet/sctp_ip.h
+++ b/usr/src/uts/common/inet/sctp_ip.h
@@ -38,18 +38,18 @@ extern "C" {
/* SCTP routines for IP to call. */
extern void ip_fanout_sctp(mblk_t *, ill_t *, ipha_t *, uint32_t,
- uint_t, boolean_t, boolean_t, uint_t, zoneid_t);
+ uint_t, boolean_t, boolean_t, zoneid_t);
extern void sctp_ddi_g_init(void);
extern void sctp_ddi_g_destroy(void);
-extern conn_t *sctp_find_conn(in6_addr_t *, in6_addr_t *, uint32_t, uint_t,
+extern conn_t *sctp_find_conn(in6_addr_t *, in6_addr_t *, uint32_t,
zoneid_t, sctp_stack_t *);
-extern conn_t *sctp_fanout(in6_addr_t *, in6_addr_t *, uint32_t, uint_t,
+extern conn_t *sctp_fanout(in6_addr_t *, in6_addr_t *, uint32_t,
zoneid_t, mblk_t *, sctp_stack_t *);
extern void sctp_input(conn_t *, ipha_t *, mblk_t *, mblk_t *, ill_t *,
boolean_t, boolean_t);
extern void sctp_wput(queue_t *, mblk_t *);
-extern void sctp_ootb_input(mblk_t *, ill_t *, uint_t, zoneid_t, boolean_t);
+extern void sctp_ootb_input(mblk_t *, ill_t *, zoneid_t, boolean_t);
extern void sctp_hash_init(sctp_stack_t *);
extern void sctp_hash_destroy(sctp_stack_t *);
extern uint32_t sctp_cksum(mblk_t *, int);
@@ -78,6 +78,7 @@ extern void sctp_free(conn_t *);
extern void sctp_update_ill(ill_t *, int);
extern void sctp_update_ipif(ipif_t *, int);
extern void sctp_move_ipif(ipif_t *, ill_t *, ill_t *);
+extern void sctp_update_ipif_addr(ipif_t *, in6_addr_t);
#define SCTP_ILL_INSERT 1
#define SCTP_ILL_REMOVE 2
@@ -89,7 +90,7 @@ extern void sctp_move_ipif(ipif_t *, ill_t *, ill_t *);
/* IP routines for SCTP to call. */
extern void ip_fanout_sctp_raw(mblk_t *, ill_t *, ipha_t *, boolean_t,
- uint32_t, boolean_t, uint_t, boolean_t, uint_t, zoneid_t);
+ uint32_t, boolean_t, uint_t, boolean_t, zoneid_t);
extern void sctp_ire_cache_flush(ipif_t *);
/*