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. --- 17 unchanged lines hidden (view full) --- 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_pcb.c,v 1.38 2005/03/06 16:04:18 itojun Exp $ */ 32 33#include <sys/cdefs.h> |
34__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.c 167598 2007-03-15 11:27:14Z rrs $"); |
35 36#include <netinet/sctp_os.h> 37#include <sys/proc.h> 38#include <netinet/sctp_var.h> |
39#include <netinet/sctp_sysctl.h> |
40#include <netinet/sctp_pcb.h> 41#include <netinet/sctputil.h> 42#include <netinet/sctp.h> 43#include <netinet/sctp_header.h> 44#include <netinet/sctp_asconf.h> 45#include <netinet/sctp_output.h> 46#include <netinet/sctp_timer.h> |
47#include <netinet/sctp_bsd_addr.h> |
48 49 |
50struct sctp_epinfo sctppcbinfo; 51 52/* FIX: we don't handle multiple link local scopes */ 53/* "scopeless" replacement IN6_ARE_ADDR_EQUAL */ 54int 55SCTP6_ARE_ADDR_EQUAL(struct in6_addr *a, struct in6_addr *b) 56{ 57 struct in6_addr tmp_a, tmp_b; 58 59 /* use a copy of a and b */ 60 tmp_a = *a; 61 tmp_b = *b; 62 in6_clearscope(&tmp_a); 63 in6_clearscope(&tmp_b); 64 return (IN6_ARE_ADDR_EQUAL(&tmp_a, &tmp_b)); 65} 66 |
67void 68sctp_fill_pcbinfo(struct sctp_pcbinfo *spcb) 69{ 70 /* 71 * We really don't need to lock this, but I will just because it 72 * does not hurt. 73 */ 74 SCTP_INP_INFO_RLOCK(); --- 4 unchanged lines hidden (view full) --- 79 spcb->chk_count = sctppcbinfo.ipi_count_chunk; 80 spcb->readq_count = sctppcbinfo.ipi_count_readq; 81 spcb->stream_oque = sctppcbinfo.ipi_count_strmoq; 82 spcb->free_chunks = sctppcbinfo.ipi_free_chunks; 83 84 SCTP_INP_INFO_RUNLOCK(); 85} 86 |
87/* 88 * Addresses are added to VRF's (Virtual Router's). For BSD we 89 * have only the default VRF 0. We maintain a hash list of 90 * VRF's. Each VRF has its own list of sctp_ifn's. Each of 91 * these has a list of addresses. When we add a new address 92 * to a VRF we lookup the ifn/ifn_index, if the ifn does 93 * not exist we create it and add it to the list of IFN's 94 * within the VRF. Once we have the sctp_ifn, we add the 95 * address to the list. So we look something like: 96 * 97 * hash-vrf-table 98 * vrf-> ifn-> ifn -> ifn 99 * vrf | 100 * ... +--ifa-> ifa -> ifa 101 * vrf 102 * 103 * We keep these seperate lists since the SCTP subsystem will 104 * point to these from its source address selection nets structure. 105 * When an address is deleted it does not happen right away on 106 * the SCTP side, it gets scheduled. What we do when a 107 * delete happens is immediately remove the address from 108 * the master list and decrement the refcount. As our 109 * addip iterator works through and frees the src address 110 * selection pointing to the sctp_ifa, eventually the refcount 111 * will reach 0 and we will delete it. Note that it is assumed 112 * that any locking on system level ifn/ifa is done at the 113 * caller of these functions and these routines will only 114 * lock the SCTP structures as they add or delete things. 115 * 116 * Other notes on VRF concepts. 117 * - An endpoint can be in multiple VRF's 118 * - An association lives within a VRF and only one VRF. 119 * - Any incoming packet we can deduce the VRF for by 120 * looking at the mbuf/pak inbound (for BSD its VRF=0 :D) 121 * - Any downward send call or connect call must supply the 122 * VRF via ancillary data or via some sort of set default 123 * VRF socket option call (again for BSD no brainer since 124 * the VRF is always 0). 125 * - An endpoint may add multiple VRF's to it. 126 * - Listening sockets can accept associations in any 127 * of the VRF's they are in but the assoc will end up 128 * in only one VRF (gotten from the packet or connect/send). 129 * 130 */ |
131 |
132struct sctp_vrf * 133sctp_allocate_vrf(int vrfid) 134{ 135 struct sctp_vrf *vrf = NULL; 136 struct sctp_vrflist *bucket; 137 138 /* First allocate the VRF structure */ 139 vrf = sctp_find_vrf(vrfid); 140 if (vrf) { 141 /* Already allocated */ 142 return (vrf); 143 } 144 SCTP_MALLOC(vrf, struct sctp_vrf *, sizeof(struct sctp_vrf), 145 "SCTP_VRF"); 146 if (vrf == NULL) { 147 /* No memory */ 148#ifdef INVARIANTS 149 panic("No memory for VRF:%d", vrfid); 150#endif 151 return (NULL); 152 } 153 /* setup the VRF */ 154 memset(vrf, 0, sizeof(struct sctp_vrf)); 155 vrf->vrf_id = vrfid; 156 LIST_INIT(&vrf->ifnlist); 157 vrf->total_ifa_count = 0; 158 /* Add it to the hash table */ 159 bucket = &sctppcbinfo.sctp_vrfhash[(vrfid & sctppcbinfo.hashvrfmark)]; 160 LIST_INSERT_HEAD(bucket, vrf, next_vrf); 161 return (vrf); 162} 163 164 165struct sctp_ifn * 166sctp_find_ifn(struct sctp_vrf *vrf, void *ifn, uint32_t ifn_index) 167{ 168 struct sctp_ifn *sctp_ifnp; 169 170 /* 171 * We assume the lock is held for the addresses if thats wrong 172 * problems could occur :-) 173 */ 174 LIST_FOREACH(sctp_ifnp, &vrf->ifnlist, next_ifn) { 175 if (sctp_ifnp->ifn_index == ifn_index) { 176 return (sctp_ifnp); 177 } 178 if (sctp_ifnp->ifn_p && ifn && (sctp_ifnp->ifn_p == ifn)) { 179 return (sctp_ifnp); 180 } 181 } 182 return (NULL); 183} 184 185struct sctp_vrf * 186sctp_find_vrf(uint32_t vrfid) 187{ 188 struct sctp_vrflist *bucket; 189 struct sctp_vrf *liste; 190 191 bucket = &sctppcbinfo.sctp_vrfhash[(vrfid & sctppcbinfo.hashvrfmark)]; 192 LIST_FOREACH(liste, bucket, next_vrf) { 193 if (vrfid == liste->vrf_id) { 194 return (liste); 195 } 196 } 197 return (NULL); 198} 199 200void 201sctp_free_ifa(struct sctp_ifa *sctp_ifap) 202{ 203 int ret; 204 205 ret = atomic_fetchadd_int(&sctp_ifap->refcount, -1); 206 if (ret == 1) { 207 /* We zero'd the count */ 208 SCTP_FREE(sctp_ifap); 209 } 210} 211 212struct sctp_ifa * 213sctp_add_addr_to_vrf(uint32_t vrfid, void *ifn, uint32_t ifn_index, 214 uint32_t ifn_type, const char *if_name, 215 void *ifa, struct sockaddr *addr, uint32_t ifa_flags) 216{ 217 struct sctp_vrf *vrf; 218 struct sctp_ifn *sctp_ifnp = NULL; 219 struct sctp_ifa *sctp_ifap = NULL; 220 221 /* How granular do we need the locks to be here? */ 222 SCTP_IPI_ADDR_LOCK(); 223 vrf = sctp_find_vrf(vrfid); 224 if (vrf == NULL) { 225 vrf = sctp_allocate_vrf(vrfid); 226 if (vrf == NULL) { 227 SCTP_IPI_ADDR_UNLOCK(); 228 return (NULL); 229 } 230 } 231 sctp_ifnp = sctp_find_ifn(vrf, ifn, ifn_index); 232 if (sctp_ifnp == NULL) { 233 /* 234 * build one and add it, can't hold lock until after malloc 235 * done though. 236 */ 237 SCTP_IPI_ADDR_UNLOCK(); 238 SCTP_MALLOC(sctp_ifnp, struct sctp_ifn *, sizeof(struct sctp_ifn), "SCTP_IFN"); 239 if (sctp_ifnp == NULL) { 240#ifdef INVARIANTS 241 panic("No memory for IFN:%u", sctp_ifnp->ifn_index); 242#endif 243 return (NULL); 244 } 245 sctp_ifnp->ifn_index = ifn_index; 246 sctp_ifnp->ifn_p = ifn; 247 sctp_ifnp->ifn_type = ifn_type; 248 sctp_ifnp->ifa_count = 0; 249 sctp_ifnp->refcount = 0; 250 sctp_ifnp->vrf = vrf; 251 memcpy(sctp_ifnp->ifn_name, if_name, SCTP_IFNAMSIZ); 252 LIST_INIT(&sctp_ifnp->ifalist); 253 SCTP_IPI_ADDR_LOCK(); 254 LIST_INSERT_HEAD(&vrf->ifnlist, sctp_ifnp, next_ifn); 255 } 256 sctp_ifap = sctp_find_ifa_by_addr(addr, vrf->vrf_id, 1); 257 if (sctp_ifap) { 258 /* Hmm, it already exists? */ 259 if ((sctp_ifap->ifn_p) && 260 (sctp_ifap->ifn_p->ifn_index == ifn_index)) { 261 if (sctp_ifap->localifa_flags & SCTP_BEING_DELETED) { 262 /* easy to solve, just switch back to active */ 263 sctp_ifap->localifa_flags = SCTP_ADDR_VALID; 264 sctp_ifap->ifn_p = sctp_ifnp; 265 exit_stage_left: 266 SCTP_IPI_ADDR_UNLOCK(); 267 return (sctp_ifap); 268 } else { 269 goto exit_stage_left; 270 } 271 } else { 272 if (sctp_ifap->ifn_p) { 273 /* 274 * The first IFN gets the address, 275 * duplicates are ignored. 276 */ 277 goto exit_stage_left; 278 } else { 279 /* repair ifnp which was NULL ? */ 280 sctp_ifap->localifa_flags = SCTP_ADDR_VALID; 281 sctp_ifap->ifn_p = sctp_ifnp; 282 atomic_add_int(&sctp_ifnp->refcount, 1); 283 } 284 goto exit_stage_left; 285 } 286 } 287 SCTP_IPI_ADDR_UNLOCK(); 288 SCTP_MALLOC(sctp_ifap, struct sctp_ifa *, sizeof(struct sctp_ifa), "SCTP_IFA"); 289 if (sctp_ifap == NULL) { 290#ifdef INVARIANTS 291 panic("No memory for IFA"); 292#endif 293 return (NULL); 294 } 295 memset(sctp_ifap, 0, sizeof(sctp_ifap)); 296 sctp_ifap->ifn_p = sctp_ifnp; 297 atomic_add_int(&sctp_ifnp->refcount, 1); 298 299 sctp_ifap->ifa = ifa; 300 memcpy(&sctp_ifap->address, addr, addr->sa_len); 301 sctp_ifap->localifa_flags = SCTP_ADDR_VALID | SCTP_ADDR_DEFER_USE; 302 sctp_ifap->flags = ifa_flags; 303 /* Set scope */ 304 if (sctp_ifap->address.sa.sa_family == AF_INET) { 305 struct sockaddr_in *sin; 306 307 sin = (struct sockaddr_in *)&sctp_ifap->address.sin; 308 if (SCTP_IFN_IS_IFT_LOOP(sctp_ifap->ifn_p) || 309 (IN4_ISLOOPBACK_ADDRESS(&sin->sin_addr))) { 310 sctp_ifap->src_is_loop = 1; 311 } 312 if ((IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) { 313 sctp_ifap->src_is_priv = 1; 314 } 315 } else if (sctp_ifap->address.sa.sa_family == AF_INET6) { 316 /* ok to use deprecated addresses? */ 317 struct sockaddr_in6 *sin6; 318 319 sin6 = (struct sockaddr_in6 *)&sctp_ifap->address.sin6; 320 if (SCTP_IFN_IS_IFT_LOOP(sctp_ifap->ifn_p) || 321 (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))) { 322 sctp_ifap->src_is_loop = 1; 323 } 324 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 325 sctp_ifap->src_is_priv = 1; 326 } 327 } 328 if ((sctp_ifap->src_is_priv == 0) && 329 (sctp_ifap->src_is_loop == 0)) { 330 sctp_ifap->src_is_glob = 1; 331 } 332 SCTP_IPI_ADDR_LOCK(); 333 sctp_ifap->refcount = 1; 334 LIST_INSERT_HEAD(&sctp_ifnp->ifalist, sctp_ifap, next_ifa); 335 sctp_ifnp->ifa_count++; 336 vrf->total_ifa_count++; 337 SCTP_IPI_ADDR_UNLOCK(); 338 return (sctp_ifap); 339} 340 341struct sctp_ifa * 342sctp_del_addr_from_vrf(uint32_t vrfid, struct sockaddr *addr, 343 uint32_t ifn_index) 344{ 345 struct sctp_vrf *vrf; 346 struct sctp_ifa *sctp_ifap = NULL; 347 struct sctp_ifn *sctp_ifnp = NULL; 348 349 SCTP_IPI_ADDR_LOCK(); 350 351 vrf = sctp_find_vrf(vrfid); 352 if (vrf == NULL) { 353 printf("Can't find vrfid:%d\n", vrfid); 354 goto out_now; 355 } 356 sctp_ifnp = sctp_find_ifn(vrf, (void *)NULL, ifn_index); 357 if (sctp_ifnp == NULL) { 358 sctp_ifap = sctp_find_ifa_by_addr(addr, vrf->vrf_id, 1); 359 } else { 360 sctp_ifap = sctp_find_ifa_in_ifn(sctp_ifnp, addr, 1); 361 } 362 363 if (sctp_ifap) { 364 sctp_ifap->localifa_flags &= SCTP_ADDR_VALID; 365 sctp_ifap->localifa_flags |= SCTP_BEING_DELETED; 366 sctp_ifnp->ifa_count--; 367 vrf->total_ifa_count--; 368 LIST_REMOVE(sctp_ifap, next_ifa); 369 atomic_add_int(&sctp_ifnp->refcount, -1); 370 } else { 371 printf("Del Addr-ifn:%d Could not find address:", 372 ifn_index); 373 sctp_print_address(addr); 374 } 375out_now: 376 SCTP_IPI_ADDR_UNLOCK(); 377 return (sctp_ifap); 378} 379 |
380/* 381 * Notes on locks for FreeBSD 5 and up. All association lookups that have a 382 * definte ep, the INP structure is assumed to be locked for reading. If we 383 * need to go find the INP (ususally when a **inp is passed) then we must 384 * lock the INFO structure first and if needed lock the INP too. Note that if 385 * we lock it we must 386 * 387 */ --- 67 unchanged lines hidden (view full) --- 455 if (laddr->ifa == NULL) { 456#ifdef SCTP_DEBUG 457 if (sctp_debug_on & SCTP_DEBUG_PCB1) { 458 printf("An ounce of prevention is worth a pound of cure\n"); 459 } 460#endif 461 continue; 462 } |
463 if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) { |
464#ifdef SCTP_DEBUG 465 if (sctp_debug_on & SCTP_DEBUG_PCB1) { |
466 printf("ifa being deleted\n"); |
467 } 468#endif 469 continue; 470 } |
471 if (laddr->ifa->address.sa.sa_family == |
472 to->sa_family) { 473 /* see if it matches */ 474 struct sockaddr_in *intf_addr, *sin; 475 |
476 intf_addr = &laddr->ifa->address.sin; |
477 sin = (struct sockaddr_in *)to; 478 if (from->sa_family == AF_INET) { 479 if (sin->sin_addr.s_addr == 480 intf_addr->sin_addr.s_addr) { 481 match = 1; 482 break; 483 } 484 } else { 485 struct sockaddr_in6 *intf_addr6; 486 struct sockaddr_in6 *sin6; 487 488 sin6 = (struct sockaddr_in6 *) 489 to; |
490 intf_addr6 = &laddr->ifa->address.sin6; |
491 492 if (SCTP6_ARE_ADDR_EQUAL(&sin6->sin6_addr, 493 &intf_addr6->sin6_addr)) { 494 match = 1; 495 break; 496 } 497 } 498 } --- 372 unchanged lines hidden (view full) --- 871 } 872 SCTP_INP_INFO_RUNLOCK(); 873 return (NULL); 874} 875 876 877static struct sctp_inpcb * 878sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head, |
879 uint16_t lport, uint32_t vrf_id) |
880{ 881 struct sctp_inpcb *inp; 882 struct sockaddr_in *sin; 883 struct sockaddr_in6 *sin6; 884 struct sctp_laddr *laddr; |
885 int fnd; |
886 887 /* 888 * Endpoing probe expects that the INP_INFO is locked. 889 */ 890 if (nam->sa_family == AF_INET) { 891 sin = (struct sockaddr_in *)nam; 892 sin6 = NULL; 893 } else if (nam->sa_family == AF_INET6) { --- 22 unchanged lines hidden (view full) --- 916 continue; 917 } 918 /* A V6 address and the endpoint is NOT bound V6 */ 919 if (nam->sa_family == AF_INET6 && 920 (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { 921 SCTP_INP_RUNLOCK(inp); 922 continue; 923 } |
924 /* does a VRF id match? */ 925 fnd = 0; 926 if (inp->def_vrf_id == vrf_id) 927 fnd = 1; 928 |
929 SCTP_INP_RUNLOCK(inp); |
930 if (!fnd) 931 continue; |
932 return (inp); 933 } 934 SCTP_INP_RUNLOCK(inp); 935 } 936 937 if ((nam->sa_family == AF_INET) && 938 (sin->sin_addr.s_addr == INADDR_ANY)) { 939 /* Can't hunt for one that has no address specified */ --- 20 unchanged lines hidden (view full) --- 960 /* 961 * Ok this could be a likely candidate, look at all of its 962 * addresses 963 */ 964 if (inp->sctp_lport != lport) { 965 SCTP_INP_RUNLOCK(inp); 966 continue; 967 } |
968 /* does a VRF id match? */ 969 fnd = 0; 970 if (inp->def_vrf_id == vrf_id) 971 fnd = 1; 972 973 if (!fnd) { 974 SCTP_INP_RUNLOCK(inp); 975 continue; 976 } |
977 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { 978 if (laddr->ifa == NULL) { 979#ifdef SCTP_DEBUG 980 if (sctp_debug_on & SCTP_DEBUG_PCB1) { 981 printf("An ounce of prevention is worth a pound of cure\n"); 982 } 983#endif 984 continue; 985 } 986#ifdef SCTP_DEBUG 987 if (sctp_debug_on & SCTP_DEBUG_PCB1) { 988 printf("Ok laddr->ifa:%p is possible, ", 989 laddr->ifa); 990 } 991#endif |
992 if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) { |
993#ifdef SCTP_DEBUG 994 if (sctp_debug_on & SCTP_DEBUG_PCB1) { |
995 printf("Huh IFA being deleted\n"); |
996 } 997#endif 998 continue; 999 } |
1000 if (laddr->ifa->address.sa.sa_family == nam->sa_family) { |
1001 /* possible, see if it matches */ 1002 struct sockaddr_in *intf_addr; 1003 |
1004 intf_addr = &laddr->ifa->address.sin; |
1005 if (nam->sa_family == AF_INET) { 1006 if (sin->sin_addr.s_addr == 1007 intf_addr->sin_addr.s_addr) { 1008 SCTP_INP_RUNLOCK(inp); 1009 return (inp); 1010 } 1011 } else if (nam->sa_family == AF_INET6) { 1012 struct sockaddr_in6 *intf_addr6; 1013 |
1014 intf_addr6 = &laddr->ifa->address.sin6; |
1015 if (SCTP6_ARE_ADDR_EQUAL(&sin6->sin6_addr, 1016 &intf_addr6->sin6_addr)) { 1017 SCTP_INP_RUNLOCK(inp); 1018 return (inp); 1019 } 1020 } 1021 } 1022 } 1023 SCTP_INP_RUNLOCK(inp); 1024 } 1025 return (NULL); 1026} 1027 1028 1029struct sctp_inpcb * |
1030sctp_pcb_findep(struct sockaddr *nam, int find_tcp_pool, int have_lock, uint32_t vrf_id) |
1031{ 1032 /* 1033 * First we check the hash table to see if someone has this port 1034 * bound with just the port. 1035 */ 1036 struct sctp_inpcb *inp; 1037 struct sctppcbhead *head; 1038 struct sockaddr_in *sin; --- 17 unchanged lines hidden (view full) --- 1056 */ 1057 /* Find the head of the ALLADDR chain */ 1058 if (have_lock == 0) { 1059 SCTP_INP_INFO_RLOCK(); 1060 1061 } 1062 head = &sctppcbinfo.sctp_ephash[SCTP_PCBHASH_ALLADDR(lport, 1063 sctppcbinfo.hashmark)]; |
1064 inp = sctp_endpoint_probe(nam, head, lport, vrf_id); |
1065 1066 /* 1067 * If the TCP model exists it could be that the main listening 1068 * endpoint is gone but there exists a connected socket for this guy 1069 * yet. If so we can return the first one that we find. This may NOT 1070 * be the correct one but the sctp_findassociation_ep_addr has 1071 * further code to look at all TCP models. 1072 */ --- 4 unchanged lines hidden (view full) --- 1077 /* 1078 * This is real gross, but we do NOT have a remote 1079 * port at this point depending on who is calling. 1080 * We must therefore look for ANY one that matches 1081 * our local port :/ 1082 */ 1083 head = &sctppcbinfo.sctp_tcpephash[i]; 1084 if (LIST_FIRST(head)) { |
1085 inp = sctp_endpoint_probe(nam, head, lport, vrf_id); |
1086 if (inp) { 1087 /* Found one */ 1088 break; 1089 } 1090 } 1091 } 1092 } 1093 if (inp) { --- 7 unchanged lines hidden (view full) --- 1101 1102/* 1103 * Find an association for an endpoint with the pointer to whom you want to 1104 * send to and the endpoint pointer. The address can be IPv4 or IPv6. We may 1105 * need to change the *to to some other struct like a mbuf... 1106 */ 1107struct sctp_tcb * 1108sctp_findassociation_addr_sa(struct sockaddr *to, struct sockaddr *from, |
1109 struct sctp_inpcb **inp_p, struct sctp_nets **netp, int find_tcp_pool, uint32_t vrf_id) |
1110{ 1111 struct sctp_inpcb *inp; 1112 struct sctp_tcb *retval; 1113 1114 SCTP_INP_INFO_RLOCK(); 1115 if (find_tcp_pool) { 1116 if (inp_p != NULL) { 1117 retval = sctp_tcb_special_locate(inp_p, from, to, netp); 1118 } else { 1119 retval = sctp_tcb_special_locate(&inp, from, to, netp); 1120 } 1121 if (retval != NULL) { 1122 SCTP_INP_INFO_RUNLOCK(); 1123 return (retval); 1124 } 1125 } |
1126 inp = sctp_pcb_findep(to, 0, 1, vrf_id); |
1127 if (inp_p != NULL) { 1128 *inp_p = inp; 1129 } 1130 SCTP_INP_INFO_RUNLOCK(); 1131 1132 if (inp == NULL) { 1133 return (NULL); 1134 } --- 183 unchanged lines hidden (view full) --- 1318{ 1319 int find_tcp_pool; 1320 struct ip *iph; 1321 struct sctp_tcb *retval; 1322 struct sockaddr_storage to_store, from_store; 1323 struct sockaddr *to = (struct sockaddr *)&to_store; 1324 struct sockaddr *from = (struct sockaddr *)&from_store; 1325 struct sctp_inpcb *inp; |
1326 uint32_t vrf_id; |
1327 |
1328 vrf_id = SCTP_DEFAULT_VRFID; |
1329 iph = mtod(m, struct ip *); 1330 if (iph->ip_v == IPVERSION) { 1331 /* its IPv4 */ 1332 struct sockaddr_in *from4; 1333 1334 from4 = (struct sockaddr_in *)&from_store; 1335 bzero(from4, sizeof(*from4)); 1336 from4->sin_family = AF_INET; --- 66 unchanged lines hidden (view full) --- 1403 (ch->chunk_type != SCTP_INITIATION_ACK) && 1404 (ch->chunk_type != SCTP_COOKIE_ACK) && 1405 (ch->chunk_type != SCTP_COOKIE_ECHO)) { 1406 /* Other chunk types go to the tcp pool. */ 1407 find_tcp_pool = 1; 1408 } 1409 if (inp_p) { 1410 retval = sctp_findassociation_addr_sa(to, from, inp_p, netp, |
1411 find_tcp_pool, vrf_id); |
1412 inp = *inp_p; 1413 } else { 1414 retval = sctp_findassociation_addr_sa(to, from, &inp, netp, |
1415 find_tcp_pool, vrf_id); |
1416 } 1417#ifdef SCTP_DEBUG 1418 if (sctp_debug_on & SCTP_DEBUG_PCB1) { 1419 printf("retval:%p inp:%p\n", retval, inp); 1420 } 1421#endif 1422 if (retval == NULL && inp) { 1423 /* Found a EP but not this address */ --- 150 unchanged lines hidden (view full) --- 1574 stcb = sctp_findassociation_ep_addr(inp_p, 1575 (struct sockaddr *)&remote_store, netp, 1576 (struct sockaddr *)&local_store, NULL); 1577 } 1578 return (stcb); 1579} 1580 1581 |
1582/* 1583 * allocate a sctp_inpcb and setup a temporary binding to a port/all 1584 * addresses. This way if we don't get a bind we by default pick a ephemeral 1585 * port with all addresses bound. 1586 */ 1587int 1588sctp_inpcb_alloc(struct socket *so) 1589{ --- 48 unchanged lines hidden (view full) --- 1638 } 1639#endif /* IPSEC */ 1640 SCTP_INCR_EP_COUNT(); 1641 inp->ip_inp.inp.inp_ip_ttl = ip_defttl; 1642 SCTP_INP_INFO_WUNLOCK(); 1643 1644 so->so_pcb = (caddr_t)inp; 1645 |
1646 if ((SCTP_SO_TYPE(so) == SOCK_DGRAM) || 1647 (SCTP_SO_TYPE(so) == SOCK_SEQPACKET)) { |
1648 /* UDP style socket */ 1649 inp->sctp_flags = (SCTP_PCB_FLAGS_UDPTYPE | 1650 SCTP_PCB_FLAGS_UNBOUND); 1651 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT); 1652 /* Be sure it is NON-BLOCKING IO for UDP */ |
1653 /* SCTP_SET_SO_NBIO(so); */ 1654 } else if (SCTP_SO_TYPE(so) == SOCK_STREAM) { |
1655 /* TCP style socket */ 1656 inp->sctp_flags = (SCTP_PCB_FLAGS_TCPTYPE | 1657 SCTP_PCB_FLAGS_UNBOUND); 1658 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT); 1659 /* Be sure we have blocking IO by default */ |
1660 SCTP_CLEAR_SO_NBIO(so); |
1661 } else { 1662 /* 1663 * unsupported socket type (RAW, etc)- in case we missed it 1664 * in protosw 1665 */ 1666 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_ep, inp); 1667 return (EOPNOTSUPP); 1668 } 1669 inp->sctp_tcbhash = SCTP_HASH_INIT(sctp_pcbtblsize, 1670 &inp->sctp_hashmark); 1671 if (inp->sctp_tcbhash == NULL) { 1672 printf("Out of SCTP-INPCB->hashinit - no resources\n"); 1673 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_ep, inp); 1674 return (ENOBUFS); 1675 } |
1676 inp->def_vrf_id = SCTP_DEFAULT_VRFID; 1677 |
1678 SCTP_INP_INFO_WLOCK(); 1679 SCTP_INP_LOCK_INIT(inp); 1680 SCTP_INP_READ_INIT(inp); 1681 SCTP_ASOC_CREATE_LOCK_INIT(inp); 1682 /* lock the new ep */ 1683 SCTP_INP_WLOCK(inp); 1684 1685 /* add it to the info area */ 1686 LIST_INSERT_HEAD(&sctppcbinfo.listhead, inp, sctp_list); 1687 SCTP_INP_INFO_WUNLOCK(); 1688 1689 TAILQ_INIT(&inp->read_queue); 1690 LIST_INIT(&inp->sctp_addr_list); |
1691 |
1692 LIST_INIT(&inp->sctp_asoc_list); 1693 1694#ifdef SCTP_TRACK_FREED_ASOCS 1695 /* TEMP CODE */ 1696 LIST_INIT(&inp->sctp_asoc_free_list); 1697#endif 1698 /* Init the timer structure for signature change */ 1699 SCTP_OS_TIMER_INIT(&inp->sctp_ep.signature_change.timer); --- 10 unchanged lines hidden (view full) --- 1710 m->sctp_timeoutticks[SCTP_TIMER_PMTU] = SEC_TO_TICKS(sctp_pmtu_raise_time_default); 1711 m->sctp_timeoutticks[SCTP_TIMER_MAXSHUTDOWN] = SEC_TO_TICKS(sctp_shutdown_guard_time_default); 1712 m->sctp_timeoutticks[SCTP_TIMER_SIGNATURE] = SEC_TO_TICKS(sctp_secret_lifetime_default); 1713 /* all max/min max are in ms */ 1714 m->sctp_maxrto = sctp_rto_max_default; 1715 m->sctp_minrto = sctp_rto_min_default; 1716 m->initial_rto = sctp_rto_initial_default; 1717 m->initial_init_rto_max = sctp_init_rto_max_default; |
1718 m->sctp_sack_freq = sctp_sack_freq_default; |
1719 1720 m->max_open_streams_intome = MAX_SCTP_STREAMS; 1721 1722 m->max_init_times = sctp_init_rtx_max_default; 1723 m->max_send_times = sctp_assoc_rtx_max_default; 1724 m->def_net_failure = sctp_path_rtx_max_default; 1725 m->sctp_sws_sender = SCTP_SWS_SENDER_DEF; 1726 m->sctp_sws_receiver = SCTP_SWS_RECEIVER_DEF; --- 21 unchanged lines hidden (view full) --- 1748 1749 for (i = 0; i < SCTP_NUMBER_OF_SECRETS; i++) { 1750 m->secret_key[0][i] = sctp_select_initial_TSN(m); 1751 } 1752 sctp_timer_start(SCTP_TIMER_TYPE_NEWCOOKIE, inp, NULL, NULL); 1753 1754 /* How long is a cookie good for ? */ 1755 m->def_cookie_life = sctp_valid_cookie_life_default; |
1756 /* 1757 * Initialize authentication parameters 1758 */ 1759 m->local_hmacs = sctp_default_supported_hmaclist(); 1760 m->local_auth_chunks = sctp_alloc_chunklist(); 1761 sctp_auth_set_default_chunks(m->local_auth_chunks); 1762 LIST_INIT(&m->shared_keys); 1763 /* add default NULL key as key id 0 */ --- 114 unchanged lines hidden (view full) --- 1878 net->rxt_timer.ep = (void *)new_inp; 1879 net->fr_timer.ep = (void *)new_inp; 1880 } 1881 SCTP_INP_WUNLOCK(new_inp); 1882 SCTP_INP_WUNLOCK(old_inp); 1883} 1884 1885static int |
1886sctp_isport_inuse(struct sctp_inpcb *inp, uint16_t lport, uint32_t vrf_id) |
1887{ 1888 struct sctppcbhead *head; 1889 struct sctp_inpcb *t_inp; |
1890 int fnd; |
1891 1892 head = &sctppcbinfo.sctp_ephash[SCTP_PCBHASH_ALLADDR(lport, 1893 sctppcbinfo.hashmark)]; 1894 1895 LIST_FOREACH(t_inp, head, sctp_hash) { 1896 if (t_inp->sctp_lport != lport) { 1897 continue; 1898 } |
1899 /* is it in the VRF in question */ 1900 fnd = 0; 1901 if (t_inp->def_vrf_id == vrf_id) 1902 fnd = 1; 1903 if (!fnd) 1904 continue; 1905 |
1906 /* This one is in use. */ 1907 /* check the v6/v4 binding issue */ 1908 if ((t_inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 1909 SCTP_IPV6_V6ONLY(t_inp)) { 1910 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { 1911 /* collision in V6 space */ 1912 return (1); 1913 } else { --- 24 unchanged lines hidden (view full) --- 1938{ 1939 /* bind a ep to a socket address */ 1940 struct sctppcbhead *head; 1941 struct sctp_inpcb *inp, *inp_tmp; 1942 struct inpcb *ip_inp; 1943 int bindall; 1944 uint16_t lport; 1945 int error; |
1946 uint32_t vrf_id; |
1947 1948 lport = 0; 1949 error = 0; 1950 bindall = 1; 1951 inp = (struct sctp_inpcb *)so->so_pcb; 1952 ip_inp = (struct inpcb *)so->so_pcb; 1953#ifdef SCTP_DEBUG 1954 if (sctp_debug_on & SCTP_DEBUG_PCB1) { --- 43 unchanged lines hidden (view full) --- 1998 return (EINVAL); 1999 } 2000 /* this must be cleared for ifa_ifwithaddr() */ 2001 sin6->sin6_scope_id = 0; 2002 } else { 2003 return (EAFNOSUPPORT); 2004 } 2005 } |
2006 /* 2007 * Setup a vrf_id to be the default for the non-bind-all case. 2008 */ 2009 vrf_id = inp->def_vrf_id; 2010 |
2011 SCTP_INP_INFO_WLOCK(); 2012 SCTP_INP_WLOCK(inp); 2013 /* increase our count due to the unlock we do */ 2014 SCTP_INP_INCR_REF(inp); 2015 if (lport) { 2016 /* 2017 * Did the caller specify a port? if so we must see if a ep 2018 * already has this one bound. 2019 */ 2020 /* got to be root to get at low ports */ 2021 if (ntohs(lport) < IPPORT_RESERVED) { 2022 if (p && (error = |
2023 priv_check_cred(p->td_ucred, 2024 PRIV_NETINET_RESERVEDPORT, 2025 SUSER_ALLOWJAIL 2026 ) |
2027 )) { 2028 SCTP_INP_DECR_REF(inp); 2029 SCTP_INP_WUNLOCK(inp); 2030 SCTP_INP_INFO_WUNLOCK(); 2031 return (error); 2032 } 2033 } 2034 if (p == NULL) { 2035 SCTP_INP_DECR_REF(inp); 2036 SCTP_INP_WUNLOCK(inp); 2037 SCTP_INP_INFO_WUNLOCK(); 2038 return (error); 2039 } 2040 SCTP_INP_WUNLOCK(inp); |
2041 if (bindall) { 2042 vrf_id = inp->def_vrf_id; 2043 inp_tmp = sctp_pcb_findep(addr, 0, 1, vrf_id); 2044 if (inp_tmp != NULL) { 2045 /* 2046 * lock guy returned and lower count note 2047 * that we are not bound so inp_tmp should 2048 * NEVER be inp. And it is this inp 2049 * (inp_tmp) that gets the reference bump, 2050 * so we must lower it. 2051 */ 2052 SCTP_INP_DECR_REF(inp_tmp); 2053 SCTP_INP_DECR_REF(inp); 2054 /* unlock info */ 2055 SCTP_INP_INFO_WUNLOCK(); 2056 return (EADDRNOTAVAIL); 2057 } 2058 } else { 2059 inp_tmp = sctp_pcb_findep(addr, 0, 1, vrf_id); 2060 if (inp_tmp != NULL) { 2061 /* 2062 * lock guy returned and lower count note 2063 * that we are not bound so inp_tmp should 2064 * NEVER be inp. And it is this inp 2065 * (inp_tmp) that gets the reference bump, 2066 * so we must lower it. 2067 */ 2068 SCTP_INP_DECR_REF(inp_tmp); 2069 SCTP_INP_DECR_REF(inp); 2070 /* unlock info */ 2071 SCTP_INP_INFO_WUNLOCK(); 2072 return (EADDRNOTAVAIL); 2073 } |
2074 } 2075 SCTP_INP_WLOCK(inp); 2076 if (bindall) { 2077 /* verify that no lport is not used by a singleton */ |
2078 if (sctp_isport_inuse(inp, lport, vrf_id)) { |
2079 /* Sorry someone already has this one bound */ 2080 SCTP_INP_DECR_REF(inp); 2081 SCTP_INP_WUNLOCK(inp); 2082 SCTP_INP_INFO_WUNLOCK(); 2083 return (EADDRNOTAVAIL); 2084 } 2085 } 2086 } else { --- 4 unchanged lines hidden (view full) --- 2091 2092 /* 2093 * setup the inp to the top (I could use the union but this 2094 * is just as easy 2095 */ 2096 uint32_t port_guess; 2097 uint16_t port_attempt; 2098 int not_done = 1; |
2099 int not_found = 1; |
2100 2101 while (not_done) { 2102 port_guess = sctp_select_initial_TSN(&inp->sctp_ep); 2103 port_attempt = (port_guess & 0x0000ffff); 2104 if (port_attempt == 0) { 2105 goto next_half; 2106 } 2107 if (port_attempt < IPPORT_RESERVED) { 2108 port_attempt += IPPORT_RESERVED; 2109 } |
2110 vrf_id = inp->def_vrf_id; 2111 if (sctp_isport_inuse(inp, htons(port_attempt), vrf_id) == 1) { |
2112 /* got a port we can use */ |
2113 not_found = 0; 2114 break; 2115 } 2116 if (not_found == 1) { 2117 /* We can use this port */ |
2118 not_done = 0; 2119 continue; 2120 } 2121 /* try upper half */ 2122 next_half: 2123 port_attempt = ((port_guess >> 16) & 0x0000ffff); 2124 if (port_attempt == 0) { 2125 goto last_try; 2126 } 2127 if (port_attempt < IPPORT_RESERVED) { 2128 port_attempt += IPPORT_RESERVED; 2129 } |
2130 vrf_id = inp->def_vrf_id; 2131 if (sctp_isport_inuse(inp, htons(port_attempt), vrf_id) == 1) { |
2132 /* got a port we can use */ |
2133 not_found = 0; 2134 break; 2135 } 2136 if (not_found == 1) { 2137 /* We can use this port */ |
2138 not_done = 0; 2139 continue; 2140 } 2141 /* try two half's added together */ 2142 last_try: 2143 port_attempt = (((port_guess >> 16) & 0x0000ffff) + 2144 (port_guess & 0x0000ffff)); 2145 if (port_attempt == 0) { 2146 /* get a new random number */ 2147 continue; 2148 } 2149 if (port_attempt < IPPORT_RESERVED) { 2150 port_attempt += IPPORT_RESERVED; 2151 } |
2152 vrf_id = inp->def_vrf_id; 2153 if (sctp_isport_inuse(inp, htons(port_attempt), vrf_id) == 1) { |
2154 /* got a port we can use */ |
2155 not_found = 0; 2156 break; 2157 } 2158 if (not_found == 1) { 2159 /* We can use this port */ |
2160 not_done = 0; 2161 continue; 2162 } 2163 } 2164 /* we don't get out of the loop until we have a port */ 2165 lport = htons(port_attempt); 2166 } 2167 SCTP_INP_DECR_REF(inp); --- 24 unchanged lines hidden (view full) --- 2192 * address structure to the sctp_addr_list inside the ep 2193 * structure. 2194 * 2195 * We will need to allocate one and insert it at the head. The 2196 * socketopt call can just insert new addresses in there as 2197 * well. It will also have to do the embed scope kame hack 2198 * too (before adding). 2199 */ |
2200 struct sctp_ifa *ifa; |
2201 struct sockaddr_storage store_sa; 2202 2203 memset(&store_sa, 0, sizeof(store_sa)); 2204 if (addr->sa_family == AF_INET) { 2205 struct sockaddr_in *sin; 2206 2207 sin = (struct sockaddr_in *)&store_sa; 2208 memcpy(sin, addr, sizeof(struct sockaddr_in)); --- 5 unchanged lines hidden (view full) --- 2214 memcpy(sin6, addr, sizeof(struct sockaddr_in6)); 2215 sin6->sin6_port = 0; 2216 } 2217 /* 2218 * first find the interface with the bound address need to 2219 * zero out the port to find the address! yuck! can't do 2220 * this earlier since need port for sctp_pcb_findep() 2221 */ |
2222 ifa = sctp_find_ifa_by_addr((struct sockaddr *)&store_sa, vrf_id, 0); |
2223 if (ifa == NULL) { 2224 /* Can't find an interface with that address */ 2225 SCTP_INP_WUNLOCK(inp); 2226 SCTP_INP_INFO_WUNLOCK(); 2227 return (EADDRNOTAVAIL); 2228 } 2229 if (addr->sa_family == AF_INET6) { |
2230 /* GAK, more FIXME IFA lock? */ 2231 if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) { |
2232 /* Can't bind a non-existent addr. */ 2233 SCTP_INP_WUNLOCK(inp); 2234 SCTP_INP_INFO_WUNLOCK(); 2235 return (EINVAL); 2236 } 2237 } 2238 /* we're not bound all */ 2239 inp->sctp_flags &= ~SCTP_PCB_FLAGS_BOUNDALL; 2240 /* set the automatic addr changes from kernel flag */ |
2241 sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF); |
2242 if (sctp_auto_asconf == 0) { 2243 sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTO_ASCONF); 2244 } else { |
2245 /* 2246 * allow bindx() to send ASCONF's for binding 2247 * changes 2248 */ |
2249 sctp_feature_on(inp, SCTP_PCB_FLAGS_AUTO_ASCONF); 2250 } |
2251 |
2252 /* add this address to the endpoint list */ |
2253 error = sctp_insert_laddr(&inp->sctp_addr_list, ifa, 0); |
2254 if (error != 0) { 2255 SCTP_INP_WUNLOCK(inp); 2256 SCTP_INP_INFO_WUNLOCK(); 2257 return (error); 2258 } 2259 inp->laddr_count++; 2260 } 2261 /* find the bucket */ --- 30 unchanged lines hidden (view full) --- 2292 /* 2293 * Go through all iterators, we must do this since it is possible 2294 * that some iterator does NOT have the lock, but is waiting for it. 2295 * And the one that had the lock has either moved in the last 2296 * iteration or we just cleared it above. We need to find all of 2297 * those guys. The list of iterators should never be very big 2298 * though. 2299 */ |
2300 TAILQ_FOREACH(it, &sctppcbinfo.iteratorhead, sctp_nxt_itr) { |
2301 if (it == inp->inp_starting_point_for_iterator) 2302 /* skip this guy, he's special */ 2303 continue; 2304 if (it->inp == inp) { 2305 /* 2306 * This is tricky and we DON'T lock the iterator. 2307 * Reason is he's running but waiting for me since 2308 * inp->inp_starting_point_for_iterator has the lock --- 412 unchanged lines hidden (view full) --- 2721 /* 2722 * if we have an address list the following will free the list of 2723 * ifaddr's that are set into this ep. Again macro limitations here, 2724 * since the LIST_FOREACH could be a bad idea. 2725 */ 2726 for ((laddr = LIST_FIRST(&inp->sctp_addr_list)); laddr != NULL; 2727 laddr = nladdr) { 2728 nladdr = LIST_NEXT(laddr, sctp_nxt_addr); |
2729 sctp_remove_laddr(laddr); |
2730 } 2731 2732#ifdef SCTP_TRACK_FREED_ASOCS 2733 /* TEMP CODE */ 2734 for ((asoc = LIST_FIRST(&inp->sctp_asoc_free_list)); asoc != NULL; 2735 asoc = nasoc) { 2736 nasoc = LIST_NEXT(asoc, sctp_tcblist); 2737 LIST_REMOVE(asoc, sctp_tcblist); --- 36 unchanged lines hidden (view full) --- 2774 2775 2776/* 2777 * add's a remote endpoint address, done with the INIT/INIT-ACK as well as 2778 * when a ASCONF arrives that adds it. It will also initialize all the cwnd 2779 * stats of stuff. 2780 */ 2781int |
2782sctp_is_address_on_local_host(struct sockaddr *addr, uint32_t vrf_id) |
2783{ |
2784 struct sctp_ifa *sctp_ifa; |
2785 |
2786 sctp_ifa = sctp_find_ifa_by_addr(addr, vrf_id, 0); 2787 if (sctp_ifa) { 2788 return (1); 2789 } else { 2790 return (0); 2791 } 2792} |
2793 |
2794void 2795sctp_set_initial_cc_param(struct sctp_tcb *stcb, struct sctp_nets *net) 2796{ 2797 net->cwnd = min((net->mtu * 4), max((2 * net->mtu), SCTP_INITIAL_CWND)); 2798 /* we always get at LEAST 2 MTU's */ 2799 if (net->cwnd < (2 * net->mtu)) { 2800 net->cwnd = 2 * net->mtu; |
2801 } |
2802 net->ssthresh = stcb->asoc.peers_rwnd; |
2803} 2804 2805int 2806sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr, 2807 int set_scope, int from) 2808{ 2809 /* 2810 * The following is redundant to the same lines in the --- 48 unchanged lines hidden (view full) --- 2859 if (set_scope) { 2860#ifdef SCTP_DONT_DO_PRIVADDR_SCOPE 2861 stcb->ipv4_local_scope = 1; 2862#else 2863 if (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { 2864 stcb->asoc.ipv4_local_scope = 1; 2865 } 2866#endif /* SCTP_DONT_DO_PRIVADDR_SCOPE */ |
2867 } else { |
2868 /* Validate the address is in scope */ 2869 if ((IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) && 2870 (stcb->asoc.ipv4_local_scope == 0)) { 2871 addr_inscope = 0; 2872 } 2873 } 2874 } else if (newaddr->sa_family == AF_INET6) { 2875 struct sockaddr_in6 *sin6; 2876 2877 sin6 = (struct sockaddr_in6 *)newaddr; 2878 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 2879 /* Invalid address */ 2880 return (-1); 2881 } 2882 /* assure len is set */ 2883 sin6->sin6_len = sizeof(struct sockaddr_in6); 2884 if (set_scope) { |
2885 if (sctp_is_address_on_local_host(newaddr, stcb->asoc.vrf_id)) { |
2886 stcb->asoc.loopback_scope = 1; |
2887 stcb->asoc.local_scope = 0; |
2888 stcb->asoc.ipv4_local_scope = 1; 2889 stcb->asoc.site_scope = 1; 2890 } else if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 2891 /* 2892 * If the new destination is a LINK_LOCAL we 2893 * must have common site scope. Don't set 2894 * the local scope since we may not share 2895 * all links, only loopback can do this. --- 5 unchanged lines hidden (view full) --- 2901 } else if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) { 2902 /* 2903 * If the new destination is SITE_LOCAL then 2904 * we must have site scope in common. 2905 */ 2906 stcb->asoc.site_scope = 1; 2907 } 2908 } else { |
2909 /* Validate the address is in scope */ 2910 if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) && 2911 (stcb->asoc.loopback_scope == 0)) { 2912 addr_inscope = 0; 2913 } else if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && 2914 (stcb->asoc.local_scope == 0)) { 2915 addr_inscope = 0; 2916 } else if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) && --- 13 unchanged lines hidden (view full) --- 2930 bzero(net, sizeof(*net)); 2931 SCTP_GETTIME_TIMEVAL(&net->start_time); 2932 memcpy(&net->ro._l_addr, newaddr, newaddr->sa_len); 2933 if (newaddr->sa_family == AF_INET) { 2934 ((struct sockaddr_in *)&net->ro._l_addr)->sin_port = stcb->rport; 2935 } else if (newaddr->sa_family == AF_INET6) { 2936 ((struct sockaddr_in6 *)&net->ro._l_addr)->sin6_port = stcb->rport; 2937 } |
2938 net->addr_is_local = sctp_is_address_on_local_host(newaddr, stcb->asoc.vrf_id); 2939 if (net->addr_is_local && ((set_scope || (from == SCTP_ADDR_IS_CONFIRMED)))) { 2940 stcb->asoc.loopback_scope = 1; 2941 stcb->asoc.ipv4_local_scope = 1; 2942 stcb->asoc.local_scope = 0; 2943 stcb->asoc.site_scope = 1; 2944 addr_inscope = 1; 2945 } |
2946 net->failure_threshold = stcb->asoc.def_net_failure; 2947 if (addr_inscope == 0) { 2948 net->dest_state = (SCTP_ADDR_REACHABLE | 2949 SCTP_ADDR_OUT_OF_SCOPE); 2950 } else { 2951 if (from == SCTP_ADDR_IS_CONFIRMED) 2952 /* SCTP_ADDR_IS_CONFIRMED is passed by connect_x */ 2953 net->dest_state = SCTP_ADDR_REACHABLE; 2954 else 2955 net->dest_state = SCTP_ADDR_REACHABLE | 2956 SCTP_ADDR_UNCONFIRMED; 2957 } 2958 net->RTO = stcb->asoc.initial_rto; 2959 stcb->asoc.numnets++; 2960 *(&net->ref_count) = 1; 2961 net->tos_flowlabel = 0; |
2962#ifdef INET |
2963 if (newaddr->sa_family == AF_INET) 2964 net->tos_flowlabel = stcb->asoc.default_tos; 2965#endif |
2966#ifdef INET6 |
2967 if (newaddr->sa_family == AF_INET6) 2968 net->tos_flowlabel = stcb->asoc.default_flowlabel; 2969#endif 2970 /* Init the timer structure */ 2971 SCTP_OS_TIMER_INIT(&net->rxt_timer.timer); 2972 SCTP_OS_TIMER_INIT(&net->fr_timer.timer); 2973 SCTP_OS_TIMER_INIT(&net->pmtu_timer.timer); 2974 --- 27 unchanged lines hidden (view full) --- 3002 3003 if (stcb->asoc.smallest_mtu > net->mtu) { 3004 stcb->asoc.smallest_mtu = net->mtu; 3005 } 3006 /* 3007 * We take the max of the burst limit times a MTU or the 3008 * INITIAL_CWND. We then limit this to 4 MTU's of sending. 3009 */ |
3010 sctp_set_initial_cc_param(stcb, net); |
3011 |
3012 3013#if defined(SCTP_CWND_MONITOR) || defined(SCTP_CWND_LOGGING) 3014 sctp_log_cwnd(stcb, net, 0, SCTP_CWND_INITIALIZATION); 3015#endif 3016 3017 /* 3018 * CMT: CUC algo - set find_pseudo_cumack to TRUE (1) at beginning 3019 * of assoc (2005/06/27, iyengar@cis.udel.edu) --- 82 unchanged lines hidden (view full) --- 3102 3103/* 3104 * allocate an association and add it to the endpoint. The caller must be 3105 * careful to add all additional addresses once they are know right away or 3106 * else the assoc will be may experience a blackout scenario. 3107 */ 3108struct sctp_tcb * 3109sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr, |
3110 int for_a_init, int *error, uint32_t override_tag, uint32_t vrf) |
3111{ 3112 struct sctp_tcb *stcb; 3113 struct sctp_association *asoc; 3114 struct sctpasochead *head; 3115 uint16_t rport; 3116 int err; 3117 3118 /* --- 83 unchanged lines hidden (view full) --- 3202 3203 bzero(stcb, sizeof(*stcb)); 3204 asoc = &stcb->asoc; 3205 SCTP_TCB_LOCK_INIT(stcb); 3206 SCTP_TCB_SEND_LOCK_INIT(stcb); 3207 /* setup back pointer's */ 3208 stcb->sctp_ep = inp; 3209 stcb->sctp_socket = inp->sctp_socket; |
3210 if ((err = sctp_init_asoc(inp, asoc, for_a_init, override_tag, vrf))) { |
3211 /* failed */ 3212 SCTP_TCB_LOCK_DESTROY(stcb); 3213 SCTP_TCB_SEND_LOCK_DESTROY(stcb); 3214 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_asoc, stcb); 3215 SCTP_DECR_ASOC_COUNT(); 3216 *error = err; 3217 return (NULL); 3218 } --- 64 unchanged lines hidden (view full) --- 3283void 3284sctp_remove_net(struct sctp_tcb *stcb, struct sctp_nets *net) 3285{ 3286 struct sctp_association *asoc; 3287 3288 asoc = &stcb->asoc; 3289 asoc->numnets--; 3290 TAILQ_REMOVE(&asoc->nets, net, sctp_next); |
3291 if (net == asoc->primary_destination) { 3292 /* Reset primary */ 3293 struct sctp_nets *lnet; 3294 3295 lnet = TAILQ_FIRST(&asoc->nets); 3296 /* Try to find a confirmed primary */ |
3297 asoc->primary_destination = sctp_find_alternate_net(stcb, lnet, 0); |
3298 } 3299 if (net == asoc->last_data_chunk_from) { 3300 /* Reset primary */ 3301 asoc->last_data_chunk_from = TAILQ_FIRST(&asoc->nets); 3302 } 3303 if (net == asoc->last_control_chunk_from) { 3304 /* Clear net */ 3305 asoc->last_control_chunk_from = NULL; 3306 } |
3307 sctp_free_remote_addr(net); |
3308} 3309 3310/* 3311 * remove a remote endpoint address from an association, it will fail if the 3312 * address does not exist. 3313 */ 3314int 3315sctp_del_remote_addr(struct sctp_tcb *stcb, struct sockaddr *remaddr) --- 592 unchanged lines hidden (view full) --- 3908#endif 3909 break; 3910 } 3911 prev = net; 3912 TAILQ_REMOVE(&asoc->nets, net, sctp_next); 3913 sctp_free_remote_addr(net); 3914 } 3915 |
3916 while (!SCTP_LIST_EMPTY(&asoc->sctp_restricted_addrs)) { 3917 laddr = LIST_FIRST(&asoc->sctp_restricted_addrs); 3918 sctp_remove_laddr(laddr); |
3919 } |
3920 |
3921 /* pending asconf (address) parameters */ 3922 while (!TAILQ_EMPTY(&asoc->asconf_queue)) { 3923 aparam = TAILQ_FIRST(&asoc->asconf_queue); 3924 TAILQ_REMOVE(&asoc->asconf_queue, aparam, next); 3925 SCTP_FREE(aparam); 3926 } 3927 if (asoc->last_asconf_ack_sent != NULL) { 3928 sctp_m_freem(asoc->last_asconf_ack_sent); --- 137 unchanged lines hidden (view full) --- 4066 if (laddr->ifa == NULL) { 4067#ifdef SCTP_DEBUG 4068 if (sctp_debug_on & SCTP_DEBUG_PCB1) { 4069 printf("An ounce of prevention is worth a pound of cure\n"); 4070 } 4071#endif /* SCTP_DEBUG */ 4072 continue; 4073 } |
4074 if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) { |
4075 continue; 4076 } |
4077 if (laddr->ifa->address.sa.sa_family == AF_INET6) { |
4078 inp->ip_inp.inp.inp_vflag |= INP_IPV6; |
4079 } else if (laddr->ifa->address.sa.sa_family == AF_INET) { |
4080 inp->ip_inp.inp.inp_vflag |= INP_IPV4; 4081 } 4082 } 4083} 4084 4085/* 4086 * Add the address to the endpoint local address list There is nothing to be 4087 * done if we are bound to all addresses 4088 */ 4089int |
4090sctp_add_local_addr_ep(struct sctp_inpcb *inp, struct sctp_ifa *ifa, uint32_t action) |
4091{ 4092 struct sctp_laddr *laddr; 4093 int fnd, error; 4094 4095 fnd = 0; 4096 4097 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 4098 /* You are already bound to all. You have it already */ 4099 return (0); 4100 } |
4101 if (ifa->address.sa.sa_family == AF_INET6) { 4102 if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) { 4103 /* Can't bind a non-useable addr. */ |
4104 return (-1); |
4105 } |
4106 } 4107 /* first, is it already present? */ 4108 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { 4109 if (laddr->ifa == ifa) { 4110 fnd = 1; 4111 break; 4112 } 4113 } 4114 |
4115 if (fnd == 0) { 4116 /* Not in the ep list */ 4117 error = sctp_insert_laddr(&inp->sctp_addr_list, ifa, action); |
4118 if (error != 0) 4119 return (error); 4120 inp->laddr_count++; 4121 /* update inp_vflag flags */ |
4122 if (ifa->address.sa.sa_family == AF_INET6) { |
4123 inp->ip_inp.inp.inp_vflag |= INP_IPV6; |
4124 } else if (ifa->address.sa.sa_family == AF_INET) { |
4125 inp->ip_inp.inp.inp_vflag |= INP_IPV4; 4126 } 4127 } 4128 return (0); 4129} 4130 4131 4132/* --- 20 unchanged lines hidden (view full) --- 4153} 4154 4155 4156/* 4157 * Delete the address from the endpoint local address list There is nothing 4158 * to be done if we are bound to all addresses 4159 */ 4160int |
4161sctp_del_local_addr_ep(struct sctp_inpcb *inp, struct sctp_ifa *ifa) |
4162{ 4163 struct sctp_laddr *laddr; 4164 int fnd; 4165 4166 fnd = 0; 4167 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 4168 /* You are already bound to all. You have it already */ 4169 return (EINVAL); 4170 } 4171 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { 4172 if (laddr->ifa == ifa) { 4173 fnd = 1; 4174 break; 4175 } 4176 } 4177 if (fnd && (inp->laddr_count < 2)) { 4178 /* can't delete unless there are at LEAST 2 addresses */ 4179 return (-1); 4180 } |
4181 if (fnd) { |
4182 /* 4183 * clean up any use of this address go through our 4184 * associations and clear any last_used_address that match 4185 * this one for each assoc, see if a new primary_destination 4186 * is needed 4187 */ 4188 struct sctp_tcb *stcb; 4189 4190 /* clean up "next_addr_touse" */ 4191 if (inp->next_addr_touse == laddr) 4192 /* delete this address */ 4193 inp->next_addr_touse = NULL; 4194 4195 /* clean up "last_used_address" */ 4196 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { |
4197 struct sctp_nets *net; 4198 4199 SCTP_TCB_LOCK(stcb); |
4200 if (stcb->asoc.last_used_address == laddr) 4201 /* delete this address */ 4202 stcb->asoc.last_used_address = NULL; |
4203 /* 4204 * Now spin through all the nets and purge any ref 4205 * to laddr 4206 */ 4207 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 4208 if (net->ro._s_addr && 4209 (net->ro._s_addr->ifa == laddr->ifa)) { 4210 /* Yep, purge src address selected */ 4211 struct rtentry *rt; |
4212 |
4213 /* delete this address if cached */ 4214 rt = net->ro.ro_rt; 4215 if (rt != NULL) { 4216 RTFREE(rt); 4217 net->ro.ro_rt = NULL; 4218 } 4219 sctp_free_ifa(net->ro._s_addr); 4220 net->ro._s_addr = NULL; 4221 net->src_addr_selected = 0; 4222 } 4223 } 4224 SCTP_TCB_UNLOCK(stcb); 4225 } /* for each tcb */ |
4226 /* remove it from the ep list */ 4227 sctp_remove_laddr(laddr); 4228 inp->laddr_count--; 4229 /* update inp_vflag flags */ 4230 sctp_update_ep_vflag(inp); |
4231 } 4232 return (0); 4233} 4234 4235/* 4236 * Add the addr to the TCB local address list For the BOUNDALL or dynamic 4237 * case, this is a "pending" address list (eg. addresses waiting for an 4238 * ASCONF-ACK response) For the subset binding, static case, this is a 4239 * "valid" address list 4240 */ 4241int |
4242sctp_add_local_addr_assoc(struct sctp_tcb *stcb, struct sctp_ifa *ifa, int restricted_list) |
4243{ 4244 struct sctp_inpcb *inp; 4245 struct sctp_laddr *laddr; |
4246 struct sctpladdr *list; |
4247 int error; 4248 4249 /* |
4250 * Assumes TCB is locked.. and possibly the INP. May need to |
4251 * confirm/fix that if we need it and is not the case. 4252 */ |
4253 list = &stcb->asoc.sctp_restricted_addrs; |
4254 |
4255 inp = stcb->sctp_ep; 4256 if (ifa->address.sa.sa_family == AF_INET6) { 4257 if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) { |
4258 /* Can't bind a non-existent addr. */ 4259 return (-1); |
4260 } |
4261 } 4262 /* does the address already exist? */ |
4263 LIST_FOREACH(laddr, list, sctp_nxt_addr) { |
4264 if (laddr->ifa == ifa) { 4265 return (-1); 4266 } 4267 } 4268 4269 /* add to the list */ |
4270 error = sctp_insert_laddr(list, ifa, 0); |
4271 if (error != 0) 4272 return (error); 4273 return (0); 4274} 4275 4276/* 4277 * insert an laddr entry with the given ifa for the desired list 4278 */ 4279int |
4280sctp_insert_laddr(struct sctpladdr *list, struct sctp_ifa *ifa, uint32_t act) |
4281{ 4282 struct sctp_laddr *laddr; 4283 4284 laddr = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_laddr, struct sctp_laddr); 4285 if (laddr == NULL) { 4286 /* out of memory? */ 4287 return (EINVAL); 4288 } 4289 SCTP_INCR_LADDR_COUNT(); 4290 bzero(laddr, sizeof(*laddr)); 4291 laddr->ifa = ifa; |
4292 laddr->action = act; 4293 atomic_add_int(&ifa->refcount, 1); |
4294 /* insert it */ 4295 LIST_INSERT_HEAD(list, laddr, sctp_nxt_addr); 4296 4297 return (0); 4298} 4299 4300/* 4301 * Remove an laddr entry from the local address list (on an assoc) 4302 */ 4303void 4304sctp_remove_laddr(struct sctp_laddr *laddr) 4305{ 4306 4307 /* remove from the list */ 4308 LIST_REMOVE(laddr, sctp_nxt_addr); |
4309 sctp_free_ifa(laddr->ifa); |
4310 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_laddr, laddr); 4311 SCTP_DECR_LADDR_COUNT(); 4312} 4313 4314/* 4315 * Remove an address from the TCB local address list 4316 */ 4317int |
4318sctp_del_local_addr_assoc(struct sctp_tcb *stcb, struct sctp_ifa *ifa) |
4319{ 4320 struct sctp_inpcb *inp; 4321 struct sctp_laddr *laddr; 4322 4323 /* 4324 * This is called by asconf work. It is assumed that a) The TCB is 4325 * locked and b) The INP is locked. This is true in as much as I can 4326 * trace through the entry asconf code where I did these locks. --- 7 unchanged lines hidden (view full) --- 4334 /* if subset bound and don't allow ASCONF's, can't delete last */ 4335 if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) && 4336 (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_ASCONF) == 0)) { 4337 if (stcb->asoc.numnets < 2) { 4338 /* can't delete last address */ 4339 return (-1); 4340 } 4341 } |
4342 LIST_FOREACH(laddr, &stcb->asoc.sctp_restricted_addrs, sctp_nxt_addr) { |
4343 /* remove the address if it exists */ 4344 if (laddr->ifa == NULL) 4345 continue; 4346 if (laddr->ifa == ifa) { 4347 sctp_remove_laddr(laddr); 4348 return (0); 4349 } 4350 } 4351 4352 /* address not found! */ 4353 return (-1); 4354} 4355 |
4356static char sctp_pcb_initialized = 0; 4357 4358/* 4359 * Temporarily remove for __APPLE__ until we use the Tiger equivalents 4360 */ 4361/* sysctl */ 4362static int sctp_max_number_of_assoc = SCTP_MAX_NUM_OF_ASOC; 4363static int sctp_scale_up_for_address = SCTP_SCALE_FOR_ADDR; --- 14 unchanged lines hidden (view full) --- 4378 sctp_pcb_initialized = 1; 4379 4380 bzero(&sctpstat, sizeof(struct sctpstat)); 4381 SCTP_GETTIME_TIMEVAL(&sctpstat.sctps_discontinuitytime); 4382 /* init the empty list of (All) Endpoints */ 4383 LIST_INIT(&sctppcbinfo.listhead); 4384 4385 /* init the iterator head */ |
4386 TAILQ_INIT(&sctppcbinfo.iteratorhead); |
4387 4388 /* init the hash table of endpoints */ 4389 TUNABLE_INT_FETCH("net.inet.sctp.tcbhashsize", &sctp_hashtblsize); 4390 TUNABLE_INT_FETCH("net.inet.sctp.pcbhashsize", &sctp_pcbtblsize); 4391 TUNABLE_INT_FETCH("net.inet.sctp.chunkscale", &sctp_chunkscale); 4392 sctppcbinfo.sctp_asochash = SCTP_HASH_INIT((sctp_hashtblsize * 31), 4393 &sctppcbinfo.hashasocmark); 4394 sctppcbinfo.sctp_ephash = SCTP_HASH_INIT(sctp_hashtblsize, 4395 &sctppcbinfo.hashmark); 4396 sctppcbinfo.sctp_tcpephash = SCTP_HASH_INIT(sctp_hashtblsize, 4397 &sctppcbinfo.hashtcpmark); 4398 sctppcbinfo.hashtblsize = sctp_hashtblsize; 4399 4400 /* init the small hash table we use to track restarted asoc's */ 4401 sctppcbinfo.sctp_restarthash = SCTP_HASH_INIT(SCTP_STACK_VTAG_HASH_SIZE, 4402 &sctppcbinfo.hashrestartmark); 4403 |
4404 4405 sctppcbinfo.sctp_vrfhash = SCTP_HASH_INIT(SCTP_SIZE_OF_VRF_HASH, 4406 &sctppcbinfo.hashvrfmark); 4407 |
4408 /* init the zones */ 4409 /* 4410 * FIX ME: Should check for NULL returns, but if it does fail we are 4411 * doomed to panic anyways... add later maybe. 4412 */ 4413 SCTP_ZONE_INIT(sctppcbinfo.ipi_zone_ep, "sctp_ep", 4414 sizeof(struct sctp_inpcb), maxsockets); 4415 --- 22 unchanged lines hidden (view full) --- 4438 4439 /* Master Lock INIT for info structure */ 4440 SCTP_INP_INFO_LOCK_INIT(); 4441 SCTP_STATLOG_INIT_LOCK(); 4442 SCTP_ITERATOR_LOCK_INIT(); 4443 4444 SCTP_IPI_COUNT_INIT(); 4445 SCTP_IPI_ADDR_INIT(); |
4446 SCTP_IPI_ITERATOR_WQ_INIT(); 4447 |
4448 LIST_INIT(&sctppcbinfo.addr_wq); 4449 4450 /* not sure if we need all the counts */ 4451 sctppcbinfo.ipi_count_ep = 0; 4452 /* assoc/tcb zone info */ 4453 sctppcbinfo.ipi_count_asoc = 0; 4454 /* local addrlist zone info */ 4455 sctppcbinfo.ipi_count_laddr = 0; --- 13 unchanged lines hidden (view full) --- 4469 4470 SCTP_OS_TIMER_INIT(&sctppcbinfo.addr_wq_timer.timer); 4471 4472 /* Init the TIMEWAIT list */ 4473 for (i = 0; i < SCTP_STACK_VTAG_HASH_SIZE; i++) { 4474 LIST_INIT(&sctppcbinfo.vtag_timewait[i]); 4475 } 4476 |
4477#if defined(SCTP_USE_THREAD_BASED_ITERATOR) 4478 sctppcbinfo.iterator_running = 0; 4479 sctp_startup_iterator(); 4480#endif 4481 4482 /* 4483 * INIT the default VRF which for BSD is the only one, other O/S's 4484 * may have more. But initially they must start with one and then 4485 * add the VRF's as addresses are added. 4486 */ 4487 sctp_init_vrf_list(SCTP_DEFAULT_VRF); 4488 |
4489} 4490 4491 4492int 4493sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, 4494 int iphlen, int offset, int limit, struct sctphdr *sh, 4495 struct sockaddr *altsa) 4496{ --- 554 unchanged lines hidden (view full) --- 5051 net = sctp_findnet(stcb, sa); 5052 5053 if (net == NULL) { 5054 /* didn't find the requested primary address! */ 5055 return (-1); 5056 } else { 5057 /* set the primary address */ 5058 if (net->dest_state & SCTP_ADDR_UNCONFIRMED) { |
5059 /* Must be confirmed, so queue to set */ 5060 net->dest_state |= SCTP_ADDR_REQ_PRIMARY; 5061 return (0); |
5062 } 5063 stcb->asoc.primary_destination = net; 5064 net->dest_state &= ~SCTP_ADDR_WAS_PRIMARY; 5065 net = TAILQ_FIRST(&stcb->asoc.nets); 5066 if (net != stcb->asoc.primary_destination) { 5067 /* 5068 * first one on the list is NOT the primary 5069 * sctp_cmpaddr() is much more efficent if the --- 90 unchanged lines hidden (view full) --- 5160 } 5161 } 5162 /* Not found, ok to use the tag */ 5163 SCTP_INP_INFO_WUNLOCK(); 5164 return (1); 5165} 5166 5167 |
5168static sctp_assoc_t reneged_asoc_ids[256]; 5169static uint8_t reneged_at = 0; 5170 |
5171 5172static void 5173sctp_drain_mbufs(struct sctp_inpcb *inp, struct sctp_tcb *stcb) 5174{ 5175 /* 5176 * We must hunt this association for MBUF's past the cumack (i.e. 5177 * out of order data that we can renege on). 5178 */ --- 139 unchanged lines hidden (view full) --- 5318 /* Nothing left in map */ 5319 memset(asoc->mapping_array, 0, asoc->mapping_array_size); 5320 asoc->mapping_array_base_tsn = asoc->cumulative_tsn + 1; 5321 asoc->highest_tsn_inside_map = asoc->cumulative_tsn; 5322 } 5323 asoc->last_revoke_count = cnt; 5324 SCTP_OS_TIMER_STOP(&stcb->asoc.dack_timer.timer); 5325 sctp_send_sack(stcb); |
5326 sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_DRAIN); |
5327 reneged_asoc_ids[reneged_at] = sctp_get_associd(stcb); 5328 reneged_at++; 5329 } 5330 /* 5331 * Another issue, in un-setting the TSN's in the mapping array we 5332 * DID NOT adjust the higest_tsn marker. This will cause one of two 5333 * things to occur. It may cause us to do extra work in checking for 5334 * our mapping array movement. More importantly it may cause us to --- 33 unchanged lines hidden (view full) --- 5368 * start a new iterator 5369 * iterates through all endpoints and associations based on the pcb_state 5370 * flags and asoc_state. "af" (mandatory) is executed for all matching 5371 * assocs and "ef" (optional) is executed when the iterator completes. 5372 * "inpf" (optional) is executed for each new endpoint as it is being 5373 * iterated through. 5374 */ 5375int |
5376sctp_initiate_iterator(inp_func inpf, 5377 asoc_func af, 5378 inp_func inpe, 5379 uint32_t pcb_state, 5380 uint32_t pcb_features, 5381 uint32_t asoc_state, 5382 void *argp, 5383 uint32_t argi, 5384 end_func ef, 5385 struct sctp_inpcb *s_inp, 5386 uint8_t chunk_output_off) |
5387{ 5388 struct sctp_iterator *it = NULL; 5389 5390 if (af == NULL) { 5391 return (-1); 5392 } 5393 SCTP_MALLOC(it, struct sctp_iterator *, sizeof(struct sctp_iterator), 5394 "Iterator"); 5395 if (it == NULL) { 5396 return (ENOMEM); 5397 } 5398 memset(it, 0, sizeof(*it)); 5399 it->function_assoc = af; 5400 it->function_inp = inpf; |
5401 if (inpf) 5402 it->done_current_ep = 0; 5403 else 5404 it->done_current_ep = 1; |
5405 it->function_atend = ef; 5406 it->pointer = argp; 5407 it->val = argi; 5408 it->pcb_flags = pcb_state; 5409 it->pcb_features = pcb_features; 5410 it->asoc_state = asoc_state; |
5411 it->function_inp_end = inpe; |
5412 it->no_chunk_output = chunk_output_off; 5413 if (s_inp) { 5414 it->inp = s_inp; 5415 it->iterator_flags = SCTP_ITERATOR_DO_SINGLE_INP; 5416 } else { 5417 SCTP_INP_INFO_RLOCK(); 5418 it->inp = LIST_FIRST(&sctppcbinfo.listhead); |
5419 |
5420 SCTP_INP_INFO_RUNLOCK(); 5421 it->iterator_flags = SCTP_ITERATOR_DO_ALL_INP; 5422 5423 } |
5424 SCTP_IPI_ITERATOR_WQ_LOCK(); 5425 if (it->inp) 5426 SCTP_INP_INCR_REF(it->inp); 5427 TAILQ_INSERT_TAIL(&sctppcbinfo.iteratorhead, it, sctp_nxt_itr); 5428#if defined(SCTP_USE_THREAD_BASED_ITERATOR) 5429 if (sctppcbinfo.iterator_running == 0) { 5430 sctp_wakeup_iterator(); 5431 } 5432 SCTP_IPI_ITERATOR_WQ_UNLOCK(); 5433#else 5434 if (it->inp) 5435 SCTP_INP_DECR_REF(it->inp); 5436 SCTP_IPI_ITERATOR_WQ_UNLOCK(); |
5437 /* Init the timer */ 5438 SCTP_OS_TIMER_INIT(&it->tmr.timer); 5439 /* add to the list of all iterators */ |
5440 sctp_timer_start(SCTP_TIMER_TYPE_ITERATOR, (struct sctp_inpcb *)it, 5441 NULL, NULL); |
5442#endif |
5443 return (0); 5444} |