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