Print this page
12694 race between write() and shutdown() for unix sockets

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/io/tl.c
          +++ new/usr/src/uts/common/io/tl.c
↓ open down ↓ 17 lines elided ↑ open up ↑
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   */
  25   25  /*
  26   26   * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  27   27   * Copyright (c) 2012 by Delphix. All rights reserved.
  28      - * Copyright (c) 2018, Joyent, Inc.
       28 + * Copyright 2020 Joyent, Inc.
  29   29   */
  30   30  
  31   31  /*
  32   32   * Multithreaded STREAMS Local Transport Provider.
  33   33   *
  34   34   * OVERVIEW
  35   35   * ========
  36   36   *
  37   37   * This driver provides TLI as well as socket semantics.  It provides
  38   38   * connectionless, connection oriented, and connection oriented with orderly
↓ open down ↓ 330 lines elided ↑ open up ↑
 369  369   */
 370  370  
 371  371  /*
 372  372   * CONSTANT DECLARATIONS
 373  373   * --------------------
 374  374   */
 375  375  
 376  376  /*
 377  377   * Local declarations
 378  378   */
 379      -#define NEXTSTATE(EV, ST)       ti_statetbl[EV][ST]
 380      -
 381  379  #define BADSEQNUM       (-1)    /* initial seq number used by T_DISCON_IND */
 382  380  #define TL_BUFWAIT      (10000) /* usecs to wait for allocb buffer timeout */
 383  381  #define TL_TIDUSZ (64*1024)     /* tidu size when "strmsgz" is unlimited (0) */
 384  382  /*
 385  383   * Hash tables size.
 386  384   */
 387  385  #define TL_HASH_SIZE 311
 388  386  
 389  387  /*
 390  388   * Definitions for module_info
↓ open down ↓ 19 lines elided ↑ open up ↑
 410  408  
 411  409  #define         TL_MINOR_MASK   0x7
 412  410  #define         TL_MINOR_START  (TL_TICLTS + 1)
 413  411  
 414  412  /*
 415  413   * LOCAL MACROS
 416  414   */
 417  415  #define T_ALIGN(p)      P2ROUNDUP((p), sizeof (t_scalar_t))
 418  416  
 419  417  /*
 420      - * EXTERNAL VARIABLE DECLARATIONS
 421      - * -----------------------------
 422      - */
 423      -/*
 424      - * state table defined in the OS space.c
 425      - */
 426      -extern  char    ti_statetbl[TE_NOEVENTS][TS_NOSTATES];
 427      -
 428      -/*
 429  418   * STREAMS DRIVER ENTRY POINTS PROTOTYPES
 430  419   */
 431  420  static int tl_open(queue_t *, dev_t *, int, int, cred_t *);
 432  421  static int tl_close(queue_t *, int, cred_t *);
 433  422  static int tl_wput(queue_t *, mblk_t *);
 434  423  static int tl_wsrv(queue_t *);
 435  424  static int tl_rsrv(queue_t *);
 436  425  
 437  426  static int tl_attach(dev_info_t *, ddi_attach_cmd_t);
 438  427  static int tl_detach(dev_info_t *, ddi_detach_cmd_t);
↓ open down ↓ 377 lines elided ↑ open up ↑
 816  805  
 817  806  /*
 818  807   * Debug and test variable ONLY. Turn off T_CONN_IND queueing
 819  808   * for sockets.
 820  809   */
 821  810  static int tl_disable_early_connect = 0;
 822  811  static int tl_client_closing_when_accepting;
 823  812  
 824  813  static int tl_serializer_noswitch;
 825  814  
      815 +#define nr      127             /* not reachable */
      816 +
      817 +#define TE_NOEVENTS     28
      818 +
      819 +static char nextstate[TE_NOEVENTS][TS_NOSTATES] = {
      820 +                                /* STATES */
      821 +        /* 0  1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16 */
      822 +
      823 +/* Initialization events */
      824 +
      825 +#define TE_BIND_REQ     0       /* bind request                         */
      826 +        { 1, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr},
      827 +#define TE_UNBIND_REQ   1       /* unbind request                       */
      828 +        {nr, nr, nr,  2, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr},
      829 +#define TE_OPTMGMT_REQ  2       /* manage options req                   */
      830 +        {nr, nr, nr,  4, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr},
      831 +#define TE_BIND_ACK     3       /* bind acknowledment                   */
      832 +        {nr,  3, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr},
      833 +#define TE_OPTMGMT_ACK  4       /* manage options ack                   */
      834 +        {nr, nr, nr, nr,  3, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr},
      835 +#define TE_ERROR_ACK    5       /* error acknowledgment                 */
      836 +        {nr,  0,  3, nr,  3,  3, nr, nr,  7, nr, nr, nr,  6,  7,  9, 10, 11},
      837 +#define TE_OK_ACK1      6       /* ok ack  seqcnt == 0                  */
      838 +        {nr, nr,  0, nr, nr,  6, nr, nr, nr, nr, nr, nr,  3, nr,  3,  3,  3},
      839 +#define TE_OK_ACK2      7       /* ok ack  seqcnt == 1, q == resq       */
      840 +        {nr, nr, nr, nr, nr, nr, nr, nr,  9, nr, nr, nr, nr,  3, nr, nr, nr},
      841 +#define TE_OK_ACK3      8       /* ok ack  seqcnt == 1, q != resq       */
      842 +        {nr, nr, nr, nr, nr, nr, nr, nr,  3, nr, nr, nr, nr,  3, nr, nr, nr},
      843 +#define TE_OK_ACK4      9       /* ok ack  seqcnt > 1                   */
      844 +        {nr, nr, nr, nr, nr, nr, nr, nr,  7, nr, nr, nr, nr,  7, nr, nr, nr},
      845 +
      846 +/* Connection oriented events */
      847 +#define TE_CONN_REQ     10      /* connection request                   */
      848 +        {nr, nr, nr,  5, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr},
      849 +#define TE_CONN_RES     11      /* connection response                  */
      850 +        {nr, nr, nr, nr, nr, nr, nr,  8, nr, nr, nr, nr, nr, nr, nr, nr, nr},
      851 +#define TE_DISCON_REQ   12      /* disconnect request                   */
      852 +        {nr, nr, nr, nr, nr, nr, 12, 13, nr, 14, 15, 16, nr, nr, nr, nr, nr},
      853 +#define TE_DATA_REQ     13      /* data request                         */
      854 +        {nr, nr, nr, nr, nr, nr, nr, nr, nr,  9, nr, 11, nr, nr, nr, nr, nr},
      855 +#define TE_EXDATA_REQ   14      /* expedited data request               */
      856 +        {nr, nr, nr, nr, nr, nr, nr, nr, nr,  9, nr, 11, nr, nr, nr, nr, nr},
      857 +#define TE_ORDREL_REQ   15      /* orderly release req                  */
      858 +        {nr, nr, nr, nr, nr, nr, nr, nr, nr, 10, nr,  3, nr, nr, nr, nr, nr},
      859 +#define TE_CONN_IND     16      /* connection indication                */
      860 +        {nr, nr, nr,  7, nr, nr, nr,  7, nr, nr, nr, nr, nr, nr, nr, nr, nr},
      861 +#define TE_CONN_CON     17      /* connection confirmation              */
      862 +        {nr, nr, nr, nr, nr, nr,  9, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr},
      863 +#define TE_DATA_IND     18      /* data indication                      */
      864 +        {nr, nr, nr, nr, nr, nr, nr, nr, nr,  9, 10, nr, nr, nr, nr, nr, nr},
      865 +#define TE_EXDATA_IND   19      /* expedited data indication            */
      866 +        {nr, nr, nr, nr, nr, nr, nr, nr, nr,  9, 10, nr, nr, nr, nr, nr, nr},
      867 +#define TE_ORDREL_IND   20      /* orderly release ind                  */
      868 +        {nr, nr, nr, nr, nr, nr, nr, nr, nr, 11,  3, nr, nr, nr, nr, nr, nr},
      869 +#define TE_DISCON_IND1  21      /* disconnect indication seq == 0       */
      870 +        {nr, nr, nr, nr, nr, nr,  3, nr, nr,  3,  3,  3, nr, nr, nr, nr, nr},
      871 +#define TE_DISCON_IND2  22      /* disconnect indication seq == 1       */
      872 +        {nr, nr, nr, nr, nr, nr, nr,  3, nr, nr, nr, nr, nr, nr, nr, nr, nr},
      873 +#define TE_DISCON_IND3  23      /* disconnect indication seq > 1        */
      874 +        {nr, nr, nr, nr, nr, nr, nr,  7, nr, nr, nr, nr, nr, nr, nr, nr, nr},
      875 +#define TE_PASS_CONN    24      /* pass connection                      */
      876 +        {nr, nr, nr,  9, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr},
      877 +
      878 +
      879 +/* Unit data events */
      880 +
      881 +#define TE_UNITDATA_REQ 25      /* unitdata request                     */
      882 +        {nr, nr, nr,  3, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr},
      883 +#define TE_UNITDATA_IND 26      /* unitdata indication                  */
      884 +        {nr, nr, nr,  3, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr},
      885 +#define TE_UDERROR_IND  27      /* unitdata error indication            */
      886 +        {nr, nr, nr,  3, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr, nr},
      887 +};
      888 +
      889 +
      890 +
 826  891  /*
 827  892   * LOCAL FUNCTION PROTOTYPES
 828  893   * -------------------------
 829  894   */
 830  895  static boolean_t tl_eqaddr(tl_addr_t *, tl_addr_t *);
 831  896  static void tl_do_proto(mblk_t *, tl_endpt_t *);
 832  897  static void tl_do_ioctl(mblk_t *, tl_endpt_t *);
 833  898  static void tl_do_ioctl_ser(mblk_t *, tl_endpt_t *);
 834  899  static void tl_error_ack(queue_t *, mblk_t *, t_scalar_t, t_scalar_t,
 835  900      t_scalar_t);
