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