Deleted Added
sdiff udiff text old ( 166675 ) new ( 167598 )
full compact
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_output.c,v 1.46 2005/03/06 16:04:17 itojun Exp $ */
32
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD: head/sys/netinet/sctp_output.c 166675 2007-02-12 23:24:31Z rrs $");
35
36#include <netinet/sctp_os.h>
37#include <sys/proc.h>
38#include <netinet/sctp_var.h>
39#include <netinet/sctp_header.h>
40#include <netinet/sctp_pcb.h>
41#include <netinet/sctputil.h>
42#include <netinet/sctp_output.h>
43#include <netinet/sctp_uio.h>
44#include <netinet/sctputil.h>
45#include <netinet/sctp_auth.h>
46#include <netinet/sctp_timer.h>
47#include <netinet/sctp_asconf.h>
48#include <netinet/sctp_indata.h>
49#include <netinet/sctp_bsd_addr.h>
50
51#ifdef SCTP_DEBUG
52extern uint32_t sctp_debug_on;
53
54#endif
55
56
57
58#define SCTP_MAX_GAPS_INARRAY 4
59struct sack_track {
60 uint8_t right_edge; /* mergable on the right edge */
61 uint8_t left_edge; /* mergable on the left edge */
62 uint8_t num_entries;
63 uint8_t spare;
64 struct sctp_gap_ack_block gaps[SCTP_MAX_GAPS_INARRAY];
65};

--- 1789 unchanged lines hidden (view full) ---

1855 {0, 0},
1856 {0, 0},
1857 {0, 0}
1858 }
1859 }
1860};
1861
1862
1863
1864
1865extern int sctp_peer_chunk_oh;
1866
1867static int
1868sctp_find_cmsg(int c_type, void *data, struct mbuf *control, int cpsize)
1869{
1870 struct cmsghdr cmh;
1871 int tlen, at;
1872
1873 tlen = SCTP_BUF_LEN(control);
1874 at = 0;
1875 /*

--- 33 unchanged lines hidden (view full) ---

1909 }
1910 }
1911 }
1912 /* not found */
1913 return (0);
1914}
1915
1916
1917extern int sctp_mbuf_threshold_count;
1918
1919
1920__inline struct mbuf *
1921sctp_get_mbuf_for_msg(unsigned int space_needed, int want_header,
1922 int how, int allonebuf, int type)
1923{
1924 struct mbuf *m = NULL;
1925 int aloc_size;
1926 int index = 0;
1927 int mbuf_threshold;
1928

--- 187 unchanged lines hidden (view full) ---

2116 stcb->asoc.hb_ect_randombit++;
2117 return (SCTP_ECT1_BIT);
2118 } else {
2119 stcb->asoc.hb_ect_randombit++;
2120 return (SCTP_ECT0_BIT);
2121 }
2122}
2123
2124extern int sctp_no_csum_on_loopback;
2125
2126static int
2127sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
2128 struct sctp_tcb *stcb, /* may be NULL */
2129 struct sctp_nets *net,
2130 struct sockaddr *to,
2131 struct mbuf *m,
2132 uint32_t auth_offset,
2133 struct sctp_auth_chunk *auth,

--- 17 unchanged lines hidden (view full) ---

2151 struct mbuf *o_pak;
2152
2153 struct sctphdr *sctphdr;
2154 int packet_length;
2155 int o_flgs;
2156 uint32_t csum;
2157 int ret;
2158 unsigned int have_mtu;
2159 struct route *ro;
2160
2161 if ((net) && (net->dest_state & SCTP_ADDR_OUT_OF_SCOPE)) {
2162 sctp_m_freem(m);
2163 return (EFAULT);
2164 }
2165 /* fill in the HMAC digest for any AUTH chunk in the packet */
2166 if ((auth != NULL) && (stcb != NULL)) {
2167 sctp_fill_hmac_digest_m(m, auth_offset, auth, stcb);
2168 }
2169 /* Calculate the csum and fill in the length of the packet */
2170 sctphdr = mtod(m, struct sctphdr *);
2171 have_mtu = 0;
2172 if (sctp_no_csum_on_loopback &&

--- 8 unchanged lines hidden (view full) ---

2181 packet_length = sctp_calculate_len(m);
2182 } else {
2183 sctphdr->checksum = 0;
2184 csum = sctp_calculate_sum(m, &packet_length, 0);
2185 sctphdr->checksum = csum;
2186 }
2187
2188 if (to->sa_family == AF_INET) {
2189 struct ip *ip;
2190 struct route iproute;
2191 uint8_t tos_value;
2192
2193 o_pak = SCTP_GET_HEADER_FOR_OUTPUT(sizeof(struct ip));
2194 if (o_pak == NULL) {
2195 /* failed to prepend data, give up */
2196 sctp_m_freem(m);
2197 return (ENOMEM);

--- 47 unchanged lines hidden (view full) ---

2245 }
2246 /* Now the address selection part */
2247 ip->ip_dst.s_addr = ((struct sockaddr_in *)to)->sin_addr.s_addr;
2248
2249 /* call the routine to select the src address */
2250 if (net) {
2251 if (net->src_addr_selected == 0) {
2252 /* Cache the source address */
2253 ((struct sockaddr_in *)&net->ro._s_addr)->sin_addr = sctp_ipv4_source_address_selection(inp,
2254 stcb,
2255 ro, net, out_of_asoc_ok);
2256 if (ro->ro_rt)
2257 net->src_addr_selected = 1;
2258 }
2259 ip->ip_src = ((struct sockaddr_in *)&net->ro._s_addr)->sin_addr;
2260 } else {
2261 ip->ip_src = sctp_ipv4_source_address_selection(inp,
2262 stcb, ro, net, out_of_asoc_ok);
2263 }
2264
2265 /*
2266 * If source address selection fails and we find no route
2267 * then the ip_output should fail as well with a
2268 * NO_ROUTE_TO_HOST type error. We probably should catch
2269 * that somewhere and abort the association right away
2270 * (assuming this is an INIT being sent).
2271 */
2272 if ((ro->ro_rt == NULL)) {
2273 /*
2274 * src addr selection failed to find a route (or
2275 * valid source addr), so we can't get there from
2276 * here!
2277 */
2278#ifdef SCTP_DEBUG
2279 if (sctp_debug_on & SCTP_DEBUG_OUTPUT1) {
2280 printf("low_level_output: dropped v4 packet- no valid source addr\n");
2281 printf("Destination was %x\n", (uint32_t) (ntohl(ip->ip_dst.s_addr)));
2282 }
2283#endif /* SCTP_DEBUG */
2284 if (net) {
2285 if ((net->dest_state & SCTP_ADDR_REACHABLE) && stcb)
2286 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
2287 stcb,
2288 SCTP_FAILED_THRESHOLD,
2289 (void *)net);
2290 net->dest_state &= ~SCTP_ADDR_REACHABLE;
2291 net->dest_state |= SCTP_ADDR_NOT_REACHABLE;
2292 if (stcb) {
2293 if (net == stcb->asoc.primary_destination) {
2294 /* need a new primary */
2295 struct sctp_nets *alt;
2296
2297 alt = sctp_find_alternate_net(stcb, net, 0);
2298 if (alt != net) {
2299 if (sctp_set_primary_addr(stcb,
2300 (struct sockaddr *)NULL,
2301 alt) == 0) {
2302 net->dest_state |= SCTP_ADDR_WAS_PRIMARY;
2303 net->src_addr_selected = 0;
2304 }
2305 }
2306 }
2307 }
2308 }
2309 sctp_m_freem(o_pak);
2310 return (EHOSTUNREACH);

--- 33 unchanged lines hidden (view full) ---

2344 SCTP_STAT_INCR(sctps_senderrors);
2345#ifdef SCTP_DEBUG
2346 if (sctp_debug_on & SCTP_DEBUG_OUTPUT3) {
2347 printf("Ip output returns %d\n", ret);
2348 }
2349#endif
2350 if (net == NULL) {
2351 /* free tempy routes */
2352 if (ro->ro_rt)
2353 RTFREE(ro->ro_rt);
2354 } else {
2355 /* PMTU check versus smallest asoc MTU goes here */
2356 if (ro->ro_rt != NULL) {
2357 if (ro->ro_rt->rt_rmx.rmx_mtu &&
2358 (stcb->asoc.smallest_mtu > ro->ro_rt->rt_rmx.rmx_mtu)) {
2359 sctp_mtu_size_reset(inp, &stcb->asoc,
2360 ro->ro_rt->rt_rmx.rmx_mtu);
2361 }
2362 } else {
2363 /* route was freed */
2364 net->src_addr_selected = 0;
2365 }
2366 }
2367 return (ret);
2368 }
2369#ifdef INET6
2370 else if (to->sa_family == AF_INET6) {
2371 uint32_t flowlabel;

--- 71 unchanged lines hidden (view full) ---

2443 */
2444 bzero(&lsa6_tmp, sizeof(lsa6_tmp));
2445 lsa6_tmp.sin6_family = AF_INET6;
2446 lsa6_tmp.sin6_len = sizeof(lsa6_tmp);
2447 lsa6 = &lsa6_tmp;
2448 if (net) {
2449 if (net->src_addr_selected == 0) {
2450 /* Cache the source address */
2451 ((struct sockaddr_in6 *)&net->ro._s_addr)->sin6_addr = sctp_ipv6_source_address_selection(inp,
2452 stcb, ro, net, out_of_asoc_ok);
2453
2454 if (ro->ro_rt)
2455 net->src_addr_selected = 1;
2456 }
2457 lsa6->sin6_addr = ((struct sockaddr_in6 *)&net->ro._s_addr)->sin6_addr;
2458 } else {
2459 lsa6->sin6_addr = sctp_ipv6_source_address_selection(
2460 inp, stcb, ro, net, out_of_asoc_ok);
2461 }
2462 lsa6->sin6_port = inp->sctp_lport;
2463
2464 if ((ro->ro_rt == NULL)) {
2465 /*
2466 * src addr selection failed to find a route (or
2467 * valid source addr), so we can't get there from
2468 * here!
2469 */
2470#ifdef SCTP_DEBUG
2471 if (sctp_debug_on & SCTP_DEBUG_OUTPUT1) {
2472 printf("low_level_output: dropped v6 pkt- no valid source addr\n");
2473 }
2474#endif
2475 sctp_m_freem(o_pak);
2476 if (net) {
2477 if ((net->dest_state & SCTP_ADDR_REACHABLE) && stcb)
2478 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
2479 stcb,
2480 SCTP_FAILED_THRESHOLD,
2481 (void *)net);
2482 net->dest_state &= ~SCTP_ADDR_REACHABLE;
2483 net->dest_state |= SCTP_ADDR_NOT_REACHABLE;
2484 if (stcb) {
2485 if (net == stcb->asoc.primary_destination) {
2486 /* need a new primary */
2487 struct sctp_nets *alt;
2488
2489 alt = sctp_find_alternate_net(stcb, net, 0);
2490 if (alt != net) {
2491 if (sctp_set_primary_addr(stcb,
2492 (struct sockaddr *)NULL,
2493 alt) == 0) {
2494 net->dest_state |= SCTP_ADDR_WAS_PRIMARY;
2495 net->src_addr_selected = 0;
2496 }
2497 }
2498 }
2499 }
2500 }
2501 return (EHOSTUNREACH);
2502 }
2503 /*
2504 * XXX: sa6 may not have a valid sin6_scope_id in the
2505 * non-SCOPEDROUTING case.
2506 */
2507 bzero(&lsa6_storage, sizeof(lsa6_storage));
2508 lsa6_storage.sin6_family = AF_INET6;
2509 lsa6_storage.sin6_len = sizeof(lsa6_storage);

--- 50 unchanged lines hidden (view full) ---

2560 }
2561#ifdef SCTP_DEBUG
2562 if (sctp_debug_on & SCTP_DEBUG_OUTPUT3) {
2563 printf("return from send is %d\n", ret);
2564 }
2565#endif /* SCTP_DEBUG_OUTPUT */
2566 SCTP_STAT_INCR(sctps_sendpackets);
2567 SCTP_STAT_INCR_COUNTER64(sctps_outpackets);
2568 if (ret)
2569 SCTP_STAT_INCR(sctps_senderrors);
2570 if (net == NULL) {
2571 /* Now if we had a temp route free it */
2572 if (ro->ro_rt) {
2573 RTFREE(ro->ro_rt);
2574 }
2575 } else {
2576 /* PMTU check versus smallest asoc MTU goes here */
2577 if (ro->ro_rt == NULL) {
2578 /* Route was freed */
2579 net->src_addr_selected = 0;
2580 }
2581 if (ro->ro_rt != NULL) {
2582 if (ro->ro_rt->rt_rmx.rmx_mtu &&
2583 (stcb->asoc.smallest_mtu > ro->ro_rt->rt_rmx.rmx_mtu)) {
2584 sctp_mtu_size_reset(inp,
2585 &stcb->asoc,
2586 ro->ro_rt->rt_rmx.rmx_mtu);

--- 672 unchanged lines hidden (view full) ---

3259 struct sockaddr *to;
3260 struct sctp_state_cookie stc;
3261 struct sctp_nets *net = NULL;
3262 int cnt_inits_to = 0;
3263 uint16_t his_limit, i_want;
3264 int abort_flag, padval, sz_of;
3265 int num_ext;
3266 int p_len;
3267
3268 if (stcb) {
3269 asoc = &stcb->asoc;
3270 } else {
3271 asoc = NULL;
3272 }
3273 m_last = NULL;
3274 if ((asoc != NULL) &&
3275 (SCTP_GET_STATE(asoc) != SCTP_STATE_COOKIE_WAIT) &&

--- 77 unchanged lines hidden (view full) ---

3353 /* now for scope setup */
3354 memset((caddr_t)&store, 0, sizeof(store));
3355 sin = (struct sockaddr_in *)&store;
3356 sin6 = (struct sockaddr_in6 *)&store;
3357 if (net == NULL) {
3358 to = (struct sockaddr *)&store;
3359 iph = mtod(init_pkt, struct ip *);
3360 if (iph->ip_v == IPVERSION) {
3361 struct in_addr addr;
3362 struct route iproute;
3363
3364 sin->sin_family = AF_INET;
3365 sin->sin_len = sizeof(struct sockaddr_in);
3366 sin->sin_port = sh->src_port;
3367 sin->sin_addr = iph->ip_src;
3368 /* lookup address */
3369 stc.address[0] = sin->sin_addr.s_addr;
3370 stc.address[1] = 0;
3371 stc.address[2] = 0;
3372 stc.address[3] = 0;
3373 stc.addr_type = SCTP_IPV4_ADDRESS;
3374 /* local from address */
3375 memset(&iproute, 0, sizeof(iproute));
3376 ro = &iproute;
3377 memcpy(&ro->ro_dst, sin, sizeof(*sin));
3378 addr = sctp_ipv4_source_address_selection(inp, NULL,
3379 ro, NULL, 0);
3380 if (ro->ro_rt) {
3381 RTFREE(ro->ro_rt);
3382 }
3383 stc.laddress[0] = addr.s_addr;
3384 stc.laddress[1] = 0;
3385 stc.laddress[2] = 0;
3386 stc.laddress[3] = 0;
3387 stc.laddr_type = SCTP_IPV4_ADDRESS;
3388 /* scope_id is only for v6 */
3389 stc.scope_id = 0;
3390#ifndef SCTP_DONT_DO_PRIVADDR_SCOPE
3391 if (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
3392 stc.ipv4_scope = 1;
3393 }
3394#else
3395 stc.ipv4_scope = 1;
3396#endif /* SCTP_DONT_DO_PRIVADDR_SCOPE */
3397 /* Must use the address in this case */
3398 if (sctp_is_address_on_local_host((struct sockaddr *)sin)) {
3399 stc.loopback_scope = 1;
3400 stc.ipv4_scope = 1;
3401 stc.site_scope = 1;
3402 stc.local_scope = 1;
3403 }
3404 } else if (iph->ip_v == (IPV6_VERSION >> 4)) {
3405 struct in6_addr addr;
3406
3407 struct route_in6 iproute6;
3408
3409 ip6 = mtod(init_pkt, struct ip6_hdr *);
3410 sin6->sin6_family = AF_INET6;
3411 sin6->sin6_len = sizeof(struct sockaddr_in6);
3412 sin6->sin6_port = sh->src_port;
3413 sin6->sin6_addr = ip6->ip6_src;
3414 /* lookup address */
3415 memcpy(&stc.address, &sin6->sin6_addr,
3416 sizeof(struct in6_addr));
3417 sin6->sin6_scope_id = 0;
3418 stc.addr_type = SCTP_IPV6_ADDRESS;
3419 stc.scope_id = 0;
3420 if (sctp_is_address_on_local_host((struct sockaddr *)sin6)) {
3421 stc.loopback_scope = 1;
3422 stc.local_scope = 1;
3423 stc.site_scope = 1;
3424 stc.ipv4_scope = 1;
3425 } else if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
3426 /*
3427 * If the new destination is a LINK_LOCAL we
3428 * must have common both site and local
3429 * scope. Don't set local scope though since
3430 * we must depend on the source to be added

--- 23 unchanged lines hidden (view full) ---

3454 * we must have site scope in common.
3455 */
3456 stc.site_scope = 1;
3457 }
3458 /* local from address */
3459 memset(&iproute6, 0, sizeof(iproute6));
3460 ro = (struct route *)&iproute6;
3461 memcpy(&ro->ro_dst, sin6, sizeof(*sin6));
3462 addr = sctp_ipv6_source_address_selection(inp, NULL,
3463 ro, NULL, 0);
3464 if (ro->ro_rt) {
3465 RTFREE(ro->ro_rt);
3466 }
3467 memcpy(&stc.laddress, &addr, sizeof(struct in6_addr));
3468 stc.laddr_type = SCTP_IPV6_ADDRESS;
3469 }
3470 } else {
3471 /* set the scope per the existing tcb */
3472 struct sctp_nets *lnet;
3473
3474 stc.loopback_scope = asoc->loopback_scope;
3475 stc.ipv4_scope = asoc->ipv4_local_scope;

--- 20 unchanged lines hidden (view full) ---

3496 stc.address[2] = 0;
3497 stc.address[3] = 0;
3498 stc.addr_type = SCTP_IPV4_ADDRESS;
3499 if (net->src_addr_selected == 0) {
3500 /*
3501 * strange case here, the INIT should have
3502 * did the selection.
3503 */
3504 net->ro._s_addr.sin.sin_addr =
3505 sctp_ipv4_source_address_selection(inp,
3506 stcb, (struct route *)&net->ro, net, 0);
3507 net->src_addr_selected = 1;
3508
3509 }
3510 stc.laddress[0] = net->ro._s_addr.sin.sin_addr.s_addr;
3511 stc.laddress[1] = 0;
3512 stc.laddress[2] = 0;
3513 stc.laddress[3] = 0;
3514 stc.laddr_type = SCTP_IPV4_ADDRESS;
3515 } else if (to->sa_family == AF_INET6) {
3516 sin6 = (struct sockaddr_in6 *)to;
3517 memcpy(&stc.address, &sin6->sin6_addr,
3518 sizeof(struct in6_addr));
3519 stc.addr_type = SCTP_IPV6_ADDRESS;
3520 if (net->src_addr_selected == 0) {
3521 /*
3522 * strange case here, the INIT should have
3523 * did the selection.
3524 */
3525 net->ro._s_addr.sin6.sin6_addr =
3526 sctp_ipv6_source_address_selection(inp,
3527 stcb, (struct route *)&net->ro, net, 0);
3528 net->src_addr_selected = 1;
3529 }
3530 memcpy(&stc.laddress, &net->ro._l_addr.sin6.sin6_addr,
3531 sizeof(struct in6_addr));
3532 stc.laddr_type = SCTP_IPV6_ADDRESS;
3533 }
3534 }
3535 /* Now lets put the SCTP header in place */
3536 initackm_out = mtod(m, struct sctp_init_msg *);
3537 initackm_out->sh.src_port = inp->sctp_lport;
3538 initackm_out->sh.dest_port = sh->src_port;

--- 126 unchanged lines hidden (view full) ---

3665 /* add authentication parameters */
3666 if (!sctp_auth_disable) {
3667 struct sctp_auth_random *random;
3668 struct sctp_auth_hmac_algo *hmacs;
3669 struct sctp_auth_chunk_list *chunks;
3670 uint16_t random_len;
3671
3672 /* generate and add RANDOM parameter */
3673 random_len = sctp_auth_random_len;
3674 random = (struct sctp_auth_random *)(mtod(m, caddr_t)+SCTP_BUF_LEN(m));
3675 random->ph.param_type = htons(SCTP_RANDOM);
3676 p_len = sizeof(*random) + random_len;
3677 random->ph.param_length = htons(p_len);
3678 SCTP_READ_RANDOM(random->random_data, random_len);
3679 /* zero out any padding required */
3680 bzero((caddr_t)random + p_len, SCTP_SIZE32(p_len) - p_len);
3681 SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len);

--- 324 unchanged lines hidden (view full) ---

4006 siz -= sctp_get_auth_chunk_len(stcb->asoc.peer_hmac_id);
4007
4008 if (siz % 4) {
4009 /* make it an even word boundary please */
4010 siz -= (siz % 4);
4011 }
4012 return (siz);
4013}
4014extern unsigned int sctp_max_chunks_on_queue;
4015
4016static void
4017sctp_set_prsctp_policy(struct sctp_tcb *stcb,
4018 struct sctp_stream_queue_pending *sp)
4019{
4020 sp->pr_sctp_on = 0;
4021 if (stcb->asoc.peer_supports_prsctp) {
4022 /*

--- 584 unchanged lines hidden (view full) ---

4607 mat = m;
4608 ca->sndlen = 0;
4609 while (m) {
4610 ca->sndlen += SCTP_BUF_LEN(m);
4611 m = SCTP_BUF_NEXT(m);
4612 }
4613 ca->m = m;
4614 }
4615 ret = sctp_initiate_iterator(NULL, sctp_sendall_iterator,
4616 SCTP_PCB_ANY_FLAGS, SCTP_PCB_ANY_FEATURES, SCTP_ASOC_ANY_STATE,
4617 (void *)ca, 0,
4618 sctp_sendall_completes, inp, 1);
4619 if (ret) {
4620#ifdef SCTP_DEBUG
4621 printf("Failed to initiate iterator for sendall\n");
4622#endif
4623 SCTP_FREE(ca);

--- 178 unchanged lines hidden (view full) ---

4802 /* special handling, we must look into the param */
4803 if (chk != asoc->str_reset) {
4804 goto clean_up_anyway;
4805 }
4806 }
4807 }
4808}
4809
4810extern int sctp_min_split_point;
4811
4812static __inline int
4813sctp_can_we_split_this(struct sctp_tcb *stcb,
4814 struct sctp_stream_queue_pending *sp,
4815 int goal_mtu, int frag_point, int eeor_on)
4816{
4817 /*
4818 * Make a decision on if I should split a msg into multiple parts.

--- 370 unchanged lines hidden (view full) ---

5189
5190}
5191
5192static void
5193sctp_fill_outqueue(struct sctp_tcb *stcb,
5194 struct sctp_nets *net, int frag_point, int eeor_mode)
5195{
5196 struct sctp_association *asoc;
5197 struct sctp_stream_out *strq, *strqn;
5198 int goal_mtu, moved_how_much, total_moved = 0;
5199 int locked, giveup;
5200 struct sctp_stream_queue_pending *sp;
5201
5202 SCTP_TCB_LOCK_ASSERT(stcb);
5203 asoc = &stcb->asoc;
5204#ifdef AF_INET6
5205 if (net->ro._l_addr.sin6.sin6_family == AF_INET6) {
5206 goal_mtu = net->mtu - SCTP_MIN_OVERHEAD;
5207 } else {
5208 /* ?? not sure what else to do */
5209 goal_mtu = net->mtu - SCTP_MIN_V4_OVERHEAD;
5210 }
5211#else
5212 goal_mtu = net->mtu - SCTP_MIN_OVERHEAD;

--- 50 unchanged lines hidden (view full) ---

5263 asoc->last_out_stream = strq;
5264 if (locked) {
5265 asoc->locked_on_sending = strq;
5266 if ((moved_how_much == 0) || (giveup))
5267 /* no more to move for now */
5268 break;
5269 } else {
5270 asoc->locked_on_sending = NULL;
5271 if (TAILQ_FIRST(&strq->outqueue) == NULL) {
5272 sctp_remove_from_wheel(stcb, asoc, strq);
5273 }
5274 if (giveup) {
5275 break;
5276 }
5277 strq = sctp_select_a_stream(stcb, asoc);
5278 if (strq == NULL) {
5279 break;
5280 }
5281 }
5282 total_moved += moved_how_much;
5283 goal_mtu -= moved_how_much;
5284 goal_mtu &= 0xfffffffc;
5285 }

--- 45 unchanged lines hidden (view full) ---

5331 sctp_free_remote_addr(chk->whoTo);
5332 chk->whoTo = a_net;
5333 atomic_add_int(&a_net->ref_count, 1);
5334 }
5335 }
5336 }
5337}
5338
5339extern int sctp_early_fr;
5340
5341int
5342sctp_med_chunk_output(struct sctp_inpcb *inp,
5343 struct sctp_tcb *stcb,
5344 struct sctp_association *asoc,
5345 int *num_out,
5346 int *reason_code,
5347 int control_only, int *cwnd_full, int from_where,
5348 struct timeval *now, int *now_filled, int frag_point)

