xref: /netbsd-src/sys/netinet/dccp_usrreq.c (revision 481d3881954fd794ca5f2d880b68c53a5db8620e)
165278823Srjs /*	$KAME: dccp_usrreq.c,v 1.67 2005/11/03 16:05:04 nishida Exp $	*/
2*481d3881Srin /*	$NetBSD: dccp_usrreq.c,v 1.27 2024/07/05 04:31:54 rin Exp $ */
365278823Srjs 
465278823Srjs /*
565278823Srjs  * Copyright (c) 2003 Joacim H�ggmark, Magnus Erixzon, Nils-Erik Mattsson
665278823Srjs  * All rights reserved.
765278823Srjs  *
865278823Srjs  * Redistribution and use in source and binary forms, with or without
965278823Srjs  * modification, are permitted provided that the following conditions
1065278823Srjs  * are met:
1165278823Srjs  *
1265278823Srjs  * 1. Redistributions of source code must retain the above copyright
1365278823Srjs  *    notice, this list of conditions and the following disclaimer.
1465278823Srjs  * 2. Redistributions in binary form must reproduce the above copyright
1565278823Srjs  *    notice, this list of conditions and the following disclaimer in the
1665278823Srjs  *    documentation and/or other materials provided with the distribution.
1765278823Srjs  * 3. The name of the author may not be used to endorse or promote products
1865278823Srjs  *    derived from this software without specific prior written permission.
1965278823Srjs  *
2065278823Srjs  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2165278823Srjs  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2265278823Srjs  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2365278823Srjs  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2465278823Srjs  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2565278823Srjs  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2665278823Srjs  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2765278823Srjs  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2865278823Srjs  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2965278823Srjs  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3065278823Srjs  *
3165278823Srjs  * Id: dccp_usrreq.c,v 1.47 2003/07/31 11:23:08 joahag-9 Exp
3265278823Srjs  */
3365278823Srjs 
3465278823Srjs /*
3565278823Srjs  * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
3665278823Srjs  *	The Regents of the University of California.  All rights reserved.
3765278823Srjs  *
3865278823Srjs  * Redistribution and use in source and binary forms, with or without
3965278823Srjs  * modification, are permitted provided that the following conditions
4065278823Srjs  * are met:
4165278823Srjs  * 1. Redistributions of source code must retain the above copyright
4265278823Srjs  *    notice, this list of conditions and the following disclaimer.
4365278823Srjs  * 2. Redistributions in binary form must reproduce the above copyright
4465278823Srjs  *    notice, this list of conditions and the following disclaimer in the
4565278823Srjs  *    documentation and/or other materials provided with the distribution.
4665278823Srjs  * 3. All advertising materials mentioning features or use of this software
4765278823Srjs  *    must display the following acknowledgement:
4865278823Srjs  *	This product includes software developed by the University of
4965278823Srjs  *	California, Berkeley and its contributors.
5065278823Srjs  * 4. Neither the name of the University nor the names of its contributors
5165278823Srjs  *    may be used to endorse or promote products derived from this software
5265278823Srjs  *    without specific prior written permission.
5365278823Srjs  *
5465278823Srjs  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
5565278823Srjs  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5665278823Srjs  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5765278823Srjs  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
5865278823Srjs  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5965278823Srjs  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
6065278823Srjs  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
6165278823Srjs  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
6265278823Srjs  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
6365278823Srjs  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
6465278823Srjs  * SUCH DAMAGE.
6565278823Srjs  *
6665278823Srjs  *	@(#)udp_usrreq.c	8.6 (Berkeley) 5/23/95
6765278823Srjs  */
6865278823Srjs 
6965278823Srjs #include <sys/cdefs.h>
70*481d3881Srin __KERNEL_RCSID(0, "$NetBSD: dccp_usrreq.c,v 1.27 2024/07/05 04:31:54 rin Exp $");
7165278823Srjs 
721c4a50f1Spooka #ifdef _KERNEL_OPT
7365278823Srjs #include "opt_inet.h"
7465278823Srjs #include "opt_dccp.h"
751c4a50f1Spooka #endif
7665278823Srjs 
7765278823Srjs #include <sys/param.h>
7865278823Srjs #include <sys/systm.h>
7965278823Srjs #include <sys/domain.h>
8065278823Srjs #include <sys/kernel.h>
8165278823Srjs #include <sys/pool.h>
8265278823Srjs #include <sys/lock.h>
8365278823Srjs #include <sys/malloc.h>
8465278823Srjs #include <sys/mbuf.h>
8565278823Srjs #include <sys/proc.h>
8665278823Srjs #include <sys/protosw.h>
8765278823Srjs #include <sys/signalvar.h>
8865278823Srjs #include <sys/socket.h>
8965278823Srjs #include <sys/socketvar.h>
9065278823Srjs #include <sys/mutex.h>
9165278823Srjs #include <sys/sysctl.h>
9265278823Srjs #include <sys/syslog.h>
9365278823Srjs #include <sys/queue.h>
9465278823Srjs 
9565278823Srjs #include <net/if.h>
9665278823Srjs 
9765278823Srjs #include <netinet/in.h>
9865278823Srjs #include <netinet/in_systm.h>
9965278823Srjs #include <netinet/ip.h>
10065278823Srjs #include <netinet/in_pcb.h>
10165278823Srjs #include <netinet/in_var.h>
10265278823Srjs #ifdef INET6
10365278823Srjs #include <netinet/ip6.h>
10465278823Srjs #endif
10565278823Srjs #include <netinet/ip_icmp.h>
10665278823Srjs #include <netinet/icmp_var.h>
10765278823Srjs #include <netinet/ip_var.h>
10865278823Srjs #ifdef INET6
10965278823Srjs #include <netinet6/in6_pcb.h>
11065278823Srjs #include <netinet6/ip6_var.h>
11165278823Srjs #include <netinet6/dccp6_var.h>
11265278823Srjs #endif
11365278823Srjs #include <netinet/dccp.h>
11465278823Srjs #include <netinet/dccp_var.h>
11565278823Srjs #include <netinet/dccp_cc_sw.h>
11665278823Srjs 
11765278823Srjs #define DEFAULT_CCID 2
11865278823Srjs 
11965278823Srjs #define INP_INFO_LOCK_INIT(x,y)
12065278823Srjs #define INP_INFO_WLOCK(x)
12165278823Srjs #define INP_INFO_WUNLOCK(x)
12265278823Srjs #define INP_INFO_RLOCK(x)
12365278823Srjs #define INP_INFO_RUNLOCK(x)
12465278823Srjs #define INP_LOCK(x)
12565278823Srjs #define IN6P_LOCK(x)
12665278823Srjs #define INP_UNLOCK(x)
12765278823Srjs #define IN6P_UNLOCK(x)
12865278823Srjs 
12965278823Srjs /* Congestion control switch table */
13065278823Srjs extern struct dccp_cc_sw cc_sw[];
13165278823Srjs 
13265278823Srjs int	dccp_log_in_vain = 1;
13365278823Srjs int	dccp_do_feature_nego = 1;
13465278823Srjs 
13565278823Srjs struct	inpcbhead dccpb;		/* from dccp_var.h */
13665278823Srjs #ifdef __FreeBSD__
13765278823Srjs struct	inpcbinfo dccpbinfo;
13865278823Srjs #else
13965278823Srjs struct	inpcbtable dccpbtable;
14065278823Srjs #endif
14165278823Srjs 
14265278823Srjs #ifndef DCCPBHASHSIZE
14365278823Srjs #define DCCPBHASHSIZE 16
14465278823Srjs #endif
14565278823Srjs 
14665278823Srjs struct	pool dccpcb_pool;
14765278823Srjs 
14865278823Srjs u_long	dccp_sendspace = 32768;
14965278823Srjs u_long	dccp_recvspace = 65536;
15065278823Srjs 
15165278823Srjs struct	dccpstat dccpstat;	/* from dccp_var.h */
15265278823Srjs 
15365278823Srjs static struct dccpcb * dccp_close(struct dccpcb *);
15465278823Srjs static int dccp_disconnect2(struct dccpcb *);
15565278823Srjs int dccp_get_option(char *, int, int, char *,int);
15665278823Srjs void dccp_parse_options(struct dccpcb *, char *, int);
15765278823Srjs int dccp_remove_feature(struct dccpcb *, u_int8_t, u_int8_t);
15865278823Srjs int dccp_add_feature_option(struct dccpcb *, u_int8_t, u_int8_t, char *, u_int8_t);
15965278823Srjs void dccp_feature_neg(struct dccpcb *, u_int8_t, u_int8_t, u_int8_t, char *);
16065278823Srjs void dccp_close_t(void *);
16165278823Srjs void dccp_timewait_t(void *);
16265278823Srjs 
16365278823Srjs /* Ack Vector functions */
16465278823Srjs #define DCCP_VECTORSIZE 512 /* initial ack and cwnd-vector size. Multiple of 8 ! */
16565278823Srjs void dccp_use_ackvector(struct dccpcb *);
16665278823Srjs void dccp_update_ackvector(struct dccpcb *, u_int64_t);
16765278823Srjs void dccp_increment_ackvector(struct dccpcb *, u_int64_t);
16865278823Srjs u_int16_t dccp_generate_ackvector(struct dccpcb *, u_char *);
16965278823Srjs u_char dccp_ackvector_state(struct dccpcb *, u_int64_t);
17065278823Srjs 
17165278823Srjs /*
17265278823Srjs  * DCCP initialization
17365278823Srjs  */
17465278823Srjs void
dccp_init(void)17565278823Srjs dccp_init(void)
17665278823Srjs {
17765278823Srjs 	pool_init(&dccpcb_pool, sizeof(struct dccpcb), 0, 0, 0, "dccpcbpl",
17865278823Srjs 		  NULL, IPL_SOFTNET);
17965278823Srjs 
1802ba9f052Sozaki-r 	inpcb_init(&dccpbtable, DCCPBHASHSIZE, DCCPBHASHSIZE);
18165278823Srjs }
18265278823Srjs 
18365278823Srjs void
dccp_input(struct mbuf * m,int off,int proto)18415652348Smaxv dccp_input(struct mbuf *m, int off, int proto)
18565278823Srjs {
18665278823Srjs 	int iphlen;
18765278823Srjs 	struct ip *ip = NULL;
18865278823Srjs 	struct dccphdr *dh;
18965278823Srjs 	struct dccplhdr *dlh;
19065278823Srjs 	struct inpcb *inp = NULL, *oinp = NULL;
19165278823Srjs 	struct dccpcb *dp;
19265278823Srjs 	struct ipovly *ipov = NULL;
19365278823Srjs 	struct dccp_requesthdr *drqh;
19465278823Srjs 	struct dccp_ackhdr *dah = NULL;
19565278823Srjs 	struct dccp_acklhdr *dalh = NULL;
19665278823Srjs 	struct dccp_resethdr *drth;
19765278823Srjs 	struct socket *so;
19865278823Srjs 	u_char *optp = NULL;
19965278823Srjs 	struct mbuf *opts = 0;
20065278823Srjs 	int len, data_off, extrah_len, optlen;
20165278823Srjs 	/*struct ip save_ip;*/
20265278823Srjs 	char options[DCCP_MAX_OPTIONS];
20365278823Srjs 	char test[2];
20465278823Srjs 	u_int32_t cslen;
20565278823Srjs 	dccp_seq seqnr, low_seqnr, high_seqnr;
20665278823Srjs 	int isipv6 = 0;
20765278823Srjs 	int is_shortseq; /* Is this shortseq packet? */
20865278823Srjs #ifdef INET6
20965278823Srjs 	struct ip6_hdr *ip6 = NULL;
21065278823Srjs #endif
21165278823Srjs 
21215652348Smaxv 	iphlen = off;
21365278823Srjs 
21465278823Srjs 	DCCP_DEBUG((LOG_INFO, "Got DCCP packet!\n"));
21565278823Srjs 
21665278823Srjs 	dccpstat.dccps_ipackets++;
21765278823Srjs 	dccpstat.dccps_ibytes += m->m_pkthdr.len;
21865278823Srjs 
21965278823Srjs #ifdef INET6
22065278823Srjs 	isipv6 = (mtod(m, struct ip *)->ip_v == 6) ? 1 : 0;
22165278823Srjs #endif
22265278823Srjs 
22365278823Srjs #ifdef INET6
22465278823Srjs 	if (isipv6) {
22565278823Srjs 		DCCP_DEBUG((LOG_INFO, "Got DCCP ipv6 packet, iphlen = %u!\n", iphlen));
22665278823Srjs 		ip6 = mtod(m, struct ip6_hdr *);
227a1d8c752Smaxv 		M_REGION_GET(dh, struct dccphdr *, m, iphlen, sizeof(*dh));
22865278823Srjs 		if (dh == NULL) {
22965278823Srjs 			dccpstat.dccps_badlen++;
23065278823Srjs 			return;
23165278823Srjs 		}
23265278823Srjs 	} else
23365278823Srjs #endif
23465278823Srjs 	{
23565278823Srjs 		/*
23665278823Srjs 		 * Strip IP options, if any; should skip this,
23765278823Srjs 		 * make available to user, and use on returned packets,
23865278823Srjs 		 * but we don't yet have a way to check the checksum
23965278823Srjs 		 * with options still present.
24065278823Srjs 		 */
24165278823Srjs 		if (iphlen > sizeof (struct ip)) {
24265278823Srjs 			DCCP_DEBUG((LOG_INFO, "Need to strip options\n"));
24365278823Srjs #if 0				/* XXX */
24465278823Srjs 			ip_stripoptions(m, (struct mbuf *)0);
24565278823Srjs #endif
24665278823Srjs 			iphlen = sizeof(struct ip);
24765278823Srjs 		}
24865278823Srjs 
24965278823Srjs 		/*
25065278823Srjs 		 * Get IP and DCCP header together in first mbuf.
25165278823Srjs 		 */
25265278823Srjs 		ip = mtod(m, struct ip *);
253a1d8c752Smaxv 		M_REGION_GET(dh, struct dccphdr *, m, iphlen, sizeof(*dh));
25465278823Srjs 		if (dh == NULL) {
25565278823Srjs 			dccpstat.dccps_badlen++;
25665278823Srjs 			return;
25765278823Srjs 		}
25865278823Srjs 	}
25965278823Srjs 	dlh = (struct dccplhdr*)dh;
26065278823Srjs 	is_shortseq = !dh->dh_x;
26165278823Srjs 
26265278823Srjs 	if (!is_shortseq) {
26365278823Srjs 		DCCP_DEBUG((LOG_INFO,
26465278823Srjs 		"Header info: cslen = %u, off = %u, type = %u, reserved = %u, seq = %u.%lu\n",
26565278823Srjs 			 dlh->dh_cscov, dlh->dh_off, dlh->dh_type, dlh->dh_res, ntohs(dlh->dh_seq),
26665278823Srjs 			 (unsigned long)ntohl(dlh->dh_seq2)));
26765278823Srjs 	} else {
26865278823Srjs 		DCCP_DEBUG((LOG_INFO,
26965278823Srjs 		"Header info(short): cslen = %u, off = %u, type = %u, reserved = %u, seq = %u\n",
27065278823Srjs 			dh->dh_cscov, dh->dh_off, dh->dh_type, dh->dh_res, ntohl(dh->dh_seq)));
27165278823Srjs 	}
27265278823Srjs 
27365278823Srjs 	/*
27465278823Srjs 	 * Make mbuf data length reflect DCCP length.
27565278823Srjs 	 * If not enough data to reflect DCCP length, drop.
27665278823Srjs 	 */
27765278823Srjs 
27865278823Srjs #ifdef INET6
27965278823Srjs 	if (isipv6)
28065278823Srjs 		len = m->m_pkthdr.len - off;
28165278823Srjs 	else
28265278823Srjs #endif
28365278823Srjs 	{
28465278823Srjs 		len = ntohs(ip->ip_len);
28565278823Srjs 		len -= ip->ip_hl << 2;
28665278823Srjs 	}
28765278823Srjs 
28865278823Srjs 	if (len < sizeof(struct dccphdr)) {
28965278823Srjs 		DCCP_DEBUG((LOG_INFO, "Dropping DCCP packet!\n"));
29065278823Srjs 		dccpstat.dccps_badlen++;
29165278823Srjs 		goto badunlocked;
29265278823Srjs 	}
29365278823Srjs 	/*
29465278823Srjs 	 * Save a copy of the IP header in case we want restore it
29565278823Srjs 	 * for sending a DCCP reset packet in response.
29665278823Srjs 	 */
29765278823Srjs 	if (!isipv6) {
29865278823Srjs 		/*save_ip = *ip;*/
29965278823Srjs 		ipov = (struct ipovly *)ip;
30065278823Srjs 	}
30165278823Srjs 
30265278823Srjs 	if (dh->dh_cscov == 0) {
30365278823Srjs 		cslen = len;
30465278823Srjs 	} else {
30565278823Srjs 		cslen = dh->dh_off * 4 + (dh->dh_cscov - 1) * 4;
30665278823Srjs 		if (cslen > len)
30765278823Srjs 			cslen = len;
30865278823Srjs 	}
30965278823Srjs 
31065278823Srjs 	/*
31165278823Srjs 	 * Checksum extended DCCP header and data.
31265278823Srjs 	 */
31365278823Srjs 
31465278823Srjs #ifdef INET6
31565278823Srjs 	if (isipv6) {
31665278823Srjs 		if (in6_cksum(m, IPPROTO_DCCP, off, cslen) != 0) {
31765278823Srjs 			dccpstat.dccps_badsum++;
31865278823Srjs 			goto badunlocked;
31965278823Srjs 		}
32065278823Srjs 	} else
32165278823Srjs #endif
32265278823Srjs 	{
323a72ef8c3Srjs 		memset(ipov->ih_x1, 0, sizeof(ipov->ih_x1));
32465278823Srjs 		ip->ip_len = htons(m->m_pkthdr.len);
32565278823Srjs 		dh->dh_sum = in4_cksum(m, IPPROTO_DCCP, off, cslen);
32665278823Srjs 
32765278823Srjs 		if (dh->dh_sum) {
32865278823Srjs 			dccpstat.dccps_badsum++;
32965278823Srjs 			goto badunlocked;
33065278823Srjs 		}
33165278823Srjs 	}
33265278823Srjs 
33365278823Srjs 	INP_INFO_WLOCK(&dccpbinfo);
33465278823Srjs 
33565278823Srjs 	/*
33665278823Srjs 	 * Locate pcb for datagram.
33765278823Srjs 	 */
33865278823Srjs #ifdef INET6
33965278823Srjs 	if (isipv6) {
340b000e63fSozaki-r 		inp = in6pcb_lookup(&dccpbtable, &ip6->ip6_src,
34165278823Srjs 		    dh->dh_sport, &ip6->ip6_dst, dh->dh_dport, 0, 0);
342f8c27a68Sozaki-r 		if (inp == NULL) {
34365278823Srjs 			/* XXX stats increment? */
344b000e63fSozaki-r 			inp = in6pcb_lookup_bound(&dccpbtable, &ip6->ip6_dst,
34565278823Srjs 			    dh->dh_dport, 0);
34665278823Srjs 		}
34765278823Srjs 	} else
34865278823Srjs #endif
34965278823Srjs 	{
3502ba9f052Sozaki-r 		inp = inpcb_lookup(&dccpbtable, ip->ip_src,
35165278823Srjs 		    dh->dh_sport, ip->ip_dst, dh->dh_dport, 0);
35265278823Srjs 		if (inp == NULL) {
35365278823Srjs 			/* XXX stats increment? */
3542ba9f052Sozaki-r 			inp = inpcb_lookup_bound(&dccpbtable, ip->ip_dst,
35565278823Srjs 			    dh->dh_dport);
35665278823Srjs 		}
35765278823Srjs 	}
35865278823Srjs 	if (isipv6) {
359f8c27a68Sozaki-r 		DCCP_DEBUG((LOG_INFO, "in6p=%p\n", inp));
36065278823Srjs 	} else {
36165278823Srjs 		DCCP_DEBUG((LOG_INFO, "inp=%p\n", inp));
36265278823Srjs 	}
36365278823Srjs 
364f8c27a68Sozaki-r 	if (inp == NULL) {
36565278823Srjs 		if (dccp_log_in_vain) {
36665278823Srjs #ifdef INET6
36765278823Srjs 			char dbuf[INET6_ADDRSTRLEN+2], sbuf[INET6_ADDRSTRLEN+2];
36865278823Srjs #else
36965278823Srjs 			char dbuf[4*sizeof "123"], sbuf[4*sizeof "123"];
37065278823Srjs #endif
37165278823Srjs 
37265278823Srjs #ifdef INET6
37365278823Srjs 			if (isipv6) {
37428f4c24cSryo 				char ip6buf[INET6_ADDRSTRLEN];
37565278823Srjs 				strlcpy(dbuf, "[", sizeof dbuf);
37635561f6bSchristos 				strlcat(dbuf, IN6_PRINT(ip6buf, &ip6->ip6_dst), sizeof dbuf);
37765278823Srjs 				strlcat(dbuf, "]", sizeof dbuf);
37865278823Srjs 				strlcpy(sbuf, "[", sizeof sbuf);
37935561f6bSchristos 				strlcat(sbuf, IN6_PRINT(ip6buf, &ip6->ip6_src), sizeof sbuf);
38065278823Srjs 				strlcat(sbuf, "]", sizeof sbuf);
38165278823Srjs 			} else
38265278823Srjs #endif
38365278823Srjs 			{
38465278823Srjs 				strlcpy(dbuf, inet_ntoa(ip->ip_dst), sizeof dbuf);
38565278823Srjs 				strlcpy(sbuf, inet_ntoa(ip->ip_src), sizeof sbuf);
38665278823Srjs 			}
38765278823Srjs 			log(LOG_INFO,
38865278823Srjs 			    "Connection attempt to DCCP %s:%d from %s:%d\n",
38965278823Srjs 			    dbuf, ntohs(dh->dh_dport), sbuf,
39065278823Srjs 			    ntohs(dh->dh_sport));
39165278823Srjs 		}
39265278823Srjs 		dccpstat.dccps_noport++;
39365278823Srjs 
39465278823Srjs 		/*
39565278823Srjs 		 * We should send DCCP reset here but we can't call dccp_output
39665278823Srjs 		 * since we have no dccpcb. A icmp unreachable works great but
39765278823Srjs 		 * the specs says DCCP reset :(
39865278823Srjs 		 *
39965278823Srjs 		 * if (!isipv6) {
40065278823Srjs 		 *	*ip = save_ip;
40165278823Srjs 		 *	ip->ip_len += iphlen;
40265278823Srjs 		 *	icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
40365278823Srjs 		 * }
40465278823Srjs 		 */
40565278823Srjs 
40665278823Srjs 		INP_INFO_WUNLOCK(&dccpbinfo);
40765278823Srjs 		goto badunlocked;
40865278823Srjs 	}
40965278823Srjs 	INP_LOCK(inp);
41065278823Srjs 
41165278823Srjs 	dp = intodccpcb(inp);
412f8c27a68Sozaki-r 	if (dp == NULL) {
41365278823Srjs 		INP_UNLOCK(inp);
41465278823Srjs 		INP_INFO_WUNLOCK(&dccpbinfo);
41565278823Srjs 		goto badunlocked;
41665278823Srjs 	}
41765278823Srjs 
41865278823Srjs 	if (dp->state == DCCPS_CLOSED) {
41965278823Srjs 		DCCP_DEBUG((LOG_INFO, "We are in closed state, dropping packet and sending reset!\n"));
42065278823Srjs 		if (dh->dh_type != DCCP_TYPE_RESET)
42165278823Srjs 			dccp_output(dp, DCCP_TYPE_RESET + 2);
42265278823Srjs 		INP_UNLOCK(inp);
42365278823Srjs 		INP_INFO_WUNLOCK(&dccpbinfo);
42465278823Srjs 		goto badunlocked;
42565278823Srjs 	}
42665278823Srjs 
42765278823Srjs 	so = inp->inp_socket;
42865278823Srjs 
42965278823Srjs 	if (so->so_options & SO_ACCEPTCONN) {
43065278823Srjs 		DCCP_DEBUG((LOG_INFO, "so->options & SO_ACCEPTCONN! dp->state = %i\n", dp->state));
43165278823Srjs 		so = sonewconn(so, SS_ISCONNECTED);
43265278823Srjs 		if (so == 0) {
43365278823Srjs 			DCCP_DEBUG((LOG_INFO, "Error, sonewconn failed!\n"));
43465278823Srjs 			INP_UNLOCK(inp);
43565278823Srjs 			INP_INFO_WUNLOCK(&dccpbinfo);
43665278823Srjs 			goto badunlocked;
43765278823Srjs 		}
43865278823Srjs 
43965278823Srjs 		/* INP_LOCK(inp); XXX */
44065278823Srjs 
44165278823Srjs 		oinp = inp;
44265278823Srjs 
44365278823Srjs #ifdef INET6
44465278823Srjs 		if (isipv6) {
445f8c27a68Sozaki-r 			inp = sotoinpcb(so);
4467118c214Sozaki-r 			in6p_laddr(inp) = ip6->ip6_dst;
4477118c214Sozaki-r 			in6p_faddr(inp) = ip6->ip6_src;
448f8c27a68Sozaki-r 			inp->inp_lport = dh->dh_dport;
449f8c27a68Sozaki-r 			inp->inp_fport = dh->dh_sport;
4502ba9f052Sozaki-r 			inpcb_set_state(inp, INP_CONNECTED);
45165278823Srjs 		} else
45265278823Srjs #endif
45365278823Srjs 		{
45465278823Srjs 			inp = sotoinpcb(so);
4557118c214Sozaki-r 			in4p_laddr(inp) = ip->ip_dst;
4567118c214Sozaki-r 			in4p_faddr(inp) = ip->ip_src;
45765278823Srjs 			inp->inp_lport = dh->dh_dport;
45865278823Srjs 			inp->inp_fport = dh->dh_sport;
45965278823Srjs 		}
46065278823Srjs 
46165278823Srjs 		if (!isipv6)
4622ba9f052Sozaki-r 			inpcb_set_state(inp, INP_BOUND);
46365278823Srjs 
464f8c27a68Sozaki-r 		dp = inp->inp_ppcb;
46565278823Srjs 
46665278823Srjs 		dp->state = DCCPS_LISTEN;
46765278823Srjs 		dp->who = DCCP_SERVER;
46865278823Srjs 		dp->cslen = ((struct dccpcb *)oinp->inp_ppcb)->cslen;
46965278823Srjs 		dp->avgpsize = ((struct dccpcb *)oinp->inp_ppcb)->avgpsize;
47065278823Srjs 		dp->scode = ((struct dccpcb *)oinp->inp_ppcb)->scode;
47165278823Srjs 		dp->seq_snd = (((u_int64_t)random() << 32) | random()) % 281474976710656LL;
47265278823Srjs 		dp->ref_seq.hi = dp->seq_snd >> 24;
47365278823Srjs 		dp->ref_seq.lo = (u_int64_t)(dp->seq_snd & 0xffffff);
47465278823Srjs 		INP_UNLOCK(oinp);
47565278823Srjs 		DCCP_DEBUG((LOG_INFO, "New dp = %u, dp->state = %u!\n", (int)dp, dp->state));
47665278823Srjs 	}
47765278823Srjs 
47865278823Srjs 	INP_INFO_WUNLOCK(&dccpbinfo);
47965278823Srjs 
48065278823Srjs 	/*
48165278823Srjs 	 * Check if sequence number is inside the loss window
48265278823Srjs 	 */
48365278823Srjs 	if (!is_shortseq) {
48465278823Srjs 		DHDR_TO_DSEQ(seqnr, dlh);
48565278823Srjs 	} else {
48665278823Srjs 		/* shortseq */
48765278823Srjs 		seqnr = CONVERT_TO_LONGSEQ((ntohl(dh->dh_seq) >> 8), dp->ref_pseq);
48865278823Srjs 		DCCP_DEBUG((LOG_INFO, "short seq conversion %x,  %u %u\n",
48965278823Srjs 			ntohl(dh->dh_seq) >> 8, dp->ref_pseq.hi, dp->ref_pseq.lo));
49065278823Srjs 	}
49165278823Srjs 
49265278823Srjs 	DCCP_DEBUG((LOG_INFO, "Received DCCP packet with sequence number = %llu , gsn_rcv %llu\n", seqnr, dp->gsn_rcv));
49365278823Srjs 
49465278823Srjs 	/* store ccval */
49565278823Srjs 	dp->ccval = dh->dh_ccval;
49665278823Srjs 
49765278823Srjs 	if (dp->gsn_rcv == 281474976710656LL) dp->gsn_rcv = seqnr;
49865278823Srjs 	if (dp->gsn_rcv > (dp->loss_window / 4))
49965278823Srjs 		low_seqnr = (dp->gsn_rcv - (dp->loss_window / 4)) % 281474976710656LL;
50065278823Srjs 	else
50165278823Srjs 		low_seqnr = 0ll;
50265278823Srjs 	high_seqnr = (dp->gsn_rcv + (dp->loss_window / 4 * 3)) % 281474976710656LL;
50365278823Srjs 
50465278823Srjs 	if (! (DCCP_SEQ_GT(seqnr, low_seqnr) && DCCP_SEQ_LT(seqnr, high_seqnr))) {
50565278823Srjs 		dccpstat.dccps_badseq++;
50632cded6cSdholland 		DCCP_DEBUG((LOG_INFO, "Received DCCP packet with bad sequence number = %llu (low_seqnr = %llu, high_seqnr = %llu)\n", seqnr, low_seqnr, high_seqnr));
50765278823Srjs 		INP_UNLOCK(inp);
50865278823Srjs 		goto badunlocked;
50965278823Srjs 	}
51065278823Srjs 
51165278823Srjs 	/* dp->gsn_rcv should always be the highest received valid sequence number */
51265278823Srjs 	if (DCCP_SEQ_GT(seqnr, dp->gsn_rcv))
51365278823Srjs 		dp->gsn_rcv = seqnr;
51465278823Srjs 
51565278823Srjs 	/* Just ignore DCCP-Move for now */
51665278823Srjs 	if (dlh->dh_type == DCCP_TYPE_DATA) {
51765278823Srjs 		extrah_len = 0;
51865278823Srjs 		if (!is_shortseq)
51965278823Srjs 			optp = (u_char *)(dlh + 1);
52065278823Srjs 		else
52165278823Srjs 			optp = (u_char *)(dh + 1);
52265278823Srjs 	} else if (dh->dh_type == DCCP_TYPE_REQUEST) {
52365278823Srjs 		drqh = (struct dccp_requesthdr *)(dlh + 1);
52465278823Srjs 		if (drqh->drqh_scode != dp->scode){
52565278823Srjs 			DCCP_DEBUG((LOG_INFO, "service code in request packet doesn't match! %x %x\n", drqh->drqh_scode, dp->scode));
52665278823Srjs 			INP_UNLOCK(inp);
52765278823Srjs 			dp->state = DCCPS_SERVER_CLOSE; /* So disconnect2 doesn't send CLOSEREQ */
52865278823Srjs 			dccp_disconnect2(dp);
52965278823Srjs 			dccp_output(dp, DCCP_TYPE_RESET + 2);
53065278823Srjs 			dccp_close(dp);
53165278823Srjs 			goto badunlocked;
53265278823Srjs 		}
53365278823Srjs 		optp = (u_char *)(drqh + 1);
53465278823Srjs 		extrah_len = 4;
53565278823Srjs 
53665278823Srjs 		/* store reference peer sequence number */
53765278823Srjs 		dp->ref_pseq.hi = seqnr >> 24;
53865278823Srjs 		dp->ref_pseq.lo = (u_int64_t)(seqnr & 0xffffff);
53965278823Srjs 
54065278823Srjs 	} else if (dh->dh_type == DCCP_TYPE_RESET) {
54165278823Srjs 		extrah_len = 8 ;
54265278823Srjs 		drth = (struct dccp_resethdr *)(dlh + 1);
54365278823Srjs 		optp = (u_char *)(drth + 1);
54465278823Srjs 	} else {
54565278823Srjs 		if (!is_shortseq){
54665278823Srjs 			extrah_len = 8;
54765278823Srjs 			dalh = (struct dccp_acklhdr *)(dlh + 1);
54865278823Srjs 			if (dh->dh_type == DCCP_TYPE_RESPONSE) {
54965278823Srjs 				extrah_len += 4;
55065278823Srjs 				drqh = (struct dccp_requesthdr *)(dalh + 1);
55165278823Srjs 				if (drqh->drqh_scode != dp->scode){
55265278823Srjs 					DCCP_DEBUG((LOG_INFO, "service code in response packet doesn't match! %x %x\n", drqh->drqh_scode, dp->scode));
55365278823Srjs 					INP_UNLOCK(inp);
55465278823Srjs 					dp->state = DCCPS_CLIENT_CLOSE; /* So disconnect2 doesn't send CLOSEREQ */
55565278823Srjs 					dccp_disconnect2(dp);
55665278823Srjs 					dccp_output(dp, DCCP_TYPE_RESET + 2);
55765278823Srjs 					dccp_close(dp);
55865278823Srjs 					goto badunlocked;
55965278823Srjs 				}
56065278823Srjs 				optp = (u_char *)(drqh + 1);
56165278823Srjs 
56265278823Srjs 				/* store reference peer sequence number */
56365278823Srjs 				dp->ref_pseq.hi = seqnr >> 24;
56465278823Srjs 				dp->ref_pseq.lo = (u_int64_t)(seqnr & 0xffffff);
56565278823Srjs 			} else
56665278823Srjs 				optp = (u_char *)(dalh + 1);
56765278823Srjs 		} else {
56865278823Srjs 			extrah_len = 4;
56965278823Srjs 			dah = (struct dccp_ackhdr *)(dh + 1);
57065278823Srjs 			optp = (u_char *)(dah + 1);
57165278823Srjs 		}
57265278823Srjs 
57365278823Srjs 	}
57465278823Srjs 
57565278823Srjs 	data_off = (dh->dh_off << 2);
57665278823Srjs 
57765278823Srjs 	dp->seq_rcv = seqnr;
57865278823Srjs 	dp->ack_rcv = 0; /* Clear it for now */
57965278823Srjs 	dp->type_rcv = dh->dh_type;
58065278823Srjs 	dp->len_rcv = m->m_len - data_off - iphlen; /* Correct length ? */
58165278823Srjs 
58265278823Srjs 	if (!is_shortseq)
58365278823Srjs 		optlen = data_off - (sizeof(struct dccplhdr) + extrah_len);
58465278823Srjs 	else
58565278823Srjs 		optlen = data_off - (sizeof(struct dccphdr) + extrah_len);
58665278823Srjs 
58765278823Srjs 	if (optlen < 0) {
58865278823Srjs 		DCCP_DEBUG((LOG_INFO, "Data offset is smaller then it could be, optlen = %i data_off = %i, m_len = %i, iphlen = %i extrah_len = %i !\n", optlen, data_off, m->m_len, iphlen, extrah_len));
58965278823Srjs 		INP_UNLOCK(inp);
59065278823Srjs 		goto badunlocked;
59165278823Srjs 	}
59265278823Srjs 
59365278823Srjs 	if (optlen > 0) {
59465278823Srjs 		if (optlen > DCCP_MAX_OPTIONS) {
59565278823Srjs 			DCCP_DEBUG((LOG_INFO, "Error, more options (%i) then DCCP_MAX_OPTIONS options!\n", optlen));
59665278823Srjs 			INP_UNLOCK(inp);
59765278823Srjs 			goto badunlocked;
59865278823Srjs 		}
59965278823Srjs 
60065278823Srjs 		DCCP_DEBUG((LOG_INFO, "Parsing DCCP options, optlen = %i\n", optlen));
601a72ef8c3Srjs 		memcpy(options, optp, optlen);
60265278823Srjs 		dccp_parse_options(dp, options, optlen);
60365278823Srjs 	}
60465278823Srjs 
60565278823Srjs 	DCCP_DEBUG((LOG_INFO, "BEFORE state check, Got a %u packet while in %u state, who = %u!\n", dh->dh_type, dp->state, dp->who));
60665278823Srjs 
60765278823Srjs 	if (dp->state == DCCPS_LISTEN) {
60865278823Srjs 		switch (dh->dh_type) {
60965278823Srjs 
61065278823Srjs 		case DCCP_TYPE_REQUEST:
61165278823Srjs 			DCCP_DEBUG((LOG_INFO, "Got DCCP REQUEST\n"));
61265278823Srjs 			dp->state = DCCPS_REQUEST;
61365278823Srjs 			if (dp->cc_in_use[1] < 0) {
61465278823Srjs 				test[0] = DEFAULT_CCID;
61565278823Srjs 				test[1] = 3;
61665278823Srjs 				dccp_add_feature(dp, DCCP_OPT_CHANGE_R, DCCP_FEATURE_CC, test, 2);
61765278823Srjs 			}
61865278823Srjs 			if (len > data_off) {
61965278823Srjs 				DCCP_DEBUG((LOG_INFO, "XXX: len=%d, data_off=%d\n", len, data_off));
62065278823Srjs 				dccp_add_option(dp, DCCP_OPT_DATA_DISCARD, test, 0);
62165278823Srjs 			}
62265278823Srjs 			callout_reset(&dp->connect_timer, DCCP_CONNECT_TIMER,
62365278823Srjs 			    dccp_connect_t, dp);
62465278823Srjs 			dccp_output(dp, 0);
62565278823Srjs 			break;
62665278823Srjs 
62765278823Srjs 
62865278823Srjs 		/* These are ok if the sender has a valid init Cookie */
62965278823Srjs 		case DCCP_TYPE_ACK:
63065278823Srjs 		case DCCP_TYPE_DATAACK:
63165278823Srjs 		case DCCP_TYPE_DATA:
63265278823Srjs 			DCCP_DEBUG((LOG_INFO, "Got DCCP ACK/DATAACK/DATA, should check init cookie...\n"));
63365278823Srjs 			dccp_output(dp, DCCP_TYPE_RESET + 2);
63465278823Srjs 			break;
63565278823Srjs 
63665278823Srjs 		case DCCP_TYPE_RESET:
63765278823Srjs 			DCCP_DEBUG((LOG_INFO, "Got DCCP RESET\n"));
63865278823Srjs 			dp->state = DCCPS_TIME_WAIT;
63965278823Srjs 			dp = dccp_close(dp);
64065278823Srjs 			return;
64165278823Srjs 
64265278823Srjs 		default:
64365278823Srjs 			DCCP_DEBUG((LOG_INFO, "Got a %u packet while in listen stage!\n", dh->dh_type));
64465278823Srjs 			/* Force send reset. */
64565278823Srjs 			dccp_output(dp, DCCP_TYPE_RESET + 2);
64665278823Srjs 		}
64765278823Srjs 	} else if (dp->state == DCCPS_REQUEST) {
64865278823Srjs 		switch (dh->dh_type) {
64965278823Srjs 		case DCCP_TYPE_RESPONSE:
65065278823Srjs 			DAHDR_TO_DSEQ(dp->ack_rcv, ((struct dccp_acklhdr*)dalh)->dash);
65165278823Srjs 			dp->ack_snd = dp->seq_rcv;
65265278823Srjs 			DCCP_DEBUG((LOG_INFO, "Got DCCP REPSONSE %x %llx\n", dp, dp->ack_snd));
65365278823Srjs 
65465278823Srjs 			callout_stop(&dp->retrans_timer);
65565278823Srjs 			callout_stop(&dp->connect_timer);
65665278823Srjs 
65765278823Srjs 			/* First check if we have negotiated a cc */
65865278823Srjs 			if (dp->cc_in_use[0] > 0 && dp->cc_in_use[1] > 0) {
65965278823Srjs 				DCCP_DEBUG((LOG_INFO, "Setting DCCPS_ESTAB & soisconnected\n"));
66065278823Srjs 				dp->state = DCCPS_ESTAB;
66165278823Srjs 				dccpstat.dccps_connects++;
66265278823Srjs 				soisconnected(inp->inp_socket);
66365278823Srjs 			} else {
66465278823Srjs 				dp->state = DCCPS_RESPOND;
66565278823Srjs 				DCCP_DEBUG((LOG_INFO, "CC negotiation is not finished, cc_in_use[0] = %u, cc_in_use[1] = %u\n",dp->cc_in_use[0], dp->cc_in_use[1]));
66665278823Srjs 
66765278823Srjs 			}
66865278823Srjs 			dccp_output(dp, 0);
66965278823Srjs 			break;
67065278823Srjs 
67165278823Srjs 		case DCCP_TYPE_RESET:
67265278823Srjs 			DCCP_DEBUG((LOG_INFO, "Got DCCP RESET\n"));
67365278823Srjs 			dp->state = DCCPS_TIME_WAIT;
67465278823Srjs 			dp = dccp_close(dp);
67565278823Srjs 			return;
67665278823Srjs 
67765278823Srjs 		default:
67865278823Srjs 			DCCP_DEBUG((LOG_INFO, "Got a %u packet while in REQUEST stage!\n", dh->dh_type));
67965278823Srjs 			/* Force send reset. */
68065278823Srjs 			dccp_output(dp, DCCP_TYPE_RESET + 2);
68165278823Srjs 			if (dh->dh_type == DCCP_TYPE_CLOSE) {
68265278823Srjs 				dp = dccp_close(dp);
68365278823Srjs 				return;
68465278823Srjs 			} else {
68565278823Srjs 				callout_stop(&dp->retrans_timer);
68665278823Srjs 				dp->state = DCCPS_TIME_WAIT;
68765278823Srjs 			}
68865278823Srjs 		}
68965278823Srjs 	} else if (dp->state == DCCPS_RESPOND) {
69065278823Srjs 		switch (dh->dh_type) {
69165278823Srjs 
69265278823Srjs 		case DCCP_TYPE_REQUEST:
69365278823Srjs 			break;
69465278823Srjs 		case DCCP_TYPE_ACK:
69565278823Srjs 		case DCCP_TYPE_DATAACK:
69665278823Srjs 			DCCP_DEBUG((LOG_INFO, "Got DCCP ACK/DATAACK\n"));
69765278823Srjs 
69865278823Srjs 			callout_stop(&dp->connect_timer);
69965278823Srjs 
70065278823Srjs 			if (!is_shortseq) {
70165278823Srjs 				DAHDR_TO_DSEQ(dp->ack_rcv, ((struct dccp_acklhdr*)dalh)->dash);
70265278823Srjs 			} else {
70365278823Srjs 				/* shortseq XXX */
70465278823Srjs 				dp->ack_rcv = CONVERT_TO_LONGSEQ((ntohl(dah->dash.dah_ack) >> 8), dp->ref_seq);
70565278823Srjs 			}
70665278823Srjs 
70765278823Srjs 			if (dp->cc_in_use[0] > 0 && dp->cc_in_use[1] > 0) {
70865278823Srjs 				DCCP_DEBUG((LOG_INFO, "Setting DCCPS_ESTAB & soisconnected\n"));
70965278823Srjs 				dp->state = DCCPS_ESTAB;
71065278823Srjs 				dccpstat.dccps_connects++;
71165278823Srjs 				soisconnected(inp->inp_socket);
71265278823Srjs 			} else {
71365278823Srjs 				DCCP_DEBUG((LOG_INFO, "CC negotiation is not finished, cc_in_use[0] = %u, cc_in_use[1] = %u\n",dp->cc_in_use[0], dp->cc_in_use[1]));
71465278823Srjs 				/* Force an output!!! */
71565278823Srjs 				dp->ack_snd = dp->seq_rcv;
71665278823Srjs 				dccp_output(dp, 0);
71765278823Srjs 			}
71865278823Srjs 
71965278823Srjs 			if (dh->dh_type == DCCP_TYPE_DATAACK && dp->cc_in_use[1] > 0) {
72065278823Srjs 				if (!dp->ack_snd) dp->ack_snd = dp->seq_rcv;
72165278823Srjs 				DCCP_DEBUG((LOG_INFO, "Calling *cc_sw[%u].cc_recv_packet_recv!\n", dp->cc_in_use[1]));
72265278823Srjs 				(*cc_sw[dp->cc_in_use[1]].cc_recv_packet_recv)(dp->cc_state[1], options, optlen);
72365278823Srjs 			}
72465278823Srjs 			break;
72565278823Srjs 
72665278823Srjs 		case DCCP_TYPE_CLOSE:
72765278823Srjs 			dccp_output(dp, DCCP_TYPE_CLOSE + 1);
72865278823Srjs 			dp = dccp_close(dp);
72965278823Srjs 			goto badunlocked;
73065278823Srjs 
73165278823Srjs 		case DCCP_TYPE_RESET:
73265278823Srjs 			dp->state = DCCPS_TIME_WAIT;
73365278823Srjs 			callout_stop(&dp->retrans_timer);
73465278823Srjs 			break;
73565278823Srjs 
73665278823Srjs 		default:
73765278823Srjs 			DCCP_DEBUG((LOG_INFO, "Got a %u packet while in response stage!\n", dh->dh_type));
73865278823Srjs 			/* Force send reset. */
73965278823Srjs 			dccp_output(dp, DCCP_TYPE_RESET + 2);
74065278823Srjs 		}
74165278823Srjs 	} else if (dp->state == DCCPS_ESTAB) {
74265278823Srjs 		switch (dh->dh_type) {
74365278823Srjs 
74465278823Srjs 		case DCCP_TYPE_DATA:
74565278823Srjs 			DCCP_DEBUG((LOG_INFO, "Got DCCP DATA, state = %i, cc_in_use[1] = %u\n", dp->state, dp->cc_in_use[1]));
74665278823Srjs 
74765278823Srjs 			if (dp->cc_in_use[1] > 0) {
74865278823Srjs 				if (!dp->ack_snd) dp->ack_snd = dp->seq_rcv;
74965278823Srjs 				DCCP_DEBUG((LOG_INFO, "Calling data *cc_sw[%u].cc_recv_packet_recv! %llx %llx dp=%x\n", dp->cc_in_use[1], dp->ack_snd, dp->seq_rcv, dp));
75065278823Srjs 				(*cc_sw[dp->cc_in_use[1]].cc_recv_packet_recv)(dp->cc_state[1], options, optlen);
75165278823Srjs 			}
75265278823Srjs 			break;
75365278823Srjs 
75465278823Srjs 		case DCCP_TYPE_ACK:
75565278823Srjs 			DCCP_DEBUG((LOG_INFO, "Got DCCP ACK\n"));
75665278823Srjs 			if (!is_shortseq) {
75765278823Srjs 				DAHDR_TO_DSEQ(dp->ack_rcv, ((struct dccp_acklhdr*)dalh)->dash);
75865278823Srjs 			} else {
75965278823Srjs 				/* shortseq */
76065278823Srjs 				dp->ack_rcv = CONVERT_TO_LONGSEQ((ntohl(dah->dash.dah_ack) >> 8), dp->ref_seq);
76165278823Srjs 			}
76265278823Srjs 
76365278823Srjs 			if (dp->cc_in_use[1] > 0) {
76465278823Srjs 				/* This is called so Acks on Acks can be handled */
76565278823Srjs 				if (!dp->ack_snd) dp->ack_snd = dp->seq_rcv;
76665278823Srjs 				DCCP_DEBUG((LOG_INFO, "Calling ACK *cc_sw[%u].cc_recv_packet_recv! %llx %llx\n", dp->cc_in_use[1], dp->ack_snd, dp->seq_rcv));
76765278823Srjs 				(*cc_sw[dp->cc_in_use[1]].cc_recv_packet_recv)(dp->cc_state[1], options, optlen);
76865278823Srjs 			}
76965278823Srjs 			break;
77065278823Srjs 
77165278823Srjs 		case DCCP_TYPE_DATAACK:
77265278823Srjs 			DCCP_DEBUG((LOG_INFO, "Got DCCP DATAACK\n"));
77365278823Srjs 
77465278823Srjs 			if (!is_shortseq) {
77565278823Srjs 				DAHDR_TO_DSEQ(dp->ack_rcv, ((struct dccp_acklhdr*)dalh)->dash);
77665278823Srjs 			} else {
77765278823Srjs 				/* shortseq */
77865278823Srjs 				dp->ack_rcv = CONVERT_TO_LONGSEQ((ntohl(dah->dash.dah_ack) >> 8), dp->ref_seq);
77965278823Srjs 			}
78065278823Srjs 
78165278823Srjs 			if (dp->cc_in_use[1] > 0) {
78265278823Srjs 				if (!dp->ack_snd) dp->ack_snd = dp->seq_rcv;
78365278823Srjs 				DCCP_DEBUG((LOG_INFO, "Calling *cc_sw[%u].cc_recv_packet_recv! %llx %llx\n", dp->cc_in_use[1], dp->ack_snd, dp->seq_rcv));
78465278823Srjs 				(*cc_sw[dp->cc_in_use[1]].cc_recv_packet_recv)(dp->cc_state[1], options, optlen);
78565278823Srjs 			}
78665278823Srjs 			break;
78765278823Srjs 
78865278823Srjs 		case DCCP_TYPE_CLOSEREQ:
78965278823Srjs 			DCCP_DEBUG((LOG_INFO, "Got DCCP CLOSEREQ, state = estab\n"));
79065278823Srjs 			if (dp->who == DCCP_CLIENT) {
79165278823Srjs 				dccp_disconnect2(dp);
79265278823Srjs 			} else {
79365278823Srjs 				dccp_output(dp, DCCP_TYPE_RESET + 2);
79465278823Srjs 			}
79565278823Srjs 			break;
79665278823Srjs 
79765278823Srjs 		case DCCP_TYPE_CLOSE:
79865278823Srjs 			DCCP_DEBUG((LOG_INFO, "Got DCCP CLOSE, state = estab\n"));
79965278823Srjs 			dp->state = DCCPS_SERVER_CLOSE; /* So disconnect2 doesn't send CLOSEREQ */
80065278823Srjs 			dccp_disconnect2(dp);
80165278823Srjs 			dccp_output(dp, DCCP_TYPE_RESET + 2);
80265278823Srjs 			dccp_close(dp);
80365278823Srjs 			goto badunlocked;
80465278823Srjs 			break;
80565278823Srjs 
80665278823Srjs 		case DCCP_TYPE_RESET:
80765278823Srjs 			DCCP_DEBUG((LOG_INFO, "Got DCCP RESET\n"));
80865278823Srjs 			dp->state = DCCPS_TIME_WAIT;
80965278823Srjs 			callout_stop(&dp->retrans_timer);
81065278823Srjs 			callout_reset(&dp->timewait_timer, DCCP_TIMEWAIT_TIMER,
81165278823Srjs 			    dccp_timewait_t, dp);
81265278823Srjs 			break;
81365278823Srjs 
81465278823Srjs 		case DCCP_TYPE_MOVE:
81565278823Srjs 			DCCP_DEBUG((LOG_INFO, "Got DCCP MOVE\n"));
81665278823Srjs 			break;
81765278823Srjs 
81865278823Srjs 		default:
81965278823Srjs 			DCCP_DEBUG((LOG_INFO, "Got a %u packet while in established stage!\n", dh->dh_type));
82065278823Srjs 		}
82165278823Srjs 
82265278823Srjs 	} else if (dp->state == DCCPS_SERVER_CLOSE) {
82365278823Srjs 		/* Server */
82465278823Srjs 		switch (dh->dh_type) {
82565278823Srjs 		case DCCP_TYPE_CLOSE:
82665278823Srjs 			DCCP_DEBUG((LOG_INFO, "Got DCCP CLOSE (State DCCPS_SERVER_CLOSE)\n"));
82765278823Srjs 			callout_stop(&dp->retrans_timer);
82865278823Srjs 			dccp_output(dp, DCCP_TYPE_RESET + 2);
82965278823Srjs 			dp = dccp_close(dp);
83065278823Srjs 			goto badunlocked;
83165278823Srjs 
83265278823Srjs 		case DCCP_TYPE_RESET:
83365278823Srjs 			DCCP_DEBUG((LOG_INFO, "Got DCCP RESET\n"));
83465278823Srjs 			callout_stop(&dp->retrans_timer);
83565278823Srjs 			dccp_output(dp, DCCP_TYPE_RESET + 2);
83665278823Srjs 			dp->state = DCCPS_TIME_WAIT;
83765278823Srjs 			break;
83865278823Srjs 		default:
83965278823Srjs 			DCCP_DEBUG((LOG_INFO, "Got a %u packet while in server_close stage!\n", dh->dh_type));
84065278823Srjs 		}
84165278823Srjs 
84265278823Srjs 	} else if (dp->state == DCCPS_CLIENT_CLOSE) {
84365278823Srjs 		/* Client */
84465278823Srjs 		switch (dh->dh_type) {
84565278823Srjs 		case DCCP_TYPE_CLOSE:
84665278823Srjs 			/* Ignore */
84765278823Srjs 			break;
84865278823Srjs 		case DCCP_TYPE_CLOSEREQ:
84965278823Srjs 			DCCP_DEBUG((LOG_INFO, "Got DCCP CLOSEREQ, state = DCCPS_CLIENT_CLOSE\n"));
85065278823Srjs 			/* Just resend close */
85165278823Srjs 			dccp_output(dp, 0);
85265278823Srjs 			break;
85365278823Srjs 		case DCCP_TYPE_RESET:
85465278823Srjs 			DCCP_DEBUG((LOG_INFO, "Got DCCP RESET\n"));
85565278823Srjs 			callout_stop(&dp->retrans_timer);
85665278823Srjs 			dp->state = DCCPS_TIME_WAIT;
85765278823Srjs 			callout_reset(&dp->timewait_timer, DCCP_TIMEWAIT_TIMER,
85865278823Srjs 			    dccp_timewait_t, dp);
85965278823Srjs 			break;
86065278823Srjs 		default:
86165278823Srjs 			DCCP_DEBUG((LOG_INFO, "Got a %u packet while in client_close stage!\n", dh->dh_type));
86265278823Srjs 
86365278823Srjs 		}
86465278823Srjs 	} else {
86565278823Srjs 		DCCP_DEBUG((LOG_INFO, "Got a %u packet while in %u state!\n", dh->dh_type, dp->state));
86665278823Srjs 		if (dh->dh_type != DCCP_TYPE_RESET) {
86765278823Srjs 			/* Force send reset. */
86865278823Srjs 			DCCP_DEBUG((LOG_INFO, "Force sending a request!\n"));
86965278823Srjs 			dccp_output(dp, DCCP_TYPE_RESET + 2);
87065278823Srjs 		}
87165278823Srjs 	}
87265278823Srjs 
87365278823Srjs 	if (dh->dh_type == DCCP_TYPE_DATA ||
87465278823Srjs 	    dh->dh_type == DCCP_TYPE_ACK  ||
87565278823Srjs 	    dh->dh_type == DCCP_TYPE_DATAACK) {
87665278823Srjs 		if (dp->cc_in_use[0] > 0) {
87765278823Srjs 			(*cc_sw[dp->cc_in_use[0]].cc_send_packet_recv)(dp->cc_state[0],options, optlen);
87865278823Srjs 		}
87965278823Srjs 
88065278823Srjs 	}
88165278823Srjs 
88265278823Srjs 	if (dh->dh_type == DCCP_TYPE_DATA || dh->dh_type == DCCP_TYPE_DATAACK) {
883*481d3881Srin 		if (so->so_state & SS_CANTRCVMORE) {
88465278823Srjs 			DCCP_DEBUG((LOG_INFO, "state & SS_CANTRCVMORE...!\n"));
88565278823Srjs 			m_freem(m);
88665278823Srjs 			m_freem(opts);
88765278823Srjs 		} else {
88865278823Srjs 			m_adj(m, (iphlen + data_off));
88965278823Srjs 			DCCP_DEBUG((LOG_INFO, "Calling sbappend!\n"));
89065278823Srjs 			sbappend(&so->so_rcv, m);
89165278823Srjs 		}
89265278823Srjs 		DCCP_DEBUG((LOG_INFO, "Calling sorwakeup...!\n"));
89365278823Srjs 		sorwakeup(so);
89465278823Srjs 	} else {
89565278823Srjs 		m_freem(m);
89665278823Srjs 		m_freem(opts);
89765278823Srjs 	}
89865278823Srjs #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
89965278823Srjs 	if (dp)
90065278823Srjs 		INP_UNLOCK(inp);
90165278823Srjs #endif
90265278823Srjs 
90365278823Srjs 	return;
90465278823Srjs 
90565278823Srjs badunlocked:
90665278823Srjs 	m_freem(m);
90765278823Srjs 	m_freem(opts);
90865278823Srjs 	return;
90965278823Srjs }
91065278823Srjs 
91165278823Srjs /*
91265278823Srjs  * Notify a dccp user of an asynchronous error;
91365278823Srjs  * just wake up so that he can collect error status.
91465278823Srjs  */
91565278823Srjs void
dccp_notify(struct inpcb * inp,int errno)91665278823Srjs dccp_notify(struct inpcb *inp, int errno)
91765278823Srjs {
91865278823Srjs 	inp->inp_socket->so_error = errno;
91965278823Srjs 	sorwakeup(inp->inp_socket);
92065278823Srjs 	sowwakeup(inp->inp_socket);
92165278823Srjs 	return;
92265278823Srjs }
92365278823Srjs 
92465278823Srjs /*
9254dbe3593Sandvar  * Called when we get ICMP errors (destination unreachable,
92665278823Srjs  * parameter problem, source quench, time exceeded and redirects)
92765278823Srjs  */
92865278823Srjs void *
dccp_ctlinput(int cmd,const struct sockaddr * sa,void * vip)92965278823Srjs dccp_ctlinput(int cmd, const struct sockaddr *sa, void *vip)
93065278823Srjs {
93165278823Srjs 	struct ip *ip = vip;
93265278823Srjs 	struct dccphdr *dh;
93365278823Srjs 	void (*notify)(struct inpcb *, int) = dccp_notify;
93465278823Srjs 	struct in_addr faddr;
93565278823Srjs 	struct inpcb *inp = NULL;
93665278823Srjs 
93765278823Srjs 	faddr = ((const struct sockaddr_in *)sa)->sin_addr;
93865278823Srjs 	if (sa->sa_family != AF_INET || faddr.s_addr == INADDR_ANY)
93965278823Srjs 		return NULL;
94065278823Srjs 
94165278823Srjs 	if (PRC_IS_REDIRECT(cmd)) {
94265278823Srjs 		ip = 0;
9432ba9f052Sozaki-r 		notify = inpcb_rtchange;
94465278823Srjs 	} else if (cmd == PRC_HOSTDEAD)
94565278823Srjs 		ip = 0;
94665278823Srjs 	else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0)
94765278823Srjs 		return NULL;
94865278823Srjs 	if (ip) {
94965278823Srjs 		/*s = splsoftnet();*/
95065278823Srjs 		dh = (struct dccphdr *)((vaddr_t)ip + (ip->ip_hl << 2));
95165278823Srjs 		INP_INFO_RLOCK(&dccpbinfo);
9522ba9f052Sozaki-r 		inpcb_notify(&dccpbtable, faddr, dh->dh_dport,
95365278823Srjs 		    ip->ip_src, dh->dh_sport, inetctlerrmap[cmd], notify);
95465278823Srjs 		if (inp != NULL) {
95565278823Srjs 			INP_LOCK(inp);
95665278823Srjs 			if (inp->inp_socket != NULL) {
95765278823Srjs 				(*notify)(inp, inetctlerrmap[cmd]);
95865278823Srjs 			}
95965278823Srjs 			INP_UNLOCK(inp);
96065278823Srjs 		}
96165278823Srjs 		INP_INFO_RUNLOCK(&dccpbinfo);
96265278823Srjs 		/*splx(s);*/
96365278823Srjs 	} else
9642ba9f052Sozaki-r 		inpcb_notifyall(&dccpbtable, faddr, inetctlerrmap[cmd], notify);
96565278823Srjs 
96665278823Srjs 	return NULL;
96765278823Srjs }
96865278823Srjs 
96965278823Srjs static int
dccp_optsset(struct dccpcb * dp,struct sockopt * sopt)97065278823Srjs dccp_optsset(struct dccpcb *dp, struct sockopt *sopt)
97165278823Srjs {
97265278823Srjs 	int optval;
97365278823Srjs 	int error = 0;
97465278823Srjs 
97565278823Srjs 	switch (sopt->sopt_name) {
97665278823Srjs 	case DCCP_CCID:
97765278823Srjs 		error = sockopt_getint(sopt, &optval);
97865278823Srjs 		/* Add check that optval is a CCID we support!!! */
97965278823Srjs 		if (optval == 2 || optval == 3 || optval == 0) {
98065278823Srjs 			dp->pref_cc = optval;
98165278823Srjs 		} else {
98265278823Srjs 			error = EINVAL;
98365278823Srjs 		}
98465278823Srjs 		break;
98565278823Srjs 	case DCCP_CSLEN:
98665278823Srjs 		error = sockopt_getint(sopt, &optval);
98765278823Srjs 		if (optval > 15 || optval < 0) {
98865278823Srjs 			error = EINVAL;
98965278823Srjs 		} else {
99065278823Srjs 			dp->cslen = optval;
99165278823Srjs 		}
99265278823Srjs 		break;
99365278823Srjs 	case DCCP_MAXSEG:
99465278823Srjs 		error = sockopt_getint(sopt, &optval);
99565278823Srjs 		if (optval > 0 && optval <= dp->d_maxseg) {
99665278823Srjs 			dp->d_maxseg = optval;
99765278823Srjs 		} else {
99865278823Srjs 			error = EINVAL;
99965278823Srjs 		}
100065278823Srjs 		break;
100165278823Srjs 	case DCCP_SERVICE:
100265278823Srjs 		error = sockopt_getint(sopt, &optval);
100365278823Srjs 		dp->scode = optval;
100465278823Srjs 		break;
100565278823Srjs 
100665278823Srjs 	default:
100765278823Srjs 		error = ENOPROTOOPT;
100865278823Srjs 	}
100965278823Srjs 
101065278823Srjs 	return error;
101165278823Srjs }
101265278823Srjs 
101365278823Srjs static int
dccp_optsget(struct dccpcb * dp,struct sockopt * sopt)101465278823Srjs dccp_optsget(struct dccpcb *dp, struct sockopt *sopt)
101565278823Srjs {
101665278823Srjs 	int optval = 0;
101765278823Srjs 	int error = 0;
101865278823Srjs 
101965278823Srjs 	switch (sopt->sopt_name) {
102065278823Srjs 	case DCCP_CCID:
102165278823Srjs 		optval = dp->pref_cc;
102265278823Srjs 		error = sockopt_set(sopt, &optval, sizeof(optval));
102365278823Srjs 		break;
102465278823Srjs 	case DCCP_CSLEN:
102565278823Srjs 		optval = dp->cslen;
102665278823Srjs 		error = sockopt_set(sopt, &optval, sizeof(optval));
102765278823Srjs 		break;
102865278823Srjs 	case DCCP_MAXSEG:
102965278823Srjs 		optval = dp->d_maxseg;
103065278823Srjs 		error = sockopt_set(sopt, &optval, sizeof(optval));
103165278823Srjs 		break;
103265278823Srjs 	case DCCP_SERVICE:
103365278823Srjs 		optval = dp->scode;
103465278823Srjs 		error = sockopt_set(sopt, &optval, sizeof(optval));
103565278823Srjs 		break;
103665278823Srjs 	default:
103765278823Srjs 		error = ENOPROTOOPT;
103865278823Srjs 	}
103965278823Srjs 
104065278823Srjs 	return error;
104165278823Srjs }
104265278823Srjs 
104365278823Srjs /*
104465278823Srjs  * Called by getsockopt and setsockopt.
104565278823Srjs  *
104665278823Srjs  */
104765278823Srjs int
dccp_ctloutput(int op,struct socket * so,struct sockopt * sopt)104865278823Srjs dccp_ctloutput(int op, struct socket *so, struct sockopt *sopt)
104965278823Srjs {
105065278823Srjs 	int s, error = 0;
105165278823Srjs 	struct inpcb	*inp;
105265278823Srjs 	struct dccpcb	*dp;
105365278823Srjs 	int family;	/* family of the socket */
105465278823Srjs 
105565278823Srjs 	family = so->so_proto->pr_domain->dom_family;
105665278823Srjs 	error = 0;
105765278823Srjs 
105865278823Srjs 	s = splsoftnet();
105965278823Srjs 	INP_INFO_RLOCK(&dccpbinfo);
106065278823Srjs 	inp = sotoinpcb(so);
106165278823Srjs 	if (inp == NULL)
106265278823Srjs 	{
106365278823Srjs 		INP_INFO_RUNLOCK(&dccpbinfo);
106465278823Srjs 		splx(s);
106565278823Srjs 		return (ECONNRESET);
106665278823Srjs 	}
106765278823Srjs /*
106865278823Srjs 	if (inp)
106965278823Srjs 		INP_LOCK(inp);
107065278823Srjs 	else
107165278823Srjs 		IN6P_LOCK(in6p);
107265278823Srjs 	INP_INFO_RUNLOCK(&dccpbinfo);
107365278823Srjs */
107465278823Srjs 	if (sopt->sopt_level != IPPROTO_DCCP) {
107565278823Srjs 		switch (family) {
107665278823Srjs 		case PF_INET:
107765278823Srjs 			error = ip_ctloutput(op, so, sopt);
107865278823Srjs 			break;
107965278823Srjs #if defined(INET6)
108065278823Srjs 		case PF_INET6:
108165278823Srjs 			error = ip6_ctloutput(op, so, sopt);
108265278823Srjs 			break;
108365278823Srjs #endif
108465278823Srjs 		}
108565278823Srjs 		splx(s);
108665278823Srjs 		return (error);
108765278823Srjs 	}
108865278823Srjs 
108965278823Srjs 	dp = intodccpcb(inp);
109065278823Srjs 
109165278823Srjs 	if (op == PRCO_SETOPT) {
109265278823Srjs 		error = dccp_optsset(dp, sopt);
109365278823Srjs 	} else if (op ==  PRCO_GETOPT) {
109465278823Srjs 		error = dccp_optsget(dp, sopt);
109565278823Srjs 	} else {
109665278823Srjs 		error = EINVAL;
109765278823Srjs 	}
109865278823Srjs /*
109965278823Srjs 	if (inp)
110065278823Srjs 		INP_UNLOCK(inp);
110165278823Srjs 	else
110265278823Srjs 		IN6P_UNLOCK(in6p);
110365278823Srjs */
110465278823Srjs 	splx(s);
110565278823Srjs 	return error;
110665278823Srjs }
110765278823Srjs 
110865278823Srjs int
dccp_output(struct dccpcb * dp,u_int8_t extra)110965278823Srjs dccp_output(struct dccpcb *dp, u_int8_t extra)
111065278823Srjs {
111165278823Srjs 	struct inpcb *inp;
111265278823Srjs 	struct socket *so;
111365278823Srjs 	struct mbuf *m;
111465278823Srjs 
111565278823Srjs 	struct ip *ip = NULL;
111665278823Srjs 	struct dccphdr *dh;
111765278823Srjs 	struct dccplhdr *dlh;
111865278823Srjs 	struct dccp_requesthdr *drqh;
111965278823Srjs 	struct dccp_ackhdr *dah;
112065278823Srjs 	struct dccp_acklhdr *dalh;
112165278823Srjs 	struct dccp_resethdr *drth;
112265278823Srjs 	u_char *optp = NULL;
112365278823Srjs 	int error = 0;
112465278823Srjs 	int off, sendalot, t, i;
112565278823Srjs 	u_int32_t hdrlen, optlen, extrah_len, cslen;
112665278823Srjs 	u_int8_t type;
112765278823Srjs 	char options[DCCP_MAX_OPTIONS *2];
112865278823Srjs 	long len, pktlen;
112965278823Srjs 	int isipv6 = 0;
113065278823Srjs 	int use_shortseq = 0;
113165278823Srjs #ifdef INET6
113265278823Srjs 	struct ip6_hdr *ip6 = NULL;
113365278823Srjs #endif
113465278823Srjs 
113565278823Srjs 	DCCP_DEBUG((LOG_INFO, "dccp_output start!\n"));
113665278823Srjs 
113765278823Srjs 	isipv6 = (dp->inp_vflag & INP_IPV6) != 0;
113865278823Srjs 
113965278823Srjs 	DCCP_DEBUG((LOG_INFO, "Going to send a DCCP packet!\n"));
114065278823Srjs #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
114165278823Srjs 	KASSERT(mutex_assert(&dp->d_inpcb->inp_mtx, MA_OWNED));
114265278823Srjs #endif
114365278823Srjs 
114465278823Srjs 	inp = dp->d_inpcb;
114565278823Srjs 	so = inp->inp_socket;
114665278823Srjs 
114765278823Srjs 	if (dp->state != DCCPS_ESTAB && extra == 1) {
11484dbe3593Sandvar 		/* Only let cc decide when to resend if we are in established state */
114965278823Srjs 		return 0;
115065278823Srjs 	}
115165278823Srjs 
115265278823Srjs 	if (so->so_snd.sb_cc){
115365278823Srjs 		pktlen = dp->pktlen[dp->pktlenidx];
115465278823Srjs 	} else
115565278823Srjs 		pktlen = 0;
115665278823Srjs 
115765278823Srjs 	/* Check with CC if we can send... */
115865278823Srjs 	if (pktlen && dp->cc_in_use[0] > 0 && dp->state == DCCPS_ESTAB) {
115965278823Srjs 		if (!(*cc_sw[dp->cc_in_use[0]].cc_send_packet)(dp->cc_state[0], pktlen)) {
116065278823Srjs 			DCCP_DEBUG((LOG_INFO, "Not allowed to send right now\n"));
116165278823Srjs 			return 0;
116265278823Srjs 		}
116365278823Srjs 	}
116465278823Srjs 
116565278823Srjs 	if (pktlen) {
116665278823Srjs 		dp->pktcnt --;
116765278823Srjs 		dp->pktlenidx = (dp->pktlenidx +1) % DCCP_MAX_PKTS;
116865278823Srjs 	}
116965278823Srjs 
117065278823Srjs again:
117165278823Srjs 	sendalot = 0;
117265278823Srjs 
117365278823Srjs 	/*
117465278823Srjs 	 * off not needed for dccp because we do not need to wait for ACK
117565278823Srjs 	 * before removing the packet
117665278823Srjs 	 */
117765278823Srjs 	off = 0;
117865278823Srjs 	optlen = 0;
117965278823Srjs 
118065278823Srjs 	if (pktlen > dp->d_maxseg) {
118165278823Srjs 		/* this should not happen */
118265278823Srjs 		DCCP_DEBUG((LOG_INFO, "packet will be fragmented! maxseg %d\n", dp->d_maxseg));
118365278823Srjs 		len = dp->d_maxseg;
118465278823Srjs 		pktlen -= len;
118565278823Srjs 		sendalot = 1;
118665278823Srjs 	} else
118765278823Srjs 		len = pktlen;
118865278823Srjs 
118965278823Srjs 	if (extra == DCCP_TYPE_RESET + 2) {
119065278823Srjs 		DCCP_DEBUG((LOG_INFO, "Force sending of DCCP TYPE_RESET! seq=%llu\n", dp->seq_snd));
119165278823Srjs 		type = DCCP_TYPE_RESET;
119265278823Srjs 		extrah_len = 12;
119365278823Srjs 	} else if (dp->state <= DCCPS_REQUEST && dp->who == DCCP_CLIENT) {
119465278823Srjs 		DCCP_DEBUG((LOG_INFO, "Sending DCCP TYPE_REQUEST!\n"));
119565278823Srjs 		type = DCCP_TYPE_REQUEST;
119665278823Srjs 		dp->state = DCCPS_REQUEST;
119765278823Srjs 		extrah_len = 4;
119865278823Srjs 	} else if (dp->state == DCCPS_REQUEST && dp->who == DCCP_SERVER) {
119965278823Srjs 		DCCP_DEBUG((LOG_INFO, "Sending DCCP TYPE_RESPONSE!\n"));
120065278823Srjs 		type = DCCP_TYPE_RESPONSE;
120165278823Srjs 		dp->state = DCCPS_RESPOND;
120265278823Srjs 		extrah_len = 12;
120365278823Srjs 	} else if (dp->state == DCCPS_RESPOND) {
120465278823Srjs 		DCCP_DEBUG((LOG_INFO, "Still in feature neg, sending DCCP TYPE_ACK!\n"));
120565278823Srjs 		type = DCCP_TYPE_ACK;
120665278823Srjs 		if (!dp->shortseq)
120765278823Srjs 			extrah_len = 8;
120865278823Srjs 		else {
120965278823Srjs 			extrah_len = 4;
121065278823Srjs 			use_shortseq = 1;
121165278823Srjs 		}
121265278823Srjs 	} else if (dp->state == DCCPS_ESTAB) {
121365278823Srjs 		if (dp->ack_snd && len) {
121465278823Srjs 			DCCP_DEBUG((LOG_INFO, "Sending DCCP TYPE_DATAACK!\n"));
121565278823Srjs 			type = DCCP_TYPE_DATAACK;
121665278823Srjs 			/*(u_int32_t *)&extrah = dp->seq_rcv; */
121765278823Srjs 			if (!dp->shortseq)
121865278823Srjs 				extrah_len = 8;
121965278823Srjs 			else {
122065278823Srjs 				extrah_len = 4;
122165278823Srjs 				use_shortseq = 1;
122265278823Srjs 			}
122365278823Srjs 		} else if (dp->ack_snd) {
122465278823Srjs 			DCCP_DEBUG((LOG_INFO, "Sending DCCP TYPE_ACK!\n"));
122565278823Srjs 			type = DCCP_TYPE_ACK;
122665278823Srjs 			if (!dp->shortseq)
122765278823Srjs 				extrah_len = 8;
122865278823Srjs 			else {
122965278823Srjs 				extrah_len = 4;
123065278823Srjs 				use_shortseq = 1;
123165278823Srjs 			}
123265278823Srjs 		} else if (len) {
123365278823Srjs 			DCCP_DEBUG((LOG_INFO, "Sending DCCP TYPE_DATA!\n"));
123465278823Srjs 			type = DCCP_TYPE_DATA;
123565278823Srjs 			extrah_len = 0;
123665278823Srjs 		} else {
123765278823Srjs 			DCCP_DEBUG((LOG_INFO, "No ack or data to send!\n"));
123865278823Srjs 			return 0;
123965278823Srjs 		}
124065278823Srjs 	} else if (dp->state == DCCPS_CLIENT_CLOSE) {
124165278823Srjs 		DCCP_DEBUG((LOG_INFO, "Sending DCCP TYPE_CLOSE!\n"));
124265278823Srjs 		type = DCCP_TYPE_CLOSE;
124365278823Srjs 		extrah_len = 8;
124465278823Srjs 	} else if (dp->state == DCCPS_SERVER_CLOSE) {
124565278823Srjs 		DCCP_DEBUG((LOG_INFO, "Sending DCCP TYPE_CLOSEREQ!\n"));
124665278823Srjs 		type = DCCP_TYPE_CLOSEREQ;
124765278823Srjs 		extrah_len = 8;
124865278823Srjs 	} else {
124965278823Srjs 		DCCP_DEBUG((LOG_INFO, "Hey, we should never get here, state = %u\n", dp->state));
125065278823Srjs 		return 1;
125165278823Srjs 	}
125265278823Srjs 
125365278823Srjs 	/* Adding options. */
125465278823Srjs 	if (dp->optlen) {
125565278823Srjs 		DCCP_DEBUG((LOG_INFO, "Copying options from dp->options! %u\n", dp->optlen));
1256a72ef8c3Srjs 		memcpy(options, dp->options, dp->optlen);
125765278823Srjs 		optlen = dp->optlen;
125865278823Srjs 		dp->optlen = 0;
125965278823Srjs 	}
126065278823Srjs 
126165278823Srjs 	if (dp->featlen && (optlen + dp->featlen < DCCP_MAX_OPTIONS)) {
126265278823Srjs 		DCCP_DEBUG((LOG_INFO, "Copying options from dp->features! %u\n", dp->featlen));
1263a72ef8c3Srjs 		memcpy(options + optlen, dp->features, dp->featlen);
126465278823Srjs 		optlen += dp->featlen;
126565278823Srjs 	}
126665278823Srjs 
126765278823Srjs 	t = optlen % 4;
126865278823Srjs 
126965278823Srjs 	if (t) {
127065278823Srjs 		t = 4 - t;
127165278823Srjs 		for (i = 0 ; i<t; i++) {
127265278823Srjs 			options[optlen] = 0;
127365278823Srjs 			optlen++;
127465278823Srjs 		}
127565278823Srjs 	}
127665278823Srjs 
127765278823Srjs #ifdef INET6
127865278823Srjs 	if (isipv6) {
127965278823Srjs 		DCCP_DEBUG((LOG_INFO, "Sending ipv6 packet...\n"));
128065278823Srjs 		if (!use_shortseq)
128165278823Srjs 			hdrlen = sizeof(struct ip6_hdr) + sizeof(struct dccplhdr) +
128265278823Srjs 			    extrah_len + optlen;
128365278823Srjs 		else
128465278823Srjs 			hdrlen = sizeof(struct ip6_hdr) + sizeof(struct dccphdr) +
128565278823Srjs 			    extrah_len + optlen;
128665278823Srjs 	} else
128765278823Srjs #endif
128865278823Srjs 	{
128965278823Srjs 		if (!use_shortseq)
129065278823Srjs 			hdrlen = sizeof(struct ip) + sizeof(struct dccplhdr) +
129165278823Srjs 		   		extrah_len + optlen;
129265278823Srjs 		else
129365278823Srjs 			hdrlen = sizeof(struct ip) + sizeof(struct dccphdr) +
129465278823Srjs 		   		extrah_len + optlen;
129565278823Srjs 	}
129665278823Srjs 	DCCP_DEBUG((LOG_INFO, "Pkt headerlen %u\n", hdrlen));
129765278823Srjs 
129865278823Srjs 	if (len > (dp->d_maxseg - extrah_len - optlen)) {
129965278823Srjs 		len = dp->d_maxseg - extrah_len - optlen;
130065278823Srjs 		sendalot = 1;
130165278823Srjs 	}
130265278823Srjs 
130365278823Srjs 	MGETHDR(m, M_DONTWAIT, MT_HEADER);
130465278823Srjs 	if (m == NULL) {
130565278823Srjs 		error = ENOBUFS;
130665278823Srjs 		goto release;
130765278823Srjs 	}
130865278823Srjs 	if (MHLEN < hdrlen + max_linkhdr) {
130965278823Srjs 		MCLGET(m, M_DONTWAIT);
131065278823Srjs 		if ((m->m_flags & M_EXT) == 0) {
131165278823Srjs 			error = ENOBUFS;
131265278823Srjs 			goto release;
131365278823Srjs 		}
131465278823Srjs 	}
131565278823Srjs 
131665278823Srjs 	m->m_data += max_linkhdr;
131765278823Srjs 	m->m_len = hdrlen;
131865278823Srjs 
131965278823Srjs 	if (len) { /* We have data to send */
132065278823Srjs 		if (len <= M_TRAILINGSPACE(m) - hdrlen) {
132165278823Srjs 			m_copydata(so->so_snd.sb_mb, off, (int) len,
132265278823Srjs 			mtod(m, char *) + hdrlen);
132365278823Srjs 			m->m_len += len;
132465278823Srjs 		} else {
13254a165b52Smaxv 			m->m_next = m_copym(so->so_snd.sb_mb, off,
13264a165b52Smaxv 			    (int)len, M_DONTWAIT);
132765278823Srjs 			if (m->m_next == 0) {
132865278823Srjs 				error = ENOBUFS;
132965278823Srjs 				goto release;
133065278823Srjs 			}
133165278823Srjs 		}
133265278823Srjs 	} else {
133365278823Srjs 		dp->ndp++;
133465278823Srjs 	}
133565278823Srjs 
1336d938d837Sozaki-r 	m_reset_rcvif(m);
133765278823Srjs 
133865278823Srjs 	if (!isipv6 && (len + hdrlen) > IP_MAXPACKET) {
133965278823Srjs 		error = EMSGSIZE;
134065278823Srjs 		goto release;
134165278823Srjs 	}
134265278823Srjs 
134365278823Srjs 	/*
134465278823Srjs 	 * Fill in mbuf with extended DCCP header
134565278823Srjs 	 * and addresses and length put into network format.
134665278823Srjs 	 */
134765278823Srjs #ifdef INET6
134865278823Srjs 	if (isipv6) {
134965278823Srjs 		ip6 = mtod(m, struct ip6_hdr *);
135065278823Srjs 		dh = (struct dccphdr *)(ip6 + 1);
135165278823Srjs 		ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) |
13527118c214Sozaki-r 			(in6p_flowinfo(inp) & IPV6_FLOWINFO_MASK);
135365278823Srjs 		ip6->ip6_vfc = (ip6->ip6_vfc & ~IPV6_VERSION_MASK) |
135465278823Srjs 			 (IPV6_VERSION & IPV6_VERSION_MASK);
135565278823Srjs 		ip6->ip6_nxt = IPPROTO_DCCP;
13567118c214Sozaki-r 		ip6->ip6_src = in6p_laddr(inp);
13577118c214Sozaki-r 		ip6->ip6_dst = in6p_faddr(inp);
135865278823Srjs 	} else
135965278823Srjs #endif
136065278823Srjs 	{
136165278823Srjs 		ip = mtod(m, struct ip *);
136265278823Srjs 		dh = (struct dccphdr *)(ip + 1);
1363a72ef8c3Srjs 		memset(ip, 0, sizeof(struct ip));
136465278823Srjs 		ip->ip_p = IPPROTO_DCCP;
13657118c214Sozaki-r 		ip->ip_src = in4p_laddr(inp);
13667118c214Sozaki-r 		ip->ip_dst = in4p_faddr(inp);
136765278823Srjs 	}
136865278823Srjs 	dlh = (struct dccplhdr *)dh;
136965278823Srjs 
137065278823Srjs 	dh->dh_sport = inp->inp_lport;
137165278823Srjs 	dh->dh_dport = inp->inp_fport;
137265278823Srjs 	dh->dh_cscov = dp->cslen;
137365278823Srjs 	dh->dh_ccval = dp->ccval;
137465278823Srjs 	dh->dh_type = type;
137565278823Srjs 	dh->dh_res = 0; /* Reserved field should be zero */
137665278823Srjs 	if (!use_shortseq) {
137765278823Srjs 		dlh->dh_res2 = 0; /* Reserved field should be zero */
137865278823Srjs 		dh->dh_off = 4 + (extrah_len / 4) + (optlen / 4);
137965278823Srjs 	} else
138065278823Srjs 		dh->dh_off = 3 + (extrah_len / 4) + (optlen / 4);
138165278823Srjs 
138265278823Srjs 	dp->seq_snd = (dp->seq_snd +1) % 281474976710656LL;
138365278823Srjs 	if (!use_shortseq) {
138465278823Srjs 		DSEQ_TO_DHDR(dlh, dp->seq_snd);
138565278823Srjs 		dlh->dh_x = 1;
138665278823Srjs 	} else {
138765278823Srjs 		/* short sequene number */
138865278823Srjs 		dh->dh_seq = htonl(dp->seq_snd) >> 8;
138965278823Srjs 		dh->dh_x = 0;
139065278823Srjs 	}
139165278823Srjs 
139265278823Srjs 	if (!use_shortseq) {
139365278823Srjs 		DCCP_DEBUG((LOG_INFO, "Sending with seq %x.%x, (dp->seq_snd = %llu)\n\n", dlh->dh_seq, dlh->dh_seq2, dp->seq_snd));
139465278823Srjs 	} else {
139565278823Srjs 		DCCP_DEBUG((LOG_INFO, "Sending with seq %x, (dp->seq_snd = %llu)\n\n", dh->dh_seq, dp->seq_snd));
139665278823Srjs 	}
139765278823Srjs 
139865278823Srjs 	if (dh->dh_type == DCCP_TYPE_REQUEST) {
139965278823Srjs 		drqh = (struct dccp_requesthdr *)(dlh + 1);
140065278823Srjs 		drqh->drqh_scode = dp->scode;
140165278823Srjs 		optp = (u_char *)(drqh + 1);
140265278823Srjs 	} else if (dh->dh_type == DCCP_TYPE_RESET) {
140365278823Srjs 		drth = (struct dccp_resethdr *)(dlh + 1);
140465278823Srjs 		drth->drth_dash.dah_res = 0;
140565278823Srjs 		DSEQ_TO_DAHDR(drth->drth_dash, dp->seq_rcv);
140665278823Srjs 		if (dp->state == DCCPS_SERVER_CLOSE)
140765278823Srjs 			drth->drth_reason = 1;
140865278823Srjs 		else
140965278823Srjs 			drth->drth_reason = 2;
141065278823Srjs 		drth->drth_data1 = 0;
141165278823Srjs 		drth->drth_data2 = 0;
141265278823Srjs 		drth->drth_data3 = 0;
141365278823Srjs 		optp = (u_char *)(drth + 1);
141465278823Srjs 	} else if (extrah_len) {
141565278823Srjs 		if (!use_shortseq){
141665278823Srjs 			dalh = (struct dccp_acklhdr *)(dlh + 1);
141765278823Srjs 			dalh->dash.dah_res = 0; /* Reserved field should be zero */
141865278823Srjs 
141965278823Srjs 			if (dp->state == DCCPS_ESTAB) {
142065278823Srjs 				DSEQ_TO_DAHDR(dalh->dash, dp->ack_snd);
142165278823Srjs 				dp->ack_snd = 0;
142265278823Srjs 			} else {
142365278823Srjs 				DSEQ_TO_DAHDR(dalh->dash, dp->seq_rcv);
142465278823Srjs 			}
142565278823Srjs 
142665278823Srjs 			if (dh->dh_type == DCCP_TYPE_RESPONSE) {
142765278823Srjs 				DCCP_DEBUG((LOG_INFO, "Sending dccp type response\n"));
142865278823Srjs 				drqh = (struct dccp_requesthdr *)(dalh + 1);
142965278823Srjs 				drqh->drqh_scode = dp->scode;
143065278823Srjs 				optp = (u_char *)(drqh + 1);
143165278823Srjs 			} else
143265278823Srjs 				optp = (u_char *)(dalh + 1);
143365278823Srjs 		} else {
143465278823Srjs 			/* XXX shortseq */
143565278823Srjs 			dah = (struct dccp_ackhdr *)(dh + 1);
143665278823Srjs 			dah->dash.dah_res = 0; /* Reserved field should be zero */
143765278823Srjs 			dah->dash.dah_ack = htonl(dp->seq_rcv) >> 8;
143865278823Srjs 			optp = (u_char *)(dah + 1);
143965278823Srjs 		}
144065278823Srjs 
144165278823Srjs 	} else {
144265278823Srjs 		optp = (u_char *)(dlh + 1);
144365278823Srjs 	}
144465278823Srjs 
144565278823Srjs 	if (optlen)
1446a72ef8c3Srjs 		memcpy(optp, options, optlen);
144765278823Srjs 
144865278823Srjs 	m->m_pkthdr.len = hdrlen + len;
144965278823Srjs 
145065278823Srjs 	if (dh->dh_cscov == 0) {
145165278823Srjs #ifdef INET6
145265278823Srjs 		if (isipv6)
145365278823Srjs 			cslen = (hdrlen - sizeof(struct ip6_hdr)) + len;
145465278823Srjs 		else
145565278823Srjs 			cslen = (hdrlen - sizeof(struct ip)) + len;
145665278823Srjs #else
145765278823Srjs 		cslen = (hdrlen - sizeof(struct ip)) + len;
145865278823Srjs #endif
145965278823Srjs 	} else {
146065278823Srjs 		cslen = dh->dh_off * 4 + (dh->dh_cscov - 1) * 4;
146165278823Srjs #ifdef INET6
146265278823Srjs 		if (isipv6) {
146365278823Srjs 			if (cslen > (hdrlen - sizeof(struct ip6_hdr)) + len)
146465278823Srjs 				cslen = (hdrlen - sizeof(struct ip6_hdr)) + len;
146565278823Srjs 		} else {
146665278823Srjs 			if (cslen > (hdrlen - sizeof(struct ip)) + len)
146765278823Srjs 				cslen = (hdrlen - sizeof(struct ip)) + len;
146865278823Srjs 		}
146965278823Srjs #else
147065278823Srjs 		if (cslen > (hdrlen - sizeof(struct ip)) + len)
147165278823Srjs 			cslen = (hdrlen - sizeof(struct ip)) + len;
147265278823Srjs #endif
147365278823Srjs 	}
147465278823Srjs 
147565278823Srjs 	/*
147665278823Srjs 	 * Set up checksum
147765278823Srjs 	 */
147865278823Srjs 	m->m_pkthdr.csum_flags = 0;
147965278823Srjs 
148065278823Srjs 	dh->dh_sum = 0;
148165278823Srjs #ifdef INET6
148265278823Srjs 	if (isipv6) {
148365278823Srjs 		dh->dh_sum = in6_cksum(m, IPPROTO_DCCP, sizeof(struct ip6_hdr),
148465278823Srjs 		    cslen);
148565278823Srjs 	} else
148665278823Srjs #endif
148765278823Srjs 	{
148865278823Srjs 		ip->ip_len = htons(hdrlen + len);
148965278823Srjs 		ip->ip_ttl = dp->inp_ip_ttl;	/* XXX */
149065278823Srjs 		ip->ip_tos = dp->inp_ip_tos;	/* XXX */
149165278823Srjs 
149265278823Srjs 		dh->dh_sum = in4_cksum(m, IPPROTO_DCCP, sizeof(struct ip),
149365278823Srjs 		    cslen);
149465278823Srjs #ifndef __OpenBSD__
149565278823Srjs 		m->m_pkthdr.csum_data = offsetof(struct dccphdr, dh_sum);
149665278823Srjs #endif
149765278823Srjs 	}
149865278823Srjs 
149965278823Srjs 	dccpstat.dccps_opackets++;
150065278823Srjs 	dccpstat.dccps_obytes += m->m_pkthdr.len;
150165278823Srjs 
150265278823Srjs #ifdef INET6
150365278823Srjs 	if (isipv6) {
150465278823Srjs 		DCCP_DEBUG((LOG_INFO, "Calling ip_output6, mbuf->m_len = %u, mbuf->m_pkthdr.len = %u\n", m->m_len, m->m_pkthdr.len));
150565278823Srjs 
15067118c214Sozaki-r 		error = ip6_output(m, in6p_outputopts(inp), &inp->inp_route,
1507f8c27a68Sozaki-r 		    (inp->inp_socket->so_options & SO_DONTROUTE), NULL, NULL,
150865278823Srjs 		    NULL);
150965278823Srjs 	} else
151065278823Srjs #endif
151165278823Srjs 	{
151265278823Srjs 		DCCP_DEBUG((LOG_INFO, "Calling ip_output, mbuf->m_len = %u, mbuf->m_pkthdr.len = %u\n", m->m_len, m->m_pkthdr.len));
151365278823Srjs 		error = ip_output(m, inp->inp_options, &inp->inp_route,
151465278823Srjs 		    (inp->inp_socket->so_options & SO_DONTROUTE), 0,
15152495e7a0Sozaki-r 				  inp);
151665278823Srjs 	}
151765278823Srjs 
151865278823Srjs 	if (error) {
151965278823Srjs 		DCCP_DEBUG((LOG_INFO, "IP output failed! %d\n", error));
152065278823Srjs 		return (error);
152165278823Srjs 	}
152265278823Srjs 
152365278823Srjs 	sbdrop(&inp->inp_socket->so_snd, len);
152465278823Srjs 	sowwakeup(inp->inp_socket);
152565278823Srjs 
152665278823Srjs 	if (dp->cc_in_use[0] > 0  && dp->state == DCCPS_ESTAB) {
152765278823Srjs 		DCCP_DEBUG((LOG_INFO, "Calling *cc_sw[%u].cc_send_packet_sent!\n", dp->cc_in_use[0]));
152865278823Srjs 		if (sendalot) {
152965278823Srjs 			(*cc_sw[dp->cc_in_use[0]].cc_send_packet_sent)(dp->cc_state[0], 1,len);
153065278823Srjs 			goto again;
153165278823Srjs 		} else {
153265278823Srjs 			(*cc_sw[dp->cc_in_use[0]].cc_send_packet_sent)(dp->cc_state[0], 0,len);
153365278823Srjs 		}
153465278823Srjs 	} else {
153565278823Srjs 		if (sendalot)
153665278823Srjs 			goto again;
153765278823Srjs 	}
153865278823Srjs 
153965278823Srjs 	DCCP_DEBUG((LOG_INFO, "dccp_output finished\n"));
154065278823Srjs 
154165278823Srjs 	return (0);
154265278823Srjs 
154365278823Srjs release:
154465278823Srjs 	m_freem(m);
154565278823Srjs 	return (error);
154665278823Srjs }
154765278823Srjs 
154865278823Srjs int
dccp_abort(struct socket * so)154965278823Srjs dccp_abort(struct socket *so)
155065278823Srjs {
1551f8c27a68Sozaki-r 	struct inpcb *inp = NULL;
155265278823Srjs 	struct dccpcb *dp;
155365278823Srjs 
155465278823Srjs 	DCCP_DEBUG((LOG_INFO, "Entering dccp_abort!\n"));
155565278823Srjs 	INP_INFO_WLOCK(&dccpbinfo);
155665278823Srjs 	inp = sotoinpcb(so);
1557f8c27a68Sozaki-r 	if (inp == NULL) {
155865278823Srjs 		INP_INFO_WUNLOCK(&dccpbinfo);
155965278823Srjs 		return EINVAL;
156065278823Srjs 	}
1561f8c27a68Sozaki-r 	dp = inp->inp_ppcb;
156265278823Srjs 
156365278823Srjs 	dccp_disconnect2(dp);
156465278823Srjs 
156565278823Srjs 	INP_INFO_WUNLOCK(&dccpbinfo);
156665278823Srjs 	return 0;
156765278823Srjs }
156865278823Srjs 
156965278823Srjs static struct dccpcb *
dccp_close(struct dccpcb * dp)157065278823Srjs dccp_close(struct dccpcb *dp)
157165278823Srjs {
157265278823Srjs 	struct socket *so;
157365278823Srjs 	struct inpcb *inp = dp->d_inpcb;
157465278823Srjs 	so = dptosocket(dp);
157565278823Srjs 
157665278823Srjs 	DCCP_DEBUG((LOG_INFO, "Entering dccp_close!\n"));
157765278823Srjs 
157865278823Srjs 	/* Stop all timers */
157965278823Srjs 	callout_stop(&dp->connect_timer);
158065278823Srjs 	callout_stop(&dp->retrans_timer);
158165278823Srjs 	callout_stop(&dp->close_timer);
158265278823Srjs 	callout_stop(&dp->timewait_timer);
158365278823Srjs 
158465278823Srjs 	if (dp->cc_in_use[0] > 0)
158565278823Srjs 		(*cc_sw[dp->cc_in_use[0]].cc_send_free)(dp->cc_state[0]);
158665278823Srjs 	if (dp->cc_in_use[1] > 0)
158765278823Srjs 		(*cc_sw[dp->cc_in_use[1]].cc_recv_free)(dp->cc_state[1]);
158865278823Srjs 
158965278823Srjs 	pool_put(&dccpcb_pool, dp);
159065278823Srjs 	inp->inp_ppcb = NULL;
159165278823Srjs 	soisdisconnected(so);
15922ba9f052Sozaki-r 	inpcb_destroy(inp);
159365278823Srjs 	return ((struct dccpcb *)0);
159465278823Srjs }
159565278823Srjs 
159665278823Srjs /*
159765278823Srjs  * Runs when a new socket is created with the
159865278823Srjs  * socket system call or sonewconn.
159965278823Srjs  */
160065278823Srjs int
dccp_attach(struct socket * so,int proto)160165278823Srjs dccp_attach(struct socket *so, int proto)
160265278823Srjs {
1603f8c27a68Sozaki-r 	struct inpcb *inp = NULL;
160465278823Srjs 	struct dccpcb *dp;
1605f8c27a68Sozaki-r 	int s, error = 0;
160665278823Srjs 
160765278823Srjs 	DCCP_DEBUG((LOG_INFO, "Entering dccp_attach(proto=%d)!\n", proto));
160865278823Srjs 	INP_INFO_WLOCK(&dccpbinfo);
160965278823Srjs 	s = splsoftnet();
161065278823Srjs 	sosetlock(so);
161165278823Srjs 
161265278823Srjs 	inp = sotoinpcb(so);
161365278823Srjs 	if (inp != 0) {
161465278823Srjs 		error = EINVAL;
161565278823Srjs 		goto out;
161665278823Srjs 	}
161765278823Srjs 	error = soreserve(so, dccp_sendspace, dccp_recvspace);
161865278823Srjs 	if (error)
161965278823Srjs 		goto out;
16202ba9f052Sozaki-r 	error = inpcb_create(so, &dccpbtable);
162165278823Srjs 	if (error)
162265278823Srjs 		goto out;
162365278823Srjs 	inp = sotoinpcb(so);
162465278823Srjs 
1625f8c27a68Sozaki-r 	dp = dccp_newdccpcb(inp->inp_af, inp);
162665278823Srjs 	if (dp == 0) {
162765278823Srjs 		int nofd = so->so_state & SS_NOFDREF;
162865278823Srjs 		so->so_state &= ~SS_NOFDREF;
16292ba9f052Sozaki-r 		inpcb_destroy(inp);
163065278823Srjs 		so->so_state |= nofd;
163165278823Srjs 		error = ENOBUFS;
163265278823Srjs 		goto out;
163365278823Srjs 	}
163465278823Srjs 
163565278823Srjs #ifdef INET6
163665278823Srjs 	if (proto == PF_INET6) {
16374dbe3593Sandvar 		DCCP_DEBUG((LOG_INFO, "We are an ipv6 socket!!!\n"));
163865278823Srjs 		dp->inp_vflag |= INP_IPV6;
163965278823Srjs 	} else
164065278823Srjs #endif
164165278823Srjs 		dp->inp_vflag |= INP_IPV4;
164265278823Srjs 	dp->inp_ip_ttl = ip_defttl;
164365278823Srjs 
164465278823Srjs 	dp->state = DCCPS_CLOSED;
164565278823Srjs out:
164665278823Srjs 	splx(s);
164765278823Srjs 	INP_INFO_WUNLOCK(&dccpbinfo);
164865278823Srjs 	return error;
164965278823Srjs }
165065278823Srjs 
165165278823Srjs static int
dccp_bind(struct socket * so,struct sockaddr * nam,struct lwp * l)165280ea8cccSrtr dccp_bind(struct socket *so, struct sockaddr *nam, struct lwp *l)
165365278823Srjs {
165465278823Srjs 	struct inpcb *inp;
165565278823Srjs 	int error;
1656a36cc654Srjs 	int s;
165780ea8cccSrtr 	struct sockaddr_in *sin = (struct sockaddr_in *)nam;
165865278823Srjs 
165965278823Srjs 	DCCP_DEBUG((LOG_INFO, "Entering dccp_bind!\n"));
166065278823Srjs 	INP_INFO_WLOCK(&dccpbinfo);
166165278823Srjs 	inp = sotoinpcb(so);
166265278823Srjs 	if (inp == 0) {
166365278823Srjs 		INP_INFO_WUNLOCK(&dccpbinfo);
166465278823Srjs 		return EINVAL;
166565278823Srjs 	}
166665278823Srjs 
166765278823Srjs 	/* Do not bind to multicast addresses! */
166880ea8cccSrtr 	if (sin->sin_family == AF_INET &&
166980ea8cccSrtr 	    IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
167065278823Srjs 		INP_INFO_WUNLOCK(&dccpbinfo);
167165278823Srjs 		return EAFNOSUPPORT;
167265278823Srjs 	}
167365278823Srjs 	INP_LOCK(inp);
1674a36cc654Srjs 	s = splsoftnet();
16752ba9f052Sozaki-r 	error = inpcb_bind(inp, sin, l);
1676a36cc654Srjs 	splx(s);
167765278823Srjs 	INP_UNLOCK(inp);
167865278823Srjs 	INP_INFO_WUNLOCK(&dccpbinfo);
167965278823Srjs 	return error;
168065278823Srjs }
168165278823Srjs 
168265278823Srjs /*
168365278823Srjs  * Initiates a connection to a server
168465278823Srjs  * Called by the connect system call.
168565278823Srjs  */
168665278823Srjs static int
dccp_connect(struct socket * so,struct sockaddr * nam,struct lwp * l)1687fd12cf39Srtr dccp_connect(struct socket *so, struct sockaddr *nam, struct lwp *l)
168865278823Srjs {
168965278823Srjs 	struct inpcb *inp;
169065278823Srjs 	struct dccpcb *dp;
169165278823Srjs 	int error;
169265278823Srjs 	struct sockaddr_in *sin;
169365278823Srjs 	char test[2];
169465278823Srjs 
169565278823Srjs 	DCCP_DEBUG((LOG_INFO, "Entering dccp_connect!\n"));
169665278823Srjs 
169765278823Srjs 	INP_INFO_WLOCK(&dccpbinfo);
169865278823Srjs 	inp = sotoinpcb(so);
169965278823Srjs 	if (inp == 0) {
170065278823Srjs 		INP_INFO_WUNLOCK(&dccpbinfo);
170165278823Srjs 		return EINVAL;
170265278823Srjs 	}
170365278823Srjs 	INP_LOCK(inp);
17047118c214Sozaki-r 	if (in4p_faddr(inp).s_addr != INADDR_ANY) {
170565278823Srjs 		INP_UNLOCK(inp);
170665278823Srjs 		INP_INFO_WUNLOCK(&dccpbinfo);
170765278823Srjs 		return EISCONN;
170865278823Srjs 	}
170965278823Srjs 
171065278823Srjs 	dp = (struct dccpcb *)inp->inp_ppcb;
171165278823Srjs 
171265278823Srjs 	if (dp->state == DCCPS_ESTAB) {
17134dbe3593Sandvar 		DCCP_DEBUG((LOG_INFO, "Why are we in connect when we already have an established connection?\n"));
171465278823Srjs 	}
171565278823Srjs 
171665278823Srjs 	dp->who = DCCP_CLIENT;
171765278823Srjs 	dp->seq_snd = (((u_int64_t)random() << 32) | random()) % 281474976710656LL;
171865278823Srjs 	dp->ref_seq.hi = dp->seq_snd >> 24;
171965278823Srjs 	dp->ref_seq.lo = (u_int64_t)(dp->seq_snd & 0xffffff);
172065278823Srjs 	DCCP_DEBUG((LOG_INFO, "dccp_connect seq_snd %llu\n", dp->seq_snd));
172165278823Srjs 
172265278823Srjs 	dccpstat.dccps_connattempt++;
172365278823Srjs 
172465278823Srjs 	sin = (struct sockaddr_in *)nam;
172565278823Srjs 	if (sin->sin_family == AF_INET
172665278823Srjs 	    && IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
172765278823Srjs 		error = EAFNOSUPPORT;
172865278823Srjs 		goto bad;
172965278823Srjs 	}
173065278823Srjs 
1731fd12cf39Srtr 	error = dccp_doconnect(so, nam, l, 0);
173265278823Srjs 
173365278823Srjs 	if (error != 0)
173465278823Srjs 		goto bad;
173565278823Srjs 
173665278823Srjs 	callout_reset(&dp->retrans_timer, dp->retrans, dccp_retrans_t, dp);
173765278823Srjs 	callout_reset(&dp->connect_timer, DCCP_CONNECT_TIMER, dccp_connect_t, dp);
173865278823Srjs 
173965278823Srjs 	if (dccp_do_feature_nego){
174065278823Srjs 		test[0] = dp->pref_cc;
174165278823Srjs 		dccp_add_feature(dp, DCCP_OPT_CHANGE_R, DCCP_FEATURE_CC, test, 1);
174265278823Srjs 	}
174365278823Srjs 
174465278823Srjs 	error = dccp_output(dp, 0);
174565278823Srjs 
174665278823Srjs bad:
174765278823Srjs 	INP_UNLOCK(inp);
174865278823Srjs 	INP_INFO_WUNLOCK(&dccpbinfo);
174965278823Srjs 	return error;
175065278823Srjs }
175165278823Srjs 
175265278823Srjs static int
dccp_connect2(struct socket * so,struct socket * so2)175365278823Srjs dccp_connect2(struct socket *so, struct socket *so2)
175465278823Srjs {
175565278823Srjs 	KASSERT(solocked(so));
175665278823Srjs 
175765278823Srjs 	return EOPNOTSUPP;
175865278823Srjs }
175965278823Srjs 
176065278823Srjs /*
176165278823Srjs  *
176265278823Srjs  *
176365278823Srjs  */
176465278823Srjs int
dccp_doconnect(struct socket * so,struct sockaddr * nam,struct lwp * l,int isipv6)1765fd12cf39Srtr dccp_doconnect(struct socket *so, struct sockaddr *nam,
1766fd12cf39Srtr     struct lwp *l, int isipv6)
176765278823Srjs {
176865278823Srjs 	struct inpcb *inp;
176965278823Srjs 	int error = 0;
177065278823Srjs 
177165278823Srjs 	DCCP_DEBUG((LOG_INFO, "Entering dccp_doconnect!\n"));
177265278823Srjs 
177365278823Srjs 	inp = sotoinpcb(so);
177465278823Srjs 
177565278823Srjs 	if (inp->inp_lport == 0) {
177665278823Srjs #ifdef INET6
177765278823Srjs 		if (isipv6) {
1778b000e63fSozaki-r 			DCCP_DEBUG((LOG_INFO, "Running in6pcb_bind!\n"));
1779b000e63fSozaki-r 			error = in6pcb_bind(inp, NULL, l);
178065278823Srjs 		} else
178165278823Srjs #endif /* INET6 */
178265278823Srjs 		{
17832ba9f052Sozaki-r 			error = inpcb_bind(inp, NULL, l);
178465278823Srjs 		}
178565278823Srjs 		if (error) {
17862ba9f052Sozaki-r 			DCCP_DEBUG((LOG_INFO, "inpcb_bind=%d\n",error));
178765278823Srjs 			return error;
178865278823Srjs 		}
178965278823Srjs 	}
179065278823Srjs 
179165278823Srjs #ifdef INET6
179265278823Srjs 	if (isipv6) {
1793b000e63fSozaki-r 		error = in6pcb_connect(inp, (struct sockaddr_in6 *)nam, l);
1794b000e63fSozaki-r 		DCCP_DEBUG((LOG_INFO, "in6pcb_connect=%d\n",error));
179565278823Srjs 	} else
179665278823Srjs #endif
17972ba9f052Sozaki-r 		error = inpcb_connect(inp, (struct sockaddr_in *)nam, l);
179865278823Srjs 	if (error) {
17992ba9f052Sozaki-r 		DCCP_DEBUG((LOG_INFO, "inpcb_connect=%d\n",error));
180065278823Srjs 		return error;
180165278823Srjs 	}
180265278823Srjs 
180365278823Srjs 	soisconnecting(so);
180465278823Srjs 	return error;
180565278823Srjs }
180665278823Srjs 
180765278823Srjs /*
180865278823Srjs  * Detaches the DCCP protocol from the socket.
180965278823Srjs  *
181065278823Srjs  */
181165278823Srjs int
dccp_detach(struct socket * so)181265278823Srjs dccp_detach(struct socket *so)
181365278823Srjs {
181465278823Srjs 	struct inpcb *inp;
181565278823Srjs 	struct dccpcb *dp;
181665278823Srjs 
181765278823Srjs 	DCCP_DEBUG((LOG_INFO, "Entering dccp_detach!\n"));
181865278823Srjs 	inp = sotoinpcb(so);
1819f8c27a68Sozaki-r 	if (inp == NULL) {
182065278823Srjs 		return EINVAL;
182165278823Srjs 	}
1822f8c27a68Sozaki-r 	dp = inp->inp_ppcb;
182365278823Srjs 	if (! dccp_disconnect2(dp)) {
182465278823Srjs 		INP_UNLOCK(inp);
182565278823Srjs 	}
182665278823Srjs 	INP_INFO_WUNLOCK(&dccpbinfo);
182765278823Srjs 	return 0;
182865278823Srjs }
182965278823Srjs 
183065278823Srjs /*
183165278823Srjs  *
183265278823Srjs  *
183365278823Srjs  */
183465278823Srjs int
dccp_disconnect(struct socket * so)183565278823Srjs dccp_disconnect(struct socket *so)
183665278823Srjs {
183765278823Srjs 	struct inpcb *inp;
183865278823Srjs 	struct dccpcb *dp;
183965278823Srjs 
184065278823Srjs 	DCCP_DEBUG((LOG_INFO, "Entering dccp_disconnect!\n"));
184165278823Srjs 	INP_INFO_WLOCK(&dccpbinfo);
184265278823Srjs #ifndef __NetBSD__
184365278823Srjs 	inp = sotoinpcb(so);
184465278823Srjs 	if (inp == 0) {
184565278823Srjs 		INP_INFO_WUNLOCK(&dccpbinfo);
184665278823Srjs 		return EINVAL;
184765278823Srjs 	}
184865278823Srjs 	INP_LOCK(inp);
18497118c214Sozaki-r 	if (in4p_faddr(inp).s_addr == INADDR_ANY) {
185065278823Srjs 		INP_INFO_WUNLOCK(&dccpbinfo);
185165278823Srjs 		INP_UNLOCK(inp);
185265278823Srjs 		return ENOTCONN;
185365278823Srjs 	}
185465278823Srjs 
185565278823Srjs 	dp = (struct dccpcb *)inp->inp_ppcb;
185665278823Srjs #else /* NetBSD */
1857f8c27a68Sozaki-r 	inp = sotoinpcb(so);
1858f8c27a68Sozaki-r 	if (inp == NULL) {
185965278823Srjs 		INP_INFO_WUNLOCK(&dccpbinfo);
186065278823Srjs 		return EINVAL;
186165278823Srjs 	}
1862f8c27a68Sozaki-r 	dp = inp->inp_ppcb;
186365278823Srjs #endif
186465278823Srjs 	if (!dccp_disconnect2(dp)) {
186565278823Srjs 		INP_UNLOCK(inp);
186665278823Srjs 	}
186765278823Srjs 	INP_INFO_WUNLOCK(&dccpbinfo);
186865278823Srjs 	return 0;
186965278823Srjs }
187065278823Srjs 
187165278823Srjs /*
18724dbe3593Sandvar  * If we have don't have an established connection
187365278823Srjs  * we can call dccp_close, otherwise we can just
187465278823Srjs  * set SS_ISDISCONNECTED and flush the receive queue.
187565278823Srjs  */
187665278823Srjs static int
dccp_disconnect2(struct dccpcb * dp)187765278823Srjs dccp_disconnect2(struct dccpcb *dp)
187865278823Srjs {
187965278823Srjs 	struct socket *so = dptosocket(dp);
188065278823Srjs 
188165278823Srjs 	DCCP_DEBUG((LOG_INFO, "Entering dccp_disconnect2!\n"));
188265278823Srjs 
188365278823Srjs 	if (dp->state < DCCPS_ESTAB) {
188465278823Srjs 		dccp_close(dp);
188565278823Srjs 		return 1;
188665278823Srjs 	} else {
188765278823Srjs 		soisdisconnecting(so);
188865278823Srjs 		sbflush(&so->so_rcv);
188965278823Srjs 		if (dp->state == DCCPS_ESTAB) {
189065278823Srjs 			dp->retrans = 100;
189165278823Srjs 			callout_reset(&dp->retrans_timer, dp->retrans,
189265278823Srjs 			    dccp_retrans_t, dp);
189365278823Srjs 			callout_reset(&dp->close_timer, DCCP_CLOSE_TIMER,
189465278823Srjs 			    dccp_close_t, dp);
189565278823Srjs 			if (dp->who == DCCP_CLIENT) {
189665278823Srjs 				dp->state = DCCPS_CLIENT_CLOSE;
189765278823Srjs 			} else {
189865278823Srjs 				dp->state = DCCPS_SERVER_CLOSE;
189965278823Srjs 			}
190065278823Srjs 			dccp_output(dp, 0);
190165278823Srjs 		}
190265278823Srjs 	}
190365278823Srjs 	return 0;
190465278823Srjs }
190565278823Srjs 
190665278823Srjs int
dccp_send(struct socket * so,struct mbuf * m,struct sockaddr * addr,struct mbuf * control,struct lwp * l)1907fd12cf39Srtr dccp_send(struct socket *so, struct mbuf *m, struct sockaddr *addr,
190865278823Srjs     struct mbuf *control, struct lwp *l)
190965278823Srjs {
191065278823Srjs 	struct inpcb	*inp;
191165278823Srjs 	struct dccpcb	*dp;
191265278823Srjs 	int		error = 0;
191365278823Srjs 	int		isipv6 = 0;
191465278823Srjs 
191565278823Srjs 	DCCP_DEBUG((LOG_INFO, "Entering dccp_send!\n"));
191665278823Srjs 	KASSERT(solocked(so));
191765278823Srjs 	KASSERT(m != NULL);
191865278823Srjs 
191965278823Srjs 	if (control && control->m_len) {
192065278823Srjs 		m_freem(control);
192165278823Srjs 		m_freem(m);
192265278823Srjs 		return EINVAL;
192365278823Srjs 	}
192465278823Srjs 
192565278823Srjs #ifdef INET6
192665278823Srjs 	isipv6 = addr && addr->sa_family == AF_INET6;
192765278823Srjs #endif
192865278823Srjs 
192965278823Srjs 	INP_INFO_WLOCK(&dccpbinfo);
193065278823Srjs 	inp = sotoinpcb(so);
1931f8c27a68Sozaki-r 	if (inp == NULL) {
193265278823Srjs 		error = EINVAL;
193365278823Srjs 		goto release;
193465278823Srjs 	}
193565278823Srjs 	INP_LOCK(inp);
1936f8c27a68Sozaki-r 	dp = inp->inp_ppcb;
1937f8c27a68Sozaki-r 
193865278823Srjs 	if (dp->state != DCCPS_ESTAB) {
193965278823Srjs 		DCCP_DEBUG((LOG_INFO, "We have no established connection!\n"));
194065278823Srjs 	}
194165278823Srjs 
194265278823Srjs 	if (control != NULL) {
194365278823Srjs 		DCCP_DEBUG((LOG_INFO, "We got a control message!\n"));
194465278823Srjs 		/* Are we going to use control messages??? */
194565278823Srjs 		if (control->m_len) {
194665278823Srjs 			m_freem(control);
194765278823Srjs 		}
194865278823Srjs 	}
194965278823Srjs 
19505d8a69c4Schristos 	if (sbspace_oob(&so->so_snd) == 0) {
195165278823Srjs 		INP_UNLOCK(inp);
195265278823Srjs 		error = ENOBUFS;
195365278823Srjs 		goto release;
195465278823Srjs 	}
195565278823Srjs 
195665278823Srjs 	if (m->m_pkthdr.len > dp->d_maxseg) {
195765278823Srjs 		/* XXX we should calculate packet size more carefully */
195865278823Srjs 		INP_UNLOCK(inp);
195965278823Srjs 		error = EINVAL;
196065278823Srjs 		goto release;
196165278823Srjs 	}
196265278823Srjs 
196365278823Srjs 	if (dp->pktcnt >= DCCP_MAX_PKTS) {
196465278823Srjs 		INP_UNLOCK(inp);
196565278823Srjs 		error = ENOBUFS;
196665278823Srjs 		goto release;
196765278823Srjs 	}
196865278823Srjs 
196965278823Srjs 	sbappend(&so->so_snd, m);
197065278823Srjs 	dp->pktlen[(dp->pktlenidx + dp->pktcnt) % DCCP_MAX_PKTS] = m->m_pkthdr.len;
197165278823Srjs 	dp->pktcnt ++;
197265278823Srjs 
197365278823Srjs 	if (addr && dp->state == DCCPS_CLOSED) {
1974fd12cf39Srtr 		error = dccp_doconnect(so, addr, l, isipv6);
197565278823Srjs 		if (error)
197665278823Srjs 			goto out;
197765278823Srjs 	}
197865278823Srjs 
197965278823Srjs 	error = dccp_output(dp, 0);
198065278823Srjs 
198165278823Srjs out:
198265278823Srjs 	INP_UNLOCK(inp);
198365278823Srjs 	INP_INFO_WUNLOCK(&dccpbinfo);
198465278823Srjs 	return error;
198565278823Srjs 
198665278823Srjs release:
198765278823Srjs 	INP_INFO_WUNLOCK(&dccpbinfo);
198865278823Srjs 	m_freem(m);
198965278823Srjs 	return (error);
199065278823Srjs }
199165278823Srjs 
199265278823Srjs /*
199365278823Srjs  * Sets socket to SS_CANTSENDMORE
199465278823Srjs  */
199565278823Srjs int
dccp_shutdown(struct socket * so)199665278823Srjs dccp_shutdown(struct socket *so)
199765278823Srjs {
199865278823Srjs 	struct inpcb *inp;
199965278823Srjs 
200065278823Srjs 	DCCP_DEBUG((LOG_INFO, "Entering dccp_shutdown!\n"));
200165278823Srjs 	INP_INFO_RLOCK(&dccpbinfo);
200265278823Srjs 	inp = sotoinpcb(so);
200365278823Srjs 	if (inp == 0) {
200465278823Srjs 		INP_INFO_RUNLOCK(&dccpbinfo);
200565278823Srjs 		return EINVAL;
200665278823Srjs 	}
200765278823Srjs 	INP_LOCK(inp);
200865278823Srjs 	INP_INFO_RUNLOCK(&dccpbinfo);
200965278823Srjs 	socantsendmore(so);
201065278823Srjs 	INP_UNLOCK(inp);
201165278823Srjs 	return 0;
201265278823Srjs }
201365278823Srjs 
201465278823Srjs static int
dccp_listen(struct socket * so,struct lwp * td)201565278823Srjs dccp_listen(struct socket *so, struct lwp *td)
201665278823Srjs {
201765278823Srjs 	struct inpcb *inp;
201865278823Srjs 	struct dccpcb *dp;
201965278823Srjs 	int error = 0;
202065278823Srjs 
202165278823Srjs 	DCCP_DEBUG((LOG_INFO, "Entering dccp_listen!\n"));
202265278823Srjs 
202365278823Srjs 	INP_INFO_RLOCK(&dccpbinfo);
202465278823Srjs 	inp = sotoinpcb(so);
202565278823Srjs 	if (inp == 0) {
202665278823Srjs 		INP_INFO_RUNLOCK(&dccpbinfo);
202765278823Srjs 		return EINVAL;
202865278823Srjs 	}
202965278823Srjs 	INP_LOCK(inp);
203065278823Srjs 	INP_INFO_RUNLOCK(&dccpbinfo);
203165278823Srjs 	dp = (struct dccpcb *)inp->inp_ppcb;
203265278823Srjs 	if (inp->inp_lport == 0)
20332ba9f052Sozaki-r 		error = inpcb_bind(inp, NULL, td);
203465278823Srjs 	if (error == 0) {
203565278823Srjs 		dp->state = DCCPS_LISTEN;
203665278823Srjs 		dp->who = DCCP_LISTENER;
203765278823Srjs 	}
203865278823Srjs 	INP_UNLOCK(inp);
203965278823Srjs 	return error;
204065278823Srjs }
204165278823Srjs 
204265278823Srjs /*
204365278823Srjs  * Accepts a connection (accept system call)
204465278823Srjs  */
204565278823Srjs static int
dccp_accept(struct socket * so,struct sockaddr * nam)2046eddf3af3Srtr dccp_accept(struct socket *so, struct sockaddr *nam)
204765278823Srjs {
204865278823Srjs 	struct inpcb *inp = NULL;
204965278823Srjs 	int error = 0;
205065278823Srjs 
205165278823Srjs 	DCCP_DEBUG((LOG_INFO, "Entering dccp_accept!\n"));
205265278823Srjs 
205365278823Srjs 	if (nam == NULL) {
205465278823Srjs 		return EINVAL;
205565278823Srjs 	}
205665278823Srjs 	if (so->so_state & SS_ISDISCONNECTED) {
205765278823Srjs 		DCCP_DEBUG((LOG_INFO, "so_state && SS_ISDISCONNECTED!, so->state = %i\n", so->so_state));
205865278823Srjs 		return ECONNABORTED;
205965278823Srjs 	}
206065278823Srjs 
206165278823Srjs 	INP_INFO_RLOCK(&dccpbinfo);
206265278823Srjs 	inp = sotoinpcb(so);
206365278823Srjs 	if (inp == 0) {
206465278823Srjs 		INP_INFO_RUNLOCK(&dccpbinfo);
206565278823Srjs 		return EINVAL;
206665278823Srjs 	}
206765278823Srjs 	INP_LOCK(inp);
206865278823Srjs 	INP_INFO_RUNLOCK(&dccpbinfo);
20692ba9f052Sozaki-r 	inpcb_fetch_peeraddr(inp, (struct sockaddr_in *)nam);
207065278823Srjs 
207165278823Srjs 	return error;
207265278823Srjs }
207365278823Srjs 
207465278823Srjs /*
207565278823Srjs  * Initializes a new DCCP control block
20762ba9f052Sozaki-r  * (inpcb_create in attach has already allocated memory for it)
207765278823Srjs  */
207865278823Srjs struct dccpcb *
dccp_newdccpcb(int family,void * aux)207965278823Srjs dccp_newdccpcb(int family, void *aux)
208065278823Srjs {
208165278823Srjs 	struct inpcb *inp;
208265278823Srjs 	struct dccpcb	*dp;
208365278823Srjs 
208465278823Srjs 	DCCP_DEBUG((LOG_INFO, "Creating a new dccpcb!\n"));
208565278823Srjs 
208665278823Srjs 	dp = pool_get(&dccpcb_pool, PR_NOWAIT);
208765278823Srjs 	if (dp == NULL)
208865278823Srjs 		return NULL;
2089a72ef8c3Srjs 	memset((char *) dp, 0, sizeof(struct dccpcb));
209065278823Srjs 
209165278823Srjs 	callout_init(&dp->connect_timer, 0);
209265278823Srjs 	callout_init(&dp->retrans_timer, 0);
209365278823Srjs 	callout_init(&dp->close_timer, 0);
209465278823Srjs 	callout_init(&dp->timewait_timer, 0);
209565278823Srjs 
209665278823Srjs 	dp->ndp = 0;
209765278823Srjs 	dp->loss_window = 1000;
209865278823Srjs 	dp->cslen = 0;
209965278823Srjs 	dp->pref_cc = DEFAULT_CCID;
210065278823Srjs 	dp->who = DCCP_UNDEF;
210165278823Srjs 	dp->seq_snd = 0;
210265278823Srjs 	dp->seq_rcv = 0;
210365278823Srjs 	dp->shortseq = 0;
210465278823Srjs 	dp->gsn_rcv = 281474976710656LL;
210565278823Srjs 	dp->optlen = 0;
210665278823Srjs 	if (dccp_do_feature_nego){
210765278823Srjs 		dp->cc_in_use[0] = -1;
210865278823Srjs 		dp->cc_in_use[1] = -1;
210965278823Srjs 	} else {
211065278823Srjs 		/* for compatibility with linux */
211165278823Srjs 		dp->cc_in_use[0] = 4;
211265278823Srjs 		dp->cc_in_use[1] = 4;
211365278823Srjs 	}
211465278823Srjs 	dp->av_size = 0; /* no ack vector initially */
211565278823Srjs 	dp->remote_ackvector = 0; /* no ack vector on remote side initially */
211665278823Srjs 	dp->retrans = 200;
211765278823Srjs 	dp->avgpsize = 0;
211865278823Srjs 	dp->d_maxseg = 1400;
211965278823Srjs 	dp->ref_pseq.hi = 0;
212065278823Srjs 	dp->ref_pseq.lo = 0;
212165278823Srjs 	dp->pktlenidx = 0;
212265278823Srjs 	dp->pktcnt = 0;
212365278823Srjs 
212465278823Srjs 	inp = (struct inpcb *)aux;
212565278823Srjs 	dp->d_inpcb = inp;
212665278823Srjs 	inp->inp_ppcb = dp;
2127f8c27a68Sozaki-r 	switch (family) {
2128f8c27a68Sozaki-r 	case PF_INET:
21297118c214Sozaki-r 		in4p_ip(inp).ip_ttl = ip_defttl;
213065278823Srjs 		break;
213165278823Srjs 	case PF_INET6:
2132b000e63fSozaki-r 		in6p_ip6(inp).ip6_hlim = in6pcb_selecthlim_rt(inp);
213365278823Srjs 		break;
213465278823Srjs 	}
213565278823Srjs 
213665278823Srjs 	if (!dccp_do_feature_nego){
213765278823Srjs 		dp->cc_state[0] = (*cc_sw[4].cc_send_init)(dp);
213865278823Srjs 		dp->cc_state[1] = (*cc_sw[4].cc_recv_init)(dp);
213965278823Srjs 	}
214065278823Srjs 
214165278823Srjs 	return dp;
214265278823Srjs }
214365278823Srjs 
214465278823Srjs int
dccp_add_option(struct dccpcb * dp,u_int8_t opt,char * val,u_int8_t val_len)214565278823Srjs dccp_add_option(struct dccpcb *dp, u_int8_t opt, char *val, u_int8_t val_len)
214665278823Srjs {
214765278823Srjs 	return dccp_add_feature_option(dp, opt, 0, val, val_len);
214865278823Srjs }
214965278823Srjs 
215065278823Srjs int
dccp_add_feature_option(struct dccpcb * dp,u_int8_t opt,u_int8_t feature,char * val,u_int8_t val_len)215165278823Srjs dccp_add_feature_option(struct dccpcb *dp, u_int8_t opt, u_int8_t feature, char *val, u_int8_t val_len)
215265278823Srjs {
215365278823Srjs 	int i;
215465278823Srjs 	DCCP_DEBUG((LOG_INFO, "Entering dccp_add_feature_option, opt = %u, val_len = %u optlen %u\n", opt, val_len, dp->optlen));
215565278823Srjs 
215665278823Srjs 	if (DCCP_MAX_OPTIONS > (dp->optlen + val_len + 2)) {
215765278823Srjs 		dp->options[dp->optlen] = opt;
215865278823Srjs 		if (opt < 32) {
215965278823Srjs 			dp->optlen++;
216065278823Srjs 		} else {
216165278823Srjs 			if (opt == DCCP_OPT_CONFIRM_L && val_len) {
216265278823Srjs 				dp->options[dp->optlen + 1] = val_len + 3;
216365278823Srjs 				dp->options[dp->optlen +2] = feature;
216465278823Srjs 				dp->optlen += 3;
216565278823Srjs 			} else {
216665278823Srjs 				dp->options[dp->optlen + 1] = val_len + 2;
216765278823Srjs 				dp->optlen += 2;
216865278823Srjs 			}
216965278823Srjs 
217065278823Srjs 			for (i = 0; i<val_len; i++) {
217165278823Srjs 				dp->options[dp->optlen] = val[i];
217265278823Srjs 				dp->optlen++;
217365278823Srjs 			}
217465278823Srjs 		}
217565278823Srjs 	} else {
217665278823Srjs 		DCCP_DEBUG((LOG_INFO, "No room for more options, optlen = %u\n", dp->optlen));
217765278823Srjs 		return -1;
217865278823Srjs 	}
217965278823Srjs 
218065278823Srjs 	return 0;
218165278823Srjs }
218265278823Srjs 
218365278823Srjs /*
218465278823Srjs  * Searches "options" for given option type. if found, the data is copied to buffer
218565278823Srjs  * and returns the data length.
218665278823Srjs  * Returns 0 if option type not found
218765278823Srjs  */
218865278823Srjs int
dccp_get_option(char * options,int optlen,int type,char * buffer,int buflen)218965278823Srjs dccp_get_option(char *options, int optlen, int type, char *buffer, int buflen)
219065278823Srjs {
219165278823Srjs 	int i, j, size;
219265278823Srjs 	u_int8_t t;
219365278823Srjs 
219465278823Srjs 	for (i=0; i < optlen;) {
219565278823Srjs 		t = options[i++];
219665278823Srjs 		if (t >= 32) {
219765278823Srjs 			size = options[i++] - 2;
219865278823Srjs 			if (t == type) {
219965278823Srjs 				if (size > buflen)
220065278823Srjs 					return 0;
220165278823Srjs 				for (j = 0; j < size; j++)
220265278823Srjs 					buffer[j] = options[i++];
220365278823Srjs 				return size;
220465278823Srjs 			}
220565278823Srjs 			i += size;
220665278823Srjs 		}
220765278823Srjs 	}
220865278823Srjs 	/* If we get here the options was not found */
220965278823Srjs 	DCCP_DEBUG((LOG_INFO, "dccp_get_option option(%d) not found\n", type));
221065278823Srjs 	return 0;
221165278823Srjs }
221265278823Srjs 
221365278823Srjs void
dccp_parse_options(struct dccpcb * dp,char * options,int optlen)221465278823Srjs dccp_parse_options(struct dccpcb *dp, char *options, int optlen)
221565278823Srjs {
221665278823Srjs 	u_int8_t opt, size, i, j;
221765278823Srjs 	char val[8];
221865278823Srjs 
221965278823Srjs 	for (i = 0; i < optlen; i++) {
222065278823Srjs 		opt = options[i];
222165278823Srjs 
222265278823Srjs 		DCCP_DEBUG((LOG_INFO, "Parsing opt: 0x%02x\n", opt));
222365278823Srjs 
222465278823Srjs 		if (opt < 32) {
222565278823Srjs 			switch (opt) {
222665278823Srjs 			    case DCCP_OPT_PADDING:
222765278823Srjs 				DCCP_DEBUG((LOG_INFO, "Got DCCP_OPT_PADDING!\n"));
222865278823Srjs 				break;
222965278823Srjs 			    case DCCP_OPT_DATA_DISCARD:
223065278823Srjs 				DCCP_DEBUG((LOG_INFO, "Got DCCP_OPT_DATA_DISCARD!\n"));
223165278823Srjs 				break;
223265278823Srjs 			    case DCCP_OPT_SLOW_RECV:
223365278823Srjs 				DCCP_DEBUG((LOG_INFO, "Got DCCP_OPT_SLOW_RECV!\n"));
223465278823Srjs 				break;
223565278823Srjs 			    case DCCP_OPT_BUF_CLOSED:
223665278823Srjs 				DCCP_DEBUG((LOG_INFO, "Got DCCP_OPT_BUF_CLOSED!\n"));
223765278823Srjs 				break;
223865278823Srjs 			    default:
223965278823Srjs 				DCCP_DEBUG((LOG_INFO, "Got an unknown option, option = %u!\n", opt));
224065278823Srjs 			}
224165278823Srjs 		} else if (opt > 32 && opt < 36) {
224265278823Srjs 			size = options[i+ 1];
224365278823Srjs 			if (size < 3 || size > 10) {
224465278823Srjs 				DCCP_DEBUG((LOG_INFO, "Error, option size = %u\n", size));
224565278823Srjs 				return;
224665278823Srjs 			}
224765278823Srjs 			/* Feature negotiations are options 33 to 35 */
224865278823Srjs 			DCCP_DEBUG((LOG_INFO, "Got option %u, size = %u, feature = %u\n", opt, size, options[i+2]));
2249a72ef8c3Srjs 			memcpy(val, options + i + 3, size -3);
225065278823Srjs 			DCCP_DEBUG((LOG_INFO, "Calling dccp_feature neg(%u, %u, options[%u + 1], %u)!\n", (u_int)dp, opt, i+ 1, (size - 3)));
225165278823Srjs 			dccp_feature_neg(dp, opt, options[i+2], (size -3) , val);
225265278823Srjs 			i += size - 1;
225365278823Srjs 
225465278823Srjs 		} else if (opt < 128) {
225565278823Srjs 			size = options[i+ 1];
225665278823Srjs 			if (size < 3 || size > 10) {
225765278823Srjs 				DCCP_DEBUG((LOG_INFO, "Error, option size = %u\n", size));
225865278823Srjs 				return;
225965278823Srjs 			}
226065278823Srjs 
226165278823Srjs 			switch (opt) {
226265278823Srjs 			    case DCCP_OPT_RECV_BUF_DROPS:
226365278823Srjs 					DCCP_DEBUG((LOG_INFO, "Got DCCP_OPT_RECV_BUF_DROPS, size = %u!\n", size));
226465278823Srjs 					for (j=2; j < size; j++) {
226565278823Srjs 						DCCP_DEBUG((LOG_INFO, "val[%u] = %u ", j-1, options[i+j]));
226665278823Srjs 					}
226765278823Srjs 					DCCP_DEBUG((LOG_INFO, "\n"));
226865278823Srjs 				break;
226965278823Srjs 
227065278823Srjs 			    case DCCP_OPT_TIMESTAMP:
227165278823Srjs 					DCCP_DEBUG((LOG_INFO, "Got DCCP_OPT_TIMESTAMP, size = %u\n", size));
227265278823Srjs 
227365278823Srjs 					/* Adding TimestampEcho to next outgoing */
2274a72ef8c3Srjs 					memcpy(val, options + i + 2, 4);
2275a72ef8c3Srjs 					memset(val + 4, 0, 4);
227665278823Srjs 					dccp_add_option(dp, DCCP_OPT_TIMESTAMP_ECHO, val, 8);
227765278823Srjs 				break;
227865278823Srjs 
227965278823Srjs 			    case DCCP_OPT_TIMESTAMP_ECHO:
228065278823Srjs 					DCCP_DEBUG((LOG_INFO, "Got DCCP_OPT_TIMESTAMP_ECHO, size = %u\n",size));
228165278823Srjs 					for (j=2; j < size; j++) {
228265278823Srjs 						DCCP_DEBUG((LOG_INFO, "val[%u] = %u ", j-1, options[i+j]));
228365278823Srjs 					}
228465278823Srjs 					DCCP_DEBUG((LOG_INFO, "\n"));
228565278823Srjs 
228665278823Srjs 					/*
2287a72ef8c3Srjs 					memcpy(&(dp->timestamp_echo), options + i + 2, 4);
2288a72ef8c3Srjs 					memcpy(&(dp->timestamp_elapsed), options + i + 6, 4);
228965278823Srjs 					ACK_DEBUG((LOG_INFO, "DATA; echo = %u , elapsed = %u\n",
229065278823Srjs 					    dp->timestamp_echo, dp->timestamp_elapsed));
229165278823Srjs 					*/
229265278823Srjs 
229365278823Srjs 				break;
229465278823Srjs 
229565278823Srjs 			case DCCP_OPT_ACK_VECTOR0:
229665278823Srjs 			case DCCP_OPT_ACK_VECTOR1:
229765278823Srjs 			case DCCP_OPT_ELAPSEDTIME:
229865278823Srjs 				/* Dont do nothing here. Let the CC deal with it */
229965278823Srjs 				break;
230065278823Srjs 
230165278823Srjs 			default:
230265278823Srjs 				DCCP_DEBUG((LOG_INFO, "Got an unknown option, option = %u, size = %u!\n", opt, size));
230365278823Srjs 				break;
230465278823Srjs 
230565278823Srjs 			}
230665278823Srjs 			i += size - 1;
230765278823Srjs 
230865278823Srjs 		} else {
230965278823Srjs 			DCCP_DEBUG((LOG_INFO, "Got a CCID option (%d), do nothing!\n", opt));
231065278823Srjs 			size = options[i+ 1];
231165278823Srjs 			if (size < 3 || size > 10) {
231265278823Srjs 				DCCP_DEBUG((LOG_INFO, "Error, option size = %u\n", size));
231365278823Srjs 				return;
231465278823Srjs 			}
231565278823Srjs 			i += size - 1;
231665278823Srjs 		}
231765278823Srjs 	}
231865278823Srjs 
231965278823Srjs }
232065278823Srjs 
232165278823Srjs int
dccp_add_feature(struct dccpcb * dp,u_int8_t opt,u_int8_t feature,char * val,u_int8_t val_len)232265278823Srjs dccp_add_feature(struct dccpcb *dp, u_int8_t opt, u_int8_t feature, char *val, u_int8_t val_len)
232365278823Srjs {
232465278823Srjs 	int i;
232565278823Srjs 	DCCP_DEBUG((LOG_INFO, "Entering dccp_add_feature, opt = %u, feature = %u, val_len = %u\n", opt, feature, val_len));
232665278823Srjs 
232765278823Srjs 	if (DCCP_MAX_OPTIONS > (dp->featlen + val_len + 3)) {
232865278823Srjs 		dp->features[dp->featlen] = opt;
232965278823Srjs 		dp->features[dp->featlen + 1] = val_len + 3;
233065278823Srjs 		dp->features[dp->featlen +2] = feature;
233165278823Srjs 		dp->featlen += 3;
233265278823Srjs 		for (i = 0; i<val_len; i++) {
233365278823Srjs 			dp->features[dp->featlen] = val[i];
233465278823Srjs 			dp->featlen++;
233565278823Srjs 		}
233665278823Srjs 	} else {
233765278823Srjs 		DCCP_DEBUG((LOG_INFO, "No room for more features, featlen = %u\n", dp->featlen));
233865278823Srjs 		return -1;
233965278823Srjs 	}
234065278823Srjs 
234165278823Srjs 	return 0;
234265278823Srjs }
234365278823Srjs 
234465278823Srjs int
dccp_remove_feature(struct dccpcb * dp,u_int8_t opt,u_int8_t feature)234565278823Srjs dccp_remove_feature(struct dccpcb *dp, u_int8_t opt, u_int8_t feature)
234665278823Srjs {
234765278823Srjs 	int i = 0, j = 0, k;
234865278823Srjs 	u_int8_t t_opt, t_feature, len;
234965278823Srjs 	DCCP_DEBUG((LOG_INFO, "Entering dccp_remove_feature, featlen = %u, opt = %u, feature = %u\n", dp->featlen, opt, feature));
235065278823Srjs 
235165278823Srjs 	while (i < dp->featlen) {
235265278823Srjs 		t_opt = dp->features[i];
235365278823Srjs 		len = dp->features[i+ 1];
235465278823Srjs 
235565278823Srjs 		if (i + len > dp->featlen) {
235665278823Srjs 			DCCP_DEBUG((LOG_INFO, "Error, len = %u and i(%u) + len > dp->featlen (%u)\n", len, i, dp->featlen));
235765278823Srjs 			return 1;
235865278823Srjs 		}
235965278823Srjs 		t_feature = dp->features[i+2];
236065278823Srjs 
236165278823Srjs 		if (t_opt == opt && t_feature == feature) {
236265278823Srjs 			i += len;
236365278823Srjs 		} else {
236465278823Srjs 			if (i != j) {
236565278823Srjs 				for (k = 0; k < len; k++) {
236665278823Srjs 					dp->features[j+k] = dp->features[i+k];
236765278823Srjs 				}
236865278823Srjs 			}
236965278823Srjs 			i += len;
237065278823Srjs 			j += len;
237165278823Srjs 		}
237265278823Srjs 	}
237365278823Srjs 	dp->featlen = j;
237465278823Srjs 	DCCP_DEBUG((LOG_INFO, "Exiting dccp_remove_feature, featlen = %u\n", dp->featlen));
237565278823Srjs 	return 0;
237665278823Srjs }
237765278823Srjs 
237865278823Srjs void
dccp_feature_neg(struct dccpcb * dp,u_int8_t opt,u_int8_t feature,u_int8_t val_len,char * val)237965278823Srjs dccp_feature_neg(struct dccpcb *dp, u_int8_t opt, u_int8_t feature, u_int8_t val_len, char *val)
238065278823Srjs {
238165278823Srjs 	DCCP_DEBUG((LOG_INFO, "Running dccp_feature_neg, opt = %u, feature = %u len = %u ", opt, feature, val_len));
238265278823Srjs 
238365278823Srjs 	switch (feature) {
238465278823Srjs 		case DCCP_FEATURE_CC:
238565278823Srjs 			DCCP_DEBUG((LOG_INFO, "Got CCID negotiation, opt = %u, val[0] = %u\n", opt, val[0]));
238665278823Srjs 			if (opt == DCCP_OPT_CHANGE_R) {
238765278823Srjs 				if (val[0] == 2 || val[0] == 3 || val[0] == 0) {
238865278823Srjs 					/* try to use preferable CCID */
238965278823Srjs 					int i;
239065278823Srjs 					for (i = 1; i < val_len; i ++) if (val[i] == dp->pref_cc) val[0] = dp->pref_cc;
239165278823Srjs 					DCCP_DEBUG((LOG_INFO, "Sending DCCP_OPT_CONFIRM_L on CCID %u\n", val[0]));
239265278823Srjs 					dccp_remove_feature(dp, DCCP_OPT_CONFIRM_L, DCCP_FEATURE_CC);
239365278823Srjs 					dccp_add_feature_option(dp, DCCP_OPT_CONFIRM_L, DCCP_FEATURE_CC , val, 1);
239465278823Srjs 					if (dp->cc_in_use[0] < 1) {
239565278823Srjs 						dp->cc_state[0] = (*cc_sw[val[0] + 1].cc_send_init)(dp);
239665278823Srjs 						dp->cc_in_use[0] = val[0] + 1;
239765278823Srjs 					} else {
239865278823Srjs 						DCCP_DEBUG((LOG_INFO, "We already have negotiated a CC!!!\n"));
239965278823Srjs 					}
240065278823Srjs 				}
240165278823Srjs 			} else if (opt == DCCP_OPT_CONFIRM_L) {
240265278823Srjs 				DCCP_DEBUG((LOG_INFO, "Got DCCP_OPT_CONFIRM_L on CCID %u\n", val[0]));
240365278823Srjs 				dccp_remove_feature(dp, DCCP_OPT_CHANGE_R, DCCP_FEATURE_CC);
240465278823Srjs 				if (dp->cc_in_use[1] < 1) {
240565278823Srjs 					dp->cc_state[1] = (*cc_sw[val[0] + 1].cc_recv_init)(dp);
240665278823Srjs 					dp->cc_in_use[1] = val[0] + 1;
240765278823Srjs 					DCCP_DEBUG((LOG_INFO, "confirmed cc_in_use[1] = %d\n", dp->cc_in_use[1]));
240865278823Srjs 				} else {
240965278823Srjs 					DCCP_DEBUG((LOG_INFO, "We already have negotiated a CC!!! (confirm) %d\n", dp->cc_in_use[1]));
241065278823Srjs 				}
241165278823Srjs 			}
241265278823Srjs 
241365278823Srjs 		break;
241465278823Srjs 
241565278823Srjs 		case DCCP_FEATURE_ACKVECTOR:
241665278823Srjs 			ACK_DEBUG((LOG_INFO, "Got _Use Ack Vector_\n"));
241765278823Srjs 			if (opt == DCCP_OPT_CHANGE_R) {
241865278823Srjs 				if (val[0] == 1) {
241965278823Srjs 					dccp_use_ackvector(dp);
242065278823Srjs 					dccp_remove_feature(dp, DCCP_OPT_CONFIRM_L, DCCP_FEATURE_ACKVECTOR);
242165278823Srjs 					dccp_add_feature_option(dp, DCCP_OPT_CONFIRM_L, DCCP_FEATURE_ACKVECTOR , val, 1);
242265278823Srjs 				} else {
242365278823Srjs 					ACK_DEBUG((LOG_INFO, "ERROR. Strange val %u\n", val[0]));
242465278823Srjs 				}
242565278823Srjs 			} else if (opt == DCCP_OPT_CONFIRM_L) {
242665278823Srjs 					dccp_remove_feature(dp, DCCP_OPT_CONFIRM_L, DCCP_FEATURE_ACKVECTOR);
242765278823Srjs 			if (val[0] == 1) {
242865278823Srjs 					dp->remote_ackvector = 1;
242965278823Srjs 					ACK_DEBUG((LOG_INFO,"Remote side confirmed AckVector usage\n"));
243065278823Srjs 				} else {
243165278823Srjs 					ACK_DEBUG((LOG_INFO, "ERROR. Strange val %u\n", val[0]));
243265278823Srjs 				}
243365278823Srjs 			}
243465278823Srjs 			break;
243565278823Srjs 
243665278823Srjs 		case DCCP_FEATURE_ACKRATIO:
243765278823Srjs 			if (opt == DCCP_OPT_CHANGE_R) {
2438a72ef8c3Srjs 				memcpy(&(dp->ack_ratio), val, 1);
243965278823Srjs 				ACK_DEBUG((LOG_INFO, "Feature: Change Ack Ratio to %u\n", dp->ack_ratio));
244065278823Srjs 			}
244165278823Srjs 			break;
244265278823Srjs 
244365278823Srjs 		case DCCP_FEATURE_ECN:
244465278823Srjs 		case DCCP_FEATURE_MOBILITY:
244565278823Srjs 		default:
244665278823Srjs 			/* we should send back empty CONFIRM_L for unknown feature unless it's not mandatory */
244765278823Srjs 			dccp_add_option(dp, DCCP_OPT_CONFIRM_L, NULL, 0);
244865278823Srjs 		break;
244965278823Srjs 
245065278823Srjs 	}
245165278823Srjs }
245265278823Srjs 
245365278823Srjs #ifdef __FreeBSD__
245465278823Srjs static int
dccp_pcblist(SYSCTL_HANDLER_ARGS)245565278823Srjs dccp_pcblist(SYSCTL_HANDLER_ARGS)
245665278823Srjs {
245765278823Srjs 
245865278823Srjs 	int error, i, n, s;
245965278823Srjs 	struct inpcb *inp, **inp_list;
246065278823Srjs 	inp_gen_t gencnt;
246165278823Srjs 	struct xinpgen xig;
246265278823Srjs 
246365278823Srjs 	/*
246465278823Srjs 	 * The process of preparing the TCB list is too time-consuming and
246565278823Srjs 	 * resource-intensive to repeat twice on every request.
246665278823Srjs 	 */
246765278823Srjs 	if (req->oldptr == 0) {
246865278823Srjs 		n = dccpbinfo.ipi_count;
246965278823Srjs 		req->oldidx = 2 * (sizeof xig)
247065278823Srjs 			+ (n + n/8) * sizeof(struct xdccpcb);
247165278823Srjs 		return 0;
247265278823Srjs 	}
247365278823Srjs 
247465278823Srjs 
247565278823Srjs 	if (req->newptr != 0)
247665278823Srjs 		return EPERM;
247765278823Srjs 
247865278823Srjs 
247965278823Srjs 	/*
248065278823Srjs 	 * OK, now we're committed to doing something.
248165278823Srjs 	 */
248265278823Srjs 	s = splnet();
248365278823Srjs 	gencnt = dccpbinfo.ipi_gencnt;
248465278823Srjs 	n = dccpbinfo.ipi_count;
248565278823Srjs 	splx(s);
248665278823Srjs 
248765278823Srjs #if __FreeBSD_version >= 500000
248865278823Srjs 	sysctl_wire_old_buffer(req, 2 * (sizeof xig)
248965278823Srjs 		+ n * sizeof(struct xdccpcb));
249065278823Srjs #endif
249165278823Srjs 
249265278823Srjs 	xig.xig_len = sizeof xig;
249365278823Srjs 	xig.xig_count = n;
249465278823Srjs 	xig.xig_gen = gencnt;
249565278823Srjs 	xig.xig_sogen = so_gencnt;
249665278823Srjs 	error = SYSCTL_OUT(req, &xig, sizeof xig);
249765278823Srjs 	if (error)
249865278823Srjs 		return error;
249965278823Srjs 
250065278823Srjs 	inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK);
250165278823Srjs 	if (inp_list == 0)
250265278823Srjs 		return ENOMEM;
250365278823Srjs 
250465278823Srjs 	s = splsoftnet();
250565278823Srjs 	INP_INFO_RLOCK(&dccpbinfo);
250665278823Srjs 
250765278823Srjs 	for (inp = LIST_FIRST(dccpbinfo.listhead), i = 0; inp && i < n;
250865278823Srjs 	     inp = LIST_NEXT(inp, inp_list)) {
250965278823Srjs 		INP_LOCK(inp);
251065278823Srjs 		if (inp->inp_gencnt <= gencnt &&
251165278823Srjs #if __FreeBSD_version >= 500000
251265278823Srjs 		    cr_canseesocket(req->td->td_ucred, inp->inp_socket) == 0)
251365278823Srjs #else
251465278823Srjs 		    !prison_xinpcb(req->p, inp))
251565278823Srjs #endif
251665278823Srjs 			inp_list[i++] = inp;
251765278823Srjs 		INP_UNLOCK(inp);
251865278823Srjs 	}
251965278823Srjs 	INP_INFO_RUNLOCK(&dccpbinfo);
252065278823Srjs 	splx(s);
252165278823Srjs 	n = i;
252265278823Srjs 
252365278823Srjs 	error = 0;
252465278823Srjs 	for (i = 0; i < n; i++) {
252565278823Srjs 		inp = inp_list[i];
252665278823Srjs 		INP_LOCK(inp);
252765278823Srjs 
252865278823Srjs 		if (inp->inp_gencnt <= gencnt) {
252965278823Srjs 			struct xdccpcb xd;
253065278823Srjs 			vaddr_t inp_ppcb;
253165278823Srjs 			xd.xd_len = sizeof xd;
253265278823Srjs 			/* XXX should avoid extra copy */
2533a72ef8c3Srjs 			memcpy(&xd.xd_inp, inp, sizeof *inp);
253465278823Srjs 			inp_ppcb = inp->inp_ppcb;
253565278823Srjs 			if (inp_ppcb != NULL)
2536a72ef8c3Srjs 				memcpy(&xd.xd_dp, inp_ppcb, sizeof xd.xd_dp);
253765278823Srjs 			else
2538a72ef8c3Srjs 				memset((char *) &xd.xd_dp, 0, sizeof xd.xd_dp);
253965278823Srjs 			if (inp->inp_socket)
254065278823Srjs 				 sotoxsocket(inp->inp_socket, &xd.xd_socket);
254165278823Srjs 			error = SYSCTL_OUT(req, &xd, sizeof xd);
254265278823Srjs 		}
254365278823Srjs 		INP_UNLOCK(inp);
254465278823Srjs 	}
254565278823Srjs 	if (!error) {
254665278823Srjs 		/*
254765278823Srjs 		 * Give the user an updated idea of our state.
254865278823Srjs 		 * If the generation differs from what we told
254965278823Srjs 		 * her before, she knows that something happened
255065278823Srjs 		 * while we were processing this request, and it
255165278823Srjs 		 * might be necessary to retry.
255265278823Srjs 		 */
255365278823Srjs 		s = splnet();
255465278823Srjs 		INP_INFO_RLOCK(&dccpbinfo);
255565278823Srjs 		xig.xig_gen = dccpbinfo.ipi_gencnt;
255665278823Srjs 		xig.xig_sogen = so_gencnt;
255765278823Srjs 		xig.xig_count = dccpbinfo.ipi_count;
255865278823Srjs 
255965278823Srjs 
256065278823Srjs 		INP_INFO_RUNLOCK(&dccpbinfo);
256165278823Srjs 		splx(s);
256265278823Srjs 		error = SYSCTL_OUT(req, &xig, sizeof xig);
256365278823Srjs 	}
256465278823Srjs 	free(inp_list, M_TEMP);
256565278823Srjs 	return error;
256665278823Srjs }
256765278823Srjs #endif
256865278823Srjs 
256965278823Srjs #ifdef __FreeBSD__
257065278823Srjs SYSCTL_PROC(_net_inet_dccp, DCCPCTL_PCBLIST, pcblist, CTLFLAG_RD, 0, 0,
257165278823Srjs     dccp_pcblist, "S,xdccpcb", "List of active DCCP sockets");
257265278823Srjs #endif
257365278823Srjs 
257465278823Srjs void
dccp_timewait_t(void * dcb)257565278823Srjs dccp_timewait_t(void *dcb)
257665278823Srjs {
257765278823Srjs 	struct dccpcb *dp = dcb;
257865278823Srjs 
257965278823Srjs 	DCCP_DEBUG((LOG_INFO, "Entering dccp_timewait_t!\n"));
258065278823Srjs 	mutex_enter(softnet_lock);
258165278823Srjs 	INP_INFO_WLOCK(&dccpbinfo);
258265278823Srjs 	INP_LOCK(dp->d_inpcb);
258365278823Srjs 	dccp_close(dp);
258465278823Srjs 	INP_INFO_WUNLOCK(&dccpbinfo);
258565278823Srjs 	mutex_exit(softnet_lock);
258665278823Srjs }
258765278823Srjs 
258865278823Srjs void
dccp_connect_t(void * dcb)258965278823Srjs dccp_connect_t(void *dcb)
259065278823Srjs {
259165278823Srjs 	struct dccpcb *dp = dcb;
259265278823Srjs 
259365278823Srjs 	DCCP_DEBUG((LOG_INFO, "Entering dccp_connect_t!\n"));
259465278823Srjs 	mutex_enter(softnet_lock);
259565278823Srjs 	INP_INFO_WLOCK(&dccpbinfo);
259665278823Srjs 	INP_LOCK(dp->d_inpcb);
259765278823Srjs 	dccp_close(dp);
259865278823Srjs 	INP_INFO_WUNLOCK(&dccpbinfo);
259965278823Srjs 	mutex_exit(softnet_lock);
260065278823Srjs }
260165278823Srjs 
260265278823Srjs void
dccp_close_t(void * dcb)260365278823Srjs dccp_close_t(void *dcb)
260465278823Srjs {
260565278823Srjs 	struct dccpcb *dp = dcb;
260665278823Srjs 
260765278823Srjs 	DCCP_DEBUG((LOG_INFO, "Entering dccp_close_t!\n"));
260865278823Srjs 	mutex_enter(softnet_lock);
260965278823Srjs 	INP_INFO_WLOCK(&dccpbinfo);
261065278823Srjs 	dp->state = DCCPS_TIME_WAIT; /* HMM */
261165278823Srjs 	if (dp->who == DCCP_SERVER) {
261265278823Srjs 		INP_LOCK(dp->d_inpcb);
261365278823Srjs 		KERNEL_LOCK(1, NULL);
261465278823Srjs 		dccp_output(dp, DCCP_TYPE_RESET + 2);
261565278823Srjs 		KERNEL_UNLOCK_ONE(NULL);
261665278823Srjs 		dccp_close(dp);
261765278823Srjs 	} else {
261865278823Srjs 		INP_LOCK(dp->d_inpcb);
261965278823Srjs 		dccp_output(dp, DCCP_TYPE_RESET + 2);
262065278823Srjs 		/*dp->state = DCCPS_TIME_WAIT; */
262165278823Srjs 		callout_reset(&dp->timewait_timer, DCCP_TIMEWAIT_TIMER,
262265278823Srjs 		    dccp_timewait_t, dp);
262365278823Srjs 		INP_UNLOCK(dp->d_inpcb);
262465278823Srjs 	}
262565278823Srjs 	INP_INFO_WUNLOCK(&dccpbinfo);
262665278823Srjs 	mutex_exit(softnet_lock);
262765278823Srjs }
262865278823Srjs 
262965278823Srjs void
dccp_retrans_t(void * dcb)263065278823Srjs dccp_retrans_t(void *dcb)
263165278823Srjs {
263265278823Srjs 	struct dccpcb *dp = dcb;
263365278823Srjs 	/*struct inpcb *inp;*/
263465278823Srjs 
263565278823Srjs 	DCCP_DEBUG((LOG_INFO, "Entering dccp_retrans_t!\n"));
263665278823Srjs 	mutex_enter(softnet_lock);
263765278823Srjs 	INP_INFO_RLOCK(&dccpbinfo);
263865278823Srjs 	/*inp = dp->d_inpcb;*/
263965278823Srjs 	INP_LOCK(inp);
264065278823Srjs 	INP_INFO_RUNLOCK(&dccpbinfo);
264165278823Srjs 	callout_stop(&dp->retrans_timer);
264265278823Srjs 	KERNEL_LOCK(1, NULL);
264365278823Srjs 	dccp_output(dp, 0);
264465278823Srjs 	KERNEL_UNLOCK_ONE(NULL);
264565278823Srjs 	dp->retrans = dp->retrans * 2;
264665278823Srjs 	callout_reset(&dp->retrans_timer, dp->retrans, dccp_retrans_t, dp);
264765278823Srjs 	INP_UNLOCK(inp);
264865278823Srjs 	mutex_exit(softnet_lock);
264965278823Srjs }
265065278823Srjs 
265165278823Srjs static int
dccp_ioctl(struct socket * so,u_long cmd,void * nam,struct ifnet * ifp)265265278823Srjs dccp_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp)
265365278823Srjs {
265465278823Srjs 	int error = 0;
265565278823Srjs 	int family;
265665278823Srjs 
265765278823Srjs 	family = so->so_proto->pr_domain->dom_family;
265865278823Srjs 	switch (family) {
265965278823Srjs 	case PF_INET:
266065278823Srjs 		error = in_control(so, cmd, nam, ifp);
266165278823Srjs 		break;
266265278823Srjs #ifdef INET6
266365278823Srjs 	case PF_INET6:
266465278823Srjs 		error = in6_control(so, cmd, nam, ifp);
266565278823Srjs 		break;
266665278823Srjs #endif
266765278823Srjs 	default:
266865278823Srjs 		error =	 EAFNOSUPPORT;
266965278823Srjs 	}
267065278823Srjs 	return (error);
267165278823Srjs }
267265278823Srjs 
267365278823Srjs static int
dccp_stat(struct socket * so,struct stat * ub)267465278823Srjs dccp_stat(struct socket *so, struct stat *ub)
267565278823Srjs {
267665278823Srjs 	return 0;
267765278823Srjs }
267865278823Srjs 
267965278823Srjs static int
dccp_peeraddr(struct socket * so,struct sockaddr * nam)2680eddf3af3Srtr dccp_peeraddr(struct socket *so, struct sockaddr *nam)
268165278823Srjs {
2682eddf3af3Srtr 
268365278823Srjs 	KASSERT(solocked(so));
268465278823Srjs 	KASSERT(sotoinpcb(so) != NULL);
268565278823Srjs 	KASSERT(nam != NULL);
268665278823Srjs 
26872ba9f052Sozaki-r 	inpcb_fetch_peeraddr(sotoinpcb(so), (struct sockaddr_in *)nam);
268865278823Srjs 	return 0;
268965278823Srjs }
269065278823Srjs 
269165278823Srjs static int
dccp_sockaddr(struct socket * so,struct sockaddr * nam)2692eddf3af3Srtr dccp_sockaddr(struct socket *so, struct sockaddr *nam)
269365278823Srjs {
2694eddf3af3Srtr 
269565278823Srjs 	KASSERT(solocked(so));
269665278823Srjs 	KASSERT(sotoinpcb(so) != NULL);
269765278823Srjs 	KASSERT(nam != NULL);
269865278823Srjs 
26992ba9f052Sozaki-r 	inpcb_fetch_sockaddr(sotoinpcb(so), (struct sockaddr_in *)nam);
270065278823Srjs 	return 0;
270165278823Srjs }
270265278823Srjs 
270365278823Srjs static int
dccp_rcvd(struct socket * so,int flags,struct lwp * l)270465278823Srjs dccp_rcvd(struct socket *so, int flags, struct lwp *l)
270565278823Srjs {
270665278823Srjs 	KASSERT(solocked(so));
270765278823Srjs 
270865278823Srjs 	return EOPNOTSUPP;
270965278823Srjs }
271065278823Srjs 
271165278823Srjs static int
dccp_recvoob(struct socket * so,struct mbuf * m,int flags)271265278823Srjs dccp_recvoob(struct socket *so, struct mbuf *m, int flags)
271365278823Srjs {
271465278823Srjs 	KASSERT(solocked(so));
271565278823Srjs 
271665278823Srjs 	return EOPNOTSUPP;
271765278823Srjs }
271865278823Srjs 
271965278823Srjs static int
dccp_sendoob(struct socket * so,struct mbuf * m,struct mbuf * control)272065278823Srjs dccp_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control)
272165278823Srjs {
272265278823Srjs 	KASSERT(solocked(so));
272365278823Srjs 
272465278823Srjs 	m_freem(m);
272565278823Srjs 	m_freem(control);
272665278823Srjs 
272765278823Srjs 	return EOPNOTSUPP;
272865278823Srjs }
272965278823Srjs 
273065278823Srjs static int
dccp_purgeif(struct socket * so,struct ifnet * ifp)273165278823Srjs dccp_purgeif(struct socket *so, struct ifnet *ifp)
273265278823Srjs {
273365278823Srjs 	int s;
273465278823Srjs 
273565278823Srjs 	s = splsoftnet();
273665278823Srjs 	mutex_enter(softnet_lock);
27372ba9f052Sozaki-r 	inpcb_purgeif0(&dccpbtable, ifp);
273865278823Srjs 	in_purgeif(ifp);
27392ba9f052Sozaki-r 	inpcb_purgeif(&dccpbtable, ifp);
274065278823Srjs 	mutex_exit(softnet_lock);
274165278823Srjs 	splx(s);
274265278823Srjs 
274365278823Srjs 	return 0;
274465278823Srjs }
274565278823Srjs 
274665278823Srjs /****** Ack Vector functions *********/
274765278823Srjs 
274865278823Srjs /**
274965278823Srjs  * Initialize and allocate mem for Ack Vector
275065278823Srjs  **/
275165278823Srjs void
dccp_use_ackvector(struct dccpcb * dp)275265278823Srjs dccp_use_ackvector(struct dccpcb *dp)
275365278823Srjs {
275465278823Srjs 	DCCP_DEBUG((LOG_INFO,"Initializing AckVector\n"));
275565278823Srjs 	if (dp->ackvector != 0) {
275665278823Srjs 		DCCP_DEBUG((LOG_INFO, "It was already initialized!!!\n"));
275765278823Srjs 		return;
275865278823Srjs 	}
275965278823Srjs 	dp->av_size = DCCP_VECTORSIZE;
276065278823Srjs 	/* need 2 bits per entry */
276165278823Srjs 	dp->ackvector = malloc(dp->av_size/4, M_PCB, M_NOWAIT | M_ZERO);
276265278823Srjs 	if (dp->ackvector == 0) {
276365278823Srjs 		DCCP_DEBUG((LOG_INFO, "Unable to allocate memory for ackvector\n"));
276465278823Srjs 		/* What to do now? */
276565278823Srjs 		dp->av_size = 0;
276665278823Srjs 		return;
276765278823Srjs 	}
276865278823Srjs 	memset(dp->ackvector, 0xff, dp->av_size/4);
276965278823Srjs 	dp->av_hs = dp->av_ts = 0;
277065278823Srjs 	dp->av_hp = dp->ackvector;
277165278823Srjs }
277265278823Srjs 
277365278823Srjs /**
277465278823Srjs  * Set 'seqnr' as the new head in ackvector
277565278823Srjs  **/
277665278823Srjs void
dccp_update_ackvector(struct dccpcb * dp,u_int64_t seqnr)277765278823Srjs dccp_update_ackvector(struct dccpcb *dp, u_int64_t seqnr)
277865278823Srjs {
277965278823Srjs 	int64_t gap;
278065278823Srjs 	u_char *t;
278165278823Srjs 
278265278823Srjs 	/* Ignore wrapping for now */
278365278823Srjs 
278465278823Srjs 	ACK_DEBUG((LOG_INFO,"New head in ackvector: %u\n", seqnr));
278565278823Srjs 
278665278823Srjs 	if (dp->av_size == 0) {
278765278823Srjs 		ACK_DEBUG((LOG_INFO, "Update: AckVector NOT YET INITIALIZED!!!\n"));
278865278823Srjs 		dccp_use_ackvector(dp);
278965278823Srjs 	}
279065278823Srjs 
279165278823Srjs 	if (seqnr > dp->av_hs) {
279265278823Srjs 		gap = seqnr - dp->av_hs;
279365278823Srjs 	} else {
279465278823Srjs 		/* We received obsolete information */
279565278823Srjs 		return;
279665278823Srjs 	}
279765278823Srjs 
279865278823Srjs 	t = dp->av_hp + (gap/4);
279965278823Srjs 	if (t >= (dp->ackvector + (dp->av_size/4)))
280065278823Srjs 		t -= (dp->av_size / 4); /* ackvector wrapped */
280165278823Srjs 	dp->av_hp = t;
280265278823Srjs 	dp->av_hs = seqnr;
280365278823Srjs }
280465278823Srjs 
280565278823Srjs /**
280665278823Srjs  * We've received a packet. store in local av so it's included in
280765278823Srjs  * next Ack Vector sent
280865278823Srjs  **/
280965278823Srjs void
dccp_increment_ackvector(struct dccpcb * dp,u_int64_t seqnr)281065278823Srjs dccp_increment_ackvector(struct dccpcb *dp, u_int64_t seqnr)
281165278823Srjs {
281265278823Srjs 	u_int64_t offset, dc;
281365278823Srjs 	int64_t gap;
281465278823Srjs 	u_char *t, *n;
281565278823Srjs 
281665278823Srjs 	DCCP_DEBUG((LOG_INFO, "Entering dccp_increment_ackvecktor %d\n", dp->av_size));
281765278823Srjs 	if (dp->av_size == 0) {
281865278823Srjs 		DCCP_DEBUG((LOG_INFO, "Increment: AckVector NOT YET INITIALIZED!!!\n"));
281965278823Srjs 		dccp_use_ackvector(dp);
282065278823Srjs 	}
282165278823Srjs 
282265278823Srjs 	if (dp->av_hs == dp->av_ts) {
282365278823Srjs 		/* Empty ack vector */
282465278823Srjs 		dp->av_hs = dp->av_ts = seqnr;
282565278823Srjs 	}
282665278823Srjs 
282765278823Srjs 	/* Check for wrapping */
282865278823Srjs 	if (seqnr >= dp->av_hs) {
282965278823Srjs 		/* Not wrapped */
283065278823Srjs 		gap = seqnr - dp->av_hs;
283165278823Srjs 	} else {
283265278823Srjs 		/* Wrapped */
283365278823Srjs 		gap = seqnr + 0x1000000000000LL - dp->av_hs; /* seqnr = 48 bits */
283465278823Srjs 	}
283565278823Srjs 	DCCP_DEBUG((LOG_INFO, "dccp_increment_ackvecktor gap=%llu av_size %d\n", gap, dp->av_size));
283665278823Srjs 
283765278823Srjs 	if (gap >= dp->av_size) {
283865278823Srjs 		/* gap is bigger than ackvector size? baaad */
283965278823Srjs 		/* maybe we should increase the ackvector here */
284065278823Srjs 		DCCP_DEBUG((LOG_INFO, "increment_ackvector error. gap: %llu, av_size: %d, seqnr: %d\n",
284165278823Srjs 			    gap, dp->av_size, seqnr));
284265278823Srjs 		return;
284365278823Srjs 	}
284465278823Srjs 
284565278823Srjs 	offset = gap % 4; /* hi or low 2 bits to mark */
284665278823Srjs 	t = dp->av_hp + (gap/4);
284765278823Srjs 	if (t >= (dp->ackvector + (dp->av_size/4)))
284865278823Srjs 		t -= (dp->av_size / 4); /* ackvector wrapped */
284965278823Srjs 
285065278823Srjs 	*t = *t & (~(0x03 << (offset *2))); /* turn off bits, 00 is rcvd, 11 is missing */
285165278823Srjs 
285265278823Srjs 	dp->av_ts = seqnr + 1;
285365278823Srjs 	if (dp->av_ts == 0x1000000000000LL)
285465278823Srjs 		dp->av_ts = 0;
285565278823Srjs 
285665278823Srjs 	if (gap > (dp->av_size - 128)) {
285765278823Srjs 		n = malloc(dp->av_size/2, M_PCB, M_NOWAIT | M_ZERO); /* old size * 2 */
285865278823Srjs 		memset (n + dp->av_size / 4, 0xff, dp->av_size / 4); /* new half all missing */
285965278823Srjs 		dc = (dp->ackvector + (dp->av_size/4)) - dp->av_hp;
286065278823Srjs 		memcpy (n, dp->av_hp, dc); /* tail to end */
286165278823Srjs 		memcpy (n+dc, dp->ackvector, dp->av_hp - dp->ackvector); /* start to tail */
286265278823Srjs 		dp->av_size = dp->av_size * 2; /* counted in items, so it';s a doubling */
286365278823Srjs 		free (dp->ackvector, M_PCB);
286465278823Srjs 		dp->av_hp = dp->ackvector = n;
286565278823Srjs 	}
286665278823Srjs }
286765278823Srjs 
286865278823Srjs /**
286965278823Srjs  * Generates the ack vector to send in outgoing packet.
287065278823Srjs  * These are backwards (first packet in ack vector is packet indicated by Ack Number,
287165278823Srjs  * subsequent are older packets).
287265278823Srjs  **/
287365278823Srjs 
287465278823Srjs u_int16_t
dccp_generate_ackvector(struct dccpcb * dp,u_char * buf)287565278823Srjs dccp_generate_ackvector(struct dccpcb *dp, u_char *buf)
287665278823Srjs {
287765278823Srjs 	int64_t j;
287865278823Srjs 	u_int64_t i;
287965278823Srjs 	u_int16_t cnt, oldlen, bufsize;
288065278823Srjs 	u_char oldstate, st;
288165278823Srjs 
288265278823Srjs 	bufsize = 16;
288365278823Srjs 	cnt = 0;
288465278823Srjs 
288565278823Srjs 	oldstate = 0x04; /* bad value */
288665278823Srjs 	oldlen = 0;
288765278823Srjs 
288865278823Srjs 	if (dp->av_size == 0) {
288965278823Srjs 		ACK_DEBUG((LOG_INFO, "Generate: AckVector NOT YET INITIALIZED!!!\n"));
289065278823Srjs 		return 0;
289165278823Srjs 	}
289265278823Srjs 
289365278823Srjs 	if (dp->seq_rcv > dp->av_ts) {
289465278823Srjs 		/* AckNum is beyond our av-list , so we'll start with some
289565278823Srjs 		 * 0x3 (Packet not yet received) */
289665278823Srjs 		j = dp->seq_rcv - dp->av_ts -1;
289765278823Srjs 		do {
289865278823Srjs 			/* state | length */
289965278823Srjs 			oldstate = 0x03;
290065278823Srjs 			if (j > 63)
290165278823Srjs 				oldlen = 63;
290265278823Srjs 			else
290365278823Srjs 				oldlen = j;
290465278823Srjs 
290565278823Srjs 			buf[cnt] = (0x03 << 6) | oldlen;
290665278823Srjs 			cnt++;
290765278823Srjs 			if (cnt == bufsize) {
290865278823Srjs 				/* I've skipped the realloc bshit */
290965278823Srjs 				/* PANIC */
291065278823Srjs 			}
291165278823Srjs 			j-=63;
291265278823Srjs 		} while (j > 0);
291365278823Srjs 	}
291465278823Srjs 
291565278823Srjs 	/* Ok now we're at dp->av_ts (unless AckNum is lower) */
291665278823Srjs 	i = (dp->seq_rcv < dp->av_ts) ? dp->seq_rcv : dp->av_ts;
291765278823Srjs 	st = dccp_ackvector_state(dp, i);
291865278823Srjs 
291965278823Srjs 	if (st == oldstate) {
292065278823Srjs 		cnt--;
292165278823Srjs 		oldlen++;
292265278823Srjs 	} else {
292365278823Srjs 		oldlen = 0;
292465278823Srjs 		oldstate = st;
292565278823Srjs 	}
292665278823Srjs 
292765278823Srjs 	if (dp->av_ts > dp->av_hs) {
292865278823Srjs 		do {
292965278823Srjs 			i--;
293065278823Srjs 			st = dccp_ackvector_state(dp, i);
293165278823Srjs 			if (st == oldstate && oldlen < 64) {
293265278823Srjs 				oldlen++;
293365278823Srjs 			} else {
293465278823Srjs 				buf[cnt] = (oldstate << 6) | (oldlen & 0x3f);
293565278823Srjs 				cnt++;
293665278823Srjs 				oldlen = 0;
293765278823Srjs 				oldstate = st;
293865278823Srjs 				if (cnt == bufsize) {
293965278823Srjs 					/* PANIC */
294065278823Srjs 				}
294165278823Srjs 			}
294265278823Srjs 
294365278823Srjs 		} while (i > dp->av_hs);
294465278823Srjs 	} else {
294565278823Srjs 		/* It's wrapped */
294665278823Srjs 		do {
294765278823Srjs 			i--;
294865278823Srjs 			st = dccp_ackvector_state(dp, i);
294965278823Srjs 			if (st == oldstate && oldlen < 64) {
295065278823Srjs 				oldlen++;
295165278823Srjs 			} else {
295265278823Srjs 				buf[cnt] = (oldstate << 6) | (oldlen & 0x3f);
295365278823Srjs 				cnt++;
295465278823Srjs 				oldlen = 0;
295565278823Srjs 				oldstate = st;
295665278823Srjs 				if (cnt == bufsize) {
295765278823Srjs 					/* PANIC */
295865278823Srjs 				}
295965278823Srjs 			}
296065278823Srjs 
296165278823Srjs 		} while (i > 0);
296265278823Srjs 		i = 0x1000000;
296365278823Srjs 		do {
296465278823Srjs 			i--;
296565278823Srjs 			st = dccp_ackvector_state(dp, i);
296665278823Srjs 			if (st == oldstate && oldlen < 64) {
296765278823Srjs 				oldlen++;
296865278823Srjs 			} else {
296965278823Srjs 				buf[cnt] = (oldstate << 6) | (oldlen & 0x3f);
297065278823Srjs 				cnt++;
297165278823Srjs 				oldlen = 0;
297265278823Srjs 				oldstate = st;
297365278823Srjs 				if (cnt == bufsize) {
297465278823Srjs 					/* PANIC */
297565278823Srjs 				}
297665278823Srjs 			}
297765278823Srjs 		} while (i > dp->av_hs);
297865278823Srjs 	}
297965278823Srjs 
298065278823Srjs 	/* add the last one */
298165278823Srjs 	buf[cnt] = (oldstate << 6) | (oldlen & 0x3f);
298265278823Srjs 	cnt++;
298365278823Srjs 
298465278823Srjs 	return cnt;
298565278823Srjs }
298665278823Srjs 
298765278823Srjs u_char
dccp_ackvector_state(struct dccpcb * dp,u_int64_t seqnr)298865278823Srjs dccp_ackvector_state(struct dccpcb *dp, u_int64_t seqnr)
298965278823Srjs {
299065278823Srjs 	u_int64_t gap, offset;
299165278823Srjs 	u_char *t;
299265278823Srjs 
299365278823Srjs 	/* Check for wrapping */
299465278823Srjs 	if (seqnr >= dp->av_hs) {
299565278823Srjs 		/* Not wrapped */
299665278823Srjs 		gap = seqnr - dp->av_hs;
299765278823Srjs 	} else {
299865278823Srjs 		/* Wrapped */
299965278823Srjs 		gap = seqnr + 0x1000000000000LL - dp->av_hs; /* seq nr = 48 bits */
300065278823Srjs 	}
300165278823Srjs 
300265278823Srjs 	if (gap >= dp->av_size) {
300365278823Srjs 		/* gap is bigger than ackvector size? baaad */
300465278823Srjs 		return 0x03;
300565278823Srjs 	}
300665278823Srjs 
300765278823Srjs 	offset = gap % 4 *2;
300865278823Srjs 	t = dp->av_hp + (gap/4);
300965278823Srjs 	if (t >= (dp->ackvector + (dp->av_size/4)))
301065278823Srjs 		t -= (dp->av_size / 4); /* wrapped */
301165278823Srjs 
301265278823Srjs 	return ((*t & (0x03 << offset)) >> offset);
301365278823Srjs }
301465278823Srjs 
301565278823Srjs /****** End of Ack Vector functions *********/
301665278823Srjs 
301765278823Srjs /* No cc functions */
301865278823Srjs void *
dccp_nocc_init(struct dccpcb * pcb)301965278823Srjs dccp_nocc_init(struct dccpcb *pcb)
302065278823Srjs {
302165278823Srjs   return (void*) 1;
302265278823Srjs }
302365278823Srjs 
302465278823Srjs void
dccp_nocc_free(void * ccb)302565278823Srjs dccp_nocc_free(void *ccb)
302665278823Srjs {
302765278823Srjs }
302865278823Srjs 
302965278823Srjs int
dccp_nocc_send_packet(void * ccb,long size)303065278823Srjs dccp_nocc_send_packet(void *ccb, long size)
303165278823Srjs {
303265278823Srjs   return 1;
303365278823Srjs }
303465278823Srjs 
303565278823Srjs void
dccp_nocc_send_packet_sent(void * ccb,int moreToSend,long size)303665278823Srjs dccp_nocc_send_packet_sent(void *ccb, int moreToSend, long size)
303765278823Srjs {
303865278823Srjs }
303965278823Srjs 
304065278823Srjs void
dccp_nocc_packet_recv(void * ccb,char * options,int optlen)304165278823Srjs dccp_nocc_packet_recv(void *ccb, char* options ,int optlen)
304265278823Srjs {
304365278823Srjs }
304465278823Srjs 
304565278823Srjs void
dccp_log(int level,const char * format,...)304665278823Srjs dccp_log(int level, const char *format, ...)
304765278823Srjs {
304865278823Srjs 	va_list ap;
304965278823Srjs 
305065278823Srjs 	va_start(ap, format);
305165278823Srjs 	vprintf(format,  ap);
305265278823Srjs 	va_end(ap);
305365278823Srjs 	return;
305465278823Srjs }
305565278823Srjs 
305665278823Srjs /*
305765278823Srjs  * Sysctl for dccp variables.
305865278823Srjs  */
305965278823Srjs SYSCTL_SETUP(sysctl_net_inet_dccp_setup, "sysctl net.inet.dccp subtree setup")
306065278823Srjs {
306165278823Srjs 
306265278823Srjs 	sysctl_createv(clog, 0, NULL, NULL,
306365278823Srjs 		CTLFLAG_PERMANENT,
306465278823Srjs 		CTLTYPE_NODE, "net", NULL,
306565278823Srjs 		NULL, 0, NULL, 0,
306665278823Srjs 		CTL_NET, CTL_EOL);
306765278823Srjs 
306865278823Srjs 	sysctl_createv(clog, 0, NULL, NULL,
306965278823Srjs 		CTLFLAG_PERMANENT,
307065278823Srjs 		CTLTYPE_NODE, "inet", NULL,
307165278823Srjs 		NULL, 0, NULL, 0,
307265278823Srjs 		CTL_NET, PF_INET, CTL_EOL);
307365278823Srjs 
307465278823Srjs 	sysctl_createv(clog, 0, NULL, NULL,
307565278823Srjs 		CTLFLAG_PERMANENT,
307665278823Srjs 		CTLTYPE_NODE, "dccp",
307765278823Srjs 		SYSCTL_DESCR("DCCPv4 related settings"),
307865278823Srjs 		NULL, 0, NULL, 0,
307965278823Srjs 		CTL_NET, PF_INET, IPPROTO_DCCP, CTL_EOL);
308065278823Srjs 
308165278823Srjs 	sysctl_createv(clog, 0, NULL, NULL,
308265278823Srjs 		CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
308365278823Srjs 		CTLTYPE_INT, "dccp_log_in_vain",
308465278823Srjs 		SYSCTL_DESCR("log all connection attempt"),
308565278823Srjs 		NULL, 0, &dccp_log_in_vain, 0,
308665278823Srjs 		CTL_NET, PF_INET, IPPROTO_DCCP, DCCPCTL_LOGINVAIN,
308765278823Srjs 		CTL_EOL);
308865278823Srjs 
308965278823Srjs 	sysctl_createv(clog, 0, NULL, NULL,
309065278823Srjs 		CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
309165278823Srjs 		CTLTYPE_INT, "do_feature_nego",
309265278823Srjs 		SYSCTL_DESCR("enable feature negotiation"),
309365278823Srjs 		NULL, 0, &dccp_do_feature_nego, 0,
309465278823Srjs 		CTL_NET, PF_INET, IPPROTO_DCCP, DCCPCTL_DOFEATURENEGO,
309565278823Srjs 		CTL_EOL);
309665278823Srjs }
309765278823Srjs 
309865278823Srjs PR_WRAP_USRREQS(dccp)
309965278823Srjs #define	dccp_attach	dccp_attach_wrapper
310065278823Srjs #define	dccp_detach	dccp_detach_wrapper
310165278823Srjs #define dccp_accept	dccp_accept_wrapper
310265278823Srjs #define	dccp_bind	dccp_bind_wrapper
310365278823Srjs #define	dccp_listen	dccp_listen_wrapper
310465278823Srjs #define	dccp_connect	dccp_connect_wrapper
310565278823Srjs #define	dccp_connect2	dccp_connect2_wrapper
310665278823Srjs #define	dccp_disconnect	dccp_disconnect_wrapper
310765278823Srjs #define	dccp_shutdown	dccp_shutdown_wrapper
310865278823Srjs #define	dccp_abort	dccp_abort_wrapper
310965278823Srjs #define	dccp_ioctl	dccp_ioctl_wrapper
311065278823Srjs #define	dccp_stat	dccp_stat_wrapper
311165278823Srjs #define	dccp_peeraddr	dccp_peeraddr_wrapper
311265278823Srjs #define	dccp_sockaddr	dccp_sockaddr_wrapper
311365278823Srjs #define	dccp_rcvd	dccp_rcvd_wrapper
311465278823Srjs #define	dccp_recvoob	dccp_recvoob_wrapper
311565278823Srjs #define	dccp_send	dccp_send_wrapper
311665278823Srjs #define	dccp_sendoob	dccp_sendoob_wrapper
311765278823Srjs #define	dccp_purgeif	dccp_purgeif_wrapper
311865278823Srjs 
311965278823Srjs const struct pr_usrreqs dccp_usrreqs = {
312065278823Srjs 	.pr_attach	= dccp_attach,
312165278823Srjs 	.pr_detach	= dccp_detach,
312265278823Srjs 	.pr_accept	= dccp_accept,
312365278823Srjs 	.pr_bind	= dccp_bind,
312465278823Srjs 	.pr_listen	= dccp_listen,
312565278823Srjs 	.pr_connect	= dccp_connect,
312665278823Srjs 	.pr_connect2	= dccp_connect2,
312765278823Srjs 	.pr_disconnect	= dccp_disconnect,
312865278823Srjs 	.pr_shutdown	= dccp_shutdown,
312965278823Srjs 	.pr_abort	= dccp_abort,
313065278823Srjs 	.pr_ioctl	= dccp_ioctl,
313165278823Srjs 	.pr_stat	= dccp_stat,
313265278823Srjs 	.pr_peeraddr	= dccp_peeraddr,
313365278823Srjs 	.pr_sockaddr	= dccp_sockaddr,
313465278823Srjs 	.pr_rcvd	= dccp_rcvd,
313565278823Srjs 	.pr_recvoob	= dccp_recvoob,
313665278823Srjs 	.pr_send	= dccp_send,
313765278823Srjs 	.pr_sendoob	= dccp_sendoob,
313865278823Srjs 	.pr_purgeif	= dccp_purgeif,
313965278823Srjs };
3140