summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorrrs <rrs@FreeBSD.org>2007-01-15 15:12:10 +0000
committerrrs <rrs@FreeBSD.org>2007-01-15 15:12:10 +0000
commit094d70fac7c91a2d4fa26601007f25c9d46b058e (patch)
tree7e51ed488736cee7b8b3fdcc5a1fa638803647b8 /sys
parentaf870dbd2eb2b7c401adbdae5995f68a5ff112a3 (diff)
downloadFreeBSD-src-094d70fac7c91a2d4fa26601007f25c9d46b058e.zip
FreeBSD-src-094d70fac7c91a2d4fa26601007f25c9d46b058e.tar.gz
- Macroizes the V6ONLY flag check.
- Added a short time wait (not used yet) constant - Corrected the type of the crc32c table (it was unsigned long and really is a uint32_t - Got rid of the user of MHeaders until they are truely needed by lower layers. - Fixed an initialization problem in the readq structure (ordering was off). - Found yet another collision bug when the random number generator returns two numbers on one side (during a collision) that are the same. Also added some tracking of cookies that will go away when we know that we have the last collision bug gone. - Fixed an init bug for book_size_scale, that was causing Early FR code to run when it should not. - Fixed a flight size tracking bug that was associated with Early FR but due to above bug also effected all FR's - Fixed it so Max Burst also will apply to Fast Retransmit. - Fixed a bug in the temporary logging code that allowed a static log array overflow - hashinit_flags is now used. - Two last mcopym's were converted to the macro sctp_m_copym that has always been used by all other places - macro sctp_m_copym was converted to upper case. - We now validate sinfo_flags on input (we did not before). - Fixed a bug that prevented a user from sending data and immediately shuting down with one send operation. - Moved to use hashdestroy instead of free() in our macros. - Fixed an init problem in our timed_wait vtag where we did not fully initialize our time-wait blocks. - Timer stops were re-positioned. - A pcb cleanup method was added, however this probably will not be used in BSD.. unless we make module loadable protocols - I think this fixes the mysterious timer bug.. it was a ordering of locks problem in the way we did timers. It now conforms to the timeout(9) manual (except for the _drain part, we had to do this a different way due to locks). - Fixed error return code so we get either CONNREUSED or CONNRESET depending on where one is in progression - Purged an unused clone macro. - Fixed a read erro code issue where we were NOT getting the proper error when the connection was reset. - Purged an unused clone macro. - Fixed a read erro code issue where we were NOT getting the proper error when the connection was reset. Approved by: gnn
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet/sctp_asconf.c6
-rw-r--r--sys/netinet/sctp_constants.h6
-rw-r--r--sys/netinet/sctp_crc32.c130
-rw-r--r--sys/netinet/sctp_indata.c6
-rw-r--r--sys/netinet/sctp_indata.h16
-rw-r--r--sys/netinet/sctp_input.c84
-rw-r--r--sys/netinet/sctp_os_bsd.h9
-rw-r--r--sys/netinet/sctp_output.c100
-rw-r--r--sys/netinet/sctp_pcb.c92
-rw-r--r--sys/netinet/sctp_pcb.h9
-rw-r--r--sys/netinet/sctp_structs.h1
-rw-r--r--sys/netinet/sctp_uio.h15
-rw-r--r--sys/netinet/sctp_usrreq.c30
-rw-r--r--sys/netinet/sctp_var.h3
-rw-r--r--sys/netinet/sctputil.c107
-rw-r--r--sys/netinet/sctputil.h5
-rw-r--r--sys/netinet6/sctp6_usrreq.c21
17 files changed, 397 insertions, 243 deletions
diff --git a/sys/netinet/sctp_asconf.c b/sys/netinet/sctp_asconf.c
index 0d2fe04..4ef29c6 100644
--- a/sys/netinet/sctp_asconf.c
+++ b/sys/netinet/sctp_asconf.c
@@ -1786,8 +1786,7 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
inp6 = (struct in6pcb *)&inp->ip_inp.inp;
/* invalid if we are a v6 only endpoint */
if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
- (inp6->inp_flags & IN6P_IPV6_V6ONLY)
- )
+ SCTP_IPV6_V6ONLY(inp6))
return;
sin = (struct sockaddr_in *)ifa->ifa_addr;
@@ -1877,8 +1876,7 @@ sctp_addr_mgmt_ep(struct sctp_inpcb *inp, struct ifaddr *ifa, uint16_t type)
inp6 = (struct in6pcb *)&inp->ip_inp.inp;
if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
- (inp6->inp_flags & IN6P_IPV6_V6ONLY)
- ) {
+ SCTP_IPV6_V6ONLY(inp6)) {
SCTP_INP_WUNLOCK(inp);
return;
}
diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h
index 5d00193..06490d3 100644
--- a/sys/netinet/sctp_constants.h
+++ b/sys/netinet/sctp_constants.h
@@ -891,6 +891,12 @@ __FBSDID("$FreeBSD$");
*/
#define SCTP_TIME_WAIT 480
+/* This time wait is the same as the default cookie life
+ * since we now enter a tag in every time we send a cookie.
+ * We want this shorter to avoid vtag depletion.
+ */
+#define SCTP_TIME_WAIT_SHORT 60
+
/* The system retains a cache of free chunks such to
* cut down on calls the memory allocation system. There
* is a per association limit of free items and a overall
diff --git a/sys/netinet/sctp_crc32.c b/sys/netinet/sctp_crc32.c
index c0842a7..3728ef3 100644
--- a/sys/netinet/sctp_crc32.c
+++ b/sys/netinet/sctp_crc32.c
@@ -593,71 +593,71 @@ update_crc32(uint32_t crc32,
return (sctp_crc32c_sb8_64_bit(crc32, buffer, length, offset));
}
-unsigned long sctp_crc_c[256] = {
- 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
- 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
- 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
- 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
- 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
- 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
- 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
- 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
- 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
- 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
- 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
- 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
- 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
- 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
- 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
- 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
- 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
- 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
- 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
- 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
- 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
- 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
- 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
- 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
- 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
- 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
- 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
- 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
- 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
- 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
- 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
- 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
- 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
- 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
- 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
- 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
- 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
- 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
- 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
- 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
- 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
- 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
- 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
- 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
- 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
- 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
- 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
- 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
- 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
- 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
- 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
- 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
- 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
- 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
- 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
- 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
- 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
- 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
- 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
- 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
- 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
- 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
- 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
- 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L,
+uint32_t sctp_crc_c[256] = {
+ 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
+ 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
+ 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
+ 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
+ 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
+ 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
+ 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
+ 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
+ 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
+ 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
+ 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
+ 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
+ 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
+ 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
+ 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
+ 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
+ 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
+ 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
+ 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
+ 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
+ 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
+ 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
+ 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
+ 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
+ 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
+ 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
+ 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
+ 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
+ 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
+ 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
+ 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
+ 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
+ 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
+ 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
+ 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
+ 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
+ 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
+ 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
+ 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
+ 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
+ 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
+ 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
+ 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
+ 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
+ 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
+ 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
+ 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
+ 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
+ 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
+ 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
+ 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
+ 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
+ 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
+ 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
+ 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
+ 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
+ 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
+ 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
+ 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
+ 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
+ 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
+ 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
+ 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
+ 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351,
};
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
index 935ecf1..232362a 100644
--- a/sys/netinet/sctp_indata.c
+++ b/sys/netinet/sctp_indata.c
@@ -1698,7 +1698,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
}
the_len = (chk_length - sizeof(struct sctp_data_chunk));
if (last_chunk == 0) {
- dmbuf = sctp_m_copym(*m,
+ dmbuf = SCTP_M_COPYM(*m,
(offset + sizeof(struct sctp_data_chunk)),
the_len, M_DONTWAIT);
#ifdef SCTP_MBUF_LOGGING
@@ -2561,7 +2561,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
* to a smaller mbuf and free up the cluster mbuf. This will help
* with cluster starvation.
*/
- if (SCTP_BUF_LEN(m) < (long)MHLEN && SCTP_BUF_NEXT(m) == NULL) {
+ if (SCTP_BUF_LEN(m) < (long)MLEN && SCTP_BUF_NEXT(m) == NULL) {
/* we only handle mbufs that are singletons.. not chains */
m = sctp_get_mbuf_for_msg(SCTP_BUF_LEN(m), 0, M_DONTWAIT, 1, MT_DATA);
if (m) {
@@ -2720,7 +2720,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
phd->param_length =
htons(chk_length + sizeof(*phd));
SCTP_BUF_LEN(mm) = sizeof(*phd);
- SCTP_BUF_NEXT(mm) = sctp_m_copym(m, *offset,
+ SCTP_BUF_NEXT(mm) = SCTP_M_COPYM(m, *offset,
SCTP_SIZE32(chk_length),
M_DONTWAIT);
if (SCTP_BUF_NEXT(mm)) {
diff --git a/sys/netinet/sctp_indata.h b/sys/netinet/sctp_indata.h
index 9de4694..0dc0ae4 100644
--- a/sys/netinet/sctp_indata.h
+++ b/sys/netinet/sctp_indata.h
@@ -54,24 +54,28 @@ sctp_build_readq_entry(struct sctp_tcb *stcb,
#define sctp_build_readq_entry_mac(_ctl, in_it, a, net, tsn, ppid, context, stream_no, stream_seq, flags, dm) do { \
if (_ctl) { \
- (_ctl)->sinfo_context = a; \
- (_ctl)->stcb = (in_it); \
- (_ctl)->sinfo_assoc_id = sctp_get_associd((in_it)); \
- (_ctl)->port_from = (in_it)->rport; \
+ atomic_add_int(&((net)->ref_count), 1); \
(_ctl)->sinfo_stream = stream_no; \
(_ctl)->sinfo_ssn = stream_seq; \
(_ctl)->sinfo_flags = (flags << 8); \
(_ctl)->sinfo_ppid = ppid; \
+ (_ctl)->sinfo_context = a; \
(_ctl)->sinfo_timetolive = 0; \
(_ctl)->sinfo_tsn = tsn; \
(_ctl)->sinfo_cumtsn = tsn; \
- (_ctl)->whoFrom = net; \
+ (_ctl)->sinfo_assoc_id = sctp_get_associd((in_it)); \
(_ctl)->length = 0; \
- atomic_add_int(&((net)->ref_count), 1); \
+ (_ctl)->held_length = 0; \
+ (_ctl)->whoFrom = net; \
(_ctl)->data = dm; \
(_ctl)->tail_mbuf = NULL; \
+ (_ctl)->stcb = (in_it); \
+ (_ctl)->port_from = (in_it)->rport; \
+ (_ctl)->spec_flags = 0; \
(_ctl)->do_not_ref_stcb = 0; \
(_ctl)->end_added = 0; \
+ (_ctl)->pdapi_aborted = 0; \
+ (_ctl)->resv = 0; \
} \
} while (0)
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index 8674713..5287423 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -1102,10 +1102,17 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
int init_offset, initack_offset, i;
int retval;
int spec_flag = 0;
+ int how_indx;
/* I know that the TCB is non-NULL from the caller */
asoc = &stcb->asoc;
-
+ for (how_indx = 0; how_indx < sizeof(asoc->cookie_how); i++) {
+ if (asoc->cookie_how[how_indx] == 0)
+ break;
+ }
+ if (how_indx < sizeof(asoc->cookie_how)) {
+ asoc->cookie_how[how_indx] = 1;
+ }
if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) {
/* SHUTDOWN came in after sending INIT-ACK */
struct mbuf *op_err;
@@ -1128,6 +1135,8 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
ph->param_type = htons(SCTP_CAUSE_COOKIE_IN_SHUTDOWN);
ph->param_length = htons(sizeof(struct sctp_paramhdr));
sctp_send_operr_to(m, iphlen, op_err, cookie->peers_vtag);
+ if (how_indx < sizeof(asoc->cookie_how))
+ asoc->cookie_how[how_indx] = 2;
return (NULL);
}
/*
@@ -1170,22 +1179,26 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
* case D in Section 5.2.4 Table 2: MMAA process accordingly
* to get into the OPEN state
*/
+ if (ntohl(initack_cp->init.initial_tsn) != asoc->init_seq_number) {
+ panic("Case D and non-match seq?");
+ }
switch SCTP_GET_STATE
(asoc) {
case SCTP_STATE_COOKIE_WAIT:
+ case SCTP_STATE_COOKIE_ECHOED:
/*
* INIT was sent, but got got a COOKIE_ECHO with the
- * correct tags... just accept it...
+ * correct tags... just accept it...but we must
+ * process the init so that we can make sure we have
+ * the right seq no's.
*/
/* First we must process the INIT !! */
retval = sctp_process_init(init_cp, stcb, net);
if (retval < 0) {
+ if (how_indx < sizeof(asoc->cookie_how))
+ asoc->cookie_how[how_indx] = 3;
return (NULL);
}
- /* intentional fall through to below... */
-
- case SCTP_STATE_COOKIE_ECHOED:
- /* Duplicate INIT case */
/* we have already processed the INIT so no problem */
sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb,
net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_11);
@@ -1246,11 +1259,15 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
if (sctp_load_addresses_from_init(stcb, m, iphlen,
init_offset + sizeof(struct sctp_init_chunk),
initack_offset, sh, init_src)) {
+ if (how_indx < sizeof(asoc->cookie_how))
+ asoc->cookie_how[how_indx] = 4;
return (NULL);
}
/* respond with a COOKIE-ACK */
sctp_toss_old_cookies(stcb, asoc);
sctp_send_cookie_ack(stcb);
+ if (how_indx < sizeof(asoc->cookie_how))
+ asoc->cookie_how[how_indx] = 5;
return (stcb);
} /* end if */
if (ntohl(initack_cp->init.initiate_tag) != asoc->my_vtag &&
@@ -1260,6 +1277,8 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
/*
* case C in Section 5.2.4 Table 2: XMOO silently discard
*/
+ if (how_indx < sizeof(asoc->cookie_how))
+ asoc->cookie_how[how_indx] = 6;
return (NULL);
}
if (ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag &&
@@ -1269,6 +1288,31 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
* case B in Section 5.2.4 Table 2: MXAA or MOAA my info
* should be ok, re-accept peer info
*/
+ if (ntohl(initack_cp->init.initial_tsn) != asoc->init_seq_number) {
+ /*
+ * Extension of case C. If we hit this, then the
+ * random number generator returned the same vtag
+ * when we first sent our INIT-ACK and when we later
+ * sent our INIT. The side with the seq numbers that
+ * are different will be the one that normnally
+ * would have hit case C. This in effect "extends"
+ * our vtags in this collision case to be 64 bits.
+ * The same collision could occur aka you get both
+ * vtag and seq number the same twice in a row.. but
+ * is much less likely. If it did happen then we
+ * would proceed through and bring up the assoc.. we
+ * may end up with the wrong stream setup however..
+ * which would be bad.. but there is no way to
+ * tell.. until we send on a stream that does not
+ * exist :-)
+ */
+ if (how_indx < sizeof(asoc->cookie_how))
+ asoc->cookie_how[how_indx] = 7;
+
+ return (NULL);
+ }
+ if (how_indx < sizeof(asoc->cookie_how))
+ asoc->cookie_how[how_indx] = 8;
sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_13);
sctp_stop_all_cookie_timers(stcb);
/*
@@ -1309,11 +1353,15 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
/* process the INIT info (peer's info) */
retval = sctp_process_init(init_cp, stcb, net);
if (retval < 0) {
+ if (how_indx < sizeof(asoc->cookie_how))
+ asoc->cookie_how[how_indx] = 9;
return (NULL);
}
if (sctp_load_addresses_from_init(stcb, m, iphlen,
init_offset + sizeof(struct sctp_init_chunk),
initack_offset, sh, init_src)) {
+ if (how_indx < sizeof(asoc->cookie_how))
+ asoc->cookie_how[how_indx] = 10;
return (NULL);
}
if ((asoc->state & SCTP_STATE_COOKIE_WAIT) ||
@@ -1350,6 +1398,9 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
*/
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_COOKIE_ACK);
}
+ if (how_indx < sizeof(asoc->cookie_how))
+ asoc->cookie_how[how_indx] = 11;
+
return (stcb);
}
if ((ntohl(initack_cp->init.initiate_tag) != asoc->my_vtag &&
@@ -1363,6 +1414,8 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
* case A in Section 5.2.4 Table 2: XXMM (peer restarted)
*/
/* temp code */
+ if (how_indx < sizeof(asoc->cookie_how))
+ asoc->cookie_how[how_indx] = 12;
sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_14);
sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_15);
@@ -1438,6 +1491,9 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
retval = sctp_process_init(init_cp, stcb, net);
if (retval < 0) {
+ if (how_indx < sizeof(asoc->cookie_how))
+ asoc->cookie_how[how_indx] = 13;
+
return (NULL);
}
/*
@@ -1449,18 +1505,24 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
if (sctp_load_addresses_from_init(stcb, m, iphlen,
init_offset + sizeof(struct sctp_init_chunk),
initack_offset, sh, init_src)) {
+ if (how_indx < sizeof(asoc->cookie_how))
+ asoc->cookie_how[how_indx] = 14;
+
return (NULL);
}
/* respond with a COOKIE-ACK */
sctp_stop_all_cookie_timers(stcb);
sctp_toss_old_cookies(stcb, asoc);
sctp_send_cookie_ack(stcb);
+ if (how_indx < sizeof(asoc->cookie_how))
+ asoc->cookie_how[how_indx] = 15;
return (stcb);
}
/* if we are not a restart we need the assoc_id field pop'd */
asoc->assoc_id = ntohl(initack_cp->init.initiate_tag);
-
+ if (how_indx < sizeof(asoc->cookie_how))
+ asoc->cookie_how[how_indx] = 16;
/* all other cases... */
return (NULL);
}
@@ -3076,6 +3138,7 @@ sctp_handle_stream_reset(struct sctp_tcb *stcb, struct sctp_stream_reset_out_req
chk->asoc = &stcb->asoc;
chk->no_fr_allowed = 0;
chk->book_size = chk->send_size = sizeof(struct sctp_chunkhdr);
+ chk->book_size_scale = 0;
chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA);
if (chk->data == NULL) {
strres_nochunk:
@@ -4266,7 +4329,7 @@ process_control_chunks:
phd->param_type = htons(SCTP_CAUSE_UNRECOG_CHUNK);
phd->param_length = htons(chk_length + sizeof(*phd));
SCTP_BUF_LEN(mm) = sizeof(*phd);
- SCTP_BUF_NEXT(mm) = sctp_m_copym(m, *offset, SCTP_SIZE32(chk_length),
+ SCTP_BUF_NEXT(mm) = SCTP_M_COPYM(m, *offset, SCTP_SIZE32(chk_length),
M_DONTWAIT);
if (SCTP_BUF_NEXT(mm)) {
sctp_queue_op_err(stcb, mm);
@@ -4687,8 +4750,7 @@ sctp_input(i_pak, off)
goto bad;
}
/* validate SCTP checksum */
- if ((sctp_no_csum_on_loopback == 0) ||
- SCTP_IS_IT_LOOPBACK(i_pak)) {
+ if ((sctp_no_csum_on_loopback == 0) || !SCTP_IS_IT_LOOPBACK(i_pak)) {
/*
* we do NOT validate things from the loopback if the sysctl
* is set to 1.
@@ -4740,7 +4802,7 @@ sctp_skip_csum_4:
int x;
x = atomic_fetchadd_int(&sctp_buf_index, 1);
- if (x > 30000) {
+ if (x >= 30000) {
sctp_buf_index = 1;
x = 0;;
}
diff --git a/sys/netinet/sctp_os_bsd.h b/sys/netinet/sctp_os_bsd.h
index d355324..80e2970 100644
--- a/sys/netinet/sctp_os_bsd.h
+++ b/sys/netinet/sctp_os_bsd.h
@@ -82,6 +82,10 @@ typedef struct uma_zone *sctp_zone_t;
/* SCTP_ZONE_FREE: free element from the zone */
#define SCTP_ZONE_FREE(zone, element) \
uma_zfree(zone, element);
+#define SCTP_HASH_INIT(size, hashmark) hashinit_flags(size, M_PCB, hashmark, HASH_NOWAIT)
+#define SCTP_HASH_FREE(table, hashmark) hashdestroy(table, M_PCB, hashmark)
+
+#define SCTP_M_COPYM m_copym
/*
* timers
@@ -92,6 +96,7 @@ typedef struct callout sctp_os_timer_t;
#define SCTP_OS_TIMER_INIT(tmr) callout_init(tmr, 1)
#define SCTP_OS_TIMER_START callout_reset
#define SCTP_OS_TIMER_STOP callout_stop
+#define SCTP_OS_TIMER_STOP_DRAIN callout_drain
#define SCTP_OS_TIMER_PENDING callout_pending
#define SCTP_OS_TIMER_ACTIVE callout_active
#define SCTP_OS_TIMER_DEACTIVATE callout_deactivate
@@ -154,4 +159,8 @@ typedef struct callout sctp_os_timer_t;
#define SCTP_GET_IPV4_LENGTH(iph) (iph->ip_len)
#define SCTP_GET_IPV6_LENGTH(ip6) (ntohs(ip6->ip6_plen))
+/* is the endpoint v6only? */
+#define SCTP_IPV6_V6ONLY(inp) (((struct inpcb *)inp)->inp_flags & IN6P_IPV6_V6ONLY)
+
+
#endif
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index 261b66e..a6c129d 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -2041,7 +2041,6 @@ try_again:
}
-
static struct mbuf *
sctp_add_cookie(struct sctp_inpcb *inp, struct mbuf *init, int init_offset,
struct mbuf *initack, int initack_offset, struct sctp_state_cookie *stc_in)
@@ -2061,12 +2060,12 @@ sctp_add_cookie(struct sctp_inpcb *inp, struct mbuf *init, int init_offset,
if (mret == NULL) {
return (NULL);
}
- copy_init = sctp_m_copym(init, init_offset, M_COPYALL, M_DONTWAIT);
+ copy_init = SCTP_M_COPYM(init, init_offset, M_COPYALL, M_DONTWAIT);
if (copy_init == NULL) {
sctp_m_freem(mret);
return (NULL);
}
- copy_initack = sctp_m_copym(initack, initack_offset, M_COPYALL,
+ copy_initack = SCTP_M_COPYM(initack, initack_offset, M_COPYALL,
M_DONTWAIT);
if (copy_initack == NULL) {
sctp_m_freem(mret);
@@ -3390,9 +3389,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
in_inp = (struct inpcb *)inp;
stc.ipv6_addr_legal = 1;
/* Now look at the binding flag to see if V4 will be legal */
- if (
- (in_inp->inp_flags & IN6P_IPV6_V6ONLY)
- == 0) {
+ if (SCTP_IPV6_V6ONLY(in_inp) == 0) {
stc.ipv4_addr_legal = 1;
} else {
/* V4 addresses are NOT legal on the association */
@@ -3616,16 +3613,20 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
initackm_out->msg.init.initiate_tag = htonl(asoc->my_vtag);
initackm_out->msg.init.initial_tsn = htonl(asoc->init_seq_number);
} else {
+ uint32_t vtag;
+
if (asoc) {
atomic_add_int(&asoc->refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
- initackm_out->msg.init.initiate_tag = htonl(sctp_select_a_tag(inp));
+ vtag = sctp_select_a_tag(inp);
+ initackm_out->msg.init.initiate_tag = htonl(vtag);
/* get a TSN to use too */
initackm_out->msg.init.initial_tsn = htonl(sctp_select_initial_TSN(&inp->sctp_ep));
SCTP_TCB_LOCK(stcb);
atomic_add_int(&asoc->refcnt, -1);
} else {
- initackm_out->msg.init.initiate_tag = htonl(sctp_select_a_tag(inp));
+ vtag = sctp_select_a_tag(inp);
+ initackm_out->msg.init.initiate_tag = htonl(vtag);
/* get a TSN to use too */
initackm_out->msg.init.initial_tsn = htonl(sctp_select_initial_TSN(&inp->sctp_ep));
}
@@ -4321,7 +4322,7 @@ error_out:
return (outchain);
} else {
/* copy the old fashion way */
- appendchain = m_copy(clonechain, 0, M_COPYALL);
+ appendchain = SCTP_M_COPYM(clonechain, 0, M_COPYALL, M_DONTWAIT);
}
}
if (appendchain == NULL) {
@@ -4399,7 +4400,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
return;
}
if ((ca->m) && ca->sndlen) {
- m = m_copym(ca->m, 0, M_COPYALL, M_DONTWAIT);
+ m = SCTP_M_COPYM(ca->m, 0, M_COPYALL, M_DONTWAIT);
if (m == NULL) {
/* can't copy so we are done */
ca->cnt_failed++;
@@ -5030,7 +5031,7 @@ out_gu:
} else {
struct mbuf *m;
- chk->data = m_copym(sp->data, 0, to_move, M_DONTWAIT);
+ chk->data = SCTP_M_COPYM(sp->data, 0, to_move, M_DONTWAIT);
chk->last_mbuf = NULL;
if (chk->data == NULL) {
sp->some_taken = some_taken;
@@ -5104,6 +5105,7 @@ out_gu:
sctp_snd_sb_alloc(stcb, sizeof(struct sctp_data_chunk));
chk->book_size = chk->send_size = (to_move +
sizeof(struct sctp_data_chunk));
+ chk->book_size_scale = 0;
chk->sent = SCTP_DATAGRAM_UNSENT;
/*
@@ -6208,7 +6210,7 @@ sctp_send_cookie_echo(struct mbuf *m,
if ((pad = (plen % 4))) {
plen += 4 - pad;
}
- cookie = sctp_m_copym(m, at, plen, M_DONTWAIT);
+ cookie = SCTP_M_COPYM(m, at, plen, M_DONTWAIT);
if (cookie == NULL) {
/* No memory */
return (-2);
@@ -6269,7 +6271,7 @@ sctp_send_heartbeat_ack(struct sctp_tcb *stcb,
/* must have a net pointer */
return;
- outchain = sctp_m_copym(m, offset, chk_length, M_DONTWAIT);
+ outchain = SCTP_M_COPYM(m, offset, chk_length, M_DONTWAIT);
if (outchain == NULL) {
/* gak out of memory */
return;
@@ -6499,8 +6501,7 @@ sctp_send_asconf_ack(struct sctp_tcb *stcb, uint32_t retrans)
return (-1);
}
/* copy the asconf_ack */
- /* We no longer have pak headers here so m_copy is it */
- m_ack = m_copy(stcb->asoc.last_asconf_ack_sent, 0, M_COPYALL);
+ m_ack = SCTP_M_COPYM(stcb->asoc.last_asconf_ack_sent, 0, M_COPYALL, M_DONTWAIT);
if (m_ack == NULL) {
/* couldn't copy it */
@@ -6566,7 +6567,7 @@ static int
sctp_chunk_retransmission(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
struct sctp_association *asoc,
- int *cnt_out, struct timeval *now, int *now_filled)
+ int *cnt_out, struct timeval *now, int *now_filled, int *fr_done)
{
/*
* send out one MTU of retransmission. If fast_retransmit is
@@ -6769,6 +6770,7 @@ one_chunk_around:
* Mark the destination net to have FR recovery
* limits put on it.
*/
+ *fr_done = 1;
net->fast_retran_ip = 1;
}
@@ -6947,22 +6949,22 @@ one_chunk_around:
if (asoc->sent_queue_retran_cnt < 0) {
asoc->sent_queue_retran_cnt = 0;
}
-#ifdef SCTP_FLIGHT_LOGGING
- sctp_misc_ints(SCTP_FLIGHT_LOG_UP,
- data_list[i]->whoTo->flight_size,
- data_list[i]->book_size,
- (uintptr_t) stcb,
- data_list[i]->rec.data.TSN_seq);
-#endif
- net->flight_size += data_list[i]->book_size;
- asoc->total_flight += data_list[i]->book_size;
if (data_list[i]->book_size_scale) {
/*
* need to double the book size on
* this one
*/
data_list[i]->book_size_scale = 0;
+ /*
+ * Since we double the booksize, we
+ * must also double the output queue
+ * size, since this get shrunk when
+ * we free by this amount.
+ */
+ atomic_add_int(&((asoc)->total_output_queue_size), data_list[i]->book_size);
data_list[i]->book_size *= 2;
+
+
} else {
sctp_ucount_incr(asoc->total_flight_count);
#ifdef SCTP_LOG_RWND
@@ -6973,6 +6975,15 @@ one_chunk_around:
(uint32_t) (data_list[i]->send_size +
sctp_peer_chunk_oh));
}
+#ifdef SCTP_FLIGHT_LOGGING
+ sctp_misc_ints(SCTP_FLIGHT_LOG_UP,
+ data_list[i]->whoTo->flight_size,
+ data_list[i]->book_size,
+ (uintptr_t) stcb,
+ data_list[i]->rec.data.TSN_seq);
+#endif
+ net->flight_size += data_list[i]->book_size;
+ asoc->total_flight += data_list[i]->book_size;
if (asoc->peers_rwnd < stcb->sctp_ep->sctp_ep.sctp_sws_sender) {
/* SWS sender side engages */
asoc->peers_rwnd = 0;
@@ -7074,6 +7085,7 @@ sctp_chunk_output(struct sctp_inpcb *inp,
int nagle_on = 0;
int frag_point = sctp_get_frag_point(stcb, &stcb->asoc);
int un_sent = 0;
+ int fr_done, tot_frs = 0;
asoc = &stcb->asoc;
if (from_where == SCTP_OUTPUT_FROM_USR_SEND) {
@@ -7118,7 +7130,11 @@ sctp_chunk_output(struct sctp_inpcb *inp,
return (0);
} else if (from_where != SCTP_OUTPUT_FROM_HB_TMR) {
/* if its not from a HB then do it */
- ret = sctp_chunk_retransmission(inp, stcb, asoc, &num_out, &now, &now_filled);
+ fr_done = 0;
+ ret = sctp_chunk_retransmission(inp, stcb, asoc, &num_out, &now, &now_filled, &fr_done);
+ if (fr_done) {
+ tot_frs++;
+ }
} else {
/*
* its from any other place, we don't allow retran
@@ -7161,7 +7177,12 @@ sctp_chunk_output(struct sctp_inpcb *inp,
&now, &now_filled, frag_point);
return (ret);
}
+ if (tot_frs > asoc->max_burst) {
+ /* Hit FR burst limit */
+ return (0);
+ }
if ((num_out == 0) && (ret == 0)) {
+
/* No more retrans to send */
break;
}
@@ -8300,6 +8321,7 @@ jump_out:
}
chk->book_size = SCTP_SIZE32((chk->send_size + sizeof(struct sctp_pktdrop_chunk) +
sizeof(struct sctphdr) + SCTP_MED_OVERHEAD));
+ chk->book_size_scale = 0;
if (chk->book_size > small_one) {
drp->ch.chunk_flags = SCTP_PACKET_TRUNCATED;
drp->trunc_len = htons(chk->send_size);
@@ -8443,6 +8465,7 @@ sctp_add_stream_reset_out(struct sctp_tmit_chunk *chk,
/* now fix the chunk length */
ch->chunk_length = htons(len + old_len);
chk->book_size = len + old_len;
+ chk->book_size_scale = 0;
chk->send_size = SCTP_SIZE32(chk->book_size);
SCTP_BUF_LEN(chk->data) = chk->send_size;
return;
@@ -8486,6 +8509,7 @@ sctp_add_stream_reset_in(struct sctp_tmit_chunk *chk,
/* now fix the chunk length */
ch->chunk_length = htons(len + old_len);
chk->book_size = len + old_len;
+ chk->book_size_scale = 0;
chk->send_size = SCTP_SIZE32(chk->book_size);
SCTP_BUF_LEN(chk->data) = chk->send_size;
return;
@@ -8517,6 +8541,7 @@ sctp_add_stream_reset_tsn(struct sctp_tmit_chunk *chk,
ch->chunk_length = htons(len + old_len);
chk->send_size = len + old_len;
chk->book_size = SCTP_SIZE32(chk->send_size);
+ chk->book_size_scale = 0;
SCTP_BUF_LEN(chk->data) = SCTP_SIZE32(chk->send_size);
return;
}
@@ -8546,6 +8571,7 @@ sctp_add_stream_reset_result(struct sctp_tmit_chunk *chk,
/* now fix the chunk length */
ch->chunk_length = htons(len + old_len);
chk->book_size = len + old_len;
+ chk->book_size_scale = 0;
chk->send_size = SCTP_SIZE32(chk->book_size);
SCTP_BUF_LEN(chk->data) = chk->send_size;
return;
@@ -8582,6 +8608,7 @@ sctp_add_stream_reset_result_tsn(struct sctp_tmit_chunk *chk,
ch->chunk_length = htons(len + old_len);
chk->book_size = len + old_len;
chk->send_size = SCTP_SIZE32(chk->book_size);
+ chk->book_size_scale = 0;
SCTP_BUF_LEN(chk->data) = chk->send_size;
return;
}
@@ -8625,6 +8652,7 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb,
chk->asoc = &stcb->asoc;
chk->book_size = sizeof(struct sctp_chunkhdr);
chk->send_size = SCTP_SIZE32(chk->book_size);
+ chk->book_size_scale = 0;
chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA);
if (chk->data == NULL) {
@@ -9278,6 +9306,11 @@ sctp_lower_sosend(struct socket *so,
goto out_unlocked;
}
if ((use_rcvinfo) && srcv) {
+ if (INVALID_SINFO_FLAG(srcv->sinfo_flags) || PR_SCTP_INVALID_POLICY(srcv->sinfo_flags)) {
+ error = EINVAL;
+ splx(s);
+ goto out_unlocked;
+ }
if (srcv->sinfo_flags)
SCTP_STAT_INCR(sctps_sends_with_flags);
@@ -9383,8 +9416,13 @@ sctp_lower_sosend(struct socket *so,
* process
*/
if ((use_rcvinfo) && (srcv) &&
- (srcv->sinfo_flags & SCTP_ABORT)) {
- /* User asks to abort a non-existant asoc */
+ ((srcv->sinfo_flags & SCTP_ABORT) ||
+ ((srcv->sinfo_flags & SCTP_EOF) &&
+ (uio->uio_resid == 0)))) {
+ /*
+ * User asks to abort a non-existant assoc,
+ * or EOF a non-existant assoc with no data
+ */
error = ENOENT;
splx(s);
goto out_unlocked;
@@ -10230,7 +10268,11 @@ skip_out_eof:
queue_only = 0;
} else {
sctp_send_initiate(inp, stcb);
- stcb->asoc.state = SCTP_STATE_COOKIE_WAIT;
+ if (stcb->asoc.state & SCTP_STATE_SHUTDOWN_PENDING)
+ stcb->asoc.state = SCTP_STATE_COOKIE_WAIT |
+ SCTP_STATE_SHUTDOWN_PENDING;
+ else
+ stcb->asoc.state = SCTP_STATE_COOKIE_WAIT;
queue_only_for_init = 0;
queue_only = 1;
}
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index 67b5189..b9934b6 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -32,7 +32,6 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-
#include "opt_ipsec.h"
#include "opt_compat.h"
#include "opt_inet6.h"
@@ -671,8 +670,7 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head,
/* got it */
if ((nam->sa_family == AF_INET) &&
(inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
- (((struct inpcb *)inp)->inp_flags & IN6P_IPV6_V6ONLY)
- ) {
+ SCTP_IPV6_V6ONLY(inp)) {
/* IPv4 on a IPv6 socket with ONLY IPv6 set */
SCTP_INP_RUNLOCK(inp);
continue;
@@ -1431,8 +1429,7 @@ sctp_inpcb_alloc(struct socket *so)
SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_ep, inp);
return (EOPNOTSUPP);
}
- inp->sctp_tcbhash = hashinit(sctp_pcbtblsize,
- M_PCB,
+ inp->sctp_tcbhash = SCTP_HASH_INIT(sctp_pcbtblsize,
&inp->sctp_hashmark);
if (inp->sctp_tcbhash == NULL) {
printf("Out of SCTP-INPCB->hashinit - no resources\n");
@@ -1592,7 +1589,7 @@ sctp_move_pcb_and_assoc(struct sctp_inpcb *old_inp, struct sctp_inpcb *new_inp,
SCTP_INP_INFO_WUNLOCK();
if (new_inp->sctp_tcbhash != NULL) {
- SCTP_FREE(new_inp->sctp_tcbhash);
+ SCTP_HASH_FREE(new_inp->sctp_tcbhash, new_inp->sctp_hashmark);
new_inp->sctp_tcbhash = NULL;
}
if ((new_inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
@@ -1660,8 +1657,7 @@ sctp_isport_inuse(struct sctp_inpcb *inp, uint16_t lport)
/* This one is in use. */
/* check the v6/v4 binding issue */
if ((t_inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
- (((struct inpcb *)t_inp)->inp_flags & IN6P_IPV6_V6ONLY)
- ) {
+ SCTP_IPV6_V6ONLY(t_inp)) {
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
/* collision in V6 space */
return (1);
@@ -1675,8 +1671,7 @@ sctp_isport_inuse(struct sctp_inpcb *inp, uint16_t lport)
} else {
/* t_inp is bound only V4 */
if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
- (((struct inpcb *)inp)->inp_flags & IN6P_IPV6_V6ONLY)
- ) {
+ SCTP_IPV6_V6ONLY(t_inp)) {
/* no conflict */
continue;
}
@@ -1724,9 +1719,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
struct sockaddr_in *sin;
/* IPV6_V6ONLY socket? */
- if (
- (ip_inp->inp_flags & IN6P_IPV6_V6ONLY)
- ) {
+ if (SCTP_IPV6_V6ONLY(ip_inp)) {
return (EINVAL);
}
if (addr->sa_len != sizeof(*sin))
@@ -2460,8 +2453,8 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
#endif
/* Now lets see about freeing the EP hash table. */
if (inp->sctp_tcbhash != NULL) {
- SCTP_FREE(inp->sctp_tcbhash);
- inp->sctp_tcbhash = 0;
+ SCTP_HASH_FREE(inp->sctp_tcbhash, inp->sctp_hashmark);
+ inp->sctp_tcbhash = NULL;
}
/* Now we must put the ep memory back into the zone pool */
SCTP_INP_LOCK_DESTROY(inp);
@@ -3116,8 +3109,8 @@ sctp_del_remote_addr(struct sctp_tcb *stcb, struct sockaddr *remaddr)
}
-static void
-sctp_add_vtag_to_timewait(struct sctp_inpcb *inp, uint32_t tag)
+void
+sctp_add_vtag_to_timewait(struct sctp_inpcb *inp, uint32_t tag, uint32_t time)
{
struct sctpvtaghead *chain;
struct sctp_tagblock *twait_block;
@@ -3134,7 +3127,7 @@ sctp_add_vtag_to_timewait(struct sctp_inpcb *inp, uint32_t tag)
if ((twait_block->vtag_block[i].v_tag == 0) &&
!set) {
twait_block->vtag_block[i].tv_sec_at_expire =
- now.tv_sec + SCTP_TIME_WAIT;
+ now.tv_sec + time;
twait_block->vtag_block[i].v_tag = tag;
set = 1;
} else if ((twait_block->vtag_block[i].v_tag) &&
@@ -3167,7 +3160,7 @@ sctp_add_vtag_to_timewait(struct sctp_inpcb *inp, uint32_t tag)
if (twait_block == NULL) {
return;
}
- memset(twait_block, 0, sizeof(struct sctp_timewait));
+ memset(twait_block, 0, sizeof(struct sctp_tagblock));
LIST_INSERT_HEAD(chain, twait_block, sctp_nxt_tagblock);
twait_block->vtag_block[0].tv_sec_at_expire = now.tv_sec +
SCTP_TIME_WAIT;
@@ -3419,32 +3412,15 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
}
}
- /* Stop any timer someone may have started */
- SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer);
/*
* Make it invalid too, that way if its about to run it will abort
* and return.
*/
- asoc->strreset_timer.type = SCTP_TIMER_TYPE_NONE;
sctp_iterator_asoc_being_freed(inp, stcb);
/* re-increment the lock */
if (from_inpcbfree == SCTP_NORMAL_PROC) {
atomic_add_int(&stcb->asoc.refcnt, -1);
}
- /* now restop the timers to be sure - this is paranoia at is finest! */
- SCTP_OS_TIMER_STOP(&asoc->hb_timer.timer);
- SCTP_OS_TIMER_STOP(&asoc->dack_timer.timer);
- SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer);
- SCTP_OS_TIMER_STOP(&asoc->asconf_timer.timer);
- SCTP_OS_TIMER_STOP(&asoc->shut_guard_timer.timer);
- SCTP_OS_TIMER_STOP(&asoc->autoclose_timer.timer);
- SCTP_OS_TIMER_STOP(&asoc->delayed_event_timer.timer);
-
- TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
- SCTP_OS_TIMER_STOP(&net->fr_timer.timer);
- SCTP_OS_TIMER_STOP(&net->rxt_timer.timer);
- SCTP_OS_TIMER_STOP(&net->pmtu_timer.timer);
- }
asoc->state = 0;
if (inp->sctp_tcbhash) {
LIST_REMOVE(stcb, sctp_tcbhash);
@@ -3461,8 +3437,28 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
/* pull from vtag hash */
LIST_REMOVE(stcb, sctp_asocs);
- sctp_add_vtag_to_timewait(inp, asoc->my_vtag);
+ sctp_add_vtag_to_timewait(inp, asoc->my_vtag, SCTP_TIME_WAIT);
+
+
+ /*
+ * Now restop the timers to be sure - this is paranoia at is finest!
+ */
+ SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer);
+ SCTP_OS_TIMER_STOP(&asoc->hb_timer.timer);
+ SCTP_OS_TIMER_STOP(&asoc->dack_timer.timer);
+ SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer);
+ SCTP_OS_TIMER_STOP(&asoc->asconf_timer.timer);
+ SCTP_OS_TIMER_STOP(&asoc->shut_guard_timer.timer);
+ SCTP_OS_TIMER_STOP(&asoc->autoclose_timer.timer);
+ SCTP_OS_TIMER_STOP(&asoc->delayed_event_timer.timer);
+ TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
+ SCTP_OS_TIMER_STOP(&net->fr_timer.timer);
+ SCTP_OS_TIMER_STOP(&net->rxt_timer.timer);
+ SCTP_OS_TIMER_STOP(&net->pmtu_timer.timer);
+ }
+
+ asoc->strreset_timer.type = SCTP_TIMER_TYPE_NONE;
prev = NULL;
/*
* The chunk lists and such SHOULD be empty but we check them just
@@ -4224,26 +4220,16 @@ sctp_pcb_init()
TUNABLE_INT_FETCH("net.inet.sctp.tcbhashsize", &sctp_hashtblsize);
TUNABLE_INT_FETCH("net.inet.sctp.pcbhashsize", &sctp_pcbtblsize);
TUNABLE_INT_FETCH("net.inet.sctp.chunkscale", &sctp_chunkscale);
-
- sctppcbinfo.sctp_asochash = hashinit((sctp_hashtblsize * 31),
- M_PCB,
+ sctppcbinfo.sctp_asochash = SCTP_HASH_INIT((sctp_hashtblsize * 31),
&sctppcbinfo.hashasocmark);
-
- sctppcbinfo.sctp_ephash = hashinit(sctp_hashtblsize,
- M_PCB,
+ sctppcbinfo.sctp_ephash = SCTP_HASH_INIT(sctp_hashtblsize,
&sctppcbinfo.hashmark);
-
- sctppcbinfo.sctp_tcpephash = hashinit(sctp_hashtblsize,
- M_PCB,
+ sctppcbinfo.sctp_tcpephash = SCTP_HASH_INIT(sctp_hashtblsize,
&sctppcbinfo.hashtcpmark);
-
sctppcbinfo.hashtblsize = sctp_hashtblsize;
- /*
- * init the small hash table we use to track restarted asoc's
- */
- sctppcbinfo.sctp_restarthash = hashinit(SCTP_STACK_VTAG_HASH_SIZE,
- M_PCB,
+ /* init the small hash table we use to track restarted asoc's */
+ sctppcbinfo.sctp_restarthash = SCTP_HASH_INIT(SCTP_STACK_VTAG_HASH_SIZE,
&sctppcbinfo.hashrestartmark);
/* init the zones */
@@ -4308,8 +4294,6 @@ sctp_pcb_init()
SCTP_OS_TIMER_INIT(&sctppcbinfo.addr_wq_timer.timer);
- /* port stuff */
- sctppcbinfo.lastlow = ipport_firstauto;
/* Init the TIMEWAIT list */
for (i = 0; i < SCTP_STACK_VTAG_HASH_SIZE; i++) {
LIST_INIT(&sctppcbinfo.vtag_timewait[i]);
diff --git a/sys/netinet/sctp_pcb.h b/sys/netinet/sctp_pcb.h
index d421c36..d64d97a 100644
--- a/sys/netinet/sctp_pcb.h
+++ b/sys/netinet/sctp_pcb.h
@@ -225,14 +225,8 @@ struct sctp_epinfo {
struct sctpvtaghead vtag_timewait[SCTP_STACK_VTAG_HASH_SIZE];
-
struct sctp_timer addr_wq_timer;
- /* for port allocations */
- uint16_t lastport;
- uint16_t lastlow;
- uint16_t lasthi;
-
};
extern struct sctpstat sctpstat;
@@ -463,6 +457,9 @@ sctp_aloc_assoc(struct sctp_inpcb *, struct sockaddr *,
int sctp_free_assoc(struct sctp_inpcb *, struct sctp_tcb *, int, int);
+void
+ sctp_add_vtag_to_timewait(struct sctp_inpcb *, uint32_t, uint32_t);
+
int sctp_add_local_addr_ep(struct sctp_inpcb *, struct ifaddr *);
int sctp_insert_laddr(struct sctpladdr *, struct ifaddr *);
diff --git a/sys/netinet/sctp_structs.h b/sys/netinet/sctp_structs.h
index 35f7f7f..8f53fce 100644
--- a/sys/netinet/sctp_structs.h
+++ b/sys/netinet/sctp_structs.h
@@ -881,6 +881,7 @@ struct sctp_association {
uint8_t cmt_dac_pkts_rcvd;
uint8_t sctp_cmt_on_off;
uint8_t iam_blocking;
+ uint8_t cookie_how[8];
/*
* The mapping array is used to track out of order sequences above
* last_acked_seq. 0 indicates packet missing 1 indicates packet
diff --git a/sys/netinet/sctp_uio.h b/sys/netinet/sctp_uio.h
index f12f0b9..342f02f 100644
--- a/sys/netinet/sctp_uio.h
+++ b/sys/netinet/sctp_uio.h
@@ -136,6 +136,9 @@ struct sctp_snd_all_completes {
#define SCTP_ADDR_OVER 0x0800/* Override the primary-address */
#define SCTP_SENDALL 0x1000/* Send this on all associations */
#define SCTP_EOR 0x2000/* end of message signal */
+#define INVALID_SINFO_FLAG(x) (((x) & 0xffffff00 \
+ & ~(SCTP_EOF | SCTP_ABORT | SCTP_UNORDERED |\
+ SCTP_ADDR_OVER | SCTP_SENDALL | SCTP_EOR)) != 0)
/* for the endpoint */
/* The lower byte is an enumeration of PR-SCTP policies */
@@ -143,12 +146,12 @@ struct sctp_snd_all_completes {
#define SCTP_PR_SCTP_BUF 0x0002/* Buffer based PR-SCTP */
#define SCTP_PR_SCTP_RTX 0x0003/* Number of retransmissions based PR-SCTP */
-#define PR_SCTP_POLICY(x) ((x) & 0xff)
-#define PR_SCTP_ENABLED(x) (PR_SCTP_POLICY(x) != 0)
-#define PR_SCTP_TTL_ENABLED(x) (PR_SCTP_POLICY(x) == SCTP_PR_SCTP_TTL)
-#define PR_SCTP_BUF_ENABLED(x) (PR_SCTP_POLICY(x) == SCTP_PR_SCTP_BUF)
-#define PR_SCTP_RTX_ENABLED(x) (PR_SCTP_POLICY(x) == SCTP_PR_SCTP_RTX)
-
+#define PR_SCTP_POLICY(x) ((x) & 0xff)
+#define PR_SCTP_ENABLED(x) (PR_SCTP_POLICY(x) != 0)
+#define PR_SCTP_TTL_ENABLED(x) (PR_SCTP_POLICY(x) == SCTP_PR_SCTP_TTL)
+#define PR_SCTP_BUF_ENABLED(x) (PR_SCTP_POLICY(x) == SCTP_PR_SCTP_BUF)
+#define PR_SCTP_RTX_ENABLED(x) (PR_SCTP_POLICY(x) == SCTP_PR_SCTP_RTX)
+#define PR_SCTP_INVALID_POLICY(x) (PR_SCTP_POLICY(x) > SCTP_PR_SCTP_RTX)
/* Stat's */
struct sctp_pcbinfo {
uint32_t ep_count;
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index 79a62a0..c60f4e9 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -203,6 +203,25 @@ sctp_init(void)
}
+
+/*
+ * cleanup of the sctppcbinfo structure.
+ * Assumes that the sctppcbinfo lock is held.
+ */
+void
+sctp_pcbinfo_cleanup(void)
+{
+ /* free the hash tables */
+ if (sctppcbinfo.sctp_asochash != NULL)
+ SCTP_HASH_FREE(sctppcbinfo.sctp_asochash, sctppcbinfo.hashasocmark);
+ if (sctppcbinfo.sctp_ephash != NULL)
+ SCTP_HASH_FREE(sctppcbinfo.sctp_ephash, sctppcbinfo.hashmark);
+ if (sctppcbinfo.sctp_tcpephash != NULL)
+ SCTP_HASH_FREE(sctppcbinfo.sctp_tcpephash, sctppcbinfo.hashtcpmark);
+ if (sctppcbinfo.sctp_restarthash != NULL)
+ SCTP_HASH_FREE(sctppcbinfo.sctp_restarthash, sctppcbinfo.hashrestartmark);
+}
+
#ifdef INET6
void
ip_2_ip6_hdr(struct ip6_hdr *ip6, struct ip *ip)
@@ -1563,9 +1582,7 @@ sctp_fill_up_addresses(struct sctp_inpcb *inp,
ipv4_addr_legal = ipv6_addr_legal = 0;
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
ipv6_addr_legal = 1;
- if (
- (((struct in6pcb *)inp)->inp_flags & IN6P_IPV6_V6ONLY)
- == 0) {
+ if (SCTP_IPV6_V6ONLY(inp) == 0) {
ipv4_addr_legal = 1;
}
} else {
@@ -1881,9 +1898,7 @@ sctp_do_connect_x(struct socket *so,
struct in6pcb *inp6;
inp6 = (struct in6pcb *)inp;
- if (
- (inp6->inp_flags & IN6P_IPV6_V6ONLY)
- ) {
+ if (SCTP_IPV6_V6ONLY(inp6)) {
/*
* if IPV6_V6ONLY flag, ignore connections destined
* to a v4 addr or v4-mapped addr
@@ -3845,9 +3860,6 @@ sctp_optsset(struct socket *so,
}
SCTP_INP_WLOCK(inp);
inp->sctp_frag_point = (*segsize + ovh);
- if (inp->sctp_frag_point < MHLEN) {
- inp->sctp_frag_point = MHLEN;
- }
SCTP_INP_WUNLOCK(inp);
}
break;
diff --git a/sys/netinet/sctp_var.h b/sys/netinet/sctp_var.h
index 2293cb5..b2daa85 100644
--- a/sys/netinet/sctp_var.h
+++ b/sys/netinet/sctp_var.h
@@ -436,6 +436,9 @@ void sctp_input __P((struct mbuf *, int));
void sctp_drain __P((void));
void sctp_init __P((void));
+
+void sctp_pcbinfo_cleanup(void);
+
int sctp_shutdown __P((struct socket *));
void sctp_notify
__P((struct sctp_inpcb *, int, struct sctphdr *,
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index 6882cee..6867347 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -1080,14 +1080,11 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_association *asoc,
if (m->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
struct in6pcb *inp6;
-
/* Its a V6 socket */
inp6 = (struct in6pcb *)m;
asoc->ipv6_addr_legal = 1;
/* Now look at the binding flag to see if V4 will be legal */
- if (
- (inp6->inp_flags & IN6P_IPV6_V6ONLY)
- == 0) {
+ if (SCTP_IPV6_V6ONLY(inp6) == 0) {
asoc->ipv4_addr_legal = 1;
} else {
/* V4 addresses are NOT legal on the association */
@@ -1099,7 +1096,6 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_association *asoc,
asoc->ipv6_addr_legal = 0;
}
-
asoc->my_rwnd = max(m->sctp_socket->so_rcv.sb_hiwat, SCTP_MINIMAL_RWND);
asoc->peers_rwnd = m->sctp_socket->so_rcv.sb_hiwat;
@@ -1326,15 +1322,28 @@ sctp_timeout_handler(void *t)
return;
}
tmr->stopped_from = 0xa006;
- /* record in stopped what t-o occured */
- tmr->stopped_from = tmr->type;
if (stcb) {
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_LOCK(stcb);
atomic_add_int(&stcb->asoc.refcnt, -1);
}
+ /* record in stopped what t-o occured */
+ tmr->stopped_from = tmr->type;
+
/* mark as being serviced now */
+ if (SCTP_OS_TIMER_PENDING(&tmr->timer)) {
+ /*
+ * Callout has been rescheduled.
+ */
+ goto get_out;
+ }
+ if (!SCTP_OS_TIMER_ACTIVE(&tmr->timer)) {
+ /*
+ * Not active, so no action.
+ */
+ goto get_out;
+ }
SCTP_OS_TIMER_DEACTIVATE(&tmr->timer);
/* call the handler for the appropriate timer type */
@@ -1575,6 +1584,7 @@ sctp_timeout_handler(void *t)
*/
sctp_fix_ecn_echo(&stcb->asoc);
}
+get_out:
if (stcb) {
SCTP_TCB_UNLOCK(stcb);
}
@@ -2299,7 +2309,7 @@ sctp_calculate_sum(struct mbuf *m, int32_t * pktlen, uint32_t offset)
void
sctp_mtu_size_reset(struct sctp_inpcb *inp,
- struct sctp_association *asoc, u_long mtu)
+ struct sctp_association *asoc, uint32_t mtu)
{
/*
* Reset the P-MTU size on this association, this involves changing
@@ -2450,7 +2460,6 @@ sctp_calculate_rto(struct sctp_tcb *stcb,
return ((uint32_t) new_rto);
}
-
/*
* return a pointer to a contiguous piece of data from the given mbuf chain
* starting at 'off' for 'len' bytes. If the desired piece spans more than
@@ -2498,6 +2507,7 @@ sctp_m_getptr(struct mbuf *m, int off, int len, uint8_t * in_ptr)
}
+
struct sctp_paramhdr *
sctp_get_next_param(struct mbuf *m,
int offset,
@@ -2602,9 +2612,10 @@ sctp_notify_assoc_change(uint32_t event, struct sctp_tcb *stcb,
if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
(event == SCTP_COMM_LOST)) {
- if (TAILQ_EMPTY(&stcb->sctp_ep->read_queue)) {
+ if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT)
+ stcb->sctp_socket->so_error = ECONNREFUSED;
+ else
stcb->sctp_socket->so_error = ECONNRESET;
- }
/* Wake ANY sleepers */
sorwakeup(stcb->sctp_socket);
sowwakeup(stcb->sctp_socket);
@@ -3644,19 +3655,6 @@ sctp_print_address_pkt(struct ip *iph, struct sctphdr *sh)
}
}
-#if defined(HAVE_SCTP_SO_LASTRECORD)
-
-/* cloned from uipc_socket.c */
-
-#define SCTP_SBLINKRECORD(sb, m0) do { \
- if ((sb)->sb_lastrecord != NULL) \
- SCTP_BUF_NEXT_PKT((sb)->sb_lastrecord) = (m0); \
- else \
- (sb)->sb_mb = (m0); \
- (sb)->sb_lastrecord = (m0); \
-} while (/*CONSTCOND*/0)
-#endif
-
void
sctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp,
struct sctp_inpcb *new_inp,
@@ -3980,7 +3978,7 @@ sctp_free_bufspace(struct sctp_tcb *stcb, struct sctp_association *asoc,
0,
tp1->mbcnt);
if (asoc->total_output_queue_size >= tp1->book_size) {
- asoc->total_output_queue_size -= tp1->book_size;
+ atomic_add_int(&asoc->total_output_queue_size, -tp1->book_size);
} else {
asoc->total_output_queue_size = 0;
}
@@ -4325,9 +4323,11 @@ restart_nosblocks:
(inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) {
goto out;
}
- if (so->so_error || so->so_rcv.sb_state & SBS_CANTRCVMORE) {
+ if (so->so_rcv.sb_state & SBS_CANTRCVMORE) {
if (so->so_error) {
error = so->so_error;
+ if ((in_flags & MSG_PEEK) == 0)
+ so->so_error = 0;
} else {
error = ENOTCONN;
}
@@ -4387,7 +4387,54 @@ restart_nosblocks:
held_length = 0;
goto restart_nosblocks;
} else if (so->so_rcv.sb_cc == 0) {
- error = EWOULDBLOCK;
+ if (so->so_error) {
+ error = so->so_error;
+ if ((in_flags & MSG_PEEK) == 0)
+ so->so_error = 0;
+ } else {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0) {
+ /*
+ * For active open side clear flags
+ * for re-use passive open is
+ * blocked by connect.
+ */
+ if (inp->sctp_flags & SCTP_PCB_FLAGS_WAS_ABORTED) {
+ /*
+ * You were aborted, passive
+ * side always hits here
+ */
+ error = ECONNRESET;
+ /*
+ * You get this once if you
+ * are active open side
+ */
+ if (!(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
+ /*
+ * Remove flag if on
+ * the active open
+ * side
+ */
+ inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAS_ABORTED;
+ }
+ }
+ so->so_state &= ~(SS_ISCONNECTING |
+ SS_ISDISCONNECTING |
+ SS_ISCONFIRMING |
+ SS_ISCONNECTED);
+ if (error == 0) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) == 0) {
+ error = ENOTCONN;
+ } else {
+ inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAS_CONNECTED;
+ }
+ }
+ goto out;
+ }
+ }
+ error = EWOULDBLOCK;
+ }
goto out;
}
error = sblock(&so->so_rcv, (block_allowed ? M_WAITOK : 0));
@@ -4906,7 +4953,7 @@ get_more_data:
sctp_user_rcvd(stcb, &freed_so_far, hold_rlock, rwnd_req);
}
wait_some_more:
- if (so->so_error || so->so_rcv.sb_state & SBS_CANTRCVMORE) {
+ if (so->so_rcv.sb_state & SBS_CANTRCVMORE) {
goto release;
}
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)
@@ -5034,7 +5081,7 @@ get_more_data2:
goto release;
}
wait_some_more2:
- if (so->so_error || so->so_rcv.sb_state & SBS_CANTRCVMORE)
+ if (so->so_rcv.sb_state & SBS_CANTRCVMORE)
goto release;
if (hold_rlock == 1) {
SCTP_INP_READ_UNLOCK(inp);
@@ -5128,7 +5175,7 @@ get_more_data2:
hold_sblock = 0;
}
splx(s);
- *mp = sctp_m_copym(m, 0, cp_len,
+ *mp = SCTP_M_COPYM(m, 0, cp_len,
M_TRYWAIT
);
s = splnet();
diff --git a/sys/netinet/sctputil.h b/sys/netinet/sctputil.h
index dbd9959..e43df07 100644
--- a/sys/netinet/sctputil.h
+++ b/sys/netinet/sctputil.h
@@ -51,8 +51,6 @@ void sctp_m_freem(struct mbuf *m);
#endif
-#define sctp_m_copym m_copym
-
#define sctp_get_associd(stcb) ((sctp_assoc_t)stcb->asoc.assoc_id)
@@ -80,8 +78,7 @@ sctp_timer_stop(int, struct sctp_inpcb *, struct sctp_tcb *,
uint32_t sctp_calculate_sum(struct mbuf *, int32_t *, uint32_t);
void
-sctp_mtu_size_reset(struct sctp_inpcb *, struct sctp_association *,
- u_long);
+ sctp_mtu_size_reset(struct sctp_inpcb *, struct sctp_association *, uint32_t);
void
sctp_add_to_readq(struct sctp_inpcb *inp,
diff --git a/sys/netinet6/sctp6_usrreq.c b/sys/netinet6/sctp6_usrreq.c
index ab1141a..4d16816 100644
--- a/sys/netinet6/sctp6_usrreq.c
+++ b/sys/netinet6/sctp6_usrreq.c
@@ -656,9 +656,7 @@ sctp6_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
inp6 = (struct in6pcb *)inp;
inp6->inp_vflag &= ~INP_IPV4;
inp6->inp_vflag |= INP_IPV6;
- if (addr != NULL &&
- (inp6->inp_flags & IN6P_IPV6_V6ONLY)
- == 0) {
+ if ((addr != NULL) && (SCTP_IPV6_V6ONLY(inp6) == 0)) {
if (addr->sa_family == AF_INET) {
/* binding v4 addr to v6 socket, so reset flags */
inp6->inp_vflag |= INP_IPV4;
@@ -944,10 +942,7 @@ sctp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
}
#ifdef INET
sin6 = (struct sockaddr_in6 *)addr;
- if (
-
- (inp6->inp_flags & IN6P_IPV6_V6ONLY)
- ) {
+ if (SCTP_IPV6_V6ONLY(inp6)) {
/*
* if IPV6_V6ONLY flag, we discard datagrams destined to a
* v4 addr or v4-mapped addr
@@ -1060,9 +1055,7 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
}
#ifdef INET
sin6 = (struct sockaddr_in6 *)addr;
- if (
- (inp6->inp_flags & IN6P_IPV6_V6ONLY)
- ) {
+ if (SCTP_IPV6_V6ONLY(inp6)) {
/*
* if IPV6_V6ONLY flag, ignore connections destined to a v4
* addr or v4-mapped addr
@@ -1325,9 +1318,7 @@ sctp6_in6getaddr(struct socket *so, struct sockaddr **nam)
}
addr = *nam;
/* if I'm V6ONLY, convert it to v4-mapped */
- if (
- (inp6->inp_flags & IN6P_IPV6_V6ONLY)
- ) {
+ if (SCTP_IPV6_V6ONLY(inp6)) {
struct sockaddr_in6 sin6;
in6_sin_2_v4mapsin6((struct sockaddr_in *)addr, &sin6);
@@ -1361,9 +1352,7 @@ sctp6_getpeeraddr(struct socket *so, struct sockaddr **nam)
return (error);
}
/* if I'm V6ONLY, convert it to v4-mapped */
- if (
- (inp6->inp_flags & IN6P_IPV6_V6ONLY)
- ) {
+ if (SCTP_IPV6_V6ONLY(inp6)) {
struct sockaddr_in6 sin6;
in6_sin_2_v4mapsin6((struct sockaddr_in *)addr, &sin6);
OpenPOWER on IntegriCloud