--- 10 unchanged lines hidden (view full) ---

5359 struct sctp_nets *net;
5360 struct mbuf *outchain, *endoutchain;
5361 struct sctp_tmit_chunk *chk, *nchk;
5362 struct sctphdr *shdr;
5363
5364 /* temp arrays for unlinking */
5365 struct sctp_tmit_chunk *data_list[SCTP_MAX_DATA_BUNDLING];
5366 int no_fragmentflg, error;
5367 int one_chunk, hbflag;
5368 int asconf, cookie, no_out_cnt;
5369 int bundle_at, ctl_cnt, no_data_chunks, cwnd_full_ind, eeor_mode;
5370 unsigned int mtu, r_mtu, omtu, mx_mtu, to_out;
5371 struct sctp_nets *start_at, *old_startat = NULL, *send_start_at;
5372 int tsns_sent = 0;
5373 uint32_t auth_offset = 0;
5374 struct sctp_auth_chunk *auth = NULL;
5375

--- 134 unchanged lines hidden (view full) ---

5510 * queued to this address. Skip it.
5511 */
5512 continue;
5513 }
5514 ctl_cnt = bundle_at = 0;
5515 endoutchain = outchain = NULL;
5516 no_fragmentflg = 1;
5517 one_chunk = 0;
5518
5519 if ((net->ro.ro_rt) && (net->ro.ro_rt->rt_ifp)) {
5520 /*
5521 * if we have a route and an ifp check to see if we
5522 * have room to send to this guy
5523 */
5524 struct ifnet *ifp;
5525
5526 ifp = net->ro.ro_rt->rt_ifp;

--- 209 unchanged lines hidden (view full) ---

5736 if (error == EHOSTUNREACH) {
5737 /*
5738 * Destination went
5739 * unreachable
5740 * during this send
5741 */
5742 sctp_move_to_an_alt(stcb, asoc, net);
5743 }
5744 sctp_clean_up_ctl(stcb, asoc);
5745 *reason_code = 7;
5746 return (error);
5747 } else
5748 asoc->ifp_had_enobuf = 0;
5749 /* Only HB or ASCONF advances time */
5750 if (hbflag) {
5751 if (*now_filled == 0) {
5752 SCTP_GETTIME_TIMEVAL(&net->last_sent_time);
5753 *now_filled = 1;
5754 *now = net->last_sent_time;

--- 44 unchanged lines hidden (view full) ---

5799 else
5800 omtu = 0;
5801 } else {
5802 if (net->mtu > (sizeof(struct ip6_hdr) + sizeof(struct sctphdr)))
5803 omtu = net->mtu - (sizeof(struct ip6_hdr) + sizeof(struct sctphdr));
5804 else
5805 omtu = 0;
5806 }
5807 if (((asoc->state & SCTP_STATE_OPEN) == SCTP_STATE_OPEN) ||
5808 (cookie)) {
5809 for (chk = TAILQ_FIRST(&asoc->send_queue); chk; chk = nchk) {
5810 if (no_data_chunks) {
5811 /* let only control go out */
5812 *reason_code = 1;
5813 break;
5814 }
5815 if (net->flight_size >= net->cwnd) {

--- 188 unchanged lines hidden (view full) ---

6004 }
6005 if (error == EHOSTUNREACH) {
6006 /*
6007 * Destination went unreachable
6008 * during this send
6009 */
6010 sctp_move_to_an_alt(stcb, asoc, net);
6011 }
6012 sctp_clean_up_ctl(stcb, asoc);
6013 *reason_code = 6;
6014 return (error);
6015 } else {
6016 asoc->ifp_had_enobuf = 0;
6017 }
6018 outchain = endoutchain = NULL;
6019 auth = NULL;
6020 auth_offset = 0;
6021 if (bundle_at || hbflag) {
6022 /* For data/asconf and hb set time */

--- 879 unchanged lines hidden (view full) ---

6902 SCTP_STAT_INCR(sctps_sendretransdata);
6903 data_list[i]->sent = SCTP_DATAGRAM_SENT;
6904 /*
6905 * When we have a revoked data, and we
6906 * retransmit it, then we clear the revoked
6907 * flag since this flag dictates if we
6908 * subtracted from the fs
6909 */
6910 data_list[i]->rec.data.chunk_was_revoked = 0;
6911 data_list[i]->snd_count++;
6912 sctp_ucount_decr(asoc->sent_queue_retran_cnt);
6913 /* record the time */
6914 data_list[i]->sent_rcv_time = asoc->time_last_sent;
6915 if (asoc->sent_queue_retran_cnt < 0) {
6916 asoc->sent_queue_retran_cnt = 0;
6917 }
6918 if (data_list[i]->book_size_scale) {

--- 602 unchanged lines hidden (view full) ---

7521 a_chk->whoTo = NULL;
7522 break;
7523 }
7524 }
7525 if (a_chk == NULL) {
7526 sctp_alloc_a_chunk(stcb, a_chk);
7527 if (a_chk == NULL) {
7528 /* No memory so we drop the idea, and set a timer */
7529 sctp_timer_stop(SCTP_TIMER_TYPE_RECV,
7530 stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_5);
7531 sctp_timer_start(SCTP_TIMER_TYPE_RECV,
7532 stcb->sctp_ep, stcb, NULL);
7533 return;
7534 }
7535 a_chk->copy_by_ref = 0;
7536 /* a_chk->rec.chunk_id.id = SCTP_SELECTIVE_ACK; */
7537 a_chk->rec.chunk_id.id = SCTP_SELECTIVE_ACK;
7538 a_chk->rec.chunk_id.can_take_data = 1;
7539 }
7540 a_chk->asoc = asoc;
7541 a_chk->snd_count = 0;
7542 a_chk->send_size = 0; /* fill in later */
7543 a_chk->sent = SCTP_DATAGRAM_UNSENT;
7544
7545 if ((asoc->numduptsns) ||
7546 (asoc->last_data_chunk_from->dest_state & SCTP_ADDR_NOT_REACHABLE)
7547 ) {

--- 42 unchanged lines hidden (view full) ---

7590 if (a_chk->data) {
7591 /* was a problem with the destination */
7592 sctp_m_freem(a_chk->data);
7593 a_chk->data = NULL;
7594 }
7595 if (a_chk->whoTo)
7596 atomic_subtract_int(&a_chk->whoTo->ref_count, 1);
7597 sctp_free_a_chunk(stcb, a_chk);
7598 sctp_timer_stop(SCTP_TIMER_TYPE_RECV,
7599 stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_6);
7600 sctp_timer_start(SCTP_TIMER_TYPE_RECV,
7601 stcb->sctp_ep, stcb, NULL);
7602 return;
7603 }
7604 /* ok, lets go through and fill it in */
7605 SCTP_BUF_RESV_UF(a_chk->data, SCTP_MIN_OVERHEAD);
7606 space = M_TRAILINGSPACE(a_chk->data);
7607 if (space > (a_chk->whoTo->mtu - SCTP_MIN_OVERHEAD)) {
7608 space = (a_chk->whoTo->mtu - SCTP_MIN_OVERHEAD);
7609 }

--- 122 unchanged lines hidden (view full) ---

7732 (num_gap_blocks * sizeof(struct sctp_gap_ack_block)) +
7733 (num_dups * sizeof(int32_t)));
7734 SCTP_BUF_LEN(a_chk->data) = a_chk->send_size;
7735 sack->sack.num_gap_ack_blks = htons(num_gap_blocks);
7736 sack->sack.num_dup_tsns = htons(num_dups);
7737 sack->ch.chunk_length = htons(a_chk->send_size);
7738 TAILQ_INSERT_TAIL(&asoc->control_send_queue, a_chk, sctp_next);
7739 asoc->ctrl_queue_cnt++;
7740 SCTP_STAT_INCR(sctps_sendsacks);
7741 return;
7742}
7743
7744
7745void
7746sctp_send_abort_tcb(struct sctp_tcb *stcb, struct mbuf *operr)
7747{

--- 1461 unchanged lines hidden (view full) ---

9209 }
9210 }
9211 error = sctp_lower_sosend(so, addr, uio, top, control, flags,
9212 use_rcvinfo, &srcv, p);
9213 return (error);
9214}
9215
9216
9217extern unsigned int sctp_add_more_threshold;
9218int
9219sctp_lower_sosend(struct socket *so,
9220 struct sockaddr *addr,
9221 struct uio *uio,
9222 struct mbuf *i_pak,
9223 struct mbuf *control,
9224 int flags,
9225 int use_rcvinfo,

--- 150 unchanged lines hidden (view full) ---

9376 } else if (addr == NULL) {
9377 error = ENOENT;
9378 goto out_unlocked;
9379 } else {
9380 /*
9381 * UDP style, we must go ahead and start the INIT
9382 * process
9383 */
9384 if ((use_rcvinfo) && (srcv) &&
9385 ((srcv->sinfo_flags & SCTP_ABORT) ||
9386 ((srcv->sinfo_flags & SCTP_EOF) &&
9387 (uio->uio_resid == 0)))) {
9388 /*
9389 * User asks to abort a non-existant assoc,
9390 * or EOF a non-existant assoc with no data
9391 */
9392 error = ENOENT;
9393 goto out_unlocked;
9394 }
9395 /* get an asoc/stcb struct */
9396 stcb = sctp_aloc_assoc(inp, addr, 1, &error, 0);
9397 if (stcb == NULL) {
9398 /* Error is setup for us in the call */
9399 goto out_unlocked;
9400 }
9401 if (create_lock_applied) {
9402 SCTP_ASOC_CREATE_UNLOCK(inp);
9403 create_lock_applied = 0;
9404 } else {

--- 112 unchanged lines hidden (view full) ---

9517 * but the ro structure may now have an update and
9518 * thus we may need to change it BEFORE we append
9519 * the message.
9520 */
9521 net = stcb->asoc.primary_destination;
9522 asoc = &stcb->asoc;
9523 }
9524 }
9525 if (((so->so_state & SS_NBIO)
9526 || (flags & MSG_NBIO)
9527 )) {
9528 non_blocking = 1;
9529 }
9530 asoc = &stcb->asoc;
9531 /* would we block? */
9532 if (non_blocking) {
9533 if ((so->so_snd.sb_hiwat <

--- 858 unchanged lines hidden ---