Print this page
    
dccp: snoop, build system fixes
    
      
        | Split | Close | 
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ip.c
          +++ new/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ip.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
  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   24   */
  25   25  
  26   26  #include <stdio.h>
  27   27  #include <string.h>
  28   28  #include <fcntl.h>
  29   29  #include <string.h>
  30   30  #include <sys/types.h>
  31   31  #include <sys/time.h>
  32   32  
  33   33  #include <sys/stropts.h>
  34   34  #include <sys/socket.h>
  35   35  #include <net/if.h>
  36   36  #include <netinet/in_systm.h>
  37   37  #include <netinet/in.h>
  38   38  #include <netinet/ip.h>
  39   39  #include <netinet/ip6.h>
  40   40  #include <netinet/ip_icmp.h>
  41   41  #include <netinet/icmp6.h>
  42   42  #include <netinet/if_ether.h>
  43   43  #include <inet/ip.h>
  44   44  #include <inet/ip6.h>
  45   45  #include <arpa/inet.h>
  46   46  #include <netdb.h>
  47   47  #include <tsol/label.h>
  48   48  #include <sys/tsol/tndb.h>
  49   49  #include <sys/tsol/label_macro.h>
  50   50  
  51   51  #include "snoop.h"
  52   52  
  53   53  
  54   54  /*
  55   55   * IPv6 extension header masks.  These are used by the print_ipv6_extensions()
  56   56   * function to return information to the caller about which extension headers
  57   57   * were processed.  This can be useful if the caller wants to know if the
  58   58   * packet is an IPv6 fragment, for example.
  59   59   */
  60   60  #define SNOOP_HOPOPTS   0x01U
  61   61  #define SNOOP_ROUTING   0x02U
  62   62  #define SNOOP_DSTOPTS   0x04U
  63   63  #define SNOOP_FRAGMENT  0x08U
  64   64  #define SNOOP_AH        0x10U
  65   65  #define SNOOP_ESP       0x20U
  66   66  #define SNOOP_IPV6      0x40U
  67   67  
  68   68  static void prt_routing_hdr(int, const struct ip6_rthdr *);
  69   69  static void prt_fragment_hdr(int, const struct ip6_frag *);
  70   70  static void prt_hbh_options(int, const struct ip6_hbh *);
  71   71  static void prt_dest_options(int, const struct ip6_dest *);
  72   72  static void print_route(const uchar_t *);
  73   73  static void print_ipoptions(const uchar_t *, int);
  74   74  static void print_ripso(const uchar_t *);
  75   75  static void print_cipso(const uchar_t *);
  76   76  
  77   77  /* Keep track of how many nested IP headers we have. */
  78   78  unsigned int encap_levels;
  79   79  unsigned int total_encap_levels = 1;
  80   80  
  81   81  int
  82   82  interpret_ip(int flags, const struct ip *ip, int fraglen)
  83   83  {
  84   84          uchar_t *data;
  85   85          char buff[24];
  86   86          boolean_t isfrag = B_FALSE;
  87   87          boolean_t morefrag;
  88   88          uint16_t fragoffset;
  89   89          int hdrlen;
  90   90          uint16_t iplen, uitmp;
  91   91  
  92   92          if (ip->ip_v == IPV6_VERSION) {
  93   93                  iplen = interpret_ipv6(flags, (ip6_t *)ip, fraglen);
  94   94                  return (iplen);
  95   95          }
  96   96  
  97   97          if (encap_levels == 0)
  98   98                  total_encap_levels = 0;
  99   99          encap_levels++;
 100  100          total_encap_levels++;
 101  101  
 102  102          hdrlen = ip->ip_hl * 4;
 103  103          data = ((uchar_t *)ip) + hdrlen;
 104  104          iplen = ntohs(ip->ip_len) - hdrlen;
 105  105          fraglen -= hdrlen;
 106  106          if (fraglen > iplen)
 107  107                  fraglen = iplen;
 108  108          if (fraglen < 0) {
 109  109                  (void) snprintf(get_sum_line(), MAXLINE,
 110  110                      "IP truncated: header missing %d bytes", -fraglen);
 111  111                  encap_levels--;
 112  112                  return (fraglen + iplen);
 113  113          }
 114  114          /*
 115  115           * We flag this as a fragment if the more fragments bit is set, or
 116  116           * if the fragment offset is non-zero.
 117  117           */
 118  118          morefrag = (ntohs(ip->ip_off) & IP_MF) == 0 ? B_FALSE : B_TRUE;
 119  119          fragoffset = (ntohs(ip->ip_off) & 0x1FFF) * 8;
 120  120          if (morefrag || fragoffset != 0)
 121  121                  isfrag = B_TRUE;
 122  122  
 123  123          src_name = addrtoname(AF_INET, &ip->ip_src);
 124  124          dst_name = addrtoname(AF_INET, &ip->ip_dst);
 125  125  
 126  126          if (flags & F_SUM) {
 127  127                  if (isfrag) {
 128  128                          (void) snprintf(get_sum_line(), MAXLINE,
 129  129                              "%s IP fragment ID=%d Offset=%-4d MF=%d TOS=0x%x "
 130  130                              "TTL=%d",
 131  131                              getproto(ip->ip_p),
 132  132                              ntohs(ip->ip_id),
 133  133                              fragoffset,
 134  134                              morefrag,
 135  135                              ip->ip_tos,
 136  136                              ip->ip_ttl);
 137  137                  } else {
 138  138                          (void) strlcpy(buff, inet_ntoa(ip->ip_dst),
 139  139                              sizeof (buff));
 140  140                          uitmp = ntohs(ip->ip_len);
 141  141                          (void) snprintf(get_sum_line(), MAXLINE,
 142  142                              "IP  D=%s S=%s LEN=%u%s, ID=%d, TOS=0x%x, TTL=%d",
 143  143                              buff,
 144  144                              inet_ntoa(ip->ip_src),
 145  145                              uitmp,
 146  146                              iplen > fraglen ? "?" : "",
 147  147                              ntohs(ip->ip_id),
 148  148                              ip->ip_tos,
 149  149                              ip->ip_ttl);
 150  150                  }
 151  151          }
 152  152  
 153  153          if (flags & F_DTAIL) {
 154  154                  show_header("IP:   ", "IP Header", iplen);
 155  155                  show_space();
 156  156                  (void) snprintf(get_line(0, 0), get_line_remain(),
 157  157                      "Version = %d", ip->ip_v);
 158  158                  (void) snprintf(get_line(0, 0), get_line_remain(),
 159  159                      "Header length = %d bytes", hdrlen);
 160  160                  (void) snprintf(get_line(0, 0), get_line_remain(),
 161  161                      "Type of service = 0x%02x", ip->ip_tos);
 162  162                  (void) snprintf(get_line(0, 0), get_line_remain(),
 163  163                      "      xxx. .... = %d (precedence)",
 164  164                      ip->ip_tos >> 5);
 165  165                  (void) snprintf(get_line(0, 0), get_line_remain(),
 166  166                      "      %s", getflag(ip->ip_tos, IPTOS_LOWDELAY,
 167  167                      "low delay", "normal delay"));
 168  168                  (void) snprintf(get_line(0, 0), get_line_remain(), "      %s",
 169  169                      getflag(ip->ip_tos, IPTOS_THROUGHPUT,
 170  170                      "high throughput", "normal throughput"));
 171  171                  (void) snprintf(get_line(0, 0), get_line_remain(), "      %s",
 172  172                      getflag(ip->ip_tos, IPTOS_RELIABILITY,
 173  173                      "high reliability", "normal reliability"));
 174  174                  (void) snprintf(get_line(0, 0), get_line_remain(), "      %s",
 175  175                      getflag(ip->ip_tos, IPTOS_ECT,
 176  176                      "ECN capable transport", "not ECN capable transport"));
 177  177                  (void) snprintf(get_line(0, 0), get_line_remain(), "      %s",
 178  178                      getflag(ip->ip_tos, IPTOS_CE,
 179  179                      "ECN congestion experienced",
 180  180                      "no ECN congestion experienced"));
 181  181                  /* warning: ip_len is signed in netinet/ip.h */
 182  182                  uitmp = ntohs(ip->ip_len);
 183  183                  (void) snprintf(get_line(0, 0), get_line_remain(),
 184  184                      "Total length = %u bytes%s", uitmp,
 185  185                      iplen > fraglen ? " -- truncated" : "");
 186  186                  (void) snprintf(get_line(0, 0), get_line_remain(),
 187  187                      "Identification = %d", ntohs(ip->ip_id));
 188  188                  /* warning: ip_off is signed in netinet/ip.h */
 189  189                  uitmp = ntohs(ip->ip_off);
 190  190                  (void) snprintf(get_line(0, 0), get_line_remain(),
 191  191                      "Flags = 0x%x", uitmp >> 12);
 192  192                  (void) snprintf(get_line(0, 0), get_line_remain(), "      %s",
 193  193                      getflag(uitmp >> 8, IP_DF >> 8,
 194  194                      "do not fragment", "may fragment"));
 195  195                  (void) snprintf(get_line(0, 0), get_line_remain(), "      %s",
 196  196                      getflag(uitmp >> 8, IP_MF >> 8,
 197  197                      "more fragments", "last fragment"));
 198  198                  (void) snprintf(get_line(0, 0), get_line_remain(),
 199  199                      "Fragment offset = %u bytes",
 200  200                      fragoffset);
 201  201                  (void) snprintf(get_line(0, 0), get_line_remain(),
 202  202                      "Time to live = %d seconds/hops",
 203  203                      ip->ip_ttl);
 204  204                  (void) snprintf(get_line(0, 0), get_line_remain(),
 205  205                      "Protocol = %d (%s)", ip->ip_p,
 206  206                      getproto(ip->ip_p));
 207  207                  /*
 208  208                   * XXX need to compute checksum and print whether it's correct
 209  209                   */
 210  210                  (void) snprintf(get_line(0, 0), get_line_remain(),
 211  211                      "Header checksum = %04x",
 212  212                      ntohs(ip->ip_sum));
 213  213                  (void) snprintf(get_line(0, 0), get_line_remain(),
 214  214                      "Source address = %s, %s",
 215  215                      inet_ntoa(ip->ip_src), addrtoname(AF_INET, &ip->ip_src));
 216  216                  (void) snprintf(get_line(0, 0), get_line_remain(),
 217  217                      "Destination address = %s, %s",
 218  218                      inet_ntoa(ip->ip_dst), addrtoname(AF_INET, &ip->ip_dst));
 219  219  
 220  220                  /* Print IP options - if any */
 221  221  
 222  222                  print_ipoptions((const uchar_t *)(ip + 1),
 223  223                      hdrlen - sizeof (struct ip));
 224  224                  show_space();
 225  225          }
 226  226  
 227  227          /*
 228  228           * If we are in detail mode, and this is not the first fragment of
 229  229           * a fragmented packet, print out a little line stating this.
 230  230           * Otherwise, go to the next protocol layer only if this is not a
 231  231           * fragment, or we are in detail mode and this is the first fragment
 232  232           * of a fragmented packet.
 233  233           */
 234  234          if (flags & F_DTAIL && fragoffset != 0) {
 235  235                  (void) snprintf(get_detail_line(0, 0), MAXLINE,
 236  236                      "%s:  [%d byte(s) of data, continuation of IP ident=%d]",
 237  237                      getproto(ip->ip_p),
 238  238                      iplen,
 239  239                      ntohs(ip->ip_id));
 240  240          } else if (!isfrag || (flags & F_DTAIL) && isfrag && fragoffset == 0) {
 241  241                  /* go to the next protocol layer */
 242  242  
 243  243                  if (fraglen > 0) {
 244  244                          switch (ip->ip_p) {
 245  245                          case IPPROTO_IP:
 246  246                                  break;
 247  247                          case IPPROTO_ENCAP:
 248  248                                  (void) interpret_ip(flags,
 249  249                                      /* LINTED: alignment */
 250  250                                      (const struct ip *)data, fraglen);
 251  251                                  break;
 252  252                          case IPPROTO_ICMP:
 253  253                                  (void) interpret_icmp(flags,
 254  254                                      /* LINTED: alignment */
 255  255                                      (struct icmp *)data, iplen, fraglen);
 256  256                                  break;
 257  257                          case IPPROTO_IGMP:
 258  258                                  interpret_igmp(flags, data, iplen, fraglen);
 259  259                                  break;
 260  260                          case IPPROTO_GGP:
 261  261                                  break;
 262  262                          case IPPROTO_TCP:
 263  263                                  (void) interpret_tcp(flags,
 264  264                                      (struct tcphdr *)data, iplen, fraglen);
 265  265                                  break;
 266  266  
 267  267                          case IPPROTO_ESP:
 268  268                                  (void) interpret_esp(flags, data, iplen,
 269  269                                      fraglen);
 270  270                                  break;
 271  271                          case IPPROTO_AH:
 272  272                                  (void) interpret_ah(flags, data, iplen,
 273  273                                      fraglen);
 274  274                                  break;
 275  275  
 276  276                          case IPPROTO_OSPF:
 277  277                                  interpret_ospf(flags, data, iplen, fraglen);
 278  278                                  break;
 279  279  
 280  280                          case IPPROTO_EGP:
 281  281                          case IPPROTO_PUP:
 282  282                                  break;
 283  283                          case IPPROTO_UDP:
 284  284                                  (void) interpret_udp(flags,
 285  285                                      (struct udphdr *)data, iplen, fraglen);
 286  286                                  break;
 287  287  
 288  288                          case IPPROTO_IDP:
 289  289                          case IPPROTO_HELLO:
 290  290                          case IPPROTO_ND:
 291  291                          case IPPROTO_RAW:
  
    | ↓ open down ↓ | 291 lines elided | ↑ open up ↑ | 
 292  292                                  break;
 293  293                          case IPPROTO_IPV6:      /* IPV6 encap */
 294  294                                  /* LINTED: alignment */
 295  295                                  (void) interpret_ipv6(flags, (ip6_t *)data,
 296  296                                      iplen);
 297  297                                  break;
 298  298                          case IPPROTO_SCTP:
 299  299                                  (void) interpret_sctp(flags,
 300  300                                      (struct sctp_hdr *)data, iplen, fraglen);
 301  301                                  break;
      302 +                        case IPPROTO_DCCP:
      303 +                                (void) interpret_dccp(flags,
      304 +                                    (struct dccphdr *)data, iplen, fraglen);
      305 +                                break;
 302  306                          }
 303  307                  }
 304  308          }
 305  309  
 306  310          encap_levels--;
 307  311          return (iplen);
 308  312  }
 309  313  
 310  314  int
 311  315  interpret_ipv6(int flags, const ip6_t *ip6h, int fraglen)
 312  316  {
 313  317          uint8_t *data;
 314  318          int hdrlen, iplen;
 315  319          int version, flow, class;
 316  320          uchar_t proto;
 317  321          boolean_t isfrag = B_FALSE;
 318  322          uint8_t extmask;
 319  323          /*
 320  324           * The print_srcname and print_dstname strings are the hostname
 321  325           * parts of the verbose IPv6 header output, including the comma
 322  326           * and the space after the litteral address strings.
 323  327           */
 324  328          char print_srcname[MAXHOSTNAMELEN + 2];
 325  329          char print_dstname[MAXHOSTNAMELEN + 2];
 326  330          char src_addrstr[INET6_ADDRSTRLEN];
 327  331          char dst_addrstr[INET6_ADDRSTRLEN];
 328  332  
 329  333          iplen = ntohs(ip6h->ip6_plen);
 330  334          hdrlen = IPV6_HDR_LEN;
 331  335          fraglen -= hdrlen;
 332  336          if (fraglen < 0)
 333  337                  return (fraglen + hdrlen);
 334  338          data = ((uint8_t *)ip6h) + hdrlen;
 335  339  
 336  340          proto = ip6h->ip6_nxt;
 337  341  
 338  342          src_name = addrtoname(AF_INET6, &ip6h->ip6_src);
 339  343          dst_name = addrtoname(AF_INET6, &ip6h->ip6_dst);
 340  344  
 341  345          /*
 342  346           * Use endian-aware masks to extract traffic class and
 343  347           * flowinfo.  Also, flowinfo is now 20 bits and class 8
 344  348           * rather than 24 and 4.
 345  349           */
 346  350          class = ntohl((ip6h->ip6_vcf & IPV6_FLOWINFO_TCLASS) >> 20);
 347  351          flow = ntohl(ip6h->ip6_vcf & IPV6_FLOWINFO_FLOWLABEL);
 348  352  
 349  353          /*
 350  354           * NOTE: the F_SUM and F_DTAIL flags are mutually exclusive,
 351  355           * so the code within the first part of the following if statement
 352  356           * will not affect the detailed printing of the packet.
 353  357           */
 354  358          if (flags & F_SUM) {
 355  359                  (void) snprintf(get_sum_line(), MAXLINE,
 356  360                      "IPv6  S=%s D=%s LEN=%d HOPS=%d CLASS=0x%x FLOW=0x%x",
 357  361                      src_name, dst_name, iplen, ip6h->ip6_hops, class, flow);
 358  362          } else if (flags & F_DTAIL) {
 359  363  
 360  364                  (void) inet_ntop(AF_INET6, &ip6h->ip6_src, src_addrstr,
 361  365                      INET6_ADDRSTRLEN);
 362  366                  (void) inet_ntop(AF_INET6, &ip6h->ip6_dst, dst_addrstr,
 363  367                      INET6_ADDRSTRLEN);
 364  368  
 365  369                  version = ntohl(ip6h->ip6_vcf) >> 28;
 366  370  
 367  371                  if (strcmp(src_name, src_addrstr) == 0) {
 368  372                          print_srcname[0] = '\0';
 369  373                  } else {
 370  374                          snprintf(print_srcname, sizeof (print_srcname),
 371  375                              ", %s", src_name);
 372  376                  }
 373  377  
 374  378                  if (strcmp(dst_name, dst_addrstr) == 0) {
 375  379                          print_dstname[0] = '\0';
 376  380                  } else {
 377  381                          snprintf(print_dstname, sizeof (print_dstname),
 378  382                              ", %s", dst_name);
 379  383                  }
 380  384  
 381  385                  show_header("IPv6:   ", "IPv6 Header", iplen);
 382  386                  show_space();
 383  387  
 384  388                  (void) snprintf(get_line(0, 0), get_line_remain(),
 385  389                      "Version = %d", version);
 386  390                  (void) snprintf(get_line(0, 0), get_line_remain(),
 387  391                      "Traffic Class = %d", class);
 388  392                  (void) snprintf(get_line(0, 0), get_line_remain(),
 389  393                      "Flow label = 0x%x", flow);
 390  394                  (void) snprintf(get_line(0, 0), get_line_remain(),
 391  395                      "Payload length = %d", iplen);
 392  396                  (void) snprintf(get_line(0, 0), get_line_remain(),
 393  397                      "Next Header = %d (%s)", proto,
 394  398                      getproto(proto));
 395  399                  (void) snprintf(get_line(0, 0), get_line_remain(),
 396  400                      "Hop Limit = %d", ip6h->ip6_hops);
 397  401                  (void) snprintf(get_line(0, 0), get_line_remain(),
 398  402                      "Source address = %s%s", src_addrstr, print_srcname);
 399  403                  (void) snprintf(get_line(0, 0), get_line_remain(),
 400  404                      "Destination address = %s%s", dst_addrstr, print_dstname);
 401  405  
 402  406                  show_space();
 403  407          }
 404  408  
 405  409          /*
 406  410           * Print IPv6 Extension Headers, or skip them in the summary case.
 407  411           * Set isfrag to true if one of the extension headers encounterred
 408  412           * was a fragment header.
 409  413           */
 410  414          if (proto == IPPROTO_HOPOPTS || proto == IPPROTO_DSTOPTS ||
 411  415              proto == IPPROTO_ROUTING || proto == IPPROTO_FRAGMENT) {
 412  416                  extmask = print_ipv6_extensions(flags, &data, &proto, &iplen,
 413  417                      &fraglen);
 414  418                  if ((extmask & SNOOP_FRAGMENT) != 0) {
 415  419                          isfrag = B_TRUE;
 416  420                  }
 417  421          }
 418  422  
 419  423          /*
 420  424           * We only want to print upper layer information if this is not
 421  425           * a fragment, or if we're printing in detail.  Note that the
 422  426           * proto variable will be set to IPPROTO_NONE if this is a fragment
 423  427           * with a non-zero fragment offset.
 424  428           */
 425  429          if (!isfrag || flags & F_DTAIL) {
 426  430                  /* go to the next protocol layer */
 427  431  
 428  432                  switch (proto) {
 429  433                  case IPPROTO_IP:
 430  434                          break;
 431  435                  case IPPROTO_ENCAP:
 432  436                          /* LINTED: alignment */
 433  437                          (void) interpret_ip(flags, (const struct ip *)data,
 434  438                              fraglen);
 435  439                          break;
 436  440                  case IPPROTO_ICMPV6:
 437  441                          /* LINTED: alignment */
 438  442                          (void) interpret_icmpv6(flags, (icmp6_t *)data, iplen,
 439  443                              fraglen);
 440  444                          break;
 441  445                  case IPPROTO_IGMP:
 442  446                          interpret_igmp(flags, data, iplen, fraglen);
 443  447                          break;
 444  448                  case IPPROTO_GGP:
 445  449                          break;
 446  450                  case IPPROTO_TCP:
 447  451                          (void) interpret_tcp(flags, (struct tcphdr *)data,
 448  452                              iplen, fraglen);
 449  453                          break;
 450  454                  case IPPROTO_ESP:
 451  455                          (void) interpret_esp(flags, data, iplen, fraglen);
 452  456                          break;
 453  457                  case IPPROTO_AH:
 454  458                          (void) interpret_ah(flags, data, iplen, fraglen);
 455  459                          break;
 456  460                  case IPPROTO_EGP:
 457  461                  case IPPROTO_PUP:
 458  462                          break;
 459  463                  case IPPROTO_UDP:
 460  464                          (void) interpret_udp(flags, (struct udphdr *)data,
 461  465                              iplen, fraglen);
 462  466                          break;
 463  467                  case IPPROTO_IDP:
 464  468                  case IPPROTO_HELLO:
 465  469                  case IPPROTO_ND:
 466  470                  case IPPROTO_RAW:
 467  471                          break;
 468  472                  case IPPROTO_IPV6:
 469  473                          /* LINTED: alignment */
  
    | ↓ open down ↓ | 158 lines elided | ↑ open up ↑ | 
 470  474                          (void) interpret_ipv6(flags, (const ip6_t *)data,
 471  475                              iplen);
 472  476                          break;
 473  477                  case IPPROTO_SCTP:
 474  478                          (void) interpret_sctp(flags, (struct sctp_hdr *)data,
 475  479                              iplen, fraglen);
 476  480                          break;
 477  481                  case IPPROTO_OSPF:
 478  482                          interpret_ospf6(flags, data, iplen, fraglen);
 479  483                          break;
      484 +                case IPPROTO_DCCP:
      485 +                        (void) interpret_dccp(flags, (struct dccphdr *)data,
      486 +                            iplen, fraglen);
      487 +                        break;
 480  488                  }
 481  489          }
 482  490  
 483  491          return (iplen);
 484  492  }
 485  493  
 486  494  /*
 487  495   * ip_ext: data including the extension header.
 488  496   * iplen: length of the data remaining in the packet.
 489  497   * Returns a mask of IPv6 extension headers it processed.
 490  498   */
 491  499  uint8_t
 492  500  print_ipv6_extensions(int flags, uint8_t **hdr, uint8_t *next, int *iplen,
 493  501      int *fraglen)
 494  502  {
 495  503          uint8_t *data_ptr;
 496  504          uchar_t proto = *next;
 497  505          boolean_t is_extension_header;
 498  506          struct ip6_hbh *ipv6ext_hbh;
 499  507          struct ip6_dest *ipv6ext_dest;
 500  508          struct ip6_rthdr *ipv6ext_rthdr;
 501  509          struct ip6_frag *ipv6ext_frag;
 502  510          uint32_t exthdrlen;
 503  511          uint8_t extmask = 0;
 504  512  
 505  513          if ((hdr == NULL) || (*hdr == NULL) || (next == NULL) || (iplen == 0))
 506  514                  return (0);
 507  515  
 508  516          data_ptr = *hdr;
 509  517          is_extension_header = B_TRUE;
 510  518          while (is_extension_header) {
 511  519  
 512  520                  /*
 513  521                   * There must be at least enough data left to read the
 514  522                   * next header and header length fields from the next
 515  523                   * header.
 516  524                   */
 517  525                  if (*fraglen < 2) {
 518  526                          return (extmask);
 519  527                  }
 520  528  
 521  529                  switch (proto) {
 522  530                  case IPPROTO_HOPOPTS:
 523  531                          ipv6ext_hbh = (struct ip6_hbh *)data_ptr;
 524  532                          exthdrlen = 8 + ipv6ext_hbh->ip6h_len * 8;
 525  533                          if (*fraglen <= exthdrlen) {
 526  534                                  return (extmask);
 527  535                          }
 528  536                          prt_hbh_options(flags, ipv6ext_hbh);
 529  537                          extmask |= SNOOP_HOPOPTS;
 530  538                          proto = ipv6ext_hbh->ip6h_nxt;
 531  539                          break;
 532  540                  case IPPROTO_DSTOPTS:
 533  541                          ipv6ext_dest = (struct ip6_dest *)data_ptr;
 534  542                          exthdrlen = 8 + ipv6ext_dest->ip6d_len * 8;
 535  543                          if (*fraglen <= exthdrlen) {
 536  544                                  return (extmask);
 537  545                          }
 538  546                          prt_dest_options(flags, ipv6ext_dest);
 539  547                          extmask |= SNOOP_DSTOPTS;
 540  548                          proto = ipv6ext_dest->ip6d_nxt;
 541  549                          break;
 542  550                  case IPPROTO_ROUTING:
 543  551                          ipv6ext_rthdr = (struct ip6_rthdr *)data_ptr;
 544  552                          exthdrlen = 8 + ipv6ext_rthdr->ip6r_len * 8;
 545  553                          if (*fraglen <= exthdrlen) {
 546  554                                  return (extmask);
 547  555                          }
 548  556                          prt_routing_hdr(flags, ipv6ext_rthdr);
 549  557                          extmask |= SNOOP_ROUTING;
 550  558                          proto = ipv6ext_rthdr->ip6r_nxt;
 551  559                          break;
 552  560                  case IPPROTO_FRAGMENT:
 553  561                          /* LINTED: alignment */
 554  562                          ipv6ext_frag = (struct ip6_frag *)data_ptr;
 555  563                          exthdrlen = sizeof (struct ip6_frag);
 556  564                          if (*fraglen <= exthdrlen) {
 557  565                                  return (extmask);
 558  566                          }
 559  567                          prt_fragment_hdr(flags, ipv6ext_frag);
 560  568                          extmask |= SNOOP_FRAGMENT;
 561  569                          /*
 562  570                           * If this is not the first fragment, forget about
 563  571                           * the rest of the packet, snoop decoding is
 564  572                           * stateless.
 565  573                           */
 566  574                          if ((ipv6ext_frag->ip6f_offlg & IP6F_OFF_MASK) != 0)
 567  575                                  proto = IPPROTO_NONE;
 568  576                          else
 569  577                                  proto = ipv6ext_frag->ip6f_nxt;
 570  578                          break;
 571  579                  default:
 572  580                          is_extension_header = B_FALSE;
 573  581                          break;
 574  582                  }
 575  583  
 576  584                  if (is_extension_header) {
 577  585                          *iplen -= exthdrlen;
 578  586                          *fraglen -= exthdrlen;
 579  587                          data_ptr += exthdrlen;
 580  588                  }
 581  589          }
 582  590  
 583  591          *next = proto;
 584  592          *hdr = data_ptr;
 585  593          return (extmask);
 586  594  }
 587  595  
 588  596  static void
 589  597  print_ipoptions(const uchar_t *opt, int optlen)
 590  598  {
 591  599          int len;
 592  600          int remain;
 593  601          char *line;
 594  602          const char *truncstr;
 595  603  
 596  604          if (optlen <= 0) {
 597  605                  (void) snprintf(get_line(0, 0), get_line_remain(),
 598  606                      "No options");
 599  607                  return;
 600  608          }
 601  609  
 602  610          (void) snprintf(get_line(0, 0), get_line_remain(),
 603  611              "Options: (%d bytes)", optlen);
 604  612  
 605  613          while (optlen > 0) {
 606  614                  line = get_line(0, 0);
 607  615                  remain = get_line_remain();
 608  616                  len = opt[1];
 609  617                  truncstr = len > optlen ? "?" : "";
 610  618                  switch (opt[0]) {
 611  619                  case IPOPT_EOL:
 612  620                          (void) strlcpy(line, "  - End of option list", remain);
 613  621                          return;
 614  622                  case IPOPT_NOP:
 615  623                          (void) strlcpy(line, "  - No op", remain);
 616  624                          len = 1;
 617  625                          break;
 618  626                  case IPOPT_RR:
 619  627                          (void) snprintf(line, remain,
 620  628                              "  - Record route (%d bytes%s)", len, truncstr);
 621  629                          print_route(opt);
 622  630                          break;
 623  631                  case IPOPT_TS:
 624  632                          (void) snprintf(line, remain,
 625  633                              "  - Time stamp (%d bytes%s)", len, truncstr);
 626  634                          break;
 627  635                  case IPOPT_SECURITY:
 628  636                          (void) snprintf(line, remain, "  - RIPSO (%d bytes%s)",
 629  637                              len, truncstr);
 630  638                          print_ripso(opt);
 631  639                          break;
 632  640                  case IPOPT_COMSEC:
 633  641                          (void) snprintf(line, remain, "  - CIPSO (%d bytes%s)",
 634  642                              len, truncstr);
 635  643                          print_cipso(opt);
 636  644                          break;
 637  645                  case IPOPT_LSRR:
 638  646                          (void) snprintf(line, remain,
 639  647                              "  - Loose source route (%d bytes%s)", len,
 640  648                              truncstr);
 641  649                          print_route(opt);
 642  650                          break;
 643  651                  case IPOPT_SATID:
 644  652                          (void) snprintf(line, remain,
 645  653                              "  - SATNET Stream id (%d bytes%s)",
 646  654                              len, truncstr);
 647  655                          break;
 648  656                  case IPOPT_SSRR:
 649  657                          (void) snprintf(line, remain,
 650  658                              "  - Strict source route, (%d bytes%s)", len,
 651  659                              truncstr);
 652  660                          print_route(opt);
 653  661                          break;
 654  662                  default:
 655  663                          (void) snprintf(line, remain,
 656  664                              "  - Option %d (unknown - %d bytes%s) %s",
 657  665                              opt[0], len, truncstr,
 658  666                              tohex((char *)&opt[2], len - 2));
 659  667                          break;
 660  668                  }
 661  669                  if (len <= 0) {
 662  670                          (void) snprintf(line, remain,
 663  671                              "  - Incomplete option len %d", len);
 664  672                          break;
 665  673                  }
 666  674                  opt += len;
 667  675                  optlen -= len;
 668  676          }
 669  677  }
 670  678  
 671  679  static void
 672  680  print_route(const uchar_t *opt)
 673  681  {
 674  682          int len, pointer, remain;
 675  683          struct in_addr addr;
 676  684          char *line;
 677  685  
 678  686          len = opt[1];
 679  687          pointer = opt[2];
 680  688  
 681  689          (void) snprintf(get_line(0, 0), get_line_remain(),
 682  690              "    Pointer = %d", pointer);
 683  691  
 684  692          pointer -= IPOPT_MINOFF;
 685  693          opt += (IPOPT_OFFSET + 1);
 686  694          len -= (IPOPT_OFFSET + 1);
 687  695  
 688  696          while (len > 0) {
 689  697                  line = get_line(0, 0);
 690  698                  remain = get_line_remain();
 691  699                  memcpy((char *)&addr, opt, sizeof (addr));
 692  700                  if (addr.s_addr == INADDR_ANY)
 693  701                          (void) strlcpy(line, "      -", remain);
 694  702                  else
 695  703                          (void) snprintf(line, remain, "      %s",
 696  704                              addrtoname(AF_INET, &addr));
 697  705                  if (pointer == 0)
 698  706                          (void) strlcat(line, "  <-- (current)", remain);
 699  707  
 700  708                  opt += sizeof (addr);
 701  709                  len -= sizeof (addr);
 702  710                  pointer -= sizeof (addr);
 703  711          }
 704  712  }
 705  713  
 706  714  char *
 707  715  getproto(int p)
 708  716  {
 709  717          switch (p) {
 710  718          case IPPROTO_HOPOPTS:   return ("IPv6-HopOpts");
 711  719          case IPPROTO_IPV6:      return ("IPv6");
 712  720          case IPPROTO_ROUTING:   return ("IPv6-Route");
 713  721          case IPPROTO_FRAGMENT:  return ("IPv6-Frag");
 714  722          case IPPROTO_RSVP:      return ("RSVP");
 715  723          case IPPROTO_ENCAP:     return ("IP-in-IP");
 716  724          case IPPROTO_AH:        return ("AH");
 717  725          case IPPROTO_ESP:       return ("ESP");
 718  726          case IPPROTO_ICMP:      return ("ICMP");
 719  727          case IPPROTO_ICMPV6:    return ("ICMPv6");
 720  728          case IPPROTO_DSTOPTS:   return ("IPv6-DstOpts");
 721  729          case IPPROTO_IGMP:      return ("IGMP");
 722  730          case IPPROTO_GGP:       return ("GGP");
  
    | ↓ open down ↓ | 233 lines elided | ↑ open up ↑ | 
 723  731          case IPPROTO_TCP:       return ("TCP");
 724  732          case IPPROTO_EGP:       return ("EGP");
 725  733          case IPPROTO_PUP:       return ("PUP");
 726  734          case IPPROTO_UDP:       return ("UDP");
 727  735          case IPPROTO_IDP:       return ("IDP");
 728  736          case IPPROTO_HELLO:     return ("HELLO");
 729  737          case IPPROTO_ND:        return ("ND");
 730  738          case IPPROTO_EON:       return ("EON");
 731  739          case IPPROTO_RAW:       return ("RAW");
 732  740          case IPPROTO_OSPF:      return ("OSPF");
      741 +        case IPPROTO_DCCP:      return ("DCCP");
 733  742          default:                return ("");
 734  743          }
 735  744  }
 736  745  
 737  746  static void
 738  747  prt_routing_hdr(int flags, const struct ip6_rthdr *ipv6ext_rthdr)
 739  748  {
 740  749          uint8_t nxt_hdr;
 741  750          uint8_t type;
 742  751          uint32_t len;
 743  752          uint8_t segleft;
 744  753          uint32_t numaddrs;
 745  754          int i;
 746  755          struct ip6_rthdr0 *ipv6ext_rthdr0;
 747  756          struct in6_addr *addrs;
 748  757          char addr[INET6_ADDRSTRLEN];
 749  758  
 750  759          /* in summary mode, we don't do anything. */
 751  760          if (flags & F_SUM) {
 752  761                  return;
 753  762          }
 754  763  
 755  764          nxt_hdr = ipv6ext_rthdr->ip6r_nxt;
 756  765          type = ipv6ext_rthdr->ip6r_type;
 757  766          len = 8 * (ipv6ext_rthdr->ip6r_len + 1);
 758  767          segleft = ipv6ext_rthdr->ip6r_segleft;
 759  768  
 760  769          show_header("IPv6-Route:  ", "IPv6 Routing Header", 0);
 761  770          show_space();
 762  771  
 763  772          (void) snprintf(get_line(0, 0), get_line_remain(),
 764  773              "Next header = %d (%s)", nxt_hdr, getproto(nxt_hdr));
 765  774          (void) snprintf(get_line(0, 0), get_line_remain(),
 766  775              "Header length = %d", len);
 767  776          (void) snprintf(get_line(0, 0), get_line_remain(),
 768  777              "Routing type = %d", type);
 769  778          (void) snprintf(get_line(0, 0), get_line_remain(),
 770  779              "Segments left = %d", segleft);
 771  780  
 772  781          if (type == IPV6_RTHDR_TYPE_0) {
 773  782                  /*
 774  783                   * XXX This loop will print all addresses in the routing header,
 775  784                   * XXX not just the segments left.
 776  785                   * XXX (The header length field is twice the number of
 777  786                   * XXX addresses)
 778  787                   * XXX At some future time, we may want to change this
 779  788                   * XXX to differentiate between the hops yet to do
 780  789                   * XXX and the hops already taken.
 781  790                   */
 782  791                  /* LINTED: alignment */
 783  792                  ipv6ext_rthdr0 = (struct ip6_rthdr0 *)ipv6ext_rthdr;
 784  793                  numaddrs = ipv6ext_rthdr0->ip6r0_len / 2;
 785  794                  addrs = (struct in6_addr *)(ipv6ext_rthdr0 + 1);
 786  795                  for (i = 0; i < numaddrs; i++) {
 787  796                          (void) inet_ntop(AF_INET6, &addrs[i], addr,
 788  797                              INET6_ADDRSTRLEN);
 789  798                          (void) snprintf(get_line(0, 0), get_line_remain(),
 790  799                              "address[%d]=%s", i, addr);
 791  800                  }
 792  801          }
 793  802  
 794  803          show_space();
 795  804  }
 796  805  
 797  806  static void
 798  807  prt_fragment_hdr(int flags, const struct ip6_frag *ipv6ext_frag)
 799  808  {
 800  809          boolean_t morefrag;
 801  810          uint16_t fragoffset;
 802  811          uint8_t nxt_hdr;
 803  812          uint32_t fragident;
 804  813  
 805  814          /* extract the various fields from the fragment header */
 806  815          nxt_hdr = ipv6ext_frag->ip6f_nxt;
 807  816          morefrag = (ipv6ext_frag->ip6f_offlg & IP6F_MORE_FRAG) == 0
 808  817              ? B_FALSE : B_TRUE;
 809  818          fragoffset = ntohs(ipv6ext_frag->ip6f_offlg & IP6F_OFF_MASK);
 810  819          fragident = ntohl(ipv6ext_frag->ip6f_ident);
 811  820  
 812  821          if (flags & F_SUM) {
 813  822                  (void) snprintf(get_sum_line(), MAXLINE,
 814  823                      "IPv6 fragment ID=%u Offset=%-4d MF=%d",
 815  824                      fragident,
 816  825                      fragoffset,
 817  826                      morefrag);
 818  827          } else { /* F_DTAIL */
 819  828                  show_header("IPv6-Frag:  ", "IPv6 Fragment Header", 0);
 820  829                  show_space();
 821  830  
 822  831                  (void) snprintf(get_line(0, 0), get_line_remain(),
 823  832                      "Next Header = %d (%s)", nxt_hdr, getproto(nxt_hdr));
 824  833                  (void) snprintf(get_line(0, 0), get_line_remain(),
 825  834                      "Fragment Offset = %d", fragoffset);
 826  835                  (void) snprintf(get_line(0, 0), get_line_remain(),
 827  836                      "More Fragments Flag = %s", morefrag ? "true" : "false");
 828  837                  (void) snprintf(get_line(0, 0), get_line_remain(),
 829  838                      "Identification = %u", fragident);
 830  839  
 831  840                  show_space();
 832  841          }
 833  842  }
 834  843  
 835  844  static void
 836  845  print_ip6opt_ls(const uchar_t *data, unsigned int op_len)
 837  846  {
 838  847          uint32_t doi;
 839  848          uint8_t sotype, solen;
 840  849          uint16_t value, value2;
 841  850          char *cp;
 842  851          int remlen;
 843  852          boolean_t printed;
 844  853  
 845  854          (void) snprintf(get_line(0, 0), get_line_remain(),
 846  855              "Labeled Security Option len = %u bytes%s", op_len,
 847  856              op_len < sizeof (uint32_t) || (op_len & 1) != 0 ? "?" : "");
 848  857          if (op_len < sizeof (uint32_t))
 849  858                  return;
 850  859          GETINT32(doi, data);
 851  860          (void) snprintf(get_line(0, 0), get_line_remain(),
 852  861              "    DOI = %d (%s)", doi, doi == IP6LS_DOI_V4 ? "IPv4" : "???");
 853  862          op_len -= sizeof (uint32_t);
 854  863          while (op_len > 0) {
 855  864                  GETINT8(sotype, data);
 856  865                  if (op_len < 2) {
 857  866                          (void) snprintf(get_line(0, 0), get_line_remain(),
 858  867                              "    truncated %u suboption (no len)", sotype);
 859  868                          break;
 860  869                  }
 861  870                  GETINT8(solen, data);
 862  871                  if (solen < 2 || solen > op_len) {
 863  872                          (void) snprintf(get_line(0, 0), get_line_remain(),
 864  873                              "    bad %u suboption (len 2 <= %u <= %u)",
 865  874                              sotype, solen, op_len);
 866  875                          if (solen < 2)
 867  876                                  solen = 2;
 868  877                          if (solen > op_len)
 869  878                                  solen = op_len;
 870  879                  }
 871  880                  op_len -= solen;
 872  881                  solen -= 2;
 873  882                  cp = get_line(0, 0);
 874  883                  remlen = get_line_remain();
 875  884                  (void) strlcpy(cp, "    ", remlen);
 876  885                  cp += 4;
 877  886                  remlen -= 4;
 878  887                  printed = B_TRUE;
 879  888                  switch (sotype) {
 880  889                  case IP6LS_TT_LEVEL:
 881  890                          if (solen != 2) {
 882  891                                  printed = B_FALSE;
 883  892                                  break;
 884  893                          }
 885  894                          GETINT16(value, data);
 886  895                          (void) snprintf(cp, remlen, "Level %u", value);
 887  896                          solen = 0;
 888  897                          break;
 889  898                  case IP6LS_TT_VECTOR:
 890  899                          (void) strlcpy(cp, "Bit-Vector: ", remlen);
 891  900                          remlen -= strlen(cp);
 892  901                          cp += strlen(cp);
 893  902                          while (solen > 1) {
 894  903                                  GETINT16(value, data);
 895  904                                  solen -= 2;
 896  905                                  (void) snprintf(cp, remlen, "%04x", value);
 897  906                                  remlen -= strlen(cp);
 898  907                                  cp += strlen(cp);
 899  908                          }
 900  909                          break;
 901  910                  case IP6LS_TT_ENUM:
 902  911                          (void) strlcpy(cp, "Enumeration:", remlen);
 903  912                          remlen -= strlen(cp);
 904  913                          cp += strlen(cp);
 905  914                          while (solen > 1) {
 906  915                                  GETINT16(value, data);
 907  916                                  solen -= 2;
 908  917                                  (void) snprintf(cp, remlen, " %u", value);
 909  918                                  remlen -= strlen(cp);
 910  919                                  cp += strlen(cp);
 911  920                          }
 912  921                          break;
 913  922                  case IP6LS_TT_RANGES:
 914  923                          (void) strlcpy(cp, "Ranges:", remlen);
 915  924                          remlen -= strlen(cp);
 916  925                          cp += strlen(cp);
 917  926                          while (solen > 3) {
 918  927                                  GETINT16(value, data);
 919  928                                  GETINT16(value2, data);
 920  929                                  solen -= 4;
 921  930                                  (void) snprintf(cp, remlen, " %u-%u", value,
 922  931                                      value2);
 923  932                                  remlen -= strlen(cp);
 924  933                                  cp += strlen(cp);
 925  934                          }
 926  935                          break;
 927  936                  case IP6LS_TT_V4:
 928  937                          (void) strlcpy(cp, "IPv4 Option", remlen);
 929  938                          print_ipoptions(data, solen);
 930  939                          solen = 0;
 931  940                          break;
 932  941                  case IP6LS_TT_DEST:
 933  942                          (void) snprintf(cp, remlen,
 934  943                              "Destination-Only Data length %u", solen);
 935  944                          solen = 0;
 936  945                          break;
 937  946                  default:
 938  947                          (void) snprintf(cp, remlen,
 939  948                              "    unknown %u suboption (len %u)", sotype, solen);
 940  949                          solen = 0;
 941  950                          break;
 942  951                  }
 943  952                  if (solen != 0) {
 944  953                          if (printed) {
 945  954                                  cp = get_line(0, 0);
 946  955                                  remlen = get_line_remain();
 947  956                          }
 948  957                          (void) snprintf(cp, remlen,
 949  958                              "    malformed %u suboption (remaining %u)",
 950  959                              sotype, solen);
 951  960                          data += solen;
 952  961                  }
 953  962          }
 954  963  }
 955  964  
 956  965  static void
 957  966  prt_hbh_options(int flags, const struct ip6_hbh *ipv6ext_hbh)
 958  967  {
 959  968          const uint8_t *data, *ndata;
 960  969          uint32_t len;
 961  970          uint8_t op_type;
 962  971          uint8_t op_len;
 963  972          uint8_t nxt_hdr;
 964  973  
 965  974          /* in summary mode, we don't do anything. */
 966  975          if (flags & F_SUM) {
 967  976                  return;
 968  977          }
 969  978  
 970  979          show_header("IPv6-HopOpts:  ", "IPv6 Hop-by-Hop Options Header", 0);
 971  980          show_space();
 972  981  
 973  982          /*
 974  983           * Store the lengh of this ext hdr in bytes.  The caller has
 975  984           * ensured that there is at least len bytes of data left.
 976  985           */
 977  986          len = ipv6ext_hbh->ip6h_len * 8 + 8;
 978  987  
 979  988          ndata = (const uint8_t *)ipv6ext_hbh + 2;
 980  989          len -= 2;
 981  990  
 982  991          nxt_hdr = ipv6ext_hbh->ip6h_nxt;
 983  992          (void) snprintf(get_line(0, 0), get_line_remain(),
 984  993              "Next Header = %u (%s)", nxt_hdr, getproto(nxt_hdr));
 985  994  
 986  995          while (len > 0) {
 987  996                  data = ndata;
 988  997                  GETINT8(op_type, data);
 989  998                  /* This is the only one-octet IPv6 option */
 990  999                  if (op_type == IP6OPT_PAD1) {
 991 1000                          (void) snprintf(get_line(0, 0), get_line_remain(),
 992 1001                              "pad1 option ");
 993 1002                          len--;
 994 1003                          ndata = data;
 995 1004                          continue;
 996 1005                  }
 997 1006                  GETINT8(op_len, data);
 998 1007                  if (len < 2 || op_len + 2 > len) {
 999 1008                          (void) snprintf(get_line(0, 0), get_line_remain(),
1000 1009                              "Error: option %u truncated (%u + 2 > %u)",
1001 1010                              op_type, op_len, len);
1002 1011                          op_len = len - 2;
1003 1012                          /*
1004 1013                           * Continue processing the malformed option so that we
1005 1014                           * can display as much as possible.
1006 1015                           */
1007 1016                  }
1008 1017  
1009 1018                  /* advance pointers to the next option */
1010 1019                  len -= op_len + 2;
1011 1020                  ndata = data + op_len;
1012 1021  
1013 1022                  /* process this option */
1014 1023                  switch (op_type) {
1015 1024                  case IP6OPT_PADN:
1016 1025                          (void) snprintf(get_line(0, 0), get_line_remain(),
1017 1026                              "padN option len = %u", op_len);
1018 1027                          break;
1019 1028                  case IP6OPT_JUMBO: {
1020 1029                          uint32_t payload_len;
1021 1030  
1022 1031                          (void) snprintf(get_line(0, 0), get_line_remain(),
1023 1032                              "Jumbo Payload Option len = %u bytes%s", op_len,
1024 1033                              op_len == sizeof (uint32_t) ? "" : "?");
1025 1034                          if (op_len == sizeof (uint32_t)) {
1026 1035                                  GETINT32(payload_len, data);
1027 1036                                  (void) snprintf(get_line(0, 0),
1028 1037                                      get_line_remain(),
1029 1038                                      "Jumbo Payload Length = %u bytes",
1030 1039                                      payload_len);
1031 1040                          }
1032 1041                          break;
1033 1042                  }
1034 1043                  case IP6OPT_ROUTER_ALERT: {
1035 1044                          uint16_t value;
1036 1045                          const char *label[] = {"MLD", "RSVP", "AN"};
1037 1046  
1038 1047                          (void) snprintf(get_line(0, 0), get_line_remain(),
1039 1048                              "Router Alert Option len = %u bytes%s", op_len,
1040 1049                              op_len == sizeof (uint16_t) ? "" : "?");
1041 1050                          if (op_len == sizeof (uint16_t)) {
1042 1051                                  GETINT16(value, data);
1043 1052                                  (void) snprintf(get_line(0, 0),
1044 1053                                      get_line_remain(),
1045 1054                                      "Alert Type = %d (%s)", value,
1046 1055                                      value < sizeof (label) / sizeof (label[0]) ?
1047 1056                                      label[value] : "???");
1048 1057                          }
1049 1058                          break;
1050 1059                  }
1051 1060                  case IP6OPT_LS:
1052 1061                          print_ip6opt_ls(data, op_len);
1053 1062                          break;
1054 1063                  default:
1055 1064                          (void) snprintf(get_line(0, 0), get_line_remain(),
1056 1065                              "Option type = %u, len = %u", op_type, op_len);
1057 1066                          break;
1058 1067                  }
1059 1068          }
1060 1069  
1061 1070          show_space();
1062 1071  }
1063 1072  
1064 1073  static void
1065 1074  prt_dest_options(int flags, const struct ip6_dest *ipv6ext_dest)
1066 1075  {
1067 1076          const uint8_t *data, *ndata;
1068 1077          uint32_t len;
1069 1078          uint8_t op_type;
1070 1079          uint32_t op_len;
1071 1080          uint8_t nxt_hdr;
1072 1081          uint8_t value;
1073 1082  
1074 1083          /* in summary mode, we don't do anything. */
1075 1084          if (flags & F_SUM) {
1076 1085                  return;
1077 1086          }
1078 1087  
1079 1088          show_header("IPv6-DstOpts:  ", "IPv6 Destination Options Header", 0);
1080 1089          show_space();
1081 1090  
1082 1091          /*
1083 1092           * Store the length of this ext hdr in bytes.  The caller has
1084 1093           * ensured that there is at least len bytes of data left.
1085 1094           */
1086 1095          len = ipv6ext_dest->ip6d_len * 8 + 8;
1087 1096  
1088 1097          ndata = (const uint8_t *)ipv6ext_dest + 2; /* skip hdr/len */
1089 1098          len -= 2;
1090 1099  
1091 1100          nxt_hdr = ipv6ext_dest->ip6d_nxt;
1092 1101          (void) snprintf(get_line(0, 0), get_line_remain(),
1093 1102              "Next Header = %u (%s)", nxt_hdr, getproto(nxt_hdr));
1094 1103  
1095 1104          while (len > 0) {
1096 1105                  data = ndata;
1097 1106                  GETINT8(op_type, data);
1098 1107                  if (op_type == IP6OPT_PAD1) {
1099 1108                          (void) snprintf(get_line(0, 0), get_line_remain(),
1100 1109                              "pad1 option ");
1101 1110                          len--;
1102 1111                          ndata = data;
1103 1112                          continue;
1104 1113                  }
1105 1114                  GETINT8(op_len, data);
1106 1115                  if (len < 2 || op_len + 2 > len) {
1107 1116                          (void) snprintf(get_line(0, 0), get_line_remain(),
1108 1117                              "Error: option %u truncated (%u + 2 > %u)",
1109 1118                              op_type, op_len, len);
1110 1119                          op_len = len - 2;
1111 1120                          /*
1112 1121                           * Continue processing the malformed option so that we
1113 1122                           * can display as much as possible.
1114 1123                           */
1115 1124                  }
1116 1125  
1117 1126                  /* advance pointers to the next option */
1118 1127                  len -= op_len + 2;
1119 1128                  ndata = data + op_len;
1120 1129  
1121 1130                  /* process this option */
1122 1131                  switch (op_type) {
1123 1132                  case IP6OPT_PADN:
1124 1133                          (void) snprintf(get_line(0, 0), get_line_remain(),
1125 1134                              "padN option len = %u", op_len);
1126 1135                          break;
1127 1136                  case IP6OPT_TUNNEL_LIMIT:
1128 1137                          GETINT8(value, data);
1129 1138                          (void) snprintf(get_line(0, 0), get_line_remain(),
1130 1139                              "tunnel encapsulation limit len = %d, value = %d",
1131 1140                              op_len, value);
1132 1141                          break;
1133 1142                  case IP6OPT_LS:
1134 1143                          print_ip6opt_ls(data, op_len);
1135 1144                          break;
1136 1145                  default:
1137 1146                          (void) snprintf(get_line(0, 0), get_line_remain(),
1138 1147                              "Option type = %u, len = %u", op_type, op_len);
1139 1148                          break;
1140 1149                  }
1141 1150          }
1142 1151  
1143 1152          show_space();
1144 1153  }
1145 1154  
1146 1155  #define ALABEL_MAXLEN   256
1147 1156  
1148 1157  static char ascii_label[ALABEL_MAXLEN];
1149 1158  static char *plabel = ascii_label;
1150 1159  
1151 1160  struct snoop_pair {
1152 1161          int val;
1153 1162          const char *name;
1154 1163  };
1155 1164  
1156 1165  static struct snoop_pair ripso_class_tbl[] = {
1157 1166          TSOL_CL_TOP_SECRET,     "TOP SECRET",
1158 1167          TSOL_CL_SECRET,         "SECRET",
1159 1168          TSOL_CL_CONFIDENTIAL,   "CONFIDENTIAL",
1160 1169          TSOL_CL_UNCLASSIFIED,   "UNCLASSIFIED",
1161 1170          -1,                     NULL
1162 1171  };
1163 1172  
1164 1173  static struct snoop_pair ripso_prot_tbl[] = {
1165 1174          TSOL_PA_GENSER,         "GENSER",
1166 1175          TSOL_PA_SIOP_ESI,       "SIOP-ESI",
1167 1176          TSOL_PA_SCI,            "SCI",
1168 1177          TSOL_PA_NSA,            "NSA",
1169 1178          TSOL_PA_DOE,            "DOE",
1170 1179          0x04,                   "UNASSIGNED",
1171 1180          0x02,                   "UNASSIGNED",
1172 1181          -1,                     NULL
1173 1182  };
1174 1183  
1175 1184  static struct snoop_pair *
1176 1185  get_pair_byval(struct snoop_pair pairlist[], int val)
1177 1186  {
1178 1187          int i;
1179 1188  
1180 1189          for (i = 0; pairlist[i].name != NULL; i++)
1181 1190                  if (pairlist[i].val == val)
1182 1191                          return (&pairlist[i]);
1183 1192          return (NULL);
1184 1193  }
1185 1194  
1186 1195  static void
1187 1196  print_ripso(const uchar_t *opt)
1188 1197  {
1189 1198          struct snoop_pair *ripso_class;
1190 1199          int i, index, prot_len;
1191 1200          boolean_t first_prot;
1192 1201          char line[100], *ptr;
1193 1202  
1194 1203          prot_len = opt[1] - 3;
1195 1204          if (prot_len < 0)
1196 1205                  return;
1197 1206  
1198 1207          show_header("RIPSO:  ", "Revised IP Security Option", 0);
1199 1208          show_space();
1200 1209  
1201 1210          (void) snprintf(get_line(0, 0), get_line_remain(),
1202 1211              "Type = Basic Security Option (%d), Length = %d", opt[0], opt[1]);
1203 1212  
1204 1213          /*
1205 1214           * Display Classification Level
1206 1215           */
1207 1216          ripso_class = get_pair_byval(ripso_class_tbl, (int)opt[2]);
1208 1217          if (ripso_class != NULL)
1209 1218                  (void) snprintf(get_line(0, 0), get_line_remain(),
1210 1219                      "Classification = Unknown (0x%02x)", opt[2]);
1211 1220          else
1212 1221                  (void) snprintf(get_line(0, 0), get_line_remain(),
1213 1222                      "Classification = %s (0x%02x)",
1214 1223                      ripso_class->name, ripso_class->val);
1215 1224  
1216 1225          /*
1217 1226           * Display Protection Authority Flags
1218 1227           */
1219 1228          (void) snprintf(line, sizeof (line), "Protection Authority = ");
1220 1229          ptr = line;
1221 1230          first_prot = B_TRUE;
1222 1231          for (i = 0; i < prot_len; i++) {
1223 1232                  index = 0;
1224 1233                  while (ripso_prot_tbl[index].name != NULL) {
1225 1234                          if (opt[3 + i] & ripso_prot_tbl[index].val) {
1226 1235                                  ptr = strchr(ptr, 0);
1227 1236                                  if (!first_prot) {
1228 1237                                          (void) strlcpy(ptr, ", ",
1229 1238                                              sizeof (line) - (ptr - line));
1230 1239                                          ptr = strchr(ptr, 0);
1231 1240                                  }
1232 1241                                  (void) snprintf(ptr,
1233 1242                                      sizeof (line) - (ptr - line),
1234 1243                                      "%s (0x%02x)",
1235 1244                                      ripso_prot_tbl[index].name,
1236 1245                                      ripso_prot_tbl[index].val);
1237 1246                          }
1238 1247                          index++;
1239 1248                  }
1240 1249                  if ((opt[3 + i] & 1) == 0)
1241 1250                          break;
1242 1251          }
1243 1252          if (!first_prot)
1244 1253                  (void) snprintf(get_line(0, 0), get_line_remain(), "%s", line);
1245 1254          else
1246 1255                  (void) snprintf(get_line(0, 0), get_line_remain(), "%sNone",
1247 1256                      line);
1248 1257  }
1249 1258  
1250 1259  #define CIPSO_GENERIC_ARRAY_LEN 200
1251 1260  
1252 1261  /*
1253 1262   * Return 1 if CIPSO SL and Categories are all 1's; 0 otherwise.
1254 1263   *
1255 1264   * Note: opt starts with "Tag Type":
1256 1265   *
1257 1266   * |tag_type(1)|tag_length(1)|align(1)|sl(1)|categories(variable)|
1258 1267   *
1259 1268   */
1260 1269  static boolean_t
1261 1270  cipso_high(const uchar_t *opt)
1262 1271  {
1263 1272          int i;
1264 1273  
1265 1274          if (((int)opt[1] + 6) < IP_MAX_OPT_LENGTH)
1266 1275                  return (B_FALSE);
1267 1276          for (i = 0; i < ((int)opt[1] - 3); i++)
1268 1277                  if (opt[3 + i] != 0xff)
1269 1278                          return (B_FALSE);
1270 1279          return (B_TRUE);
1271 1280  }
1272 1281  
1273 1282  /*
1274 1283   * Converts CIPSO label to SL.
1275 1284   *
1276 1285   * Note: opt starts with "Tag Type":
1277 1286   *
1278 1287   * |tag_type(1)|tag_length(1)|align(1)|sl(1)|categories(variable)|
1279 1288   *
1280 1289   */
1281 1290  static void
1282 1291  cipso2sl(const uchar_t *opt, bslabel_t *sl, int *high)
1283 1292  {
1284 1293          int i, taglen;
1285 1294          uchar_t *q = (uchar_t *)&((_bslabel_impl_t *)sl)->compartments;
1286 1295  
1287 1296          *high = 0;
1288 1297          taglen = opt[1];
1289 1298          memset((caddr_t)sl, 0, sizeof (bslabel_t));
1290 1299  
1291 1300          if (cipso_high(opt)) {
1292 1301                  BSLHIGH(sl);
1293 1302                  *high = 1;
1294 1303          } else {
1295 1304                  LCLASS_SET((_bslabel_impl_t *)sl, opt[3]);
1296 1305                  for (i = 0; i < taglen - TSOL_TT1_MIN_LENGTH; i++)
1297 1306                          q[i] = opt[TSOL_TT1_MIN_LENGTH + i];
1298 1307          }
1299 1308          SETBLTYPE(sl, SUN_SL_ID);
1300 1309  }
1301 1310  
1302 1311  static int
1303 1312  interpret_cipso_tagtype1(const uchar_t *opt)
1304 1313  {
1305 1314          int i, taglen, ishigh;
1306 1315          bslabel_t sl;
1307 1316          char line[CIPSO_GENERIC_ARRAY_LEN], *ptr;
1308 1317  
1309 1318          taglen = opt[1];
1310 1319          if (taglen < TSOL_TT1_MIN_LENGTH ||
1311 1320              taglen > TSOL_TT1_MAX_LENGTH)
1312 1321                  return (taglen);
1313 1322  
1314 1323          (void) snprintf(get_line(0, 0), get_line_remain(),
1315 1324              "Tag Type = %d, Tag Length = %d", opt[0], opt[1]);
1316 1325          (void) snprintf(get_line(0, 0), get_line_remain(),
1317 1326              "Sensitivity Level = 0x%02x", opt[3]);
1318 1327          ptr = line;
1319 1328          for (i = 0; i < taglen - TSOL_TT1_MIN_LENGTH; i++) {
1320 1329                  (void) snprintf(ptr, sizeof (line) - (ptr - line), "%02x",
1321 1330                      opt[TSOL_TT1_MIN_LENGTH + i]);
1322 1331                  ptr = strchr(ptr, 0);
1323 1332          }
1324 1333          if (i != 0) {
1325 1334                  (void) snprintf(get_line(0, 0), get_line_remain(),
1326 1335                      "Categories = ");
1327 1336                  (void) snprintf(get_line(0, 0), get_line_remain(), "\t%s",
1328 1337                      line);
1329 1338          } else {
1330 1339                  (void) snprintf(get_line(0, 0), get_line_remain(),
1331 1340                      "Categories = None");
1332 1341          }
1333 1342          cipso2sl(opt, &sl, &ishigh);
1334 1343          if (is_system_labeled()) {
1335 1344                  if (bsltos(&sl, &plabel, ALABEL_MAXLEN,
1336 1345                      LONG_CLASSIFICATION|LONG_WORDS|VIEW_INTERNAL) < 0) {
1337 1346                          (void) snprintf(get_line(0, 0), get_line_remain(),
1338 1347                              "The Sensitivity Level and Categories can't be "
1339 1348                              "mapped to a valid SL");
1340 1349                  } else {
1341 1350                          (void) snprintf(get_line(0, 0), get_line_remain(),
1342 1351                              "The Sensitivity Level and Categories are mapped "
1343 1352                              "to the SL:");
1344 1353                          (void) snprintf(get_line(0, 0), get_line_remain(),
1345 1354                              "\t%s", ascii_label);
1346 1355                  }
1347 1356          }
1348 1357          return (taglen);
1349 1358  }
1350 1359  
1351 1360  /*
1352 1361   * The following struct definition #define's are copied from TS1.x. They are
1353 1362   * not used here (except TTYPE_3_MAX_TOKENS), but included as a reference for
1354 1363   * the tag type 3 packet format.
1355 1364   */
1356 1365  #define TTYPE_3_MAX_TOKENS      7
1357 1366  
1358 1367  /*
1359 1368   * Display CIPSO tag type 3 which is defined by MAXSIX.
1360 1369   */
1361 1370  static int
1362 1371  interpret_cipso_tagtype3(const uchar_t *opt)
1363 1372  {
1364 1373          uchar_t tagtype;
1365 1374          int index, numtokens, taglen;
1366 1375          uint16_t mask;
1367 1376          uint32_t token;
1368 1377          static const char *name[] = {
1369 1378                  "SL",
1370 1379                  "NCAV",
1371 1380                  "INTEG",
1372 1381                  "SID",
1373 1382                  "undefined",
1374 1383                  "undefined",
1375 1384                  "IL",
1376 1385                  "PRIVS",
1377 1386                  "LUID",
1378 1387                  "PID",
1379 1388                  "IDS",
1380 1389                  "ACL"
1381 1390          };
1382 1391  
1383 1392          tagtype = *opt++;
1384 1393          (void) memcpy(&mask, opt + 3, sizeof (mask));
1385 1394          (void) snprintf(get_line(0, 0), get_line_remain(),
1386 1395              "Tag Type = %d (MAXSIX)", tagtype);
1387 1396          (void) snprintf(get_line(0, 0), get_line_remain(),
1388 1397              "Generation = 0x%02x%02x%02x, Mask = 0x%04x", opt[0], opt[1],
1389 1398              opt[2], mask);
1390 1399          opt += 3 + sizeof (mask);
1391 1400  
1392 1401          /*
1393 1402           * Display tokens
1394 1403           */
1395 1404          numtokens = 0;
1396 1405          index = 0;
1397 1406          while (mask != 0 && numtokens < TTYPE_3_MAX_TOKENS) {
1398 1407                  if (mask & 0x0001) {
1399 1408                          (void) memcpy(&token, opt, sizeof (token));
1400 1409                          opt += sizeof (token);
1401 1410                          (void) snprintf(get_line(0, 0), get_line_remain(),
1402 1411                              "Attribute = %s, Token = 0x%08x",
1403 1412                              index < sizeof (name) / sizeof (*name) ?
1404 1413                              name[index] : "unknown", token);
1405 1414                          numtokens++;
1406 1415                  }
1407 1416                  mask = mask >> 1;
1408 1417                  index++;
1409 1418          }
1410 1419  
1411 1420          taglen = 6 + numtokens * 4;
1412 1421          return (taglen);
1413 1422  }
1414 1423  
1415 1424  static void
1416 1425  print_cipso(const uchar_t *opt)
1417 1426  {
1418 1427          int optlen, taglen, tagnum;
1419 1428          uint32_t doi;
1420 1429          char line[CIPSO_GENERIC_ARRAY_LEN];
1421 1430          char *oldnest;
1422 1431  
1423 1432          optlen = opt[1];
1424 1433          if (optlen < TSOL_CIPSO_MIN_LENGTH || optlen > TSOL_CIPSO_MAX_LENGTH)
1425 1434                  return;
1426 1435  
1427 1436          oldnest = prot_nest_prefix;
1428 1437          prot_nest_prefix = prot_prefix;
1429 1438          show_header("CIPSO:  ", "Common IP Security Option", 0);
1430 1439          show_space();
1431 1440  
1432 1441          /*
1433 1442           * Display CIPSO Header
1434 1443           */
1435 1444          (void) snprintf(get_line(0, 0), get_line_remain(),
1436 1445              "Type = CIPSO (%d), Length = %d", opt[0], opt[1]);
1437 1446          (void) memcpy(&doi, opt + 2, sizeof (doi));
1438 1447          (void) snprintf(get_line(0, 0), get_line_remain(),
1439 1448              "Domain of Interpretation = %u", (unsigned)ntohl(doi));
1440 1449  
1441 1450          if (opt[1] == TSOL_CIPSO_MIN_LENGTH) {  /* no tags */
1442 1451                  show_space();
1443 1452                  prot_prefix = prot_nest_prefix;
1444 1453                  prot_nest_prefix = oldnest;
1445 1454                  return;
1446 1455          }
1447 1456          optlen -= TSOL_CIPSO_MIN_LENGTH;
1448 1457          opt += TSOL_CIPSO_MIN_LENGTH;
1449 1458  
1450 1459          /*
1451 1460           * Display Each Tag
1452 1461           */
1453 1462          tagnum = 1;
1454 1463          while (optlen >= TSOL_TT1_MIN_LENGTH) {
1455 1464                  (void) snprintf(line, sizeof (line), "Tag# %d", tagnum);
1456 1465                  show_header("CIPSO:  ", line, 0);
1457 1466                  /*
1458 1467                   * We handle tag type 1 and 3 only. Note, tag type 3
1459 1468                   * is MAXSIX defined.
1460 1469                   */
1461 1470                  switch (opt[0]) {
1462 1471                  case 1:
1463 1472                          taglen = interpret_cipso_tagtype1(opt);
1464 1473                          break;
1465 1474                  case 3:
1466 1475                          taglen = interpret_cipso_tagtype3(opt);
1467 1476                          break;
1468 1477                  default:
1469 1478                          (void) snprintf(get_line(0, 0), get_line_remain(),
1470 1479                              "Unknown Tag Type %d", opt[0]);
1471 1480                          show_space();
1472 1481                          prot_prefix = prot_nest_prefix;
1473 1482                          prot_nest_prefix = oldnest;
1474 1483                          return;
1475 1484                  }
1476 1485  
1477 1486                  /*
1478 1487                   * Move to the next tag
1479 1488                   */
1480 1489                  if (taglen <= 0)
1481 1490                          break;
1482 1491                  optlen -= taglen;
1483 1492                  opt += taglen;
1484 1493                  tagnum++;
1485 1494          }
1486 1495          show_space();
1487 1496          prot_prefix = prot_nest_prefix;
1488 1497          prot_nest_prefix = oldnest;
1489 1498  }
  
    | ↓ open down ↓ | 747 lines elided | ↑ open up ↑ | 
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX