@@ -22,9 +22,9 @@ LDFLAGS_pcap.o := -r $(shell $(CC) $(KBUILD_CFLAGS) -print-file-name=libpcap.a)
LDFLAGS_vde.o := -r $(shell $(CC) $(CFLAGS) -print-file-name=libvdeplug.a)
-targets := pcap_kern.o pcap_user.o vde_kern.o vde_user.o
+targets := pcap_user.o vde_kern.o vde_user.o
-$(obj)/pcap.o: $(obj)/pcap_kern.o $(obj)/pcap_user.o
+$(obj)/pcap.o: $(obj)/pcap_user.o
$(LD) -r -dp -o $@ $^ $(ld_flags)
$(obj)/vde.o: $(obj)/vde_kern.o $(obj)/vde_user.o
@@ -42,6 +42,9 @@ static DEFINE_SPINLOCK(drop_lock);
static struct sk_buff *drop_skb;
static int drop_max;
+static const char *migrated_to_vector = {"pcap"};
+#define MAX_MIGRATED 1
+
static int update_drop_skb(int max)
{
struct sk_buff *new;
@@ -581,6 +584,26 @@ static int check_transport(struct transport *transport, char *eth, int n,
}
return 1;
}
+static int register_compat(void)
+{
+ struct list_head *ele, *next;
+ struct eth_init *eth;
+ int compat;
+
+ list_for_each_safe(ele, next, ð_cmd_line) {
+ eth = list_entry(ele, struct eth_init, list);
+ for (compat = 0; compat < MAX_MIGRATED; compat++) {
+ if (strncmp(eth->init, &migrated_to_vector[compat], strlen(&migrated_to_vector[compat])) == 0) {
+ vector_compat_eth_configure(eth->init, eth->index);
+ list_del(ð->list);
+ continue;
+ }
+ }
+ }
+ return 0;
+}
+
+late_initcall(register_compat);
void register_transport(struct transport *new)
{
@@ -597,8 +620,9 @@ void register_transport(struct transport *new)
list_for_each_safe(ele, next, ð_cmd_line) {
eth = list_entry(ele, struct eth_init, list);
+
match = check_transport(new, eth->init, eth->index, &init,
- &mac, GFP_KERNEL);
+ &mac, GFP_KERNEL);
if (!match)
continue;
else if (init != NULL) {
@@ -615,7 +639,12 @@ static int eth_setup_common(char *str, int index)
struct transport *transport;
void *init;
char *mac = NULL;
- int found = 0;
+ int found = 0, compat;
+
+ for (compat = 0; compat < MAX_MIGRATED; compat++) {
+ if (strncmp(str, &migrated_to_vector[compat], strlen(&migrated_to_vector[compat])) == 0)
+ return vector_compat_eth_configure(str, index);
+ }
spin_lock(&transports_lock);
list_for_each(ele, &transports) {
deleted file mode 100644
@@ -1,113 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- */
-
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <net_kern.h>
-#include "pcap_user.h"
-
-struct pcap_init {
- char *host_if;
- int promisc;
- int optimize;
- char *filter;
-};
-
-void pcap_init(struct net_device *dev, void *data)
-{
- struct uml_net_private *pri;
- struct pcap_data *ppri;
- struct pcap_init *init = data;
-
- pri = netdev_priv(dev);
- ppri = (struct pcap_data *) pri->user;
- ppri->host_if = init->host_if;
- ppri->promisc = init->promisc;
- ppri->optimize = init->optimize;
- ppri->filter = init->filter;
-
- printk("pcap backend, host interface %s\n", ppri->host_if);
-}
-
-static int pcap_read(int fd, struct sk_buff *skb, struct uml_net_private *lp)
-{
- return pcap_user_read(fd, skb_mac_header(skb),
- skb->dev->mtu + ETH_HEADER_OTHER,
- (struct pcap_data *) &lp->user);
-}
-
-static int pcap_write(int fd, struct sk_buff *skb, struct uml_net_private *lp)
-{
- return -EPERM;
-}
-
-static const struct net_kern_info pcap_kern_info = {
- .init = pcap_init,
- .protocol = eth_protocol,
- .read = pcap_read,
- .write = pcap_write,
-};
-
-int pcap_setup(char *str, char **mac_out, void *data)
-{
- struct pcap_init *init = data;
- char *remain, *host_if = NULL, *options[2] = { NULL, NULL };
- int i;
-
- *init = ((struct pcap_init)
- { .host_if = "eth0",
- .promisc = 1,
- .optimize = 0,
- .filter = NULL });
-
- remain = split_if_spec(str, &host_if, &init->filter,
- &options[0], &options[1], mac_out, NULL);
- if (remain != NULL) {
- printk(KERN_ERR "pcap_setup - Extra garbage on "
- "specification : '%s'\n", remain);
- return 0;
- }
-
- if (host_if != NULL)
- init->host_if = host_if;
-
- for (i = 0; i < ARRAY_SIZE(options); i++) {
- if (options[i] == NULL)
- continue;
- if (!strcmp(options[i], "promisc"))
- init->promisc = 1;
- else if (!strcmp(options[i], "nopromisc"))
- init->promisc = 0;
- else if (!strcmp(options[i], "optimize"))
- init->optimize = 1;
- else if (!strcmp(options[i], "nooptimize"))
- init->optimize = 0;
- else {
- printk(KERN_ERR "pcap_setup : bad option - '%s'\n",
- options[i]);
- return 0;
- }
- }
-
- return 1;
-}
-
-static struct transport pcap_transport = {
- .list = LIST_HEAD_INIT(pcap_transport.list),
- .name = "pcap",
- .setup = pcap_setup,
- .user = &pcap_user_info,
- .kern = &pcap_kern_info,
- .private_size = sizeof(struct pcap_data),
- .setup_size = sizeof(struct pcap_init),
-};
-
-static int register_pcap(void)
-{
- register_transport(&pcap_transport);
- return 0;
-}
-
-late_initcall(register_pcap);
@@ -8,130 +8,50 @@
#include <string.h>
#include <asm/types.h>
#include <net_user.h>
-#include "pcap_user.h"
+#include <sys/socket.h>
+#include <linux/filter.h>
#include <um_malloc.h>
-#define PCAP_FD(p) (*(int *)(p))
-
-static int pcap_user_init(void *data, void *dev)
+void *uml_vector_compile_pcap(char *filter, int optimize)
{
- struct pcap_data *pri = data;
- pcap_t *p;
- char errors[PCAP_ERRBUF_SIZE];
-
- p = pcap_open_live(pri->host_if, ETH_MAX_PACKET + ETH_HEADER_OTHER,
- pri->promisc, 0, errors);
- if (p == NULL) {
- printk(UM_KERN_ERR "pcap_user_init : pcap_open_live failed - "
- "'%s'\n", errors);
- return -EINVAL;
- }
+ struct sock_fprog *bpf_prog = NULL;
+ struct bpf_program *pcap_prog = NULL;
- pri->dev = dev;
- pri->pcap = p;
- return 0;
-}
-
-static int pcap_open(void *data)
-{
- struct pcap_data *pri = data;
- __u32 netmask;
- int err;
+ if (filter == NULL)
+ return NULL;
- if (pri->pcap == NULL)
- return -ENODEV;
+ pcap_prog = uml_kmalloc(sizeof(struct bpf_program), UM_GFP_KERNEL);
+ if (!pcap_prog)
+ goto pcap_failed;
- if (pri->filter != NULL) {
- err = dev_netmask(pri->dev, &netmask);
- if (err < 0) {
- printk(UM_KERN_ERR "pcap_open : dev_netmask failed\n");
- return -EIO;
- }
+ bpf_prog = uml_kmalloc(sizeof(struct sock_fprog), UM_GFP_KERNEL);
+ if (!bpf_prog)
+ goto pcap_failed;
+ else
+ bpf_prog->filter = NULL;
- pri->compiled = uml_kmalloc(sizeof(struct bpf_program),
- UM_GFP_KERNEL);
- if (pri->compiled == NULL) {
- printk(UM_KERN_ERR "pcap_open : kmalloc failed\n");
- return -ENOMEM;
- }
-
- err = pcap_compile(pri->pcap,
- (struct bpf_program *) pri->compiled,
- pri->filter, pri->optimize, netmask);
- if (err < 0) {
- printk(UM_KERN_ERR "pcap_open : pcap_compile failed - "
- "'%s'\n", pcap_geterr(pri->pcap));
- goto out;
- }
-
- err = pcap_setfilter(pri->pcap, pri->compiled);
- if (err < 0) {
- printk(UM_KERN_ERR "pcap_open : pcap_setfilter "
- "failed - '%s'\n", pcap_geterr(pri->pcap));
- goto out;
- }
+ if (pcap_compile_nopcap((1 < 16) - 1, DLT_EN10MB, pcap_prog, filter, optimize, PCAP_NETMASK_UNKNOWN)) {
+ printk(KERN_ERR "Failed to compile filter");
+ goto pcap_failed;
}
- return PCAP_FD(pri->pcap);
-
- out:
- kfree(pri->compiled);
- return -EIO;
-}
-
-static void pcap_remove(void *data)
-{
- struct pcap_data *pri = data;
-
- if (pri->compiled != NULL)
- pcap_freecode(pri->compiled);
-
- if (pri->pcap != NULL)
- pcap_close(pri->pcap);
-}
-
-struct pcap_handler_data {
- char *buffer;
- int len;
-};
+ bpf_prog->filter = uml_kmalloc(pcap_prog->bf_len * sizeof(struct bpf_insn), UM_GFP_KERNEL);
-static void handler(u_char *data, const struct pcap_pkthdr *header,
- const u_char *packet)
-{
- int len;
+ if (bpf_prog->filter == NULL) {
+ printk(KERN_ERR "Failed to allocate bpf buffer");
+ pcap_freecode(pcap_prog);
+ goto pcap_failed;
+ }
+ bpf_prog->len = pcap_prog->bf_len;
+ memcpy(bpf_prog->filter, pcap_prog->bf_insns, pcap_prog->bf_len * sizeof(struct bpf_insn));
- struct pcap_handler_data *hdata = (struct pcap_handler_data *) data;
+ pcap_freecode(pcap_prog);
+ return bpf_prog;
- len = hdata->len < header->caplen ? hdata->len : header->caplen;
- memcpy(hdata->buffer, packet, len);
- hdata->len = len;
+pcap_failed:
+ kfree(pcap_prog);
+ kfree(bpf_prog);
+ return NULL;
}
-int pcap_user_read(int fd, void *buffer, int len, struct pcap_data *pri)
-{
- struct pcap_handler_data hdata = ((struct pcap_handler_data)
- { .buffer = buffer,
- .len = len });
- int n;
-
- n = pcap_dispatch(pri->pcap, 1, handler, (u_char *) &hdata);
- if (n < 0) {
- printk(UM_KERN_ERR "pcap_dispatch failed - %s\n",
- pcap_geterr(pri->pcap));
- return -EIO;
- }
- else if (n == 0)
- return 0;
- return hdata.len;
-}
-const struct net_user_info pcap_user_info = {
- .init = pcap_user_init,
- .open = pcap_open,
- .close = NULL,
- .remove = pcap_remove,
- .add_address = NULL,
- .delete_address = NULL,
- .mtu = ETH_MAX_PACKET,
- .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER,
-};
deleted file mode 100644
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- */
-
-#include <net_user.h>
-
-struct pcap_data {
- char *host_if;
- int promisc;
- int optimize;
- char *filter;
- void *compiled;
- void *pcap;
- void *dev;
-};
-
-extern const struct net_user_info pcap_user_info;
-
-extern int pcap_user_read(int fd, void *buf, int len, struct pcap_data *pri);
-
@@ -28,6 +28,7 @@
#include <irq_kern.h>
#include <irq_user.h>
#include <net_kern.h>
+#include <net_user.h>
#include <os.h>
#include "mconsole_kern.h"
#include "vector_user.h"
@@ -46,6 +47,7 @@
#define DRIVER_NAME "uml-vector"
+#define DRIVER_CNAME "uml-vector-compat"
#define DRIVER_VERSION "01"
struct vector_cmd_line_arg {
struct list_head list;
@@ -68,7 +70,7 @@ static LIST_HEAD(vector_devices);
static int driver_registered;
-static void vector_eth_configure(int n, struct arglist *def);
+static void vector_eth_configure(int n, struct arglist *def, bool compat);
/* Argument accessors to set variables (and/or set default values)
* mtu, buffer sizing, default headroom, etc
@@ -101,6 +103,7 @@ static const struct {
};
#define VECTOR_NUM_STATS ARRAY_SIZE(ethtool_stats_keys)
+#define MAX_COMPAT_ARG 256
static void vector_reset_stats(struct vector_private *vp)
{
@@ -131,11 +134,28 @@ static int get_mtu(struct arglist *def)
return ETH_MAX_PACKET;
}
+static int get_optimize(struct arglist *def)
+{
+ char *opt = uml_vector_fetch_arg(def, "optimize");
+ long result;
+
+ if (opt != NULL) {
+ if (kstrtoul(opt, 10, &result) == 0)
+ return result;
+ }
+ return 0;
+}
+
static char *get_bpf_file(struct arglist *def)
{
return uml_vector_fetch_arg(def, "bpffile");
}
+static char *get_pcap_filter(struct arglist *def)
+{
+ return uml_vector_fetch_arg(def, "filter");
+}
+
static bool get_bpf_flash(struct arglist *def)
{
char *allow = uml_vector_fetch_arg(def, "bpfflash");
@@ -772,7 +792,7 @@ static int vector_config(char *str, char **error_out)
return -EINVAL;
}
- vector_eth_configure(n, parsed);
+ vector_eth_configure(n, parsed, false);
return 0;
}
@@ -1225,7 +1245,14 @@ static int vector_net_open(struct net_device *dev)
vp->opened = true;
spin_unlock_irqrestore(&vp->lock, flags);
- vp->bpf = uml_vector_user_bpf(get_bpf_file(vp->parsed));
+#ifdef CONFIG_UML_NET_PCAP
+ vp->bpf = uml_vector_compile_pcap(get_pcap_filter(vp->parsed), get_optimize(vp->parsed));
+#else
+ vp->bpf = NULL;
+#endif
+
+ if (!vp->bpf)
+ vp->bpf = uml_vector_user_bpf(get_bpf_file(vp->parsed));
vp->fds = uml_vector_user_open(vp->unit, vp->parsed);
@@ -1547,7 +1574,8 @@ static void vector_timer_expire(struct timer_list *t)
static void vector_eth_configure(
int n,
- struct arglist *def
+ struct arglist *def,
+ bool compat
)
{
struct vector_device *device;
@@ -1577,7 +1605,10 @@ static void vector_eth_configure(
* netdevice, that is OK, register_netdev{,ice}() will notice this
* and fail.
*/
- snprintf(dev->name, sizeof(dev->name), "vec%d", n);
+ if (compat)
+ snprintf(dev->name, sizeof(dev->name), "eth%d", n);
+ else
+ snprintf(dev->name, sizeof(dev->name), "vec%d", n);
uml_net_setup_etheraddr(dev, uml_vector_fetch_arg(def, "mac"));
vp = netdev_priv(dev);
@@ -1587,7 +1618,10 @@ static void vector_eth_configure(
driver_registered = 1;
}
device->pdev.id = n;
- device->pdev.name = DRIVER_NAME;
+ if (compat)
+ device->pdev.name = DRIVER_CNAME;
+ else
+ device->pdev.name = DRIVER_NAME;
device->pdev.dev.release = vector_device_release;
dev_set_drvdata(&device->pdev.dev, device);
if (platform_device_register(&device->pdev))
@@ -1660,7 +1694,59 @@ static void vector_eth_configure(
kfree(device);
}
+int vector_compat_eth_configure(char *str, int index)
+{
+ char *newargs, *tempargs;
+ char *remain;
+ int do_compat = 0;
+ struct arglist *parsed;
+ newargs = kmalloc(GFP_KERNEL, MAX_COMPAT_ARG);
+ if (!newargs)
+ return -ENOMEM;
+ tempargs = kmalloc(GFP_KERNEL, MAX_COMPAT_ARG);
+ if (!tempargs) {
+ kfree(newargs);
+ return -ENOMEM;
+ }
+ if (strncmp(str, "pcap", strlen("pcap")) == 0) {
+ char *ifname = NULL, *filter = NULL, *transport = NULL, *mac = NULL;
+ char *options[2] = { NULL, NULL};
+
+ remain = split_if_spec(str, &transport, &ifname, &filter,
+ &options[0], &options[1], &mac, NULL);
+
+ if ((mac != NULL) && strlen(mac) > 0)
+ snprintf(tempargs, MAX_COMPAT_ARG, "transport=raw,ifname=%s,mac=%s", ifname, mac);
+ else
+ snprintf(tempargs, MAX_COMPAT_ARG, "transport=raw,ifname=%s", ifname);
+
+ strcpy(newargs, tempargs);
+
+ if (filter != NULL) {
+ snprintf(tempargs, MAX_COMPAT_ARG, "%s,filter=%s", newargs, filter);
+ strcpy(newargs, tempargs);
+ }
+ if (options[0] != NULL) {
+ snprintf(tempargs, MAX_COMPAT_ARG, "%s,%s=1", newargs, options[0]);
+ strcpy(newargs, tempargs);
+ }
+ if (options[1] != NULL) {
+ snprintf(tempargs, MAX_COMPAT_ARG, "%s,%s=1", newargs, options[1]);
+ strcpy(newargs, tempargs);
+ }
+ do_compat = 1;
+
+ }
+ if (do_compat) {
+ parsed = uml_parse_vector_ifspec(newargs);
+ vector_eth_configure(index, parsed, true);
+ } else
+ kfree(newargs);
+
+ kfree(tempargs);
+ return 0;
+}
/*
@@ -1677,7 +1763,7 @@ static int __init vector_init(void)
def = list_entry(ele, struct vector_cmd_line_arg, list);
parsed = uml_parse_vector_ifspec(def->arguments);
if (parsed != NULL)
- vector_eth_configure(def->unit, parsed);
+ vector_eth_configure(def->unit, parsed, false);
}
return 0;
}
@@ -31,9 +31,6 @@
#define VECTOR_QDISC_BYPASS (1 << 3)
#define VECTOR_BPF_FLASH (1 << 4)
-#define ETH_MAX_PACKET 1500
-#define ETH_HEADER_OTHER 32 /* just in case someone decides to go mad on QnQ */
-
#define MAX_FILTER_PROG (2 << 16)
struct vector_queue {
@@ -367,6 +367,17 @@ static struct vector_fds *user_init_raw_fds(struct arglist *ifspec)
err = -errno;
goto raw_cleanup;
}
+
+ if (uml_vector_fetch_arg(ifspec, "promisc")) {
+ struct ifreq ifopts;
+
+ memset(&ifopts, 0, sizeof(struct ifreq));
+ strncpy(ifopts.ifr_name, iface, IFNAMSIZ-1);
+ ioctl(rxfd, SIOCGIFFLAGS, &ifopts);
+ ifopts.ifr_flags |= IFF_PROMISC;
+ ioctl(rxfd, SIOCSIFFLAGS, &ifopts);
+ }
+
txfd = create_raw_fd(iface, 0, ETH_P_IP); /* Turn off RX on this fd */
if (txfd == -1) {
err = -errno;
@@ -764,3 +775,4 @@ void *uml_vector_user_bpf(char *filename)
kfree(bpf_prog);
return NULL;
}
+
@@ -105,5 +105,4 @@ extern bool uml_raw_enable_qdisc_bypass(int fd);
extern bool uml_raw_enable_vnet_headers(int fd);
extern bool uml_tap_enable_vnet_headers(int fd);
-
#endif
@@ -66,6 +66,6 @@ extern int tap_setup_common(char *str, char *type, char **dev_name,
extern void register_transport(struct transport *new);
extern unsigned short eth_protocol(struct sk_buff *skb);
extern void uml_net_setup_etheraddr(struct net_device *dev, char *str);
-
+extern int vector_compat_eth_configure(char *str, int index);
#endif
@@ -50,4 +50,6 @@ extern char *split_if_spec(char *str, ...);
extern int dev_netmask(void *d, void *m);
+extern void *uml_vector_compile_pcap(char *filter, int optimize);
+
#endif