↓ open down ↓ 1112 lines elided ↑ open up ↑
1948 2013  
1949 2014          /*
1950 2015           * fastpath for data. Ignore flow control if tep is closing.
1951 2016           */
1952 2017          if ((peer_tep != NULL) &&
1953 2018              !peer_tep->te_closing &&
1954 2019              ((tep->te_state == TS_DATA_XFER) ||
1955 2020              (tep->te_state == TS_WREQ_ORDREL)) &&
1956 2021              (tep->te_wq != NULL) &&
1957 2022              (tep->te_wq->q_first == NULL) &&
1958      -            ((peer_tep->te_state == TS_DATA_XFER) ||
1959      -            (peer_tep->te_state == TS_WREQ_ORDREL))     &&
     2023 +            (peer_tep->te_state == TS_DATA_XFER ||
     2024 +            peer_tep->te_state == TS_WIND_ORDREL ||
     2025 +            peer_tep->te_state == TS_WREQ_ORDREL) &&
1960 2026              ((peer_rq = peer_tep->te_rq) != NULL) &&
1961 2027              (canputnext(peer_rq) || tep->te_closing)) {
1962 2028                  putnext(peer_rq, mp);
1963 2029          } else if (tep->te_closing) {
1964 2030                  /*
1965 2031                   * It is possible that by the time we got here tep started to
1966 2032                   * close. If the write queue is not empty, and the state is
1967 2033                   * TS_DATA_XFER the data should be delivered in order, so we
1968 2034                   * call putq() instead of freeing the data.
1969 2035                   */
↓ open down ↓ 405 lines elided ↑ open up ↑
2375 2441                  tli_err = TOUTSTATE;
2376 2442                  goto error;
2377 2443          }
2378 2444  
2379 2445          if (msz < sizeof (struct T_bind_req)) {
2380 2446                  tli_err = TSYSERR;
2381 2447                  unix_err = EINVAL;
2382 2448                  goto error;
2383 2449          }
2384 2450  
2385      -        tep->te_state = NEXTSTATE(TE_BIND_REQ, tep->te_state);
     2451 +        tep->te_state = nextstate[TE_BIND_REQ][tep->te_state];
