1 /* 2 * Copyright (c) 1984, 1985 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)spp_usrreq.c 6.15 (Berkeley) 10/30/85 7 */ 8 9 #include "param.h" 10 #include "dir.h" 11 #include "user.h" 12 #include "mbuf.h" 13 #include "protosw.h" 14 #include "socket.h" 15 #include "socketvar.h" 16 #include "errno.h" 17 18 #include "../net/if.h" 19 #include "../net/route.h" 20 #include "../netinet/tcp_fsm.h" 21 #include "../netinet/tcp_timer.h" 22 23 #include "ns.h" 24 #include "ns_pcb.h" 25 #include "idp.h" 26 #include "idp_var.h" 27 #include "ns_error.h" 28 #include "sp.h" 29 #include "spidp.h" 30 #include "spp_var.h" 31 #include "spp_debug.h" 32 33 /* 34 * SP protocol implementation. 35 */ 36 spp_init() 37 { 38 39 spp_iss = 1; /* WRONG !! should fish it out of TODR */ 40 } 41 struct spidp spp_savesi; 42 int traceallspps = 0; 43 extern int sppconsdebug; 44 int spp_hardnosed; 45 int spp_use_delack = 0; 46 47 /*ARGSUSED*/ 48 spp_input(m, nsp, ifp) 49 register struct mbuf *m; 50 register struct nspcb *nsp; 51 struct ifnet *ifp; 52 { 53 register struct sppcb *cb; 54 register struct spidp *si = mtod(m, struct spidp *); 55 register struct socket *so; 56 short ostate; 57 int dropsocket = 0; 58 59 60 if (nsp == 0) { 61 panic("No nspcb in spp_input\n"); 62 return; 63 } 64 65 cb = nstosppcb(nsp); 66 if (cb == 0) goto bad; 67 68 if (m->m_len < sizeof(*si)) { 69 if ((m = m_pullup(m, sizeof(*si))) == 0) { 70 spp_istat.hdrops++; 71 return; 72 } 73 si = mtod(m, struct spidp *); 74 } 75 si->si_seq = ntohs(si->si_seq); 76 si->si_ack = ntohs(si->si_ack); 77 si->si_alo = ntohs(si->si_alo); 78 79 so = nsp->nsp_socket; 80 if (so->so_options & SO_DEBUG || traceallspps) { 81 ostate = cb->s_state; 82 spp_savesi = *si; 83 } 84 if (so->so_options & SO_ACCEPTCONN) { 85 so = sonewconn(so); 86 if (so == 0) { 87 spp_istat.nonucn++; 88 goto drop; 89 } 90 /* 91 * This is ugly, but .... 92 * 93 * Mark socket as temporary until we're 94 * committed to keeping it. The code at 95 * ``drop'' and ``dropwithreset'' check the 96 * flag dropsocket to see if the temporary 97 * socket created here should be discarded. 98 * We mark the socket as discardable until 99 * we're committed to it below in TCPS_LISTEN. 100 */ 101 dropsocket++; 102 nsp = (struct nspcb *)so->so_pcb; 103 nsp->nsp_laddr = si->si_dna; 104 cb = nstosppcb(nsp); 105 cb->s_state = TCPS_LISTEN; 106 } 107 108 /* 109 * Packet received on connection. 110 * reset idle time and keep-alive timer; 111 */ 112 cb->s_idle = 0; 113 cb->s_timer[TCPT_KEEP] = TCPTV_KEEP; 114 115 switch (cb->s_state) { 116 117 case TCPS_LISTEN:{ 118 struct mbuf *am; 119 register struct sockaddr_ns *sns; 120 struct ns_addr laddr; 121 122 /* 123 * If somebody here was carying on a conversation 124 * and went away, and his pen pal thinks he can 125 * still talk, we get the misdirected packet. 126 */ 127 if (spp_hardnosed && (si->si_did != 0 || si->si_seq != 0)) { 128 spp_istat.gonawy++; 129 goto dropwithreset; 130 } 131 am = m_get(M_DONTWAIT, MT_SONAME); 132 if (am == NULL) 133 goto drop; 134 am->m_len = sizeof (struct sockaddr_ns); 135 sns = mtod(am, struct sockaddr_ns *); 136 sns->sns_family = AF_NS; 137 sns->sns_addr = si->si_sna; 138 laddr = nsp->nsp_laddr; 139 if (ns_nullhost(laddr)) 140 nsp->nsp_laddr = si->si_dna; 141 if (ns_pcbconnect(nsp, am)) { 142 nsp->nsp_laddr = laddr; 143 (void) m_free(am); 144 spp_istat.noconn++; 145 goto drop; 146 } 147 (void) m_free(am); 148 spp_template(cb); 149 dropsocket = 0; /* committed to socket */ 150 cb->s_did = si->si_sid; 151 cb->s_rack = si->si_ack; 152 cb->s_ralo = si->si_alo; 153 #define THREEWAYSHAKE 154 #ifdef THREEWAYSHAKE 155 cb->s_state = TCPS_SYN_RECEIVED; 156 cb->s_force = 1 + TCPT_REXMT; 157 cb->s_timer[TCPT_REXMT] = 2 * TCPTV_MIN; 158 } 159 break; 160 /* 161 * This state means that we have heard a response 162 * to our acceptance of their connection 163 * It is probably logically unnecessary in this 164 * implementation. 165 */ 166 case TCPS_SYN_RECEIVED: 167 if (si->si_did!=cb->s_sid) { 168 spp_istat.wrncon++; 169 goto drop; 170 } 171 #endif 172 nsp->nsp_fport = si->si_sport; 173 cb->s_timer[TCPT_REXMT] = 0; 174 cb->s_timer[TCPT_KEEP] = TCPTV_KEEP; 175 soisconnected(so); 176 cb->s_state = TCPS_ESTABLISHED; 177 break; 178 179 /* 180 * This state means that we have gotten a response 181 * to our attempt to establish a connection. 182 * We fill in the data from the other side, 183 * telling us which port to respond to, instead of the well- 184 * known one we might have sent to in the first place. 185 * We also require that this is a response to our 186 * connection id. 187 */ 188 case TCPS_SYN_SENT: 189 if (si->si_did!=cb->s_sid) { 190 spp_istat.notme++; 191 goto drop; 192 } 193 cb->s_did = si->si_sid; 194 cb->s_rack = si->si_ack; 195 cb->s_ralo = si->si_alo; 196 cb->s_dport = nsp->nsp_fport = si->si_sport; 197 cb->s_timer[TCPT_REXMT] = 0; 198 cb->s_flags |= SF_AK; 199 soisconnected(so); 200 cb->s_state = TCPS_ESTABLISHED; 201 } 202 if (so->so_options & SO_DEBUG || traceallspps) 203 spp_trace(SA_INPUT, (u_char)ostate, cb, &spp_savesi, 0); 204 205 m->m_len -= sizeof (struct idp); 206 m->m_off += sizeof (struct idp); 207 208 if (spp_reass(cb, si)) { 209 m_freem(m); 210 } 211 (void) spp_output(cb, (struct mbuf *)0); 212 return; 213 214 dropwithreset: 215 if (dropsocket) 216 (void) soabort(so); 217 si->si_seq = ntohs(si->si_seq); 218 si->si_ack = ntohs(si->si_ack); 219 si->si_alo = ntohs(si->si_alo); 220 ns_error(dtom(si), NS_ERR_NOSOCK, 0); 221 if (cb->s_nspcb->nsp_socket->so_options & SO_DEBUG || traceallspps) 222 spp_trace(SA_DROP, (u_char)ostate, cb, &spp_savesi, 0); 223 return; 224 225 drop: 226 bad: 227 if (cb == 0 || cb->s_nspcb->nsp_socket->so_options & SO_DEBUG || traceallspps) 228 spp_trace(SA_DROP, (u_char)ostate, cb, &spp_savesi, 0); 229 m_freem(m); 230 } 231 232 /* 233 * This is structurally similar to the tcp reassembly routine 234 * but its function is somewhat different: It merely queues 235 * packets up, and suppresses duplicates. 236 */ 237 spp_reass(cb, si) 238 register struct sppcb *cb; 239 register struct spidp *si; 240 { 241 register struct spidp_q *q; 242 register struct mbuf *m; 243 struct socket *so = cb->s_nspcb->nsp_socket; 244 struct sockbuf *sb = & (so->so_rcv); 245 char packetp = cb->s_flags & SF_HI; 246 char wakeup = 0; 247 248 249 if (si == SI(0)) 250 goto present; 251 /* 252 * Update our news from them. 253 */ 254 if (si->si_cc & SP_SA) 255 cb->s_flags |= (spp_use_delack ? SF_DELACK : SF_AK); 256 if (SSEQ_GT(si->si_ack, cb->s_rack)) { 257 cb->s_rack = si->si_ack; 258 /* 259 * If there are other packets outstanding, 260 * restart the timer for them. 261 */ 262 if (SSEQ_GEQ(cb->s_snt, si->si_ack)) { 263 TCPT_RANGESET(cb->s_timer[TCPT_REXMT], 264 tcp_beta * cb->s_srtt, TCPTV_MIN, 265 TCPTV_MAX); 266 cb->s_rxtshift = 0; 267 } else 268 cb->s_timer[TCPT_REXMT] = 0; 269 /* 270 * If transmit timer is running and timed sequence 271 * number was acked, update smoothed round trip time. 272 */ 273 if (cb->s_rtt && SSEQ_GT(si->si_ack, cb->s_rtseq)) { 274 if (cb->s_srtt == 0) 275 cb->s_srtt = cb->s_rtt; 276 else 277 cb->s_srtt = 278 tcp_alpha * cb->s_srtt + 279 (1 - tcp_alpha) * cb->s_rtt; 280 cb->s_rtt = 0; 281 } 282 } 283 if (SSEQ_GT(si->si_alo, cb->s_ralo)) { 284 cb->s_ralo = si->si_alo; 285 cb->s_timer[TCPT_PERSIST] = 0; 286 } 287 /* 288 * If this is a system packet, we don't need to 289 * queue it up, and won't update acknowledge # 290 */ 291 if (si->si_cc & SP_SP) { 292 m_freem(dtom(si)); 293 return (0); 294 } 295 296 /* 297 * If this packet number has a sequence number less 298 * than that of the first packet not yet seen coming 299 * from them, this must be a duplicate, so drop. 300 */ 301 if (SSEQ_LT(si->si_seq, cb->s_ack)) { 302 spp_istat.bdreas++; 303 if (si->si_seq == cb->s_ack-1) 304 spp_istat.lstdup++; 305 return (1); 306 } 307 /* 308 * If this packet number is higher than that which 309 * we have allocated refuse it, unless urgent 310 */ 311 if (SSEQ_GT(si->si_seq, cb->s_alo)) { 312 if (si->si_cc & SP_OB) { 313 if (SSEQ_GT(si->si_seq, cb->s_alo + 60)) { 314 ns_error(dtom(si), NS_ERR_FULLUP, 0); 315 return (0); 316 } /* else queue this packet; */ 317 } else { 318 spp_istat.notyet++; 319 return (1); 320 } 321 } 322 323 /* 324 * Loop through all packets queued up to insert in 325 * appropriate sequence. 326 */ 327 328 for (q = cb->s_q.si_next; q!=&cb->s_q; q = q->si_next) { 329 if (si->si_seq == SI(q)->si_seq) return (1); /*duplicate */ 330 if (SSEQ_LT(si->si_seq, SI(q)->si_seq)) break; 331 } 332 insque(si, q->si_prev); 333 /* 334 * If this packet is urgent, inform process 335 */ 336 if (si->si_cc & SP_OB) { 337 cb->s_iobc = ((char *)si)[1 + sizeof(*si)]; 338 sohasoutofband(so); 339 cb->s_oobflags |= SF_IOOB; 340 } 341 present: 342 #define SPINC sizeof(struct sphdr) 343 /* 344 * Loop through all packets queued up to update acknowledge 345 * number, and present all acknowledged data to user; 346 * If in packet interface mode, show packet headers. 347 */ 348 for (q = cb->s_q.si_next; q!=&cb->s_q; q = q->si_next) { 349 if (SI(q)->si_seq == cb->s_ack) { 350 cb->s_ack++; 351 m = dtom(q); 352 if (SI(q)->si_cc & SP_OB) { 353 cb->s_oobflags &= ~SF_IOOB; 354 if (sb->sb_cc) 355 so->so_oobmark = sb->sb_cc; 356 else 357 so->so_state |= SS_RCVATMARK; 358 } 359 q = q->si_prev; 360 remque(q->si_next); 361 wakeup = 1; 362 if (packetp) { 363 sbappendrecord(sb, m); 364 } else { 365 cb->s_rhdr = *mtod(m, struct sphdr *); 366 m->m_off += SPINC; 367 m->m_len -= SPINC; 368 sbappend(sb, m); 369 } 370 } else 371 break; 372 } 373 if (wakeup) sorwakeup(so); 374 return (0); 375 } 376 377 spp_ctlinput(cmd, arg) 378 int cmd; 379 caddr_t arg; 380 { 381 struct ns_addr *na; 382 extern u_char nsctlerrmap[]; 383 extern spp_abort(); 384 extern struct nspcb *idp_drop(); 385 struct ns_errp *errp; 386 struct nspcb *nsp; 387 struct sockaddr_ns *sns; 388 int type; 389 390 if (cmd < 0 || cmd > PRC_NCMDS) 391 return; 392 type = NS_ERR_UNREACH_HOST; 393 394 switch (cmd) { 395 396 case PRC_ROUTEDEAD: 397 case PRC_QUENCH: 398 break; 399 400 case PRC_IFDOWN: 401 case PRC_HOSTDEAD: 402 case PRC_HOSTUNREACH: 403 sns = (struct sockaddr_ns *)arg; 404 if (sns->sns_family != AF_NS) 405 return; 406 na = &sns->sns_addr; 407 break; 408 409 default: 410 errp = (struct ns_errp *)arg; 411 na = &errp->ns_err_idp.idp_dna; 412 type = errp->ns_err_num; 413 type = ntohs((u_short)type); 414 } 415 switch (type) { 416 417 case NS_ERR_UNREACH_HOST: 418 ns_pcbnotify(na, (int)nsctlerrmap[cmd], spp_abort, (long) 0); 419 break; 420 421 case NS_ERR_TOO_BIG: 422 case NS_ERR_NOSOCK: 423 nsp = ns_pcblookup(na, errp->ns_err_idp.idp_sna.x_port, 424 NS_WILDCARD); 425 if (nsp) { 426 if(nsp->nsp_pcb) 427 (void) spp_drop((struct sppcb *)nsp->nsp_pcb, 428 (int)nsctlerrmap[cmd]); 429 else 430 (void) idp_drop(nsp, (int)nsctlerrmap[cmd]); 431 } 432 } 433 } 434 435 #ifdef notdef 436 int 437 spp_fixmtu(nsp) 438 register struct nspcb *nsp; 439 { 440 register struct sppcb *cb = (struct sppcb *)(nsp->nsp_pcb); 441 register struct mbuf *m; 442 register struct spidp *si; 443 struct ns_errp *ep; 444 struct sockbuf *sb; 445 int badseq, len; 446 struct mbuf *firstbad, *m0; 447 448 if (cb) { 449 /* 450 * The notification that we have sent 451 * too much is bad news -- we will 452 * have to go through queued up so far 453 * splitting ones which are too big and 454 * reassigning sequence numbers and checksums. 455 * we should then retransmit all packets from 456 * one above the offending packet to the last one 457 * we had sent (or our allocation) 458 * then the offending one so that the any queued 459 * data at our destination will be discarded. 460 */ 461 ep = (struct ns_errp *)nsp->nsp_notify_param; 462 sb = &nsp->nsp_socket->so_snd; 463 cb->s_mtu = ep->ns_err_param; 464 badseq = SI(&ep->ns_err_idp)->si_seq; 465 for (m = sb->sb_mb; m; m = m->m_act) { 466 si = mtod(m, struct spidp *); 467 if (si->si_seq == badseq) 468 break; 469 } 470 if (m == 0) return; 471 firstbad = m; 472 /*for (;;) {*/ 473 /* calculate length */ 474 for (m0 = m, len = 0; m ; m = m->m_next) 475 len += m->m_len; 476 if (len > cb->s_mtu) { 477 } 478 /* FINISH THIS 479 } */ 480 } 481 } 482 #endif 483 484 int spp_output_cnt = 0; 485 486 spp_output(cb, m0) 487 register struct sppcb *cb; 488 struct mbuf *m0; 489 { 490 struct socket *so = cb->s_nspcb->nsp_socket; 491 register struct mbuf *m; 492 register struct spidp *si = (struct spidp *) 0; 493 register struct sockbuf *sb = &(so->so_snd); 494 register int len = 0; 495 int error = 0; 496 u_short lookfor = 0; 497 struct mbuf *mprev; 498 extern int idpcksum; 499 500 if (m0) { 501 int mtu = cb->s_mtu; 502 int datalen; 503 /* 504 * Make sure that packet isn't too big. 505 */ 506 for (m = m0; m ; m = m->m_next) { 507 mprev = m; 508 len += m->m_len; 509 } 510 datalen = (cb->s_flags & SF_HO) ? 511 len - sizeof (struct sphdr) : len; 512 if (datalen > mtu) { 513 if (cb->s_flags & SF_PI) { 514 m_freem(m0); 515 return (EMSGSIZE); 516 } else { 517 int off = 0; 518 int oldEM = cb->s_cc & SP_EM; 519 520 cb->s_cc &= ~SP_EM; 521 while (len > mtu) { 522 m = m_copy(m0, off, mtu); 523 if (m == NULL) { 524 error = ENOBUFS; 525 goto bad_copy; 526 } 527 error = spp_output(cb, m); 528 if (error) { 529 bad_copy: 530 cb->s_cc |= oldEM; 531 m_freem(m0); 532 return(error); 533 } 534 m_adj(m0, mtu); 535 len -= mtu; 536 } 537 cb->s_cc |= oldEM; 538 } 539 } 540 /* 541 * Force length even, by adding a "garbage byte" if 542 * necessary. 543 */ 544 if (len & 1) { 545 m = mprev; 546 if (m->m_len + m->m_off < MMAXOFF) 547 m->m_len++; 548 else { 549 struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA); 550 551 if (m1 == 0) { 552 m_freem(m0); 553 return (ENOBUFS); 554 } 555 m1->m_len = 1; 556 m1->m_off = MMAXOFF - 1; 557 m->m_next = m1; 558 } 559 } 560 m = m_get(M_DONTWAIT, MT_HEADER); 561 if (m == 0) { 562 m_freem(m0); 563 return (ENOBUFS); 564 } 565 /* 566 * Fill in mbuf with extended SP header 567 * and addresses and length put into network format. 568 */ 569 m->m_off = MMAXOFF - sizeof (struct spidp); 570 m->m_len = sizeof (struct spidp); 571 m->m_next = m0; 572 si = mtod(m, struct spidp *); 573 *si = cb->s_shdr; 574 if ((cb->s_flags & SF_PI) && (cb->s_flags & SF_HO)) { 575 register struct sphdr *sh; 576 if (m0->m_len < sizeof (*sh)) { 577 if((m0 = m_pullup(m0, sizeof(*sh))) == NULL) { 578 (void) m_free(m); 579 m_freem(m0); 580 return (EINVAL); 581 } 582 m->m_next = m0; 583 } 584 sh = mtod(m0, struct sphdr *); 585 si->si_dt = sh->sp_dt; 586 si->si_cc |= sh->sp_cc & SP_EM; 587 m0->m_len -= sizeof (*sh); 588 m0->m_off += sizeof (*sh); 589 len -= sizeof (*sh); 590 } 591 len += sizeof(*si); 592 if (cb->s_oobflags & SF_SOOB) { 593 /* 594 * Per jqj@cornell: 595 * make sure OB packets convey exactly 1 byte. 596 * If the packet is 1 byte or larger, we 597 * have already guaranted there to be at least 598 * one garbage byte for the checksum, and 599 * extra bytes shouldn't hurt! 600 */ 601 if (len > sizeof(*si)) { 602 si->si_cc |= SP_OB; 603 len = (1 + sizeof(*si)); 604 } 605 } 606 si->si_len = htons((u_short)len); 607 /* 608 * queue stuff up for output 609 */ 610 sbappendrecord(sb, m); 611 cb->s_seq++; 612 } 613 /* 614 * update window 615 */ 616 { 617 register struct sockbuf *sb2 = &so->so_rcv; 618 int credit = ((sb2->sb_mbmax - sb2->sb_mbcnt) / 619 ((short)cb->s_mtu)); 620 int alo = cb->s_ack + (credit > 0 ? credit : 0) - 1; 621 622 if (cb->s_alo < alo) { 623 /* If the amount we are raising the window 624 is more than his remaining headroom, tell 625 him about it. In particular, if he is at 626 his limit, any amount at all will do! */ 627 u_short raise = alo - cb->s_alo; 628 u_short headroom = 1 + cb->s_alo - cb->s_ack; 629 630 if(SSEQ_LT(headroom, raise)) 631 cb->s_flags |= SF_AK; 632 cb->s_alo = alo; 633 } 634 } 635 636 if (cb->s_oobflags & SF_SOOB) { 637 /* 638 * must transmit this out of band packet 639 */ 640 cb->s_oobflags &= ~ SF_SOOB; 641 } else { 642 /* 643 * Decide what to transmit: 644 * If it is time to retransmit a packet, 645 * send that. 646 * If we have a new packet, send that 647 * (So long as it is in our allocation) 648 * Otherwise, see if it time to bang on them 649 * to ask for our current allocation. 650 */ 651 if (cb->s_force == (1+TCPT_REXMT)) { 652 lookfor = cb->s_rack; 653 } else if (SSEQ_LT(cb->s_snt, cb->s_ralo)) { 654 lookfor = cb->s_snt + 1; 655 } else if (SSEQ_LT(cb->s_ralo, cb->s_seq)) { 656 lookfor = 0; 657 if (cb->s_timer[TCPT_PERSIST] == 0) { 658 spp_setpersist(cb); 659 /* tcp has cb->s_rxtshift = 0; here */ 660 } 661 } 662 m = sb->sb_mb; 663 while (m) { 664 si = mtod(m, struct spidp *); 665 m = m->m_act; 666 if (SSEQ_LT(si->si_seq, cb->s_rack)) { 667 if ((sb->sb_flags & SB_WAIT) 668 || so->so_snd.sb_sel) 669 sowwakeup(so); 670 sbdroprecord(sb); 671 si = 0; 672 continue; 673 } 674 if (SSEQ_LT(si->si_seq, lookfor)) 675 continue; 676 break; 677 } 678 if (si && (si->si_seq != lookfor)) 679 si = 0; 680 } 681 cb->s_want = lookfor; 682 683 if (si) { 684 /* 685 * must make a copy of this packet for 686 * idp_output to monkey with 687 */ 688 m = m_copy(dtom(si), 0, (int)M_COPYALL); 689 if (m == NULL) 690 return (ENOBUFS); 691 m0 = m; 692 si = mtod(m, struct spidp *); 693 } else if (cb->s_force || cb->s_flags & SF_AK) { 694 /* 695 * Must send an acknowledgement or a probe 696 */ 697 m = m_get(M_DONTWAIT, MT_HEADER); 698 if (m == 0) 699 return (ENOBUFS); 700 /* 701 * Fill in mbuf with extended SP header 702 * and addresses and length put into network format. 703 */ 704 m->m_off = MMAXOFF - sizeof (struct spidp); 705 m->m_len = sizeof (*si); 706 m->m_next = 0; 707 si = mtod(m, struct spidp *); 708 *si = cb->s_shdr; 709 si->si_seq = cb->s_snt + 1; 710 si->si_len = htons(sizeof (*si)); 711 si->si_cc |= SP_SP; 712 } 713 /* 714 * Stuff checksum and output datagram. 715 */ 716 if (si) { 717 if (cb->s_flags & (SF_AK|SF_DELACK)) 718 cb->s_flags &= ~(SF_AK|SF_DELACK); 719 /* 720 * If we are almost out of allocation 721 * or one of the timers has gone off 722 * request an ack. 723 */ 724 if (SSEQ_GEQ(cb->s_seq, cb->s_ralo)) 725 si->si_cc |= SP_SA; 726 if (cb->s_force) { 727 si->si_cc |= SP_SA; 728 cb->s_force = 0; 729 } 730 /* 731 * If this is a new packet (and not a system packet), 732 * and we are not currently timing anything, 733 * time this one and ask for an ack. 734 */ 735 if (SSEQ_LT(cb->s_snt, si->si_seq) && (!(si->si_cc & SP_SP))) { 736 cb->s_snt = si->si_seq; 737 if (cb->s_rtt == 0) { 738 cb->s_rtseq = si->si_seq; 739 cb->s_rtt = 1; 740 si->si_cc |= SP_SA; 741 } 742 /* 743 * If the retransmit timer has not been set 744 * and this is a real packet 745 * then start the retransmit timer 746 */ 747 if (cb->s_timer[TCPT_REXMT] == 0) { 748 TCPT_RANGESET(cb->s_timer[TCPT_REXMT], 749 tcp_beta * cb->s_srtt, TCPTV_MIN, 750 TCPTV_MAX); 751 cb->s_rxtshift = 0; 752 } 753 } 754 si->si_seq = htons(si->si_seq); 755 si->si_alo = htons(cb->s_alo); 756 si->si_ack = htons(cb->s_ack); 757 758 if (idpcksum) { 759 si->si_sum = 0; 760 len = ntohs(si->si_len); 761 if (len & 1) 762 len++; 763 si->si_sum = ns_cksum(dtom(si), len); 764 } else 765 si->si_sum = 0xffff; 766 767 if (so->so_options & SO_DEBUG || traceallspps) 768 spp_trace(SA_OUTPUT, cb->s_state, cb, si, 0); 769 spp_output_cnt++; 770 if (so->so_options & SO_DONTROUTE) 771 error = ns_output(m, (struct route *)0, NS_ROUTETOIF); 772 else 773 error = ns_output(m, &cb->s_nspcb->nsp_route, 0); 774 if (traceallspps && sppconsdebug) { 775 printf("spp_out: %x\n", error); 776 } 777 if (so->so_options & SO_DEBUG || traceallspps) 778 spp_trace(SA_OUTPUT, cb->s_state, cb, si, 0); 779 } 780 return (error); 781 } 782 783 /*ARGSUSED*/ 784 spp_ctloutput(req, so, level, name, value) 785 int req; 786 struct socket *so; 787 int name; 788 struct mbuf **value; 789 { 790 register struct mbuf *m; 791 struct nspcb *nsp = sotonspcb(so); 792 register struct sppcb *cb; 793 int mask, error = 0; 794 795 if (level != NSPROTO_SPP) { 796 /* This will have to be changed when we do more general 797 stacking of protocols */ 798 return (idp_ctloutput(req, so, level, name, value)); 799 } 800 if (nsp == NULL) { 801 error = EINVAL; 802 goto release; 803 } else 804 cb = nstosppcb(nsp); 805 806 switch (req) { 807 808 case PRCO_GETOPT: 809 if (value == NULL) 810 return (EINVAL); 811 m = m_get(M_DONTWAIT, MT_DATA); 812 if (m == NULL) 813 return (ENOBUFS); 814 switch (name) { 815 816 case SO_HEADERS_ON_INPUT: 817 mask = SF_HI; 818 goto get_flags; 819 820 case SO_HEADERS_ON_OUTPUT: 821 mask = SF_HO; 822 get_flags: 823 m->m_len = sizeof(short); 824 m->m_off = MMAXOFF - sizeof(short); 825 *mtod(m, short *) = cb->s_flags & mask; 826 break; 827 828 case SO_MTU: 829 m->m_len = sizeof(u_short); 830 m->m_off = MMAXOFF - sizeof(short); 831 *mtod(m, short *) = cb->s_mtu; 832 break; 833 834 case SO_LAST_HEADER: 835 m->m_len = sizeof(struct sphdr); 836 m->m_off = MMAXOFF - sizeof(struct sphdr); 837 *mtod(m, struct sphdr *) = cb->s_rhdr; 838 break; 839 840 case SO_DEFAULT_HEADERS: 841 m->m_len = sizeof(struct spidp); 842 m->m_off = MMAXOFF - sizeof(struct sphdr); 843 *mtod(m, struct sphdr *) = cb->s_shdr.si_s; 844 break; 845 846 default: 847 error = EINVAL; 848 } 849 *value = m; 850 break; 851 852 case PRCO_SETOPT: 853 if (value == 0 || *value == 0) { 854 error = EINVAL; 855 break; 856 } 857 switch (name) { 858 int *ok; 859 860 case SO_HEADERS_ON_INPUT: 861 mask = SF_HI; 862 goto set_head; 863 864 case SO_HEADERS_ON_OUTPUT: 865 mask = SF_HO; 866 set_head: 867 if (cb->s_flags & SF_PI) { 868 ok = mtod(*value, int *); 869 if (*ok) 870 cb->s_flags |= mask; 871 else 872 cb->s_flags &= ~mask; 873 } else error = EINVAL; 874 break; 875 876 case SO_MTU: 877 cb->s_mtu = *(mtod(*value, u_short *)); 878 break; 879 880 case SO_DEFAULT_HEADERS: 881 { 882 register struct sphdr *sp 883 = mtod(*value, struct sphdr *); 884 cb->s_dt = sp->sp_dt; 885 cb->s_cc = sp->sp_cc & SP_EM; 886 } 887 break; 888 889 default: 890 error = EINVAL; 891 } 892 m_freem(*value); 893 break; 894 } 895 release: 896 return (error); 897 } 898 899 /*ARGSUSED*/ 900 spp_usrreq(so, req, m, nam, rights) 901 struct socket *so; 902 int req; 903 struct mbuf *m, *nam, *rights; 904 { 905 struct nspcb *nsp = sotonspcb(so); 906 register struct sppcb *cb; 907 int s = splnet(); 908 int error = 0, ostate; 909 910 if (req == PRU_CONTROL) 911 return (ns_control(so, (int)m, (caddr_t)nam, 912 (struct ifnet *)rights)); 913 if (rights && rights->m_len) { 914 error = EINVAL; 915 goto release; 916 } 917 if (nsp == NULL) { 918 if (req != PRU_ATTACH) { 919 error = EINVAL; 920 goto release; 921 } 922 } else 923 cb = nstosppcb(nsp); 924 925 ostate = cb ? cb->s_state : 0; 926 927 switch (req) { 928 929 case PRU_ATTACH: 930 if (nsp != NULL) { 931 error = EISCONN; 932 break; 933 } 934 error = ns_pcballoc(so, &nspcb); 935 if (error) 936 break; 937 error = soreserve(so, 2048, 2048); 938 if (error) 939 break; 940 nsp = sotonspcb(so); 941 { 942 struct mbuf *mm = m_getclr(M_DONTWAIT, MT_PCB); 943 944 if (mm == NULL) { 945 error = ENOBUFS; 946 break; 947 } 948 cb = mtod(mm, struct sppcb *); 949 cb->s_state = TCPS_LISTEN; 950 cb->s_snt = -1; 951 cb->s_q.si_next = cb->s_q.si_prev = &cb->s_q; 952 cb->s_nspcb = nsp; 953 nsp->nsp_pcb = (caddr_t) cb; 954 } 955 break; 956 957 case PRU_DETACH: 958 if (nsp == NULL) { 959 error = ENOTCONN; 960 break; 961 } 962 if (cb->s_state > TCPS_LISTEN) 963 cb = spp_disconnect(cb); 964 else 965 cb = spp_close(cb); 966 break; 967 968 case PRU_BIND: 969 error = ns_pcbbind(nsp, nam); 970 break; 971 972 case PRU_LISTEN: 973 if (nsp->nsp_lport == 0) 974 error = ns_pcbbind(nsp, (struct mbuf *)0); 975 if (error == 0) 976 cb->s_state = TCPS_LISTEN; 977 break; 978 979 /* 980 * Initiate connection to peer. 981 * Enter SYN_SENT state, and mark socket as connecting. 982 * Start keep-alive timer, setup prototype header, 983 * Send initial system packet requesting connection. 984 */ 985 case PRU_CONNECT: 986 if (nsp->nsp_lport == 0) { 987 error = ns_pcbbind(nsp, (struct mbuf *)0); 988 if (error) 989 break; 990 } 991 error = ns_pcbconnect(nsp, nam); 992 if (error) 993 break; 994 soisconnecting(so); 995 cb->s_state = TCPS_SYN_SENT; 996 cb->s_did = 0; 997 spp_template(cb); 998 cb->s_timer[TCPT_KEEP] = TCPTV_KEEP; 999 cb->s_force = 1 + TCPTV_KEEP; 1000 /* 1001 * Other party is required to respond to 1002 * the port I send from, but he is not 1003 * required to answer from where I am sending to, 1004 * so allow wildcarding. 1005 * original port I am sending to is still saved in 1006 * cb->s_dport. 1007 */ 1008 nsp->nsp_fport = 0; 1009 error = spp_output(cb, (struct mbuf *) 0); 1010 break; 1011 1012 case PRU_CONNECT2: 1013 error = EOPNOTSUPP; 1014 break; 1015 1016 /* 1017 * We may decide later to implement connection closing 1018 * handshaking at the spp level optionally. 1019 * here is the hook to do it: 1020 */ 1021 case PRU_DISCONNECT: 1022 cb = spp_disconnect(cb); 1023 break; 1024 1025 /* 1026 * Accept a connection. Essentially all the work is 1027 * done at higher levels; just return the address 1028 * of the peer, storing through addr. 1029 */ 1030 case PRU_ACCEPT: { 1031 struct sockaddr_ns *sns = mtod(nam, struct sockaddr_ns *); 1032 1033 nam->m_len = sizeof (struct sockaddr_ns); 1034 sns->sns_family = AF_NS; 1035 sns->sns_addr = nsp->nsp_faddr; 1036 break; 1037 } 1038 1039 case PRU_SHUTDOWN: 1040 socantsendmore(so); 1041 cb = spp_usrclosed(cb); 1042 if (cb) 1043 error = spp_output(cb, (struct mbuf *) 0); 1044 break; 1045 1046 /* 1047 * After a receive, possibly send acknowledgment 1048 * updating allocation. 1049 */ 1050 case PRU_RCVD: 1051 (void) spp_output(cb, (struct mbuf *) 0); 1052 break; 1053 1054 case PRU_SEND: 1055 error = spp_output(cb, m); 1056 m = NULL; 1057 break; 1058 1059 case PRU_ABORT: 1060 (void) spp_drop(cb, ECONNABORTED); 1061 break; 1062 1063 case PRU_SENSE: 1064 case PRU_CONTROL: 1065 m = NULL; 1066 error = EOPNOTSUPP; 1067 break; 1068 1069 case PRU_RCVOOB: 1070 if ((cb->s_oobflags & SF_IOOB) || so->so_oobmark || 1071 (so->so_state & SS_RCVATMARK)) { 1072 m->m_len = 1; 1073 *mtod(m, caddr_t) = cb->s_iobc; 1074 break; 1075 } 1076 error = EINVAL; 1077 break; 1078 1079 case PRU_SENDOOB: 1080 if (sbspace(&so->so_snd) < -512) { 1081 m_freem(m); 1082 error = ENOBUFS; 1083 break; 1084 } 1085 cb->s_oobflags |= SF_SOOB; 1086 error = spp_output(cb, m); 1087 m = NULL; 1088 break; 1089 1090 case PRU_SOCKADDR: 1091 ns_setsockaddr(nsp, nam); 1092 break; 1093 1094 case PRU_PEERADDR: 1095 ns_setpeeraddr(nsp, nam); 1096 break; 1097 1098 case PRU_SLOWTIMO: 1099 cb = spp_timers(cb, (int)nam); 1100 break; 1101 1102 case PRU_FASTTIMO: 1103 case PRU_PROTORCV: 1104 case PRU_PROTOSEND: 1105 error = EOPNOTSUPP; 1106 break; 1107 1108 default: 1109 panic("sp_usrreq"); 1110 } 1111 if (cb && (so->so_options & SO_DEBUG || traceallspps)) 1112 spp_trace(SA_USER, (u_char)ostate, cb, (struct spidp *)0, req); 1113 release: 1114 if (m != NULL) 1115 m_freem(m); 1116 splx(s); 1117 return (error); 1118 } 1119 1120 spp_usrreq_sp(so, req, m, nam, rights) 1121 struct socket *so; 1122 int req; 1123 struct mbuf *m, *nam, *rights; 1124 { 1125 int error = spp_usrreq(so, req, m, nam, rights); 1126 1127 if (req == PRU_ATTACH && error == 0) { 1128 struct nspcb *nsp = sotonspcb(so); 1129 ((struct sppcb *)nsp->nsp_pcb)->s_flags |= 1130 (SF_HI | SF_HO | SF_PI); 1131 } 1132 return (error); 1133 } 1134 1135 /* 1136 * Create template to be used to send spp packets on a connection. 1137 * Called after host entry created, fills 1138 * in a skeletal spp header (choosing connection id), 1139 * minimizing the amount of work necessary when the connection is used. 1140 */ 1141 spp_template(cb) 1142 struct sppcb *cb; 1143 { 1144 register struct nspcb *nsp = cb->s_nspcb; 1145 register struct spidp *n = &(cb->s_shdr); 1146 1147 cb->s_mtu = 576 - sizeof (struct spidp); 1148 n->si_pt = NSPROTO_SPP; 1149 n->si_sna = nsp->nsp_laddr; 1150 n->si_dna = nsp->nsp_faddr; 1151 n->si_sid = htons(spp_iss); 1152 spp_iss += SPP_ISSINCR/2; 1153 n->si_alo = 1; 1154 } 1155 1156 /* 1157 * Close a SPIP control block: 1158 * discard spp control block itself 1159 * discard ns protocol control block 1160 * wake up any sleepers 1161 */ 1162 struct sppcb * 1163 spp_close(cb) 1164 register struct sppcb *cb; 1165 { 1166 register struct spidp_q *s; 1167 struct nspcb *nsp = cb->s_nspcb; 1168 struct socket *so = nsp->nsp_socket; 1169 register struct mbuf *m; 1170 1171 s = cb->s_q.si_next; 1172 while (s != &(cb->s_q)) { 1173 s = s->si_next; 1174 m = dtom(s->si_prev); 1175 remque(s->si_prev); 1176 m_freem(m); 1177 } 1178 (void) m_free(dtom(cb)); 1179 nsp->nsp_pcb = 0; 1180 soisdisconnected(so); 1181 ns_pcbdetach(nsp); 1182 return ((struct sppcb *)0); 1183 } 1184 /* 1185 * Someday we may do level 3 handshaking 1186 * to close a connection or send a xerox style error. 1187 * For now, just close. 1188 */ 1189 struct sppcb * 1190 spp_usrclosed(cb) 1191 register struct sppcb *cb; 1192 { 1193 return (spp_close(cb)); 1194 } 1195 struct sppcb * 1196 spp_disconnect(cb) 1197 register struct sppcb *cb; 1198 { 1199 return (spp_close(cb)); 1200 } 1201 /* 1202 * Drop connection, reporting 1203 * the specified error. 1204 */ 1205 struct sppcb * 1206 spp_drop(cb, errno) 1207 register struct sppcb *cb; 1208 int errno; 1209 { 1210 struct socket *so = cb->s_nspcb->nsp_socket; 1211 1212 /* 1213 * someday, in the xerox world 1214 * we will generate error protocol packets 1215 * announcing that the socket has gone away. 1216 */ 1217 /*if (TCPS_HAVERCVDSYN(tp->t_state)) { 1218 tp->t_state = TCPS_CLOSED; 1219 (void) tcp_output(tp); 1220 }*/ 1221 so->so_error = errno; 1222 return (spp_close(cb)); 1223 } 1224 1225 spp_abort(nsp) 1226 struct nspcb *nsp; 1227 { 1228 1229 (void) spp_close((struct sppcb *)nsp->nsp_pcb); 1230 } 1231 1232 spp_setpersist(cb) 1233 register struct sppcb *cb; 1234 { 1235 1236 /*if (cb->s_timer[TCPT_REXMT]) 1237 panic("spp_output REXMT");*/ 1238 /* 1239 * Start/restart persistance timer. 1240 */ 1241 TCPT_RANGESET(cb->s_timer[TCPT_PERSIST], 1242 ((int)(tcp_beta * cb->s_srtt)) << cb->s_rxtshift, 1243 TCPTV_PERSMIN, TCPTV_MAX); 1244 cb->s_rxtshift++; 1245 if (cb->s_rxtshift >= TCP_MAXRXTSHIFT) 1246 cb->s_rxtshift = 0; 1247 } 1248 /* 1249 * Fast timeout routine for processing delayed acks 1250 */ 1251 int spp_ftcnt; 1252 spp_fasttimo() 1253 { 1254 register struct nspcb *nsp; 1255 register struct sppcb *cb; 1256 int s = splnet(); 1257 1258 nsp = nspcb.nsp_next; 1259 spp_ftcnt++; 1260 if (nsp) 1261 for (; nsp != &nspcb; nsp = nsp->nsp_next) 1262 if ((cb = (struct sppcb *)nsp->nsp_pcb) && 1263 (cb->s_flags & SF_DELACK)) { 1264 cb->s_flags &= ~SF_DELACK; 1265 cb->s_flags |= SF_AK; 1266 (void) spp_output(cb, (struct mbuf *) 0); 1267 } 1268 splx(s); 1269 } 1270 1271 /* 1272 * spp protocol timeout routine called every 500 ms. 1273 * Updates the timers in all active pcb's and 1274 * causes finite state machine actions if timers expire. 1275 */ 1276 spp_slowtimo() 1277 { 1278 register struct nspcb *ip, *ipnxt; 1279 register struct sppcb *cb; 1280 int s = splnet(); 1281 register int i; 1282 1283 /* 1284 * Search through tcb's and update active timers. 1285 */ 1286 ip = nspcb.nsp_next; 1287 if (ip == 0) { 1288 splx(s); 1289 return; 1290 } 1291 while (ip != &nspcb) { 1292 cb = nstosppcb(ip); 1293 ipnxt = ip->nsp_next; 1294 if (cb == 0) 1295 goto tpgone; 1296 for (i = 0; i < TCPT_NTIMERS; i++) { 1297 if (cb->s_timer[i] && --cb->s_timer[i] == 0) { 1298 (void) spp_usrreq(cb->s_nspcb->nsp_socket, 1299 PRU_SLOWTIMO, (struct mbuf *)0, 1300 (struct mbuf *)i, (struct mbuf *)0); 1301 if (ipnxt->nsp_prev != ip) 1302 goto tpgone; 1303 } 1304 } 1305 cb->s_idle++; 1306 if (cb->s_rtt) 1307 cb->s_rtt++; 1308 tpgone: 1309 ip = ipnxt; 1310 } 1311 spp_iss += SPP_ISSINCR/PR_SLOWHZ; /* increment iss */ 1312 splx(s); 1313 } 1314 1315 float spp_backoff[TCP_MAXRXTSHIFT] = 1316 { 1.0, 1.2, 1.4, 1.7, 2.0, 3.0, 5.0, 8.0, 16.0, 32.0 }; 1317 int sppexprexmtbackoff = 0; 1318 /* 1319 * SPP timer processing. 1320 */ 1321 struct sppcb * 1322 spp_timers(cb, timer) 1323 register struct sppcb *cb; 1324 int timer; 1325 { 1326 1327 cb->s_force = 1 + timer; 1328 switch (timer) { 1329 1330 /* 1331 * 2 MSL timeout in shutdown went off. Delete connection 1332 * control block. 1333 */ 1334 case TCPT_2MSL: 1335 cb = spp_close(cb); 1336 break; 1337 1338 /* 1339 * Retransmission timer went off. Message has not 1340 * been acked within retransmit interval. Back off 1341 * to a longer retransmit interval and retransmit all 1342 * unacknowledged messages in the window. 1343 */ 1344 case TCPT_REXMT: 1345 cb->s_rxtshift++; 1346 if (cb->s_rxtshift > TCP_MAXRXTSHIFT) { 1347 cb = spp_drop(cb, ETIMEDOUT); 1348 break; 1349 } 1350 (void) spp_output(cb, (struct mbuf *) 0); 1351 TCPT_RANGESET(cb->s_timer[TCPT_REXMT], 1352 (int)cb->s_srtt, TCPTV_MIN, TCPTV_MAX); 1353 if (sppexprexmtbackoff) { 1354 TCPT_RANGESET(cb->s_timer[TCPT_REXMT], 1355 cb->s_timer[TCPT_REXMT] << cb->s_rxtshift, 1356 TCPTV_MIN, TCPTV_MAX); 1357 } else { 1358 TCPT_RANGESET(cb->s_timer[TCPT_REXMT], 1359 cb->s_timer[TCPT_REXMT] * 1360 spp_backoff[cb->s_rxtshift - 1], 1361 TCPTV_MIN, TCPTV_MAX); 1362 } 1363 break; 1364 1365 /* 1366 * Persistance timer into zero window. 1367 * Force a probe to be sent. 1368 */ 1369 case TCPT_PERSIST: 1370 (void) spp_output(cb, (struct mbuf *) 0); 1371 spp_setpersist(cb); 1372 break; 1373 1374 /* 1375 * Keep-alive timer went off; send something 1376 * or drop connection if idle for too long. 1377 */ 1378 case TCPT_KEEP: 1379 if (cb->s_state < TCPS_ESTABLISHED) 1380 goto dropit; 1381 if (cb->s_nspcb->nsp_socket->so_options & SO_KEEPALIVE) { 1382 if (cb->s_idle >= TCPTV_MAXIDLE) 1383 goto dropit; 1384 (void) spp_output(cb, (struct mbuf *) 0); 1385 } else 1386 cb->s_idle = 0; 1387 cb->s_timer[TCPT_KEEP] = TCPTV_KEEP; 1388 break; 1389 dropit: 1390 cb = spp_drop(cb, ETIMEDOUT); 1391 break; 1392 } 1393 return (cb); 1394 } 1395