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