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