Commit be9ca388 authored by David S. Miller's avatar David S. Miller

Merge master.kernel.org:/home/acme/BK/appletalk-2.5

into nuts.ninka.net:/home/davem/src/BK/net-2.5
parents 43bd3834 f1bbf6ab
#ifndef __LINUX_ATALK_H__
#define __LINUX_ATALK_H__
/*
* AppleTalk networking structures
* AppleTalk networking structures
*
* The following are directly referenced from the University Of Michigan
* netatalk for compatibility reasons.
* The following are directly referenced from the University Of Michigan
* netatalk for compatibility reasons.
*/
#ifndef __LINUX_ATALK_H__
#define __LINUX_ATALK_H__
#define ATPORT_FIRST 1
#define ATPORT_RESERVED 128
#define ATPORT_LAST 254 /* 254 is only legal on localtalk */
#define ATPORT_LAST 254 /* 254 is only legal on localtalk */
#define ATADDR_ANYNET (__u16)0
#define ATADDR_ANYNODE (__u8)0
#define ATADDR_ANYPORT (__u8)0
#define ATADDR_BCAST (__u8)255
#define DDP_MAXSZ 587
#define DDP_MAXHOPS 15 /* 4 bits of hop counter */
#define DDP_MAXHOPS 15 /* 4 bits of hop counter */
#define SIOCATALKDIFADDR (SIOCPROTOPRIVATE + 0)
struct at_addr
{
struct atalk_addr {
__u16 s_net;
__u8 s_node;
};
struct sockaddr_at
{
sa_family_t sat_family;
__u8 sat_port;
struct at_addr sat_addr;
char sat_zero[ 8 ];
struct sockaddr_at {
sa_family_t sat_family;
__u8 sat_port;
struct atalk_addr sat_addr;
char sat_zero[8];
};
struct netrange
{
struct atalk_netrange {
__u8 nr_phase;
__u16 nr_firstnet;
__u16 nr_lastnet;
};
struct atalk_route
{
struct net_device *dev;
struct at_addr target;
struct at_addr gateway;
int flags;
struct atalk_route {
struct net_device *dev;
struct atalk_addr target;
struct atalk_addr gateway;
int flags;
struct atalk_route *next;
};
struct atalk_iface
{
struct net_device *dev;
struct at_addr address; /* Our address */
int status; /* What are we doing? */
/**
* struct atalk_iface - AppleTalk Interface
* @dev - Network device associated with this interface
* @address - Our address
* @status - What are we doing?
* @nets - Associated direct netrange
* @next - next element in the list of interfaces
*/
struct atalk_iface {
struct net_device *dev;
struct atalk_addr address;
int status;
#define ATIF_PROBE 1 /* Probing for an address */
#define ATIF_PROBE_FAIL 2 /* Probe collided */
struct netrange nets; /* Associated direct netrange */
struct atalk_iface *next;
struct atalk_netrange nets;
struct atalk_iface *next;
};
struct atalk_sock
{
unsigned short dest_net;
unsigned short src_net;
unsigned char dest_node;
unsigned char src_node;
unsigned char dest_port;
unsigned char src_port;
struct atalk_sock {
unsigned short dest_net;
unsigned short src_net;
unsigned char dest_node;
unsigned char src_node;
unsigned char dest_port;
unsigned char src_port;
};
#ifdef __KERNEL__
#include <asm/byteorder.h>
struct ddpehdr
{
struct ddpehdr {
#ifdef __LITTLE_ENDIAN_BITFIELD
__u16 deh_len:10, deh_hops:4, deh_pad:2;
__u16 deh_len:10,
deh_hops:4,
deh_pad:2;
#else
__u16 deh_pad:2, deh_hops:4, deh_len:10;
__u16 deh_pad:2,
deh_hops:4,
deh_len:10;
#endif
__u16 deh_sum;
__u16 deh_dnet;
......@@ -92,30 +95,35 @@ struct ddpehdr
/* And netatalk apps expect to stick the type in themselves */
};
static __inline__ struct ddpehdr *ddp_hdr(struct sk_buff *skb)
{
return (struct ddpehdr *)skb->h.raw;
}
/*
* Don't drop the struct into the struct above. You'll get some
* surprise padding.
*/
struct ddpebits
{
struct ddpebits {
#ifdef __LITTLE_ENDIAN_BITFIELD
__u16 deh_len:10, deh_hops:4, deh_pad:2;
__u16 deh_len:10,
deh_hops:4,
deh_pad:2;
#else
__u16 deh_pad:2, deh_hops:4, deh_len:10;
__u16 deh_pad:2,
deh_hops:4,
deh_len:10;
#endif
};
/*
* Short form header
*/
struct ddpshdr
{
/* Short form header */
struct ddpshdr {
#ifdef __LITTLE_ENDIAN_BITFIELD
__u16 dsh_len:10, dsh_pad:6;
__u16 dsh_len:10,
dsh_pad:6;
#else
__u16 dsh_pad:6, dsh_len:10;
__u16 dsh_pad:6,
dsh_len:10;
#endif
__u8 dsh_dport;
__u8 dsh_sport;
......@@ -123,9 +131,7 @@ struct ddpshdr
};
/* AppleTalk AARP headers */
struct elapaarp
{
struct elapaarp {
__u16 hw_type;
#define AARP_HW_TYPE_ETHERNET 1
#define AARP_HW_TYPE_TOKENRING 2
......@@ -147,30 +153,44 @@ struct elapaarp
__u8 pa_dst_node __attribute__ ((packed));
};
#define AARP_EXPIRY_TIME (5*60*HZ) /* Not specified - how long till we drop a resolved entry */
#define AARP_HASH_SIZE 16 /* Size of hash table */
#define AARP_TICK_TIME (HZ/5) /* Fast retransmission timer when resolving */
#define AARP_RETRANSMIT_LIMIT 10 /* Send 10 requests then give up (2 seconds) */
#define AARP_RESOLVE_TIME (10*HZ) /* Some value bigger than total retransmit time + a bit for last reply to appear and to stop continual requests */
static __inline__ struct elapaarp *aarp_hdr(struct sk_buff *skb)
{
return (struct elapaarp *)skb->h.raw;
}
/* Not specified - how long till we drop a resolved entry */
#define AARP_EXPIRY_TIME (5 * 60 * HZ)
/* Size of hash table */
#define AARP_HASH_SIZE 16
/* Fast retransmission timer when resolving */
#define AARP_TICK_TIME (HZ / 5)
/* Send 10 requests then give up (2 seconds) */
#define AARP_RETRANSMIT_LIMIT 10
/*
* Some value bigger than total retransmit time + a bit for last reply to
* appear and to stop continual requests
*/
#define AARP_RESOLVE_TIME (10 * HZ)
extern struct datalink_proto *ddp_dl, *aarp_dl;
extern void aarp_proto_init(void);
/* Inter module exports */
/*
* Give a device find its atif control structure
*/
/* Inter module exports */
/* Give a device find its atif control structure */
static inline struct atalk_iface *atalk_find_dev(struct net_device *dev)
{
return dev->atalk_ptr;
}
extern struct at_addr *atalk_find_dev_addr(struct net_device *dev);
extern struct net_device *atrtr_get_dev(struct at_addr *sa);
extern int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb, struct at_addr *sa, void *hwaddr);
extern void aarp_send_probe(struct net_device *dev, struct at_addr *addr);
extern void aarp_device_down(struct net_device *dev);
extern struct atalk_addr *atalk_find_dev_addr(struct net_device *dev);
extern struct net_device *atrtr_get_dev(struct atalk_addr *sa);
extern int aarp_send_ddp(struct net_device *dev,
struct sk_buff *skb,
struct atalk_addr *sa, void *hwaddr);
extern void aarp_send_probe(struct net_device *dev,
struct atalk_addr *addr);
extern void aarp_device_down(struct net_device *dev);
#ifdef MODULE
extern void aarp_cleanup_module(void);
......
......@@ -30,7 +30,6 @@
*/
#include <linux/config.h>
#if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE)
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/bitops.h>
......@@ -84,7 +83,7 @@ struct aarp_entry {
struct sk_buff_head packet_queue;
int status;
unsigned long expires_at;
struct at_addr target_addr;
struct atalk_addr target_addr;
struct net_device *dev;
char hwaddr[6];
unsigned short xmit_count;
......@@ -122,14 +121,13 @@ static void __aarp_expire(struct aarp_entry *a)
static void __aarp_send_query(struct aarp_entry *a)
{
static char aarp_eth_multicast[ETH_ALEN] =
{ 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF };
static unsigned char aarp_eth_multicast[ETH_ALEN] =
{ 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF };
struct net_device *dev = a->dev;
int len = dev->hard_header_len + sizeof(struct elapaarp) +
aarp_dl->header_length;
struct sk_buff *skb = alloc_skb(len, GFP_ATOMIC);
struct at_addr *sat = atalk_find_dev_addr(dev);
struct elapaarp *eah;
int len = dev->hard_header_len + sizeof(*eah) + aarp_dl->header_length;
struct sk_buff *skb = alloc_skb(len, GFP_ATOMIC);
struct atalk_addr *sat = atalk_find_dev_addr(dev);
if (!skb)
return;
......@@ -141,30 +139,29 @@ static void __aarp_send_query(struct aarp_entry *a)
/* Set up the buffer */
skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length);
eah = (struct elapaarp *)skb_put(skb,
sizeof(struct elapaarp));
skb->protocol = htons(ETH_P_ATALK);
skb->nh.raw = skb->h.raw = (void *) eah;
skb->dev = dev;
skb->nh.raw = skb->h.raw = skb_put(skb, sizeof(*eah));
skb->protocol = htons(ETH_P_ATALK);
skb->dev = dev;
eah = aarp_hdr(skb);
/* Set up the ARP */
eah->hw_type = htons(AARP_HW_TYPE_ETHERNET);
eah->pa_type = htons(ETH_P_ATALK);
eah->hw_len = ETH_ALEN;
eah->pa_len = AARP_PA_ALEN;
eah->function = htons(AARP_REQUEST);
eah->hw_type = htons(AARP_HW_TYPE_ETHERNET);
eah->pa_type = htons(ETH_P_ATALK);
eah->hw_len = ETH_ALEN;
eah->pa_len = AARP_PA_ALEN;
eah->function = htons(AARP_REQUEST);
memcpy(eah->hw_src, dev->dev_addr, ETH_ALEN);
eah->pa_src_zero= 0;
eah->pa_src_net = sat->s_net;
eah->pa_src_node= sat->s_node;
eah->pa_src_zero = 0;
eah->pa_src_net = sat->s_net;
eah->pa_src_node = sat->s_node;
memset(eah->hw_dst, '\0', ETH_ALEN);
eah->pa_dst_zero= 0;
eah->pa_dst_net = a->target_addr.s_net;
eah->pa_dst_node= a->target_addr.s_node;
eah->pa_dst_zero = 0;
eah->pa_dst_net = a->target_addr.s_net;
eah->pa_dst_node = a->target_addr.s_node;
/* Add ELAP headers and set target to the AARP multicast */
aarp_dl->datalink_header(aarp_dl, skb, aarp_eth_multicast);
......@@ -177,46 +174,44 @@ static void __aarp_send_query(struct aarp_entry *a)
/* This runs under aarp_lock and in softint context, so only atomic memory
* allocations can be used. */
static void aarp_send_reply(struct net_device *dev, struct at_addr *us,
struct at_addr *them, unsigned char *sha)
static void aarp_send_reply(struct net_device *dev, struct atalk_addr *us,
struct atalk_addr *them, unsigned char *sha)
{
int len = dev->hard_header_len + sizeof(struct elapaarp) +
aarp_dl->header_length;
struct sk_buff *skb = alloc_skb(len, GFP_ATOMIC);
struct elapaarp *eah;
int len = dev->hard_header_len + sizeof(*eah) + aarp_dl->header_length;
struct sk_buff *skb = alloc_skb(len, GFP_ATOMIC);
if (!skb)
return;
/* Set up the buffer */
skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length);
eah = (struct elapaarp *)skb_put(skb,
sizeof(struct elapaarp));
skb->protocol = htons(ETH_P_ATALK);
skb->nh.raw = skb->h.raw = (void *) eah;
skb->dev = dev;
skb->nh.raw = skb->h.raw = skb_put(skb, sizeof(*eah));
skb->protocol = htons(ETH_P_ATALK);
skb->dev = dev;
eah = aarp_hdr(skb);
/* Set up the ARP */
eah->hw_type = htons(AARP_HW_TYPE_ETHERNET);
eah->pa_type = htons(ETH_P_ATALK);
eah->hw_len = ETH_ALEN;
eah->pa_len = AARP_PA_ALEN;
eah->function = htons(AARP_REPLY);
eah->hw_type = htons(AARP_HW_TYPE_ETHERNET);
eah->pa_type = htons(ETH_P_ATALK);
eah->hw_len = ETH_ALEN;
eah->pa_len = AARP_PA_ALEN;
eah->function = htons(AARP_REPLY);
memcpy(eah->hw_src, dev->dev_addr, ETH_ALEN);
eah->pa_src_zero= 0;
eah->pa_src_net = us->s_net;
eah->pa_src_node= us->s_node;
eah->pa_src_zero = 0;
eah->pa_src_net = us->s_net;
eah->pa_src_node = us->s_node;
if (!sha)
memset(eah->hw_dst, '\0', ETH_ALEN);
else
memcpy(eah->hw_dst, sha, ETH_ALEN);
eah->pa_dst_zero= 0;
eah->pa_dst_net = them->s_net;
eah->pa_dst_node= them->s_node;
eah->pa_dst_zero = 0;
eah->pa_dst_net = them->s_net;
eah->pa_dst_node = them->s_node;
/* Add ELAP headers and set target to the AARP multicast */
aarp_dl->datalink_header(aarp_dl, skb, sha);
......@@ -229,44 +224,42 @@ static void aarp_send_reply(struct net_device *dev, struct at_addr *us,
* aarp_proxy_probe_network.
*/
void aarp_send_probe(struct net_device *dev, struct at_addr *us)
void aarp_send_probe(struct net_device *dev, struct atalk_addr *us)
{
int len = dev->hard_header_len + sizeof(struct elapaarp) +
aarp_dl->header_length;
struct sk_buff *skb = alloc_skb(len, GFP_ATOMIC);
static char aarp_eth_multicast[ETH_ALEN] =
{ 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF };
struct elapaarp *eah;
int len = dev->hard_header_len + sizeof(*eah) + aarp_dl->header_length;
struct sk_buff *skb = alloc_skb(len, GFP_ATOMIC);
static unsigned char aarp_eth_multicast[ETH_ALEN] =
{ 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF };
if (!skb)
return;
/* Set up the buffer */
skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length);
eah = (struct elapaarp *)skb_put(skb,
sizeof(struct elapaarp));
skb->protocol = htons(ETH_P_ATALK);
skb->nh.raw = skb->h.raw = (void *) eah;
skb->dev = dev;
skb->nh.raw = skb->h.raw = skb_put(skb, sizeof(*eah));
skb->protocol = htons(ETH_P_ATALK);
skb->dev = dev;
eah = aarp_hdr(skb);
/* Set up the ARP */
eah->hw_type = htons(AARP_HW_TYPE_ETHERNET);
eah->pa_type = htons(ETH_P_ATALK);
eah->hw_len = ETH_ALEN;
eah->pa_len = AARP_PA_ALEN;
eah->function = htons(AARP_PROBE);
eah->hw_type = htons(AARP_HW_TYPE_ETHERNET);
eah->pa_type = htons(ETH_P_ATALK);
eah->hw_len = ETH_ALEN;
eah->pa_len = AARP_PA_ALEN;
eah->function = htons(AARP_PROBE);
memcpy(eah->hw_src, dev->dev_addr, ETH_ALEN);
eah->pa_src_zero= 0;
eah->pa_src_net = us->s_net;
eah->pa_src_node= us->s_node;
eah->pa_src_zero = 0;
eah->pa_src_net = us->s_net;
eah->pa_src_node = us->s_node;
memset(eah->hw_dst, '\0', ETH_ALEN);
eah->pa_dst_zero= 0;
eah->pa_dst_net = us->s_net;
eah->pa_dst_node= us->s_node;
eah->pa_dst_zero = 0;
eah->pa_dst_net = us->s_net;
eah->pa_dst_node = us->s_node;
/* Add ELAP headers and set target to the AARP multicast */
aarp_dl->datalink_header(aarp_dl, skb, aarp_eth_multicast);
......@@ -398,7 +391,7 @@ static struct aarp_entry *aarp_alloc(void)
*/
static struct aarp_entry *__aarp_find_entry(struct aarp_entry *list,
struct net_device *dev,
struct at_addr *sat)
struct atalk_addr *sat)
{
while (list) {
if (list->target_addr.s_net == sat->s_net &&
......@@ -412,7 +405,7 @@ static struct aarp_entry *__aarp_find_entry(struct aarp_entry *list,
}
/* Called from the DDP code, and thus must be exported. */
void aarp_proxy_remove(struct net_device *dev, struct at_addr *sa)
void aarp_proxy_remove(struct net_device *dev, struct atalk_addr *sa)
{
int hash = sa->s_node % (AARP_HASH_SIZE - 1);
struct aarp_entry *a;
......@@ -427,8 +420,8 @@ void aarp_proxy_remove(struct net_device *dev, struct at_addr *sa)
}
/* This must run under aarp_lock. */
static struct at_addr *__aarp_proxy_find(struct net_device *dev,
struct at_addr *sa)
static struct atalk_addr *__aarp_proxy_find(struct net_device *dev,
struct atalk_addr *sa)
{
int hash = sa->s_node % (AARP_HASH_SIZE - 1);
struct aarp_entry *a = __aarp_find_entry(proxies[hash], dev, sa);
......@@ -482,7 +475,7 @@ void aarp_probe_network(struct atalk_iface *atif)
}
}
int aarp_proxy_probe_network(struct atalk_iface *atif, struct at_addr *sa)
int aarp_proxy_probe_network(struct atalk_iface *atif, struct atalk_addr *sa)
{
int hash, retval = -EPROTONOSUPPORT;
struct aarp_entry *entry;
......@@ -545,7 +538,7 @@ int aarp_proxy_probe_network(struct atalk_iface *atif, struct at_addr *sa)
/* Send a DDP frame */
int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb,
struct at_addr *sa, void *hwaddr)
struct atalk_addr *sa, void *hwaddr)
{
static char ddp_eth_multicast[ETH_ALEN] =
{ 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF };
......@@ -556,15 +549,15 @@ int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb,
/* Check for LocalTalk first */
if (dev->type == ARPHRD_LOCALTLK) {
struct at_addr *at = atalk_find_dev_addr(dev);
struct atalk_addr *at = atalk_find_dev_addr(dev);
struct ddpehdr *ddp = (struct ddpehdr *)skb->data;
int ft = 2;
/*
* Compressible ?
* Compressible ?
*
* IFF: src_net==dest_net==device_net
* (zero matches anything)
* IFF: src_net == dest_net == device_net
* (zero matches anything)
*/
if ((!ddp->deh_snet || at->s_net == ddp->deh_snet) &&
......@@ -580,15 +573,15 @@ int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb,
ft = 1;
}
/*
* Nice and easy. No AARP type protocols occur here
* so we can just shovel it out with a 3 byte LLAP header
* Nice and easy. No AARP type protocols occur here so we can
* just shovel it out with a 3 byte LLAP header
*/
skb_push(skb, 3);
skb->data[0] = sa->s_node;
skb->data[1] = at->s_node;
skb->data[2] = ft;
skb->dev = dev;
skb->dev = dev;
goto sendit;
}
......@@ -652,8 +645,8 @@ int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb,
__aarp_send_query(a);
/*
* Switch to fast timer if needed (That is if this is the
* first unresolved entry to get added)
* Switch to fast timer if needed (That is if this is the first
* unresolved entry to get added)
*/
if (unresolved_count == 1)
......@@ -713,11 +706,11 @@ static void __aarp_resolved(struct aarp_entry **list, struct aarp_entry *a,
static int aarp_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt)
{
struct elapaarp *ea = (struct elapaarp *)skb->h.raw;
struct elapaarp *ea = aarp_hdr(skb);
int hash, ret = 0;
__u16 function;
struct aarp_entry *a;
struct at_addr sa, *ma, da;
struct atalk_addr sa, *ma, da;
struct atalk_iface *ifa;
/* We only do Ethernet SNAP AARP. */
......@@ -791,20 +784,21 @@ static int aarp_rcv(struct sk_buff *skb, struct net_device *dev,
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.
* 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.
* 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;
sa.s_net = ea->pa_dst_net;
/* See if we have a matching proxy. */
ma = __aarp_proxy_find(dev, &sa);
......@@ -817,16 +811,22 @@ static int aarp_rcv(struct sk_buff *skb, struct net_device *dev,
}
if (function == AARP_PROBE) {
/* A probe implies someone trying to get an
/*
* A probe implies someone trying to get an
* address. So as a precaution flush any
* entries we have for this address. */
* entries we have for this address.
*/
struct aarp_entry *a = __aarp_find_entry(
resolved[sa.s_node%(AARP_HASH_SIZE-1)],
skb->dev, &sa);
/* Make it expire next tick - that avoids us
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. */
* to respond host addr.
*/
if (a) {
a->expires_at = jiffies - 1;
mod_timer(&aarp_timer, jiffies +
......@@ -862,7 +862,7 @@ static struct notifier_block aarp_notifier = {
.notifier_call =aarp_device_event,
};
static char aarp_snap_id[] = { 0x00, 0x00, 0x00, 0x80, 0xF3 };
static unsigned char aarp_snap_id[] = { 0x00, 0x00, 0x00, 0x80, 0xF3 };
void __init aarp_proto_init(void)
{
......@@ -1003,5 +1003,4 @@ void aarp_unregister_proc_fs(void)
proc_net_remove("aarp");
}
#endif
#endif /* CONFIG_ATALK || CONFIG_ATALK_MODULE */
MODULE_LICENSE("GPL");
......@@ -49,7 +49,6 @@
*/
#include <linux/config.h>
#if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE)
#include <linux/module.h>
#include <asm/uaccess.h>
#include <asm/system.h>
......@@ -96,8 +95,8 @@ extern void aarp_cleanup_module(void);
extern void aarp_probe_network(struct atalk_iface *atif);
extern int aarp_proxy_probe_network(struct atalk_iface *atif,
struct at_addr *sa);
extern void aarp_proxy_remove(struct net_device *dev, struct at_addr *sa);
struct atalk_addr *sa);
extern void aarp_proxy_remove(struct net_device *dev, struct atalk_addr *sa);
#ifdef CONFIG_SYSCTL
extern inline void atalk_register_sysctl(void);
......@@ -332,7 +331,7 @@ static void atif_drop_device(struct net_device *dev)
}
static struct atalk_iface *atif_add_device(struct net_device *dev,
struct at_addr *sa)
struct atalk_addr *sa)
{
struct atalk_iface *iface;
......@@ -407,7 +406,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 at_addr* proxy_addr)
struct atalk_addr* proxy_addr)
{
int netrange = ntohs(atif->nets.nr_lastnet) -
ntohs(atif->nets.nr_firstnet) + 1;
......@@ -451,16 +450,16 @@ static int atif_proxy_probe_device(struct atalk_iface *atif,
}
struct at_addr *atalk_find_dev_addr(struct net_device *dev)
struct atalk_addr *atalk_find_dev_addr(struct net_device *dev)
{
struct atalk_iface *iface = dev->atalk_ptr;
return iface ? &iface->address : NULL;
}
static struct at_addr *atalk_find_primary(void)
static struct atalk_addr *atalk_find_primary(void)
{
struct atalk_iface *fiface = NULL;
struct at_addr *retval;
struct atalk_addr *retval;
struct atalk_iface *iface;
/*
......@@ -497,14 +496,17 @@ static struct atalk_iface *atalk_find_anynet(int node, struct net_device *dev)
struct atalk_iface *iface = dev->atalk_ptr;
if (!iface || iface->status & ATIF_PROBE)
return NULL;
goto out_err;
if (node == ATADDR_BCAST ||
iface->address.s_node == node ||
node == ATADDR_ANYNODE)
return iface;
return NULL;
if (node != ATADDR_BCAST &&
iface->address.s_node != node &&
node != ATADDR_ANYNODE)
goto out_err;
out:
return iface;
out_err:
iface = NULL;
goto out;
}
/* Find a match for a specific network:node pair */
......@@ -537,7 +539,7 @@ static struct atalk_iface *atalk_find_interface(int net, int node)
* the socket (later on...). We know about host routes and the fact
* that a route must be direct to broadcast.
*/
static struct atalk_route *atrtr_find(struct at_addr *target)
static struct atalk_route *atrtr_find(struct atalk_addr *target)
{
/*
* we must search through all routes unless we find a
......@@ -589,7 +591,7 @@ static struct atalk_route *atrtr_find(struct at_addr *target)
* Given an AppleTalk network, find the device to use. This can be
* a simple lookup.
*/
struct net_device *atrtr_get_dev(struct at_addr *sa)
struct net_device *atrtr_get_dev(struct atalk_addr *sa)
{
struct atalk_route *atr = atrtr_find(sa);
return atr ? atr->dev : NULL;
......@@ -598,9 +600,9 @@ struct net_device *atrtr_get_dev(struct at_addr *sa)
/* Set up a default router */
static void atrtr_set_default(struct net_device *dev)
{
atrtr_default.dev = dev;
atrtr_default.flags = RTF_UP;
atrtr_default.gateway.s_net = htons(0);
atrtr_default.dev = dev;
atrtr_default.flags = RTF_UP;
atrtr_default.gateway.s_net = htons(0);
atrtr_default.gateway.s_node = 0;
}
......@@ -691,7 +693,7 @@ static int atrtr_create(struct rtentry *r, struct net_device *devhint)
}
/* Delete a route. Find it and discard it */
static int atrtr_delete(struct at_addr * addr)
static int atrtr_delete(struct atalk_addr * addr)
{
struct atalk_route **r = &atalk_router_list;
int retval = 0;
......@@ -750,7 +752,7 @@ static inline void atalk_dev_down(struct net_device *dev)
* delete our use of them (iface and route).
*/
static int ddp_device_event(struct notifier_block *this, unsigned long event,
void *ptr)
void *ptr)
{
if (event == NETDEV_DOWN)
/* Discard any use of this */
......@@ -765,7 +767,7 @@ static int atif_ioctl(int cmd, void *arg)
{
static char aarp_mcast[6] = { 0x09, 0x00, 0x00, 0xFF, 0xFF, 0xFF };
struct ifreq atreq;
struct netrange *nr;
struct atalk_netrange *nr;
struct sockaddr_at *sa;
struct net_device *dev;
struct atalk_iface *atif;
......@@ -796,7 +798,7 @@ static int atif_ioctl(int cmd, void *arg)
dev->type != ARPHRD_PPP)
return -EPROTONOSUPPORT;
nr = (struct netrange *)&sa->sat_zero[0];
nr = (struct atalk_netrange *)&sa->sat_zero[0];
add_route = 1;
/*
......@@ -936,7 +938,7 @@ static int atif_ioctl(int cmd, void *arg)
if (!atif)
return -EADDRNOTAVAIL;
nr = (struct netrange *)&(atif->nets);
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.
......@@ -982,7 +984,6 @@ static int atif_ioctl(int cmd, void *arg)
/* Routing ioctl() calls */
static int atrtr_ioctl(unsigned int cmd, void *arg)
{
struct net_device *dev = NULL;
struct rtentry rt;
if (copy_from_user(&rt, arg, sizeof(rt)))
......@@ -995,15 +996,19 @@ static int atrtr_ioctl(unsigned int cmd, void *arg)
return atrtr_delete(&((struct sockaddr_at *)
&rt.rt_dst)->sat_addr);
case SIOCADDRT:
/* FIXME: the name of the device is still in user
* space, isn't it? */
case SIOCADDRT: {
struct net_device *dev = NULL;
/*
* FIXME: the name of the device is still in user
* space, isn't it?
*/
if (rt.rt_dev) {
dev = __dev_get_by_name(rt.rt_dev);
if (!dev)
return -ENODEV;
}
return atrtr_create(&rt, dev);
}
}
return -EINVAL;
}
......@@ -1159,14 +1164,13 @@ static int atalk_release(struct socket *sock)
{
struct sock *sk = sock->sk;
if (!sk)
goto out;
if (!sk->dead)
sk->state_change(sk);
sk->dead = 1;
sock->sk = NULL;
atalk_destroy_socket(sk);
out:
if (sk) {
if (!sk->dead)
sk->state_change(sk);
sk->dead = 1;
sock->sk = NULL;
atalk_destroy_socket(sk);
}
return 0;
}
......@@ -1222,7 +1226,7 @@ static int atalk_autobind(struct sock *sk)
{
struct atalk_sock *at = at_sk(sk);
struct sockaddr_at sat;
struct at_addr *ap = atalk_find_primary();
struct atalk_addr *ap = atalk_find_primary();
int n = -EADDRNOTAVAIL;
if (!ap || ap->s_net == htons(ATADDR_ANYNET))
......@@ -1252,7 +1256,7 @@ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
return -EAFNOSUPPORT;
if (addr->sat_addr.s_net == htons(ATADDR_ANYNET)) {
struct at_addr *ap = atalk_find_primary();
struct atalk_addr *ap = atalk_find_primary();
if (!ap)
return -EADDRNOTAVAIL;
......@@ -1330,7 +1334,6 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr,
return 0;
}
/*
* Find the name of an AppleTalk socket. Just copy the right
* fields into the sockaddr.
......@@ -1366,22 +1369,140 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr,
return 0;
}
#if defined(CONFIG_IPDDP) || defined(CONFIG_IPDDP_MODULE)
static __inline__ int is_ip_over_ddp(struct sk_buff *skb)
{
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_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;
}
#else
/* make it easy for gcc to optimize this test out, i.e. kill the code */
#define is_ip_over_ddp(skb) 0
#define handle_ip_over_ddp(skb) 0
#endif
static void atalk_route_packet(struct sk_buff *skb, struct net_device *dev,
struct ddpehdr *ddp, struct ddpebits *ddphv,
int origlen)
{
struct atalk_route *rt;
struct atalk_addr ta;
/*
* Don't route multicast, etc., packets, or packets sent to "this
* network"
*/
if (skb->pkt_type != PACKET_HOST || !ddp->deh_dnet) {
/*
* FIXME:
*
* Can it ever happen that a packet is from a PPP iface and
* needs to be broadcast onto the default network?
*/
if (dev->type == ARPHRD_PPP)
printk(KERN_DEBUG "AppleTalk: didn't forward broadcast "
"packet received from PPP iface\n");
goto free_it;
}
ta.s_net = ddp->deh_dnet;
ta.s_node = ddp->deh_dnode;
/* Route the packet */
rt = atrtr_find(&ta);
if (!rt || ddphv->deh_hops == DDP_MAXHOPS)
goto free_it;
/* FIXME: use skb->cb to be able to use shared skbs */
ddphv->deh_hops++;
/*
* Route goes through another gateway, so set the target to the
* gateway instead.
*/
if (rt->flags & RTF_GATEWAY) {
ta.s_net = rt->gateway.s_net;
ta.s_node = rt->gateway.s_node;
}
/* Fix up skb->len field */
skb_trim(skb, min_t(unsigned int, origlen,
(rt->dev->hard_header_len +
ddp_dl->header_length + ddphv->deh_len)));
/* Mend the byte order */
/* FIXME: use skb->cb to be able to use shared skbs */
*((__u16 *)ddp) = ntohs(*((__u16 *)ddphv));
/*
* Send the buffer onwards
*
* Now we must always be careful. If it's come from LocalTalk to
* EtherTalk it might not fit
*
* Order matters here: If a packet has to be copied to make a new
* headroom (rare hopefully) then it won't need unsharing.
*
* Note. ddp-> becomes invalid at the realloc.
*/
if (skb_headroom(skb) < 22) {
/* 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;
free_it:
kfree_skb(skb);
}
/**
* atalk_rcv - Receive a packet (in skb) from device dev
* @skb - packet received
* @dev - network device where the packet comes from
* @pt - packet type
* atalk_rcv - Receive a packet (in skb) from device dev
* @skb - packet received
* @dev - network device where the packet comes from
* @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]
* 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]
*/
static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt)
{
struct ddpehdr *ddp = (void *)skb->h.raw;
struct ddpehdr *ddp = ddp_hdr(skb);
struct sock *sock;
struct atalk_iface *atif;
struct sockaddr_at tosat;
......@@ -1432,106 +1553,13 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
/* Not ours, so we route the packet via the correct AppleTalk iface */
if (!atif) {
struct atalk_route *rt;
struct at_addr ta;
/*
* Don't route multicast, etc., packets, or packets
* sent to "this network"
*/
if (skb->pkt_type != PACKET_HOST || !ddp->deh_dnet) {
/* FIXME:
* Can it ever happen that a packet is from a PPP
* iface and needs to be broadcast onto the default
* network? */
if (dev->type == ARPHRD_PPP)
printk(KERN_DEBUG "AppleTalk: didn't forward "
"broadcast packet received "
"from PPP iface\n");
goto freeit;
}
ta.s_net = ddp->deh_dnet;
ta.s_node = ddp->deh_dnode;
/* Route the packet */
rt = atrtr_find(&ta);
if (!rt || ddphv.deh_hops == DDP_MAXHOPS)
goto freeit;
/* FIXME: use skb->cb to be able to use shared skbs */
ddphv.deh_hops++;
/*
* Route goes through another gateway, so
* set the target to the gateway instead.
*/
if (rt->flags & RTF_GATEWAY) {
ta.s_net = rt->gateway.s_net;
ta.s_node = rt->gateway.s_node;
}
/* Fix up skb->len field */
skb_trim(skb, min_t(unsigned int, origlen,
(rt->dev->hard_header_len +
ddp_dl->header_length + ddphv.deh_len)));
/* Mend the byte order */
/* FIXME: use skb->cb to be able to use shared skbs */
*((__u16 *)ddp) = ntohs(*((__u16 *)&ddphv));
/*
* Send the buffer onwards
*
* Now we must always be careful. If it's come from
* LocalTalk to EtherTalk it might not fit
*
* Order matters here: If a packet has to be copied
* to make a new headroom (rare hopefully) then it
* won't need unsharing.
*
* Note. ddp-> becomes invalid at the realloc.
*/
if (skb_headroom(skb) < 22) {
/* 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 freeit;
atalk_route_packet(skb, dev, ddp, &ddphv, origlen);
goto out;
}
#if defined(CONFIG_IPDDP) || defined(CONFIG_IPDDP_MODULE)
/* Check if IP-over-DDP */
if (skb->data[12] == 22) {
struct net_device *dev = __dev_get_by_name("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. */
goto out;
}
#endif
/* if IP over DDP is not selected this code will be optimized out */
if (is_ip_over_ddp(skb))
return handle_ip_over_ddp(skb);
/*
* Which socket - atalk_search_socket() looks for a *full match*
* of the <net, node, port> tuple.
......@@ -1568,7 +1596,7 @@ static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev,
if (skb->mac.raw[2] == 1) {
struct ddpehdr *ddp;
/* Find our address */
struct at_addr *ap = atalk_find_dev_addr(dev);
struct atalk_addr *ap = atalk_find_dev_addr(dev);
if (!ap || skb->len < sizeof(struct ddpshdr))
goto freeit;
......@@ -1674,7 +1702,7 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, int len,
dev = rt->dev;
} else {
struct at_addr at_hint;
struct atalk_addr at_hint;
at_hint.s_node = 0;
at_hint.s_net = at->src_net;
......@@ -1792,7 +1820,7 @@ static int atalk_recvmsg(struct socket *sock, struct msghdr *msg, int size,
return err;
/* FIXME: use skb->cb to be able to use shared skbs */
ddp = (struct ddpehdr *)(skb->h.raw);
ddp = ddp_hdr(skb);
*((__u16 *)&ddphv) = ntohs(*((__u16 *)ddp));
if (sk->type == SOCK_RAW) {
......@@ -1833,40 +1861,48 @@ static int atalk_recvmsg(struct socket *sock, struct msghdr *msg, int size,
*/
static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
long amount = 0;
int rc = -EINVAL;
struct sock *sk = sock->sk;
switch (cmd) {
/* Protocol layer */
case TIOCOUTQ:
amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);
case TIOCOUTQ: {
long amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);
if (amount < 0)
amount = 0;
rc = put_user(amount, (int *)arg);
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->receive_queue);
long amount = 0;
if (skb)
amount = skb->len - sizeof(struct ddpehdr);
rc = put_user(amount, (int *)arg);
break;
}
case SIOCGSTAMP:
if (!sk)
return -EINVAL;
break;
rc = -ENOENT;
if (!sk->stamp.tv_sec)
return -ENOENT;
return copy_to_user((void *)arg, &sk->stamp,
sizeof(struct timeval)) ? -EFAULT : 0;
break;
rc = copy_to_user((void *)arg, &sk->stamp,
sizeof(struct timeval)) ? -EFAULT : 0;
break;
/* Routing */
case SIOCADDRT:
case SIOCDELRT:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
return atrtr_ioctl(cmd, (void *)arg);
rc = -EPERM;
if (capable(CAP_NET_ADMIN))
rc = atrtr_ioctl(cmd, (void *)arg);
break;
/* Interface */
case SIOCGIFADDR:
case SIOCSIFADDR:
......@@ -1874,15 +1910,11 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCATALKDIFADDR:
case SIOCDIFADDR:
case SIOCSARP: /* proxy AARP */
case SIOCDARP: { /* proxy AARP */
int ret;
case SIOCDARP: /* proxy AARP */
rtnl_lock();
ret = atif_ioctl(cmd, (void *)arg);
rc = atif_ioctl(cmd, (void *)arg);
rtnl_unlock();
return ret;
}
break;
/* Physical layer ioctl calls */
case SIOCSIFLINK:
case SIOCGIFHWADDR:
......@@ -1896,21 +1928,11 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCGIFCOUNT:
case SIOCGIFINDEX:
case SIOCGIFNAME:
return dev_ioctl(cmd, (void *)arg);
case SIOCSIFMETRIC:
case SIOCSIFBRDADDR:
case SIOCGIFNETMASK:
case SIOCSIFNETMASK:
case SIOCGIFMEM:
case SIOCSIFMEM:
case SIOCGIFDSTADDR:
case SIOCSIFDSTADDR:
return -EINVAL;
default:
return -EINVAL;
rc = dev_ioctl(cmd, (void *)arg);
break;
}
return put_user(amount, (int *)arg);
return rc;
}
static struct net_proto_family atalk_family_ops = {
......@@ -1955,7 +1977,7 @@ struct packet_type ppptalk_packet_type = {
.func = atalk_rcv,
};
static char ddp_snap_id[] = { 0x08, 0x00, 0x07, 0x80, 0x9B };
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);
......@@ -2023,4 +2045,3 @@ static void __exit atalk_exit(void)
}
module_exit(atalk_exit);
#endif /* MODULE */
#endif /* CONFIG_ATALK || CONFIG_ATALK_MODULE */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment