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