diff options
Diffstat (limited to 'drivers/net/netkit.c')
| -rw-r--r-- | drivers/net/netkit.c | 30 | 
1 files changed, 24 insertions, 6 deletions
diff --git a/drivers/net/netkit.c b/drivers/net/netkit.c index a4d2e76a8d58..16789cd446e9 100644 --- a/drivers/net/netkit.c +++ b/drivers/net/netkit.c @@ -55,6 +55,7 @@ static void netkit_prep_forward(struct sk_buff *skb, bool xnet)  	skb_scrub_packet(skb, xnet);  	skb->priority = 0;  	nf_skip_egress(skb, true); +	skb_reset_mac_header(skb);  }  static struct netkit *netkit_priv(const struct net_device *dev) @@ -78,6 +79,7 @@ static netdev_tx_t netkit_xmit(struct sk_buff *skb, struct net_device *dev)  		     skb_orphan_frags(skb, GFP_ATOMIC)))  		goto drop;  	netkit_prep_forward(skb, !net_eq(dev_net(dev), dev_net(peer))); +	eth_skb_pkt_type(skb, peer);  	skb->dev = peer;  	entry = rcu_dereference(nk->active);  	if (entry) @@ -85,7 +87,7 @@ static netdev_tx_t netkit_xmit(struct sk_buff *skb, struct net_device *dev)  	switch (ret) {  	case NETKIT_NEXT:  	case NETKIT_PASS: -		skb->protocol = eth_type_trans(skb, skb->dev); +		eth_skb_pull_mac(skb);  		skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);  		if (likely(__netif_rx(skb) == NET_RX_SUCCESS)) {  			dev_sw_netstats_tx_add(dev, 1, len); @@ -155,6 +157,16 @@ static void netkit_set_multicast(struct net_device *dev)  	/* Nothing to do, we receive whatever gets pushed to us! */  } +static int netkit_set_macaddr(struct net_device *dev, void *sa) +{ +	struct netkit *nk = netkit_priv(dev); + +	if (nk->mode != NETKIT_L2) +		return -EOPNOTSUPP; + +	return eth_mac_addr(dev, sa); +} +  static void netkit_set_headroom(struct net_device *dev, int headroom)  {  	struct netkit *nk = netkit_priv(dev), *nk2; @@ -198,6 +210,7 @@ static const struct net_device_ops netkit_netdev_ops = {  	.ndo_start_xmit		= netkit_xmit,  	.ndo_set_rx_mode	= netkit_set_multicast,  	.ndo_set_rx_headroom	= netkit_set_headroom, +	.ndo_set_mac_address	= netkit_set_macaddr,  	.ndo_get_iflink		= netkit_get_iflink,  	.ndo_get_peer_dev	= netkit_peer_dev,  	.ndo_get_stats64	= netkit_get_stats, @@ -300,9 +313,11 @@ static int netkit_validate(struct nlattr *tb[], struct nlattr *data[],  	if (!attr)  		return 0; -	NL_SET_ERR_MSG_ATTR(extack, attr, -			    "Setting Ethernet address is not supported"); -	return -EOPNOTSUPP; +	if (nla_len(attr) != ETH_ALEN) +		return -EINVAL; +	if (!is_valid_ether_addr(nla_data(attr))) +		return -EADDRNOTAVAIL; +	return 0;  }  static struct rtnl_link_ops netkit_link_ops; @@ -365,6 +380,9 @@ static int netkit_new_link(struct net *src_net, struct net_device *dev,  		strscpy(ifname, "nk%d", IFNAMSIZ);  		ifname_assign_type = NET_NAME_ENUM;  	} +	if (mode != NETKIT_L2 && +	    (tb[IFLA_ADDRESS] || tbp[IFLA_ADDRESS])) +		return -EOPNOTSUPP;  	net = rtnl_link_get_net(src_net, tbp);  	if (IS_ERR(net)) @@ -379,7 +397,7 @@ static int netkit_new_link(struct net *src_net, struct net_device *dev,  	netif_inherit_tso_max(peer, dev); -	if (mode == NETKIT_L2) +	if (mode == NETKIT_L2 && !(ifmp && tbp[IFLA_ADDRESS]))  		eth_hw_addr_random(peer);  	if (ifmp && dev->ifindex)  		peer->ifindex = ifmp->ifi_index; @@ -402,7 +420,7 @@ static int netkit_new_link(struct net *src_net, struct net_device *dev,  	if (err < 0)  		goto err_configure_peer; -	if (mode == NETKIT_L2) +	if (mode == NETKIT_L2 && !tb[IFLA_ADDRESS])  		eth_hw_addr_random(dev);  	if (tb[IFLA_IFNAME])  		nla_strscpy(dev->name, tb[IFLA_IFNAME], IFNAMSIZ);  |