All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
proto_arp.c
Go to the documentation of this file.
1 /*
2  * arp.c ARP processing.
3  *
4  * Version: $Id: 4a709e8786640581b419a3d6a84ce320fe78a9d7 $
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright (C) 2013 Network RADIUS SARL <info@networkradius.com>
21  */
22 
23 #include <freeradius-devel/radiusd.h>
24 #include <freeradius-devel/protocol.h>
25 #include <freeradius-devel/modules.h>
26 #include <freeradius-devel/process.h>
27 #include <freeradius-devel/rad_assert.h>
28 #include <freeradius-devel/pcap.h>
29 #include <net/if_arp.h>
30 
31 typedef struct arp_socket_t {
33  uint64_t counter;
35 } arp_socket_t;
36 
37 /*
38  * ARP for ethernet && IPv4.
39  */
40 typedef struct arp_over_ether {
41  uint16_t htype; //!< Format of hardware address.
42  uint16_t ptype; //!< Format of protocol address.
43  uint8_t hlen; //!< Length of hardware address.
44  uint8_t plen; //!< Length of protocol address.
45  uint8_t op; //!< 1 - Request, 2 - Reply.
46  uint8_t sha[ETHER_ADDR_LEN]; //!< sender hardware address.
47  uint8_t spa[4]; //!< Sender protocol address.
48  uint8_t tha[ETHER_ADDR_LEN]; //!< Target hardware address.
49  uint8_t tpa[4]; //!< Target protocol address.
51 
52 static int arp_process(REQUEST *request)
53 {
54  RADIUS_PACKET *packet = request->packet;
55  struct arphdr const *arp;
56  uint8_t const *p;
57 
58  arp = (struct arphdr *) request->packet->data;
59 
60  p = (const uint8_t *) arp;
61  if (p > (packet->data + packet->data_len)) return 0;
62 
63 #if 0
64  {
65  size_t len, i;
66  len = packet->data_len;
67  len -= (p - packet->data);
68 
69  for (i = 0; i < len; i++) {
70  if ((i & 0x0f) == 0) printf("%04zx: ", i);
71  printf("%02x ", p[i]);
72  if ((i & 0x0f) == 0x0f) printf("\r\n");
73  fflush(stdout);
74  }
75  printf("\n");
76  fflush(stdout);
77  }
78 #endif
79 
80  /*
81  *
82  */
83  process_post_auth(0, request);
84 
85  return 1;
86 }
87 
88 
89 /*
90  * Check if an incoming request is "ok"
91  *
92  * It takes packets, not requests. It sees if the packet looks
93  * OK. If so, it does a number of sanity checks on it.
94  */
95 static int arp_socket_recv(rad_listen_t *listener)
96 {
97  int ret;
98  arp_socket_t *sock = listener->data;
99  pcap_t *handle = sock->lsock.pcap->handle;
100 
101  const uint8_t *data;
102  struct pcap_pkthdr *header;
103  ssize_t link_len;
104 
105  arp_over_ether_t const *arp;
106  RADIUS_PACKET *packet;
107 
108  ret = pcap_next_ex(handle, &header, &data);
109  if (ret == 0) {
110  DEBUG("No packet retrieved from pcap.");
111  return 0; /* no packet */
112  }
113 
114  if (ret < 0) {
115  ERROR("Error requesting next packet, got (%i): %s", ret, pcap_geterr(handle));
116  return 0;
117  }
118 
119  link_len = fr_link_layer_offset(data, header->caplen, sock->lsock.pcap->link_layer);
120  if (link_len < 0) {
121  ERROR("Failed determining link layer header offset: %s", fr_strerror());
122  return 0;
123  }
124 
125  /*
126  * Silently ignore it if it's too small to be ARP.
127  *
128  * This can happen when pcap gets overloaded and starts truncating packets.
129  */
130  if (header->caplen < (link_len + sizeof(*arp))) {
131  ERROR("Packet too small, we require at least %zu bytes, got %i bytes",
132  link_len + sizeof(*arp), header->caplen);
133  return 0;
134  }
135 
136  data += link_len;
137  arp = (arp_over_ether_t const *) data;
138 
139  if (ntohs(arp->htype) != ARPHRD_ETHER) return 0;
140 
141  if (ntohs(arp->ptype) != 0x0800) return 0;
142 
143  if (arp->hlen != ETHER_ADDR_LEN) return 0; /* FIXME: malformed error */
144 
145  if (arp->plen != 4) return 0; /* FIXME: malformed packet error */
146 
147  packet = talloc_zero(NULL, RADIUS_PACKET);
148  if (!packet) return 0;
149 
150  packet->dst_port = 1; /* so it's not a "fake" request */
151  packet->data_len = header->caplen - link_len;
152  packet->data = talloc_memdup(packet, arp, packet->data_len);
153  talloc_set_type(packet->data, uint8_t);
154 
155  DEBUG("ARP received on interface %s", sock->lsock.interface);
156 
157  if (!request_receive(NULL, listener, packet, &sock->client, arp_process)) {
158  fr_radius_free(&packet);
159  return 0;
160  }
161 
162  return 1;
163 }
164 
165 static int arp_socket_send(UNUSED rad_listen_t *listener, UNUSED REQUEST *request)
166 {
167  return 0;
168 }
169 
170 
171 static int arp_socket_encode(UNUSED rad_listen_t *listener, UNUSED REQUEST *request)
172 {
173  return 0;
174 }
175 
176 
177 typedef struct arp_decode_t {
178  char const *name;
179  size_t len;
180 } arp_decode_t;
181 
182 static const arp_decode_t header_names[] = {
183  { "ARP-Hardware-Format", 2 },
184  { "ARP-Protocol-Format", 2 },
185  { "ARP-Hardware-Address-Length", 1 },
186  { "ARP-Protocol-Address-Length", 1 },
187  { "ARP-Operation", 2 },
188  { "ARP-Sender-Hardware-Address", 6 },
189  { "ARP-Sender-Protocol-Address", 4 },
190  { "ARP-Target-Hardware-Address", 6 },
191  { "ARP-Target-Protocol-Address", 4 },
192 
193  { NULL, 0 }
194 };
195 
196 static int arp_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
197 {
198  int i;
199  arp_over_ether_t const *arp;
200  uint8_t const *p;
201 
202  arp = (arp_over_ether_t const *) request->packet->data;
203  /*
204  * arp_socket_recv() takes care of validating it's really
205  * our kind of ARP.
206  */
207  for (i = 0, p = (uint8_t const *) arp; header_names[i].name != NULL; p += header_names[i].len, i++) {
208  ssize_t len;
209  fr_dict_attr_t const *da;
210  VALUE_PAIR *vp = NULL;;
211  vp_cursor_t cursor;
212  fr_radius_ctx_t decoder_ctx = {
213  .packet = request->packet,
214  .original = request->packet
215  };
216 
217  da = fr_dict_attr_by_name(NULL, header_names[i].name);
218  if (!da) return 0;
219 
220  fr_cursor_init(&cursor, &vp);
221  len = fr_radius_decode_pair_value(request->packet, &cursor, da, p, header_names[i].len,
222  header_names[i].len, &decoder_ctx);
223  if (len <= 0) {
224  RDEBUG("Failed decoding %s: %s",
225  header_names[i].name, fr_strerror());
226  return 0;
227  }
228 
229  debug_pair(vp);
230  fr_pair_add(&request->packet->vps, vp);
231  }
232 
233  return 0;
234 }
235 
236 
237 static void arp_socket_free(rad_listen_t *this)
238 {
239  arp_socket_t *sock = this->data;
240 
241  talloc_free(sock);
242  this->data = NULL;
243 }
244 
245 /** Build PCAP filter string to pass to libpcap
246  * Will be called by init_pcap.
247  *
248  * @param this listen section (not used)
249  * @return PCAP filter string
250  */
251 static const char * arp_pcap_filter_builder(UNUSED rad_listen_t *this)
252 {
253  return "arp";
254 }
255 
257 {
258  int rcode;
259  arp_socket_t *sock = this->data;
260  RADCLIENT *client;
261  CONF_PAIR *cp = NULL;
262 
263  sock->lsock.pcap_filter_builder = arp_pcap_filter_builder;
264  sock->lsock.pcap_type = PCAP_INTERFACE_IN;
265 
266  this->nodup = true; /* don't check for duplicates */
267 
268  /* Add ipaddress to conf section as it is not required by ARP config */
269  cp = cf_pair_alloc(cs, "ipv4addr", "0.0.0.0", T_OP_SET, T_BARE_WORD, T_BARE_WORD);
270  cf_pair_add(cs, cp);
271 
272  rcode = common_socket_parse(cs, this);
273  if (rcode != 0) return rcode;
274 
275  if (!sock->lsock.interface) {
276  cf_log_err_cs(cs, "'interface' is required for arp");
277  return -1;
278  }
279 
280  /*
281  * The server core is still RADIUS, and needs a client.
282  * So we fake one here.
283  */
284  client = &sock->client;
285  memset(client, 0, sizeof(*client));
286  client->ipaddr.af = AF_INET;
287  client->ipaddr.ipaddr.ip4addr.s_addr = INADDR_NONE;
288  client->ipaddr.prefix = 0;
289  client->longname = client->shortname = sock->lsock.interface;
290  client->secret = client->shortname;
291  client->nas_type = talloc_typed_strdup(sock, "none");
292 
293  return 0;
294 }
295 
296 static int arp_socket_print(const rad_listen_t *this, char *buffer, size_t bufsize)
297 {
298  arp_socket_t *sock = this->data;
299 
300  snprintf(buffer, bufsize, "arp interface %s", sock->lsock.interface);
301 
302  return 1;
303 }
304 
305 extern fr_protocol_t proto_arp;
306 fr_protocol_t proto_arp = {
308  .name = "arp",
309  .inst_size = sizeof(arp_socket_t),
310  .transports = 0,
311  .tls = false,
312  .parse = arp_socket_parse,
313  .open = common_socket_open,
314  .free = arp_socket_free,
315  .recv = arp_socket_recv,
316  .send = arp_socket_send,
317  .print = arp_socket_print,
318  .debug = common_packet_debug,
319  .encode = arp_socket_encode,
320  .decode = arp_socket_decode
321 };
uint8_t spa[4]
Sender protocol address.
Definition: proto_arp.c:47
char const * interface
Definition: listen.h:124
struct arp_decode_t arp_decode_t
char const * nas_type
Type of client (arbitrary).
Definition: clients.h:47
Dictionary attribute.
Definition: dict.h:77
int common_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
Definition: listen.c:1274
void common_packet_debug(REQUEST *request, RADIUS_PACKET *packet, bool received)
Definition: listen.c:1153
static int arp_socket_send(UNUSED rad_listen_t *listener, UNUSED REQUEST *request)
Definition: proto_arp.c:165
uint8_t prefix
Prefix length - Between 0-32 for IPv4 and 0-128 for IPv6.
Definition: inet.h:47
static char const * name
fr_protocol_t proto_arp
Definition: proto_arp.c:306
rlm_rcode_t process_post_auth(int type, REQUEST *request)
Definition: modules.c:2178
uint8_t op
1 - Request, 2 - Reply.
Definition: proto_arp.c:45
static const arp_decode_t header_names[]
Definition: proto_arp.c:182
static int arp_socket_print(const rad_listen_t *this, char *buffer, size_t bufsize)
Definition: proto_arp.c:296
#define debug_pair(vp)
Definition: pair.h:184
ssize_t fr_link_layer_offset(uint8_t const *data, size_t len, int link_layer)
Returns the length of the link layer header.
Definition: net.c:95
void cf_pair_add(CONF_SECTION *parent, CONF_PAIR *cp)
Add a configuration pair to a section.
Definition: conffile.c:612
#define UNUSED
Definition: libradius.h:134
#define RLM_MODULE_INIT
Definition: modules.h:86
VALUE_PAIR * vps
Result of decoding the packet into VALUE_PAIRs.
Definition: libradius.h:162
char const * secret
Secret PSK.
Definition: clients.h:43
VALUE_PAIR * fr_cursor_init(vp_cursor_t *cursor, VALUE_PAIR *const *node)
Setup a cursor to iterate over attribute pairs.
Definition: cursor.c:60
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition: snprintf.c:686
static int arp_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
Definition: proto_arp.c:256
struct arp_over_ether arp_over_ether_t
uint8_t * data
Packet data (body).
Definition: libradius.h:160
static void arp_socket_free(rad_listen_t *this)
Definition: proto_arp.c:237
uint16_t dst_port
DST Port of packet.
Definition: libradius.h:152
Abstraction to allow iterating over different configurations of VALUE_PAIRs.
Definition: pair.h:144
int af
Address family.
Definition: inet.h:42
ssize_t fr_radius_decode_pair_value(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *parent, uint8_t const *data, size_t const attr_len, size_t const packet_len, void *decoder_ctx)
Create any kind of VP from the attribute contents.
uint8_t plen
Length of protocol address.
Definition: proto_arp.c:44
#define DEBUG(fmt,...)
Definition: log.h:175
void fr_pair_add(VALUE_PAIR **head, VALUE_PAIR *vp)
Add a VP to the end of the list.
Definition: pair.c:659
union fr_ipaddr_t::@1 ipaddr
fr_ipaddr_t ipaddr
IPv4/IPv6 address of the host.
Definition: clients.h:36
int common_socket_open(CONF_SECTION *cs, rad_listen_t *this)
Definition: listen.c:1599
Stores an attribute, a value and various bits of other data.
Definition: pair.h:112
size_t len
Definition: proto_arp.c:179
void void cf_log_err_cs(CONF_SECTION const *cs, char const *fmt,...) CC_HINT(format(printf
uint8_t hlen
Length of hardware address.
Definition: proto_arp.c:43
Configuration AVP similar to a VALUE_PAIR.
Definition: conffile.c:82
Definition: token.h:45
char const * fr_strerror(void)
Get the last library error.
Definition: log.c:212
RADCLIENT client
Definition: proto_arp.c:34
uint8_t sha[ETHER_ADDR_LEN]
sender hardware address.
Definition: proto_arp.c:46
uint16_t ptype
Format of protocol address.
Definition: proto_arp.c:42
int request_receive(TALLOC_CTX *ctx, rad_listen_t *listener, RADIUS_PACKET *packet, RADCLIENT *client, RAD_REQUEST_FUNP fun)
Definition: process.c:1523
CONF_PAIR * cf_pair_alloc(CONF_SECTION *parent, char const *attr, char const *value, FR_TOKEN op, FR_TOKEN lhs_type, FR_TOKEN rhs_type)
Allocate a CONF_PAIR.
Definition: conffile.c:546
struct arp_socket_t arp_socket_t
Describes a host allowed to send packets to the server.
Definition: clients.h:35
uint8_t data[]
Definition: eap_pwd.h:625
uint8_t tha[ETHER_ADDR_LEN]
Target hardware address.
Definition: proto_arp.c:48
#define ETHER_ADDR_LEN
Definition: net.h:53
void fr_radius_free(RADIUS_PACKET **)
Free a RADIUS_PACKET.
Definition: radius.c:1727
static int arp_socket_encode(UNUSED rad_listen_t *listener, UNUSED REQUEST *request)
Definition: proto_arp.c:171
size_t data_len
Length of packet data.
Definition: libradius.h:161
RADIUS_PACKET * packet
Incoming request.
Definition: radiusd.h:221
static const char * arp_pcap_filter_builder(UNUSED rad_listen_t *this)
Build PCAP filter string to pass to libpcap Will be called by init_pcap.
Definition: proto_arp.c:251
uint16_t htype
Format of hardware address.
Definition: proto_arp.c:41
listen_socket_t lsock
Definition: proto_arp.c:32
static int arp_socket_recv(rad_listen_t *listener)
Definition: proto_arp.c:95
char const * longname
Client identifier.
Definition: clients.h:40
uint64_t magic
Used to validate loaded library.
Definition: protocol.h:40
RADIUS_PACKET const * packet
Definition: libradius.h:267
uint8_t tpa[4]
Target protocol address.
Definition: proto_arp.c:49
void * data
Definition: listen.h:103
uint64_t counter
Definition: proto_arp.c:33
char * talloc_typed_strdup(void const *t, char const *p)
Call talloc strdup, setting the type on the new chunk correctly.
Definition: missing.c:588
#define RDEBUG(fmt,...)
Definition: log.h:243
#define ERROR(fmt,...)
Definition: log.h:145
char const * name
Definition: proto_arp.c:178
static int arp_process(REQUEST *request)
Definition: proto_arp.c:52
char const * shortname
Client nickname.
Definition: clients.h:41
static int arp_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
Definition: proto_arp.c:196
fr_dict_attr_t const * fr_dict_attr_by_name(fr_dict_t *dict, char const *attr)
Locate a fr_dict_attr_t by its name.
Definition: dict.c:3493