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