The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
dhcpv6.h
Go to the documentation of this file.
1 #pragma once
2 /*
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
16  */
17 
18 /**
19  * $Id: c8eb3e6c090bc48d899e1e508608ef5b7f73d408 $
20  *
21  * @file protocols/dhcpv6/dhcpv6.h
22  * @brief Implementation of the DHCPv6 protocol.
23  *
24  * @author Arran Cudbard-Bell (a.cudbardb@freeradius.org)
25  *
26  * @copyright 2018 The FreeRADIUS server project
27  * @copyright 2018 NetworkRADIUS SARL (legal@networkradius.com)
28  */
29 RCSIDH(dhcpv6_h, "$Id: c8eb3e6c090bc48d899e1e508608ef5b7f73d408 $")
30 
31 #include <freeradius-devel/util/dict.h>
32 
33 #include <freeradius-devel/protocol/dhcpv6/dictionary.h>
34 
35 #define DHCPV6_MSG_TYPE_LEN 1U
36 
37 #define DHCPV6_TRANSACTION_ID_LEN 3U
38 
39 #define DHCPV6_HOP_COUNT_LEN 1U
40 #define DHCPV6_LINK_ADDRESS_LEN 16U
41 #define DHCPV6_PEER_ADDRESS_LEN 16U
42 
43 #define DHCPV6_HDR_LEN (DHCPV6_MSG_TYPE_LEN + DHCPV6_TRANSACTION_ID_LEN)
44 #define DHCPV6_RELAY_HDR_LEN (DHCPV6_MSG_TYPE_LEN + DHCPV6_HOP_COUNT_LEN + DHCPV6_LINK_ADDRESS_LEN + DHCPV6_PEER_ADDRESS_LEN)
45 #define DHCPV6_OPT_HDR_LEN (sizeof(uint16_t) * 2)
46 
47 #define DHCPV6_GET_OPTION_NUM(_x) fr_nbo_to_uint16(_x)
48 #define DHCPV6_GET_OPTION_LEN(_x) fr_nbo_to_uint16((_x) + 2)
49 
50 #define DHCPV6_MAX_RELAY_NESTING 10
51 
52 #define DHCPV6_MAX_ATTRIBUTES 1024
53 
54 /*
55  * Defined addresses from RFC 8415 Section 7.1
56  */
57 #define IN6ADDR_ALL_DHCP_RELAY_AGENTS_AND_SERVERS "FF02::1:2"
58 #define IN6ADDR_ALL_DHCP_RELAY_AGENTS_AND_SERVERS_INIT {{{ 0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,1,2}}}
59 #define IN6ADDR_ALL_DHCP_SERVERS "FF05::1:3"
60 #define IN6ADDR_ALL_DHCP_SERVERS_INIT {{{ 0xff,0x05,0,0,0,0,0,0,0,0,0,0,0,0,1,3}}}
61 
62 /*
63  * Copied from src/include/protocols/dhcpv6/freeradius.internal.h
64  * and edited.
65  */
66 typedef enum {
106 
107 #define FR_DHCPV6_PACKET_CODE_VALID(_code) (((_code) > 0) && ((_code) < FR_DHCPV6_CODE_MAX))
108 
109 extern char const *fr_dhcpv6_packet_names[FR_DHCPV6_CODE_MAX];
110 
111 /** subtype values for DHCPv4 and DHCPv6
112  *
113  */
114 typedef struct CC_HINT(__packed__) {
116  uint8_t transaction_id[3];
118 
119 /*
120  * DHCPv6 defines dates to start from Jan 1, 2000. Which is
121  * exactly this number of seconds off of the standard Unix time
122  * stamps.
123  */
124 #define DHCPV6_DATE_OFFSET (946684800)
125 
126 typedef struct {
127  fr_dict_attr_t const *root; //!< Root attribute of the dictionary.
128  uint8_t const *original; //!< original packet
129  size_t original_length; //!< length of the original packet
131 
132 typedef struct {
133  TALLOC_CTX *tmp_ctx; //!< for temporary things cleaned up during decoding
134  uint32_t transaction_id; //!< previous transaction ID
135  uint8_t *duid; //!< the expected DUID, in wire format
136  size_t duid_len; //!< length of the expected DUID
138 
139 typedef struct {
140  bool dns_label;
143 
145 {
147 }
148 
149 #define fr_dhcpv6_flag_dns_label(_da) (fr_dhcpv6_attr_flags(_da)->dns_label)
150 #define fr_dhcpv6_flag_partial_dns_label(_da) (fr_dhcpv6_attr_flags(_da)->partial_dns_label)
151 
152 static inline bool fr_dhcpv6_flag_any_dns_label(fr_dict_attr_t const *da)
153 {
154  fr_dhcpv6_attr_flags_t const *flags = fr_dhcpv6_attr_flags(da);
155 
156  return flags->dns_label || flags->partial_dns_label;
157 }
158 
159 /*
160  * base.c
161  */
162 uint8_t const *fr_dhcpv6_option_find(uint8_t const *start, uint8_t const *end, unsigned int option);
163 
164 bool fr_dhcpv6_ok(uint8_t const *packet, size_t packet_len,
165  uint32_t max_attributes);
166 
167 bool fr_dhcpv6_verify(uint8_t const *packet, size_t packet_len, fr_dhcpv6_decode_ctx_t const *packet_ctx,
168  bool from_server);
169 
170 ssize_t fr_dhcpv6_encode(fr_dbuff_t *dbuff, uint8_t const *original, size_t length,
171  int msg_type, fr_pair_list_t *vps);
172 
173 ssize_t fr_dhcpv6_decode(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *packet, size_t packet_len);
174 
175 void fr_dhcpv6_print_hex(FILE *fp, uint8_t const *packet, size_t packet_len);
176 
177 int fr_dhcpv6_global_init(void);
178 
179 void fr_dhcpv6_global_free(void);
180 
181 /*
182  * encode.c
183  */
185 
187 
188 /*
189  * decode.c
190  */
192  uint8_t const *data, size_t data_len, void *decode_ctx);
193 
195  uint8_t const *data, size_t data_len);
#define RCSIDH(h, id)
Definition: build.h:482
uint32_t transaction_id
previous transaction ID
Definition: dhcpv6.h:134
fr_dhcpv6_packet_code_t
Definition: dhcpv6.h:66
@ FR_DHCPV6_RELEASE
Definition: dhcpv6.h:75
@ FR_DHCPV6_DECLINE
Definition: dhcpv6.h:76
@ FR_DHCPV6_BIND_REPLY
Definition: dhcpv6.h:92
@ FR_DHCPV6_ADVERTISE
Definition: dhcpv6.h:69
@ FR_DHCPV6_ACTIVE_LEASE_QUERY
Definition: dhcpv6.h:89
@ FR_DHCPV6_DO_NOT_RESPOND
Definition: dhcpv6.h:104
@ FR_DHCPV6_REBIND
Definition: dhcpv6.h:73
@ FR_DHCPV6_POOL_REQUEST
Definition: dhcpv6.h:93
@ FR_DHCPV6_BIND_UPDATE
Definition: dhcpv6.h:91
@ FR_DHCPV6_REPLY
Definition: dhcpv6.h:74
@ FR_DHCPV6_LEASE_QUERY_DATA
Definition: dhcpv6.h:84
@ FR_DHCPV6_START_TLS
Definition: dhcpv6.h:90
@ FR_DHCPV6_POOL_RESPONSE
Definition: dhcpv6.h:94
@ FR_DHCPV6_INVALID
Definition: dhcpv6.h:67
@ FR_DHCPV6_CONTACT
Definition: dhcpv6.h:102
@ FR_DHCPV6_CONFIRM
Definition: dhcpv6.h:71
@ FR_DHCPV6_RECONFIGURE_REPLY
Definition: dhcpv6.h:86
@ FR_DHCPV6_DHCPV4_RESPONSE
Definition: dhcpv6.h:88
@ FR_DHCPV6_LEASE_QUERY
Definition: dhcpv6.h:81
@ FR_DHCPV6_RECONFIGURE_REQUEST
Definition: dhcpv6.h:85
@ FR_DHCPV6_UPDATE_REQUEST_ALL
Definition: dhcpv6.h:96
@ FR_DHCPV6_SOLICIT
Definition: dhcpv6.h:68
@ FR_DHCPV6_CONNECT_REPLY
Definition: dhcpv6.h:99
@ FR_DHCPV6_DISCONNECT
Definition: dhcpv6.h:100
@ FR_DHCPV6_UPDATE_DONE
Definition: dhcpv6.h:97
@ FR_DHCPV6_RENEW
Definition: dhcpv6.h:72
@ FR_DHCPV6_INFORMATION_REQUEST
Definition: dhcpv6.h:78
@ FR_DHCPV6_STATE
Definition: dhcpv6.h:101
@ FR_DHCPV6_LEASE_QUERY_DONE
Definition: dhcpv6.h:83
@ FR_DHCPV6_REQUEST
Definition: dhcpv6.h:70
@ FR_DHCPV6_DHCPV4_QUERY
Definition: dhcpv6.h:87
@ FR_DHCPV6_CODE_MAX
Definition: dhcpv6.h:103
@ FR_DHCPV6_CONNECT
Definition: dhcpv6.h:98
@ FR_DHCPV6_RECONFIGURE
Definition: dhcpv6.h:77
@ FR_DHCPV6_RELAY_FORWARD
Definition: dhcpv6.h:79
@ FR_DHCPV6_RELAY_REPLY
Definition: dhcpv6.h:80
@ FR_DHCPV6_LEASE_QUERY_REPLY
Definition: dhcpv6.h:82
@ FR_DHCPV6_UPDATE_REQUEST
Definition: dhcpv6.h:95
fr_dict_attr_t const * root
Root attribute of the dictionary.
Definition: dhcpv6.h:127
uint8_t const * fr_dhcpv6_option_find(uint8_t const *start, uint8_t const *end, unsigned int option)
Definition: base.c:246
void fr_dhcpv6_global_free(void)
Definition: base.c:941
ssize_t fr_dhcpv6_decode_option(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *data, size_t data_len, void *decode_ctx)
Create a "normal" fr_pair_t from the given data.
Definition: decode.c:421
bool fr_dhcpv6_ok(uint8_t const *packet, size_t packet_len, uint32_t max_attributes)
See if the data pointed to by PTR is a valid DHCPv6 packet.
Definition: base.c:230
uint8_t * duid
the expected DUID, in wire format
Definition: dhcpv6.h:135
int fr_dhcpv6_global_init(void)
Definition: base.c:899
static fr_dhcpv6_attr_flags_t const * fr_dhcpv6_attr_flags(fr_dict_attr_t const *da)
Definition: dhcpv6.h:144
ssize_t fr_dhcpv6_decode(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *packet, size_t packet_len)
Decode a DHCPv6 packet.
Definition: base.c:581
char const * fr_dhcpv6_packet_names[FR_DHCPV6_CODE_MAX]
Definition: base.c:71
static bool fr_dhcpv6_flag_any_dns_label(fr_dict_attr_t const *da)
Definition: dhcpv6.h:152
uint8_t const * original
original packet
Definition: dhcpv6.h:128
ssize_t fr_dhcpv6_encode_option(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, void *encode_ctx)
Encode a DHCPv6 option and any sub-options.
Definition: encode.c:670
size_t original_length
length of the original packet
Definition: dhcpv6.h:129
bool fr_dhcpv6_verify(uint8_t const *packet, size_t packet_len, fr_dhcpv6_decode_ctx_t const *packet_ctx, bool from_server)
Verify the packet under some various circumstances.
Definition: base.c:547
void fr_dhcpv6_print_hex(FILE *fp, uint8_t const *packet, size_t packet_len)
Print a raw DHCP packet as hex.
Definition: base.c:894
size_t duid_len
length of the expected DUID
Definition: dhcpv6.h:136
TALLOC_CTX * tmp_ctx
for temporary things cleaned up during decoding
Definition: dhcpv6.h:133
ssize_t fr_dhcpv6_decode_foreign(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *data, size_t data_len)
Definition: decode.c:436
ssize_t fr_dhcpv6_encode_foreign(fr_dbuff_t *dbuff, fr_pair_list_t const *list)
Definition: encode.c:721
uint8_t code
Definition: dhcpv6.h:115
ssize_t fr_dhcpv6_encode(fr_dbuff_t *dbuff, uint8_t const *original, size_t length, int msg_type, fr_pair_list_t *vps)
Encode a DHCPv6 packet.
Definition: base.c:720
subtype values for DHCPv4 and DHCPv6
Definition: dhcpv6.h:114
@ FR_DICT_ATTR_EXT_PROTOCOL_SPECIFIC
Protocol specific extensions.
Definition: dict.h:170
static void * fr_dict_attr_ext(fr_dict_attr_t const *da, fr_dict_attr_ext_t ext)
Definition: dict_ext.h:140
unsigned int uint32_t
Definition: merged_model.c:33
long int ssize_t
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
static fr_internal_encode_ctx_t encode_ctx
static fr_slen_t data
Definition: value.h:1265
static size_t char ** out
Definition: value.h:997