45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * CDDL HEADER START
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * The contents of this file are subject to the terms of the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Common Development and Distribution License (the "License").
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * You may not use this file except in compliance with the License.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * or http://www.opensolaris.org/os/licensing.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * See the License for the specific language governing permissions
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * and limitations under the License.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * When distributing Covered Code, include this CDDL HEADER in each
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If applicable, add the following below this CDDL HEADER, with the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * fields enclosed by brackets "[]" replaced with your own identifying
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * information: Portions Copyright [yyyy] [name of copyright owner]
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * CDDL HEADER END
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
9e3469d3db608feb0e43d9955cbf406c22025463Erik Nordmark * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Use is subject to license terms.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/types.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/systm.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/kmem.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/disp.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/stream.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/strsubr.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/strsun.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/policy.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/tsol/label_macro.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/tsol/tndb.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/tsol/tnet.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <inet/ip.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <inet/ip6.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <inet/tcp.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <inet/ipclassifier.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <inet/ip_ire.h>
c793af95640863cd29868fc7c419c5d2496b207bsangeeta#include <inet/ip_ftable.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * This routine takes a sensitivity label as input and creates a CIPSO
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * option in the specified buffer. It returns the size of the CIPSO option.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If the sensitivity label is too large for the CIPSO option, then 0
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * is returned.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * tsol2cipso_tt1 returns 0 for failure and greater than 0 for success
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * (more accurately, success means a return value between 10 and 40).
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic int
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktsol2cipso_tt1(const bslabel_t *sl, unsigned char *cop, uint32_t doi)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk struct cipso_tag_type_1 *tt1;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const _bslabel_impl_t *bsl;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const uchar_t *ucp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int i;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (doi == 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* check for Admin High sensitivity label */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (blequal(sl, label2bslabel(l_admin_high)))
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* check whether classification will fit in one octet */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bsl = (const _bslabel_impl_t *)sl;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (LCLASS(bsl) & 0xFF00)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Check whether compartments will fit in 30 octets.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Compartments 241 - 256 are not allowed.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (ntohl(bsl->compartments.c8) & 0x0000FFFF)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Compute option length and tag length.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * 'p' points to the last two bytes in the Sensitivity Label's
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * compartments; these cannot be mapped into CIPSO compartments.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ucp = (const uchar_t *)&bsl->compartments.c8 + 2;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk while (--ucp >= (const uchar_t *)&bsl->compartments.c1)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (*ucp != 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk i = ucp - (const uchar_t *)&bsl->compartments.c1 + 1;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (cop == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (10 + i);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk doi = htonl(doi);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ucp = (const uchar_t *)&doi;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk cop[IPOPT_OPTVAL] = IPOPT_COMSEC;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk cop[IPOPT_OLEN] = 10 + i;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk cop[IPOPT_OLEN+1] = ucp[0];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk cop[IPOPT_OLEN+2] = ucp[1];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk cop[IPOPT_OLEN+3] = ucp[2];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk cop[IPOPT_OLEN+4] = ucp[3];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tt1 = (struct cipso_tag_type_1 *)&cop[IPOPT_OLEN + 5];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tt1->tag_type = 1;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tt1->tag_align = 0;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tt1->tag_sl = LCLASS(bsl);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tt1->tag_length = 4 + i;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bcopy(&bsl->compartments.c1, tt1->tag_cat, i);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (cop[IPOPT_OLEN]);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * The following routine searches for a security label in an IPv4 datagram.
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * It returns label_type of:
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * OPT_CIPSO if a CIPSO IP option is found.
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * OPT_NONE if no security label is found.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * If OPT_CIPSO, a pointer to the CIPSO IP option will be returned in
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * the buffer parameter.
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem *
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * The function will return with B_FALSE if an IP format error
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * is encountered.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystemboolean_t
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystemtsol_get_option_v4(mblk_t *mp, tsol_ip_label_t *label_type, uchar_t **buffer)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ipha_t *ipha;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uchar_t *opt;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint32_t totallen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint32_t optval;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint32_t optlen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem *label_type = OPT_NONE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Get length (in 4 byte octets) of IP header options.
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * If header doesn't contain options, then return a label_type
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * of OPT_NONE.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem ipha = (ipha_t *)mp->b_rptr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk totallen = ipha->ipha_version_and_hdr_length -
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem (uint8_t)((IP_VERSION << 4));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk totallen <<= 2;
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem if (totallen < IP_SIMPLE_HDR_LENGTH || totallen > MBLKL(mp))
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (B_FALSE);
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem totallen -= IP_SIMPLE_HDR_LENGTH;
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem if (totallen == 0)
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (B_TRUE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Search for CIPSO option.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If no such option is present, then return OPT_NONE.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk opt = (uchar_t *)&ipha[1];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk while (totallen != 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk switch (optval = opt[IPOPT_OPTVAL]) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case IPOPT_EOL:
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (B_TRUE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case IPOPT_NOP:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk optlen = 1;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk default:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (totallen <= IPOPT_OLEN)
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk optlen = opt[IPOPT_OLEN];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (optlen < 2)
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (optlen > totallen)
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Copy pointer to option into '*buffer' and
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * return the option type.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk switch (optval) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case IPOPT_COMSEC:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (TSOL_CIPSO_TAG_OFFSET < optlen &&
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem opt[TSOL_CIPSO_TAG_OFFSET] == 1) {
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem *label_type = OPT_CIPSO;
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem *buffer = opt;
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (B_TRUE);
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem }
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk totallen -= optlen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk opt += optlen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (B_TRUE);
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem}
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem/*
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * The following routine searches for a security label in an IPv6 datagram.
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * It returns label_type of:
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * OPT_CIPSO if a CIPSO IP option is found.
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * OPT_NONE if no security label is found.
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem *
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * If OPT_CIPSO, a pointer to the IPv4 portion of the CIPSO IP option will
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * be returned in the buffer parameter.
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem *
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * The function will return with B_FALSE if an IP format error
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * or an unexpected label content error is encountered.
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem */
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystemboolean_t
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystemtsol_get_option_v6(mblk_t *mp, tsol_ip_label_t *label_type, uchar_t **buffer)
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem{
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem uchar_t *opt_ptr = NULL;
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem uchar_t *after_secopt;
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem boolean_t hbh_needed;
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem const uchar_t *ip6hbh;
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem size_t optlen;
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem uint32_t doi;
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem const ip6_t *ip6h;
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem *label_type = OPT_NONE;
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem *buffer = NULL;
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem ip6h = (const ip6_t *)mp->b_rptr;
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem if (ip6h->ip6_nxt != IPPROTO_HOPOPTS)
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (B_TRUE);
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem ip6hbh = (const uchar_t *)&ip6h[1];
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem if (ip6hbh + MIN_EHDR_LEN > mp->b_wptr)
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (B_FALSE);
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem optlen = (ip6hbh[1] + 1) << 3;
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem if (ip6hbh + optlen > mp->b_wptr)
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (B_FALSE);
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem if (!tsol_find_secopt_v6(ip6hbh, optlen,
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem &opt_ptr, &after_secopt, &hbh_needed))
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (B_FALSE);
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem /* tsol_find_secopt_v6 guarantees some sanity */
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem if (opt_ptr != NULL) {
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem /*
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * IPv6 Option
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * opt_ptr[0]: Option type
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * opt_ptr[1]: Length of option data in bytes
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * opt_ptr[2]: First byte of option data
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem */
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem if ((optlen = opt_ptr[1]) < 8)
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (B_FALSE);
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem opt_ptr += 2;
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem /*
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * From "Generalized Labeled Security Option for IPv6" draft
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * opt_ptr[0] - opt_ptr[4]: DOI = IP6LS_DOI_V4
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * opt_ptr[4]: Tag type = IP6LS_TT_V4
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * opt_ptr[5]: Tag length in bytes starting at Tag type field
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * IPv4 CIPSO Option
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * opt_ptr[6]: option type
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * opt_ptr[7]: option length in bytes starting at type field
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem */
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem bcopy(opt_ptr, &doi, sizeof (doi));
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem doi = ntohl(doi);
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem if (doi == IP6LS_DOI_V4 &&
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem opt_ptr[4] == IP6LS_TT_V4 &&
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem opt_ptr[5] <= optlen - 4 &&
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem opt_ptr[7] <= optlen - 6 &&
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem opt_ptr[7] <= opt_ptr[5] - 2) {
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem opt_ptr += sizeof (doi) + 2;
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem *label_type = OPT_CIPSO;
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem *buffer = opt_ptr;
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (B_TRUE);
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem }
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (B_FALSE);
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem }
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (B_TRUE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem/*
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * tsol_check_dest()
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem *
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * This routine verifies if a destination is allowed to recieve messages
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * based on the security label. If any adjustments to the label are needed
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * due to the connection's MAC mode or the destination's ability
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * to receive labels, an "effective label" will be returned.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * zone_is_global is set if the actual zoneid is global. That is, it is
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * not set for an exclusive-IP zone.
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * On successful return, effective_tsl will point to the new label needed
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * or will be NULL if a new label isn't needed. On error, effective_tsl will
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * point to NULL.
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem *
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * Returns:
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * 0 Label (was|is now) correct
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * EHOSTUNREACH The label failed the remote host accreditation
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * ENOMEM Memory allocation failure
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem */
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystemint
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarktsol_check_dest(const ts_label_t *tsl, const void *dst,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uchar_t version, uint_t mac_mode, boolean_t zone_is_global,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ts_label_t **effective_tsl)
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem{
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ts_label_t *newtsl = NULL;
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem tsol_tpc_t *dst_rhtp;
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (effective_tsl != NULL)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *effective_tsl = NULL;
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem ASSERT(version == IPV4_VERSION ||
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem (version == IPV6_VERSION &&
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem !IN6_IS_ADDR_V4MAPPED((in6_addr_t *)dst)));
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem /* Always pass kernel level communication (NULL label) */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (tsl == NULL) {
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem DTRACE_PROBE2(tx__tnopt__log__info__labeling__mac__allownull,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark char *, "destination ip(1) with null label was passed",
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem ipaddr_t, dst);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem return (0);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem }
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld if (tsl->tsl_flags & TSLF_IMPLICIT_IN) {
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld DTRACE_PROBE3(tx__tnopt__log__info__labeling__unresolved__label,
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld char *,
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld "implicit-in packet to ip(1) reached tsol_check_dest "
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld "with implied security label sl(2)",
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld ipaddr_t, dst, ts_label_t *, tsl);
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld }
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem /* Always pass multicast */
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem if (version == IPV4_VERSION &&
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem CLASSD(*(ipaddr_t *)dst)) {
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem DTRACE_PROBE2(tx__tnopt__log__info__labeling__mac__allowmult,
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem char *, "destination ip(1) with multicast dest was passed",
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem ipaddr_t, dst);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem return (0);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem } else if (version == IPV6_VERSION &&
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem IN6_IS_ADDR_MULTICAST((in6_addr_t *)dst)) {
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem DTRACE_PROBE2(tx__tnopt__log__info__labeling__mac__allowmult_v6,
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem char *, "destination ip(1) with multicast dest was passed",
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem in6_addr_t *, dst);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem return (0);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem }
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem /* Never pass an undefined destination */
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem if ((dst_rhtp = find_tpc(dst, version, B_FALSE)) == NULL) {
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem DTRACE_PROBE2(tx__tnopt__log__info__labeling__lookupdst,
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem char *, "destination ip(1) not in tn database.",
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem void *, dst);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem return (EHOSTUNREACH);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem }
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem switch (dst_rhtp->tpc_tp.host_type) {
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem case UNLABELED:
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem /*
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * Can talk to unlabeled hosts if
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * (1) zone's label matches the default label, or
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * (2) SO_MAC_EXEMPT is on and we
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * dominate the peer's label, or
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * (3) SO_MAC_EXEMPT is on and
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * this is the global zone
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem */
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem if (dst_rhtp->tpc_tp.tp_doi != tsl->tsl_doi) {
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem DTRACE_PROBE4(tx__tnopt__log__info__labeling__doi,
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem char *, "unlabeled dest ip(1)/tpc(2) doi does "
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem "not match msg label(3) doi.", void *, dst,
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem tsol_tpc_t *, dst_rhtp, ts_label_t *, tsl);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem TPC_RELE(dst_rhtp);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem return (EHOSTUNREACH);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem }
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem if (!blequal(&dst_rhtp->tpc_tp.tp_def_label,
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem &tsl->tsl_label)) {
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld if (mac_mode != CONN_MAC_AWARE ||
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark !(zone_is_global ||
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem bldominates(&tsl->tsl_label,
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem &dst_rhtp->tpc_tp.tp_def_label))) {
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem DTRACE_PROBE4(
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem tx__tnopt__log__info__labeling__mac,
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem char *, "unlabeled dest ip(1)/tpc(2) does "
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem "not match msg label(3).", void *, dst,
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem tsol_tpc_t *, dst_rhtp, ts_label_t *, tsl);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem TPC_RELE(dst_rhtp);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem return (EHOSTUNREACH);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem }
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem /*
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * This is a downlabel MAC-exempt exchange.
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * Use the remote destination's default label
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * as the label of the message data.
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem */
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem if ((newtsl = labelalloc(&dst_rhtp->tpc_tp.tp_def_label,
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem dst_rhtp->tpc_tp.tp_doi, KM_NOSLEEP)) == NULL) {
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem TPC_RELE(dst_rhtp);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem return (ENOMEM);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem }
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem newtsl->tsl_flags |= TSLF_UNLABELED;
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem } else if (!(tsl->tsl_flags & TSLF_UNLABELED)) {
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem /*
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * The security labels are the same but we need
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * to flag that the remote node is unlabeled.
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem */
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem if ((newtsl = labeldup(tsl, KM_NOSLEEP)) == NULL) {
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem TPC_RELE(dst_rhtp);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem return (ENOMEM);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem }
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem newtsl->tsl_flags |= TSLF_UNLABELED;
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem }
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem break;
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem case SUN_CIPSO:
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem /*
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * Can talk to labeled hosts if zone's label is within target's
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * label range or set.
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem */
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem if (dst_rhtp->tpc_tp.tp_cipso_doi_cipso != tsl->tsl_doi ||
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem (!_blinrange(&tsl->tsl_label,
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem &dst_rhtp->tpc_tp.tp_sl_range_cipso) &&
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem !blinlset(&tsl->tsl_label,
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem dst_rhtp->tpc_tp.tp_sl_set_cipso))) {
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem DTRACE_PROBE4(tx__tnopt__log__info__labeling__mac,
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem char *, "labeled dest ip(1)/tpc(2) does not "
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem "match msg label(3).", void *, dst,
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem tsol_tpc_t *, dst_rhtp, ts_label_t *, tsl);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem TPC_RELE(dst_rhtp);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem return (EHOSTUNREACH);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem }
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld if ((tsl->tsl_flags & TSLF_UNLABELED) ||
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld (mac_mode == CONN_MAC_IMPLICIT)) {
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem /*
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * Copy label so we can modify the flags
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem */
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem if ((newtsl = labeldup(tsl, KM_NOSLEEP)) == NULL) {
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem TPC_RELE(dst_rhtp);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem return (ENOMEM);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem }
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld /*
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * The security label is a match but we need to
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld * clear the unlabeled flag for this remote node.
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld */
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld newtsl->tsl_flags &= ~TSLF_UNLABELED;
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld if (mac_mode == CONN_MAC_IMPLICIT)
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld newtsl->tsl_flags |= TSLF_IMPLICIT_OUT;
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem }
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem break;
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem default:
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem TPC_RELE(dst_rhtp);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem return (EHOSTUNREACH);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem }
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem /*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Return the new label.
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem */
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem if (newtsl != NULL) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (effective_tsl != NULL)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *effective_tsl = newtsl;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark else
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark label_rele(newtsl);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem }
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem TPC_RELE(dst_rhtp);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem return (0);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem}
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * tsol_compute_label_v4()
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * This routine computes the IP label that should be on a packet based on the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * connection and destination information.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * The zoneid is the IP zoneid (i.e., GLOBAL_ZONEID for exlusive-IP zones).
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Returns:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * 0 Fetched label
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * EHOSTUNREACH No route to destination
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * EINVAL Label cannot be computed
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkint
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarktsol_compute_label_v4(const ts_label_t *tsl, zoneid_t zoneid, ipaddr_t dst,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uchar_t *opt_storage, ip_stack_t *ipst)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint_t sec_opt_len;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ire_t *ire;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark tsol_ire_gw_secattr_t *attrp = NULL;
de8c4a14ec9a49bad5e62b2cfa6c1ba21de1c708Erik Nordmark
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (opt_storage != NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk opt_storage[IPOPT_OLEN] = 0;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (tsl == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* always pass multicast */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (CLASSD(dst))
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld if (tsl->tsl_flags & TSLF_IMPLICIT_OUT)
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld return (0);
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem if (tsl->tsl_flags & TSLF_UNLABELED) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * The destination is unlabeled. Only add a label if the
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * destination is not a broadcast/local/loopback address,
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * the destination is not on the same subnet, and the
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * next-hop gateway is labeled.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ire = ire_route_recursive_v4(dst, 0, NULL, zoneid, tsl,
9e3469d3db608feb0e43d9955cbf406c22025463Erik Nordmark MATCH_IRE_SECATTR, IRR_ALLOCATE, 0, ipst, NULL, &attrp,
9e3469d3db608feb0e43d9955cbf406c22025463Erik Nordmark NULL);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ASSERT(ire != NULL);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* no route to destination */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ire_refrele(ire);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem DTRACE_PROBE3(
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tx__tnopt__log__info__labeling__routedst__v4,
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem char *, "No route to unlabeled dest ip(1) with "
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark "with label(2).", ipaddr_t, dst, ts_label_t *, tsl);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem return (EHOSTUNREACH);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (ire->ire_type & (IRE_BROADCAST | IRE_LOCAL | IRE_LOOPBACK |
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark IRE_INTERFACE)) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ire_refrele(ire);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (0);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ire_route_recursive gives us the first attrp it finds
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * in the recursive lookup.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * Return now if next hop gateway is unlabeled. There is
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * no need to generate a CIPSO option for this message.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem if (attrp == NULL || attrp->igsa_rhc == NULL ||
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem attrp->igsa_rhc->rhc_tpc->tpc_tp.host_type == UNLABELED) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ire_refrele(ire);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ire_refrele(ire);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* compute the CIPSO option */
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem sec_opt_len = tsol2cipso_tt1(&tsl->tsl_label, opt_storage,
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem tsl->tsl_doi);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (sec_opt_len == 0) {
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem DTRACE_PROBE3(tx__tnopt__log__error__labeling__lostops__v4,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark char *, "options lack length for dest ip(1) with label(2).",
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ipaddr_t, dst, ts_label_t *, tsl);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (EINVAL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Remove any existing security option (CIPSO) from the given IP
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * header, move the 'buflen' bytes back to fill the gap, and return the number
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * of bytes removed (as zero or negative number). Assumes that the headers are
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * sane.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Note that tsol_remove_secopt does not adjust ipha_length but
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * tsol_remove_secopt_v6 does adjust ip6_plen.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkint
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktsol_remove_secopt(ipha_t *ipha, int buflen)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int remlen, olen, oval, delta;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uchar_t *fptr, *tptr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk boolean_t noop_keep;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk remlen = IPH_HDR_LENGTH(ipha) - IP_SIMPLE_HDR_LENGTH;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk fptr = tptr = (uchar_t *)(ipha + 1);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk noop_keep = B_TRUE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk while (remlen > 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk oval = fptr[IPOPT_OPTVAL];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* terminate on end of list */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (oval == IPOPT_EOL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Delete any no-ops following a deleted option, at least up
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * to a 4 octet alignment; copy others.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (oval == IPOPT_NOP) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (((fptr - (uchar_t *)ipha) & 3) == 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk noop_keep = B_TRUE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (noop_keep)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *tptr++ = oval;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk fptr++;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk remlen--;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk continue;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* stop on corrupted list; just do nothing. */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (remlen < 2)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk olen = fptr[IPOPT_OLEN];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (olen < 2 || olen > remlen)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* skip over security options to delete them */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (oval == IPOPT_COMSEC || oval == IPOPT_SECURITY) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk noop_keep = B_FALSE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk fptr += olen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk remlen -= olen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk continue;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* copy the rest */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk noop_keep = B_TRUE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tptr != fptr)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ovbcopy(fptr, tptr, olen);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk fptr += olen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tptr += olen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk remlen -= olen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk fptr += remlen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* figure how much padding we'll need for header alignment */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk olen = (tptr - (uchar_t *)ipha) & 3;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (olen > 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk olen = 4 - olen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* pad with end-of-list */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bzero(tptr, olen);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tptr += olen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* slide back the headers that follow and update the IP header */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk delta = fptr - tptr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (delta != 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ovbcopy(fptr, tptr, ((uchar_t *)ipha + buflen) - fptr);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ipha->ipha_version_and_hdr_length -= delta / 4;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (-delta);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Insert the option in 'optbuf' into the IP header pointed to by 'ipha', and
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * move the data following the IP header (up to buflen) to accomodate the new
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * option. Assumes that up to IP_MAX_OPT_LENGTH bytes are available (in total)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * for IP options. Returns the number of bytes actually inserted, or -1 if the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * option cannot be inserted. (Note that negative return values are possible
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * when noops must be compressed, and that only -1 indicates error. Successful
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * return value is always evenly divisible by 4, by definition.)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Note that tsol_prepend_option does not adjust ipha_length but
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * tsol_prepend_option_v6 does adjust ip6_plen.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkint
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktsol_prepend_option(uchar_t *optbuf, ipha_t *ipha, int buflen)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int remlen, padding, lastpad, totlen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int oval, olen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int delta;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uchar_t *optr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uchar_t tempopt[IP_MAX_OPT_LENGTH], *toptr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (optbuf[IPOPT_OPTVAL] == IPOPT_EOL ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk optbuf[IPOPT_OPTVAL] == IPOPT_NOP ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk optbuf[IPOPT_OLEN] == 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(optbuf[IPOPT_OLEN] >= 2 &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk optbuf[IPOPT_OLEN] <= IP_MAX_OPT_LENGTH);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* first find the real (unpadded) length of the existing options */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk remlen = IPH_HDR_LENGTH(ipha) - IP_SIMPLE_HDR_LENGTH;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk padding = totlen = lastpad = 0;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk optr = (uchar_t *)(ipha + 1);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk while (remlen > 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk oval = optr[IPOPT_OPTVAL];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* stop at end of list */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (oval == IPOPT_EOL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* skip no-ops, noting that length byte isn't present */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (oval == IPOPT_NOP) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk optr++;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk padding++;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk lastpad++;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk totlen++;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk remlen--;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk continue;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* give up on a corrupted list; report failure */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (remlen < 2)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (-1);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk olen = optr[IPOPT_OLEN];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (olen < 2 || olen > remlen)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (-1);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk lastpad = 0;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk optr += olen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk totlen += olen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk remlen -= olen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* completely ignore any trailing padding */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk totlen -= lastpad;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk padding -= lastpad;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If some sort of inter-option alignment was present, try to preserve
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * that alignment. If alignment pushes us out past the maximum, then
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * discard it and try to compress to fit. (We just "assume" that any
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * padding added was attempting to get 32 bit alignment. If that's
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * wrong, that's just too bad.)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (padding > 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk olen = (optbuf[IPOPT_OLEN] + 3) & ~3;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (olen + totlen > IP_MAX_OPT_LENGTH) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk totlen -= padding;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (olen + totlen > IP_MAX_OPT_LENGTH)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (-1);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk padding = 0;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Since we may need to compress or expand the option list, we write to
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * a temporary buffer and then copy the results back to the IP header.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk toptr = tempopt;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* compute actual option to insert */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk olen = optbuf[IPOPT_OLEN];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bcopy(optbuf, toptr, olen);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk toptr += olen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (padding > 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk while ((olen & 3) != 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *toptr++ = IPOPT_NOP;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk olen++;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* copy over the existing options */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk optr = (uchar_t *)(ipha + 1);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk while (totlen > 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk oval = optr[IPOPT_OPTVAL];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* totlen doesn't include end-of-list marker */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(oval != IPOPT_EOL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* handle no-ops; copy if desired, ignore otherwise */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (oval == IPOPT_NOP) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (padding > 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* note: cannot overflow due to checks above */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(toptr < tempopt + IP_MAX_OPT_LENGTH);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *toptr++ = oval;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk optr++;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk totlen--;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk continue;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* list cannot be corrupt at this point */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(totlen >= 2);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk olen = optr[IPOPT_OLEN];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(olen >= 2 && olen <= totlen);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* cannot run out of room due to tests above */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(toptr + olen <= tempopt + IP_MAX_OPT_LENGTH);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bcopy(optr, toptr, olen);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk optr += olen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk toptr += olen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk totlen -= olen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* figure how much padding we'll need for header alignment */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk olen = (toptr - tempopt) & 3;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (olen > 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk olen = 4 - olen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(toptr + olen <= tempopt + IP_MAX_OPT_LENGTH);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* pad with end-of-list value */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bzero(toptr, olen);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk toptr += olen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* move the headers as needed and update IP header */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk olen = (toptr - tempopt) + IP_SIMPLE_HDR_LENGTH;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk remlen = IPH_HDR_LENGTH(ipha);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk delta = olen - remlen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (delta != 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ovbcopy((uchar_t *)ipha + remlen, (uchar_t *)ipha + olen,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk buflen - remlen);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ipha->ipha_version_and_hdr_length += delta / 4;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* slap in the new options */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bcopy(tempopt, ipha + 1, olen - IP_SIMPLE_HDR_LENGTH);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (delta);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * tsol_check_label_v4()
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * This routine computes the IP label that should be on the packet based on the
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * connection and destination information. It's called by the IP forwarding
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * logic and by ip_output_simple. The ULPs generate the labels before calling
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * conn_ip_output. If any adjustments to
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * the label are needed due to the connection's MAC-exempt status or
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * the destination's ability to receive labels, an "effective label"
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * will be returned.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
222c5bce8762079550e5ccd485a12de1fff5a82ekp * The packet's header is clear before entering IPsec's engine.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * The zoneid is the IP zoneid (i.e., GLOBAL_ZONEID for exlusive-IP zones).
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * zone_is_global is set if the actual zoneid is global.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * On successful return, effective_tslp will point to the new label needed
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * or will be NULL if a new label isn't needed. On error, effective_tsl will
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * point to NULL.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Returns:
0e0e37a8f0c38eb919c913bbb67030114a6b74a9Erik Nordmark * 0 Label (was|is now) correct
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * EACCES The packet failed the remote host accreditation.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * ENOMEM Memory allocation failure.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * EINVAL Label cannot be computed
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkint
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarktsol_check_label_v4(const ts_label_t *tsl, zoneid_t zoneid, mblk_t **mpp,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint_t mac_mode, boolean_t zone_is_global, ip_stack_t *ipst,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ts_label_t **effective_tslp)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mblk_t *mp = *mpp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ipha_t *ipha;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ts_label_t *effective_tsl = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uchar_t opt_storage[IP_MAX_OPT_LENGTH];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint_t hlen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint_t sec_opt_len;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uchar_t *optr;
222c5bce8762079550e5ccd485a12de1fff5a82ekp int delta_remove = 0, delta_add, adjust;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int retv;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *effective_tslp = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk opt_storage[IPOPT_OPTVAL] = 0;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ipha = (ipha_t *)mp->b_rptr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem /*
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * Verify the destination is allowed to receive packets at
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * the security label of the message data. tsol_check_dest()
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * may create a new effective label or label flags.
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark retv = tsol_check_dest(tsl, &ipha->ipha_dst, IPV4_VERSION,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mac_mode, zone_is_global, &effective_tsl);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (retv != 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (retv);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem /*
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * Calculate the security label to be placed in the text
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * of the message (if any).
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (effective_tsl != NULL) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if ((retv = tsol_compute_label_v4(effective_tsl, zoneid,
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem ipha->ipha_dst, opt_storage, ipst)) != 0) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark label_rele(effective_tsl);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem return (retv);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *effective_tslp = effective_tsl;
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem } else {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if ((retv = tsol_compute_label_v4(tsl, zoneid,
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem ipha->ipha_dst, opt_storage, ipst)) != 0) {
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem return (retv);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem }
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem }
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk optr = (uchar_t *)(ipha + 1);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk hlen = IPH_HDR_LENGTH(ipha) - IP_SIMPLE_HDR_LENGTH;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk sec_opt_len = opt_storage[IPOPT_OLEN];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (hlen >= sec_opt_len) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* If no option is supposed to be there, make sure it's not */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (sec_opt_len == 0 && hlen > 0 &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk optr[IPOPT_OPTVAL] != IPOPT_COMSEC &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk optr[IPOPT_OPTVAL] != IPOPT_SECURITY)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* if the option is there, it's always first */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (sec_opt_len != 0 &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bcmp(opt_storage, optr, sec_opt_len) == 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If there is an option there, then it must be the wrong one; delete.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
222c5bce8762079550e5ccd485a12de1fff5a82ekp if (hlen > 0) {
222c5bce8762079550e5ccd485a12de1fff5a82ekp delta_remove = tsol_remove_secopt(ipha, MBLKL(mp));
222c5bce8762079550e5ccd485a12de1fff5a82ekp mp->b_wptr += delta_remove;
222c5bce8762079550e5ccd485a12de1fff5a82ekp }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Make sure we have room for the worst-case addition */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk hlen = IPH_HDR_LENGTH(ipha) + opt_storage[IPOPT_OLEN];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk hlen = (hlen + 3) & ~3;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (hlen > IP_MAX_HDR_LENGTH)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk hlen = IP_MAX_HDR_LENGTH;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk hlen -= IPH_HDR_LENGTH(ipha);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (mp->b_wptr + hlen > mp->b_datap->db_lim) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int copylen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mblk_t *new_mp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* allocate enough to be meaningful, but not *too* much */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk copylen = MBLKL(mp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (copylen > 256)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk copylen = 256;
de8c4a14ec9a49bad5e62b2cfa6c1ba21de1c708Erik Nordmark new_mp = allocb_tmpl(hlen + copylen +
de8c4a14ec9a49bad5e62b2cfa6c1ba21de1c708Erik Nordmark (mp->b_rptr - mp->b_datap->db_base), mp);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (new_mp == NULL) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (effective_tsl != NULL) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark label_rele(effective_tsl);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *effective_tslp = NULL;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (ENOMEM);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* keep the bias */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk new_mp->b_rptr += mp->b_rptr - mp->b_datap->db_base;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk new_mp->b_wptr = new_mp->b_rptr + copylen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bcopy(mp->b_rptr, new_mp->b_rptr, copylen);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk new_mp->b_cont = mp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((mp->b_rptr += copylen) >= mp->b_wptr) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk new_mp->b_cont = mp->b_cont;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk freeb(mp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *mpp = mp = new_mp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ipha = (ipha_t *)mp->b_rptr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
222c5bce8762079550e5ccd485a12de1fff5a82ekp delta_add = tsol_prepend_option(opt_storage, ipha, MBLKL(mp));
222c5bce8762079550e5ccd485a12de1fff5a82ekp if (delta_add == -1)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk goto param_prob;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
222c5bce8762079550e5ccd485a12de1fff5a82ekp ASSERT((mp->b_wptr + delta_add) <= DB_LIM(mp));
222c5bce8762079550e5ccd485a12de1fff5a82ekp mp->b_wptr += delta_add;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
222c5bce8762079550e5ccd485a12de1fff5a82ekp adjust = delta_remove + delta_add;
222c5bce8762079550e5ccd485a12de1fff5a82ekp adjust += ntohs(ipha->ipha_length);
222c5bce8762079550e5ccd485a12de1fff5a82ekp ipha->ipha_length = htons(adjust);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkparam_prob:
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (effective_tsl != NULL) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark label_rele(effective_tsl);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *effective_tslp = NULL;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (EINVAL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * IPv6 HopOpt extension header for the label option layout:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * - One octet giving the type of the 'next extension header'
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * - Header extension length in 8-byte words, not including the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * 1st 8 bytes, but including any pad bytes at the end.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Eg. A value of 2 means 16 bytes not including the 1st 8 bytes.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * - Followed by TLV encoded IPv6 label option. Option layout is
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * * One octet, IP6OPT_LS
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * * One octet option length in bytes of the option data following
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * the length, but not including any pad bytes at the end.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * * Four-octet DOI (IP6LS_DOI_V4)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * * One octet suboption, IP6LS_TT_V4
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * * One octet suboption length in bytes of the suboption
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * following the suboption length, including the suboption
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * header length, but not including any pad bytes at the end.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * - Pad to make the extension header a multiple of 8 bytes.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * This function returns the contents of 'IPv6 option structure' in the above.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * i.e starting from the IP6OPT_LS but not including the pad at the end.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * The user must prepend two octets (either padding or next header / length)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * and append padding out to the next 8 octet boundary.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * The zoneid is the IP zoneid (i.e., GLOBAL_ZONEID for exlusive-IP zones).
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkint
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarktsol_compute_label_v6(const ts_label_t *tsl, zoneid_t zoneid,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark const in6_addr_t *dst, uchar_t *opt_storage, ip_stack_t *ipst)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint_t sec_opt_len;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint32_t doi;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ire_t *ire;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark tsol_ire_gw_secattr_t *attrp = NULL;
de8c4a14ec9a49bad5e62b2cfa6c1ba21de1c708Erik Nordmark
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (ip6opt_ls == 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (EINVAL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (opt_storage != NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk opt_storage[IPOPT_OLEN] = 0;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (tsl == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Always pass multicast */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (IN6_IS_ADDR_MULTICAST(dst))
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Fill in a V6 label. If a new format is added here, make certain
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * that the maximum size of this label is reflected in sys/tsol/tnet.h
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * as TSOL_MAX_IPV6_OPTION.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld if (tsl->tsl_flags & TSLF_IMPLICIT_OUT)
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld return (0);
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem if (tsl->tsl_flags & TSLF_UNLABELED) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * The destination is unlabeled. Only add a label if the
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * destination is not a broadcast/local/loopback address,
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * the destination is not on the same subnet, and the
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * next-hop gateway is labeled.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ire = ire_route_recursive_v6(dst, 0, NULL, zoneid, tsl,
9e3469d3db608feb0e43d9955cbf406c22025463Erik Nordmark MATCH_IRE_SECATTR, IRR_ALLOCATE, 0, ipst, NULL, &attrp,
9e3469d3db608feb0e43d9955cbf406c22025463Erik Nordmark NULL);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ASSERT(ire != NULL);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* no route to destination */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ire_refrele(ire);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem DTRACE_PROBE3(
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tx__tnopt__log__info__labeling__routedst__v6,
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem char *, "No route to unlabeled dest ip6(1) with "
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark "label(2).", in6_addr_t *, dst, ts_label_t *, tsl);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem return (EHOSTUNREACH);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (ire->ire_type & (IRE_LOCAL | IRE_LOOPBACK |
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark IRE_INTERFACE)) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ire_refrele(ire);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (0);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ire_route_recursive gives us the first attrp it finds
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * in the recursive lookup.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem /*
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * Return now if next hop gateway is unlabeled. There is
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * no need to generate a CIPSO option for this message.
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem */
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem if (attrp == NULL || attrp->igsa_rhc == NULL ||
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem attrp->igsa_rhc->rhc_tpc->tpc_tp.host_type == UNLABELED) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ire_refrele(ire);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ire_refrele(ire);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* compute the CIPSO option */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (opt_storage != NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk opt_storage += 8;
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem sec_opt_len = tsol2cipso_tt1(&tsl->tsl_label, opt_storage,
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem tsl->tsl_doi);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (sec_opt_len == 0) {
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem DTRACE_PROBE3(tx__tnopt__log__error__labeling__lostops__v6,
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem char *, "options lack length for dest ip6(1) with "
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark "label(2).", in6_addr_t *, dst, ts_label_t *, tsl);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (EINVAL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (opt_storage == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (sec_opt_len < IP_MAX_OPT_LENGTH)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk opt_storage[sec_opt_len] = IPOPT_EOL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Just in case the option length is odd, round it up to the next even
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * multiple. The IPv6 option definition doesn't like odd numbers for
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * some reason.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Length in the overall option header (IP6OPT_LS) does not include the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * option header itself, but the length in the suboption does include
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * the suboption header. Thus, when there's just one suboption, the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * length in the option header is the suboption length plus 4 (for the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * DOI value).
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk opt_storage[-2] = IP6LS_TT_V4;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk opt_storage[-1] = (sec_opt_len + 2 + 1) & ~1;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk opt_storage[-8] = ip6opt_ls;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk opt_storage[-7] = opt_storage[-1] + 4;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk doi = htons(IP6LS_DOI_V4);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bcopy(&doi, opt_storage - 6, 4);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Locate the start of the IP6OPT_LS label option and return it.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Also return the start of the next non-pad option in after_secoptp.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Usually the label option is the first option at least when packets
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * are generated, but for generality we don't assume that on received packets.
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem *
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * The function will return with B_FALSE if an IP format error
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * or an unexpected label content error is encountered.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystemboolean_t
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktsol_find_secopt_v6(
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const uchar_t *ip6hbh, /* Start of the hop-by-hop extension header */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint_t hbhlen, /* Length of the hop-by-hop extension header */
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem uchar_t **secoptp, /* Location of IP6OPT_LS label option */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uchar_t **after_secoptp, /* Non-pad option following the label option */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk boolean_t *hbh_needed) /* Is hop-by-hop hdr needed w/o label */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint_t optlen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint_t optused;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const uchar_t *optptr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uchar_t opt_type;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem *secoptp = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *hbh_needed = B_FALSE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *after_secoptp = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk optlen = hbhlen - 2;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk optptr = ip6hbh + 2;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk while (optlen != 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk opt_type = *optptr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (opt_type == IP6OPT_PAD1) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk optptr++;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk optlen--;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk continue;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (optlen == 1)
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk optused = 2 + optptr[1];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (optused > optlen)
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * if we get here, ip6opt_ls can
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * not be 0 because it will always
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * match the IP6OPT_PAD1 above.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Therefore ip6opt_ls == 0 forces
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * this test to always fail here.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem if (opt_type == ip6opt_ls) {
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem if (*secoptp != NULL)
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem /* More than one security option found */
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (B_FALSE);
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem *secoptp = (uchar_t *)optptr;
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem } else switch (opt_type) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk case IP6OPT_PADN:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk default:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * There is at least 1 option other than
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * the label option. So the hop-by-hop header is needed
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *hbh_needed = B_TRUE;
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem if (*secoptp != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *after_secoptp = (uchar_t *)optptr;
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (B_TRUE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk optlen -= optused;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk optptr += optused;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (B_TRUE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Remove the label option from the hop-by-hop options header if it exists.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * 'buflen' is the total length of the packet typically b_wptr - b_rptr.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Header and data following the label option that is deleted are copied
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy * (i.e. slid backward) to the right position, and returns the number
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy * of bytes removed (as zero or negative number.)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Note that tsol_remove_secopt does not adjust ipha_length but
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * tsol_remove_secopt_v6 does adjust ip6_plen.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkint
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktsol_remove_secopt_v6(ip6_t *ip6h, int buflen)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uchar_t *ip6hbh; /* hop-by-hop header */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint_t hbhlen; /* hop-by-hop extension header length */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uchar_t *secopt = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uchar_t *after_secopt;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint_t pad;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint_t delta;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk boolean_t hbh_needed;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * hop-by-hop extension header must appear first, if it does not
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * exist, there is no label option.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (ip6h->ip6_nxt != IPPROTO_HOPOPTS)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ip6hbh = (uchar_t *)&ip6h[1];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk hbhlen = (ip6hbh[1] + 1) << 3;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Locate the start of the label option if it exists and the end
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * of the label option including pads if any.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem if (!tsol_find_secopt_v6(ip6hbh, hbhlen, &secopt, &after_secopt,
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem &hbh_needed)) {
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem /*
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * This function should not see invalid messages.
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * If one occurs, it would indicate either an
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * option previously verified in the forwarding
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * path has been corrupted or an option was
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * incorrectly generated locally.
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem */
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem ASSERT(0);
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (0);
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (secopt == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (!hbh_needed) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uchar_t next_hdr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * The label option was the only option in the hop-by-hop
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * header. We don't need the hop-by-hop header itself any
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * longer.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk next_hdr = ip6hbh[0];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ovbcopy(ip6hbh + hbhlen, ip6hbh,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk buflen - (IPV6_HDR_LEN + hbhlen));
d7ab25acb993ab117834d04e877943640f215b79kp ip6h->ip6_plen = htons(ntohs(ip6h->ip6_plen) - hbhlen);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ip6h->ip6_nxt = next_hdr;
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy return (-hbhlen);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (after_secopt == NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* There is no option following the label option */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk after_secopt = ip6hbh + hbhlen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * After deleting the label option, we need to slide the headers
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * and data back, while still maintaining the same alignment (module 8)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * for the other options. So we slide the headers and data back only
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * by an integral multiple of 8 bytes, and fill the remaining bytes
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * with pads.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk delta = after_secopt - secopt;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk pad = delta % 8;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (pad == 1) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk secopt[0] = IP6OPT_PAD1;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else if (pad > 1) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk secopt[0] = IP6OPT_PADN;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk secopt[1] = pad - 2;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (pad > 2)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bzero(&secopt[2], pad - 2);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk secopt += pad;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk delta -= pad;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ovbcopy(after_secopt, secopt,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (uchar_t *)ip6h + buflen - after_secopt);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ip6hbh[1] -= delta/8;
d7ab25acb993ab117834d04e877943640f215b79kp ip6h->ip6_plen = htons(ntohs(ip6h->ip6_plen) - delta);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
0ec92a15793cedb674b4f9dffc0b3dd9058fc529wy return (-delta);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * 'optbuf' contains a CIPSO label embedded in an IPv6 hop-by-hop option,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * starting with the IP6OPT_LS option type. The format of this hop-by-hop
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * option is described in the block comment above tsol_compute_label_v6.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * This function prepends this hop-by-hop option before any other hop-by-hop
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * options in the hop-by-hop header if one already exists, else a new
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * hop-by-hop header is created and stuffed into the packet following
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * the IPv6 header. 'buflen' is the total length of the packet i.e.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * b_wptr - b_rptr. The caller ensures that there is enough space for the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * extra option being added. Header and data following the position where
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * the label option is inserted are copied (i.e. slid forward) to the right
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * position.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Note that tsol_prepend_option does not adjust ipha_length but
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * tsol_prepend_option_v6 does adjust ip6_plen.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkint
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpktsol_prepend_option_v6(uchar_t *optbuf, ip6_t *ip6h, int buflen)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * rawlen is the length of the label option in bytes, not including
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * any pads, starting from the IP6OPT_LS (option type) byte.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint_t rawlen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint_t optlen; /* rawlen rounded to an 8 byte multiple */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uchar_t *ip6hbh; /* start of the hop-by-hop extension header */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint_t hbhlen; /* Length of the hop-by-hop extension header */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint_t pad_len;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uchar_t *pad_position;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int delta; /* Actual number of bytes inserted */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rawlen = optbuf[1] + 2; /* Add 2 for the option type, option length */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ip6hbh = (uchar_t *)&ip6h[1];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (ip6h->ip6_nxt == IPPROTO_HOPOPTS) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * There is a hop-by-hop header present already. In order to
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * preserve the alignment of the other options at the existing
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * value (modulo 8) we need to pad the label option to a
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * multiple of 8 bytes before prepending it to the other
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * options. Slide the extension headers and data forward to
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * accomodate the label option at the start of the hop-by-hop
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * header
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk delta = optlen = (rawlen + 7) & ~7;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk pad_len = optlen - rawlen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk pad_position = ip6hbh + 2 + rawlen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ovbcopy(ip6hbh + 2, ip6hbh + 2 + optlen,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk buflen - (IPV6_HDR_LEN + 2));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Bump up the hop-by-hop extension header length by
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * the number of 8-byte words added
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk optlen >>= 3;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (ip6hbh[1] + optlen > 255)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (-1);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ip6hbh[1] += optlen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * There is no hop-by-hop header in the packet. Construct a
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * new Hop-by-hop extension header (a multiple of 8 bytes).
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Slide any other extension headers and data forward to
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * accomodate this hop-by-hop header
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk delta = hbhlen = (2 + rawlen + 7) & ~7; /* +2 for nxthdr, len */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk pad_len = hbhlen - (2 + rawlen);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk pad_position = ip6hbh + 2 + rawlen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ovbcopy(ip6hbh, ip6hbh + hbhlen, buflen - IPV6_HDR_LEN);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ip6hbh[0] = ip6h->ip6_nxt;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * hop-by-hop extension header length in 8-byte words, not
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * including the 1st 8 bytes of the hop-by-hop header.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ip6hbh[1] = (hbhlen >> 3) - 1;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ip6h->ip6_nxt = IPPROTO_HOPOPTS;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Copy the label option into the hop-by-hop header and insert any
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * needed pads
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bcopy(optbuf, ip6hbh + 2, rawlen);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (pad_len == 1) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk pad_position[0] = IP6OPT_PAD1;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else if (pad_len > 1) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk pad_position[0] = IP6OPT_PADN;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk pad_position[1] = pad_len - 2;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (pad_len > 2)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bzero(pad_position + 2, pad_len - 2);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
d7ab25acb993ab117834d04e877943640f215b79kp ip6h->ip6_plen = htons(ntohs(ip6h->ip6_plen) + delta);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (delta);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * tsol_check_label_v6()
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * This routine computes the IP label that should be on the packet based on the
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * connection and destination information. It's called by the IP forwarding
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * logic and by ip_output_simple. The ULPs generate the labels before calling
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * conn_ip_output. If any adjustments to
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * the label are needed due to the connection's MAC-exempt status or
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * the destination's ability to receive labels, an "effective label"
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * will be returned.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * The packet's header is clear before entering IPsec's engine.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * The zoneid is the IP zoneid (i.e., GLOBAL_ZONEID for exlusive-IP zones).
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * zone_is_global is set if the actual zoneid is global.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * On successful return, effective_tslp will point to the new label needed
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * or will be NULL if a new label isn't needed. On error, effective_tsl will
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * point to NULL.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Returns:
0e0e37a8f0c38eb919c913bbb67030114a6b74a9Erik Nordmark * 0 Label (was|is now) correct
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * EACCES The packet failed the remote host accreditation.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * ENOMEM Memory allocation failure.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * EINVAL Label cannot be computed
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkint
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarktsol_check_label_v6(const ts_label_t *tsl, zoneid_t zoneid, mblk_t **mpp,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint_t mac_mode, boolean_t zone_is_global, ip_stack_t *ipst,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ts_label_t **effective_tslp)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mblk_t *mp = *mpp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ip6_t *ip6h;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ts_label_t *effective_tsl = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Label option length is limited to IP_MAX_OPT_LENGTH for
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * symmetry with IPv4. Can be relaxed if needed
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uchar_t opt_storage[TSOL_MAX_IPV6_OPTION];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint_t hlen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint_t sec_opt_len; /* label option length not including type, len */
222c5bce8762079550e5ccd485a12de1fff5a82ekp int delta_remove = 0, delta_add;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int retv;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uchar_t *after_secopt;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uchar_t *secopt = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uchar_t *ip6hbh;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint_t hbhlen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk boolean_t hbh_needed;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *effective_tslp = NULL;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem /*
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * Verify the destination is allowed to receive packets at
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * the security label of the message data. tsol_check_dest()
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * may create a new effective label or label flags.
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ip6h = (ip6_t *)mp->b_rptr;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark retv = tsol_check_dest(tsl, &ip6h->ip6_dst, IPV6_VERSION,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mac_mode, zone_is_global, &effective_tsl);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (retv != 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (retv);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem /*
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * Calculate the security label to be placed in the text
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem * of the message (if any).
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (effective_tsl != NULL) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if ((retv = tsol_compute_label_v6(effective_tsl, zoneid,
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem &ip6h->ip6_dst, opt_storage, ipst)) != 0) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark label_rele(effective_tsl);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem return (retv);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *effective_tslp = effective_tsl;
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem } else {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if ((retv = tsol_compute_label_v6(tsl, zoneid,
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem &ip6h->ip6_dst, opt_storage, ipst)) != 0)
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem return (retv);
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem }
5f9878b0212a5bc5924a85d227160bf7f43712f1ken Powell - Sun Microsystem
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk sec_opt_len = opt_storage[1];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (ip6h->ip6_nxt == IPPROTO_HOPOPTS) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ip6hbh = (uchar_t *)&ip6h[1];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk hbhlen = (ip6hbh[1] + 1) << 3;
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem if (!tsol_find_secopt_v6(ip6hbh, hbhlen, &secopt,
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem &after_secopt, &hbh_needed)) {
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem /*
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * This function should not see invalid messages.
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * If one occurs, it would indicate either an
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * option previously verified in the forwarding
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * path has been corrupted or an option was
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem * incorrectly generated locally.
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem */
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem ASSERT(0);
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem return (EACCES);
c4e55c13cee53b72d8c5c01391d9154039975bfbken Powell - Sun Microsystem }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (sec_opt_len == 0 && secopt == NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * The packet is not supposed to have a label, and it
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * does not have one currently
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
5d3b8cb7141cfa596d20cdc5043b8a6df635938dBill Sommerfeld
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (secopt != NULL && sec_opt_len != 0 &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (bcmp(opt_storage, secopt, sec_opt_len + 2) == 0)) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* The packet has the correct label already */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If there is an option there, then it must be the wrong one; delete.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
222c5bce8762079550e5ccd485a12de1fff5a82ekp if (secopt != NULL) {
222c5bce8762079550e5ccd485a12de1fff5a82ekp delta_remove = tsol_remove_secopt_v6(ip6h, MBLKL(mp));
222c5bce8762079550e5ccd485a12de1fff5a82ekp mp->b_wptr += delta_remove;
222c5bce8762079550e5ccd485a12de1fff5a82ekp }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Make sure we have room for the worst-case addition. Add 2 bytes for
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * the hop-by-hop ext header's next header and length fields. Add
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * another 2 bytes for the label option type, len and then round
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * up to the next 8-byte multiple.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk hlen = (4 + sec_opt_len + 7) & ~7;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (mp->b_wptr + hlen > mp->b_datap->db_lim) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int copylen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mblk_t *new_mp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk uint16_t hdr_len;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk hdr_len = ip_hdr_length_v6(mp, ip6h);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Allocate enough to be meaningful, but not *too* much.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Also all the IPv6 extension headers must be in the same mblk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk copylen = MBLKL(mp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (copylen > 256)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk copylen = 256;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (copylen < hdr_len)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk copylen = hdr_len;
de8c4a14ec9a49bad5e62b2cfa6c1ba21de1c708Erik Nordmark new_mp = allocb_tmpl(hlen + copylen +
de8c4a14ec9a49bad5e62b2cfa6c1ba21de1c708Erik Nordmark (mp->b_rptr - mp->b_datap->db_base), mp);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (new_mp == NULL) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (effective_tsl != NULL) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark label_rele(effective_tsl);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *effective_tslp = NULL;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (ENOMEM);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* keep the bias */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk new_mp->b_rptr += mp->b_rptr - mp->b_datap->db_base;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk new_mp->b_wptr = new_mp->b_rptr + copylen;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bcopy(mp->b_rptr, new_mp->b_rptr, copylen);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk new_mp->b_cont = mp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((mp->b_rptr += copylen) >= mp->b_wptr) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk new_mp->b_cont = mp->b_cont;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk freeb(mp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *mpp = mp = new_mp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ip6h = (ip6_t *)mp->b_rptr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
222c5bce8762079550e5ccd485a12de1fff5a82ekp delta_add = tsol_prepend_option_v6(opt_storage, ip6h, MBLKL(mp));
222c5bce8762079550e5ccd485a12de1fff5a82ekp if (delta_add == -1)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk goto param_prob;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
222c5bce8762079550e5ccd485a12de1fff5a82ekp ASSERT(mp->b_wptr + delta_add <= DB_LIM(mp));
222c5bce8762079550e5ccd485a12de1fff5a82ekp mp->b_wptr += delta_add;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* tsol_prepend_option_v6 has adjusted ip6_plen */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkparam_prob:
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (effective_tsl != NULL) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark label_rele(effective_tsl);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *effective_tslp = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (EINVAL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}