Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (33 commits) IPVS: Use global mutex in ip_vs_app.c ipvs: fix a typo in __ip_vs_control_init() veth: Fix the byte counters net ipv6: Fix duplicate /proc/sys/net/ipv6/neigh directory entries. macvlan: Fix use after free of struct macvlan_port. net: fix incorrect spelling in drop monitor protocol can: c_can: Do basic c_can configuration _before_ enabling the interrupts net/appletalk: fix atalk_release use after free ipx: fix ipx_release() snmp: SNMP_UPD_PO_STATS_BH() always called from softirq l2tp: fix possible oops on l2tp_eth module unload xfrm: Fix initialize repl field of struct xfrm_state netfilter: ipt_CLUSTERIP: fix buffer overflow netfilter: xtables: fix reentrancy netfilter: ipset: fix checking the type revision at create command netfilter: ipset: fix address ranges at hash:*port* types niu: Rename NIU parent platform device name to fix conflict. r8169: fix a bug in rtl8169_init_phy() bonding: fix a typo in a comment ftmac100: use resource_size() ...
This commit is contained in:
Коммит
c62b389863
|
@ -2130,7 +2130,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
|
|||
}
|
||||
|
||||
/*
|
||||
* First release a slave and than destroy the bond if no more slaves are left.
|
||||
* First release a slave and then destroy the bond if no more slaves are left.
|
||||
* Must be under rtnl_lock when this function is called.
|
||||
*/
|
||||
static int bond_release_and_destroy(struct net_device *bond_dev,
|
||||
|
|
|
@ -633,9 +633,6 @@ static void c_can_start(struct net_device *dev)
|
|||
{
|
||||
struct c_can_priv *priv = netdev_priv(dev);
|
||||
|
||||
/* enable status change, error and module interrupts */
|
||||
c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS);
|
||||
|
||||
/* basic c_can configuration */
|
||||
c_can_chip_config(dev);
|
||||
|
||||
|
@ -643,6 +640,9 @@ static void c_can_start(struct net_device *dev)
|
|||
|
||||
/* reset tx helper pointers */
|
||||
priv->tx_next = priv->tx_echo = 0;
|
||||
|
||||
/* enable status change, error and module interrupts */
|
||||
c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS);
|
||||
}
|
||||
|
||||
static void c_can_stop(struct net_device *dev)
|
||||
|
|
|
@ -1102,7 +1102,7 @@ static int ftmac100_probe(struct platform_device *pdev)
|
|||
goto err_req_mem;
|
||||
}
|
||||
|
||||
priv->base = ioremap(res->start, res->end - res->start);
|
||||
priv->base = ioremap(res->start, resource_size(res));
|
||||
if (!priv->base) {
|
||||
dev_err(&pdev->dev, "Failed to ioremap ethernet registers\n");
|
||||
err = -EIO;
|
||||
|
|
|
@ -949,6 +949,11 @@ static void gfar_detect_errata(struct gfar_private *priv)
|
|||
(pvr == 0x80861010 && (mod & 0xfff9) == 0x80c0))
|
||||
priv->errata |= GFAR_ERRATA_A002;
|
||||
|
||||
/* MPC8313 Rev < 2.0, MPC8548 rev 2.0 */
|
||||
if ((pvr == 0x80850010 && mod == 0x80b0 && rev < 0x0020) ||
|
||||
(pvr == 0x80210020 && mod == 0x8030 && rev == 0x0020))
|
||||
priv->errata |= GFAR_ERRATA_12;
|
||||
|
||||
if (priv->errata)
|
||||
dev_info(dev, "enabled errata workarounds, flags: 0x%x\n",
|
||||
priv->errata);
|
||||
|
@ -2154,8 +2159,15 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
/* Set up checksumming */
|
||||
if (CHECKSUM_PARTIAL == skb->ip_summed) {
|
||||
fcb = gfar_add_fcb(skb);
|
||||
lstatus |= BD_LFLAG(TXBD_TOE);
|
||||
gfar_tx_checksum(skb, fcb);
|
||||
/* as specified by errata */
|
||||
if (unlikely(gfar_has_errata(priv, GFAR_ERRATA_12)
|
||||
&& ((unsigned long)fcb % 0x20) > 0x18)) {
|
||||
__skb_pull(skb, GMAC_FCB_LEN);
|
||||
skb_checksum_help(skb);
|
||||
} else {
|
||||
lstatus |= BD_LFLAG(TXBD_TOE);
|
||||
gfar_tx_checksum(skb, fcb);
|
||||
}
|
||||
}
|
||||
|
||||
if (vlan_tx_tag_present(skb)) {
|
||||
|
|
|
@ -1039,6 +1039,7 @@ enum gfar_errata {
|
|||
GFAR_ERRATA_74 = 0x01,
|
||||
GFAR_ERRATA_76 = 0x02,
|
||||
GFAR_ERRATA_A002 = 0x04,
|
||||
GFAR_ERRATA_12 = 0x08, /* a.k.a errata eTSEC49 */
|
||||
};
|
||||
|
||||
/* Struct stolen almost completely (and shamelessly) from the FCC enet source
|
||||
|
|
|
@ -39,8 +39,11 @@ struct macvlan_port {
|
|||
struct list_head vlans;
|
||||
struct rcu_head rcu;
|
||||
bool passthru;
|
||||
int count;
|
||||
};
|
||||
|
||||
static void macvlan_port_destroy(struct net_device *dev);
|
||||
|
||||
#define macvlan_port_get_rcu(dev) \
|
||||
((struct macvlan_port *) rcu_dereference(dev->rx_handler_data))
|
||||
#define macvlan_port_get(dev) ((struct macvlan_port *) dev->rx_handler_data)
|
||||
|
@ -457,8 +460,13 @@ static int macvlan_init(struct net_device *dev)
|
|||
static void macvlan_uninit(struct net_device *dev)
|
||||
{
|
||||
struct macvlan_dev *vlan = netdev_priv(dev);
|
||||
struct macvlan_port *port = vlan->port;
|
||||
|
||||
free_percpu(vlan->pcpu_stats);
|
||||
|
||||
port->count -= 1;
|
||||
if (!port->count)
|
||||
macvlan_port_destroy(port->dev);
|
||||
}
|
||||
|
||||
static struct rtnl_link_stats64 *macvlan_dev_get_stats64(struct net_device *dev,
|
||||
|
@ -691,12 +699,13 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
|
|||
vlan->mode = nla_get_u32(data[IFLA_MACVLAN_MODE]);
|
||||
|
||||
if (vlan->mode == MACVLAN_MODE_PASSTHRU) {
|
||||
if (!list_empty(&port->vlans))
|
||||
if (port->count)
|
||||
return -EINVAL;
|
||||
port->passthru = true;
|
||||
memcpy(dev->dev_addr, lowerdev->dev_addr, ETH_ALEN);
|
||||
}
|
||||
|
||||
port->count += 1;
|
||||
err = register_netdevice(dev);
|
||||
if (err < 0)
|
||||
goto destroy_port;
|
||||
|
@ -707,7 +716,8 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
|
|||
return 0;
|
||||
|
||||
destroy_port:
|
||||
if (list_empty(&port->vlans))
|
||||
port->count -= 1;
|
||||
if (!port->count)
|
||||
macvlan_port_destroy(lowerdev);
|
||||
|
||||
return err;
|
||||
|
@ -725,13 +735,9 @@ static int macvlan_newlink(struct net *src_net, struct net_device *dev,
|
|||
void macvlan_dellink(struct net_device *dev, struct list_head *head)
|
||||
{
|
||||
struct macvlan_dev *vlan = netdev_priv(dev);
|
||||
struct macvlan_port *port = vlan->port;
|
||||
|
||||
list_del(&vlan->list);
|
||||
unregister_netdevice_queue(dev, head);
|
||||
|
||||
if (list_empty(&port->vlans))
|
||||
macvlan_port_destroy(port->dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(macvlan_dellink);
|
||||
|
||||
|
|
|
@ -9501,7 +9501,7 @@ static struct niu_parent * __devinit niu_new_parent(struct niu *np,
|
|||
struct niu_parent *p;
|
||||
int i;
|
||||
|
||||
plat_dev = platform_device_register_simple("niu", niu_parent_index,
|
||||
plat_dev = platform_device_register_simple("niu-board", niu_parent_index,
|
||||
NULL, 0);
|
||||
if (IS_ERR(plat_dev))
|
||||
return NULL;
|
||||
|
|
|
@ -171,7 +171,7 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
if (skb->ip_summed == CHECKSUM_NONE)
|
||||
skb->ip_summed = rcv_priv->ip_summed;
|
||||
|
||||
length = skb->len + ETH_HLEN;
|
||||
length = skb->len;
|
||||
if (dev_forward_skb(rcv, skb) != NET_RX_SUCCESS)
|
||||
goto rx_drop;
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@ static int move_iovec_hdr(struct iovec *from, struct iovec *to,
|
|||
{
|
||||
int seg = 0;
|
||||
size_t size;
|
||||
|
||||
while (len && seg < iov_count) {
|
||||
size = min(from->iov_len, len);
|
||||
to->iov_base = from->iov_base;
|
||||
|
@ -79,6 +80,7 @@ static void copy_iovec_hdr(const struct iovec *from, struct iovec *to,
|
|||
{
|
||||
int seg = 0;
|
||||
size_t size;
|
||||
|
||||
while (len && seg < iovcount) {
|
||||
size = min(from->iov_len, len);
|
||||
to->iov_base = from->iov_base;
|
||||
|
@ -211,12 +213,13 @@ static int peek_head_len(struct sock *sk)
|
|||
{
|
||||
struct sk_buff *head;
|
||||
int len = 0;
|
||||
unsigned long flags;
|
||||
|
||||
lock_sock(sk);
|
||||
spin_lock_irqsave(&sk->sk_receive_queue.lock, flags);
|
||||
head = skb_peek(&sk->sk_receive_queue);
|
||||
if (head)
|
||||
if (likely(head))
|
||||
len = head->len;
|
||||
release_sock(sk);
|
||||
spin_unlock_irqrestore(&sk->sk_receive_queue.lock, flags);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
@ -227,6 +230,7 @@ static int peek_head_len(struct sock *sk)
|
|||
* @iovcount - returned count of io vectors we fill
|
||||
* @log - vhost log
|
||||
* @log_num - log offset
|
||||
* @quota - headcount quota, 1 for big buffer
|
||||
* returns number of buffer heads allocated, negative on error
|
||||
*/
|
||||
static int get_rx_bufs(struct vhost_virtqueue *vq,
|
||||
|
@ -234,7 +238,8 @@ static int get_rx_bufs(struct vhost_virtqueue *vq,
|
|||
int datalen,
|
||||
unsigned *iovcount,
|
||||
struct vhost_log *log,
|
||||
unsigned *log_num)
|
||||
unsigned *log_num,
|
||||
unsigned int quota)
|
||||
{
|
||||
unsigned int out, in;
|
||||
int seg = 0;
|
||||
|
@ -242,7 +247,7 @@ static int get_rx_bufs(struct vhost_virtqueue *vq,
|
|||
unsigned d;
|
||||
int r, nlogs = 0;
|
||||
|
||||
while (datalen > 0) {
|
||||
while (datalen > 0 && headcount < quota) {
|
||||
if (unlikely(seg >= UIO_MAXIOV)) {
|
||||
r = -ENOBUFS;
|
||||
goto err;
|
||||
|
@ -282,117 +287,7 @@ err:
|
|||
|
||||
/* Expects to be always run from workqueue - which acts as
|
||||
* read-size critical section for our kind of RCU. */
|
||||
static void handle_rx_big(struct vhost_net *net)
|
||||
{
|
||||
struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_RX];
|
||||
unsigned out, in, log, s;
|
||||
int head;
|
||||
struct vhost_log *vq_log;
|
||||
struct msghdr msg = {
|
||||
.msg_name = NULL,
|
||||
.msg_namelen = 0,
|
||||
.msg_control = NULL, /* FIXME: get and handle RX aux data. */
|
||||
.msg_controllen = 0,
|
||||
.msg_iov = vq->iov,
|
||||
.msg_flags = MSG_DONTWAIT,
|
||||
};
|
||||
|
||||
struct virtio_net_hdr hdr = {
|
||||
.flags = 0,
|
||||
.gso_type = VIRTIO_NET_HDR_GSO_NONE
|
||||
};
|
||||
|
||||
size_t len, total_len = 0;
|
||||
int err;
|
||||
size_t hdr_size;
|
||||
/* TODO: check that we are running from vhost_worker? */
|
||||
struct socket *sock = rcu_dereference_check(vq->private_data, 1);
|
||||
if (!sock || skb_queue_empty(&sock->sk->sk_receive_queue))
|
||||
return;
|
||||
|
||||
mutex_lock(&vq->mutex);
|
||||
vhost_disable_notify(vq);
|
||||
hdr_size = vq->vhost_hlen;
|
||||
|
||||
vq_log = unlikely(vhost_has_feature(&net->dev, VHOST_F_LOG_ALL)) ?
|
||||
vq->log : NULL;
|
||||
|
||||
for (;;) {
|
||||
head = vhost_get_vq_desc(&net->dev, vq, vq->iov,
|
||||
ARRAY_SIZE(vq->iov),
|
||||
&out, &in,
|
||||
vq_log, &log);
|
||||
/* On error, stop handling until the next kick. */
|
||||
if (unlikely(head < 0))
|
||||
break;
|
||||
/* OK, now we need to know about added descriptors. */
|
||||
if (head == vq->num) {
|
||||
if (unlikely(vhost_enable_notify(vq))) {
|
||||
/* They have slipped one in as we were
|
||||
* doing that: check again. */
|
||||
vhost_disable_notify(vq);
|
||||
continue;
|
||||
}
|
||||
/* Nothing new? Wait for eventfd to tell us
|
||||
* they refilled. */
|
||||
break;
|
||||
}
|
||||
/* We don't need to be notified again. */
|
||||
if (out) {
|
||||
vq_err(vq, "Unexpected descriptor format for RX: "
|
||||
"out %d, int %d\n",
|
||||
out, in);
|
||||
break;
|
||||
}
|
||||
/* Skip header. TODO: support TSO/mergeable rx buffers. */
|
||||
s = move_iovec_hdr(vq->iov, vq->hdr, hdr_size, in);
|
||||
msg.msg_iovlen = in;
|
||||
len = iov_length(vq->iov, in);
|
||||
/* Sanity check */
|
||||
if (!len) {
|
||||
vq_err(vq, "Unexpected header len for RX: "
|
||||
"%zd expected %zd\n",
|
||||
iov_length(vq->hdr, s), hdr_size);
|
||||
break;
|
||||
}
|
||||
err = sock->ops->recvmsg(NULL, sock, &msg,
|
||||
len, MSG_DONTWAIT | MSG_TRUNC);
|
||||
/* TODO: Check specific error and bomb out unless EAGAIN? */
|
||||
if (err < 0) {
|
||||
vhost_discard_vq_desc(vq, 1);
|
||||
break;
|
||||
}
|
||||
/* TODO: Should check and handle checksum. */
|
||||
if (err > len) {
|
||||
pr_debug("Discarded truncated rx packet: "
|
||||
" len %d > %zd\n", err, len);
|
||||
vhost_discard_vq_desc(vq, 1);
|
||||
continue;
|
||||
}
|
||||
len = err;
|
||||
err = memcpy_toiovec(vq->hdr, (unsigned char *)&hdr, hdr_size);
|
||||
if (err) {
|
||||
vq_err(vq, "Unable to write vnet_hdr at addr %p: %d\n",
|
||||
vq->iov->iov_base, err);
|
||||
break;
|
||||
}
|
||||
len += hdr_size;
|
||||
vhost_add_used_and_signal(&net->dev, vq, head, len);
|
||||
if (unlikely(vq_log))
|
||||
vhost_log_write(vq, vq_log, log, len);
|
||||
total_len += len;
|
||||
if (unlikely(total_len >= VHOST_NET_WEIGHT)) {
|
||||
vhost_poll_queue(&vq->poll);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&vq->mutex);
|
||||
}
|
||||
|
||||
/* Expects to be always run from workqueue - which acts as
|
||||
* read-size critical section for our kind of RCU. */
|
||||
static void handle_rx_mergeable(struct vhost_net *net)
|
||||
static void handle_rx(struct vhost_net *net)
|
||||
{
|
||||
struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_RX];
|
||||
unsigned uninitialized_var(in), log;
|
||||
|
@ -405,19 +300,18 @@ static void handle_rx_mergeable(struct vhost_net *net)
|
|||
.msg_iov = vq->iov,
|
||||
.msg_flags = MSG_DONTWAIT,
|
||||
};
|
||||
|
||||
struct virtio_net_hdr_mrg_rxbuf hdr = {
|
||||
.hdr.flags = 0,
|
||||
.hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE
|
||||
};
|
||||
|
||||
size_t total_len = 0;
|
||||
int err, headcount;
|
||||
int err, headcount, mergeable;
|
||||
size_t vhost_hlen, sock_hlen;
|
||||
size_t vhost_len, sock_len;
|
||||
/* TODO: check that we are running from vhost_worker? */
|
||||
struct socket *sock = rcu_dereference_check(vq->private_data, 1);
|
||||
if (!sock || skb_queue_empty(&sock->sk->sk_receive_queue))
|
||||
|
||||
if (!sock)
|
||||
return;
|
||||
|
||||
mutex_lock(&vq->mutex);
|
||||
|
@ -427,12 +321,14 @@ static void handle_rx_mergeable(struct vhost_net *net)
|
|||
|
||||
vq_log = unlikely(vhost_has_feature(&net->dev, VHOST_F_LOG_ALL)) ?
|
||||
vq->log : NULL;
|
||||
mergeable = vhost_has_feature(&net->dev, VIRTIO_NET_F_MRG_RXBUF);
|
||||
|
||||
while ((sock_len = peek_head_len(sock->sk))) {
|
||||
sock_len += sock_hlen;
|
||||
vhost_len = sock_len + vhost_hlen;
|
||||
headcount = get_rx_bufs(vq, vq->heads, vhost_len,
|
||||
&in, vq_log, &log);
|
||||
&in, vq_log, &log,
|
||||
likely(mergeable) ? UIO_MAXIOV : 1);
|
||||
/* On error, stop handling until the next kick. */
|
||||
if (unlikely(headcount < 0))
|
||||
break;
|
||||
|
@ -476,7 +372,7 @@ static void handle_rx_mergeable(struct vhost_net *net)
|
|||
break;
|
||||
}
|
||||
/* TODO: Should check and handle checksum. */
|
||||
if (vhost_has_feature(&net->dev, VIRTIO_NET_F_MRG_RXBUF) &&
|
||||
if (likely(mergeable) &&
|
||||
memcpy_toiovecend(vq->hdr, (unsigned char *)&headcount,
|
||||
offsetof(typeof(hdr), num_buffers),
|
||||
sizeof hdr.num_buffers)) {
|
||||
|
@ -498,14 +394,6 @@ static void handle_rx_mergeable(struct vhost_net *net)
|
|||
mutex_unlock(&vq->mutex);
|
||||
}
|
||||
|
||||
static void handle_rx(struct vhost_net *net)
|
||||
{
|
||||
if (vhost_has_feature(&net->dev, VIRTIO_NET_F_MRG_RXBUF))
|
||||
handle_rx_mergeable(net);
|
||||
else
|
||||
handle_rx_big(net);
|
||||
}
|
||||
|
||||
static void handle_tx_kick(struct vhost_work *work)
|
||||
{
|
||||
struct vhost_virtqueue *vq = container_of(work, struct vhost_virtqueue,
|
||||
|
@ -654,6 +542,7 @@ static struct socket *get_raw_socket(int fd)
|
|||
} uaddr;
|
||||
int uaddr_len = sizeof uaddr, r;
|
||||
struct socket *sock = sockfd_lookup(fd, &r);
|
||||
|
||||
if (!sock)
|
||||
return ERR_PTR(-ENOTSOCK);
|
||||
|
||||
|
@ -682,6 +571,7 @@ static struct socket *get_tap_socket(int fd)
|
|||
{
|
||||
struct file *file = fget(fd);
|
||||
struct socket *sock;
|
||||
|
||||
if (!file)
|
||||
return ERR_PTR(-EBADF);
|
||||
sock = tun_get_socket(file);
|
||||
|
@ -696,6 +586,7 @@ static struct socket *get_tap_socket(int fd)
|
|||
static struct socket *get_socket(int fd)
|
||||
{
|
||||
struct socket *sock;
|
||||
|
||||
/* special case to disable backend */
|
||||
if (fd == -1)
|
||||
return NULL;
|
||||
|
@ -741,9 +632,9 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
|
|||
oldsock = rcu_dereference_protected(vq->private_data,
|
||||
lockdep_is_held(&vq->mutex));
|
||||
if (sock != oldsock) {
|
||||
vhost_net_disable_vq(n, vq);
|
||||
rcu_assign_pointer(vq->private_data, sock);
|
||||
vhost_net_enable_vq(n, vq);
|
||||
vhost_net_disable_vq(n, vq);
|
||||
rcu_assign_pointer(vq->private_data, sock);
|
||||
vhost_net_enable_vq(n, vq);
|
||||
}
|
||||
|
||||
mutex_unlock(&vq->mutex);
|
||||
|
@ -768,6 +659,7 @@ static long vhost_net_reset_owner(struct vhost_net *n)
|
|||
struct socket *tx_sock = NULL;
|
||||
struct socket *rx_sock = NULL;
|
||||
long err;
|
||||
|
||||
mutex_lock(&n->dev.mutex);
|
||||
err = vhost_dev_check_owner(&n->dev);
|
||||
if (err)
|
||||
|
@ -829,6 +721,7 @@ static long vhost_net_ioctl(struct file *f, unsigned int ioctl,
|
|||
struct vhost_vring_file backend;
|
||||
u64 features;
|
||||
int r;
|
||||
|
||||
switch (ioctl) {
|
||||
case VHOST_NET_SET_BACKEND:
|
||||
if (copy_from_user(&backend, argp, sizeof backend))
|
||||
|
|
|
@ -41,8 +41,8 @@ static void vhost_poll_func(struct file *file, wait_queue_head_t *wqh,
|
|||
poll_table *pt)
|
||||
{
|
||||
struct vhost_poll *poll;
|
||||
poll = container_of(pt, struct vhost_poll, table);
|
||||
|
||||
poll = container_of(pt, struct vhost_poll, table);
|
||||
poll->wqh = wqh;
|
||||
add_wait_queue(wqh, &poll->wait);
|
||||
}
|
||||
|
@ -85,6 +85,7 @@ void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn,
|
|||
void vhost_poll_start(struct vhost_poll *poll, struct file *file)
|
||||
{
|
||||
unsigned long mask;
|
||||
|
||||
mask = file->f_op->poll(file, &poll->table);
|
||||
if (mask)
|
||||
vhost_poll_wakeup(&poll->wait, 0, 0, (void *)mask);
|
||||
|
@ -101,6 +102,7 @@ static bool vhost_work_seq_done(struct vhost_dev *dev, struct vhost_work *work,
|
|||
unsigned seq)
|
||||
{
|
||||
int left;
|
||||
|
||||
spin_lock_irq(&dev->work_lock);
|
||||
left = seq - work->done_seq;
|
||||
spin_unlock_irq(&dev->work_lock);
|
||||
|
@ -222,6 +224,7 @@ static int vhost_worker(void *data)
|
|||
static long vhost_dev_alloc_iovecs(struct vhost_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dev->nvqs; ++i) {
|
||||
dev->vqs[i].indirect = kmalloc(sizeof *dev->vqs[i].indirect *
|
||||
UIO_MAXIOV, GFP_KERNEL);
|
||||
|
@ -235,6 +238,7 @@ static long vhost_dev_alloc_iovecs(struct vhost_dev *dev)
|
|||
goto err_nomem;
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_nomem:
|
||||
for (; i >= 0; --i) {
|
||||
kfree(dev->vqs[i].indirect);
|
||||
|
@ -247,6 +251,7 @@ err_nomem:
|
|||
static void vhost_dev_free_iovecs(struct vhost_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dev->nvqs; ++i) {
|
||||
kfree(dev->vqs[i].indirect);
|
||||
dev->vqs[i].indirect = NULL;
|
||||
|
@ -296,26 +301,28 @@ long vhost_dev_check_owner(struct vhost_dev *dev)
|
|||
}
|
||||
|
||||
struct vhost_attach_cgroups_struct {
|
||||
struct vhost_work work;
|
||||
struct task_struct *owner;
|
||||
int ret;
|
||||
struct vhost_work work;
|
||||
struct task_struct *owner;
|
||||
int ret;
|
||||
};
|
||||
|
||||
static void vhost_attach_cgroups_work(struct vhost_work *work)
|
||||
{
|
||||
struct vhost_attach_cgroups_struct *s;
|
||||
s = container_of(work, struct vhost_attach_cgroups_struct, work);
|
||||
s->ret = cgroup_attach_task_all(s->owner, current);
|
||||
struct vhost_attach_cgroups_struct *s;
|
||||
|
||||
s = container_of(work, struct vhost_attach_cgroups_struct, work);
|
||||
s->ret = cgroup_attach_task_all(s->owner, current);
|
||||
}
|
||||
|
||||
static int vhost_attach_cgroups(struct vhost_dev *dev)
|
||||
{
|
||||
struct vhost_attach_cgroups_struct attach;
|
||||
attach.owner = current;
|
||||
vhost_work_init(&attach.work, vhost_attach_cgroups_work);
|
||||
vhost_work_queue(dev, &attach.work);
|
||||
vhost_work_flush(dev, &attach.work);
|
||||
return attach.ret;
|
||||
struct vhost_attach_cgroups_struct attach;
|
||||
|
||||
attach.owner = current;
|
||||
vhost_work_init(&attach.work, vhost_attach_cgroups_work);
|
||||
vhost_work_queue(dev, &attach.work);
|
||||
vhost_work_flush(dev, &attach.work);
|
||||
return attach.ret;
|
||||
}
|
||||
|
||||
/* Caller should have device mutex */
|
||||
|
@ -323,11 +330,13 @@ static long vhost_dev_set_owner(struct vhost_dev *dev)
|
|||
{
|
||||
struct task_struct *worker;
|
||||
int err;
|
||||
|
||||
/* Is there an owner already? */
|
||||
if (dev->mm) {
|
||||
err = -EBUSY;
|
||||
goto err_mm;
|
||||
}
|
||||
|
||||
/* No owner, become one */
|
||||
dev->mm = get_task_mm(current);
|
||||
worker = kthread_create(vhost_worker, dev, "vhost-%d", current->pid);
|
||||
|
@ -380,6 +389,7 @@ long vhost_dev_reset_owner(struct vhost_dev *dev)
|
|||
void vhost_dev_cleanup(struct vhost_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dev->nvqs; ++i) {
|
||||
if (dev->vqs[i].kick && dev->vqs[i].handle_kick) {
|
||||
vhost_poll_stop(&dev->vqs[i].poll);
|
||||
|
@ -421,6 +431,7 @@ void vhost_dev_cleanup(struct vhost_dev *dev)
|
|||
static int log_access_ok(void __user *log_base, u64 addr, unsigned long sz)
|
||||
{
|
||||
u64 a = addr / VHOST_PAGE_SIZE / 8;
|
||||
|
||||
/* Make sure 64 bit math will not overflow. */
|
||||
if (a > ULONG_MAX - (unsigned long)log_base ||
|
||||
a + (unsigned long)log_base > ULONG_MAX)
|
||||
|
@ -461,6 +472,7 @@ static int memory_access_ok(struct vhost_dev *d, struct vhost_memory *mem,
|
|||
int log_all)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < d->nvqs; ++i) {
|
||||
int ok;
|
||||
mutex_lock(&d->vqs[i].mutex);
|
||||
|
@ -527,6 +539,7 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
|
|||
{
|
||||
struct vhost_memory mem, *newmem, *oldmem;
|
||||
unsigned long size = offsetof(struct vhost_memory, regions);
|
||||
|
||||
if (copy_from_user(&mem, m, size))
|
||||
return -EFAULT;
|
||||
if (mem.padding)
|
||||
|
@ -544,7 +557,8 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
|
|||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (!memory_access_ok(d, newmem, vhost_has_feature(d, VHOST_F_LOG_ALL))) {
|
||||
if (!memory_access_ok(d, newmem,
|
||||
vhost_has_feature(d, VHOST_F_LOG_ALL))) {
|
||||
kfree(newmem);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
@ -560,6 +574,7 @@ static int init_used(struct vhost_virtqueue *vq,
|
|||
struct vring_used __user *used)
|
||||
{
|
||||
int r = put_user(vq->used_flags, &used->flags);
|
||||
|
||||
if (r)
|
||||
return r;
|
||||
return get_user(vq->last_used_idx, &used->idx);
|
||||
|
@ -849,6 +864,7 @@ static const struct vhost_memory_region *find_region(struct vhost_memory *mem,
|
|||
{
|
||||
struct vhost_memory_region *reg;
|
||||
int i;
|
||||
|
||||
/* linear search is not brilliant, but we really have on the order of 6
|
||||
* regions in practice */
|
||||
for (i = 0; i < mem->nregions; ++i) {
|
||||
|
@ -871,6 +887,7 @@ static int set_bit_to_user(int nr, void __user *addr)
|
|||
void *base;
|
||||
int bit = nr + (log % PAGE_SIZE) * 8;
|
||||
int r;
|
||||
|
||||
r = get_user_pages_fast(log, 1, 1, &page);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -888,6 +905,7 @@ static int log_write(void __user *log_base,
|
|||
{
|
||||
u64 write_page = write_address / VHOST_PAGE_SIZE;
|
||||
int r;
|
||||
|
||||
if (!write_length)
|
||||
return 0;
|
||||
write_length += write_address % VHOST_PAGE_SIZE;
|
||||
|
@ -1037,8 +1055,8 @@ static int get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
|
|||
i, count);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (unlikely(memcpy_fromiovec((unsigned char *)&desc, vq->indirect,
|
||||
sizeof desc))) {
|
||||
if (unlikely(memcpy_fromiovec((unsigned char *)&desc,
|
||||
vq->indirect, sizeof desc))) {
|
||||
vq_err(vq, "Failed indirect descriptor: idx %d, %zx\n",
|
||||
i, (size_t)indirect->addr + i * sizeof desc);
|
||||
return -EINVAL;
|
||||
|
@ -1153,7 +1171,7 @@ int vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
|
|||
i, vq->num, head);
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = copy_from_user(&desc, vq->desc + i, sizeof desc);
|
||||
ret = __copy_from_user(&desc, vq->desc + i, sizeof desc);
|
||||
if (unlikely(ret)) {
|
||||
vq_err(vq, "Failed to get descriptor: idx %d addr %p\n",
|
||||
i, vq->desc + i);
|
||||
|
@ -1317,6 +1335,7 @@ int vhost_add_used_n(struct vhost_virtqueue *vq, struct vring_used_elem *heads,
|
|||
void vhost_signal(struct vhost_dev *dev, struct vhost_virtqueue *vq)
|
||||
{
|
||||
__u16 flags;
|
||||
|
||||
/* Flush out used index updates. This is paired
|
||||
* with the barrier that the Guest executes when enabling
|
||||
* interrupts. */
|
||||
|
@ -1361,6 +1380,7 @@ bool vhost_enable_notify(struct vhost_virtqueue *vq)
|
|||
{
|
||||
u16 avail_idx;
|
||||
int r;
|
||||
|
||||
if (!(vq->used_flags & VRING_USED_F_NO_NOTIFY))
|
||||
return false;
|
||||
vq->used_flags &= ~VRING_USED_F_NO_NOTIFY;
|
||||
|
@ -1387,6 +1407,7 @@ bool vhost_enable_notify(struct vhost_virtqueue *vq)
|
|||
void vhost_disable_notify(struct vhost_virtqueue *vq)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (vq->used_flags & VRING_USED_F_NO_NOTIFY)
|
||||
return;
|
||||
vq->used_flags |= VRING_USED_F_NO_NOTIFY;
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
#ifndef _LINUX_ETHTOOL_H
|
||||
#define _LINUX_ETHTOOL_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/compat.h>
|
||||
#endif
|
||||
#include <linux/types.h>
|
||||
#include <linux/if_ether.h>
|
||||
|
||||
|
@ -450,6 +453,37 @@ struct ethtool_rxnfc {
|
|||
__u32 rule_locs[0];
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
||||
struct compat_ethtool_rx_flow_spec {
|
||||
u32 flow_type;
|
||||
union {
|
||||
struct ethtool_tcpip4_spec tcp_ip4_spec;
|
||||
struct ethtool_tcpip4_spec udp_ip4_spec;
|
||||
struct ethtool_tcpip4_spec sctp_ip4_spec;
|
||||
struct ethtool_ah_espip4_spec ah_ip4_spec;
|
||||
struct ethtool_ah_espip4_spec esp_ip4_spec;
|
||||
struct ethtool_usrip4_spec usr_ip4_spec;
|
||||
struct ethhdr ether_spec;
|
||||
u8 hdata[72];
|
||||
} h_u, m_u;
|
||||
compat_u64 ring_cookie;
|
||||
u32 location;
|
||||
};
|
||||
|
||||
struct compat_ethtool_rxnfc {
|
||||
u32 cmd;
|
||||
u32 flow_type;
|
||||
compat_u64 data;
|
||||
struct compat_ethtool_rx_flow_spec fs;
|
||||
u32 rule_cnt;
|
||||
u32 rule_locs[0];
|
||||
};
|
||||
|
||||
#endif /* CONFIG_COMPAT */
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
/**
|
||||
* struct ethtool_rxfh_indir - command to get or set RX flow hash indirection
|
||||
* @cmd: Specific command number - %ETHTOOL_GRXFHINDIR or %ETHTOOL_SRXFHINDIR
|
||||
|
|
|
@ -114,14 +114,14 @@ struct pppol2tp_ioc_stats {
|
|||
__u16 tunnel_id; /* redundant */
|
||||
__u16 session_id; /* if zero, get tunnel stats */
|
||||
__u32 using_ipsec:1; /* valid only for session_id == 0 */
|
||||
aligned_u64 tx_packets;
|
||||
aligned_u64 tx_bytes;
|
||||
aligned_u64 tx_errors;
|
||||
aligned_u64 rx_packets;
|
||||
aligned_u64 rx_bytes;
|
||||
aligned_u64 rx_seq_discards;
|
||||
aligned_u64 rx_oos_packets;
|
||||
aligned_u64 rx_errors;
|
||||
__aligned_u64 tx_packets;
|
||||
__aligned_u64 tx_bytes;
|
||||
__aligned_u64 tx_errors;
|
||||
__aligned_u64 rx_packets;
|
||||
__aligned_u64 rx_bytes;
|
||||
__aligned_u64 rx_seq_discards;
|
||||
__aligned_u64 rx_oos_packets;
|
||||
__aligned_u64 rx_errors;
|
||||
};
|
||||
|
||||
#define ifr__name b.ifr_ifrn.ifrn_name
|
||||
|
|
|
@ -18,4 +18,14 @@ static inline bool ip_set_get_ip6_port(const struct sk_buff *skb, bool src,
|
|||
extern bool ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src,
|
||||
__be16 *port);
|
||||
|
||||
static inline bool ip_set_proto_with_ports(u8 proto)
|
||||
{
|
||||
switch (proto) {
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_UDP:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /*_IP_SET_GETPORT_H*/
|
||||
|
|
|
@ -28,8 +28,8 @@ struct nfulnl_msg_packet_hw {
|
|||
};
|
||||
|
||||
struct nfulnl_msg_packet_timestamp {
|
||||
aligned_be64 sec;
|
||||
aligned_be64 usec;
|
||||
__aligned_be64 sec;
|
||||
__aligned_be64 usec;
|
||||
};
|
||||
|
||||
enum nfulnl_attr_type {
|
||||
|
|
|
@ -25,8 +25,8 @@ struct nfqnl_msg_packet_hw {
|
|||
};
|
||||
|
||||
struct nfqnl_msg_packet_timestamp {
|
||||
aligned_be64 sec;
|
||||
aligned_be64 usec;
|
||||
__aligned_be64 sec;
|
||||
__aligned_be64 usec;
|
||||
};
|
||||
|
||||
enum nfqnl_attr_type {
|
||||
|
|
|
@ -17,8 +17,8 @@ enum xt_connbytes_direction {
|
|||
|
||||
struct xt_connbytes_info {
|
||||
struct {
|
||||
aligned_u64 from; /* count to be matched */
|
||||
aligned_u64 to; /* count to be matched */
|
||||
__aligned_u64 from; /* count to be matched */
|
||||
__aligned_u64 to; /* count to be matched */
|
||||
} count;
|
||||
__u8 what; /* ipt_connbytes_what */
|
||||
__u8 direction; /* ipt_connbytes_direction */
|
||||
|
|
|
@ -13,7 +13,7 @@ struct xt_quota_priv;
|
|||
struct xt_quota_info {
|
||||
__u32 flags;
|
||||
__u32 pad;
|
||||
aligned_u64 quota;
|
||||
__aligned_u64 quota;
|
||||
|
||||
/* Used internally by the kernel */
|
||||
struct xt_quota_priv *master;
|
||||
|
|
|
@ -801,8 +801,6 @@ struct netns_ipvs {
|
|||
struct list_head rs_table[IP_VS_RTAB_SIZE];
|
||||
/* ip_vs_app */
|
||||
struct list_head app_list;
|
||||
struct mutex app_mutex;
|
||||
struct lock_class_key app_key; /* mutex debuging */
|
||||
|
||||
/* ip_vs_proto */
|
||||
#define IP_VS_PROTO_TAB_SIZE 32 /* must be power of 2 */
|
||||
|
|
|
@ -150,7 +150,7 @@ struct linux_xfrm_mib {
|
|||
#define SNMP_UPD_PO_STATS_BH(mib, basefield, addend) \
|
||||
do { \
|
||||
__typeof__(*mib[0]) *ptr = \
|
||||
__this_cpu_ptr((mib)[!in_softirq()]); \
|
||||
__this_cpu_ptr((mib)[0]); \
|
||||
ptr->mibs[basefield##PKTS]++; \
|
||||
ptr->mibs[basefield##OCTETS] += addend;\
|
||||
} while (0)
|
||||
|
@ -202,7 +202,7 @@ struct linux_xfrm_mib {
|
|||
#define SNMP_UPD_PO_STATS64_BH(mib, basefield, addend) \
|
||||
do { \
|
||||
__typeof__(*mib[0]) *ptr; \
|
||||
ptr = __this_cpu_ptr((mib)[!in_softirq()]); \
|
||||
ptr = __this_cpu_ptr((mib)[0]); \
|
||||
u64_stats_update_begin(&ptr->syncp); \
|
||||
ptr->mibs[basefield##PKTS]++; \
|
||||
ptr->mibs[basefield##OCTETS] += addend; \
|
||||
|
|
|
@ -1430,6 +1430,7 @@ extern void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si);
|
|||
extern u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq);
|
||||
extern int xfrm_init_replay(struct xfrm_state *x);
|
||||
extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
|
||||
extern int __xfrm_init_state(struct xfrm_state *x, bool init_replay);
|
||||
extern int xfrm_init_state(struct xfrm_state *x);
|
||||
extern int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb);
|
||||
extern int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi,
|
||||
|
|
|
@ -720,6 +720,7 @@ static int vlan_dev_init(struct net_device *dev)
|
|||
dev->fcoe_ddp_xid = real_dev->fcoe_ddp_xid;
|
||||
#endif
|
||||
|
||||
dev->needed_headroom = real_dev->needed_headroom;
|
||||
if (real_dev->features & NETIF_F_HW_VLAN_TX) {
|
||||
dev->header_ops = real_dev->header_ops;
|
||||
dev->hard_header_len = real_dev->hard_header_len;
|
||||
|
|
|
@ -1051,6 +1051,7 @@ static int atalk_release(struct socket *sock)
|
|||
{
|
||||
struct sock *sk = sock->sk;
|
||||
|
||||
sock_hold(sk);
|
||||
lock_sock(sk);
|
||||
if (sk) {
|
||||
sock_orphan(sk);
|
||||
|
@ -1058,6 +1059,8 @@ static int atalk_release(struct socket *sock)
|
|||
atalk_destroy_socket(sk);
|
||||
}
|
||||
release_sock(sk);
|
||||
sock_put(sk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -739,6 +739,9 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff *skb,
|
|||
nf_bridge->mask |= BRNF_PKT_TYPE;
|
||||
}
|
||||
|
||||
if (br_parse_ip_options(skb))
|
||||
return NF_DROP;
|
||||
|
||||
/* The physdev module checks on this */
|
||||
nf_bridge->mask |= BRNF_BRIDGED;
|
||||
nf_bridge->physoutdev = skb->dev;
|
||||
|
|
|
@ -350,7 +350,7 @@ static int __init init_net_drop_monitor(void)
|
|||
struct per_cpu_dm_data *data;
|
||||
int cpu, rc;
|
||||
|
||||
printk(KERN_INFO "Initalizing network drop monitor service\n");
|
||||
printk(KERN_INFO "Initializing network drop monitor service\n");
|
||||
|
||||
if (sizeof(void *) > 8) {
|
||||
printk(KERN_ERR "Unable to store program counters on this arch, Drop monitor failed\n");
|
||||
|
|
|
@ -1457,6 +1457,9 @@ static int __ethtool_set_sg(struct net_device *dev, u32 data)
|
|||
{
|
||||
int err;
|
||||
|
||||
if (!dev->ethtool_ops->set_sg)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (data && !(dev->features & NETIF_F_ALL_CSUM))
|
||||
return -EINVAL;
|
||||
|
||||
|
|
|
@ -435,10 +435,10 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
|
|||
udpdest.sin_addr.s_addr = htonl(network | addr.station);
|
||||
}
|
||||
|
||||
memset(&ah, 0, sizeof(ah));
|
||||
ah.port = port;
|
||||
ah.cb = cb & 0x7f;
|
||||
ah.code = 2; /* magic */
|
||||
ah.pad = 0;
|
||||
|
||||
/* tack our header on the front of the iovec */
|
||||
size = sizeof(struct aunhdr);
|
||||
|
|
|
@ -387,7 +387,7 @@ ipt_do_table(struct sk_buff *skb,
|
|||
verdict = (unsigned)(-v) - 1;
|
||||
break;
|
||||
}
|
||||
if (*stackptr == 0) {
|
||||
if (*stackptr <= origptr) {
|
||||
e = get_entry(table_base,
|
||||
private->underflow[hook]);
|
||||
pr_debug("Underflow (this is normal) "
|
||||
|
@ -427,10 +427,10 @@ ipt_do_table(struct sk_buff *skb,
|
|||
/* Verdict */
|
||||
break;
|
||||
} while (!acpar.hotdrop);
|
||||
xt_info_rdunlock_bh();
|
||||
pr_debug("Exiting %s; resetting sp from %u to %u\n",
|
||||
__func__, *stackptr, origptr);
|
||||
*stackptr = origptr;
|
||||
xt_info_rdunlock_bh();
|
||||
#ifdef DEBUG_ALLOW_ALL
|
||||
return NF_ACCEPT;
|
||||
#else
|
||||
|
|
|
@ -664,8 +664,11 @@ static ssize_t clusterip_proc_write(struct file *file, const char __user *input,
|
|||
char buffer[PROC_WRITELEN+1];
|
||||
unsigned long nodenum;
|
||||
|
||||
if (copy_from_user(buffer, input, PROC_WRITELEN))
|
||||
if (size > PROC_WRITELEN)
|
||||
return -EIO;
|
||||
if (copy_from_user(buffer, input, size))
|
||||
return -EFAULT;
|
||||
buffer[size] = 0;
|
||||
|
||||
if (*buffer == '+') {
|
||||
nodenum = simple_strtoul(buffer+1, NULL, 10);
|
||||
|
|
|
@ -410,7 +410,7 @@ ip6t_do_table(struct sk_buff *skb,
|
|||
verdict = (unsigned)(-v) - 1;
|
||||
break;
|
||||
}
|
||||
if (*stackptr == 0)
|
||||
if (*stackptr <= origptr)
|
||||
e = get_entry(table_base,
|
||||
private->underflow[hook]);
|
||||
else
|
||||
|
@ -441,8 +441,8 @@ ip6t_do_table(struct sk_buff *skb,
|
|||
break;
|
||||
} while (!acpar.hotdrop);
|
||||
|
||||
xt_info_rdunlock_bh();
|
||||
*stackptr = origptr;
|
||||
xt_info_rdunlock_bh();
|
||||
|
||||
#ifdef DEBUG_ALLOW_ALL
|
||||
return NF_ACCEPT;
|
||||
|
|
|
@ -17,6 +17,16 @@
|
|||
|
||||
static struct ctl_table empty[1];
|
||||
|
||||
static ctl_table ipv6_static_skeleton[] = {
|
||||
{
|
||||
.procname = "neigh",
|
||||
.maxlen = 0,
|
||||
.mode = 0555,
|
||||
.child = empty,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
static ctl_table ipv6_table_template[] = {
|
||||
{
|
||||
.procname = "route",
|
||||
|
@ -37,12 +47,6 @@ static ctl_table ipv6_table_template[] = {
|
|||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec
|
||||
},
|
||||
{
|
||||
.procname = "neigh",
|
||||
.maxlen = 0,
|
||||
.mode = 0555,
|
||||
.child = empty,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -160,7 +164,7 @@ static struct ctl_table_header *ip6_base;
|
|||
|
||||
int ipv6_static_sysctl_register(void)
|
||||
{
|
||||
ip6_base = register_sysctl_paths(net_ipv6_ctl_path, empty);
|
||||
ip6_base = register_sysctl_paths(net_ipv6_ctl_path, ipv6_static_skeleton);
|
||||
if (ip6_base == NULL)
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
|
|
|
@ -148,7 +148,6 @@ static void ipx_destroy_socket(struct sock *sk)
|
|||
ipx_remove_socket(sk);
|
||||
skb_queue_purge(&sk->sk_receive_queue);
|
||||
sk_refcnt_debug_dec(sk);
|
||||
sock_put(sk);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1404,6 +1403,7 @@ static int ipx_release(struct socket *sock)
|
|||
sk_refcnt_debug_release(sk);
|
||||
ipx_destroy_socket(sk);
|
||||
release_sock(sk);
|
||||
sock_put(sk);
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -283,7 +283,7 @@ static __net_init int l2tp_eth_init_net(struct net *net)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static __net_initdata struct pernet_operations l2tp_eth_net_ops = {
|
||||
static struct pernet_operations l2tp_eth_net_ops = {
|
||||
.init = l2tp_eth_init_net,
|
||||
.id = &l2tp_eth_net_id,
|
||||
.size = sizeof(struct l2tp_eth_net),
|
||||
|
|
|
@ -94,16 +94,28 @@ static int
|
|||
find_set_type_get(const char *name, u8 family, u8 revision,
|
||||
struct ip_set_type **found)
|
||||
{
|
||||
struct ip_set_type *type;
|
||||
int err;
|
||||
|
||||
rcu_read_lock();
|
||||
*found = find_set_type(name, family, revision);
|
||||
if (*found) {
|
||||
int err = !try_module_get((*found)->me);
|
||||
rcu_read_unlock();
|
||||
return err ? -EFAULT : 0;
|
||||
err = !try_module_get((*found)->me) ? -EFAULT : 0;
|
||||
goto unlock;
|
||||
}
|
||||
/* Make sure the type is loaded but we don't support the revision */
|
||||
list_for_each_entry_rcu(type, &ip_set_type_list, list)
|
||||
if (STREQ(type->name, name)) {
|
||||
err = -IPSET_ERR_FIND_TYPE;
|
||||
goto unlock;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
return try_to_load_type(name);
|
||||
|
||||
unlock:
|
||||
rcu_read_unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Find a given set type by name and family.
|
||||
|
@ -116,7 +128,7 @@ find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max)
|
|||
struct ip_set_type *type;
|
||||
bool found = false;
|
||||
|
||||
*min = *max = 0;
|
||||
*min = 255; *max = 0;
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(type, &ip_set_type_list, list)
|
||||
if (STREQ(type->name, name) &&
|
||||
|
@ -124,7 +136,7 @@ find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max)
|
|||
found = true;
|
||||
if (type->revision < *min)
|
||||
*min = type->revision;
|
||||
else if (type->revision > *max)
|
||||
if (type->revision > *max)
|
||||
*max = type->revision;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
|
|
@ -150,6 +150,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
struct hash_ipport4_elem data = { };
|
||||
u32 ip, ip_to, p, port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
bool with_ports = false;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
|
@ -172,21 +173,15 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
with_ports = ip_set_proto_with_ports(data.proto);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
switch (data.proto) {
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_ICMP:
|
||||
break;
|
||||
default:
|
||||
if (!(with_ports || data.proto == IPPROTO_ICMP))
|
||||
data.port = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
|
@ -195,7 +190,6 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
}
|
||||
|
||||
if (adt == IPSET_TEST ||
|
||||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
|
||||
!(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
|
||||
tb[IPSET_ATTR_PORT_TO])) {
|
||||
ret = adtfn(set, &data, timeout);
|
||||
|
@ -219,13 +213,12 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
} else
|
||||
ip_to = ip;
|
||||
|
||||
port = ntohs(data.port);
|
||||
if (tb[IPSET_ATTR_PORT_TO]) {
|
||||
port_to = port = ntohs(data.port);
|
||||
if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port > port_to)
|
||||
swap(port, port_to);
|
||||
} else
|
||||
port_to = port;
|
||||
}
|
||||
|
||||
for (; !before(ip_to, ip); ip++)
|
||||
for (p = port; p <= port_to; p++) {
|
||||
|
@ -361,6 +354,7 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
struct hash_ipport6_elem data = { };
|
||||
u32 port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
bool with_ports = false;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
|
@ -385,21 +379,15 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
with_ports = ip_set_proto_with_ports(data.proto);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
switch (data.proto) {
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_ICMPV6:
|
||||
break;
|
||||
default:
|
||||
if (!(with_ports || data.proto == IPPROTO_ICMPV6))
|
||||
data.port = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
|
@ -407,9 +395,7 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST ||
|
||||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
|
||||
!tb[IPSET_ATTR_PORT_TO]) {
|
||||
if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
|
||||
ret = adtfn(set, &data, timeout);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
|
|
@ -154,6 +154,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
struct hash_ipportip4_elem data = { };
|
||||
u32 ip, ip_to, p, port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
bool with_ports = false;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
|
||||
|
@ -180,21 +181,15 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
with_ports = ip_set_proto_with_ports(data.proto);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
switch (data.proto) {
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_ICMP:
|
||||
break;
|
||||
default:
|
||||
if (!(with_ports || data.proto == IPPROTO_ICMP))
|
||||
data.port = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
|
@ -203,7 +198,6 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
}
|
||||
|
||||
if (adt == IPSET_TEST ||
|
||||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
|
||||
!(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
|
||||
tb[IPSET_ATTR_PORT_TO])) {
|
||||
ret = adtfn(set, &data, timeout);
|
||||
|
@ -227,13 +221,12 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
} else
|
||||
ip_to = ip;
|
||||
|
||||
port = ntohs(data.port);
|
||||
if (tb[IPSET_ATTR_PORT_TO]) {
|
||||
port_to = port = ntohs(data.port);
|
||||
if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port > port_to)
|
||||
swap(port, port_to);
|
||||
} else
|
||||
port_to = port;
|
||||
}
|
||||
|
||||
for (; !before(ip_to, ip); ip++)
|
||||
for (p = port; p <= port_to; p++) {
|
||||
|
@ -375,6 +368,7 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
struct hash_ipportip6_elem data = { };
|
||||
u32 port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
bool with_ports = false;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
|
||||
|
@ -403,21 +397,15 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
with_ports = ip_set_proto_with_ports(data.proto);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
switch (data.proto) {
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_ICMPV6:
|
||||
break;
|
||||
default:
|
||||
if (!(with_ports || data.proto == IPPROTO_ICMPV6))
|
||||
data.port = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
|
@ -425,9 +413,7 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST ||
|
||||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
|
||||
!tb[IPSET_ATTR_PORT_TO]) {
|
||||
if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
|
||||
ret = adtfn(set, &data, timeout);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
|
|
@ -174,6 +174,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
struct hash_ipportnet4_elem data = { .cidr = HOST_MASK };
|
||||
u32 ip, ip_to, p, port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
bool with_ports = false;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
|
||||
|
@ -208,21 +209,15 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
with_ports = ip_set_proto_with_ports(data.proto);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
switch (data.proto) {
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_ICMP:
|
||||
break;
|
||||
default:
|
||||
if (!(with_ports || data.proto == IPPROTO_ICMP))
|
||||
data.port = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
|
@ -231,7 +226,6 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
}
|
||||
|
||||
if (adt == IPSET_TEST ||
|
||||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
|
||||
!(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
|
||||
tb[IPSET_ATTR_PORT_TO])) {
|
||||
ret = adtfn(set, &data, timeout);
|
||||
|
@ -255,13 +249,12 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
} else
|
||||
ip_to = ip;
|
||||
|
||||
port = ntohs(data.port);
|
||||
if (tb[IPSET_ATTR_PORT_TO]) {
|
||||
port_to = port = ntohs(data.port);
|
||||
if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port > port_to)
|
||||
swap(port, port_to);
|
||||
} else
|
||||
port_to = port;
|
||||
}
|
||||
|
||||
for (; !before(ip_to, ip); ip++)
|
||||
for (p = port; p <= port_to; p++) {
|
||||
|
@ -429,6 +422,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
struct hash_ipportnet6_elem data = { .cidr = HOST_MASK };
|
||||
u32 port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
bool with_ports = false;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
|
||||
|
@ -465,21 +459,15 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
with_ports = ip_set_proto_with_ports(data.proto);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
switch (data.proto) {
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_ICMPV6:
|
||||
break;
|
||||
default:
|
||||
if (!(with_ports || data.proto == IPPROTO_ICMPV6))
|
||||
data.port = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
|
@ -487,9 +475,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST ||
|
||||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
|
||||
!tb[IPSET_ATTR_PORT_TO]) {
|
||||
if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
|
||||
ret = adtfn(set, &data, timeout);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
|
|
@ -170,6 +170,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
struct hash_netport4_elem data = { .cidr = HOST_MASK };
|
||||
u32 port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
bool with_ports = false;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
|
@ -198,21 +199,15 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
with_ports = ip_set_proto_with_ports(data.proto);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
switch (data.proto) {
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_ICMP:
|
||||
break;
|
||||
default:
|
||||
if (!(with_ports || data.proto == IPPROTO_ICMP))
|
||||
data.port = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
|
@ -220,9 +215,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST ||
|
||||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
|
||||
!tb[IPSET_ATTR_PORT_TO]) {
|
||||
if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
|
||||
ret = adtfn(set, &data, timeout);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
@ -390,6 +383,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
struct hash_netport6_elem data = { .cidr = HOST_MASK };
|
||||
u32 port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
bool with_ports = false;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
|
@ -418,21 +412,15 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
with_ports = ip_set_proto_with_ports(data.proto);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
switch (data.proto) {
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_ICMPV6:
|
||||
break;
|
||||
default:
|
||||
if (!(with_ports || data.proto == IPPROTO_ICMPV6))
|
||||
data.port = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
|
@ -440,9 +428,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
|
|||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST ||
|
||||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
|
||||
!tb[IPSET_ATTR_PORT_TO]) {
|
||||
if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
|
||||
ret = adtfn(set, &data, timeout);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
|
|
@ -43,6 +43,8 @@ EXPORT_SYMBOL(register_ip_vs_app);
|
|||
EXPORT_SYMBOL(unregister_ip_vs_app);
|
||||
EXPORT_SYMBOL(register_ip_vs_app_inc);
|
||||
|
||||
static DEFINE_MUTEX(__ip_vs_app_mutex);
|
||||
|
||||
/*
|
||||
* Get an ip_vs_app object
|
||||
*/
|
||||
|
@ -167,14 +169,13 @@ int
|
|||
register_ip_vs_app_inc(struct net *net, struct ip_vs_app *app, __u16 proto,
|
||||
__u16 port)
|
||||
{
|
||||
struct netns_ipvs *ipvs = net_ipvs(net);
|
||||
int result;
|
||||
|
||||
mutex_lock(&ipvs->app_mutex);
|
||||
mutex_lock(&__ip_vs_app_mutex);
|
||||
|
||||
result = ip_vs_app_inc_new(net, app, proto, port);
|
||||
|
||||
mutex_unlock(&ipvs->app_mutex);
|
||||
mutex_unlock(&__ip_vs_app_mutex);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -189,11 +190,11 @@ int register_ip_vs_app(struct net *net, struct ip_vs_app *app)
|
|||
/* increase the module use count */
|
||||
ip_vs_use_count_inc();
|
||||
|
||||
mutex_lock(&ipvs->app_mutex);
|
||||
mutex_lock(&__ip_vs_app_mutex);
|
||||
|
||||
list_add(&app->a_list, &ipvs->app_list);
|
||||
|
||||
mutex_unlock(&ipvs->app_mutex);
|
||||
mutex_unlock(&__ip_vs_app_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -205,10 +206,9 @@ int register_ip_vs_app(struct net *net, struct ip_vs_app *app)
|
|||
*/
|
||||
void unregister_ip_vs_app(struct net *net, struct ip_vs_app *app)
|
||||
{
|
||||
struct netns_ipvs *ipvs = net_ipvs(net);
|
||||
struct ip_vs_app *inc, *nxt;
|
||||
|
||||
mutex_lock(&ipvs->app_mutex);
|
||||
mutex_lock(&__ip_vs_app_mutex);
|
||||
|
||||
list_for_each_entry_safe(inc, nxt, &app->incs_list, a_list) {
|
||||
ip_vs_app_inc_release(net, inc);
|
||||
|
@ -216,7 +216,7 @@ void unregister_ip_vs_app(struct net *net, struct ip_vs_app *app)
|
|||
|
||||
list_del(&app->a_list);
|
||||
|
||||
mutex_unlock(&ipvs->app_mutex);
|
||||
mutex_unlock(&__ip_vs_app_mutex);
|
||||
|
||||
/* decrease the module use count */
|
||||
ip_vs_use_count_dec();
|
||||
|
@ -501,7 +501,7 @@ static void *ip_vs_app_seq_start(struct seq_file *seq, loff_t *pos)
|
|||
struct net *net = seq_file_net(seq);
|
||||
struct netns_ipvs *ipvs = net_ipvs(net);
|
||||
|
||||
mutex_lock(&ipvs->app_mutex);
|
||||
mutex_lock(&__ip_vs_app_mutex);
|
||||
|
||||
return *pos ? ip_vs_app_idx(ipvs, *pos - 1) : SEQ_START_TOKEN;
|
||||
}
|
||||
|
@ -535,9 +535,7 @@ static void *ip_vs_app_seq_next(struct seq_file *seq, void *v, loff_t *pos)
|
|||
|
||||
static void ip_vs_app_seq_stop(struct seq_file *seq, void *v)
|
||||
{
|
||||
struct netns_ipvs *ipvs = net_ipvs(seq_file_net(seq));
|
||||
|
||||
mutex_unlock(&ipvs->app_mutex);
|
||||
mutex_unlock(&__ip_vs_app_mutex);
|
||||
}
|
||||
|
||||
static int ip_vs_app_seq_show(struct seq_file *seq, void *v)
|
||||
|
@ -583,7 +581,6 @@ static int __net_init __ip_vs_app_init(struct net *net)
|
|||
struct netns_ipvs *ipvs = net_ipvs(net);
|
||||
|
||||
INIT_LIST_HEAD(&ipvs->app_list);
|
||||
__mutex_init(&ipvs->app_mutex, "ipvs->app_mutex", &ipvs->app_key);
|
||||
proc_net_fops_create(net, "ip_vs_app", 0, &ip_vs_app_fops);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -3605,7 +3605,7 @@ int __net_init __ip_vs_control_init(struct net *net)
|
|||
|
||||
/* procfs stats */
|
||||
ipvs->tot_stats.cpustats = alloc_percpu(struct ip_vs_cpu_stats);
|
||||
if (ipvs->tot_stats.cpustats) {
|
||||
if (!ipvs->tot_stats.cpustats) {
|
||||
pr_err("%s(): alloc_percpu.\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
|
118
net/socket.c
118
net/socket.c
|
@ -2588,23 +2588,123 @@ static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
|
|||
|
||||
static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
|
||||
{
|
||||
struct compat_ethtool_rxnfc __user *compat_rxnfc;
|
||||
bool convert_in = false, convert_out = false;
|
||||
size_t buf_size = ALIGN(sizeof(struct ifreq), 8);
|
||||
struct ethtool_rxnfc __user *rxnfc;
|
||||
struct ifreq __user *ifr;
|
||||
u32 rule_cnt = 0, actual_rule_cnt;
|
||||
u32 ethcmd;
|
||||
u32 data;
|
||||
void __user *datap;
|
||||
|
||||
ifr = compat_alloc_user_space(sizeof(*ifr));
|
||||
|
||||
if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
|
||||
return -EFAULT;
|
||||
int ret;
|
||||
|
||||
if (get_user(data, &ifr32->ifr_ifru.ifru_data))
|
||||
return -EFAULT;
|
||||
|
||||
datap = compat_ptr(data);
|
||||
if (put_user(datap, &ifr->ifr_ifru.ifru_data))
|
||||
compat_rxnfc = compat_ptr(data);
|
||||
|
||||
if (get_user(ethcmd, &compat_rxnfc->cmd))
|
||||
return -EFAULT;
|
||||
|
||||
return dev_ioctl(net, SIOCETHTOOL, ifr);
|
||||
/* Most ethtool structures are defined without padding.
|
||||
* Unfortunately struct ethtool_rxnfc is an exception.
|
||||
*/
|
||||
switch (ethcmd) {
|
||||
default:
|
||||
break;
|
||||
case ETHTOOL_GRXCLSRLALL:
|
||||
/* Buffer size is variable */
|
||||
if (get_user(rule_cnt, &compat_rxnfc->rule_cnt))
|
||||
return -EFAULT;
|
||||
if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32))
|
||||
return -ENOMEM;
|
||||
buf_size += rule_cnt * sizeof(u32);
|
||||
/* fall through */
|
||||
case ETHTOOL_GRXRINGS:
|
||||
case ETHTOOL_GRXCLSRLCNT:
|
||||
case ETHTOOL_GRXCLSRULE:
|
||||
convert_out = true;
|
||||
/* fall through */
|
||||
case ETHTOOL_SRXCLSRLDEL:
|
||||
case ETHTOOL_SRXCLSRLINS:
|
||||
buf_size += sizeof(struct ethtool_rxnfc);
|
||||
convert_in = true;
|
||||
break;
|
||||
}
|
||||
|
||||
ifr = compat_alloc_user_space(buf_size);
|
||||
rxnfc = (void *)ifr + ALIGN(sizeof(struct ifreq), 8);
|
||||
|
||||
if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
|
||||
return -EFAULT;
|
||||
|
||||
if (put_user(convert_in ? rxnfc : compat_ptr(data),
|
||||
&ifr->ifr_ifru.ifru_data))
|
||||
return -EFAULT;
|
||||
|
||||
if (convert_in) {
|
||||
/* We expect there to be holes between fs.m_u and
|
||||
* fs.ring_cookie and at the end of fs, but nowhere else.
|
||||
*/
|
||||
BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_u) +
|
||||
sizeof(compat_rxnfc->fs.m_u) !=
|
||||
offsetof(struct ethtool_rxnfc, fs.m_u) +
|
||||
sizeof(rxnfc->fs.m_u));
|
||||
BUILD_BUG_ON(
|
||||
offsetof(struct compat_ethtool_rxnfc, fs.location) -
|
||||
offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) !=
|
||||
offsetof(struct ethtool_rxnfc, fs.location) -
|
||||
offsetof(struct ethtool_rxnfc, fs.ring_cookie));
|
||||
|
||||
if (copy_in_user(rxnfc, compat_rxnfc,
|
||||
(void *)(&rxnfc->fs.m_u + 1) -
|
||||
(void *)rxnfc) ||
|
||||
copy_in_user(&rxnfc->fs.ring_cookie,
|
||||
&compat_rxnfc->fs.ring_cookie,
|
||||
(void *)(&rxnfc->fs.location + 1) -
|
||||
(void *)&rxnfc->fs.ring_cookie) ||
|
||||
copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt,
|
||||
sizeof(rxnfc->rule_cnt)))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ret = dev_ioctl(net, SIOCETHTOOL, ifr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (convert_out) {
|
||||
if (copy_in_user(compat_rxnfc, rxnfc,
|
||||
(const void *)(&rxnfc->fs.m_u + 1) -
|
||||
(const void *)rxnfc) ||
|
||||
copy_in_user(&compat_rxnfc->fs.ring_cookie,
|
||||
&rxnfc->fs.ring_cookie,
|
||||
(const void *)(&rxnfc->fs.location + 1) -
|
||||
(const void *)&rxnfc->fs.ring_cookie) ||
|
||||
copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt,
|
||||
sizeof(rxnfc->rule_cnt)))
|
||||
return -EFAULT;
|
||||
|
||||
if (ethcmd == ETHTOOL_GRXCLSRLALL) {
|
||||
/* As an optimisation, we only copy the actual
|
||||
* number of rules that the underlying
|
||||
* function returned. Since Mallory might
|
||||
* change the rule count in user memory, we
|
||||
* check that it is less than the rule count
|
||||
* originally given (as the user buffer size),
|
||||
* which has been range-checked.
|
||||
*/
|
||||
if (get_user(actual_rule_cnt, &rxnfc->rule_cnt))
|
||||
return -EFAULT;
|
||||
if (actual_rule_cnt < rule_cnt)
|
||||
rule_cnt = actual_rule_cnt;
|
||||
if (copy_in_user(&compat_rxnfc->rule_locs[0],
|
||||
&rxnfc->rule_locs[0],
|
||||
rule_cnt * sizeof(u32)))
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
|
||||
|
|
|
@ -1907,7 +1907,7 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu)
|
|||
return res;
|
||||
}
|
||||
|
||||
int xfrm_init_state(struct xfrm_state *x)
|
||||
int __xfrm_init_state(struct xfrm_state *x, bool init_replay)
|
||||
{
|
||||
struct xfrm_state_afinfo *afinfo;
|
||||
struct xfrm_mode *inner_mode;
|
||||
|
@ -1980,12 +1980,25 @@ int xfrm_init_state(struct xfrm_state *x)
|
|||
if (x->outer_mode == NULL)
|
||||
goto error;
|
||||
|
||||
if (init_replay) {
|
||||
err = xfrm_init_replay(x);
|
||||
if (err)
|
||||
goto error;
|
||||
}
|
||||
|
||||
x->km.state = XFRM_STATE_VALID;
|
||||
|
||||
error:
|
||||
return err;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(__xfrm_init_state);
|
||||
|
||||
int xfrm_init_state(struct xfrm_state *x)
|
||||
{
|
||||
return __xfrm_init_state(x, true);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(xfrm_init_state);
|
||||
|
||||
int __net_init xfrm_state_init(struct net *net)
|
||||
|
|
|
@ -511,7 +511,7 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
|
|||
|
||||
xfrm_mark_get(attrs, &x->mark);
|
||||
|
||||
err = xfrm_init_state(x);
|
||||
err = __xfrm_init_state(x, false);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче