Print this page
    
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/inet/udp/udp_opt_data.c
          +++ new/usr/src/uts/common/inet/udp/udp_opt_data.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  
    | 
      ↓ open down ↓ | 
    13 lines elided | 
    
      ↑ open up ↑ | 
  
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24      - * Copyright 2015, Joyent, Inc.
  25   24   */
  26   25  
  27   26  #include <sys/types.h>
  28   27  #include <sys/stream.h>
  29   28  #define _SUN_TPI_VERSION 2
  30   29  #include <sys/tihdr.h>
  31   30  #include <sys/socket.h>
  32   31  #include <sys/xti_xtiopt.h>
  33   32  #include <sys/xti_inet.h>
  34   33  
  35   34  #include <inet/common.h>
  36   35  #include <netinet/ip6.h>
  37   36  #include <inet/ip.h>
  38   37  #include <inet/udp_impl.h>
  39   38  /*
  40   39   * MK_XXX Following 2 includes temporary to import ip6_rthdr_t
  41   40   *        definition. May not be needed if we fix ip6_dg_snd_attrs_t
  42   41   *        to do all extension headers in identical manner.
  43   42   */
  44   43  #include <net/if.h>
  45   44  #include <inet/ip6.h>
  46   45  
  47   46  #include <netinet/in.h>
  48   47  #include <netinet/udp.h>
  49   48  #include <inet/optcom.h>
  50   49  
  51   50  /*
  52   51   * Table of all known options handled on a UDP protocol stack.
  53   52   *
  54   53   * Note: This table contains options processed by both UDP and IP levels
  55   54   *       and is the superset of options that can be performed on a UDP over IP
  56   55   *       stack.
  57   56   */
  58   57  opdes_t udp_opt_arr[] = {
  59   58  
  60   59  { SO_DEBUG,     SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
  61   60  { SO_DONTROUTE, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
  62   61  { SO_USELOOPBACK, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0
  63   62          },
  64   63  { SO_BROADCAST, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
  65   64  { SO_REUSEADDR, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
  66   65  { SO_TYPE,      SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
  67   66  { SO_SNDBUF,    SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
  68   67  { SO_RCVBUF,    SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
  69   68  { SO_SNDTIMEO,  SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0,
  70   69          sizeof (struct timeval), 0 },
  71   70  { SO_RCVTIMEO,  SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0,
  72   71          sizeof (struct timeval), 0 },
  73   72  { SO_DGRAM_ERRIND, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int),
  74   73          0 },
  75   74  { SO_RECVUCRED, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0
  76   75          },
  77   76  { SO_ALLZONES, SOL_SOCKET, OA_R, OA_RW, OP_CONFIG, 0, sizeof (int),
  78   77          0 },
  79   78  { SO_VRRP, SOL_SOCKET, OA_RW, OA_RW, OP_CONFIG, 0, sizeof (int), 0 },
  80   79  { SO_TIMESTAMP, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0
  81   80          },
  82   81  { SO_ANON_MLP, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int),
  83   82      0 },
  84   83  { SO_MAC_EXEMPT, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int),
  85   84      0 },
  86   85  { SO_MAC_IMPLICIT, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int),
  87   86      0 },
  88   87  /*
  89   88   * The maximum size reported here depends on the maximum value for
  90   89   * ucredsize; unfortunately, we can't add ucredsize here so we need
  91   90   * to estimate here.  Before it was 512 or 384 + NGROUPS_UMAX * sizeof (gid_t);
  92   91   * as we're changing NGROUPS_UMAX we now codify this here using NGROUPS_UMAX.
  93   92   */
  94   93  { SCM_UCRED, SOL_SOCKET, OA_W, OA_W, OP_NP, OP_VARLEN|OP_NODEFAULT,
  95   94      384 + NGROUPS_UMAX * sizeof (gid_t), 0 },
  96   95  { SO_EXCLBIND, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
  97   96  { SO_DOMAIN,    SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
  98   97  { SO_PROTOTYPE, SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
  99   98  
 100   99  { IP_OPTIONS,   IPPROTO_IP, OA_RW, OA_RW, OP_NP,
 101  100          (OP_VARLEN|OP_NODEFAULT),
 102  101          IP_MAX_OPT_LENGTH + IP_ADDR_LEN, -1 /* not initialized */ },
 103  102  { T_IP_OPTIONS, IPPROTO_IP, OA_RW, OA_RW, OP_NP,
 104  103          (OP_VARLEN|OP_NODEFAULT),
 105  104          IP_MAX_OPT_LENGTH + IP_ADDR_LEN, -1 /* not initialized */ },
 106  105  
 107  106  { IP_TOS,       IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
 108  107  { T_IP_TOS,     IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
 109  108  { IP_TTL,       IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
 110  109  { IP_RECVOPTS,  IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
 111  110  { IP_RECVDSTADDR, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0
 112  111          },
 113  112  { IP_RECVIF, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
 114  113  { IP_RECVSLLA, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
 115  114  { IP_RECVTTL,   IPPROTO_IP,  OA_RW, OA_RW, OP_NP, 0, sizeof (int),
 116  115          0 },
 117  116  { IP_MULTICAST_IF, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0,
 118  117          sizeof (struct in_addr),        0 /* INADDR_ANY */ },
 119  118  
 120  119  { IP_MULTICAST_LOOP, IPPROTO_IP, OA_RW, OA_RW, OP_NP, OP_DEF_FN,
 121  120          sizeof (uchar_t), -1 /* not initialized */},
 122  121  
 123  122  { IP_MULTICAST_TTL, IPPROTO_IP, OA_RW, OA_RW, OP_NP, OP_DEF_FN,
 124  123          sizeof (uchar_t), -1 /* not initialized */ },
 125  124  
 126  125  { IP_ADD_MEMBERSHIP, IPPROTO_IP, OA_X, OA_X, OP_NP, OP_NODEFAULT,
 127  126          sizeof (struct ip_mreq), -1 /* not initialized */ },
 128  127  
 129  128  { IP_DROP_MEMBERSHIP, IPPROTO_IP, OA_X, OA_X, OP_NP, OP_NODEFAULT,
 130  129          sizeof (struct ip_mreq), -1 /* not initialized */ },
 131  130  
 132  131  { IP_BLOCK_SOURCE, IPPROTO_IP, OA_X, OA_X, OP_NP, OP_NODEFAULT,
 133  132          sizeof (struct ip_mreq_source), -1 /* not initialized */ },
 134  133  
 135  134  { IP_UNBLOCK_SOURCE, IPPROTO_IP, OA_X, OA_X, OP_NP, OP_NODEFAULT,
 136  135          sizeof (struct ip_mreq_source), -1 /* not initialized */ },
 137  136  
 138  137  { IP_ADD_SOURCE_MEMBERSHIP, IPPROTO_IP, OA_X, OA_X, OP_NP,
 139  138          OP_NODEFAULT, sizeof (struct ip_mreq_source), -1 },
 140  139  
 141  140  { IP_DROP_SOURCE_MEMBERSHIP, IPPROTO_IP, OA_X, OA_X, OP_NP,
 142  141          OP_NODEFAULT, sizeof (struct ip_mreq_source), -1 },
 143  142  
 144  143  { IP_SEC_OPT, IPPROTO_IP, OA_RW, OA_RW, OP_NP, OP_NODEFAULT,
 145  144          sizeof (ipsec_req_t), -1 /* not initialized */ },
 146  145  
 147  146  { IP_BOUND_IF, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0,
 148  147          sizeof (int),   0 /* no ifindex */ },
 149  148  
 150  149  { IP_DHCPINIT_IF, IPPROTO_IP, OA_R, OA_RW, OP_CONFIG, 0,
 151  150          sizeof (int), 0 },
 152  151  
 153  152  { IP_UNSPEC_SRC, IPPROTO_IP, OA_R, OA_RW, OP_RAW, 0,
 154  153          sizeof (int), 0 },
 155  154  
 156  155  { IP_BROADCAST_TTL, IPPROTO_IP, OA_R, OA_RW, OP_RAW, 0, sizeof (uchar_t),
 157  156          0 /* disabled */ },
 158  157  
 159  158  { IP_PKTINFO, IPPROTO_IP, OA_RW, OA_RW, OP_NP,
 160  159          (OP_NODEFAULT|OP_VARLEN),
 161  160          sizeof (struct in_pktinfo), -1 /* not initialized */ },
 162  161  { IP_NEXTHOP, IPPROTO_IP, OA_R, OA_RW, OP_CONFIG, 0,
 163  162          sizeof (in_addr_t),     -1 /* not initialized  */ },
 164  163  
 165  164  { IP_DONTFRAG, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
 166  165  
 167  166  { MCAST_JOIN_GROUP, IPPROTO_IP, OA_X, OA_X, OP_NP,
 168  167          OP_NODEFAULT, sizeof (struct group_req),
 169  168          -1 /* not initialized */ },
 170  169  { MCAST_LEAVE_GROUP, IPPROTO_IP, OA_X, OA_X, OP_NP,
 171  170          OP_NODEFAULT, sizeof (struct group_req),
 172  171          -1 /* not initialized */ },
 173  172  { MCAST_BLOCK_SOURCE, IPPROTO_IP, OA_X, OA_X, OP_NP,
 174  173          OP_NODEFAULT, sizeof (struct group_source_req),
 175  174          -1 /* not initialized */ },
 176  175  { MCAST_UNBLOCK_SOURCE, IPPROTO_IP, OA_X, OA_X, OP_NP,
 177  176          OP_NODEFAULT, sizeof (struct group_source_req),
 178  177          -1 /* not initialized */ },
 179  178  { MCAST_JOIN_SOURCE_GROUP, IPPROTO_IP, OA_X, OA_X, OP_NP,
 180  179          OP_NODEFAULT, sizeof (struct group_source_req),
 181  180          -1 /* not initialized */ },
 182  181  { MCAST_LEAVE_SOURCE_GROUP, IPPROTO_IP, OA_X, OA_X, OP_NP,
 183  182          OP_NODEFAULT, sizeof (struct group_source_req),
 184  183          -1 /* not initialized */ },
 185  184  
 186  185  { IPV6_MULTICAST_IF, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 187  186          sizeof (int), 0 },
 188  187  
 189  188  { IPV6_MULTICAST_HOPS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
 190  189          OP_DEF_FN, sizeof (int), -1 /* not initialized */ },
 191  190  
 192  191  { IPV6_MULTICAST_LOOP, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
 193  192          OP_DEF_FN, sizeof (int), -1 /* not initialized */},
 194  193  
 195  194  { IPV6_JOIN_GROUP, IPPROTO_IPV6, OA_X, OA_X, OP_NP, OP_NODEFAULT,
 196  195          sizeof (struct ipv6_mreq), -1 /* not initialized */ },
 197  196  
 198  197  { IPV6_LEAVE_GROUP,     IPPROTO_IPV6, OA_X, OA_X, OP_NP,
 199  198          OP_NODEFAULT,
 200  199          sizeof (struct ipv6_mreq), -1 /* not initialized */ },
 201  200  
 202  201  { IPV6_UNICAST_HOPS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, OP_DEF_FN,
 203  202          sizeof (int), -1 /* not initialized */ },
 204  203  
 205  204  { IPV6_BOUND_IF, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 206  205          sizeof (int),   0 /* no ifindex */ },
 207  206  
 208  207  { IPV6_UNSPEC_SRC, IPPROTO_IPV6, OA_R, OA_RW, OP_RAW, 0,
 209  208          sizeof (int), 0 },
 210  209  
 211  210  { IPV6_PKTINFO, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
 212  211          (OP_NODEFAULT|OP_VARLEN),
 213  212          sizeof (struct in6_pktinfo), -1 /* not initialized */ },
 214  213  { IPV6_HOPLIMIT, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
 215  214          OP_NODEFAULT,
 216  215          sizeof (int), -1 /* not initialized */ },
 217  216  { IPV6_NEXTHOP, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
 218  217          (OP_NODEFAULT|OP_VARLEN),
 219  218          sizeof (sin6_t), -1 /* not initialized */ },
 220  219  { IPV6_HOPOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
 221  220          (OP_VARLEN|OP_NODEFAULT),
 222  221          MAX_EHDR_LEN, -1 /* not initialized */ },
 223  222  { IPV6_DSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
 224  223          (OP_VARLEN|OP_NODEFAULT),
 225  224          MAX_EHDR_LEN, -1 /* not initialized */ },
 226  225  { IPV6_RTHDRDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
 227  226          (OP_VARLEN|OP_NODEFAULT),
 228  227          MAX_EHDR_LEN, -1 /* not initialized */ },
 229  228  { IPV6_RTHDR, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
 230  229          (OP_VARLEN|OP_NODEFAULT),
 231  230          MAX_EHDR_LEN, -1 /* not initialized */ },
 232  231  { IPV6_TCLASS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
 233  232          OP_NODEFAULT,
 234  233          sizeof (int), -1 /* not initialized */ },
 235  234  { IPV6_PATHMTU, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
 236  235          OP_NODEFAULT,
 237  236          sizeof (struct ip6_mtuinfo), -1 },
 238  237  { IPV6_DONTFRAG, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 239  238          sizeof (int), 0 },
 240  239  { IPV6_USE_MIN_MTU, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 241  240          sizeof (int), 0 },
 242  241  { IPV6_V6ONLY, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 243  242          sizeof (int), 0 },
 244  243  
 245  244  { IPV6_RECVPKTINFO, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 246  245          sizeof (int), 0 },
 247  246  { IPV6_RECVHOPLIMIT, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 248  247          sizeof (int), 0 },
 249  248  { IPV6_RECVHOPOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 250  249          sizeof (int), 0 },
 251  250  { _OLD_IPV6_RECVDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 252  251          sizeof (int), 0 },
 253  252  { IPV6_RECVDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 254  253          sizeof (int), 0 },
 255  254  { IPV6_RECVRTHDR, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 256  255          sizeof (int), 0 },
 257  256  { IPV6_RECVRTHDRDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 258  257          sizeof (int), 0 },
 259  258  { IPV6_RECVPATHMTU, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
 260  259          0, sizeof (int), 0 },
 261  260  { IPV6_RECVTCLASS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 262  261          sizeof (int), 0 },
 263  262  
 264  263  { IPV6_SEC_OPT, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, OP_NODEFAULT,
 265  264          sizeof (ipsec_req_t), -1 /* not initialized */ },
 266  265  { IPV6_SRC_PREFERENCES, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 267  266          sizeof (uint32_t), IPV6_PREFER_SRC_DEFAULT },
 268  267  
 269  268  { MCAST_JOIN_GROUP, IPPROTO_IPV6, OA_X, OA_X, OP_NP,
 270  269          OP_NODEFAULT, sizeof (struct group_req),
 271  270          -1 /* not initialized */ },
 272  271  { MCAST_LEAVE_GROUP, IPPROTO_IPV6, OA_X, OA_X, OP_NP,
 273  272          OP_NODEFAULT, sizeof (struct group_req),
 274  273          -1 /* not initialized */ },
 275  274  { MCAST_BLOCK_SOURCE, IPPROTO_IPV6, OA_X, OA_X, OP_NP,
 276  275          OP_NODEFAULT, sizeof (struct group_source_req),
 277  276          -1 /* not initialized */ },
 278  277  { MCAST_UNBLOCK_SOURCE, IPPROTO_IPV6, OA_X, OA_X, OP_NP,
 279  278          OP_NODEFAULT, sizeof (struct group_source_req),
 280  279          -1 /* not initialized */ },
 281  280  { MCAST_JOIN_SOURCE_GROUP, IPPROTO_IPV6, OA_X, OA_X, OP_NP,
 282  281          OP_NODEFAULT, sizeof (struct group_source_req),
 283  282          -1 /* not initialized */ },
 284  283  { MCAST_LEAVE_SOURCE_GROUP, IPPROTO_IPV6, OA_X, OA_X, OP_NP,
 285  284          OP_NODEFAULT, sizeof (struct group_source_req),
  
    | 
      ↓ open down ↓ | 
    251 lines elided | 
    
      ↑ open up ↑ | 
  
 286  285          -1 /* not initialized */ },
 287  286  
 288  287  { UDP_ANONPRIVBIND, IPPROTO_UDP, OA_R, OA_RW, OP_PRIVPORT, 0,
 289  288          sizeof (int), 0 },
 290  289  { UDP_EXCLBIND, IPPROTO_UDP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0
 291  290          },
 292  291  { UDP_RCVHDR, IPPROTO_UDP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0
 293  292          },
 294  293  { UDP_NAT_T_ENDPOINT, IPPROTO_UDP, OA_RW, OA_RW, OP_PRIVPORT, 0, sizeof (int),
 295  294          0 },
 296      -{ UDP_SRCPORT_HASH, IPPROTO_UDP, OA_R, OA_RW, OP_CONFIG, 0, sizeof (int), 0 },
 297  295  { UDP_SND_TO_CONNECTED, IPPROTO_UDP, OA_R, OA_RW, OP_CONFIG, 0, sizeof (int),
 298  296          0 }
 299  297  };
 300  298  
 301  299  /*
 302  300   * Table of all supported levels
 303  301   * Note: Some levels (e.g. XTI_GENERIC) may be valid but may not have
 304  302   * any supported options so we need this info separately.
 305  303   *
 306  304   * This is needed only for topmost tpi providers and is used only by
 307  305   * XTI interfaces.
 308  306   */
 309  307  optlevel_t      udp_valid_levels_arr[] = {
 310  308          XTI_GENERIC,
 311  309          SOL_SOCKET,
 312  310          IPPROTO_UDP,
 313  311          IPPROTO_IP,
 314  312          IPPROTO_IPV6
 315  313  };
 316  314  
 317  315  #define UDP_VALID_LEVELS_CNT    A_CNT(udp_valid_levels_arr)
 318  316  #define UDP_OPT_ARR_CNT         A_CNT(udp_opt_arr)
 319  317  
 320  318  uint_t udp_max_optsize; /* initialized when UDP driver is loaded */
 321  319  
 322  320  /*
 323  321   * Initialize option database object for UDP
 324  322   *
 325  323   * This object represents database of options to search passed to
 326  324   * {sock,tpi}optcom_req() interface routine to take care of option
 327  325   * management and associated methods.
 328  326   */
 329  327  
 330  328  optdb_obj_t udp_opt_obj = {
 331  329          udp_opt_default,        /* UDP default value function pointer */
 332  330          udp_tpi_opt_get,        /* UDP get function pointer */
 333  331          udp_tpi_opt_set,        /* UDP set function pointer */
 334  332          UDP_OPT_ARR_CNT,        /* UDP option database count of entries */
 335  333          udp_opt_arr,            /* UDP option database */
 336  334          UDP_VALID_LEVELS_CNT,   /* UDP valid level count of entries */
 337  335          udp_valid_levels_arr    /* UDP valid level array */
 338  336  };
  
    | 
      ↓ open down ↓ | 
    32 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX