Print this page
9832 Original bug discovered as 9560 has friends IPv4 packets coming in as IPv6 creating chaos
Reviewed by: Robert Mustacchi <rm@joyent.com>


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2015, Joyent, Inc.  All rights reserved.
  25  */
  26 /*
  27  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
  28  */
  29 
  30 #include <sys/cmn_err.h>
  31 #include <sys/strsun.h>
  32 #include <sys/sdt.h>
  33 #include <sys/mac.h>
  34 #include <sys/mac_impl.h>
  35 #include <sys/mac_client_impl.h>
  36 #include <sys/mac_client_priv.h>
  37 #include <sys/ethernet.h>
  38 #include <sys/vlan.h>
  39 #include <sys/dlpi.h>
  40 #include <sys/avl.h>
  41 #include <inet/ip.h>
  42 #include <inet/ip6.h>
  43 #include <inet/arp.h>
  44 #include <netinet/arp.h>


 795                 return (0);
 796 }
 797 
 798 /*
 799  * Locate the start of a DHCPv6 header.
 800  * The possible return values and associated meanings are:
 801  * 0      - packet is DHCP and has a DHCP header.
 802  * EINVAL - packet is not DHCP. the recommended action is to let it pass.
 803  * ENOSPC - packet is a initial fragment that is DHCP or is unidentifiable.
 804  *          the recommended action is to drop it.
 805  */
 806 static int
 807 get_dhcpv6_info(ip6_t *ip6h, uchar_t *end, dhcpv6_message_t **dh6)
 808 {
 809         uint16_t        hdrlen, client, server;
 810         boolean_t       first_frag = B_FALSE;
 811         ip6_frag_t      *frag = NULL;
 812         uint8_t         proto;
 813         struct udphdr   *udph;
 814         uchar_t         *dh;

 815 
 816         if (!mac_ip_hdr_length_v6(ip6h, end, &hdrlen, &proto, &frag))
 817                 return (ENOSPC);

 818 
 819         if (proto != IPPROTO_UDP)
 820                 return (EINVAL);
 821 
 822         if (frag != NULL) {
 823                 /*
 824                  * All non-initial fragments may pass because we cannot
 825                  * identify their type. It's safe to let them through
 826                  * because reassembly will fail if we decide to drop the
 827                  * initial fragment.
 828                  */
 829                 if ((ntohs(frag->ip6f_offlg) & ~7) != 0)
 830                         return (EINVAL);
 831                 first_frag = B_TRUE;
 832         }
 833         /* drop packets without a udp header */
 834         udph = (struct udphdr *)((uchar_t *)ip6h + hdrlen);
 835         if ((uchar_t *)&udph[1] > end)
 836                 return (ENOSPC);
 837 


 844         /* drop dhcp fragments */
 845         if (first_frag)
 846                 return (ENOSPC);
 847 
 848         dh = (uchar_t *)&udph[1];
 849         if (dh + sizeof (dhcpv6_message_t) > end)
 850                 return (EINVAL);
 851 
 852         *dh6 = (dhcpv6_message_t *)dh;
 853         return (0);
 854 }
 855 
 856 static int
 857 get_ra_info(ip6_t *ip6h, uchar_t *end, nd_router_advert_t **ra)
 858 {
 859         uint16_t                hdrlen;
 860         ip6_frag_t              *frag = NULL;
 861         uint8_t                 proto;
 862         uchar_t                 *hdrp;
 863         struct icmp6_hdr        *icmp;

 864 
 865         if (!mac_ip_hdr_length_v6(ip6h, end, &hdrlen, &proto, &frag))
 866                 return (ENOSPC);

 867 
 868         if (proto != IPPROTO_ICMPV6)
 869                 return (EINVAL);
 870 
 871         if (frag != NULL) {
 872                 /*
 873                  * All non-initial fragments may pass because we cannot
 874                  * identify their type. It's safe to let them through
 875                  * because reassembly will fail if we decide to drop the
 876                  * initial fragment.
 877                  */
 878                 if ((ntohs(frag->ip6f_offlg) & ~7) != 0)
 879                         return (EINVAL);
 880                 return (ENOSPC);
 881         }
 882 
 883         /*
 884          * Ensure that the ICMP header falls w/in packet boundaries, in case
 885          * we've received a malicious packet that reports incorrect lengths.
 886          */




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2019, Joyent, Inc.  All rights reserved.
  25  */
  26 /*
  27  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
  28  */
  29 
  30 #include <sys/cmn_err.h>
  31 #include <sys/strsun.h>
  32 #include <sys/sdt.h>
  33 #include <sys/mac.h>
  34 #include <sys/mac_impl.h>
  35 #include <sys/mac_client_impl.h>
  36 #include <sys/mac_client_priv.h>
  37 #include <sys/ethernet.h>
  38 #include <sys/vlan.h>
  39 #include <sys/dlpi.h>
  40 #include <sys/avl.h>
  41 #include <inet/ip.h>
  42 #include <inet/ip6.h>
  43 #include <inet/arp.h>
  44 #include <netinet/arp.h>


 795                 return (0);
 796 }
 797 
 798 /*
 799  * Locate the start of a DHCPv6 header.
 800  * The possible return values and associated meanings are:
 801  * 0      - packet is DHCP and has a DHCP header.
 802  * EINVAL - packet is not DHCP. the recommended action is to let it pass.
 803  * ENOSPC - packet is a initial fragment that is DHCP or is unidentifiable.
 804  *          the recommended action is to drop it.
 805  */
 806 static int
 807 get_dhcpv6_info(ip6_t *ip6h, uchar_t *end, dhcpv6_message_t **dh6)
 808 {
 809         uint16_t        hdrlen, client, server;
 810         boolean_t       first_frag = B_FALSE;
 811         ip6_frag_t      *frag = NULL;
 812         uint8_t         proto;
 813         struct udphdr   *udph;
 814         uchar_t         *dh;
 815         int             errno;
 816 
 817         errno = mac_ip_hdr_length_v6(ip6h, end, &hdrlen, &proto, &frag);
 818         if (errno != 0)
 819                 return (errno);
 820 
 821         if (proto != IPPROTO_UDP)
 822                 return (EINVAL);
 823 
 824         if (frag != NULL) {
 825                 /*
 826                  * All non-initial fragments may pass because we cannot
 827                  * identify their type. It's safe to let them through
 828                  * because reassembly will fail if we decide to drop the
 829                  * initial fragment.
 830                  */
 831                 if ((ntohs(frag->ip6f_offlg) & ~7) != 0)
 832                         return (EINVAL);
 833                 first_frag = B_TRUE;
 834         }
 835         /* drop packets without a udp header */
 836         udph = (struct udphdr *)((uchar_t *)ip6h + hdrlen);
 837         if ((uchar_t *)&udph[1] > end)
 838                 return (ENOSPC);
 839 


 846         /* drop dhcp fragments */
 847         if (first_frag)
 848                 return (ENOSPC);
 849 
 850         dh = (uchar_t *)&udph[1];
 851         if (dh + sizeof (dhcpv6_message_t) > end)
 852                 return (EINVAL);
 853 
 854         *dh6 = (dhcpv6_message_t *)dh;
 855         return (0);
 856 }
 857 
 858 static int
 859 get_ra_info(ip6_t *ip6h, uchar_t *end, nd_router_advert_t **ra)
 860 {
 861         uint16_t                hdrlen;
 862         ip6_frag_t              *frag = NULL;
 863         uint8_t                 proto;
 864         uchar_t                 *hdrp;
 865         struct icmp6_hdr        *icmp;
 866         int                     errno;
 867 
 868         errno = mac_ip_hdr_length_v6(ip6h, end, &hdrlen, &proto, &frag);
 869         if (errno != 0)
 870                 return (errno);
 871 
 872         if (proto != IPPROTO_ICMPV6)
 873                 return (EINVAL);
 874 
 875         if (frag != NULL) {
 876                 /*
 877                  * All non-initial fragments may pass because we cannot
 878                  * identify their type. It's safe to let them through
 879                  * because reassembly will fail if we decide to drop the
 880                  * initial fragment.
 881                  */
 882                 if ((ntohs(frag->ip6f_offlg) & ~7) != 0)
 883                         return (EINVAL);
 884                 return (ENOSPC);
 885         }
 886 
 887         /*
 888          * Ensure that the ICMP header falls w/in packet boundaries, in case
 889          * we've received a malicious packet that reports incorrect lengths.
 890          */