summaryrefslogtreecommitdiffstats
path: root/sys/netinet/sctp_pcb.c
diff options
context:
space:
mode:
authorrrs <rrs@FreeBSD.org>2007-07-17 20:58:26 +0000
committerrrs <rrs@FreeBSD.org>2007-07-17 20:58:26 +0000
commitbaae800484b92bf7eee24218fdc96dca410b1846 (patch)
tree6c79e4122192f2fc2cd2730d66ed9af4e467112a /sys/netinet/sctp_pcb.c
parenteeef9fbdacbbff0d2c008a8f385bddf21f2b0f04 (diff)
downloadFreeBSD-src-baae800484b92bf7eee24218fdc96dca410b1846.zip
FreeBSD-src-baae800484b92bf7eee24218fdc96dca410b1846.tar.gz
- added pre-checks to the bindx call.
- use proper tick gathering macro instead of ticks directly. - Placed reasonable boundaries on sets that a user can do that are converted to ticks from ms. - Fix CMT_PF to always check to be sure CMT is on. - Fix ticks use of CMT_PF. - put back code to allow asconfs to be queued while INITs are in flight and before the assoc is established. - During window probes, an ack'd packet might be left with the window probe mark on it causing it to be retransmitted. Change so that the flight decrease macro clears the window_probe mark. - Additional logging flight size/reading and ASOC LOG. This is only enabled if you manually insert things into opt_sctp.h since its a set of debug code only. - Found an interesting SMP race in the way data was appended which could cause a reader to lose a part of a message, had to reorder when we marked the message was complete to after the data was appended. - bug in ADD-IP for the subset bound socket case when the peer has only one address - fix ASCONF implicit success/error handling case - proper support of jails in Freebsd 6> - copy out the timeval for the 64 bit sparc world on cookie-echo alignment error crashes without this). Approved by: re(Ken Smith)
Diffstat (limited to 'sys/netinet/sctp_pcb.c')
-rw-r--r--sys/netinet/sctp_pcb.c40
1 files changed, 30 insertions, 10 deletions
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index fc847f6..2ffc0fa 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -2125,13 +2125,14 @@ sctp_isport_inuse(struct sctp_inpcb *inp, uint16_t lport, uint32_t vrf_id)
int
sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
- struct sctp_ifa *sctp_ifap, struct thread *p)
+ struct thread *p)
{
/* bind a ep to a socket address */
struct sctppcbhead *head;
struct sctp_inpcb *inp, *inp_tmp;
struct inpcb *ip_inp;
int bindall;
+ int prison = 0;
uint16_t lport;
int error;
uint32_t vrf_id;
@@ -2153,6 +2154,9 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
/* already did a bind, subsequent binds NOT allowed ! */
return (EINVAL);
}
+ if (jailed(p->td_ucred)) {
+ prison = 1;
+ }
if (addr != NULL) {
if (addr->sa_family == AF_INET) {
struct sockaddr_in *sin;
@@ -2166,7 +2170,15 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
sin = (struct sockaddr_in *)addr;
lport = sin->sin_port;
-
+ if (prison) {
+ /*
+ * For INADDR_ANY and LOOPBACK the
+ * prison_ip() call will tranmute the ip
+ * address to the proper valie.
+ */
+ if (prison_ip(p->td_ucred, 0, &sin->sin_addr.s_addr))
+ return (EINVAL);
+ }
if (sin->sin_addr.s_addr != INADDR_ANY) {
bindall = 0;
}
@@ -2180,6 +2192,11 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
return (EINVAL);
lport = sin6->sin6_port;
+ /*
+ * Jail checks for IPv6 should go HERE! i.e. add the
+ * prison_ip() equivilant in this postion to
+ * transmute the addresses to the proper one jailed.
+ */
if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
bindall = 0;
/* KAME hack: embed scopeid */
@@ -2375,11 +2392,8 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
* zero out the port to find the address! yuck! can't do
* this earlier since need port for sctp_pcb_findep()
*/
- if (sctp_ifap)
- ifa = sctp_ifap;
- else
- ifa = sctp_find_ifa_by_addr((struct sockaddr *)&store_sa,
- vrf_id, 0);
+ ifa = sctp_find_ifa_by_addr((struct sockaddr *)&store_sa,
+ vrf_id, 0);
if (ifa == NULL) {
/* Can't find an interface with that address */
SCTP_INP_WUNLOCK(inp);
@@ -3378,7 +3392,7 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
* ephemerial bind for you.
*/
if ((err = sctp_inpcb_bind(inp->sctp_socket,
- (struct sockaddr *)NULL, (struct sctp_ifa *)NULL,
+ (struct sockaddr *)NULL,
(struct thread *)NULL
))) {
/* bind error, probably perm */
@@ -4537,8 +4551,8 @@ sctp_del_local_addr_assoc(struct sctp_tcb *stcb, struct sctp_ifa *ifa)
inp = stcb->sctp_ep;
/* if subset bound and don't allow ASCONF's, can't delete last */
if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) &&
- (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_ASCONF) == 0)) {
- if (stcb->asoc.numnets < 2) {
+ sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_ASCONF)) {
+ if (stcb->sctp_ep->laddr_count < 2) {
/* can't delete last address */
return;
}
@@ -4823,6 +4837,12 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
/* the assoc was freed? */
return (-4);
}
+ /*
+ * peer must explicitly turn this on. This may have been initialized
+ * to be "on" in order to allow local addr changes while INIT's are
+ * in flight.
+ */
+ stcb->asoc.peer_supports_asconf = 0;
/* now we must go through each of the params. */
phdr = sctp_get_next_param(m, offset, &parm_buf, sizeof(parm_buf));
while (phdr) {
OpenPOWER on IntegriCloud