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