4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
26 #include <sys/types.h>
27 #include <sys/systm.h>
28 #include <sys/stream.h>
29 #include <sys/cmn_err.h>
30 #include <sys/strsubr.h>
32 #include <netinet/in.h>
33 #include <netinet/ip6.h>
35 #include <inet/common.h>
37 #include <inet/mib2.h>
38 #include <inet/ipclassifier.h>
39 #include "sctp_impl.h"
42 sctp_return_heartbeat(sctp_t
*sctp
, sctp_chunk_hdr_t
*hbcp
, mblk_t
*mp
)
52 sctp_stack_t
*sctps
= sctp
->sctp_sctps
;
54 BUMP_LOCAL(sctp
->sctp_ibchunks
);
56 /* Update the faddr for the src addr */
57 isv4
= (IPH_HDR_VERSION(mp
->b_rptr
) == IPV4_VERSION
);
59 iniph
= (ipha_t
*)mp
->b_rptr
;
60 IN6_IPADDR_TO_V4MAPPED(iniph
->ipha_src
, &addr
);
62 inip6h
= (ip6_t
*)mp
->b_rptr
;
63 addr
= inip6h
->ip6_src
;
65 fp
= sctp_lookup_faddr(sctp
, &addr
);
66 /* If the source address is bogus we silently drop the packet */
69 ("sctp_return_heartbeat: %p bogus hb from %x:%x:%x:%x\n",
70 (void *)sctp
, SCTP_PRINTADDR(addr
)));
71 SCTP_KSTAT(sctps
, sctp_return_hb_failed
);
74 dprint(3, ("sctp_return_heartbeat: %p got hb from %x:%x:%x:%x\n",
75 (void *)sctp
, SCTP_PRINTADDR(addr
)));
78 * XXX It's really tempting to reuse the heartbeat mblk. But
79 * this complicates processing in sctp_dispatch (i.e. it will
80 * screw up sctp_next_chunk since we will set the chunk
81 * header's length into network byte-order), and if we ever
82 * encounter a heartbeat bundled with other chunks...
83 * So we take the slower-but-safe route.
85 len
= ntohs(hbcp
->sch_len
);
87 /* Create an IP header, returning to the src addr from the heartbt */
88 smp
= sctp_make_mp(sctp
, fp
, len
);
90 SCTP_KSTAT(sctps
, sctp_return_hb_failed
);
94 cp
= (sctp_chunk_hdr_t
*)smp
->b_wptr
;
95 cp
->sch_id
= CHUNK_HEARTBEAT_ACK
;
97 cp
->sch_len
= htons(len
);
99 /* Copy the information field from the heartbeat */
100 bcopy((void *)(hbcp
+ 1), (void *)(cp
+ 1), len
- sizeof (*cp
));
104 BUMP_LOCAL(sctp
->sctp_obchunks
);
106 sctp_set_iplen(sctp
, smp
, fp
->sf_ixa
);
107 (void) conn_ip_output(smp
, fp
->sf_ixa
);
108 BUMP_LOCAL(sctp
->sctp_opkts
);
112 * The data section of the heartbeat contains a time field (lbolt64),
113 * a 64 bit secret, followed by the v6 (possible a v4mapped) address this
114 * heartbeat was sent to. No byte-ordering is done, since the heartbeat
115 * is not interpreted by the peer.
118 sctp_send_heartbeat(sctp_t
*sctp
, sctp_faddr_t
*fp
)
120 sctp_chunk_hdr_t
*cp
;
121 sctp_parm_hdr_t
*hpp
;
127 sctp_stack_t
*sctps
= sctp
->sctp_sctps
;
129 dprint(3, ("sctp_send_heartbeat: to %x:%x:%x:%x from %x:%x:%x:%x\n",
130 SCTP_PRINTADDR(fp
->sf_faddr
), SCTP_PRINTADDR(fp
->sf_saddr
)));
132 hblen
= sizeof (*cp
) +
135 sizeof (fp
->sf_hb_secret
) +
136 sizeof (fp
->sf_faddr
);
137 hbmp
= sctp_make_mp(sctp
, fp
, hblen
);
139 SCTP_KSTAT(sctps
, sctp_send_hb_failed
);
143 cp
= (sctp_chunk_hdr_t
*)hbmp
->b_wptr
;
144 cp
->sch_id
= CHUNK_HEARTBEAT
;
147 cp
->sch_len
= htons(cp
->sch_len
);
149 hpp
= (sctp_parm_hdr_t
*)(cp
+ 1);
150 hpp
->sph_type
= htons(PARM_HBINFO
);
151 hpp
->sph_len
= hblen
- sizeof (*cp
);
152 hpp
->sph_len
= htons(hpp
->sph_len
);
157 * Copy the current time to the heartbeat and we can use it to
158 * calculate the RTT when we get it back in the heartbeat ACK.
160 now
= ddi_get_lbolt64();
161 t
= (int64_t *)(hpp
+ 1);
162 bcopy(&now
, t
, sizeof (now
));
167 * The per peer address secret is used to make sure that the heartbeat
168 * ack is really in response to our heartbeat. This prevents blind
169 * spoofing of heartbeat ack to fake the validity of an address.
172 bcopy(&fp
->sf_hb_secret
, t
, sizeof (uint64_t));
177 * The peer address is used to associate the heartbeat ack with
178 * the correct peer address. The reason is that the peer is
179 * multihomed so that it may not use the same address as source
180 * in response to our heartbeat.
182 a
= (in6_addr_t
*)(t
+ 1);
183 bcopy(&fp
->sf_faddr
, a
, sizeof (*a
));
185 hbmp
->b_wptr
+= hblen
;
187 /* Update the faddr's info */
188 fp
->sf_lastactive
= now
;
189 fp
->sf_hb_pending
= B_TRUE
;
191 BUMP_LOCAL(sctp
->sctp_obchunks
);
192 SCTPS_BUMP_MIB(sctps
, sctpTimHeartBeatProbe
);
194 sctp_set_iplen(sctp
, hbmp
, fp
->sf_ixa
);
195 (void) conn_ip_output(hbmp
, fp
->sf_ixa
);
196 BUMP_LOCAL(sctp
->sctp_opkts
);
200 * Call right after any address change to validate peer addresses.
203 sctp_validate_peer(sctp_t
*sctp
)
208 int64_t earliest_expiry
;
209 sctp_stack_t
*sctps
= sctp
->sctp_sctps
;
211 now
= ddi_get_lbolt64();
213 cnt
= sctps
->sctps_maxburst
;
216 * Loop thru the list looking for unconfirmed addresses and
217 * send a heartbeat. But we should only send at most sctp_maxburst
220 for (fp
= sctp
->sctp_faddrs
; fp
!= NULL
; fp
= fp
->sf_next
) {
221 /* No need to validate unreachable address. */
222 if (fp
->sf_state
== SCTP_FADDRS_UNREACH
)
224 if (fp
->sf_state
== SCTP_FADDRS_UNCONFIRMED
) {
226 fp
->sf_hb_expiry
= now
+ fp
->sf_rto
;
227 sctp_send_heartbeat(sctp
, fp
);
230 * If we cannot send now, be more aggressive
231 * and try again about half of RTO. Note that
232 * all the unsent probes are set to expire at
235 fp
->sf_hb_expiry
= now
+
236 (sctp
->sctp_rto_initial
>> 1);
239 /* Find the earliest heartbeat expiry time for ALL fps. */
240 if (fp
->sf_hb_interval
!= 0 && (earliest_expiry
== 0 ||
241 fp
->sf_hb_expiry
< earliest_expiry
)) {
242 earliest_expiry
= fp
->sf_hb_expiry
;
245 /* We use heartbeat timer for autoclose. */
246 if (sctp
->sctp_autoclose
!= 0) {
249 expire
= sctp
->sctp_active
+ sctp
->sctp_autoclose
;
250 if (earliest_expiry
== 0 || expire
< earliest_expiry
)
251 earliest_expiry
= expire
;
255 * Set the timer to fire for the earliest heartbeat unless
256 * heartbeat is disabled for all addresses.
258 if (earliest_expiry
!= 0) {
259 earliest_expiry
-= now
;
260 if (earliest_expiry
< 0)
262 sctp_timer(sctp
, sctp
->sctp_heartbeat_mp
, earliest_expiry
);
267 * Process an incoming heartbeat ack. When sending a heartbeat, we
268 * put the timestamp, a secret and the peer address the heartbeat is
269 * sent in the data part of the heartbeat. We will extract this info
270 * and verify that this heartbeat ack is valid.
273 sctp_process_heartbeat(sctp_t
*sctp
, sctp_chunk_hdr_t
*cp
)
275 int64_t *sentp
, sent
;
279 sctp_parm_hdr_t
*hpp
;
282 BUMP_LOCAL(sctp
->sctp_ibchunks
);
285 ASSERT(OK_32PTR(cp
));
286 if (ntohs(cp
->sch_len
) < (sizeof (*cp
) + sizeof (*hpp
) +
287 sizeof (sent
) + sizeof (secret
) + sizeof (addr
))) {
289 dprint(2, ("sctp_process_heartbeat: malformed ack %p\n",
294 hpp
= (sctp_parm_hdr_t
*)(cp
+ 1);
295 if (ntohs(hpp
->sph_type
) != PARM_HBINFO
||
296 ntohs(hpp
->sph_len
) != (ntohs(cp
->sch_len
) - sizeof (*cp
))) {
298 ("sctp_process_heartbeat: malformed param in ack %p\n",
304 * Pull out the time sent from the ack.
305 * SCTP is 32-bit aligned, so copy 64 bit quantity. Since we
306 * put it in, it should be in our byte order.
308 sentp
= (int64_t *)(hpp
+ 1);
309 bcopy(sentp
, &sent
, sizeof (sent
));
311 /* Grab the secret to make sure that this heartbeat is valid */
312 bcopy(++sentp
, &secret
, sizeof (secret
));
314 /* Next, verify the address to make sure that it is the right one. */
315 bcopy(++sentp
, &addr
, sizeof (addr
));
316 fp
= sctp_lookup_faddr(sctp
, &addr
);
318 dprint(2, ("sctp_process_heartbeat: invalid faddr (sctp=%p)\n",
322 if (secret
!= fp
->sf_hb_secret
) {
324 ("sctp_process_heartbeat: invalid secret in ack %p\n",
329 /* This address is now confirmed and alive. */
330 sctp_faddr_alive(sctp
, fp
);
331 now
= ddi_get_lbolt64();
332 sctp_update_rtt(sctp
, fp
, now
- sent
);
335 * Note that the heartbeat timer should still be running, we don't
336 * reset it to avoid going through the whole list of peer addresses
337 * for each heartbeat ack as we probably are in interrupt context.
339 fp
->sf_hb_expiry
= now
+ SET_HB_INTVL(fp
);