xref: /netbsd-src/sys/netinet/dccp_usrreq.c (revision 2e2322c9c07009df921d11b1268f8506affbb8ba)
1 /*	$KAME: dccp_usrreq.c,v 1.67 2005/11/03 16:05:04 nishida Exp $	*/
2 /*	$NetBSD: dccp_usrreq.c,v 1.10 2016/12/13 08:29:03 ozaki-r Exp $ */
3 
4 /*
5  * Copyright (c) 2003 Joacim H�ggmark, Magnus Erixzon, Nils-Erik Mattsson
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. The name of the author may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  * Id: dccp_usrreq.c,v 1.47 2003/07/31 11:23:08 joahag-9 Exp
32  */
33 
34 /*
35  * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
36  *	The Regents of the University of California.  All rights reserved.
37  *
38  * Redistribution and use in source and binary forms, with or without
39  * modification, are permitted provided that the following conditions
40  * are met:
41  * 1. Redistributions of source code must retain the above copyright
42  *    notice, this list of conditions and the following disclaimer.
43  * 2. Redistributions in binary form must reproduce the above copyright
44  *    notice, this list of conditions and the following disclaimer in the
45  *    documentation and/or other materials provided with the distribution.
46  * 3. All advertising materials mentioning features or use of this software
47  *    must display the following acknowledgement:
48  *	This product includes software developed by the University of
49  *	California, Berkeley and its contributors.
50  * 4. Neither the name of the University nor the names of its contributors
51  *    may be used to endorse or promote products derived from this software
52  *    without specific prior written permission.
53  *
54  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
55  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
58  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64  * SUCH DAMAGE.
65  *
66  *	@(#)udp_usrreq.c	8.6 (Berkeley) 5/23/95
67  */
68 
69 #include <sys/cdefs.h>
70 __KERNEL_RCSID(0, "$NetBSD: dccp_usrreq.c,v 1.10 2016/12/13 08:29:03 ozaki-r Exp $");
71 
72 #ifdef _KERNEL_OPT
73 #include "opt_inet.h"
74 #include "opt_dccp.h"
75 #endif
76 
77 #include <sys/param.h>
78 #include <sys/systm.h>
79 #include <sys/domain.h>
80 #include <sys/kernel.h>
81 #include <sys/pool.h>
82 #include <sys/lock.h>
83 #include <sys/malloc.h>
84 #include <sys/mbuf.h>
85 #include <sys/proc.h>
86 #include <sys/protosw.h>
87 #include <sys/signalvar.h>
88 #include <sys/socket.h>
89 #include <sys/socketvar.h>
90 #include <sys/mutex.h>
91 #include <sys/sysctl.h>
92 #include <sys/syslog.h>
93 #include <sys/queue.h>
94 
95 #include <net/if.h>
96 
97 #include <netinet/in.h>
98 #include <netinet/in_systm.h>
99 #include <netinet/ip.h>
100 #include <netinet/in_pcb.h>
101 #include <netinet/in_var.h>
102 #ifdef INET6
103 #include <netinet/ip6.h>
104 #endif
105 #include <netinet/ip_icmp.h>
106 #include <netinet/icmp_var.h>
107 #include <netinet/ip_var.h>
108 #ifdef INET6
109 #include <netinet6/in6_pcb.h>
110 #include <netinet6/ip6_var.h>
111 #include <netinet6/dccp6_var.h>
112 #endif
113 #include <netinet/dccp.h>
114 #include <netinet/dccp_var.h>
115 #include <netinet/dccp_cc_sw.h>
116 
117 #define DEFAULT_CCID 2
118 
119 #define INP_INFO_LOCK_INIT(x,y)
120 #define INP_INFO_WLOCK(x)
121 #define INP_INFO_WUNLOCK(x)
122 #define INP_INFO_RLOCK(x)
123 #define INP_INFO_RUNLOCK(x)
124 #define INP_LOCK(x)
125 #define IN6P_LOCK(x)
126 #define INP_UNLOCK(x)
127 #define IN6P_UNLOCK(x)
128 
129 /* Congestion control switch table */
130 extern struct dccp_cc_sw cc_sw[];
131 
132 int	dccp_log_in_vain = 1;
133 int	dccp_do_feature_nego = 1;
134 
135 struct	inpcbhead dccpb;		/* from dccp_var.h */
136 #ifdef __FreeBSD__
137 struct	inpcbinfo dccpbinfo;
138 #else
139 struct	inpcbtable dccpbtable;
140 #endif
141 
142 #ifndef DCCPBHASHSIZE
143 #define DCCPBHASHSIZE 16
144 #endif
145 
146 struct	pool dccpcb_pool;
147 
148 u_long	dccp_sendspace = 32768;
149 u_long	dccp_recvspace = 65536;
150 
151 struct	dccpstat dccpstat;	/* from dccp_var.h */
152 
153 static struct dccpcb * dccp_close(struct dccpcb *);
154 static int dccp_disconnect2(struct dccpcb *);
155 int dccp_get_option(char *, int, int, char *,int);
156 void dccp_parse_options(struct dccpcb *, char *, int);
157 int dccp_remove_feature(struct dccpcb *, u_int8_t, u_int8_t);
158 int dccp_add_feature_option(struct dccpcb *, u_int8_t, u_int8_t, char *, u_int8_t);
159 void dccp_feature_neg(struct dccpcb *, u_int8_t, u_int8_t, u_int8_t, char *);
160 void dccp_close_t(void *);
161 void dccp_timewait_t(void *);
162 
163 /* Ack Vector functions */
164 #define DCCP_VECTORSIZE 512 /* initial ack and cwnd-vector size. Multiple of 8 ! */
165 void dccp_use_ackvector(struct dccpcb *);
166 void dccp_update_ackvector(struct dccpcb *, u_int64_t);
167 void dccp_increment_ackvector(struct dccpcb *, u_int64_t);
168 u_int16_t dccp_generate_ackvector(struct dccpcb *, u_char *);
169 u_char dccp_ackvector_state(struct dccpcb *, u_int64_t);
170 
171 /*
172  * DCCP initialization
173  */
174 void
175 dccp_init(void)
176 {
177 	pool_init(&dccpcb_pool, sizeof(struct dccpcb), 0, 0, 0, "dccpcbpl",
178 		  NULL, IPL_SOFTNET);
179 
180 	in_pcbinit(&dccpbtable, DCCPBHASHSIZE, DCCPBHASHSIZE);
181 }
182 
183 void
184 dccp_input(struct mbuf *m, ...)
185 {
186 	int iphlen;
187 	struct ip *ip = NULL;
188 	struct dccphdr *dh;
189 	struct dccplhdr *dlh;
190 	struct inpcb *inp = NULL, *oinp = NULL;
191 	struct in6pcb *in6p = NULL, *oin6p = NULL;
192 	struct dccpcb *dp;
193 	struct ipovly *ipov = NULL;
194 	struct dccp_requesthdr *drqh;
195 	struct dccp_ackhdr *dah = NULL;
196 	struct dccp_acklhdr *dalh = NULL;
197 	struct dccp_resethdr *drth;
198 	struct socket *so;
199 	u_char *optp = NULL;
200 	struct mbuf *opts = 0;
201 	int len, data_off, extrah_len, optlen;
202 	/*struct ip save_ip;*/
203 	char options[DCCP_MAX_OPTIONS];
204 	char test[2];
205 	u_int32_t cslen;
206 	dccp_seq seqnr, low_seqnr, high_seqnr;
207 	int isipv6 = 0;
208 	int is_shortseq; /* Is this shortseq packet? */
209 #ifdef INET6
210 	struct ip6_hdr *ip6 = NULL;
211 #endif
212 
213 	int off;
214 	va_list ap;
215 
216 	va_start(ap, m);
217 	iphlen = off = va_arg(ap, int);
218 	va_end(ap);
219 
220 	DCCP_DEBUG((LOG_INFO, "Got DCCP packet!\n"));
221 
222 	dccpstat.dccps_ipackets++;
223 	dccpstat.dccps_ibytes += m->m_pkthdr.len;
224 
225 #ifdef INET6
226 	isipv6 = (mtod(m, struct ip *)->ip_v == 6) ? 1 : 0;
227 #endif
228 
229 #ifdef INET6
230 	if (isipv6) {
231 		DCCP_DEBUG((LOG_INFO, "Got DCCP ipv6 packet, iphlen = %u!\n", iphlen));
232 		ip6 = mtod(m, struct ip6_hdr *);
233 		IP6_EXTHDR_GET(dh, struct dccphdr *, m, iphlen, sizeof(*dh));
234 		if (dh == NULL) {
235 			dccpstat.dccps_badlen++;
236 			return;
237 		}
238 	} else
239 #endif
240 	{
241 		/*
242 		 * Strip IP options, if any; should skip this,
243 		 * make available to user, and use on returned packets,
244 		 * but we don't yet have a way to check the checksum
245 		 * with options still present.
246 		 */
247 		if (iphlen > sizeof (struct ip)) {
248 			DCCP_DEBUG((LOG_INFO, "Need to strip options\n"));
249 #if 0				/* XXX */
250 			ip_stripoptions(m, (struct mbuf *)0);
251 #endif
252 			iphlen = sizeof(struct ip);
253 		}
254 
255 		/*
256 		 * Get IP and DCCP header together in first mbuf.
257 		 */
258 		ip = mtod(m, struct ip *);
259 		IP6_EXTHDR_GET(dh, struct dccphdr *, m, iphlen, sizeof(*dh));
260 		if (dh == NULL) {
261 			dccpstat.dccps_badlen++;
262 			return;
263 		}
264 	}
265 	dlh = (struct dccplhdr*)dh;
266 	is_shortseq = !dh->dh_x;
267 
268 	if (!is_shortseq) {
269 		DCCP_DEBUG((LOG_INFO,
270 		"Header info: cslen = %u, off = %u, type = %u, reserved = %u, seq = %u.%lu\n",
271 			 dlh->dh_cscov, dlh->dh_off, dlh->dh_type, dlh->dh_res, ntohs(dlh->dh_seq),
272 			 (unsigned long)ntohl(dlh->dh_seq2)));
273 	} else {
274 		DCCP_DEBUG((LOG_INFO,
275 		"Header info(short): cslen = %u, off = %u, type = %u, reserved = %u, seq = %u\n",
276 			dh->dh_cscov, dh->dh_off, dh->dh_type, dh->dh_res, ntohl(dh->dh_seq)));
277 	}
278 
279 	/*
280 	 * Make mbuf data length reflect DCCP length.
281 	 * If not enough data to reflect DCCP length, drop.
282 	 */
283 
284 #ifdef INET6
285 	if (isipv6)
286 		len = m->m_pkthdr.len - off;
287 	else
288 #endif
289 	{
290 		len = ntohs(ip->ip_len);
291 		len -= ip->ip_hl << 2;
292 	}
293 
294 	if (len < sizeof(struct dccphdr)) {
295 		DCCP_DEBUG((LOG_INFO, "Dropping DCCP packet!\n"));
296 		dccpstat.dccps_badlen++;
297 		goto badunlocked;
298 	}
299 	/*
300 	 * Save a copy of the IP header in case we want restore it
301 	 * for sending a DCCP reset packet in response.
302 	 */
303 	if (!isipv6) {
304 		/*save_ip = *ip;*/
305 		ipov = (struct ipovly *)ip;
306 	}
307 
308 	if (dh->dh_cscov == 0) {
309 		cslen = len;
310 	} else {
311 		cslen = dh->dh_off * 4 + (dh->dh_cscov - 1) * 4;
312 		if (cslen > len)
313 			cslen = len;
314 	}
315 
316 	/*
317 	 * Checksum extended DCCP header and data.
318 	 */
319 
320 #ifdef INET6
321 	if (isipv6) {
322 		if (in6_cksum(m, IPPROTO_DCCP, off, cslen) != 0) {
323 			dccpstat.dccps_badsum++;
324 			goto badunlocked;
325 		}
326 	} else
327 #endif
328 	{
329 		bzero(ipov->ih_x1, sizeof(ipov->ih_x1));
330 		ip->ip_len = htons(m->m_pkthdr.len);
331 		dh->dh_sum = in4_cksum(m, IPPROTO_DCCP, off, cslen);
332 
333 		if (dh->dh_sum) {
334 			dccpstat.dccps_badsum++;
335 			goto badunlocked;
336 		}
337 	}
338 
339 	INP_INFO_WLOCK(&dccpbinfo);
340 
341 	/*
342 	 * Locate pcb for datagram.
343 	 */
344 #ifdef INET6
345 	if (isipv6) {
346 		in6p = in6_pcblookup_connect(&dccpbtable, &ip6->ip6_src,
347 		    dh->dh_sport, &ip6->ip6_dst, dh->dh_dport, 0, 0);
348 		if (in6p == 0) {
349 			/* XXX stats increment? */
350 			in6p = in6_pcblookup_bind(&dccpbtable, &ip6->ip6_dst,
351 			    dh->dh_dport, 0);
352 		}
353 	} else
354 #endif
355 	{
356 		inp = in_pcblookup_connect(&dccpbtable, ip->ip_src,
357 		    dh->dh_sport, ip->ip_dst, dh->dh_dport, 0);
358 		if (inp == NULL) {
359 			/* XXX stats increment? */
360 			inp = in_pcblookup_bind(&dccpbtable, ip->ip_dst,
361 			    dh->dh_dport);
362 		}
363 	}
364 	if (isipv6) {
365 		DCCP_DEBUG((LOG_INFO, "in6p=%p\n", in6p));
366 	} else {
367 		DCCP_DEBUG((LOG_INFO, "inp=%p\n", inp));
368 	}
369 
370 	if (isipv6 ? in6p == NULL : inp == NULL) {
371 		if (dccp_log_in_vain) {
372 #ifdef INET6
373 			char dbuf[INET6_ADDRSTRLEN+2], sbuf[INET6_ADDRSTRLEN+2];
374 #else
375 			char dbuf[4*sizeof "123"], sbuf[4*sizeof "123"];
376 #endif
377 
378 #ifdef INET6
379 			if (isipv6) {
380 				strlcpy(dbuf, "[", sizeof dbuf);
381 				strlcat(dbuf, ip6_sprintf(&ip6->ip6_dst), sizeof dbuf);
382 				strlcat(dbuf, "]", sizeof dbuf);
383 				strlcpy(sbuf, "[", sizeof sbuf);
384 				strlcat(sbuf, ip6_sprintf(&ip6->ip6_src), sizeof sbuf);
385 				strlcat(sbuf, "]", sizeof sbuf);
386 			} else
387 #endif
388 			{
389 				strlcpy(dbuf, inet_ntoa(ip->ip_dst), sizeof dbuf);
390 				strlcpy(sbuf, inet_ntoa(ip->ip_src), sizeof sbuf);
391 			}
392 			log(LOG_INFO,
393 			    "Connection attempt to DCCP %s:%d from %s:%d\n",
394 			    dbuf, ntohs(dh->dh_dport), sbuf,
395 			    ntohs(dh->dh_sport));
396 		}
397 		dccpstat.dccps_noport++;
398 
399 		/*
400 		 * We should send DCCP reset here but we can't call dccp_output
401 		 * since we have no dccpcb. A icmp unreachable works great but
402 		 * the specs says DCCP reset :(
403 		 *
404 		 * if (!isipv6) {
405 		 *	*ip = save_ip;
406 		 *	ip->ip_len += iphlen;
407 		 *	icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
408 		 * }
409 		 */
410 
411 		INP_INFO_WUNLOCK(&dccpbinfo);
412 		goto badunlocked;
413 	}
414 	INP_LOCK(inp);
415 
416 #ifdef INET6
417 	if (isipv6)
418 		dp = in6todccpcb(in6p);
419 	else
420 #endif
421 		dp = intodccpcb(inp);
422 
423 	if (dp == 0) {
424 		INP_UNLOCK(inp);
425 		INP_INFO_WUNLOCK(&dccpbinfo);
426 		goto badunlocked;
427 	}
428 
429 	if (dp->state == DCCPS_CLOSED) {
430 		DCCP_DEBUG((LOG_INFO, "We are in closed state, dropping packet and sending reset!\n"));
431 		if (dh->dh_type != DCCP_TYPE_RESET)
432 			dccp_output(dp, DCCP_TYPE_RESET + 2);
433 		INP_UNLOCK(inp);
434 		INP_INFO_WUNLOCK(&dccpbinfo);
435 		goto badunlocked;
436 	}
437 
438 #if defined(INET6)
439 	if (isipv6)
440 		so = in6p->in6p_socket;
441 	else
442 #endif
443 		so = inp->inp_socket;
444 
445 	if (so->so_options & SO_ACCEPTCONN) {
446 		DCCP_DEBUG((LOG_INFO, "so->options & SO_ACCEPTCONN! dp->state = %i\n", dp->state));
447 		so = sonewconn(so, SS_ISCONNECTED);
448 		if (so == 0) {
449 			DCCP_DEBUG((LOG_INFO, "Error, sonewconn failed!\n"));
450 			INP_UNLOCK(inp);
451 			INP_INFO_WUNLOCK(&dccpbinfo);
452 			goto badunlocked;
453 		}
454 
455 		/* INP_LOCK(inp); XXX */
456 
457 #if defined(INET6)
458 		if (isipv6)
459 			oin6p = in6p;
460 		else
461 #endif
462 			oinp = inp;
463 
464 #ifdef INET6
465 		if (isipv6) {
466 			in6p = sotoin6pcb(so);
467 			in6p->in6p_laddr = ip6->ip6_dst;
468 			in6p->in6p_faddr = ip6->ip6_src;
469 			in6p->in6p_lport = dh->dh_dport;
470 			in6p->in6p_fport = dh->dh_sport;
471 			in6_pcbstate(in6p, IN6P_CONNECTED);
472 		} else
473 #endif
474 		{
475 			inp = sotoinpcb(so);
476 			inp->inp_laddr = ip->ip_dst;
477 			inp->inp_faddr = ip->ip_src;
478 			inp->inp_lport = dh->dh_dport;
479 			inp->inp_fport = dh->dh_sport;
480 		}
481 
482 		if (!isipv6)
483 			in_pcbstate(inp, INP_BOUND);
484 
485 #if defined(INET6)
486 		if (isipv6)
487 			dp = (struct dccpcb *)in6p->in6p_ppcb;
488 		else
489 #endif
490 			dp = (struct dccpcb *)inp->inp_ppcb;
491 
492 		dp->state = DCCPS_LISTEN;
493 		dp->who = DCCP_SERVER;
494 #if defined(INET6)
495 		if (isipv6) {
496 			dp->cslen = ((struct dccpcb *)oin6p->in6p_ppcb)->cslen;
497 			dp->avgpsize = ((struct dccpcb *)oin6p->in6p_ppcb)->avgpsize;
498 			dp->scode = ((struct dccpcb *)oin6p->in6p_ppcb)->scode;
499 		} else
500 #endif
501 		{
502 			dp->cslen = ((struct dccpcb *)oinp->inp_ppcb)->cslen;
503 			dp->avgpsize = ((struct dccpcb *)oinp->inp_ppcb)->avgpsize;
504 			dp->scode = ((struct dccpcb *)oinp->inp_ppcb)->scode;
505 		}
506 		dp->seq_snd = (((u_int64_t)random() << 32) | random()) % 281474976710656LL;
507 		dp->ref_seq.hi = dp->seq_snd >> 24;
508 		dp->ref_seq.lo = (u_int64_t)(dp->seq_snd & 0xffffff);
509 		INP_UNLOCK(oinp);
510 		DCCP_DEBUG((LOG_INFO, "New dp = %u, dp->state = %u!\n", (int)dp, dp->state));
511 	}
512 
513 	INP_INFO_WUNLOCK(&dccpbinfo);
514 
515 	/*
516 	 * Check if sequence number is inside the loss window
517 	 */
518 	if (!is_shortseq) {
519 		DHDR_TO_DSEQ(seqnr, dlh);
520 	} else {
521 		/* shortseq */
522 		seqnr = CONVERT_TO_LONGSEQ((ntohl(dh->dh_seq) >> 8), dp->ref_pseq);
523 		DCCP_DEBUG((LOG_INFO, "short seq conversion %x,  %u %u\n",
524 			ntohl(dh->dh_seq) >> 8, dp->ref_pseq.hi, dp->ref_pseq.lo));
525 	}
526 
527 	DCCP_DEBUG((LOG_INFO, "Received DCCP packet with sequence number = %llu , gsn_rcv %llu\n", seqnr, dp->gsn_rcv));
528 
529 	/* store ccval */
530 	dp->ccval = dh->dh_ccval;
531 
532 	if (dp->gsn_rcv == 281474976710656LL) dp->gsn_rcv = seqnr;
533 	if (dp->gsn_rcv > (dp->loss_window / 4))
534 		low_seqnr = (dp->gsn_rcv - (dp->loss_window / 4)) % 281474976710656LL;
535 	else
536 		low_seqnr = 0ll;
537 	high_seqnr = (dp->gsn_rcv + (dp->loss_window / 4 * 3)) % 281474976710656LL;
538 
539 	if (! (DCCP_SEQ_GT(seqnr, low_seqnr) && DCCP_SEQ_LT(seqnr, high_seqnr))) {
540 		dccpstat.dccps_badseq++;
541 		DCCP_DEBUG((LOG_INFO, "Recieved DCCP packet with bad sequence number = %llu (low_seqnr = %llu, high_seqnr = %llu)\n", seqnr, low_seqnr, high_seqnr));
542 		INP_UNLOCK(inp);
543 		goto badunlocked;
544 	}
545 
546 	/* dp->gsn_rcv should always be the highest received valid sequence number */
547 	if (DCCP_SEQ_GT(seqnr, dp->gsn_rcv))
548 		dp->gsn_rcv = seqnr;
549 
550 	/* Just ignore DCCP-Move for now */
551 	if (dlh->dh_type == DCCP_TYPE_DATA) {
552 		extrah_len = 0;
553 		if (!is_shortseq)
554 			optp = (u_char *)(dlh + 1);
555 		else
556 			optp = (u_char *)(dh + 1);
557 	} else if (dh->dh_type == DCCP_TYPE_REQUEST) {
558 		drqh = (struct dccp_requesthdr *)(dlh + 1);
559 		if (drqh->drqh_scode != dp->scode){
560 			DCCP_DEBUG((LOG_INFO, "service code in request packet doesn't match! %x %x\n", drqh->drqh_scode, dp->scode));
561 			INP_UNLOCK(inp);
562 			dp->state = DCCPS_SERVER_CLOSE; /* So disconnect2 doesn't send CLOSEREQ */
563 			dccp_disconnect2(dp);
564 			dccp_output(dp, DCCP_TYPE_RESET + 2);
565 			dccp_close(dp);
566 			goto badunlocked;
567 		}
568 		optp = (u_char *)(drqh + 1);
569 		extrah_len = 4;
570 
571 		/* store reference peer sequence number */
572 		dp->ref_pseq.hi = seqnr >> 24;
573 		dp->ref_pseq.lo = (u_int64_t)(seqnr & 0xffffff);
574 
575 	} else if (dh->dh_type == DCCP_TYPE_RESET) {
576 		extrah_len = 8 ;
577 		drth = (struct dccp_resethdr *)(dlh + 1);
578 		optp = (u_char *)(drth + 1);
579 	} else {
580 		if (!is_shortseq){
581 			extrah_len = 8;
582 			dalh = (struct dccp_acklhdr *)(dlh + 1);
583 			if (dh->dh_type == DCCP_TYPE_RESPONSE) {
584 				extrah_len += 4;
585 				drqh = (struct dccp_requesthdr *)(dalh + 1);
586 				if (drqh->drqh_scode != dp->scode){
587 					DCCP_DEBUG((LOG_INFO, "service code in response packet doesn't match! %x %x\n", drqh->drqh_scode, dp->scode));
588 					INP_UNLOCK(inp);
589 					dp->state = DCCPS_CLIENT_CLOSE; /* So disconnect2 doesn't send CLOSEREQ */
590 					dccp_disconnect2(dp);
591 					dccp_output(dp, DCCP_TYPE_RESET + 2);
592 					dccp_close(dp);
593 					goto badunlocked;
594 				}
595 				optp = (u_char *)(drqh + 1);
596 
597 				/* store reference peer sequence number */
598 				dp->ref_pseq.hi = seqnr >> 24;
599 				dp->ref_pseq.lo = (u_int64_t)(seqnr & 0xffffff);
600 			} else
601 				optp = (u_char *)(dalh + 1);
602 		} else {
603 			extrah_len = 4;
604 			dah = (struct dccp_ackhdr *)(dh + 1);
605 			optp = (u_char *)(dah + 1);
606 		}
607 
608 	}
609 
610 	data_off = (dh->dh_off << 2);
611 
612 	dp->seq_rcv = seqnr;
613 	dp->ack_rcv = 0; /* Clear it for now */
614 	dp->type_rcv = dh->dh_type;
615 	dp->len_rcv = m->m_len - data_off - iphlen; /* Correct length ? */
616 
617 	if (!is_shortseq)
618 		optlen = data_off - (sizeof(struct dccplhdr) + extrah_len);
619 	else
620 		optlen = data_off - (sizeof(struct dccphdr) + extrah_len);
621 
622 	if (optlen < 0) {
623 		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));
624 		INP_UNLOCK(inp);
625 		goto badunlocked;
626 	}
627 
628 	if (optlen > 0) {
629 		if (optlen > DCCP_MAX_OPTIONS) {
630 			DCCP_DEBUG((LOG_INFO, "Error, more options (%i) then DCCP_MAX_OPTIONS options!\n", optlen));
631 			INP_UNLOCK(inp);
632 			goto badunlocked;
633 		}
634 
635 		DCCP_DEBUG((LOG_INFO, "Parsing DCCP options, optlen = %i\n", optlen));
636 		bcopy(optp, options, optlen);
637 		dccp_parse_options(dp, options, optlen);
638 	}
639 
640 	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));
641 
642 	if (dp->state == DCCPS_LISTEN) {
643 		switch (dh->dh_type) {
644 
645 		case DCCP_TYPE_REQUEST:
646 			DCCP_DEBUG((LOG_INFO, "Got DCCP REQUEST\n"));
647 			dp->state = DCCPS_REQUEST;
648 			if (dp->cc_in_use[1] < 0) {
649 				test[0] = DEFAULT_CCID;
650 				test[1] = 3;
651 				dccp_add_feature(dp, DCCP_OPT_CHANGE_R, DCCP_FEATURE_CC, test, 2);
652 			}
653 			if (len > data_off) {
654 				DCCP_DEBUG((LOG_INFO, "XXX: len=%d, data_off=%d\n", len, data_off));
655 				dccp_add_option(dp, DCCP_OPT_DATA_DISCARD, test, 0);
656 			}
657 			callout_reset(&dp->connect_timer, DCCP_CONNECT_TIMER,
658 			    dccp_connect_t, dp);
659 			dccp_output(dp, 0);
660 			break;
661 
662 
663 		/* These are ok if the sender has a valid init Cookie */
664 		case DCCP_TYPE_ACK:
665 		case DCCP_TYPE_DATAACK:
666 		case DCCP_TYPE_DATA:
667 			DCCP_DEBUG((LOG_INFO, "Got DCCP ACK/DATAACK/DATA, should check init cookie...\n"));
668 			dccp_output(dp, DCCP_TYPE_RESET + 2);
669 			break;
670 
671 		case DCCP_TYPE_RESET:
672 			DCCP_DEBUG((LOG_INFO, "Got DCCP RESET\n"));
673 			dp->state = DCCPS_TIME_WAIT;
674 			dp = dccp_close(dp);
675 			return;
676 
677 		default:
678 			DCCP_DEBUG((LOG_INFO, "Got a %u packet while in listen stage!\n", dh->dh_type));
679 			/* Force send reset. */
680 			dccp_output(dp, DCCP_TYPE_RESET + 2);
681 		}
682 	} else if (dp->state == DCCPS_REQUEST) {
683 		switch (dh->dh_type) {
684 		case DCCP_TYPE_RESPONSE:
685 			DAHDR_TO_DSEQ(dp->ack_rcv, ((struct dccp_acklhdr*)dalh)->dash);
686 			dp->ack_snd = dp->seq_rcv;
687 			DCCP_DEBUG((LOG_INFO, "Got DCCP REPSONSE %x %llx\n", dp, dp->ack_snd));
688 
689 			callout_stop(&dp->retrans_timer);
690 			callout_stop(&dp->connect_timer);
691 
692 			/* First check if we have negotiated a cc */
693 			if (dp->cc_in_use[0] > 0 && dp->cc_in_use[1] > 0) {
694 				DCCP_DEBUG((LOG_INFO, "Setting DCCPS_ESTAB & soisconnected\n"));
695 				dp->state = DCCPS_ESTAB;
696 				dccpstat.dccps_connects++;
697 #if defined(INET6)
698 				if (isipv6)
699 					soisconnected(in6p->in6p_socket);
700 				else
701 #endif
702 					soisconnected(inp->inp_socket);
703 			} else {
704 				dp->state = DCCPS_RESPOND;
705 				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]));
706 
707 			}
708 			dccp_output(dp, 0);
709 			break;
710 
711 		case DCCP_TYPE_RESET:
712 			DCCP_DEBUG((LOG_INFO, "Got DCCP RESET\n"));
713 			dp->state = DCCPS_TIME_WAIT;
714 			dp = dccp_close(dp);
715 			return;
716 
717 		default:
718 			DCCP_DEBUG((LOG_INFO, "Got a %u packet while in REQUEST stage!\n", dh->dh_type));
719 			/* Force send reset. */
720 			dccp_output(dp, DCCP_TYPE_RESET + 2);
721 			if (dh->dh_type == DCCP_TYPE_CLOSE) {
722 				dp = dccp_close(dp);
723 				return;
724 			} else {
725 				callout_stop(&dp->retrans_timer);
726 				dp->state = DCCPS_TIME_WAIT;
727 			}
728 		}
729 	} else if (dp->state == DCCPS_RESPOND) {
730 		switch (dh->dh_type) {
731 
732 		case DCCP_TYPE_REQUEST:
733 			break;
734 		case DCCP_TYPE_ACK:
735 		case DCCP_TYPE_DATAACK:
736 			DCCP_DEBUG((LOG_INFO, "Got DCCP ACK/DATAACK\n"));
737 
738 			callout_stop(&dp->connect_timer);
739 
740 			if (!is_shortseq) {
741 				DAHDR_TO_DSEQ(dp->ack_rcv, ((struct dccp_acklhdr*)dalh)->dash);
742 			} else {
743 				/* shortseq XXX */
744 				dp->ack_rcv = CONVERT_TO_LONGSEQ((ntohl(dah->dash.dah_ack) >> 8), dp->ref_seq);
745 			}
746 
747 			if (dp->cc_in_use[0] > 0 && dp->cc_in_use[1] > 0) {
748 				DCCP_DEBUG((LOG_INFO, "Setting DCCPS_ESTAB & soisconnected\n"));
749 				dp->state = DCCPS_ESTAB;
750 				dccpstat.dccps_connects++;
751 #if defined(INET6)
752 				if (isipv6)
753 					soisconnected(in6p->in6p_socket);
754 				else
755 #endif
756 					soisconnected(inp->inp_socket);
757 			} else {
758 				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]));
759 				/* Force an output!!! */
760 				dp->ack_snd = dp->seq_rcv;
761 				dccp_output(dp, 0);
762 			}
763 
764 			if (dh->dh_type == DCCP_TYPE_DATAACK && dp->cc_in_use[1] > 0) {
765 				if (!dp->ack_snd) dp->ack_snd = dp->seq_rcv;
766 				DCCP_DEBUG((LOG_INFO, "Calling *cc_sw[%u].cc_recv_packet_recv!\n", dp->cc_in_use[1]));
767 				(*cc_sw[dp->cc_in_use[1]].cc_recv_packet_recv)(dp->cc_state[1], options, optlen);
768 			}
769 			break;
770 
771 		case DCCP_TYPE_CLOSE:
772 			dccp_output(dp, DCCP_TYPE_CLOSE + 1);
773 			dp = dccp_close(dp);
774 			goto badunlocked;
775 
776 		case DCCP_TYPE_RESET:
777 			dp->state = DCCPS_TIME_WAIT;
778 			callout_stop(&dp->retrans_timer);
779 			break;
780 
781 		default:
782 			DCCP_DEBUG((LOG_INFO, "Got a %u packet while in response stage!\n", dh->dh_type));
783 			/* Force send reset. */
784 			dccp_output(dp, DCCP_TYPE_RESET + 2);
785 		}
786 	} else if (dp->state == DCCPS_ESTAB) {
787 		switch (dh->dh_type) {
788 
789 		case DCCP_TYPE_DATA:
790 			DCCP_DEBUG((LOG_INFO, "Got DCCP DATA, state = %i, cc_in_use[1] = %u\n", dp->state, dp->cc_in_use[1]));
791 
792 			if (dp->cc_in_use[1] > 0) {
793 				if (!dp->ack_snd) dp->ack_snd = dp->seq_rcv;
794 				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));
795 				(*cc_sw[dp->cc_in_use[1]].cc_recv_packet_recv)(dp->cc_state[1], options, optlen);
796 			}
797 			break;
798 
799 		case DCCP_TYPE_ACK:
800 			DCCP_DEBUG((LOG_INFO, "Got DCCP ACK\n"));
801 			if (!is_shortseq) {
802 				DAHDR_TO_DSEQ(dp->ack_rcv, ((struct dccp_acklhdr*)dalh)->dash);
803 			} else {
804 				/* shortseq */
805 				dp->ack_rcv = CONVERT_TO_LONGSEQ((ntohl(dah->dash.dah_ack) >> 8), dp->ref_seq);
806 			}
807 
808 			if (dp->cc_in_use[1] > 0) {
809 				/* This is called so Acks on Acks can be handled */
810 				if (!dp->ack_snd) dp->ack_snd = dp->seq_rcv;
811 				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));
812 				(*cc_sw[dp->cc_in_use[1]].cc_recv_packet_recv)(dp->cc_state[1], options, optlen);
813 			}
814 			break;
815 
816 		case DCCP_TYPE_DATAACK:
817 			DCCP_DEBUG((LOG_INFO, "Got DCCP DATAACK\n"));
818 
819 			if (!is_shortseq) {
820 				DAHDR_TO_DSEQ(dp->ack_rcv, ((struct dccp_acklhdr*)dalh)->dash);
821 			} else {
822 				/* shortseq */
823 				dp->ack_rcv = CONVERT_TO_LONGSEQ((ntohl(dah->dash.dah_ack) >> 8), dp->ref_seq);
824 			}
825 
826 			if (dp->cc_in_use[1] > 0) {
827 				if (!dp->ack_snd) dp->ack_snd = dp->seq_rcv;
828 				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));
829 				(*cc_sw[dp->cc_in_use[1]].cc_recv_packet_recv)(dp->cc_state[1], options, optlen);
830 			}
831 			break;
832 
833 		case DCCP_TYPE_CLOSEREQ:
834 			DCCP_DEBUG((LOG_INFO, "Got DCCP CLOSEREQ, state = estab\n"));
835 			if (dp->who == DCCP_CLIENT) {
836 				dccp_disconnect2(dp);
837 			} else {
838 				dccp_output(dp, DCCP_TYPE_RESET + 2);
839 			}
840 			break;
841 
842 		case DCCP_TYPE_CLOSE:
843 			DCCP_DEBUG((LOG_INFO, "Got DCCP CLOSE, state = estab\n"));
844 			dp->state = DCCPS_SERVER_CLOSE; /* So disconnect2 doesn't send CLOSEREQ */
845 			dccp_disconnect2(dp);
846 			dccp_output(dp, DCCP_TYPE_RESET + 2);
847 			dccp_close(dp);
848 			goto badunlocked;
849 			break;
850 
851 		case DCCP_TYPE_RESET:
852 			DCCP_DEBUG((LOG_INFO, "Got DCCP RESET\n"));
853 			dp->state = DCCPS_TIME_WAIT;
854 			callout_stop(&dp->retrans_timer);
855 			callout_reset(&dp->timewait_timer, DCCP_TIMEWAIT_TIMER,
856 			    dccp_timewait_t, dp);
857 			break;
858 
859 		case DCCP_TYPE_MOVE:
860 			DCCP_DEBUG((LOG_INFO, "Got DCCP MOVE\n"));
861 			break;
862 
863 		default:
864 			DCCP_DEBUG((LOG_INFO, "Got a %u packet while in established stage!\n", dh->dh_type));
865 		}
866 
867 	} else if (dp->state == DCCPS_SERVER_CLOSE) {
868 		/* Server */
869 		switch (dh->dh_type) {
870 		case DCCP_TYPE_CLOSE:
871 			DCCP_DEBUG((LOG_INFO, "Got DCCP CLOSE (State DCCPS_SERVER_CLOSE)\n"));
872 			callout_stop(&dp->retrans_timer);
873 			dccp_output(dp, DCCP_TYPE_RESET + 2);
874 			dp = dccp_close(dp);
875 			goto badunlocked;
876 
877 		case DCCP_TYPE_RESET:
878 			DCCP_DEBUG((LOG_INFO, "Got DCCP RESET\n"));
879 			callout_stop(&dp->retrans_timer);
880 			dccp_output(dp, DCCP_TYPE_RESET + 2);
881 			dp->state = DCCPS_TIME_WAIT;
882 			break;
883 		default:
884 			DCCP_DEBUG((LOG_INFO, "Got a %u packet while in server_close stage!\n", dh->dh_type));
885 		}
886 
887 	} else if (dp->state == DCCPS_CLIENT_CLOSE) {
888 		/* Client */
889 		switch (dh->dh_type) {
890 		case DCCP_TYPE_CLOSE:
891 			/* Ignore */
892 			break;
893 		case DCCP_TYPE_CLOSEREQ:
894 			DCCP_DEBUG((LOG_INFO, "Got DCCP CLOSEREQ, state = DCCPS_CLIENT_CLOSE\n"));
895 			/* Just resend close */
896 			dccp_output(dp, 0);
897 			break;
898 		case DCCP_TYPE_RESET:
899 			DCCP_DEBUG((LOG_INFO, "Got DCCP RESET\n"));
900 			callout_stop(&dp->retrans_timer);
901 			dp->state = DCCPS_TIME_WAIT;
902 			callout_reset(&dp->timewait_timer, DCCP_TIMEWAIT_TIMER,
903 			    dccp_timewait_t, dp);
904 			break;
905 		default:
906 			DCCP_DEBUG((LOG_INFO, "Got a %u packet while in client_close stage!\n", dh->dh_type));
907 
908 		}
909 	} else {
910 		DCCP_DEBUG((LOG_INFO, "Got a %u packet while in %u state!\n", dh->dh_type, dp->state));
911 		if (dh->dh_type != DCCP_TYPE_RESET) {
912 			/* Force send reset. */
913 			DCCP_DEBUG((LOG_INFO, "Force sending a request!\n"));
914 			dccp_output(dp, DCCP_TYPE_RESET + 2);
915 		}
916 	}
917 
918 	if (dh->dh_type == DCCP_TYPE_DATA ||
919 	    dh->dh_type == DCCP_TYPE_ACK  ||
920 	    dh->dh_type == DCCP_TYPE_DATAACK) {
921 		if (dp->cc_in_use[0] > 0) {
922 			(*cc_sw[dp->cc_in_use[0]].cc_send_packet_recv)(dp->cc_state[0],options, optlen);
923 		}
924 
925 	}
926 
927 	if (dh->dh_type == DCCP_TYPE_DATA || dh->dh_type == DCCP_TYPE_DATAACK) {
928 #if defined(__FreeBSD__) && __FreeBSD_version >= 503000
929 		if (so->so_rcv.sb_state & SBS_CANTRCVMORE)
930 #else
931 		if (so->so_state & SS_CANTRCVMORE)
932 #endif
933 		{
934 			DCCP_DEBUG((LOG_INFO, "state & SS_CANTRCVMORE...!\n"));
935 			m_freem(m);
936 			if (opts)
937 				m_freem(opts);
938 		} else {
939 			m_adj(m, (iphlen + data_off));
940 			DCCP_DEBUG((LOG_INFO, "Calling sbappend!\n"));
941 			sbappend(&so->so_rcv, m);
942 		}
943 		DCCP_DEBUG((LOG_INFO, "Calling sorwakeup...!\n"));
944 		sorwakeup(so);
945 	} else {
946 		m_freem(m);
947 		if (opts)
948 			m_freem(opts);
949 	}
950 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
951 	if (dp)
952 		INP_UNLOCK(inp);
953 #endif
954 
955 	return;
956 
957 badunlocked:
958 	m_freem(m);
959 	if (opts)
960 		m_freem(opts);
961 	return;
962 }
963 
964 /*
965  * Notify a dccp user of an asynchronous error;
966  * just wake up so that he can collect error status.
967  */
968 void
969 dccp_notify(struct inpcb *inp, int errno)
970 {
971 	inp->inp_socket->so_error = errno;
972 	sorwakeup(inp->inp_socket);
973 	sowwakeup(inp->inp_socket);
974 	return;
975 }
976 
977 /*
978  * Called when we get ICMP errors (destination unrechable,
979  * parameter problem, source quench, time exceeded and redirects)
980  */
981 void *
982 dccp_ctlinput(int cmd, const struct sockaddr *sa, void *vip)
983 {
984 	struct ip *ip = vip;
985 	struct dccphdr *dh;
986 	void (*notify)(struct inpcb *, int) = dccp_notify;
987 	struct in_addr faddr;
988 	struct inpcb *inp = NULL;
989 
990 	faddr = ((const struct sockaddr_in *)sa)->sin_addr;
991 	if (sa->sa_family != AF_INET || faddr.s_addr == INADDR_ANY)
992 		return NULL;
993 
994 	if (PRC_IS_REDIRECT(cmd)) {
995 		ip = 0;
996 		notify = in_rtchange;
997 	} else if (cmd == PRC_HOSTDEAD)
998 		ip = 0;
999 	else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0)
1000 		return NULL;
1001 	if (ip) {
1002 		/*s = splsoftnet();*/
1003 		dh = (struct dccphdr *)((vaddr_t)ip + (ip->ip_hl << 2));
1004 		INP_INFO_RLOCK(&dccpbinfo);
1005 		in_pcbnotify(&dccpbtable, faddr, dh->dh_dport,
1006 		    ip->ip_src, dh->dh_sport, inetctlerrmap[cmd], notify);
1007 		if (inp != NULL) {
1008 			INP_LOCK(inp);
1009 			if (inp->inp_socket != NULL) {
1010 				(*notify)(inp, inetctlerrmap[cmd]);
1011 			}
1012 			INP_UNLOCK(inp);
1013 		}
1014 		INP_INFO_RUNLOCK(&dccpbinfo);
1015 		/*splx(s);*/
1016 	} else
1017 		in_pcbnotifyall(&dccpbtable, faddr, inetctlerrmap[cmd], notify);
1018 
1019 	return NULL;
1020 }
1021 
1022 static int
1023 dccp_optsset(struct dccpcb *dp, struct sockopt *sopt)
1024 {
1025 	int optval;
1026 	int error = 0;
1027 
1028 	switch (sopt->sopt_name) {
1029 	case DCCP_CCID:
1030 		error = sockopt_getint(sopt, &optval);
1031 		/* Add check that optval is a CCID we support!!! */
1032 		if (optval == 2 || optval == 3 || optval == 0) {
1033 			dp->pref_cc = optval;
1034 		} else {
1035 			error = EINVAL;
1036 		}
1037 		break;
1038 	case DCCP_CSLEN:
1039 		error = sockopt_getint(sopt, &optval);
1040 		if (optval > 15 || optval < 0) {
1041 			error = EINVAL;
1042 		} else {
1043 			dp->cslen = optval;
1044 		}
1045 		break;
1046 	case DCCP_MAXSEG:
1047 		error = sockopt_getint(sopt, &optval);
1048 		if (optval > 0 && optval <= dp->d_maxseg) {
1049 			dp->d_maxseg = optval;
1050 		} else {
1051 			error = EINVAL;
1052 		}
1053 		break;
1054 	case DCCP_SERVICE:
1055 		error = sockopt_getint(sopt, &optval);
1056 		dp->scode = optval;
1057 		break;
1058 
1059 	default:
1060 		error = ENOPROTOOPT;
1061 	}
1062 
1063 	return error;
1064 }
1065 
1066 static int
1067 dccp_optsget(struct dccpcb *dp, struct sockopt *sopt)
1068 {
1069 	int optval = 0;
1070 	int error = 0;
1071 
1072 	switch (sopt->sopt_name) {
1073 	case DCCP_CCID:
1074 		optval = dp->pref_cc;
1075 		error = sockopt_set(sopt, &optval, sizeof(optval));
1076 		break;
1077 	case DCCP_CSLEN:
1078 		optval = dp->cslen;
1079 		error = sockopt_set(sopt, &optval, sizeof(optval));
1080 		break;
1081 	case DCCP_MAXSEG:
1082 		optval = dp->d_maxseg;
1083 		error = sockopt_set(sopt, &optval, sizeof(optval));
1084 		break;
1085 	case DCCP_SERVICE:
1086 		optval = dp->scode;
1087 		error = sockopt_set(sopt, &optval, sizeof(optval));
1088 		break;
1089 	default:
1090 		error = ENOPROTOOPT;
1091 	}
1092 
1093 	return error;
1094 }
1095 
1096 /*
1097  * Called by getsockopt and setsockopt.
1098  *
1099  */
1100 int
1101 dccp_ctloutput(int op, struct socket *so, struct sockopt *sopt)
1102 {
1103 	int s, error = 0;
1104 	struct inpcb	*inp;
1105 #if defined(INET6)
1106 	struct in6pcb *in6p;
1107 #endif
1108 	struct dccpcb	*dp;
1109 	int family;	/* family of the socket */
1110 
1111 	family = so->so_proto->pr_domain->dom_family;
1112 	error = 0;
1113 
1114 	s = splsoftnet();
1115 	INP_INFO_RLOCK(&dccpbinfo);
1116 	switch (family) {
1117 	case PF_INET:
1118 		inp = sotoinpcb(so);
1119 #if defined(INET6)
1120 		in6p = NULL;
1121 #endif
1122 		break;
1123 #if defined(INET6)
1124 	case PF_INET6:
1125 		inp = NULL;
1126 		in6p = sotoin6pcb(so);
1127 		break;
1128 #endif
1129 	default:
1130 		INP_INFO_RUNLOCK(&dccpbinfo);
1131 		splx(s);
1132 		return EAFNOSUPPORT;
1133 	}
1134 #if defined(INET6)
1135 	if (inp == NULL && in6p == NULL)
1136 #else
1137 	if (inp == NULL)
1138 #endif
1139 	{
1140 		INP_INFO_RUNLOCK(&dccpbinfo);
1141 		splx(s);
1142 		return (ECONNRESET);
1143 	}
1144 /*
1145 	if (inp)
1146 		INP_LOCK(inp);
1147 	else
1148 		IN6P_LOCK(in6p);
1149 	INP_INFO_RUNLOCK(&dccpbinfo);
1150 */
1151 	if (sopt->sopt_level != IPPROTO_DCCP) {
1152 		switch (family) {
1153 		case PF_INET:
1154 			error = ip_ctloutput(op, so, sopt);
1155 			break;
1156 #if defined(INET6)
1157 		case PF_INET6:
1158 			error = ip6_ctloutput(op, so, sopt);
1159 			break;
1160 #endif
1161 		}
1162 		splx(s);
1163 		return (error);
1164 	}
1165 
1166 	if (inp)
1167 		dp = intodccpcb(inp);
1168 #if defined(INET6)
1169 	else if (in6p)
1170 		dp = in6todccpcb(in6p);
1171 #endif
1172 	else
1173 		dp = NULL;
1174 
1175 	if (op == PRCO_SETOPT) {
1176 		error = dccp_optsset(dp, sopt);
1177 	} else if (op ==  PRCO_GETOPT) {
1178 		error = dccp_optsget(dp, sopt);
1179 	} else {
1180 		error = EINVAL;
1181 	}
1182 /*
1183 	if (inp)
1184 		INP_UNLOCK(inp);
1185 	else
1186 		IN6P_UNLOCK(in6p);
1187 */
1188 	splx(s);
1189 	return error;
1190 }
1191 
1192 int
1193 dccp_output(struct dccpcb *dp, u_int8_t extra)
1194 {
1195 	struct inpcb *inp;
1196 	struct in6pcb *in6p = NULL;
1197 	struct socket *so;
1198 	struct mbuf *m;
1199 
1200 	struct ip *ip = NULL;
1201 	struct dccphdr *dh;
1202 	struct dccplhdr *dlh;
1203 	struct dccp_requesthdr *drqh;
1204 	struct dccp_ackhdr *dah;
1205 	struct dccp_acklhdr *dalh;
1206 	struct dccp_resethdr *drth;
1207 	u_char *optp = NULL;
1208 	int error = 0;
1209 	int off, sendalot, t, i;
1210 	u_int32_t hdrlen, optlen, extrah_len, cslen;
1211 	u_int8_t type;
1212 	char options[DCCP_MAX_OPTIONS *2];
1213 	long len, pktlen;
1214 	int isipv6 = 0;
1215 	int use_shortseq = 0;
1216 #ifdef INET6
1217 	struct ip6_hdr *ip6 = NULL;
1218 #endif
1219 
1220 	DCCP_DEBUG((LOG_INFO, "dccp_output start!\n"));
1221 
1222 	isipv6 = (dp->inp_vflag & INP_IPV6) != 0;
1223 
1224 	DCCP_DEBUG((LOG_INFO, "Going to send a DCCP packet!\n"));
1225 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
1226 	KASSERT(mutex_assert(&dp->d_inpcb->inp_mtx, MA_OWNED));
1227 #endif
1228 
1229 #if defined(INET6)
1230 	if (isipv6) {
1231 		inp = 0;
1232 		in6p = dp->d_in6pcb;
1233 		so = in6p->in6p_socket;
1234 	} else
1235 #endif
1236 	{
1237 		inp = dp->d_inpcb;
1238 		so = inp->inp_socket;
1239 	}
1240 
1241 	if (dp->state != DCCPS_ESTAB && extra == 1) {
1242 		/* Only let cc decide when to resend if we are in establised state */
1243 		return 0;
1244 	}
1245 
1246 	if (so->so_snd.sb_cc){
1247 		pktlen = dp->pktlen[dp->pktlenidx];
1248 	} else
1249 		pktlen = 0;
1250 
1251 	/* Check with CC if we can send... */
1252 	if (pktlen && dp->cc_in_use[0] > 0 && dp->state == DCCPS_ESTAB) {
1253 		if (!(*cc_sw[dp->cc_in_use[0]].cc_send_packet)(dp->cc_state[0], pktlen)) {
1254 			DCCP_DEBUG((LOG_INFO, "Not allowed to send right now\n"));
1255 			return 0;
1256 		}
1257 	}
1258 
1259 	if (pktlen) {
1260 		dp->pktcnt --;
1261 		dp->pktlenidx = (dp->pktlenidx +1) % DCCP_MAX_PKTS;
1262 	}
1263 
1264 again:
1265 	sendalot = 0;
1266 
1267 	/*
1268 	 * off not needed for dccp because we do not need to wait for ACK
1269 	 * before removing the packet
1270 	 */
1271 	off = 0;
1272 	optlen = 0;
1273 
1274 	if (pktlen > dp->d_maxseg) {
1275 		/* this should not happen */
1276 		DCCP_DEBUG((LOG_INFO, "packet will be fragmented! maxseg %d\n", dp->d_maxseg));
1277 		len = dp->d_maxseg;
1278 		pktlen -= len;
1279 		sendalot = 1;
1280 	} else
1281 		len = pktlen;
1282 
1283 	if (extra == DCCP_TYPE_RESET + 2) {
1284 		DCCP_DEBUG((LOG_INFO, "Force sending of DCCP TYPE_RESET! seq=%llu\n", dp->seq_snd));
1285 		type = DCCP_TYPE_RESET;
1286 		extrah_len = 12;
1287 	} else if (dp->state <= DCCPS_REQUEST && dp->who == DCCP_CLIENT) {
1288 		DCCP_DEBUG((LOG_INFO, "Sending DCCP TYPE_REQUEST!\n"));
1289 		type = DCCP_TYPE_REQUEST;
1290 		dp->state = DCCPS_REQUEST;
1291 		extrah_len = 4;
1292 	} else if (dp->state == DCCPS_REQUEST && dp->who == DCCP_SERVER) {
1293 		DCCP_DEBUG((LOG_INFO, "Sending DCCP TYPE_RESPONSE!\n"));
1294 		type = DCCP_TYPE_RESPONSE;
1295 		dp->state = DCCPS_RESPOND;
1296 		extrah_len = 12;
1297 	} else if (dp->state == DCCPS_RESPOND) {
1298 		DCCP_DEBUG((LOG_INFO, "Still in feature neg, sending DCCP TYPE_ACK!\n"));
1299 		type = DCCP_TYPE_ACK;
1300 		if (!dp->shortseq)
1301 			extrah_len = 8;
1302 		else {
1303 			extrah_len = 4;
1304 			use_shortseq = 1;
1305 		}
1306 	} else if (dp->state == DCCPS_ESTAB) {
1307 		if (dp->ack_snd && len) {
1308 			DCCP_DEBUG((LOG_INFO, "Sending DCCP TYPE_DATAACK!\n"));
1309 			type = DCCP_TYPE_DATAACK;
1310 			/*(u_int32_t *)&extrah = dp->seq_rcv; */
1311 			if (!dp->shortseq)
1312 				extrah_len = 8;
1313 			else {
1314 				extrah_len = 4;
1315 				use_shortseq = 1;
1316 			}
1317 		} else if (dp->ack_snd) {
1318 			DCCP_DEBUG((LOG_INFO, "Sending DCCP TYPE_ACK!\n"));
1319 			type = DCCP_TYPE_ACK;
1320 			if (!dp->shortseq)
1321 				extrah_len = 8;
1322 			else {
1323 				extrah_len = 4;
1324 				use_shortseq = 1;
1325 			}
1326 		} else if (len) {
1327 			DCCP_DEBUG((LOG_INFO, "Sending DCCP TYPE_DATA!\n"));
1328 			type = DCCP_TYPE_DATA;
1329 			extrah_len = 0;
1330 		} else {
1331 			DCCP_DEBUG((LOG_INFO, "No ack or data to send!\n"));
1332 			return 0;
1333 		}
1334 	} else if (dp->state == DCCPS_CLIENT_CLOSE) {
1335 		DCCP_DEBUG((LOG_INFO, "Sending DCCP TYPE_CLOSE!\n"));
1336 		type = DCCP_TYPE_CLOSE;
1337 		extrah_len = 8;
1338 	} else if (dp->state == DCCPS_SERVER_CLOSE) {
1339 		DCCP_DEBUG((LOG_INFO, "Sending DCCP TYPE_CLOSEREQ!\n"));
1340 		type = DCCP_TYPE_CLOSEREQ;
1341 		extrah_len = 8;
1342 	} else {
1343 		DCCP_DEBUG((LOG_INFO, "Hey, we should never get here, state = %u\n", dp->state));
1344 		return 1;
1345 	}
1346 
1347 	/* Adding options. */
1348 	if (dp->optlen) {
1349 		DCCP_DEBUG((LOG_INFO, "Copying options from dp->options! %u\n", dp->optlen));
1350 		bcopy(dp->options, options , dp->optlen);
1351 		optlen = dp->optlen;
1352 		dp->optlen = 0;
1353 	}
1354 
1355 	if (dp->featlen && (optlen + dp->featlen < DCCP_MAX_OPTIONS)) {
1356 		DCCP_DEBUG((LOG_INFO, "Copying options from dp->features! %u\n", dp->featlen));
1357 		bcopy(dp->features, options + optlen, dp->featlen);
1358 		optlen += dp->featlen;
1359 	}
1360 
1361 	t = optlen % 4;
1362 
1363 	if (t) {
1364 		t = 4 - t;
1365 		for (i = 0 ; i<t; i++) {
1366 			options[optlen] = 0;
1367 			optlen++;
1368 		}
1369 	}
1370 
1371 #ifdef INET6
1372 	if (isipv6) {
1373 		DCCP_DEBUG((LOG_INFO, "Sending ipv6 packet...\n"));
1374 		if (!use_shortseq)
1375 			hdrlen = sizeof(struct ip6_hdr) + sizeof(struct dccplhdr) +
1376 			    extrah_len + optlen;
1377 		else
1378 			hdrlen = sizeof(struct ip6_hdr) + sizeof(struct dccphdr) +
1379 			    extrah_len + optlen;
1380 	} else
1381 #endif
1382 	{
1383 		if (!use_shortseq)
1384 			hdrlen = sizeof(struct ip) + sizeof(struct dccplhdr) +
1385 		   		extrah_len + optlen;
1386 		else
1387 			hdrlen = sizeof(struct ip) + sizeof(struct dccphdr) +
1388 		   		extrah_len + optlen;
1389 	}
1390 	DCCP_DEBUG((LOG_INFO, "Pkt headerlen %u\n", hdrlen));
1391 
1392 	if (len > (dp->d_maxseg - extrah_len - optlen)) {
1393 		len = dp->d_maxseg - extrah_len - optlen;
1394 		sendalot = 1;
1395 	}
1396 
1397 	MGETHDR(m, M_DONTWAIT, MT_HEADER);
1398 	if (m == NULL) {
1399 		error = ENOBUFS;
1400 		goto release;
1401 	}
1402 	if (MHLEN < hdrlen + max_linkhdr) {
1403 		MCLGET(m, M_DONTWAIT);
1404 		if ((m->m_flags & M_EXT) == 0) {
1405 			error = ENOBUFS;
1406 			goto release;
1407 		}
1408 	}
1409 
1410 	m->m_data += max_linkhdr;
1411 	m->m_len = hdrlen;
1412 
1413 	if (len) { /* We have data to send */
1414 		if (len <= M_TRAILINGSPACE(m) - hdrlen) {
1415 			m_copydata(so->so_snd.sb_mb, off, (int) len,
1416 			mtod(m, char *) + hdrlen);
1417 			m->m_len += len;
1418 		} else {
1419 			m->m_next = m_copy(so->so_snd.sb_mb, off, (int) len);
1420 			if (m->m_next == 0) {
1421 				error = ENOBUFS;
1422 				goto release;
1423 			}
1424 		}
1425 	} else {
1426 		dp->ndp++;
1427 	}
1428 
1429 	m_reset_rcvif(m);
1430 
1431 	if (!isipv6 && (len + hdrlen) > IP_MAXPACKET) {
1432 		error = EMSGSIZE;
1433 		goto release;
1434 	}
1435 
1436 	/*
1437 	 * Fill in mbuf with extended DCCP header
1438 	 * and addresses and length put into network format.
1439 	 */
1440 #ifdef INET6
1441 	if (isipv6) {
1442 		ip6 = mtod(m, struct ip6_hdr *);
1443 		dh = (struct dccphdr *)(ip6 + 1);
1444 		ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) |
1445 			(in6p->in6p_flowinfo & IPV6_FLOWINFO_MASK);
1446 		ip6->ip6_vfc = (ip6->ip6_vfc & ~IPV6_VERSION_MASK) |
1447 			 (IPV6_VERSION & IPV6_VERSION_MASK);
1448 		ip6->ip6_nxt = IPPROTO_DCCP;
1449 		ip6->ip6_src = in6p->in6p_laddr;
1450 		ip6->ip6_dst = in6p->in6p_faddr;
1451 	} else
1452 #endif
1453 	{
1454 		ip = mtod(m, struct ip *);
1455 		dh = (struct dccphdr *)(ip + 1);
1456 		bzero(ip, sizeof(struct ip));
1457 		ip->ip_p = IPPROTO_DCCP;
1458 		ip->ip_src = inp->inp_laddr;
1459 		ip->ip_dst = inp->inp_faddr;
1460 	}
1461 	dlh = (struct dccplhdr *)dh;
1462 
1463 	if (inp) {
1464 		dh->dh_sport = inp->inp_lport;
1465 		dh->dh_dport = inp->inp_fport;
1466 	}
1467 #ifdef INET6
1468 	else if (in6p) {
1469 		dh->dh_sport = in6p->in6p_lport;
1470 		dh->dh_dport = in6p->in6p_fport;
1471 	}
1472 #endif
1473 	dh->dh_cscov = dp->cslen;
1474 	dh->dh_ccval = dp->ccval;
1475 	dh->dh_type = type;
1476 	dh->dh_res = 0; /* Reserved field should be zero */
1477 	if (!use_shortseq) {
1478 		dlh->dh_res2 = 0; /* Reserved field should be zero */
1479 		dh->dh_off = 4 + (extrah_len / 4) + (optlen / 4);
1480 	} else
1481 		dh->dh_off = 3 + (extrah_len / 4) + (optlen / 4);
1482 
1483 	dp->seq_snd = (dp->seq_snd +1) % 281474976710656LL;
1484 	if (!use_shortseq) {
1485 		DSEQ_TO_DHDR(dlh, dp->seq_snd);
1486 		dlh->dh_x = 1;
1487 	} else {
1488 		/* short sequene number */
1489 		dh->dh_seq = htonl(dp->seq_snd) >> 8;
1490 		dh->dh_x = 0;
1491 	}
1492 
1493 	if (!use_shortseq) {
1494 		DCCP_DEBUG((LOG_INFO, "Sending with seq %x.%x, (dp->seq_snd = %llu)\n\n", dlh->dh_seq, dlh->dh_seq2, dp->seq_snd));
1495 	} else {
1496 		DCCP_DEBUG((LOG_INFO, "Sending with seq %x, (dp->seq_snd = %llu)\n\n", dh->dh_seq, dp->seq_snd));
1497 	}
1498 
1499 	if (dh->dh_type == DCCP_TYPE_REQUEST) {
1500 		drqh = (struct dccp_requesthdr *)(dlh + 1);
1501 		drqh->drqh_scode = dp->scode;
1502 		optp = (u_char *)(drqh + 1);
1503 	} else if (dh->dh_type == DCCP_TYPE_RESET) {
1504 		drth = (struct dccp_resethdr *)(dlh + 1);
1505 		drth->drth_dash.dah_res = 0;
1506 		DSEQ_TO_DAHDR(drth->drth_dash, dp->seq_rcv);
1507 		if (dp->state == DCCPS_SERVER_CLOSE)
1508 			drth->drth_reason = 1;
1509 		else
1510 			drth->drth_reason = 2;
1511 		drth->drth_data1 = 0;
1512 		drth->drth_data2 = 0;
1513 		drth->drth_data3 = 0;
1514 		optp = (u_char *)(drth + 1);
1515 	} else if (extrah_len) {
1516 		if (!use_shortseq){
1517 			dalh = (struct dccp_acklhdr *)(dlh + 1);
1518 			dalh->dash.dah_res = 0; /* Reserved field should be zero */
1519 
1520 			if (dp->state == DCCPS_ESTAB) {
1521 				DSEQ_TO_DAHDR(dalh->dash, dp->ack_snd);
1522 				dp->ack_snd = 0;
1523 			} else {
1524 				DSEQ_TO_DAHDR(dalh->dash, dp->seq_rcv);
1525 			}
1526 
1527 			if (dh->dh_type == DCCP_TYPE_RESPONSE) {
1528 				DCCP_DEBUG((LOG_INFO, "Sending dccp type response\n"));
1529 				drqh = (struct dccp_requesthdr *)(dalh + 1);
1530 				drqh->drqh_scode = dp->scode;
1531 				optp = (u_char *)(drqh + 1);
1532 			} else
1533 				optp = (u_char *)(dalh + 1);
1534 		} else {
1535 			/* XXX shortseq */
1536 			dah = (struct dccp_ackhdr *)(dh + 1);
1537 			dah->dash.dah_res = 0; /* Reserved field should be zero */
1538 			dah->dash.dah_ack = htonl(dp->seq_rcv) >> 8;
1539 			optp = (u_char *)(dah + 1);
1540 		}
1541 
1542 	} else {
1543 		optp = (u_char *)(dlh + 1);
1544 	}
1545 
1546 	if (optlen)
1547 		bcopy(options, optp, optlen);
1548 
1549 	m->m_pkthdr.len = hdrlen + len;
1550 
1551 	if (dh->dh_cscov == 0) {
1552 #ifdef INET6
1553 		if (isipv6)
1554 			cslen = (hdrlen - sizeof(struct ip6_hdr)) + len;
1555 		else
1556 			cslen = (hdrlen - sizeof(struct ip)) + len;
1557 #else
1558 		cslen = (hdrlen - sizeof(struct ip)) + len;
1559 #endif
1560 	} else {
1561 		cslen = dh->dh_off * 4 + (dh->dh_cscov - 1) * 4;
1562 #ifdef INET6
1563 		if (isipv6) {
1564 			if (cslen > (hdrlen - sizeof(struct ip6_hdr)) + len)
1565 				cslen = (hdrlen - sizeof(struct ip6_hdr)) + len;
1566 		} else {
1567 			if (cslen > (hdrlen - sizeof(struct ip)) + len)
1568 				cslen = (hdrlen - sizeof(struct ip)) + len;
1569 		}
1570 #else
1571 		if (cslen > (hdrlen - sizeof(struct ip)) + len)
1572 			cslen = (hdrlen - sizeof(struct ip)) + len;
1573 #endif
1574 	}
1575 
1576 	/*
1577 	 * Set up checksum
1578 	 */
1579 #ifdef __FreeBSD__
1580 	m->m_pkthdr.csum_flags = CSUM_IP; /* Do not allow the network card to calculate the checksum */
1581 #elif defined(__NetBSD__)
1582 	m->m_pkthdr.csum_flags = 0;
1583 #else
1584 	m->m_pkthdr.csum = 0;
1585 #endif
1586 
1587 	dh->dh_sum = 0;
1588 #ifdef INET6
1589 	if (isipv6) {
1590 		dh->dh_sum = in6_cksum(m, IPPROTO_DCCP, sizeof(struct ip6_hdr),
1591 		    cslen);
1592 	} else
1593 #endif
1594 	{
1595 		ip->ip_len = htons(hdrlen + len);
1596 		ip->ip_ttl = dp->inp_ip_ttl;	/* XXX */
1597 		ip->ip_tos = dp->inp_ip_tos;	/* XXX */
1598 
1599 		dh->dh_sum = in4_cksum(m, IPPROTO_DCCP, sizeof(struct ip),
1600 		    cslen);
1601 #ifndef __OpenBSD__
1602 		m->m_pkthdr.csum_data = offsetof(struct dccphdr, dh_sum);
1603 #endif
1604 	}
1605 
1606 	dccpstat.dccps_opackets++;
1607 	dccpstat.dccps_obytes += m->m_pkthdr.len;
1608 
1609 #ifdef INET6
1610 	if (isipv6) {
1611 		DCCP_DEBUG((LOG_INFO, "Calling ip_output6, mbuf->m_len = %u, mbuf->m_pkthdr.len = %u\n", m->m_len, m->m_pkthdr.len));
1612 
1613 		error = ip6_output(m, in6p->in6p_outputopts, &in6p->in6p_route,
1614 		    (in6p->in6p_socket->so_options & SO_DONTROUTE), NULL, NULL,
1615 		    NULL);
1616 	} else
1617 #endif
1618 	{
1619 		DCCP_DEBUG((LOG_INFO, "Calling ip_output, mbuf->m_len = %u, mbuf->m_pkthdr.len = %u\n", m->m_len, m->m_pkthdr.len));
1620 		error = ip_output(m, inp->inp_options, &inp->inp_route,
1621 		    (inp->inp_socket->so_options & SO_DONTROUTE), 0,
1622 				  inp->inp_socket);
1623 	}
1624 
1625 	if (error) {
1626 		DCCP_DEBUG((LOG_INFO, "IP output failed! %d\n", error));
1627 		return (error);
1628 	}
1629 
1630 #if defined(INET6)
1631 	if (isipv6) {
1632 		sbdrop(&in6p->in6p_socket->so_snd, len);
1633 		sowwakeup(in6p->in6p_socket);
1634 	} else
1635 #endif
1636 	{
1637 		sbdrop(&inp->inp_socket->so_snd, len);
1638 		sowwakeup(inp->inp_socket);
1639 	}
1640 
1641 	if (dp->cc_in_use[0] > 0  && dp->state == DCCPS_ESTAB) {
1642 		DCCP_DEBUG((LOG_INFO, "Calling *cc_sw[%u].cc_send_packet_sent!\n", dp->cc_in_use[0]));
1643 		if (sendalot) {
1644 			(*cc_sw[dp->cc_in_use[0]].cc_send_packet_sent)(dp->cc_state[0], 1,len);
1645 			goto again;
1646 		} else {
1647 			(*cc_sw[dp->cc_in_use[0]].cc_send_packet_sent)(dp->cc_state[0], 0,len);
1648 		}
1649 	} else {
1650 		if (sendalot)
1651 			goto again;
1652 	}
1653 
1654 	DCCP_DEBUG((LOG_INFO, "dccp_output finished\n"));
1655 
1656 	return (0);
1657 
1658 release:
1659 	m_freem(m);
1660 	return (error);
1661 }
1662 
1663 int
1664 dccp_abort(struct socket *so)
1665 {
1666 	struct inpcb *inp = 0;
1667 	struct in6pcb *in6p;
1668 	struct dccpcb *dp;
1669 
1670 	DCCP_DEBUG((LOG_INFO, "Entering dccp_abort!\n"));
1671 	INP_INFO_WLOCK(&dccpbinfo);
1672 	if (so->so_proto->pr_domain->dom_family == PF_INET6) {
1673 		in6p = sotoin6pcb(so);
1674 		if (in6p == 0) {
1675 			return EINVAL;
1676 		}
1677 		inp = 0;
1678 		dp = (struct dccpcb *)in6p->in6p_ppcb;
1679 	} else {
1680 		inp = sotoinpcb(so);
1681 		if (inp == 0) {
1682 			INP_INFO_WUNLOCK(&dccpbinfo);
1683 			return EINVAL;
1684 		}
1685 		dp = (struct dccpcb *)inp->inp_ppcb;
1686 	}
1687 
1688 	dccp_disconnect2(dp);
1689 
1690 	INP_INFO_WUNLOCK(&dccpbinfo);
1691 	return 0;
1692 }
1693 
1694 static struct dccpcb *
1695 dccp_close(struct dccpcb *dp)
1696 {
1697 	struct socket *so;
1698 	struct inpcb *inp = dp->d_inpcb;
1699 	struct in6pcb *in6p = dp->d_in6pcb;
1700 	so = dptosocket(dp);
1701 
1702 	DCCP_DEBUG((LOG_INFO, "Entering dccp_close!\n"));
1703 
1704 	/* Stop all timers */
1705 	callout_stop(&dp->connect_timer);
1706 	callout_stop(&dp->retrans_timer);
1707 	callout_stop(&dp->close_timer);
1708 	callout_stop(&dp->timewait_timer);
1709 
1710 	if (dp->cc_in_use[0] > 0)
1711 		(*cc_sw[dp->cc_in_use[0]].cc_send_free)(dp->cc_state[0]);
1712 	if (dp->cc_in_use[1] > 0)
1713 		(*cc_sw[dp->cc_in_use[1]].cc_recv_free)(dp->cc_state[1]);
1714 
1715 	pool_put(&dccpcb_pool, dp);
1716 	if (inp) {
1717 		inp->inp_ppcb = NULL;
1718 		soisdisconnected(so);
1719 		in_pcbdetach(inp);
1720 	}
1721 #if defined(INET6)
1722 	else if (in6p) {
1723 		in6p->in6p_ppcb = 0;
1724 		soisdisconnected(so);
1725 		in6_pcbdetach(in6p);
1726 	}
1727 #endif
1728 	return ((struct dccpcb *)0);
1729 }
1730 
1731 /*
1732  * Runs when a new socket is created with the
1733  * socket system call or sonewconn.
1734  */
1735 int
1736 dccp_attach(struct socket *so, int proto)
1737 {
1738 	struct inpcb *inp = 0;
1739 	struct in6pcb *in6p = 0;
1740 	struct dccpcb *dp;
1741 	int s, family, error = 0;
1742 
1743 	DCCP_DEBUG((LOG_INFO, "Entering dccp_attach(proto=%d)!\n", proto));
1744 	INP_INFO_WLOCK(&dccpbinfo);
1745 	s = splsoftnet();
1746 	sosetlock(so);
1747 
1748 	family = so->so_proto->pr_domain->dom_family;
1749 	switch (family) {
1750 	case PF_INET:
1751 		inp = sotoinpcb(so);
1752 		if (inp != 0) {
1753 			error = EINVAL;
1754 			goto out;
1755 		}
1756 		error = soreserve(so, dccp_sendspace, dccp_recvspace);
1757 		if (error)
1758 			goto out;
1759 		error = in_pcballoc(so, &dccpbtable);
1760 		if (error)
1761 			goto out;
1762 		inp = sotoinpcb(so);
1763 		break;
1764 #if defined(INET6)
1765 	case PF_INET6:
1766 		in6p = sotoin6pcb(so);
1767 		if (in6p != 0) {
1768 			error = EINVAL;
1769 			goto out;
1770 		}
1771 		error = soreserve(so, dccp_sendspace, dccp_recvspace);
1772 		if (error)
1773 			goto out;
1774 		error = in6_pcballoc(so, &dccpbtable);
1775 		if (error)
1776 			goto out;
1777 		in6p = sotoin6pcb(so);
1778 		break;
1779 #endif
1780 	default:
1781 		error = EAFNOSUPPORT;
1782 		goto out;
1783 	}
1784 
1785 	if (inp)
1786 		dp = dccp_newdccpcb(PF_INET, (void *)inp);
1787 	else if (in6p)
1788 		dp = dccp_newdccpcb(PF_INET6, (void *)in6p);
1789 	else
1790 		dp = NULL;
1791 
1792 	if (dp == 0) {
1793 		int nofd = so->so_state & SS_NOFDREF;
1794 		so->so_state &= ~SS_NOFDREF;
1795 #if defined(INET6)
1796 		if (proto == PF_INET6) {
1797 			in6_pcbdetach(in6p);
1798 		} else
1799 #endif
1800 			in_pcbdetach(inp);
1801 		so->so_state |= nofd;
1802 		error = ENOBUFS;
1803 		goto out;
1804 	}
1805 
1806 #ifdef INET6
1807 	if (proto == PF_INET6) {
1808 		DCCP_DEBUG((LOG_INFO, "We are a ipv6 socket!!!\n"));
1809 		dp->inp_vflag |= INP_IPV6;
1810 	} else
1811 #endif
1812 		dp->inp_vflag |= INP_IPV4;
1813 	dp->inp_ip_ttl = ip_defttl;
1814 
1815 	dp->state = DCCPS_CLOSED;
1816 out:
1817 	splx(s);
1818 	INP_INFO_WUNLOCK(&dccpbinfo);
1819 	return error;
1820 }
1821 
1822 static int
1823 dccp_bind(struct socket *so, struct sockaddr *nam, struct lwp *l)
1824 {
1825 	struct inpcb *inp;
1826 	int error;
1827 	struct sockaddr_in *sin = (struct sockaddr_in *)nam;
1828 
1829 	DCCP_DEBUG((LOG_INFO, "Entering dccp_bind!\n"));
1830 	INP_INFO_WLOCK(&dccpbinfo);
1831 	inp = sotoinpcb(so);
1832 	if (inp == 0) {
1833 		INP_INFO_WUNLOCK(&dccpbinfo);
1834 		return EINVAL;
1835 	}
1836 
1837 	/* Do not bind to multicast addresses! */
1838 	if (sin->sin_family == AF_INET &&
1839 	    IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
1840 		INP_INFO_WUNLOCK(&dccpbinfo);
1841 		return EAFNOSUPPORT;
1842 	}
1843 	INP_LOCK(inp);
1844 	error = in_pcbbind(inp, sin, l);
1845 	INP_UNLOCK(inp);
1846 	INP_INFO_WUNLOCK(&dccpbinfo);
1847 	return error;
1848 }
1849 
1850 /*
1851  * Initiates a connection to a server
1852  * Called by the connect system call.
1853  */
1854 static int
1855 dccp_connect(struct socket *so, struct sockaddr *nam, struct lwp *l)
1856 {
1857 	struct inpcb *inp;
1858 	struct dccpcb *dp;
1859 	int error;
1860 	struct sockaddr_in *sin;
1861 	char test[2];
1862 
1863 	DCCP_DEBUG((LOG_INFO, "Entering dccp_connect!\n"));
1864 
1865 	INP_INFO_WLOCK(&dccpbinfo);
1866 	inp = sotoinpcb(so);
1867 	if (inp == 0) {
1868 		INP_INFO_WUNLOCK(&dccpbinfo);
1869 		return EINVAL;
1870 	}
1871 	INP_LOCK(inp);
1872 	if (inp->inp_faddr.s_addr != INADDR_ANY) {
1873 		INP_UNLOCK(inp);
1874 		INP_INFO_WUNLOCK(&dccpbinfo);
1875 		return EISCONN;
1876 	}
1877 
1878 	dp = (struct dccpcb *)inp->inp_ppcb;
1879 
1880 	if (dp->state == DCCPS_ESTAB) {
1881 		DCCP_DEBUG((LOG_INFO, "Why are we in connect when we already have a established connection?\n"));
1882 	}
1883 
1884 	dp->who = DCCP_CLIENT;
1885 	dp->seq_snd = (((u_int64_t)random() << 32) | random()) % 281474976710656LL;
1886 	dp->ref_seq.hi = dp->seq_snd >> 24;
1887 	dp->ref_seq.lo = (u_int64_t)(dp->seq_snd & 0xffffff);
1888 	DCCP_DEBUG((LOG_INFO, "dccp_connect seq_snd %llu\n", dp->seq_snd));
1889 
1890 	dccpstat.dccps_connattempt++;
1891 
1892 	sin = (struct sockaddr_in *)nam;
1893 	if (sin->sin_family == AF_INET
1894 	    && IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
1895 		error = EAFNOSUPPORT;
1896 		goto bad;
1897 	}
1898 
1899 	error = dccp_doconnect(so, nam, l, 0);
1900 
1901 	if (error != 0)
1902 		goto bad;
1903 
1904 	callout_reset(&dp->retrans_timer, dp->retrans, dccp_retrans_t, dp);
1905 	callout_reset(&dp->connect_timer, DCCP_CONNECT_TIMER, dccp_connect_t, dp);
1906 
1907 	if (dccp_do_feature_nego){
1908 		test[0] = dp->pref_cc;
1909 		dccp_add_feature(dp, DCCP_OPT_CHANGE_R, DCCP_FEATURE_CC, test, 1);
1910 	}
1911 
1912 	error = dccp_output(dp, 0);
1913 
1914 bad:
1915 	INP_UNLOCK(inp);
1916 	INP_INFO_WUNLOCK(&dccpbinfo);
1917 	return error;
1918 }
1919 
1920 static int
1921 dccp_connect2(struct socket *so, struct socket *so2)
1922 {
1923 	KASSERT(solocked(so));
1924 
1925 	return EOPNOTSUPP;
1926 }
1927 
1928 /*
1929  *
1930  *
1931  */
1932 int
1933 dccp_doconnect(struct socket *so, struct sockaddr *nam,
1934     struct lwp *l, int isipv6)
1935 {
1936 	struct inpcb *inp;
1937 #ifdef INET6
1938 	struct in6pcb *in6p;
1939 #endif
1940 	int error = 0;
1941 
1942 	DCCP_DEBUG((LOG_INFO, "Entering dccp_doconnect!\n"));
1943 
1944 #if defined(INET6)
1945 	if (isipv6) {
1946 		in6p = sotoin6pcb(so);
1947 		inp = 0;
1948 	} else
1949 #endif
1950 	{
1951 		inp = sotoinpcb(so);
1952 		in6p = 0;
1953 	}
1954 
1955 #if !defined(__NetBSD__) || !defined(INET6)
1956 	if (inp->inp_lport == 0) {
1957 #else
1958 	if (isipv6 ? in6p->in6p_lport == 0 : inp->inp_lport == 0) {
1959 #endif
1960 #ifdef INET6
1961 		if (isipv6) {
1962 			DCCP_DEBUG((LOG_INFO, "Running in6_pcbbind!\n"));
1963 			error = in6_pcbbind(in6p, NULL, l);
1964 		} else
1965 #endif /* INET6 */
1966 		{
1967 			error = in_pcbbind(inp, NULL, l);
1968 		}
1969 		if (error) {
1970 			DCCP_DEBUG((LOG_INFO, "in_pcbbind=%d\n",error));
1971 			return error;
1972 		}
1973 	}
1974 
1975 #ifdef INET6
1976 	if (isipv6) {
1977 		error = in6_pcbconnect(in6p, (struct sockaddr_in6 *)nam, l);
1978 		DCCP_DEBUG((LOG_INFO, "in6_pcbconnect=%d\n",error));
1979 	} else
1980 #endif
1981 		error = in_pcbconnect(inp, (struct sockaddr_in *)nam, l);
1982 	if (error) {
1983 		DCCP_DEBUG((LOG_INFO, "in_pcbconnect=%d\n",error));
1984 		return error;
1985 	}
1986 
1987 	soisconnecting(so);
1988 	return error;
1989 }
1990 
1991 /*
1992  * Detaches the DCCP protocol from the socket.
1993  *
1994  */
1995 int
1996 dccp_detach(struct socket *so)
1997 {
1998 	struct inpcb *inp;
1999 	struct in6pcb *in6p;
2000 	struct dccpcb *dp;
2001 
2002 	DCCP_DEBUG((LOG_INFO, "Entering dccp_detach!\n"));
2003 #ifdef INET6
2004 	if (so->so_proto->pr_domain->dom_family == AF_INET6) {
2005 		in6p = sotoin6pcb(so);
2006 		if (in6p == 0) {
2007 			return EINVAL;
2008 		}
2009 		dp = (struct dccpcb *)in6p->in6p_ppcb;
2010 	} else
2011 #endif
2012 	{
2013 		inp = sotoinpcb(so);
2014 		if (inp == 0) {
2015 			return EINVAL;
2016 		}
2017 		dp = (struct dccpcb *)inp->inp_ppcb;
2018 	}
2019 	if (! dccp_disconnect2(dp)) {
2020 		INP_UNLOCK(inp);
2021 	}
2022 	INP_INFO_WUNLOCK(&dccpbinfo);
2023 	return 0;
2024 }
2025 
2026 /*
2027  *
2028  *
2029  */
2030 int
2031 dccp_disconnect(struct socket *so)
2032 {
2033 	struct inpcb *inp;
2034 	struct in6pcb *in6p;
2035 	struct dccpcb *dp;
2036 
2037 	DCCP_DEBUG((LOG_INFO, "Entering dccp_disconnect!\n"));
2038 	INP_INFO_WLOCK(&dccpbinfo);
2039 #ifndef __NetBSD__
2040 	inp = sotoinpcb(so);
2041 	if (inp == 0) {
2042 		INP_INFO_WUNLOCK(&dccpbinfo);
2043 		return EINVAL;
2044 	}
2045 	INP_LOCK(inp);
2046 	if (inp->inp_faddr.s_addr == INADDR_ANY) {
2047 		INP_INFO_WUNLOCK(&dccpbinfo);
2048 		INP_UNLOCK(inp);
2049 		return ENOTCONN;
2050 	}
2051 
2052 	dp = (struct dccpcb *)inp->inp_ppcb;
2053 #else /* NetBSD */
2054 #ifdef INET6
2055 	if (so->so_proto->pr_domain->dom_family == AF_INET6) {
2056 		in6p = sotoin6pcb(so);
2057 		if (in6p == 0) {
2058 			INP_INFO_WUNLOCK(&dccpbinfo);
2059 			return EINVAL;
2060 		}
2061 		dp = (struct dccpcb *)in6p->in6p_ppcb;
2062 	} else
2063 #endif
2064 	{
2065 		inp = sotoinpcb(so);
2066 		if (inp == 0) {
2067 			return EINVAL;
2068 		}
2069 		dp = (struct dccpcb *)inp->inp_ppcb;
2070 	}
2071 #endif
2072 	if (!dccp_disconnect2(dp)) {
2073 		INP_UNLOCK(inp);
2074 	}
2075 	INP_INFO_WUNLOCK(&dccpbinfo);
2076 	return 0;
2077 }
2078 
2079 /*
2080  * If we have don't have a established connection
2081  * we can call dccp_close, otherwise we can just
2082  * set SS_ISDISCONNECTED and flush the receive queue.
2083  */
2084 static int
2085 dccp_disconnect2(struct dccpcb *dp)
2086 {
2087 	struct socket *so = dptosocket(dp);
2088 
2089 	DCCP_DEBUG((LOG_INFO, "Entering dccp_disconnect2!\n"));
2090 
2091 	if (dp->state < DCCPS_ESTAB) {
2092 		dccp_close(dp);
2093 		return 1;
2094 	} else {
2095 		soisdisconnecting(so);
2096 		sbflush(&so->so_rcv);
2097 		if (dp->state == DCCPS_ESTAB) {
2098 			dp->retrans = 100;
2099 			callout_reset(&dp->retrans_timer, dp->retrans,
2100 			    dccp_retrans_t, dp);
2101 			callout_reset(&dp->close_timer, DCCP_CLOSE_TIMER,
2102 			    dccp_close_t, dp);
2103 			if (dp->who == DCCP_CLIENT) {
2104 				dp->state = DCCPS_CLIENT_CLOSE;
2105 			} else {
2106 				dp->state = DCCPS_SERVER_CLOSE;
2107 			}
2108 			dccp_output(dp, 0);
2109 		}
2110 	}
2111 	return 0;
2112 }
2113 
2114 int
2115 dccp_send(struct socket *so, struct mbuf *m, struct sockaddr *addr,
2116     struct mbuf *control, struct lwp *l)
2117 {
2118 	struct inpcb	*inp;
2119 	struct dccpcb	*dp;
2120 	int		error = 0;
2121 	int		isipv6 = 0;
2122 
2123 	DCCP_DEBUG((LOG_INFO, "Entering dccp_send!\n"));
2124 	KASSERT(solocked(so));
2125 	KASSERT(m != NULL);
2126 
2127 	if (control && control->m_len) {
2128 		m_freem(control);
2129 		m_freem(m);
2130 		return EINVAL;
2131 	}
2132 
2133 #ifdef INET6
2134 	isipv6 = addr && addr->sa_family == AF_INET6;
2135 #endif
2136 
2137 #if defined(INET6)
2138 	if (so->so_proto->pr_domain->dom_family == AF_INET6) {
2139 		struct in6pcb	*in6p;
2140 		in6p = sotoin6pcb(so);
2141 		if (in6p == 0) {
2142 			error = EINVAL;
2143 			goto release;
2144 		}
2145 		dp = (struct dccpcb *)in6p->in6p_ppcb;
2146 	} else
2147 #endif
2148 	{
2149 		INP_INFO_WLOCK(&dccpbinfo);
2150 		inp = sotoinpcb(so);
2151 		if (inp == 0) {
2152 			error = EINVAL;
2153 			goto release;
2154 		}
2155 		INP_LOCK(inp);
2156 		dp = (struct dccpcb *)inp->inp_ppcb;
2157 	}
2158 	if (dp->state != DCCPS_ESTAB) {
2159 		DCCP_DEBUG((LOG_INFO, "We have no established connection!\n"));
2160 	}
2161 
2162 	if (control != NULL) {
2163 		DCCP_DEBUG((LOG_INFO, "We got a control message!\n"));
2164 		/* Are we going to use control messages??? */
2165 		if (control->m_len) {
2166 			m_freem(control);
2167 		}
2168 	}
2169 
2170 	if (sbspace(&so->so_snd) < -512) {
2171 		INP_UNLOCK(inp);
2172 		error = ENOBUFS;
2173 		goto release;
2174 	}
2175 
2176 	if (m->m_pkthdr.len > dp->d_maxseg) {
2177 		/* XXX we should calculate packet size more carefully */
2178 		INP_UNLOCK(inp);
2179 		error = EINVAL;
2180 		goto release;
2181 	}
2182 
2183 	if (dp->pktcnt >= DCCP_MAX_PKTS) {
2184 		INP_UNLOCK(inp);
2185 		error = ENOBUFS;
2186 		goto release;
2187 	}
2188 
2189 	sbappend(&so->so_snd, m);
2190 	dp->pktlen[(dp->pktlenidx + dp->pktcnt) % DCCP_MAX_PKTS] = m->m_pkthdr.len;
2191 	dp->pktcnt ++;
2192 
2193 	if (addr && dp->state == DCCPS_CLOSED) {
2194 		error = dccp_doconnect(so, addr, l, isipv6);
2195 		if (error)
2196 			goto out;
2197 	}
2198 
2199 	error = dccp_output(dp, 0);
2200 
2201 out:
2202 	INP_UNLOCK(inp);
2203 	INP_INFO_WUNLOCK(&dccpbinfo);
2204 	return error;
2205 
2206 release:
2207 	INP_INFO_WUNLOCK(&dccpbinfo);
2208 	m_freem(m);
2209 	return (error);
2210 }
2211 
2212 /*
2213  * Sets socket to SS_CANTSENDMORE
2214  */
2215 int
2216 dccp_shutdown(struct socket *so)
2217 {
2218 	struct inpcb *inp;
2219 
2220 	DCCP_DEBUG((LOG_INFO, "Entering dccp_shutdown!\n"));
2221 	INP_INFO_RLOCK(&dccpbinfo);
2222 	inp = sotoinpcb(so);
2223 	if (inp == 0) {
2224 		INP_INFO_RUNLOCK(&dccpbinfo);
2225 		return EINVAL;
2226 	}
2227 	INP_LOCK(inp);
2228 	INP_INFO_RUNLOCK(&dccpbinfo);
2229 	socantsendmore(so);
2230 	INP_UNLOCK(inp);
2231 	return 0;
2232 }
2233 
2234 static int
2235 dccp_listen(struct socket *so, struct lwp *td)
2236 {
2237 	struct inpcb *inp;
2238 	struct dccpcb *dp;
2239 	int error = 0;
2240 
2241 	DCCP_DEBUG((LOG_INFO, "Entering dccp_listen!\n"));
2242 
2243 	INP_INFO_RLOCK(&dccpbinfo);
2244 	inp = sotoinpcb(so);
2245 	if (inp == 0) {
2246 		INP_INFO_RUNLOCK(&dccpbinfo);
2247 		return EINVAL;
2248 	}
2249 	INP_LOCK(inp);
2250 	INP_INFO_RUNLOCK(&dccpbinfo);
2251 	dp = (struct dccpcb *)inp->inp_ppcb;
2252 	if (inp->inp_lport == 0)
2253 		error = in_pcbbind(inp, NULL, td);
2254 	if (error == 0) {
2255 		dp->state = DCCPS_LISTEN;
2256 		dp->who = DCCP_LISTENER;
2257 	}
2258 	INP_UNLOCK(inp);
2259 	return error;
2260 }
2261 
2262 /*
2263  * Accepts a connection (accept system call)
2264  */
2265 static int
2266 dccp_accept(struct socket *so, struct sockaddr *nam)
2267 {
2268 	struct inpcb *inp = NULL;
2269 	int error = 0;
2270 
2271 	DCCP_DEBUG((LOG_INFO, "Entering dccp_accept!\n"));
2272 
2273 	if (nam == NULL) {
2274 		return EINVAL;
2275 	}
2276 	if (so->so_state & SS_ISDISCONNECTED) {
2277 		DCCP_DEBUG((LOG_INFO, "so_state && SS_ISDISCONNECTED!, so->state = %i\n", so->so_state));
2278 		return ECONNABORTED;
2279 	}
2280 
2281 	INP_INFO_RLOCK(&dccpbinfo);
2282 	inp = sotoinpcb(so);
2283 	if (inp == 0) {
2284 		INP_INFO_RUNLOCK(&dccpbinfo);
2285 		return EINVAL;
2286 	}
2287 	INP_LOCK(inp);
2288 	INP_INFO_RUNLOCK(&dccpbinfo);
2289 	in_setpeeraddr(inp, (struct sockaddr_in *)nam);
2290 
2291 	return error;
2292 }
2293 
2294 /*
2295  * Initializes a new DCCP control block
2296  * (in_pcballoc in attach has already allocated memory for it)
2297  */
2298 struct dccpcb *
2299 dccp_newdccpcb(int family, void *aux)
2300 {
2301 	struct inpcb *inp;
2302 	struct in6pcb *in6p;
2303 	struct dccpcb	*dp;
2304 
2305 	DCCP_DEBUG((LOG_INFO, "Creating a new dccpcb!\n"));
2306 
2307 	dp = pool_get(&dccpcb_pool, PR_NOWAIT);
2308 	if (dp == NULL)
2309 		return NULL;
2310 	bzero((char *) dp, sizeof(struct dccpcb));
2311 
2312 	callout_init(&dp->connect_timer, 0);
2313 	callout_init(&dp->retrans_timer, 0);
2314 	callout_init(&dp->close_timer, 0);
2315 	callout_init(&dp->timewait_timer, 0);
2316 
2317 	dp->ndp = 0;
2318 	dp->loss_window = 1000;
2319 	dp->cslen = 0;
2320 	dp->pref_cc = DEFAULT_CCID;
2321 	dp->who = DCCP_UNDEF;
2322 	dp->seq_snd = 0;
2323 	dp->seq_rcv = 0;
2324 	dp->shortseq = 0;
2325 	dp->gsn_rcv = 281474976710656LL;
2326 	dp->optlen = 0;
2327 	if (dccp_do_feature_nego){
2328 		dp->cc_in_use[0] = -1;
2329 		dp->cc_in_use[1] = -1;
2330 	} else {
2331 		/* for compatibility with linux */
2332 		dp->cc_in_use[0] = 4;
2333 		dp->cc_in_use[1] = 4;
2334 	}
2335 	dp->av_size = 0; /* no ack vector initially */
2336 	dp->remote_ackvector = 0; /* no ack vector on remote side initially */
2337 	dp->retrans = 200;
2338 	dp->avgpsize = 0;
2339 	dp->d_maxseg = 1400;
2340 	dp->ref_pseq.hi = 0;
2341 	dp->ref_pseq.lo = 0;
2342 	dp->pktlenidx = 0;
2343 	dp->pktcnt = 0;
2344 
2345 	switch (family) {
2346 	case PF_INET:
2347 		inp = (struct inpcb *)aux;
2348 		dp->d_inpcb = inp;
2349 		inp->inp_ip.ip_ttl = ip_defttl;
2350 		inp->inp_ppcb = dp;
2351 		break;
2352 	case PF_INET6:
2353 		in6p = (struct in6pcb *)aux;
2354 		dp->d_in6pcb = in6p;
2355 		in6p->in6p_ip6.ip6_hlim = in6_selecthlim_rt(in6p);
2356 		in6p->in6p_ppcb = dp;
2357 		break;
2358 	}
2359 
2360 	if (!dccp_do_feature_nego){
2361 		dp->cc_state[0] = (*cc_sw[4].cc_send_init)(dp);
2362 		dp->cc_state[1] = (*cc_sw[4].cc_recv_init)(dp);
2363 	}
2364 
2365 	return dp;
2366 }
2367 
2368 int
2369 dccp_add_option(struct dccpcb *dp, u_int8_t opt, char *val, u_int8_t val_len)
2370 {
2371 	return dccp_add_feature_option(dp, opt, 0, val, val_len);
2372 }
2373 
2374 int
2375 dccp_add_feature_option(struct dccpcb *dp, u_int8_t opt, u_int8_t feature, char *val, u_int8_t val_len)
2376 {
2377 	int i;
2378 	DCCP_DEBUG((LOG_INFO, "Entering dccp_add_feature_option, opt = %u, val_len = %u optlen %u\n", opt, val_len, dp->optlen));
2379 
2380 	if (DCCP_MAX_OPTIONS > (dp->optlen + val_len + 2)) {
2381 		dp->options[dp->optlen] = opt;
2382 		if (opt < 32) {
2383 			dp->optlen++;
2384 		} else {
2385 			if (opt == DCCP_OPT_CONFIRM_L && val_len) {
2386 				dp->options[dp->optlen + 1] = val_len + 3;
2387 				dp->options[dp->optlen +2] = feature;
2388 				dp->optlen += 3;
2389 			} else {
2390 				dp->options[dp->optlen + 1] = val_len + 2;
2391 				dp->optlen += 2;
2392 			}
2393 
2394 			for (i = 0; i<val_len; i++) {
2395 				dp->options[dp->optlen] = val[i];
2396 				dp->optlen++;
2397 			}
2398 		}
2399 	} else {
2400 		DCCP_DEBUG((LOG_INFO, "No room for more options, optlen = %u\n", dp->optlen));
2401 		return -1;
2402 	}
2403 
2404 	return 0;
2405 }
2406 
2407 /*
2408  * Searches "options" for given option type. if found, the data is copied to buffer
2409  * and returns the data length.
2410  * Returns 0 if option type not found
2411  */
2412 int
2413 dccp_get_option(char *options, int optlen, int type, char *buffer, int buflen)
2414 {
2415 	int i, j, size;
2416 	u_int8_t t;
2417 
2418 	for (i=0; i < optlen;) {
2419 		t = options[i++];
2420 		if (t >= 32) {
2421 			size = options[i++] - 2;
2422 			if (t == type) {
2423 				if (size > buflen)
2424 					return 0;
2425 				for (j = 0; j < size; j++)
2426 					buffer[j] = options[i++];
2427 				return size;
2428 			}
2429 			i += size;
2430 		}
2431 	}
2432 	/* If we get here the options was not found */
2433 	DCCP_DEBUG((LOG_INFO, "dccp_get_option option(%d) not found\n", type));
2434 	return 0;
2435 }
2436 
2437 void
2438 dccp_parse_options(struct dccpcb *dp, char *options, int optlen)
2439 {
2440 	u_int8_t opt, size, i, j;
2441 	char val[8];
2442 
2443 	for (i = 0; i < optlen; i++) {
2444 		opt = options[i];
2445 
2446 		DCCP_DEBUG((LOG_INFO, "Parsing opt: 0x%02x\n", opt));
2447 
2448 		if (opt < 32) {
2449 			switch (opt) {
2450 			    case DCCP_OPT_PADDING:
2451 				DCCP_DEBUG((LOG_INFO, "Got DCCP_OPT_PADDING!\n"));
2452 				break;
2453 			    case DCCP_OPT_DATA_DISCARD:
2454 				DCCP_DEBUG((LOG_INFO, "Got DCCP_OPT_DATA_DISCARD!\n"));
2455 				break;
2456 			    case DCCP_OPT_SLOW_RECV:
2457 				DCCP_DEBUG((LOG_INFO, "Got DCCP_OPT_SLOW_RECV!\n"));
2458 				break;
2459 			    case DCCP_OPT_BUF_CLOSED:
2460 				DCCP_DEBUG((LOG_INFO, "Got DCCP_OPT_BUF_CLOSED!\n"));
2461 				break;
2462 			    default:
2463 				DCCP_DEBUG((LOG_INFO, "Got an unknown option, option = %u!\n", opt));
2464 			}
2465 		} else if (opt > 32 && opt < 36) {
2466 			size = options[i+ 1];
2467 			if (size < 3 || size > 10) {
2468 				DCCP_DEBUG((LOG_INFO, "Error, option size = %u\n", size));
2469 				return;
2470 			}
2471 			/* Feature negotiations are options 33 to 35 */
2472 			DCCP_DEBUG((LOG_INFO, "Got option %u, size = %u, feature = %u\n", opt, size, options[i+2]));
2473 			bcopy(options + i + 3, val, size -3);
2474 			DCCP_DEBUG((LOG_INFO, "Calling dccp_feature neg(%u, %u, options[%u + 1], %u)!\n", (u_int)dp, opt, i+ 1, (size - 3)));
2475 			dccp_feature_neg(dp, opt, options[i+2], (size -3) , val);
2476 			i += size - 1;
2477 
2478 		} else if (opt < 128) {
2479 			size = options[i+ 1];
2480 			if (size < 3 || size > 10) {
2481 				DCCP_DEBUG((LOG_INFO, "Error, option size = %u\n", size));
2482 				return;
2483 			}
2484 
2485 			switch (opt) {
2486 			    case DCCP_OPT_RECV_BUF_DROPS:
2487 					DCCP_DEBUG((LOG_INFO, "Got DCCP_OPT_RECV_BUF_DROPS, size = %u!\n", size));
2488 					for (j=2; j < size; j++) {
2489 						DCCP_DEBUG((LOG_INFO, "val[%u] = %u ", j-1, options[i+j]));
2490 					}
2491 					DCCP_DEBUG((LOG_INFO, "\n"));
2492 				break;
2493 
2494 			    case DCCP_OPT_TIMESTAMP:
2495 					DCCP_DEBUG((LOG_INFO, "Got DCCP_OPT_TIMESTAMP, size = %u\n", size));
2496 
2497 					/* Adding TimestampEcho to next outgoing */
2498 					bcopy(options + i + 2, val, 4);
2499 					bzero(val + 4, 4);
2500 					dccp_add_option(dp, DCCP_OPT_TIMESTAMP_ECHO, val, 8);
2501 				break;
2502 
2503 			    case DCCP_OPT_TIMESTAMP_ECHO:
2504 					DCCP_DEBUG((LOG_INFO, "Got DCCP_OPT_TIMESTAMP_ECHO, size = %u\n",size));
2505 					for (j=2; j < size; j++) {
2506 						DCCP_DEBUG((LOG_INFO, "val[%u] = %u ", j-1, options[i+j]));
2507 					}
2508 					DCCP_DEBUG((LOG_INFO, "\n"));
2509 
2510 					/*
2511 						bcopy(options + i + 2, &(dp->timestamp_echo), 4);
2512 						bcopy(options + i + 6, &(dp->timestamp_elapsed), 4);
2513 						ACK_DEBUG((LOG_INFO, "DATA; echo = %u , elapsed = %u\n",
2514 						   dp->timestamp_echo, dp->timestamp_elapsed));
2515 					*/
2516 
2517 				break;
2518 
2519 			case DCCP_OPT_ACK_VECTOR0:
2520 			case DCCP_OPT_ACK_VECTOR1:
2521 			case DCCP_OPT_ELAPSEDTIME:
2522 				/* Dont do nothing here. Let the CC deal with it */
2523 				break;
2524 
2525 			default:
2526 				DCCP_DEBUG((LOG_INFO, "Got an unknown option, option = %u, size = %u!\n", opt, size));
2527 				break;
2528 
2529 			}
2530 			i += size - 1;
2531 
2532 		} else {
2533 			DCCP_DEBUG((LOG_INFO, "Got a CCID option (%d), do nothing!\n", opt));
2534 			size = options[i+ 1];
2535 			if (size < 3 || size > 10) {
2536 				DCCP_DEBUG((LOG_INFO, "Error, option size = %u\n", size));
2537 				return;
2538 			}
2539 			i += size - 1;
2540 		}
2541 	}
2542 
2543 }
2544 
2545 int
2546 dccp_add_feature(struct dccpcb *dp, u_int8_t opt, u_int8_t feature, char *val, u_int8_t val_len)
2547 {
2548 	int i;
2549 	DCCP_DEBUG((LOG_INFO, "Entering dccp_add_feature, opt = %u, feature = %u, val_len = %u\n", opt, feature, val_len));
2550 
2551 	if (DCCP_MAX_OPTIONS > (dp->featlen + val_len + 3)) {
2552 		dp->features[dp->featlen] = opt;
2553 		dp->features[dp->featlen + 1] = val_len + 3;
2554 		dp->features[dp->featlen +2] = feature;
2555 		dp->featlen += 3;
2556 		for (i = 0; i<val_len; i++) {
2557 			dp->features[dp->featlen] = val[i];
2558 			dp->featlen++;
2559 		}
2560 	} else {
2561 		DCCP_DEBUG((LOG_INFO, "No room for more features, featlen = %u\n", dp->featlen));
2562 		return -1;
2563 	}
2564 
2565 	return 0;
2566 }
2567 
2568 int
2569 dccp_remove_feature(struct dccpcb *dp, u_int8_t opt, u_int8_t feature)
2570 {
2571 	int i = 0, j = 0, k;
2572 	u_int8_t t_opt, t_feature, len;
2573 	DCCP_DEBUG((LOG_INFO, "Entering dccp_remove_feature, featlen = %u, opt = %u, feature = %u\n", dp->featlen, opt, feature));
2574 
2575 	while (i < dp->featlen) {
2576 		t_opt = dp->features[i];
2577 		len = dp->features[i+ 1];
2578 
2579 		if (i + len > dp->featlen) {
2580 			DCCP_DEBUG((LOG_INFO, "Error, len = %u and i(%u) + len > dp->featlen (%u)\n", len, i, dp->featlen));
2581 			return 1;
2582 		}
2583 		t_feature = dp->features[i+2];
2584 
2585 		if (t_opt == opt && t_feature == feature) {
2586 			i += len;
2587 		} else {
2588 			if (i != j) {
2589 				for (k = 0; k < len; k++) {
2590 					dp->features[j+k] = dp->features[i+k];
2591 				}
2592 			}
2593 			i += len;
2594 			j += len;
2595 		}
2596 	}
2597 	dp->featlen = j;
2598 	DCCP_DEBUG((LOG_INFO, "Exiting dccp_remove_feature, featlen = %u\n", dp->featlen));
2599 	return 0;
2600 }
2601 
2602 void
2603 dccp_feature_neg(struct dccpcb *dp, u_int8_t opt, u_int8_t feature, u_int8_t val_len, char *val)
2604 {
2605 	DCCP_DEBUG((LOG_INFO, "Running dccp_feature_neg, opt = %u, feature = %u len = %u ", opt, feature, val_len));
2606 
2607 	switch (feature) {
2608 		case DCCP_FEATURE_CC:
2609 			DCCP_DEBUG((LOG_INFO, "Got CCID negotiation, opt = %u, val[0] = %u\n", opt, val[0]));
2610 			if (opt == DCCP_OPT_CHANGE_R) {
2611 				if (val[0] == 2 || val[0] == 3 || val[0] == 0) {
2612 					/* try to use preferable CCID */
2613 					int i;
2614 					for (i = 1; i < val_len; i ++) if (val[i] == dp->pref_cc) val[0] = dp->pref_cc;
2615 					DCCP_DEBUG((LOG_INFO, "Sending DCCP_OPT_CONFIRM_L on CCID %u\n", val[0]));
2616 					dccp_remove_feature(dp, DCCP_OPT_CONFIRM_L, DCCP_FEATURE_CC);
2617 					dccp_add_feature_option(dp, DCCP_OPT_CONFIRM_L, DCCP_FEATURE_CC , val, 1);
2618 					if (dp->cc_in_use[0] < 1) {
2619 						dp->cc_state[0] = (*cc_sw[val[0] + 1].cc_send_init)(dp);
2620 						dp->cc_in_use[0] = val[0] + 1;
2621 					} else {
2622 						DCCP_DEBUG((LOG_INFO, "We already have negotiated a CC!!!\n"));
2623 					}
2624 				}
2625 			} else if (opt == DCCP_OPT_CONFIRM_L) {
2626 				DCCP_DEBUG((LOG_INFO, "Got DCCP_OPT_CONFIRM_L on CCID %u\n", val[0]));
2627 				dccp_remove_feature(dp, DCCP_OPT_CHANGE_R, DCCP_FEATURE_CC);
2628 				if (dp->cc_in_use[1] < 1) {
2629 					dp->cc_state[1] = (*cc_sw[val[0] + 1].cc_recv_init)(dp);
2630 					dp->cc_in_use[1] = val[0] + 1;
2631 					DCCP_DEBUG((LOG_INFO, "confirmed cc_in_use[1] = %d\n", dp->cc_in_use[1]));
2632 				} else {
2633 					DCCP_DEBUG((LOG_INFO, "We already have negotiated a CC!!! (confirm) %d\n", dp->cc_in_use[1]));
2634 				}
2635 			}
2636 
2637 		break;
2638 
2639 		case DCCP_FEATURE_ACKVECTOR:
2640 			ACK_DEBUG((LOG_INFO, "Got _Use Ack Vector_\n"));
2641 			if (opt == DCCP_OPT_CHANGE_R) {
2642 				if (val[0] == 1) {
2643 					dccp_use_ackvector(dp);
2644 					dccp_remove_feature(dp, DCCP_OPT_CONFIRM_L, DCCP_FEATURE_ACKVECTOR);
2645 					dccp_add_feature_option(dp, DCCP_OPT_CONFIRM_L, DCCP_FEATURE_ACKVECTOR , val, 1);
2646 				} else {
2647 					ACK_DEBUG((LOG_INFO, "ERROR. Strange val %u\n", val[0]));
2648 				}
2649 			} else if (opt == DCCP_OPT_CONFIRM_L) {
2650 					dccp_remove_feature(dp, DCCP_OPT_CONFIRM_L, DCCP_FEATURE_ACKVECTOR);
2651 			if (val[0] == 1) {
2652 					dp->remote_ackvector = 1;
2653 					ACK_DEBUG((LOG_INFO,"Remote side confirmed AckVector usage\n"));
2654 				} else {
2655 					ACK_DEBUG((LOG_INFO, "ERROR. Strange val %u\n", val[0]));
2656 				}
2657 			}
2658 			break;
2659 
2660 		case DCCP_FEATURE_ACKRATIO:
2661 			if (opt == DCCP_OPT_CHANGE_R) {
2662 				bcopy(val , &(dp->ack_ratio), 1);
2663 				ACK_DEBUG((LOG_INFO, "Feature: Change Ack Ratio to %u\n", dp->ack_ratio));
2664 			}
2665 			break;
2666 
2667 		case DCCP_FEATURE_ECN:
2668 		case DCCP_FEATURE_MOBILITY:
2669 		default:
2670 			/* we should send back empty CONFIRM_L for unknown feature unless it's not mandatory */
2671 			dccp_add_option(dp, DCCP_OPT_CONFIRM_L, NULL, 0);
2672 		break;
2673 
2674 	}
2675 }
2676 
2677 #ifdef __FreeBSD__
2678 static int
2679 dccp_pcblist(SYSCTL_HANDLER_ARGS)
2680 {
2681 
2682 	int error, i, n, s;
2683 	struct inpcb *inp, **inp_list;
2684 	inp_gen_t gencnt;
2685 	struct xinpgen xig;
2686 
2687 	/*
2688 	 * The process of preparing the TCB list is too time-consuming and
2689 	 * resource-intensive to repeat twice on every request.
2690 	 */
2691 	if (req->oldptr == 0) {
2692 		n = dccpbinfo.ipi_count;
2693 		req->oldidx = 2 * (sizeof xig)
2694 			+ (n + n/8) * sizeof(struct xdccpcb);
2695 		return 0;
2696 	}
2697 
2698 
2699 	if (req->newptr != 0)
2700 		return EPERM;
2701 
2702 
2703 	/*
2704 	 * OK, now we're committed to doing something.
2705 	 */
2706 	s = splnet();
2707 	gencnt = dccpbinfo.ipi_gencnt;
2708 	n = dccpbinfo.ipi_count;
2709 	splx(s);
2710 
2711 #if __FreeBSD_version >= 500000
2712 	sysctl_wire_old_buffer(req, 2 * (sizeof xig)
2713 		+ n * sizeof(struct xdccpcb));
2714 #endif
2715 
2716 	xig.xig_len = sizeof xig;
2717 	xig.xig_count = n;
2718 	xig.xig_gen = gencnt;
2719 	xig.xig_sogen = so_gencnt;
2720 	error = SYSCTL_OUT(req, &xig, sizeof xig);
2721 	if (error)
2722 		return error;
2723 
2724 	inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK);
2725 	if (inp_list == 0)
2726 		return ENOMEM;
2727 
2728 	s = splsoftnet();
2729 	INP_INFO_RLOCK(&dccpbinfo);
2730 
2731 	for (inp = LIST_FIRST(dccpbinfo.listhead), i = 0; inp && i < n;
2732 	     inp = LIST_NEXT(inp, inp_list)) {
2733 		INP_LOCK(inp);
2734 		if (inp->inp_gencnt <= gencnt &&
2735 #if __FreeBSD_version >= 500000
2736 		    cr_canseesocket(req->td->td_ucred, inp->inp_socket) == 0)
2737 #else
2738 		    !prison_xinpcb(req->p, inp))
2739 #endif
2740 			inp_list[i++] = inp;
2741 		INP_UNLOCK(inp);
2742 	}
2743 	INP_INFO_RUNLOCK(&dccpbinfo);
2744 	splx(s);
2745 	n = i;
2746 
2747 	error = 0;
2748 	for (i = 0; i < n; i++) {
2749 		inp = inp_list[i];
2750 		INP_LOCK(inp);
2751 
2752 		if (inp->inp_gencnt <= gencnt) {
2753 			struct xdccpcb xd;
2754 			vaddr_t inp_ppcb;
2755 			xd.xd_len = sizeof xd;
2756 			/* XXX should avoid extra copy */
2757 			bcopy(inp, &xd.xd_inp, sizeof *inp);
2758 			inp_ppcb = inp->inp_ppcb;
2759 			if (inp_ppcb != NULL)
2760 				bcopy(inp_ppcb, &xd.xd_dp, sizeof xd.xd_dp);
2761 			else
2762 				bzero((char *) &xd.xd_dp, sizeof xd.xd_dp);
2763 			if (inp->inp_socket)
2764 				 sotoxsocket(inp->inp_socket, &xd.xd_socket);
2765 			error = SYSCTL_OUT(req, &xd, sizeof xd);
2766 		}
2767 		INP_UNLOCK(inp);
2768 	}
2769 	if (!error) {
2770 		/*
2771 		 * Give the user an updated idea of our state.
2772 		 * If the generation differs from what we told
2773 		 * her before, she knows that something happened
2774 		 * while we were processing this request, and it
2775 		 * might be necessary to retry.
2776 		 */
2777 		s = splnet();
2778 		INP_INFO_RLOCK(&dccpbinfo);
2779 		xig.xig_gen = dccpbinfo.ipi_gencnt;
2780 		xig.xig_sogen = so_gencnt;
2781 		xig.xig_count = dccpbinfo.ipi_count;
2782 
2783 
2784 		INP_INFO_RUNLOCK(&dccpbinfo);
2785 		splx(s);
2786 		error = SYSCTL_OUT(req, &xig, sizeof xig);
2787 	}
2788 	free(inp_list, M_TEMP);
2789 	return error;
2790 }
2791 #endif
2792 
2793 #ifdef __FreeBSD__
2794 SYSCTL_PROC(_net_inet_dccp, DCCPCTL_PCBLIST, pcblist, CTLFLAG_RD, 0, 0,
2795     dccp_pcblist, "S,xdccpcb", "List of active DCCP sockets");
2796 #endif
2797 
2798 void
2799 dccp_timewait_t(void *dcb)
2800 {
2801 	struct dccpcb *dp = dcb;
2802 
2803 	DCCP_DEBUG((LOG_INFO, "Entering dccp_timewait_t!\n"));
2804 	mutex_enter(softnet_lock);
2805 	INP_INFO_WLOCK(&dccpbinfo);
2806 	INP_LOCK(dp->d_inpcb);
2807 	dccp_close(dp);
2808 	INP_INFO_WUNLOCK(&dccpbinfo);
2809 	mutex_exit(softnet_lock);
2810 }
2811 
2812 void
2813 dccp_connect_t(void *dcb)
2814 {
2815 	struct dccpcb *dp = dcb;
2816 
2817 	DCCP_DEBUG((LOG_INFO, "Entering dccp_connect_t!\n"));
2818 	mutex_enter(softnet_lock);
2819 	INP_INFO_WLOCK(&dccpbinfo);
2820 	INP_LOCK(dp->d_inpcb);
2821 	dccp_close(dp);
2822 	INP_INFO_WUNLOCK(&dccpbinfo);
2823 	mutex_exit(softnet_lock);
2824 }
2825 
2826 void
2827 dccp_close_t(void *dcb)
2828 {
2829 	struct dccpcb *dp = dcb;
2830 
2831 	DCCP_DEBUG((LOG_INFO, "Entering dccp_close_t!\n"));
2832 	mutex_enter(softnet_lock);
2833 	INP_INFO_WLOCK(&dccpbinfo);
2834 	dp->state = DCCPS_TIME_WAIT; /* HMM */
2835 	if (dp->who == DCCP_SERVER) {
2836 		INP_LOCK(dp->d_inpcb);
2837 		KERNEL_LOCK(1, NULL);
2838 		dccp_output(dp, DCCP_TYPE_RESET + 2);
2839 		KERNEL_UNLOCK_ONE(NULL);
2840 		dccp_close(dp);
2841 	} else {
2842 		INP_LOCK(dp->d_inpcb);
2843 		dccp_output(dp, DCCP_TYPE_RESET + 2);
2844 		/*dp->state = DCCPS_TIME_WAIT; */
2845 		callout_reset(&dp->timewait_timer, DCCP_TIMEWAIT_TIMER,
2846 		    dccp_timewait_t, dp);
2847 		INP_UNLOCK(dp->d_inpcb);
2848 	}
2849 	INP_INFO_WUNLOCK(&dccpbinfo);
2850 	mutex_exit(softnet_lock);
2851 }
2852 
2853 void
2854 dccp_retrans_t(void *dcb)
2855 {
2856 	struct dccpcb *dp = dcb;
2857 	/*struct inpcb *inp;*/
2858 
2859 	DCCP_DEBUG((LOG_INFO, "Entering dccp_retrans_t!\n"));
2860 	mutex_enter(softnet_lock);
2861 	INP_INFO_RLOCK(&dccpbinfo);
2862 	/*inp = dp->d_inpcb;*/
2863 	INP_LOCK(inp);
2864 	INP_INFO_RUNLOCK(&dccpbinfo);
2865 	callout_stop(&dp->retrans_timer);
2866 	KERNEL_LOCK(1, NULL);
2867 	dccp_output(dp, 0);
2868 	KERNEL_UNLOCK_ONE(NULL);
2869 	dp->retrans = dp->retrans * 2;
2870 	callout_reset(&dp->retrans_timer, dp->retrans, dccp_retrans_t, dp);
2871 	INP_UNLOCK(inp);
2872 	mutex_exit(softnet_lock);
2873 }
2874 
2875 static int
2876 dccp_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp)
2877 {
2878 	int error = 0;
2879 	int family;
2880 
2881 	family = so->so_proto->pr_domain->dom_family;
2882 	switch (family) {
2883 	case PF_INET:
2884 		error = in_control(so, cmd, nam, ifp);
2885 		break;
2886 #ifdef INET6
2887 	case PF_INET6:
2888 		error = in6_control(so, cmd, nam, ifp);
2889 		break;
2890 #endif
2891 	default:
2892 		error =	 EAFNOSUPPORT;
2893 	}
2894 	return (error);
2895 }
2896 
2897 static int
2898 dccp_stat(struct socket *so, struct stat *ub)
2899 {
2900 	return 0;
2901 }
2902 
2903 static int
2904 dccp_peeraddr(struct socket *so, struct sockaddr *nam)
2905 {
2906 
2907 	KASSERT(solocked(so));
2908 	KASSERT(sotoinpcb(so) != NULL);
2909 	KASSERT(nam != NULL);
2910 
2911 	in_setpeeraddr(sotoinpcb(so), (struct sockaddr_in *)nam);
2912 	return 0;
2913 }
2914 
2915 static int
2916 dccp_sockaddr(struct socket *so, struct sockaddr *nam)
2917 {
2918 
2919 	KASSERT(solocked(so));
2920 	KASSERT(sotoinpcb(so) != NULL);
2921 	KASSERT(nam != NULL);
2922 
2923 	in_setsockaddr(sotoinpcb(so), (struct sockaddr_in *)nam);
2924 	return 0;
2925 }
2926 
2927 static int
2928 dccp_rcvd(struct socket *so, int flags, struct lwp *l)
2929 {
2930 	KASSERT(solocked(so));
2931 
2932 	return EOPNOTSUPP;
2933 }
2934 
2935 static int
2936 dccp_recvoob(struct socket *so, struct mbuf *m, int flags)
2937 {
2938 	KASSERT(solocked(so));
2939 
2940 	return EOPNOTSUPP;
2941 }
2942 
2943 static int
2944 dccp_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control)
2945 {
2946 	KASSERT(solocked(so));
2947 
2948 	m_freem(m);
2949 	m_freem(control);
2950 
2951 	return EOPNOTSUPP;
2952 }
2953 
2954 static int
2955 dccp_purgeif(struct socket *so, struct ifnet *ifp)
2956 {
2957 	int s;
2958 
2959 	s = splsoftnet();
2960 	mutex_enter(softnet_lock);
2961 	in_pcbpurgeif0(&dccpbtable, ifp);
2962 	in_purgeif(ifp);
2963 	in_pcbpurgeif(&dccpbtable, ifp);
2964 	mutex_exit(softnet_lock);
2965 	splx(s);
2966 
2967 	return 0;
2968 }
2969 
2970 /****** Ack Vector functions *********/
2971 
2972 /**
2973  * Initialize and allocate mem for Ack Vector
2974  **/
2975 void
2976 dccp_use_ackvector(struct dccpcb *dp)
2977 {
2978 	DCCP_DEBUG((LOG_INFO,"Initializing AckVector\n"));
2979 	if (dp->ackvector != 0) {
2980 		DCCP_DEBUG((LOG_INFO, "It was already initialized!!!\n"));
2981 		return;
2982 	}
2983 	dp->av_size = DCCP_VECTORSIZE;
2984 	/* need 2 bits per entry */
2985 	dp->ackvector = malloc(dp->av_size/4, M_PCB, M_NOWAIT | M_ZERO);
2986 	if (dp->ackvector == 0) {
2987 		DCCP_DEBUG((LOG_INFO, "Unable to allocate memory for ackvector\n"));
2988 		/* What to do now? */
2989 		dp->av_size = 0;
2990 		return;
2991 	}
2992 	memset(dp->ackvector, 0xff, dp->av_size/4);
2993 	dp->av_hs = dp->av_ts = 0;
2994 	dp->av_hp = dp->ackvector;
2995 }
2996 
2997 /**
2998  * Set 'seqnr' as the new head in ackvector
2999  **/
3000 void
3001 dccp_update_ackvector(struct dccpcb *dp, u_int64_t seqnr)
3002 {
3003 	int64_t gap;
3004 	u_char *t;
3005 
3006 	/* Ignore wrapping for now */
3007 
3008 	ACK_DEBUG((LOG_INFO,"New head in ackvector: %u\n", seqnr));
3009 
3010 	if (dp->av_size == 0) {
3011 		ACK_DEBUG((LOG_INFO, "Update: AckVector NOT YET INITIALIZED!!!\n"));
3012 		dccp_use_ackvector(dp);
3013 	}
3014 
3015 	if (seqnr > dp->av_hs) {
3016 		gap = seqnr - dp->av_hs;
3017 	} else {
3018 		/* We received obsolete information */
3019 		return;
3020 	}
3021 
3022 	t = dp->av_hp + (gap/4);
3023 	if (t >= (dp->ackvector + (dp->av_size/4)))
3024 		t -= (dp->av_size / 4); /* ackvector wrapped */
3025 	dp->av_hp = t;
3026 	dp->av_hs = seqnr;
3027 }
3028 
3029 /**
3030  * We've received a packet. store in local av so it's included in
3031  * next Ack Vector sent
3032  **/
3033 void
3034 dccp_increment_ackvector(struct dccpcb *dp, u_int64_t seqnr)
3035 {
3036 	u_int64_t offset, dc;
3037 	int64_t gap;
3038 	u_char *t, *n;
3039 
3040 	DCCP_DEBUG((LOG_INFO, "Entering dccp_increment_ackvecktor %d\n", dp->av_size));
3041 	if (dp->av_size == 0) {
3042 		DCCP_DEBUG((LOG_INFO, "Increment: AckVector NOT YET INITIALIZED!!!\n"));
3043 		dccp_use_ackvector(dp);
3044 	}
3045 
3046 	if (dp->av_hs == dp->av_ts) {
3047 		/* Empty ack vector */
3048 		dp->av_hs = dp->av_ts = seqnr;
3049 	}
3050 
3051 	/* Check for wrapping */
3052 	if (seqnr >= dp->av_hs) {
3053 		/* Not wrapped */
3054 		gap = seqnr - dp->av_hs;
3055 	} else {
3056 		/* Wrapped */
3057 		gap = seqnr + 0x1000000000000LL - dp->av_hs; /* seqnr = 48 bits */
3058 	}
3059 	DCCP_DEBUG((LOG_INFO, "dccp_increment_ackvecktor gap=%llu av_size %d\n", gap, dp->av_size));
3060 
3061 	if (gap >= dp->av_size) {
3062 		/* gap is bigger than ackvector size? baaad */
3063 		/* maybe we should increase the ackvector here */
3064 		DCCP_DEBUG((LOG_INFO, "increment_ackvector error. gap: %llu, av_size: %d, seqnr: %d\n",
3065 			    gap, dp->av_size, seqnr));
3066 		return;
3067 	}
3068 
3069 	offset = gap % 4; /* hi or low 2 bits to mark */
3070 	t = dp->av_hp + (gap/4);
3071 	if (t >= (dp->ackvector + (dp->av_size/4)))
3072 		t -= (dp->av_size / 4); /* ackvector wrapped */
3073 
3074 	*t = *t & (~(0x03 << (offset *2))); /* turn off bits, 00 is rcvd, 11 is missing */
3075 
3076 	dp->av_ts = seqnr + 1;
3077 	if (dp->av_ts == 0x1000000000000LL)
3078 		dp->av_ts = 0;
3079 
3080 	if (gap > (dp->av_size - 128)) {
3081 		n = malloc(dp->av_size/2, M_PCB, M_NOWAIT | M_ZERO); /* old size * 2 */
3082 		memset (n + dp->av_size / 4, 0xff, dp->av_size / 4); /* new half all missing */
3083 		dc = (dp->ackvector + (dp->av_size/4)) - dp->av_hp;
3084 		memcpy (n, dp->av_hp, dc); /* tail to end */
3085 		memcpy (n+dc, dp->ackvector, dp->av_hp - dp->ackvector); /* start to tail */
3086 		dp->av_size = dp->av_size * 2; /* counted in items, so it';s a doubling */
3087 		free (dp->ackvector, M_PCB);
3088 		dp->av_hp = dp->ackvector = n;
3089 	}
3090 }
3091 
3092 /**
3093  * Generates the ack vector to send in outgoing packet.
3094  * These are backwards (first packet in ack vector is packet indicated by Ack Number,
3095  * subsequent are older packets).
3096  **/
3097 
3098 u_int16_t
3099 dccp_generate_ackvector(struct dccpcb *dp, u_char *buf)
3100 {
3101 	int64_t j;
3102 	u_int64_t i;
3103 	u_int16_t cnt, oldlen, bufsize;
3104 	u_char oldstate, st;
3105 
3106 	bufsize = 16;
3107 	cnt = 0;
3108 
3109 	oldstate = 0x04; /* bad value */
3110 	oldlen = 0;
3111 
3112 	if (dp->av_size == 0) {
3113 		ACK_DEBUG((LOG_INFO, "Generate: AckVector NOT YET INITIALIZED!!!\n"));
3114 		return 0;
3115 	}
3116 
3117 	if (dp->seq_rcv > dp->av_ts) {
3118 		/* AckNum is beyond our av-list , so we'll start with some
3119 		 * 0x3 (Packet not yet received) */
3120 		j = dp->seq_rcv - dp->av_ts -1;
3121 		do {
3122 			/* state | length */
3123 			oldstate = 0x03;
3124 			if (j > 63)
3125 				oldlen = 63;
3126 			else
3127 				oldlen = j;
3128 
3129 			buf[cnt] = (0x03 << 6) | oldlen;
3130 			cnt++;
3131 			if (cnt == bufsize) {
3132 				/* I've skipped the realloc bshit */
3133 				/* PANIC */
3134 			}
3135 			j-=63;
3136 		} while (j > 0);
3137 	}
3138 
3139 	/* Ok now we're at dp->av_ts (unless AckNum is lower) */
3140 	i = (dp->seq_rcv < dp->av_ts) ? dp->seq_rcv : dp->av_ts;
3141 	st = dccp_ackvector_state(dp, i);
3142 
3143 	if (st == oldstate) {
3144 		cnt--;
3145 		oldlen++;
3146 	} else {
3147 		oldlen = 0;
3148 		oldstate = st;
3149 	}
3150 
3151 	if (dp->av_ts > dp->av_hs) {
3152 		do {
3153 			i--;
3154 			st = dccp_ackvector_state(dp, i);
3155 			if (st == oldstate && oldlen < 64) {
3156 				oldlen++;
3157 			} else {
3158 				buf[cnt] = (oldstate << 6) | (oldlen & 0x3f);
3159 				cnt++;
3160 				oldlen = 0;
3161 				oldstate = st;
3162 				if (cnt == bufsize) {
3163 					/* PANIC */
3164 				}
3165 			}
3166 
3167 		} while (i > dp->av_hs);
3168 	} else {
3169 		/* It's wrapped */
3170 		do {
3171 			i--;
3172 			st = dccp_ackvector_state(dp, i);
3173 			if (st == oldstate && oldlen < 64) {
3174 				oldlen++;
3175 			} else {
3176 				buf[cnt] = (oldstate << 6) | (oldlen & 0x3f);
3177 				cnt++;
3178 				oldlen = 0;
3179 				oldstate = st;
3180 				if (cnt == bufsize) {
3181 					/* PANIC */
3182 				}
3183 			}
3184 
3185 		} while (i > 0);
3186 		i = 0x1000000;
3187 		do {
3188 			i--;
3189 			st = dccp_ackvector_state(dp, i);
3190 			if (st == oldstate && oldlen < 64) {
3191 				oldlen++;
3192 			} else {
3193 				buf[cnt] = (oldstate << 6) | (oldlen & 0x3f);
3194 				cnt++;
3195 				oldlen = 0;
3196 				oldstate = st;
3197 				if (cnt == bufsize) {
3198 					/* PANIC */
3199 				}
3200 			}
3201 		} while (i > dp->av_hs);
3202 	}
3203 
3204 	/* add the last one */
3205 	buf[cnt] = (oldstate << 6) | (oldlen & 0x3f);
3206 	cnt++;
3207 
3208 	return cnt;
3209 }
3210 
3211 u_char
3212 dccp_ackvector_state(struct dccpcb *dp, u_int64_t seqnr)
3213 {
3214 	u_int64_t gap, offset;
3215 	u_char *t;
3216 
3217 	/* Check for wrapping */
3218 	if (seqnr >= dp->av_hs) {
3219 		/* Not wrapped */
3220 		gap = seqnr - dp->av_hs;
3221 	} else {
3222 		/* Wrapped */
3223 		gap = seqnr + 0x1000000000000LL - dp->av_hs; /* seq nr = 48 bits */
3224 	}
3225 
3226 	if (gap >= dp->av_size) {
3227 		/* gap is bigger than ackvector size? baaad */
3228 		return 0x03;
3229 	}
3230 
3231 	offset = gap % 4 *2;
3232 	t = dp->av_hp + (gap/4);
3233 	if (t >= (dp->ackvector + (dp->av_size/4)))
3234 		t -= (dp->av_size / 4); /* wrapped */
3235 
3236 	return ((*t & (0x03 << offset)) >> offset);
3237 }
3238 
3239 /****** End of Ack Vector functions *********/
3240 
3241 /* No cc functions */
3242 void *
3243 dccp_nocc_init(struct dccpcb *pcb)
3244 {
3245   return (void*) 1;
3246 }
3247 
3248 void
3249 dccp_nocc_free(void *ccb)
3250 {
3251 }
3252 
3253 int
3254 dccp_nocc_send_packet(void *ccb, long size)
3255 {
3256   return 1;
3257 }
3258 
3259 void
3260 dccp_nocc_send_packet_sent(void *ccb, int moreToSend, long size)
3261 {
3262 }
3263 
3264 void
3265 dccp_nocc_packet_recv(void *ccb, char* options ,int optlen)
3266 {
3267 }
3268 
3269 void
3270 dccp_log(int level, const char *format, ...)
3271 {
3272 	va_list ap;
3273 
3274 	va_start(ap, format);
3275 	vprintf(format,  ap);
3276 	va_end(ap);
3277 	return;
3278 }
3279 
3280 /*
3281  * Sysctl for dccp variables.
3282  */
3283 SYSCTL_SETUP(sysctl_net_inet_dccp_setup, "sysctl net.inet.dccp subtree setup")
3284 {
3285 
3286 	sysctl_createv(clog, 0, NULL, NULL,
3287 		CTLFLAG_PERMANENT,
3288 		CTLTYPE_NODE, "net", NULL,
3289 		NULL, 0, NULL, 0,
3290 		CTL_NET, CTL_EOL);
3291 
3292 	sysctl_createv(clog, 0, NULL, NULL,
3293 		CTLFLAG_PERMANENT,
3294 		CTLTYPE_NODE, "inet", NULL,
3295 		NULL, 0, NULL, 0,
3296 		CTL_NET, PF_INET, CTL_EOL);
3297 
3298 	sysctl_createv(clog, 0, NULL, NULL,
3299 		CTLFLAG_PERMANENT,
3300 		CTLTYPE_NODE, "dccp",
3301 		SYSCTL_DESCR("DCCPv4 related settings"),
3302 		NULL, 0, NULL, 0,
3303 		CTL_NET, PF_INET, IPPROTO_DCCP, CTL_EOL);
3304 
3305 	sysctl_createv(clog, 0, NULL, NULL,
3306 		CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
3307 		CTLTYPE_INT, "dccp_log_in_vain",
3308 		SYSCTL_DESCR("log all connection attempt"),
3309 		NULL, 0, &dccp_log_in_vain, 0,
3310 		CTL_NET, PF_INET, IPPROTO_DCCP, DCCPCTL_LOGINVAIN,
3311 		CTL_EOL);
3312 
3313 	sysctl_createv(clog, 0, NULL, NULL,
3314 		CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
3315 		CTLTYPE_INT, "do_feature_nego",
3316 		SYSCTL_DESCR("enable feature negotiation"),
3317 		NULL, 0, &dccp_do_feature_nego, 0,
3318 		CTL_NET, PF_INET, IPPROTO_DCCP, DCCPCTL_DOFEATURENEGO,
3319 		CTL_EOL);
3320 }
3321 
3322 PR_WRAP_USRREQS(dccp)
3323 #define	dccp_attach	dccp_attach_wrapper
3324 #define	dccp_detach	dccp_detach_wrapper
3325 #define dccp_accept	dccp_accept_wrapper
3326 #define	dccp_bind	dccp_bind_wrapper
3327 #define	dccp_listen	dccp_listen_wrapper
3328 #define	dccp_connect	dccp_connect_wrapper
3329 #define	dccp_connect2	dccp_connect2_wrapper
3330 #define	dccp_disconnect	dccp_disconnect_wrapper
3331 #define	dccp_shutdown	dccp_shutdown_wrapper
3332 #define	dccp_abort	dccp_abort_wrapper
3333 #define	dccp_ioctl	dccp_ioctl_wrapper
3334 #define	dccp_stat	dccp_stat_wrapper
3335 #define	dccp_peeraddr	dccp_peeraddr_wrapper
3336 #define	dccp_sockaddr	dccp_sockaddr_wrapper
3337 #define	dccp_rcvd	dccp_rcvd_wrapper
3338 #define	dccp_recvoob	dccp_recvoob_wrapper
3339 #define	dccp_send	dccp_send_wrapper
3340 #define	dccp_sendoob	dccp_sendoob_wrapper
3341 #define	dccp_purgeif	dccp_purgeif_wrapper
3342 
3343 const struct pr_usrreqs dccp_usrreqs = {
3344 	.pr_attach	= dccp_attach,
3345 	.pr_detach	= dccp_detach,
3346 	.pr_accept	= dccp_accept,
3347 	.pr_bind	= dccp_bind,
3348 	.pr_listen	= dccp_listen,
3349 	.pr_connect	= dccp_connect,
3350 	.pr_connect2	= dccp_connect2,
3351 	.pr_disconnect	= dccp_disconnect,
3352 	.pr_shutdown	= dccp_shutdown,
3353 	.pr_abort	= dccp_abort,
3354 	.pr_ioctl	= dccp_ioctl,
3355 	.pr_stat	= dccp_stat,
3356 	.pr_peeraddr	= dccp_peeraddr,
3357 	.pr_sockaddr	= dccp_sockaddr,
3358 	.pr_rcvd	= dccp_rcvd,
3359 	.pr_recvoob	= dccp_recvoob,
3360 	.pr_send	= dccp_send,
3361 	.pr_sendoob	= dccp_sendoob,
3362 	.pr_purgeif	= dccp_purgeif,
3363 };
3364