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