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