NETDEV_PROMISC = 0x0002 /* Promiscuous mode? */
};
+enum netdev_pseudo_ethertype {
+ NETDEV_ETH_TYPE_NONE = -128, /* Receive no frames. */
+ NETDEV_ETH_TYPE_ANY, /* Receive all frames. */
+ NETDEV_ETH_TYPE_802_2 /* Receive all IEEE 802.2 frames. */
+};
+
struct netdev;
-int netdev_open(const char *name, struct netdev **);
+int netdev_open(const char *name, int ethertype, struct netdev **);
void netdev_close(struct netdev *);
int netdev_recv(struct netdev *, struct buffer *);
void netdev_recv_wait(struct netdev *);
/* Opens the network device named 'name' (e.g. "eth0") and returns zero if
* successful, otherwise a positive errno value. On success, sets '*netdev'
- * to the new network device, otherwise to null. */
+ * to the new network device, otherwise to null.
+ *
+ * 'ethertype' may be a 16-bit Ethernet protocol value in host byte order to
+ * capture frames of that type received on the device. It may also be one of
+ * the 'enum netdev_pseudo_ethertype' values to receive frames in one of those
+ * categories. */
int
-netdev_open(const char *name, struct netdev **netdev_)
+netdev_open(const char *name, int ethertype, struct netdev **netdev_)
{
int fd;
struct sockaddr sa;
* We have to use SOCK_PACKET, despite its deprecation, because only
* SOCK_PACKET lets us set the hardware source address of outgoing
* packets. */
- fd = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ALL));
+ fd = socket(PF_PACKET, SOCK_PACKET,
+ htons(ethertype == NETDEV_ETH_TYPE_NONE ? 0
+ : ethertype == NETDEV_ETH_TYPE_ANY ? ETH_P_ALL
+ : ethertype == NETDEV_ETH_TYPE_802_2 ? ETH_P_802_2
+ : ethertype));
if (fd < 0) {
return errno;
}
}
snprintf(of_name, sizeof of_name, "of%s", nl_name + 3);
- retval = netdev_open(of_name, &of_device);
+ retval = netdev_open(of_name, NETDEV_ETH_TYPE_NONE, &of_device);
if (!retval) {
enum netdev_flags flags;
retval = netdev_get_flags(of_device, &flags);