29#include <freeradius-devel/util/net.h> 
   30#include <freeradius-devel/util/pair.h> 
   31#include <freeradius-devel/util/proto.h> 
   32#include <freeradius-devel/util/syserror.h> 
   33#include <freeradius-devel/util/udpfromto.h> 
   37#ifdef HAVE_SYS_SOCKET_H 
   39#ifdef HAVE_SYS_TYPES_H 
   42#ifdef HAVE_LINUX_IF_PACKET_H 
   43#  include <linux/if_ether.h> 
   46#include <net/if_arp.h> 
   48#ifdef HAVE_LINUX_IF_PACKET_H 
   58int fr_dhcpv4_raw_socket_open(
struct sockaddr_ll *link_layer, 
int ifindex)
 
   66        fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
 
   73        memset(link_layer, 0, 
sizeof(
struct sockaddr_ll));
 
   75        link_layer->sll_family = AF_PACKET;
 
   76        link_layer->sll_protocol = htons(ETH_P_ALL);
 
   77        link_layer->sll_ifindex = ifindex;
 
   78        link_layer->sll_hatype = ARPHRD_ETHER;
 
   79        link_layer->sll_pkttype = PACKET_OTHERHOST;
 
   80        link_layer->sll_halen = 6;
 
   82        if (bind(fd, (
struct sockaddr *)link_layer, 
sizeof(
struct sockaddr_ll)) < 0) {
 
  101int fr_dhcpv4_raw_packet_send(
int sockfd, 
struct sockaddr_ll *link_layer,
 
  104        uint8_t                 dhcp_packet[1518] = { 0 };
 
  127        ip_hdr->
ip_len = htons(IP_HDR_SIZE +  UDP_HDR_SIZE + packet->
data_len);
 
  135        ip_hdr->ip_src.s_addr = packet->
socket.inet.src_ipaddr.addr.v4.s_addr;
 
  138        ip_hdr->
ip_dst.s_addr = packet->
socket.inet.dst_ipaddr.addr.v4.s_addr;
 
  143        udp_hdr->
src = htons(packet->
socket.inet.src_port);
 
  144        udp_hdr->
dst = htons(packet->
socket.inet.dst_port);
 
  146        udp_hdr->
len = htons(l4_len);
 
  157                                            packet->
socket.inet.src_ipaddr.addr.v4, packet->
socket.inet.dst_ipaddr.addr.v4);
 
  159        return sendto(
sockfd, dhcp_packet, (ETH_HDR_SIZE + IP_HDR_SIZE + UDP_HDR_SIZE + packet->
data_len),
 
  160                      0, (
struct sockaddr *) link_layer, 
sizeof(
struct sockaddr_ll));
 
