The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
udp.c
Go to the documentation of this file.
1/*
2 * This library is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2.1 of the License, or (at your option) any later version.
6 *
7 * This library is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with this library; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: ab4ad5ed2201c5e327faa9f9374efecff886a9e4 $
19 *
20 * @file protocols/dhcpv4/udp.c
21 * @brief Send/recv DHCP packets using udp sockets.
22 *
23 * @copyright 2008,2017 The FreeRADIUS server project
24 * @copyright 2008 Alan DeKok (aland@deployingradius.com)
25 */
26#include "dhcpv4.h"
27#include "attrs.h"
28
29#include <freeradius-devel/util/pair.h>
30#include <freeradius-devel/util/proto.h>
31#include <freeradius-devel/util/udpfromto.h>
32#include <freeradius-devel/util/syserror.h>
33
34/** Send DHCP packet using a connectionless UDP socket
35 *
36 * @param packet to send
37 * @return
38 * - >= 0 if successful.
39 * - < 0 if failed.
40 */
42{
43 int ret;
44 struct sockaddr_storage dst;
45 socklen_t sizeof_dst;
46 struct sockaddr_storage src;
47 socklen_t sizeof_src;
48
49 fr_ipaddr_to_sockaddr(&src, &sizeof_src, &packet->socket.inet.src_ipaddr, packet->socket.inet.src_port);
50 fr_ipaddr_to_sockaddr(&dst, &sizeof_dst, &packet->socket.inet.dst_ipaddr, packet->socket.inet.dst_port);
51 if (packet->data_len == 0) {
52 fr_strerror_const("No data to send");
53 return -1;
54 }
55
56 errno = 0;
57
58 ret = sendfromto(packet->socket.fd, packet->data, packet->data_len, 0,
59 packet->socket.inet.ifindex,
60 (struct sockaddr *)&src, sizeof_src,
61 (struct sockaddr *)&dst, sizeof_dst);
62 if ((ret < 0) && errno) fr_strerror_printf("dhcp_send_socket: %s", fr_syserror(errno));
63
64 return ret;
65}
66
67/** Receive DHCP packet using a connectionless UDP socket
68 *
69 * @param sockfd handle.
70 * @return
71 * - pointer to fr_packet_t if successful.
72 * - NULL if failed.
73 */
75{
76 struct sockaddr_storage src;
77 struct sockaddr_storage dst;
78 socklen_t sizeof_src;
79 socklen_t sizeof_dst;
80 fr_packet_t *packet;
82 ssize_t data_len;
83 fr_ipaddr_t src_ipaddr, dst_ipaddr;
84 uint16_t src_port, dst_port;
85 int ifindex = 0;
86 fr_time_t when;
87
88 data = talloc_zero_array(NULL, uint8_t, MAX_PACKET_SIZE);
89 if (!data) {
90 fr_strerror_const("Out of memory");
91 return NULL;
92 }
93
94 sizeof_src = sizeof(src);
95 sizeof_dst = sizeof(dst);
96 data_len = recvfromto(sockfd, data, MAX_PACKET_SIZE, 0,
97 &ifindex,
98 (struct sockaddr *)&src, &sizeof_src,
99 (struct sockaddr *)&dst, &sizeof_dst, &when);
100
101 if (data_len <= 0) {
102 fr_strerror_printf("Failed reading data from DHCP socket: %s", fr_syserror(errno));
104 return NULL;
105 }
106
107 if (!fr_cond_assert(data_len <= (ssize_t)talloc_array_length(data))) {
108 talloc_free(data); /* Bounds check for tainted scalar (Coverity) */
109 return NULL;
110 }
111 sizeof_dst = sizeof(dst);
112
113 /*
114 * This should never fail...
115 */
116 if (getsockname(sockfd, (struct sockaddr *) &dst, &sizeof_dst) < 0) {
117 fr_strerror_printf("getsockname failed: %s", fr_syserror(errno));
119 return NULL;
120 }
121
122 fr_ipaddr_from_sockaddr(&dst_ipaddr, &dst_port, &dst, sizeof_dst);
123 fr_ipaddr_from_sockaddr(&src_ipaddr, &src_port, &src, sizeof_src);
124
125 if (!fr_dhcpv4_ok(data, data_len, NULL, NULL)) return NULL;
126
127 packet = fr_dhcpv4_packet_alloc(data, data_len);
128 if (!packet) return NULL;
129
130 fr_socket_addr_init_inet(&packet->socket, IPPROTO_UDP, ifindex, &src_ipaddr, src_port, &dst_ipaddr, dst_port);
131
132 talloc_steal(packet, data);
133 packet->data = data;
134 packet->socket.fd = sockfd;
135
136 packet->timestamp = when;
137 return packet;
138}
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:139
static int sockfd
Definition dhcpclient.c:56
Implementation of the DHCPv4 protocol.
fr_packet_t * fr_dhcpv4_packet_alloc(uint8_t const *data, ssize_t data_len)
Definition packet.c:395
#define MAX_PACKET_SIZE
Definition dhcpv4.h:90
int fr_ipaddr_from_sockaddr(fr_ipaddr_t *ipaddr, uint16_t *port, struct sockaddr_storage const *sa, socklen_t salen)
Convert sockaddr to our internal ip address representation.
Definition inet.c:1441
int fr_ipaddr_to_sockaddr(struct sockaddr_storage *sa, socklen_t *salen, fr_ipaddr_t const *ipaddr, uint16_t port)
Convert our internal ip address representation to a sockaddr.
Definition inet.c:1392
IPv4/6 prefix.
talloc_free(reap)
unsigned short uint16_t
long int ssize_t
unsigned char uint8_t
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:240
int fr_dhcpv4_udp_packet_send(fr_packet_t *packet)
Send DHCP packet using a connectionless UDP socket.
Definition udp.c:41
fr_packet_t * fr_dhcpv4_udp_packet_recv(int sockfd)
Receive DHCP packet using a connectionless UDP socket.
Definition udp.c:74
VQP attributes.
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition syserror.c:243
"server local" time.
Definition time.h:69
int sendfromto(int fd, void *buf, size_t len, int flags, int ifindex, struct sockaddr *from, socklen_t from_len, struct sockaddr *to, socklen_t to_len)
Send packet via a file descriptor, setting the src address and outbound interface.
Definition udpfromto.c:391
int recvfromto(int fd, void *buf, size_t len, int flags, int *ifindex, struct sockaddr *from, socklen_t *from_len, struct sockaddr *to, socklen_t *to_len, fr_time_t *when)
Read a packet from a file descriptor, retrieving additional header information.
Definition udpfromto.c:191
fr_socket_t socket
This packet was received on.
Definition packet.h:57
uint8_t * data
Packet data (body).
Definition packet.h:63
size_t data_len
Length of packet data.
Definition packet.h:64
fr_time_t timestamp
When we received the packet.
Definition packet.h:58
int fd
File descriptor if this is a live socket.
Definition socket.h:81
static fr_socket_t * fr_socket_addr_init_inet(fr_socket_t *addr, int proto, int ifindex, fr_ipaddr_t const *src_ipaddr, int src_port, fr_ipaddr_t const *dst_ipaddr, int dst_port)
Initialise a fr_socket_t for connecting to a remote host using a specific src interface,...
Definition socket.h:151
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_strerror_const(_msg)
Definition strerror.h:223
static fr_slen_t data
Definition value.h:1265