1 /*- 2 * Copyright (c) 2001-2007, 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_indata.h> 48 #include <sys/unistd.h> 49 50 #ifdef SCTP_DEBUG 51 extern uint32_t sctp_debug_on; 52 53 #endif 54 55 56 #if defined(SCTP_USE_THREAD_BASED_ITERATOR) 57 void 58 sctp_wakeup_iterator(void) 59 { 60 wakeup(&sctppcbinfo.iterator_running); 61 } 62 63 static void 64 sctp_iterator_thread(void *v) 65 { 66 SCTP_IPI_ITERATOR_WQ_LOCK(); 67 sctppcbinfo.iterator_running = 0; 68 while (1) { 69 msleep(&sctppcbinfo.iterator_running, 70 &sctppcbinfo.ipi_iterator_wq_mtx, 71 0, "waiting_for_work", 0); 72 sctp_iterator_worker(); 73 } 74 } 75 76 void 77 sctp_startup_iterator(void) 78 { 79 int ret; 80 81 ret = kthread_create(sctp_iterator_thread, 82 (void *)NULL, 83 &sctppcbinfo.thread_proc, 84 RFPROC, 85 SCTP_KTHREAD_PAGES, 86 SCTP_KTRHEAD_NAME); 87 } 88 89 #endif 90 91 92 void 93 sctp_gather_internal_ifa_flags(struct sctp_ifa *ifa) 94 { 95 struct in6_ifaddr *ifa6; 96 97 ifa6 = (struct in6_ifaddr *)ifa->ifa; 98 ifa->flags = ifa6->ia6_flags; 99 if (!ip6_use_deprecated) { 100 if (ifa->flags & 101 IN6_IFF_DEPRECATED) { 102 ifa->localifa_flags |= SCTP_ADDR_IFA_UNUSEABLE; 103 } else { 104 ifa->localifa_flags &= ~SCTP_ADDR_IFA_UNUSEABLE; 105 } 106 } else { 107 ifa->localifa_flags &= ~SCTP_ADDR_IFA_UNUSEABLE; 108 } 109 if (ifa->flags & 110 (IN6_IFF_DETACHED | 111 IN6_IFF_ANYCAST | 112 IN6_IFF_NOTREADY)) { 113 ifa->localifa_flags |= SCTP_ADDR_IFA_UNUSEABLE; 114 } else { 115 ifa->localifa_flags &= ~SCTP_ADDR_IFA_UNUSEABLE; 116 } 117 } 118 119 120 121 static uint32_t 122 sctp_is_desired_interface_type(struct ifaddr *ifa) 123 { 124 int result; 125 126 /* check the interface type to see if it's one we care about */ 127 switch (ifa->ifa_ifp->if_type) { 128 case IFT_ETHER: 129 case IFT_ISO88023: 130 case IFT_ISO88024: 131 case IFT_ISO88025: 132 case IFT_ISO88026: 133 case IFT_STARLAN: 134 case IFT_P10: 135 case IFT_P80: 136 case IFT_HY: 137 case IFT_FDDI: 138 case IFT_XETHER: 139 case IFT_ISDNBASIC: 140 case IFT_ISDNPRIMARY: 141 case IFT_PTPSERIAL: 142 case IFT_PPP: 143 case IFT_LOOP: 144 case IFT_SLIP: 145 case IFT_IP: 146 case IFT_IPOVERCDLC: 147 case IFT_IPOVERCLAW: 148 case IFT_VIRTUALIPADDRESS: 149 result = 1; 150 break; 151 default: 152 result = 0; 153 } 154 155 return (result); 156 } 157 158 static void 159 sctp_init_ifns_for_vrf(int vrfid) 160 { 161 /* 162 * Here we must apply ANY locks needed by the IFN we access and also 163 * make sure we lock any IFA that exists as we float through the 164 * list of IFA's 165 */ 166 struct ifnet *ifn; 167 struct ifaddr *ifa; 168 struct in6_ifaddr *ifa6; 169 struct sctp_ifa *sctp_ifa; 170 uint32_t ifa_flags; 171 172 TAILQ_FOREACH(ifn, &ifnet, if_list) { 173 TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) { 174 if (ifa->ifa_addr == NULL) { 175 continue; 176 } 177 if ((ifa->ifa_addr->sa_family != AF_INET) && 178 (ifa->ifa_addr->sa_family != AF_INET6) 179 ) { 180 /* non inet/inet6 skip */ 181 continue; 182 } 183 if (ifa->ifa_addr->sa_family == AF_INET6) { 184 ifa6 = (struct in6_ifaddr *)ifa; 185 ifa_flags = ifa6->ia6_flags; 186 if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) { 187 /* skip unspecifed addresses */ 188 continue; 189 } 190 } else if (ifa->ifa_addr->sa_family == AF_INET) { 191 if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) { 192 continue; 193 } 194 } 195 if (sctp_is_desired_interface_type(ifa) == 0) { 196 /* non desired type */ 197 continue; 198 } 199 if ((ifa->ifa_addr->sa_family == AF_INET6) || 200 (ifa->ifa_addr->sa_family == AF_INET)) { 201 if (ifa->ifa_addr->sa_family == AF_INET6) { 202 ifa6 = (struct in6_ifaddr *)ifa; 203 ifa_flags = ifa6->ia6_flags; 204 } else { 205 ifa_flags = 0; 206 } 207 sctp_ifa = sctp_add_addr_to_vrf(vrfid, 208 (void *)ifn, 209 ifn->if_index, 210 ifn->if_type, 211 ifn->if_xname, 212 (void *)ifa, 213 ifa->ifa_addr, 214 ifa_flags 215 ); 216 if (sctp_ifa) { 217 sctp_ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE; 218 } 219 } 220 } 221 } 222 } 223 224 225 void 226 sctp_init_vrf_list(int vrfid) 227 { 228 if (vrfid > SCTP_MAX_VRF_ID) 229 /* can't do that */ 230 return; 231 232 /* Don't care about return here */ 233 (void)sctp_allocate_vrf(vrfid); 234 235 /* 236 * Now we need to build all the ifn's for this vrf and there 237 * addresses 238 */ 239 sctp_init_ifns_for_vrf(vrfid); 240 } 241 242 static uint8_t first_time = 0; 243 244 245 void 246 sctp_addr_change(struct ifaddr *ifa, int cmd) 247 { 248 struct sctp_laddr *wi; 249 struct sctp_ifa *ifap = NULL; 250 uint32_t ifa_flags = 0; 251 struct in6_ifaddr *ifa6; 252 253 /* 254 * BSD only has one VRF, if this changes we will need to hook in the 255 * right things here to get the id to pass to the address managment 256 * routine. 257 */ 258 if (first_time == 0) { 259 /* Special test to see if my ::1 will showup with this */ 260 first_time = 1; 261 sctp_init_ifns_for_vrf(SCTP_DEFAULT_VRFID); 262 } 263 if ((cmd != RTM_ADD) && (cmd != RTM_DELETE)) { 264 /* don't know what to do with this */ 265 return; 266 } 267 if (ifa->ifa_addr == NULL) { 268 return; 269 } 270 if ((ifa->ifa_addr->sa_family != AF_INET) && 271 (ifa->ifa_addr->sa_family != AF_INET6) 272 ) { 273 /* non inet/inet6 skip */ 274 return; 275 } 276 if (ifa->ifa_addr->sa_family == AF_INET6) { 277 ifa6 = (struct in6_ifaddr *)ifa; 278 ifa_flags = ifa6->ia6_flags; 279 if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) { 280 /* skip unspecifed addresses */ 281 return; 282 } 283 } else if (ifa->ifa_addr->sa_family == AF_INET) { 284 if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) { 285 return; 286 } 287 } 288 if (sctp_is_desired_interface_type(ifa) == 0) { 289 /* non desired type */ 290 return; 291 } 292 if (cmd == RTM_ADD) { 293 ifap = sctp_add_addr_to_vrf(SCTP_DEFAULT_VRFID, (void *)ifa->ifa_ifp, 294 ifa->ifa_ifp->if_index, ifa->ifa_ifp->if_type, 295 ifa->ifa_ifp->if_xname, 296 (void *)ifa, ifa->ifa_addr, ifa_flags); 297 /* 298 * Bump up the refcount so that when the timer completes it 299 * will drop back down. 300 */ 301 if (ifap) 302 atomic_add_int(&ifap->refcount, 1); 303 304 } else if (cmd == RTM_DELETE) { 305 306 ifap = sctp_del_addr_from_vrf(SCTP_DEFAULT_VRFID, ifa->ifa_addr, ifa->ifa_ifp->if_index); 307 /* 308 * We don't bump refcount here so when it completes the 309 * final delete will happen. 310 */ 311 } 312 if (ifap == NULL) 313 return; 314 315 wi = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_laddr, struct sctp_laddr); 316 if (wi == NULL) { 317 /* 318 * Gak, what can we do? We have lost an address change can 319 * you say HOSED? 320 */ 321 #ifdef SCTP_DEBUG 322 if (sctp_debug_on & SCTP_DEBUG_PCB1) { 323 printf("Lost and address change ???\n"); 324 } 325 #endif /* SCTP_DEBUG */ 326 327 /* Opps, must decrement the count */ 328 sctp_free_ifa(ifap); 329 return; 330 } 331 SCTP_INCR_LADDR_COUNT(); 332 bzero(wi, sizeof(*wi)); 333 wi->ifa = ifap; 334 if (cmd == RTM_ADD) { 335 wi->action = SCTP_ADD_IP_ADDRESS; 336 } else if (cmd == RTM_DELETE) { 337 wi->action = SCTP_DEL_IP_ADDRESS; 338 } 339 SCTP_IPI_ITERATOR_WQ_LOCK(); 340 /* 341 * Should this really be a tailq? As it is we will process the 342 * newest first :-0 343 */ 344 LIST_INSERT_HEAD(&sctppcbinfo.addr_wq, wi, sctp_nxt_addr); 345 sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ, 346 (struct sctp_inpcb *)NULL, 347 (struct sctp_tcb *)NULL, 348 (struct sctp_nets *)NULL); 349 SCTP_IPI_ITERATOR_WQ_UNLOCK(); 350 } 351