The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
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: 24d4195921871fb197d1b759eb818b23c30c6f5a $
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  */
27 RCSIDH(dhcp_h, "$Id: 24d4195921871fb197d1b759eb818b23c30c6f5a $")
28 
29 #ifdef __cplusplus
30 extern "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 (0x63825363)
42 
43 typedef enum {
63 
64 #define FR_DHCP_PACKET_CODE_VALID(_code) (((_code) > 0) && ((_code) < FR_DHCP_CODE_MAX))
65 
66 /** subtype values for DHCPv4 and DHCPv6
67  *
68  */
69 enum {
70  FLAG_ENCODE_NONE = 0, //!< no particular encoding for DHCPv6 strings
71  FLAG_ENCODE_DNS_LABEL, //!< encode as DNS label
72  FLAG_ENCODE_SPLIT_PREFIX, //!< encode IPv4 prefixes as Policy-Filter, split into IP/mask
73  FLAG_ENCODE_BITS_PREFIX, //!< encode IPv4 prefixes as prefix bits, followed by IP.
74  FLAG_ENCODE_BOOL_EXISTS, //!< bool as existence checks
75 };
76 
77 #define da_is_dns_label(_da) (!(_da)->flags.extra && ((_da)->flags.subtype == FLAG_ENCODE_DNS_LABEL))
78 #define da_is_split_prefix(_da) (!(_da)->flags.extra && ((_da)->flags.subtype == FLAG_ENCODE_SPLIT_PREFIX))
79 #define da_is_bits_prefix(_da) (!(_da)->flags.extra && ((_da)->flags.subtype == FLAG_ENCODE_BITS_PREFIX))
80 #define da_is_bool_exists(_da) (!(_da)->flags.extra && ((_da)->flags.subtype == FLAG_ENCODE_BOOL_EXISTS))
81 
82 typedef struct {
87  uint32_t xid; /* 4 */
88  uint16_t secs; /* 8 */
90  uint32_t ciaddr; /* 12 */
91  uint32_t yiaddr; /* 16 */
92  uint32_t siaddr; /* 20 */
93  uint32_t giaddr; /* 24 */
94  uint8_t chaddr[DHCP_CHADDR_LEN]; /* 28 */
95  uint8_t sname[DHCP_SNAME_LEN]; /* 44 */
100 
101 /*
102  * Some clients silently ignore responses less than 300 bytes.
103  */
104 #define MIN_PACKET_SIZE (244)
105 #define DEFAULT_PACKET_SIZE (300)
106 #define MAX_PACKET_SIZE (1500 - 40)
107 #define DHCPV4_MAX_ATTRIBUTES 255
108 
109 #define DHCP_OPTION_FIELD (0)
110 #define DHCP_FILE_FIELD (1)
111 #define DHCP_SNAME_FIELD (2)
112 
113 #define FR_DHCP_OPTION_82 (82)
114 #define DHCP_PACK_OPTION1(x,y) ((x) | ((y) << 8))
115 #define DHCP_UNPACK_OPTION1(x) (((x) & 0xff00) >> 8)
116 
117 #ifndef INADDR_BROADCAST
118 # define INADDR_BROADCAST INADDR_NONE
119 #endif
120 #define ETH_ADDR_LEN 6
121 
122 #if defined(HAVE_LIBPCAP) || defined(HAVE_LINUX_IF_PACKET_H)
123 # define ETH_TYPE_IP 0x0800
124 # define IP_HDR_SIZE 20
125 # define UDP_HDR_SIZE 8
126 #endif
127 
128 extern fr_dict_attr_t const **dhcp_header_attrs[];
129 extern size_t dhcp_header_attrs_len;
130 extern char const *dhcp_message_types[];
131 extern int dhcp_header_sizes[];
133 extern HIDDEN fr_dict_attr_t const *dhcp_option_82;
134 
135 #ifdef HAVE_LINUX_IF_PACKET_H
136 # define ETH_HDR_SIZE 14
137 /* Discard raw packets which we are not interested in. Allow to trace why we discard. */
138 # define DISCARD_RP(...) { \
139  if (fr_debug_lvl > 2) { \
140  fprintf(stdout, "dhcpclient: discarding received packet: "); \
141  fprintf(stdout, ## __VA_ARGS__); \
142  fprintf(stdout, "\n"); \
143  } \
144  fr_packet_free(&packet); \
145  return NULL; \
146 }
147 #endif
148 
149 /** Used as the decoder ctx
150  *
151  */
152 typedef struct {
154  TALLOC_CTX *tmp_ctx; //!< for temporary things cleaned up during decoding
156 
157 /*
158  * base.c
159  */
160 int8_t fr_dhcpv4_attr_cmp(void const *a, void const *b);
161 
162 bool fr_dhcpv4_ok(uint8_t const *data, ssize_t data_len, uint8_t *message_type, uint32_t *xid);
164 bool fr_dhcpv4_is_encodable(void const *item, void const *uctx);
165 void *fr_dhcpv4_next_encodable(fr_dlist_head_t *list, void *to_eval, void *uctx);
166 ssize_t fr_dhcpv4_encode(uint8_t *buffer, size_t buflen, dhcp_packet_t *original, int code, uint32_t xid, fr_pair_list_t *vps);
167 ssize_t fr_dhcpv4_encode_dbuff(fr_dbuff_t *dbuff, dhcp_packet_t *original, int code, uint32_t xid, fr_pair_list_t *vps);
169 int fr_dhcpv4_global_init(void);
170 void fr_dhcpv4_global_free(void);
171 void fr_dhcpv4_print_hex(FILE *fp, uint8_t const *packet, size_t packet_len);
172 
173 /*
174  * decode.c
175  */
177  uint8_t const *data, size_t len, void *decode_ctx) CC_HINT(nonnull);
178 
180  uint8_t const *data, size_t data_len) CC_HINT(nonnull);
181 
182 /*
183  * encode.c
184  */
186 
187 /*
188  * packet.c
189  */
190 uint8_t const *fr_dhcpv4_packet_get_option(dhcp_packet_t const *packet, size_t packet_size, fr_dict_attr_t const *da);
191 
192 int fr_dhcpv4_decode(TALLOC_CTX *ctx, fr_pair_list_t *out,
193  uint8_t const *data, size_t data_len, unsigned int *code);
194 
196 
197 #ifdef HAVE_LINUX_IF_PACKET_H
198 /*
199  * raw.c
200  */
201 #include <linux/if_packet.h>
202 int fr_dhcpv4_raw_socket_open(struct sockaddr_ll *p_ll, int iface_index);
203 
204 int fr_dhcpv4_raw_packet_send(int sockfd, struct sockaddr_ll *p_ll,
205  fr_packet_t *packet, fr_pair_list_t *list);
206 
207 fr_packet_t *fr_dhcpv4_raw_packet_recv(int sockfd, struct sockaddr_ll *p_ll,
208  fr_packet_t *request, fr_pair_list_t *list);
209 #endif
210 
211 /*
212  * pcap.c
213  */
214 #ifdef HAVE_LIBPCAP
215 /*
216  * Use fr_pcap_init and fr_pcap_open to create/open handles.
217  */
218 fr_packet_t *fr_dhcpv4_pcap_recv(fr_pcap_t *pcap);
219 
220 int fr_dhcpv4_pcap_send(fr_pcap_t *pcap, uint8_t *dst_ether_addr, fr_packet_t *packet);
221 #endif
222 
223 /*
224  * udp.c
225  */
228 
229 #ifdef __cplusplus
230 }
231 #endif
static int const char char buffer[256]
Definition: acutest.h:574
int const char * file
Definition: acutest.h:702
#define RCSIDH(h, id)
Definition: build.h:445
#define HIDDEN
Definition: build.h:312
static int sockfd
Definition: dhcpclient.c:56
TALLOC_CTX * tmp_ctx
for temporary things cleaned up during decoding
Definition: dhcpv4.h:154
char const * dhcp_message_types[]
Definition: base.c:124
uint8_t eth_bcast[ETH_ADDR_LEN]
Definition: base.c:162
@ FLAG_ENCODE_NONE
no particular encoding for DHCPv6 strings
Definition: dhcpv4.h:70
@ FLAG_ENCODE_SPLIT_PREFIX
encode IPv4 prefixes as Policy-Filter, split into IP/mask
Definition: dhcpv4.h:72
@ FLAG_ENCODE_BOOL_EXISTS
bool as existence checks
Definition: dhcpv4.h:74
@ FLAG_ENCODE_DNS_LABEL
encode as DNS label
Definition: dhcpv4.h:71
@ FLAG_ENCODE_BITS_PREFIX
encode IPv4 prefixes as prefix bits, followed by IP.
Definition: dhcpv4.h:73
#define DHCP_CHADDR_LEN
Definition: dhcpv4.h:37
bool fr_dhcpv4_ok(uint8_t const *data, ssize_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:215
size_t dhcp_header_attrs_len
Definition: base.c:122
uint32_t yiaddr
Definition: dhcpv4.h:91
int fr_dhcpv4_global_init(void)
Resolve/cache attributes in the DHCP dictionary.
Definition: base.c:557
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_encode_foreign(fr_dbuff_t *dbuff, fr_pair_list_t const *list)
Definition: encode.c:759
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
#define DHCP_FILE_LEN
Definition: dhcpv4.h:39
int8_t fr_dhcpv4_attr_cmp(void const *a, void const *b)
Definition: base.c:166
uint32_t giaddr
Definition: dhcpv4.h:93
#define DHCP_VEND_LEN
Definition: dhcpv4.h:40
#define ETH_ADDR_LEN
Definition: dhcpv4.h:120
ssize_t fr_dhcpv4_encode_dbuff(fr_dbuff_t *dbuff, dhcp_packet_t *original, int code, uint32_t xid, fr_pair_list_t *vps)
Definition: base.c:316
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
uint16_t secs
Definition: dhcpv4.h:88
uint32_t option_format
Definition: dhcpv4.h:97
uint8_t htype
Definition: dhcpv4.h:84
void fr_dhcpv4_global_free(void)
Definition: base.c:601
fr_packet_t * fr_dhcpv4_packet_alloc(uint8_t const *data, ssize_t data_len)
Definition: packet.c:401
HIDDEN fr_dict_attr_t const * dhcp_option_82
Definition: base.c:164
uint8_t opcode
Definition: dhcpv4.h:83
uint8_t hlen
Definition: dhcpv4.h:85
void * fr_dhcpv4_next_encodable(fr_dlist_head_t *list, void *to_eval, void *uctx)
DHCPV4-specific iterator.
Definition: base.c:294
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:538
uint8_t hops
Definition: dhcpv4.h:86
int dhcp_header_sizes[]
Definition: base.c:145
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
uint16_t flags
Definition: dhcpv4.h:89
ssize_t fr_dhcpv4_encode(uint8_t *buffer, size_t buflen, dhcp_packet_t *original, int code, uint32_t xid, fr_pair_list_t *vps)
Definition: base.c:311
bool fr_dhcpv4_is_encodable(void const *item, void const *uctx)
fr_dict_attr_t const ** dhcp_header_attrs[]
Definition: base.c:106
int fr_dhcpv4_packet_encode(fr_packet_t *packet, fr_pair_list_t *list)
Definition: packet.c:373
fr_dict_attr_t const * root
Definition: dhcpv4.h:153
uint32_t xid
Definition: dhcpv4.h:87
uint32_t siaddr
Definition: dhcpv4.h:92
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:711
uint32_t ciaddr
Definition: dhcpv4.h:90
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:640
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:100
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:645
Used as the decoder ctx.
Definition: dhcpv4.h:152
Head of a doubly linked list.
Definition: dlist.h:51
static void * item(fr_lst_t const *lst, fr_lst_index_t idx)
Definition: lst.c:122
unsigned short uint16_t
Definition: merged_model.c:31
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:1259
int nonnull(2, 5))
static size_t char ** out
Definition: value.h:984