summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorrrs <rrs@FreeBSD.org>2007-05-29 09:29:03 +0000
committerrrs <rrs@FreeBSD.org>2007-05-29 09:29:03 +0000
commitf827c93ac67113093cd06e755372cf7cd9302d8f (patch)
treeb0a3898608d9bf9a7a2b4c780e734bf27af057e1 /sys
parent0cadc213d533d92acab0d770376baacbd16de8bf (diff)
downloadFreeBSD-src-f827c93ac67113093cd06e755372cf7cd9302d8f.zip
FreeBSD-src-f827c93ac67113093cd06e755372cf7cd9302d8f.tar.gz
- 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
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet/sctp.h15
-rw-r--r--sys/netinet/sctp_asconf.c22
-rw-r--r--sys/netinet/sctp_auth.c21
-rw-r--r--sys/netinet/sctp_bsd_addr.c193
-rw-r--r--sys/netinet/sctp_bsd_addr.h7
-rw-r--r--sys/netinet/sctp_indata.c9
-rw-r--r--sys/netinet/sctp_input.c44
-rw-r--r--sys/netinet/sctp_lock_bsd.h13
-rw-r--r--sys/netinet/sctp_os_bsd.h32
-rw-r--r--sys/netinet/sctp_output.c38
-rw-r--r--sys/netinet/sctp_pcb.c60
-rw-r--r--sys/netinet/sctp_pcb.h1
-rw-r--r--sys/netinet/sctp_sysctl.c1
-rw-r--r--sys/netinet/sctp_timer.c2
-rw-r--r--sys/netinet/sctp_uio.h3
-rw-r--r--sys/netinet/sctp_usrreq.c25
-rw-r--r--sys/netinet/sctputil.c21
-rw-r--r--sys/netinet6/sctp6_usrreq.c4
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,
OpenPOWER on IntegriCloud