  169fr_packet_t *fr_dhcpv4_raw_packet_recv(
int sockfd, 
struct sockaddr_ll *link_layer,
 
  186        size_t                  dhcp_data_len;
 
  206        sock_len = 
sizeof(
struct sockaddr_ll);
 
  207        data_len = recvfrom(
sockfd, raw_packet, 
MAX_PACKET_SIZE, 0, (
struct sockaddr *)link_layer, &sock_len);
 
  209        data_offset = ETH_HDR_SIZE + IP_HDR_SIZE + UDP_HDR_SIZE; 
 
  211        if (data_len <= data_offset) DISCARD_RP(
"Payload (%d) smaller than required for layers 2+3+4", (
int)data_len);
 
  219        if (ntohs(eth_hdr->
ether_type) != ETH_TYPE_IP) DISCARD_RP(
"Ethernet type (%d) != IP",
 
  231                DISCARD_RP(
"Ethernet destination (%pV) is not broadcast and doesn't match request source (%pV)",
 
  238        ip_hdr = (
ip_header_t *)(raw_packet + ETH_HDR_SIZE);
 
  243        if (ip_hdr->
ip_p != IPPROTO_UDP) DISCARD_RP(
"IP protocol (%d) != UDP", ip_hdr->
ip_p);
 
  254        udp_hdr = (
udp_header_t *)(raw_packet + ETH_HDR_SIZE + IP_HDR_SIZE);
 
  259        udp_src_port = ntohs(udp_hdr->
src);
 
  260        udp_dst_port = ntohs(udp_hdr->
dst);
 
  265        dhcp_data_len = data_len - data_offset;
 
  267        if (dhcp_data_len < 
MIN_PACKET_SIZE) DISCARD_RP(
"DHCP packet is too small (%zu < %i)",
 
  269        if (dhcp_data_len > 
MAX_PACKET_SIZE) DISCARD_RP(
"DHCP packet is too large (%zu > %i)",
 
  272        dhcp_hdr = (
dhcp_packet_t *)(raw_packet + ETH_HDR_SIZE + IP_HDR_SIZE + UDP_HDR_SIZE);
 
  274        if (dhcp_hdr->
htype != 1) DISCARD_RP(
"DHCP hardware type (%d) != Ethernet (1)", dhcp_hdr->
htype);
 
  275        if (dhcp_hdr->
hlen != 6) DISCARD_RP(
"DHCP hardware address length (%d) != 6", dhcp_hdr->
hlen);
 
  285        xid = ntohl(dhcp_hdr->
xid);
 
  286        if (xid != (
uint32_t)request->
id) DISCARD_RP(
"DHCP transaction ID (0x%04x) != xid from request (0x%04x)",
 
  298        packet->data_len = dhcp_data_len;
 
  299        dhcp_data = talloc_memdup(packet, raw_packet + data_offset, dhcp_data_len);
 
  301        TALLOC_FREE(raw_packet);
 
  312        if ((code[1] < 1) || (code[2] == 0) || (code[2] > 8)) {
 
  318        packet->
code = code[2];
 
  320        packet->
socket.inet.src_port = udp_src_port;
 
  321        packet->
socket.inet.dst_port = udp_dst_port;
 
  323        packet->
socket.inet.src_ipaddr.
af = AF_INET;
 
  324        packet->
socket.inet.src_ipaddr.addr.v4.s_addr = ip_hdr->ip_src.s_addr;
 
  325        packet->
socket.inet.dst_ipaddr.
af = AF_INET;
 
  326        packet->
socket.inet.dst_ipaddr.addr.v4.s_addr = ip_hdr->
ip_dst.s_addr;
 
static fr_dict_attr_t const  * attr_dhcp_message_type
 
Implementation of the DHCPv4 protocol.
 
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.
 
#define DHCP_OPTION_MAGIC_NUMBER
 
uint8_t dst_addr[ETHER_ADDR_LEN]
 
uint8_t src_addr[ETHER_ADDR_LEN]
 
fr_packet_t * fr_packet_alloc(TALLOC_CTX *ctx, bool new_vector)
Allocate a new fr_packet_t.
 
void fr_packet_free(fr_packet_t **packet_p)
Free a fr_packet_t.
 
@ FR_TYPE_ETHERNET
48 Bit Mac-Address.
 
uint16_t fr_udp_checksum(uint8_t const *data, uint16_t len, uint16_t checksum, struct in_addr const src_addr, struct in_addr const dst_addr)
Calculate UDP checksum.
 
uint16_t fr_ip_header_checksum(uint8_t const *data, uint8_t ihl)
Calculate IP header checksum.
 
uint8_t ip_tos
Type of service.
 
uint16_t ip_len
Total length.
 
uint16_t ip_id
identification.
 
uint8_t ip_ttl
Time To Live.
 
uint16_t ip_off
Fragment offset field.
 
uint16_t dst
Destination port.
 
uint16_t checksum
UDP checksum.
 
struct in_addr ip_src ip_dst
Src and Dst address.
 
uint8_t ip_vhl
Header length, version.
 
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
 
HIDDEN fr_dict_attr_t const  * attr_dhcp_client_hardware_address
 
uint8_t eth_bcast[ETH_ADDR_LEN]
 
Stores an attribute, a value and various bits of other data.
 
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
 
unsigned int code
Packet code (type).
 
fr_socket_t socket
This packet was received on.
 
int id
Packet ID (used to link requests/responses).
 
uint8_t * data
Packet data (body).
 
size_t data_len
Length of packet data.
 
int af
AF_INET, AF_INET6, or AF_UNIX.
 
int fd
File descriptor if this is a live socket.
 
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
 
#define fr_strerror_const(_msg)
 
#define fr_box_ether(_val)