2386 2452  
2387 2453          ASSERT((bind->PRIM_type == O_T_BIND_REQ) ||
2388 2454              (bind->PRIM_type == T_BIND_REQ));
2389 2455  
2390 2456          alen = bind->ADDR_length;
2391 2457          aoff = bind->ADDR_offset;
2392 2458  
2393 2459          /* negotiate max conn req pending */
2394 2460          if (IS_COTS(tep)) {
2395 2461                  qlen = bind->CONIND_number;
↓ open down ↓ 19 lines elided ↑ open up ↑
2415 2481           */
2416 2482          if (IS_SOCKET(tep)) {
2417 2483                  ASSERT(bind->PRIM_type == O_T_BIND_REQ);
2418 2484  
2419 2485                  if ((alen != TL_SOUX_ADDRLEN) ||
2420 2486                      (aoff < 0) ||
2421 2487                      (aoff + alen > msz)) {
2422 2488                          (void) (STRLOG(TL_ID, tep->te_minor,
2423 2489                              1, SL_TRACE | SL_ERROR,
2424 2490                              "tl_bind: invalid socket addr"));
2425      -                        tep->te_state = NEXTSTATE(TE_ERROR_ACK, tep->te_state);
     2491 +                        tep->te_state = nextstate[TE_ERROR_ACK][tep->te_state];
2426 2492                          tli_err = TSYSERR;
2427 2493                          unix_err = EINVAL;
2428 2494                          goto error;
2429 2495                  }
2430 2496                  /* Copy address from message to local buffer. */
2431 2497                  bcopy(mp->b_rptr + aoff, &ux_addr, sizeof (ux_addr));
2432 2498                  /*
2433 2499                   * Check that we got correct address from sockets
2434 2500                   */
2435 2501                  if ((ux_addr.soua_magic != SOU_MAGIC_EXPLICIT) &&
2436 2502                      (ux_addr.soua_magic != SOU_MAGIC_IMPLICIT)) {
2437 2503                          (void) (STRLOG(TL_ID, tep->te_minor,
2438 2504                              1, SL_TRACE | SL_ERROR,
2439 2505                              "tl_bind: invalid socket magic"));
2440      -                        tep->te_state = NEXTSTATE(TE_ERROR_ACK, tep->te_state);
     2506 +                        tep->te_state = nextstate[TE_ERROR_ACK][tep->te_state];
2441 2507                          tli_err = TSYSERR;
2442 2508                          unix_err = EINVAL;
2443 2509                          goto error;
2444 2510                  }
2445 2511                  if ((ux_addr.soua_magic == SOU_MAGIC_IMPLICIT) &&
2446 2512                      (ux_addr.soua_vp != NULL)) {
2447 2513                          (void) (STRLOG(TL_ID, tep->te_minor,
2448 2514                              1, SL_TRACE | SL_ERROR,
2449 2515                              "tl_bind: implicit addr non-empty"));
2450      -                        tep->te_state = NEXTSTATE(TE_ERROR_ACK, tep->te_state);
     2516 +                        tep->te_state = nextstate[TE_ERROR_ACK][tep->te_state];
2451 2517                          tli_err = TSYSERR;
2452 2518                          unix_err = EINVAL;
2453 2519                          goto error;
2454 2520                  }
2455 2521                  if ((ux_addr.soua_magic == SOU_MAGIC_EXPLICIT) &&
2456 2522                      (ux_addr.soua_vp == NULL)) {
2457 2523                          (void) (STRLOG(TL_ID, tep->te_minor,
2458 2524                              1, SL_TRACE | SL_ERROR,
2459 2525                              "tl_bind: explicit addr empty"));
2460      -                        tep->te_state = NEXTSTATE(TE_ERROR_ACK, tep->te_state);
     2526 +                        tep->te_state = nextstate[TE_ERROR_ACK][tep->te_state];
2461 2527                          tli_err = TSYSERR;
2462 2528                          unix_err = EINVAL;
2463 2529                          goto error;
2464 2530                  }
2465 2531          } else {
2466 2532                  if ((alen > 0) && ((aoff < 0) ||
2467 2533                      ((ssize_t)(aoff + alen) > msz) ||
2468 2534                      ((aoff + alen) < 0))) {
2469 2535                          (void) (STRLOG(TL_ID, tep->te_minor,
2470 2536                              1, SL_TRACE | SL_ERROR,
2471 2537                              "tl_bind: invalid message"));
2472      -                        tep->te_state = NEXTSTATE(TE_ERROR_ACK, tep->te_state);
     2538 +                        tep->te_state = nextstate[TE_ERROR_ACK][tep->te_state];
2473 2539                          tli_err = TSYSERR;
2474 2540                          unix_err = EINVAL;
2475 2541                          goto error;
2476 2542                  }
2477 2543                  if ((alen < 0) || (alen > (msz - sizeof (struct T_bind_req)))) {
2478 2544                          (void) (STRLOG(TL_ID, tep->te_minor,
2479 2545                              1, SL_TRACE | SL_ERROR,
2480 2546                              "tl_bind: bad addr in  message"));
2481      -                        tep->te_state = NEXTSTATE(TE_ERROR_ACK, tep->te_state);
     2547 +                        tep->te_state = nextstate[TE_ERROR_ACK][tep->te_state];
2482 2548                          tli_err = TBADADDR;
2483 2549                          goto error;
2484 2550                  }
2485 2551  #ifdef DEBUG
2486 2552                  /*
2487 2553                   * Mild form of ASSERT()ion to detect broken TPI apps.
2488 2554                   * if (!assertion)
2489 2555                   *      log warning;
2490 2556                   */
2491 2557                  if (!((alen == 0 && aoff == 0) ||
↓ open down ↓ 145 lines elided ↑ open up ↑
2637 2703          b_ack->ADDR_offset = (t_scalar_t)sizeof (struct T_bind_ack);
2638 2704          addr_startp = bamp->b_rptr + b_ack->ADDR_offset;
2639 2705          bcopy(tep->te_abuf, addr_startp, tep->te_alen);
2640 2706  
2641 2707          if (IS_COTS(tep)) {
2642 2708                  tep->te_qlen = qlen;
2643 2709                  if (qlen > 0)
2644 2710                          tep->te_flag |= TL_LISTENER;
2645 2711          }
2646 2712  
2647      -        tep->te_state = NEXTSTATE(TE_BIND_ACK, tep->te_state);
     2713 +        tep->te_state = nextstate[TE_BIND_ACK][tep->te_state];
2648 2714          /*
2649 2715           * send T_BIND_ACK message
2650 2716           */
2651 2717          (void) qreply(wq, bamp);
2652 2718          return;
2653 2719  
2654 2720  error:
2655 2721          ackmp = reallocb(mp, sizeof (struct T_error_ack), 0);
2656 2722          if (ackmp == NULL) {
2657 2723                  /*
2658 2724                   * roll back state changes
2659 2725                   */
2660 2726                  tep->te_state = save_state;
2661 2727                  tl_memrecover(wq, mp, sizeof (struct T_error_ack));
2662 2728                  return;
2663 2729          }
2664      -        tep->te_state = NEXTSTATE(TE_ERROR_ACK, tep->te_state);
     2730 +        tep->te_state = nextstate[TE_ERROR_ACK][tep->te_state];
2665 2731          tl_error_ack(wq, ackmp, tli_err, unix_err, save_prim_type);
2666 2732  }
2667 2733  
2668 2734  /*
2669 2735   * Process T_UNBIND_REQ.
2670 2736   * Called from serializer.
2671 2737   */
2672 2738  static void
2673 2739  tl_unbind(mblk_t *mp, tl_endpt_t *tep)
2674 2740  {
↓ open down ↓ 25 lines elided ↑ open up ↑
2700 2766           * validate state
2701 2767           */
2702 2768          if (tep->te_state != TS_IDLE) {
2703 2769                  (void) (STRLOG(TL_ID, tep->te_minor, 1,
2704 2770                      SL_TRACE | SL_ERROR,
2705 2771                      "tl_wput:T_UNBIND_REQ:out of state, state=%d",
2706 2772                      tep->te_state));
2707 2773                  tl_error_ack(wq, ackmp, TOUTSTATE, 0, T_UNBIND_REQ);
2708 2774                  return;
2709 2775          }
2710      -        tep->te_state = NEXTSTATE(TE_UNBIND_REQ, tep->te_state);
     2776 +        tep->te_state = nextstate[TE_UNBIND_REQ][tep->te_state];
2711 2777  
2712 2778          /*
2713 2779           * TPI says on T_UNBIND_REQ:
2714 2780           *    send up a M_FLUSH to flush both
2715 2781           *    read and write queues
2716 2782           */
2717 2783          (void) putnextctl1(RD(wq), M_FLUSH, FLUSHRW);
2718 2784  
2719 2785          if (!IS_SOCKET(tep) || !IS_CLTS(tep) || tep->te_qlen != 0 ||
2720 2786              tep->te_magic != SOU_MAGIC_EXPLICIT) {
2721 2787  
2722 2788                  /*
2723 2789                   * Sockets use bind with qlen==0 followed by bind() to
2724 2790                   * the same address with qlen > 0 for listeners.
2725 2791                   * We allow rebind with a new qlen value.
2726 2792                   */
2727 2793                  tl_addr_unbind(tep);
2728 2794          }
2729 2795  
2730      -        tep->te_state = NEXTSTATE(TE_OK_ACK1, tep->te_state);
     2796 +        tep->te_state = nextstate[TE_OK_ACK1][tep->te_state];
2731 2797          /*
2732 2798           * send  T_OK_ACK
2733 2799           */
2734 2800          tl_ok_ack(wq, ackmp, T_UNBIND_REQ);
2735 2801  }
2736 2802  
2737 2803  
2738 2804  /*
2739 2805   * Option management code from drv/ip is used here
2740 2806   * Note: TL_PROT_LEVEL/TL_IOC_CREDOPT option is not part of tl_opt_arr
↓ open down ↓ 217 lines elided ↑ open up ↑
2958 3024           * Prevent tep from closing on us.
2959 3025           */
2960 3026          if (!tl_noclose(tep)) {
2961 3027                  (void) (STRLOG(TL_ID, tep->te_minor, 1, SL_TRACE | SL_ERROR,
2962 3028                      "tl_conn_req:endpoint is closing"));
2963 3029                  tl_error_ack(wq, ackmp, TOUTSTATE, 0, T_CONN_REQ);
2964 3030                  freemsg(mp);
2965 3031                  return;
2966 3032          }
2967 3033  
2968      -        tep->te_state = NEXTSTATE(TE_CONN_REQ, tep->te_state);
     3034 +        tep->te_state = nextstate[TE_CONN_REQ][tep->te_state];
2969 3035          /*
2970 3036           * get endpoint to connect to
2971 3037           * check that peer with DEST addr is bound to addr
2972 3038           * and has CONIND_number > 0
2973 3039           */
2974 3040          dst.ta_alen = alen;
2975 3041          dst.ta_abuf = mp->b_rptr + aoff;
2976 3042          dst.ta_zoneid = tep->te_zoneid;
2977 3043  
2978 3044          /*
↓ open down ↓ 17 lines elided ↑ open up ↑
2996 3062                  err = ECONNREFUSED;
2997 3063          }
2998 3064  
2999 3065          /*
3000 3066           * Send T_DISCON_IND in case of error
3001 3067           */
3002 3068          if (err != 0) {
3003 3069                  if (peer_tep != NULL)
3004 3070                          tl_refrele(peer_tep);
3005 3071                  /* We are still expected to send T_OK_ACK */
3006      -                tep->te_state = NEXTSTATE(TE_OK_ACK1, tep->te_state);
     3072 +                tep->te_state = nextstate[TE_OK_ACK1][tep->te_state];
3007 3073                  tl_ok_ack(tep->te_wq, ackmp, T_CONN_REQ);
3008 3074                  tl_closeok(tep);
3009 3075                  dimp = tpi_ack_alloc(mp, sizeof (struct T_discon_ind),
3010 3076                      M_PROTO, T_DISCON_IND);
3011 3077                  if (dimp == NULL) {
3012 3078                          tl_merror(wq, NULL, ENOSR);
3013 3079                          return;
3014 3080                  }
3015 3081                  di = (struct T_discon_ind *)dimp->b_rptr;
3016 3082                  di->DISCON_reason = err;
↓ open down ↓ 200 lines elided ↑ open up ↑
3217 3283          tip->ti_mp = NULL;
3218 3284  
3219 3285          /*
3220 3286           * memory is now committed for T_DISCON_IND/T_CONN_IND/T_CONN_CON
3221 3287           * and tl_icon_t cell.
3222 3288           */
3223 3289  
3224 3290          /*
3225 3291           * ack validity of request and send the peer credential in the ACK.
3226 3292           */
3227      -        tep->te_state = NEXTSTATE(TE_OK_ACK1, tep->te_state);
     3293 +        tep->te_state = nextstate[TE_OK_ACK1][tep->te_state];
3228 3294  
3229 3295          if (peer_tep != NULL && peer_tep->te_credp != NULL &&
3230 3296              confmp != NULL) {
3231 3297                  mblk_setcred(confmp, peer_tep->te_credp, peer_tep->te_cpid);
3232 3298          }
3233 3299  
3234 3300          tl_ok_ack(wq, ackmp, T_CONN_REQ);
3235 3301  
3236 3302          /*
3237 3303           * prepare message to send T_CONN_IND
↓ open down ↓ 53 lines elided ↑ open up ↑
3291 3357           * register connection request with server peer
3292 3358           * append to list of incoming connections
3293 3359           * increment references for both peer_tep and tep: peer_tep is placed on
3294 3360           * te_oconp and tep is placed on listeners queue.
3295 3361           */
3296 3362          tip->ti_tep = tep;
3297 3363          tip->ti_seqno = tep->te_seqno;
3298 3364          list_insert_tail(&peer_tep->te_iconp, tip);
3299 3365          peer_tep->te_nicon++;
3300 3366  
3301      -        peer_tep->te_state = NEXTSTATE(TE_CONN_IND, peer_tep->te_state);
     3367 +        peer_tep->te_state = nextstate[TE_CONN_IND][peer_tep->te_state];
3302 3368          /*
3303 3369           * send the T_CONN_IND message
3304 3370           */
3305 3371          putnext(peer_tep->te_rq, cimp);
3306 3372  
3307 3373          /*
3308 3374           * Send a T_CONN_CON message for sockets.
3309 3375           * Disable the queues until we have reached the correct state!
3310 3376           */
3311 3377          if (confmp != NULL) {
3312      -                tep->te_state = NEXTSTATE(TE_CONN_CON, tep->te_state);
     3378 +                tep->te_state = nextstate[TE_CONN_CON][tep->te_state];
3313 3379                  noenable(wq);
3314 3380                  putnext(tep->te_rq, confmp);
3315 3381          }
3316 3382          /*
3317 3383           * Now we need to increment tep reference because tep is referenced by
3318 3384           * server list of pending connections. We also need to decrement
3319 3385           * reference before exiting serializer. Two operations void each other
3320 3386           * so we don't modify reference at all.
3321 3387           */
3322 3388          ASSERT(tep->te_refcnt >= 2);
↓ open down ↓ 99 lines elided ↑ open up ↑
3422 3488                   * no opts in connect res
3423 3489                   * supported in this provider
3424 3490                   */
3425 3491                  (void) (STRLOG(TL_ID, tep->te_minor, 1, SL_TRACE | SL_ERROR,
3426 3492                      "tl_conn_res:options not supported in message"));
3427 3493                  tl_error_ack(wq, ackmp, TBADOPT, 0, prim);
3428 3494                  freemsg(mp);
3429 3495                  return;
3430 3496          }
3431 3497  
3432      -        tep->te_state = NEXTSTATE(TE_CONN_RES, tep->te_state);
     3498 +        tep->te_state = nextstate[TE_CONN_RES][tep->te_state];
3433 3499          ASSERT(tep->te_state == TS_WACK_CRES);
3434 3500  
3435 3501          if (cres->SEQ_number < TL_MINOR_START &&
3436 3502              cres->SEQ_number >= BADSEQNUM) {
3437 3503                  (void) (STRLOG(TL_ID, tep->te_minor, 2, SL_TRACE | SL_ERROR,
3438 3504                      "tl_conn_res:remote endpoint sequence number bad"));
3439      -                tep->te_state = NEXTSTATE(TE_ERROR_ACK, tep->te_state);
     3505 +                tep->te_state = nextstate[TE_ERROR_ACK][tep->te_state];
3440 3506                  tl_error_ack(wq, ackmp, TBADSEQ, 0, prim);
3441 3507                  freemsg(mp);
3442 3508                  return;
3443 3509          }
3444 3510  
3445 3511          /*
3446 3512           * find accepting endpoint. Will have extra reference if found.
3447 3513           */
3448 3514          if (mod_hash_find_cb(tep->te_transport->tr_ai_hash,
3449 3515              (mod_hash_key_t)(uintptr_t)cres->ACCEPTOR_id,
3450 3516              (mod_hash_val_t *)&acc_ep, tl_find_callback) != 0) {
3451 3517                  (void) (STRLOG(TL_ID, tep->te_minor, 2, SL_TRACE | SL_ERROR,
3452 3518                      "tl_conn_res:bad accepting endpoint"));
3453      -                tep->te_state = NEXTSTATE(TE_ERROR_ACK, tep->te_state);
     3519 +                tep->te_state = nextstate[TE_ERROR_ACK][tep->te_state];
3454 3520                  tl_error_ack(wq, ackmp, TBADF, 0, prim);
3455 3521                  freemsg(mp);
3456 3522                  return;
3457 3523          }
3458 3524  
3459 3525          /*
3460 3526           * Prevent acceptor from closing.
3461 3527           */
3462 3528          if (!tl_noclose(acc_ep)) {
3463 3529                  (void) (STRLOG(TL_ID, tep->te_minor, 2, SL_TRACE | SL_ERROR,
3464 3530                      "tl_conn_res:bad accepting endpoint"));
3465      -                tep->te_state = NEXTSTATE(TE_ERROR_ACK, tep->te_state);
     3531 +                tep->te_state = nextstate[TE_ERROR_ACK][tep->te_state];
3466 3532                  tl_error_ack(wq, ackmp, TBADF, 0, prim);
3467 3533                  tl_refrele(acc_ep);
3468 3534                  freemsg(mp);
3469 3535                  return;
3470 3536          }
3471 3537  
3472 3538          acc_ep->te_flag |= TL_ACCEPTOR;
3473 3539  
3474 3540          /*
3475 3541           * validate that accepting endpoint, if different from listening
3476 3542           * has address bound => state is TS_IDLE
3477 3543           * TROUBLE in XPG4 !!?
3478 3544           */
3479 3545          if ((tep != acc_ep) && (acc_ep->te_state != TS_IDLE)) {
3480 3546                  (void) (STRLOG(TL_ID, tep->te_minor, 2, SL_TRACE | SL_ERROR,
3481 3547                      "tl_conn_res:accepting endpoint has no address bound,"
3482 3548                      "state=%d", acc_ep->te_state));
3483      -                tep->te_state = NEXTSTATE(TE_ERROR_ACK, tep->te_state);
     3549 +                tep->te_state = nextstate[TE_ERROR_ACK][tep->te_state];
3484 3550                  tl_error_ack(wq, ackmp, TOUTSTATE, 0, prim);
3485 3551                  freemsg(mp);
3486 3552                  tl_closeok(acc_ep);
3487 3553                  tl_refrele(acc_ep);
3488 3554                  return;
3489 3555          }
3490 3556  
3491 3557          /*
3492 3558           * validate if accepting endpt same as listening, then
3493 3559           * no other incoming connection should be on the queue
3494 3560           */
3495 3561  
3496 3562          if ((tep == acc_ep) && (tep->te_nicon > 1)) {
3497 3563                  (void) (STRLOG(TL_ID, tep->te_minor, 3, SL_TRACE | SL_ERROR,
3498 3564                      "tl_conn_res: > 1 conn_ind on listener-acceptor"));
3499      -                tep->te_state = NEXTSTATE(TE_ERROR_ACK, tep->te_state);
     3565 +                tep->te_state = nextstate[TE_ERROR_ACK][tep->te_state];
3500 3566                  tl_error_ack(wq, ackmp, TBADF, 0, prim);
3501 3567                  freemsg(mp);
3502 3568                  tl_closeok(acc_ep);
3503 3569                  tl_refrele(acc_ep);
3504 3570                  return;
3505 3571          }
3506 3572  
3507 3573          /*
3508 3574           * Mark for deletion, the entry corresponding to client
3509 3575           * on list of pending connections made by the listener
3510 3576           *  search list to see if client is one of the
3511 3577           * recorded as a listener.
3512 3578           */
3513 3579          tip = tl_icon_find(tep, cres->SEQ_number);
3514 3580          if (tip == NULL) {
3515 3581                  (void) (STRLOG(TL_ID, tep->te_minor, 2, SL_TRACE | SL_ERROR,
3516 3582                      "tl_conn_res:no client in listener list"));
3517      -                tep->te_state = NEXTSTATE(TE_ERROR_ACK, tep->te_state);
     3583 +                tep->te_state = nextstate[TE_ERROR_ACK][tep->te_state];
3518 3584                  tl_error_ack(wq, ackmp, TBADSEQ, 0, prim);
3519 3585                  freemsg(mp);
3520 3586                  tl_closeok(acc_ep);
3521 3587                  tl_refrele(acc_ep);
3522 3588                  return;
3523 3589          }
3524 3590  
3525 3591          /*
3526 3592           * If ti_tep is NULL the client has already closed. In this case
3527 3593           * the code below will avoid any action on the client side
↓ open down ↓ 97 lines elided ↑ open up ↑
3625 3691                          return;
3626 3692                  }
3627 3693                  mp = NULL;
3628 3694          }
3629 3695  
3630 3696          /*
3631 3697           * Now ack validity of request
3632 3698           */
3633 3699          if (tep->te_nicon == 1) {
3634 3700                  if (tep == acc_ep)
3635      -                        tep->te_state = NEXTSTATE(TE_OK_ACK2, tep->te_state);
     3701 +                        tep->te_state = nextstate[TE_OK_ACK2][tep->te_state];
3636 3702                  else
3637      -                        tep->te_state = NEXTSTATE(TE_OK_ACK3, tep->te_state);
     3703 +                        tep->te_state = nextstate[TE_OK_ACK3][tep->te_state];
3638 3704          } else {
3639      -                tep->te_state = NEXTSTATE(TE_OK_ACK4, tep->te_state);
     3705 +                tep->te_state = nextstate[TE_OK_ACK4][tep->te_state];
3640 3706          }
3641 3707  
3642 3708          /*
3643 3709           * send T_DISCON_IND now if client state validation failed earlier
3644 3710           */
3645 3711          if (err) {
3646 3712                  tl_ok_ack(wq, ackmp, prim);
3647 3713                  /*
3648 3714                   * flush the queues - why always ?
3649 3715                   */
↓ open down ↓ 32 lines elided ↑ open up ↑
3682 3748                          tl_closeok(cl_ep);
3683 3749                  tl_closeok(acc_ep);
3684 3750                  tl_refrele(acc_ep);
3685 3751                  return;
3686 3752          }
3687 3753  
3688 3754          /*
3689 3755           * now start connecting the accepting endpoint
3690 3756           */
3691 3757          if (tep != acc_ep)
3692      -                acc_ep->te_state = NEXTSTATE(TE_PASS_CONN, acc_ep->te_state);
     3758 +                acc_ep->te_state = nextstate[TE_PASS_CONN][acc_ep->te_state];
3693 3759  
3694 3760          if (cl_ep == NULL) {
3695 3761                  /*
3696 3762                   * The client has already closed. Send up any queued messages
3697 3763                   * and change the state accordingly.
3698 3764                   */
3699 3765                  tl_ok_ack(wq, ackmp, prim);
3700 3766                  tl_icon_sendmsgs(acc_ep, &tip->ti_mp);
3701 3767  
3702 3768                  /*
↓ open down ↓ 140 lines elided ↑ open up ↑
3843 3909           */
3844 3910          if (IS_SOCKET(cl_ep) && !tl_disable_early_connect) {
3845 3911                  enableok(cl_ep->te_wq);
3846 3912                  TL_QENABLE(cl_ep);
3847 3913                  if (ccmp != NULL)
3848 3914                          freemsg(ccmp);
3849 3915          } else {
3850 3916                  /*
3851 3917                   * change client state on TE_CONN_CON event
3852 3918                   */
3853      -                cl_ep->te_state = NEXTSTATE(TE_CONN_CON, cl_ep->te_state);
     3919 +                cl_ep->te_state = nextstate[TE_CONN_CON][cl_ep->te_state];
3854 3920                  putnext(cl_ep->te_rq, ccmp);
3855 3921          }
3856 3922  
3857 3923          /* Mark the both endpoints as accepted */
3858 3924          cl_ep->te_flag |= TL_ACCEPTED;
3859 3925          acc_ep->te_flag |= TL_ACCEPTED;
3860 3926  
3861 3927          /*
3862 3928           * Allow client and acceptor to close.
3863 3929           */
↓ open down ↓ 65 lines elided ↑ open up ↑
3929 3995                      "tl_wput:T_DISCON_REQ:out of state, state=%d",
3930 3996                      tep->te_state));
3931 3997                  tl_error_ack(wq, ackmp, TOUTSTATE, 0, T_DISCON_REQ);
3932 3998                  freemsg(mp);
3933 3999                  return;
3934 4000          }
3935 4001          /*
3936 4002           * Defer committing the state change until it is determined if
3937 4003           * the message will be queued with the tl_icon or not.
3938 4004           */
3939      -        new_state  = NEXTSTATE(TE_DISCON_REQ, tep->te_state);
     4005 +        new_state  = nextstate[TE_DISCON_REQ][tep->te_state];
3940 4006  
3941 4007          /* validate the message */
3942 4008          if (msz < sizeof (struct T_discon_req)) {
3943 4009                  (void) (STRLOG(TL_ID, tep->te_minor, 1, SL_TRACE | SL_ERROR,
3944 4010                      "tl_discon_req:invalid message"));
3945      -                tep->te_state = NEXTSTATE(TE_ERROR_ACK, new_state);
     4011 +                tep->te_state = nextstate[TE_ERROR_ACK][new_state];
3946 4012                  tl_error_ack(wq, ackmp, TSYSERR, EINVAL, T_DISCON_REQ);
3947 4013                  freemsg(mp);
3948 4014                  return;
3949 4015          }
3950 4016  
3951 4017          /*
3952 4018           * if server, then validate that client exists
3953 4019           * by connection sequence number etc.
3954 4020           */
3955 4021          if (tep->te_nicon > 0) { /* server */
3956 4022  
3957 4023                  /*
3958 4024                   * search server list for disconnect client
3959 4025                   */
3960 4026                  tip = tl_icon_find(tep, dr->SEQ_number);
3961 4027                  if (tip == NULL) {
3962 4028                          (void) (STRLOG(TL_ID, tep->te_minor, 2,
3963 4029                              SL_TRACE | SL_ERROR,
3964 4030                              "tl_discon_req:no disconnect endpoint"));
3965      -                        tep->te_state = NEXTSTATE(TE_ERROR_ACK, new_state);
     4031 +                        tep->te_state = nextstate[TE_ERROR_ACK][new_state];
3966 4032                          tl_error_ack(wq, ackmp, TBADSEQ, 0, T_DISCON_REQ);
3967 4033                          freemsg(mp);
3968 4034                          return;
3969 4035                  }
3970 4036                  /*
3971 4037                   * If ti_tep is NULL the client has already closed. In this case
3972 4038                   * the code below will avoid any action on the client side.
3973 4039                   */
3974 4040  
3975 4041                  IMPLY(tip->ti_tep != NULL,
↓ open down ↓ 9 lines elided ↑ open up ↑
3985 4051          if ((respmp = reallocb(mp, size, 0)) == NULL) {
3986 4052                  tl_memrecover(wq, mp, size);
3987 4053                  freemsg(ackmp);
3988 4054                  return;
3989 4055          }
3990 4056  
3991 4057          /*
3992 4058           * prepare message to ack validity of request
3993 4059           */
3994 4060          if (tep->te_nicon == 0) {
3995      -                new_state = NEXTSTATE(TE_OK_ACK1, new_state);
     4061 +                new_state = nextstate[TE_OK_ACK1][new_state];
3996 4062          } else {
3997 4063                  if (tep->te_nicon == 1)
3998      -                        new_state = NEXTSTATE(TE_OK_ACK2, new_state);
     4064 +                        new_state = nextstate[TE_OK_ACK2][new_state];
3999 4065                  else
4000      -                        new_state = NEXTSTATE(TE_OK_ACK4, new_state);
     4066 +                        new_state = nextstate[TE_OK_ACK4][new_state];
4001 4067          }
4002 4068  
4003 4069          /*
4004 4070           * Flushing queues according to TPI. Using the old state.
4005 4071           */
4006 4072          if ((tep->te_nicon <= 1) &&
4007 4073              ((save_state == TS_DATA_XFER) ||
4008 4074              (save_state == TS_WIND_ORDREL) ||
4009 4075              (save_state == TS_WREQ_ORDREL)))
4010 4076                  (void) putnextctl1(RD(wq), M_FLUSH, FLUSHRW);
↓ open down ↓ 79 lines elided ↑ open up ↑
4090 4156                           */
4091 4157                          new_state = tep->te_state;
4092 4158                  } else {
4093 4159                          /* Found - delete it */
4094 4160                          tip = tl_icon_find(peer_tep, tep->te_seqno);
4095 4161                          if (tip != NULL) {
4096 4162                                  ASSERT(tep == tip->ti_tep);
4097 4163                                  save_state = peer_tep->te_state;
4098 4164                                  if (peer_tep->te_nicon == 1)
4099 4165                                          peer_tep->te_state =
4100      -                                            NEXTSTATE(TE_DISCON_IND2,
4101      -                                            peer_tep->te_state);
     4166 +                                            nextstate[TE_DISCON_IND2]
     4167 +                                            [peer_tep->te_state];
4102 4168                                  else
4103 4169                                          peer_tep->te_state =
4104      -                                            NEXTSTATE(TE_DISCON_IND3,
4105      -                                            peer_tep->te_state);
     4170 +                                            nextstate[TE_DISCON_IND3]
     4171 +                                            [peer_tep->te_state];
4106 4172                                  tl_freetip(peer_tep, tip);
4107 4173                          }
4108 4174                          ASSERT(tep->te_oconp != NULL);
4109 4175                          TL_UNCONNECT(tep->te_oconp);
4110 4176                  }
4111 4177          } else if ((peer_tep = tep->te_conp) != NULL) { /* connected! */
4112 4178                  if ((dimp = tl_resizemp(respmp, size)) == NULL) {
4113 4179                          (void) (STRLOG(TL_ID, tep->te_minor, 2,
4114 4180                              SL_TRACE | SL_ERROR,
4115 4181                              "tl_discon_req: reallocb failed"));
↓ open down ↓ 442 lines elided ↑ open up ↑
4558 4624                  break;
4559 4625  
4560 4626          default:
4561 4627                  /* invalid state for event TE_DATA_REQ */
4562 4628                  (void) (STRLOG(TL_ID, tep->te_minor, 1, SL_TRACE | SL_ERROR,
4563 4629                      "tl_data:cots:out of state"));
4564 4630                  tl_merror(wq, mp, EPROTO);
4565 4631                  return;
4566 4632          }
4567 4633          /*
4568      -         * tep->te_state = NEXTSTATE(TE_DATA_REQ, tep->te_state);
     4634 +         * tep->te_state = nextstate[TE_DATA_REQ][tep->te_state];
4569 4635           * (State stays same on this event)
4570 4636           */
4571 4637  
4572 4638          /*
4573 4639           * get connected endpoint
4574 4640           */
4575 4641          if (((peer_tep = tep->te_conp) == NULL) || peer_tep->te_closing) {
4576 4642                  freemsg(mp);
4577 4643                  /* Peer closed */
4578 4644                  (void) (STRLOG(TL_ID, tep->te_minor, 3, SL_TRACE,
↓ open down ↓ 29 lines elided ↑ open up ↑
4608 4674                  return;
4609 4675          }
4610 4676          if (DB_TYPE(mp) == M_PROTO) {
4611 4677                  /* reuse message block - just change REQ to IND */
4612 4678                  if (prim->type == T_DATA_REQ)
4613 4679                          prim->type = T_DATA_IND;
4614 4680                  else
4615 4681                          prim->type = T_OPTDATA_IND;
4616 4682          }
4617 4683          /*
4618      -         * peer_tep->te_state = NEXTSTATE(TE_DATA_IND, peer_tep->te_state);
     4684 +         * peer_tep->te_state = nextstate[TE_DATA_IND][peer_tep->te_state];
4619 4685           * (peer state stays same on this event)
4620 4686           */
4621 4687          /*
4622 4688           * send data to connected peer
4623 4689           */
4624 4690          putnext(peer_rq, mp);
4625 4691  }
4626 4692  
4627 4693  
4628 4694  
↓ open down ↓ 96 lines elided ↑ open up ↑
4725 4791  
4726 4792          default:
4727 4793                  (void) (STRLOG(TL_ID, tep->te_minor, 1,
4728 4794                      SL_TRACE | SL_ERROR,
4729 4795                      "tl_wput:T_EXDATA_REQ:out of state, state=%d",
4730 4796                      tep->te_state));
4731 4797                  tl_merror(wq, mp, EPROTO);
4732 4798                  return;
4733 4799          }
4734 4800          /*
4735      -         * tep->te_state = NEXTSTATE(TE_EXDATA_REQ, tep->te_state);
     4801 +         * tep->te_state = nextstate[TE_EXDATA_REQ][tep->te_state];
4736 4802           * (state stays same on this event)
4737 4803           */
4738 4804  
4739 4805          /*
4740 4806           * get connected endpoint
4741 4807           */
4742 4808          if (((peer_tep = tep->te_conp) == NULL) || peer_tep->te_closing) {
4743 4809                  freemsg(mp);
4744 4810                  /* Peer closed */
4745 4811                  (void) (STRLOG(TL_ID, tep->te_minor, 3, SL_TRACE,
↓ open down ↓ 21 lines elided ↑ open up ↑
4767 4833          case TS_WIND_ORDREL:
4768 4834                  /* valid states */
4769 4835                  break;
4770 4836          default:
4771 4837                  (void) (STRLOG(TL_ID, tep->te_minor, 1, SL_TRACE | SL_ERROR,
4772 4838                      "tl_exdata:rx side:invalid state"));
4773 4839                  tl_merror(peer_tep->te_wq, mp, EPROTO);
4774 4840                  return;
4775 4841          }
4776 4842          /*
4777      -         * peer_tep->te_state = NEXTSTATE(TE_DATA_IND, peer_tep->te_state);
     4843 +         * peer_tep->te_state = nextstate[TE_DATA_IND][peer_tep->te_state];
4778 4844           * (peer state stays same on this event)
4779 4845           */
4780 4846          /*
4781 4847           * reuse message block
4782 4848           */
4783 4849          prim->type = T_EXDATA_IND;
4784 4850  
4785 4851          /*
4786 4852           * send data to connected peer
4787 4853           */
↓ open down ↓ 63 lines elided ↑ open up ↑
4851 4917                      SL_TRACE | SL_ERROR,
4852 4918                      "tl_wput:T_ORDREL_REQ:out of state, state=%d",
4853 4919                      tep->te_state));
4854 4920                  if (!closing) {
4855 4921                          tl_merror(wq, mp, EPROTO);
4856 4922                  } else {
4857 4923                          freemsg(mp);
4858 4924                  }
4859 4925                  return;
4860 4926          }
4861      -        tep->te_state = NEXTSTATE(TE_ORDREL_REQ, tep->te_state);
     4927 +        tep->te_state = nextstate[TE_ORDREL_REQ][tep->te_state];
4862 4928  
4863 4929          /*
4864 4930           * get connected endpoint
4865 4931           */
4866 4932          if (((peer_tep = tep->te_conp) == NULL) || peer_tep->te_closing) {
4867 4933                  /* Peer closed */
4868 4934                  (void) (STRLOG(TL_ID, tep->te_minor, 3, SL_TRACE,
4869 4935                      "tl_ordrel: peer gone"));
4870 4936                  freemsg(mp);
4871 4937                  return;
↓ open down ↓ 18 lines elided ↑ open up ↑
4890 4956          case TS_DATA_XFER:
4891 4957          case TS_WIND_ORDREL:
4892 4958                  /* valid states */
4893 4959                  break;
4894 4960          default:
4895 4961                  (void) (STRLOG(TL_ID, tep->te_minor, 1, SL_TRACE | SL_ERROR,
4896 4962                      "tl_ordrel:rx side:invalid state"));
4897 4963                  tl_merror(peer_tep->te_wq, mp, EPROTO);
4898 4964                  return;
4899 4965          }
4900      -        peer_tep->te_state = NEXTSTATE(TE_ORDREL_IND, peer_tep->te_state);
     4966 +        peer_tep->te_state = nextstate[TE_ORDREL_IND][peer_tep->te_state];
4901 4967  
4902 4968          /*
4903 4969           * reuse message block
4904 4970           */
4905 4971          prim->type = T_ORDREL_IND;
4906 4972          (void) (STRLOG(TL_ID, tep->te_minor, 3, SL_TRACE,
4907 4973              "tl_ordrel: send ordrel_ind"));
4908 4974  
4909 4975          /*
4910 4976           * send data to connected peer
↓ open down ↓ 64 lines elided ↑ open up ↑
4975 5041                      uderr->DEST_length);
4976 5042                  addr_startp = mp->b_rptr + udreq->OPT_offset;
4977 5043                  bcopy(addr_startp, err_mp->b_rptr+uderr->OPT_offset,
4978 5044                      (size_t)olen);
4979 5045          }
4980 5046          freemsg(mp);
4981 5047  
4982 5048          /*
4983 5049           * send indication message
4984 5050           */
4985      -        tep->te_state = NEXTSTATE(TE_UDERROR_IND, tep->te_state);
     5051 +        tep->te_state = nextstate[TE_UDERROR_IND][tep->te_state];
4986 5052  
4987 5053          qreply(wq, err_mp);
4988 5054  }
4989 5055  
4990 5056  static void
4991 5057  tl_unitdata_ser(mblk_t *mp, tl_endpt_t *tep)
4992 5058  {
4993 5059          queue_t *wq = tep->te_wq;
4994 5060  
4995 5061          if (!tep->te_closing && (wq->q_first != NULL)) {
↓ open down ↓ 37 lines elided ↑ open up ↑
5033 5099           * validate the state
5034 5100           */
5035 5101          if (tep->te_state != TS_IDLE) {
5036 5102                  (void) (STRLOG(TL_ID, tep->te_minor, 1,
5037 5103                      SL_TRACE | SL_ERROR,
5038 5104                      "tl_wput:T_CONN_REQ:out of state"));
5039 5105                  tl_merror(wq, mp, EPROTO);
5040 5106                  return;
5041 5107          }
5042 5108          /*
5043      -         * tep->te_state = NEXTSTATE(TE_UNITDATA_REQ, tep->te_state);
     5109 +         * tep->te_state = nextstate[TE_UNITDATA_REQ][tep->te_state];
5044 5110           * (state does not change on this event)
5045 5111           */
5046 5112  
5047 5113          /*
5048 5114           * validate the message
5049 5115           * Note: dereference fields in struct inside message only
5050 5116           * after validating the message length.
5051 5117           */
5052 5118          if (msz < sizeof (struct T_unitdata_req)) {
5053 5119                  (void) (STRLOG(TL_ID, tep->te_minor, 1, SL_TRACE | SL_ERROR,
↓ open down ↓ 278 lines elided ↑ open up ↑
5332 5398                  /*
5333 5399                   * relink data blocks from mp to ui_mp
5334 5400                   */
5335 5401                  ui_mp->b_cont = mp->b_cont;
5336 5402                  freeb(mp);
5337 5403                  mp = ui_mp;
5338 5404          }
5339 5405          /*
5340 5406           * send indication message
5341 5407           */
5342      -        peer_tep->te_state = NEXTSTATE(TE_UNITDATA_IND, peer_tep->te_state);
     5408 +        peer_tep->te_state = nextstate[TE_UNITDATA_IND][peer_tep->te_state];
5343 5409          putnext(peer_tep->te_rq, mp);
5344 5410  }
5345 5411  
5346 5412  
5347 5413  
5348 5414  /*
5349 5415   * Check if a given addr is in use.
5350 5416   * Endpoint ptr returned or NULL if not found.
5351 5417   * The name space is separate for each mode. This implies that
5352 5418   * sockets get their own name space.
↓ open down ↓ 301 lines elided ↑ open up ↑
5654 5720                          if (tip == NULL) {
5655 5721                                  freemsg(d_mp);
5656 5722                          } else {
5657 5723                                  ASSERT(tep == tip->ti_tep);
5658 5724                                  ASSERT(tep->te_ser == srv_tep->te_ser);
5659 5725                                  /*
5660 5726                                   * Delete tip from the server list.
5661 5727                                   */
5662 5728                                  if (srv_tep->te_nicon == 1) {
5663 5729                                          srv_tep->te_state =
5664      -                                            NEXTSTATE(TE_DISCON_IND2,
5665      -                                            srv_tep->te_state);
     5730 +                                            nextstate[TE_DISCON_IND2]
     5731 +                                            [srv_tep->te_state];
5666 5732                                  } else {
5667 5733                                          srv_tep->te_state =
5668      -                                            NEXTSTATE(TE_DISCON_IND3,
5669      -                                            srv_tep->te_state);
     5734 +                                            nextstate[TE_DISCON_IND3]
     5735 +                                            [srv_tep->te_state];
5670 5736                                  }
5671 5737                                  ASSERT(*(uint32_t *)(d_mp->b_rptr) ==
5672 5738                                      T_DISCON_IND);
5673 5739                                  putnext(srv_tep->te_rq, d_mp);
5674 5740                                  tl_freetip(srv_tep, tip);
5675 5741                          }
5676 5742                          TL_UNCONNECT(tep->te_oconp);
5677 5743                          srv_tep = NULL;
5678 5744                  }
5679 5745          } else if (peer_tep != NULL) {
↓ open down ↓ 7 lines elided ↑ open up ↑
5687 5753                  ASSERT(tep->te_ser == peer_tep->te_ser);
5688 5754                  if (IS_COTSORD(peer_tep) &&
5689 5755                      (peer_tep->te_state == TS_WIND_ORDREL ||
5690 5756                      peer_tep->te_state == TS_DATA_XFER)) {
5691 5757                          /*
5692 5758                           * send ordrel ind
5693 5759                           */
5694 5760                          (void) (STRLOG(TL_ID, tep->te_minor, 3, SL_TRACE,
5695 5761                          "tl_co_unconnect:connected: ordrel_ind state %d->%d",
5696 5762                              peer_tep->te_state,
5697      -                            NEXTSTATE(TE_ORDREL_IND, peer_tep->te_state)));
     5763 +                            nextstate[TE_ORDREL_IND][peer_tep->te_state]));
5698 5764                          d_mp = tl_ordrel_ind_alloc();
5699 5765                          if (d_mp == NULL) {
5700 5766                                  (void) (STRLOG(TL_ID, tep->te_minor, 3,
5701 5767                                      SL_TRACE | SL_ERROR,
5702 5768                                      "tl_co_unconnect:connected:"
5703 5769                                      "allocb failure"));
5704 5770                                  /*
5705 5771                                   * Continue with cleaning up peer as
5706 5772                                   * this side may go away with the close
5707 5773                                   */
5708 5774                                  TL_QENABLE(peer_tep);
5709 5775                                  goto discon_peer;
5710 5776                          }
5711 5777                          peer_tep->te_state =
5712      -                            NEXTSTATE(TE_ORDREL_IND, peer_tep->te_state);
     5778 +                            nextstate[TE_ORDREL_IND][peer_tep->te_state];
5713 5779  
5714 5780                          putnext(peer_tep->te_rq, d_mp);
5715 5781                          /*
5716 5782                           * Handle flow control case.  This will generate
5717 5783                           * a t_discon_ind message with reason 0 if there
5718 5784                           * is data queued on the write side.
5719 5785                           */
5720 5786                          TL_QENABLE(peer_tep);
5721 5787                  } else if (IS_COTSORD(peer_tep) &&
5722 5788                      peer_tep->te_state == TS_WREQ_ORDREL) {
↓ open down ↓ 223 lines elided ↑ open up ↑
5946 6012                  case M_PROTO:
5947 6013                          primp = (union T_primitives *)mp->b_rptr;
5948 6014                          switch (primp->type) {
5949 6015                          case T_UNITDATA_IND:
5950 6016                          case T_DATA_IND:
5951 6017                          case T_OPTDATA_IND:
5952 6018                          case T_EXDATA_IND:
5953 6019                                  putnext(tep->te_rq, mp);
5954 6020                                  break;
5955 6021                          case T_ORDREL_IND:
5956      -                                tep->te_state = NEXTSTATE(TE_ORDREL_IND,
5957      -                                    tep->te_state);
     6022 +                                tep->te_state = nextstate[TE_ORDREL_IND]
     6023 +                                    [tep->te_state];
5958 6024                                  putnext(tep->te_rq, mp);
5959 6025                                  break;
5960 6026                          case T_DISCON_IND:
5961 6027                                  tep->te_state = TS_IDLE;
5962 6028                                  putnext(tep->te_rq, mp);
5963 6029                                  break;
5964 6030                          default:
5965 6031  #ifdef DEBUG
5966 6032                                  cmn_err(CE_PANIC,
5967 6033                                      "tl_icon_sendmsgs: unknown primitive");
↓ open down ↓ 356 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX