17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
545916cd2Sjpk * Common Development and Distribution License (the "License").
645916cd2Sjpk * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
2177c67f2fSkcpoon
227c478bd9Sstevel@tonic-gate /*
23fd7b5aedSGeorge Shepherd * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include <sys/types.h>
277c478bd9Sstevel@tonic-gate #include <sys/systm.h>
287c478bd9Sstevel@tonic-gate #include <sys/stream.h>
2945916cd2Sjpk #include <sys/strsubr.h>
307c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
317c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
327c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
337c478bd9Sstevel@tonic-gate #include <sys/socket.h>
347c478bd9Sstevel@tonic-gate #include <sys/random.h>
3545916cd2Sjpk #include <sys/tsol/tndb.h>
3645916cd2Sjpk #include <sys/tsol/tnet.h>
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate #include <netinet/in.h>
397c478bd9Sstevel@tonic-gate #include <netinet/ip6.h>
407c478bd9Sstevel@tonic-gate #include <netinet/sctp.h>
417c478bd9Sstevel@tonic-gate
427c478bd9Sstevel@tonic-gate #include <inet/common.h>
437c478bd9Sstevel@tonic-gate #include <inet/ip.h>
447c478bd9Sstevel@tonic-gate #include <inet/ip6.h>
457c478bd9Sstevel@tonic-gate #include <inet/ip_ire.h>
46bd670b35SErik Nordmark #include <inet/ip_if.h>
47bd670b35SErik Nordmark #include <inet/ip_ndp.h>
487c478bd9Sstevel@tonic-gate #include <inet/mib2.h>
497c478bd9Sstevel@tonic-gate #include <inet/nd.h>
507c478bd9Sstevel@tonic-gate #include <inet/optcom.h>
517c478bd9Sstevel@tonic-gate #include <inet/sctp_ip.h>
527c478bd9Sstevel@tonic-gate #include <inet/ipclassifier.h>
5345916cd2Sjpk
547c478bd9Sstevel@tonic-gate #include "sctp_impl.h"
557c478bd9Sstevel@tonic-gate #include "sctp_addr.h"
56769b977dSvi117747 #include "sctp_asconf.h"
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate static struct kmem_cache *sctp_kmem_faddr_cache;
5977c67f2fSkcpoon static void sctp_init_faddr(sctp_t *, sctp_faddr_t *, in6_addr_t *, mblk_t *);
607c478bd9Sstevel@tonic-gate
61bd670b35SErik Nordmark /* Set the source address. Refer to comments in sctp_get_dest(). */
62769b977dSvi117747 void
sctp_set_saddr(sctp_t * sctp,sctp_faddr_t * fp)63769b977dSvi117747 sctp_set_saddr(sctp_t *sctp, sctp_faddr_t *fp)
647c478bd9Sstevel@tonic-gate {
65*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India boolean_t v6 = !fp->sf_isv4;
66c31292eeSkcpoon boolean_t addr_set;
67b46e5978Sjarrett
68*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_saddr = sctp_get_valid_addr(sctp, v6, &addr_set);
69c31292eeSkcpoon /*
70c31292eeSkcpoon * If there is no source address avaialble, mark this peer address
71c31292eeSkcpoon * as unreachable for now. When the heartbeat timer fires, it will
72bd670b35SErik Nordmark * call sctp_get_dest() to re-check if there is any source address
73c31292eeSkcpoon * available.
74c31292eeSkcpoon */
75c31292eeSkcpoon if (!addr_set)
76*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_state = SCTP_FADDRS_UNREACH;
777c478bd9Sstevel@tonic-gate }
787c478bd9Sstevel@tonic-gate
797c478bd9Sstevel@tonic-gate /*
80bd670b35SErik Nordmark * Call this function to get information about a peer addr fp.
81bd670b35SErik Nordmark *
82bd670b35SErik Nordmark * Uses ip_attr_connect to avoid explicit use of ire and source address
83bd670b35SErik Nordmark * selection.
847c478bd9Sstevel@tonic-gate */
857c478bd9Sstevel@tonic-gate void
sctp_get_dest(sctp_t * sctp,sctp_faddr_t * fp)86bd670b35SErik Nordmark sctp_get_dest(sctp_t *sctp, sctp_faddr_t *fp)
877c478bd9Sstevel@tonic-gate {
887c478bd9Sstevel@tonic-gate in6_addr_t laddr;
89bd670b35SErik Nordmark in6_addr_t nexthop;
907c478bd9Sstevel@tonic-gate sctp_saddr_ipif_t *sp;
917c478bd9Sstevel@tonic-gate int hdrlen;
92f4b3ec61Sdh155122 sctp_stack_t *sctps = sctp->sctp_sctps;
93bd670b35SErik Nordmark conn_t *connp = sctp->sctp_connp;
94bd670b35SErik Nordmark iulp_t uinfo;
95bd670b35SErik Nordmark uint_t pmtu;
96bd670b35SErik Nordmark int error;
97bd670b35SErik Nordmark uint32_t flags = IPDF_VERIFY_DST | IPDF_IPSEC |
98bd670b35SErik Nordmark IPDF_SELECT_SRC | IPDF_UNIQUE_DCE;
997c478bd9Sstevel@tonic-gate
100bd670b35SErik Nordmark /*
101bd670b35SErik Nordmark * Tell sctp_make_mp it needs to call us again should we not
102bd670b35SErik Nordmark * complete and set the saddr.
103bd670b35SErik Nordmark */
104*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_saddr = ipv6_all_zeros;
1057c478bd9Sstevel@tonic-gate
1067c478bd9Sstevel@tonic-gate /*
1077c478bd9Sstevel@tonic-gate * If this addr is not reachable, mark it as unconfirmed for now, the
1087c478bd9Sstevel@tonic-gate * state will be changed back to unreachable later in this function
1097c478bd9Sstevel@tonic-gate * if it is still the case.
1107c478bd9Sstevel@tonic-gate */
111*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (fp->sf_state == SCTP_FADDRS_UNREACH) {
112*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_state = SCTP_FADDRS_UNCONFIRMED;
1137c478bd9Sstevel@tonic-gate }
1147c478bd9Sstevel@tonic-gate
115bd670b35SErik Nordmark /*
116bd670b35SErik Nordmark * Socket is connected - enable PMTU discovery.
117bd670b35SErik Nordmark */
118bd670b35SErik Nordmark if (!sctps->sctps_ignore_path_mtu)
119*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_ixa->ixa_flags |= IXAF_PMTU_DISCOVERY;
12045916cd2Sjpk
121*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India ip_attr_nexthop(&connp->conn_xmit_ipp, fp->sf_ixa, &fp->sf_faddr,
122bd670b35SErik Nordmark &nexthop);
1237c478bd9Sstevel@tonic-gate
124*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India laddr = fp->sf_saddr;
125*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India error = ip_attr_connect(connp, fp->sf_ixa, &laddr, &fp->sf_faddr,
126*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India &nexthop, connp->conn_fport, &laddr, &uinfo, flags);
127bd670b35SErik Nordmark
128bd670b35SErik Nordmark if (error != 0) {
129bd670b35SErik Nordmark dprint(3, ("sctp_get_dest: no ire for %x:%x:%x:%x\n",
130*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India SCTP_PRINTADDR(fp->sf_faddr)));
1317c478bd9Sstevel@tonic-gate /*
1327c478bd9Sstevel@tonic-gate * It is tempting to just leave the src addr
1337c478bd9Sstevel@tonic-gate * unspecified and let IP figure it out, but we
1347c478bd9Sstevel@tonic-gate * *cannot* do this, since IP may choose a src addr
1357c478bd9Sstevel@tonic-gate * that is not part of this association... unless
136bd670b35SErik Nordmark * this sctp has bound to all addrs. So if the dest
1377c478bd9Sstevel@tonic-gate * lookup fails, try to find one in our src addr
1387c478bd9Sstevel@tonic-gate * list, unless the sctp has bound to all addrs, in
1397c478bd9Sstevel@tonic-gate * which case we change the src addr to unspec.
1407c478bd9Sstevel@tonic-gate *
1417c478bd9Sstevel@tonic-gate * Note that if this is a v6 endpoint but it does
1427c478bd9Sstevel@tonic-gate * not have any v4 address at this point (e.g. may
1437c478bd9Sstevel@tonic-gate * have been deleted), sctp_get_valid_addr() will
1447c478bd9Sstevel@tonic-gate * return mapped INADDR_ANY. In this case, this
1457c478bd9Sstevel@tonic-gate * address should be marked not reachable so that
1467c478bd9Sstevel@tonic-gate * it won't be used to send data.
1477c478bd9Sstevel@tonic-gate */
148769b977dSvi117747 sctp_set_saddr(sctp, fp);
149*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (fp->sf_state == SCTP_FADDRS_UNREACH)
15077c67f2fSkcpoon return;
15177c67f2fSkcpoon goto check_current;
1527c478bd9Sstevel@tonic-gate }
153*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India ASSERT(fp->sf_ixa->ixa_ire != NULL);
154*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India ASSERT(!(fp->sf_ixa->ixa_ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)));
155bd670b35SErik Nordmark
156bd670b35SErik Nordmark if (!sctp->sctp_loopback)
157bd670b35SErik Nordmark sctp->sctp_loopback = uinfo.iulp_loopback;
1587c478bd9Sstevel@tonic-gate
15977c67f2fSkcpoon /* Make sure the laddr is part of this association */
160bd670b35SErik Nordmark if ((sp = sctp_saddr_lookup(sctp, &laddr, 0)) != NULL &&
161bd670b35SErik Nordmark !sp->saddr_ipif_dontsrc) {
162f551bb10Svi117747 if (sp->saddr_ipif_unconfirmed == 1)
163f551bb10Svi117747 sp->saddr_ipif_unconfirmed = 0;
164bd670b35SErik Nordmark /* We did IPsec policy lookup for laddr already */
165*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_saddr = laddr;
1667c478bd9Sstevel@tonic-gate } else {
167bd670b35SErik Nordmark dprint(2, ("sctp_get_dest: src addr is not part of assoc "
168bd670b35SErik Nordmark "%x:%x:%x:%x\n", SCTP_PRINTADDR(laddr)));
16977c67f2fSkcpoon
17077c67f2fSkcpoon /*
17177c67f2fSkcpoon * Set the src to the first saddr and hope for the best.
172bd670b35SErik Nordmark * Note that this case should very seldomly
17377c67f2fSkcpoon * happen. One scenario this can happen is an app
17477c67f2fSkcpoon * explicitly bind() to an address. But that address is
17577c67f2fSkcpoon * not the preferred source address to send to the peer.
17677c67f2fSkcpoon */
177769b977dSvi117747 sctp_set_saddr(sctp, fp);
178*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (fp->sf_state == SCTP_FADDRS_UNREACH) {
17977c67f2fSkcpoon return;
18077c67f2fSkcpoon }
1817c478bd9Sstevel@tonic-gate }
1827c478bd9Sstevel@tonic-gate
18377c67f2fSkcpoon /*
1847c478bd9Sstevel@tonic-gate * Pull out RTO information for this faddr and use it if we don't
1857c478bd9Sstevel@tonic-gate * have any yet.
1867c478bd9Sstevel@tonic-gate */
187*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (fp->sf_srtt == -1 && uinfo.iulp_rtt != 0) {
188d1d9f9adSkcpoon /* The cached value is in ms. */
189*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_srtt = MSEC_TO_TICK(uinfo.iulp_rtt);
190*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_rttvar = MSEC_TO_TICK(uinfo.iulp_rtt_sd);
191*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_rto = 3 * fp->sf_srtt;
1927c478bd9Sstevel@tonic-gate
1937c478bd9Sstevel@tonic-gate /* Bound the RTO by configured min and max values */
194*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (fp->sf_rto < sctp->sctp_rto_min) {
195*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_rto = sctp->sctp_rto_min;
1967c478bd9Sstevel@tonic-gate }
197*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (fp->sf_rto > sctp->sctp_rto_max) {
198*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_rto = sctp->sctp_rto_max;
1997c478bd9Sstevel@tonic-gate }
2009f13099eSGeorge Shepherd SCTP_MAX_RTO(sctp, fp);
2017c478bd9Sstevel@tonic-gate }
202bd670b35SErik Nordmark pmtu = uinfo.iulp_mtu;
2037c478bd9Sstevel@tonic-gate
2047c478bd9Sstevel@tonic-gate /*
2057c478bd9Sstevel@tonic-gate * Record the MTU for this faddr. If the MTU for this faddr has
2067c478bd9Sstevel@tonic-gate * changed, check if the assc MTU will also change.
2077c478bd9Sstevel@tonic-gate */
208*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (fp->sf_isv4) {
2097c478bd9Sstevel@tonic-gate hdrlen = sctp->sctp_hdr_len;
2107c478bd9Sstevel@tonic-gate } else {
2117c478bd9Sstevel@tonic-gate hdrlen = sctp->sctp_hdr6_len;
2127c478bd9Sstevel@tonic-gate }
213*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if ((fp->sf_pmss + hdrlen) != pmtu) {
214*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India /* Make sure that sf_pmss is a multiple of SCTP_ALIGN. */
215*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_pmss = (pmtu - hdrlen) & ~(SCTP_ALIGN - 1);
216*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (fp->sf_cwnd < (fp->sf_pmss * 2)) {
217*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India SET_CWND(fp, fp->sf_pmss,
21812f47623Skcpoon sctps->sctps_slow_start_initial);
2197c478bd9Sstevel@tonic-gate }
2207c478bd9Sstevel@tonic-gate }
2217c478bd9Sstevel@tonic-gate
22277c67f2fSkcpoon check_current:
22377c67f2fSkcpoon if (fp == sctp->sctp_current)
22477c67f2fSkcpoon sctp_set_faddr_current(sctp, fp);
2257c478bd9Sstevel@tonic-gate }
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate void
sctp_update_dce(sctp_t * sctp)228bd670b35SErik Nordmark sctp_update_dce(sctp_t *sctp)
2297c478bd9Sstevel@tonic-gate {
23077c67f2fSkcpoon sctp_faddr_t *fp;
231f4b3ec61Sdh155122 sctp_stack_t *sctps = sctp->sctp_sctps;
232bd670b35SErik Nordmark iulp_t uinfo;
233bd670b35SErik Nordmark ip_stack_t *ipst = sctps->sctps_netstack->netstack_ip;
234bd670b35SErik Nordmark uint_t ifindex;
2357c478bd9Sstevel@tonic-gate
236*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->sf_next) {
237bd670b35SErik Nordmark bzero(&uinfo, sizeof (uinfo));
2387c478bd9Sstevel@tonic-gate /*
2397c478bd9Sstevel@tonic-gate * Only record the PMTU for this faddr if we actually have
2407c478bd9Sstevel@tonic-gate * done discovery. This prevents initialized default from
2417c478bd9Sstevel@tonic-gate * clobbering any real info that IP may have.
2427c478bd9Sstevel@tonic-gate */
243*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (fp->sf_pmtu_discovered) {
244*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (fp->sf_isv4) {
245*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India uinfo.iulp_mtu = fp->sf_pmss +
24677c67f2fSkcpoon sctp->sctp_hdr_len;
2477c478bd9Sstevel@tonic-gate } else {
248*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India uinfo.iulp_mtu = fp->sf_pmss +
24977c67f2fSkcpoon sctp->sctp_hdr6_len;
2507c478bd9Sstevel@tonic-gate }
2517c478bd9Sstevel@tonic-gate }
252f4b3ec61Sdh155122 if (sctps->sctps_rtt_updates != 0 &&
253*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_rtt_updates >= sctps->sctps_rtt_updates) {
2547c478bd9Sstevel@tonic-gate /*
255bd670b35SErik Nordmark * dce_update_uinfo() merges these values with the
256bd670b35SErik Nordmark * old values.
2577c478bd9Sstevel@tonic-gate */
258*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India uinfo.iulp_rtt = TICK_TO_MSEC(fp->sf_srtt);
259*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India uinfo.iulp_rtt_sd = TICK_TO_MSEC(fp->sf_rttvar);
260*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_rtt_updates = 0;
2617c478bd9Sstevel@tonic-gate }
262bd670b35SErik Nordmark ifindex = 0;
263*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (IN6_IS_ADDR_LINKSCOPE(&fp->sf_faddr)) {
264bd670b35SErik Nordmark /*
265bd670b35SErik Nordmark * If we are going to create a DCE we'd better have
266bd670b35SErik Nordmark * an ifindex
267bd670b35SErik Nordmark */
268*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (fp->sf_ixa->ixa_nce != NULL) {
269*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India ifindex = fp->sf_ixa->ixa_nce->nce_common->
270bd670b35SErik Nordmark ncec_ill->ill_phyint->phyint_ifindex;
271bd670b35SErik Nordmark } else {
272bd670b35SErik Nordmark continue;
273bd670b35SErik Nordmark }
274bd670b35SErik Nordmark }
275bd670b35SErik Nordmark
276*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India (void) dce_update_uinfo(&fp->sf_faddr, ifindex, &uinfo, ipst);
2777c478bd9Sstevel@tonic-gate }
27877c67f2fSkcpoon }
2797c478bd9Sstevel@tonic-gate
2807c478bd9Sstevel@tonic-gate /*
281bd670b35SErik Nordmark * The sender must later set the total length in the IP header.
2827c478bd9Sstevel@tonic-gate */
2837c478bd9Sstevel@tonic-gate mblk_t *
sctp_make_mp(sctp_t * sctp,sctp_faddr_t * fp,int trailer)284bd670b35SErik Nordmark sctp_make_mp(sctp_t *sctp, sctp_faddr_t *fp, int trailer)
2857c478bd9Sstevel@tonic-gate {
2867c478bd9Sstevel@tonic-gate mblk_t *mp;
2877c478bd9Sstevel@tonic-gate size_t ipsctplen;
2887c478bd9Sstevel@tonic-gate int isv4;
289f4b3ec61Sdh155122 sctp_stack_t *sctps = sctp->sctp_sctps;
290c31292eeSkcpoon boolean_t src_changed = B_FALSE;
2917c478bd9Sstevel@tonic-gate
292bd670b35SErik Nordmark ASSERT(fp != NULL);
293*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India isv4 = fp->sf_isv4;
2947c478bd9Sstevel@tonic-gate
295*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (SCTP_IS_ADDR_UNSPEC(isv4, fp->sf_saddr) ||
296*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India (fp->sf_ixa->ixa_ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE))) {
297bd670b35SErik Nordmark /* Need to pick a source */
298bd670b35SErik Nordmark sctp_get_dest(sctp, fp);
299c31292eeSkcpoon /*
300c31292eeSkcpoon * Although we still may not get an IRE, the source address
301c31292eeSkcpoon * may be changed in sctp_get_ire(). Set src_changed to
302c31292eeSkcpoon * true so that the source address is copied again.
303c31292eeSkcpoon */
304c31292eeSkcpoon src_changed = B_TRUE;
305c31292eeSkcpoon }
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate /* There is no suitable source address to use, return. */
308*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (fp->sf_state == SCTP_FADDRS_UNREACH)
3097c478bd9Sstevel@tonic-gate return (NULL);
310bd670b35SErik Nordmark
311*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India ASSERT(fp->sf_ixa->ixa_ire != NULL);
312*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India ASSERT(!SCTP_IS_ADDR_UNSPEC(isv4, fp->sf_saddr));
3137c478bd9Sstevel@tonic-gate
3147c478bd9Sstevel@tonic-gate if (isv4) {
3157c478bd9Sstevel@tonic-gate ipsctplen = sctp->sctp_hdr_len;
3167c478bd9Sstevel@tonic-gate } else {
3177c478bd9Sstevel@tonic-gate ipsctplen = sctp->sctp_hdr6_len;
3187c478bd9Sstevel@tonic-gate }
3197c478bd9Sstevel@tonic-gate
320bd670b35SErik Nordmark mp = allocb(ipsctplen + sctps->sctps_wroff_xtra + trailer, BPRI_MED);
3217c478bd9Sstevel@tonic-gate if (mp == NULL) {
32245916cd2Sjpk ip1dbg(("sctp_make_mp: error making mp..\n"));
3237c478bd9Sstevel@tonic-gate return (NULL);
3247c478bd9Sstevel@tonic-gate }
325f4b3ec61Sdh155122 mp->b_rptr += sctps->sctps_wroff_xtra;
3267c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + ipsctplen;
3277c478bd9Sstevel@tonic-gate
3287c478bd9Sstevel@tonic-gate ASSERT(OK_32PTR(mp->b_wptr));
3297c478bd9Sstevel@tonic-gate
3307c478bd9Sstevel@tonic-gate if (isv4) {
3317c478bd9Sstevel@tonic-gate ipha_t *iph = (ipha_t *)mp->b_rptr;
3327c478bd9Sstevel@tonic-gate
3337c478bd9Sstevel@tonic-gate bcopy(sctp->sctp_iphc, mp->b_rptr, ipsctplen);
334c31292eeSkcpoon if (fp != sctp->sctp_current || src_changed) {
335c31292eeSkcpoon /* Fix the source and destination addresses. */
336*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India IN6_V4MAPPED_TO_IPADDR(&fp->sf_faddr, iph->ipha_dst);
337*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India IN6_V4MAPPED_TO_IPADDR(&fp->sf_saddr, iph->ipha_src);
3387c478bd9Sstevel@tonic-gate }
3397c478bd9Sstevel@tonic-gate /* set or clear the don't fragment bit */
340*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (fp->sf_df) {
3417c478bd9Sstevel@tonic-gate iph->ipha_fragment_offset_and_flags = htons(IPH_DF);
3427c478bd9Sstevel@tonic-gate } else {
3437c478bd9Sstevel@tonic-gate iph->ipha_fragment_offset_and_flags = 0;
3447c478bd9Sstevel@tonic-gate }
3457c478bd9Sstevel@tonic-gate } else {
3467c478bd9Sstevel@tonic-gate bcopy(sctp->sctp_iphc6, mp->b_rptr, ipsctplen);
347c31292eeSkcpoon if (fp != sctp->sctp_current || src_changed) {
348c31292eeSkcpoon /* Fix the source and destination addresses. */
349*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India ((ip6_t *)(mp->b_rptr))->ip6_dst = fp->sf_faddr;
350*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India ((ip6_t *)(mp->b_rptr))->ip6_src = fp->sf_saddr;
3517c478bd9Sstevel@tonic-gate }
3527c478bd9Sstevel@tonic-gate }
3537c478bd9Sstevel@tonic-gate ASSERT(sctp->sctp_connp != NULL);
3547c478bd9Sstevel@tonic-gate return (mp);
3557c478bd9Sstevel@tonic-gate }
3567c478bd9Sstevel@tonic-gate
3577c478bd9Sstevel@tonic-gate /*
3587c478bd9Sstevel@tonic-gate * Notify upper layers about preferred write offset, write size.
3597c478bd9Sstevel@tonic-gate */
3607c478bd9Sstevel@tonic-gate void
sctp_set_ulp_prop(sctp_t * sctp)3617c478bd9Sstevel@tonic-gate sctp_set_ulp_prop(sctp_t *sctp)
3627c478bd9Sstevel@tonic-gate {
3637c478bd9Sstevel@tonic-gate int hdrlen;
3640f1702c5SYu Xiangning struct sock_proto_props sopp;
3650f1702c5SYu Xiangning
366f4b3ec61Sdh155122 sctp_stack_t *sctps = sctp->sctp_sctps;
3677c478bd9Sstevel@tonic-gate
368*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (sctp->sctp_current->sf_isv4) {
3697c478bd9Sstevel@tonic-gate hdrlen = sctp->sctp_hdr_len;
3707c478bd9Sstevel@tonic-gate } else {
3717c478bd9Sstevel@tonic-gate hdrlen = sctp->sctp_hdr6_len;
3727c478bd9Sstevel@tonic-gate }
3737c478bd9Sstevel@tonic-gate ASSERT(sctp->sctp_ulpd);
3747c478bd9Sstevel@tonic-gate
375bd670b35SErik Nordmark sctp->sctp_connp->conn_wroff = sctps->sctps_wroff_xtra + hdrlen +
376bd670b35SErik Nordmark sizeof (sctp_data_hdr_t);
377bd670b35SErik Nordmark
378*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India ASSERT(sctp->sctp_current->sf_pmss == sctp->sctp_mss);
3790f1702c5SYu Xiangning bzero(&sopp, sizeof (sopp));
3800f1702c5SYu Xiangning sopp.sopp_flags = SOCKOPT_MAXBLK|SOCKOPT_WROFF;
381bd670b35SErik Nordmark sopp.sopp_wroff = sctp->sctp_connp->conn_wroff;
3820f1702c5SYu Xiangning sopp.sopp_maxblk = sctp->sctp_mss - sizeof (sctp_data_hdr_t);
3830f1702c5SYu Xiangning sctp->sctp_ulp_prop(sctp->sctp_ulpd, &sopp);
3847c478bd9Sstevel@tonic-gate }
3857c478bd9Sstevel@tonic-gate
386bd670b35SErik Nordmark /*
387bd670b35SErik Nordmark * Set the lengths in the packet and the transmit attributes.
388bd670b35SErik Nordmark */
3897c478bd9Sstevel@tonic-gate void
sctp_set_iplen(sctp_t * sctp,mblk_t * mp,ip_xmit_attr_t * ixa)390bd670b35SErik Nordmark sctp_set_iplen(sctp_t *sctp, mblk_t *mp, ip_xmit_attr_t *ixa)
3917c478bd9Sstevel@tonic-gate {
3927c478bd9Sstevel@tonic-gate uint16_t sum = 0;
3937c478bd9Sstevel@tonic-gate ipha_t *iph;
3947c478bd9Sstevel@tonic-gate ip6_t *ip6h;
3957c478bd9Sstevel@tonic-gate mblk_t *pmp = mp;
3967c478bd9Sstevel@tonic-gate boolean_t isv4;
3977c478bd9Sstevel@tonic-gate
3987c478bd9Sstevel@tonic-gate isv4 = (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION);
3997c478bd9Sstevel@tonic-gate for (; pmp; pmp = pmp->b_cont)
4007c478bd9Sstevel@tonic-gate sum += pmp->b_wptr - pmp->b_rptr;
4017c478bd9Sstevel@tonic-gate
402bd670b35SErik Nordmark ixa->ixa_pktlen = sum;
4037c478bd9Sstevel@tonic-gate if (isv4) {
4047c478bd9Sstevel@tonic-gate iph = (ipha_t *)mp->b_rptr;
4057c478bd9Sstevel@tonic-gate iph->ipha_length = htons(sum);
406bd670b35SErik Nordmark ixa->ixa_ip_hdr_length = sctp->sctp_ip_hdr_len;
4077c478bd9Sstevel@tonic-gate } else {
4087c478bd9Sstevel@tonic-gate ip6h = (ip6_t *)mp->b_rptr;
409bd670b35SErik Nordmark ip6h->ip6_plen = htons(sum - IPV6_HDR_LEN);
410bd670b35SErik Nordmark ixa->ixa_ip_hdr_length = sctp->sctp_ip_hdr6_len;
4117c478bd9Sstevel@tonic-gate }
4127c478bd9Sstevel@tonic-gate }
4137c478bd9Sstevel@tonic-gate
4147c478bd9Sstevel@tonic-gate int
sctp_compare_faddrsets(sctp_faddr_t * a1,sctp_faddr_t * a2)4157c478bd9Sstevel@tonic-gate sctp_compare_faddrsets(sctp_faddr_t *a1, sctp_faddr_t *a2)
4167c478bd9Sstevel@tonic-gate {
4177c478bd9Sstevel@tonic-gate int na1 = 0;
4187c478bd9Sstevel@tonic-gate int overlap = 0;
4197c478bd9Sstevel@tonic-gate int equal = 1;
4207c478bd9Sstevel@tonic-gate int onematch;
4217c478bd9Sstevel@tonic-gate sctp_faddr_t *fp1, *fp2;
4227c478bd9Sstevel@tonic-gate
423*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India for (fp1 = a1; fp1; fp1 = fp1->sf_next) {
4247c478bd9Sstevel@tonic-gate onematch = 0;
425*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India for (fp2 = a2; fp2; fp2 = fp2->sf_next) {
426*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (IN6_ARE_ADDR_EQUAL(&fp1->sf_faddr,
427*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India &fp2->sf_faddr)) {
4287c478bd9Sstevel@tonic-gate overlap++;
4297c478bd9Sstevel@tonic-gate onematch = 1;
4307c478bd9Sstevel@tonic-gate break;
4317c478bd9Sstevel@tonic-gate }
4327c478bd9Sstevel@tonic-gate if (!onematch) {
4337c478bd9Sstevel@tonic-gate equal = 0;
4347c478bd9Sstevel@tonic-gate }
4357c478bd9Sstevel@tonic-gate }
4367c478bd9Sstevel@tonic-gate na1++;
4377c478bd9Sstevel@tonic-gate }
4387c478bd9Sstevel@tonic-gate
4397c478bd9Sstevel@tonic-gate if (equal) {
4407c478bd9Sstevel@tonic-gate return (SCTP_ADDR_EQUAL);
4417c478bd9Sstevel@tonic-gate }
4427c478bd9Sstevel@tonic-gate if (overlap == na1) {
4437c478bd9Sstevel@tonic-gate return (SCTP_ADDR_SUBSET);
4447c478bd9Sstevel@tonic-gate }
4457c478bd9Sstevel@tonic-gate if (overlap) {
4467c478bd9Sstevel@tonic-gate return (SCTP_ADDR_OVERLAP);
4477c478bd9Sstevel@tonic-gate }
4487c478bd9Sstevel@tonic-gate return (SCTP_ADDR_DISJOINT);
4497c478bd9Sstevel@tonic-gate }
4507c478bd9Sstevel@tonic-gate
4517c478bd9Sstevel@tonic-gate /*
4525f9878b0Sken Powell - Sun Microsystem * Returns 0 on success, ENOMEM on memory allocation failure, EHOSTUNREACH
4535f9878b0Sken Powell - Sun Microsystem * if the connection credentials fail remote host accreditation or
4545f9878b0Sken Powell - Sun Microsystem * if the new destination does not support the previously established
4555f9878b0Sken Powell - Sun Microsystem * connection security label. If sleep is true, this function should
4565f9878b0Sken Powell - Sun Microsystem * never fail for a memory allocation failure. The boolean parameter
4575f9878b0Sken Powell - Sun Microsystem * "first" decides whether the newly created faddr structure should be
45877c67f2fSkcpoon * added at the beginning of the list or at the end.
45977c67f2fSkcpoon *
46077c67f2fSkcpoon * Note: caller must hold conn fanout lock.
4617c478bd9Sstevel@tonic-gate */
46277c67f2fSkcpoon int
sctp_add_faddr(sctp_t * sctp,in6_addr_t * addr,int sleep,boolean_t first)46377c67f2fSkcpoon sctp_add_faddr(sctp_t *sctp, in6_addr_t *addr, int sleep, boolean_t first)
4647c478bd9Sstevel@tonic-gate {
4657c478bd9Sstevel@tonic-gate sctp_faddr_t *faddr;
46677c67f2fSkcpoon mblk_t *timer_mp;
4675f9878b0Sken Powell - Sun Microsystem int err;
468bd670b35SErik Nordmark conn_t *connp = sctp->sctp_connp;
4697c478bd9Sstevel@tonic-gate
47045916cd2Sjpk if (is_system_labeled()) {
471bd670b35SErik Nordmark ip_xmit_attr_t *ixa = connp->conn_ixa;
472bd670b35SErik Nordmark ts_label_t *effective_tsl = NULL;
473bd670b35SErik Nordmark
474bd670b35SErik Nordmark ASSERT(ixa->ixa_tsl != NULL);
4757c478bd9Sstevel@tonic-gate
47645916cd2Sjpk /*
4775f9878b0Sken Powell - Sun Microsystem * Verify the destination is allowed to receive packets
4785f9878b0Sken Powell - Sun Microsystem * at the security label of the connection we are initiating.
4795f9878b0Sken Powell - Sun Microsystem *
480bd670b35SErik Nordmark * tsol_check_dest() will create a new effective label for
4815f9878b0Sken Powell - Sun Microsystem * this connection with a modified label or label flags only
482bd670b35SErik Nordmark * if there are changes from the original label.
4835f9878b0Sken Powell - Sun Microsystem *
4845f9878b0Sken Powell - Sun Microsystem * Accept whatever label we get if this is the first
4855f9878b0Sken Powell - Sun Microsystem * destination address for this connection. The security
4865f9878b0Sken Powell - Sun Microsystem * label and label flags must match any previuous settings
4875f9878b0Sken Powell - Sun Microsystem * for all subsequent destination addresses.
48845916cd2Sjpk */
4895f9878b0Sken Powell - Sun Microsystem if (IN6_IS_ADDR_V4MAPPED(addr)) {
4905f9878b0Sken Powell - Sun Microsystem uint32_t dst;
4915f9878b0Sken Powell - Sun Microsystem IN6_V4MAPPED_TO_IPADDR(addr, dst);
492bd670b35SErik Nordmark err = tsol_check_dest(ixa->ixa_tsl,
493bd670b35SErik Nordmark &dst, IPV4_VERSION, connp->conn_mac_mode,
494bd670b35SErik Nordmark connp->conn_zone_is_global, &effective_tsl);
4955f9878b0Sken Powell - Sun Microsystem } else {
496bd670b35SErik Nordmark err = tsol_check_dest(ixa->ixa_tsl,
497bd670b35SErik Nordmark addr, IPV6_VERSION, connp->conn_mac_mode,
498bd670b35SErik Nordmark connp->conn_zone_is_global, &effective_tsl);
4997c478bd9Sstevel@tonic-gate }
5005f9878b0Sken Powell - Sun Microsystem if (err != 0)
5015f9878b0Sken Powell - Sun Microsystem return (err);
502bd670b35SErik Nordmark
503bd670b35SErik Nordmark if (sctp->sctp_faddrs == NULL && effective_tsl != NULL) {
504bd670b35SErik Nordmark ip_xmit_attr_replace_tsl(ixa, effective_tsl);
505bd670b35SErik Nordmark } else if (effective_tsl != NULL) {
506bd670b35SErik Nordmark label_rele(effective_tsl);
5075f9878b0Sken Powell - Sun Microsystem return (EHOSTUNREACH);
50845916cd2Sjpk }
50945916cd2Sjpk }
51045916cd2Sjpk
51145916cd2Sjpk if ((faddr = kmem_cache_alloc(sctp_kmem_faddr_cache, sleep)) == NULL)
51245916cd2Sjpk return (ENOMEM);
513bd670b35SErik Nordmark bzero(faddr, sizeof (*faddr));
514121e5416Skcpoon timer_mp = sctp_timer_alloc((sctp), sctp_rexmit_timer, sleep);
51577c67f2fSkcpoon if (timer_mp == NULL) {
51677c67f2fSkcpoon kmem_cache_free(sctp_kmem_faddr_cache, faddr);
51777c67f2fSkcpoon return (ENOMEM);
51877c67f2fSkcpoon }
51977c67f2fSkcpoon ((sctpt_t *)(timer_mp->b_rptr))->sctpt_faddr = faddr;
5207c478bd9Sstevel@tonic-gate
521bd670b35SErik Nordmark /* Start with any options set on the conn */
522*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India faddr->sf_ixa = conn_get_ixa_exclusive(connp);
523*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (faddr->sf_ixa == NULL) {
524bd670b35SErik Nordmark freemsg(timer_mp);
525c31292eeSkcpoon kmem_cache_free(sctp_kmem_faddr_cache, faddr);
526bd670b35SErik Nordmark return (ENOMEM);
527c31292eeSkcpoon }
528*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India faddr->sf_ixa->ixa_notify_cookie = connp->conn_sctp;
529bd670b35SErik Nordmark
530bd670b35SErik Nordmark sctp_init_faddr(sctp, faddr, addr, timer_mp);
531*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India ASSERT(faddr->sf_ixa->ixa_cred != NULL);
532bd670b35SErik Nordmark
533bd670b35SErik Nordmark /* ip_attr_connect didn't allow broadcats/multicast dest */
534*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India ASSERT(faddr->sf_next == NULL);
5357c478bd9Sstevel@tonic-gate
53645916cd2Sjpk if (sctp->sctp_faddrs == NULL) {
53745916cd2Sjpk ASSERT(sctp->sctp_lastfaddr == NULL);
53845916cd2Sjpk /* only element on list; first and last are same */
53945916cd2Sjpk sctp->sctp_faddrs = sctp->sctp_lastfaddr = faddr;
54045916cd2Sjpk } else if (first) {
54145916cd2Sjpk ASSERT(sctp->sctp_lastfaddr != NULL);
542*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India faddr->sf_next = sctp->sctp_faddrs;
5437c478bd9Sstevel@tonic-gate sctp->sctp_faddrs = faddr;
54445916cd2Sjpk } else {
545*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India sctp->sctp_lastfaddr->sf_next = faddr;
5467c478bd9Sstevel@tonic-gate sctp->sctp_lastfaddr = faddr;
54745916cd2Sjpk }
5481d8c4025Svi117747 sctp->sctp_nfaddrs++;
5497c478bd9Sstevel@tonic-gate
5507c478bd9Sstevel@tonic-gate return (0);
5517c478bd9Sstevel@tonic-gate }
5527c478bd9Sstevel@tonic-gate
5537c478bd9Sstevel@tonic-gate sctp_faddr_t *
sctp_lookup_faddr(sctp_t * sctp,in6_addr_t * addr)5547c478bd9Sstevel@tonic-gate sctp_lookup_faddr(sctp_t *sctp, in6_addr_t *addr)
5557c478bd9Sstevel@tonic-gate {
5567c478bd9Sstevel@tonic-gate sctp_faddr_t *fp;
5577c478bd9Sstevel@tonic-gate
558*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->sf_next) {
559*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (IN6_ARE_ADDR_EQUAL(&fp->sf_faddr, addr))
5607c478bd9Sstevel@tonic-gate break;
5617c478bd9Sstevel@tonic-gate }
5627c478bd9Sstevel@tonic-gate
5637c478bd9Sstevel@tonic-gate return (fp);
5647c478bd9Sstevel@tonic-gate }
5657c478bd9Sstevel@tonic-gate
5667c478bd9Sstevel@tonic-gate sctp_faddr_t *
sctp_lookup_faddr_nosctp(sctp_faddr_t * fp,in6_addr_t * addr)5677c478bd9Sstevel@tonic-gate sctp_lookup_faddr_nosctp(sctp_faddr_t *fp, in6_addr_t *addr)
5687c478bd9Sstevel@tonic-gate {
569*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India for (; fp; fp = fp->sf_next) {
570*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (IN6_ARE_ADDR_EQUAL(&fp->sf_faddr, addr)) {
5717c478bd9Sstevel@tonic-gate break;
5727c478bd9Sstevel@tonic-gate }
5737c478bd9Sstevel@tonic-gate }
5747c478bd9Sstevel@tonic-gate
5757c478bd9Sstevel@tonic-gate return (fp);
5767c478bd9Sstevel@tonic-gate }
5777c478bd9Sstevel@tonic-gate
57877c67f2fSkcpoon /*
57977c67f2fSkcpoon * To change the currently used peer address to the specified one.
58077c67f2fSkcpoon */
5817c478bd9Sstevel@tonic-gate void
sctp_set_faddr_current(sctp_t * sctp,sctp_faddr_t * fp)58277c67f2fSkcpoon sctp_set_faddr_current(sctp_t *sctp, sctp_faddr_t *fp)
5837c478bd9Sstevel@tonic-gate {
58477c67f2fSkcpoon /* Now setup the composite header. */
585*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (fp->sf_isv4) {
586*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India IN6_V4MAPPED_TO_IPADDR(&fp->sf_faddr,
5877c478bd9Sstevel@tonic-gate sctp->sctp_ipha->ipha_dst);
588*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India IN6_V4MAPPED_TO_IPADDR(&fp->sf_saddr,
589*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India sctp->sctp_ipha->ipha_src);
5907c478bd9Sstevel@tonic-gate /* update don't fragment bit */
591*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (fp->sf_df) {
5927c478bd9Sstevel@tonic-gate sctp->sctp_ipha->ipha_fragment_offset_and_flags =
5937c478bd9Sstevel@tonic-gate htons(IPH_DF);
5947c478bd9Sstevel@tonic-gate } else {
5957c478bd9Sstevel@tonic-gate sctp->sctp_ipha->ipha_fragment_offset_and_flags = 0;
5967c478bd9Sstevel@tonic-gate }
5977c478bd9Sstevel@tonic-gate } else {
598*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India sctp->sctp_ip6h->ip6_dst = fp->sf_faddr;
599*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India sctp->sctp_ip6h->ip6_src = fp->sf_saddr;
6007c478bd9Sstevel@tonic-gate }
60177c67f2fSkcpoon
60277c67f2fSkcpoon sctp->sctp_current = fp;
603*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India sctp->sctp_mss = fp->sf_pmss;
60477c67f2fSkcpoon
60577c67f2fSkcpoon /* Update the uppper layer for the change. */
60677c67f2fSkcpoon if (!SCTP_IS_DETACHED(sctp))
60777c67f2fSkcpoon sctp_set_ulp_prop(sctp);
6087c478bd9Sstevel@tonic-gate }
6097c478bd9Sstevel@tonic-gate
6107c478bd9Sstevel@tonic-gate void
sctp_redo_faddr_srcs(sctp_t * sctp)6117c478bd9Sstevel@tonic-gate sctp_redo_faddr_srcs(sctp_t *sctp)
6127c478bd9Sstevel@tonic-gate {
6137c478bd9Sstevel@tonic-gate sctp_faddr_t *fp;
6147c478bd9Sstevel@tonic-gate
615*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->sf_next) {
616bd670b35SErik Nordmark sctp_get_dest(sctp, fp);
6177c478bd9Sstevel@tonic-gate }
6187c478bd9Sstevel@tonic-gate }
6197c478bd9Sstevel@tonic-gate
6207c478bd9Sstevel@tonic-gate void
sctp_faddr_alive(sctp_t * sctp,sctp_faddr_t * fp)6217c478bd9Sstevel@tonic-gate sctp_faddr_alive(sctp_t *sctp, sctp_faddr_t *fp)
6227c478bd9Sstevel@tonic-gate {
6235dd46ab5SKacheong Poon int64_t now = LBOLT_FASTPATH64;
6247c478bd9Sstevel@tonic-gate
6255dd46ab5SKacheong Poon /*
6265dd46ab5SKacheong Poon * If we are under memory pressure, we abort association waiting
6275dd46ab5SKacheong Poon * in zero window probing state for too long. We do this by not
6285dd46ab5SKacheong Poon * resetting sctp_strikes. So if sctp_zero_win_probe continues
6295dd46ab5SKacheong Poon * while under memory pressure, this association will eventually
6305dd46ab5SKacheong Poon * time out.
6315dd46ab5SKacheong Poon */
6325dd46ab5SKacheong Poon if (!sctp->sctp_zero_win_probe || !sctp->sctp_sctps->sctps_reclaim) {
6337c478bd9Sstevel@tonic-gate sctp->sctp_strikes = 0;
6345dd46ab5SKacheong Poon }
635*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_strikes = 0;
636*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_lastactive = now;
637*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_hb_expiry = now + SET_HB_INTVL(fp);
638*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_hb_pending = B_FALSE;
639*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (fp->sf_state != SCTP_FADDRS_ALIVE) {
640*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_state = SCTP_FADDRS_ALIVE;
641*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India sctp_intf_event(sctp, fp->sf_faddr, SCTP_ADDR_AVAILABLE, 0);
642c31292eeSkcpoon /* Should have a full IRE now */
643bd670b35SErik Nordmark sctp_get_dest(sctp, fp);
6447c478bd9Sstevel@tonic-gate
64577c67f2fSkcpoon /*
64677c67f2fSkcpoon * If this is the primary, switch back to it now. And
64777c67f2fSkcpoon * we probably want to reset the source addr used to reach
64877c67f2fSkcpoon * it.
649bd670b35SErik Nordmark * Note that if we didn't find a source in sctp_get_dest
650bd670b35SErik Nordmark * then we'd be unreachable at this point in time.
65177c67f2fSkcpoon */
652bd670b35SErik Nordmark if (fp == sctp->sctp_primary &&
653*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_state != SCTP_FADDRS_UNREACH) {
65477c67f2fSkcpoon sctp_set_faddr_current(sctp, fp);
65577c67f2fSkcpoon return;
6567c478bd9Sstevel@tonic-gate }
6577c478bd9Sstevel@tonic-gate }
6587c478bd9Sstevel@tonic-gate }
6597c478bd9Sstevel@tonic-gate
6605dd46ab5SKacheong Poon /*
6615dd46ab5SKacheong Poon * Return B_TRUE if there is still an active peer address with zero strikes;
6625dd46ab5SKacheong Poon * otherwise rturn B_FALSE.
6635dd46ab5SKacheong Poon */
6645dd46ab5SKacheong Poon boolean_t
sctp_is_a_faddr_clean(sctp_t * sctp)6657c478bd9Sstevel@tonic-gate sctp_is_a_faddr_clean(sctp_t *sctp)
6667c478bd9Sstevel@tonic-gate {
6677c478bd9Sstevel@tonic-gate sctp_faddr_t *fp;
6687c478bd9Sstevel@tonic-gate
669*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India for (fp = sctp->sctp_faddrs; fp; fp = fp->sf_next) {
670*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (fp->sf_state == SCTP_FADDRS_ALIVE && fp->sf_strikes == 0) {
6715dd46ab5SKacheong Poon return (B_TRUE);
6727c478bd9Sstevel@tonic-gate }
6737c478bd9Sstevel@tonic-gate }
6747c478bd9Sstevel@tonic-gate
6755dd46ab5SKacheong Poon return (B_FALSE);
6767c478bd9Sstevel@tonic-gate }
6777c478bd9Sstevel@tonic-gate
6787c478bd9Sstevel@tonic-gate /*
6797c478bd9Sstevel@tonic-gate * Returns 0 if there is at leave one other active faddr, -1 if there
6807c478bd9Sstevel@tonic-gate * are none. If there are none left, faddr_dead() will start killing the
6817c478bd9Sstevel@tonic-gate * association.
6827c478bd9Sstevel@tonic-gate * If the downed faddr was the current faddr, a new current faddr
6837c478bd9Sstevel@tonic-gate * will be chosen.
6847c478bd9Sstevel@tonic-gate */
6857c478bd9Sstevel@tonic-gate int
sctp_faddr_dead(sctp_t * sctp,sctp_faddr_t * fp,int newstate)6867c478bd9Sstevel@tonic-gate sctp_faddr_dead(sctp_t *sctp, sctp_faddr_t *fp, int newstate)
6877c478bd9Sstevel@tonic-gate {
6887c478bd9Sstevel@tonic-gate sctp_faddr_t *ofp;
689f4b3ec61Sdh155122 sctp_stack_t *sctps = sctp->sctp_sctps;
6907c478bd9Sstevel@tonic-gate
691*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (fp->sf_state == SCTP_FADDRS_ALIVE) {
692*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India sctp_intf_event(sctp, fp->sf_faddr, SCTP_ADDR_UNREACHABLE, 0);
6937c478bd9Sstevel@tonic-gate }
694*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_state = newstate;
6957c478bd9Sstevel@tonic-gate
6967c478bd9Sstevel@tonic-gate dprint(1, ("sctp_faddr_dead: %x:%x:%x:%x down (state=%d)\n",
697*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India SCTP_PRINTADDR(fp->sf_faddr), newstate));
6987c478bd9Sstevel@tonic-gate
6997c478bd9Sstevel@tonic-gate if (fp == sctp->sctp_current) {
7007c478bd9Sstevel@tonic-gate /* Current faddr down; need to switch it */
7017c478bd9Sstevel@tonic-gate sctp->sctp_current = NULL;
7027c478bd9Sstevel@tonic-gate }
7037c478bd9Sstevel@tonic-gate
7047c478bd9Sstevel@tonic-gate /* Find next alive faddr */
7057c478bd9Sstevel@tonic-gate ofp = fp;
706*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India for (fp = fp->sf_next; fp != NULL; fp = fp->sf_next) {
707*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (fp->sf_state == SCTP_FADDRS_ALIVE) {
7087c478bd9Sstevel@tonic-gate break;
7097c478bd9Sstevel@tonic-gate }
7107c478bd9Sstevel@tonic-gate }
7117c478bd9Sstevel@tonic-gate
7127c478bd9Sstevel@tonic-gate if (fp == NULL) {
7137c478bd9Sstevel@tonic-gate /* Continue from beginning of list */
714*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India for (fp = sctp->sctp_faddrs; fp != ofp; fp = fp->sf_next) {
715*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (fp->sf_state == SCTP_FADDRS_ALIVE) {
7167c478bd9Sstevel@tonic-gate break;
7177c478bd9Sstevel@tonic-gate }
7187c478bd9Sstevel@tonic-gate }
7197c478bd9Sstevel@tonic-gate }
7207c478bd9Sstevel@tonic-gate
72177c67f2fSkcpoon /*
72277c67f2fSkcpoon * Find a new fp, so if the current faddr is dead, use the new fp
72377c67f2fSkcpoon * as the current one.
72477c67f2fSkcpoon */
7257c478bd9Sstevel@tonic-gate if (fp != ofp) {
7267c478bd9Sstevel@tonic-gate if (sctp->sctp_current == NULL) {
7277c478bd9Sstevel@tonic-gate dprint(1, ("sctp_faddr_dead: failover->%x:%x:%x:%x\n",
728*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India SCTP_PRINTADDR(fp->sf_faddr)));
72977c67f2fSkcpoon /*
73077c67f2fSkcpoon * Note that we don't need to reset the source addr
73177c67f2fSkcpoon * of the new fp.
73277c67f2fSkcpoon */
73377c67f2fSkcpoon sctp_set_faddr_current(sctp, fp);
7347c478bd9Sstevel@tonic-gate }
7357c478bd9Sstevel@tonic-gate return (0);
7367c478bd9Sstevel@tonic-gate }
7377c478bd9Sstevel@tonic-gate
7387c478bd9Sstevel@tonic-gate
7397c478bd9Sstevel@tonic-gate /* All faddrs are down; kill the association */
7407c478bd9Sstevel@tonic-gate dprint(1, ("sctp_faddr_dead: all faddrs down, killing assoc\n"));
7415dd46ab5SKacheong Poon SCTPS_BUMP_MIB(sctps, sctpAborted);
7427c478bd9Sstevel@tonic-gate sctp_assoc_event(sctp, sctp->sctp_state < SCTPS_ESTABLISHED ?
7437c478bd9Sstevel@tonic-gate SCTP_CANT_STR_ASSOC : SCTP_COMM_LOST, 0, NULL);
7447c478bd9Sstevel@tonic-gate sctp_clean_death(sctp, sctp->sctp_client_errno ?
7457c478bd9Sstevel@tonic-gate sctp->sctp_client_errno : ETIMEDOUT);
7467c478bd9Sstevel@tonic-gate
7477c478bd9Sstevel@tonic-gate return (-1);
7487c478bd9Sstevel@tonic-gate }
7497c478bd9Sstevel@tonic-gate
7507c478bd9Sstevel@tonic-gate sctp_faddr_t *
sctp_rotate_faddr(sctp_t * sctp,sctp_faddr_t * ofp)7517c478bd9Sstevel@tonic-gate sctp_rotate_faddr(sctp_t *sctp, sctp_faddr_t *ofp)
7527c478bd9Sstevel@tonic-gate {
7537c478bd9Sstevel@tonic-gate sctp_faddr_t *nfp = NULL;
75437d5888bSGeorge Shepherd sctp_faddr_t *saved_fp = NULL;
75537d5888bSGeorge Shepherd int min_strikes;
7567c478bd9Sstevel@tonic-gate
7577c478bd9Sstevel@tonic-gate if (ofp == NULL) {
7587c478bd9Sstevel@tonic-gate ofp = sctp->sctp_current;
7597c478bd9Sstevel@tonic-gate }
76037d5888bSGeorge Shepherd /* Nothing to do */
76137d5888bSGeorge Shepherd if (sctp->sctp_nfaddrs < 2)
76237d5888bSGeorge Shepherd return (ofp);
7637c478bd9Sstevel@tonic-gate
7647c478bd9Sstevel@tonic-gate /*
76537d5888bSGeorge Shepherd * Find the next live peer address with zero strikes. In case
76637d5888bSGeorge Shepherd * there is none, find the one with the lowest number of strikes.
7677c478bd9Sstevel@tonic-gate */
768*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India min_strikes = ofp->sf_strikes;
769*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India nfp = ofp->sf_next;
7706dee1faeSGeorge Shepherd while (nfp != ofp) {
77137d5888bSGeorge Shepherd /* If reached end of list, continue scan from the head */
77237d5888bSGeorge Shepherd if (nfp == NULL) {
77337d5888bSGeorge Shepherd nfp = sctp->sctp_faddrs;
77437d5888bSGeorge Shepherd continue;
77537d5888bSGeorge Shepherd }
776*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (nfp->sf_state == SCTP_FADDRS_ALIVE) {
777*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (nfp->sf_strikes == 0)
77837d5888bSGeorge Shepherd break;
779*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (nfp->sf_strikes < min_strikes) {
780*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India min_strikes = nfp->sf_strikes;
78137d5888bSGeorge Shepherd saved_fp = nfp;
78237d5888bSGeorge Shepherd }
78337d5888bSGeorge Shepherd }
784*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India nfp = nfp->sf_next;
78537d5888bSGeorge Shepherd }
78637d5888bSGeorge Shepherd /* If reached the old address, there is no zero strike path */
78737d5888bSGeorge Shepherd if (nfp == ofp)
78837d5888bSGeorge Shepherd nfp = NULL;
78937d5888bSGeorge Shepherd
79037d5888bSGeorge Shepherd /*
79137d5888bSGeorge Shepherd * If there is a peer address with zero strikes we use that, if not
79237d5888bSGeorge Shepherd * return a peer address with fewer strikes than the one last used,
79337d5888bSGeorge Shepherd * if neither exist we may as well stay with the old one.
79437d5888bSGeorge Shepherd */
79537d5888bSGeorge Shepherd if (nfp != NULL)
7967c478bd9Sstevel@tonic-gate return (nfp);
79737d5888bSGeorge Shepherd if (saved_fp != NULL)
79837d5888bSGeorge Shepherd return (saved_fp);
79937d5888bSGeorge Shepherd return (ofp);
8007c478bd9Sstevel@tonic-gate }
8017c478bd9Sstevel@tonic-gate
8027c478bd9Sstevel@tonic-gate void
sctp_unlink_faddr(sctp_t * sctp,sctp_faddr_t * fp)8037c478bd9Sstevel@tonic-gate sctp_unlink_faddr(sctp_t *sctp, sctp_faddr_t *fp)
8047c478bd9Sstevel@tonic-gate {
8057c478bd9Sstevel@tonic-gate sctp_faddr_t *fpp;
8067c478bd9Sstevel@tonic-gate
8077c478bd9Sstevel@tonic-gate if (!sctp->sctp_faddrs) {
8087c478bd9Sstevel@tonic-gate return;
8097c478bd9Sstevel@tonic-gate }
8107c478bd9Sstevel@tonic-gate
811*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (fp->sf_timer_mp != NULL) {
812*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India sctp_timer_free(fp->sf_timer_mp);
813*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_timer_mp = NULL;
814*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_timer_running = 0;
8157c478bd9Sstevel@tonic-gate }
816*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (fp->sf_rc_timer_mp != NULL) {
817*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India sctp_timer_free(fp->sf_rc_timer_mp);
818*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_rc_timer_mp = NULL;
819*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_rc_timer_running = 0;
8207c478bd9Sstevel@tonic-gate }
821*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (fp->sf_ixa != NULL) {
822*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India ixa_refrele(fp->sf_ixa);
823*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_ixa = NULL;
8247c478bd9Sstevel@tonic-gate }
8257c478bd9Sstevel@tonic-gate
8267c478bd9Sstevel@tonic-gate if (fp == sctp->sctp_faddrs) {
8277c478bd9Sstevel@tonic-gate goto gotit;
8287c478bd9Sstevel@tonic-gate }
8297c478bd9Sstevel@tonic-gate
830*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India for (fpp = sctp->sctp_faddrs; fpp->sf_next != fp; fpp = fpp->sf_next)
8317c478bd9Sstevel@tonic-gate ;
8327c478bd9Sstevel@tonic-gate
8337c478bd9Sstevel@tonic-gate gotit:
8347c478bd9Sstevel@tonic-gate ASSERT(sctp->sctp_conn_tfp != NULL);
8357c478bd9Sstevel@tonic-gate mutex_enter(&sctp->sctp_conn_tfp->tf_lock);
8367c478bd9Sstevel@tonic-gate if (fp == sctp->sctp_faddrs) {
837*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India sctp->sctp_faddrs = fp->sf_next;
8387c478bd9Sstevel@tonic-gate } else {
839*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fpp->sf_next = fp->sf_next;
8407c478bd9Sstevel@tonic-gate }
8417c478bd9Sstevel@tonic-gate mutex_exit(&sctp->sctp_conn_tfp->tf_lock);
8427c478bd9Sstevel@tonic-gate kmem_cache_free(sctp_kmem_faddr_cache, fp);
8431d8c4025Svi117747 sctp->sctp_nfaddrs--;
8447c478bd9Sstevel@tonic-gate }
8457c478bd9Sstevel@tonic-gate
8467c478bd9Sstevel@tonic-gate void
sctp_zap_faddrs(sctp_t * sctp,int caller_holds_lock)8477c478bd9Sstevel@tonic-gate sctp_zap_faddrs(sctp_t *sctp, int caller_holds_lock)
8487c478bd9Sstevel@tonic-gate {
8497c478bd9Sstevel@tonic-gate sctp_faddr_t *fp, *fpn;
8507c478bd9Sstevel@tonic-gate
8517c478bd9Sstevel@tonic-gate if (sctp->sctp_faddrs == NULL) {
8527c478bd9Sstevel@tonic-gate ASSERT(sctp->sctp_lastfaddr == NULL);
8537c478bd9Sstevel@tonic-gate return;
8547c478bd9Sstevel@tonic-gate }
8557c478bd9Sstevel@tonic-gate
8567c478bd9Sstevel@tonic-gate ASSERT(sctp->sctp_lastfaddr != NULL);
8577c478bd9Sstevel@tonic-gate sctp->sctp_lastfaddr = NULL;
8587c478bd9Sstevel@tonic-gate sctp->sctp_current = NULL;
8597c478bd9Sstevel@tonic-gate sctp->sctp_primary = NULL;
8607c478bd9Sstevel@tonic-gate
8617c478bd9Sstevel@tonic-gate sctp_free_faddr_timers(sctp);
8627c478bd9Sstevel@tonic-gate
8637c478bd9Sstevel@tonic-gate if (sctp->sctp_conn_tfp != NULL && !caller_holds_lock) {
8647c478bd9Sstevel@tonic-gate /* in conn fanout; need to hold lock */
8657c478bd9Sstevel@tonic-gate mutex_enter(&sctp->sctp_conn_tfp->tf_lock);
8667c478bd9Sstevel@tonic-gate }
8677c478bd9Sstevel@tonic-gate
8687c478bd9Sstevel@tonic-gate for (fp = sctp->sctp_faddrs; fp; fp = fpn) {
869*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fpn = fp->sf_next;
870*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (fp->sf_ixa != NULL) {
871*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India ixa_refrele(fp->sf_ixa);
872*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_ixa = NULL;
873bd670b35SErik Nordmark }
8747c478bd9Sstevel@tonic-gate kmem_cache_free(sctp_kmem_faddr_cache, fp);
8751d8c4025Svi117747 sctp->sctp_nfaddrs--;
8767c478bd9Sstevel@tonic-gate }
8777c478bd9Sstevel@tonic-gate
8787c478bd9Sstevel@tonic-gate sctp->sctp_faddrs = NULL;
8791d8c4025Svi117747 ASSERT(sctp->sctp_nfaddrs == 0);
8807c478bd9Sstevel@tonic-gate if (sctp->sctp_conn_tfp != NULL && !caller_holds_lock) {
8817c478bd9Sstevel@tonic-gate mutex_exit(&sctp->sctp_conn_tfp->tf_lock);
8827c478bd9Sstevel@tonic-gate }
8837c478bd9Sstevel@tonic-gate
8847c478bd9Sstevel@tonic-gate }
8857c478bd9Sstevel@tonic-gate
8867c478bd9Sstevel@tonic-gate void
sctp_zap_addrs(sctp_t * sctp)8877c478bd9Sstevel@tonic-gate sctp_zap_addrs(sctp_t *sctp)
8887c478bd9Sstevel@tonic-gate {
8897c478bd9Sstevel@tonic-gate sctp_zap_faddrs(sctp, 0);
8907c478bd9Sstevel@tonic-gate sctp_free_saddrs(sctp);
8917c478bd9Sstevel@tonic-gate }
8927c478bd9Sstevel@tonic-gate
8937c478bd9Sstevel@tonic-gate /*
894bd670b35SErik Nordmark * Build two SCTP header templates; one for IPv4 and one for IPv6.
895bd670b35SErik Nordmark * Store them in sctp_iphc and sctp_iphc6 respectively (and related fields).
896bd670b35SErik Nordmark * There are no IP addresses in the templates, but the port numbers and
897bd670b35SErik Nordmark * verifier are field in from the conn_t and sctp_t.
8987c478bd9Sstevel@tonic-gate *
899bd670b35SErik Nordmark * Returns failure if can't allocate memory, or if there is a problem
900bd670b35SErik Nordmark * with a routing header/option.
901bd670b35SErik Nordmark *
902bd670b35SErik Nordmark * We allocate space for the minimum sctp header (sctp_hdr_t).
903bd670b35SErik Nordmark *
904bd670b35SErik Nordmark * We massage an routing option/header. There is no checksum implication
905bd670b35SErik Nordmark * for a routing header for sctp.
906bd670b35SErik Nordmark *
907bd670b35SErik Nordmark * Caller needs to update conn_wroff if desired.
908bd670b35SErik Nordmark *
909bd670b35SErik Nordmark * TSol notes: This assumes that a SCTP association has a single peer label
910bd670b35SErik Nordmark * since we only track a single pair of ipp_label_v4/v6 and not a separate one
911bd670b35SErik Nordmark * for each faddr.
9127c478bd9Sstevel@tonic-gate */
9137c478bd9Sstevel@tonic-gate int
sctp_build_hdrs(sctp_t * sctp,int sleep)914bd670b35SErik Nordmark sctp_build_hdrs(sctp_t *sctp, int sleep)
9157c478bd9Sstevel@tonic-gate {
916bd670b35SErik Nordmark conn_t *connp = sctp->sctp_connp;
917bd670b35SErik Nordmark ip_pkt_t *ipp = &connp->conn_xmit_ipp;
918bd670b35SErik Nordmark uint_t ip_hdr_length;
919bd670b35SErik Nordmark uchar_t *hdrs;
9207c478bd9Sstevel@tonic-gate uint_t hdrs_len;
921bd670b35SErik Nordmark uint_t ulp_hdr_length = sizeof (sctp_hdr_t);
922bd670b35SErik Nordmark ipha_t *ipha;
923bd670b35SErik Nordmark ip6_t *ip6h;
924bd670b35SErik Nordmark sctp_hdr_t *sctph;
925bd670b35SErik Nordmark in6_addr_t v6src, v6dst;
926bd670b35SErik Nordmark ipaddr_t v4src, v4dst;
92745916cd2Sjpk
928bd670b35SErik Nordmark v4src = connp->conn_saddr_v4;
929bd670b35SErik Nordmark v4dst = connp->conn_faddr_v4;
930bd670b35SErik Nordmark v6src = connp->conn_saddr_v6;
931bd670b35SErik Nordmark v6dst = connp->conn_faddr_v6;
932bd670b35SErik Nordmark
933bd670b35SErik Nordmark /* First do IPv4 header */
934bd670b35SErik Nordmark ip_hdr_length = ip_total_hdrs_len_v4(ipp);
935bd670b35SErik Nordmark
936bd670b35SErik Nordmark /* In case of TX label and IP options it can be too much */
937bd670b35SErik Nordmark if (ip_hdr_length > IP_MAX_HDR_LENGTH) {
938bd670b35SErik Nordmark /* Preserves existing TX errno for this */
939bd670b35SErik Nordmark return (EHOSTUNREACH);
940bd670b35SErik Nordmark }
941bd670b35SErik Nordmark hdrs_len = ip_hdr_length + ulp_hdr_length;
9427c478bd9Sstevel@tonic-gate ASSERT(hdrs_len != 0);
943bd670b35SErik Nordmark
944bd670b35SErik Nordmark if (hdrs_len != sctp->sctp_iphc_len) {
945bd670b35SErik Nordmark /* Allocate new before we free any old */
946bd670b35SErik Nordmark hdrs = kmem_alloc(hdrs_len, sleep);
9477c478bd9Sstevel@tonic-gate if (hdrs == NULL)
9487c478bd9Sstevel@tonic-gate return (ENOMEM);
9497c478bd9Sstevel@tonic-gate
950bd670b35SErik Nordmark if (sctp->sctp_iphc != NULL)
951bd670b35SErik Nordmark kmem_free(sctp->sctp_iphc, sctp->sctp_iphc_len);
952bd670b35SErik Nordmark sctp->sctp_iphc = hdrs;
953bd670b35SErik Nordmark sctp->sctp_iphc_len = hdrs_len;
954bd670b35SErik Nordmark } else {
955bd670b35SErik Nordmark hdrs = sctp->sctp_iphc;
956bd670b35SErik Nordmark }
957bd670b35SErik Nordmark sctp->sctp_hdr_len = sctp->sctp_iphc_len;
958bd670b35SErik Nordmark sctp->sctp_ip_hdr_len = ip_hdr_length;
959bd670b35SErik Nordmark
960bd670b35SErik Nordmark sctph = (sctp_hdr_t *)(hdrs + ip_hdr_length);
961bd670b35SErik Nordmark sctp->sctp_sctph = sctph;
962bd670b35SErik Nordmark sctph->sh_sport = connp->conn_lport;
963bd670b35SErik Nordmark sctph->sh_dport = connp->conn_fport;
964bd670b35SErik Nordmark sctph->sh_verf = sctp->sctp_fvtag;
965bd670b35SErik Nordmark sctph->sh_chksum = 0;
966bd670b35SErik Nordmark
967bd670b35SErik Nordmark ipha = (ipha_t *)hdrs;
968bd670b35SErik Nordmark sctp->sctp_ipha = ipha;
969bd670b35SErik Nordmark
970bd670b35SErik Nordmark ipha->ipha_src = v4src;
971bd670b35SErik Nordmark ipha->ipha_dst = v4dst;
972bd670b35SErik Nordmark ip_build_hdrs_v4(hdrs, ip_hdr_length, ipp, connp->conn_proto);
973bd670b35SErik Nordmark ipha->ipha_length = htons(hdrs_len);
974bd670b35SErik Nordmark ipha->ipha_fragment_offset_and_flags = 0;
975bd670b35SErik Nordmark
976bd670b35SErik Nordmark if (ipp->ipp_fields & IPPF_IPV4_OPTIONS)
977bd670b35SErik Nordmark (void) ip_massage_options(ipha, connp->conn_netstack);
978bd670b35SErik Nordmark
979bd670b35SErik Nordmark /* Now IPv6 */
980bd670b35SErik Nordmark ip_hdr_length = ip_total_hdrs_len_v6(ipp);
981bd670b35SErik Nordmark hdrs_len = ip_hdr_length + ulp_hdr_length;
982bd670b35SErik Nordmark ASSERT(hdrs_len != 0);
983bd670b35SErik Nordmark
984bd670b35SErik Nordmark if (hdrs_len != sctp->sctp_iphc6_len) {
985bd670b35SErik Nordmark /* Allocate new before we free any old */
986bd670b35SErik Nordmark hdrs = kmem_alloc(hdrs_len, sleep);
987bd670b35SErik Nordmark if (hdrs == NULL)
988bd670b35SErik Nordmark return (ENOMEM);
989bd670b35SErik Nordmark
990bd670b35SErik Nordmark if (sctp->sctp_iphc6 != NULL)
9917c478bd9Sstevel@tonic-gate kmem_free(sctp->sctp_iphc6, sctp->sctp_iphc6_len);
9927c478bd9Sstevel@tonic-gate sctp->sctp_iphc6 = hdrs;
9937c478bd9Sstevel@tonic-gate sctp->sctp_iphc6_len = hdrs_len;
9947c478bd9Sstevel@tonic-gate } else {
995bd670b35SErik Nordmark hdrs = sctp->sctp_iphc6;
9967c478bd9Sstevel@tonic-gate }
997bd670b35SErik Nordmark sctp->sctp_hdr6_len = sctp->sctp_iphc6_len;
998bd670b35SErik Nordmark sctp->sctp_ip_hdr6_len = ip_hdr_length;
9997c478bd9Sstevel@tonic-gate
1000bd670b35SErik Nordmark sctph = (sctp_hdr_t *)(hdrs + ip_hdr_length);
1001bd670b35SErik Nordmark sctp->sctp_sctph6 = sctph;
1002bd670b35SErik Nordmark sctph->sh_sport = connp->conn_lport;
1003bd670b35SErik Nordmark sctph->sh_dport = connp->conn_fport;
1004bd670b35SErik Nordmark sctph->sh_verf = sctp->sctp_fvtag;
1005bd670b35SErik Nordmark sctph->sh_chksum = 0;
10067c478bd9Sstevel@tonic-gate
1007bd670b35SErik Nordmark ip6h = (ip6_t *)hdrs;
1008bd670b35SErik Nordmark sctp->sctp_ip6h = ip6h;
10097c478bd9Sstevel@tonic-gate
1010bd670b35SErik Nordmark ip6h->ip6_src = v6src;
1011bd670b35SErik Nordmark ip6h->ip6_dst = v6dst;
1012bd670b35SErik Nordmark ip_build_hdrs_v6(hdrs, ip_hdr_length, ipp, connp->conn_proto,
1013bd670b35SErik Nordmark connp->conn_flowinfo);
1014bd670b35SErik Nordmark ip6h->ip6_plen = htons(hdrs_len - IPV6_HDR_LEN);
1015bd670b35SErik Nordmark
1016bd670b35SErik Nordmark if (ipp->ipp_fields & IPPF_RTHDR) {
1017bd670b35SErik Nordmark uint8_t *end;
10187c478bd9Sstevel@tonic-gate ip6_rthdr_t *rth;
10197c478bd9Sstevel@tonic-gate
1020bd670b35SErik Nordmark end = (uint8_t *)ip6h + ip_hdr_length;
1021bd670b35SErik Nordmark rth = ip_find_rthdr_v6(ip6h, end);
1022f4b3ec61Sdh155122 if (rth != NULL) {
1023bd670b35SErik Nordmark (void) ip_massage_options_v6(ip6h, rth,
1024bd670b35SErik Nordmark connp->conn_netstack);
10257c478bd9Sstevel@tonic-gate }
10267c478bd9Sstevel@tonic-gate
10277c478bd9Sstevel@tonic-gate /*
1028bd670b35SErik Nordmark * Verify that the first hop isn't a mapped address.
1029bd670b35SErik Nordmark * Routers along the path need to do this verification
1030bd670b35SErik Nordmark * for subsequent hops.
10317c478bd9Sstevel@tonic-gate */
1032bd670b35SErik Nordmark if (IN6_IS_ADDR_V4MAPPED(&ip6h->ip6_dst))
1033bd670b35SErik Nordmark return (EADDRNOTAVAIL);
103445916cd2Sjpk }
103545916cd2Sjpk return (0);
103645916cd2Sjpk }
103745916cd2Sjpk
103845916cd2Sjpk static int
sctp_v4_label(sctp_t * sctp,sctp_faddr_t * fp)1039bd670b35SErik Nordmark sctp_v4_label(sctp_t *sctp, sctp_faddr_t *fp)
104045916cd2Sjpk {
1041bd670b35SErik Nordmark conn_t *connp = sctp->sctp_connp;
104245916cd2Sjpk
1043*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India ASSERT(fp->sf_ixa->ixa_flags & IXAF_IS_IPV4);
1044*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India return (conn_update_label(connp, fp->sf_ixa, &fp->sf_faddr,
1045bd670b35SErik Nordmark &connp->conn_xmit_ipp));
1046bd670b35SErik Nordmark }
1047bd670b35SErik Nordmark
1048bd670b35SErik Nordmark static int
sctp_v6_label(sctp_t * sctp,sctp_faddr_t * fp)1049bd670b35SErik Nordmark sctp_v6_label(sctp_t *sctp, sctp_faddr_t *fp)
1050bd670b35SErik Nordmark {
1051bd670b35SErik Nordmark conn_t *connp = sctp->sctp_connp;
1052bd670b35SErik Nordmark
1053*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India ASSERT(!(fp->sf_ixa->ixa_flags & IXAF_IS_IPV4));
1054*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India return (conn_update_label(connp, fp->sf_ixa, &fp->sf_faddr,
1055bd670b35SErik Nordmark &connp->conn_xmit_ipp));
105645916cd2Sjpk }
105745916cd2Sjpk
10587c478bd9Sstevel@tonic-gate /*
10597c478bd9Sstevel@tonic-gate * XXX implement more sophisticated logic
1060bd670b35SErik Nordmark *
1061bd670b35SErik Nordmark * Tsol note: We have already verified the addresses using tsol_check_dest
1062bd670b35SErik Nordmark * in sctp_add_faddr, thus no need to redo that here.
1063bd670b35SErik Nordmark * We do setup ipp_label_v4 and ipp_label_v6 based on which addresses
1064bd670b35SErik Nordmark * we have.
10657c478bd9Sstevel@tonic-gate */
106645916cd2Sjpk int
sctp_set_hdraddrs(sctp_t * sctp)106777c67f2fSkcpoon sctp_set_hdraddrs(sctp_t *sctp)
10687c478bd9Sstevel@tonic-gate {
10697c478bd9Sstevel@tonic-gate sctp_faddr_t *fp;
10707c478bd9Sstevel@tonic-gate int gotv4 = 0;
10717c478bd9Sstevel@tonic-gate int gotv6 = 0;
1072bd670b35SErik Nordmark conn_t *connp = sctp->sctp_connp;
10737c478bd9Sstevel@tonic-gate
10747c478bd9Sstevel@tonic-gate ASSERT(sctp->sctp_faddrs != NULL);
10757c478bd9Sstevel@tonic-gate ASSERT(sctp->sctp_nsaddrs > 0);
10767c478bd9Sstevel@tonic-gate
10777c478bd9Sstevel@tonic-gate /* Set up using the primary first */
1078*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India connp->conn_faddr_v6 = sctp->sctp_primary->sf_faddr;
10797c478bd9Sstevel@tonic-gate /* saddr may be unspec; make_mp() will handle this */
1080*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India connp->conn_saddr_v6 = sctp->sctp_primary->sf_saddr;
1081bd670b35SErik Nordmark connp->conn_laddr_v6 = connp->conn_saddr_v6;
1082*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (IN6_IS_ADDR_V4MAPPED(&sctp->sctp_primary->sf_faddr)) {
1083bd670b35SErik Nordmark if (!is_system_labeled() ||
1084bd670b35SErik Nordmark sctp_v4_label(sctp, sctp->sctp_primary) == 0) {
10857c478bd9Sstevel@tonic-gate gotv4 = 1;
1086bd670b35SErik Nordmark if (connp->conn_family == AF_INET) {
1087bd670b35SErik Nordmark goto done;
10887c478bd9Sstevel@tonic-gate }
108945916cd2Sjpk }
10907c478bd9Sstevel@tonic-gate } else {
1091bd670b35SErik Nordmark if (!is_system_labeled() ||
1092bd670b35SErik Nordmark sctp_v6_label(sctp, sctp->sctp_primary) == 0) {
10937c478bd9Sstevel@tonic-gate gotv6 = 1;
10947c478bd9Sstevel@tonic-gate }
1095bd670b35SErik Nordmark }
10967c478bd9Sstevel@tonic-gate
1097*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India for (fp = sctp->sctp_faddrs; fp; fp = fp->sf_next) {
1098*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (!gotv4 && IN6_IS_ADDR_V4MAPPED(&fp->sf_faddr)) {
1099bd670b35SErik Nordmark if (!is_system_labeled() ||
1100bd670b35SErik Nordmark sctp_v4_label(sctp, fp) == 0) {
11017c478bd9Sstevel@tonic-gate gotv4 = 1;
1102bd670b35SErik Nordmark if (connp->conn_family == AF_INET || gotv6) {
11037c478bd9Sstevel@tonic-gate break;
11047c478bd9Sstevel@tonic-gate }
110545916cd2Sjpk }
1106*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India } else if (!gotv6 && !IN6_IS_ADDR_V4MAPPED(&fp->sf_faddr)) {
1107bd670b35SErik Nordmark if (!is_system_labeled() ||
1108bd670b35SErik Nordmark sctp_v6_label(sctp, fp) == 0) {
11097c478bd9Sstevel@tonic-gate gotv6 = 1;
111045916cd2Sjpk if (gotv4)
11117c478bd9Sstevel@tonic-gate break;
11127c478bd9Sstevel@tonic-gate }
11137c478bd9Sstevel@tonic-gate }
11147c478bd9Sstevel@tonic-gate }
11157c478bd9Sstevel@tonic-gate
1116bd670b35SErik Nordmark done:
111745916cd2Sjpk if (!gotv4 && !gotv6)
111845916cd2Sjpk return (EACCES);
111945916cd2Sjpk
112045916cd2Sjpk return (0);
11217c478bd9Sstevel@tonic-gate }
11227c478bd9Sstevel@tonic-gate
1123c513743fSGeorge Shepherd /*
1124c513743fSGeorge Shepherd * got_errchunk is set B_TRUE only if called from validate_init_params(), when
1125c513743fSGeorge Shepherd * an ERROR chunk is already prepended the size of which needs updating for
1126c513743fSGeorge Shepherd * additional unrecognized parameters. Other callers either prepend the ERROR
1127c513743fSGeorge Shepherd * chunk with the correct size after calling this function, or they are calling
1128c513743fSGeorge Shepherd * to add an invalid parameter to an INIT_ACK chunk, in that case no ERROR chunk
1129c513743fSGeorge Shepherd * exists, the CAUSE blocks go into the INIT_ACK directly.
1130c513743fSGeorge Shepherd *
1131c513743fSGeorge Shepherd * *errmp will be non-NULL both when adding an additional CAUSE block to an
1132c513743fSGeorge Shepherd * existing prepended COOKIE ERROR chunk (processing params of an INIT_ACK),
1133c513743fSGeorge Shepherd * and when adding unrecognized parameters after the first, to an INIT_ACK
1134c513743fSGeorge Shepherd * (processing params of an INIT chunk).
1135c513743fSGeorge Shepherd */
11367c478bd9Sstevel@tonic-gate void
sctp_add_unrec_parm(sctp_parm_hdr_t * uph,mblk_t ** errmp,boolean_t got_errchunk)1137c513743fSGeorge Shepherd sctp_add_unrec_parm(sctp_parm_hdr_t *uph, mblk_t **errmp,
1138c513743fSGeorge Shepherd boolean_t got_errchunk)
11397c478bd9Sstevel@tonic-gate {
11407c478bd9Sstevel@tonic-gate mblk_t *mp;
11417c478bd9Sstevel@tonic-gate sctp_parm_hdr_t *ph;
11427c478bd9Sstevel@tonic-gate size_t len;
11437c478bd9Sstevel@tonic-gate int pad;
114477ebe684SGeorge Shepherd sctp_chunk_hdr_t *ecp;
11457c478bd9Sstevel@tonic-gate
11467c478bd9Sstevel@tonic-gate len = sizeof (*ph) + ntohs(uph->sph_len);
114777ebe684SGeorge Shepherd if ((pad = len % SCTP_ALIGN) != 0) {
114877ebe684SGeorge Shepherd pad = SCTP_ALIGN - pad;
11497c478bd9Sstevel@tonic-gate len += pad;
11507c478bd9Sstevel@tonic-gate }
11517c478bd9Sstevel@tonic-gate mp = allocb(len, BPRI_MED);
11527c478bd9Sstevel@tonic-gate if (mp == NULL) {
11537c478bd9Sstevel@tonic-gate return;
11547c478bd9Sstevel@tonic-gate }
11557c478bd9Sstevel@tonic-gate
11567c478bd9Sstevel@tonic-gate ph = (sctp_parm_hdr_t *)(mp->b_rptr);
11577c478bd9Sstevel@tonic-gate ph->sph_type = htons(PARM_UNRECOGNIZED);
11587c478bd9Sstevel@tonic-gate ph->sph_len = htons(len - pad);
11597c478bd9Sstevel@tonic-gate
11607c478bd9Sstevel@tonic-gate /* copy in the unrecognized parameter */
11617c478bd9Sstevel@tonic-gate bcopy(uph, ph + 1, ntohs(uph->sph_len));
11627c478bd9Sstevel@tonic-gate
116377ebe684SGeorge Shepherd if (pad != 0)
116477ebe684SGeorge Shepherd bzero((mp->b_rptr + len - pad), pad);
116577ebe684SGeorge Shepherd
11667c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + len;
11677c478bd9Sstevel@tonic-gate if (*errmp != NULL) {
116877ebe684SGeorge Shepherd /*
1169c513743fSGeorge Shepherd * Update total length if an ERROR chunk, then link
1170c513743fSGeorge Shepherd * this CAUSE block to the possible chain of CAUSE
1171c513743fSGeorge Shepherd * blocks attached to the ERROR chunk or INIT_ACK
1172c513743fSGeorge Shepherd * being created.
117377ebe684SGeorge Shepherd */
1174c513743fSGeorge Shepherd if (got_errchunk) {
1175c513743fSGeorge Shepherd /* ERROR chunk already prepended */
117677ebe684SGeorge Shepherd ecp = (sctp_chunk_hdr_t *)((*errmp)->b_rptr);
117777ebe684SGeorge Shepherd ecp->sch_len = htons(ntohs(ecp->sch_len) + len);
1178c513743fSGeorge Shepherd }
11797c478bd9Sstevel@tonic-gate linkb(*errmp, mp);
11807c478bd9Sstevel@tonic-gate } else {
11817c478bd9Sstevel@tonic-gate *errmp = mp;
11827c478bd9Sstevel@tonic-gate }
11837c478bd9Sstevel@tonic-gate }
11847c478bd9Sstevel@tonic-gate
11857c478bd9Sstevel@tonic-gate /*
11867c478bd9Sstevel@tonic-gate * o Bounds checking
11877c478bd9Sstevel@tonic-gate * o Updates remaining
11887c478bd9Sstevel@tonic-gate * o Checks alignment
11897c478bd9Sstevel@tonic-gate */
11907c478bd9Sstevel@tonic-gate sctp_parm_hdr_t *
sctp_next_parm(sctp_parm_hdr_t * current,ssize_t * remaining)11917c478bd9Sstevel@tonic-gate sctp_next_parm(sctp_parm_hdr_t *current, ssize_t *remaining)
11927c478bd9Sstevel@tonic-gate {
11937c478bd9Sstevel@tonic-gate int pad;
11947c478bd9Sstevel@tonic-gate uint16_t len;
11957c478bd9Sstevel@tonic-gate
11967c478bd9Sstevel@tonic-gate len = ntohs(current->sph_len);
11977c478bd9Sstevel@tonic-gate *remaining -= len;
11987c478bd9Sstevel@tonic-gate if (*remaining < sizeof (*current) || len < sizeof (*current)) {
11997c478bd9Sstevel@tonic-gate return (NULL);
12007c478bd9Sstevel@tonic-gate }
12017c478bd9Sstevel@tonic-gate if ((pad = len & (SCTP_ALIGN - 1)) != 0) {
12027c478bd9Sstevel@tonic-gate pad = SCTP_ALIGN - pad;
12037c478bd9Sstevel@tonic-gate *remaining -= pad;
12047c478bd9Sstevel@tonic-gate }
12057c478bd9Sstevel@tonic-gate /*LINTED pointer cast may result in improper alignment*/
12067c478bd9Sstevel@tonic-gate current = (sctp_parm_hdr_t *)((char *)current + len + pad);
12077c478bd9Sstevel@tonic-gate return (current);
12087c478bd9Sstevel@tonic-gate }
12097c478bd9Sstevel@tonic-gate
12107c478bd9Sstevel@tonic-gate /*
12117c478bd9Sstevel@tonic-gate * Sets the address parameters given in the INIT chunk into sctp's
12127c478bd9Sstevel@tonic-gate * faddrs; if psctp is non-NULL, copies psctp's saddrs. If there are
12137c478bd9Sstevel@tonic-gate * no address parameters in the INIT chunk, a single faddr is created
12147c478bd9Sstevel@tonic-gate * from the ip hdr at the beginning of pkt.
12157c478bd9Sstevel@tonic-gate * If there already are existing addresses hanging from sctp, merge
12167c478bd9Sstevel@tonic-gate * them in, if the old info contains addresses which are not present
12177c478bd9Sstevel@tonic-gate * in this new info, get rid of them, and clean the pointers if there's
12187c478bd9Sstevel@tonic-gate * messages which have this as their target address.
12197c478bd9Sstevel@tonic-gate *
1220f551bb10Svi117747 * We also re-adjust the source address list here since the list may
1221f551bb10Svi117747 * contain more than what is actually part of the association. If
1222f551bb10Svi117747 * we get here from sctp_send_cookie_echo(), we are on the active
1223f551bb10Svi117747 * side and psctp will be NULL and ich will be the INIT-ACK chunk.
1224f551bb10Svi117747 * If we get here from sctp_accept_comm(), ich will be the INIT chunk
1225f551bb10Svi117747 * and psctp will the listening endpoint.
1226f551bb10Svi117747 *
1227f551bb10Svi117747 * INIT processing: When processing the INIT we inherit the src address
1228f551bb10Svi117747 * list from the listener. For a loopback or linklocal association, we
1229f551bb10Svi117747 * delete the list and just take the address from the IP header (since
1230f551bb10Svi117747 * that's how we created the INIT-ACK). Additionally, for loopback we
1231f551bb10Svi117747 * ignore the address params in the INIT. For determining which address
1232f551bb10Svi117747 * types were sent in the INIT-ACK we follow the same logic as in
1233f551bb10Svi117747 * creating the INIT-ACK. We delete addresses of the type that are not
1234f551bb10Svi117747 * supported by the peer.
1235f551bb10Svi117747 *
1236f551bb10Svi117747 * INIT-ACK processing: When processing the INIT-ACK since we had not
1237f551bb10Svi117747 * included addr params for loopback or linklocal addresses when creating
1238f551bb10Svi117747 * the INIT, we just use the address from the IP header. Further, for
1239f551bb10Svi117747 * loopback we ignore the addr param list. We mark addresses of the
1240f551bb10Svi117747 * type not supported by the peer as unconfirmed.
1241f551bb10Svi117747 *
1242f551bb10Svi117747 * In case of INIT processing we look for supported address types in the
1243f551bb10Svi117747 * supported address param, if present. In both cases the address type in
1244f551bb10Svi117747 * the IP header is supported as well as types for addresses in the param
1245f551bb10Svi117747 * list, if any.
1246f551bb10Svi117747 *
1247f551bb10Svi117747 * Once we have the supported address types sctp_check_saddr() runs through
1248f551bb10Svi117747 * the source address list and deletes or marks as unconfirmed address of
1249f551bb10Svi117747 * types not supported by the peer.
1250f551bb10Svi117747 *
12517c478bd9Sstevel@tonic-gate * Returns 0 on success, sys errno on failure
12527c478bd9Sstevel@tonic-gate */
12537c478bd9Sstevel@tonic-gate int
sctp_get_addrparams(sctp_t * sctp,sctp_t * psctp,mblk_t * pkt,sctp_chunk_hdr_t * ich,uint_t * sctp_options)12547c478bd9Sstevel@tonic-gate sctp_get_addrparams(sctp_t *sctp, sctp_t *psctp, mblk_t *pkt,
12557c478bd9Sstevel@tonic-gate sctp_chunk_hdr_t *ich, uint_t *sctp_options)
12567c478bd9Sstevel@tonic-gate {
12577c478bd9Sstevel@tonic-gate sctp_init_chunk_t *init;
12587c478bd9Sstevel@tonic-gate ipha_t *iph;
12597c478bd9Sstevel@tonic-gate ip6_t *ip6h;
1260f551bb10Svi117747 in6_addr_t hdrsaddr[1];
1261f551bb10Svi117747 in6_addr_t hdrdaddr[1];
12627c478bd9Sstevel@tonic-gate sctp_parm_hdr_t *ph;
12637c478bd9Sstevel@tonic-gate ssize_t remaining;
12647c478bd9Sstevel@tonic-gate int isv4;
12657c478bd9Sstevel@tonic-gate int err;
12667c478bd9Sstevel@tonic-gate sctp_faddr_t *fp;
1267f551bb10Svi117747 int supp_af = 0;
1268f551bb10Svi117747 boolean_t check_saddr = B_TRUE;
12691d8c4025Svi117747 in6_addr_t curaddr;
1270f4b3ec61Sdh155122 sctp_stack_t *sctps = sctp->sctp_sctps;
1271bd670b35SErik Nordmark conn_t *connp = sctp->sctp_connp;
12727c478bd9Sstevel@tonic-gate
12737c478bd9Sstevel@tonic-gate if (sctp_options != NULL)
12747c478bd9Sstevel@tonic-gate *sctp_options = 0;
12757c478bd9Sstevel@tonic-gate
1276f551bb10Svi117747 /* extract the address from the IP header */
1277f551bb10Svi117747 isv4 = (IPH_HDR_VERSION(pkt->b_rptr) == IPV4_VERSION);
1278f551bb10Svi117747 if (isv4) {
1279f551bb10Svi117747 iph = (ipha_t *)pkt->b_rptr;
1280f551bb10Svi117747 IN6_IPADDR_TO_V4MAPPED(iph->ipha_src, hdrsaddr);
1281f551bb10Svi117747 IN6_IPADDR_TO_V4MAPPED(iph->ipha_dst, hdrdaddr);
1282f551bb10Svi117747 supp_af |= PARM_SUPP_V4;
1283f551bb10Svi117747 } else {
1284f551bb10Svi117747 ip6h = (ip6_t *)pkt->b_rptr;
1285f551bb10Svi117747 hdrsaddr[0] = ip6h->ip6_src;
1286f551bb10Svi117747 hdrdaddr[0] = ip6h->ip6_dst;
1287f551bb10Svi117747 supp_af |= PARM_SUPP_V6;
1288f551bb10Svi117747 }
1289f551bb10Svi117747
1290f551bb10Svi117747 /*
1291f551bb10Svi117747 * Unfortunately, we can't delay this because adding an faddr
1292f551bb10Svi117747 * looks for the presence of the source address (from the ire
1293f551bb10Svi117747 * for the faddr) in the source address list. We could have
1294f551bb10Svi117747 * delayed this if, say, this was a loopback/linklocal connection.
1295f551bb10Svi117747 * Now, we just end up nuking this list and taking the addr from
1296f551bb10Svi117747 * the IP header for loopback/linklocal.
1297f551bb10Svi117747 */
12987c478bd9Sstevel@tonic-gate if (psctp != NULL && psctp->sctp_nsaddrs > 0) {
12997c478bd9Sstevel@tonic-gate ASSERT(sctp->sctp_nsaddrs == 0);
13007c478bd9Sstevel@tonic-gate
13017c478bd9Sstevel@tonic-gate err = sctp_dup_saddrs(psctp, sctp, KM_NOSLEEP);
13027c478bd9Sstevel@tonic-gate if (err != 0)
13037c478bd9Sstevel@tonic-gate return (err);
13047c478bd9Sstevel@tonic-gate }
1305f551bb10Svi117747 /*
1306f551bb10Svi117747 * We will add the faddr before parsing the address list as this
1307f551bb10Svi117747 * might be a loopback connection and we would not have to
1308f551bb10Svi117747 * go through the list.
1309f551bb10Svi117747 *
1310f551bb10Svi117747 * Make sure the header's addr is in the list
1311f551bb10Svi117747 */
1312f551bb10Svi117747 fp = sctp_lookup_faddr(sctp, hdrsaddr);
1313f551bb10Svi117747 if (fp == NULL) {
1314f551bb10Svi117747 /* not included; add it now */
131577c67f2fSkcpoon err = sctp_add_faddr(sctp, hdrsaddr, KM_NOSLEEP, B_TRUE);
131645916cd2Sjpk if (err != 0)
131745916cd2Sjpk return (err);
13187c478bd9Sstevel@tonic-gate
1319f551bb10Svi117747 /* sctp_faddrs will be the hdr addr */
1320f551bb10Svi117747 fp = sctp->sctp_faddrs;
13217c478bd9Sstevel@tonic-gate }
1322f551bb10Svi117747 /* make the header addr the primary */
13231d8c4025Svi117747
13241d8c4025Svi117747 if (cl_sctp_assoc_change != NULL && psctp == NULL)
1325*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India curaddr = sctp->sctp_current->sf_faddr;
13261d8c4025Svi117747
1327f551bb10Svi117747 sctp->sctp_primary = fp;
1328f551bb10Svi117747 sctp->sctp_current = fp;
1329*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India sctp->sctp_mss = fp->sf_pmss;
13307c478bd9Sstevel@tonic-gate
1331f551bb10Svi117747 /* For loopback connections & linklocal get address from the header */
1332f551bb10Svi117747 if (sctp->sctp_loopback || sctp->sctp_linklocal) {
1333f551bb10Svi117747 if (sctp->sctp_nsaddrs != 0)
1334f551bb10Svi117747 sctp_free_saddrs(sctp);
13351d8c4025Svi117747 if ((err = sctp_saddr_add_addr(sctp, hdrdaddr, 0)) != 0)
1336f551bb10Svi117747 return (err);
1337f551bb10Svi117747 /* For loopback ignore address list */
13387c478bd9Sstevel@tonic-gate if (sctp->sctp_loopback)
1339f551bb10Svi117747 return (0);
1340f551bb10Svi117747 check_saddr = B_FALSE;
1341f551bb10Svi117747 }
13427c478bd9Sstevel@tonic-gate
13437c478bd9Sstevel@tonic-gate /* Walk the params in the INIT [ACK], pulling out addr params */
13447c478bd9Sstevel@tonic-gate remaining = ntohs(ich->sch_len) - sizeof (*ich) -
13457c478bd9Sstevel@tonic-gate sizeof (sctp_init_chunk_t);
13467c478bd9Sstevel@tonic-gate if (remaining < sizeof (*ph)) {
1347f551bb10Svi117747 if (check_saddr) {
1348f551bb10Svi117747 sctp_check_saddr(sctp, supp_af, psctp == NULL ?
1349c31292eeSkcpoon B_FALSE : B_TRUE, hdrdaddr);
13507c478bd9Sstevel@tonic-gate }
13511d8c4025Svi117747 ASSERT(sctp_saddr_lookup(sctp, hdrdaddr, 0) != NULL);
1352f551bb10Svi117747 return (0);
1353f551bb10Svi117747 }
1354f551bb10Svi117747
13557c478bd9Sstevel@tonic-gate init = (sctp_init_chunk_t *)(ich + 1);
13567c478bd9Sstevel@tonic-gate ph = (sctp_parm_hdr_t *)(init + 1);
13577c478bd9Sstevel@tonic-gate
13587c478bd9Sstevel@tonic-gate /* params will have already been byteordered when validating */
1359f551bb10Svi117747 while (ph != NULL) {
1360f551bb10Svi117747 if (ph->sph_type == htons(PARM_SUPP_ADDRS)) {
1361f551bb10Svi117747 int plen;
1362f551bb10Svi117747 uint16_t *p;
1363f551bb10Svi117747 uint16_t addrtype;
1364f551bb10Svi117747
1365f551bb10Svi117747 ASSERT(psctp != NULL);
1366f551bb10Svi117747 plen = ntohs(ph->sph_len);
1367f551bb10Svi117747 p = (uint16_t *)(ph + 1);
1368f551bb10Svi117747 while (plen > 0) {
1369f551bb10Svi117747 addrtype = ntohs(*p);
1370f551bb10Svi117747 switch (addrtype) {
1371f551bb10Svi117747 case PARM_ADDR6:
1372f551bb10Svi117747 supp_af |= PARM_SUPP_V6;
1373f551bb10Svi117747 break;
1374f551bb10Svi117747 case PARM_ADDR4:
1375f551bb10Svi117747 supp_af |= PARM_SUPP_V4;
1376f551bb10Svi117747 break;
1377f551bb10Svi117747 default:
1378f551bb10Svi117747 break;
1379f551bb10Svi117747 }
1380f551bb10Svi117747 p++;
1381f551bb10Svi117747 plen -= sizeof (*p);
1382f551bb10Svi117747 }
1383f551bb10Svi117747 } else if (ph->sph_type == htons(PARM_ADDR4)) {
13847c478bd9Sstevel@tonic-gate if (remaining >= PARM_ADDR4_LEN) {
13857c478bd9Sstevel@tonic-gate in6_addr_t addr;
13867c478bd9Sstevel@tonic-gate ipaddr_t ta;
13877c478bd9Sstevel@tonic-gate
1388f551bb10Svi117747 supp_af |= PARM_SUPP_V4;
13897c478bd9Sstevel@tonic-gate /*
13907c478bd9Sstevel@tonic-gate * Screen out broad/multicasts & loopback.
13917c478bd9Sstevel@tonic-gate * If the endpoint only accepts v6 address,
13927c478bd9Sstevel@tonic-gate * go to the next one.
1393c31292eeSkcpoon *
1394c31292eeSkcpoon * Subnet broadcast check is done in
1395c31292eeSkcpoon * sctp_add_faddr(). If the address is
1396c31292eeSkcpoon * a broadcast address, it won't be added.
13977c478bd9Sstevel@tonic-gate */
13987c478bd9Sstevel@tonic-gate bcopy(ph + 1, &ta, sizeof (ta));
13997c478bd9Sstevel@tonic-gate if (ta == 0 ||
14007c478bd9Sstevel@tonic-gate ta == INADDR_BROADCAST ||
14017c478bd9Sstevel@tonic-gate ta == htonl(INADDR_LOOPBACK) ||
1402bd670b35SErik Nordmark CLASSD(ta) || connp->conn_ipv6_v6only) {
14037c478bd9Sstevel@tonic-gate goto next;
14047c478bd9Sstevel@tonic-gate }
14057c478bd9Sstevel@tonic-gate IN6_INADDR_TO_V4MAPPED((struct in_addr *)
14067c478bd9Sstevel@tonic-gate (ph + 1), &addr);
1407c31292eeSkcpoon
14087c478bd9Sstevel@tonic-gate /* Check for duplicate. */
14097c478bd9Sstevel@tonic-gate if (sctp_lookup_faddr(sctp, &addr) != NULL)
14107c478bd9Sstevel@tonic-gate goto next;
14117c478bd9Sstevel@tonic-gate
14127c478bd9Sstevel@tonic-gate /* OK, add it to the faddr set */
141377c67f2fSkcpoon err = sctp_add_faddr(sctp, &addr, KM_NOSLEEP,
141477c67f2fSkcpoon B_FALSE);
1415c31292eeSkcpoon /* Something is wrong... Try the next one. */
141645916cd2Sjpk if (err != 0)
1417c31292eeSkcpoon goto next;
14187c478bd9Sstevel@tonic-gate }
14197c478bd9Sstevel@tonic-gate } else if (ph->sph_type == htons(PARM_ADDR6) &&
1420bd670b35SErik Nordmark connp->conn_family == AF_INET6) {
14217c478bd9Sstevel@tonic-gate /* An v4 socket should not take v6 addresses. */
14227c478bd9Sstevel@tonic-gate if (remaining >= PARM_ADDR6_LEN) {
14237c478bd9Sstevel@tonic-gate in6_addr_t *addr6;
14247c478bd9Sstevel@tonic-gate
1425f551bb10Svi117747 supp_af |= PARM_SUPP_V6;
14267c478bd9Sstevel@tonic-gate addr6 = (in6_addr_t *)(ph + 1);
14277c478bd9Sstevel@tonic-gate /*
14287c478bd9Sstevel@tonic-gate * Screen out link locals, mcast, loopback
14297c478bd9Sstevel@tonic-gate * and bogus v6 address.
14307c478bd9Sstevel@tonic-gate */
14317c478bd9Sstevel@tonic-gate if (IN6_IS_ADDR_LINKLOCAL(addr6) ||
14327c478bd9Sstevel@tonic-gate IN6_IS_ADDR_MULTICAST(addr6) ||
14337c478bd9Sstevel@tonic-gate IN6_IS_ADDR_LOOPBACK(addr6) ||
14347c478bd9Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(addr6)) {
14357c478bd9Sstevel@tonic-gate goto next;
14367c478bd9Sstevel@tonic-gate }
14377c478bd9Sstevel@tonic-gate /* Check for duplicate. */
14387c478bd9Sstevel@tonic-gate if (sctp_lookup_faddr(sctp, addr6) != NULL)
14397c478bd9Sstevel@tonic-gate goto next;
14407c478bd9Sstevel@tonic-gate
144145916cd2Sjpk err = sctp_add_faddr(sctp,
144277c67f2fSkcpoon (in6_addr_t *)(ph + 1), KM_NOSLEEP,
144377c67f2fSkcpoon B_FALSE);
1444c31292eeSkcpoon /* Something is wrong... Try the next one. */
144545916cd2Sjpk if (err != 0)
1446c31292eeSkcpoon goto next;
14477c478bd9Sstevel@tonic-gate }
14487c478bd9Sstevel@tonic-gate } else if (ph->sph_type == htons(PARM_FORWARD_TSN)) {
14497c478bd9Sstevel@tonic-gate if (sctp_options != NULL)
14507c478bd9Sstevel@tonic-gate *sctp_options |= SCTP_PRSCTP_OPTION;
14517c478bd9Sstevel@tonic-gate } /* else; skip */
14527c478bd9Sstevel@tonic-gate
14537c478bd9Sstevel@tonic-gate next:
14547c478bd9Sstevel@tonic-gate ph = sctp_next_parm(ph, &remaining);
14557c478bd9Sstevel@tonic-gate }
1456f551bb10Svi117747 if (check_saddr) {
1457f551bb10Svi117747 sctp_check_saddr(sctp, supp_af, psctp == NULL ? B_FALSE :
1458c31292eeSkcpoon B_TRUE, hdrdaddr);
14597c478bd9Sstevel@tonic-gate }
14601d8c4025Svi117747 ASSERT(sctp_saddr_lookup(sctp, hdrdaddr, 0) != NULL);
14611d8c4025Svi117747 /*
14621d8c4025Svi117747 * We have the right address list now, update clustering's
14631d8c4025Svi117747 * knowledge because when we sent the INIT we had just added
14641d8c4025Svi117747 * the address the INIT was sent to.
14651d8c4025Svi117747 */
14661d8c4025Svi117747 if (psctp == NULL && cl_sctp_assoc_change != NULL) {
14671d8c4025Svi117747 uchar_t *alist;
14681d8c4025Svi117747 size_t asize;
14691d8c4025Svi117747 uchar_t *dlist;
14701d8c4025Svi117747 size_t dsize;
14711d8c4025Svi117747
14721d8c4025Svi117747 asize = sizeof (in6_addr_t) * sctp->sctp_nfaddrs;
14731d8c4025Svi117747 alist = kmem_alloc(asize, KM_NOSLEEP);
147477c67f2fSkcpoon if (alist == NULL) {
1475f4b3ec61Sdh155122 SCTP_KSTAT(sctps, sctp_cl_assoc_change);
14761d8c4025Svi117747 return (ENOMEM);
147777c67f2fSkcpoon }
14781d8c4025Svi117747 /*
14791d8c4025Svi117747 * Just include the address the INIT was sent to in the
14801d8c4025Svi117747 * delete list and send the entire faddr list. We could
14811d8c4025Svi117747 * do it differently (i.e include all the addresses in the
14821d8c4025Svi117747 * add list even if it contains the original address OR
14831d8c4025Svi117747 * remove the original address from the add list etc.), but
14841d8c4025Svi117747 * this seems reasonable enough.
14851d8c4025Svi117747 */
14861d8c4025Svi117747 dsize = sizeof (in6_addr_t);
14871d8c4025Svi117747 dlist = kmem_alloc(dsize, KM_NOSLEEP);
14881d8c4025Svi117747 if (dlist == NULL) {
14891d8c4025Svi117747 kmem_free(alist, asize);
1490f4b3ec61Sdh155122 SCTP_KSTAT(sctps, sctp_cl_assoc_change);
14911d8c4025Svi117747 return (ENOMEM);
14921d8c4025Svi117747 }
14931d8c4025Svi117747 bcopy(&curaddr, dlist, sizeof (curaddr));
14941d8c4025Svi117747 sctp_get_faddr_list(sctp, alist, asize);
1495bd670b35SErik Nordmark (*cl_sctp_assoc_change)(connp->conn_family, alist, asize,
14961d8c4025Svi117747 sctp->sctp_nfaddrs, dlist, dsize, 1, SCTP_CL_PADDR,
14971d8c4025Svi117747 (cl_sctp_handle_t)sctp);
14981d8c4025Svi117747 /* alist and dlist will be freed by the clustering module */
14991d8c4025Svi117747 }
15007c478bd9Sstevel@tonic-gate return (0);
15017c478bd9Sstevel@tonic-gate }
15027c478bd9Sstevel@tonic-gate
15037c478bd9Sstevel@tonic-gate /*
15047c478bd9Sstevel@tonic-gate * Returns 0 if the check failed and the restart should be refused,
15057c478bd9Sstevel@tonic-gate * 1 if the check succeeded.
15067c478bd9Sstevel@tonic-gate */
15077c478bd9Sstevel@tonic-gate int
sctp_secure_restart_check(mblk_t * pkt,sctp_chunk_hdr_t * ich,uint32_t ports,int sleep,sctp_stack_t * sctps,ip_recv_attr_t * ira)15087c478bd9Sstevel@tonic-gate sctp_secure_restart_check(mblk_t *pkt, sctp_chunk_hdr_t *ich, uint32_t ports,
1509bd670b35SErik Nordmark int sleep, sctp_stack_t *sctps, ip_recv_attr_t *ira)
15107c478bd9Sstevel@tonic-gate {
15117f093707Skcpoon sctp_faddr_t *fp, *fphead = NULL;
15127c478bd9Sstevel@tonic-gate sctp_parm_hdr_t *ph;
15137c478bd9Sstevel@tonic-gate ssize_t remaining;
15147c478bd9Sstevel@tonic-gate int isv4;
15157c478bd9Sstevel@tonic-gate ipha_t *iph;
15167c478bd9Sstevel@tonic-gate ip6_t *ip6h;
15177c478bd9Sstevel@tonic-gate in6_addr_t hdraddr[1];
15187c478bd9Sstevel@tonic-gate int retval = 0;
15197c478bd9Sstevel@tonic-gate sctp_tf_t *tf;
15207c478bd9Sstevel@tonic-gate sctp_t *sctp;
15217c478bd9Sstevel@tonic-gate int compres;
15227c478bd9Sstevel@tonic-gate sctp_init_chunk_t *init;
15237c478bd9Sstevel@tonic-gate int nadded = 0;
15247c478bd9Sstevel@tonic-gate
15257c478bd9Sstevel@tonic-gate /* extract the address from the IP header */
15267c478bd9Sstevel@tonic-gate isv4 = (IPH_HDR_VERSION(pkt->b_rptr) == IPV4_VERSION);
15277c478bd9Sstevel@tonic-gate if (isv4) {
15287c478bd9Sstevel@tonic-gate iph = (ipha_t *)pkt->b_rptr;
15297c478bd9Sstevel@tonic-gate IN6_IPADDR_TO_V4MAPPED(iph->ipha_src, hdraddr);
15307c478bd9Sstevel@tonic-gate } else {
15317c478bd9Sstevel@tonic-gate ip6h = (ip6_t *)pkt->b_rptr;
15327c478bd9Sstevel@tonic-gate hdraddr[0] = ip6h->ip6_src;
15337c478bd9Sstevel@tonic-gate }
15347c478bd9Sstevel@tonic-gate
15357c478bd9Sstevel@tonic-gate /* Walk the params in the INIT [ACK], pulling out addr params */
15367c478bd9Sstevel@tonic-gate remaining = ntohs(ich->sch_len) - sizeof (*ich) -
15377c478bd9Sstevel@tonic-gate sizeof (sctp_init_chunk_t);
15387c478bd9Sstevel@tonic-gate if (remaining < sizeof (*ph)) {
15397c478bd9Sstevel@tonic-gate /* no parameters; restart OK */
15407c478bd9Sstevel@tonic-gate return (1);
15417c478bd9Sstevel@tonic-gate }
15427c478bd9Sstevel@tonic-gate init = (sctp_init_chunk_t *)(ich + 1);
15437c478bd9Sstevel@tonic-gate ph = (sctp_parm_hdr_t *)(init + 1);
15447c478bd9Sstevel@tonic-gate
15457c478bd9Sstevel@tonic-gate while (ph != NULL) {
15467f093707Skcpoon sctp_faddr_t *fpa = NULL;
15477f093707Skcpoon
15487c478bd9Sstevel@tonic-gate /* params will have already been byteordered when validating */
15497c478bd9Sstevel@tonic-gate if (ph->sph_type == htons(PARM_ADDR4)) {
15507c478bd9Sstevel@tonic-gate if (remaining >= PARM_ADDR4_LEN) {
15517c478bd9Sstevel@tonic-gate in6_addr_t addr;
15527c478bd9Sstevel@tonic-gate IN6_INADDR_TO_V4MAPPED((struct in_addr *)
15537c478bd9Sstevel@tonic-gate (ph + 1), &addr);
15547c478bd9Sstevel@tonic-gate fpa = kmem_cache_alloc(sctp_kmem_faddr_cache,
15557c478bd9Sstevel@tonic-gate sleep);
15567f093707Skcpoon if (fpa == NULL) {
15577c478bd9Sstevel@tonic-gate goto done;
15587c478bd9Sstevel@tonic-gate }
15597c478bd9Sstevel@tonic-gate bzero(fpa, sizeof (*fpa));
1560*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fpa->sf_faddr = addr;
1561*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fpa->sf_next = NULL;
15627c478bd9Sstevel@tonic-gate }
15637c478bd9Sstevel@tonic-gate } else if (ph->sph_type == htons(PARM_ADDR6)) {
15647c478bd9Sstevel@tonic-gate if (remaining >= PARM_ADDR6_LEN) {
15657c478bd9Sstevel@tonic-gate fpa = kmem_cache_alloc(sctp_kmem_faddr_cache,
15667c478bd9Sstevel@tonic-gate sleep);
15677f093707Skcpoon if (fpa == NULL) {
15687c478bd9Sstevel@tonic-gate goto done;
15697c478bd9Sstevel@tonic-gate }
15707c478bd9Sstevel@tonic-gate bzero(fpa, sizeof (*fpa));
1571*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India bcopy(ph + 1, &fpa->sf_faddr,
1572*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India sizeof (fpa->sf_faddr));
1573*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fpa->sf_next = NULL;
15747c478bd9Sstevel@tonic-gate }
15757c478bd9Sstevel@tonic-gate }
15767c478bd9Sstevel@tonic-gate /* link in the new addr, if it was an addr param */
15777f093707Skcpoon if (fpa != NULL) {
15787f093707Skcpoon if (fphead == NULL) {
15797c478bd9Sstevel@tonic-gate fphead = fpa;
15807c478bd9Sstevel@tonic-gate } else {
1581*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fpa->sf_next = fphead;
15827f093707Skcpoon fphead = fpa;
15837c478bd9Sstevel@tonic-gate }
15847c478bd9Sstevel@tonic-gate }
15857c478bd9Sstevel@tonic-gate
15867c478bd9Sstevel@tonic-gate ph = sctp_next_parm(ph, &remaining);
15877c478bd9Sstevel@tonic-gate }
15887c478bd9Sstevel@tonic-gate
15897c478bd9Sstevel@tonic-gate if (fphead == NULL) {
15907c478bd9Sstevel@tonic-gate /* no addr parameters; restart OK */
15917c478bd9Sstevel@tonic-gate return (1);
15927c478bd9Sstevel@tonic-gate }
15937c478bd9Sstevel@tonic-gate
15947c478bd9Sstevel@tonic-gate /*
15957c478bd9Sstevel@tonic-gate * got at least one; make sure the header's addr is
15967c478bd9Sstevel@tonic-gate * in the list
15977c478bd9Sstevel@tonic-gate */
15987c478bd9Sstevel@tonic-gate fp = sctp_lookup_faddr_nosctp(fphead, hdraddr);
15997f093707Skcpoon if (fp == NULL) {
16007c478bd9Sstevel@tonic-gate /* not included; add it now */
16017c478bd9Sstevel@tonic-gate fp = kmem_cache_alloc(sctp_kmem_faddr_cache, sleep);
16027f093707Skcpoon if (fp == NULL) {
16037c478bd9Sstevel@tonic-gate goto done;
16047c478bd9Sstevel@tonic-gate }
16057c478bd9Sstevel@tonic-gate bzero(fp, sizeof (*fp));
1606*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_faddr = *hdraddr;
1607*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_next = fphead;
16087c478bd9Sstevel@tonic-gate fphead = fp;
16097c478bd9Sstevel@tonic-gate }
16107c478bd9Sstevel@tonic-gate
16117c478bd9Sstevel@tonic-gate /*
16127c478bd9Sstevel@tonic-gate * Now, we can finally do the check: For each sctp instance
16137c478bd9Sstevel@tonic-gate * on the hash line for ports, compare its faddr set against
16147c478bd9Sstevel@tonic-gate * the new one. If the new one is a strict subset of any
16157c478bd9Sstevel@tonic-gate * existing sctp's faddrs, the restart is OK. However, if there
16167c478bd9Sstevel@tonic-gate * is an overlap, this could be an attack, so return failure.
16177c478bd9Sstevel@tonic-gate * If all sctp's faddrs are disjoint, this is a legitimate new
16187c478bd9Sstevel@tonic-gate * association.
16197c478bd9Sstevel@tonic-gate */
1620f4b3ec61Sdh155122 tf = &(sctps->sctps_conn_fanout[SCTP_CONN_HASH(sctps, ports)]);
16217c478bd9Sstevel@tonic-gate mutex_enter(&tf->tf_lock);
16227c478bd9Sstevel@tonic-gate
16237c478bd9Sstevel@tonic-gate for (sctp = tf->tf_sctp; sctp; sctp = sctp->sctp_conn_hash_next) {
1624bd670b35SErik Nordmark if (ports != sctp->sctp_connp->conn_ports) {
16257c478bd9Sstevel@tonic-gate continue;
16267c478bd9Sstevel@tonic-gate }
16277c478bd9Sstevel@tonic-gate compres = sctp_compare_faddrsets(fphead, sctp->sctp_faddrs);
16287c478bd9Sstevel@tonic-gate if (compres <= SCTP_ADDR_SUBSET) {
16297c478bd9Sstevel@tonic-gate retval = 1;
16307c478bd9Sstevel@tonic-gate mutex_exit(&tf->tf_lock);
16317c478bd9Sstevel@tonic-gate goto done;
16327c478bd9Sstevel@tonic-gate }
16337c478bd9Sstevel@tonic-gate if (compres == SCTP_ADDR_OVERLAP) {
16347c478bd9Sstevel@tonic-gate dprint(1,
16357c478bd9Sstevel@tonic-gate ("new assoc from %x:%x:%x:%x overlaps with %p\n",
163645916cd2Sjpk SCTP_PRINTADDR(*hdraddr), (void *)sctp));
16377c478bd9Sstevel@tonic-gate /*
16387c478bd9Sstevel@tonic-gate * While we still hold the lock, we need to
16397c478bd9Sstevel@tonic-gate * figure out which addresses have been
16407c478bd9Sstevel@tonic-gate * added so we can include them in the abort
16417c478bd9Sstevel@tonic-gate * we will send back. Since these faddrs will
16427c478bd9Sstevel@tonic-gate * never be used, we overload the rto field
16437c478bd9Sstevel@tonic-gate * here, setting it to 0 if the address was
16447c478bd9Sstevel@tonic-gate * not added, 1 if it was added.
16457c478bd9Sstevel@tonic-gate */
1646*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India for (fp = fphead; fp; fp = fp->sf_next) {
1647*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (sctp_lookup_faddr(sctp, &fp->sf_faddr)) {
1648*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_rto = 0;
16497c478bd9Sstevel@tonic-gate } else {
1650*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_rto = 1;
16517c478bd9Sstevel@tonic-gate nadded++;
16527c478bd9Sstevel@tonic-gate }
16537c478bd9Sstevel@tonic-gate }
16547c478bd9Sstevel@tonic-gate mutex_exit(&tf->tf_lock);
16557c478bd9Sstevel@tonic-gate goto done;
16567c478bd9Sstevel@tonic-gate }
16577c478bd9Sstevel@tonic-gate }
16587c478bd9Sstevel@tonic-gate mutex_exit(&tf->tf_lock);
16597c478bd9Sstevel@tonic-gate
16607c478bd9Sstevel@tonic-gate /* All faddrs are disjoint; legit new association */
16617c478bd9Sstevel@tonic-gate retval = 1;
16627c478bd9Sstevel@tonic-gate
16637c478bd9Sstevel@tonic-gate done:
16647c478bd9Sstevel@tonic-gate /* If are attempted adds, send back an abort listing the addrs */
16657c478bd9Sstevel@tonic-gate if (nadded > 0) {
16667c478bd9Sstevel@tonic-gate void *dtail;
16677c478bd9Sstevel@tonic-gate size_t dlen;
16687c478bd9Sstevel@tonic-gate
16697c478bd9Sstevel@tonic-gate dtail = kmem_alloc(PARM_ADDR6_LEN * nadded, KM_NOSLEEP);
16707c478bd9Sstevel@tonic-gate if (dtail == NULL) {
16717c478bd9Sstevel@tonic-gate goto cleanup;
16727c478bd9Sstevel@tonic-gate }
16737c478bd9Sstevel@tonic-gate
16747c478bd9Sstevel@tonic-gate ph = dtail;
16757c478bd9Sstevel@tonic-gate dlen = 0;
1676*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India for (fp = fphead; fp; fp = fp->sf_next) {
1677*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (fp->sf_rto == 0) {
16787c478bd9Sstevel@tonic-gate continue;
16797c478bd9Sstevel@tonic-gate }
1680*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (IN6_IS_ADDR_V4MAPPED(&fp->sf_faddr)) {
16817c478bd9Sstevel@tonic-gate ipaddr_t addr4;
16827c478bd9Sstevel@tonic-gate
16837c478bd9Sstevel@tonic-gate ph->sph_type = htons(PARM_ADDR4);
16847c478bd9Sstevel@tonic-gate ph->sph_len = htons(PARM_ADDR4_LEN);
1685*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India IN6_V4MAPPED_TO_IPADDR(&fp->sf_faddr, addr4);
16867c478bd9Sstevel@tonic-gate ph++;
16877c478bd9Sstevel@tonic-gate bcopy(&addr4, ph, sizeof (addr4));
16887c478bd9Sstevel@tonic-gate ph = (sctp_parm_hdr_t *)
16897c478bd9Sstevel@tonic-gate ((char *)ph + sizeof (addr4));
16907c478bd9Sstevel@tonic-gate dlen += PARM_ADDR4_LEN;
16917c478bd9Sstevel@tonic-gate } else {
16927c478bd9Sstevel@tonic-gate ph->sph_type = htons(PARM_ADDR6);
16937c478bd9Sstevel@tonic-gate ph->sph_len = htons(PARM_ADDR6_LEN);
16947c478bd9Sstevel@tonic-gate ph++;
1695*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India bcopy(&fp->sf_faddr, ph, sizeof (fp->sf_faddr));
16967c478bd9Sstevel@tonic-gate ph = (sctp_parm_hdr_t *)
1697*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India ((char *)ph + sizeof (fp->sf_faddr));
16987c478bd9Sstevel@tonic-gate dlen += PARM_ADDR6_LEN;
16997c478bd9Sstevel@tonic-gate }
17007c478bd9Sstevel@tonic-gate }
17017c478bd9Sstevel@tonic-gate
17027c478bd9Sstevel@tonic-gate /* Send off the abort */
17037c478bd9Sstevel@tonic-gate sctp_send_abort(sctp, sctp_init2vtag(ich),
1704bd670b35SErik Nordmark SCTP_ERR_RESTART_NEW_ADDRS, dtail, dlen, pkt, 0, B_TRUE,
1705bd670b35SErik Nordmark ira);
17067c478bd9Sstevel@tonic-gate
17077c478bd9Sstevel@tonic-gate kmem_free(dtail, PARM_ADDR6_LEN * nadded);
17087c478bd9Sstevel@tonic-gate }
17097c478bd9Sstevel@tonic-gate
17107c478bd9Sstevel@tonic-gate cleanup:
17117c478bd9Sstevel@tonic-gate /* Clean up */
17127c478bd9Sstevel@tonic-gate if (fphead) {
17137c478bd9Sstevel@tonic-gate sctp_faddr_t *fpn;
17147c478bd9Sstevel@tonic-gate for (fp = fphead; fp; fp = fpn) {
1715*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fpn = fp->sf_next;
1716*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India if (fp->sf_ixa != NULL) {
1717*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India ixa_refrele(fp->sf_ixa);
1718*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_ixa = NULL;
1719bd670b35SErik Nordmark }
17207c478bd9Sstevel@tonic-gate kmem_cache_free(sctp_kmem_faddr_cache, fp);
17217c478bd9Sstevel@tonic-gate }
17227c478bd9Sstevel@tonic-gate }
17237c478bd9Sstevel@tonic-gate
17247c478bd9Sstevel@tonic-gate return (retval);
17257c478bd9Sstevel@tonic-gate }
17267c478bd9Sstevel@tonic-gate
1727769b977dSvi117747 /*
1728769b977dSvi117747 * Reset any state related to transmitted chunks.
1729769b977dSvi117747 */
17307c478bd9Sstevel@tonic-gate void
sctp_congest_reset(sctp_t * sctp)17317c478bd9Sstevel@tonic-gate sctp_congest_reset(sctp_t *sctp)
17327c478bd9Sstevel@tonic-gate {
17337c478bd9Sstevel@tonic-gate sctp_faddr_t *fp;
1734f4b3ec61Sdh155122 sctp_stack_t *sctps = sctp->sctp_sctps;
1735769b977dSvi117747 mblk_t *mp;
17367c478bd9Sstevel@tonic-gate
1737*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->sf_next) {
1738*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_ssthresh = sctps->sctps_initial_mtu;
1739*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India SET_CWND(fp, fp->sf_pmss, sctps->sctps_slow_start_initial);
1740*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_suna = 0;
1741*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_pba = 0;
17427c478bd9Sstevel@tonic-gate }
1743769b977dSvi117747 /*
1744769b977dSvi117747 * Clean up the transmit list as well since we have reset accounting
1745769b977dSvi117747 * on all the fps. Send event upstream, if required.
1746769b977dSvi117747 */
1747769b977dSvi117747 while ((mp = sctp->sctp_xmit_head) != NULL) {
1748769b977dSvi117747 sctp->sctp_xmit_head = mp->b_next;
1749769b977dSvi117747 mp->b_next = NULL;
1750769b977dSvi117747 if (sctp->sctp_xmit_head != NULL)
1751769b977dSvi117747 sctp->sctp_xmit_head->b_prev = NULL;
1752769b977dSvi117747 sctp_sendfail_event(sctp, mp, 0, B_TRUE);
1753769b977dSvi117747 }
1754769b977dSvi117747 sctp->sctp_xmit_head = NULL;
1755769b977dSvi117747 sctp->sctp_xmit_tail = NULL;
1756769b977dSvi117747 sctp->sctp_xmit_unacked = NULL;
1757769b977dSvi117747
1758769b977dSvi117747 sctp->sctp_unacked = 0;
1759769b977dSvi117747 /*
1760769b977dSvi117747 * Any control message as well. We will clean-up this list as well.
1761769b977dSvi117747 * This contains any pending ASCONF request that we have queued/sent.
1762769b977dSvi117747 * If we do get an ACK we will just drop it. However, given that
1763769b977dSvi117747 * we are restarting chances are we aren't going to get any.
1764769b977dSvi117747 */
1765769b977dSvi117747 if (sctp->sctp_cxmit_list != NULL)
1766769b977dSvi117747 sctp_asconf_free_cxmit(sctp, NULL);
1767769b977dSvi117747 sctp->sctp_cxmit_list = NULL;
1768769b977dSvi117747 sctp->sctp_cchunk_pend = 0;
1769769b977dSvi117747
1770769b977dSvi117747 sctp->sctp_rexmitting = B_FALSE;
1771769b977dSvi117747 sctp->sctp_rxt_nxttsn = 0;
1772769b977dSvi117747 sctp->sctp_rxt_maxtsn = 0;
1773769b977dSvi117747
1774769b977dSvi117747 sctp->sctp_zero_win_probe = B_FALSE;
17757c478bd9Sstevel@tonic-gate }
17767c478bd9Sstevel@tonic-gate
17777c478bd9Sstevel@tonic-gate static void
sctp_init_faddr(sctp_t * sctp,sctp_faddr_t * fp,in6_addr_t * addr,mblk_t * timer_mp)177877c67f2fSkcpoon sctp_init_faddr(sctp_t *sctp, sctp_faddr_t *fp, in6_addr_t *addr,
177977c67f2fSkcpoon mblk_t *timer_mp)
17807c478bd9Sstevel@tonic-gate {
1781f4b3ec61Sdh155122 sctp_stack_t *sctps = sctp->sctp_sctps;
1782f4b3ec61Sdh155122
1783*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India ASSERT(fp->sf_ixa != NULL);
1784bd670b35SErik Nordmark
1785*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India bcopy(addr, &fp->sf_faddr, sizeof (*addr));
17867c478bd9Sstevel@tonic-gate if (IN6_IS_ADDR_V4MAPPED(addr)) {
1787*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_isv4 = 1;
1788*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India /* Make sure that sf_pmss is a multiple of SCTP_ALIGN. */
1789*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_pmss =
1790121e5416Skcpoon (sctps->sctps_initial_mtu - sctp->sctp_hdr_len) &
17917c478bd9Sstevel@tonic-gate ~(SCTP_ALIGN - 1);
1792*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_ixa->ixa_flags |= IXAF_IS_IPV4;
17937c478bd9Sstevel@tonic-gate } else {
1794*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_isv4 = 0;
1795*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_pmss =
1796f4b3ec61Sdh155122 (sctps->sctps_initial_mtu - sctp->sctp_hdr6_len) &
17977c478bd9Sstevel@tonic-gate ~(SCTP_ALIGN - 1);
1798*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_ixa->ixa_flags &= ~IXAF_IS_IPV4;
17997c478bd9Sstevel@tonic-gate }
1800*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_cwnd = sctps->sctps_slow_start_initial * fp->sf_pmss;
1801*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_rto = MIN(sctp->sctp_rto_initial, sctp->sctp_rto_max_init);
18029f13099eSGeorge Shepherd SCTP_MAX_RTO(sctp, fp);
1803*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_srtt = -1;
1804*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_rtt_updates = 0;
1805*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_strikes = 0;
1806*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_max_retr = sctp->sctp_pp_max_rxt;
18077c478bd9Sstevel@tonic-gate /* Mark it as not confirmed. */
1808*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_state = SCTP_FADDRS_UNCONFIRMED;
1809*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_hb_interval = sctp->sctp_hb_interval;
1810*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_ssthresh = sctps->sctps_initial_ssthresh;
1811*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_suna = 0;
1812*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_pba = 0;
1813*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_acked = 0;
1814*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_lastactive = fp->sf_hb_expiry = ddi_get_lbolt64();
1815*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_timer_mp = timer_mp;
1816*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_hb_pending = B_FALSE;
1817*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_hb_enabled = B_TRUE;
1818*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_df = 1;
1819*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_pmtu_discovered = 0;
1820*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_next = NULL;
1821*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_T3expire = 0;
1822*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India (void) random_get_pseudo_bytes((uint8_t *)&fp->sf_hb_secret,
1823*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India sizeof (fp->sf_hb_secret));
1824*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_rxt_unacked = 0;
18257c478bd9Sstevel@tonic-gate
1826bd670b35SErik Nordmark sctp_get_dest(sctp, fp);
18277c478bd9Sstevel@tonic-gate }
18287c478bd9Sstevel@tonic-gate
18297c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1830b5fca8f8Stomee static int
faddr_constructor(void * buf,void * arg,int flags)1831b5fca8f8Stomee faddr_constructor(void *buf, void *arg, int flags)
1832b5fca8f8Stomee {
1833b5fca8f8Stomee sctp_faddr_t *fp = buf;
1834b5fca8f8Stomee
1835*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_timer_mp = NULL;
1836*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_timer_running = 0;
1837b5fca8f8Stomee
1838*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_rc_timer_mp = NULL;
1839*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India fp->sf_rc_timer_running = 0;
1840b5fca8f8Stomee
1841b5fca8f8Stomee return (0);
1842b5fca8f8Stomee }
1843b5fca8f8Stomee
1844b5fca8f8Stomee /*ARGSUSED*/
18457c478bd9Sstevel@tonic-gate static void
faddr_destructor(void * buf,void * arg)1846b5fca8f8Stomee faddr_destructor(void *buf, void *arg)
18477c478bd9Sstevel@tonic-gate {
18487c478bd9Sstevel@tonic-gate sctp_faddr_t *fp = buf;
18497c478bd9Sstevel@tonic-gate
1850*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India ASSERT(fp->sf_timer_mp == NULL);
1851*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India ASSERT(fp->sf_timer_running == 0);
18527c478bd9Sstevel@tonic-gate
1853*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India ASSERT(fp->sf_rc_timer_mp == NULL);
1854*6be61d4eSchandrasekar marimuthu - Sun Microsystems - Bangalore India ASSERT(fp->sf_rc_timer_running == 0);
18557c478bd9Sstevel@tonic-gate }
18567c478bd9Sstevel@tonic-gate
18577c478bd9Sstevel@tonic-gate void
sctp_faddr_init(void)185845916cd2Sjpk sctp_faddr_init(void)
18597c478bd9Sstevel@tonic-gate {
18607c478bd9Sstevel@tonic-gate sctp_kmem_faddr_cache = kmem_cache_create("sctp_faddr_cache",
1861b5fca8f8Stomee sizeof (sctp_faddr_t), 0, faddr_constructor, faddr_destructor,
18627c478bd9Sstevel@tonic-gate NULL, NULL, NULL, 0);
18637c478bd9Sstevel@tonic-gate }
18647c478bd9Sstevel@tonic-gate
18657c478bd9Sstevel@tonic-gate void
sctp_faddr_fini(void)186645916cd2Sjpk sctp_faddr_fini(void)
18677c478bd9Sstevel@tonic-gate {
18687c478bd9Sstevel@tonic-gate kmem_cache_destroy(sctp_kmem_faddr_cache);
18697c478bd9Sstevel@tonic-gate }
1870