summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fastd.c41
-rw-r--r--fastd.h8
2 files changed, 37 insertions, 12 deletions
diff --git a/fastd.c b/fastd.c
index 7373e86..1ce476f 100644
--- a/fastd.c
+++ b/fastd.c
@@ -60,11 +60,12 @@
#include "fastd.h"
-#define FASTD_HEADROOM \
+#define FASTD_HDRLEN \
(ETH_HLEN + sizeof(struct ipv6hdr) + sizeof(struct udphdr) + 24)
#define FASTD_DEFAULT_MTU 1500
#define FASTD_MIN_MTU 68
+#define FASTD_MAX_MTU 65535
static LIST_HEAD(fastd_list);
@@ -126,10 +127,23 @@ static struct notifier_block nl_notifier = {
};
+
+static int fastd_ndo_change_mtu(struct net_device *dev, int mtu)
+{
+ if (mtu < FASTD_MIN_MTU || mtu > (FASTD_MAX_MTU-dev->hard_header_len))
+ return -EINVAL;
+
+ dev->mtu = mtu;
+ return 0;
+}
+
+
static const struct net_device_ops fastd_netdev_ops_eth = {
+ .ndo_change_mtu = fastd_ndo_change_mtu,
};
static const struct net_device_ops fastd_netdev_ops_ip = {
+ .ndo_change_mtu = fastd_ndo_change_mtu,
};
@@ -163,7 +177,8 @@ static const struct ethtool_ops fastd_ethtool_ops = {
};
-static void fastd_netdev_free(struct net_device *dev) {
+static void fastd_netdev_free(struct net_device *dev)
+{
struct fastd_struct *fastd = netdev_priv(dev);
put_net(fastd->net);
@@ -178,6 +193,17 @@ static void fastd_netdev_setup(struct net_device *dev)
dev->destructor = fastd_netdev_free;
}
+static inline u16 fastd_header_len(u16 mode)
+{
+ switch (mode) {
+ case FASTD_MODE_ETH:
+ return FASTD_HDRLEN + ETH_HLEN;
+
+ default:
+ return FASTD_HDRLEN;
+ }
+}
+
static void fastd_netdev_init(struct net_device *dev)
{
struct fastd_struct *fastd = netdev_priv(dev);
@@ -189,19 +215,17 @@ static void fastd_netdev_init(struct net_device *dev)
eth_hw_addr_random(dev);
ether_setup(dev);
- dev->hard_header_len = FASTD_HEADROOM + ETH_HLEN;
-
break;
case FASTD_MODE_IP:
- dev->netdev_ops = &fastd_netdev_ops_eth;
+ dev->netdev_ops = &fastd_netdev_ops_ip;
dev->addr_len = 0;
- dev->hard_header_len = FASTD_HEADROOM;
-
dev->type = ARPHRD_NONE;
dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
}
+
+ dev->hard_header_len = fastd_header_len(fastd->mode);
}
static void fastd_destroy_work(struct work_struct *work)
@@ -240,10 +264,9 @@ static int fastd_cmd_create(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[FASTD_A_MTU])
mtu = nla_get_u16(info->attrs[FASTD_A_MTU]);
- if (mtu < FASTD_MIN_MTU)
+ if (mtu < FASTD_MIN_MTU || mtu > (FASTD_MAX_MTU-fastd_header_len(mode)))
return -EINVAL;
-
if (info->attrs[FASTD_A_IFNAME])
name = nla_data(info->attrs[FASTD_A_IFNAME]);
diff --git a/fastd.h b/fastd.h
index 5c3ca86..8b89130 100644
--- a/fastd.h
+++ b/fastd.h
@@ -39,9 +39,11 @@
#ifndef __LINUX_FASTD_H
#define __LINUX_FASTD_H
-#define FASTD_MODE_ETH 0x0001
-#define FASTD_MODE_IP 0x0002
-
+enum {
+ FASTD_MODE_UNSPEC,
+ FASTD_MODE_ETH,
+ FASTD_MODE_IP
+};
enum {
FASTD_CMD_UNSPEC,