1 /*- 2 * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * a) Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. 9 * 10 * b) Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the distribution. 13 * 14 * c) Neither the name of Cisco Systems, Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 * THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 /* $KAME: sctp_output.c,v 1.46 2005/03/06 16:04:17 itojun Exp $ */ 32 33 #include <sys/cdefs.h> 34 __FBSDID("$FreeBSD$"); 35 36 #include <netinet/sctp_os.h> 37 #include <netinet/sctp_var.h> 38 #include <netinet/sctp_pcb.h> 39 #include <netinet/sctp_header.h> 40 #include <netinet/sctputil.h> 41 #include <netinet/sctp_output.h> 42 #include <netinet/sctp_bsd_addr.h> 43 #include <netinet/sctp_uio.h> 44 #include <netinet/sctputil.h> 45 #include <netinet/sctp_timer.h> 46 #include <netinet/sctp_asconf.h> 47 #include <netinet/sctp_sysctl.h> 48 #include <netinet/sctp_indata.h> 49 #include <sys/unistd.h> 50 51 52 #if defined(SCTP_USE_THREAD_BASED_ITERATOR) 53 void 54 sctp_wakeup_iterator(void) 55 { 56 wakeup(&sctppcbinfo.iterator_running); 57 } 58 59 static void 60 sctp_iterator_thread(void *v) 61 { 62 SCTP_IPI_ITERATOR_WQ_LOCK(); 63 sctppcbinfo.iterator_running = 0; 64 while (1) { 65 msleep(&sctppcbinfo.iterator_running, 66 &sctppcbinfo.ipi_iterator_wq_mtx, 67 0, "waiting_for_work", 0); 68 sctp_iterator_worker(); 69 } 70 } 71 72 void 73 sctp_startup_iterator(void) 74 { 75 int ret; 76 77 ret = kthread_create(sctp_iterator_thread, 78 (void *)NULL, 79 &sctppcbinfo.thread_proc, 80 RFPROC, 81 SCTP_KTHREAD_PAGES, 82 SCTP_KTRHEAD_NAME); 83 } 84 85 #endif 86 87 88 void 89 sctp_gather_internal_ifa_flags(struct sctp_ifa *ifa) 90 { 91 struct in6_ifaddr *ifa6; 92 93 ifa6 = (struct in6_ifaddr *)ifa->ifa; 94 ifa->flags = ifa6->ia6_flags; 95 if (!ip6_use_deprecated) { 96 if (ifa->flags & 97 IN6_IFF_DEPRECATED) { 98 ifa->localifa_flags |= SCTP_ADDR_IFA_UNUSEABLE; 99 } else { 100 ifa->localifa_flags &= ~SCTP_ADDR_IFA_UNUSEABLE; 101 } 102 } else { 103 ifa->localifa_flags &= ~SCTP_ADDR_IFA_UNUSEABLE; 104 } 105 if (ifa->flags & 106 (IN6_IFF_DETACHED | 107 IN6_IFF_ANYCAST | 108 IN6_IFF_NOTREADY)) { 109 ifa->localifa_flags |= SCTP_ADDR_IFA_UNUSEABLE; 110 } else { 111 ifa->localifa_flags &= ~SCTP_ADDR_IFA_UNUSEABLE; 112 } 113 } 114 115 116 117 static uint32_t 118 sctp_is_desired_interface_type(struct ifaddr *ifa) 119 { 120 int result; 121 122 /* check the interface type to see if it's one we care about */ 123 switch (ifa->ifa_ifp->if_type) { 124 case IFT_ETHER: 125 case IFT_ISO88023: 126 case IFT_ISO88024: 127 case IFT_ISO88025: 128 case IFT_ISO88026: 129 case IFT_STARLAN: 130 case IFT_P10: 131 case IFT_P80: 132 case IFT_HY: 133 case IFT_FDDI: 134 case IFT_XETHER: 135 case IFT_ISDNBASIC: 136 case IFT_ISDNPRIMARY: 137 case IFT_PTPSERIAL: 138 case IFT_PPP: 139 case IFT_LOOP: 140 case IFT_SLIP: 141 case IFT_IP: 142 case IFT_IPOVERCDLC: 143 case IFT_IPOVERCLAW: 144 case IFT_VIRTUALIPADDRESS: 145 result = 1; 146 break; 147 default: 148 result = 0; 149 } 150 151 return (result); 152 } 153 154 static void 155 sctp_init_ifns_for_vrf(int vrfid) 156 { 157 /* 158 * Here we must apply ANY locks needed by the IFN we access and also 159 * make sure we lock any IFA that exists as we float through the 160 * list of IFA's 161 */ 162 struct ifnet *ifn; 163 struct ifaddr *ifa; 164 struct in6_ifaddr *ifa6; 165 struct sctp_ifa *sctp_ifa; 166 uint32_t ifa_flags; 167 168 TAILQ_FOREACH(ifn, &ifnet, if_list) { 169 TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) { 170 if (ifa->ifa_addr == NULL) { 171 continue; 172 } 173 if ((ifa->ifa_addr->sa_family != AF_INET) && 174 (ifa->ifa_addr->sa_family != AF_INET6) 175 ) { 176 /* non inet/inet6 skip */ 177 continue; 178 } 179 if (ifa->ifa_addr->sa_family == AF_INET6) { 180 ifa6 = (struct in6_ifaddr *)ifa; 181 ifa_flags = ifa6->ia6_flags; 182 if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) { 183 /* skip unspecifed addresses */ 184 continue; 185 } 186 } else if (ifa->ifa_addr->sa_family == AF_INET) { 187 if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) { 188 continue; 189 } 190 } 191 if (sctp_is_desired_interface_type(ifa) == 0) { 192 /* non desired type */ 193 continue; 194 } 195 if ((ifa->ifa_addr->sa_family == AF_INET6) || 196 (ifa->ifa_addr->sa_family == AF_INET)) { 197 if (ifa->ifa_addr->sa_family == AF_INET6) { 198 ifa6 = (struct in6_ifaddr *)ifa; 199 ifa_flags = ifa6->ia6_flags; 200 } else { 201 ifa_flags = 0; 202 } 203 sctp_ifa = sctp_add_addr_to_vrf(vrfid, 204 (void *)ifn, 205 ifn->if_index, 206 ifn->if_type, 207 ifn->if_xname, 208 (void *)ifa, 209 ifa->ifa_addr, 210 ifa_flags, 0 211 ); 212 if (sctp_ifa) { 213 sctp_ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE; 214 } 215 } 216 } 217 } 218 } 219 220 221 void 222 sctp_init_vrf_list(int vrfid) 223 { 224 if (vrfid > SCTP_MAX_VRF_ID) 225 /* can't do that */ 226 return; 227 228 /* Don't care about return here */ 229 (void)sctp_allocate_vrf(vrfid); 230 231 /* 232 * Now we need to build all the ifn's for this vrf and there 233 * addresses 234 */ 235 sctp_init_ifns_for_vrf(vrfid); 236 } 237 238 static uint8_t first_time = 0; 239 240 241 void 242 sctp_addr_change(struct ifaddr *ifa, int cmd) 243 { 244 struct sctp_ifa *ifap = NULL; 245 uint32_t ifa_flags = 0; 246 struct in6_ifaddr *ifa6; 247 248 /* 249 * BSD only has one VRF, if this changes we will need to hook in the 250 * right things here to get the id to pass to the address managment 251 * routine. 252 */ 253 if (first_time == 0) { 254 /* Special test to see if my ::1 will showup with this */ 255 first_time = 1; 256 sctp_init_ifns_for_vrf(SCTP_DEFAULT_VRFID); 257 } 258 if ((cmd != RTM_ADD) && (cmd != RTM_DELETE)) { 259 /* don't know what to do with this */ 260 return; 261 } 262 if (ifa->ifa_addr == NULL) { 263 return; 264 } 265 if ((ifa->ifa_addr->sa_family != AF_INET) && 266 (ifa->ifa_addr->sa_family != AF_INET6) 267 ) { 268 /* non inet/inet6 skip */ 269 return; 270 } 271 if (ifa->ifa_addr->sa_family == AF_INET6) { 272 ifa6 = (struct in6_ifaddr *)ifa; 273 ifa_flags = ifa6->ia6_flags; 274 if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) { 275 /* skip unspecifed addresses */ 276 return; 277 } 278 } else if (ifa->ifa_addr->sa_family == AF_INET) { 279 if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) { 280 return; 281 } 282 } 283 if (sctp_is_desired_interface_type(ifa) == 0) { 284 /* non desired type */ 285 return; 286 } 287 if (cmd == RTM_ADD) { 288 ifap = sctp_add_addr_to_vrf(SCTP_DEFAULT_VRFID, (void *)ifa->ifa_ifp, 289 ifa->ifa_ifp->if_index, ifa->ifa_ifp->if_type, 290 ifa->ifa_ifp->if_xname, 291 (void *)ifa, ifa->ifa_addr, ifa_flags, 1); 292 293 } else if (cmd == RTM_DELETE) { 294 295 sctp_del_addr_from_vrf(SCTP_DEFAULT_VRFID, ifa->ifa_addr, ifa->ifa_ifp->if_index); 296 /* 297 * We don't bump refcount here so when it completes the 298 * final delete will happen. 299 */ 300 } 301 } 302 303 struct mbuf * 304 sctp_get_mbuf_for_msg(unsigned int space_needed, int want_header, 305 int how, int allonebuf, int type) 306 { 307 struct mbuf *m = NULL; 308 309 m = m_getm2(NULL, space_needed, how, type, want_header ? M_PKTHDR : 0); 310 if (m == NULL) { 311 /* bad, no memory */ 312 return (m); 313 } 314 if (allonebuf) { 315 int siz; 316 317 if (SCTP_BUF_IS_EXTENDED(m)) { 318 siz = SCTP_BUF_EXTEND_SIZE(m); 319 } else { 320 if (want_header) 321 siz = MHLEN; 322 else 323 siz = MLEN; 324 } 325 if (siz < space_needed) { 326 m_freem(m); 327 return (NULL); 328 } 329 } 330 if (SCTP_BUF_NEXT(m)) { 331 sctp_m_freem(SCTP_BUF_NEXT(m)); 332 SCTP_BUF_NEXT(m) = NULL; 333 } 334 #ifdef SCTP_MBUF_LOGGING 335 if (SCTP_BUF_IS_EXTENDED(m)) { 336 sctp_log_mb(m, SCTP_MBUF_IALLOC); 337 } 338 #endif 339 return (m); 340 } 341