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.16 (Berkeley) 12/18/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 * Long align so prepended ip headers will work on Gould. 569 */ 570 m->m_off = MMAXOFF - sizeof (struct spidp) - 2; 571 m->m_len = sizeof (struct spidp); 572 m->m_next = m0; 573 si = mtod(m, struct spidp *); 574 *si = cb->s_shdr; 575 if ((cb->s_flags & SF_PI) && (cb->s_flags & SF_HO)) { 576 register struct sphdr *sh; 577 if (m0->m_len < sizeof (*sh)) { 578 if((m0 = m_pullup(m0, sizeof(*sh))) == NULL) { 579 (void) m_free(m); 580 m_freem(m0); 581 return (EINVAL); 582 } 583 m->m_next = m0; 584 } 585 sh = mtod(m0, struct sphdr *); 586 si->si_dt = sh->sp_dt; 587 si->si_cc |= sh->sp_cc & SP_EM; 588 m0->m_len -= sizeof (*sh); 589 m0->m_off += sizeof (*sh); 590 len -= sizeof (*sh); 591 } 592 len += sizeof(*si); 593 if (cb->s_oobflags & SF_SOOB) { 594 /* 595 * Per jqj@cornell: 596 * make sure OB packets convey exactly 1 byte. 597 * If the packet is 1 byte or larger, we 598 * have already guaranted there to be at least 599 * one garbage byte for the checksum, and 600 * extra bytes shouldn't hurt! 601 */ 602 if (len > sizeof(*si)) { 603 si->si_cc |= SP_OB; 604 len = (1 + sizeof(*si)); 605 } 606 } 607 si->si_len = htons((u_short)len); 608 /* 609 * queue stuff up for output 610 */ 611 sbappendrecord(sb, m); 612 cb->s_seq++; 613 } 614 /* 615 * update window 616 */ 617 { 618 register struct sockbuf *sb2 = &so->so_rcv; 619 int credit = ((((int)sb2->sb_mbmax) - (int)sb2->sb_mbcnt) / 620 ((short)cb->s_mtu)); 621 int alo = cb->s_ack + (credit > 0 ? credit : 0) - 1; 622 623 if (cb->s_alo < alo) { 624 /* If the amount we are raising the window 625 is more than his remaining headroom, tell 626 him about it. In particular, if he is at 627 his limit, any amount at all will do! */ 628 u_short raise = alo - cb->s_alo; 629 u_short headroom = 1 + cb->s_alo - cb->s_ack; 630 631 if(SSEQ_LT(headroom, raise)) 632 cb->s_flags |= SF_AK; 633 cb->s_alo = alo; 634 } 635 } 636 637 if (cb->s_oobflags & SF_SOOB) { 638 /* 639 * must transmit this out of band packet 640 */ 641 cb->s_oobflags &= ~ SF_SOOB; 642 } else { 643 /* 644 * Decide what to transmit: 645 * If it is time to retransmit a packet, 646 * send that. 647 * If we have a new packet, send that 648 * (So long as it is in our allocation) 649 * Otherwise, see if it time to bang on them 650 * to ask for our current allocation. 651 */ 652 if (cb->s_force == (1+TCPT_REXMT)) { 653 lookfor = cb->s_rack; 654 } else if (SSEQ_LT(cb->s_snt, cb->s_ralo)) { 655 lookfor = cb->s_snt + 1; 656 } else if (SSEQ_LT(cb->s_ralo, cb->s_seq)) { 657 lookfor = 0; 658 if (cb->s_timer[TCPT_PERSIST] == 0) { 659 spp_setpersist(cb); 660 /* tcp has cb->s_rxtshift = 0; here */ 661 } 662 } 663 m = sb->sb_mb; 664 while (m) { 665 si = mtod(m, struct spidp *); 666 m = m->m_act; 667 if (SSEQ_LT(si->si_seq, cb->s_rack)) { 668 if ((sb->sb_flags & SB_WAIT) 669 || so->so_snd.sb_sel) 670 sowwakeup(so); 671 sbdroprecord(sb); 672 si = 0; 673 continue; 674 } 675 if (SSEQ_LT(si->si_seq, lookfor)) 676 continue; 677 break; 678 } 679 if (si && (si->si_seq != lookfor)) 680 si = 0; 681 } 682 cb->s_want = lookfor; 683 684 if (si) { 685 /* 686 * must make a copy of this packet for 687 * idp_output to monkey with 688 */ 689 m = m_copy(dtom(si), 0, (int)M_COPYALL); 690 if (m == NULL) 691 return (ENOBUFS); 692 m0 = m; 693 si = mtod(m, struct spidp *); 694 } else if (cb->s_force || cb->s_flags & SF_AK) { 695 /* 696 * Must send an acknowledgement or a probe 697 */ 698 m = m_get(M_DONTWAIT, MT_HEADER); 699 if (m == 0) 700 return (ENOBUFS); 701 /* 702 * Fill in mbuf with extended SP header 703 * and addresses and length put into network format. 704 */ 705 m->m_off = MMAXOFF - sizeof (struct spidp); 706 m->m_len = sizeof (*si); 707 m->m_next = 0; 708 si = mtod(m, struct spidp *); 709 *si = cb->s_shdr; 710 si->si_seq = cb->s_snt + 1; 711 si->si_len = htons(sizeof (*si)); 712 si->si_cc |= SP_SP; 713 } 714 /* 715 * Stuff checksum and output datagram. 716 */ 717 if (si) { 718 if (cb->s_flags & (SF_AK|SF_DELACK)) 719 cb->s_flags &= ~(SF_AK|SF_DELACK); 720 /* 721 * If we are almost out of allocation 722 * or one of the timers has gone off 723 * request an ack. 724 */ 725 if (SSEQ_GEQ(cb->s_seq, cb->s_ralo)) 726 si->si_cc |= SP_SA; 727 if (cb->s_force) { 728 si->si_cc |= SP_SA; 729 cb->s_force = 0; 730 } 731 /* 732 * If this is a new packet (and not a system packet), 733 * and we are not currently timing anything, 734 * time this one and ask for an ack. 735 */ 736 if (SSEQ_LT(cb->s_snt, si->si_seq) && (!(si->si_cc & SP_SP))) { 737 cb->s_snt = si->si_seq; 738 if (cb->s_rtt == 0) { 739 cb->s_rtseq = si->si_seq; 740 cb->s_rtt = 1; 741 si->si_cc |= SP_SA; 742 } 743 /* 744 * If the retransmit timer has not been set 745 * and this is a real packet 746 * then start the retransmit timer 747 */ 748 if (cb->s_timer[TCPT_REXMT] == 0) { 749 TCPT_RANGESET(cb->s_timer[TCPT_REXMT], 750 tcp_beta * cb->s_srtt, TCPTV_MIN, 751 TCPTV_MAX); 752 cb->s_rxtshift = 0; 753 } 754 } 755 si->si_seq = htons(si->si_seq); 756 si->si_alo = htons(cb->s_alo); 757 si->si_ack = htons(cb->s_ack); 758 759 if (idpcksum) { 760 si->si_sum = 0; 761 len = ntohs(si->si_len); 762 if (len & 1) 763 len++; 764 si->si_sum = ns_cksum(dtom(si), len); 765 } else 766 si->si_sum = 0xffff; 767 768 if (so->so_options & SO_DEBUG || traceallspps) 769 spp_trace(SA_OUTPUT, cb->s_state, cb, si, 0); 770 spp_output_cnt++; 771 if (so->so_options & SO_DONTROUTE) 772 error = ns_output(m, (struct route *)0, NS_ROUTETOIF); 773 else 774 error = ns_output(m, &cb->s_nspcb->nsp_route, 0); 775 if (traceallspps && sppconsdebug) { 776 printf("spp_out: %x\n", error); 777 } 778 if (so->so_options & SO_DEBUG || traceallspps) 779 spp_trace(SA_OUTPUT, cb->s_state, cb, si, 0); 780 } 781 return (error); 782 } 783 784 /*ARGSUSED*/ 785 spp_ctloutput(req, so, level, name, value) 786 int req; 787 struct socket *so; 788 int name; 789 struct mbuf **value; 790 { 791 register struct mbuf *m; 792 struct nspcb *nsp = sotonspcb(so); 793 register struct sppcb *cb; 794 int mask, error = 0; 795 796 if (level != NSPROTO_SPP) { 797 /* This will have to be changed when we do more general 798 stacking of protocols */ 799 return (idp_ctloutput(req, so, level, name, value)); 800 } 801 if (nsp == NULL) { 802 error = EINVAL; 803 goto release; 804 } else 805 cb = nstosppcb(nsp); 806 807 switch (req) { 808 809 case PRCO_GETOPT: 810 if (value == NULL) 811 return (EINVAL); 812 m = m_get(M_DONTWAIT, MT_DATA); 813 if (m == NULL) 814 return (ENOBUFS); 815 switch (name) { 816 817 case SO_HEADERS_ON_INPUT: 818 mask = SF_HI; 819 goto get_flags; 820 821 case SO_HEADERS_ON_OUTPUT: 822 mask = SF_HO; 823 get_flags: 824 m->m_len = sizeof(short); 825 m->m_off = MMAXOFF - sizeof(short); 826 *mtod(m, short *) = cb->s_flags & mask; 827 break; 828 829 case SO_MTU: 830 m->m_len = sizeof(u_short); 831 m->m_off = MMAXOFF - sizeof(short); 832 *mtod(m, short *) = cb->s_mtu; 833 break; 834 835 case SO_LAST_HEADER: 836 m->m_len = sizeof(struct sphdr); 837 m->m_off = MMAXOFF - sizeof(struct sphdr); 838 *mtod(m, struct sphdr *) = cb->s_rhdr; 839 break; 840 841 case SO_DEFAULT_HEADERS: 842 m->m_len = sizeof(struct spidp); 843 m->m_off = MMAXOFF - sizeof(struct sphdr); 844 *mtod(m, struct sphdr *) = cb->s_shdr.si_s; 845 break; 846 847 default: 848 error = EINVAL; 849 } 850 *value = m; 851 break; 852 853 case PRCO_SETOPT: 854 if (value == 0 || *value == 0) { 855 error = EINVAL; 856 break; 857 } 858 switch (name) { 859 int *ok; 860 861 case SO_HEADERS_ON_INPUT: 862 mask = SF_HI; 863 goto set_head; 864 865 case SO_HEADERS_ON_OUTPUT: 866 mask = SF_HO; 867 set_head: 868 if (cb->s_flags & SF_PI) { 869 ok = mtod(*value, int *); 870 if (*ok) 871 cb->s_flags |= mask; 872 else 873 cb->s_flags &= ~mask; 874 } else error = EINVAL; 875 break; 876 877 case SO_MTU: 878 cb->s_mtu = *(mtod(*value, u_short *)); 879 break; 880 881 case SO_DEFAULT_HEADERS: 882 { 883 register struct sphdr *sp 884 = mtod(*value, struct sphdr *); 885 cb->s_dt = sp->sp_dt; 886 cb->s_cc = sp->sp_cc & SP_EM; 887 } 888 break; 889 890 default: 891 error = EINVAL; 892 } 893 m_freem(*value); 894 break; 895 } 896 release: 897 return (error); 898 } 899 900 /*ARGSUSED*/ 901 spp_usrreq(so, req, m, nam, rights) 902 struct socket *so; 903 int req; 904 struct mbuf *m, *nam, *rights; 905 { 906 struct nspcb *nsp = sotonspcb(so); 907 register struct sppcb *cb; 908 int s = splnet(); 909 int error = 0, ostate; 910 911 if (req == PRU_CONTROL) 912 return (ns_control(so, (int)m, (caddr_t)nam, 913 (struct ifnet *)rights)); 914 if (rights && rights->m_len) { 915 error = EINVAL; 916 goto release; 917 } 918 if (nsp == NULL) { 919 if (req != PRU_ATTACH) { 920 error = EINVAL; 921 goto release; 922 } 923 } else 924 cb = nstosppcb(nsp); 925 926 ostate = cb ? cb->s_state : 0; 927 928 switch (req) { 929 930 case PRU_ATTACH: 931 if (nsp != NULL) { 932 error = EISCONN; 933 break; 934 } 935 error = ns_pcballoc(so, &nspcb); 936 if (error) 937 break; 938 error = soreserve(so, 2048, 2048); 939 if (error) 940 break; 941 nsp = sotonspcb(so); 942 { 943 struct mbuf *mm = m_getclr(M_DONTWAIT, MT_PCB); 944 945 if (mm == NULL) { 946 error = ENOBUFS; 947 break; 948 } 949 cb = mtod(mm, struct sppcb *); 950 cb->s_state = TCPS_LISTEN; 951 cb->s_snt = -1; 952 cb->s_q.si_next = cb->s_q.si_prev = &cb->s_q; 953 cb->s_nspcb = nsp; 954 nsp->nsp_pcb = (caddr_t) cb; 955 } 956 break; 957 958 case PRU_DETACH: 959 if (nsp == NULL) { 960 error = ENOTCONN; 961 break; 962 } 963 if (cb->s_state > TCPS_LISTEN) 964 cb = spp_disconnect(cb); 965 else 966 cb = spp_close(cb); 967 break; 968 969 case PRU_BIND: 970 error = ns_pcbbind(nsp, nam); 971 break; 972 973 case PRU_LISTEN: 974 if (nsp->nsp_lport == 0) 975 error = ns_pcbbind(nsp, (struct mbuf *)0); 976 if (error == 0) 977 cb->s_state = TCPS_LISTEN; 978 break; 979 980 /* 981 * Initiate connection to peer. 982 * Enter SYN_SENT state, and mark socket as connecting. 983 * Start keep-alive timer, setup prototype header, 984 * Send initial system packet requesting connection. 985 */ 986 case PRU_CONNECT: 987 if (nsp->nsp_lport == 0) { 988 error = ns_pcbbind(nsp, (struct mbuf *)0); 989 if (error) 990 break; 991 } 992 error = ns_pcbconnect(nsp, nam); 993 if (error) 994 break; 995 soisconnecting(so); 996 cb->s_state = TCPS_SYN_SENT; 997 cb->s_did = 0; 998 spp_template(cb); 999 cb->s_timer[TCPT_KEEP] = TCPTV_KEEP; 1000 cb->s_force = 1 + TCPTV_KEEP; 1001 /* 1002 * Other party is required to respond to 1003 * the port I send from, but he is not 1004 * required to answer from where I am sending to, 1005 * so allow wildcarding. 1006 * original port I am sending to is still saved in 1007 * cb->s_dport. 1008 */ 1009 nsp->nsp_fport = 0; 1010 error = spp_output(cb, (struct mbuf *) 0); 1011 break; 1012 1013 case PRU_CONNECT2: 1014 error = EOPNOTSUPP; 1015 break; 1016 1017 /* 1018 * We may decide later to implement connection closing 1019 * handshaking at the spp level optionally. 1020 * here is the hook to do it: 1021 */ 1022 case PRU_DISCONNECT: 1023 cb = spp_disconnect(cb); 1024 break; 1025 1026 /* 1027 * Accept a connection. Essentially all the work is 1028 * done at higher levels; just return the address 1029 * of the peer, storing through addr. 1030 */ 1031 case PRU_ACCEPT: { 1032 struct sockaddr_ns *sns = mtod(nam, struct sockaddr_ns *); 1033 1034 nam->m_len = sizeof (struct sockaddr_ns); 1035 sns->sns_family = AF_NS; 1036 sns->sns_addr = nsp->nsp_faddr; 1037 break; 1038 } 1039 1040 case PRU_SHUTDOWN: 1041 socantsendmore(so); 1042 cb = spp_usrclosed(cb); 1043 if (cb) 1044 error = spp_output(cb, (struct mbuf *) 0); 1045 break; 1046 1047 /* 1048 * After a receive, possibly send acknowledgment 1049 * updating allocation. 1050 */ 1051 case PRU_RCVD: 1052 (void) spp_output(cb, (struct mbuf *) 0); 1053 break; 1054 1055 case PRU_ABORT: 1056 (void) spp_drop(cb, ECONNABORTED); 1057 break; 1058 1059 case PRU_SENSE: 1060 case PRU_CONTROL: 1061 m = NULL; 1062 error = EOPNOTSUPP; 1063 break; 1064 1065 case PRU_RCVOOB: 1066 if ((cb->s_oobflags & SF_IOOB) || so->so_oobmark || 1067 (so->so_state & SS_RCVATMARK)) { 1068 m->m_len = 1; 1069 *mtod(m, caddr_t) = cb->s_iobc; 1070 break; 1071 } 1072 error = EINVAL; 1073 break; 1074 1075 case PRU_SENDOOB: 1076 if (sbspace(&so->so_snd) < -512) { 1077 error = ENOBUFS; 1078 break; 1079 } 1080 cb->s_oobflags |= SF_SOOB; 1081 /* fall into */ 1082 case PRU_SEND: 1083 error = spp_output(cb, m); 1084 m = NULL; 1085 break; 1086 1087 case PRU_SOCKADDR: 1088 ns_setsockaddr(nsp, nam); 1089 break; 1090 1091 case PRU_PEERADDR: 1092 ns_setpeeraddr(nsp, nam); 1093 break; 1094 1095 case PRU_SLOWTIMO: 1096 cb = spp_timers(cb, (int)nam); 1097 break; 1098 1099 case PRU_FASTTIMO: 1100 case PRU_PROTORCV: 1101 case PRU_PROTOSEND: 1102 error = EOPNOTSUPP; 1103 break; 1104 1105 default: 1106 panic("sp_usrreq"); 1107 } 1108 if (cb && (so->so_options & SO_DEBUG || traceallspps)) 1109 spp_trace(SA_USER, (u_char)ostate, cb, (struct spidp *)0, req); 1110 release: 1111 if (m != NULL) 1112 m_freem(m); 1113 splx(s); 1114 return (error); 1115 } 1116 1117 spp_usrreq_sp(so, req, m, nam, rights) 1118 struct socket *so; 1119 int req; 1120 struct mbuf *m, *nam, *rights; 1121 { 1122 int error = spp_usrreq(so, req, m, nam, rights); 1123 1124 if (req == PRU_ATTACH && error == 0) { 1125 struct nspcb *nsp = sotonspcb(so); 1126 ((struct sppcb *)nsp->nsp_pcb)->s_flags |= 1127 (SF_HI | SF_HO | SF_PI); 1128 } 1129 return (error); 1130 } 1131 1132 /* 1133 * Create template to be used to send spp packets on a connection. 1134 * Called after host entry created, fills 1135 * in a skeletal spp header (choosing connection id), 1136 * minimizing the amount of work necessary when the connection is used. 1137 */ 1138 spp_template(cb) 1139 struct sppcb *cb; 1140 { 1141 register struct nspcb *nsp = cb->s_nspcb; 1142 register struct spidp *n = &(cb->s_shdr); 1143 1144 cb->s_mtu = 576 - sizeof (struct spidp); 1145 n->si_pt = NSPROTO_SPP; 1146 n->si_sna = nsp->nsp_laddr; 1147 n->si_dna = nsp->nsp_faddr; 1148 n->si_sid = htons(spp_iss); 1149 spp_iss += SPP_ISSINCR/2; 1150 n->si_alo = 1; 1151 } 1152 1153 /* 1154 * Close a SPIP control block: 1155 * discard spp control block itself 1156 * discard ns protocol control block 1157 * wake up any sleepers 1158 */ 1159 struct sppcb * 1160 spp_close(cb) 1161 register struct sppcb *cb; 1162 { 1163 register struct spidp_q *s; 1164 struct nspcb *nsp = cb->s_nspcb; 1165 struct socket *so = nsp->nsp_socket; 1166 register struct mbuf *m; 1167 1168 s = cb->s_q.si_next; 1169 while (s != &(cb->s_q)) { 1170 s = s->si_next; 1171 m = dtom(s->si_prev); 1172 remque(s->si_prev); 1173 m_freem(m); 1174 } 1175 (void) m_free(dtom(cb)); 1176 nsp->nsp_pcb = 0; 1177 soisdisconnected(so); 1178 ns_pcbdetach(nsp); 1179 return ((struct sppcb *)0); 1180 } 1181 /* 1182 * Someday we may do level 3 handshaking 1183 * to close a connection or send a xerox style error. 1184 * For now, just close. 1185 */ 1186 struct sppcb * 1187 spp_usrclosed(cb) 1188 register struct sppcb *cb; 1189 { 1190 return (spp_close(cb)); 1191 } 1192 struct sppcb * 1193 spp_disconnect(cb) 1194 register struct sppcb *cb; 1195 { 1196 return (spp_close(cb)); 1197 } 1198 /* 1199 * Drop connection, reporting 1200 * the specified error. 1201 */ 1202 struct sppcb * 1203 spp_drop(cb, errno) 1204 register struct sppcb *cb; 1205 int errno; 1206 { 1207 struct socket *so = cb->s_nspcb->nsp_socket; 1208 1209 /* 1210 * someday, in the xerox world 1211 * we will generate error protocol packets 1212 * announcing that the socket has gone away. 1213 */ 1214 /*if (TCPS_HAVERCVDSYN(tp->t_state)) { 1215 tp->t_state = TCPS_CLOSED; 1216 (void) tcp_output(tp); 1217 }*/ 1218 so->so_error = errno; 1219 return (spp_close(cb)); 1220 } 1221 1222 spp_abort(nsp) 1223 struct nspcb *nsp; 1224 { 1225 1226 (void) spp_close((struct sppcb *)nsp->nsp_pcb); 1227 } 1228 1229 spp_setpersist(cb) 1230 register struct sppcb *cb; 1231 { 1232 1233 /*if (cb->s_timer[TCPT_REXMT]) 1234 panic("spp_output REXMT");*/ 1235 /* 1236 * Start/restart persistance timer. 1237 */ 1238 TCPT_RANGESET(cb->s_timer[TCPT_PERSIST], 1239 ((int)(tcp_beta * cb->s_srtt)) << cb->s_rxtshift, 1240 TCPTV_PERSMIN, TCPTV_MAX); 1241 cb->s_rxtshift++; 1242 if (cb->s_rxtshift >= TCP_MAXRXTSHIFT) 1243 cb->s_rxtshift = 0; 1244 } 1245 /* 1246 * Fast timeout routine for processing delayed acks 1247 */ 1248 int spp_ftcnt; 1249 spp_fasttimo() 1250 { 1251 register struct nspcb *nsp; 1252 register struct sppcb *cb; 1253 int s = splnet(); 1254 1255 nsp = nspcb.nsp_next; 1256 spp_ftcnt++; 1257 if (nsp) 1258 for (; nsp != &nspcb; nsp = nsp->nsp_next) 1259 if ((cb = (struct sppcb *)nsp->nsp_pcb) && 1260 (cb->s_flags & SF_DELACK)) { 1261 cb->s_flags &= ~SF_DELACK; 1262 cb->s_flags |= SF_AK; 1263 (void) spp_output(cb, (struct mbuf *) 0); 1264 } 1265 splx(s); 1266 } 1267 1268 /* 1269 * spp protocol timeout routine called every 500 ms. 1270 * Updates the timers in all active pcb's and 1271 * causes finite state machine actions if timers expire. 1272 */ 1273 spp_slowtimo() 1274 { 1275 register struct nspcb *ip, *ipnxt; 1276 register struct sppcb *cb; 1277 int s = splnet(); 1278 register int i; 1279 1280 /* 1281 * Search through tcb's and update active timers. 1282 */ 1283 ip = nspcb.nsp_next; 1284 if (ip == 0) { 1285 splx(s); 1286 return; 1287 } 1288 while (ip != &nspcb) { 1289 cb = nstosppcb(ip); 1290 ipnxt = ip->nsp_next; 1291 if (cb == 0) 1292 goto tpgone; 1293 for (i = 0; i < TCPT_NTIMERS; i++) { 1294 if (cb->s_timer[i] && --cb->s_timer[i] == 0) { 1295 (void) spp_usrreq(cb->s_nspcb->nsp_socket, 1296 PRU_SLOWTIMO, (struct mbuf *)0, 1297 (struct mbuf *)i, (struct mbuf *)0); 1298 if (ipnxt->nsp_prev != ip) 1299 goto tpgone; 1300 } 1301 } 1302 cb->s_idle++; 1303 if (cb->s_rtt) 1304 cb->s_rtt++; 1305 tpgone: 1306 ip = ipnxt; 1307 } 1308 spp_iss += SPP_ISSINCR/PR_SLOWHZ; /* increment iss */ 1309 splx(s); 1310 } 1311 1312 float spp_backoff[TCP_MAXRXTSHIFT] = 1313 { 1.0, 1.2, 1.4, 1.7, 2.0, 3.0, 5.0, 8.0, 16.0, 32.0 }; 1314 int sppexprexmtbackoff = 0; 1315 /* 1316 * SPP timer processing. 1317 */ 1318 struct sppcb * 1319 spp_timers(cb, timer) 1320 register struct sppcb *cb; 1321 int timer; 1322 { 1323 1324 cb->s_force = 1 + timer; 1325 switch (timer) { 1326 1327 /* 1328 * 2 MSL timeout in shutdown went off. Delete connection 1329 * control block. 1330 */ 1331 case TCPT_2MSL: 1332 cb = spp_close(cb); 1333 break; 1334 1335 /* 1336 * Retransmission timer went off. Message has not 1337 * been acked within retransmit interval. Back off 1338 * to a longer retransmit interval and retransmit all 1339 * unacknowledged messages in the window. 1340 */ 1341 case TCPT_REXMT: 1342 cb->s_rxtshift++; 1343 if (cb->s_rxtshift > TCP_MAXRXTSHIFT) { 1344 cb = spp_drop(cb, ETIMEDOUT); 1345 break; 1346 } 1347 (void) spp_output(cb, (struct mbuf *) 0); 1348 TCPT_RANGESET(cb->s_timer[TCPT_REXMT], 1349 (int)cb->s_srtt, TCPTV_MIN, TCPTV_MAX); 1350 if (sppexprexmtbackoff) { 1351 TCPT_RANGESET(cb->s_timer[TCPT_REXMT], 1352 cb->s_timer[TCPT_REXMT] << cb->s_rxtshift, 1353 TCPTV_MIN, TCPTV_MAX); 1354 } else { 1355 TCPT_RANGESET(cb->s_timer[TCPT_REXMT], 1356 cb->s_timer[TCPT_REXMT] * 1357 spp_backoff[cb->s_rxtshift - 1], 1358 TCPTV_MIN, TCPTV_MAX); 1359 } 1360 break; 1361 1362 /* 1363 * Persistance timer into zero window. 1364 * Force a probe to be sent. 1365 */ 1366 case TCPT_PERSIST: 1367 (void) spp_output(cb, (struct mbuf *) 0); 1368 spp_setpersist(cb); 1369 break; 1370 1371 /* 1372 * Keep-alive timer went off; send something 1373 * or drop connection if idle for too long. 1374 */ 1375 case TCPT_KEEP: 1376 if (cb->s_state < TCPS_ESTABLISHED) 1377 goto dropit; 1378 if (cb->s_nspcb->nsp_socket->so_options & SO_KEEPALIVE) { 1379 if (cb->s_idle >= TCPTV_MAXIDLE) 1380 goto dropit; 1381 (void) spp_output(cb, (struct mbuf *) 0); 1382 } else 1383 cb->s_idle = 0; 1384 cb->s_timer[TCPT_KEEP] = TCPTV_KEEP; 1385 break; 1386 dropit: 1387 cb = spp_drop(cb, ETIMEDOUT); 1388 break; 1389 } 1390 return (cb); 1391 } 1392