- Fixes so we won't try to start a timer when we

hold a wq lock for the iterator. Panda uses a
  silly recursive lock they hold through the timer.
- Add poor mans wireshark compile option..
- Allocate and start using SCTP_M_XXX for all SCTP_MALLOC() calls.
- sysctl now will get back the refcnt for viewing by onlookers.

Reviewed by:	gnn
This commit is contained in:
Randall Stewart 2007-05-29 09:29:03 +00:00
parent 20a990117d
commit 207304d4b7
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=170091
18 changed files with 425 additions and 86 deletions

View File

@ -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_ */

View File

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

View File

@ -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_??); */
}

View File

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

View File

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

View File

@ -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 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
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 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
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);
}

View File

@ -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 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
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 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
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 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
}
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 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
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 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
}
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 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
}
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.

View File

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

View File

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

View File

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

View File

@ -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 @@ sctp_del_addr_from_vrf(uint32_t vrf_id, struct sockaddr *addr,
* 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);
}

View File

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

View File

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

View File

@ -1640,7 +1640,7 @@ sctp_iterator_timer(struct sctp_iterator *it)
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:

View File

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

View File

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

View File

@ -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 @@ sctp_iterator_work(struct sctp_iterator *it)
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 @@ sctp_sorecvmsg(struct socket *so,
* 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;
/*

View File

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