3 Linux packet filter code, contributed by Brian Murrel at Interlinx
4 Support Services in Vancouver, B.C. */
7 * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
8 * Copyright (c) 1996-2003 by Internet Software Consortium
10 * This Source Code Form is subject to the terms of the Mozilla Public
11 * License, v. 2.0. If a copy of the MPL was not distributed with this
12 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
14 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
15 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
17 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
20 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 * Internet Systems Consortium, Inc.
24 * Newmarket, NH 03857 USA
26 * https://www.isc.org/
30 #if defined (USE_LPF_SEND) || defined (USE_LPF_RECEIVE)
34 #include <asm/types.h>
35 #include <linux/filter.h>
36 #include <linux/if_ether.h>
37 #include <linux/if_packet.h>
38 #include <netinet/in_systm.h>
39 #include "includes/netinet/ip.h"
40 #include "includes/netinet/udp.h"
41 #include "includes/netinet/if_ether.h"
44 #if defined (USE_LPF_RECEIVE) || defined (USE_LPF_HWADDR)
45 #include <sys/ioctl.h>
46 #include <sys/socket.h>
50 #if defined (USE_LPF_SEND) || defined (USE_LPF_RECEIVE)
51 /* Reinitializes the specified interface after an address change. This
52 is not required for packet-filter APIs. */
55 void if_reinitialize_send (info
)
56 struct interface_info
*info
;
61 #ifdef USE_LPF_RECEIVE
62 void if_reinitialize_receive (info
)
63 struct interface_info
*info
;
68 /* Called by get_interface_list for each interface that's discovered.
69 Opens a packet filter for each interface and adds it to the select
72 int if_register_lpf (info
)
73 struct interface_info
*info
;
77 struct sockaddr_ll ll
;
78 struct sockaddr common
;
82 /* Make an LPF socket. */
83 if ((sock
= socket(PF_PACKET
, SOCK_RAW
,
84 htons((short)ETH_P_ALL
))) < 0) {
85 if (errno
== ENOPROTOOPT
|| errno
== EPROTONOSUPPORT
||
86 errno
== ESOCKTNOSUPPORT
|| errno
== EPFNOSUPPORT
||
87 errno
== EAFNOSUPPORT
|| errno
== EINVAL
) {
88 log_error ("socket: %m - make sure");
89 log_error ("CONFIG_PACKET (Packet socket) %s",
91 log_error ("(Socket Filtering) are enabled %s",
93 log_fatal ("configuration!");
95 log_fatal ("Open a socket for LPF: %m");
98 memset (&ifr
, 0, sizeof ifr
);
99 strncpy (ifr
.ifr_name
, (const char *)info
-> ifp
, sizeof ifr
.ifr_name
);
100 ifr
.ifr_name
[IFNAMSIZ
-1] = '\0';
101 if (ioctl (sock
, SIOCGIFINDEX
, &ifr
))
102 log_fatal ("Failed to get interface index: %m");
104 /* Bind to the interface name */
105 memset (&sa
, 0, sizeof sa
);
106 sa
.ll
.sll_family
= AF_PACKET
;
107 sa
.ll
.sll_ifindex
= ifr
.ifr_ifindex
;
108 if (bind (sock
, &sa
.common
, sizeof sa
)) {
109 if (errno
== ENOPROTOOPT
|| errno
== EPROTONOSUPPORT
||
110 errno
== ESOCKTNOSUPPORT
|| errno
== EPFNOSUPPORT
||
111 errno
== EAFNOSUPPORT
|| errno
== EINVAL
) {
112 log_error ("socket: %m - make sure");
113 log_error ("CONFIG_PACKET (Packet socket) %s",
114 "and CONFIG_FILTER");
115 log_error ("(Socket Filtering) are enabled %s",
117 log_fatal ("configuration!");
119 log_fatal ("Bind socket to interface: %m");
123 get_hw_addr(info
->name
, &info
->hw_address
);
127 #endif /* USE_LPF_SEND || USE_LPF_RECEIVE */
130 void if_register_send (info
)
131 struct interface_info
*info
;
133 /* If we're using the lpf API for sending and receiving,
134 we don't need to register this interface twice. */
135 #ifndef USE_LPF_RECEIVE
136 info
-> wfdesc
= if_register_lpf (info
);
138 info
-> wfdesc
= info
-> rfdesc
;
140 if (!quiet_interface_discovery
)
141 log_info ("Sending on LPF/%s/%s%s%s",
143 print_hw_addr (info
-> hw_address
.hbuf
[0],
144 info
-> hw_address
.hlen
- 1,
145 &info
-> hw_address
.hbuf
[1]),
146 (info
-> shared_network
? "/" : ""),
147 (info
-> shared_network
?
148 info
-> shared_network
-> name
: ""));
151 void if_deregister_send (info
)
152 struct interface_info
*info
;
154 /* don't need to close twice if we are using lpf for sending and
156 #ifndef USE_LPF_RECEIVE
157 /* for LPF this is simple, packet filters are removed when sockets
159 close (info
-> wfdesc
);
162 if (!quiet_interface_discovery
)
163 log_info ("Disabling output on LPF/%s/%s%s%s",
165 print_hw_addr (info
-> hw_address
.hbuf
[0],
166 info
-> hw_address
.hlen
- 1,
167 &info
-> hw_address
.hbuf
[1]),
168 (info
-> shared_network
? "/" : ""),
169 (info
-> shared_network
?
170 info
-> shared_network
-> name
: ""));
172 #endif /* USE_LPF_SEND */
174 #ifdef USE_LPF_RECEIVE
175 /* Defined in bpf.c. We can't extern these in dhcpd.h without pulling
176 in bpf includes... */
177 extern struct sock_filter dhcp_bpf_filter
[];
178 extern int dhcp_bpf_filter_len
;
180 #if defined(RELAY_PORT)
181 extern struct sock_filter dhcp_bpf_relay_filter
[];
182 extern int dhcp_bpf_relay_filter_len
;
185 #if defined (HAVE_TR_SUPPORT)
186 extern struct sock_filter dhcp_bpf_tr_filter
[];
187 extern int dhcp_bpf_tr_filter_len
;
188 static void lpf_tr_filter_setup (struct interface_info
*);
191 static void lpf_gen_filter_setup (struct interface_info
*);
193 void if_register_receive (info
)
194 struct interface_info
*info
;
196 /* Open a LPF device and hang it on this interface... */
197 info
-> rfdesc
= if_register_lpf (info
);
199 #ifdef PACKET_AUXDATA
203 if (setsockopt(info
->rfdesc
, SOL_PACKET
, PACKET_AUXDATA
,
204 &val
, sizeof(val
)) < 0) {
205 if (errno
!= ENOPROTOOPT
) {
206 log_fatal ("Failed to set auxiliary packet data: %m");
213 #if defined (HAVE_TR_SUPPORT)
214 if (info
-> hw_address
.hbuf
[0] == HTYPE_IEEE802
)
215 lpf_tr_filter_setup (info
);
218 lpf_gen_filter_setup (info
);
220 if (!quiet_interface_discovery
)
221 log_info ("Listening on LPF/%s/%s%s%s",
223 print_hw_addr (info
-> hw_address
.hbuf
[0],
224 info
-> hw_address
.hlen
- 1,
225 &info
-> hw_address
.hbuf
[1]),
226 (info
-> shared_network
? "/" : ""),
227 (info
-> shared_network
?
228 info
-> shared_network
-> name
: ""));
231 void if_deregister_receive (info
)
232 struct interface_info
*info
;
234 /* for LPF this is simple, packet filters are removed when sockets
236 close (info
-> rfdesc
);
238 if (!quiet_interface_discovery
)
239 log_info ("Disabling input on LPF/%s/%s%s%s",
241 print_hw_addr (info
-> hw_address
.hbuf
[0],
242 info
-> hw_address
.hlen
- 1,
243 &info
-> hw_address
.hbuf
[1]),
244 (info
-> shared_network
? "/" : ""),
245 (info
-> shared_network
?
246 info
-> shared_network
-> name
: ""));
249 static void lpf_gen_filter_setup (info
)
250 struct interface_info
*info
;
254 memset(&p
, 0, sizeof(p
));
256 /* Set up the bpf filter program structure. This is defined in
258 p
.len
= dhcp_bpf_filter_len
;
259 p
.filter
= dhcp_bpf_filter
;
261 /* Patch the server port into the LPF program...
262 XXX changes to filter program may require changes
263 to the insn number(s) used below! XXX */
264 #if defined(RELAY_PORT)
267 * If user defined relay UDP port, we need to filter
268 * also on the user UDP port.
270 p
.len
= dhcp_bpf_relay_filter_len
;
271 p
.filter
= dhcp_bpf_relay_filter
;
273 dhcp_bpf_relay_filter
[10].k
= ntohs (relay_port
);
276 dhcp_bpf_filter
[8].k
= ntohs (local_port
);
278 if (setsockopt (info
-> rfdesc
, SOL_SOCKET
, SO_ATTACH_FILTER
, &p
,
280 if (errno
== ENOPROTOOPT
|| errno
== EPROTONOSUPPORT
||
281 errno
== ESOCKTNOSUPPORT
|| errno
== EPFNOSUPPORT
||
282 errno
== EAFNOSUPPORT
) {
283 log_error ("socket: %m - make sure");
284 log_error ("CONFIG_PACKET (Packet socket) %s",
285 "and CONFIG_FILTER");
286 log_error ("(Socket Filtering) are enabled %s",
288 log_fatal ("configuration!");
290 log_fatal ("Can't install packet filter program: %m");
294 #if defined (HAVE_TR_SUPPORT)
295 static void lpf_tr_filter_setup (info
)
296 struct interface_info
*info
;
300 memset(&p
, 0, sizeof(p
));
302 /* Set up the bpf filter program structure. This is defined in
304 p
.len
= dhcp_bpf_tr_filter_len
;
305 p
.filter
= dhcp_bpf_tr_filter
;
307 /* Patch the server port into the LPF program...
308 XXX changes to filter program may require changes
309 XXX to the insn number(s) used below!
310 XXX Token ring filter is null - when/if we have a filter
311 XXX that's not, we'll need this code.
312 XXX dhcp_bpf_filter [?].k = ntohs (local_port); */
314 if (setsockopt (info
-> rfdesc
, SOL_SOCKET
, SO_ATTACH_FILTER
, &p
,
316 if (errno
== ENOPROTOOPT
|| errno
== EPROTONOSUPPORT
||
317 errno
== ESOCKTNOSUPPORT
|| errno
== EPFNOSUPPORT
||
318 errno
== EAFNOSUPPORT
) {
319 log_error ("socket: %m - make sure");
320 log_error ("CONFIG_PACKET (Packet socket) %s",
321 "and CONFIG_FILTER");
322 log_error ("(Socket Filtering) are enabled %s",
324 log_fatal ("configuration!");
326 log_fatal ("Can't install packet filter program: %m");
329 #endif /* HAVE_TR_SUPPORT */
330 #endif /* USE_LPF_RECEIVE */
333 ssize_t
send_packet (interface
, packet
, raw
, len
, from
, to
, hto
)
334 struct interface_info
*interface
;
335 struct packet
*packet
;
336 struct dhcp_packet
*raw
;
339 struct sockaddr_in
*to
;
340 struct hardware
*hto
;
342 unsigned hbufp
= 0, ibufp
= 0;
344 double ih
[1536 / sizeof (double)];
345 unsigned char *buf
= (unsigned char *)ih
;
349 if (!strcmp (interface
-> name
, "fallback"))
350 return send_fallback (interface
, packet
, raw
,
353 if (hto
== NULL
&& interface
->anycast_mac_addr
.hlen
)
354 hto
= &interface
->anycast_mac_addr
;
356 /* Assemble the headers... */
357 assemble_hw_header (interface
, (unsigned char *)hh
, &hbufp
, hto
);
358 fudge
= hbufp
% 4; /* IP header must be word-aligned. */
359 memcpy (buf
+ fudge
, (unsigned char *)hh
, hbufp
);
360 ibufp
= hbufp
+ fudge
;
361 assemble_udp_ip_header (interface
, buf
, &ibufp
, from
.s_addr
,
362 to
-> sin_addr
.s_addr
, to
-> sin_port
,
363 (unsigned char *)raw
, len
);
364 memcpy (buf
+ ibufp
, raw
, len
);
365 result
= write(interface
->wfdesc
, buf
+ fudge
, ibufp
+ len
- fudge
);
367 log_error ("send_packet: %m");
370 #endif /* USE_LPF_SEND */
372 #ifdef USE_LPF_RECEIVE
373 ssize_t
receive_packet (interface
, buf
, len
, from
, hfrom
)
374 struct interface_info
*interface
;
377 struct sockaddr_in
*from
;
378 struct hardware
*hfrom
;
383 unsigned char ibuf
[1536];
388 .iov_len
= sizeof ibuf
,
390 #ifdef PACKET_AUXDATA
392 * We only need cmsgbuf if we are getting the aux data and we
393 * only get the auxdata if it is actually defined
395 unsigned char cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
396 struct msghdr msg
= {
399 .msg_control
= cmsgbuf
,
400 .msg_controllen
= sizeof(cmsgbuf
),
403 struct msghdr msg
= {
409 #endif /* PACKET_AUXDATA */
411 length
= recvmsg (interface
->rfdesc
, &msg
, 0);
415 #ifdef PACKET_AUXDATA
417 /* Use auxiliary packet data to:
419 * a. Weed out extraneous VLAN-tagged packets - If the NIC driver is
420 * handling VLAN encapsulation (i.e. stripping/adding VLAN tags),
421 * then an inbound VLAN packet will be seen twice: Once by
422 * the parent interface (e.g. eth0) with a VLAN tag != 0; and once
423 * by the vlan interface (e.g. eth0.n) with a VLAN tag of 0 (i.e none).
424 * We want to discard the packet sent to the parent and thus respond
425 * only over the vlan interface. (Drivers for Intel PRO/1000 series
426 * NICs perform VLAN encapsulation, while drivers for PCnet series
427 * do not, for example. The linux kernel makes stripped vlan info
428 * visible to user space via CMSG/auxdata, this appears to not be
429 * true for BSD OSs.). NOTE: this is only supported on linux flavors
430 * which define the tpacket_auxdata.tp_vlan_tci.
432 * b. Determine if checksum is valid for use. It may not be if
433 * checksum offloading is enabled on the interface. */
434 struct cmsghdr
*cmsg
;
436 for (cmsg
= CMSG_FIRSTHDR(&msg
); cmsg
; cmsg
= CMSG_NXTHDR(&msg
, cmsg
)) {
437 if (cmsg
->cmsg_level
== SOL_PACKET
&&
438 cmsg
->cmsg_type
== PACKET_AUXDATA
) {
439 struct tpacket_auxdata
*aux
= (void *)CMSG_DATA(cmsg
);
440 #ifdef VLAN_TCI_PRESENT
441 /* Discard packets with stripped vlan id */
442 /* VLAN ID is only bottom 12-bits of TCI */
443 if (aux
->tp_vlan_tci
& 0x0fff)
447 csum_ready
= ((aux
->tp_status
& TP_STATUS_CSUMNOTREADY
)
453 #endif /* PACKET_AUXDATA */
456 /* Decode the physical header... */
457 offset
= decode_hw_header (interface
, ibuf
, bufix
, hfrom
);
459 /* If a physical layer checksum failed (dunno of any
460 physical layer that supports this, but WTH), skip this
469 /* Decode the IP and UDP headers... */
470 offset
= decode_udp_ip_header (interface
, ibuf
, bufix
, from
,
471 (unsigned)length
, &paylen
, csum_ready
);
473 /* If the IP or UDP checksum was bad, skip the packet... */
481 log_fatal("Internal inconsistency at %s:%d.", MDL
);
483 /* Copy out the data in the packet... */
484 memcpy(buf
, &ibuf
[bufix
], paylen
);
488 int can_unicast_without_arp (ip
)
489 struct interface_info
*ip
;
494 int can_receive_unicast_unconfigured (ip
)
495 struct interface_info
*ip
;
500 int supports_multiple_interfaces (ip
)
501 struct interface_info
*ip
;
506 void maybe_setup_fallback ()
509 struct interface_info
*fbi
= (struct interface_info
*)0;
510 if (setup_fallback (&fbi
, MDL
)) {
511 if_register_fallback (fbi
);
512 status
= omapi_register_io_object ((omapi_object_t
*)fbi
,
514 fallback_discard
, 0, 0);
515 if (status
!= ISC_R_SUCCESS
)
516 log_fatal ("Can't register I/O handle for \"%s\": %s",
517 fbi
-> name
, isc_result_totext (status
));
518 interface_dereference (&fbi
, MDL
);
523 #if defined (USE_LPF_RECEIVE) || defined (USE_LPF_HWADDR)
525 get_hw_addr(const char *name
, struct hardware
*hw
) {
530 if (strlen(name
) >= sizeof(tmp
.ifr_name
)) {
531 log_fatal("Device name too long: \"%s\"", name
);
534 sock
= socket(AF_INET
, SOCK_DGRAM
, 0);
536 log_fatal("Can't create socket for \"%s\": %m", name
);
539 memset(&tmp
, 0, sizeof(tmp
));
540 strcpy(tmp
.ifr_name
, name
);
541 if (ioctl(sock
, SIOCGIFHWADDR
, &tmp
) < 0) {
542 log_fatal("Error getting hardware address for \"%s\": %m",
546 sa
= &tmp
.ifr_hwaddr
;
547 switch (sa
->sa_family
) {
550 hw
->hbuf
[0] = HTYPE_ETHER
;
551 memcpy(&hw
->hbuf
[1], sa
->sa_data
, 6);
554 #ifdef ARPHRD_IEEE802_TR
555 case ARPHRD_IEEE802_TR
:
556 #endif /* ARPHRD_IEEE802_TR */
558 hw
->hbuf
[0] = HTYPE_IEEE802
;
559 memcpy(&hw
->hbuf
[1], sa
->sa_data
, 6);
563 hw
->hbuf
[0] = HTYPE_FDDI
;
564 memcpy(&hw
->hbuf
[1], sa
->sa_data
, 6);
567 log_fatal("Unsupported device type %ld for \"%s\"",
568 (long int)sa
->sa_family
, name
);