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