1 /* 2 * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 * 17 * @(#)spp_usrreq.c 7.11 (Berkeley) 05/05/89 18 */ 19 20 #include "param.h" 21 #include "systm.h" 22 #include "user.h" 23 #include "malloc.h" 24 #include "mbuf.h" 25 #include "protosw.h" 26 #include "socket.h" 27 #include "socketvar.h" 28 #include "errno.h" 29 30 #include "../net/if.h" 31 #include "../net/route.h" 32 #include "../netinet/tcp_fsm.h" 33 34 #include "ns.h" 35 #include "ns_pcb.h" 36 #include "idp.h" 37 #include "idp_var.h" 38 #include "ns_error.h" 39 #include "sp.h" 40 #include "spidp.h" 41 #include "spp_timer.h" 42 #include "spp_var.h" 43 #include "spp_debug.h" 44 45 /* 46 * SP protocol implementation. 47 */ 48 spp_init() 49 { 50 51 spp_iss = 1; /* WRONG !! should fish it out of TODR */ 52 } 53 struct spidp spp_savesi; 54 int traceallspps = 0; 55 extern int sppconsdebug; 56 int spp_hardnosed; 57 int spp_use_delack = 0; 58 u_short spp_newchecks[50]; 59 60 /*ARGSUSED*/ 61 spp_input(m, nsp) 62 register struct mbuf *m; 63 register struct nspcb *nsp; 64 { 65 register struct sppcb *cb; 66 register struct spidp *si = mtod(m, struct spidp *); 67 register struct socket *so; 68 short ostate; 69 int dropsocket = 0; 70 71 72 sppstat.spps_rcvtotal++; 73 if (nsp == 0) { 74 panic("No nspcb in spp_input\n"); 75 return; 76 } 77 78 cb = nstosppcb(nsp); 79 if (cb == 0) goto bad; 80 81 if (m->m_len < sizeof(*si)) { 82 if ((m = m_pullup(m, sizeof(*si))) == 0) { 83 sppstat.spps_rcvshort++; 84 return; 85 } 86 si = mtod(m, struct spidp *); 87 } 88 si->si_seq = ntohs(si->si_seq); 89 si->si_ack = ntohs(si->si_ack); 90 si->si_alo = ntohs(si->si_alo); 91 92 so = nsp->nsp_socket; 93 if (so->so_options & SO_DEBUG || traceallspps) { 94 ostate = cb->s_state; 95 spp_savesi = *si; 96 } 97 if (so->so_options & SO_ACCEPTCONN) { 98 struct sppcb *ocb = cb; 99 100 so = sonewconn(so); 101 if (so == 0) { 102 goto drop; 103 } 104 /* 105 * This is ugly, but .... 106 * 107 * Mark socket as temporary until we're 108 * committed to keeping it. The code at 109 * ``drop'' and ``dropwithreset'' check the 110 * flag dropsocket to see if the temporary 111 * socket created here should be discarded. 112 * We mark the socket as discardable until 113 * we're committed to it below in TCPS_LISTEN. 114 */ 115 dropsocket++; 116 nsp = (struct nspcb *)so->so_pcb; 117 nsp->nsp_laddr = si->si_dna; 118 cb = nstosppcb(nsp); 119 cb->s_mtu = ocb->s_mtu; /* preserve sockopts */ 120 cb->s_flags = ocb->s_flags; /* preserve sockopts */ 121 cb->s_flags2 = ocb->s_flags2; /* preserve sockopts */ 122 cb->s_state = TCPS_LISTEN; 123 } 124 125 /* 126 * Packet received on connection. 127 * reset idle time and keep-alive timer; 128 */ 129 cb->s_idle = 0; 130 cb->s_timer[SPPT_KEEP] = SPPTV_KEEP; 131 132 switch (cb->s_state) { 133 134 case TCPS_LISTEN:{ 135 struct mbuf *am; 136 register struct sockaddr_ns *sns; 137 struct ns_addr laddr; 138 139 /* 140 * If somebody here was carying on a conversation 141 * and went away, and his pen pal thinks he can 142 * still talk, we get the misdirected packet. 143 */ 144 if (spp_hardnosed && (si->si_did != 0 || si->si_seq != 0)) { 145 spp_istat.gonawy++; 146 goto dropwithreset; 147 } 148 am = m_get(M_DONTWAIT, MT_SONAME); 149 if (am == NULL) 150 goto drop; 151 am->m_len = sizeof (struct sockaddr_ns); 152 sns = mtod(am, struct sockaddr_ns *); 153 sns->sns_len = sizeof(*sns); 154 sns->sns_family = AF_NS; 155 sns->sns_addr = si->si_sna; 156 laddr = nsp->nsp_laddr; 157 if (ns_nullhost(laddr)) 158 nsp->nsp_laddr = si->si_dna; 159 if (ns_pcbconnect(nsp, am)) { 160 nsp->nsp_laddr = laddr; 161 (void) m_free(am); 162 spp_istat.noconn++; 163 goto drop; 164 } 165 (void) m_free(am); 166 spp_template(cb); 167 dropsocket = 0; /* committed to socket */ 168 cb->s_did = si->si_sid; 169 cb->s_rack = si->si_ack; 170 cb->s_ralo = si->si_alo; 171 #define THREEWAYSHAKE 172 #ifdef THREEWAYSHAKE 173 cb->s_state = TCPS_SYN_RECEIVED; 174 cb->s_force = 1 + SPPT_KEEP; 175 sppstat.spps_accepts++; 176 cb->s_timer[SPPT_KEEP] = SPPTV_KEEP; 177 } 178 break; 179 /* 180 * This state means that we have heard a response 181 * to our acceptance of their connection 182 * It is probably logically unnecessary in this 183 * implementation. 184 */ 185 case TCPS_SYN_RECEIVED: { 186 if (si->si_did!=cb->s_sid) { 187 spp_istat.wrncon++; 188 goto drop; 189 } 190 #endif 191 nsp->nsp_fport = si->si_sport; 192 cb->s_timer[SPPT_REXMT] = 0; 193 cb->s_timer[SPPT_KEEP] = SPPTV_KEEP; 194 soisconnected(so); 195 cb->s_state = TCPS_ESTABLISHED; 196 sppstat.spps_accepts++; 197 } 198 break; 199 200 /* 201 * This state means that we have gotten a response 202 * to our attempt to establish a connection. 203 * We fill in the data from the other side, 204 * telling us which port to respond to, instead of the well- 205 * known one we might have sent to in the first place. 206 * We also require that this is a response to our 207 * connection id. 208 */ 209 case TCPS_SYN_SENT: 210 if (si->si_did!=cb->s_sid) { 211 spp_istat.notme++; 212 goto drop; 213 } 214 sppstat.spps_connects++; 215 cb->s_did = si->si_sid; 216 cb->s_rack = si->si_ack; 217 cb->s_ralo = si->si_alo; 218 cb->s_dport = nsp->nsp_fport = si->si_sport; 219 cb->s_timer[SPPT_REXMT] = 0; 220 cb->s_flags |= SF_ACKNOW; 221 soisconnected(so); 222 cb->s_state = TCPS_ESTABLISHED; 223 /* Use roundtrip time of connection request for initial rtt */ 224 if (cb->s_rtt) { 225 cb->s_srtt = cb->s_rtt << 3; 226 cb->s_rttvar = cb->s_rtt << 1; 227 SPPT_RANGESET(cb->s_rxtcur, 228 ((cb->s_srtt >> 2) + cb->s_rttvar) >> 1, 229 SPPTV_MIN, SPPTV_REXMTMAX); 230 cb->s_rtt = 0; 231 } 232 } 233 if (so->so_options & SO_DEBUG || traceallspps) 234 spp_trace(SA_INPUT, (u_char)ostate, cb, &spp_savesi, 0); 235 236 m->m_len -= sizeof (struct idp); 237 m->m_pkthdr.len -= sizeof (struct idp); 238 m->m_data += sizeof (struct idp); 239 240 if (spp_reass(cb, si)) { 241 (void) m_freem(m); 242 } 243 if (cb->s_force || (cb->s_flags & (SF_ACKNOW|SF_WIN|SF_RXT))) 244 (void) spp_output(cb, (struct mbuf *)0); 245 cb->s_flags &= ~(SF_WIN|SF_RXT); 246 return; 247 248 dropwithreset: 249 if (dropsocket) 250 (void) soabort(so); 251 si->si_seq = ntohs(si->si_seq); 252 si->si_ack = ntohs(si->si_ack); 253 si->si_alo = ntohs(si->si_alo); 254 ns_error(dtom(si), NS_ERR_NOSOCK, 0); 255 if (cb->s_nspcb->nsp_socket->so_options & SO_DEBUG || traceallspps) 256 spp_trace(SA_DROP, (u_char)ostate, cb, &spp_savesi, 0); 257 return; 258 259 drop: 260 bad: 261 if (cb == 0 || cb->s_nspcb->nsp_socket->so_options & SO_DEBUG || 262 traceallspps) 263 spp_trace(SA_DROP, (u_char)ostate, cb, &spp_savesi, 0); 264 m_freem(m); 265 } 266 267 int spprexmtthresh = 3; 268 269 /* 270 * This is structurally similar to the tcp reassembly routine 271 * but its function is somewhat different: It merely queues 272 * packets up, and suppresses duplicates. 273 */ 274 spp_reass(cb, si) 275 register struct sppcb *cb; 276 register struct spidp *si; 277 { 278 register struct spidp_q *q; 279 register struct mbuf *m; 280 register struct socket *so = cb->s_nspcb->nsp_socket; 281 char packetp = cb->s_flags & SF_HI; 282 int incr; 283 char wakeup = 0; 284 285 if (si == SI(0)) 286 goto present; 287 /* 288 * Update our news from them. 289 */ 290 if (si->si_cc & SP_SA) 291 cb->s_flags |= (spp_use_delack ? SF_DELACK : SF_ACKNOW); 292 if (SSEQ_GT(si->si_alo, cb->s_ralo)) 293 cb->s_flags |= SF_WIN; 294 if (SSEQ_LEQ(si->si_ack, cb->s_rack)) { 295 if ((si->si_cc & SP_SP) && cb->s_rack != (cb->s_smax + 1)) { 296 sppstat.spps_rcvdupack++; 297 /* 298 * If this is a completely duplicate ack 299 * and other conditions hold, we assume 300 * a packet has been dropped and retransmit 301 * it exactly as in tcp_input(). 302 */ 303 if (si->si_ack != cb->s_rack || 304 si->si_alo != cb->s_ralo) 305 cb->s_dupacks = 0; 306 else if (++cb->s_dupacks == spprexmtthresh) { 307 u_short onxt = cb->s_snxt; 308 int cwnd = cb->s_cwnd; 309 310 cb->s_snxt = si->si_ack; 311 cb->s_cwnd = CUNIT; 312 cb->s_force = 1 + SPPT_REXMT; 313 (void) spp_output(cb, (struct mbuf *)0); 314 cb->s_timer[SPPT_REXMT] = cb->s_rxtcur; 315 cb->s_rtt = 0; 316 if (cwnd >= 4 * CUNIT) 317 cb->s_cwnd = cwnd / 2; 318 if (SSEQ_GT(onxt, cb->s_snxt)) 319 cb->s_snxt = onxt; 320 return (1); 321 } 322 } else 323 cb->s_dupacks = 0; 324 goto update_window; 325 } 326 cb->s_dupacks = 0; 327 /* 328 * If our correspondent acknowledges data we haven't sent 329 * TCP would drop the packet after acking. We'll be a little 330 * more permissive 331 */ 332 if (SSEQ_GT(si->si_ack, (cb->s_smax + 1))) { 333 sppstat.spps_rcvacktoomuch++; 334 si->si_ack = cb->s_smax + 1; 335 } 336 sppstat.spps_rcvackpack++; 337 /* 338 * If transmit timer is running and timed sequence 339 * number was acked, update smoothed round trip time. 340 * See discussion of algorithm in tcp_input.c 341 */ 342 if (cb->s_rtt && SSEQ_GT(si->si_ack, cb->s_rtseq)) { 343 sppstat.spps_rttupdated++; 344 if (cb->s_srtt != 0) { 345 register short delta; 346 delta = cb->s_rtt - (cb->s_srtt >> 3); 347 if ((cb->s_srtt += delta) <= 0) 348 cb->s_srtt = 1; 349 if (delta < 0) 350 delta = -delta; 351 delta -= (cb->s_rttvar >> 2); 352 if ((cb->s_rttvar += delta) <= 0) 353 cb->s_rttvar = 1; 354 } else { 355 /* 356 * No rtt measurement yet 357 */ 358 cb->s_srtt = cb->s_rtt << 3; 359 cb->s_rttvar = cb->s_rtt << 1; 360 } 361 cb->s_rtt = 0; 362 cb->s_rxtshift = 0; 363 SPPT_RANGESET(cb->s_rxtcur, 364 ((cb->s_srtt >> 2) + cb->s_rttvar) >> 1, 365 SPPTV_MIN, SPPTV_REXMTMAX); 366 } 367 /* 368 * If all outstanding data is acked, stop retransmit 369 * timer and remember to restart (more output or persist). 370 * If there is more data to be acked, restart retransmit 371 * timer, using current (possibly backed-off) value; 372 */ 373 if (si->si_ack == cb->s_smax + 1) { 374 cb->s_timer[SPPT_REXMT] = 0; 375 cb->s_flags |= SF_RXT; 376 } else if (cb->s_timer[SPPT_PERSIST] == 0) 377 cb->s_timer[SPPT_REXMT] = cb->s_rxtcur; 378 /* 379 * When new data is acked, open the congestion window. 380 * If the window gives us less than ssthresh packets 381 * in flight, open exponentially (maxseg at a time). 382 * Otherwise open linearly (maxseg^2 / cwnd at a time). 383 */ 384 incr = CUNIT; 385 if (cb->s_cwnd > cb->s_ssthresh) 386 incr = max(incr * incr / cb->s_cwnd, 1); 387 cb->s_cwnd = min(cb->s_cwnd + incr, cb->s_cwmx); 388 /* 389 * Trim Acked data from output queue. 390 */ 391 while ((m = so->so_snd.sb_mb) != NULL) { 392 if (SSEQ_LT((mtod(m, struct spidp *))->si_seq, si->si_ack)) 393 sbdroprecord(&so->so_snd); 394 else 395 break; 396 } 397 sowwakeup(so); 398 cb->s_rack = si->si_ack; 399 update_window: 400 if (SSEQ_LT(cb->s_snxt, cb->s_rack)) 401 cb->s_snxt = cb->s_rack; 402 if (SSEQ_LT(cb->s_swl1, si->si_seq) || cb->s_swl1 == si->si_seq && 403 (SSEQ_LT(cb->s_swl2, si->si_ack) || 404 cb->s_swl2 == si->si_ack && SSEQ_LT(cb->s_ralo, si->si_alo))) { 405 /* keep track of pure window updates */ 406 if ((si->si_cc & SP_SP) && cb->s_swl2 == si->si_ack 407 && SSEQ_LT(cb->s_ralo, si->si_alo)) { 408 sppstat.spps_rcvwinupd++; 409 sppstat.spps_rcvdupack--; 410 } 411 cb->s_ralo = si->si_alo; 412 cb->s_swl1 = si->si_seq; 413 cb->s_swl2 = si->si_ack; 414 cb->s_swnd = (1 + si->si_alo - si->si_ack); 415 if (cb->s_swnd > cb->s_smxw) 416 cb->s_smxw = cb->s_swnd; 417 cb->s_flags |= SF_WIN; 418 } 419 /* 420 * If this packet number is higher than that which 421 * we have allocated refuse it, unless urgent 422 */ 423 if (SSEQ_GT(si->si_seq, cb->s_alo)) { 424 if (si->si_cc & SP_SP) { 425 sppstat.spps_rcvwinprobe++; 426 return (1); 427 } else 428 sppstat.spps_rcvpackafterwin++; 429 if (si->si_cc & SP_OB) { 430 if (SSEQ_GT(si->si_seq, cb->s_alo + 60)) { 431 ns_error(dtom(si), NS_ERR_FULLUP, 0); 432 return (0); 433 } /* else queue this packet; */ 434 } else { 435 /*register struct socket *so = cb->s_nspcb->nsp_socket; 436 if (so->so_state && SS_NOFDREF) { 437 ns_error(dtom(si), NS_ERR_NOSOCK, 0); 438 (void)spp_close(cb); 439 } else 440 would crash system*/ 441 spp_istat.notyet++; 442 ns_error(dtom(si), NS_ERR_FULLUP, 0); 443 return (0); 444 } 445 } 446 /* 447 * If this is a system packet, we don't need to 448 * queue it up, and won't update acknowledge # 449 */ 450 if (si->si_cc & SP_SP) { 451 return (1); 452 } 453 /* 454 * We have already seen this packet, so drop. 455 */ 456 if (SSEQ_LT(si->si_seq, cb->s_ack)) { 457 spp_istat.bdreas++; 458 sppstat.spps_rcvduppack++; 459 if (si->si_seq == cb->s_ack - 1) 460 spp_istat.lstdup++; 461 return (1); 462 } 463 /* 464 * Loop through all packets queued up to insert in 465 * appropriate sequence. 466 */ 467 for (q = cb->s_q.si_next; q!=&cb->s_q; q = q->si_next) { 468 if (si->si_seq == SI(q)->si_seq) { 469 sppstat.spps_rcvduppack++; 470 return (1); 471 } 472 if (SSEQ_LT(si->si_seq, SI(q)->si_seq)) { 473 sppstat.spps_rcvoopack++; 474 break; 475 } 476 } 477 insque(si, q->si_prev); 478 /* 479 * If this packet is urgent, inform process 480 */ 481 if (si->si_cc & SP_OB) { 482 cb->s_iobc = ((char *)si)[1 + sizeof(*si)]; 483 sohasoutofband(so); 484 cb->s_oobflags |= SF_IOOB; 485 } 486 present: 487 #define SPINC sizeof(struct sphdr) 488 /* 489 * Loop through all packets queued up to update acknowledge 490 * number, and present all acknowledged data to user; 491 * If in packet interface mode, show packet headers. 492 */ 493 for (q = cb->s_q.si_next; q!=&cb->s_q; q = q->si_next) { 494 if (SI(q)->si_seq == cb->s_ack) { 495 cb->s_ack++; 496 m = dtom(q); 497 if (SI(q)->si_cc & SP_OB) { 498 cb->s_oobflags &= ~SF_IOOB; 499 if (so->so_rcv.sb_cc) 500 so->so_oobmark = so->so_rcv.sb_cc; 501 else 502 so->so_state |= SS_RCVATMARK; 503 } 504 q = q->si_prev; 505 remque(q->si_next); 506 wakeup = 1; 507 sppstat.spps_rcvpack++; 508 #ifdef SF_NEWCALL 509 if (cb->s_flags2 & SF_NEWCALL) { 510 struct sphdr *sp = mtod(m, struct sphdr *); 511 u_char dt = sp->sp_dt; 512 spp_newchecks[4]++; 513 if (dt != cb->s_rhdr.sp_dt) { 514 struct mbuf *mm = 515 m_getclr(M_DONTWAIT, MT_CONTROL); 516 spp_newchecks[0]++; 517 if (mm != NULL) { 518 u_short *s = 519 mtod(mm, u_short *); 520 cb->s_rhdr.sp_dt = dt; 521 mm->m_len = 5; /*XXX*/ 522 s[0] = 5; 523 s[1] = 1; 524 *(u_char *)(&s[2]) = dt; 525 sbappend(&so->so_rcv, mm); 526 } 527 } 528 if (sp->sp_cc & SP_OB) { 529 MCHTYPE(m, MT_OOBDATA); 530 spp_newchecks[1]++; 531 so->so_oobmark = 0; 532 so->so_state &= ~SS_RCVATMARK; 533 } 534 if (packetp == 0) { 535 m->m_data += SPINC; 536 m->m_len -= SPINC; 537 m->m_pkthdr.len -= SPINC; 538 } 539 if ((sp->sp_cc & SP_EM) || packetp) { 540 sbappendrecord(&so->so_rcv, m); 541 spp_newchecks[9]++; 542 } else 543 sbappend(&so->so_rcv, m); 544 } else 545 #endif 546 if (packetp) { 547 sbappendrecord(&so->so_rcv, m); 548 } else { 549 cb->s_rhdr = *mtod(m, struct sphdr *); 550 m->m_data += SPINC; 551 m->m_len -= SPINC; 552 m->m_pkthdr.len -= SPINC; 553 sbappend(&so->so_rcv, m); 554 } 555 } else 556 break; 557 } 558 if (wakeup) sorwakeup(so); 559 return (0); 560 } 561 562 spp_ctlinput(cmd, arg) 563 int cmd; 564 caddr_t arg; 565 { 566 struct ns_addr *na; 567 extern u_char nsctlerrmap[]; 568 extern spp_abort(), spp_quench(); 569 extern struct nspcb *idp_drop(); 570 struct ns_errp *errp; 571 struct nspcb *nsp; 572 struct sockaddr_ns *sns; 573 int type; 574 575 if (cmd < 0 || cmd > PRC_NCMDS) 576 return; 577 type = NS_ERR_UNREACH_HOST; 578 579 switch (cmd) { 580 581 case PRC_ROUTEDEAD: 582 return; 583 584 case PRC_IFDOWN: 585 case PRC_HOSTDEAD: 586 case PRC_HOSTUNREACH: 587 sns = (struct sockaddr_ns *)arg; 588 if (sns->sns_family != AF_NS) 589 return; 590 na = &sns->sns_addr; 591 break; 592 593 default: 594 errp = (struct ns_errp *)arg; 595 na = &errp->ns_err_idp.idp_dna; 596 type = errp->ns_err_num; 597 type = ntohs((u_short)type); 598 } 599 switch (type) { 600 601 case NS_ERR_UNREACH_HOST: 602 ns_pcbnotify(na, (int)nsctlerrmap[cmd], spp_abort, (long) 0); 603 break; 604 605 case NS_ERR_TOO_BIG: 606 case NS_ERR_NOSOCK: 607 nsp = ns_pcblookup(na, errp->ns_err_idp.idp_sna.x_port, 608 NS_WILDCARD); 609 if (nsp) { 610 if(nsp->nsp_pcb) 611 (void) spp_drop((struct sppcb *)nsp->nsp_pcb, 612 (int)nsctlerrmap[cmd]); 613 else 614 (void) idp_drop(nsp, (int)nsctlerrmap[cmd]); 615 } 616 break; 617 618 case NS_ERR_FULLUP: 619 ns_pcbnotify(na, 0, spp_quench, (long) 0); 620 } 621 } 622 /* 623 * When a source quench is received, close congestion window 624 * to one packet. We will gradually open it again as we proceed. 625 */ 626 spp_quench(nsp) 627 struct nspcb *nsp; 628 { 629 struct sppcb *cb = nstosppcb(nsp); 630 631 if (cb) 632 cb->s_cwnd = CUNIT; 633 } 634 635 #ifdef notdef 636 int 637 spp_fixmtu(nsp) 638 register struct nspcb *nsp; 639 { 640 register struct sppcb *cb = (struct sppcb *)(nsp->nsp_pcb); 641 register struct mbuf *m; 642 register struct spidp *si; 643 struct ns_errp *ep; 644 struct sockbuf *sb; 645 int badseq, len; 646 struct mbuf *firstbad, *m0; 647 648 if (cb) { 649 /* 650 * The notification that we have sent 651 * too much is bad news -- we will 652 * have to go through queued up so far 653 * splitting ones which are too big and 654 * reassigning sequence numbers and checksums. 655 * we should then retransmit all packets from 656 * one above the offending packet to the last one 657 * we had sent (or our allocation) 658 * then the offending one so that the any queued 659 * data at our destination will be discarded. 660 */ 661 ep = (struct ns_errp *)nsp->nsp_notify_param; 662 sb = &nsp->nsp_socket->so_snd; 663 cb->s_mtu = ep->ns_err_param; 664 badseq = SI(&ep->ns_err_idp)->si_seq; 665 for (m = sb->sb_mb; m; m = m->m_act) { 666 si = mtod(m, struct spidp *); 667 if (si->si_seq == badseq) 668 break; 669 } 670 if (m == 0) return; 671 firstbad = m; 672 /*for (;;) {*/ 673 /* calculate length */ 674 for (m0 = m, len = 0; m ; m = m->m_next) 675 len += m->m_len; 676 if (len > cb->s_mtu) { 677 } 678 /* FINISH THIS 679 } */ 680 } 681 } 682 #endif 683 684 spp_output(cb, m0) 685 register struct sppcb *cb; 686 struct mbuf *m0; 687 { 688 struct socket *so = cb->s_nspcb->nsp_socket; 689 register struct mbuf *m; 690 register struct spidp *si = (struct spidp *) 0; 691 register struct sockbuf *sb = &so->so_snd; 692 int len = 0, win, rcv_win; 693 short span, off, recordp = 0; 694 u_short alo; 695 int error = 0, sendalot; 696 #ifdef notdef 697 int idle; 698 #endif 699 struct mbuf *mprev; 700 extern int idpcksum; 701 702 if (m0) { 703 int mtu = cb->s_mtu; 704 int datalen; 705 /* 706 * Make sure that packet isn't too big. 707 */ 708 for (m = m0; m ; m = m->m_next) { 709 mprev = m; 710 len += m->m_len; 711 if (m->m_flags & M_EOR) 712 recordp = 1; 713 } 714 datalen = (cb->s_flags & SF_HO) ? 715 len - sizeof (struct sphdr) : len; 716 if (datalen > mtu) { 717 if (cb->s_flags & SF_PI) { 718 m_freem(m0); 719 return (EMSGSIZE); 720 } else { 721 int oldEM = cb->s_cc & SP_EM; 722 723 cb->s_cc &= ~SP_EM; 724 while (len > mtu) { 725 /* 726 * Here we are only being called 727 * from usrreq(), so it is OK to 728 * block. 729 */ 730 m = m_copym(m0, 0, mtu, M_WAIT); 731 if (cb->s_flags & SF_NEWCALL) { 732 struct mbuf *mm = m; 733 spp_newchecks[7]++; 734 while (mm) { 735 mm->m_flags &= ~M_EOR; 736 mm = mm->m_next; 737 } 738 } 739 error = spp_output(cb, m); 740 if (error) { 741 cb->s_cc |= oldEM; 742 m_freem(m0); 743 return(error); 744 } 745 m_adj(m0, mtu); 746 len -= mtu; 747 } 748 cb->s_cc |= oldEM; 749 } 750 } 751 /* 752 * Force length even, by adding a "garbage byte" if 753 * necessary. 754 */ 755 if (len & 1) { 756 m = mprev; 757 if (M_TRAILINGSPACE(m) >= 1) 758 m->m_len++; 759 else { 760 struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA); 761 762 if (m1 == 0) { 763 m_freem(m0); 764 return (ENOBUFS); 765 } 766 m1->m_len = 1; 767 *(mtod(m1, u_char *)) = 0; 768 m->m_next = m1; 769 } 770 } 771 m = m_gethdr(M_DONTWAIT, MT_HEADER); 772 if (m == 0) { 773 m_freem(m0); 774 return (ENOBUFS); 775 } 776 /* 777 * Fill in mbuf with extended SP header 778 * and addresses and length put into network format. 779 */ 780 MH_ALIGN(m, sizeof (struct spidp)); 781 m->m_len = sizeof (struct spidp); 782 m->m_next = m0; 783 si = mtod(m, struct spidp *); 784 si->si_i = *cb->s_idp; 785 si->si_s = cb->s_shdr; 786 if ((cb->s_flags & SF_PI) && (cb->s_flags & SF_HO)) { 787 register struct sphdr *sh; 788 if (m0->m_len < sizeof (*sh)) { 789 if((m0 = m_pullup(m0, sizeof(*sh))) == NULL) { 790 (void) m_free(m); 791 m_freem(m0); 792 return (EINVAL); 793 } 794 m->m_next = m0; 795 } 796 sh = mtod(m0, struct sphdr *); 797 si->si_dt = sh->sp_dt; 798 si->si_cc |= sh->sp_cc & SP_EM; 799 m0->m_len -= sizeof (*sh); 800 m0->m_data += sizeof (*sh); 801 len -= sizeof (*sh); 802 } 803 len += sizeof(*si); 804 if ((cb->s_flags2 & SF_NEWCALL) && recordp) { 805 si->si_cc |= SP_EM; 806 spp_newchecks[8]++; 807 } 808 if (cb->s_oobflags & SF_SOOB) { 809 /* 810 * Per jqj@cornell: 811 * make sure OB packets convey exactly 1 byte. 812 * If the packet is 1 byte or larger, we 813 * have already guaranted there to be at least 814 * one garbage byte for the checksum, and 815 * extra bytes shouldn't hurt! 816 */ 817 if (len > sizeof(*si)) { 818 si->si_cc |= SP_OB; 819 len = (1 + sizeof(*si)); 820 } 821 } 822 si->si_len = htons((u_short)len); 823 m->m_pkthdr.len = ((len - 1) | 1) + 1; 824 /* 825 * queue stuff up for output 826 */ 827 sbappendrecord(sb, m); 828 cb->s_seq++; 829 } 830 #ifdef notdef 831 idle = (cb->s_smax == (cb->s_rack - 1)); 832 #endif 833 again: 834 sendalot = 0; 835 off = cb->s_snxt - cb->s_rack; 836 win = min(cb->s_swnd, (cb->s_cwnd/CUNIT)); 837 838 /* 839 * If in persist timeout with window of 0, send a probe. 840 * Otherwise, if window is small but nonzero 841 * and timer expired, send what we can and go into 842 * transmit state. 843 */ 844 if (cb->s_force == 1 + SPPT_PERSIST) { 845 if (win != 0) { 846 cb->s_timer[SPPT_PERSIST] = 0; 847 cb->s_rxtshift = 0; 848 } 849 } 850 span = cb->s_seq - cb->s_rack; 851 len = min(span, win) - off; 852 853 if (len < 0) { 854 /* 855 * Window shrank after we went into it. 856 * If window shrank to 0, cancel pending 857 * restransmission and pull s_snxt back 858 * to (closed) window. We will enter persist 859 * state below. If the widndow didn't close completely, 860 * just wait for an ACK. 861 */ 862 len = 0; 863 if (win == 0) { 864 cb->s_timer[SPPT_REXMT] = 0; 865 cb->s_snxt = cb->s_rack; 866 } 867 } 868 if (len > 1) 869 sendalot = 1; 870 rcv_win = sbspace(&so->so_rcv); 871 872 /* 873 * Send if we owe peer an ACK. 874 */ 875 if (cb->s_oobflags & SF_SOOB) { 876 /* 877 * must transmit this out of band packet 878 */ 879 cb->s_oobflags &= ~ SF_SOOB; 880 sendalot = 1; 881 sppstat.spps_sndurg++; 882 goto found; 883 } 884 if (cb->s_flags & SF_ACKNOW) 885 goto send; 886 if (cb->s_state < TCPS_ESTABLISHED) 887 goto send; 888 /* 889 * Silly window can't happen in spp. 890 * Code from tcp deleted. 891 */ 892 if (len) 893 goto send; 894 /* 895 * Compare available window to amount of window 896 * known to peer (as advertised window less 897 * next expected input.) If the difference is at least two 898 * packets or at least 35% of the mximum possible window, 899 * then want to send a window update to peer. 900 */ 901 if (rcv_win > 0) { 902 u_short delta = 1 + cb->s_alo - cb->s_ack; 903 int adv = rcv_win - (delta * cb->s_mtu); 904 905 if ((so->so_rcv.sb_cc == 0 && adv >= (2 * cb->s_mtu)) || 906 (100 * adv / so->so_rcv.sb_hiwat >= 35)) { 907 sppstat.spps_sndwinup++; 908 cb->s_flags |= SF_ACKNOW; 909 goto send; 910 } 911 912 } 913 /* 914 * Many comments from tcp_output.c are appropriate here 915 * including . . . 916 * If send window is too small, there is data to transmit, and no 917 * retransmit or persist is pending, then go to persist state. 918 * If nothing happens soon, send when timer expires: 919 * if window is nonzero, transmit what we can, 920 * otherwise send a probe. 921 */ 922 if (so->so_snd.sb_cc && cb->s_timer[SPPT_REXMT] == 0 && 923 cb->s_timer[SPPT_PERSIST] == 0) { 924 cb->s_rxtshift = 0; 925 spp_setpersist(cb); 926 } 927 /* 928 * No reason to send a packet, just return. 929 */ 930 cb->s_outx = 1; 931 return (0); 932 933 send: 934 /* 935 * Find requested packet. 936 */ 937 si = 0; 938 if (len > 0) { 939 cb->s_want = cb->s_snxt; 940 for (m = sb->sb_mb; m; m = m->m_act) { 941 si = mtod(m, struct spidp *); 942 if (SSEQ_LEQ(cb->s_snxt, si->si_seq)) 943 break; 944 } 945 found: 946 if (si) { 947 if (si->si_seq == cb->s_snxt) 948 cb->s_snxt++; 949 else 950 sppstat.spps_sndvoid++, si = 0; 951 } 952 } 953 /* 954 * update window 955 */ 956 if (rcv_win < 0) 957 rcv_win = 0; 958 alo = cb->s_ack - 1 + (rcv_win / ((short)cb->s_mtu)); 959 if (SSEQ_LT(alo, cb->s_alo)) 960 alo = cb->s_alo; 961 962 if (si) { 963 /* 964 * must make a copy of this packet for 965 * idp_output to monkey with 966 */ 967 m = m_copy(dtom(si), 0, (int)M_COPYALL); 968 if (m == NULL) { 969 return (ENOBUFS); 970 } 971 si = mtod(m, struct spidp *); 972 if (SSEQ_LT(si->si_seq, cb->s_smax)) 973 sppstat.spps_sndrexmitpack++; 974 else 975 sppstat.spps_sndpack++; 976 } else if (cb->s_force || cb->s_flags & SF_ACKNOW) { 977 /* 978 * Must send an acknowledgement or a probe 979 */ 980 if (cb->s_force) 981 sppstat.spps_sndprobe++; 982 if (cb->s_flags & SF_ACKNOW) 983 sppstat.spps_sndacks++; 984 m = m_gethdr(M_DONTWAIT, MT_HEADER); 985 if (m == 0) 986 return (ENOBUFS); 987 /* 988 * Fill in mbuf with extended SP header 989 * and addresses and length put into network format. 990 */ 991 MH_ALIGN(m, sizeof (struct spidp)); 992 m->m_len = sizeof (*si); 993 m->m_pkthdr.len = sizeof (*si); 994 si = mtod(m, struct spidp *); 995 si->si_i = *cb->s_idp; 996 si->si_s = cb->s_shdr; 997 si->si_seq = cb->s_smax + 1; 998 si->si_len = htons(sizeof (*si)); 999 si->si_cc |= SP_SP; 1000 } else { 1001 cb->s_outx = 3; 1002 if (so->so_options & SO_DEBUG || traceallspps) 1003 spp_trace(SA_OUTPUT, cb->s_state, cb, si, 0); 1004 return (0); 1005 } 1006 /* 1007 * Stuff checksum and output datagram. 1008 */ 1009 if ((si->si_cc & SP_SP) == 0) { 1010 if (cb->s_force != (1 + SPPT_PERSIST) || 1011 cb->s_timer[SPPT_PERSIST] == 0) { 1012 /* 1013 * If this is a new packet and we are not currently 1014 * timing anything, time this one. 1015 */ 1016 if (SSEQ_LT(cb->s_smax, si->si_seq)) { 1017 cb->s_smax = si->si_seq; 1018 if (cb->s_rtt == 0) { 1019 sppstat.spps_segstimed++; 1020 cb->s_rtseq = si->si_seq; 1021 cb->s_rtt = 1; 1022 } 1023 } 1024 /* 1025 * Set rexmt timer if not currently set, 1026 * Initial value for retransmit timer is smoothed 1027 * round-trip time + 2 * round-trip time variance. 1028 * Initialize shift counter which is used for backoff 1029 * of retransmit time. 1030 */ 1031 if (cb->s_timer[SPPT_REXMT] == 0 && 1032 cb->s_snxt != cb->s_rack) { 1033 cb->s_timer[SPPT_REXMT] = cb->s_rxtcur; 1034 if (cb->s_timer[SPPT_PERSIST]) { 1035 cb->s_timer[SPPT_PERSIST] = 0; 1036 cb->s_rxtshift = 0; 1037 } 1038 } 1039 } else if (SSEQ_LT(cb->s_smax, si->si_seq)) { 1040 cb->s_smax = si->si_seq; 1041 } 1042 } else if (cb->s_state < TCPS_ESTABLISHED) { 1043 if (cb->s_rtt == 0) 1044 cb->s_rtt = 1; /* Time initial handshake */ 1045 if (cb->s_timer[SPPT_REXMT] == 0) 1046 cb->s_timer[SPPT_REXMT] = cb->s_rxtcur; 1047 } 1048 { 1049 /* 1050 * Do not request acks when we ack their data packets or 1051 * when we do a gratuitous window update. 1052 */ 1053 if (((si->si_cc & SP_SP) == 0) || cb->s_force) 1054 si->si_cc |= SP_SA; 1055 si->si_seq = htons(si->si_seq); 1056 si->si_alo = htons(alo); 1057 si->si_ack = htons(cb->s_ack); 1058 1059 if (idpcksum) { 1060 si->si_sum = 0; 1061 len = ntohs(si->si_len); 1062 if (len & 1) 1063 len++; 1064 si->si_sum = ns_cksum(m, len); 1065 } else 1066 si->si_sum = 0xffff; 1067 1068 cb->s_outx = 4; 1069 if (so->so_options & SO_DEBUG || traceallspps) 1070 spp_trace(SA_OUTPUT, cb->s_state, cb, si, 0); 1071 1072 if (so->so_options & SO_DONTROUTE) 1073 error = ns_output(m, (struct route *)0, NS_ROUTETOIF); 1074 else 1075 error = ns_output(m, &cb->s_nspcb->nsp_route, 0); 1076 } 1077 if (error) { 1078 return (error); 1079 } 1080 sppstat.spps_sndtotal++; 1081 /* 1082 * Data sent (as far as we can tell). 1083 * If this advertises a larger window than any other segment, 1084 * then remember the size of the advertized window. 1085 * Any pending ACK has now been sent. 1086 */ 1087 cb->s_force = 0; 1088 cb->s_flags &= ~(SF_ACKNOW|SF_DELACK); 1089 if (SSEQ_GT(alo, cb->s_alo)) 1090 cb->s_alo = alo; 1091 if (sendalot) 1092 goto again; 1093 cb->s_outx = 5; 1094 return (0); 1095 } 1096 1097 int spp_do_persist_panics = 0; 1098 1099 spp_setpersist(cb) 1100 register struct sppcb *cb; 1101 { 1102 register t = ((cb->s_srtt >> 2) + cb->s_rttvar) >> 1; 1103 extern int spp_backoff[]; 1104 1105 if (cb->s_timer[SPPT_REXMT] && spp_do_persist_panics) 1106 panic("spp_output REXMT"); 1107 /* 1108 * Start/restart persistance timer. 1109 */ 1110 SPPT_RANGESET(cb->s_timer[SPPT_PERSIST], 1111 t*spp_backoff[cb->s_rxtshift], 1112 SPPTV_PERSMIN, SPPTV_PERSMAX); 1113 if (cb->s_rxtshift < SPP_MAXRXTSHIFT) 1114 cb->s_rxtshift++; 1115 } 1116 /*ARGSUSED*/ 1117 spp_ctloutput(req, so, level, name, value) 1118 int req; 1119 struct socket *so; 1120 int name; 1121 struct mbuf **value; 1122 { 1123 register struct mbuf *m; 1124 struct nspcb *nsp = sotonspcb(so); 1125 register struct sppcb *cb; 1126 int mask, error = 0; 1127 1128 if (level != NSPROTO_SPP) { 1129 /* This will have to be changed when we do more general 1130 stacking of protocols */ 1131 return (idp_ctloutput(req, so, level, name, value)); 1132 } 1133 if (nsp == NULL) { 1134 error = EINVAL; 1135 goto release; 1136 } else 1137 cb = nstosppcb(nsp); 1138 1139 switch (req) { 1140 1141 case PRCO_GETOPT: 1142 if (value == NULL) 1143 return (EINVAL); 1144 m = m_get(M_DONTWAIT, MT_DATA); 1145 if (m == NULL) 1146 return (ENOBUFS); 1147 switch (name) { 1148 1149 case SO_HEADERS_ON_INPUT: 1150 mask = SF_HI; 1151 goto get_flags; 1152 1153 case SO_HEADERS_ON_OUTPUT: 1154 mask = SF_HO; 1155 get_flags: 1156 m->m_len = sizeof(short); 1157 *mtod(m, short *) = cb->s_flags & mask; 1158 break; 1159 1160 case SO_MTU: 1161 m->m_len = sizeof(u_short); 1162 *mtod(m, short *) = cb->s_mtu; 1163 break; 1164 1165 case SO_LAST_HEADER: 1166 m->m_len = sizeof(struct sphdr); 1167 *mtod(m, struct sphdr *) = cb->s_rhdr; 1168 break; 1169 1170 case SO_DEFAULT_HEADERS: 1171 m->m_len = sizeof(struct spidp); 1172 *mtod(m, struct sphdr *) = cb->s_shdr; 1173 break; 1174 1175 default: 1176 error = EINVAL; 1177 } 1178 *value = m; 1179 break; 1180 1181 case PRCO_SETOPT: 1182 if (value == 0 || *value == 0) { 1183 error = EINVAL; 1184 break; 1185 } 1186 switch (name) { 1187 int *ok; 1188 1189 case SO_HEADERS_ON_INPUT: 1190 mask = SF_HI; 1191 goto set_head; 1192 1193 case SO_HEADERS_ON_OUTPUT: 1194 mask = SF_HO; 1195 set_head: 1196 if (cb->s_flags & SF_PI) { 1197 ok = mtod(*value, int *); 1198 if (*ok) 1199 cb->s_flags |= mask; 1200 else 1201 cb->s_flags &= ~mask; 1202 } else error = EINVAL; 1203 break; 1204 1205 case SO_MTU: 1206 cb->s_mtu = *(mtod(*value, u_short *)); 1207 break; 1208 1209 #ifdef SF_NEWCALL 1210 case SO_NEWCALL: 1211 ok = mtod(*value, int *); 1212 if (*ok) { 1213 cb->s_flags2 |= SF_NEWCALL; 1214 spp_newchecks[5]++; 1215 } else { 1216 cb->s_flags2 &= ~SF_NEWCALL; 1217 spp_newchecks[6]++; 1218 } 1219 break; 1220 #endif 1221 1222 case SO_DEFAULT_HEADERS: 1223 { 1224 register struct sphdr *sp 1225 = mtod(*value, struct sphdr *); 1226 cb->s_dt = sp->sp_dt; 1227 cb->s_cc = sp->sp_cc & SP_EM; 1228 } 1229 break; 1230 1231 default: 1232 error = EINVAL; 1233 } 1234 m_freem(*value); 1235 break; 1236 } 1237 release: 1238 return (error); 1239 } 1240 1241 /*ARGSUSED*/ 1242 spp_usrreq(so, req, m, nam, rights, controlp) 1243 struct socket *so; 1244 int req; 1245 struct mbuf *m, *nam, *rights, *controlp; 1246 { 1247 struct nspcb *nsp = sotonspcb(so); 1248 register struct sppcb *cb; 1249 int s = splnet(); 1250 int error = 0, ostate; 1251 struct mbuf *mm; 1252 register struct sockbuf *sb; 1253 1254 if (req == PRU_CONTROL) 1255 return (ns_control(so, (int)m, (caddr_t)nam, 1256 (struct ifnet *)rights)); 1257 if (rights && rights->m_len) { 1258 error = EINVAL; 1259 goto release; 1260 } 1261 if (nsp == NULL) { 1262 if (req != PRU_ATTACH) { 1263 error = EINVAL; 1264 goto release; 1265 } 1266 } else 1267 cb = nstosppcb(nsp); 1268 1269 ostate = cb ? cb->s_state : 0; 1270 1271 switch (req) { 1272 1273 case PRU_ATTACH: 1274 if (nsp != NULL) { 1275 error = EISCONN; 1276 break; 1277 } 1278 error = ns_pcballoc(so, &nspcb); 1279 if (error) 1280 break; 1281 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { 1282 error = soreserve(so, (u_long) 3072, (u_long) 3072); 1283 if (error) 1284 break; 1285 } 1286 nsp = sotonspcb(so); 1287 1288 mm = m_getclr(M_DONTWAIT, MT_PCB); 1289 sb = &so->so_snd; 1290 1291 if (mm == NULL) { 1292 error = ENOBUFS; 1293 break; 1294 } 1295 cb = mtod(mm, struct sppcb *); 1296 mm = m_getclr(M_DONTWAIT, MT_HEADER); 1297 if (mm == NULL) { 1298 (void) m_free(dtom(m)); 1299 error = ENOBUFS; 1300 break; 1301 } 1302 cb->s_idp = mtod(mm, struct idp *); 1303 cb->s_state = TCPS_LISTEN; 1304 cb->s_smax = -1; 1305 cb->s_swl1 = -1; 1306 cb->s_q.si_next = cb->s_q.si_prev = &cb->s_q; 1307 cb->s_nspcb = nsp; 1308 cb->s_mtu = 576 - sizeof (struct spidp); 1309 cb->s_cwnd = sbspace(sb) * CUNIT / cb->s_mtu; 1310 cb->s_ssthresh = cb->s_cwnd; 1311 cb->s_cwmx = sbspace(sb) * CUNIT / 1312 (2 * sizeof (struct spidp)); 1313 /* Above is recomputed when connecting to account 1314 for changed buffering or mtu's */ 1315 cb->s_rtt = SPPTV_SRTTBASE; 1316 cb->s_rttvar = SPPTV_SRTTDFLT << 2; 1317 SPPT_RANGESET(cb->s_rxtcur, 1318 ((SPPTV_SRTTBASE >> 2) + (SPPTV_SRTTDFLT << 2)) >> 1, 1319 SPPTV_MIN, SPPTV_REXMTMAX); 1320 nsp->nsp_pcb = (caddr_t) cb; 1321 break; 1322 1323 case PRU_DETACH: 1324 if (nsp == NULL) { 1325 error = ENOTCONN; 1326 break; 1327 } 1328 if (cb->s_state > TCPS_LISTEN) 1329 cb = spp_disconnect(cb); 1330 else 1331 cb = spp_close(cb); 1332 break; 1333 1334 case PRU_BIND: 1335 error = ns_pcbbind(nsp, nam); 1336 break; 1337 1338 case PRU_LISTEN: 1339 if (nsp->nsp_lport == 0) 1340 error = ns_pcbbind(nsp, (struct mbuf *)0); 1341 if (error == 0) 1342 cb->s_state = TCPS_LISTEN; 1343 break; 1344 1345 /* 1346 * Initiate connection to peer. 1347 * Enter SYN_SENT state, and mark socket as connecting. 1348 * Start keep-alive timer, setup prototype header, 1349 * Send initial system packet requesting connection. 1350 */ 1351 case PRU_CONNECT: 1352 if (nsp->nsp_lport == 0) { 1353 error = ns_pcbbind(nsp, (struct mbuf *)0); 1354 if (error) 1355 break; 1356 } 1357 error = ns_pcbconnect(nsp, nam); 1358 if (error) 1359 break; 1360 soisconnecting(so); 1361 sppstat.spps_connattempt++; 1362 cb->s_state = TCPS_SYN_SENT; 1363 cb->s_did = 0; 1364 spp_template(cb); 1365 cb->s_timer[SPPT_KEEP] = SPPTV_KEEP; 1366 cb->s_force = 1 + SPPTV_KEEP; 1367 /* 1368 * Other party is required to respond to 1369 * the port I send from, but he is not 1370 * required to answer from where I am sending to, 1371 * so allow wildcarding. 1372 * original port I am sending to is still saved in 1373 * cb->s_dport. 1374 */ 1375 nsp->nsp_fport = 0; 1376 error = spp_output(cb, (struct mbuf *) 0); 1377 break; 1378 1379 case PRU_CONNECT2: 1380 error = EOPNOTSUPP; 1381 break; 1382 1383 /* 1384 * We may decide later to implement connection closing 1385 * handshaking at the spp level optionally. 1386 * here is the hook to do it: 1387 */ 1388 case PRU_DISCONNECT: 1389 cb = spp_disconnect(cb); 1390 break; 1391 1392 /* 1393 * Accept a connection. Essentially all the work is 1394 * done at higher levels; just return the address 1395 * of the peer, storing through addr. 1396 */ 1397 case PRU_ACCEPT: { 1398 struct sockaddr_ns *sns = mtod(nam, struct sockaddr_ns *); 1399 1400 nam->m_len = sizeof (struct sockaddr_ns); 1401 sns->sns_family = AF_NS; 1402 sns->sns_addr = nsp->nsp_faddr; 1403 break; 1404 } 1405 1406 case PRU_SHUTDOWN: 1407 socantsendmore(so); 1408 cb = spp_usrclosed(cb); 1409 if (cb) 1410 error = spp_output(cb, (struct mbuf *) 0); 1411 break; 1412 1413 /* 1414 * After a receive, possibly send acknowledgment 1415 * updating allocation. 1416 */ 1417 case PRU_RCVD: 1418 cb->s_flags |= SF_RVD; 1419 (void) spp_output(cb, (struct mbuf *) 0); 1420 cb->s_flags &= ~SF_RVD; 1421 break; 1422 1423 case PRU_ABORT: 1424 (void) spp_drop(cb, ECONNABORTED); 1425 break; 1426 1427 case PRU_SENSE: 1428 case PRU_CONTROL: 1429 m = NULL; 1430 error = EOPNOTSUPP; 1431 break; 1432 1433 case PRU_RCVOOB: 1434 if ((cb->s_oobflags & SF_IOOB) || so->so_oobmark || 1435 (so->so_state & SS_RCVATMARK)) { 1436 m->m_len = 1; 1437 *mtod(m, caddr_t) = cb->s_iobc; 1438 break; 1439 } 1440 error = EINVAL; 1441 break; 1442 1443 case PRU_SENDOOB: 1444 if (sbspace(&so->so_snd) < -512) { 1445 error = ENOBUFS; 1446 break; 1447 } 1448 cb->s_oobflags |= SF_SOOB; 1449 /* fall into */ 1450 case PRU_SEND: 1451 if (controlp) { 1452 u_short *p = mtod(controlp, u_short *); 1453 spp_newchecks[2]++; 1454 if ((p[0] == 5) && p[1] == 1) { /* XXXX, for testing */ 1455 cb->s_shdr.sp_dt = *(u_char *)(&p[2]); 1456 spp_newchecks[3]++; 1457 } 1458 } 1459 error = spp_output(cb, m); 1460 m = NULL; 1461 break; 1462 1463 case PRU_SOCKADDR: 1464 ns_setsockaddr(nsp, nam); 1465 break; 1466 1467 case PRU_PEERADDR: 1468 ns_setpeeraddr(nsp, nam); 1469 break; 1470 1471 case PRU_SLOWTIMO: 1472 cb = spp_timers(cb, (int)nam); 1473 req |= ((int)nam) << 8; 1474 break; 1475 1476 case PRU_FASTTIMO: 1477 case PRU_PROTORCV: 1478 case PRU_PROTOSEND: 1479 error = EOPNOTSUPP; 1480 break; 1481 1482 default: 1483 panic("sp_usrreq"); 1484 } 1485 if (cb && (so->so_options & SO_DEBUG || traceallspps)) 1486 spp_trace(SA_USER, (u_char)ostate, cb, (struct spidp *)0, req); 1487 release: 1488 if (m != NULL) 1489 m_freem(m); 1490 splx(s); 1491 return (error); 1492 } 1493 1494 spp_usrreq_sp(so, req, m, nam, rights, controlp) 1495 struct socket *so; 1496 int req; 1497 struct mbuf *m, *nam, *rights, *controlp; 1498 { 1499 int error = spp_usrreq(so, req, m, nam, rights, controlp); 1500 1501 if (req == PRU_ATTACH && error == 0) { 1502 struct nspcb *nsp = sotonspcb(so); 1503 ((struct sppcb *)nsp->nsp_pcb)->s_flags |= 1504 (SF_HI | SF_HO | SF_PI); 1505 } 1506 return (error); 1507 } 1508 1509 /* 1510 * Create template to be used to send spp packets on a connection. 1511 * Called after host entry created, fills 1512 * in a skeletal spp header (choosing connection id), 1513 * minimizing the amount of work necessary when the connection is used. 1514 */ 1515 spp_template(cb) 1516 register struct sppcb *cb; 1517 { 1518 register struct nspcb *nsp = cb->s_nspcb; 1519 register struct idp *idp = cb->s_idp; 1520 register struct sockbuf *sb = &(nsp->nsp_socket->so_snd); 1521 1522 idp->idp_pt = NSPROTO_SPP; 1523 idp->idp_sna = nsp->nsp_laddr; 1524 idp->idp_dna = nsp->nsp_faddr; 1525 cb->s_sid = htons(spp_iss); 1526 spp_iss += SPP_ISSINCR/2; 1527 cb->s_alo = 1; 1528 cb->s_cwnd = (sbspace(sb) * CUNIT) / cb->s_mtu; 1529 cb->s_ssthresh = cb->s_cwnd; /* Try to expand fast to full complement 1530 of large packets */ 1531 cb->s_cwmx = (sbspace(sb) * CUNIT) / (2 * sizeof(struct spidp)); 1532 cb->s_cwmx = max(cb->s_cwmx, cb->s_cwnd); 1533 /* But allow for lots of little packets as well */ 1534 } 1535 1536 /* 1537 * Close a SPIP control block: 1538 * discard spp control block itself 1539 * discard ns protocol control block 1540 * wake up any sleepers 1541 */ 1542 struct sppcb * 1543 spp_close(cb) 1544 register struct sppcb *cb; 1545 { 1546 register struct spidp_q *s; 1547 struct nspcb *nsp = cb->s_nspcb; 1548 struct socket *so = nsp->nsp_socket; 1549 register struct mbuf *m; 1550 1551 s = cb->s_q.si_next; 1552 while (s != &(cb->s_q)) { 1553 s = s->si_next; 1554 m = dtom(s->si_prev); 1555 remque(s->si_prev); 1556 m_freem(m); 1557 } 1558 (void) m_free(dtom(cb->s_idp)); 1559 (void) m_free(dtom(cb)); 1560 nsp->nsp_pcb = 0; 1561 soisdisconnected(so); 1562 ns_pcbdetach(nsp); 1563 sppstat.spps_closed++; 1564 return ((struct sppcb *)0); 1565 } 1566 /* 1567 * Someday we may do level 3 handshaking 1568 * to close a connection or send a xerox style error. 1569 * For now, just close. 1570 */ 1571 struct sppcb * 1572 spp_usrclosed(cb) 1573 register struct sppcb *cb; 1574 { 1575 return (spp_close(cb)); 1576 } 1577 struct sppcb * 1578 spp_disconnect(cb) 1579 register struct sppcb *cb; 1580 { 1581 return (spp_close(cb)); 1582 } 1583 /* 1584 * Drop connection, reporting 1585 * the specified error. 1586 */ 1587 struct sppcb * 1588 spp_drop(cb, errno) 1589 register struct sppcb *cb; 1590 int errno; 1591 { 1592 struct socket *so = cb->s_nspcb->nsp_socket; 1593 1594 /* 1595 * someday, in the xerox world 1596 * we will generate error protocol packets 1597 * announcing that the socket has gone away. 1598 */ 1599 if (TCPS_HAVERCVDSYN(cb->s_state)) { 1600 sppstat.spps_drops++; 1601 cb->s_state = TCPS_CLOSED; 1602 /*(void) tcp_output(cb);*/ 1603 } else 1604 sppstat.spps_conndrops++; 1605 so->so_error = errno; 1606 return (spp_close(cb)); 1607 } 1608 1609 spp_abort(nsp) 1610 struct nspcb *nsp; 1611 { 1612 1613 (void) spp_close((struct sppcb *)nsp->nsp_pcb); 1614 } 1615 1616 int spp_backoff[SPP_MAXRXTSHIFT+1] = 1617 { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 }; 1618 /* 1619 * Fast timeout routine for processing delayed acks 1620 */ 1621 spp_fasttimo() 1622 { 1623 register struct nspcb *nsp; 1624 register struct sppcb *cb; 1625 int s = splnet(); 1626 1627 nsp = nspcb.nsp_next; 1628 if (nsp) 1629 for (; nsp != &nspcb; nsp = nsp->nsp_next) 1630 if ((cb = (struct sppcb *)nsp->nsp_pcb) && 1631 (cb->s_flags & SF_DELACK)) { 1632 cb->s_flags &= ~SF_DELACK; 1633 cb->s_flags |= SF_ACKNOW; 1634 sppstat.spps_delack++; 1635 (void) spp_output(cb, (struct mbuf *) 0); 1636 } 1637 splx(s); 1638 } 1639 1640 /* 1641 * spp protocol timeout routine called every 500 ms. 1642 * Updates the timers in all active pcb's and 1643 * causes finite state machine actions if timers expire. 1644 */ 1645 spp_slowtimo() 1646 { 1647 register struct nspcb *ip, *ipnxt; 1648 register struct sppcb *cb; 1649 int s = splnet(); 1650 register int i; 1651 1652 /* 1653 * Search through tcb's and update active timers. 1654 */ 1655 ip = nspcb.nsp_next; 1656 if (ip == 0) { 1657 splx(s); 1658 return; 1659 } 1660 while (ip != &nspcb) { 1661 cb = nstosppcb(ip); 1662 ipnxt = ip->nsp_next; 1663 if (cb == 0) 1664 goto tpgone; 1665 for (i = 0; i < SPPT_NTIMERS; i++) { 1666 if (cb->s_timer[i] && --cb->s_timer[i] == 0) { 1667 (void) spp_usrreq(cb->s_nspcb->nsp_socket, 1668 PRU_SLOWTIMO, (struct mbuf *)0, 1669 (struct mbuf *)i, (struct mbuf *)0, 1670 (struct mbuf *)0); 1671 if (ipnxt->nsp_prev != ip) 1672 goto tpgone; 1673 } 1674 } 1675 cb->s_idle++; 1676 if (cb->s_rtt) 1677 cb->s_rtt++; 1678 tpgone: 1679 ip = ipnxt; 1680 } 1681 spp_iss += SPP_ISSINCR/PR_SLOWHZ; /* increment iss */ 1682 splx(s); 1683 } 1684 /* 1685 * SPP timer processing. 1686 */ 1687 struct sppcb * 1688 spp_timers(cb, timer) 1689 register struct sppcb *cb; 1690 int timer; 1691 { 1692 long rexmt; 1693 int win; 1694 1695 cb->s_force = 1 + timer; 1696 switch (timer) { 1697 1698 /* 1699 * 2 MSL timeout in shutdown went off. TCP deletes connection 1700 * control block. 1701 */ 1702 case SPPT_2MSL: 1703 printf("spp: SPPT_2MSL went off for no reason\n"); 1704 cb->s_timer[timer] = 0; 1705 break; 1706 1707 /* 1708 * Retransmission timer went off. Message has not 1709 * been acked within retransmit interval. Back off 1710 * to a longer retransmit interval and retransmit one packet. 1711 */ 1712 case SPPT_REXMT: 1713 if (++cb->s_rxtshift > SPP_MAXRXTSHIFT) { 1714 cb->s_rxtshift = SPP_MAXRXTSHIFT; 1715 sppstat.spps_timeoutdrop++; 1716 cb = spp_drop(cb, ETIMEDOUT); 1717 break; 1718 } 1719 sppstat.spps_rexmttimeo++; 1720 rexmt = ((cb->s_srtt >> 2) + cb->s_rttvar) >> 1; 1721 rexmt *= spp_backoff[cb->s_rxtshift]; 1722 SPPT_RANGESET(cb->s_rxtcur, rexmt, SPPTV_MIN, SPPTV_REXMTMAX); 1723 cb->s_timer[SPPT_REXMT] = cb->s_rxtcur; 1724 /* 1725 * If we have backed off fairly far, our srtt 1726 * estimate is probably bogus. Clobber it 1727 * so we'll take the next rtt measurement as our srtt; 1728 * move the current srtt into rttvar to keep the current 1729 * retransmit times until then. 1730 */ 1731 if (cb->s_rxtshift > SPP_MAXRXTSHIFT / 4 ) { 1732 cb->s_rttvar += (cb->s_srtt >> 2); 1733 cb->s_srtt = 0; 1734 } 1735 cb->s_snxt = cb->s_rack; 1736 /* 1737 * If timing a packet, stop the timer. 1738 */ 1739 cb->s_rtt = 0; 1740 /* 1741 * See very long discussion in tcp_timer.c about congestion 1742 * window and sstrhesh 1743 */ 1744 win = min(cb->s_swnd, (cb->s_cwnd/CUNIT)) / 2; 1745 if (win < 2) 1746 win = 2; 1747 cb->s_cwnd = CUNIT; 1748 cb->s_ssthresh = win * CUNIT; 1749 (void) spp_output(cb, (struct mbuf *) 0); 1750 break; 1751 1752 /* 1753 * Persistance timer into zero window. 1754 * Force a probe to be sent. 1755 */ 1756 case SPPT_PERSIST: 1757 sppstat.spps_persisttimeo++; 1758 spp_setpersist(cb); 1759 (void) spp_output(cb, (struct mbuf *) 0); 1760 break; 1761 1762 /* 1763 * Keep-alive timer went off; send something 1764 * or drop connection if idle for too long. 1765 */ 1766 case SPPT_KEEP: 1767 sppstat.spps_keeptimeo++; 1768 if (cb->s_state < TCPS_ESTABLISHED) 1769 goto dropit; 1770 if (cb->s_nspcb->nsp_socket->so_options & SO_KEEPALIVE) { 1771 if (cb->s_idle >= SPPTV_MAXIDLE) 1772 goto dropit; 1773 sppstat.spps_keepprobe++; 1774 (void) spp_output(cb, (struct mbuf *) 0); 1775 } else 1776 cb->s_idle = 0; 1777 cb->s_timer[SPPT_KEEP] = SPPTV_KEEP; 1778 break; 1779 dropit: 1780 sppstat.spps_keepdrops++; 1781 cb = spp_drop(cb, ETIMEDOUT); 1782 break; 1783 } 1784 return (cb); 1785 } 1786 #ifndef lint 1787 int SppcbSize = sizeof (struct sppcb); 1788 int NspcbSize = sizeof (struct nspcb); 1789 #endif lint 1790