1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  *
  26  * Copyright 2017 Jason King.
  27  * Copyirght 2017 Joyent, Inc.
  28  */
  29 
  30 #ifndef _PKT_H
  31 #define _PKT_H
  32 
  33 #include <sys/types.h>
  34 #include "ike.h"
  35 #include "ikev2.h"
  36 #include "buf.h"
  37 
  38 #ifdef __cplusplus
  39 extern "C" {
  40 #endif
  41 
  42 struct ikev2_sa;
  43 struct pkt;
  44 struct pkt_stack;
  45 
  46 typedef struct pkt              pkt_t;
  47 typedef struct pkt_stack        pkt_stack_t;
  48 
  49 typedef boolean_t (*pkt_finish_fn)(struct pkt *restrict, uchar_t *restrict,
  50     uintptr_t, size_t);
  51 
  52 typedef enum pkt_stack_item {
  53         PSI_NONE,
  54         PSI_PACKET,
  55         PSI_SK,
  56         PSI_SA,
  57         PSI_PAYLOAD,
  58         PSI_PROP,
  59         PSI_XFORM,
  60         PSI_XFORM_ATTR,
  61         PSI_DEL,
  62         PSI_TSP,
  63         PSI_TS
  64 } pkt_stack_item_t;
  65 
  66 struct pkt_stack {
  67         pkt_finish_fn           stk_finish;
  68         uchar_t                 *stk_ptr;
  69         size_t                  stk_count;
  70         pkt_stack_item_t        stk_type;
  71 };
  72 #define PKT_STACK_DEPTH (6)     /* maximum depth needed */
  73 
  74 typedef struct pkt_payload {
  75         uchar_t         *pp_ptr;
  76         uint16_t        pp_len;
  77         uint8_t         pp_type;
  78 } pkt_payload_t;
  79 #define PKT_PAYLOAD_NUM (16)    /* usually don't need more than this */
  80 
  81 typedef struct pkt_notify {
  82         uchar_t         *pn_ptr;
  83         uint16_t        pn_type;
  84         uint16_t        pn_len;
  85 } pkt_notify_t;
  86 #define PKT_NOTIFY_NUM  (8)
  87 
  88 #define MAX_PACKET_SIZE (8192)  /* largest datagram we accept */
  89 struct pkt {
  90                                 /* NOT refheld */
  91         struct ikev2_sa         *pkt_sa;
  92 
  93                                 /* Raw packet data */
  94         uint64_t                pkt_raw[SADB_8TO64(MAX_PACKET_SIZE)];
  95                                 /*
  96                                  * Points to one past last bit of valid data
  97                                  * in pkt_raw
  98                                  */
  99         uchar_t                 *pkt_ptr;
 100 
 101                                 /* Copy of ISAKMP header in local byte order */
 102         ike_header_t            pkt_header;
 103 
 104         pkt_payload_t           pkt_payloads[PKT_PAYLOAD_NUM];
 105         pkt_payload_t           *pkt_payload_extra;
 106         uint16_t                pkt_payload_count;
 107 
 108         pkt_notify_t            pkt_notify[PKT_NOTIFY_NUM];
 109         pkt_notify_t            *pkt_notify_extra;
 110         uint16_t                pkt_notify_count;
 111 
 112         struct pkt_stack        stack[PKT_STACK_DEPTH];
 113         uint_t                  stksize;
 114         boolean_t               pkt_stk_error;
 115 
 116         size_t                  pkt_xmit;
 117 };
 118 
 119 inline uchar_t *
 120 pkt_start(pkt_t *pkt)
 121 {
 122         return ((uchar_t *)&pkt->pkt_raw);
 123 }
 124 
 125 inline size_t
 126 pkt_len(const pkt_t *pkt)
 127 {
 128         const uchar_t *start = (const uchar_t *)&pkt->pkt_raw;
 129         size_t len = (size_t)(pkt->pkt_ptr - start);
 130 
 131         ASSERT3P(pkt->pkt_ptr, >=, start);
 132         ASSERT3U(len, <=, MAX_PACKET_SIZE);
 133         return ((size_t)(pkt->pkt_ptr - start));
 134 }
 135 
 136 inline size_t
 137 pkt_write_left(const pkt_t *pkt)
 138 {
 139         return (MAX_PACKET_SIZE - pkt_len(pkt));
 140 }
 141 
 142 inline size_t
 143 pkt_read_left(const pkt_t *pkt, const uchar_t *ptr)
 144 {
 145         const uchar_t *start = (const uchar_t *)&pkt->pkt_raw;
 146         ASSERT3P(ptr, >=, start);
 147         ASSERT3P(ptr, <=, pkt->pkt_ptr);
 148         return ((size_t)(pkt->pkt_ptr - ptr));
 149 }
 150 
 151 inline pkt_payload_t *
 152 pkt_payload(pkt_t *pkt, uint16_t idx)
 153 {
 154         ASSERT3U(idx, <, pkt->pkt_payload_count);
 155         if (idx < PKT_PAYLOAD_NUM)
 156                 return (&pkt->pkt_payloads[idx]);
 157         return (pkt->pkt_payload_extra + (idx - PKT_PAYLOAD_NUM));
 158 }
 159 
 160 inline pkt_notify_t *
 161 pkt_notify(pkt_t *pkt, uint16_t idx)
 162 {
 163         ASSERT3U(idx, <, pkt->pkt_notify_count);
 164         if (idx < PKT_NOTIFY_NUM)
 165                 return (&pkt->pkt_notify[idx]);
 166         return (pkt->pkt_notify_extra + (idx - PKT_NOTIFY_NUM));
 167 }
 168 
 169 #define PKT_APPEND_STRUCT(_pkt, _struct) do {                           \
 170         ASSERT3U(pkt_write_left(_pkt), <=, sizeof (_struct));                \
 171         (void) memcpy((_pkt)->pkt_ptr, &(_struct), sizeof (_struct));    \
 172         (_pkt)->pkt_ptr += sizeof (_struct);                         \
 173 /*CONSTCOND*/                                                           \
 174 } while (0)
 175 
 176 #define PKT_APPEND_DATA(_pkt, _ptr, _len) do {          \
 177         ASSERT3U(pkt_write_left(_pkt), <=, len);     \
 178         (void) memcpy((_pkt)->pkt_ptr, (_ptr), (_len));      \
 179         (_pkt)->pkt_ptr += (_len);                   \
 180 /*CONSTCOND*/                                           \
 181 } while (0)
 182 
 183 void pkt_hdr_ntoh(ike_header_t *restrict, const ike_header_t *restrict);
 184 void pkt_hdr_hton(ike_header_t *restrict, const ike_header_t *restrict);
 185 void put32(pkt_t *, uint32_t);
 186 void put64(pkt_t *, uint64_t);
 187 
 188 boolean_t pkt_done(pkt_t *);
 189 void pkt_init(void);
 190 void pkt_fini(void);
 191 void pkt_free(pkt_t *);
 192 
 193 boolean_t pkt_pay_shift(pkt_t *, uint8_t, size_t, ssize_t);
 194 pkt_payload_t *pkt_get_payload(pkt_t *, int, pkt_payload_t *);
 195 pkt_notify_t *pkt_get_notify(pkt_t *, int, pkt_notify_t *);
 196 
 197 #ifdef __cplusplus
 198 }
 199 #endif
 200 
 201 #endif /* _PKT_H */