3 Ultrix PacketFilter interface code. */
6 * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1996-2003 by Internet Software Consortium
9 * This Source Code Form is subject to the terms of the Mozilla Public
10 * License, v. 2.0. If a copy of the MPL was not distributed with this
11 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Internet Systems Consortium, Inc.
23 * Newmarket, NH 03857 USA
25 * https://www.isc.org/
30 #if defined (USE_UPF_SEND) || defined (USE_UPF_RECEIVE)
31 #include <sys/ioctl.h>
34 #include <net/pfilt.h>
35 #include <netinet/in_systm.h>
36 #include "includes/netinet/ip.h"
37 #include "includes/netinet/udp.h"
38 #include "includes/netinet/if_ether.h"
40 /* Reinitializes the specified interface after an address change. This
41 is not required for packet-filter APIs. */
44 void if_reinitialize_send (info
)
45 struct interface_info
*info
;
50 #ifdef USE_UPF_RECEIVE
51 void if_reinitialize_receive (info
)
52 struct interface_info
*info
;
57 /* Called by get_interface_list for each interface that's discovered.
58 Opens a packet filter for each interface and adds it to the select
61 int if_register_upf (info
)
62 struct interface_info
*info
;
69 /* Open a UPF device */
71 /* %Audit% Cannot exceed 36 bytes. %2004.06.17,Safe% */
72 sprintf(filename
, "/dev/pf/pfilt%d", b
);
74 sock
= open (filename
, O_RDWR
, 0);
79 log_fatal ("Can't find free upf: %m");
86 /* Set the UPF device to point at this interface. */
87 if (ioctl (sock
, EIOCSETIF
, info
-> ifp
) < 0)
88 log_fatal ("Can't attach interface %s to upf device %s: %m",
89 info
-> name
, filename
);
91 /* Get the hardware address. */
92 if (ioctl (sock
, EIOCDEVP
, ¶m
) < 0)
93 log_fatal ("Can't get interface %s hardware address: %m",
96 /* We only know how to do ethernet. */
97 if (param
.end_dev_type
!= ENDT_10MB
)
98 log_fatal ("Invalid device type on network interface %s: %d",
99 info
-> name
, param
.end_dev_type
);
101 if (param
.end_addr_len
!= 6)
102 log_fatal ("Invalid hardware address length on %s: %d",
103 info
-> name
, param
.end_addr_len
);
105 info
-> hw_address
.hlen
= 7;
106 info
-> hw_address
.hbuf
[0] = ARPHRD_ETHER
;
107 memcpy (&info
-> hw_address
.hbuf
[1], param
.end_addr
, 6);
111 #endif /* USE_UPF_SEND || USE_UPF_RECEIVE */
114 void if_register_send (info
)
115 struct interface_info
*info
;
117 /* If we're using the upf API for sending and receiving,
118 we don't need to register this interface twice. */
119 #ifndef USE_UPF_RECEIVE
120 info
-> wfdesc
= if_register_upf (info
, interface
);
122 info
-> wfdesc
= info
-> rfdesc
;
124 if (!quiet_interface_discovery
)
125 log_info ("Sending on UPF/%s/%s%s%s",
127 print_hw_addr (info
-> hw_address
.hbuf
[0],
128 info
-> hw_address
.hlen
- 1,
129 &info
-> hw_address
.hbuf
[1]),
130 (info
-> shared_network
? "/" : ""),
131 (info
-> shared_network
?
132 info
-> shared_network
-> name
: ""));
135 void if_deregister_send (info
)
136 struct interface_info
*info
;
138 #ifndef USE_UPF_RECEIVE
139 close (info
-> wfdesc
);
142 if (!quiet_interface_discovery
)
143 log_info ("Disabling output on UPF/%s/%s%s%s",
145 print_hw_addr (info
-> hw_address
.hbuf
[0],
146 info
-> hw_address
.hlen
- 1,
147 &info
-> hw_address
.hbuf
[1]),
148 (info
-> shared_network
? "/" : ""),
149 (info
-> shared_network
?
150 info
-> shared_network
-> name
: ""));
152 #endif /* USE_UPF_SEND */
154 #ifdef USE_UPF_RECEIVE
155 /* Packet filter program...
156 XXX Changes to the filter program may require changes to the constant
157 offsets used in if_register_send to patch the UPF program! XXX */
159 #if defined(RELAY_PORT)
160 #error "Relay port is not yet supported for UPF"
163 void if_register_receive (info
)
164 struct interface_info
*info
;
171 /* Open a UPF device and hang it on this interface... */
172 info
-> rfdesc
= if_register_upf (info
);
174 /* Allow the copyall flag to be set... */
175 if (ioctl(info
-> rfdesc
, EIOCALLOWCOPYALL
, &flag
) < 0)
176 log_fatal ("Can't set ALLOWCOPYALL: %m");
178 /* Clear all the packet filter mode bits first... */
179 flag
= (ENHOLDSIG
| ENBATCH
| ENTSTAMP
| ENPROMISC
|
180 ENNONEXCL
| ENCOPYALL
);
181 if (ioctl (info
-> rfdesc
, EIOCMBIC
, &flag
) < 0)
182 log_fatal ("Can't clear pfilt bits: %m");
184 /* Set the ENBATCH and ENCOPYALL bits... */
185 bits
= ENBATCH
| ENCOPYALL
;
186 if (ioctl (info
-> rfdesc
, EIOCMBIS
, &bits
) < 0)
187 log_fatal ("Can't set ENBATCH|ENCOPYALL: %m");
189 /* Set up the UPF filter program. */
190 /* XXX Unlike the BPF filter program, this one won't work if the
191 XXX IP packet is fragmented or if there are options on the IP
194 pf
.enf_FilterLen
= 0;
196 pf
.enf_Filter
[pf
.enf_FilterLen
++] = ENF_PUSHWORD
+ 6;
197 pf
.enf_Filter
[pf
.enf_FilterLen
++] = ENF_PUSHLIT
+ ENF_CAND
;
198 pf
.enf_Filter
[pf
.enf_FilterLen
++] = htons (ETHERTYPE_IP
);
199 pf
.enf_Filter
[pf
.enf_FilterLen
++] = ENF_PUSHLIT
;
200 pf
.enf_Filter
[pf
.enf_FilterLen
++] = htons (IPPROTO_UDP
);
201 pf
.enf_Filter
[pf
.enf_FilterLen
++] = ENF_PUSHWORD
+ 11;
202 pf
.enf_Filter
[pf
.enf_FilterLen
++] = ENF_PUSHLIT
+ ENF_AND
;
203 pf
.enf_Filter
[pf
.enf_FilterLen
++] = htons (0xFF);
204 pf
.enf_Filter
[pf
.enf_FilterLen
++] = ENF_CAND
;
205 pf
.enf_Filter
[pf
.enf_FilterLen
++] = ENF_PUSHWORD
+ 18;
206 pf
.enf_Filter
[pf
.enf_FilterLen
++] = ENF_PUSHLIT
+ ENF_CAND
;
207 pf
.enf_Filter
[pf
.enf_FilterLen
++] = local_port
;
209 if (ioctl (info
-> rfdesc
, EIOCSETF
, &pf
) < 0)
210 log_fatal ("Can't install packet filter program: %m");
211 if (!quiet_interface_discovery
)
212 log_info ("Listening on UPF/%s/%s%s%s",
214 print_hw_addr (info
-> hw_address
.hbuf
[0],
215 info
-> hw_address
.hlen
- 1,
216 &info
-> hw_address
.hbuf
[1]),
217 (info
-> shared_network
? "/" : ""),
218 (info
-> shared_network
?
219 info
-> shared_network
-> name
: ""));
222 void if_deregister_receive (info
)
223 struct interface_info
*info
;
225 close (info
-> rfdesc
);
227 if (!quiet_interface_discovery
)
228 log_info ("Disabling input on UPF/%s/%s%s%s",
230 print_hw_addr (info
-> hw_address
.hbuf
[0],
231 info
-> hw_address
.hlen
- 1,
232 &info
-> hw_address
.hbuf
[1]),
233 (info
-> shared_network
? "/" : ""),
234 (info
-> shared_network
?
235 info
-> shared_network
-> name
: ""));
237 #endif /* USE_UPF_RECEIVE */
240 ssize_t
send_packet (interface
, packet
, raw
, len
, from
, to
, hto
)
241 struct interface_info
*interface
;
242 struct packet
*packet
;
243 struct dhcp_packet
*raw
;
246 struct sockaddr_in
*to
;
247 struct hardware
*hto
;
249 unsigned hbufp
= 0, ibufp
= 0;
252 struct iovec iov
[3];
256 if (!strcmp (interface
-> name
, "fallback"))
257 return send_fallback (interface
, packet
, raw
,
260 if (hto
== NULL
&& interface
->anycast_mac_addr
.hlen
)
261 hto
= &interface
->anycast_mac_addr
;
263 /* Assemble the headers... */
264 assemble_hw_header (interface
, (unsigned char *)hw
, &hbufp
, hto
);
265 assemble_udp_ip_header (interface
,
266 (unsigned char *)ip
, &ibufp
, from
.s_addr
,
267 to
-> sin_addr
.s_addr
, to
-> sin_port
,
268 (unsigned char *)raw
, len
);
271 iov
[0].iov_base
= ((char *)hw
);
272 iov
[0].iov_len
= hbufp
;
273 iov
[1].iov_base
= ((char *)ip
);
274 iov
[1].iov_len
= ibufp
;
275 iov
[2].iov_base
= (char *)raw
;
276 iov
[2].iov_len
= len
;
278 result
= writev(interface
-> wfdesc
, iov
, 3);
280 log_error ("send_packet: %m");
283 #endif /* USE_UPF_SEND */
285 #ifdef USE_UPF_RECEIVE
286 ssize_t
receive_packet (interface
, buf
, len
, from
, hfrom
)
287 struct interface_info
*interface
;
290 struct sockaddr_in
*from
;
291 struct hardware
*hfrom
;
296 unsigned char ibuf
[1500 + sizeof (struct enstamp
)];
300 length
= read (interface
-> rfdesc
, ibuf
, sizeof ibuf
);
304 bufix
= sizeof (struct enstamp
);
305 /* Decode the physical header... */
306 offset
= decode_hw_header (interface
, ibuf
, bufix
, hfrom
);
308 /* If a physical layer checksum failed (dunno of any
309 physical layer that supports this, but WTH), skip this
318 /* Decode the IP and UDP headers... */
319 offset
= decode_udp_ip_header (interface
, ibuf
, bufix
,
320 from
, length
, &paylen
, 1);
322 /* If the IP or UDP checksum was bad, skip the packet... */
330 log_fatal("Internal inconsistency at %s:%d.", MDL
);
332 /* Copy out the data in the packet... */
333 memcpy (buf
, &ibuf
[bufix
], paylen
);
337 int can_unicast_without_arp (ip
)
338 struct interface_info
*ip
;
343 int can_receive_unicast_unconfigured (ip
)
344 struct interface_info
*ip
;
349 int supports_multiple_interfaces (ip
)
350 struct interface_info
*ip
;
355 void maybe_setup_fallback ()
358 struct interface_info
*fbi
= (struct interface_info
*)0;
359 if (setup_fallback (&fbi
, MDL
)) {
360 if_register_fallback (fbi
);
361 status
= omapi_register_io_object ((omapi_object_t
*)fbi
,
363 fallback_discard
, 0, 0);
364 if (status
!= ISC_R_SUCCESS
)
365 log_fatal ("Can't register I/O handle for %s: %s",
366 fbi
-> name
, isc_result_totext (status
));
367 interface_dereference (&fbi
, MDL
);