2 * Copyright (C) 2016 David Decotigny <ddecotig@gmail.com>
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include <ipxe/linux_api.h>
23 #include <ipxe/list.h>
24 #include <ipxe/linux.h>
25 #include <ipxe/malloc.h>
26 #include <ipxe/device.h>
27 #include <ipxe/netdevice.h>
28 #include <ipxe/iobuf.h>
29 #include <ipxe/ethernet.h>
30 #include <ipxe/settings.h>
31 #include <ipxe/socket.h>
33 /* This hack prevents pre-2.6.32 headers from redefining struct sockaddr */
36 #include <linux/socket.h>
38 #include <linux/if_ether.h>
39 #include <linux/if_packet.h>
43 /* linux-specifc syscall params */
44 #define LINUX_AF_PACKET 17
45 #define LINUX_SOCK_RAW 3
46 #define LINUX_SIOCGIFINDEX 0x8933
47 #define LINUX_SIOCGIFHWADDR 0x8927
49 #define RX_BUF_SIZE 1536
53 * The AF_PACKET driver.
55 * Bind to an existing linux network interface.
58 struct af_packet_nic
{
59 /** Linux network interface name */
61 /** Packet socket descriptor */
67 /** Open the linux interface */
68 static int af_packet_nic_open ( struct net_device
* netdev
)
70 struct af_packet_nic
* nic
= netdev
->priv
;
71 struct sockaddr_ll socket_address
;
75 nic
->fd
= linux_socket(LINUX_AF_PACKET
, LINUX_SOCK_RAW
,
78 DBGC(nic
, "af_packet %p socket(AF_PACKET) = %d (%s)\n",
79 nic
, nic
->fd
, linux_strerror(linux_errno
));
83 /* resolve ifindex of ifname */
84 memset(&if_data
, 0, sizeof(if_data
));
85 strncpy(if_data
.ifr_name
, nic
->ifname
, sizeof(if_data
.ifr_name
));
86 ret
= linux_ioctl(nic
->fd
, LINUX_SIOCGIFINDEX
, &if_data
);
88 DBGC(nic
, "af_packet %p ioctl(SIOCGIFINDEX) = %d (%s)\n",
89 nic
, ret
, linux_strerror(linux_errno
));
94 nic
->ifindex
= if_data
.ifr_ifindex
;
96 /* bind to interface */
97 memset(&socket_address
, 0, sizeof(socket_address
));
98 socket_address
.sll_family
= LINUX_AF_PACKET
;
99 socket_address
.sll_ifindex
= nic
->ifindex
;
100 socket_address
.sll_protocol
= htons(ETH_P_ALL
);
101 ret
= linux_bind(nic
->fd
, (void *) &socket_address
,
102 sizeof(socket_address
));
104 DBGC(nic
, "af_packet %p bind() = %d (%s)\n",
105 nic
, ret
, linux_strerror(linux_errno
));
106 linux_close(nic
->fd
);
110 /* Set nonblocking mode to make af_packet_nic_poll() easier */
111 ret
= linux_fcntl(nic
->fd
, F_SETFL
, O_NONBLOCK
);
113 DBGC(nic
, "af_packet %p fcntl(%d, ...) = %d (%s)\n",
114 nic
, nic
->fd
, ret
, linux_strerror(linux_errno
));
115 linux_close(nic
->fd
);
122 /** Close the packet socket */
123 static void af_packet_nic_close ( struct net_device
*netdev
)
125 struct af_packet_nic
* nic
= netdev
->priv
;
126 linux_close(nic
->fd
);
130 * Transmit an ethernet packet.
132 * The packet can be written to the socket and marked as complete immediately.
134 static int af_packet_nic_transmit ( struct net_device
*netdev
,
135 struct io_buffer
*iobuf
)
137 struct af_packet_nic
* nic
= netdev
->priv
;
138 struct sockaddr_ll socket_address
;
139 const struct ethhdr
* eh
;
142 memset(&socket_address
, 0, sizeof(socket_address
));
143 socket_address
.sll_family
= LINUX_AF_PACKET
;
144 socket_address
.sll_ifindex
= nic
->ifindex
;
145 socket_address
.sll_halen
= ETH_ALEN
;
148 memcpy(socket_address
.sll_addr
, eh
->h_dest
, ETH_ALEN
);
150 rc
= linux_sendto(nic
->fd
, iobuf
->data
, iobuf
->tail
- iobuf
->data
,
151 0, (struct sockaddr
*)&socket_address
,
152 sizeof(socket_address
));
154 DBGC2(nic
, "af_packet %p wrote %d bytes\n", nic
, rc
);
155 netdev_tx_complete(netdev
, iobuf
);
160 /** Poll for new packets */
161 static void af_packet_nic_poll ( struct net_device
*netdev
)
163 struct af_packet_nic
* nic
= netdev
->priv
;
165 struct io_buffer
* iobuf
;
170 if (linux_poll(&pfd
, 1, 0) == -1) {
171 DBGC(nic
, "af_packet %p poll failed (%s)\n",
172 nic
, linux_strerror(linux_errno
));
175 if ((pfd
.revents
& POLLIN
) == 0)
178 /* At this point we know there is at least one new packet to be read */
180 iobuf
= alloc_iob(RX_BUF_SIZE
);
184 while ((r
= linux_read(nic
->fd
, iobuf
->data
, RX_BUF_SIZE
)) > 0) {
185 DBGC2(nic
, "af_packet %p read %d bytes\n", nic
, r
);
188 netdev_rx(netdev
, iobuf
);
190 iobuf
= alloc_iob(RX_BUF_SIZE
);
199 DBGC(nic
, "af_packet %p alloc_iob failed\n", nic
);
205 * Not used on linux, provide a dummy implementation.
207 static void af_packet_nic_irq ( struct net_device
*netdev
, int enable
)
209 struct af_packet_nic
*nic
= netdev
->priv
;
211 DBGC(nic
, "af_packet %p irq enable = %d\n", nic
, enable
);
215 static int af_packet_update_properties ( struct net_device
*netdev
)
217 struct af_packet_nic
*nic
= netdev
->priv
;
218 struct ifreq if_data
;
221 /* retrieve default MAC address */
222 int fd
= linux_socket(LINUX_AF_PACKET
, LINUX_SOCK_RAW
, 0);
224 DBGC(nic
, "af_packet %p cannot create raw socket (%s)\n",
225 nic
, linux_strerror(linux_errno
));
229 /* retrieve host's MAC address */
230 memset(&if_data
, 0, sizeof(if_data
));
231 strncpy(if_data
.ifr_name
, nic
->ifname
, sizeof(if_data
.ifr_name
));
232 ret
= linux_ioctl(fd
, LINUX_SIOCGIFHWADDR
, &if_data
);
234 DBGC(nic
, "af_packet %p cannot get mac addr (%s)\n",
235 nic
, linux_strerror(linux_errno
));
241 /* struct sockaddr = { u16 family, u8 pad[14] (equiv. sa_data) }; */
242 memcpy(netdev
->ll_addr
, if_data
.ifr_hwaddr
.pad
, ETH_ALEN
);
246 /** AF_PACKET operations */
247 static struct net_device_operations af_packet_nic_operations
= {
248 .open
= af_packet_nic_open
,
249 .close
= af_packet_nic_close
,
250 .transmit
= af_packet_nic_transmit
,
251 .poll
= af_packet_nic_poll
,
252 .irq
= af_packet_nic_irq
,
255 /** Handle a device request for the af_packet driver */
256 static int af_packet_nic_probe ( struct linux_device
*device
,
257 struct linux_device_request
*request
)
259 struct linux_setting
*if_setting
;
260 struct net_device
*netdev
;
261 struct af_packet_nic
*nic
;
264 netdev
= alloc_etherdev(sizeof(*nic
));
268 netdev_init(netdev
, &af_packet_nic_operations
);
270 linux_set_drvdata(device
, netdev
);
271 netdev
->dev
= &device
->dev
;
273 memset(nic
, 0, sizeof(*nic
));
275 /* Look for the mandatory if setting */
276 if_setting
= linux_find_setting("if", &request
->settings
);
280 printf("af_packet missing a mandatory if setting\n");
285 nic
->ifname
= if_setting
->value
;
286 snprintf ( device
->dev
.name
, sizeof ( device
->dev
.name
), "%s",
288 device
->dev
.desc
.bus_type
= BUS_TYPE_TAP
;
289 af_packet_update_properties(netdev
);
290 if_setting
->applied
= 1;
292 /* Apply rest of the settings */
293 linux_apply_settings(&request
->settings
, &netdev
->settings
.settings
);
295 /* Register network device */
296 if ((rc
= register_netdev(netdev
)) != 0)
299 netdev_link_up(netdev
);
304 unregister_netdev(netdev
);
306 netdev_nullify(netdev
);
311 /** Remove the device */
312 static void af_packet_nic_remove ( struct linux_device
*device
)
314 struct net_device
*netdev
= linux_get_drvdata(device
);
315 unregister_netdev(netdev
);
316 netdev_nullify(netdev
);
320 /** AF_PACKET linux_driver */
321 struct linux_driver af_packet_nic_driver __linux_driver
= {
323 .probe
= af_packet_nic_probe
,
324 .remove
= af_packet_nic_remove
,