- 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
This commit is contained in:
parent
b939bb368a
commit
44b7479ba2
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
||||
|
@ -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)) {
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
|
||||
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_input(i_pak, off)
|
||||
int x;
|
||||
|
||||
x = atomic_fetchadd_int(&sctp_buf_index, 1);
|
||||
if (x > 30000) {
|
||||
if (x >= 30000) {
|
||||
sctp_buf_index = 1;
|
||||
x = 0;;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -2041,7 +2041,6 @@ sctp_get_mbuf_for_msg(unsigned int space_needed, int want_header,
|
||||
}
|
||||
|
||||
|
||||
|
||||
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 @@ sctp_copy_mbufchain(struct mbuf *clonechain,
|
||||
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 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb, struct sctp_nets *net,
|
||||
} 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 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb, struct sctp_nets *net,
|
||||
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 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
|
||||
* Mark the destination net to have FR recovery
|
||||
* limits put on it.
|
||||
*/
|
||||
*fr_done = 1;
|
||||
net->fast_retran_ip = 1;
|
||||
}
|
||||
|
||||
@ -6947,22 +6949,22 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
|
||||
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 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
|
||||
(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 @@ sctp_send_packet_dropped(struct sctp_tcb *stcb, struct sctp_nets *net,
|
||||
}
|
||||
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 @@ sctp_lower_sosend(struct socket *so,
|
||||
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;
|
||||
}
|
||||
|
@ -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]);
|
||||
|
@ -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 *);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 *,
|
||||
|
@ -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 @@ sctp_sorecvmsg(struct socket *so,
|
||||
(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 @@ sctp_sorecvmsg(struct socket *so,
|
||||
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 @@ sctp_sorecvmsg(struct socket *so,
|
||||
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 @@ sctp_sorecvmsg(struct socket *so,
|
||||
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 @@ sctp_sorecvmsg(struct socket *so,
|
||||
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();
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user