xref: /netbsd-src/sys/netinet/dccp_usrreq.c (revision f89f6560d453f5e37386cc7938c072d2f528b9fa)
1 /*	$KAME: dccp_usrreq.c,v 1.67 2005/11/03 16:05:04 nishida Exp $	*/
2 /*	$NetBSD: dccp_usrreq.c,v 1.2 2015/04/04 04:33:38 rtr 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.2 2015/04/04 04:33:38 rtr Exp $");
71 
72 #include "opt_inet.h"
73 #include "opt_dccp.h"
74 
75 #include <sys/param.h>
76 #include <sys/systm.h>
77 #include <sys/domain.h>
78 #include <sys/kernel.h>
79 #include <sys/pool.h>
80 #include <sys/lock.h>
81 #include <sys/malloc.h>
82 #include <sys/mbuf.h>
83 #include <sys/proc.h>
84 #include <sys/protosw.h>
85 #include <sys/signalvar.h>
86 #include <sys/socket.h>
87 #include <sys/socketvar.h>
88 #include <sys/mutex.h>
89 #include <sys/sysctl.h>
90 #include <sys/syslog.h>
91 #include <sys/queue.h>
92 
93 #include <net/if.h>
94 #include <net/route.h>
95 
96 #include <netinet/in.h>
97 #include <netinet/in_systm.h>
98 #include <netinet/ip.h>
99 #include <netinet/in_pcb.h>
100 #include <netinet/in_var.h>
101 #ifdef INET6
102 #include <netinet/ip6.h>
103 #endif
104 #include <netinet/ip_icmp.h>
105 #include <netinet/icmp_var.h>
106 #include <netinet/ip_var.h>
107 #ifdef INET6
108 #include <netinet6/in6_pcb.h>
109 #include <netinet6/ip6_var.h>
110 #include <netinet6/nd6.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->m_pkthdr.rcvif = (struct ifnet *)0;
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 mbuf *m, struct lwp *l)
1856 {
1857 	struct inpcb *inp;
1858 	struct dccpcb *dp;
1859 	struct sockaddr *nam;
1860 	int error;
1861 	struct sockaddr_in *sin;
1862 	char test[2];
1863 
1864 	DCCP_DEBUG((LOG_INFO, "Entering dccp_connect!\n"));
1865 
1866 	INP_INFO_WLOCK(&dccpbinfo);
1867 	inp = sotoinpcb(so);
1868 	if (inp == 0) {
1869 		INP_INFO_WUNLOCK(&dccpbinfo);
1870 		return EINVAL;
1871 	}
1872 	INP_LOCK(inp);
1873 	if (inp->inp_faddr.s_addr != INADDR_ANY) {
1874 		INP_UNLOCK(inp);
1875 		INP_INFO_WUNLOCK(&dccpbinfo);
1876 		return EISCONN;
1877 	}
1878 
1879 	dp = (struct dccpcb *)inp->inp_ppcb;
1880 
1881 	if (dp->state == DCCPS_ESTAB) {
1882 		DCCP_DEBUG((LOG_INFO, "Why are we in connect when we already have a established connection?\n"));
1883 	}
1884 
1885 	dp->who = DCCP_CLIENT;
1886 	dp->seq_snd = (((u_int64_t)random() << 32) | random()) % 281474976710656LL;
1887 	dp->ref_seq.hi = dp->seq_snd >> 24;
1888 	dp->ref_seq.lo = (u_int64_t)(dp->seq_snd & 0xffffff);
1889 	DCCP_DEBUG((LOG_INFO, "dccp_connect seq_snd %llu\n", dp->seq_snd));
1890 
1891 	dccpstat.dccps_connattempt++;
1892 
1893 	nam = mtod(m, struct sockaddr *);
1894 	sin = (struct sockaddr_in *)nam;
1895 	if (sin->sin_family == AF_INET
1896 	    && IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
1897 		error = EAFNOSUPPORT;
1898 		goto bad;
1899 	}
1900 
1901 	error = dccp_doconnect(so, m, l, 0);
1902 
1903 	if (error != 0)
1904 		goto bad;
1905 
1906 	callout_reset(&dp->retrans_timer, dp->retrans, dccp_retrans_t, dp);
1907 	callout_reset(&dp->connect_timer, DCCP_CONNECT_TIMER, dccp_connect_t, dp);
1908 
1909 	if (dccp_do_feature_nego){
1910 		test[0] = dp->pref_cc;
1911 		dccp_add_feature(dp, DCCP_OPT_CHANGE_R, DCCP_FEATURE_CC, test, 1);
1912 	}
1913 
1914 	error = dccp_output(dp, 0);
1915 
1916 bad:
1917 	INP_UNLOCK(inp);
1918 	INP_INFO_WUNLOCK(&dccpbinfo);
1919 	return error;
1920 }
1921 
1922 static int
1923 dccp_connect2(struct socket *so, struct socket *so2)
1924 {
1925 	KASSERT(solocked(so));
1926 
1927 	return EOPNOTSUPP;
1928 }
1929 
1930 /*
1931  *
1932  *
1933  */
1934 int
1935 dccp_doconnect(struct socket *so, struct mbuf *m, struct lwp *l, int isipv6)
1936 {
1937 	struct inpcb *inp;
1938 #ifdef INET6
1939 	struct in6pcb *in6p;
1940 #endif
1941 	int error = 0;
1942 
1943 	DCCP_DEBUG((LOG_INFO, "Entering dccp_doconnect!\n"));
1944 
1945 #if defined(INET6)
1946 	if (isipv6) {
1947 		in6p = sotoin6pcb(so);
1948 		inp = 0;
1949 	} else
1950 #endif
1951 	{
1952 		inp = sotoinpcb(so);
1953 		in6p = 0;
1954 	}
1955 
1956 #if !defined(__NetBSD__) || !defined(INET6)
1957 	if (inp->inp_lport == 0) {
1958 #else
1959 	if (isipv6 ? in6p->in6p_lport == 0 : inp->inp_lport == 0) {
1960 #endif
1961 #ifdef INET6
1962 		if (isipv6) {
1963 			DCCP_DEBUG((LOG_INFO, "Running in6_pcbbind!\n"));
1964 			error = in6_pcbbind(in6p, NULL, l);
1965 		} else
1966 #endif /* INET6 */
1967 		{
1968 			error = in_pcbbind(inp, NULL, l);
1969 		}
1970 		if (error) {
1971 			DCCP_DEBUG((LOG_INFO, "in_pcbbind=%d\n",error));
1972 			return error;
1973 		}
1974 	}
1975 
1976 #ifdef INET6
1977 	if (isipv6) {
1978 		error = in6_pcbconnect(in6p, m, l);
1979 		DCCP_DEBUG((LOG_INFO, "in6_pcbconnect=%d\n",error));
1980 	} else
1981 #endif
1982 		error = in_pcbconnect(inp, m, l);
1983 	if (error) {
1984 		DCCP_DEBUG((LOG_INFO, "in_pcbconnect=%d\n",error));
1985 		return error;
1986 	}
1987 
1988 	soisconnecting(so);
1989 	return error;
1990 }
1991 
1992 /*
1993  * Detaches the DCCP protocol from the socket.
1994  *
1995  */
1996 int
1997 dccp_detach(struct socket *so)
1998 {
1999 	struct inpcb *inp;
2000 	struct in6pcb *in6p;
2001 	struct dccpcb *dp;
2002 
2003 	DCCP_DEBUG((LOG_INFO, "Entering dccp_detach!\n"));
2004 #ifdef INET6
2005 	if (so->so_proto->pr_domain->dom_family == AF_INET6) {
2006 		in6p = sotoin6pcb(so);
2007 		if (in6p == 0) {
2008 			return EINVAL;
2009 		}
2010 		dp = (struct dccpcb *)in6p->in6p_ppcb;
2011 	} else
2012 #endif
2013 	{
2014 		inp = sotoinpcb(so);
2015 		if (inp == 0) {
2016 			return EINVAL;
2017 		}
2018 		dp = (struct dccpcb *)inp->inp_ppcb;
2019 	}
2020 	if (! dccp_disconnect2(dp)) {
2021 		INP_UNLOCK(inp);
2022 	}
2023 	INP_INFO_WUNLOCK(&dccpbinfo);
2024 	return 0;
2025 }
2026 
2027 /*
2028  *
2029  *
2030  */
2031 int
2032 dccp_disconnect(struct socket *so)
2033 {
2034 	struct inpcb *inp;
2035 	struct in6pcb *in6p;
2036 	struct dccpcb *dp;
2037 
2038 	DCCP_DEBUG((LOG_INFO, "Entering dccp_disconnect!\n"));
2039 	INP_INFO_WLOCK(&dccpbinfo);
2040 #ifndef __NetBSD__
2041 	inp = sotoinpcb(so);
2042 	if (inp == 0) {
2043 		INP_INFO_WUNLOCK(&dccpbinfo);
2044 		return EINVAL;
2045 	}
2046 	INP_LOCK(inp);
2047 	if (inp->inp_faddr.s_addr == INADDR_ANY) {
2048 		INP_INFO_WUNLOCK(&dccpbinfo);
2049 		INP_UNLOCK(inp);
2050 		return ENOTCONN;
2051 	}
2052 
2053 	dp = (struct dccpcb *)inp->inp_ppcb;
2054 #else /* NetBSD */
2055 #ifdef INET6
2056 	if (so->so_proto->pr_domain->dom_family == AF_INET6) {
2057 		in6p = sotoin6pcb(so);
2058 		if (in6p == 0) {
2059 			INP_INFO_WUNLOCK(&dccpbinfo);
2060 			return EINVAL;
2061 		}
2062 		dp = (struct dccpcb *)in6p->in6p_ppcb;
2063 	} else
2064 #endif
2065 	{
2066 		inp = sotoinpcb(so);
2067 		if (inp == 0) {
2068 			return EINVAL;
2069 		}
2070 		dp = (struct dccpcb *)inp->inp_ppcb;
2071 	}
2072 #endif
2073 	if (!dccp_disconnect2(dp)) {
2074 		INP_UNLOCK(inp);
2075 	}
2076 	INP_INFO_WUNLOCK(&dccpbinfo);
2077 	return 0;
2078 }
2079 
2080 /*
2081  * If we have don't have a established connection
2082  * we can call dccp_close, otherwise we can just
2083  * set SS_ISDISCONNECTED and flush the receive queue.
2084  */
2085 static int
2086 dccp_disconnect2(struct dccpcb *dp)
2087 {
2088 	struct socket *so = dptosocket(dp);
2089 
2090 	DCCP_DEBUG((LOG_INFO, "Entering dccp_disconnect2!\n"));
2091 
2092 	if (dp->state < DCCPS_ESTAB) {
2093 		dccp_close(dp);
2094 		return 1;
2095 	} else {
2096 		soisdisconnecting(so);
2097 		sbflush(&so->so_rcv);
2098 		if (dp->state == DCCPS_ESTAB) {
2099 			dp->retrans = 100;
2100 			callout_reset(&dp->retrans_timer, dp->retrans,
2101 			    dccp_retrans_t, dp);
2102 			callout_reset(&dp->close_timer, DCCP_CLOSE_TIMER,
2103 			    dccp_close_t, dp);
2104 			if (dp->who == DCCP_CLIENT) {
2105 				dp->state = DCCPS_CLIENT_CLOSE;
2106 			} else {
2107 				dp->state = DCCPS_SERVER_CLOSE;
2108 			}
2109 			dccp_output(dp, 0);
2110 		}
2111 	}
2112 	return 0;
2113 }
2114 
2115 int
2116 dccp_send(struct socket *so, struct mbuf *m, struct mbuf *nam,
2117     struct mbuf *control, struct lwp *l)
2118 {
2119 	struct inpcb	*inp;
2120 	struct dccpcb	*dp;
2121 	struct sockaddr *addr;
2122 	int		error = 0;
2123 	int		isipv6 = 0;
2124 
2125 	DCCP_DEBUG((LOG_INFO, "Entering dccp_send!\n"));
2126 	KASSERT(solocked(so));
2127 	KASSERT(m != NULL);
2128 
2129 	if (control && control->m_len) {
2130 		m_freem(control);
2131 		m_freem(m);
2132 		return EINVAL;
2133 	}
2134 
2135 	if (nam == 0)
2136 		addr = NULL;
2137 	else
2138 		addr = mtod(nam, struct sockaddr *);
2139 
2140 #ifdef INET6
2141 	isipv6 = addr && addr->sa_family == AF_INET6;
2142 #endif
2143 
2144 #if defined(INET6)
2145 	if (so->so_proto->pr_domain->dom_family == AF_INET6) {
2146 		struct in6pcb	*in6p;
2147 		in6p = sotoin6pcb(so);
2148 		if (in6p == 0) {
2149 			error = EINVAL;
2150 			goto release;
2151 		}
2152 		dp = (struct dccpcb *)in6p->in6p_ppcb;
2153 	} else
2154 #endif
2155 	{
2156 		INP_INFO_WLOCK(&dccpbinfo);
2157 		inp = sotoinpcb(so);
2158 		if (inp == 0) {
2159 			error = EINVAL;
2160 			goto release;
2161 		}
2162 		INP_LOCK(inp);
2163 		dp = (struct dccpcb *)inp->inp_ppcb;
2164 	}
2165 	if (dp->state != DCCPS_ESTAB) {
2166 		DCCP_DEBUG((LOG_INFO, "We have no established connection!\n"));
2167 	}
2168 
2169 	if (control != NULL) {
2170 		DCCP_DEBUG((LOG_INFO, "We got a control message!\n"));
2171 		/* Are we going to use control messages??? */
2172 		if (control->m_len) {
2173 			m_freem(control);
2174 		}
2175 	}
2176 
2177 	if (sbspace(&so->so_snd) < -512) {
2178 		INP_UNLOCK(inp);
2179 		error = ENOBUFS;
2180 		goto release;
2181 	}
2182 
2183 	if (m->m_pkthdr.len > dp->d_maxseg) {
2184 		/* XXX we should calculate packet size more carefully */
2185 		INP_UNLOCK(inp);
2186 		error = EINVAL;
2187 		goto release;
2188 	}
2189 
2190 	if (dp->pktcnt >= DCCP_MAX_PKTS) {
2191 		INP_UNLOCK(inp);
2192 		error = ENOBUFS;
2193 		goto release;
2194 	}
2195 
2196 	sbappend(&so->so_snd, m);
2197 	dp->pktlen[(dp->pktlenidx + dp->pktcnt) % DCCP_MAX_PKTS] = m->m_pkthdr.len;
2198 	dp->pktcnt ++;
2199 
2200 	if (addr && dp->state == DCCPS_CLOSED) {
2201 		error = dccp_doconnect(so, nam, l, isipv6);
2202 		if (error)
2203 			goto out;
2204 	}
2205 
2206 	error = dccp_output(dp, 0);
2207 
2208 out:
2209 	INP_UNLOCK(inp);
2210 	INP_INFO_WUNLOCK(&dccpbinfo);
2211 	return error;
2212 
2213 release:
2214 	INP_INFO_WUNLOCK(&dccpbinfo);
2215 	m_freem(m);
2216 	return (error);
2217 }
2218 
2219 /*
2220  * Sets socket to SS_CANTSENDMORE
2221  */
2222 int
2223 dccp_shutdown(struct socket *so)
2224 {
2225 	struct inpcb *inp;
2226 
2227 	DCCP_DEBUG((LOG_INFO, "Entering dccp_shutdown!\n"));
2228 	INP_INFO_RLOCK(&dccpbinfo);
2229 	inp = sotoinpcb(so);
2230 	if (inp == 0) {
2231 		INP_INFO_RUNLOCK(&dccpbinfo);
2232 		return EINVAL;
2233 	}
2234 	INP_LOCK(inp);
2235 	INP_INFO_RUNLOCK(&dccpbinfo);
2236 	socantsendmore(so);
2237 	INP_UNLOCK(inp);
2238 	return 0;
2239 }
2240 
2241 static int
2242 dccp_listen(struct socket *so, struct lwp *td)
2243 {
2244 	struct inpcb *inp;
2245 	struct dccpcb *dp;
2246 	int error = 0;
2247 
2248 	DCCP_DEBUG((LOG_INFO, "Entering dccp_listen!\n"));
2249 
2250 	INP_INFO_RLOCK(&dccpbinfo);
2251 	inp = sotoinpcb(so);
2252 	if (inp == 0) {
2253 		INP_INFO_RUNLOCK(&dccpbinfo);
2254 		return EINVAL;
2255 	}
2256 	INP_LOCK(inp);
2257 	INP_INFO_RUNLOCK(&dccpbinfo);
2258 	dp = (struct dccpcb *)inp->inp_ppcb;
2259 	if (inp->inp_lport == 0)
2260 		error = in_pcbbind(inp, NULL, td);
2261 	if (error == 0) {
2262 		dp->state = DCCPS_LISTEN;
2263 		dp->who = DCCP_LISTENER;
2264 	}
2265 	INP_UNLOCK(inp);
2266 	return error;
2267 }
2268 
2269 /*
2270  * Accepts a connection (accept system call)
2271  */
2272 static int
2273 dccp_accept(struct socket *so, struct mbuf *nam)
2274 {
2275 	struct inpcb *inp = NULL;
2276 	int error = 0;
2277 
2278 	DCCP_DEBUG((LOG_INFO, "Entering dccp_accept!\n"));
2279 
2280 	if (nam == NULL) {
2281 		return EINVAL;
2282 	}
2283 	if (so->so_state & SS_ISDISCONNECTED) {
2284 		DCCP_DEBUG((LOG_INFO, "so_state && SS_ISDISCONNECTED!, so->state = %i\n", so->so_state));
2285 		return ECONNABORTED;
2286 	}
2287 
2288 	INP_INFO_RLOCK(&dccpbinfo);
2289 	inp = sotoinpcb(so);
2290 	if (inp == 0) {
2291 		INP_INFO_RUNLOCK(&dccpbinfo);
2292 		return EINVAL;
2293 	}
2294 	INP_LOCK(inp);
2295 	INP_INFO_RUNLOCK(&dccpbinfo);
2296 	in_setpeeraddr(inp, nam);
2297 
2298 	return error;
2299 }
2300 
2301 /*
2302  * Initializes a new DCCP control block
2303  * (in_pcballoc in attach has already allocated memory for it)
2304  */
2305 struct dccpcb *
2306 dccp_newdccpcb(int family, void *aux)
2307 {
2308 	struct inpcb *inp;
2309 	struct in6pcb *in6p;
2310 	struct dccpcb	*dp;
2311 #ifdef INET6
2312 	struct rtentry *rt;
2313 #endif
2314 
2315 	DCCP_DEBUG((LOG_INFO, "Creating a new dccpcb!\n"));
2316 
2317 	dp = pool_get(&dccpcb_pool, PR_NOWAIT);
2318 	if (dp == NULL)
2319 		return NULL;
2320 	bzero((char *) dp, sizeof(struct dccpcb));
2321 
2322 	callout_init(&dp->connect_timer, 0);
2323 	callout_init(&dp->retrans_timer, 0);
2324 	callout_init(&dp->close_timer, 0);
2325 	callout_init(&dp->timewait_timer, 0);
2326 
2327 	dp->ndp = 0;
2328 	dp->loss_window = 1000;
2329 	dp->cslen = 0;
2330 	dp->pref_cc = DEFAULT_CCID;
2331 	dp->who = DCCP_UNDEF;
2332 	dp->seq_snd = 0;
2333 	dp->seq_rcv = 0;
2334 	dp->shortseq = 0;
2335 	dp->gsn_rcv = 281474976710656LL;
2336 	dp->optlen = 0;
2337 	if (dccp_do_feature_nego){
2338 		dp->cc_in_use[0] = -1;
2339 		dp->cc_in_use[1] = -1;
2340 	} else {
2341 		/* for compatibility with linux */
2342 		dp->cc_in_use[0] = 4;
2343 		dp->cc_in_use[1] = 4;
2344 	}
2345 	dp->av_size = 0; /* no ack vector initially */
2346 	dp->remote_ackvector = 0; /* no ack vector on remote side initially */
2347 	dp->retrans = 200;
2348 	dp->avgpsize = 0;
2349 	dp->d_maxseg = 1400;
2350 	dp->ref_pseq.hi = 0;
2351 	dp->ref_pseq.lo = 0;
2352 	dp->pktlenidx = 0;
2353 	dp->pktcnt = 0;
2354 
2355 	switch (family) {
2356 	case PF_INET:
2357 		inp = (struct inpcb *)aux;
2358 		dp->d_inpcb = inp;
2359 		inp->inp_ip.ip_ttl = ip_defttl;
2360 		inp->inp_ppcb = dp;
2361 		break;
2362 	case PF_INET6:
2363 		in6p = (struct in6pcb *)aux;
2364 		dp->d_in6pcb = in6p;
2365 		rt = rtcache_validate(&in6p->in6p_route);
2366 		in6p->in6p_ip6.ip6_hlim = in6_selecthlim(in6p, (rt != NULL) ? rt->rt_ifp : NULL);
2367 		in6p->in6p_ppcb = dp;
2368 		break;
2369 	}
2370 
2371 	if (!dccp_do_feature_nego){
2372 		dp->cc_state[0] = (*cc_sw[4].cc_send_init)(dp);
2373 		dp->cc_state[1] = (*cc_sw[4].cc_recv_init)(dp);
2374 	}
2375 
2376 	return dp;
2377 }
2378 
2379 int
2380 dccp_add_option(struct dccpcb *dp, u_int8_t opt, char *val, u_int8_t val_len)
2381 {
2382 	return dccp_add_feature_option(dp, opt, 0, val, val_len);
2383 }
2384 
2385 int
2386 dccp_add_feature_option(struct dccpcb *dp, u_int8_t opt, u_int8_t feature, char *val, u_int8_t val_len)
2387 {
2388 	int i;
2389 	DCCP_DEBUG((LOG_INFO, "Entering dccp_add_feature_option, opt = %u, val_len = %u optlen %u\n", opt, val_len, dp->optlen));
2390 
2391 	if (DCCP_MAX_OPTIONS > (dp->optlen + val_len + 2)) {
2392 		dp->options[dp->optlen] = opt;
2393 		if (opt < 32) {
2394 			dp->optlen++;
2395 		} else {
2396 			if (opt == DCCP_OPT_CONFIRM_L && val_len) {
2397 				dp->options[dp->optlen + 1] = val_len + 3;
2398 				dp->options[dp->optlen +2] = feature;
2399 				dp->optlen += 3;
2400 			} else {
2401 				dp->options[dp->optlen + 1] = val_len + 2;
2402 				dp->optlen += 2;
2403 			}
2404 
2405 			for (i = 0; i<val_len; i++) {
2406 				dp->options[dp->optlen] = val[i];
2407 				dp->optlen++;
2408 			}
2409 		}
2410 	} else {
2411 		DCCP_DEBUG((LOG_INFO, "No room for more options, optlen = %u\n", dp->optlen));
2412 		return -1;
2413 	}
2414 
2415 	return 0;
2416 }
2417 
2418 /*
2419  * Searches "options" for given option type. if found, the data is copied to buffer
2420  * and returns the data length.
2421  * Returns 0 if option type not found
2422  */
2423 int
2424 dccp_get_option(char *options, int optlen, int type, char *buffer, int buflen)
2425 {
2426 	int i, j, size;
2427 	u_int8_t t;
2428 
2429 	for (i=0; i < optlen;) {
2430 		t = options[i++];
2431 		if (t >= 32) {
2432 			size = options[i++] - 2;
2433 			if (t == type) {
2434 				if (size > buflen)
2435 					return 0;
2436 				for (j = 0; j < size; j++)
2437 					buffer[j] = options[i++];
2438 				return size;
2439 			}
2440 			i += size;
2441 		}
2442 	}
2443 	/* If we get here the options was not found */
2444 	DCCP_DEBUG((LOG_INFO, "dccp_get_option option(%d) not found\n", type));
2445 	return 0;
2446 }
2447 
2448 void
2449 dccp_parse_options(struct dccpcb *dp, char *options, int optlen)
2450 {
2451 	u_int8_t opt, size, i, j;
2452 	char val[8];
2453 
2454 	for (i = 0; i < optlen; i++) {
2455 		opt = options[i];
2456 
2457 		DCCP_DEBUG((LOG_INFO, "Parsing opt: 0x%02x\n", opt));
2458 
2459 		if (opt < 32) {
2460 			switch (opt) {
2461 			    case DCCP_OPT_PADDING:
2462 				DCCP_DEBUG((LOG_INFO, "Got DCCP_OPT_PADDING!\n"));
2463 				break;
2464 			    case DCCP_OPT_DATA_DISCARD:
2465 				DCCP_DEBUG((LOG_INFO, "Got DCCP_OPT_DATA_DISCARD!\n"));
2466 				break;
2467 			    case DCCP_OPT_SLOW_RECV:
2468 				DCCP_DEBUG((LOG_INFO, "Got DCCP_OPT_SLOW_RECV!\n"));
2469 				break;
2470 			    case DCCP_OPT_BUF_CLOSED:
2471 				DCCP_DEBUG((LOG_INFO, "Got DCCP_OPT_BUF_CLOSED!\n"));
2472 				break;
2473 			    default:
2474 				DCCP_DEBUG((LOG_INFO, "Got an unknown option, option = %u!\n", opt));
2475 			}
2476 		} else if (opt > 32 && opt < 36) {
2477 			size = options[i+ 1];
2478 			if (size < 3 || size > 10) {
2479 				DCCP_DEBUG((LOG_INFO, "Error, option size = %u\n", size));
2480 				return;
2481 			}
2482 			/* Feature negotiations are options 33 to 35 */
2483 			DCCP_DEBUG((LOG_INFO, "Got option %u, size = %u, feature = %u\n", opt, size, options[i+2]));
2484 			bcopy(options + i + 3, val, size -3);
2485 			DCCP_DEBUG((LOG_INFO, "Calling dccp_feature neg(%u, %u, options[%u + 1], %u)!\n", (u_int)dp, opt, i+ 1, (size - 3)));
2486 			dccp_feature_neg(dp, opt, options[i+2], (size -3) , val);
2487 			i += size - 1;
2488 
2489 		} else if (opt < 128) {
2490 			size = options[i+ 1];
2491 			if (size < 3 || size > 10) {
2492 				DCCP_DEBUG((LOG_INFO, "Error, option size = %u\n", size));
2493 				return;
2494 			}
2495 
2496 			switch (opt) {
2497 			    case DCCP_OPT_RECV_BUF_DROPS:
2498 					DCCP_DEBUG((LOG_INFO, "Got DCCP_OPT_RECV_BUF_DROPS, size = %u!\n", size));
2499 					for (j=2; j < size; j++) {
2500 						DCCP_DEBUG((LOG_INFO, "val[%u] = %u ", j-1, options[i+j]));
2501 					}
2502 					DCCP_DEBUG((LOG_INFO, "\n"));
2503 				break;
2504 
2505 			    case DCCP_OPT_TIMESTAMP:
2506 					DCCP_DEBUG((LOG_INFO, "Got DCCP_OPT_TIMESTAMP, size = %u\n", size));
2507 
2508 					/* Adding TimestampEcho to next outgoing */
2509 					bcopy(options + i + 2, val, 4);
2510 					bzero(val + 4, 4);
2511 					dccp_add_option(dp, DCCP_OPT_TIMESTAMP_ECHO, val, 8);
2512 				break;
2513 
2514 			    case DCCP_OPT_TIMESTAMP_ECHO:
2515 					DCCP_DEBUG((LOG_INFO, "Got DCCP_OPT_TIMESTAMP_ECHO, size = %u\n",size));
2516 					for (j=2; j < size; j++) {
2517 						DCCP_DEBUG((LOG_INFO, "val[%u] = %u ", j-1, options[i+j]));
2518 					}
2519 					DCCP_DEBUG((LOG_INFO, "\n"));
2520 
2521 					/*
2522 						bcopy(options + i + 2, &(dp->timestamp_echo), 4);
2523 						bcopy(options + i + 6, &(dp->timestamp_elapsed), 4);
2524 						ACK_DEBUG((LOG_INFO, "DATA; echo = %u , elapsed = %u\n",
2525 						   dp->timestamp_echo, dp->timestamp_elapsed));
2526 					*/
2527 
2528 				break;
2529 
2530 			case DCCP_OPT_ACK_VECTOR0:
2531 			case DCCP_OPT_ACK_VECTOR1:
2532 			case DCCP_OPT_ELAPSEDTIME:
2533 				/* Dont do nothing here. Let the CC deal with it */
2534 				break;
2535 
2536 			default:
2537 				DCCP_DEBUG((LOG_INFO, "Got an unknown option, option = %u, size = %u!\n", opt, size));
2538 				break;
2539 
2540 			}
2541 			i += size - 1;
2542 
2543 		} else {
2544 			DCCP_DEBUG((LOG_INFO, "Got a CCID option (%d), do nothing!\n", opt));
2545 			size = options[i+ 1];
2546 			if (size < 3 || size > 10) {
2547 				DCCP_DEBUG((LOG_INFO, "Error, option size = %u\n", size));
2548 				return;
2549 			}
2550 			i += size - 1;
2551 		}
2552 	}
2553 
2554 }
2555 
2556 int
2557 dccp_add_feature(struct dccpcb *dp, u_int8_t opt, u_int8_t feature, char *val, u_int8_t val_len)
2558 {
2559 	int i;
2560 	DCCP_DEBUG((LOG_INFO, "Entering dccp_add_feature, opt = %u, feature = %u, val_len = %u\n", opt, feature, val_len));
2561 
2562 	if (DCCP_MAX_OPTIONS > (dp->featlen + val_len + 3)) {
2563 		dp->features[dp->featlen] = opt;
2564 		dp->features[dp->featlen + 1] = val_len + 3;
2565 		dp->features[dp->featlen +2] = feature;
2566 		dp->featlen += 3;
2567 		for (i = 0; i<val_len; i++) {
2568 			dp->features[dp->featlen] = val[i];
2569 			dp->featlen++;
2570 		}
2571 	} else {
2572 		DCCP_DEBUG((LOG_INFO, "No room for more features, featlen = %u\n", dp->featlen));
2573 		return -1;
2574 	}
2575 
2576 	return 0;
2577 }
2578 
2579 int
2580 dccp_remove_feature(struct dccpcb *dp, u_int8_t opt, u_int8_t feature)
2581 {
2582 	int i = 0, j = 0, k;
2583 	u_int8_t t_opt, t_feature, len;
2584 	DCCP_DEBUG((LOG_INFO, "Entering dccp_remove_feature, featlen = %u, opt = %u, feature = %u\n", dp->featlen, opt, feature));
2585 
2586 	while (i < dp->featlen) {
2587 		t_opt = dp->features[i];
2588 		len = dp->features[i+ 1];
2589 
2590 		if (i + len > dp->featlen) {
2591 			DCCP_DEBUG((LOG_INFO, "Error, len = %u and i(%u) + len > dp->featlen (%u)\n", len, i, dp->featlen));
2592 			return 1;
2593 		}
2594 		t_feature = dp->features[i+2];
2595 
2596 		if (t_opt == opt && t_feature == feature) {
2597 			i += len;
2598 		} else {
2599 			if (i != j) {
2600 				for (k = 0; k < len; k++) {
2601 					dp->features[j+k] = dp->features[i+k];
2602 				}
2603 			}
2604 			i += len;
2605 			j += len;
2606 		}
2607 	}
2608 	dp->featlen = j;
2609 	DCCP_DEBUG((LOG_INFO, "Exiting dccp_remove_feature, featlen = %u\n", dp->featlen));
2610 	return 0;
2611 }
2612 
2613 void
2614 dccp_feature_neg(struct dccpcb *dp, u_int8_t opt, u_int8_t feature, u_int8_t val_len, char *val)
2615 {
2616 	DCCP_DEBUG((LOG_INFO, "Running dccp_feature_neg, opt = %u, feature = %u len = %u ", opt, feature, val_len));
2617 
2618 	switch (feature) {
2619 		case DCCP_FEATURE_CC:
2620 			DCCP_DEBUG((LOG_INFO, "Got CCID negotiation, opt = %u, val[0] = %u\n", opt, val[0]));
2621 			if (opt == DCCP_OPT_CHANGE_R) {
2622 				if (val[0] == 2 || val[0] == 3 || val[0] == 0) {
2623 					/* try to use preferable CCID */
2624 					int i;
2625 					for (i = 1; i < val_len; i ++) if (val[i] == dp->pref_cc) val[0] = dp->pref_cc;
2626 					DCCP_DEBUG((LOG_INFO, "Sending DCCP_OPT_CONFIRM_L on CCID %u\n", val[0]));
2627 					dccp_remove_feature(dp, DCCP_OPT_CONFIRM_L, DCCP_FEATURE_CC);
2628 					dccp_add_feature_option(dp, DCCP_OPT_CONFIRM_L, DCCP_FEATURE_CC , val, 1);
2629 					if (dp->cc_in_use[0] < 1) {
2630 						dp->cc_state[0] = (*cc_sw[val[0] + 1].cc_send_init)(dp);
2631 						dp->cc_in_use[0] = val[0] + 1;
2632 					} else {
2633 						DCCP_DEBUG((LOG_INFO, "We already have negotiated a CC!!!\n"));
2634 					}
2635 				}
2636 			} else if (opt == DCCP_OPT_CONFIRM_L) {
2637 				DCCP_DEBUG((LOG_INFO, "Got DCCP_OPT_CONFIRM_L on CCID %u\n", val[0]));
2638 				dccp_remove_feature(dp, DCCP_OPT_CHANGE_R, DCCP_FEATURE_CC);
2639 				if (dp->cc_in_use[1] < 1) {
2640 					dp->cc_state[1] = (*cc_sw[val[0] + 1].cc_recv_init)(dp);
2641 					dp->cc_in_use[1] = val[0] + 1;
2642 					DCCP_DEBUG((LOG_INFO, "confirmed cc_in_use[1] = %d\n", dp->cc_in_use[1]));
2643 				} else {
2644 					DCCP_DEBUG((LOG_INFO, "We already have negotiated a CC!!! (confirm) %d\n", dp->cc_in_use[1]));
2645 				}
2646 			}
2647 
2648 		break;
2649 
2650 		case DCCP_FEATURE_ACKVECTOR:
2651 			ACK_DEBUG((LOG_INFO, "Got _Use Ack Vector_\n"));
2652 			if (opt == DCCP_OPT_CHANGE_R) {
2653 				if (val[0] == 1) {
2654 					dccp_use_ackvector(dp);
2655 					dccp_remove_feature(dp, DCCP_OPT_CONFIRM_L, DCCP_FEATURE_ACKVECTOR);
2656 					dccp_add_feature_option(dp, DCCP_OPT_CONFIRM_L, DCCP_FEATURE_ACKVECTOR , val, 1);
2657 				} else {
2658 					ACK_DEBUG((LOG_INFO, "ERROR. Strange val %u\n", val[0]));
2659 				}
2660 			} else if (opt == DCCP_OPT_CONFIRM_L) {
2661 					dccp_remove_feature(dp, DCCP_OPT_CONFIRM_L, DCCP_FEATURE_ACKVECTOR);
2662 			if (val[0] == 1) {
2663 					dp->remote_ackvector = 1;
2664 					ACK_DEBUG((LOG_INFO,"Remote side confirmed AckVector usage\n"));
2665 				} else {
2666 					ACK_DEBUG((LOG_INFO, "ERROR. Strange val %u\n", val[0]));
2667 				}
2668 			}
2669 			break;
2670 
2671 		case DCCP_FEATURE_ACKRATIO:
2672 			if (opt == DCCP_OPT_CHANGE_R) {
2673 				bcopy(val , &(dp->ack_ratio), 1);
2674 				ACK_DEBUG((LOG_INFO, "Feature: Change Ack Ratio to %u\n", dp->ack_ratio));
2675 			}
2676 			break;
2677 
2678 		case DCCP_FEATURE_ECN:
2679 		case DCCP_FEATURE_MOBILITY:
2680 		default:
2681 			/* we should send back empty CONFIRM_L for unknown feature unless it's not mandatory */
2682 			dccp_add_option(dp, DCCP_OPT_CONFIRM_L, NULL, 0);
2683 		break;
2684 
2685 	}
2686 }
2687 
2688 #ifdef __FreeBSD__
2689 static int
2690 dccp_pcblist(SYSCTL_HANDLER_ARGS)
2691 {
2692 
2693 	int error, i, n, s;
2694 	struct inpcb *inp, **inp_list;
2695 	inp_gen_t gencnt;
2696 	struct xinpgen xig;
2697 
2698 	/*
2699 	 * The process of preparing the TCB list is too time-consuming and
2700 	 * resource-intensive to repeat twice on every request.
2701 	 */
2702 	if (req->oldptr == 0) {
2703 		n = dccpbinfo.ipi_count;
2704 		req->oldidx = 2 * (sizeof xig)
2705 			+ (n + n/8) * sizeof(struct xdccpcb);
2706 		return 0;
2707 	}
2708 
2709 
2710 	if (req->newptr != 0)
2711 		return EPERM;
2712 
2713 
2714 	/*
2715 	 * OK, now we're committed to doing something.
2716 	 */
2717 	s = splnet();
2718 	gencnt = dccpbinfo.ipi_gencnt;
2719 	n = dccpbinfo.ipi_count;
2720 	splx(s);
2721 
2722 #if __FreeBSD_version >= 500000
2723 	sysctl_wire_old_buffer(req, 2 * (sizeof xig)
2724 		+ n * sizeof(struct xdccpcb));
2725 #endif
2726 
2727 	xig.xig_len = sizeof xig;
2728 	xig.xig_count = n;
2729 	xig.xig_gen = gencnt;
2730 	xig.xig_sogen = so_gencnt;
2731 	error = SYSCTL_OUT(req, &xig, sizeof xig);
2732 	if (error)
2733 		return error;
2734 
2735 	inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK);
2736 	if (inp_list == 0)
2737 		return ENOMEM;
2738 
2739 	s = splsoftnet();
2740 	INP_INFO_RLOCK(&dccpbinfo);
2741 
2742 	for (inp = LIST_FIRST(dccpbinfo.listhead), i = 0; inp && i < n;
2743 	     inp = LIST_NEXT(inp, inp_list)) {
2744 		INP_LOCK(inp);
2745 		if (inp->inp_gencnt <= gencnt &&
2746 #if __FreeBSD_version >= 500000
2747 		    cr_canseesocket(req->td->td_ucred, inp->inp_socket) == 0)
2748 #else
2749 		    !prison_xinpcb(req->p, inp))
2750 #endif
2751 			inp_list[i++] = inp;
2752 		INP_UNLOCK(inp);
2753 	}
2754 	INP_INFO_RUNLOCK(&dccpbinfo);
2755 	splx(s);
2756 	n = i;
2757 
2758 	error = 0;
2759 	for (i = 0; i < n; i++) {
2760 		inp = inp_list[i];
2761 		INP_LOCK(inp);
2762 
2763 		if (inp->inp_gencnt <= gencnt) {
2764 			struct xdccpcb xd;
2765 			vaddr_t inp_ppcb;
2766 			xd.xd_len = sizeof xd;
2767 			/* XXX should avoid extra copy */
2768 			bcopy(inp, &xd.xd_inp, sizeof *inp);
2769 			inp_ppcb = inp->inp_ppcb;
2770 			if (inp_ppcb != NULL)
2771 				bcopy(inp_ppcb, &xd.xd_dp, sizeof xd.xd_dp);
2772 			else
2773 				bzero((char *) &xd.xd_dp, sizeof xd.xd_dp);
2774 			if (inp->inp_socket)
2775 				 sotoxsocket(inp->inp_socket, &xd.xd_socket);
2776 			error = SYSCTL_OUT(req, &xd, sizeof xd);
2777 		}
2778 		INP_UNLOCK(inp);
2779 	}
2780 	if (!error) {
2781 		/*
2782 		 * Give the user an updated idea of our state.
2783 		 * If the generation differs from what we told
2784 		 * her before, she knows that something happened
2785 		 * while we were processing this request, and it
2786 		 * might be necessary to retry.
2787 		 */
2788 		s = splnet();
2789 		INP_INFO_RLOCK(&dccpbinfo);
2790 		xig.xig_gen = dccpbinfo.ipi_gencnt;
2791 		xig.xig_sogen = so_gencnt;
2792 		xig.xig_count = dccpbinfo.ipi_count;
2793 
2794 
2795 		INP_INFO_RUNLOCK(&dccpbinfo);
2796 		splx(s);
2797 		error = SYSCTL_OUT(req, &xig, sizeof xig);
2798 	}
2799 	free(inp_list, M_TEMP);
2800 	return error;
2801 }
2802 #endif
2803 
2804 #ifdef __FreeBSD__
2805 SYSCTL_PROC(_net_inet_dccp, DCCPCTL_PCBLIST, pcblist, CTLFLAG_RD, 0, 0,
2806     dccp_pcblist, "S,xdccpcb", "List of active DCCP sockets");
2807 #endif
2808 
2809 void
2810 dccp_timewait_t(void *dcb)
2811 {
2812 	struct dccpcb *dp = dcb;
2813 
2814 	DCCP_DEBUG((LOG_INFO, "Entering dccp_timewait_t!\n"));
2815 	mutex_enter(softnet_lock);
2816 	INP_INFO_WLOCK(&dccpbinfo);
2817 	INP_LOCK(dp->d_inpcb);
2818 	dccp_close(dp);
2819 	INP_INFO_WUNLOCK(&dccpbinfo);
2820 	mutex_exit(softnet_lock);
2821 }
2822 
2823 void
2824 dccp_connect_t(void *dcb)
2825 {
2826 	struct dccpcb *dp = dcb;
2827 
2828 	DCCP_DEBUG((LOG_INFO, "Entering dccp_connect_t!\n"));
2829 	mutex_enter(softnet_lock);
2830 	INP_INFO_WLOCK(&dccpbinfo);
2831 	INP_LOCK(dp->d_inpcb);
2832 	dccp_close(dp);
2833 	INP_INFO_WUNLOCK(&dccpbinfo);
2834 	mutex_exit(softnet_lock);
2835 }
2836 
2837 void
2838 dccp_close_t(void *dcb)
2839 {
2840 	struct dccpcb *dp = dcb;
2841 
2842 	DCCP_DEBUG((LOG_INFO, "Entering dccp_close_t!\n"));
2843 	mutex_enter(softnet_lock);
2844 	INP_INFO_WLOCK(&dccpbinfo);
2845 	dp->state = DCCPS_TIME_WAIT; /* HMM */
2846 	if (dp->who == DCCP_SERVER) {
2847 		INP_LOCK(dp->d_inpcb);
2848 		KERNEL_LOCK(1, NULL);
2849 		dccp_output(dp, DCCP_TYPE_RESET + 2);
2850 		KERNEL_UNLOCK_ONE(NULL);
2851 		dccp_close(dp);
2852 	} else {
2853 		INP_LOCK(dp->d_inpcb);
2854 		dccp_output(dp, DCCP_TYPE_RESET + 2);
2855 		/*dp->state = DCCPS_TIME_WAIT; */
2856 		callout_reset(&dp->timewait_timer, DCCP_TIMEWAIT_TIMER,
2857 		    dccp_timewait_t, dp);
2858 		INP_UNLOCK(dp->d_inpcb);
2859 	}
2860 	INP_INFO_WUNLOCK(&dccpbinfo);
2861 	mutex_exit(softnet_lock);
2862 }
2863 
2864 void
2865 dccp_retrans_t(void *dcb)
2866 {
2867 	struct dccpcb *dp = dcb;
2868 	/*struct inpcb *inp;*/
2869 
2870 	DCCP_DEBUG((LOG_INFO, "Entering dccp_retrans_t!\n"));
2871 	mutex_enter(softnet_lock);
2872 	INP_INFO_RLOCK(&dccpbinfo);
2873 	/*inp = dp->d_inpcb;*/
2874 	INP_LOCK(inp);
2875 	INP_INFO_RUNLOCK(&dccpbinfo);
2876 	callout_stop(&dp->retrans_timer);
2877 	KERNEL_LOCK(1, NULL);
2878 	dccp_output(dp, 0);
2879 	KERNEL_UNLOCK_ONE(NULL);
2880 	dp->retrans = dp->retrans * 2;
2881 	callout_reset(&dp->retrans_timer, dp->retrans, dccp_retrans_t, dp);
2882 	INP_UNLOCK(inp);
2883 	mutex_exit(softnet_lock);
2884 }
2885 
2886 static int
2887 dccp_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp)
2888 {
2889 	int error = 0;
2890 	int family;
2891 
2892 	family = so->so_proto->pr_domain->dom_family;
2893 	switch (family) {
2894 	case PF_INET:
2895 		error = in_control(so, cmd, nam, ifp);
2896 		break;
2897 #ifdef INET6
2898 	case PF_INET6:
2899 		error = in6_control(so, cmd, nam, ifp);
2900 		break;
2901 #endif
2902 	default:
2903 		error =	 EAFNOSUPPORT;
2904 	}
2905 	return (error);
2906 }
2907 
2908 static int
2909 dccp_stat(struct socket *so, struct stat *ub)
2910 {
2911 	return 0;
2912 }
2913 
2914 static int
2915 dccp_peeraddr(struct socket *so, struct mbuf *nam)
2916 {
2917 	KASSERT(solocked(so));
2918 	KASSERT(sotoinpcb(so) != NULL);
2919 	KASSERT(nam != NULL);
2920 
2921 	in_setpeeraddr(sotoinpcb(so), nam);
2922 	return 0;
2923 }
2924 
2925 static int
2926 dccp_sockaddr(struct socket *so, struct mbuf *nam)
2927 {
2928 	KASSERT(solocked(so));
2929 	KASSERT(sotoinpcb(so) != NULL);
2930 	KASSERT(nam != NULL);
2931 
2932 	in_setsockaddr(sotoinpcb(so), nam);
2933 	return 0;
2934 }
2935 
2936 static int
2937 dccp_rcvd(struct socket *so, int flags, struct lwp *l)
2938 {
2939 	KASSERT(solocked(so));
2940 
2941 	return EOPNOTSUPP;
2942 }
2943 
2944 static int
2945 dccp_recvoob(struct socket *so, struct mbuf *m, int flags)
2946 {
2947 	KASSERT(solocked(so));
2948 
2949 	return EOPNOTSUPP;
2950 }
2951 
2952 static int
2953 dccp_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control)
2954 {
2955 	KASSERT(solocked(so));
2956 
2957 	m_freem(m);
2958 	m_freem(control);
2959 
2960 	return EOPNOTSUPP;
2961 }
2962 
2963 static int
2964 dccp_purgeif(struct socket *so, struct ifnet *ifp)
2965 {
2966 	int s;
2967 
2968 	s = splsoftnet();
2969 	mutex_enter(softnet_lock);
2970 	in_pcbpurgeif0(&dccpbtable, ifp);
2971 	in_purgeif(ifp);
2972 	in_pcbpurgeif(&dccpbtable, ifp);
2973 	mutex_exit(softnet_lock);
2974 	splx(s);
2975 
2976 	return 0;
2977 }
2978 
2979 int
2980 dccp_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam,
2981 	    struct mbuf *control, struct lwp *l)
2982 {
2983 	KASSERT(req != PRU_ATTACH);
2984 	KASSERT(req != PRU_DETACH);
2985 	KASSERT(req != PRU_ACCEPT);
2986 	KASSERT(req != PRU_BIND);
2987 	KASSERT(req != PRU_LISTEN);
2988 	KASSERT(req != PRU_CONNECT);
2989 	KASSERT(req != PRU_CONNECT2);
2990 	KASSERT(req != PRU_DISCONNECT);
2991 	KASSERT(req != PRU_SHUTDOWN);
2992 	KASSERT(req != PRU_ABORT);
2993 	KASSERT(req != PRU_CONTROL);
2994 	KASSERT(req != PRU_SENSE);
2995 	KASSERT(req != PRU_PEERADDR);
2996 	KASSERT(req != PRU_SOCKADDR);
2997 	KASSERT(req != PRU_RCVD);
2998 	KASSERT(req != PRU_RCVOOB);
2999 	KASSERT(req != PRU_SEND);
3000 	KASSERT(req != PRU_SENDOOB);
3001 	KASSERT(req != PRU_PURGEIF);
3002 
3003 	KASSERT(solocked(so));
3004 
3005 	if (sotoinpcb(so) == NULL)
3006 		return EINVAL;
3007 
3008 	panic("dccp_usrreq");
3009 
3010 	return 0;
3011 }
3012 
3013 /****** Ack Vector functions *********/
3014 
3015 /**
3016  * Initialize and allocate mem for Ack Vector
3017  **/
3018 void
3019 dccp_use_ackvector(struct dccpcb *dp)
3020 {
3021 	DCCP_DEBUG((LOG_INFO,"Initializing AckVector\n"));
3022 	if (dp->ackvector != 0) {
3023 		DCCP_DEBUG((LOG_INFO, "It was already initialized!!!\n"));
3024 		return;
3025 	}
3026 	dp->av_size = DCCP_VECTORSIZE;
3027 	/* need 2 bits per entry */
3028 	dp->ackvector = malloc(dp->av_size/4, M_PCB, M_NOWAIT | M_ZERO);
3029 	if (dp->ackvector == 0) {
3030 		DCCP_DEBUG((LOG_INFO, "Unable to allocate memory for ackvector\n"));
3031 		/* What to do now? */
3032 		dp->av_size = 0;
3033 		return;
3034 	}
3035 	memset(dp->ackvector, 0xff, dp->av_size/4);
3036 	dp->av_hs = dp->av_ts = 0;
3037 	dp->av_hp = dp->ackvector;
3038 }
3039 
3040 /**
3041  * Set 'seqnr' as the new head in ackvector
3042  **/
3043 void
3044 dccp_update_ackvector(struct dccpcb *dp, u_int64_t seqnr)
3045 {
3046 	int64_t gap;
3047 	u_char *t;
3048 
3049 	/* Ignore wrapping for now */
3050 
3051 	ACK_DEBUG((LOG_INFO,"New head in ackvector: %u\n", seqnr));
3052 
3053 	if (dp->av_size == 0) {
3054 		ACK_DEBUG((LOG_INFO, "Update: AckVector NOT YET INITIALIZED!!!\n"));
3055 		dccp_use_ackvector(dp);
3056 	}
3057 
3058 	if (seqnr > dp->av_hs) {
3059 		gap = seqnr - dp->av_hs;
3060 	} else {
3061 		/* We received obsolete information */
3062 		return;
3063 	}
3064 
3065 	t = dp->av_hp + (gap/4);
3066 	if (t >= (dp->ackvector + (dp->av_size/4)))
3067 		t -= (dp->av_size / 4); /* ackvector wrapped */
3068 	dp->av_hp = t;
3069 	dp->av_hs = seqnr;
3070 }
3071 
3072 /**
3073  * We've received a packet. store in local av so it's included in
3074  * next Ack Vector sent
3075  **/
3076 void
3077 dccp_increment_ackvector(struct dccpcb *dp, u_int64_t seqnr)
3078 {
3079 	u_int64_t offset, dc;
3080 	int64_t gap;
3081 	u_char *t, *n;
3082 
3083 	DCCP_DEBUG((LOG_INFO, "Entering dccp_increment_ackvecktor %d\n", dp->av_size));
3084 	if (dp->av_size == 0) {
3085 		DCCP_DEBUG((LOG_INFO, "Increment: AckVector NOT YET INITIALIZED!!!\n"));
3086 		dccp_use_ackvector(dp);
3087 	}
3088 
3089 	if (dp->av_hs == dp->av_ts) {
3090 		/* Empty ack vector */
3091 		dp->av_hs = dp->av_ts = seqnr;
3092 	}
3093 
3094 	/* Check for wrapping */
3095 	if (seqnr >= dp->av_hs) {
3096 		/* Not wrapped */
3097 		gap = seqnr - dp->av_hs;
3098 	} else {
3099 		/* Wrapped */
3100 		gap = seqnr + 0x1000000000000LL - dp->av_hs; /* seqnr = 48 bits */
3101 	}
3102 	DCCP_DEBUG((LOG_INFO, "dccp_increment_ackvecktor gap=%llu av_size %d\n", gap, dp->av_size));
3103 
3104 	if (gap >= dp->av_size) {
3105 		/* gap is bigger than ackvector size? baaad */
3106 		/* maybe we should increase the ackvector here */
3107 		DCCP_DEBUG((LOG_INFO, "increment_ackvector error. gap: %llu, av_size: %d, seqnr: %d\n",
3108 			    gap, dp->av_size, seqnr));
3109 		return;
3110 	}
3111 
3112 	offset = gap % 4; /* hi or low 2 bits to mark */
3113 	t = dp->av_hp + (gap/4);
3114 	if (t >= (dp->ackvector + (dp->av_size/4)))
3115 		t -= (dp->av_size / 4); /* ackvector wrapped */
3116 
3117 	*t = *t & (~(0x03 << (offset *2))); /* turn off bits, 00 is rcvd, 11 is missing */
3118 
3119 	dp->av_ts = seqnr + 1;
3120 	if (dp->av_ts == 0x1000000000000LL)
3121 		dp->av_ts = 0;
3122 
3123 	if (gap > (dp->av_size - 128)) {
3124 		n = malloc(dp->av_size/2, M_PCB, M_NOWAIT | M_ZERO); /* old size * 2 */
3125 		memset (n + dp->av_size / 4, 0xff, dp->av_size / 4); /* new half all missing */
3126 		dc = (dp->ackvector + (dp->av_size/4)) - dp->av_hp;
3127 		memcpy (n, dp->av_hp, dc); /* tail to end */
3128 		memcpy (n+dc, dp->ackvector, dp->av_hp - dp->ackvector); /* start to tail */
3129 		dp->av_size = dp->av_size * 2; /* counted in items, so it';s a doubling */
3130 		free (dp->ackvector, M_PCB);
3131 		dp->av_hp = dp->ackvector = n;
3132 	}
3133 }
3134 
3135 /**
3136  * Generates the ack vector to send in outgoing packet.
3137  * These are backwards (first packet in ack vector is packet indicated by Ack Number,
3138  * subsequent are older packets).
3139  **/
3140 
3141 u_int16_t
3142 dccp_generate_ackvector(struct dccpcb *dp, u_char *buf)
3143 {
3144 	int64_t j;
3145 	u_int64_t i;
3146 	u_int16_t cnt, oldlen, bufsize;
3147 	u_char oldstate, st;
3148 
3149 	bufsize = 16;
3150 	cnt = 0;
3151 
3152 	oldstate = 0x04; /* bad value */
3153 	oldlen = 0;
3154 
3155 	if (dp->av_size == 0) {
3156 		ACK_DEBUG((LOG_INFO, "Generate: AckVector NOT YET INITIALIZED!!!\n"));
3157 		return 0;
3158 	}
3159 
3160 	if (dp->seq_rcv > dp->av_ts) {
3161 		/* AckNum is beyond our av-list , so we'll start with some
3162 		 * 0x3 (Packet not yet received) */
3163 		j = dp->seq_rcv - dp->av_ts -1;
3164 		do {
3165 			/* state | length */
3166 			oldstate = 0x03;
3167 			if (j > 63)
3168 				oldlen = 63;
3169 			else
3170 				oldlen = j;
3171 
3172 			buf[cnt] = (0x03 << 6) | oldlen;
3173 			cnt++;
3174 			if (cnt == bufsize) {
3175 				/* I've skipped the realloc bshit */
3176 				/* PANIC */
3177 			}
3178 			j-=63;
3179 		} while (j > 0);
3180 	}
3181 
3182 	/* Ok now we're at dp->av_ts (unless AckNum is lower) */
3183 	i = (dp->seq_rcv < dp->av_ts) ? dp->seq_rcv : dp->av_ts;
3184 	st = dccp_ackvector_state(dp, i);
3185 
3186 	if (st == oldstate) {
3187 		cnt--;
3188 		oldlen++;
3189 	} else {
3190 		oldlen = 0;
3191 		oldstate = st;
3192 	}
3193 
3194 	if (dp->av_ts > dp->av_hs) {
3195 		do {
3196 			i--;
3197 			st = dccp_ackvector_state(dp, i);
3198 			if (st == oldstate && oldlen < 64) {
3199 				oldlen++;
3200 			} else {
3201 				buf[cnt] = (oldstate << 6) | (oldlen & 0x3f);
3202 				cnt++;
3203 				oldlen = 0;
3204 				oldstate = st;
3205 				if (cnt == bufsize) {
3206 					/* PANIC */
3207 				}
3208 			}
3209 
3210 		} while (i > dp->av_hs);
3211 	} else {
3212 		/* It's wrapped */
3213 		do {
3214 			i--;
3215 			st = dccp_ackvector_state(dp, i);
3216 			if (st == oldstate && oldlen < 64) {
3217 				oldlen++;
3218 			} else {
3219 				buf[cnt] = (oldstate << 6) | (oldlen & 0x3f);
3220 				cnt++;
3221 				oldlen = 0;
3222 				oldstate = st;
3223 				if (cnt == bufsize) {
3224 					/* PANIC */
3225 				}
3226 			}
3227 
3228 		} while (i > 0);
3229 		i = 0x1000000;
3230 		do {
3231 			i--;
3232 			st = dccp_ackvector_state(dp, i);
3233 			if (st == oldstate && oldlen < 64) {
3234 				oldlen++;
3235 			} else {
3236 				buf[cnt] = (oldstate << 6) | (oldlen & 0x3f);
3237 				cnt++;
3238 				oldlen = 0;
3239 				oldstate = st;
3240 				if (cnt == bufsize) {
3241 					/* PANIC */
3242 				}
3243 			}
3244 		} while (i > dp->av_hs);
3245 	}
3246 
3247 	/* add the last one */
3248 	buf[cnt] = (oldstate << 6) | (oldlen & 0x3f);
3249 	cnt++;
3250 
3251 	return cnt;
3252 }
3253 
3254 u_char
3255 dccp_ackvector_state(struct dccpcb *dp, u_int64_t seqnr)
3256 {
3257 	u_int64_t gap, offset;
3258 	u_char *t;
3259 
3260 	/* Check for wrapping */
3261 	if (seqnr >= dp->av_hs) {
3262 		/* Not wrapped */
3263 		gap = seqnr - dp->av_hs;
3264 	} else {
3265 		/* Wrapped */
3266 		gap = seqnr + 0x1000000000000LL - dp->av_hs; /* seq nr = 48 bits */
3267 	}
3268 
3269 	if (gap >= dp->av_size) {
3270 		/* gap is bigger than ackvector size? baaad */
3271 		return 0x03;
3272 	}
3273 
3274 	offset = gap % 4 *2;
3275 	t = dp->av_hp + (gap/4);
3276 	if (t >= (dp->ackvector + (dp->av_size/4)))
3277 		t -= (dp->av_size / 4); /* wrapped */
3278 
3279 	return ((*t & (0x03 << offset)) >> offset);
3280 }
3281 
3282 /****** End of Ack Vector functions *********/
3283 
3284 /* No cc functions */
3285 void *
3286 dccp_nocc_init(struct dccpcb *pcb)
3287 {
3288   return (void*) 1;
3289 }
3290 
3291 void
3292 dccp_nocc_free(void *ccb)
3293 {
3294 }
3295 
3296 int
3297 dccp_nocc_send_packet(void *ccb, long size)
3298 {
3299   return 1;
3300 }
3301 
3302 void
3303 dccp_nocc_send_packet_sent(void *ccb, int moreToSend, long size)
3304 {
3305 }
3306 
3307 void
3308 dccp_nocc_packet_recv(void *ccb, char* options ,int optlen)
3309 {
3310 }
3311 
3312 void
3313 dccp_log(int level, const char *format, ...)
3314 {
3315 	va_list ap;
3316 
3317 	va_start(ap, format);
3318 	vprintf(format,  ap);
3319 	va_end(ap);
3320 	return;
3321 }
3322 
3323 /*
3324  * Sysctl for dccp variables.
3325  */
3326 SYSCTL_SETUP(sysctl_net_inet_dccp_setup, "sysctl net.inet.dccp subtree setup")
3327 {
3328 
3329 	sysctl_createv(clog, 0, NULL, NULL,
3330 		CTLFLAG_PERMANENT,
3331 		CTLTYPE_NODE, "net", NULL,
3332 		NULL, 0, NULL, 0,
3333 		CTL_NET, CTL_EOL);
3334 
3335 	sysctl_createv(clog, 0, NULL, NULL,
3336 		CTLFLAG_PERMANENT,
3337 		CTLTYPE_NODE, "inet", NULL,
3338 		NULL, 0, NULL, 0,
3339 		CTL_NET, PF_INET, CTL_EOL);
3340 
3341 	sysctl_createv(clog, 0, NULL, NULL,
3342 		CTLFLAG_PERMANENT,
3343 		CTLTYPE_NODE, "dccp",
3344 		SYSCTL_DESCR("DCCPv4 related settings"),
3345 		NULL, 0, NULL, 0,
3346 		CTL_NET, PF_INET, IPPROTO_DCCP, CTL_EOL);
3347 
3348 	sysctl_createv(clog, 0, NULL, NULL,
3349 		CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
3350 		CTLTYPE_INT, "dccp_log_in_vain",
3351 		SYSCTL_DESCR("log all connection attempt"),
3352 		NULL, 0, &dccp_log_in_vain, 0,
3353 		CTL_NET, PF_INET, IPPROTO_DCCP, DCCPCTL_LOGINVAIN,
3354 		CTL_EOL);
3355 
3356 	sysctl_createv(clog, 0, NULL, NULL,
3357 		CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
3358 		CTLTYPE_INT, "do_feature_nego",
3359 		SYSCTL_DESCR("enable feature negotiation"),
3360 		NULL, 0, &dccp_do_feature_nego, 0,
3361 		CTL_NET, PF_INET, IPPROTO_DCCP, DCCPCTL_DOFEATURENEGO,
3362 		CTL_EOL);
3363 }
3364 
3365 PR_WRAP_USRREQS(dccp)
3366 #define	dccp_attach	dccp_attach_wrapper
3367 #define	dccp_detach	dccp_detach_wrapper
3368 #define dccp_accept	dccp_accept_wrapper
3369 #define	dccp_bind	dccp_bind_wrapper
3370 #define	dccp_listen	dccp_listen_wrapper
3371 #define	dccp_connect	dccp_connect_wrapper
3372 #define	dccp_connect2	dccp_connect2_wrapper
3373 #define	dccp_disconnect	dccp_disconnect_wrapper
3374 #define	dccp_shutdown	dccp_shutdown_wrapper
3375 #define	dccp_abort	dccp_abort_wrapper
3376 #define	dccp_ioctl	dccp_ioctl_wrapper
3377 #define	dccp_stat	dccp_stat_wrapper
3378 #define	dccp_peeraddr	dccp_peeraddr_wrapper
3379 #define	dccp_sockaddr	dccp_sockaddr_wrapper
3380 #define	dccp_rcvd	dccp_rcvd_wrapper
3381 #define	dccp_recvoob	dccp_recvoob_wrapper
3382 #define	dccp_send	dccp_send_wrapper
3383 #define	dccp_sendoob	dccp_sendoob_wrapper
3384 #define	dccp_purgeif	dccp_purgeif_wrapper
3385 #define	dccp_usrreq	dccp_usrreq_wrapper
3386 
3387 const struct pr_usrreqs dccp_usrreqs = {
3388 	.pr_attach	= dccp_attach,
3389 	.pr_detach	= dccp_detach,
3390 	.pr_accept	= dccp_accept,
3391 	.pr_bind	= dccp_bind,
3392 	.pr_listen	= dccp_listen,
3393 	.pr_connect	= dccp_connect,
3394 	.pr_connect2	= dccp_connect2,
3395 	.pr_disconnect	= dccp_disconnect,
3396 	.pr_shutdown	= dccp_shutdown,
3397 	.pr_abort	= dccp_abort,
3398 	.pr_ioctl	= dccp_ioctl,
3399 	.pr_stat	= dccp_stat,
3400 	.pr_peeraddr	= dccp_peeraddr,
3401 	.pr_sockaddr	= dccp_sockaddr,
3402 	.pr_rcvd	= dccp_rcvd,
3403 	.pr_recvoob	= dccp_recvoob,
3404 	.pr_send	= dccp_send,
3405 	.pr_sendoob	= dccp_sendoob,
3406 	.pr_purgeif	= dccp_purgeif,
3407 	.pr_generic	= dccp_usrreq,
3408 };
3409