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