1/*
2 * Copyright (c) 2009-2013 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24/*
25 * DHCPv6Options.h
26 * - definitions and API's to handle DHCPv6 options
27 */
28
29/*
30 * Modification History
31 *
32 * September 18, 2009		Dieter Siegmund (dieter@apple.com)
33 * - created
34 */
35
36#ifndef _S_DHCPV6OPTIONS_H
37#define _S_DHCPV6OPTIONS_H
38
39#include <stdint.h>
40#include <stdbool.h>
41#include <string.h>
42#include "symbol_scope.h"
43#include "DHCPv6.h"
44
45enum {
46    kDHCPv6OPTION_CLIENTID		= 1,
47    kDHCPv6OPTION_SERVERID		= 2,
48    kDHCPv6OPTION_IA_NA			= 3,
49    kDHCPv6OPTION_IA_TA			= 4,
50    kDHCPv6OPTION_IAADDR		= 5,
51    kDHCPv6OPTION_ORO			= 6,
52    kDHCPv6OPTION_PREFERENCE		= 7,
53    kDHCPv6OPTION_ELAPSED_TIME		= 8,
54    kDHCPv6OPTION_RELAY_MSG		= 9,
55    kDHCPv6OPTION_AUTH			= 11,
56    kDHCPv6OPTION_UNICAST		= 12,
57    kDHCPv6OPTION_STATUS_CODE		= 13,
58    kDHCPv6OPTION_RAPID_COMMIT		= 14,
59    kDHCPv6OPTION_USER_CLASS		= 15,
60    kDHCPv6OPTION_VENDOR_CLASS		= 16,
61    kDHCPv6OPTION_VENDOR_OPTS		= 17,
62    kDHCPv6OPTION_INTERFACE_ID		= 18,
63    kDHCPv6OPTION_RECONF_MSG		= 19,
64    kDHCPv6OPTION_RECONF_ACCEPT		= 20,
65    kDHCPv6OPTION_DNS_SERVERS		= 23,
66    kDHCPv6OPTION_DOMAIN_LIST		= 24,
67};
68
69typedef struct {
70    uint8_t		code[2];
71    uint8_t		len[2];
72    uint8_t		data[1]; /* variable length */
73} DHCPv6Option, * DHCPv6OptionRef;
74
75#define DHCPV6_OPTION_HEADER_SIZE	offsetof(DHCPv6Option, data)
76
77INLINE int
78DHCPv6OptionGetLength(DHCPv6OptionRef option)
79{
80    return (net_uint16_get(option->len));
81}
82
83INLINE void
84DHCPv6OptionSetLength(DHCPv6OptionRef option, uint16_t len)
85{
86    net_uint16_set(option->len, len);
87    return;
88}
89
90INLINE int
91DHCPv6OptionGetCode(DHCPv6OptionRef option)
92{
93    return (net_uint16_get(option->code));
94}
95
96INLINE void
97DHCPv6OptionSetCode(DHCPv6OptionRef option, uint16_t code)
98{
99    net_uint16_set(option->code, code);
100}
101
102INLINE const uint8_t *
103DHCPv6OptionGetData(DHCPv6OptionRef option)
104{
105    return (option->data);
106}
107
108const char *
109DHCPv6OptionCodeGetName(int option_code);
110
111enum {
112    kDHCPv6OptionTypeNone = 0,
113    kDHCPv6OptionTypeUnknown = 1,
114    kDHCPv6OptionTypeDUID = 2,
115    kDHCPv6OptionTypeUInt16 = 3,
116    kDHCPv6OptionTypeUInt32 = 4,
117    kDHCPv6OptionTypeIPv6Address = 5,
118    kDHCPv6OptionTypeDNSNameList = 6,
119    kDHCPv6OptionTypeIA_NA = 7,
120    kDHCPv6OptionTypeIAADDR = 8,
121    kDHCPv6OptionTypeStatusCode = 9,
122};
123
124typedef int	 DHCPv6OptionType;
125
126DHCPv6OptionType
127DHCPv6OptionCodeGetType(int option_code);
128
129typedef struct {
130    char	str[256];
131} DHCPv6OptionErrorString, *DHCPv6OptionErrorStringRef;
132
133/**
134 ** DHCPv6OptionArea
135 **/
136typedef struct {
137    uint8_t *			buf;
138    int				size;
139    int				used;
140} DHCPv6OptionArea, * DHCPv6OptionAreaRef;
141
142void
143DHCPv6OptionAreaInit(DHCPv6OptionAreaRef oa_p, uint8_t * buf, int size);
144
145int
146DHCPv6OptionAreaGetUsedLength(DHCPv6OptionAreaRef oa_p);
147
148bool
149DHCPv6OptionAreaAddOption(DHCPv6OptionAreaRef oa_p, int option_code,
150			  int option_len, const void * option_data,
151			  DHCPv6OptionErrorStringRef err_p);
152bool
153DHCPv6OptionAreaAddOptionRequestOption(DHCPv6OptionAreaRef oa_p,
154				       const uint16_t * requested_options,
155				       int count,
156				       DHCPv6OptionErrorStringRef err_p);
157/**
158 ** DHCPv6OptionList
159 **/
160typedef struct DHCPv6OptionList * DHCPv6OptionListRef;
161
162DHCPv6OptionListRef
163DHCPv6OptionListCreate(const uint8_t * buf, int buf_size,
164		       DHCPv6OptionErrorStringRef err_p);
165
166DHCPv6OptionListRef
167DHCPv6OptionListCreateWithPacket(const DHCPv6PacketRef pkt, int pkt_len,
168				 DHCPv6OptionErrorStringRef err_p);
169
170void
171DHCPv6OptionListRelease(DHCPv6OptionListRef * dhcpol_p);
172
173const uint8_t *
174DHCPv6OptionListGetOptionDataAndLength(DHCPv6OptionListRef options,
175				       int option_code, int * ret_length,
176				       int * start_index);
177void
178DHCPv6OptionListFPrint(FILE * file, DHCPv6OptionListRef options);
179
180void
181DHCPv6OptionListPrintToString(CFMutableStringRef str,
182			      DHCPv6OptionListRef options);
183
184
185int
186DHCPv6OptionListGetCount(DHCPv6OptionListRef options);
187
188DHCPv6OptionRef
189DHCPv6OptionListGetOptionAtIndex(DHCPv6OptionListRef options, int i);
190
191/**
192 ** IA_NA option
193 **/
194typedef struct {
195    uint8_t		iaid[4];
196    uint8_t		t1[4];
197    uint8_t		t2[4];
198    uint8_t		options[1]; /* variable length */
199} DHCPv6OptionIA_NA, * DHCPv6OptionIA_NARef;
200
201#define DHCPv6OptionIA_NA_MIN_LENGTH	((int)offsetof(DHCPv6OptionIA_NA, options))
202
203INLINE uint32_t
204DHCPv6OptionIA_NAGetIAID(DHCPv6OptionIA_NARef ia_na)
205{
206    return (net_uint32_get(ia_na->iaid));
207}
208
209INLINE void
210DHCPv6OptionIA_NASetIAID(DHCPv6OptionIA_NARef ia_na, uint32_t iaid)
211{
212    net_uint32_set(ia_na->iaid, iaid);
213    return;
214}
215
216INLINE uint32_t
217DHCPv6OptionIA_NAGetT1(DHCPv6OptionIA_NARef ia_na)
218{
219    return (net_uint32_get(ia_na->t1));
220}
221
222INLINE void
223DHCPv6OptionIA_NASetT1(DHCPv6OptionIA_NARef ia_na, uint32_t t1)
224{
225    net_uint32_set(ia_na->t1, t1);
226    return;
227}
228
229INLINE uint32_t
230DHCPv6OptionIA_NAGetT2(DHCPv6OptionIA_NARef ia_na)
231{
232    return (net_uint32_get(ia_na->t2));
233}
234
235INLINE void
236DHCPv6OptionIA_NASetT2(DHCPv6OptionIA_NARef ia_na, uint32_t t2)
237{
238    net_uint32_set(ia_na->t2, t2);
239    return;
240}
241
242/**
243 ** IAADDR option
244 **/
245typedef struct {
246    uint8_t		address[16];
247    uint8_t		preferred_lifetime[4];
248    uint8_t		valid_lifetime[4];
249    uint8_t		options[1]; /* variable length */
250} DHCPv6OptionIAADDR, * DHCPv6OptionIAADDRRef;
251
252#define DHCPv6OptionIAADDR_MIN_LENGTH	((int)offsetof(DHCPv6OptionIAADDR, options))
253
254INLINE const uint8_t *
255DHCPv6OptionIAADDRGetAddress(DHCPv6OptionIAADDRRef ia_addr)
256{
257   return ((const uint8_t *)ia_addr->address);
258}
259
260INLINE void
261DHCPv6OptionIAADDRSetAddress(DHCPv6OptionIAADDRRef ia_addr,
262			     const void * addr_p)
263{
264    bcopy(addr_p, ia_addr->address, sizeof(struct in6_addr));
265    return;
266}
267
268INLINE uint32_t
269DHCPv6OptionIAADDRGetPreferredLifetime(DHCPv6OptionIAADDRRef ia_addr)
270{
271    return (net_uint32_get(ia_addr->preferred_lifetime));
272}
273
274INLINE void
275DHCPv6OptionIAADDRSetPreferredLifetime(DHCPv6OptionIAADDRRef ia_addr,
276				       uint32_t preferred_lifetime)
277{
278    net_uint32_set(ia_addr->preferred_lifetime, preferred_lifetime);
279    return;
280}
281
282INLINE uint32_t
283DHCPv6OptionIAADDRGetValidLifetime(DHCPv6OptionIAADDRRef ia_addr)
284{
285    return (net_uint32_get(ia_addr->valid_lifetime));
286}
287
288INLINE void
289DHCPv6OptionIAADDRSetValidLifetime(DHCPv6OptionIAADDRRef ia_addr,
290				   uint32_t valid_lifetime)
291{
292    net_uint32_set(ia_addr->valid_lifetime, valid_lifetime);
293    return;
294}
295
296void
297DHCPv6OptionIAADDRPrintToString(CFMutableStringRef str,
298				DHCPv6OptionIAADDRRef ia_addr,
299				int ia_addr_len);
300
301/**
302 ** Status Code option
303 **/
304typedef struct {
305    uint8_t		code[2];
306    uint8_t		message[1]; /* variable length */
307} DHCPv6OptionSTATUS_CODE, * DHCPv6OptionSTATUS_CODERef;
308
309#define DHCPv6OptionSTATUS_CODE_MIN_LENGTH	((int)offsetof(DHCPv6OptionSTATUS_CODE, message))
310
311enum {
312    kDHCPv6StatusCodeSuccess		= 0,
313    kDHCPv6StatusCodeFailure		= 1,
314    kDHCPv6StatusCodeNoAddrsAvail	= 2,
315    kDHCPv6StatusCodeNoBinding		= 3,
316    kDHCPv6StatusCodeNotOnLink		= 4,
317    kDHCPv6StatusCodeUseMulticast	= 5
318};
319typedef int DHCPv6StatusCode;
320
321const char *
322DHCPv6StatusCodeGetName(int option_code);
323
324INLINE uint16_t
325DHCPv6OptionSTATUS_CODEGetCode(DHCPv6OptionSTATUS_CODERef status_p)
326{
327    return (net_uint16_get(status_p->code));
328}
329
330INLINE void
331DHCPv6OptionSTATUS_CODESetCode(DHCPv6OptionSTATUS_CODERef status_p,
332			       uint16_t code)
333{
334    net_uint16_set(status_p->code, code);
335    return;
336}
337
338void
339DHCPv6OptionSTATUS_CODEFPrint(FILE * f, DHCPv6OptionSTATUS_CODERef status_p,
340			      int status_len);
341
342/**
343 ** PREFERENCE option
344 **/
345typedef struct {
346    uint8_t		value;
347} DHCPv6OptionPREFERENCE, * DHCPv6OptionPREFERENCERef;
348
349#define DHCPv6OptionPREFERENCE_MIN_LENGTH	1
350#define kDHCPv6OptionPREFERENCEMinValue		0
351#define kDHCPv6OptionPREFERENCEMaxValue		255
352
353#endif /* _S_DHCPV6OPTIONS_H */
354