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