3 Linux packet filter code, contributed by Brian Murrel at Interlinx
4 Support Services in Vancouver, B.C. */
7 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
8 * Copyright (c) 1996-2003 by Internet Software Consortium
10 * Permission to use, copy, modify, and distribute this software for any
11 * purpose with or without fee is hereby granted, provided that the above
12 * copyright notice and this permission notice appear in all copies.
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 * Redwood City, CA 94063
30 static char copyright
[] =
31 "$Id: lpf.c,v 1.32 2007/05/08 23:05:20 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
35 #if defined (USE_LPF_SEND) || defined (USE_LPF_RECEIVE)
36 #include <sys/ioctl.h>
39 #include <asm/types.h>
40 #include <linux/filter.h>
41 #include <linux/if_ether.h>
42 #include <netinet/in_systm.h>
43 #include "includes/netinet/ip.h"
44 #include "includes/netinet/udp.h"
45 #include "includes/netinet/if_ether.h"
48 /* Reinitializes the specified interface after an address change. This
49 is not required for packet-filter APIs. */
52 void if_reinitialize_send (info
)
53 struct interface_info
*info
;
58 #ifdef USE_LPF_RECEIVE
59 void if_reinitialize_receive (info
)
60 struct interface_info
*info
;
65 /* Called by get_interface_list for each interface that's discovered.
66 Opens a packet filter for each interface and adds it to the select
69 int if_register_lpf (info
)
70 struct interface_info
*info
;
77 /* Make an LPF socket. */
78 if ((sock
= socket(PF_PACKET
, SOCK_PACKET
,
79 htons((short)ETH_P_ALL
))) < 0) {
80 if (errno
== ENOPROTOOPT
|| errno
== EPROTONOSUPPORT
||
81 errno
== ESOCKTNOSUPPORT
|| errno
== EPFNOSUPPORT
||
82 errno
== EAFNOSUPPORT
|| errno
== EINVAL
) {
83 log_error ("socket: %m - make sure");
84 log_error ("CONFIG_PACKET (Packet socket) %s",
86 log_error ("(Socket Filtering) are enabled %s",
88 log_fatal ("configuration!");
90 log_fatal ("Open a socket for LPF: %m");
93 /* Bind to the interface name */
94 memset (&sa
, 0, sizeof sa
);
95 sa
.sa_family
= AF_PACKET
;
96 strncpy (sa
.sa_data
, (const char *)info
-> ifp
, sizeof sa
.sa_data
);
97 if (bind (sock
, &sa
, sizeof sa
)) {
98 if (errno
== ENOPROTOOPT
|| errno
== EPROTONOSUPPORT
||
99 errno
== ESOCKTNOSUPPORT
|| errno
== EPFNOSUPPORT
||
100 errno
== EAFNOSUPPORT
|| errno
== EINVAL
) {
101 log_error ("socket: %m - make sure");
102 log_error ("CONFIG_PACKET (Packet socket) %s",
103 "and CONFIG_FILTER");
104 log_error ("(Socket Filtering) are enabled %s",
106 log_fatal ("configuration!");
108 log_fatal ("Bind socket to interface: %m");
113 #endif /* USE_LPF_SEND || USE_LPF_RECEIVE */
116 void if_register_send (info
)
117 struct interface_info
*info
;
119 /* If we're using the lpf API for sending and receiving,
120 we don't need to register this interface twice. */
121 #ifndef USE_LPF_RECEIVE
122 info
-> wfdesc
= if_register_lpf (info
);
124 info
-> wfdesc
= info
-> rfdesc
;
126 if (!quiet_interface_discovery
)
127 log_info ("Sending on LPF/%s/%s%s%s",
129 print_hw_addr (info
-> hw_address
.hbuf
[0],
130 info
-> hw_address
.hlen
- 1,
131 &info
-> hw_address
.hbuf
[1]),
132 (info
-> shared_network
? "/" : ""),
133 (info
-> shared_network
?
134 info
-> shared_network
-> name
: ""));
137 void if_deregister_send (info
)
138 struct interface_info
*info
;
140 /* don't need to close twice if we are using lpf for sending and
142 #ifndef USE_LPF_RECEIVE
143 /* for LPF this is simple, packet filters are removed when sockets
145 close (info
-> wfdesc
);
148 if (!quiet_interface_discovery
)
149 log_info ("Disabling output on LPF/%s/%s%s%s",
151 print_hw_addr (info
-> hw_address
.hbuf
[0],
152 info
-> hw_address
.hlen
- 1,
153 &info
-> hw_address
.hbuf
[1]),
154 (info
-> shared_network
? "/" : ""),
155 (info
-> shared_network
?
156 info
-> shared_network
-> name
: ""));
158 #endif /* USE_LPF_SEND */
160 #ifdef USE_LPF_RECEIVE
161 /* Defined in bpf.c. We can't extern these in dhcpd.h without pulling
162 in bpf includes... */
163 extern struct sock_filter dhcp_bpf_filter
[];
164 extern int dhcp_bpf_filter_len
;
166 #if defined (HAVE_TR_SUPPORT)
167 extern struct sock_filter dhcp_bpf_tr_filter
[];
168 extern int dhcp_bpf_tr_filter_len
;
169 static void lpf_tr_filter_setup (struct interface_info
*);
172 static void lpf_gen_filter_setup (struct interface_info
*);
174 void if_register_receive (info
)
175 struct interface_info
*info
;
177 /* Open a LPF device and hang it on this interface... */
178 info
-> rfdesc
= if_register_lpf (info
);
180 #if defined (HAVE_TR_SUPPORT)
181 if (info
-> hw_address
.hbuf
[0] == HTYPE_IEEE802
)
182 lpf_tr_filter_setup (info
);
185 lpf_gen_filter_setup (info
);
187 if (!quiet_interface_discovery
)
188 log_info ("Listening on LPF/%s/%s%s%s",
190 print_hw_addr (info
-> hw_address
.hbuf
[0],
191 info
-> hw_address
.hlen
- 1,
192 &info
-> hw_address
.hbuf
[1]),
193 (info
-> shared_network
? "/" : ""),
194 (info
-> shared_network
?
195 info
-> shared_network
-> name
: ""));
198 void if_deregister_receive (info
)
199 struct interface_info
*info
;
201 /* for LPF this is simple, packet filters are removed when sockets
203 close (info
-> rfdesc
);
205 if (!quiet_interface_discovery
)
206 log_info ("Disabling input on LPF/%s/%s%s%s",
208 print_hw_addr (info
-> hw_address
.hbuf
[0],
209 info
-> hw_address
.hlen
- 1,
210 &info
-> hw_address
.hbuf
[1]),
211 (info
-> shared_network
? "/" : ""),
212 (info
-> shared_network
?
213 info
-> shared_network
-> name
: ""));
216 static void lpf_gen_filter_setup (info
)
217 struct interface_info
*info
;
221 /* Set up the bpf filter program structure. This is defined in
223 p
.len
= dhcp_bpf_filter_len
;
224 p
.filter
= dhcp_bpf_filter
;
226 /* Patch the server port into the LPF program...
227 XXX changes to filter program may require changes
228 to the insn number(s) used below! XXX */
229 dhcp_bpf_filter
[8].k
= ntohs ((short)local_port
);
231 if (setsockopt (info
-> rfdesc
, SOL_SOCKET
, SO_ATTACH_FILTER
, &p
,
233 if (errno
== ENOPROTOOPT
|| errno
== EPROTONOSUPPORT
||
234 errno
== ESOCKTNOSUPPORT
|| errno
== EPFNOSUPPORT
||
235 errno
== EAFNOSUPPORT
) {
236 log_error ("socket: %m - make sure");
237 log_error ("CONFIG_PACKET (Packet socket) %s",
238 "and CONFIG_FILTER");
239 log_error ("(Socket Filtering) are enabled %s",
241 log_fatal ("configuration!");
243 log_fatal ("Can't install packet filter program: %m");
247 #if defined (HAVE_TR_SUPPORT)
248 static void lpf_tr_filter_setup (info
)
249 struct interface_info
*info
;
253 /* Set up the bpf filter program structure. This is defined in
255 p
.len
= dhcp_bpf_tr_filter_len
;
256 p
.filter
= dhcp_bpf_tr_filter
;
258 /* Patch the server port into the LPF program...
259 XXX changes to filter program may require changes
260 XXX to the insn number(s) used below!
261 XXX Token ring filter is null - when/if we have a filter
262 XXX that's not, we'll need this code.
263 XXX dhcp_bpf_filter [?].k = ntohs (local_port); */
265 if (setsockopt (info
-> rfdesc
, SOL_SOCKET
, SO_ATTACH_FILTER
, &p
,
267 if (errno
== ENOPROTOOPT
|| errno
== EPROTONOSUPPORT
||
268 errno
== ESOCKTNOSUPPORT
|| errno
== EPFNOSUPPORT
||
269 errno
== EAFNOSUPPORT
) {
270 log_error ("socket: %m - make sure");
271 log_error ("CONFIG_PACKET (Packet socket) %s",
272 "and CONFIG_FILTER");
273 log_error ("(Socket Filtering) are enabled %s",
275 log_fatal ("configuration!");
277 log_fatal ("Can't install packet filter program: %m");
280 #endif /* HAVE_TR_SUPPORT */
281 #endif /* USE_LPF_RECEIVE */
284 ssize_t
send_packet (interface
, packet
, raw
, len
, from
, to
, hto
)
285 struct interface_info
*interface
;
286 struct packet
*packet
;
287 struct dhcp_packet
*raw
;
290 struct sockaddr_in
*to
;
291 struct hardware
*hto
;
293 unsigned hbufp
= 0, ibufp
= 0;
295 double ih
[1536 / sizeof (double)];
296 unsigned char *buf
= (unsigned char *)ih
;
301 if (!strcmp (interface
-> name
, "fallback"))
302 return send_fallback (interface
, packet
, raw
,
305 /* Assemble the headers... */
306 assemble_hw_header (interface
, (unsigned char *)hh
, &hbufp
, hto
);
307 fudge
= hbufp
% 4; /* IP header must be word-aligned. */
308 memcpy (buf
+ fudge
, (unsigned char *)hh
, hbufp
);
309 ibufp
= hbufp
+ fudge
;
310 assemble_udp_ip_header (interface
, buf
, &ibufp
, from
.s_addr
,
311 to
-> sin_addr
.s_addr
, to
-> sin_port
,
312 (unsigned char *)raw
, len
);
313 memcpy (buf
+ ibufp
, raw
, len
);
315 /* For some reason, SOCK_PACKET sockets can't be connected,
316 so we have to do a sentdo every time. */
317 memset (&sa
, 0, sizeof sa
);
318 sa
.sa_family
= AF_PACKET
;
320 (const char *)interface
-> ifp
, sizeof sa
.sa_data
);
322 result
= sendto (interface
-> wfdesc
,
323 buf
+ fudge
, ibufp
+ len
- fudge
, 0, &sa
, sizeof sa
);
325 log_error ("send_packet: %m");
328 #endif /* USE_LPF_SEND */
330 #ifdef USE_LPF_RECEIVE
331 ssize_t
receive_packet (interface
, buf
, len
, from
, hfrom
)
332 struct interface_info
*interface
;
335 struct sockaddr_in
*from
;
336 struct hardware
*hfrom
;
341 unsigned char ibuf
[1536];
345 length
= read (interface
-> rfdesc
, ibuf
, sizeof ibuf
);
350 /* Decode the physical header... */
351 offset
= decode_hw_header (interface
, ibuf
, bufix
, hfrom
);
353 /* If a physical layer checksum failed (dunno of any
354 physical layer that supports this, but WTH), skip this
363 /* Decode the IP and UDP headers... */
364 offset
= decode_udp_ip_header (interface
, ibuf
, bufix
, from
,
365 (unsigned)length
, &paylen
);
367 /* If the IP or UDP checksum was bad, skip the packet... */
375 log_fatal("Internal inconsistency at %s:%d.", MDL
);
377 /* Copy out the data in the packet... */
378 memcpy(buf
, &ibuf
[bufix
], paylen
);
382 int can_unicast_without_arp (ip
)
383 struct interface_info
*ip
;
388 int can_receive_unicast_unconfigured (ip
)
389 struct interface_info
*ip
;
394 int supports_multiple_interfaces (ip
)
395 struct interface_info
*ip
;
400 void maybe_setup_fallback ()
403 struct interface_info
*fbi
= (struct interface_info
*)0;
404 if (setup_fallback (&fbi
, MDL
)) {
405 if_register_fallback (fbi
);
406 status
= omapi_register_io_object ((omapi_object_t
*)fbi
,
408 fallback_discard
, 0, 0);
409 if (status
!= ISC_R_SUCCESS
)
410 log_fatal ("Can't register I/O handle for \"%s\": %s",
411 fbi
-> name
, isc_result_totext (status
));
412 interface_dereference (&fbi
, MDL
);
417 get_hw_addr(const char *name
, struct hardware
*hw
) {
422 if (strlen(name
) >= sizeof(tmp
.ifr_name
)) {
423 log_fatal("Device name too long: \"%s\"", name
);
426 sock
= socket(AF_INET
, SOCK_DGRAM
, 0);
428 log_fatal("Can't create socket for \"%s\": %m", name
);
431 memset(&tmp
, 0, sizeof(tmp
));
432 strcpy(tmp
.ifr_name
, name
);
433 if (ioctl(sock
, SIOCGIFHWADDR
, &tmp
) < 0) {
434 log_fatal("Error getting hardware address for \"%s\": %m",
438 sa
= &tmp
.ifr_hwaddr
;
439 switch (sa
->sa_family
) {
442 hw
->hbuf
[0] = HTYPE_ETHER
;
443 memcpy(&hw
->hbuf
[1], sa
->sa_data
, 6);
446 #ifdef ARPHDR_IEEE802_TR
447 case ARPHRD_IEEE802_TR
:
448 #endif /* ARPHDR_IEEE802_TR */
450 hw
->hbuf
[0] = HTYPE_IEEE802
;
451 memcpy(&hw
->hbuf
[1], sa
->sa_data
, 6);
455 hw
->hbuf
[0] = HTYPE_FDDI
;
456 memcpy(&hw
->hbuf
[1], sa
->sa_data
, 16);
459 log_fatal("Unsupported device type %ld for \"%s\"",
460 sa
->sa_family
, name
);