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/stream.h> 29 #include <sys/ddi.h> 30 #include <sys/sunddi.h> 31 32 #include <netinet/in.h> 33 #include <netinet/ip6.h> 34 35 #include <inet/common.h> 36 #include <inet/ipclassifier.h> 37 #include <inet/ip.h> 38 #include <inet/ip6.h> 39 #include <inet/mib2.h> 40 #include <inet/nd.h> 41 #include <inet/optcom.h> 42 #include <inet/ipclassifier.h> 43 #include "sctp_impl.h" 44 #include "sctp_addr.h" 45 46 /*ARGSUSED*/ 47 size_t 48 sctp_supaddr_param_len(sctp_t *sctp) 49 { 50 return (sizeof (sctp_parm_hdr_t) + sizeof (int32_t)); 51 } 52 53 size_t 54 sctp_supaddr_param(sctp_t *sctp, uchar_t *p) 55 { 56 sctp_parm_hdr_t *sph; 57 uint16_t *addrtype; 58 conn_t *connp = sctp->sctp_connp; 59 60 sph = (sctp_parm_hdr_t *)p; 61 sph->sph_type = htons(PARM_SUPP_ADDRS); 62 addrtype = (uint16_t *)(sph + 1); 63 switch (connp->conn_family) { 64 case AF_INET: 65 *addrtype++ = htons(PARM_ADDR4); 66 *addrtype = 0; 67 sph->sph_len = htons(sizeof (*sph) + sizeof (*addrtype)); 68 break; 69 case AF_INET6: 70 *addrtype++ = htons(PARM_ADDR6); 71 if (!sctp->sctp_connp->conn_ipv6_v6only) { 72 *addrtype = htons(PARM_ADDR4); 73 sph->sph_len = htons(sizeof (*sph) + 74 sizeof (*addrtype) * 2); 75 } else { 76 *addrtype = 0; 77 sph->sph_len = htons(sizeof (*sph) + 78 sizeof (*addrtype)); 79 } 80 break; 81 default: 82 break; 83 } 84 return (sizeof (*sph) + (sizeof (*addrtype) * 2)); 85 } 86 87 /* 88 * Currently, we support on PRSCTP option, there is more to come. 89 */ 90 /*ARGSUSED*/ 91 size_t 92 sctp_options_param_len(const sctp_t *sctp, int option) 93 { 94 size_t optlen; 95 96 switch (option) { 97 case SCTP_PRSCTP_OPTION: 98 optlen = sizeof (sctp_parm_hdr_t); 99 break; 100 default: 101 ASSERT(0); 102 } 103 104 return (optlen); 105 } 106 107 /*ARGSUSED*/ 108 size_t 109 sctp_options_param(const sctp_t *sctp, void *p, int option) 110 { 111 sctp_parm_hdr_t *sph = (sctp_parm_hdr_t *)p; 112 113 switch (option) { 114 case SCTP_PRSCTP_OPTION: 115 sph->sph_type = htons(PARM_FORWARD_TSN); 116 sph->sph_len = htons(sizeof (*sph)); 117 break; 118 default: 119 ASSERT(0); 120 } 121 122 return (sizeof (*sph)); 123 124 } 125 126 size_t 127 sctp_adaptation_code_param(sctp_t *sctp, uchar_t *p) 128 { 129 sctp_parm_hdr_t *sph; 130 131 if (!sctp->sctp_send_adaptation) { 132 return (0); 133 } 134 sph = (sctp_parm_hdr_t *)p; 135 sph->sph_type = htons(PARM_ADAPT_LAYER_IND); 136 sph->sph_len = htons(sizeof (*sph) + sizeof (uint32_t)); 137 *(uint32_t *)(sph + 1) = htonl(sctp->sctp_tx_adaptation_code); 138 139 return (sizeof (*sph) + sizeof (uint32_t)); 140 } 141 142 mblk_t * 143 sctp_init_mp(sctp_t *sctp, sctp_faddr_t *fp) 144 { 145 mblk_t *mp; 146 uchar_t *p; 147 size_t initlen; 148 sctp_init_chunk_t *icp; 149 sctp_chunk_hdr_t *chp; 150 uint16_t schlen; 151 int supp_af; 152 sctp_stack_t *sctps = sctp->sctp_sctps; 153 conn_t *connp = sctp->sctp_connp; 154 155 if (connp->conn_family == AF_INET) { 156 supp_af = PARM_SUPP_V4; 157 } else { 158 if (sctp->sctp_connp->conn_ipv6_v6only) 159 supp_af = PARM_SUPP_V6; 160 else 161 supp_af = PARM_SUPP_V6 | PARM_SUPP_V4; 162 } 163 initlen = sizeof (*chp) + sizeof (*icp); 164 if (sctp->sctp_send_adaptation) { 165 initlen += (sizeof (sctp_parm_hdr_t) + sizeof (uint32_t)); 166 } 167 initlen += sctp_supaddr_param_len(sctp); 168 initlen += sctp_addr_params(sctp, supp_af, NULL, B_TRUE); 169 if (sctp->sctp_prsctp_aware && sctps->sctps_prsctp_enabled) 170 initlen += sctp_options_param_len(sctp, SCTP_PRSCTP_OPTION); 171 172 /* 173 * This could be a INIT retransmission in which case sh_verf may 174 * be non-zero, zero it out just to be sure. 175 */ 176 sctp->sctp_sctph->sh_verf = 0; 177 sctp->sctp_sctph6->sh_verf = 0; 178 179 mp = sctp_make_mp(sctp, fp, initlen); 180 if (mp == NULL) { 181 SCTP_KSTAT(sctps, sctp_send_init_failed); 182 return (NULL); 183 } 184 /* sctp_make_mp could have discovered we have no usable sources */ 185 if (sctp->sctp_nsaddrs == 0) { 186 freemsg(mp); 187 SCTP_KSTAT(sctps, sctp_send_init_failed); 188 return (NULL); 189 } 190 191 /* Lay in a new INIT chunk, starting with the chunk header */ 192 chp = (sctp_chunk_hdr_t *)mp->b_wptr; 193 chp->sch_id = CHUNK_INIT; 194 chp->sch_flags = 0; 195 schlen = (uint16_t)initlen; 196 U16_TO_ABE16(schlen, &(chp->sch_len)); 197 198 mp->b_wptr += initlen; 199 200 icp = (sctp_init_chunk_t *)(chp + 1); 201 icp->sic_inittag = sctp->sctp_lvtag; 202 U32_TO_ABE32(sctp->sctp_rwnd, &(icp->sic_a_rwnd)); 203 U16_TO_ABE16(sctp->sctp_num_ostr, &(icp->sic_outstr)); 204 U16_TO_ABE16(sctp->sctp_num_istr, &(icp->sic_instr)); 205 U32_TO_ABE32(sctp->sctp_ltsn, &(icp->sic_inittsn)); 206 207 p = (uchar_t *)(icp + 1); 208 209 /* Adaptation layer param */ 210 p += sctp_adaptation_code_param(sctp, p); 211 212 /* Add supported address types parameter */ 213 p += sctp_supaddr_param(sctp, p); 214 215 /* Add address parameters */ 216 p += sctp_addr_params(sctp, supp_af, p, B_FALSE); 217 218 /* Add Forward-TSN-Supported param */ 219 if (sctp->sctp_prsctp_aware && sctps->sctps_prsctp_enabled) 220 p += sctp_options_param(sctp, p, SCTP_PRSCTP_OPTION); 221 222 BUMP_LOCAL(sctp->sctp_obchunks); 223 224 sctp_set_iplen(sctp, mp, fp->ixa); 225 226 return (mp); 227 } 228 229 /* 230 * Extracts the verification tag from an INIT chunk. If the INIT 231 * chunk is truncated or malformed, returns 0. 232 */ 233 uint32_t 234 sctp_init2vtag(sctp_chunk_hdr_t *initch) 235 { 236 sctp_init_chunk_t *init; 237 238 init = (sctp_init_chunk_t *)(initch + 1); 239 return (init->sic_inittag); 240 } 241 242 size_t 243 sctp_addr_params(sctp_t *sctp, int af, uchar_t *p, boolean_t modify) 244 { 245 size_t param_len; 246 247 ASSERT(sctp->sctp_nsaddrs > 0); 248 249 /* 250 * If we have only one local address or it is a loopback or linklocal 251 * association, we let the peer pull the address from the IP header. 252 */ 253 if ((!modify && sctp->sctp_nsaddrs == 1) || sctp->sctp_loopback || 254 sctp->sctp_linklocal) { 255 return (0); 256 } 257 258 param_len = sctp_saddr_info(sctp, af, p, modify); 259 return ((sctp->sctp_nsaddrs == 1) ? 0 : param_len); 260 } 261