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 */