The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
Loading...
Searching...
No Matches
dhcpv4.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: e9b71fe622406e0b165b8e1db5a5ae97853e058f $
20 *
21 * @file protocols/dhcpv4/dhcpv4.h
22 * @brief Implementation of the DHCPv4 protocol.
23 *
24 * @copyright 2008 The FreeRADIUS server project
25 * @copyright 2008 Alan DeKok (aland@deployingradius.com)
26 */
27RCSIDH(dhcp_h, "$Id: e9b71fe622406e0b165b8e1db5a5ae97853e058f $")
28
29#ifdef __cplusplus
30extern "C" {
31#endif
32
33#include <freeradius-devel/util/pcap.h>
34#include <freeradius-devel/util/packet.h>
35#include <freeradius-devel/protocol/dhcpv4/rfc2131.h>
36
37#define DHCP_CHADDR_LEN (16)
38#define DHCP_SNAME_LEN (64)
39#define DHCP_FILE_LEN (128)
40#define DHCP_VEND_LEN (308)
41#define DHCP_OPTION_MAGIC_NUMBER (0x63825363U)
42
63
64#define FR_DHCP_PACKET_CODE_VALID(_code) (((_code) > 0) && ((_code) < FR_DHCP_CODE_MAX))
65
84
85/*
86 * Some clients silently ignore responses less than 300 bytes.
87 */
88#define MIN_PACKET_SIZE (244)
89#define DEFAULT_PACKET_SIZE (300)
90#define MAX_PACKET_SIZE (1500 - 40)
91#define DHCPV4_MAX_ATTRIBUTES 255
92
93#define DHCP_OPTION_FIELD (0)
94#define DHCP_FILE_FIELD (1)
95#define DHCP_SNAME_FIELD (2)
96
97#define DHCP_PACK_OPTION1(x,y) ((x) | ((y) << 8))
98#define DHCP_UNPACK_OPTION1(x) (((x) & 0xff00) >> 8)
99
100#ifndef INADDR_BROADCAST
101# define INADDR_BROADCAST INADDR_NONE
102#endif
103#define ETH_ADDR_LEN 6
104
105#if defined(HAVE_LIBPCAP) || defined(HAVE_LINUX_IF_PACKET_H)
106# define ETH_TYPE_IP 0x0800
107# define IP_HDR_SIZE 20
108# define UDP_HDR_SIZE 8
109#endif
110
111extern fr_dict_attr_t const **dhcp_header_attrs[];
112extern size_t dhcp_header_attrs_len;
113extern char const *dhcp_message_types[FR_DHCP_CODE_MAX];
114extern int dhcp_header_sizes[];
116
117#ifdef HAVE_LINUX_IF_PACKET_H
118# define ETH_HDR_SIZE 14
119/* Discard raw packets which we are not interested in. Allow to trace why we discard. */
120# define DISCARD_RP(...) do { \
121 if (fr_debug_lvl > 2) { \
122 fprintf(stdout, "dhcpclient: discarding received packet: "); \
123 fprintf(stdout, ## __VA_ARGS__); \
124 fprintf(stdout, "\n"); \
125 } \
126 fr_packet_free(&packet); \
127 return NULL; \
128} while (0)
129#endif
130
131/** Used as the decoder ctx
132 *
133 */
134typedef struct {
136 TALLOC_CTX *tmp_ctx; //!< for temporary things cleaned up during decoding
138
145
151
153
154/** Return DHCPv4-specific flags for a given attribute
155 *
156 * Assert in debug builds when the attribute belongs to another dictionary, as
157 * the flags of one protocol say nothing about an attribute of another.
158 *
159 * If the attribute does not carry the protocol-specific extension, then assert.
160 * Other builds log the error and return zeroed flags instead of NULL.
161 */
163{
164 static fr_dhcpv4_attr_flags_t const no_flags = {};
165 fr_dhcpv4_attr_flags_t const *flags;
166
168 "%s is not a DHCPv4 attribute, it is from the \"%s\" dictionary",
169 da->name, fr_dict_root(da->dict)->name);
170
172 if (!fr_cond_assert_msg(flags, "%s is not a DHCPv4 attribute, it has no protocol extension",
173 da->name)) return &no_flags;
174
175 return flags;
176}
177
178static inline bool fr_dhcpv4_flag_dns_label(fr_dict_attr_t const *da)
179{
181}
182
183static inline bool fr_dhcpv4_flag_exists(fr_dict_attr_t const *da)
184{
185 return fr_dhcpv4_attr_flags(da)->exists;
186}
187
192
193static inline bool fr_dhcpv4_flag_prefix_bits(fr_dict_attr_t const *da)
194{
196}
197
198static inline bool fr_dhcpv4_flag_prefix_split(fr_dict_attr_t const *da)
199{
201}
202
203/*
204 * base.c
205 */
206fr_cmp_ret_t fr_dhcpv4_attr_cmp(void const *a, void const *b);
207
208bool fr_dhcpv4_ok(uint8_t const *data, size_t data_len, uint8_t *message_type, uint32_t *xid);
209fr_packet_t *fr_dhcpv4_packet_alloc(uint8_t const *data, size_t data_len);
210bool fr_dhcpv4_is_encodable(void const *item, void const *uctx);
211void *fr_dhcpv4_next_encodable(fr_dcursor_t *cursor, void *to_eval, void *uctx);
215int fr_dhcpv4_global_init(void);
216void fr_dhcpv4_global_free(void);
217void fr_dhcpv4_print_hex(FILE *fp, uint8_t const *packet, size_t packet_len);
218
219/*
220 * decode.c
221 */
223 uint8_t const *data, size_t len, void *decode_ctx) CC_HINT(nonnull);
224
226 uint8_t const *data, size_t data_len) CC_HINT(nonnull);
227
228/*
229 * encode.c
230 */
232
233/*
234 * packet.c
235 */
236uint8_t const *fr_dhcpv4_packet_get_option(dhcp_packet_t const *packet, size_t packet_size, fr_dict_attr_t const *da);
237
238int fr_dhcpv4_decode(TALLOC_CTX *ctx, fr_pair_list_t *out,
239 uint8_t const *data, size_t data_len, unsigned int *code);
240
242
243#ifdef HAVE_LINUX_IF_PACKET_H
244/*
245 * raw.c
246 */
247#include <linux/if_packet.h>
248int fr_dhcpv4_raw_socket_open(struct sockaddr_ll *p_ll, int iface_index);
249
250int fr_dhcpv4_raw_packet_send(int sockfd, struct sockaddr_ll *p_ll,
251 fr_packet_t *packet, fr_pair_list_t *list);
252
253fr_packet_t *fr_dhcpv4_raw_packet_recv(int sockfd, struct sockaddr_ll *p_ll,
255#endif
256
257/*
258 * pcap.c
259 */
260#ifdef HAVE_LIBPCAP
261/*
262 * Use fr_pcap_init and fr_pcap_open to create/open handles.
263 */
264fr_packet_t *fr_dhcpv4_pcap_recv(fr_pcap_t *pcap);
265
266int fr_dhcpv4_pcap_send(fr_pcap_t *pcap, uint8_t *dst_ether_addr, fr_packet_t *packet);
267#endif
268
269/*
270 * udp.c
271 */
274
275#ifdef __cplusplus
276}
277#endif
static int const char char buffer[256]
Definition acutest.h:641
int const char * file
Definition acutest.h:855
static uint8_t request[4]
#define RCSIDH(h, id)
Definition build.h:604
fr_cmp_ret_t
Result of an ordering comparison.
Definition build.h:113
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
Definition debug.h:248
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:194
static int sockfd
Definition dhcpclient.c:55
TALLOC_CTX * tmp_ctx
for temporary things cleaned up during decoding
Definition dhcpv4.h:136
fr_dict_protocol_t libfreeradius_dhcpv4_dict_protocol
Definition base.c:798
static bool fr_dhcpv4_flag_exists(fr_dict_attr_t const *da)
Definition dhcpv4.h:183
uint8_t eth_bcast[ETH_ADDR_LEN]
Definition base.c:167
#define DHCP_CHADDR_LEN
Definition dhcpv4.h:37
bool fr_dhcpv4_ok(uint8_t const *data, size_t data_len, uint8_t *message_type, uint32_t *xid)
Check received DHCP request is valid and build fr_packet_t structure if it is.
Definition base.c:248
static bool fr_dhcpv4_flag_prefix_split(fr_dict_attr_t const *da)
Definition dhcpv4.h:198
size_t dhcp_header_attrs_len
Definition base.c:127
static bool fr_dhcpv4_flag_prefix_bits(fr_dict_attr_t const *da)
Definition dhcpv4.h:193
char const * dhcp_message_types[FR_DHCP_CODE_MAX]
Definition base.c:129
uint32_t yiaddr
Definition dhcpv4.h:75
uint8_t const * fr_dhcpv4_packet_get_option(dhcp_packet_t const *packet, size_t packet_size, fr_dict_attr_t const *da)
Retrieve a DHCP option from a raw packet buffer.
Definition packet.c:37
int fr_dhcpv4_global_init(void)
Resolve/cache attributes in the DHCP dictionary.
Definition base.c:611
static fr_dhcpv4_attr_flags_t const * fr_dhcpv4_attr_flags(fr_dict_attr_t const *da)
Return DHCPv4-specific flags for a given attribute.
Definition dhcpv4.h:162
ssize_t fr_dhcpv4_encode_foreign(fr_dbuff_t *dbuff, fr_pair_list_t const *list)
Definition encode.c:786
void * fr_dhcpv4_next_encodable(fr_dcursor_t *cursor, void *to_eval, void *uctx)
DHCPV4-specific iterator.
Definition base.c:332
fr_dhcpv4_packet_code_t
Definition dhcpv4.h:43
@ FR_DHCP_REQUEST
Definition dhcpv4.h:47
@ FR_DHCP_LEASE_UNASSIGNED
Definition dhcpv4.h:55
@ FR_DHCP_DECLINE
Definition dhcpv4.h:48
@ FR_DHCP_OFFER
Definition dhcpv4.h:46
@ FR_DHCP_DISCOVER
Definition dhcpv4.h:45
@ FR_DHCP_CODE_MAX
Definition dhcpv4.h:60
@ FR_DHCP_LEASE_QUERY_DONE
Definition dhcpv4.h:59
@ FR_DHCP_LEASE_ACTIVE
Definition dhcpv4.h:57
@ FR_DHCP_LEASE_UNKNOWN
Definition dhcpv4.h:56
@ FR_DHCP_BULK_LEASE_QUERY
Definition dhcpv4.h:58
@ FR_DHCP_LEASE_QUERY
Definition dhcpv4.h:54
@ FR_DHCP_NAK
Definition dhcpv4.h:50
@ FR_DHCP_RELEASE
Definition dhcpv4.h:51
@ FR_DHCP_FORCE_RENEW
Definition dhcpv4.h:53
@ FR_DHCP_DO_NOT_RESPOND
Definition dhcpv4.h:61
@ FR_DHCP_INFORM
Definition dhcpv4.h:52
@ FR_DHCP_ACK
Definition dhcpv4.h:49
@ FR_DHCP_INVALID
Definition dhcpv4.h:44
int fr_dhcpv4_udp_packet_send(fr_packet_t *packet)
Send DHCP packet using a connectionless UDP socket.
Definition udp.c:41
#define DHCP_SNAME_LEN
Definition dhcpv4.h:38
fr_packet_t * fr_dhcpv4_packet_alloc(uint8_t const *data, size_t data_len)
Definition packet.c:418
#define DHCP_FILE_LEN
Definition dhcpv4.h:39
fr_dhcpv4_attr_flags_prefix_t prefix
Definition dhcpv4.h:149
uint32_t giaddr
Definition dhcpv4.h:77
#define DHCP_VEND_LEN
Definition dhcpv4.h:40
static fr_dhcpv4_attr_flags_prefix_t fr_dhcpv4_flag_prefix(fr_dict_attr_t const *da)
Definition dhcpv4.h:188
#define ETH_ADDR_LEN
Definition dhcpv4.h:103
uint16_t secs
Definition dhcpv4.h:72
uint32_t option_format
Definition dhcpv4.h:81
uint8_t htype
Definition dhcpv4.h:68
void fr_dhcpv4_global_free(void)
Definition base.c:635
uint8_t opcode
Definition dhcpv4.h:67
uint8_t hlen
Definition dhcpv4.h:69
fr_packet_t * fr_dhcpv4_udp_packet_recv(int sockfd)
Receive DHCP packet using a connectionless UDP socket.
Definition udp.c:74
ssize_t fr_dhcpv4_decode_option(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *data, size_t len, void *decode_ctx)
Decode DHCP option.
Definition decode.c:587
ssize_t fr_dhcpv4_encode(uint8_t *buffer, size_t buflen, dhcp_packet_t *original, fr_dhcpv4_packet_code_t code, uint32_t xid, fr_pair_list_t *vps)
Definition base.c:358
uint8_t hops
Definition dhcpv4.h:70
int dhcp_header_sizes[]
Definition base.c:150
uint16_t flags
Definition dhcpv4.h:73
bool fr_dhcpv4_is_encodable(void const *item, void const *uctx)
static bool fr_dhcpv4_flag_dns_label(fr_dict_attr_t const *da)
Definition dhcpv4.h:178
fr_dict_attr_t const ** dhcp_header_attrs[]
Definition base.c:111
fr_cmp_ret_t fr_dhcpv4_attr_cmp(void const *a, void const *b)
Definition base.c:204
fr_dhcpv4_attr_flags_prefix_t
Definition dhcpv4.h:139
@ DHCPV4_FLAG_PREFIX_INVALID
Definition dhcpv4.h:140
@ DHCPV4_FLAG_PREFIX_NONE
Definition dhcpv4.h:141
@ DHCPV4_FLAG_PREFIX_SPLIT
Definition dhcpv4.h:143
@ DHCPV4_FLAG_PREFIX_BITS
Definition dhcpv4.h:142
int fr_dhcpv4_packet_encode(fr_packet_t *packet, fr_pair_list_t *list)
Definition packet.c:390
fr_dict_attr_t const * root
Definition dhcpv4.h:135
uint32_t xid
Definition dhcpv4.h:71
uint32_t siaddr
Definition dhcpv4.h:76
ssize_t fr_dhcpv4_encode_option(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, void *encode_ctx)
Encode a DHCP option and any sub-options.
Definition encode.c:737
uint32_t ciaddr
Definition dhcpv4.h:74
ssize_t fr_dhcpv4_decode_foreign(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *data, size_t data_len)
Definition decode.c:698
ssize_t fr_dhcpv4_encode_dbuff(fr_dbuff_t *dbuff, dhcp_packet_t *original, fr_dhcpv4_packet_code_t code, uint32_t xid, fr_pair_list_t *vps)
Definition base.c:363
int fr_dhcpv4_decode(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *data, size_t data_len, unsigned int *code)
Definition packet.c:119
void fr_dhcpv4_print_hex(FILE *fp, uint8_t const *packet, size_t packet_len)
Print a raw DHCP packet as hex.
Definition base.c:682
Used as the decoder ctx.
Definition dhcpv4.h:134
@ FR_DICT_ATTR_EXT_PROTOCOL_SPECIFIC
Protocol specific extensions.
Definition dict.h:190
fr_dict_protocol_t const * fr_dict_protocol(fr_dict_t const *dict)
Return the protocol descriptor for the dictionary.
Definition dict_util.c:5389
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2717
Protocol-specific callbacks in libfreeradius-PROTOCOL.
Definition dict.h:479
static void * fr_dict_attr_ext(fr_dict_attr_t const *da, fr_dict_attr_ext_t ext)
Definition dict_ext.h:122
static void * item(fr_lst_t const *lst, fr_lst_index_t idx)
Definition lst.c:121
unsigned short uint16_t
unsigned int uint32_t
long int ssize_t
unsigned char uint8_t
static fr_internal_encode_ctx_t encode_ctx
static fr_slen_t data
Definition value.h:1366
static fr_sbuff_err_t char ** out
Definition value.h:1061
static fr_sbuff_err_t char size_t * len
Definition value.h:1061
int nonnull(2, 5))