3 Linux packet filter code, contributed by Brian Murrel at Interlinx
4 Support Services in Vancouver, B.C. */
7 * Copyright (c) 1996-2002 Internet Software Consortium.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of The Internet Software Consortium nor the names
20 * of its contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
24 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
25 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
28 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
31 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
32 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
34 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 static char copyright[] =
40 "$Id: lpf.c,v 1.29.2.1 2002/11/17 02:26:58 dhankins Exp $ Copyright (c) 1996-2002 The Internet Software Consortium. All rights reserved.\n";
44 #if defined (USE_LPF_SEND) || defined (USE_LPF_RECEIVE)
45 #include <sys/ioctl.h>
48 #include <asm/types.h>
49 #include <linux/filter.h>
50 #include <linux/if_ether.h>
51 #include <netinet/in_systm.h>
52 #include "includes/netinet/ip.h"
53 #include "includes/netinet/udp.h"
54 #include "includes/netinet/if_ether.h"
56 /* Reinitializes the specified interface after an address change. This
57 is not required for packet-filter APIs. */
60 void if_reinitialize_send (info)
61 struct interface_info *info;
66 #ifdef USE_LPF_RECEIVE
67 void if_reinitialize_receive (info)
68 struct interface_info *info;
73 /* Called by get_interface_list for each interface that's discovered.
74 Opens a packet filter for each interface and adds it to the select
77 int if_register_lpf (info)
78 struct interface_info *info;
85 /* Make an LPF socket. */
86 if ((sock = socket(PF_PACKET, SOCK_PACKET,
87 htons((short)ETH_P_ALL))) < 0) {
88 if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
89 errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT ||
90 errno == EAFNOSUPPORT || errno == EINVAL) {
91 log_error ("socket: %m - make sure");
92 log_error ("CONFIG_PACKET (Packet socket) %s",
94 log_error ("(Socket Filtering) are enabled %s",
96 log_fatal ("configuration!");
98 log_fatal ("Open a socket for LPF: %m");
101 /* Bind to the interface name */
102 memset (&sa, 0, sizeof sa);
103 sa.sa_family = AF_PACKET;
104 strncpy (sa.sa_data, (const char *)info -> ifp, sizeof sa.sa_data);
105 if (bind (sock, &sa, sizeof sa)) {
106 if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
107 errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT ||
108 errno == EAFNOSUPPORT || errno == EINVAL) {
109 log_error ("socket: %m - make sure");
110 log_error ("CONFIG_PACKET (Packet socket) %s",
111 "and CONFIG_FILTER");
112 log_error ("(Socket Filtering) are enabled %s",
114 log_fatal ("configuration!");
116 log_fatal ("Bind socket to interface: %m");
121 #endif /* USE_LPF_SEND || USE_LPF_RECEIVE */
124 void if_register_send (info)
125 struct interface_info *info;
127 /* If we're using the lpf API for sending and receiving,
128 we don't need to register this interface twice. */
129 #ifndef USE_LPF_RECEIVE
130 info -> wfdesc = if_register_lpf (info);
132 info -> wfdesc = info -> rfdesc;
134 if (!quiet_interface_discovery)
135 log_info ("Sending on LPF/%s/%s%s%s",
137 print_hw_addr (info -> hw_address.hbuf [0],
138 info -> hw_address.hlen - 1,
139 &info -> hw_address.hbuf [1]),
140 (info -> shared_network ? "/" : ""),
141 (info -> shared_network ?
142 info -> shared_network -> name : ""));
145 void if_deregister_send (info)
146 struct interface_info *info;
148 /* don't need to close twice if we are using lpf for sending and
150 #ifndef USE_LPF_RECEIVE
151 /* for LPF this is simple, packet filters are removed when sockets
153 close (info -> wfdesc);
156 if (!quiet_interface_discovery)
157 log_info ("Disabling output on LPF/%s/%s%s%s",
159 print_hw_addr (info -> hw_address.hbuf [0],
160 info -> hw_address.hlen - 1,
161 &info -> hw_address.hbuf [1]),
162 (info -> shared_network ? "/" : ""),
163 (info -> shared_network ?
164 info -> shared_network -> name : ""));
166 #endif /* USE_LPF_SEND */
168 #ifdef USE_LPF_RECEIVE
169 /* Defined in bpf.c. We can't extern these in dhcpd.h without pulling
170 in bpf includes... */
171 extern struct sock_filter dhcp_bpf_filter [];
172 extern int dhcp_bpf_filter_len;
174 #if defined (HAVE_TR_SUPPORT)
175 extern struct sock_filter dhcp_bpf_tr_filter [];
176 extern int dhcp_bpf_tr_filter_len;
177 static void lpf_tr_filter_setup (struct interface_info *);
180 static void lpf_gen_filter_setup (struct interface_info *);
182 void if_register_receive (info)
183 struct interface_info *info;
185 /* Open a LPF device and hang it on this interface... */
186 info -> rfdesc = if_register_lpf (info);
188 #if defined (HAVE_TR_SUPPORT)
189 if (info -> hw_address.hbuf [0] == HTYPE_IEEE802)
190 lpf_tr_filter_setup (info);
193 lpf_gen_filter_setup (info);
195 if (!quiet_interface_discovery)
196 log_info ("Listening on LPF/%s/%s%s%s",
198 print_hw_addr (info -> hw_address.hbuf [0],
199 info -> hw_address.hlen - 1,
200 &info -> hw_address.hbuf [1]),
201 (info -> shared_network ? "/" : ""),
202 (info -> shared_network ?
203 info -> shared_network -> name : ""));
206 void if_deregister_receive (info)
207 struct interface_info *info;
209 /* for LPF this is simple, packet filters are removed when sockets
211 close (info -> rfdesc);
213 if (!quiet_interface_discovery)
214 log_info ("Disabling input on LPF/%s/%s%s%s",
216 print_hw_addr (info -> hw_address.hbuf [0],
217 info -> hw_address.hlen - 1,
218 &info -> hw_address.hbuf [1]),
219 (info -> shared_network ? "/" : ""),
220 (info -> shared_network ?
221 info -> shared_network -> name : ""));
224 static void lpf_gen_filter_setup (info)
225 struct interface_info *info;
229 /* Set up the bpf filter program structure. This is defined in
231 p.len = dhcp_bpf_filter_len;
232 p.filter = dhcp_bpf_filter;
234 /* Patch the server port into the LPF program...
235 XXX changes to filter program may require changes
236 to the insn number(s) used below! XXX */
237 dhcp_bpf_filter [8].k = ntohs ((short)local_port);
239 if (setsockopt (info -> rfdesc, SOL_SOCKET, SO_ATTACH_FILTER, &p,
241 if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
242 errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT ||
243 errno == EAFNOSUPPORT) {
244 log_error ("socket: %m - make sure");
245 log_error ("CONFIG_PACKET (Packet socket) %s",
246 "and CONFIG_FILTER");
247 log_error ("(Socket Filtering) are enabled %s",
249 log_fatal ("configuration!");
251 log_fatal ("Can't install packet filter program: %m");
255 #if defined (HAVE_TR_SUPPORT)
256 static void lpf_tr_filter_setup (info)
257 struct interface_info *info;
261 /* Set up the bpf filter program structure. This is defined in
263 p.len = dhcp_bpf_tr_filter_len;
264 p.filter = dhcp_bpf_tr_filter;
266 /* Patch the server port into the LPF program...
267 XXX changes to filter program may require changes
268 XXX to the insn number(s) used below!
269 XXX Token ring filter is null - when/if we have a filter
270 XXX that's not, we'll need this code.
271 XXX dhcp_bpf_filter [?].k = ntohs (local_port); */
273 if (setsockopt (info -> rfdesc, SOL_SOCKET, SO_ATTACH_FILTER, &p,
275 if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
276 errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT ||
277 errno == EAFNOSUPPORT) {
278 log_error ("socket: %m - make sure");
279 log_error ("CONFIG_PACKET (Packet socket) %s",
280 "and CONFIG_FILTER");
281 log_error ("(Socket Filtering) are enabled %s",
283 log_fatal ("configuration!");
285 log_fatal ("Can't install packet filter program: %m");
288 #endif /* HAVE_TR_SUPPORT */
289 #endif /* USE_LPF_RECEIVE */
292 ssize_t send_packet (interface, packet, raw, len, from, to, hto)
293 struct interface_info *interface;
294 struct packet *packet;
295 struct dhcp_packet *raw;
298 struct sockaddr_in *to;
299 struct hardware *hto;
301 unsigned hbufp = 0, ibufp = 0;
303 double ih [1536 / sizeof (double)];
304 unsigned char *buf = (unsigned char *)ih;
309 if (!strcmp (interface -> name, "fallback"))
310 return send_fallback (interface, packet, raw,
313 /* Assemble the headers... */
314 assemble_hw_header (interface, (unsigned char *)hh, &hbufp, hto);
315 fudge = hbufp % 4; /* IP header must be word-aligned. */
316 memcpy (buf + fudge, (unsigned char *)hh, hbufp);
317 ibufp = hbufp + fudge;
318 assemble_udp_ip_header (interface, buf, &ibufp, from.s_addr,
319 to -> sin_addr.s_addr, to -> sin_port,
320 (unsigned char *)raw, len);
321 memcpy (buf + ibufp, raw, len);
323 /* For some reason, SOCK_PACKET sockets can't be connected,
324 so we have to do a sentdo every time. */
325 memset (&sa, 0, sizeof sa);
326 sa.sa_family = AF_PACKET;
328 (const char *)interface -> ifp, sizeof sa.sa_data);
330 result = sendto (interface -> wfdesc,
331 buf + fudge, ibufp + len - fudge, 0, &sa, sizeof sa);
333 log_error ("send_packet: %m");
336 #endif /* USE_LPF_SEND */
338 #ifdef USE_LPF_RECEIVE
339 ssize_t receive_packet (interface, buf, len, from, hfrom)
340 struct interface_info *interface;
343 struct sockaddr_in *from;
344 struct hardware *hfrom;
349 unsigned char ibuf [1536];
352 length = read (interface -> rfdesc, ibuf, sizeof ibuf);
357 /* Decode the physical header... */
358 offset = decode_hw_header (interface, ibuf, bufix, hfrom);
360 /* If a physical layer checksum failed (dunno of any
361 physical layer that supports this, but WTH), skip this
370 /* Decode the IP and UDP headers... */
371 offset = decode_udp_ip_header (interface, ibuf, bufix, from,
372 (unsigned char *)0, (unsigned)length);
374 /* If the IP or UDP checksum was bad, skip the packet... */
381 /* Copy out the data in the packet... */
382 memcpy (buf, &ibuf [bufix], length);
386 int can_unicast_without_arp (ip)
387 struct interface_info *ip;
392 int can_receive_unicast_unconfigured (ip)
393 struct interface_info *ip;
398 int supports_multiple_interfaces (ip)
399 struct interface_info *ip;
404 void maybe_setup_fallback ()
407 struct interface_info *fbi = (struct interface_info *)0;
408 if (setup_fallback (&fbi, MDL)) {
409 if_register_fallback (fbi);
410 status = omapi_register_io_object ((omapi_object_t *)fbi,
412 fallback_discard, 0, 0);
413 if (status != ISC_R_SUCCESS)
414 log_fatal ("Can't register I/O handle for %s: %s",
415 fbi -> name, isc_result_totext (status));
416 interface_dereference (&fbi, MDL);