27RCSIDH(dhcp_h,
"$Id: e9b71fe622406e0b165b8e1db5a5ae97853e058f $")
33#include <freeradius-devel/util/pcap.h>
34#include <freeradius-devel/util/packet.h>
35#include <freeradius-devel/protocol/dhcpv4/rfc2131.h>
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)
64#define FR_DHCP_PACKET_CODE_VALID(_code) (((_code) > 0) && ((_code) < FR_DHCP_CODE_MAX))
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
93#define DHCP_OPTION_FIELD (0)
94#define DHCP_FILE_FIELD (1)
95#define DHCP_SNAME_FIELD (2)
97#define DHCP_PACK_OPTION1(x,y) ((x) | ((y) << 8))
98#define DHCP_UNPACK_OPTION1(x) (((x) & 0xff00) >> 8)
100#ifndef INADDR_BROADCAST
101# define INADDR_BROADCAST INADDR_NONE
103#define ETH_ADDR_LEN 6
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
117#ifdef HAVE_LINUX_IF_PACKET_H
118# define ETH_HDR_SIZE 14
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"); \
126 fr_packet_free(&packet); \
139typedef enum : int8_t {
168 "%s is not a DHCPv4 attribute, it is from the \"%s\" dictionary",
172 if (!
fr_cond_assert_msg(flags,
"%s is not a DHCPv4 attribute, it has no protocol extension",
173 da->name))
return &no_flags;
239 uint8_t const *
data,
size_t data_len,
unsigned int *code);
243#ifdef HAVE_LINUX_IF_PACKET_H
247#include <linux/if_packet.h>
248int fr_dhcpv4_raw_socket_open(
struct sockaddr_ll *p_ll,
int iface_index);
250int fr_dhcpv4_raw_packet_send(
int sockfd,
struct sockaddr_ll *p_ll,
266int fr_dhcpv4_pcap_send(fr_pcap_t *pcap,
uint8_t *dst_ether_addr,
fr_packet_t *packet);
static int const char char buffer[256]
static uint8_t request[4]
fr_cmp_ret_t
Result of an ordering comparison.
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
TALLOC_CTX * tmp_ctx
for temporary things cleaned up during decoding
fr_dict_protocol_t libfreeradius_dhcpv4_dict_protocol
static bool fr_dhcpv4_flag_exists(fr_dict_attr_t const *da)
uint8_t eth_bcast[ETH_ADDR_LEN]
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.
static bool fr_dhcpv4_flag_prefix_split(fr_dict_attr_t const *da)
size_t dhcp_header_attrs_len
static bool fr_dhcpv4_flag_prefix_bits(fr_dict_attr_t const *da)
char const * dhcp_message_types[FR_DHCP_CODE_MAX]
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.
int fr_dhcpv4_global_init(void)
Resolve/cache attributes in the DHCP dictionary.
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.
ssize_t fr_dhcpv4_encode_foreign(fr_dbuff_t *dbuff, fr_pair_list_t const *list)
void * fr_dhcpv4_next_encodable(fr_dcursor_t *cursor, void *to_eval, void *uctx)
DHCPV4-specific iterator.
@ FR_DHCP_LEASE_UNASSIGNED
@ FR_DHCP_LEASE_QUERY_DONE
@ FR_DHCP_BULK_LEASE_QUERY
int fr_dhcpv4_udp_packet_send(fr_packet_t *packet)
Send DHCP packet using a connectionless UDP socket.
fr_packet_t * fr_dhcpv4_packet_alloc(uint8_t const *data, size_t data_len)
fr_dhcpv4_attr_flags_prefix_t prefix
static fr_dhcpv4_attr_flags_prefix_t fr_dhcpv4_flag_prefix(fr_dict_attr_t const *da)
void fr_dhcpv4_global_free(void)
fr_packet_t * fr_dhcpv4_udp_packet_recv(int sockfd)
Receive DHCP packet using a connectionless UDP socket.
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.
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)
bool fr_dhcpv4_is_encodable(void const *item, void const *uctx)
static bool fr_dhcpv4_flag_dns_label(fr_dict_attr_t const *da)
fr_dict_attr_t const ** dhcp_header_attrs[]
fr_cmp_ret_t fr_dhcpv4_attr_cmp(void const *a, void const *b)
fr_dhcpv4_attr_flags_prefix_t
@ DHCPV4_FLAG_PREFIX_INVALID
@ DHCPV4_FLAG_PREFIX_NONE
@ DHCPV4_FLAG_PREFIX_SPLIT
@ DHCPV4_FLAG_PREFIX_BITS
int fr_dhcpv4_packet_encode(fr_packet_t *packet, fr_pair_list_t *list)
fr_dict_attr_t const * root
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.
ssize_t fr_dhcpv4_decode_foreign(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *data, size_t data_len)
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)
int fr_dhcpv4_decode(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *data, size_t data_len, unsigned int *code)
void fr_dhcpv4_print_hex(FILE *fp, uint8_t const *packet, size_t packet_len)
Print a raw DHCP packet as hex.
@ FR_DICT_ATTR_EXT_PROTOCOL_SPECIFIC
Protocol specific extensions.
fr_dict_protocol_t const * fr_dict_protocol(fr_dict_t const *dict)
Return the protocol descriptor for the dictionary.
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Protocol-specific callbacks in libfreeradius-PROTOCOL.
static void * fr_dict_attr_ext(fr_dict_attr_t const *da, fr_dict_attr_ext_t ext)
static void * item(fr_lst_t const *lst, fr_lst_index_t idx)
static fr_internal_encode_ctx_t encode_ctx
static fr_sbuff_err_t char ** out
static fr_sbuff_err_t char size_t * len