1 /* 2 * CDDL HEADER START 3 * 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. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/systm.h> 29 #include <sys/stream.h> 30 #include <sys/cmn_err.h> 31 #include <sys/strsubr.h> 32 33 #include <netinet/in.h> 34 #include <netinet/ip6.h> 35 36 #include <inet/common.h> 37 #include <inet/ip.h> 38 #include <inet/mib2.h> 39 #include <inet/ipclassifier.h> 40 #include "sctp_impl.h" 41 42 void 43 sctp_return_heartbeat(sctp_t *sctp, sctp_chunk_hdr_t *hbcp, mblk_t *mp) 44 { 45 mblk_t *smp; 46 sctp_chunk_hdr_t *cp; 47 ipha_t *iniph; 48 ip6_t *inip6h; 49 int isv4; 50 in6_addr_t addr; 51 sctp_faddr_t *fp; 52 uint16_t len; 53 sctp_stack_t *sctps = sctp->sctp_sctps; 54 55 BUMP_LOCAL(sctp->sctp_ibchunks); 56 57 /* Update the faddr for the src addr */ 58 isv4 = (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION); 59 if (isv4) { 60 iniph = (ipha_t *)mp->b_rptr; 61 IN6_IPADDR_TO_V4MAPPED(iniph->ipha_src, &addr); 62 } else { 63 inip6h = (ip6_t *)mp->b_rptr; 64 addr = inip6h->ip6_src; 65 } 66 fp = sctp_lookup_faddr(sctp, &addr); 67 /* If the source address is bogus we silently drop the packet */ 68 if (fp == NULL) { 69 dprint(1, 70 ("sctp_return_heartbeat: %p bogus hb from %x:%x:%x:%x\n", 71 (void *)sctp, SCTP_PRINTADDR(addr))); 72 SCTP_KSTAT(sctps, sctp_return_hb_failed); 73 return; 74 } 75 dprint(3, ("sctp_return_heartbeat: %p got hb from %x:%x:%x:%x\n", 76 (void *)sctp, SCTP_PRINTADDR(addr))); 77 78 /* 79 * XXX It's really tempting to reuse the heartbeat mblk. But 80 * this complicates processing in sctp_dispatch (i.e. it will 81 * screw up sctp_next_chunk since we will set the chunk 82 * header's length into network byte-order), and if we ever 83 * encounter a heartbeat bundled with other chunks... 84 * So we take the slower-but-safe route. 85 */ 86 len = ntohs(hbcp->sch_len); 87 88 /* Create an IP header, returning to the src addr from the heartbt */ 89 smp = sctp_make_mp(sctp, fp, len); 90 if (smp == NULL) { 91 SCTP_KSTAT(sctps, sctp_return_hb_failed); 92 return; 93 } 94 95 cp = (sctp_chunk_hdr_t *)smp->b_wptr; 96 cp->sch_id = CHUNK_HEARTBEAT_ACK; 97 cp->sch_flags = 0; 98 cp->sch_len = htons(len); 99 100 /* Copy the information field from the heartbeat */ 101 bcopy((void *)(hbcp + 1), (void *)(cp + 1), len - sizeof (*cp)); 102 103 smp->b_wptr += len; 104 105 BUMP_LOCAL(sctp->sctp_obchunks); 106 107 sctp_set_iplen(sctp, smp, fp->ixa); 108 (void) conn_ip_output(smp, fp->ixa); 109 BUMP_LOCAL(sctp->sctp_opkts); 110 } 111 112 /* 113 * The data section of the heartbeat contains a time field (lbolt64), 114 * a 64 bit secret, followed by the v6 (possible a v4mapped) address this 115 * heartbeat was sent to. No byte-ordering is done, since the heartbeat 116 * is not interpreted by the peer. 117 */ 118 void 119 sctp_send_heartbeat(sctp_t *sctp, sctp_faddr_t *fp) 120 { 121 sctp_chunk_hdr_t *cp; 122 sctp_parm_hdr_t *hpp; 123 int64_t *t; 124 int64_t now; 125 in6_addr_t *a; 126 mblk_t *hbmp; 127 size_t hblen; 128 sctp_stack_t *sctps = sctp->sctp_sctps; 129 130 dprint(3, ("sctp_send_heartbeat: to %x:%x:%x:%x from %x:%x:%x:%x\n", 131 SCTP_PRINTADDR(fp->faddr), SCTP_PRINTADDR(fp->saddr))); 132 133 hblen = sizeof (*cp) + 134 sizeof (*hpp) + 135 sizeof (*t) + 136 sizeof (fp->hb_secret) + 137 sizeof (fp->faddr); 138 hbmp = sctp_make_mp(sctp, fp, hblen); 139 if (hbmp == NULL) { 140 SCTP_KSTAT(sctps, sctp_send_hb_failed); 141 return; 142 } 143 144 cp = (sctp_chunk_hdr_t *)hbmp->b_wptr; 145 cp->sch_id = CHUNK_HEARTBEAT; 146 cp->sch_flags = 0; 147 cp->sch_len = hblen; 148 cp->sch_len = htons(cp->sch_len); 149 150 hpp = (sctp_parm_hdr_t *)(cp + 1); 151 hpp->sph_type = htons(PARM_HBINFO); 152 hpp->sph_len = hblen - sizeof (*cp); 153 hpp->sph_len = htons(hpp->sph_len); 154 155 /* 156 * Timestamp 157 * 158 * Copy the current time to the heartbeat and we can use it to 159 * calculate the RTT when we get it back in the heartbeat ACK. 160 */ 161 now = ddi_get_lbolt64(); 162 t = (int64_t *)(hpp + 1); 163 bcopy(&now, t, sizeof (now)); 164 165 /* 166 * Secret 167 * 168 * The per peer address secret is used to make sure that the heartbeat 169 * ack is really in response to our heartbeat. This prevents blind 170 * spoofing of heartbeat ack to fake the validity of an address. 171 */ 172 t++; 173 bcopy(&fp->hb_secret, t, sizeof (uint64_t)); 174 175 /* 176 * Peer address 177 * 178 * The peer address is used to associate the heartbeat ack with 179 * the correct peer address. The reason is that the peer is 180 * multihomed so that it may not use the same address as source 181 * in response to our heartbeat. 182 */ 183 a = (in6_addr_t *)(t + 1); 184 bcopy(&fp->faddr, a, sizeof (*a)); 185 186 hbmp->b_wptr += hblen; 187 188 /* Update the faddr's info */ 189 fp->lastactive = now; 190 fp->hb_pending = B_TRUE; 191 192 BUMP_LOCAL(sctp->sctp_obchunks); 193 BUMP_MIB(&sctps->sctps_mib, sctpTimHeartBeatProbe); 194 195 sctp_set_iplen(sctp, hbmp, fp->ixa); 196 (void) conn_ip_output(hbmp, fp->ixa); 197 BUMP_LOCAL(sctp->sctp_opkts); 198 } 199 200 /* 201 * Call right after any address change to validate peer addresses. 202 */ 203 void 204 sctp_validate_peer(sctp_t *sctp) 205 { 206 sctp_faddr_t *fp; 207 int cnt; 208 int64_t now; 209 int64_t earliest_expiry; 210 sctp_stack_t *sctps = sctp->sctp_sctps; 211 212 now = ddi_get_lbolt64(); 213 earliest_expiry = 0; 214 cnt = sctps->sctps_maxburst; 215 216 /* 217 * Loop thru the list looking for unconfirmed addresses and 218 * send a heartbeat. But we should only send at most sctp_maxburst 219 * heartbeats. 220 */ 221 for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->next) { 222 /* No need to validate unreachable address. */ 223 if (fp->state == SCTP_FADDRS_UNREACH) 224 continue; 225 if (fp->state == SCTP_FADDRS_UNCONFIRMED) { 226 if (cnt-- > 0) { 227 fp->hb_expiry = now + fp->rto; 228 sctp_send_heartbeat(sctp, fp); 229 } else { 230 /* 231 * If we cannot send now, be more aggressive 232 * and try again about half of RTO. Note that 233 * all the unsent probes are set to expire at 234 * the same time. 235 */ 236 fp->hb_expiry = now + 237 (sctp->sctp_rto_initial >> 1); 238 } 239 } 240 /* Find the earliest heartbeat expiry time for ALL fps. */ 241 if (fp->hb_interval != 0 && (earliest_expiry == 0 || 242 fp->hb_expiry < earliest_expiry)) { 243 earliest_expiry = fp->hb_expiry; 244 } 245 } 246 /* We use heartbeat timer for autoclose. */ 247 if (sctp->sctp_autoclose != 0) { 248 int64_t expire; 249 250 expire = sctp->sctp_active + sctp->sctp_autoclose; 251 if (earliest_expiry == 0 || expire < earliest_expiry) 252 earliest_expiry = expire; 253 } 254 255 /* 256 * Set the timer to fire for the earliest heartbeat unless 257 * heartbeat is disabled for all addresses. 258 */ 259 if (earliest_expiry != 0) { 260 earliest_expiry -= now; 261 if (earliest_expiry < 0) 262 earliest_expiry = 1; 263 sctp_timer(sctp, sctp->sctp_heartbeat_mp, earliest_expiry); 264 } 265 } 266 267 /* 268 * Process an incoming heartbeat ack. When sending a heartbeat, we 269 * put the timestamp, a secret and the peer address the heartbeat is 270 * sent in the data part of the heartbeat. We will extract this info 271 * and verify that this heartbeat ack is valid. 272 */ 273 void 274 sctp_process_heartbeat(sctp_t *sctp, sctp_chunk_hdr_t *cp) 275 { 276 int64_t *sentp, sent; 277 uint64_t secret; 278 in6_addr_t addr; 279 sctp_faddr_t *fp; 280 sctp_parm_hdr_t *hpp; 281 int64_t now; 282 283 BUMP_LOCAL(sctp->sctp_ibchunks); 284 285 /* Sanity checks */ 286 ASSERT(OK_32PTR(cp)); 287 if (ntohs(cp->sch_len) < (sizeof (*cp) + sizeof (*hpp) + 288 sizeof (sent) + sizeof (secret) + sizeof (addr))) { 289 /* drop it */ 290 dprint(2, ("sctp_process_heartbeat: malformed ack %p\n", 291 (void *)sctp)); 292 return; 293 } 294 295 hpp = (sctp_parm_hdr_t *)(cp + 1); 296 if (ntohs(hpp->sph_type) != PARM_HBINFO || 297 ntohs(hpp->sph_len) != (ntohs(cp->sch_len) - sizeof (*cp))) { 298 dprint(2, 299 ("sctp_process_heartbeat: malformed param in ack %p\n", 300 (void *)sctp)); 301 return; 302 } 303 304 /* 305 * Pull out the time sent from the ack. 306 * SCTP is 32-bit aligned, so copy 64 bit quantity. Since we 307 * put it in, it should be in our byte order. 308 */ 309 sentp = (int64_t *)(hpp + 1); 310 bcopy(sentp, &sent, sizeof (sent)); 311 312 /* Grab the secret to make sure that this heartbeat is valid */ 313 bcopy(++sentp, &secret, sizeof (secret)); 314 315 /* Next, verify the address to make sure that it is the right one. */ 316 bcopy(++sentp, &addr, sizeof (addr)); 317 fp = sctp_lookup_faddr(sctp, &addr); 318 if (fp == NULL) { 319 dprint(2, ("sctp_process_heartbeat: invalid faddr (sctp=%p)\n", 320 (void *)sctp)); 321 return; 322 } 323 if (secret != fp->hb_secret) { 324 dprint(2, 325 ("sctp_process_heartbeat: invalid secret in ack %p\n", 326 (void *)sctp)); 327 return; 328 } 329 330 /* This address is now confirmed and alive. */ 331 sctp_faddr_alive(sctp, fp); 332 now = ddi_get_lbolt64(); 333 sctp_update_rtt(sctp, fp, now - sent); 334 335 /* 336 * Note that the heartbeat timer should still be running, we don't 337 * reset it to avoid going through the whole list of peer addresses 338 * for each heartbeat ack as we probably are in interrupt context. 339 */ 340 fp->hb_expiry = now + SET_HB_INTVL(fp); 341 } 342