diff options
-rw-r--r-- | sys/netinet/sctp.h | 15 | ||||
-rw-r--r-- | sys/netinet/sctp_asconf.c | 22 | ||||
-rw-r--r-- | sys/netinet/sctp_auth.c | 21 | ||||
-rw-r--r-- | sys/netinet/sctp_bsd_addr.c | 193 | ||||
-rw-r--r-- | sys/netinet/sctp_bsd_addr.h | 7 | ||||
-rw-r--r-- | sys/netinet/sctp_indata.c | 9 | ||||
-rw-r--r-- | sys/netinet/sctp_input.c | 44 | ||||
-rw-r--r-- | sys/netinet/sctp_lock_bsd.h | 13 | ||||
-rw-r--r-- | sys/netinet/sctp_os_bsd.h | 32 | ||||
-rw-r--r-- | sys/netinet/sctp_output.c | 38 | ||||
-rw-r--r-- | sys/netinet/sctp_pcb.c | 60 | ||||
-rw-r--r-- | sys/netinet/sctp_pcb.h | 1 | ||||
-rw-r--r-- | sys/netinet/sctp_sysctl.c | 1 | ||||
-rw-r--r-- | sys/netinet/sctp_timer.c | 2 | ||||
-rw-r--r-- | sys/netinet/sctp_uio.h | 3 | ||||
-rw-r--r-- | sys/netinet/sctp_usrreq.c | 25 | ||||
-rw-r--r-- | sys/netinet/sctputil.c | 21 | ||||
-rw-r--r-- | sys/netinet6/sctp6_usrreq.c | 4 |
18 files changed, 425 insertions, 86 deletions
diff --git a/sys/netinet/sctp.h b/sys/netinet/sctp.h index f51bf63..5c21aae 100644 --- a/sys/netinet/sctp.h +++ b/sys/netinet/sctp.h @@ -158,6 +158,7 @@ struct sctp_paramhdr { #define SCTP_PCB_STATUS 0x00001104 #define SCTP_GET_NONCE_VALUES 0x00001105 + /* Special hook for dynamically setting primary for all assoc's, * this is a write only option that requires root privledge. */ @@ -196,6 +197,17 @@ struct sctp_paramhdr { #define SCTP_GET_VRF_IDS 0x00003003 #define SCTP_GET_ASOC_VRF 0x00003004 #define SCTP_DEL_VRF_ID 0x00003005 + +/* + * If you enable packet logging you can get + * a poor mans ethereal output in binary + * form. Note this is a compile option to + * the kernel, SCTP_PACKET_LOGGING, and + * without it in your kernel you + * will get a ENOSUPPORT. + */ +#define SCTP_GET_PACKET_LOG 0x00004001 + /* * hidden implementation specific options these are NOT user visible (should * move out of sctp.h) @@ -453,4 +465,7 @@ struct sctp_error_unrecognized_chunk { #include <netinet/sctp_uio.h> +#define SCTP_PACKET_LOG_SIZE 65536 + + #endif /* !_NETINET_SCTP_H_ */ diff --git a/sys/netinet/sctp_asconf.c b/sys/netinet/sctp_asconf.c index 4151524..932ba5a 100644 --- a/sys/netinet/sctp_asconf.c +++ b/sys/netinet/sctp_asconf.c @@ -942,13 +942,13 @@ sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa, uint16_t type sctp_asconf_addr_mgmt_ack(stcb, aa->ifa, type, 1); /* free the entry */ sctp_free_ifa(aa->ifa); - SCTP_FREE(aa); + SCTP_FREE(aa, SCTP_M_ASC_ADDR); return (-1); } } /* for each aa */ /* adding new request to the queue */ - SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), "AsconfAddr"); + SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), SCTP_M_ASC_ADDR); if (aa == NULL) { /* didn't get memory */ SCTPDBG(SCTP_DEBUG_ASCONF1, @@ -988,7 +988,7 @@ sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa, uint16_t type sizeof(struct in_addr)); } else { /* invalid family! */ - SCTP_FREE(aa); + SCTP_FREE(aa, SCTP_M_ASC_ADDR); return (-1); } aa->sent = 0; /* clear sent flag */ @@ -1067,7 +1067,7 @@ sctp_asconf_queue_add_sa(struct sctp_tcb *stcb, struct sockaddr *sa, TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next); /* free the entry */ sctp_free_ifa(aa->ifa); - SCTP_FREE(aa); + SCTP_FREE(aa, SCTP_M_ASC_ADDR); return (-1); } else if (type == SCTP_DEL_IP_ADDRESS && aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS) { @@ -1079,7 +1079,7 @@ sctp_asconf_queue_add_sa(struct sctp_tcb *stcb, struct sockaddr *sa, sctp_asconf_addr_mgmt_ack(stcb, aa->ifa, type, 1); /* free the entry */ sctp_free_ifa(aa->ifa); - SCTP_FREE(aa); + SCTP_FREE(aa, SCTP_M_ASC_ADDR); return (-1); } } /* for each aa */ @@ -1095,7 +1095,7 @@ sctp_asconf_queue_add_sa(struct sctp_tcb *stcb, struct sockaddr *sa, return (-1); } /* adding new request to the queue */ - SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), "AsconfAddr"); + SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), SCTP_M_ASC_ADDR); if (aa == NULL) { /* didn't get memory */ SCTPDBG(SCTP_DEBUG_ASCONF1, @@ -1129,7 +1129,7 @@ sctp_asconf_queue_add_sa(struct sctp_tcb *stcb, struct sockaddr *sa, sizeof(struct in_addr)); } else { /* invalid family! */ - SCTP_FREE(aa); + SCTP_FREE(aa, SCTP_M_ASC_ADDR); return (-1); } aa->sent = 0; /* clear sent flag */ @@ -1258,7 +1258,7 @@ sctp_asconf_process_param_ack(struct sctp_tcb *stcb, /* remove the param and free it */ TAILQ_REMOVE(&stcb->asoc.asconf_queue, aparam, next); sctp_free_ifa(aparam->ifa); - SCTP_FREE(aparam); + SCTP_FREE(aparam, SCTP_M_ASC_ADDR); } /* @@ -1864,7 +1864,7 @@ sctp_iterator_end(void *ptr, uint32_t val) SCTP_DECR_LADDR_COUNT(); l = l_next; } - SCTP_FREE(asc); + SCTP_FREE(asc, SCTP_M_ASC_IT); } /* @@ -2566,14 +2566,14 @@ sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa, SCTP_MALLOC(asc, struct sctp_asconf_iterator *, sizeof(struct sctp_asconf_iterator), - "SCTP_ASCONF_ITERATOR"); + SCTP_M_ASC_IT); if (asc == NULL) { return (ENOMEM); } wi = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_laddr, struct sctp_laddr); if (wi == NULL) { - SCTP_FREE(asc); + SCTP_FREE(asc, SCTP_M_ASC_IT); return (ENOMEM); } if (type == SCTP_ADD_IP_ADDRESS) { diff --git a/sys/netinet/sctp_auth.c b/sys/netinet/sctp_auth.c index 2349c62..579bb3f 100644 --- a/sys/netinet/sctp_auth.c +++ b/sys/netinet/sctp_auth.c @@ -61,7 +61,7 @@ sctp_alloc_chunklist(void) sctp_auth_chklist_t *chklist; SCTP_MALLOC(chklist, sctp_auth_chklist_t *, sizeof(*chklist), - "AUTH chklist"); + SCTP_M_AUTH_CL); if (chklist == NULL) { SCTPDBG(SCTP_DEBUG_AUTH1, "sctp_alloc_chunklist: failed to get memory!\n"); } else { @@ -74,7 +74,7 @@ void sctp_free_chunklist(sctp_auth_chklist_t * list) { if (list != NULL) - SCTP_FREE(list); + SCTP_FREE(list, SCTP_M_AUTH_CL); } sctp_auth_chklist_t * @@ -260,7 +260,7 @@ sctp_alloc_key(uint32_t keylen) sctp_key_t *new_key; SCTP_MALLOC(new_key, sctp_key_t *, sizeof(*new_key) + keylen, - "AUTH key"); + SCTP_M_AUTH_KY); if (new_key == NULL) { /* out of memory */ return (NULL); @@ -273,7 +273,7 @@ void sctp_free_key(sctp_key_t * key) { if (key != NULL) - SCTP_FREE(key); + SCTP_FREE(key, SCTP_M_AUTH_KY); } void @@ -492,7 +492,7 @@ sctp_alloc_sharedkey(void) sctp_sharedkey_t *new_key; SCTP_MALLOC(new_key, sctp_sharedkey_t *, sizeof(*new_key), - "AUTH skey"); + SCTP_M_AUTH_KY); if (new_key == NULL) { /* out of memory */ return (NULL); @@ -508,7 +508,7 @@ sctp_free_sharedkey(sctp_sharedkey_t * skey) if (skey != NULL) { if (skey->key != NULL) sctp_free_key(skey->key); - SCTP_FREE(skey); + SCTP_FREE(skey, SCTP_M_AUTH_KY); } } @@ -607,7 +607,7 @@ sctp_alloc_hmaclist(uint8_t num_hmacs) alloc_size = sizeof(*new_list) + num_hmacs * sizeof(new_list->hmac[0]); SCTP_MALLOC(new_list, sctp_hmaclist_t *, alloc_size, - "AUTH HMAC list"); + SCTP_M_AUTH_HL); if (new_list == NULL) { /* out of memory */ return (NULL); @@ -621,7 +621,7 @@ void sctp_free_hmaclist(sctp_hmaclist_t * list) { if (list != NULL) { - SCTP_FREE(list); + SCTP_FREE(list, SCTP_M_AUTH_HL); list = NULL; } } @@ -774,7 +774,8 @@ sctp_alloc_authinfo(void) sctp_authinfo_t *new_authinfo; SCTP_MALLOC(new_authinfo, sctp_authinfo_t *, sizeof(*new_authinfo), - "AUTH info"); + SCTP_M_AUTH_IF); + if (new_authinfo == NULL) { /* out of memory */ return (NULL); @@ -799,7 +800,7 @@ sctp_free_authinfo(sctp_authinfo_t * authinfo) sctp_free_key(authinfo->recv_key); /* We are NOT dynamically allocating authinfo's right now... */ - /* SCTP_FREE(authinfo); */ + /* SCTP_FREE(authinfo, SCTP_M_AUTH_??); */ } diff --git a/sys/netinet/sctp_bsd_addr.c b/sys/netinet/sctp_bsd_addr.c index 4d6fd60..d188a12 100644 --- a/sys/netinet/sctp_bsd_addr.c +++ b/sys/netinet/sctp_bsd_addr.c @@ -49,6 +49,38 @@ __FBSDID("$FreeBSD$"); #include <sys/unistd.h> +/* Declare all of our malloc named types */ + +/* Not to Michael/Peter for mac-os, + * I think mac has this to since I + * do see the M_PCB type, so I + * will also put in the mac file the + * MALLOC_DELCARE. If this does not + * work for mac uncomment the defines for + * the strings that we use in Panda, I put + * them in comments in the mac-os file. + */ +MALLOC_DEFINE(SCTP_M_MAP, "sctp_map", "sctp asoc map descriptor"); +MALLOC_DEFINE(SCTP_M_STRMI, "sctp_stri", "sctp stream in array"); +MALLOC_DEFINE(SCTP_M_STRMO, "sctp_stro", "sctp stream out array"); +MALLOC_DEFINE(SCTP_M_ASC_ADDR, "sctp_aadr", "sctp asconf address"); +MALLOC_DEFINE(SCTP_M_ASC_IT, "sctp_a_it", "sctp asconf iterator"); +MALLOC_DEFINE(SCTP_M_AUTH_CL, "sctp_atcl", "sctp auth chunklist"); +MALLOC_DEFINE(SCTP_M_AUTH_KY, "sctp_atky", "sctp auth key"); +MALLOC_DEFINE(SCTP_M_AUTH_HL, "sctp_athm", "sctp auth hmac list"); +MALLOC_DEFINE(SCTP_M_AUTH_IF, "sctp_athi", "sctp auth info"); +MALLOC_DEFINE(SCTP_M_STRESET, "sctp_stre", "sctp stream reset"); +MALLOC_DEFINE(SCTP_M_CMSG, "sctp_cmsg", "sctp CMSG buffer"); +MALLOC_DEFINE(SCTP_M_COPYAL, "sctp_cpal", "sctp copy all"); +MALLOC_DEFINE(SCTP_M_VRF, "sctp_vrf", "sctp vrf struct"); +MALLOC_DEFINE(SCTP_M_IFA, "sctp_ifa", "sctp ifa struct"); +MALLOC_DEFINE(SCTP_M_IFN, "sctp_ifn", "sctp ifn struct"); +MALLOC_DEFINE(SCTP_M_TIMW, "sctp_timw", "sctp time block"); +MALLOC_DEFINE(SCTP_M_MVRF, "sctp_mvrf", "sctp mvrf pcb list"); +MALLOC_DEFINE(SCTP_M_ITER, "sctp_iter", "sctp iterator control"); +MALLOC_DEFINE(SCTP_M_SOCKOPT, "sctp_socko", "sctp socket option"); + + #if defined(SCTP_USE_THREAD_BASED_ITERATOR) void sctp_wakeup_iterator(void) @@ -338,3 +370,164 @@ sctp_get_mbuf_for_msg(unsigned int space_needed, int want_header, #endif return (m); } + + +#ifdef SCTP_PACKET_LOGGING + +int packet_log_start = 0; +int packet_log_end = 0; +int packet_log_old_end = SCTP_PACKET_LOG_SIZE; +int packet_log_wrapped = 0; +uint8_t packet_log_buffer[SCTP_PACKET_LOG_SIZE]; + + +void +sctp_packet_log(struct mbuf *m, int length) +{ + int *lenat, needed, thisone; + void *copyto; + uint32_t *tick_tock; + int total_len, spare; + + total_len = SCTP_SIZE32((length + (2 * sizeof(int)))); + /* Log a packet to the buffer. */ + if (total_len > SCTP_PACKET_LOG_SIZE) { + /* Can't log this packet I have not a buffer big enough */ + return; + } + if (length < (SCTP_MIN_V4_OVERHEAD + sizeof(struct sctp_cookie_ack_chunk))) { + printf("Huh, length is %d to small for sctp min:%d\n", + length, + (SCTP_MIN_V4_OVERHEAD + sizeof(struct sctp_cookie_ack_chunk))); + return; + } + SCTP_IP_PKTLOG_LOCK(); + if ((SCTP_PACKET_LOG_SIZE - packet_log_end) <= total_len) { + /* + * it won't fit on the end. We must go back to the + * beginning. To do this we go back and cahnge + * packet_log_start. + */ + int orig_end; + + lenat = (int *)packet_log_buffer; + orig_end = packet_log_end; + packet_log_old_end = packet_log_end; + packet_log_end = 0; + if (packet_log_start > packet_log_old_end) { + /* calculate the head room */ + spare = packet_log_start - packet_log_old_end; + } else { + spare = 0; + } + needed = total_len - spare; + packet_log_wrapped = 1; + /* Now update the start */ + while (needed > 0) { + thisone = (*(int *)(&packet_log_buffer[packet_log_start])); + needed -= thisone; + if (thisone == 0) { + int *foo; + + foo = (int *)(&packet_log_buffer[packet_log_start]); + goto insane; + } + /* move to next one */ + packet_log_start += thisone; + } + } else { + lenat = (int *)&packet_log_buffer[packet_log_end]; + if (packet_log_start > packet_log_end) { + if ((packet_log_end + total_len) > packet_log_start) { + /* Now need to update killing some packets */ + needed = total_len - ((packet_log_start - packet_log_end)); + while (needed > 0) { + thisone = (*(int *)(&packet_log_buffer[packet_log_start])); + needed -= thisone; + if (thisone == 0) { + goto insane; + } + /* move to next one */ + packet_log_start += thisone; + if (((packet_log_start + sizeof(struct ip)) > SCTP_PACKET_LOG_SIZE) || + (packet_log_wrapped && (packet_log_start >= packet_log_old_end))) { + packet_log_start = 0; + packet_log_old_end = 0; + packet_log_wrapped = 0; + break; + } + } + } + } + } + if (((packet_log_end + total_len) >= SCTP_PACKET_LOG_SIZE) || + ((void *)((caddr_t)lenat) < (void *)packet_log_buffer) || + ((void *)((caddr_t)lenat + total_len) > (void *)&packet_log_buffer[SCTP_PACKET_LOG_SIZE])) { + /* Madness protection */ +insane: + printf("Went mad, end:%d start:%d len:%d wrapped:%d oe:%d - zapping\n", + packet_log_end, packet_log_start, total_len, packet_log_wrapped, packet_log_old_end); + packet_log_start = packet_log_end = packet_log_old_end = packet_log_wrapped = 0; + lenat = (int *)&packet_log_buffer[0]; + } + *lenat = total_len; + lenat++; + tick_tock = (uint32_t *) lenat; + lenat++; + *tick_tock = sctp_get_tick_count(); + copyto = (void *)lenat; + packet_log_end = (((caddr_t)copyto + length) - (caddr_t)packet_log_buffer); + SCTP_IP_PKTLOG_UNLOCK(); + m_copydata(m, 0, length, (caddr_t)copyto); + +} + + +int +sctp_copy_out_packet_log(uint8_t * target, int length) +{ + /* + * We wind through the packet log starting at start copying up to + * length bytes out. We return the number of bytes copied. + */ + int tocopy, this_copy, copied = 0; + void *at; + + tocopy = length; + if (packet_log_start == packet_log_end) { + /* no data */ + return (0); + } + if (packet_log_wrapped) { + /* + * we have a wrapped buffer, we must copy from start to the + * old end. Then copy from the top of the buffer to the end. + */ + SCTP_IP_PKTLOG_LOCK(); + at = (void *)&packet_log_buffer[packet_log_start]; + this_copy = min(tocopy, (packet_log_old_end - packet_log_start)); + memcpy(target, at, this_copy); + tocopy -= this_copy; + copied += this_copy; + if (tocopy == 0) { + SCTP_IP_PKTLOG_UNLOCK(); + return (copied); + } + this_copy = min(tocopy, packet_log_end); + at = (void *)&packet_log_buffer; + memcpy(&target[copied], at, this_copy); + copied += this_copy; + SCTP_IP_PKTLOG_UNLOCK(); + return (copied); + } else { + /* we have one contiguous buffer */ + SCTP_IP_PKTLOG_LOCK(); + at = (void *)&packet_log_buffer; + this_copy = min(length, packet_log_end); + memcpy(target, at, this_copy); + SCTP_IP_PKTLOG_UNLOCK(); + return (this_copy); + } +} + +#endif diff --git a/sys/netinet/sctp_bsd_addr.h b/sys/netinet/sctp_bsd_addr.h index bb326eb..45a05b6 100644 --- a/sys/netinet/sctp_bsd_addr.h +++ b/sys/netinet/sctp_bsd_addr.h @@ -46,6 +46,13 @@ void sctp_startup_iterator(void); void sctp_gather_internal_ifa_flags(struct sctp_ifa *ifa); +#ifdef SCTP_PACKET_LOGGING + +void sctp_packet_log(struct mbuf *m, int length); +int sctp_copy_out_packet_log(uint8_t * target, int length); + +#endif + void sctp_addr_change(struct ifaddr *ifa, int cmd); #endif diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index e1277fe..0635d87 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -327,7 +327,7 @@ sctp_build_ctl_cchunk(struct sctp_inpcb *inp, } else { len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo)); } - SCTP_MALLOC(buf, char *, len, "SCTP_CMSG"); + SCTP_MALLOC(buf, char *, len, SCTP_M_CMSG); if (buf == NULL) { /* No space */ return (buf); @@ -1481,6 +1481,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, return (0); } if (gap >= (uint32_t) (asoc->mapping_array_size << 3)) { + SCTP_TCB_LOCK_ASSERT(stcb); if (sctp_expand_mapping_array(asoc)) { /* Can't expand, drop it */ return (0); @@ -1587,6 +1588,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, sctp_queue_op_err(stcb, mb); } SCTP_STAT_INCR(sctps_badsid); + SCTP_TCB_LOCK_ASSERT(stcb); SCTP_SET_TSN_PRESENT(asoc->mapping_array, gap); if (compare_with_wrap(tsn, asoc->highest_tsn_inside_map, MAX_TSN)) { /* we have a new high score */ @@ -2089,6 +2091,7 @@ finish_express_del: sctp_log_map(asoc->mapping_array_base_tsn, asoc->cumulative_tsn, asoc->highest_tsn_inside_map, SCTP_MAP_PREPARE_SLIDE); #endif + SCTP_TCB_LOCK_ASSERT(stcb); SCTP_SET_TSN_PRESENT(asoc->mapping_array, gap); /* check the special flag for stream resets */ if (((liste = TAILQ_FIRST(&asoc->resetHead)) != NULL) && @@ -2105,7 +2108,7 @@ finish_express_del: sctp_reset_in_stream(stcb, liste->number_entries, liste->req.list_of_streams); TAILQ_REMOVE(&asoc->resetHead, liste, next_resp); - SCTP_FREE(liste); + SCTP_FREE(liste, SCTP_M_STRESET); /* sa_ignore FREED_MEMORY */ liste = TAILQ_FIRST(&asoc->resetHead); ctl = TAILQ_FIRST(&asoc->pending_reply_queue); @@ -5742,8 +5745,10 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb, gap = asoc->highest_tsn_inside_map + (MAX_TSN - asoc->mapping_array_base_tsn) + 1; } + SCTP_STAT_INCR(sctps_fwdtsn_map_over); cumack_set_flag = 1; } + SCTP_TCB_LOCK_ASSERT(stcb); for (i = 0; i <= gap; i++) { SCTP_SET_TSN_PRESENT(asoc->mapping_array, i); } diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index e80c076..935a90d 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -44,7 +44,7 @@ __FBSDID("$FreeBSD$"); #include <netinet/sctp_auth.h> #include <netinet/sctp_indata.h> #include <netinet/sctp_asconf.h> - +#include <netinet/sctp_bsd_addr.h> @@ -247,6 +247,7 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb, asoc->last_echo_tsn = asoc->asconf_seq_in; asoc->advanced_peer_ack_point = asoc->last_acked_seq; /* open the requested streams */ + if (asoc->strmin != NULL) { /* Free the old ones */ struct sctp_queued_to_read *ctl; @@ -262,14 +263,14 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb, ctl = TAILQ_FIRST(&asoc->strmin[i].inqueue); } } - SCTP_FREE(asoc->strmin); + SCTP_FREE(asoc->strmin, SCTP_M_STRMI); } asoc->streamincnt = ntohs(init->num_outbound_streams); if (asoc->streamincnt > MAX_SCTP_STREAMS) { asoc->streamincnt = MAX_SCTP_STREAMS; } SCTP_MALLOC(asoc->strmin, struct sctp_stream_in *, asoc->streamincnt * - sizeof(struct sctp_stream_in), "StreamsIn"); + sizeof(struct sctp_stream_in), SCTP_M_STRMI); if (asoc->strmin == NULL) { /* we didn't get memory for the streams! */ SCTPDBG(SCTP_DEBUG_INPUT2, "process_init: couldn't get memory for the streams!\n"); @@ -3012,7 +3013,7 @@ sctp_handle_str_reset_request_out(struct sctp_tcb *stcb, siz = sizeof(struct sctp_stream_reset_list) + (number_entries * sizeof(uint16_t)); SCTP_MALLOC(liste, struct sctp_stream_reset_list *, - siz, "StrRstList"); + siz, SCTP_M_STRESET); if (liste == NULL) { /* gak out of memory */ sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_DENIED); @@ -3465,6 +3466,9 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, if (ntohs(ch->chunk_length) < sizeof(*ch)) { SCTPDBG(SCTP_DEBUG_INPUT1, "Invalid header length %d\n", ntohs(ch->chunk_length)); + if (locked_tcb) { + SCTP_TCB_UNLOCK(locked_tcb); + } return (NULL); } /* @@ -3504,6 +3508,9 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, if (*offset >= length) { /* no more data left in the mbuf chain */ *offset = length; + if (locked_tcb) { + SCTP_TCB_UNLOCK(locked_tcb); + } return (NULL); } ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, @@ -3512,6 +3519,9 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, if (ch == NULL) { /* Help */ *offset = length; + if (locked_tcb) { + SCTP_TCB_UNLOCK(locked_tcb); + } return (NULL); } if (ch->chunk_type == SCTP_COOKIE_ECHO) { @@ -3547,6 +3557,9 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, auth_offset)) { /* auth HMAC failed so dump it */ *offset = length; + if (locked_tcb) { + SCTP_TCB_UNLOCK(locked_tcb); + } return (NULL); } else { /* remaining chunks are HMAC checked */ @@ -3926,7 +3939,8 @@ process_control_chunks: stcb, *netp); break; case SCTP_ABORT_ASSOCIATION: - SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ABORT\n"); + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ABORT, stcb %p\n", + stcb); if ((stcb) && netp && *netp) sctp_handle_abort((struct sctp_abort_chunk *)ch, stcb, *netp); @@ -3934,7 +3948,8 @@ process_control_chunks: return (NULL); break; case SCTP_SHUTDOWN: - SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN\n"); + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN, stcb %p\n", + stcb); if ((stcb == NULL) || (chk_length != sizeof(struct sctp_shutdown_chunk))) { *offset = length; if (locked_tcb) { @@ -3955,7 +3970,7 @@ process_control_chunks: } break; case SCTP_SHUTDOWN_ACK: - SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN-ACK\n"); + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN-ACK, stcb %p\n", stcb); if ((stcb) && (netp) && (*netp)) sctp_handle_shutdown_ack((struct sctp_shutdown_ack_chunk *)ch, stcb, *netp); *offset = length; @@ -3972,7 +3987,7 @@ process_control_chunks: break; case SCTP_COOKIE_ECHO: SCTPDBG(SCTP_DEBUG_INPUT3, - "SCTP_COOKIE-ECHO stcb is %p\n", stcb); + "SCTP_COOKIE-ECHO, stcb %p\n", stcb); if ((stcb) && (stcb->asoc.total_output_queue_size)) { ; } else { @@ -4097,7 +4112,7 @@ process_control_chunks: } break; case SCTP_COOKIE_ACK: - SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_COOKIE-ACK\n"); + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_COOKIE-ACK, stcb %p\n", stcb); if ((stcb == NULL) || chk_length != sizeof(struct sctp_cookie_ack_chunk)) { if (locked_tcb) { SCTP_TCB_UNLOCK(locked_tcb); @@ -4154,7 +4169,7 @@ process_control_chunks: } break; case SCTP_SHUTDOWN_COMPLETE: - SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN-COMPLETE\n"); + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN-COMPLETE, stcb %p\n", stcb); /* must be first and only chunk */ if ((num_chunks > 1) || (length - *offset > SCTP_SIZE32(chk_length))) { @@ -4707,6 +4722,7 @@ sctp_input(i_pak, off) SCTP_STAT_INCR(sctps_recvpackets); SCTP_STAT_INCR_COUNTER64(sctps_inpackets); + #ifdef SCTP_MBUF_LOGGING /* Log in any input mbufs */ mat = m; @@ -4717,6 +4733,14 @@ sctp_input(i_pak, off) mat = SCTP_BUF_NEXT(mat); } #endif +#ifdef SCTP_PACKET_LOGGING + sctp_packet_log(m, mlen); +#endif + /* + * Must take out the iphlen, since mlen expects this (only effect lb + * case) + */ + mlen -= iphlen; /* * Get IP, SCTP, and first chunk header together in first mbuf. diff --git a/sys/netinet/sctp_lock_bsd.h b/sys/netinet/sctp_lock_bsd.h index 55b9ee0..59cd3f1 100644 --- a/sys/netinet/sctp_lock_bsd.h +++ b/sys/netinet/sctp_lock_bsd.h @@ -133,6 +133,19 @@ extern int sctp_logoff_stuff; #define SCTP_IPI_ITERATOR_WQ_UNLOCK() mtx_unlock(&sctppcbinfo.ipi_iterator_wq_mtx) +#define SCTP_IP_PKTLOG_INIT() \ + mtx_init(&sctppcbinfo.ipi_pktlog_mtx, "sctp-pktlog", "packetlog", MTX_DEF) + + +#define SCTP_IP_PKTLOG_LOCK() do { \ + mtx_lock(&sctppcbinfo.ipi_pktlog_mtx); \ +} while (0) + +#define SCTP_IP_PKTLOG_UNLOCK() mtx_unlock(&sctppcbinfo.ipi_pktlog_mtx) + +#define SCTP_IP_PKTLOG_DESTROY() \ + mtx_destroy(&sctppcbinfo.ipi_pktlog_mtx) + diff --git a/sys/netinet/sctp_os_bsd.h b/sys/netinet/sctp_os_bsd.h index 5847d422..57fc39d 100644 --- a/sys/netinet/sctp_os_bsd.h +++ b/sys/netinet/sctp_os_bsd.h @@ -98,8 +98,26 @@ __FBSDID("$FreeBSD$"); #ifndef in6pcb #define in6pcb inpcb #endif - - +/* Declare all the malloc names for all the various mallocs */ +MALLOC_DECLARE(SCTP_M_MAP); +MALLOC_DECLARE(SCTP_M_STRMI); +MALLOC_DECLARE(SCTP_M_STRMO); +MALLOC_DECLARE(SCTP_M_ASC_ADDR); +MALLOC_DECLARE(SCTP_M_ASC_IT); +MALLOC_DECLARE(SCTP_M_AUTH_CL); +MALLOC_DECLARE(SCTP_M_AUTH_KY); +MALLOC_DECLARE(SCTP_M_AUTH_HL); +MALLOC_DECLARE(SCTP_M_AUTH_IF); +MALLOC_DECLARE(SCTP_M_STRESET); +MALLOC_DECLARE(SCTP_M_CMSG); +MALLOC_DECLARE(SCTP_M_COPYAL); +MALLOC_DECLARE(SCTP_M_VRF); +MALLOC_DECLARE(SCTP_M_IFA); +MALLOC_DECLARE(SCTP_M_IFN); +MALLOC_DECLARE(SCTP_M_TIMW); +MALLOC_DECLARE(SCTP_M_MVRF); +MALLOC_DECLARE(SCTP_M_ITER); +MALLOC_DECLARE(SCTP_M_SOCKOPT); /* * @@ -166,10 +184,10 @@ __FBSDID("$FreeBSD$"); */ #define SCTP_MALLOC(var, type, size, name) \ do { \ - MALLOC(var, type, size, M_PCB, M_NOWAIT); \ + MALLOC(var, type, size, name, M_NOWAIT); \ } while (0) -#define SCTP_FREE(var) FREE(var, M_PCB) +#define SCTP_FREE(var, type) FREE(var, type) #define SCTP_MALLOC_SONAME(var, type, size) \ do { \ @@ -220,6 +238,8 @@ typedef struct callout sctp_os_timer_t; #define SCTP_OS_TIMER_ACTIVE callout_active #define SCTP_OS_TIMER_DEACTIVATE callout_deactivate +#define sctp_get_tick_count() (ticks) + /* * Functions */ @@ -299,8 +319,8 @@ SCTP_GET_PKT_TABLEID(void *m, uint32_t table_id) } while(0) /* Other m_pkthdr type things */ -#define SCTP_IS_IT_BROADCAST(dst, m) in_broadcast(dst, m->m_pkthdr.rcvif) -#define SCTP_IS_IT_LOOPBACK(m) ((m->m_pkthdr.rcvif == NULL) ||(m->m_pkthdr.rcvif->if_type == IFT_LOOP)) +#define SCTP_IS_IT_BROADCAST(dst, m) ((m->m_flags & M_PKTHDR) ? in_broadcast(dst, m->m_pkthdr.rcvif) : 0) +#define SCTP_IS_IT_LOOPBACK(m) ((m->m_flags & M_PKTHDR) && ((m->m_pkthdr.rcvif == NULL) || (m->m_pkthdr.rcvif->if_type == IFT_LOOP))) /* This converts any input packet header diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 0b1bac1..e18fbde 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -3463,6 +3463,9 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, sctp_m_freem(m); return (ENOMEM); } +#ifdef SCTP_PACKET_LOGGING + sctp_packet_log(m, packet_length); +#endif SCTP_ATTACH_CHAIN(o_pak, m, packet_length); /* send it out. table id is taken from stcb */ @@ -3676,6 +3679,9 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, sctp_m_freem(m); return (ENOMEM); } +#ifdef SCTP_PACKET_LOGGING + sctp_packet_log(m, packet_length); +#endif SCTP_ATTACH_CHAIN(o_pak, m, packet_length); /* send it out. table id is taken from stcb */ @@ -5773,7 +5779,7 @@ sctp_sendall_completes(void *ptr, uint32_t val) /* now free everything */ sctp_m_freem(ca->m); - SCTP_FREE(ca); + SCTP_FREE(ca, SCTP_M_COPYAL); } @@ -5833,7 +5839,7 @@ sctp_sendall(struct sctp_inpcb *inp, struct uio *uio, struct mbuf *m, struct sctp_copy_all *ca; SCTP_MALLOC(ca, struct sctp_copy_all *, sizeof(struct sctp_copy_all), - "CopyAll"); + SCTP_M_COPYAL); if (ca == NULL) { sctp_m_freem(m); return (ENOMEM); @@ -5852,7 +5858,7 @@ sctp_sendall(struct sctp_inpcb *inp, struct uio *uio, struct mbuf *m, ca->sndlen = uio->uio_resid; ca->m = sctp_copy_out_all(uio, ca->sndlen); if (ca->m == NULL) { - SCTP_FREE(ca); + SCTP_FREE(ca, SCTP_M_COPYAL); return (ENOMEM); } } else { @@ -5874,7 +5880,7 @@ sctp_sendall(struct sctp_inpcb *inp, struct uio *uio, struct mbuf *m, sctp_sendall_completes, inp, 1); if (ret) { SCTP_PRINTF("Failed to initiate iterator for sendall\n"); - SCTP_FREE(ca); + SCTP_FREE(ca, SCTP_M_COPYAL); return (EFAULT); } return (0); @@ -9344,6 +9350,9 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh, bzero(&ro, sizeof ro); /* set IPv4 length */ iph_out->ip_len = mlen; +#ifdef SCTP_PACKET_LOGGING + sctp_packet_log(mout, mlen); +#endif SCTP_ATTACH_CHAIN(o_pak, mout, mlen); /* out it goes */ @@ -9360,6 +9369,9 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh, bzero(&ro, sizeof(ro)); mlen = SCTP_BUF_LEN(mout); +#ifdef SCTP_PACKET_LOGGING + sctp_packet_log(mout, mlen); +#endif SCTP_ATTACH_CHAIN(o_pak, mout, mlen); SCTP_IP6_OUTPUT(ret, o_pak, &ro, &ifp, stcb, vrf_id, table_id); @@ -10209,6 +10221,9 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag, /* set IPv4 length */ iph_out->ip_len = len; /* out it goes */ +#ifdef SCTP_PACKET_LOGGING + sctp_packet_log(mout, len); +#endif SCTP_ATTACH_CHAIN(o_pak, mout, len); SCTP_IP_OUTPUT(ret, o_pak, &ro, stcb, vrf_id, table_id); @@ -10226,6 +10241,9 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag, SCTPDBG(SCTP_DEBUG_OUTPUT2, "sctp_send_abort calling ip6_output:\n"); SCTPDBG_PKT(SCTP_DEBUG_OUTPUT2, (struct ip *)ip6_out, &abm->sh); ip6_out->ip6_plen = len - sizeof(*ip6_out); +#ifdef SCTP_PACKET_LOGGING + sctp_packet_log(mout, len); +#endif SCTP_ATTACH_CHAIN(o_pak, mout, len); SCTP_IP6_OUTPUT(ret, o_pak, &ro, &ifp, stcb, vrf_id, table_id); @@ -10327,6 +10345,9 @@ sctp_send_operr_to(struct mbuf *m, int iphlen, struct mbuf *scm, uint32_t vtag, out->ip_src = iph->ip_dst; out->ip_dst = iph->ip_src; out->ip_len = len; +#ifdef SCTP_PACKET_LOGGING + sctp_packet_log(mout, len); +#endif SCTP_ATTACH_CHAIN(o_pak, mout, len); SCTP_IP_OUTPUT(retcode, o_pak, &ro, stcb, vrf_id, table_id); @@ -10372,6 +10393,9 @@ sctp_send_operr_to(struct mbuf *m, int iphlen, struct mbuf *scm, uint32_t vtag, SCTPDBG(SCTP_DEBUG_OUTPUT2, "dst "); SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, (struct sockaddr *)&fsa6); +#ifdef SCTP_PACKET_LOGGING + sctp_packet_log(mout, len); +#endif SCTP_ATTACH_CHAIN(o_pak, mout, len); SCTP_IP6_OUTPUT(ret, o_pak, &ro, &ifp, stcb, vrf_id, table_id); @@ -10867,12 +10891,12 @@ sctp_lower_sosend(struct socket *so, struct sctp_stream_out *, (asoc->pre_open_streams * sizeof(struct sctp_stream_out)), - "StreamsOut"); + SCTP_M_STRMO); if (had_lock) { SCTP_TCB_LOCK(stcb); } if (tmp_str != NULL) { - SCTP_FREE(asoc->strmout); + SCTP_FREE(asoc->strmout, SCTP_M_STRMO); asoc->strmout = tmp_str; asoc->streamoutcnt = asoc->pre_open_streams; } else { @@ -10943,6 +10967,8 @@ sctp_lower_sosend(struct socket *so, } } /* Keep the stcb from being freed under our feet */ + if (free_cnt_applied) + panic("refcnt already incremented"); atomic_add_int(&stcb->asoc.refcnt, 1); free_cnt_applied = 1; diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index 2b498b7..94baf43 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -142,7 +142,7 @@ sctp_allocate_vrf(int vrf_id) return (vrf); } SCTP_MALLOC(vrf, struct sctp_vrf *, sizeof(struct sctp_vrf), - "SCTP_VRF"); + SCTP_M_VRF); if (vrf == NULL) { /* No memory */ #ifdef INVARIANTS @@ -163,7 +163,7 @@ sctp_allocate_vrf(int vrf_id) #ifdef INVARIANTS panic("No memory for VRF:%d", vrf_id); #endif - SCTP_FREE(vrf); + SCTP_FREE(vrf, SCTP_M_VRF); return (NULL); } vrf->vrf_ifn_hash = SCTP_HASH_INIT(SCTP_VRF_IFN_HASH_SIZE, @@ -174,7 +174,7 @@ sctp_allocate_vrf(int vrf_id) panic("No memory for VRF:%d", vrf_id); #endif SCTP_HASH_FREE(vrf->vrf_addr_hash, vrf->vrf_addr_hashmark); - SCTP_FREE(vrf); + SCTP_FREE(vrf, SCTP_M_VRF); return (NULL); } /* Add it to the hash table */ @@ -233,7 +233,7 @@ sctp_free_ifn(struct sctp_ifn *sctp_ifnp) ret = atomic_fetchadd_int(&sctp_ifnp->refcount, -1); if (ret == 1) { /* We zero'd the count */ - SCTP_FREE(sctp_ifnp); + SCTP_FREE(sctp_ifnp, SCTP_M_IFN); atomic_subtract_int(&sctppcbinfo.ipi_count_ifns, 1); } } @@ -262,7 +262,7 @@ sctp_free_ifa(struct sctp_ifa *sctp_ifap) ret = atomic_fetchadd_int(&sctp_ifap->refcount, -1); if (ret == 1) { /* We zero'd the count */ - SCTP_FREE(sctp_ifap); + SCTP_FREE(sctp_ifap, SCTP_M_IFA); atomic_subtract_int(&sctppcbinfo.ipi_count_ifas, 1); } } @@ -318,7 +318,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index, * done though. */ SCTP_IPI_ADDR_UNLOCK(); - SCTP_MALLOC(sctp_ifnp, struct sctp_ifn *, sizeof(struct sctp_ifn), "SCTP_IFN"); + SCTP_MALLOC(sctp_ifnp, struct sctp_ifn *, sizeof(struct sctp_ifn), SCTP_M_IFN); if (sctp_ifnp == NULL) { #ifdef INVARIANTS panic("No memory for IFN:%u", sctp_ifnp->ifn_index); @@ -376,7 +376,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index, } } SCTP_IPI_ADDR_UNLOCK(); - SCTP_MALLOC(sctp_ifap, struct sctp_ifa *, sizeof(struct sctp_ifa), "SCTP_IFA"); + SCTP_MALLOC(sctp_ifap, struct sctp_ifa *, sizeof(struct sctp_ifa), SCTP_M_IFA); if (sctp_ifap == NULL) { #ifdef INVARIANTS panic("No memory for IFA"); @@ -461,11 +461,11 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index, * the newest first :-0 */ LIST_INSERT_HEAD(&sctppcbinfo.addr_wq, wi, sctp_nxt_addr); + SCTP_IPI_ITERATOR_WQ_UNLOCK(); sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ, (struct sctp_inpcb *)NULL, (struct sctp_tcb *)NULL, (struct sctp_nets *)NULL); - SCTP_IPI_ITERATOR_WQ_UNLOCK(); } else { /* it's ready for use */ sctp_ifap->localifa_flags &= ~SCTP_ADDR_DEFER_USE; @@ -539,11 +539,12 @@ out_now: * the newest first :-0 */ LIST_INSERT_HEAD(&sctppcbinfo.addr_wq, wi, sctp_nxt_addr); + SCTP_IPI_ITERATOR_WQ_UNLOCK(); + sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ, (struct sctp_inpcb *)NULL, (struct sctp_tcb *)NULL, (struct sctp_nets *)NULL); - SCTP_IPI_ITERATOR_WQ_UNLOCK(); } return; } @@ -2165,7 +2166,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, struct thread *p) SCTP_INP_DECR_REF(inp); /* unlock info */ SCTP_INP_INFO_WUNLOCK(); - return (EADDRNOTAVAIL); + return (EADDRINUSE); } } else { inp_tmp = sctp_pcb_findep(addr, 0, 1, vrf_id); @@ -2181,7 +2182,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, struct thread *p) SCTP_INP_DECR_REF(inp); /* unlock info */ SCTP_INP_INFO_WUNLOCK(); - return (EADDRNOTAVAIL); + return (EADDRINUSE); } } SCTP_INP_WLOCK(inp); @@ -2192,7 +2193,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, struct thread *p) SCTP_INP_DECR_REF(inp); SCTP_INP_WUNLOCK(inp); SCTP_INP_INFO_WUNLOCK(); - return (EADDRNOTAVAIL); + return (EADDRINUSE); } } } else { @@ -2241,7 +2242,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, struct thread *p) SCTP_INP_DECR_REF(inp); SCTP_INP_WUNLOCK(inp); SCTP_INP_INFO_WUNLOCK(); - return (EADDRNOTAVAIL); + return (EADDRINUSE); } if (candiate == last) candiate = first; @@ -2449,7 +2450,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) so = inp->sctp_socket; if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { /* been here before.. eeks.. get out of here */ - SCTP_PRINTF("This conflict in free SHOULD not be happening!\n"); + SCTP_PRINTF("This conflict in free SHOULD not be happening! from %d, imm %d\n", from, immediate); SCTP_ITERATOR_UNLOCK(); #ifdef SCTP_LOG_CLOSING sctp_log_closing(inp, NULL, 1); @@ -3375,11 +3376,14 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr, if ((err = sctp_add_remote_addr(stcb, firstaddr, SCTP_DO_SETSCOPE, SCTP_ALLOC_ASOC))) { /* failure.. memory error? */ - if (asoc->strmout) - SCTP_FREE(asoc->strmout); - if (asoc->mapping_array) - SCTP_FREE(asoc->mapping_array); - + if (asoc->strmout) { + SCTP_FREE(asoc->strmout, SCTP_M_STRMO); + asoc->strmout = NULL; + } + if (asoc->mapping_array) { + SCTP_FREE(asoc->mapping_array, SCTP_M_MAP); + asoc->mapping_array = NULL; + } SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_asoc, stcb); SCTP_DECR_ASOC_COUNT(); SCTP_TCB_LOCK_DESTROY(stcb); @@ -3526,7 +3530,7 @@ sctp_add_vtag_to_timewait(struct sctp_inpcb *inp, uint32_t tag, uint32_t time) /* Need to add a new block to chain */ if (!set) { SCTP_MALLOC(twait_block, struct sctp_tagblock *, - sizeof(struct sctp_tagblock), "TimeWait"); + sizeof(struct sctp_tagblock), SCTP_M_TIMW); if (twait_block == NULL) { return; } @@ -3877,7 +3881,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre /* sa_ignore FREED_MEMORY */ while ((liste = TAILQ_FIRST(&asoc->resetHead)) != NULL) { TAILQ_REMOVE(&asoc->resetHead, liste, next_resp); - SCTP_FREE(liste); + SCTP_FREE(liste, SCTP_M_STRESET); } sq = TAILQ_FIRST(&asoc->pending_reply_queue); @@ -4004,12 +4008,12 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre } */ if (asoc->mapping_array) { - SCTP_FREE(asoc->mapping_array); + SCTP_FREE(asoc->mapping_array, SCTP_M_MAP); asoc->mapping_array = NULL; } /* the stream outs */ if (asoc->strmout) { - SCTP_FREE(asoc->strmout); + SCTP_FREE(asoc->strmout, SCTP_M_STRMO); asoc->strmout = NULL; } asoc->streamoutcnt = 0; @@ -4039,7 +4043,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre } } } - SCTP_FREE(asoc->strmin); + SCTP_FREE(asoc->strmin, SCTP_M_STRMI); asoc->strmin = NULL; } asoc->streamincnt = 0; @@ -4069,7 +4073,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre /* sa_ignore FREED_MEMORY */ aparam = TAILQ_FIRST(&asoc->asconf_queue); TAILQ_REMOVE(&asoc->asconf_queue, aparam, next); - SCTP_FREE(aparam); + SCTP_FREE(aparam, SCTP_M_ASC_ADDR); } if (asoc->last_asconf_ack_sent != NULL) { sctp_m_freem(asoc->last_asconf_ack_sent); @@ -4589,7 +4593,9 @@ sctp_pcb_init() SCTP_IPI_COUNT_INIT(); SCTP_IPI_ADDR_INIT(); SCTP_IPI_ITERATOR_WQ_INIT(); - +#ifdef SCTP_PACKET_LOGGING + SCTP_IP_PKTLOG_INIT(); +#endif LIST_INIT(&sctppcbinfo.addr_wq); /* not sure if we need all the counts */ @@ -5559,7 +5565,7 @@ sctp_initiate_iterator(inp_func inpf, return (-1); } SCTP_MALLOC(it, struct sctp_iterator *, sizeof(struct sctp_iterator), - "Iterator"); + SCTP_M_ITER); if (it == NULL) { return (ENOMEM); } diff --git a/sys/netinet/sctp_pcb.h b/sys/netinet/sctp_pcb.h index ddcbf4d..cea9178 100644 --- a/sys/netinet/sctp_pcb.h +++ b/sys/netinet/sctp_pcb.h @@ -182,6 +182,7 @@ struct sctp_epinfo { struct mtx it_mtx; struct mtx ipi_iterator_wq_mtx; struct mtx ipi_addr_mtx; + struct mtx ipi_pktlog_mtx; uint32_t ipi_count_ep; /* assoc/tcb zone info */ diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c index fda9477..9ee6470 100644 --- a/sys/netinet/sctp_sysctl.c +++ b/sys/netinet/sctp_sysctl.c @@ -391,6 +391,7 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS) xstcb.cumulative_tsn = stcb->asoc.last_acked_seq; xstcb.cumulative_tsn_ack = stcb->asoc.cumulative_tsn; xstcb.mtu = stcb->asoc.smallest_mtu; + xstcb.refcnt = stcb->asoc.refcnt; SCTP_INP_RUNLOCK(inp); SCTP_INP_INFO_RUNLOCK(); error = SYSCTL_OUT(req, &xstcb, sizeof(struct xsctp_tcb)); diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c index 085cea5..8d67179 100644 --- a/sys/netinet/sctp_timer.c +++ b/sys/netinet/sctp_timer.c @@ -1640,7 +1640,7 @@ done_with_iterator: if (it->function_atend != NULL) { (*it->function_atend) (it->pointer, it->val); } - SCTP_FREE(it); + SCTP_FREE(it, SCTP_M_ITER); return; } select_a_new_ep: diff --git a/sys/netinet/sctp_uio.h b/sys/netinet/sctp_uio.h index 958cc3f..a7d8aed 100644 --- a/sys/netinet/sctp_uio.h +++ b/sys/netinet/sctp_uio.h @@ -897,6 +897,8 @@ struct sctpstat { * burst inflight to net */ u_long sctps_send_cwnd_avoid; /* Send cwnd full avoidance, already * max burst inflight to net */ + u_long sctps_fwdtsn_map_over; /* number of map array over-runs via + * fwd-tsn's */ }; #define SCTP_STAT_INCR(_x) SCTP_STAT_INCR_BY(_x,1) @@ -960,6 +962,7 @@ struct xsctp_tcb { uint32_t cumulative_tsn; uint32_t cumulative_tsn_ack; uint32_t mtu; + uint32_t refcnt; /* add more association specific data here */ }; diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index 597705c..2e6f7e2 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -48,6 +48,8 @@ __FBSDID("$FreeBSD$"); #include <netinet/sctp_indata.h> #include <netinet/sctp_timer.h> #include <netinet/sctp_auth.h> +#include <netinet/sctp_bsd_addr.h> + @@ -1478,7 +1480,20 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize, *optsize = sizeof(val); } break; + case SCTP_GET_PACKET_LOG: + { +#ifdef SCTP_PACKET_LOGGING + uint8_t *target; + int ret; + SCTP_CHECK_AND_CAST(target, optval, uint8_t, *optsize); + ret = sctp_copy_out_packet_log(target, (int)*optsize); + *optsize = ret; +#else + error = EOPNOTSUPP; +#endif + break; + } case SCTP_PARTIAL_DELIVERY_POINT: { uint32_t *value; @@ -3560,7 +3575,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, error = sctp_addr_mgmt_ep_sa(inp, addr_touse, SCTP_ADD_IP_ADDRESS, vrf_id); } else { - error = EADDRNOTAVAIL; + error = EADDRINUSE; } if (error) break; @@ -3659,13 +3674,13 @@ sctp_ctloutput(struct socket *so, struct sockopt *sopt) } optsize = sopt->sopt_valsize; if (optsize) { - SCTP_MALLOC(optval, void *, optsize, "SCTPSockOpt"); + SCTP_MALLOC(optval, void *, optsize, SCTP_M_SOCKOPT); if (optval == NULL) { return (ENOBUFS); } error = sooptcopyin(sopt, optval, optsize, optsize); if (error) { - SCTP_FREE(optval); + SCTP_FREE(optval, SCTP_M_SOCKOPT); goto out; } } @@ -3679,9 +3694,9 @@ sctp_ctloutput(struct socket *so, struct sockopt *sopt) } if ((error == 0) && (optval != NULL)) { error = sooptcopyout(sopt, optval, optsize); - SCTP_FREE(optval); + SCTP_FREE(optval, SCTP_M_SOCKOPT); } else if (optval != NULL) { - SCTP_FREE(optval); + SCTP_FREE(optval, SCTP_M_SOCKOPT); } out: return (error); diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index 7558875..736a562 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -1061,7 +1061,7 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_association *asoc, m->sctp_ep.pre_open_stream_count; SCTP_MALLOC(asoc->strmout, struct sctp_stream_out *, asoc->streamoutcnt * sizeof(struct sctp_stream_out), - "StreamsOut"); + SCTP_M_STRMO); if (asoc->strmout == NULL) { /* big trouble no memory */ return (ENOMEM); @@ -1085,9 +1085,9 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_association *asoc, /* Now the mapping array */ asoc->mapping_array_size = SCTP_INITIAL_MAPPING_ARRAY; SCTP_MALLOC(asoc->mapping_array, uint8_t *, asoc->mapping_array_size, - "MappingArray"); + SCTP_M_MAP); if (asoc->mapping_array == NULL) { - SCTP_FREE(asoc->strmout); + SCTP_FREE(asoc->strmout, SCTP_M_STRMO); return (ENOMEM); } memset(asoc->mapping_array, 0, asoc->mapping_array_size); @@ -1129,7 +1129,7 @@ sctp_expand_mapping_array(struct sctp_association *asoc) uint16_t new_size; new_size = asoc->mapping_array_size + SCTP_MAPPING_ARRAY_INCR; - SCTP_MALLOC(new_array, uint8_t *, new_size, "MappingArray"); + SCTP_MALLOC(new_array, uint8_t *, new_size, SCTP_M_MAP); if (new_array == NULL) { /* can't get more, forget it */ SCTP_PRINTF("No memory for expansion of SCTP mapping array %d\n", @@ -1138,7 +1138,7 @@ sctp_expand_mapping_array(struct sctp_association *asoc) } memset(new_array, 0, new_size); memcpy(new_array, asoc->mapping_array, asoc->mapping_array_size); - SCTP_FREE(asoc->mapping_array); + SCTP_FREE(asoc->mapping_array, SCTP_M_MAP); asoc->mapping_array = new_array; asoc->mapping_array_size = new_size; return (0); @@ -1162,7 +1162,7 @@ done_with_iterator: if (it->function_atend != NULL) { (*it->function_atend) (it->pointer, it->val); } - SCTP_FREE(it); + SCTP_FREE(it, SCTP_M_ITER); return; } select_a_new_ep: @@ -1314,7 +1314,7 @@ sctp_handle_addr_wq(void) struct sctp_asconf_iterator *asc; SCTP_MALLOC(asc, struct sctp_asconf_iterator *, - sizeof(struct sctp_asconf_iterator), "SCTP_ASCONF_ITERATOR"); + sizeof(struct sctp_asconf_iterator), SCTP_M_ASC_IT); if (asc == NULL) { /* Try later, no memory */ sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ, @@ -1335,7 +1335,7 @@ sctp_handle_addr_wq(void) } SCTP_IPI_ITERATOR_WQ_UNLOCK(); if (asc->cnt == 0) { - SCTP_FREE(asc); + SCTP_FREE(asc, SCTP_M_ASC_IT); } else { (void)sctp_initiate_iterator(sctp_iterator_ep, sctp_iterator_stcb, @@ -1426,6 +1426,9 @@ sctp_timeout_handler(void *t) if (inp) { SCTP_INP_DECR_REF(inp); } + if (stcb) { + atomic_add_int(&stcb->asoc.refcnt, -1); + } return; } tmr->stopped_from = 0xa006; @@ -4945,6 +4948,8 @@ found_one: * to increment, we need to use the atomic add to * the refcnt */ + if (freecnt_applied) + panic("refcnt already incremented"); atomic_add_int(&stcb->asoc.refcnt, 1); freecnt_applied = 1; /* diff --git a/sys/netinet6/sctp6_usrreq.c b/sys/netinet6/sctp6_usrreq.c index db1b81a..427b69b 100644 --- a/sys/netinet6/sctp6_usrreq.c +++ b/sys/netinet6/sctp6_usrreq.c @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); #include <netinet/sctp_auth.h> #include <netinet/sctp_input.h> #include <netinet/sctp_output.h> +#include <netinet/sctp_bsd_addr.h> extern struct protosw inetsw[]; @@ -91,6 +92,9 @@ sctp6_input(i_pak, offp, proto) m = SCTP_HEADER_TO_CHAIN(*i_pak); pkt_len = SCTP_HEADER_LEN((*i_pak)); +#ifdef SCTP_PACKET_LOGGING + sctp_packet_log(m, pkt_len); +#endif ip6 = mtod(m, struct ip6_hdr *); /* Ensure that (sctphdr + sctp_chunkhdr) in a row. */ IP6_EXTHDR_GET(sh, struct sctphdr *, m, off, |