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: sctputil.c,v 1.37 2005/03/07 23:26:09 itojun Exp $ */ 32 33#include <sys/cdefs.h> |
34__FBSDID("$FreeBSD: head/sys/netinet/sctputil.c 167598 2007-03-15 11:27:14Z rrs $"); |
35 36#include <netinet/sctp_os.h> 37#include <netinet/sctp_pcb.h> 38#include <netinet/sctputil.h> 39#include <netinet/sctp_var.h> |
40#include <netinet/sctp_sysctl.h> |
41#ifdef INET6 42#include <netinet6/sctp6_var.h> 43#endif 44#include <netinet/sctp_header.h> 45#include <netinet/sctp_output.h> 46#include <netinet/sctp_uio.h> 47#include <netinet/sctp_timer.h> 48#include <netinet/sctp_crc32.h> 49#include <netinet/sctp_indata.h>/* for sctp_deliver_data() */ 50#include <netinet/sctp_auth.h> 51#include <netinet/sctp_asconf.h> |
52#include <netinet/sctp_bsd_addr.h> |
53 |
54#define NUMBER_OF_MTU_SIZES 18 55 |
56 |
57#ifdef SCTP_STAT_LOGGING 58int global_sctp_cwnd_log_at = 0; 59int global_sctp_cwnd_log_rolled = 0; 60struct sctp_cwnd_log sctp_clog[SCTP_STAT_LOG_SIZE]; 61 62static uint32_t 63sctp_get_time_of_event(void) 64{ --- 414 unchanged lines hidden (view full) --- 479 sctp_clog[sctp_cwnd_log_at].x.blk.peer_rwnd = asoc->peers_rwnd; 480 sctp_clog[sctp_cwnd_log_at].x.blk.stream_qcnt = (uint16_t) asoc->stream_queue_cnt; 481 sctp_clog[sctp_cwnd_log_at].x.blk.chunks_on_oque = (uint16_t) asoc->chunks_on_out_queue; 482 sctp_clog[sctp_cwnd_log_at].x.blk.flight_size = (uint16_t) (asoc->total_flight / 1024); 483 sctp_clog[sctp_cwnd_log_at].x.blk.sndlen = sendlen; 484} 485 486int |
487sctp_fill_stat_log(void *optval, size_t *optsize) |
488{ 489 int sctp_cwnd_log_at; 490 struct sctp_cwnd_log_req *req; 491 size_t size_limit; 492 int num, i, at, cnt_out = 0; 493 |
494 if (*optsize < sizeof(struct sctp_cwnd_log_req)) { |
495 return (EINVAL); |
496 } 497 size_limit = (*optsize - sizeof(struct sctp_cwnd_log_req)); |
498 if (size_limit < sizeof(struct sctp_cwnd_log)) { 499 return (EINVAL); 500 } 501 sctp_cwnd_log_at = global_sctp_cwnd_log_at; |
502 req = (struct sctp_cwnd_log_req *)optval; |
503 num = size_limit / sizeof(struct sctp_cwnd_log); 504 if (global_sctp_cwnd_log_rolled) { 505 req->num_in_log = SCTP_STAT_LOG_SIZE; 506 } else { 507 req->num_in_log = sctp_cwnd_log_at; 508 /* 509 * if the log has not rolled, we don't let you have old 510 * data. --- 48 unchanged lines hidden (view full) --- 559#endif 560 for (i = 0, at = req->start_at; i < req->num_ret; i++) { 561 req->log[i] = sctp_clog[at]; 562 cnt_out++; 563 at++; 564 if (at >= SCTP_STAT_LOG_SIZE) 565 at = 0; 566 } |
567 *optsize = (cnt_out * sizeof(struct sctp_cwnd_log)) + sizeof(struct sctp_cwnd_log_req); |
568 return (0); 569} 570 571#endif 572 573#ifdef SCTP_AUDITING_ENABLED 574uint8_t sctp_audit_data[SCTP_AUDIT_SIZE][2]; 575static int sctp_audit_indx = 0; --- 323 unchanged lines hidden (view full) --- 899 } 900 } 901 return (x); 902} 903 904 905int 906sctp_init_asoc(struct sctp_inpcb *m, struct sctp_association *asoc, |
907 int for_a_init, uint32_t override_tag, uint32_t vrf_id) |
908{ 909 /* 910 * Anything set to zero is taken care of by the allocation routine's 911 * bzero 912 */ 913 914 /* 915 * Up front select what scoping to apply on addresses I tell my peer --- 4 unchanged lines hidden (view full) --- 920 int i; 921 922 /* init all variables to a known value. */ 923 asoc->state = SCTP_STATE_INUSE; 924 asoc->max_burst = m->sctp_ep.max_burst; 925 asoc->heart_beat_delay = TICKS_TO_MSEC(m->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]); 926 asoc->cookie_life = m->sctp_ep.def_cookie_life; 927 asoc->sctp_cmt_on_off = (uint8_t) sctp_cmt_on_off; |
928#ifdef INET |
929 asoc->default_tos = m->ip_inp.inp.inp_ip_tos; 930#else 931 asoc->default_tos = 0; 932#endif 933 |
934#ifdef INET6 |
935 asoc->default_flowlabel = ((struct in6pcb *)m)->in6p_flowinfo; 936#else 937 asoc->default_flowlabel = 0; 938#endif 939 if (override_tag) { 940 struct timeval now; 941 942 SCTP_GETTIME_TIMEVAL(&now); --- 4 unchanged lines hidden (view full) --- 947 } 948 949 } else { 950 asoc->my_vtag = sctp_select_a_tag(m); 951 } 952 /* Get the nonce tags */ 953 asoc->my_vtag_nonce = sctp_select_a_tag(m); 954 asoc->peer_vtag_nonce = sctp_select_a_tag(m); |
955 asoc->vrf_id = vrf_id; |
956 957 if (sctp_is_feature_on(m, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) 958 asoc->hb_is_disabled = 1; 959 else 960 asoc->hb_is_disabled = 0; 961 962 asoc->refcnt = 0; 963 asoc->assoc_up_sent = 0; --- 32 unchanged lines hidden (view full) --- 996 asoc->ecn_nonce_allowed = 0; 997 asoc->receiver_nonce_sum = 1; 998 asoc->nonce_sum_expect_base = 1; 999 asoc->nonce_sum_check = 1; 1000 asoc->nonce_resync_tsn = 0; 1001 asoc->nonce_wait_for_ecne = 0; 1002 asoc->nonce_wait_tsn = 0; 1003 asoc->delayed_ack = TICKS_TO_MSEC(m->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]); |
1004 asoc->sack_freq = m->sctp_ep.sctp_sack_freq; |
1005 asoc->pr_sctp_cnt = 0; 1006 asoc->total_output_queue_size = 0; 1007 1008 if (m->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { 1009 struct in6pcb *inp6; 1010 1011 /* Its a V6 socket */ 1012 inp6 = (struct in6pcb *)m; --- 18 unchanged lines hidden (view full) --- 1031 asoc->minrto = m->sctp_ep.sctp_minrto; 1032 asoc->maxrto = m->sctp_ep.sctp_maxrto; 1033 1034 asoc->locked_on_sending = NULL; 1035 asoc->stream_locked_on = 0; 1036 asoc->ecn_echo_cnt_onq = 0; 1037 asoc->stream_locked = 0; 1038 |
1039 asoc->send_sack = 1; 1040 1041 LIST_INIT(&asoc->sctp_restricted_addrs); 1042 |
1043 TAILQ_INIT(&asoc->nets); 1044 TAILQ_INIT(&asoc->pending_reply_queue); 1045 asoc->last_asconf_ack_sent = NULL; 1046 /* Setup to fill the hb random cache at first HB */ 1047 asoc->hb_random_idx = 4; 1048 1049 asoc->sctp_autoclose_ticks = m->sctp_ep.auto_close_time; 1050 --- 85 unchanged lines hidden (view full) --- 1136 memset(new_array, 0, new_size); 1137 memcpy(new_array, asoc->mapping_array, asoc->mapping_array_size); 1138 SCTP_FREE(asoc->mapping_array); 1139 asoc->mapping_array = new_array; 1140 asoc->mapping_array_size = new_size; 1141 return (0); 1142} 1143 |
1144#if defined(SCTP_USE_THREAD_BASED_ITERATOR) 1145static void 1146sctp_iterator_work(struct sctp_iterator *it) 1147{ 1148 int iteration_count = 0; 1149 int inp_skip = 0; |
1150 |
1151 SCTP_ITERATOR_LOCK(); 1152 if (it->inp) 1153 SCTP_INP_DECR_REF(it->inp); 1154 1155 if (it->inp == NULL) { 1156 /* iterator is complete */ 1157done_with_iterator: 1158 SCTP_ITERATOR_UNLOCK(); 1159 if (it->function_atend != NULL) { 1160 (*it->function_atend) (it->pointer, it->val); 1161 } 1162 SCTP_FREE(it); 1163 return; 1164 } 1165select_a_new_ep: 1166 SCTP_INP_WLOCK(it->inp); 1167 while (((it->pcb_flags) && 1168 ((it->inp->sctp_flags & it->pcb_flags) != it->pcb_flags)) || 1169 ((it->pcb_features) && 1170 ((it->inp->sctp_features & it->pcb_features) != it->pcb_features))) { 1171 /* endpoint flags or features don't match, so keep looking */ 1172 if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) { 1173 SCTP_INP_WUNLOCK(it->inp); 1174 goto done_with_iterator; 1175 } 1176 SCTP_INP_WUNLOCK(it->inp); 1177 it->inp = LIST_NEXT(it->inp, sctp_list); 1178 if (it->inp == NULL) { 1179 goto done_with_iterator; 1180 } 1181 SCTP_INP_WLOCK(it->inp); 1182 } 1183 1184 /* mark the current iterator on the endpoint */ 1185 it->inp->inp_starting_point_for_iterator = it; 1186 SCTP_INP_WUNLOCK(it->inp); 1187 SCTP_INP_RLOCK(it->inp); 1188 1189 /* now go through each assoc which is in the desired state */ 1190 if (it->done_current_ep == 0) { 1191 if (it->function_inp != NULL) 1192 inp_skip = (*it->function_inp) (it->inp, it->pointer, it->val); 1193 it->done_current_ep = 1; 1194 } 1195 if (it->stcb == NULL) { 1196 /* run the per instance function */ 1197 it->stcb = LIST_FIRST(&it->inp->sctp_asoc_list); 1198 } 1199 if ((inp_skip) || it->stcb == NULL) { 1200 if (it->function_inp_end != NULL) { 1201 inp_skip = (*it->function_inp_end) (it->inp, 1202 it->pointer, 1203 it->val); 1204 } 1205 SCTP_INP_RUNLOCK(it->inp); 1206 goto no_stcb; 1207 } 1208 if ((it->stcb) && 1209 (it->stcb->asoc.stcb_starting_point_for_iterator == it)) { 1210 it->stcb->asoc.stcb_starting_point_for_iterator = NULL; 1211 } 1212 while (it->stcb) { 1213 SCTP_TCB_LOCK(it->stcb); 1214 if (it->asoc_state && ((it->stcb->asoc.state & it->asoc_state) != it->asoc_state)) { 1215 /* not in the right state... keep looking */ 1216 SCTP_TCB_UNLOCK(it->stcb); 1217 goto next_assoc; 1218 } 1219 /* mark the current iterator on the assoc */ 1220 it->stcb->asoc.stcb_starting_point_for_iterator = it; 1221 /* see if we have limited out the iterator loop */ 1222 iteration_count++; 1223 if (iteration_count > SCTP_ITERATOR_MAX_AT_ONCE) { 1224 /* Pause to let others grab the lock */ 1225 atomic_add_int(&it->stcb->asoc.refcnt, 1); 1226 SCTP_TCB_UNLOCK(it->stcb); 1227 SCTP_INP_RUNLOCK(it->inp); 1228 SCTP_ITERATOR_UNLOCK(); 1229 SCTP_ITERATOR_LOCK(); 1230 SCTP_INP_RLOCK(it->inp); 1231 SCTP_TCB_LOCK(it->stcb); 1232 atomic_add_int(&it->stcb->asoc.refcnt, -1); 1233 iteration_count = 0; 1234 } 1235 /* run function on this one */ 1236 (*it->function_assoc) (it->inp, it->stcb, it->pointer, it->val); 1237 1238 /* 1239 * we lie here, it really needs to have its own type but 1240 * first I must verify that this won't effect things :-0 1241 */ 1242 if (it->no_chunk_output == 0) 1243 sctp_chunk_output(it->inp, it->stcb, SCTP_OUTPUT_FROM_T3); 1244 1245 SCTP_TCB_UNLOCK(it->stcb); 1246next_assoc: 1247 it->stcb = LIST_NEXT(it->stcb, sctp_tcblist); 1248 if (it->stcb == NULL) { 1249 /* Run last function */ 1250 if (it->function_inp_end != NULL) { 1251 inp_skip = (*it->function_inp_end) (it->inp, 1252 it->pointer, 1253 it->val); 1254 } 1255 } 1256 } 1257 SCTP_INP_RUNLOCK(it->inp); 1258no_stcb: 1259 /* done with all assocs on this endpoint, move on to next endpoint */ 1260 it->done_current_ep = 0; 1261 SCTP_INP_WLOCK(it->inp); 1262 it->inp->inp_starting_point_for_iterator = NULL; 1263 SCTP_INP_WUNLOCK(it->inp); 1264 if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) { 1265 it->inp = NULL; 1266 } else { 1267 SCTP_INP_INFO_RLOCK(); 1268 it->inp = LIST_NEXT(it->inp, sctp_list); 1269 SCTP_INP_INFO_RUNLOCK(); 1270 } 1271 if (it->inp == NULL) { 1272 goto done_with_iterator; 1273 } 1274 goto select_a_new_ep; 1275} 1276 1277void 1278sctp_iterator_worker(void) 1279{ 1280 struct sctp_iterator *it = NULL; 1281 1282 /* This function is called with the WQ lock in place */ 1283 1284 sctppcbinfo.iterator_running = 1; 1285again: 1286 it = TAILQ_FIRST(&sctppcbinfo.iteratorhead); 1287 while (it) { 1288 /* now lets work on this one */ 1289 TAILQ_REMOVE(&sctppcbinfo.iteratorhead, it, sctp_nxt_itr); 1290 SCTP_IPI_ITERATOR_WQ_UNLOCK(); 1291 sctp_iterator_work(it); 1292 SCTP_IPI_ITERATOR_WQ_LOCK(); 1293 it = TAILQ_FIRST(&sctppcbinfo.iteratorhead); 1294 } 1295 if (TAILQ_FIRST(&sctppcbinfo.iteratorhead)) { 1296 goto again; 1297 } 1298 sctppcbinfo.iterator_running = 0; 1299 return; 1300} 1301 1302#endif 1303 1304 |
1305static void 1306sctp_handle_addr_wq(void) 1307{ 1308 /* deal with the ADDR wq from the rtsock calls */ 1309 struct sctp_laddr *wi; |
1310 struct sctp_asconf_iterator *asc; |
1311 |
1312 SCTP_MALLOC(asc, struct sctp_asconf_iterator *, 1313 sizeof(struct sctp_asconf_iterator), "SCTP_ASCONF_ITERATOR"); 1314 if (asc == NULL) { 1315 /* Try later, no memory */ |
1316 sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ, 1317 (struct sctp_inpcb *)NULL, 1318 (struct sctp_tcb *)NULL, 1319 (struct sctp_nets *)NULL); |
1320 return; |
1321 } |
1322 LIST_INIT(&asc->list_of_work); 1323 asc->cnt = 0; 1324 SCTP_IPI_ITERATOR_WQ_LOCK(); 1325 wi = LIST_FIRST(&sctppcbinfo.addr_wq); 1326 while (wi != NULL) { 1327 LIST_REMOVE(wi, sctp_nxt_addr); 1328 LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr); 1329 asc->cnt++; 1330 wi = LIST_FIRST(&sctppcbinfo.addr_wq); |
1331 } |
1332 SCTP_IPI_ITERATOR_WQ_UNLOCK(); 1333 if (asc->cnt == 0) { 1334 SCTP_FREE(asc); 1335 } else { 1336 sctp_initiate_iterator(sctp_iterator_ep, 1337 sctp_iterator_stcb, 1338 NULL, /* No ep end for boundall */ 1339 SCTP_PCB_FLAGS_BOUNDALL, 1340 SCTP_PCB_ANY_FEATURES, 1341 SCTP_ASOC_ANY_STATE, (void *)asc, 0, 1342 sctp_iterator_end, NULL, 0); 1343 } 1344 |
1345} 1346 1347void 1348sctp_timeout_handler(void *t) 1349{ 1350 struct sctp_inpcb *inp; 1351 struct sctp_tcb *stcb; 1352 struct sctp_nets *net; --- 377 unchanged lines hidden (view full) --- 1730 tmr = NULL; 1731 if (stcb) { 1732 SCTP_TCB_LOCK_ASSERT(stcb); 1733 } 1734 switch (t_type) { 1735 case SCTP_TIMER_TYPE_ADDR_WQ: 1736 /* Only 1 tick away :-) */ 1737 tmr = &sctppcbinfo.addr_wq_timer; |
1738 to_ticks = SCTP_ADDRESS_TICK_DELAY; |
1739 break; 1740 case SCTP_TIMER_TYPE_ITERATOR: 1741 { 1742 struct sctp_iterator *it; 1743 1744 it = (struct sctp_iterator *)inp; 1745 tmr = &it->tmr; 1746 to_ticks = SCTP_ITERATOR_TICKS; --- 77 unchanged lines hidden (view full) --- 1824 if (cnt_of_unconf) { 1825 lnet = NULL; 1826 sctp_heartbeat_timer(inp, stcb, lnet, cnt_of_unconf); 1827 } 1828 if (stcb->asoc.hb_random_idx > 3) { 1829 rndval = sctp_select_initial_TSN(&inp->sctp_ep); 1830 memcpy(stcb->asoc.hb_random_values, &rndval, 1831 sizeof(stcb->asoc.hb_random_values)); |
1832 stcb->asoc.hb_random_idx = 0; |
1833 } |
1834 this_random = stcb->asoc.hb_random_values[stcb->asoc.hb_random_idx]; 1835 stcb->asoc.hb_random_idx++; 1836 stcb->asoc.hb_ect_randombit = 0; |
1837 /* 1838 * this_random will be 0 - 256 ms RTO is in ms. 1839 */ 1840 if ((stcb->asoc.hb_is_disabled) && 1841 (cnt_of_unconf == 0)) { 1842 return (0); 1843 } 1844 if (net) { --- 949 unchanged lines hidden (view full) --- 2794 spc->spc_length = sizeof(struct sctp_paddr_change); 2795 if (sa->sa_family == AF_INET) { 2796 memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in)); 2797 } else { 2798 struct sockaddr_in6 *sin6; 2799 2800 memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in6)); 2801 |
2802 sin6 = (struct sockaddr_in6 *)&spc->spc_aaddr; 2803 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) { |
2804 if (sin6->sin6_scope_id == 0) { 2805 /* recover scope_id for user */ 2806 (void)sa6_recoverscope(sin6); 2807 } else { 2808 /* clear embedded scope_id for user */ 2809 in6_clearscope(&sin6->sin6_addr); 2810 } |
2811 } 2812 } 2813 spc->spc_state = state; 2814 spc->spc_error = error; 2815 spc->spc_assoc_id = sctp_get_associd(stcb); 2816 2817 SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_paddr_change); 2818 SCTP_BUF_NEXT(m_notify) = NULL; --- 1068 unchanged lines hidden (view full) --- 3887 if (inp == NULL) { 3888 /* Gak, TSNH!! */ 3889#ifdef INVARIANTS 3890 panic("Gak, inp NULL on add_to_readq"); 3891#endif 3892 return; 3893 } 3894 SCTP_INP_READ_LOCK(inp); |
3895 if (!(control->spec_flags & M_NOTIFICATION)) { 3896 atomic_add_int(&inp->total_recvs, 1); 3897 if (!control->do_not_ref_stcb) { 3898 atomic_add_int(&stcb->total_recvs, 1); 3899 } 3900 } |
3901 m = control->data; 3902 control->held_length = 0; 3903 control->length = 0; 3904 while (m) { 3905 if (SCTP_BUF_LEN(m) == 0) { 3906 /* Skip mbufs with NO length */ 3907 if (prev == NULL) { 3908 /* First one */ --- 282 unchanged lines hidden (view full) --- 4191} 4192 4193/* 4194 * checks to see if the given address, sa, is one that is currently known by 4195 * the kernel note: can't distinguish the same address on multiple interfaces 4196 * and doesn't handle multiple addresses with different zone/scope id's note: 4197 * ifa_ifwithaddr() compares the entire sockaddr struct 4198 */ |
4199struct sctp_ifa * 4200sctp_find_ifa_in_ep(struct sctp_inpcb *inp, struct sockaddr *addr, int holds_lock) |
4201{ |
4202 struct sctp_laddr *laddr; |
4203 |
4204 if (holds_lock == 0) 4205 SCTP_INP_RLOCK(inp); |
4206 |
4207 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { 4208 if (laddr->ifa == NULL) 4209 continue; 4210 if (addr->sa_family != laddr->ifa->address.sa.sa_family) 4211 continue; 4212 if (addr->sa_family == AF_INET) { 4213 if (((struct sockaddr_in *)addr)->sin_addr.s_addr == 4214 laddr->ifa->address.sin.sin_addr.s_addr) { 4215 /* found him. */ 4216 if (holds_lock == 0) 4217 SCTP_INP_RUNLOCK(inp); 4218 return (laddr->ifa); 4219 break; 4220 } 4221 } else if (addr->sa_family == AF_INET6) { 4222 if (SCTP6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)addr)->sin6_addr, 4223 &laddr->ifa->address.sin6.sin6_addr)) { 4224 /* found him. */ 4225 if (holds_lock == 0) 4226 SCTP_INP_RUNLOCK(inp); 4227 return (laddr->ifa); 4228 break; 4229 } 4230 } 4231 } 4232 if (holds_lock == 0) 4233 SCTP_INP_RUNLOCK(inp); 4234 return (NULL); 4235} |
4236 |
4237struct sctp_ifa * 4238sctp_find_ifa_in_ifn(struct sctp_ifn *sctp_ifnp, struct sockaddr *addr, 4239 int holds_lock) 4240{ 4241 struct sctp_ifa *sctp_ifap; |
4242 |
4243 if (holds_lock == 0) 4244 SCTP_IPI_ADDR_LOCK(); 4245 4246 LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) { 4247 if (addr->sa_family != sctp_ifap->address.sa.sa_family) 4248 continue; 4249 if (addr->sa_family == AF_INET) { 4250 if (((struct sockaddr_in *)addr)->sin_addr.s_addr == 4251 sctp_ifap->address.sin.sin_addr.s_addr) { 4252 /* found him. */ 4253 if (holds_lock == 0) 4254 SCTP_IPI_ADDR_UNLOCK(); 4255 return (sctp_ifap); 4256 break; |
4257 } |
4258 } else if (addr->sa_family == AF_INET6) { 4259 if (SCTP6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)addr)->sin6_addr, 4260 &sctp_ifap->address.sin6.sin6_addr)) { 4261 /* found him. */ 4262 if (holds_lock == 0) 4263 SCTP_IPI_ADDR_UNLOCK(); 4264 return (sctp_ifap); 4265 break; 4266 } 4267 } 4268 } 4269 if (holds_lock == 0) 4270 SCTP_IPI_ADDR_UNLOCK(); |
4271 return (NULL); 4272} 4273 |
4274struct sctp_ifa * 4275sctp_find_ifa_by_addr(struct sockaddr *addr, uint32_t vrf_id, int holds_lock) 4276{ 4277 struct sctp_ifa *sctp_ifap; 4278 struct sctp_ifn *sctp_ifnp = NULL; 4279 struct sctp_vrf *vrf; 4280 4281 vrf = sctp_find_vrf(vrf_id); 4282 if (vrf == NULL) 4283 return (NULL); 4284 4285 if (holds_lock == 0) 4286 SCTP_IPI_ADDR_LOCK(); 4287 4288 LIST_FOREACH(sctp_ifnp, &vrf->ifnlist, next_ifn) { 4289 sctp_ifap = sctp_find_ifa_in_ifn(sctp_ifnp, addr, 1); 4290 if (sctp_ifap) { 4291 if (holds_lock == 0) 4292 SCTP_IPI_ADDR_UNLOCK(); 4293 return (sctp_ifap); 4294 } 4295 } 4296 if (holds_lock == 0) 4297 SCTP_IPI_ADDR_UNLOCK(); 4298 return (NULL); 4299} 4300 |
4301static void 4302sctp_user_rcvd(struct sctp_tcb *stcb, int *freed_so_far, int hold_rlock, 4303 uint32_t rwnd_req) 4304{ 4305 /* User pulled some data, do we need a rwnd update? */ 4306 int r_unlocked = 0; 4307 uint32_t dif, rwnd; 4308 struct socket *so = NULL; --- 119 unchanged lines hidden (view full) --- 4428 int block_allowed = 1; 4429 int freed_so_far = 0; 4430 int copied_so_far = 0; 4431 int in_eeor_mode = 0; 4432 int no_rcv_needed = 0; 4433 uint32_t rwnd_req = 0; 4434 int hold_sblock = 0; 4435 int hold_rlock = 0; |
4436 int alen = 0; 4437 int slen = 0; |
4438 int held_length = 0; 4439 4440 if (msg_flags) { 4441 in_flags = *msg_flags; 4442 } else { 4443 in_flags = 0; 4444 } 4445 slen = uio->uio_resid; 4446 /* Pull in and set up our int flags */ 4447 if (in_flags & MSG_OOB) { 4448 /* Out of band's NOT supported */ 4449 return (EOPNOTSUPP); 4450 } 4451 if ((in_flags & MSG_PEEK) && (mp != NULL)) { 4452 return (EINVAL); 4453 } 4454 if ((in_flags & (MSG_DONTWAIT 4455 | MSG_NBIO 4456 )) || |
4457 SCTP_SO_IS_NBIO(so)) { |
4458 block_allowed = 0; 4459 } 4460 /* setup the endpoint */ 4461 inp = (struct sctp_inpcb *)so->so_pcb; 4462 if (inp == NULL) { 4463 return (EFAULT); 4464 } 4465 rwnd_req = (so->so_rcv.sb_hiwat >> SCTP_RWND_HIWAT_SHIFT); --- 328 unchanged lines hidden (view full) --- 4794 * mask off the high bits, we keep the actual chunk bits in 4795 * there. 4796 */ 4797 sinfo->sinfo_flags &= 0x00ff; 4798 } 4799 if (fromlen && from) { 4800 struct sockaddr *to; 4801 |
4802#ifdef INET |
4803 cp_len = min(fromlen, control->whoFrom->ro._l_addr.sin.sin_len); 4804 memcpy(from, &control->whoFrom->ro._l_addr, cp_len); 4805 ((struct sockaddr_in *)from)->sin_port = control->port_from; 4806#else 4807 /* No AF_INET use AF_INET6 */ 4808 cp_len = min(fromlen, control->whoFrom->ro._l_addr.sin6.sin6_len); 4809 memcpy(from, &control->whoFrom->ro._l_addr, cp_len); 4810 ((struct sockaddr_in6 *)from)->sin6_port = control->port_from; 4811#endif 4812 4813 to = from; |
4814#if defined(INET) && defined(INET6) |
4815 if ((inp->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) && 4816 (to->sa_family == AF_INET) && 4817 ((size_t)fromlen >= sizeof(struct sockaddr_in6))) { 4818 struct sockaddr_in *sin; 4819 struct sockaddr_in6 sin6; 4820 4821 sin = (struct sockaddr_in *)to; 4822 bzero(&sin6, sizeof(sin6)); 4823 sin6.sin6_family = AF_INET6; 4824 sin6.sin6_len = sizeof(struct sockaddr_in6); 4825 sin6.sin6_addr.s6_addr16[2] = 0xffff; 4826 bcopy(&sin->sin_addr, 4827 &sin6.sin6_addr.s6_addr16[3], 4828 sizeof(sin6.sin6_addr.s6_addr16[3])); 4829 sin6.sin6_port = sin->sin_port; 4830 memcpy(from, (caddr_t)&sin6, sizeof(sin6)); 4831 } 4832#endif |
4833#if defined(INET6) |
4834 { 4835 struct sockaddr_in6 lsa6, *to6; 4836 4837 to6 = (struct sockaddr_in6 *)to; 4838 sctp_recover_scope_mac(to6, (&lsa6)); 4839 } 4840#endif 4841 } --- 632 unchanged lines hidden (view full) --- 5474sctp_m_freem(struct mbuf *mb) 5475{ 5476 while (mb != NULL) 5477 mb = sctp_m_free(mb); 5478} 5479 5480#endif 5481 |
5482int 5483sctp_dynamic_set_primary(struct sockaddr *sa, uint32_t vrf_id) 5484{ 5485 /* 5486 * Given a local address. For all associations that holds the 5487 * address, request a peer-set-primary. 5488 */ 5489 struct sctp_ifa *ifa; 5490 struct sctp_laddr *wi; |
5491 |
5492 ifa = sctp_find_ifa_by_addr(sa, vrf_id, 0); 5493 if (ifa == NULL) { 5494 return (EADDRNOTAVAIL); 5495 } 5496 /* 5497 * Now that we have the ifa we must awaken the iterator with this 5498 * message. 5499 */ 5500 wi = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_laddr, struct sctp_laddr); 5501 if (wi == NULL) { 5502 return (ENOMEM); 5503 } 5504 /* Now incr the count and int wi structure */ 5505 SCTP_INCR_LADDR_COUNT(); 5506 bzero(wi, sizeof(*wi)); 5507 wi->ifa = ifa; 5508 wi->action = SCTP_SET_PRIM_ADDR; 5509 atomic_add_int(&ifa->refcount, 1); 5510 5511 /* Now add it to the work queue */ 5512 SCTP_IPI_ITERATOR_WQ_LOCK(); 5513 /* 5514 * Should this really be a tailq? As it is we will process the 5515 * newest first :-0 5516 */ 5517 LIST_INSERT_HEAD(&sctppcbinfo.addr_wq, wi, sctp_nxt_addr); 5518 sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ, 5519 (struct sctp_inpcb *)NULL, 5520 (struct sctp_tcb *)NULL, 5521 (struct sctp_nets *)NULL); 5522 SCTP_IPI_ITERATOR_WQ_UNLOCK(); 5523 return (0); 5524} 5525 5526 5527 5528 |
5529int 5530sctp_soreceive(so, psa, uio, mp0, controlp, flagsp) 5531 struct socket *so; 5532 struct sockaddr **psa; 5533 struct uio *uio; 5534 struct mbuf **mp0; 5535 struct mbuf **controlp; 5536 int *flagsp; --- 48 unchanged lines hidden --- |