#include <linux/wireless.h>
#include <linux/skbuff.h>
#include <linux/udp.h>
+#include <linux/slab.h>
#include <net/sock.h>
#include <net/inet_common.h>
#include <linux/stat.h>
/* Real hardware Econet. We're not worthy etc. */
#ifdef CONFIG_ECONET_NATIVE
unsigned short proto = 0;
+ int res;
dev_hold(dev);
- skb = sock_alloc_send_skb(sk, len+LL_RESERVED_SPACE(dev),
+ skb = sock_alloc_send_skb(sk, len+LL_ALLOCATED_SPACE(dev),
msg->msg_flags & MSG_DONTWAIT, &err);
if (skb==NULL)
goto out_unlock;
eb->sec = *saddr;
eb->sent = ec_tx_done;
- if (dev->hard_header) {
- int res;
+ err = -EINVAL;
+ res = dev_hard_header(skb, dev, ntohs(proto), &addr, NULL, len);
+ if (res < 0)
+ goto out_free;
+ if (res > 0) {
struct ec_framehdr *fh;
- err = -EINVAL;
- res = dev->hard_header(skb, dev, ntohs(proto),
- &addr, NULL, len);
/* Poke in our control byte and
port number. Hack, hack. */
fh = (struct ec_framehdr *)(skb->data);
if (sock->type != SOCK_DGRAM) {
skb_reset_tail_pointer(skb);
skb->len = 0;
- } else if (res < 0)
- goto out_free;
+ }
}
/* Copy the data. Returns -EFAULT on error */
iov[0].iov_len = size;
for (i = 0; i < msg->msg_iovlen; i++) {
void __user *base = msg->msg_iov[i].iov_base;
- size_t len = msg->msg_iov[i].iov_len;
+ size_t iov_len = msg->msg_iov[i].iov_len;
/* Check it now since we switch to KERNEL_DS later. */
- if (!access_ok(VERIFY_READ, base, len)) {
+ if (!access_ok(VERIFY_READ, base, iov_len)) {
mutex_unlock(&econet_mutex);
return -EFAULT;
}
iov[i+1].iov_base = base;
- iov[i+1].iov_len = len;
- size += len;
+ iov[i+1].iov_len = iov_len;
+ size += iov_len;
}
/* Get a skbuff (no data, just holds our cb information) */
if (peer)
return -EOPNOTSUPP;
+ memset(sec, 0, sizeof(*sec));
mutex_lock(&econet_mutex);
sk = sock->sk;
{
struct sock *sk=(struct sock *)data;
- if (!atomic_read(&sk->sk_wmem_alloc) &&
- !atomic_read(&sk->sk_rmem_alloc)) {
+ if (!sk_has_allocations(sk)) {
sk_free(sk);
return;
}
sk->sk_state_change(sk); /* It is useless. Just for sanity. */
- sock->sk = NULL;
- sk->sk_socket = NULL;
- sock_set_flag(sk, SOCK_DEAD);
+ sock_orphan(sk);
/* Purge queues */
skb_queue_purge(&sk->sk_receive_queue);
- if (atomic_read(&sk->sk_rmem_alloc) ||
- atomic_read(&sk->sk_wmem_alloc)) {
+ if (sk_has_allocations(sk)) {
sk->sk_timer.data = (unsigned long)sk;
sk->sk_timer.expires = jiffies + HZ;
sk->sk_timer.function = econet_destroy_timer;
* Create an Econet socket
*/
-static int econet_create(struct net *net, struct socket *sock, int protocol)
+static int econet_create(struct net *net, struct socket *sock, int protocol,
+ int kern)
{
struct sock *sk;
struct econet_sock *eo;
int err;
- if (net != &init_net)
+ if (!net_eq(net, &init_net))
return -EAFNOSUPPORT;
/* Econet only provides datagram services. */
sock->state = SS_UNCONNECTED;
err = -ENOBUFS;
- sk = sk_alloc(net, PF_ECONET, GFP_KERNEL, &econet_proto, 1);
+ sk = sk_alloc(net, PF_ECONET, GFP_KERNEL, &econet_proto);
if (sk == NULL)
goto out;
if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
return -EFAULT;
- if ((dev = dev_get_by_name(ifr.ifr_name)) == NULL)
+ if ((dev = dev_get_by_name(&init_net, ifr.ifr_name)) == NULL)
return -ENODEV;
sec = (struct sockaddr_ec *)&ifr.ifr_addr;
return 0;
}
-static struct net_proto_family econet_family_ops = {
+static const struct net_proto_family econet_family_ops = {
.family = PF_ECONET,
.create = econet_create,
.owner = THIS_MODULE,
struct ec_cb *eb;
spin_lock_irqsave(&aun_queue_lock, flags);
- skb = skb_peek(&aun_queue);
- while (skb && skb != (struct sk_buff *)&aun_queue)
- {
- struct sk_buff *newskb = skb->next;
+ skb_queue_walk(&aun_queue, skb) {
eb = (struct ec_cb *)&skb->cb;
if (eb->seq == seq)
goto foundit;
-
- skb = newskb;
}
spin_unlock_irqrestore(&aun_queue_lock, flags);
printk(KERN_DEBUG "AUN: unknown sequence %ld\n", seq);
static void ab_cleanup(unsigned long h)
{
- struct sk_buff *skb;
+ struct sk_buff *skb, *n;
unsigned long flags;
spin_lock_irqsave(&aun_queue_lock, flags);
- skb = skb_peek(&aun_queue);
- while (skb && skb != (struct sk_buff *)&aun_queue)
- {
- struct sk_buff *newskb = skb->next;
+ skb_queue_walk_safe(&aun_queue, skb, n) {
struct ec_cb *eb = (struct ec_cb *)&skb->cb;
- if ((jiffies - eb->start) > eb->timeout)
- {
+ if ((jiffies - eb->start) > eb->timeout) {
tx_result(skb->sk, eb->cookie,
ECTYPE_TRANSMIT_NOT_PRESENT);
skb_unlink(skb, &aun_queue);
kfree_skb(skb);
}
- skb = newskb;
}
spin_unlock_irqrestore(&aun_queue_lock, flags);
skb_queue_head_init(&aun_queue);
spin_lock_init(&aun_queue_lock);
- init_timer(&ab_cleanup_timer);
+ setup_timer(&ab_cleanup_timer, ab_cleanup, 0);
ab_cleanup_timer.expires = jiffies + (HZ*2);
- ab_cleanup_timer.function = ab_cleanup;
add_timer(&ab_cleanup_timer);
memset(&sin, 0, sizeof(sin));
struct sock *sk;
struct ec_device *edev = dev->ec_ptr;
- if (dev->nd_net != &init_net)
+ if (!net_eq(dev_net(dev), &init_net))
goto drop;
if (skb->pkt_type == PACKET_OTHERHOST)
skb->protocol = htons(ETH_P_IP);
skb_pull(skb, sizeof(struct ec_framehdr));
netif_rx(skb);
- return 0;
+ return NET_RX_SUCCESS;
}
sk = ec_listening_socket(hdr->port, hdr->src_stn, hdr->src_net);
hdr->port))
goto drop;
- return 0;
+ return NET_RX_SUCCESS;
drop:
kfree_skb(skb);
return NET_RX_DROP;
}
-static struct packet_type econet_packet_type = {
- .type = __constant_htons(ETH_P_ECONET),
+static struct packet_type econet_packet_type __read_mostly = {
+ .type = cpu_to_be16(ETH_P_ECONET),
.func = econet_rcv,
};
struct net_device *dev = (struct net_device *)data;
struct ec_device *edev;
+ if (!net_eq(dev_net(dev), &init_net))
+ return NOTIFY_DONE;
+
switch (msg) {
case NETDEV_UNREGISTER:
/* A device has gone down - kill any data we hold for it. */