aboutsummaryrefslogtreecommitdiff
path: root/net/appletalk
diff options
context:
space:
mode:
Diffstat (limited to 'net/appletalk')
-rw-r--r--net/appletalk/aarp.c256
-rw-r--r--net/appletalk/atalk_proc.c83
-rw-r--r--net/appletalk/ddp.c942
-rw-r--r--net/appletalk/dev.c21
-rw-r--r--net/appletalk/sysctl_net_atalk.c41
5 files changed, 662 insertions, 681 deletions
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c
index f3777ec5bcb..d1c55d8dd0a 100644
--- a/net/appletalk/aarp.c
+++ b/net/appletalk/aarp.c
@@ -30,6 +30,7 @@
*/
#include <linux/if_arp.h>
+#include <linux/slab.h>
#include <net/sock.h>
#include <net/datalink.h>
#include <net/psnap.h>
@@ -38,6 +39,8 @@
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <linux/export.h>
+#include <linux/etherdevice.h>
int sysctl_aarp_expiry_time = AARP_EXPIRY_TIME;
int sysctl_aarp_tick_time = AARP_TICK_TIME;
@@ -65,7 +68,7 @@ struct aarp_entry {
unsigned long expires_at;
struct atalk_addr target_addr;
struct net_device *dev;
- char hwaddr[6];
+ char hwaddr[ETH_ALEN];
unsigned short xmit_count;
struct aarp_entry *next;
};
@@ -118,7 +121,9 @@ static void __aarp_send_query(struct aarp_entry *a)
/* Set up the buffer */
skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length);
- skb->nh.raw = skb->h.raw = skb_put(skb, sizeof(*eah));
+ skb_reset_network_header(skb);
+ skb_reset_transport_header(skb);
+ skb_put(skb, sizeof(*eah));
skb->protocol = htons(ETH_P_ATALK);
skb->dev = dev;
eah = aarp_hdr(skb);
@@ -130,7 +135,7 @@ static void __aarp_send_query(struct aarp_entry *a)
eah->pa_len = AARP_PA_ALEN;
eah->function = htons(AARP_REQUEST);
- memcpy(eah->hw_src, dev->dev_addr, ETH_ALEN);
+ ether_addr_copy(eah->hw_src, dev->dev_addr);
eah->pa_src_zero = 0;
eah->pa_src_net = sat->s_net;
@@ -163,7 +168,9 @@ static void aarp_send_reply(struct net_device *dev, struct atalk_addr *us,
/* Set up the buffer */
skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length);
- skb->nh.raw = skb->h.raw = skb_put(skb, sizeof(*eah));
+ skb_reset_network_header(skb);
+ skb_reset_transport_header(skb);
+ skb_put(skb, sizeof(*eah));
skb->protocol = htons(ETH_P_ATALK);
skb->dev = dev;
eah = aarp_hdr(skb);
@@ -175,7 +182,7 @@ static void aarp_send_reply(struct net_device *dev, struct atalk_addr *us,
eah->pa_len = AARP_PA_ALEN;
eah->function = htons(AARP_REPLY);
- memcpy(eah->hw_src, dev->dev_addr, ETH_ALEN);
+ ether_addr_copy(eah->hw_src, dev->dev_addr);
eah->pa_src_zero = 0;
eah->pa_src_net = us->s_net;
@@ -184,7 +191,7 @@ static void aarp_send_reply(struct net_device *dev, struct atalk_addr *us,
if (!sha)
memset(eah->hw_dst, '\0', ETH_ALEN);
else
- memcpy(eah->hw_dst, sha, ETH_ALEN);
+ ether_addr_copy(eah->hw_dst, sha);
eah->pa_dst_zero = 0;
eah->pa_dst_net = them->s_net;
@@ -212,7 +219,9 @@ static void aarp_send_probe(struct net_device *dev, struct atalk_addr *us)
/* Set up the buffer */
skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length);
- skb->nh.raw = skb->h.raw = skb_put(skb, sizeof(*eah));
+ skb_reset_network_header(skb);
+ skb_reset_transport_header(skb);
+ skb_put(skb, sizeof(*eah));
skb->protocol = htons(ETH_P_ATALK);
skb->dev = dev;
eah = aarp_hdr(skb);
@@ -224,7 +233,7 @@ static void aarp_send_probe(struct net_device *dev, struct atalk_addr *us)
eah->pa_len = AARP_PA_ALEN;
eah->function = htons(AARP_PROBE);
- memcpy(eah->hw_src, dev->dev_addr, ETH_ALEN);
+ ether_addr_copy(eah->hw_src, dev->dev_addr);
eah->pa_src_zero = 0;
eah->pa_src_net = us->s_net;
@@ -324,15 +333,19 @@ static void aarp_expire_timeout(unsigned long unused)
static int aarp_device_event(struct notifier_block *this, unsigned long event,
void *ptr)
{
+ struct net_device *dev = netdev_notifier_info_to_dev(ptr);
int ct;
+ if (!net_eq(dev_net(dev), &init_net))
+ return NOTIFY_DONE;
+
if (event == NETDEV_DOWN) {
write_lock_bh(&aarp_lock);
for (ct = 0; ct < AARP_HASH_SIZE; ct++) {
- __aarp_expire_device(&resolved[ct], ptr);
- __aarp_expire_device(&unresolved[ct], ptr);
- __aarp_expire_device(&proxies[ct], ptr);
+ __aarp_expire_device(&resolved[ct], dev);
+ __aarp_expire_device(&unresolved[ct], dev);
+ __aarp_expire_device(&proxies[ct], dev);
}
write_unlock_bh(&aarp_lock);
@@ -433,13 +446,14 @@ static void aarp_send_probe_phase1(struct atalk_iface *iface)
{
struct ifreq atreq;
struct sockaddr_at *sa = (struct sockaddr_at *)&atreq.ifr_addr;
+ const struct net_device_ops *ops = iface->dev->netdev_ops;
sa->sat_addr.s_node = iface->address.s_node;
sa->sat_addr.s_net = ntohs(iface->address.s_net);
/* We pass the Net:Node to the drivers/cards by a Device ioctl. */
- if (!(iface->dev->do_ioctl(iface->dev, &atreq, SIOCSIFADDR))) {
- (void)iface->dev->do_ioctl(iface->dev, &atreq, SIOCGIFADDR);
+ if (!(ops->ndo_do_ioctl(iface->dev, &atreq, SIOCSIFADDR))) {
+ ops->ndo_do_ioctl(iface->dev, &atreq, SIOCGIFADDR);
if (iface->address.s_net != htons(sa->sat_addr.s_net) ||
iface->address.s_node != sa->sat_addr.s_node)
iface->status |= ATIF_PROBE_FAIL;
@@ -539,7 +553,7 @@ int aarp_send_ddp(struct net_device *dev, struct sk_buff *skb,
int hash;
struct aarp_entry *a;
- skb->nh.raw = skb->data;
+ skb_reset_network_header(skb);
/* Check for LocalTalk first */
if (dev->type == ARPHRD_LOCALTLK) {
@@ -588,7 +602,7 @@ int aarp_send_ddp(struct net_device *dev, struct sk_buff *skb,
/* Non ELAP we cannot do. */
if (dev->type != ARPHRD_ETHER)
- return -1;
+ goto free_it;
skb->dev = dev;
skb->protocol = htons(ETH_P_ATALK);
@@ -623,7 +637,7 @@ int aarp_send_ddp(struct net_device *dev, struct sk_buff *skb,
if (!a) {
/* Whoops slipped... good job it's an unreliable protocol 8) */
write_unlock_bh(&aarp_lock);
- return -1;
+ goto free_it;
}
/* Set up the queue */
@@ -652,15 +666,21 @@ out_unlock:
write_unlock_bh(&aarp_lock);
/* Tell the ddp layer we have taken over for this frame. */
- return 0;
+ goto sent;
sendit:
if (skb->sk)
skb->priority = skb->sk->sk_priority;
- dev_queue_xmit(skb);
+ if (dev_queue_xmit(skb))
+ goto drop;
sent:
- return 1;
+ return NET_XMIT_SUCCESS;
+free_it:
+ kfree_skb(skb);
+drop:
+ return NET_XMIT_DROP;
}
+EXPORT_SYMBOL(aarp_send_ddp);
/*
* An entry in the aarp unresolved queue has become resolved. Send
@@ -706,6 +726,9 @@ static int aarp_rcv(struct sk_buff *skb, struct net_device *dev,
struct atalk_addr sa, *ma, da;
struct atalk_iface *ifa;
+ if (!net_eq(dev_net(dev), &init_net))
+ goto out0;
+
/* We only do Ethernet SNAP AARP. */
if (dev->type != ARPHRD_ETHER)
goto out0;
@@ -758,89 +781,87 @@ static int aarp_rcv(struct sk_buff *skb, struct net_device *dev,
}
switch (function) {
- case AARP_REPLY:
- if (!unresolved_count) /* Speed up */
- break;
-
- /* Find the entry. */
- a = __aarp_find_entry(unresolved[hash], dev, &sa);
- if (!a || dev != a->dev)
- break;
+ case AARP_REPLY:
+ if (!unresolved_count) /* Speed up */
+ break;
- /* We can fill one in - this is good. */
- memcpy(a->hwaddr, ea->hw_src, ETH_ALEN);
- __aarp_resolved(&unresolved[hash], a, hash);
- if (!unresolved_count)
- mod_timer(&aarp_timer,
- jiffies + sysctl_aarp_expiry_time);
+ /* Find the entry. */
+ a = __aarp_find_entry(unresolved[hash], dev, &sa);
+ if (!a || dev != a->dev)
break;
- case AARP_REQUEST:
- case AARP_PROBE:
+ /* We can fill one in - this is good. */
+ ether_addr_copy(a->hwaddr, ea->hw_src);
+ __aarp_resolved(&unresolved[hash], a, hash);
+ if (!unresolved_count)
+ mod_timer(&aarp_timer,
+ jiffies + sysctl_aarp_expiry_time);
+ break;
+ case AARP_REQUEST:
+ case AARP_PROBE:
+
+ /*
+ * If it is my address set ma to my address and reply.
+ * We can treat probe and request the same. Probe
+ * simply means we shouldn't cache the querying host,
+ * as in a probe they are proposing an address not
+ * using one.
+ *
+ * Support for proxy-AARP added. We check if the
+ * address is one of our proxies before we toss the
+ * packet out.
+ */
+
+ sa.s_node = ea->pa_dst_node;
+ sa.s_net = ea->pa_dst_net;
+
+ /* See if we have a matching proxy. */
+ ma = __aarp_proxy_find(dev, &sa);
+ if (!ma)
+ ma = &ifa->address;
+ else { /* We need to make a copy of the entry. */
+ da.s_node = sa.s_node;
+ da.s_net = sa.s_net;
+ ma = &da;
+ }
+
+ if (function == AARP_PROBE) {
/*
- * If it is my address set ma to my address and reply.
- * We can treat probe and request the same. Probe
- * simply means we shouldn't cache the querying host,
- * as in a probe they are proposing an address not
- * using one.
- *
- * Support for proxy-AARP added. We check if the
- * address is one of our proxies before we toss the
- * packet out.
+ * A probe implies someone trying to get an
+ * address. So as a precaution flush any
+ * entries we have for this address.
*/
+ a = __aarp_find_entry(resolved[sa.s_node %
+ (AARP_HASH_SIZE - 1)],
+ skb->dev, &sa);
- sa.s_node = ea->pa_dst_node;
- sa.s_net = ea->pa_dst_net;
-
- /* See if we have a matching proxy. */
- ma = __aarp_proxy_find(dev, &sa);
- if (!ma)
- ma = &ifa->address;
- else { /* We need to make a copy of the entry. */
- da.s_node = sa.s_node;
- da.s_net = da.s_net;
- ma = &da;
- }
-
- if (function == AARP_PROBE) {
- /*
- * A probe implies someone trying to get an
- * address. So as a precaution flush any
- * entries we have for this address.
- */
- struct aarp_entry *a;
-
- a = __aarp_find_entry(resolved[sa.s_node %
- (AARP_HASH_SIZE - 1)],
- skb->dev, &sa);
-
- /*
- * Make it expire next tick - that avoids us
- * getting into a probe/flush/learn/probe/
- * flush/learn cycle during probing of a slow
- * to respond host addr.
- */
- if (a) {
- a->expires_at = jiffies - 1;
- mod_timer(&aarp_timer, jiffies +
- sysctl_aarp_tick_time);
- }
+ /*
+ * Make it expire next tick - that avoids us
+ * getting into a probe/flush/learn/probe/
+ * flush/learn cycle during probing of a slow
+ * to respond host addr.
+ */
+ if (a) {
+ a->expires_at = jiffies - 1;
+ mod_timer(&aarp_timer, jiffies +
+ sysctl_aarp_tick_time);
}
+ }
- if (sa.s_node != ma->s_node)
- break;
+ if (sa.s_node != ma->s_node)
+ break;
- if (sa.s_net && ma->s_net && sa.s_net != ma->s_net)
- break;
+ if (sa.s_net && ma->s_net && sa.s_net != ma->s_net)
+ break;
- sa.s_node = ea->pa_src_node;
- sa.s_net = ea->pa_src_net;
+ sa.s_node = ea->pa_src_node;
+ sa.s_net = ea->pa_src_net;
- /* aarp_my_address has found the address to use for us.
- */
- aarp_send_reply(dev, ma, &sa, ea->hw_src);
- break;
+ /* aarp_my_address has found the address to use for us.
+ */
+ aarp_send_reply(dev, ma, &sa, ea->hw_src);
+ break;
}
unlock:
@@ -863,9 +884,7 @@ void __init aarp_proto_init(void)
aarp_dl = register_snap_client(aarp_snap_id, aarp_rcv);
if (!aarp_dl)
printk(KERN_CRIT "Unable to register AARP with SNAP.\n");
- init_timer(&aarp_timer);
- aarp_timer.function = aarp_expire_timeout;
- aarp_timer.data = 0;
+ setup_timer(&aarp_timer, aarp_expire_timeout, 0);
aarp_timer.expires = jiffies + sysctl_aarp_expiry_time;
add_timer(&aarp_timer);
register_netdevice_notifier(&aarp_notifier);
@@ -895,7 +914,7 @@ struct aarp_iter_state {
/*
* Get the aarp entry that is in the chain described
- * by the iterator.
+ * by the iterator.
* If pos is set then skip till that index.
* pos = 1 is the first entry
*/
@@ -905,9 +924,9 @@ static struct aarp_entry *iter_next(struct aarp_iter_state *iter, loff_t *pos)
struct aarp_entry **table = iter->table;
loff_t off = 0;
struct aarp_entry *entry;
-
+
rescan:
- while(ct < AARP_HASH_SIZE) {
+ while (ct < AARP_HASH_SIZE) {
for (entry = table[ct]; entry; entry = entry->next) {
if (!pos || ++off == *pos) {
iter->table = table;
@@ -932,6 +951,7 @@ static struct aarp_entry *iter_next(struct aarp_iter_state *iter, loff_t *pos)
}
static void *aarp_seq_start(struct seq_file *seq, loff_t *pos)
+ __acquires(aarp_lock)
{
struct aarp_iter_state *iter = seq->private;
@@ -950,9 +970,9 @@ static void *aarp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
++*pos;
/* first line after header */
- if (v == SEQ_START_TOKEN)
+ if (v == SEQ_START_TOKEN)
entry = iter_next(iter, NULL);
-
+
/* next entry in current bucket */
else if (entry->next)
entry = entry->next;
@@ -966,6 +986,7 @@ static void *aarp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
}
static void aarp_seq_stop(struct seq_file *seq, void *v)
+ __releases(aarp_lock)
{
read_unlock_bh(&aarp_lock);
}
@@ -974,7 +995,7 @@ static const char *dt2str(unsigned long ticks)
{
static char buf[32];
- sprintf(buf, "%ld.%02ld", ticks / HZ, ((ticks % HZ) * 100 ) / HZ);
+ sprintf(buf, "%ld.%02ld", ticks / HZ, ((ticks % HZ) * 100) / HZ);
return buf;
}
@@ -986,7 +1007,7 @@ static int aarp_seq_show(struct seq_file *seq, void *v)
unsigned long now = jiffies;
if (v == SEQ_START_TOKEN)
- seq_puts(seq,
+ seq_puts(seq,
"Address Interface Hardware Address"
" Expires LastSend Retry Status\n");
else {
@@ -994,13 +1015,7 @@ static int aarp_seq_show(struct seq_file *seq, void *v)
ntohs(entry->target_addr.s_net),
(unsigned int) entry->target_addr.s_node,
entry->dev ? entry->dev->name : "????");
- seq_printf(seq, "%02X:%02X:%02X:%02X:%02X:%02X",
- entry->hwaddr[0] & 0xFF,
- entry->hwaddr[1] & 0xFF,
- entry->hwaddr[2] & 0xFF,
- entry->hwaddr[3] & 0xFF,
- entry->hwaddr[4] & 0xFF,
- entry->hwaddr[5] & 0xFF);
+ seq_printf(seq, "%pM", entry->hwaddr);
seq_printf(seq, " %8s",
dt2str((long)entry->expires_at - (long)now));
if (iter->table == unresolved)
@@ -1014,11 +1029,11 @@ static int aarp_seq_show(struct seq_file *seq, void *v)
: (iter->table == unresolved) ? "unresolved"
: (iter->table == proxies) ? "proxies"
: "unknown");
- }
+ }
return 0;
}
-static struct seq_operations aarp_seq_ops = {
+static const struct seq_operations aarp_seq_ops = {
.start = aarp_seq_start,
.next = aarp_seq_next,
.stop = aarp_seq_stop,
@@ -1027,28 +1042,11 @@ static struct seq_operations aarp_seq_ops = {
static int aarp_seq_open(struct inode *inode, struct file *file)
{
- struct seq_file *seq;
- int rc = -ENOMEM;
- struct aarp_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
-
- if (!s)
- goto out;
-
- rc = seq_open(file, &aarp_seq_ops);
- if (rc)
- goto out_kfree;
-
- seq = file->private_data;
- seq->private = s;
- memset(s, 0, sizeof(*s));
-out:
- return rc;
-out_kfree:
- kfree(s);
- goto out;
+ return seq_open_private(file, &aarp_seq_ops,
+ sizeof(struct aarp_iter_state));
}
-struct file_operations atalk_seq_arp_fops = {
+const struct file_operations atalk_seq_arp_fops = {
.owner = THIS_MODULE,
.open = aarp_seq_open,
.read = seq_read,
diff --git a/net/appletalk/atalk_proc.c b/net/appletalk/atalk_proc.c
index 7ae4916cd26..af46bc49e1e 100644
--- a/net/appletalk/atalk_proc.c
+++ b/net/appletalk/atalk_proc.c
@@ -11,8 +11,10 @@
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <net/net_namespace.h>
#include <net/sock.h>
#include <linux/atalk.h>
+#include <linux/export.h>
static __inline__ struct atalk_iface *atalk_get_interface_idx(loff_t pos)
@@ -26,6 +28,7 @@ static __inline__ struct atalk_iface *atalk_get_interface_idx(loff_t pos)
}
static void *atalk_seq_interface_start(struct seq_file *seq, loff_t *pos)
+ __acquires(atalk_interfaces_lock)
{
loff_t l = *pos;
@@ -51,6 +54,7 @@ out:
}
static void atalk_seq_interface_stop(struct seq_file *seq, void *v)
+ __releases(atalk_interfaces_lock)
{
read_unlock_bh(&atalk_interfaces_lock);
}
@@ -85,6 +89,7 @@ static __inline__ struct atalk_route *atalk_get_route_idx(loff_t pos)
}
static void *atalk_seq_route_start(struct seq_file *seq, loff_t *pos)
+ __acquires(atalk_routes_lock)
{
loff_t l = *pos;
@@ -110,6 +115,7 @@ out:
}
static void atalk_seq_route_stop(struct seq_file *seq, void *v)
+ __releases(atalk_routes_lock)
{
read_unlock_bh(&atalk_routes_lock);
}
@@ -139,42 +145,20 @@ out:
return 0;
}
-static __inline__ struct sock *atalk_get_socket_idx(loff_t pos)
-{
- struct sock *s;
- struct hlist_node *node;
-
- sk_for_each(s, node, &atalk_sockets)
- if (!pos--)
- goto found;
- s = NULL;
-found:
- return s;
-}
-
static void *atalk_seq_socket_start(struct seq_file *seq, loff_t *pos)
+ __acquires(atalk_sockets_lock)
{
- loff_t l = *pos;
-
read_lock_bh(&atalk_sockets_lock);
- return l ? atalk_get_socket_idx(--l) : SEQ_START_TOKEN;
+ return seq_hlist_start_head(&atalk_sockets, *pos);
}
static void *atalk_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos)
{
- struct sock *i;
-
- ++*pos;
- if (v == SEQ_START_TOKEN) {
- i = sk_head(&atalk_sockets);
- goto out;
- }
- i = sk_next(v);
-out:
- return i;
+ return seq_hlist_next(v, &atalk_sockets, pos);
}
static void atalk_seq_socket_stop(struct seq_file *seq, void *v)
+ __releases(atalk_sockets_lock)
{
read_unlock_bh(&atalk_sockets_lock);
}
@@ -190,35 +174,36 @@ static int atalk_seq_socket_show(struct seq_file *seq, void *v)
goto out;
}
- s = v;
+ s = sk_entry(v);
at = at_sk(s);
seq_printf(seq, "%02X %04X:%02X:%02X %04X:%02X:%02X %08X:%08X "
- "%02X %d\n",
+ "%02X %u\n",
s->sk_type, ntohs(at->src_net), at->src_node, at->src_port,
ntohs(at->dest_net), at->dest_node, at->dest_port,
- atomic_read(&s->sk_wmem_alloc),
- atomic_read(&s->sk_rmem_alloc),
- s->sk_state, SOCK_INODE(s->sk_socket)->i_uid);
+ sk_wmem_alloc_get(s),
+ sk_rmem_alloc_get(s),
+ s->sk_state,
+ from_kuid_munged(seq_user_ns(seq), sock_i_uid(s)));
out:
return 0;
}
-static struct seq_operations atalk_seq_interface_ops = {
+static const struct seq_operations atalk_seq_interface_ops = {
.start = atalk_seq_interface_start,
.next = atalk_seq_interface_next,
.stop = atalk_seq_interface_stop,
.show = atalk_seq_interface_show,
};
-static struct seq_operations atalk_seq_route_ops = {
+static const struct seq_operations atalk_seq_route_ops = {
.start = atalk_seq_route_start,
.next = atalk_seq_route_next,
.stop = atalk_seq_route_stop,
.show = atalk_seq_route_show,
};
-static struct seq_operations atalk_seq_socket_ops = {
+static const struct seq_operations atalk_seq_socket_ops = {
.start = atalk_seq_socket_start,
.next = atalk_seq_socket_next,
.stop = atalk_seq_socket_stop,
@@ -240,7 +225,7 @@ static int atalk_seq_socket_open(struct inode *inode, struct file *file)
return seq_open(file, &atalk_seq_socket_ops);
}
-static struct file_operations atalk_seq_interface_fops = {
+static const struct file_operations atalk_seq_interface_fops = {
.owner = THIS_MODULE,
.open = atalk_seq_interface_open,
.read = seq_read,
@@ -248,7 +233,7 @@ static struct file_operations atalk_seq_interface_fops = {
.release = seq_release,
};
-static struct file_operations atalk_seq_route_fops = {
+static const struct file_operations atalk_seq_route_fops = {
.owner = THIS_MODULE,
.open = atalk_seq_route_open,
.read = seq_read,
@@ -256,7 +241,7 @@ static struct file_operations atalk_seq_route_fops = {
.release = seq_release,
};
-static struct file_operations atalk_seq_socket_fops = {
+static const struct file_operations atalk_seq_socket_fops = {
.owner = THIS_MODULE,
.open = atalk_seq_socket_open,
.read = seq_read,
@@ -271,30 +256,28 @@ int __init atalk_proc_init(void)
struct proc_dir_entry *p;
int rc = -ENOMEM;
- atalk_proc_dir = proc_mkdir("atalk", proc_net);
+ atalk_proc_dir = proc_mkdir("atalk", init_net.proc_net);
if (!atalk_proc_dir)
goto out;
- atalk_proc_dir->owner = THIS_MODULE;
- p = create_proc_entry("interface", S_IRUGO, atalk_proc_dir);
+ p = proc_create("interface", S_IRUGO, atalk_proc_dir,
+ &atalk_seq_interface_fops);
if (!p)
goto out_interface;
- p->proc_fops = &atalk_seq_interface_fops;
- p = create_proc_entry("route", S_IRUGO, atalk_proc_dir);
+ p = proc_create("route", S_IRUGO, atalk_proc_dir,
+ &atalk_seq_route_fops);
if (!p)
goto out_route;
- p->proc_fops = &atalk_seq_route_fops;
- p = create_proc_entry("socket", S_IRUGO, atalk_proc_dir);
+ p = proc_create("socket", S_IRUGO, atalk_proc_dir,
+ &atalk_seq_socket_fops);
if (!p)
goto out_socket;
- p->proc_fops = &atalk_seq_socket_fops;
- p = create_proc_entry("arp", S_IRUGO, atalk_proc_dir);
- if (!p)
+ p = proc_create("arp", S_IRUGO, atalk_proc_dir, &atalk_seq_arp_fops);
+ if (!p)
goto out_arp;
- p->proc_fops = &atalk_seq_arp_fops;
rc = 0;
out:
@@ -306,7 +289,7 @@ out_socket:
out_route:
remove_proc_entry("interface", atalk_proc_dir);
out_interface:
- remove_proc_entry("atalk", proc_net);
+ remove_proc_entry("atalk", init_net.proc_net);
goto out;
}
@@ -316,5 +299,5 @@ void __exit atalk_proc_exit(void)
remove_proc_entry("route", atalk_proc_dir);
remove_proc_entry("socket", atalk_proc_dir);
remove_proc_entry("arp", atalk_proc_dir);
- remove_proc_entry("atalk", proc_net);
+ remove_proc_entry("atalk", init_net.proc_net);
}
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 708e2e0371a..bfcf6be1d66 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -2,7 +2,7 @@
* DDP: An implementation of the AppleTalk DDP protocol for
* Ethernet 'ELAP'.
*
- * Alan Cox <Alan.Cox@linux.org>
+ * Alan Cox <alan@lxorguk.ukuu.org.uk>
*
* With more than a little assistance from
*
@@ -28,16 +28,16 @@
* Bradford Johnson : IP-over-DDP (experimental)
* Jay Schulist : Moved IP-over-DDP to its own
* driver file. (ipddp.c & ipddp.h)
- * Jay Schulist : Made work as module with
+ * Jay Schulist : Made work as module with
* AppleTalk drivers, cleaned it.
* Rob Newberry : Added proxy AARP and AARP
* procfs, moved probing to AARP
* module.
- * Adrian Sun/
- * Michael Zuelsdorff : fix for net.0 packets. don't
+ * Adrian Sun/
+ * Michael Zuelsdorff : fix for net.0 packets. don't
* allow illegal ether/tokentalk
- * port assignment. we lose a
- * valid localtalk port as a
+ * port assignment. we lose a
+ * valid localtalk port as a
* result.
* Arnaldo C. de Melo : Cleanup, in preparation for
* shared skb support 8)
@@ -48,19 +48,22 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
- *
+ *
*/
#include <linux/capability.h>
#include <linux/module.h>
#include <linux/if_arp.h>
#include <linux/termios.h> /* For TIOCOUTQ/INQ */
+#include <linux/compat.h>
+#include <linux/slab.h>
#include <net/datalink.h>
#include <net/psnap.h>
#include <net/sock.h>
#include <net/tcp_states.h>
#include <net/route.h>
#include <linux/atalk.h>
+#include <linux/highmem.h>
struct datalink_proto *ddp_dl, *aarp_dl;
static const struct proto_ops atalk_dgram_ops;
@@ -90,26 +93,25 @@ static struct sock *atalk_search_socket(struct sockaddr_at *to,
struct atalk_iface *atif)
{
struct sock *s;
- struct hlist_node *node;
read_lock_bh(&atalk_sockets_lock);
- sk_for_each(s, node, &atalk_sockets) {
+ sk_for_each(s, &atalk_sockets) {
struct atalk_sock *at = at_sk(s);
if (to->sat_port != at->src_port)
continue;
- if (to->sat_addr.s_net == ATADDR_ANYNET &&
+ if (to->sat_addr.s_net == ATADDR_ANYNET &&
to->sat_addr.s_node == ATADDR_BCAST)
goto found;
- if (to->sat_addr.s_net == at->src_net &&
+ if (to->sat_addr.s_net == at->src_net &&
(to->sat_addr.s_node == at->src_node ||
to->sat_addr.s_node == ATADDR_BCAST ||
to->sat_addr.s_node == ATADDR_ANYNODE))
goto found;
- /* XXXX.0 -- we got a request for this router. make sure
+ /* XXXX.0 -- we got a request for this router. make sure
* that the node is appropriately set. */
if (to->sat_addr.s_node == ATADDR_ANYNODE &&
to->sat_addr.s_net != ATADDR_ANYNET &&
@@ -126,8 +128,8 @@ found:
/**
* atalk_find_or_insert_socket - Try to find a socket matching ADDR
- * @sk - socket to insert in the list if it is not there already
- * @sat - address to search for
+ * @sk: socket to insert in the list if it is not there already
+ * @sat: address to search for
*
* Try to find a socket matching ADDR in the socket list, if found then return
* it. If not, insert SK into the socket list.
@@ -138,11 +140,10 @@ static struct sock *atalk_find_or_insert_socket(struct sock *sk,
struct sockaddr_at *sat)
{
struct sock *s;
- struct hlist_node *node;
struct atalk_sock *at;
write_lock_bh(&atalk_sockets_lock);
- sk_for_each(s, node, &atalk_sockets) {
+ sk_for_each(s, &atalk_sockets) {
at = at_sk(s);
if (at->src_net == sat->sat_addr.s_net &&
@@ -161,8 +162,7 @@ static void atalk_destroy_timer(unsigned long data)
{
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->sk_timer.expires = jiffies + SOCK_DESTROY_TIME;
add_timer(&sk->sk_timer);
} else
@@ -174,12 +174,10 @@ static inline void atalk_destroy_socket(struct sock *sk)
atalk_remove_socket(sk);
skb_queue_purge(&sk->sk_receive_queue);
- if (atomic_read(&sk->sk_wmem_alloc) ||
- atomic_read(&sk->sk_rmem_alloc)) {
- init_timer(&sk->sk_timer);
+ if (sk_has_allocations(sk)) {
+ setup_timer(&sk->sk_timer, atalk_destroy_timer,
+ (unsigned long)sk);
sk->sk_timer.expires = jiffies + SOCK_DESTROY_TIME;
- sk->sk_timer.function = atalk_destroy_timer;
- sk->sk_timer.data = (unsigned long)sk;
add_timer(&sk->sk_timer);
} else
sock_put(sk);
@@ -295,7 +293,7 @@ static int atif_probe_device(struct atalk_iface *atif)
/* Perform AARP probing for a proxy address */
static int atif_proxy_probe_device(struct atalk_iface *atif,
- struct atalk_addr* proxy_addr)
+ struct atalk_addr *proxy_addr)
{
int netrange = ntohs(atif->nets.nr_lastnet) -
ntohs(atif->nets.nr_firstnet) + 1;
@@ -313,7 +311,7 @@ static int atif_proxy_probe_device(struct atalk_iface *atif,
if (probe_node == ATADDR_ANYNODE)
probe_node = jiffies & 0xFF;
-
+
/* Scan the networks */
for (netct = 0; netct <= netrange; netct++) {
/* Sweep the available nodes from a given start */
@@ -416,7 +414,7 @@ static struct atalk_iface *atalk_find_interface(__be16 net, int node)
if (node == ATADDR_ANYNODE && net != ATADDR_ANYNET &&
ntohs(iface->nets.nr_firstnet) <= ntohs(net) &&
ntohs(net) <= ntohs(iface->nets.nr_lastnet))
- break;
+ break;
}
read_unlock_bh(&atalk_interfaces_lock);
return iface;
@@ -431,13 +429,13 @@ static struct atalk_iface *atalk_find_interface(__be16 net, int node)
static struct atalk_route *atrtr_find(struct atalk_addr *target)
{
/*
- * we must search through all routes unless we find a
+ * we must search through all routes unless we find a
* host route, because some host routes might overlap
* network routes
*/
struct atalk_route *net_route = NULL;
struct atalk_route *r;
-
+
read_lock_bh(&atalk_routes_lock);
for (r = atalk_routes; r; r = r->next) {
if (!(r->flags & RTF_UP))
@@ -459,8 +457,8 @@ static struct atalk_route *atrtr_find(struct atalk_addr *target)
net_route = r;
}
}
-
- /*
+
+ /*
* if we found a network route but not a direct host
* route, then return it
*/
@@ -539,15 +537,15 @@ static int atrtr_create(struct rtentry *r, struct net_device *devhint)
for (iface = atalk_interfaces; iface; iface = iface->next) {
if (!riface &&
ntohs(ga->sat_addr.s_net) >=
- ntohs(iface->nets.nr_firstnet) &&
+ ntohs(iface->nets.nr_firstnet) &&
ntohs(ga->sat_addr.s_net) <=
- ntohs(iface->nets.nr_lastnet))
+ ntohs(iface->nets.nr_lastnet))
riface = iface;
if (ga->sat_addr.s_net == iface->address.s_net &&
ga->sat_addr.s_node == iface->address.s_node)
riface = iface;
- }
+ }
read_unlock_bh(&atalk_interfaces_lock);
retval = -ENETUNREACH;
@@ -583,7 +581,7 @@ out:
}
/* Delete a route. Find it and discard it */
-static int atrtr_delete(struct atalk_addr * addr)
+static int atrtr_delete(struct atalk_addr *addr)
{
struct atalk_route **r = &atalk_routes;
int retval = 0;
@@ -646,9 +644,14 @@ static inline void atalk_dev_down(struct net_device *dev)
static int ddp_device_event(struct notifier_block *this, unsigned long event,
void *ptr)
{
+ struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+
+ if (!net_eq(dev_net(dev), &init_net))
+ return NOTIFY_DONE;
+
if (event == NETDEV_DOWN)
/* Discard any use of this */
- atalk_dev_down(ptr);
+ atalk_dev_down(dev);
return NOTIFY_DONE;
}
@@ -671,7 +674,7 @@ static int atif_ioctl(int cmd, void __user *arg)
if (copy_from_user(&atreq, arg, sizeof(atreq)))
return -EFAULT;
- dev = __dev_get_by_name(atreq.ifr_name);
+ dev = __dev_get_by_name(&init_net, atreq.ifr_name);
if (!dev)
return -ENODEV;
@@ -679,195 +682,192 @@ static int atif_ioctl(int cmd, void __user *arg)
atif = atalk_find_dev(dev);
switch (cmd) {
- case SIOCSIFADDR:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- if (sa->sat_family != AF_APPLETALK)
- return -EINVAL;
- if (dev->type != ARPHRD_ETHER &&
- dev->type != ARPHRD_LOOPBACK &&
- dev->type != ARPHRD_LOCALTLK &&
- dev->type != ARPHRD_PPP)
- return -EPROTONOSUPPORT;
+ case SIOCSIFADDR:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ if (sa->sat_family != AF_APPLETALK)
+ return -EINVAL;
+ if (dev->type != ARPHRD_ETHER &&
+ dev->type != ARPHRD_LOOPBACK &&
+ dev->type != ARPHRD_LOCALTLK &&
+ dev->type != ARPHRD_PPP)
+ return -EPROTONOSUPPORT;
- nr = (struct atalk_netrange *)&sa->sat_zero[0];
- add_route = 1;
+ nr = (struct atalk_netrange *)&sa->sat_zero[0];
+ add_route = 1;
- /*
- * if this is a point-to-point iface, and we already
- * have an iface for this AppleTalk address, then we
- * should not add a route
- */
- if ((dev->flags & IFF_POINTOPOINT) &&
- atalk_find_interface(sa->sat_addr.s_net,
- sa->sat_addr.s_node)) {
- printk(KERN_DEBUG "AppleTalk: point-to-point "
- "interface added with "
- "existing address\n");
- add_route = 0;
- }
-
- /*
- * Phase 1 is fine on LocalTalk but we don't do
- * EtherTalk phase 1. Anyone wanting to add it go ahead.
- */
- if (dev->type == ARPHRD_ETHER && nr->nr_phase != 2)
- return -EPROTONOSUPPORT;
- if (sa->sat_addr.s_node == ATADDR_BCAST ||
- sa->sat_addr.s_node == 254)
+ /*
+ * if this is a point-to-point iface, and we already
+ * have an iface for this AppleTalk address, then we
+ * should not add a route
+ */
+ if ((dev->flags & IFF_POINTOPOINT) &&
+ atalk_find_interface(sa->sat_addr.s_net,
+ sa->sat_addr.s_node)) {
+ printk(KERN_DEBUG "AppleTalk: point-to-point "
+ "interface added with "
+ "existing address\n");
+ add_route = 0;
+ }
+
+ /*
+ * Phase 1 is fine on LocalTalk but we don't do
+ * EtherTalk phase 1. Anyone wanting to add it go ahead.
+ */
+ if (dev->type == ARPHRD_ETHER && nr->nr_phase != 2)
+ return -EPROTONOSUPPORT;
+ if (sa->sat_addr.s_node == ATADDR_BCAST ||
+ sa->sat_addr.s_node == 254)
+ return -EINVAL;
+ if (atif) {
+ /* Already setting address */
+ if (atif->status & ATIF_PROBE)
+ return -EBUSY;
+
+ atif->address.s_net = sa->sat_addr.s_net;
+ atif->address.s_node = sa->sat_addr.s_node;
+ atrtr_device_down(dev); /* Flush old routes */
+ } else {
+ atif = atif_add_device(dev, &sa->sat_addr);
+ if (!atif)
+ return -ENOMEM;
+ }
+ atif->nets = *nr;
+
+ /*
+ * Check if the chosen address is used. If so we
+ * error and atalkd will try another.
+ */
+
+ if (!(dev->flags & IFF_LOOPBACK) &&
+ !(dev->flags & IFF_POINTOPOINT) &&
+ atif_probe_device(atif) < 0) {
+ atif_drop_device(dev);
+ return -EADDRINUSE;
+ }
+
+ /* Hey it worked - add the direct routes */
+ sa = (struct sockaddr_at *)&rtdef.rt_gateway;
+ sa->sat_family = AF_APPLETALK;
+ sa->sat_addr.s_net = atif->address.s_net;
+ sa->sat_addr.s_node = atif->address.s_node;
+ sa = (struct sockaddr_at *)&rtdef.rt_dst;
+ rtdef.rt_flags = RTF_UP;
+ sa->sat_family = AF_APPLETALK;
+ sa->sat_addr.s_node = ATADDR_ANYNODE;
+ if (dev->flags & IFF_LOOPBACK ||
+ dev->flags & IFF_POINTOPOINT)
+ rtdef.rt_flags |= RTF_HOST;
+
+ /* Routerless initial state */
+ if (nr->nr_firstnet == htons(0) &&
+ nr->nr_lastnet == htons(0xFFFE)) {
+ sa->sat_addr.s_net = atif->address.s_net;
+ atrtr_create(&rtdef, dev);
+ atrtr_set_default(dev);
+ } else {
+ limit = ntohs(nr->nr_lastnet);
+ if (limit - ntohs(nr->nr_firstnet) > 4096) {
+ printk(KERN_WARNING "Too many routes/"
+ "iface.\n");
return -EINVAL;
- if (atif) {
- /* Already setting address */
- if (atif->status & ATIF_PROBE)
- return -EBUSY;
-
- atif->address.s_net = sa->sat_addr.s_net;
- atif->address.s_node = sa->sat_addr.s_node;
- atrtr_device_down(dev); /* Flush old routes */
- } else {
- atif = atif_add_device(dev, &sa->sat_addr);
- if (!atif)
- return -ENOMEM;
}
- atif->nets = *nr;
+ if (add_route)
+ for (ct = ntohs(nr->nr_firstnet);
+ ct <= limit; ct++) {
+ sa->sat_addr.s_net = htons(ct);
+ atrtr_create(&rtdef, dev);
+ }
+ }
+ dev_mc_add_global(dev, aarp_mcast);
+ return 0;
- /*
- * Check if the chosen address is used. If so we
- * error and atalkd will try another.
- */
+ case SIOCGIFADDR:
+ if (!atif)
+ return -EADDRNOTAVAIL;
- if (!(dev->flags & IFF_LOOPBACK) &&
- !(dev->flags & IFF_POINTOPOINT) &&
- atif_probe_device(atif) < 0) {
- atif_drop_device(dev);
- return -EADDRINUSE;
- }
+ sa->sat_family = AF_APPLETALK;
+ sa->sat_addr = atif->address;
+ break;
- /* Hey it worked - add the direct routes */
- sa = (struct sockaddr_at *)&rtdef.rt_gateway;
- sa->sat_family = AF_APPLETALK;
- sa->sat_addr.s_net = atif->address.s_net;
- sa->sat_addr.s_node = atif->address.s_node;
- sa = (struct sockaddr_at *)&rtdef.rt_dst;
- rtdef.rt_flags = RTF_UP;
- sa->sat_family = AF_APPLETALK;
- sa->sat_addr.s_node = ATADDR_ANYNODE;
- if (dev->flags & IFF_LOOPBACK ||
- dev->flags & IFF_POINTOPOINT)
- rtdef.rt_flags |= RTF_HOST;
-
- /* Routerless initial state */
- if (nr->nr_firstnet == htons(0) &&
- nr->nr_lastnet == htons(0xFFFE)) {
- sa->sat_addr.s_net = atif->address.s_net;
- atrtr_create(&rtdef, dev);
- atrtr_set_default(dev);
- } else {
- limit = ntohs(nr->nr_lastnet);
- if (limit - ntohs(nr->nr_firstnet) > 4096) {
- printk(KERN_WARNING "Too many routes/"
- "iface.\n");
- return -EINVAL;
- }
- if (add_route)
- for (ct = ntohs(nr->nr_firstnet);
- ct <= limit; ct++) {
- sa->sat_addr.s_net = htons(ct);
- atrtr_create(&rtdef, dev);
- }
- }
- dev_mc_add(dev, aarp_mcast, 6, 1);
- return 0;
+ case SIOCGIFBRDADDR:
+ if (!atif)
+ return -EADDRNOTAVAIL;
- case SIOCGIFADDR:
- if (!atif)
- return -EADDRNOTAVAIL;
+ sa->sat_family = AF_APPLETALK;
+ sa->sat_addr.s_net = atif->address.s_net;
+ sa->sat_addr.s_node = ATADDR_BCAST;
+ break;
- sa->sat_family = AF_APPLETALK;
- sa->sat_addr = atif->address;
- break;
+ case SIOCATALKDIFADDR:
+ case SIOCDIFADDR:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ if (sa->sat_family != AF_APPLETALK)
+ return -EINVAL;
+ atalk_dev_down(dev);
+ break;
- case SIOCGIFBRDADDR:
- if (!atif)
- return -EADDRNOTAVAIL;
+ case SIOCSARP:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ if (sa->sat_family != AF_APPLETALK)
+ return -EINVAL;
+ /*
+ * for now, we only support proxy AARP on ELAP;
+ * we should be able to do it for LocalTalk, too.
+ */
+ if (dev->type != ARPHRD_ETHER)
+ return -EPROTONOSUPPORT;
- sa->sat_family = AF_APPLETALK;
- sa->sat_addr.s_net = atif->address.s_net;
- sa->sat_addr.s_node = ATADDR_BCAST;
- break;
+ /*
+ * atif points to the current interface on this network;
+ * we aren't concerned about its current status (at
+ * least for now), but it has all the settings about
+ * the network we're going to probe. Consequently, it
+ * must exist.
+ */
+ if (!atif)
+ return -EADDRNOTAVAIL;
- case SIOCATALKDIFADDR:
- case SIOCDIFADDR:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- if (sa->sat_family != AF_APPLETALK)
- return -EINVAL;
- atalk_dev_down(dev);
- break;
-
- case SIOCSARP:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- if (sa->sat_family != AF_APPLETALK)
- return -EINVAL;
- if (!atif)
- return -EADDRNOTAVAIL;
-
- /*
- * for now, we only support proxy AARP on ELAP;
- * we should be able to do it for LocalTalk, too.
- */
- if (dev->type != ARPHRD_ETHER)
- return -EPROTONOSUPPORT;
-
- /*
- * atif points to the current interface on this network;
- * we aren't concerned about its current status (at
- * least for now), but it has all the settings about
- * the network we're going to probe. Consequently, it
- * must exist.
- */
- if (!atif)
- return -EADDRNOTAVAIL;
-
- nr = (struct atalk_netrange *)&(atif->nets);
- /*
- * Phase 1 is fine on Localtalk but we don't do
- * Ethertalk phase 1. Anyone wanting to add it go ahead.
- */
- if (dev->type == ARPHRD_ETHER && nr->nr_phase != 2)
- return -EPROTONOSUPPORT;
-
- if (sa->sat_addr.s_node == ATADDR_BCAST ||
- sa->sat_addr.s_node == 254)
- return -EINVAL;
-
- /*
- * Check if the chosen address is used. If so we
- * error and ATCP will try another.
- */
- if (atif_proxy_probe_device(atif, &(sa->sat_addr)) < 0)
- return -EADDRINUSE;
-
- /*
- * We now have an address on the local network, and
- * the AARP code will defend it for us until we take it
- * down. We don't set up any routes right now, because
- * ATCP will install them manually via SIOCADDRT.
- */
- break;
-
- case SIOCDARP:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- if (sa->sat_family != AF_APPLETALK)
- return -EINVAL;
- if (!atif)
- return -EADDRNOTAVAIL;
-
- /* give to aarp module to remove proxy entry */
- aarp_proxy_remove(atif->dev, &(sa->sat_addr));
- return 0;
+ nr = (struct atalk_netrange *)&(atif->nets);
+ /*
+ * Phase 1 is fine on Localtalk but we don't do
+ * Ethertalk phase 1. Anyone wanting to add it go ahead.
+ */
+ if (dev->type == ARPHRD_ETHER && nr->nr_phase != 2)
+ return -EPROTONOSUPPORT;
+
+ if (sa->sat_addr.s_node == ATADDR_BCAST ||
+ sa->sat_addr.s_node == 254)
+ return -EINVAL;
+
+ /*
+ * Check if the chosen address is used. If so we
+ * error and ATCP will try another.
+ */
+ if (atif_proxy_probe_device(atif, &(sa->sat_addr)) < 0)
+ return -EADDRINUSE;
+
+ /*
+ * We now have an address on the local network, and
+ * the AARP code will defend it for us until we take it
+ * down. We don't set up any routes right now, because
+ * ATCP will install them manually via SIOCADDRT.
+ */
+ break;
+
+ case SIOCDARP:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ if (sa->sat_family != AF_APPLETALK)
+ return -EINVAL;
+ if (!atif)
+ return -EADDRNOTAVAIL;
+
+ /* give to aarp module to remove proxy entry */
+ aarp_proxy_remove(atif->dev, &(sa->sat_addr));
+ return 0;
}
return copy_to_user(arg, &atreq, sizeof(atreq)) ? -EFAULT : 0;
@@ -882,25 +882,25 @@ static int atrtr_ioctl(unsigned int cmd, void __user *arg)
return -EFAULT;
switch (cmd) {
- case SIOCDELRT:
- if (rt.rt_dst.sa_family != AF_APPLETALK)
- return -EINVAL;
- return atrtr_delete(&((struct sockaddr_at *)
- &rt.rt_dst)->sat_addr);
-
- case SIOCADDRT: {
- struct net_device *dev = NULL;
- if (rt.rt_dev) {
- char name[IFNAMSIZ];
- if (copy_from_user(name, rt.rt_dev, IFNAMSIZ-1))
- return -EFAULT;
- name[IFNAMSIZ-1] = '\0';
- dev = __dev_get_by_name(name);
- if (!dev)
- return -ENODEV;
- }
- return atrtr_create(&rt, dev);
+ case SIOCDELRT:
+ if (rt.rt_dst.sa_family != AF_APPLETALK)
+ return -EINVAL;
+ return atrtr_delete(&((struct sockaddr_at *)
+ &rt.rt_dst)->sat_addr);
+
+ case SIOCADDRT: {
+ struct net_device *dev = NULL;
+ if (rt.rt_dev) {
+ char name[IFNAMSIZ];
+ if (copy_from_user(name, rt.rt_dev, IFNAMSIZ-1))
+ return -EFAULT;
+ name[IFNAMSIZ-1] = '\0';
+ dev = __dev_get_by_name(&init_net, name);
+ if (!dev)
+ return -ENODEV;
}
+ return atrtr_create(&rt, dev);
+ }
}
return -EINVAL;
}
@@ -916,18 +916,13 @@ static int atrtr_ioctl(unsigned int cmd, void __user *arg)
* Checksum: This is 'optional'. It's quite likely also a good
* candidate for assembler hackery 8)
*/
-static unsigned long atalk_sum_partial(const unsigned char *data,
+static unsigned long atalk_sum_partial(const unsigned char *data,
int len, unsigned long sum)
{
/* This ought to be unwrapped neatly. I'll trust gcc for now */
while (len--) {
- sum += *data;
- sum <<= 1;
- if (sum & 0x10000) {
- sum++;
- sum &= 0xffff;
- }
- data++;
+ sum += *data++;
+ sum = rol16(sum, 1);
}
return sum;
}
@@ -937,14 +932,15 @@ static unsigned long atalk_sum_skb(const struct sk_buff *skb, int offset,
int len, unsigned long sum)
{
int start = skb_headlen(skb);
+ struct sk_buff *frag_iter;
int i, copy;
/* checksum stuff in header space */
- if ( (copy = start - offset) > 0) {
+ if ((copy = start - offset) > 0) {
if (copy > len)
copy = len;
sum = atalk_sum_partial(skb->data + offset, copy, sum);
- if ( (len -= copy) == 0)
+ if ((len -= copy) == 0)
return sum;
offset += copy;
@@ -953,20 +949,19 @@ static unsigned long atalk_sum_skb(const struct sk_buff *skb, int offset,
/* checksum stuff in frags */
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
int end;
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ WARN_ON(start > offset + len);
- BUG_TRAP(start <= offset + len);
-
- end = start + skb_shinfo(skb)->frags[i].size;
+ end = start + skb_frag_size(frag);
if ((copy = end - offset) > 0) {
u8 *vaddr;
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
if (copy > len)
copy = len;
- vaddr = kmap_skb_frag(frag);
+ vaddr = kmap_atomic(skb_frag_page(frag));
sum = atalk_sum_partial(vaddr + frag->page_offset +
offset - start, copy, sum);
- kunmap_skb_frag(vaddr);
+ kunmap_atomic(vaddr);
if (!(len -= copy))
return sum;
@@ -975,26 +970,22 @@ static unsigned long atalk_sum_skb(const struct sk_buff *skb, int offset,
start = end;
}
- if (skb_shinfo(skb)->frag_list) {
- struct sk_buff *list = skb_shinfo(skb)->frag_list;
-
- for (; list; list = list->next) {
- int end;
+ skb_walk_frags(skb, frag_iter) {
+ int end;
- BUG_TRAP(start <= offset + len);
+ WARN_ON(start > offset + len);
- end = start + list->len;
- if ((copy = end - offset) > 0) {
- if (copy > len)
- copy = len;
- sum = atalk_sum_skb(list, offset - start,
- copy, sum);
- if ((len -= copy) == 0)
- return sum;
- offset += copy;
- }
- start = end;
+ end = start + frag_iter->len;
+ if ((copy = end - offset) > 0) {
+ if (copy > len)
+ copy = len;
+ sum = atalk_sum_skb(frag_iter, offset - start,
+ copy, sum);
+ if ((len -= copy) == 0)
+ return sum;
+ offset += copy;
}
+ start = end;
}
BUG_ON(len > 0);
@@ -1023,19 +1014,23 @@ static struct proto ddp_proto = {
* Create a socket. Initialise the socket, blank the addresses
* set the state.
*/
-static int atalk_create(struct socket *sock, int protocol)
+static int atalk_create(struct net *net, struct socket *sock, int protocol,
+ int kern)
{
struct sock *sk;
int rc = -ESOCKTNOSUPPORT;
+ if (!net_eq(net, &init_net))
+ return -EAFNOSUPPORT;
+
/*
* We permit SOCK_DGRAM and RAW is an extension. It is trivial to do
- * and gives you the full ELAP frame. Should be handy for CAP 8)
+ * and gives you the full ELAP frame. Should be handy for CAP 8)
*/
if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM)
goto out;
rc = -ENOMEM;
- sk = sk_alloc(PF_APPLETALK, GFP_KERNEL, &ddp_proto, 1);
+ sk = sk_alloc(net, PF_APPLETALK, GFP_KERNEL, &ddp_proto);
if (!sk)
goto out;
rc = 0;
@@ -1054,17 +1049,23 @@ static int atalk_release(struct socket *sock)
struct sock *sk = sock->sk;
if (sk) {
+ sock_hold(sk);
+ lock_sock(sk);
+
sock_orphan(sk);
sock->sk = NULL;
atalk_destroy_socket(sk);
+
+ release_sock(sk);
+ sock_put(sk);
}
return 0;
}
/**
* atalk_pick_and_bind_port - Pick a source port when one is not given
- * @sk - socket to insert into the tables
- * @sat - address to search for
+ * @sk: socket to insert into the tables
+ * @sat: address to search for
*
* Pick a source port when one is not given. If we can find a suitable free
* one, we insert the socket into the tables using it.
@@ -1081,9 +1082,8 @@ static int atalk_pick_and_bind_port(struct sock *sk, struct sockaddr_at *sat)
sat->sat_port < ATPORT_LAST;
sat->sat_port++) {
struct sock *s;
- struct hlist_node *node;
- sk_for_each(s, node, &atalk_sockets) {
+ sk_for_each(s, &atalk_sockets) {
struct atalk_sock *at = at_sk(s);
if (at->src_net == sat->sat_addr.s_net &&
@@ -1133,6 +1133,7 @@ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
struct sockaddr_at *addr = (struct sockaddr_at *)uaddr;
struct sock *sk = sock->sk;
struct atalk_sock *at = at_sk(sk);
+ int err;
if (!sock_flag(sk, SOCK_ZAPPED) ||
addr_len != sizeof(struct sockaddr_at))
@@ -1141,37 +1142,44 @@ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
if (addr->sat_family != AF_APPLETALK)
return -EAFNOSUPPORT;
+ lock_sock(sk);
if (addr->sat_addr.s_net == htons(ATADDR_ANYNET)) {
struct atalk_addr *ap = atalk_find_primary();
+ err = -EADDRNOTAVAIL;
if (!ap)
- return -EADDRNOTAVAIL;
+ goto out;
at->src_net = addr->sat_addr.s_net = ap->s_net;
- at->src_node = addr->sat_addr.s_node= ap->s_node;
+ at->src_node = addr->sat_addr.s_node = ap->s_node;
} else {
+ err = -EADDRNOTAVAIL;
if (!atalk_find_interface(addr->sat_addr.s_net,
addr->sat_addr.s_node))
- return -EADDRNOTAVAIL;
+ goto out;
at->src_net = addr->sat_addr.s_net;
at->src_node = addr->sat_addr.s_node;
}
if (addr->sat_port == ATADDR_ANYPORT) {
- int n = atalk_pick_and_bind_port(sk, addr);
+ err = atalk_pick_and_bind_port(sk, addr);
- if (n < 0)
- return n;
+ if (err < 0)
+ goto out;
} else {
at->src_port = addr->sat_port;
+ err = -EADDRINUSE;
if (atalk_find_or_insert_socket(sk, addr))
- return -EADDRINUSE;
+ goto out;
}
sock_reset_flag(sk, SOCK_ZAPPED);
- return 0;
+ err = 0;
+out:
+ release_sock(sk);
+ return err;
}
/* Set the address we talk to */
@@ -1181,6 +1189,7 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr,
struct sock *sk = sock->sk;
struct atalk_sock *at = at_sk(sk);
struct sockaddr_at *addr;
+ int err;
sk->sk_state = TCP_CLOSE;
sock->state = SS_UNCONNECTED;
@@ -1195,22 +1204,23 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr,
if (addr->sat_addr.s_node == ATADDR_BCAST &&
!sock_flag(sk, SOCK_BROADCAST)) {
-#if 1
- printk(KERN_WARNING "%s is broken and did not set "
- "SO_BROADCAST. It will break when 2.2 is "
- "released.\n",
+#if 1
+ pr_warn("atalk_connect: %s is broken and did not set SO_BROADCAST.\n",
current->comm);
#else
return -EACCES;
-#endif
+#endif
}
+ lock_sock(sk);
+ err = -EBUSY;
if (sock_flag(sk, SOCK_ZAPPED))
if (atalk_autobind(sk) < 0)
- return -EBUSY;
+ goto out;
+ err = -ENETUNREACH;
if (!atrtr_get_dev(&addr->sat_addr))
- return -ENETUNREACH;
+ goto out;
at->dest_port = addr->sat_port;
at->dest_net = addr->sat_addr.s_net;
@@ -1218,7 +1228,10 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr,
sock->state = SS_CONNECTED;
sk->sk_state = TCP_ESTABLISHED;
- return 0;
+ err = 0;
+out:
+ release_sock(sk);
+ return err;
}
/*
@@ -1231,16 +1244,21 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr,
struct sockaddr_at sat;
struct sock *sk = sock->sk;
struct atalk_sock *at = at_sk(sk);
+ int err;
+ lock_sock(sk);
+ err = -ENOBUFS;
if (sock_flag(sk, SOCK_ZAPPED))
if (atalk_autobind(sk) < 0)
- return -ENOBUFS;
+ goto out;
*uaddr_len = sizeof(struct sockaddr_at);
+ memset(&sat, 0, sizeof(sat));
if (peer) {
+ err = -ENOTCONN;
if (sk->sk_state != TCP_ESTABLISHED)
- return -ENOTCONN;
+ goto out;
sat.sat_addr.s_net = at->dest_net;
sat.sat_addr.s_node = at->dest_node;
@@ -1251,36 +1269,41 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr,
sat.sat_port = at->src_port;
}
+ err = 0;
sat.sat_family = AF_APPLETALK;
memcpy(uaddr, &sat, sizeof(sat));
- return 0;
+
+out:
+ release_sock(sk);
+ return err;
}
#if defined(CONFIG_IPDDP) || defined(CONFIG_IPDDP_MODULE)
static __inline__ int is_ip_over_ddp(struct sk_buff *skb)
{
- return skb->data[12] == 22;
+ return skb->data[12] == 22;
}
static int handle_ip_over_ddp(struct sk_buff *skb)
{
- struct net_device *dev = __dev_get_by_name("ipddp0");
+ struct net_device *dev = __dev_get_by_name(&init_net, "ipddp0");
struct net_device_stats *stats;
/* This needs to be able to handle ipddp"N" devices */
- if (!dev)
- return -ENODEV;
-
- skb->protocol = htons(ETH_P_IP);
- skb_pull(skb, 13);
- skb->dev = dev;
- skb->h.raw = skb->data;
-
- stats = dev->priv;
- stats->rx_packets++;
- stats->rx_bytes += skb->len + 13;
- netif_rx(skb); /* Send the SKB up to a higher place. */
- return 0;
+ if (!dev) {
+ kfree_skb(skb);
+ return NET_RX_DROP;
+ }
+
+ skb->protocol = htons(ETH_P_IP);
+ skb_pull(skb, 13);
+ skb->dev = dev;
+ skb_reset_transport_header(skb);
+
+ stats = netdev_priv(dev);
+ stats->rx_packets++;
+ stats->rx_bytes += skb->len + 13;
+ return netif_rx(skb); /* Send the SKB up to a higher place. */
}
#else
/* make it easy for gcc to optimize this test out, i.e. kill the code */
@@ -1288,16 +1311,15 @@ static int handle_ip_over_ddp(struct sk_buff *skb)
#define handle_ip_over_ddp(skb) 0
#endif
-static void atalk_route_packet(struct sk_buff *skb, struct net_device *dev,
- struct ddpehdr *ddp, __u16 len_hops,
- int origlen)
+static int atalk_route_packet(struct sk_buff *skb, struct net_device *dev,
+ struct ddpehdr *ddp, __u16 len_hops, int origlen)
{
struct atalk_route *rt;
struct atalk_addr ta;
/*
* Don't route multicast, etc., packets, or packets sent to "this
- * network"
+ * network"
*/
if (skb->pkt_type != PACKET_HOST || !ddp->deh_dnet) {
/*
@@ -1334,8 +1356,8 @@ static void atalk_route_packet(struct sk_buff *skb, struct net_device *dev,
ta.s_node = rt->gateway.s_node;
}
- /* Fix up skb->len field */
- skb_trim(skb, min_t(unsigned int, origlen,
+ /* Fix up skb->len field */
+ skb_trim(skb, min_t(unsigned int, origlen,
(rt->dev->hard_header_len +
ddp_dl->header_length + (len_hops & 1023))));
@@ -1357,22 +1379,24 @@ static void atalk_route_packet(struct sk_buff *skb, struct net_device *dev,
/* 22 bytes - 12 ether, 2 len, 3 802.2 5 snap */
struct sk_buff *nskb = skb_realloc_headroom(skb, 32);
kfree_skb(skb);
- if (!nskb)
- goto out;
skb = nskb;
} else
skb = skb_unshare(skb, GFP_ATOMIC);
-
+
/*
* If the buffer didn't vanish into the lack of space bitbucket we can
* send it.
*/
- if (skb && aarp_send_ddp(rt->dev, skb, &ta, NULL) == -1)
- goto free_it;
-out:
- return;
+ if (skb == NULL)
+ goto drop;
+
+ if (aarp_send_ddp(rt->dev, skb, &ta, NULL) == NET_XMIT_DROP)
+ return NET_RX_DROP;
+ return NET_RX_SUCCESS;
free_it:
kfree_skb(skb);
+drop:
+ return NET_RX_DROP;
}
/**
@@ -1382,10 +1406,10 @@ free_it:
* @pt - packet type
*
* Receive a packet (in skb) from device dev. This has come from the SNAP
- * decoder, and on entry skb->h.raw is the DDP header, skb->len is the DDP
- * header, skb->len is the DDP length. The physical headers have been
- * extracted. PPP should probably pass frames marked as for this layer.
- * [ie ARPHRD_ETHERTALK]
+ * decoder, and on entry skb->transport_header is the DDP header, skb->len
+ * is the DDP header, skb->len is the DDP length. The physical headers
+ * have been extracted. PPP should probably pass frames marked as for this
+ * layer. [ie ARPHRD_ETHERTALK]
*/
static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev)
@@ -1394,16 +1418,19 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
struct sock *sock;
struct atalk_iface *atif;
struct sockaddr_at tosat;
- int origlen;
+ int origlen;
__u16 len_hops;
+ if (!net_eq(dev_net(dev), &init_net))
+ goto drop;
+
/* Don't mangle buffer if shared */
- if (!(skb = skb_share_check(skb, GFP_ATOMIC)))
+ if (!(skb = skb_share_check(skb, GFP_ATOMIC)))
goto out;
-
+
/* Size check and make sure header is contiguous */
if (!pskb_may_pull(skb, sizeof(*ddp)))
- goto freeit;
+ goto drop;
ddp = ddp_hdr(skb);
@@ -1416,10 +1443,13 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
/*
* Size check to see if ddp->deh_len was crap
* (Otherwise we'll detonate most spectacularly
- * in the middle of recvmsg()).
+ * in the middle of atalk_checksum() or recvmsg()).
*/
- if (skb->len < sizeof(*ddp))
- goto freeit;
+ if (skb->len < sizeof(*ddp) || skb->len < (len_hops & 1023)) {
+ pr_debug("AppleTalk: dropping corrupted frame (deh_len=%u, "
+ "skb->len=%u)\n", len_hops & 1023, skb->len);
+ goto drop;
+ }
/*
* Any checksums. Note we don't do htons() on this == is assumed to be
@@ -1428,7 +1458,7 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
if (ddp->deh_sum &&
atalk_checksum(skb, len_hops & 1023) != ddp->deh_sum)
/* Not a valid AppleTalk frame - dustbin time */
- goto freeit;
+ goto drop;
/* Check the packet is aimed at us */
if (!ddp->deh_dnet) /* Net 0 is 'this network' */
@@ -1440,8 +1470,7 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
/* Not ours, so we route the packet via the correct
* AppleTalk iface
*/
- atalk_route_packet(skb, dev, ddp, len_hops, origlen);
- goto out;
+ return atalk_route_packet(skb, dev, ddp, len_hops, origlen);
}
/* if IP over DDP is not selected this code will be optimized out */
@@ -1457,18 +1486,19 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
sock = atalk_search_socket(&tosat, atif);
if (!sock) /* But not one of our sockets */
- goto freeit;
+ goto drop;
/* Queue packet (standard) */
- skb->sk = sock;
-
if (sock_queue_rcv_skb(sock, skb) < 0)
- goto freeit;
-out:
- return 0;
-freeit:
+ goto drop;
+
+ return NET_RX_SUCCESS;
+
+drop:
kfree_skb(skb);
- goto out;
+out:
+ return NET_RX_DROP;
+
}
/*
@@ -1479,8 +1509,11 @@ freeit:
static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev)
{
+ if (!net_eq(dev_net(dev), &init_net))
+ goto freeit;
+
/* Expand any short form frames */
- if (skb->mac.raw[2] == 1) {
+ if (skb_mac_header(skb)[2] == 1) {
struct ddpehdr *ddp;
/* Find our address */
struct atalk_addr *ap = atalk_find_dev_addr(dev);
@@ -1489,7 +1522,7 @@ static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev,
goto freeit;
/* Don't mangle buffer if shared */
- if (!(skb = skb_share_check(skb, GFP_ATOMIC)))
+ if (!(skb = skb_share_check(skb, GFP_ATOMIC)))
return 0;
/*
@@ -1500,14 +1533,14 @@ static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev,
/* Now fill in the long header */
- /*
- * These two first. The mac overlays the new source/dest
- * network information so we MUST copy these before
- * we write the network numbers !
- */
+ /*
+ * These two first. The mac overlays the new source/dest
+ * network information so we MUST copy these before
+ * we write the network numbers !
+ */
- ddp->deh_dnode = skb->mac.raw[0]; /* From physical header */
- ddp->deh_snode = skb->mac.raw[1]; /* From physical header */
+ ddp->deh_dnode = skb_mac_header(skb)[0]; /* From physical header */
+ ddp->deh_snode = skb_mac_header(skb)[1]; /* From physical header */
ddp->deh_dnet = ap->s_net; /* Network number */
ddp->deh_snet = ap->s_net;
@@ -1518,7 +1551,7 @@ static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev,
/* Non routable, so force a drop if we slip up later */
ddp->deh_len_hops = htons(skb->len + (DDP_MAXHOPS << 10));
}
- skb->h.raw = skb->data;
+ skb_reset_transport_header(skb);
return atalk_rcv(skb, dev, pt, orig_dev);
freeit:
@@ -1531,7 +1564,7 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
{
struct sock *sk = sock->sk;
struct atalk_sock *at = at_sk(sk);
- struct sockaddr_at *usat = (struct sockaddr_at *)msg->msg_name;
+ DECLARE_SOCKADDR(struct sockaddr_at *, usat, msg->msg_name);
int flags = msg->msg_flags;
int loopback = 0;
struct sockaddr_at local_satalk, gsat;
@@ -1548,27 +1581,28 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
if (len > DDP_MAXSZ)
return -EMSGSIZE;
+ lock_sock(sk);
if (usat) {
+ err = -EBUSY;
if (sock_flag(sk, SOCK_ZAPPED))
if (atalk_autobind(sk) < 0)
- return -EBUSY;
+ goto out;
+ err = -EINVAL;
if (msg->msg_namelen < sizeof(*usat) ||
usat->sat_family != AF_APPLETALK)
- return -EINVAL;
+ goto out;
- /* netatalk doesn't implement this check */
+ err = -EPERM;
+ /* netatalk didn't implement this check */
if (usat->sat_addr.s_node == ATADDR_BCAST &&
!sock_flag(sk, SOCK_BROADCAST)) {
- printk(KERN_INFO "SO_BROADCAST: Fix your netatalk as "
- "it will break before 2.2\n");
-#if 0
- return -EPERM;
-#endif
+ goto out;
}
} else {
+ err = -ENOTCONN;
if (sk->sk_state != TCP_ESTABLISHED)
- return -ENOTCONN;
+ goto out;
usat = &local_satalk;
usat->sat_family = AF_APPLETALK;
usat->sat_port = at->dest_port;
@@ -1584,7 +1618,6 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
if (usat->sat_addr.s_net || usat->sat_addr.s_node == ATADDR_ANYNODE) {
rt = atrtr_find(&usat->sat_addr);
- dev = rt->dev;
} else {
struct atalk_addr at_hint;
@@ -1592,10 +1625,10 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
at_hint.s_net = at->src_net;
rt = atrtr_find(&at_hint);
- dev = rt->dev;
}
+ err = ENETUNREACH;
if (!rt)
- return -ENETUNREACH;
+ goto out;
dev = rt->dev;
@@ -1603,11 +1636,12 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
sk, size, dev->name);
size += dev->hard_header_len;
+ release_sock(sk);
skb = sock_alloc_send_skb(sk, size, (flags & MSG_DONTWAIT), &err);
+ lock_sock(sk);
if (!skb)
- return err;
-
- skb->sk = sk;
+ goto out;
+
skb_reserve(skb, ddp_dl->header_length);
skb_reserve(skb, dev->hard_header_len);
skb->dev = dev;
@@ -1628,10 +1662,11 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
if (err) {
kfree_skb(skb);
- return -EFAULT;
+ err = -EFAULT;
+ goto out;
}
- if (sk->sk_no_check == 1)
+ if (sk->sk_no_check_tx)
ddp->deh_sum = 0;
else
ddp->deh_sum = atalk_checksum(skb, len + sizeof(*ddp));
@@ -1647,10 +1682,10 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
if (skb2) {
loopback = 1;
SOCK_DEBUG(sk, "SK %p: send out(copy).\n", sk);
- if (aarp_send_ddp(dev, skb2,
- &usat->sat_addr, NULL) == -1)
- kfree_skb(skb2);
- /* else queued/sent above in the aarp queue */
+ /*
+ * If it fails it is queued/sent above in the aarp queue
+ */
+ aarp_send_ddp(dev, skb2, &usat->sat_addr, NULL);
}
}
@@ -1667,7 +1702,8 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
rt = atrtr_find(&at_lo);
if (!rt) {
kfree_skb(skb);
- return -ENETUNREACH;
+ err = -ENETUNREACH;
+ goto out;
}
dev = rt->dev;
skb->dev = dev;
@@ -1680,28 +1716,34 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
usat = &gsat;
}
- if (aarp_send_ddp(dev, skb, &usat->sat_addr, NULL) == -1)
- kfree_skb(skb);
- /* else queued/sent above in the aarp queue */
+ /*
+ * If it fails it is queued/sent above in the aarp queue
+ */
+ aarp_send_ddp(dev, skb, &usat->sat_addr, NULL);
}
SOCK_DEBUG(sk, "SK %p: Done write (%Zd).\n", sk, len);
- return len;
+out:
+ release_sock(sk);
+ return err ? : len;
}
static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
size_t size, int flags)
{
struct sock *sk = sock->sk;
- struct sockaddr_at *sat = (struct sockaddr_at *)msg->msg_name;
struct ddpehdr *ddp;
int copied = 0;
int offset = 0;
int err = 0;
- struct sk_buff *skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
+ struct sk_buff *skb;
+
+ skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
flags & MSG_DONTWAIT, &err);
+ lock_sock(sk);
+
if (!skb)
- return err;
+ goto out;
/* FIXME: use skb->cb to be able to use shared skbs */
ddp = ddp_hdr(skb);
@@ -1718,17 +1760,19 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
}
err = skb_copy_datagram_iovec(skb, offset, msg->msg_iov, copied);
- if (!err) {
- if (sat) {
- sat->sat_family = AF_APPLETALK;
- sat->sat_port = ddp->deh_sport;
- sat->sat_addr.s_node = ddp->deh_snode;
- sat->sat_addr.s_net = ddp->deh_snet;
- }
- msg->msg_namelen = sizeof(*sat);
+ if (!err && msg->msg_name) {
+ DECLARE_SOCKADDR(struct sockaddr_at *, sat, msg->msg_name);
+ sat->sat_family = AF_APPLETALK;
+ sat->sat_port = ddp->deh_sport;
+ sat->sat_addr.s_node = ddp->deh_snode;
+ sat->sat_addr.s_net = ddp->deh_snet;
+ msg->msg_namelen = sizeof(*sat);
}
skb_free_datagram(sk, skb); /* Free the datagram. */
+
+out:
+ release_sock(sk);
return err ? : copied;
}
@@ -1743,51 +1787,53 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
void __user *argp = (void __user *)arg;
switch (cmd) {
- /* Protocol layer */
- case TIOCOUTQ: {
- long amount = sk->sk_sndbuf -
- atomic_read(&sk->sk_wmem_alloc);
-
- if (amount < 0)
- amount = 0;
- rc = put_user(amount, (int __user *)argp);
- break;
- }
- case TIOCINQ: {
- /*
- * These two are safe on a single CPU system as only
- * user tasks fiddle here
- */
- struct sk_buff *skb = skb_peek(&sk->sk_receive_queue);
- long amount = 0;
+ /* Protocol layer */
+ case TIOCOUTQ: {
+ long amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
+
+ if (amount < 0)
+ amount = 0;
+ rc = put_user(amount, (int __user *)argp);
+ break;
+ }
+ case TIOCINQ: {
+ /*
+ * These two are safe on a single CPU system as only
+ * user tasks fiddle here
+ */
+ struct sk_buff *skb = skb_peek(&sk->sk_receive_queue);
+ long amount = 0;
- if (skb)
- amount = skb->len - sizeof(struct ddpehdr);
- rc = put_user(amount, (int __user *)argp);
- break;
- }
- case SIOCGSTAMP:
- rc = sock_get_timestamp(sk, argp);
- break;
- /* Routing */
- case SIOCADDRT:
- case SIOCDELRT:
- rc = -EPERM;
- if (capable(CAP_NET_ADMIN))
- rc = atrtr_ioctl(cmd, argp);
- break;
- /* Interface */
- case SIOCGIFADDR:
- case SIOCSIFADDR:
- case SIOCGIFBRDADDR:
- case SIOCATALKDIFADDR:
- case SIOCDIFADDR:
- case SIOCSARP: /* proxy AARP */
- case SIOCDARP: /* proxy AARP */
- rtnl_lock();
- rc = atif_ioctl(cmd, argp);
- rtnl_unlock();
- break;
+ if (skb)
+ amount = skb->len - sizeof(struct ddpehdr);
+ rc = put_user(amount, (int __user *)argp);
+ break;
+ }
+ case SIOCGSTAMP:
+ rc = sock_get_timestamp(sk, argp);
+ break;
+ case SIOCGSTAMPNS:
+ rc = sock_get_timestampns(sk, argp);
+ break;
+ /* Routing */
+ case SIOCADDRT:
+ case SIOCDELRT:
+ rc = -EPERM;
+ if (capable(CAP_NET_ADMIN))
+ rc = atrtr_ioctl(cmd, argp);
+ break;
+ /* Interface */
+ case SIOCGIFADDR:
+ case SIOCSIFADDR:
+ case SIOCGIFBRDADDR:
+ case SIOCATALKDIFADDR:
+ case SIOCDIFADDR:
+ case SIOCSARP: /* proxy AARP */
+ case SIOCDARP: /* proxy AARP */
+ rtnl_lock();
+ rc = atif_ioctl(cmd, argp);
+ rtnl_unlock();
+ break;
}
return rc;
@@ -1798,24 +1844,26 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
static int atalk_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
/*
- * All Appletalk ioctls except SIOCATALKDIFADDR are standard. And
- * SIOCATALKDIFADDR is handled by upper layer as well, so there is
- * nothing to do. Eventually SIOCATALKDIFADDR should be moved
- * here so there is no generic SIOCPROTOPRIVATE translation in the
- * system.
+ * SIOCATALKDIFADDR is a SIOCPROTOPRIVATE ioctl number, so we
+ * cannot handle it in common code. The data we access if ifreq
+ * here is compatible, so we can simply call the native
+ * handler.
*/
+ if (cmd == SIOCATALKDIFADDR)
+ return atalk_ioctl(sock, cmd, (unsigned long)compat_ptr(arg));
+
return -ENOIOCTLCMD;
}
#endif
-static struct net_proto_family atalk_family_ops = {
+static const struct net_proto_family atalk_family_ops = {
.family = PF_APPLETALK,
.create = atalk_create,
.owner = THIS_MODULE,
};
-static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = {
+static const struct proto_ops atalk_dgram_ops = {
.family = PF_APPLETALK,
.owner = THIS_MODULE,
.release = atalk_release,
@@ -1839,31 +1887,27 @@ static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = {
.sendpage = sock_no_sendpage,
};
-#include <linux/smp_lock.h>
-SOCKOPS_WRAP(atalk_dgram, PF_APPLETALK);
-
static struct notifier_block ddp_notifier = {
.notifier_call = ddp_device_event,
};
-static struct packet_type ltalk_packet_type = {
- .type = __constant_htons(ETH_P_LOCALTALK),
+static struct packet_type ltalk_packet_type __read_mostly = {
+ .type = cpu_to_be16(ETH_P_LOCALTALK),
.func = ltalk_rcv,
};
-static struct packet_type ppptalk_packet_type = {
- .type = __constant_htons(ETH_P_PPPTALK),
+static struct packet_type ppptalk_packet_type __read_mostly = {
+ .type = cpu_to_be16(ETH_P_PPPTALK),
.func = atalk_rcv,
};
static unsigned char ddp_snap_id[] = { 0x08, 0x00, 0x07, 0x80, 0x9B };
/* Export symbols for use by drivers when AppleTalk is a module */
-EXPORT_SYMBOL(aarp_send_ddp);
EXPORT_SYMBOL(atrtr_get_dev);
EXPORT_SYMBOL(atalk_find_dev_addr);
-static char atalk_err_snap[] __initdata =
+static const char atalk_err_snap[] __initconst =
KERN_CRIT "Unable to register DDP with SNAP.\n";
/* Called by proto.c on kernel start up */
@@ -1917,6 +1961,6 @@ static void __exit atalk_exit(void)
module_exit(atalk_exit);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Alan Cox <Alan.Cox@linux.org>");
+MODULE_AUTHOR("Alan Cox <alan@lxorguk.ukuu.org.uk>");
MODULE_DESCRIPTION("AppleTalk 0.20\n");
MODULE_ALIAS_NETPROTO(PF_APPLETALK);
diff --git a/net/appletalk/dev.c b/net/appletalk/dev.c
index 1237e208e24..6c8016f6186 100644
--- a/net/appletalk/dev.c
+++ b/net/appletalk/dev.c
@@ -9,33 +9,16 @@
#include <linux/if_arp.h>
#include <linux/if_ltalk.h>
-static int ltalk_change_mtu(struct net_device *dev, int mtu)
-{
- return -EINVAL;
-}
-
-static int ltalk_mac_addr(struct net_device *dev, void *addr)
-{
- return -EINVAL;
-}
-
static void ltalk_setup(struct net_device *dev)
{
/* Fill in the fields of the device structure with localtalk-generic values. */
-
- dev->change_mtu = ltalk_change_mtu;
- dev->hard_header = NULL;
- dev->rebuild_header = NULL;
- dev->set_mac_address = ltalk_mac_addr;
- dev->hard_header_cache = NULL;
- dev->header_cache_update= NULL;
dev->type = ARPHRD_LOCALTLK;
dev->hard_header_len = LTALK_HLEN;
dev->mtu = LTALK_MTU;
dev->addr_len = LTALK_ALEN;
- dev->tx_queue_len = 10;
-
+ dev->tx_queue_len = 10;
+
dev->broadcast[0] = 0xFF;
dev->flags = IFF_BROADCAST|IFF_MULTICAST|IFF_NOARP;
diff --git a/net/appletalk/sysctl_net_atalk.c b/net/appletalk/sysctl_net_atalk.c
index 40b0af7437a..ebb864361f7 100644
--- a/net/appletalk/sysctl_net_atalk.c
+++ b/net/appletalk/sysctl_net_atalk.c
@@ -12,71 +12,44 @@
static struct ctl_table atalk_table[] = {
{
- .ctl_name = NET_ATALK_AARP_EXPIRY_TIME,
.procname = "aarp-expiry-time",
.data = &sysctl_aarp_expiry_time,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &proc_dointvec_jiffies,
- .strategy = &sysctl_jiffies,
+ .proc_handler = proc_dointvec_jiffies,
},
{
- .ctl_name = NET_ATALK_AARP_TICK_TIME,
.procname = "aarp-tick-time",
.data = &sysctl_aarp_tick_time,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &proc_dointvec_jiffies,
- .strategy = &sysctl_jiffies,
+ .proc_handler = proc_dointvec_jiffies,
},
{
- .ctl_name = NET_ATALK_AARP_RETRANSMIT_LIMIT,
.procname = "aarp-retransmit-limit",
.data = &sysctl_aarp_retransmit_limit,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &proc_dointvec,
+ .proc_handler = proc_dointvec,
},
{
- .ctl_name = NET_ATALK_AARP_RESOLVE_TIME,
.procname = "aarp-resolve-time",
.data = &sysctl_aarp_resolve_time,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &proc_dointvec_jiffies,
- .strategy = &sysctl_jiffies,
+ .proc_handler = proc_dointvec_jiffies,
},
- { 0 },
-};
-
-static struct ctl_table atalk_dir_table[] = {
- {
- .ctl_name = NET_ATALK,
- .procname = "appletalk",
- .mode = 0555,
- .child = atalk_table,
- },
- { 0 },
-};
-
-static struct ctl_table atalk_root_table[] = {
- {
- .ctl_name = CTL_NET,
- .procname = "net",
- .mode = 0555,
- .child = atalk_dir_table,
- },
- { 0 },
+ { },
};
static struct ctl_table_header *atalk_table_header;
void atalk_register_sysctl(void)
{
- atalk_table_header = register_sysctl_table(atalk_root_table, 1);
+ atalk_table_header = register_net_sysctl(&init_net, "net/appletalk", atalk_table);
}
void atalk_unregister_sysctl(void)
{
- unregister_sysctl_table(atalk_table_header);
+ unregister_net_sysctl_table(atalk_table_header);
}