/*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * a) Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * b) Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the distribution. * * c) Neither the name of Cisco Systems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE.
*/
TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) { if (it->function_atend != NULL) {
(*it->function_atend) (it->pointer, it->val);
}
TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr);
SCTP_FREE(it, SCTP_M_ITER);
}
} #endif #ifdefined(__Userspace__) /*__Userspace__ TODO if we use thread based iterator * then the implementation of wakeup will need to change. * Currently we are using timeo_cond for ident so_timeo * but that is not sufficient if we need to use another ident * like wakeup(&sctppcbinfo.iterator_running);
*/ #endif
void
sctp_startup_iterator(void)
{ if (sctp_it_ctl.thread_proc) { /* You only get one */ return;
} /* Initialize global locks here, thus only once. */
SCTP_ITERATOR_LOCK_INIT();
SCTP_IPI_ITERATOR_WQ_INIT();
TAILQ_INIT(&sctp_it_ctl.iteratorhead); #ifdefined(__Userspace__) if (sctp_userspace_thread_create(&sctp_it_ctl.thread_proc, &sctp_iterator_thread)) {
SCTP_PRINTF("ERROR: Creating sctp_iterator_thread failed.\n");
} else {
SCTP_BASE_VAR(iterator_thread_started) = 1;
} #elifdefined(__FreeBSD__)
kproc_create(sctp_iterator_thread,
(void *)NULL,
&sctp_it_ctl.thread_proc,
0,
SCTP_KTHREAD_PAGES,
SCTP_KTRHEAD_NAME); #elifdefined(__APPLE__)
kernel_thread_start((thread_continue_t)sctp_iterator_thread, NULL, &sctp_it_ctl.thread_proc); #endif
}
#ifdef INET6
#ifdefined(__Userspace__) /* __Userspace__ TODO. struct in6_ifaddr is defined in sys/netinet6/in6_var.h ip6_use_deprecated is defined as int ip6_use_deprecated = 1; in /src/sys/netinet6/in6_proto.c
*/ void
sctp_gather_internal_ifa_flags(struct sctp_ifa *ifa)
{ return; /* stub */
} #else void
sctp_gather_internal_ifa_flags(struct sctp_ifa *ifa)
{ struct in6_ifaddr *ifa6;
#if !defined(__Userspace__) static uint32_t
sctp_is_desired_interface_type(struct ifnet *ifn)
{ int result;
/* check the interface type to see if it's one we care about */ #ifdefined(__APPLE__) && !defined(__Userspace__) switch(ifnet_type(ifn)) { #else switch (ifn->if_type) { #endif case IFT_ETHER: case IFT_ISO88023: case IFT_ISO88024: case IFT_ISO88025: case IFT_ISO88026: case IFT_STARLAN: case IFT_P10: case IFT_P80: case IFT_HY: case IFT_FDDI: case IFT_XETHER: case IFT_ISDNBASIC: case IFT_ISDNPRIMARY: case IFT_PTPSERIAL: case IFT_OTHER: case IFT_PPP: case IFT_LOOP: case IFT_SLIP: case IFT_GIF: case IFT_L2VLAN: case IFT_STF: #if !(defined(__APPLE__) && !defined(__Userspace__)) case IFT_IP: case IFT_IPOVERCDLC: case IFT_IPOVERCLAW: case IFT_PROPVIRTUAL: /* NetGraph Virtual too */ case IFT_VIRTUALIPADDRESS: #endif
result = 1; break; default:
result = 0;
}
if (SCTP_BASE_VAR(sctp_pcb_initialized) == 0) { return;
} /* BSD only has one VRF, if this changes * we will need to hook in the right * things here to get the id to pass to * the address management routine.
*/ if (SCTP_BASE_VAR(first_time) == 0) { /* Special test to see if my ::1 will showup with this */
SCTP_BASE_VAR(first_time) = 1;
sctp_init_ifns_for_vrf(SCTP_DEFAULT_VRFID);
}
if ((cmd != RTM_ADD) && (cmd != RTM_DELETE)) { /* don't know what to do with this */ return;
}
#ifdef SCTP_PACKET_LOGGING void
sctp_packet_log(struct mbuf *m)
{ int *lenat, thisone; void *copyto;
uint32_t *tick_tock; int length; int total_len; int grabbed_lock = 0; int value, newval, thisend, thisbegin; /* * Buffer layout. * -sizeof this entry (total_len) * -previous end (value) * -ticks of log (ticks) * o -ip packet * o -as logged * - where this started (thisbegin) * x <--end points here
*/
length = SCTP_HEADER_LEN(m);
total_len = SCTP_SIZE32((length + (4 * 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 < (int)(SCTP_MIN_V4_OVERHEAD + sizeof(struct sctp_cookie_ack_chunk))) { return;
}
atomic_add_int(&SCTP_BASE_VAR(packet_log_writers), 1);
try_again: if (SCTP_BASE_VAR(packet_log_writers) > SCTP_PKTLOG_WRITERS_NEED_LOCK) {
SCTP_IP_PKTLOG_LOCK();
grabbed_lock = 1;
again_locked:
value = SCTP_BASE_VAR(packet_log_end);
newval = SCTP_BASE_VAR(packet_log_end) + total_len; if (newval >= SCTP_PACKET_LOG_SIZE) { /* we wrapped */
thisbegin = 0;
thisend = total_len;
} else {
thisbegin = SCTP_BASE_VAR(packet_log_end);
thisend = newval;
} if (!(atomic_cmpset_int(&SCTP_BASE_VAR(packet_log_end), value, thisend))) { goto again_locked;
}
} else {
value = SCTP_BASE_VAR(packet_log_end);
newval = SCTP_BASE_VAR(packet_log_end) + total_len; if (newval >= SCTP_PACKET_LOG_SIZE) { /* we wrapped */
thisbegin = 0;
thisend = total_len;
} else {
thisbegin = SCTP_BASE_VAR(packet_log_end);
thisend = newval;
} if (!(atomic_cmpset_int(&SCTP_BASE_VAR(packet_log_end), value, thisend))) { goto try_again;
}
} /* Sanity check */ if (thisend >= SCTP_PACKET_LOG_SIZE) {
SCTP_PRINTF("Insanity stops a log thisbegin:%d thisend:%d writers:%d lock:%d end:%d\n",
thisbegin,
thisend,
SCTP_BASE_VAR(packet_log_writers),
grabbed_lock,
SCTP_BASE_VAR(packet_log_end));
SCTP_BASE_VAR(packet_log_end) = 0; goto no_log;
}
lenat = (int *)&SCTP_BASE_VAR(packet_log_buffer)[thisbegin];
*lenat = total_len;
lenat++;
*lenat = value;
lenat++;
tick_tock = (uint32_t *)lenat;
lenat++;
*tick_tock = sctp_get_tick_count();
copyto = (void *)lenat;
thisone = thisend - sizeof(int);
lenat = (int *)&SCTP_BASE_VAR(packet_log_buffer)[thisone];
*lenat = thisbegin; if (grabbed_lock) {
SCTP_IP_PKTLOG_UNLOCK();
grabbed_lock = 0;
}
m_copydata(m, 0, length, (caddr_t)copyto);
no_log: if (grabbed_lock) {
SCTP_IP_PKTLOG_UNLOCK();
}
atomic_subtract_int(&SCTP_BASE_VAR(packet_log_writers), 1);
}
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 this_copy; int *lenat; int did_delay = 0;
if (length < (int)(2 * sizeof(int))) { /* not enough room */ return (0);
} if (SCTP_PKTLOG_WRITERS_NEED_LOCK) {
atomic_add_int(&SCTP_BASE_VAR(packet_log_writers), SCTP_PKTLOG_WRITERS_NEED_LOCK);
again: if ((did_delay == 0) && (SCTP_BASE_VAR(packet_log_writers) != SCTP_PKTLOG_WRITERS_NEED_LOCK)) { /* we delay here for just a moment hoping the writer(s) that were * present when we entered will have left and we only have * locking ones that will contend with us for the lock. This * does not assure 100% access, but its good enough for * a logging facility like this.
*/
did_delay = 1;
DELAY(10); goto again;
}
}
SCTP_IP_PKTLOG_LOCK();
lenat = (int *)target;
*lenat = SCTP_BASE_VAR(packet_log_end);
lenat++;
this_copy = min((length - sizeof(int)), SCTP_PACKET_LOG_SIZE);
memcpy((void *)lenat, (void *)SCTP_BASE_VAR(packet_log_buffer), this_copy); if (SCTP_PKTLOG_WRITERS_NEED_LOCK) {
atomic_subtract_int(&SCTP_BASE_VAR(packet_log_writers),
SCTP_PKTLOG_WRITERS_NEED_LOCK);
}
SCTP_IP_PKTLOG_UNLOCK(); return (this_copy + sizeof(int));
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.