- 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:
Randall Stewart 2007-01-15 15:12:10 +00:00
parent b939bb368a
commit 44b7479ba2
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=166023
17 changed files with 397 additions and 243 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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,
};

View File

@ -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)) {

View File

@ -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)

View File

@ -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;;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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]);

View File

@ -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 *);

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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 *,

View File

@ -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();

View File

@ -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,

View File

@ -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);