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 * The following are directly referenced from the University Of Michigan
* netatalk for compatibility reasons. * netatalk for compatibility reasons.
*/ */
#ifndef __LINUX_ATALK_H__
#define __LINUX_ATALK_H__
#define ATPORT_FIRST 1 #define ATPORT_FIRST 1
#define ATPORT_RESERVED 128 #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_ANYNET (__u16)0
#define ATADDR_ANYNODE (__u8)0 #define ATADDR_ANYNODE (__u8)0
#define ATADDR_ANYPORT (__u8)0 #define ATADDR_ANYPORT (__u8)0
#define ATADDR_BCAST (__u8)255 #define ATADDR_BCAST (__u8)255
#define DDP_MAXSZ 587 #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) #define SIOCATALKDIFADDR (SIOCPROTOPRIVATE + 0)
struct at_addr struct atalk_addr {
{
__u16 s_net; __u16 s_net;
__u8 s_node; __u8 s_node;
}; };
struct sockaddr_at struct sockaddr_at {
{ sa_family_t sat_family;
sa_family_t sat_family; __u8 sat_port;
__u8 sat_port; struct atalk_addr sat_addr;
struct at_addr sat_addr; char sat_zero[8];
char sat_zero[ 8 ];
}; };
struct netrange struct atalk_netrange {
{
__u8 nr_phase; __u8 nr_phase;
__u16 nr_firstnet; __u16 nr_firstnet;
__u16 nr_lastnet; __u16 nr_lastnet;
}; };
struct atalk_route struct atalk_route {
{ struct net_device *dev;
struct net_device *dev; struct atalk_addr target;
struct at_addr target; struct atalk_addr gateway;
struct at_addr gateway; int flags;
int flags;
struct atalk_route *next; struct atalk_route *next;
}; };
struct atalk_iface /**
{ * struct atalk_iface - AppleTalk Interface
struct net_device *dev; * @dev - Network device associated with this interface
struct at_addr address; /* Our address */ * @address - Our address
int status; /* What are we doing? */ * @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 1 /* Probing for an address */
#define ATIF_PROBE_FAIL 2 /* Probe collided */ #define ATIF_PROBE_FAIL 2 /* Probe collided */
struct netrange nets; /* Associated direct netrange */ struct atalk_netrange nets;
struct atalk_iface *next; struct atalk_iface *next;
}; };
struct atalk_sock struct atalk_sock {
{ unsigned short dest_net;
unsigned short dest_net; unsigned short src_net;
unsigned short src_net; unsigned char dest_node;
unsigned char dest_node; unsigned char src_node;
unsigned char src_node; unsigned char dest_port;
unsigned char dest_port; unsigned char src_port;
unsigned char src_port;
}; };
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <asm/byteorder.h> #include <asm/byteorder.h>
struct ddpehdr struct ddpehdr {
{
#ifdef __LITTLE_ENDIAN_BITFIELD #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 #else
__u16 deh_pad:2, deh_hops:4, deh_len:10; __u16 deh_pad:2,
deh_hops:4,
deh_len:10;
#endif #endif
__u16 deh_sum; __u16 deh_sum;
__u16 deh_dnet; __u16 deh_dnet;
...@@ -92,30 +95,35 @@ struct ddpehdr ...@@ -92,30 +95,35 @@ struct ddpehdr
/* And netatalk apps expect to stick the type in themselves */ /* 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 * Don't drop the struct into the struct above. You'll get some
* surprise padding. * surprise padding.
*/ */
struct ddpebits {
struct ddpebits
{
#ifdef __LITTLE_ENDIAN_BITFIELD #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 #else
__u16 deh_pad:2, deh_hops:4, deh_len:10; __u16 deh_pad:2,
deh_hops:4,
deh_len:10;
#endif #endif
}; };
/* /* Short form header */
* Short form header struct ddpshdr {
*/
struct ddpshdr
{
#ifdef __LITTLE_ENDIAN_BITFIELD #ifdef __LITTLE_ENDIAN_BITFIELD
__u16 dsh_len:10, dsh_pad:6; __u16 dsh_len:10,
dsh_pad:6;
#else #else
__u16 dsh_pad:6, dsh_len:10; __u16 dsh_pad:6,
dsh_len:10;
#endif #endif
__u8 dsh_dport; __u8 dsh_dport;
__u8 dsh_sport; __u8 dsh_sport;
...@@ -123,9 +131,7 @@ struct ddpshdr ...@@ -123,9 +131,7 @@ struct ddpshdr
}; };
/* AppleTalk AARP headers */ /* AppleTalk AARP headers */
struct elapaarp {
struct elapaarp
{
__u16 hw_type; __u16 hw_type;
#define AARP_HW_TYPE_ETHERNET 1 #define AARP_HW_TYPE_ETHERNET 1
#define AARP_HW_TYPE_TOKENRING 2 #define AARP_HW_TYPE_TOKENRING 2
...@@ -147,30 +153,44 @@ struct elapaarp ...@@ -147,30 +153,44 @@ struct elapaarp
__u8 pa_dst_node __attribute__ ((packed)); __u8 pa_dst_node __attribute__ ((packed));
}; };
#define AARP_EXPIRY_TIME (5*60*HZ) /* Not specified - how long till we drop a resolved entry */ static __inline__ struct elapaarp *aarp_hdr(struct sk_buff *skb)
#define AARP_HASH_SIZE 16 /* Size of hash table */ {
#define AARP_TICK_TIME (HZ/5) /* Fast retransmission timer when resolving */ return (struct elapaarp *)skb->h.raw;
#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 */
/* 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 struct datalink_proto *ddp_dl, *aarp_dl;
extern void aarp_proto_init(void); extern void aarp_proto_init(void);
/* Inter module exports */
/* /* Inter module exports */
* Give a device find its atif control structure
*/
/* Give a device find its atif control structure */
static inline struct atalk_iface *atalk_find_dev(struct net_device *dev) static inline struct atalk_iface *atalk_find_dev(struct net_device *dev)
{ {
return dev->atalk_ptr; return dev->atalk_ptr;
} }
extern struct at_addr *atalk_find_dev_addr(struct net_device *dev); extern struct atalk_addr *atalk_find_dev_addr(struct net_device *dev);
extern struct net_device *atrtr_get_dev(struct at_addr *sa); 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 at_addr *sa, void *hwaddr); extern int aarp_send_ddp(struct net_device *dev,
extern void aarp_send_probe(struct net_device *dev, struct at_addr *addr); struct sk_buff *skb,
extern void aarp_device_down(struct net_device *dev); 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 #ifdef MODULE
extern void aarp_cleanup_module(void); extern void aarp_cleanup_module(void);
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
*/ */
#include <linux/config.h> #include <linux/config.h>
#if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE)
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/bitops.h> #include <asm/bitops.h>
...@@ -84,7 +83,7 @@ struct aarp_entry { ...@@ -84,7 +83,7 @@ struct aarp_entry {
struct sk_buff_head packet_queue; struct sk_buff_head packet_queue;
int status; int status;
unsigned long expires_at; unsigned long expires_at;
struct at_addr target_addr; struct atalk_addr target_addr;
struct net_device *dev; struct net_device *dev;
char hwaddr[6]; char hwaddr[6];
unsigned short xmit_count; unsigned short xmit_count;
...@@ -122,14 +121,13 @@ static void __aarp_expire(struct aarp_entry *a) ...@@ -122,14 +121,13 @@ static void __aarp_expire(struct aarp_entry *a)
static void __aarp_send_query(struct aarp_entry *a) static void __aarp_send_query(struct aarp_entry *a)
{ {
static char aarp_eth_multicast[ETH_ALEN] = static unsigned char aarp_eth_multicast[ETH_ALEN] =
{ 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF }; { 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF };
struct net_device *dev = a->dev; 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; 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) if (!skb)
return; return;
...@@ -141,30 +139,29 @@ static void __aarp_send_query(struct aarp_entry *a) ...@@ -141,30 +139,29 @@ static void __aarp_send_query(struct aarp_entry *a)
/* Set up the buffer */ /* Set up the buffer */
skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length); skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length);
eah = (struct elapaarp *)skb_put(skb, skb->nh.raw = skb->h.raw = skb_put(skb, sizeof(*eah));
sizeof(struct elapaarp)); skb->protocol = htons(ETH_P_ATALK);
skb->protocol = htons(ETH_P_ATALK); skb->dev = dev;
skb->nh.raw = skb->h.raw = (void *) eah; eah = aarp_hdr(skb);
skb->dev = dev;
/* Set up the ARP */ /* Set up the ARP */
eah->hw_type = htons(AARP_HW_TYPE_ETHERNET); eah->hw_type = htons(AARP_HW_TYPE_ETHERNET);
eah->pa_type = htons(ETH_P_ATALK); eah->pa_type = htons(ETH_P_ATALK);
eah->hw_len = ETH_ALEN; eah->hw_len = ETH_ALEN;
eah->pa_len = AARP_PA_ALEN; eah->pa_len = AARP_PA_ALEN;
eah->function = htons(AARP_REQUEST); eah->function = htons(AARP_REQUEST);
memcpy(eah->hw_src, dev->dev_addr, ETH_ALEN); memcpy(eah->hw_src, dev->dev_addr, ETH_ALEN);
eah->pa_src_zero= 0; eah->pa_src_zero = 0;
eah->pa_src_net = sat->s_net; eah->pa_src_net = sat->s_net;
eah->pa_src_node= sat->s_node; eah->pa_src_node = sat->s_node;
memset(eah->hw_dst, '\0', ETH_ALEN); memset(eah->hw_dst, '\0', ETH_ALEN);
eah->pa_dst_zero= 0; eah->pa_dst_zero = 0;
eah->pa_dst_net = a->target_addr.s_net; eah->pa_dst_net = a->target_addr.s_net;
eah->pa_dst_node= a->target_addr.s_node; eah->pa_dst_node = a->target_addr.s_node;
/* Add ELAP headers and set target to the AARP multicast */ /* Add ELAP headers and set target to the AARP multicast */
aarp_dl->datalink_header(aarp_dl, skb, aarp_eth_multicast); aarp_dl->datalink_header(aarp_dl, skb, aarp_eth_multicast);
...@@ -177,46 +174,44 @@ static void __aarp_send_query(struct aarp_entry *a) ...@@ -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 /* This runs under aarp_lock and in softint context, so only atomic memory
* allocations can be used. */ * allocations can be used. */
static void aarp_send_reply(struct net_device *dev, struct at_addr *us, static void aarp_send_reply(struct net_device *dev, struct atalk_addr *us,
struct at_addr *them, unsigned char *sha) 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; 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) if (!skb)
return; return;
/* Set up the buffer */ /* Set up the buffer */
skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length); skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length);
eah = (struct elapaarp *)skb_put(skb, skb->nh.raw = skb->h.raw = skb_put(skb, sizeof(*eah));
sizeof(struct elapaarp)); skb->protocol = htons(ETH_P_ATALK);
skb->protocol = htons(ETH_P_ATALK); skb->dev = dev;
skb->nh.raw = skb->h.raw = (void *) eah; eah = aarp_hdr(skb);
skb->dev = dev;
/* Set up the ARP */ /* Set up the ARP */
eah->hw_type = htons(AARP_HW_TYPE_ETHERNET); eah->hw_type = htons(AARP_HW_TYPE_ETHERNET);
eah->pa_type = htons(ETH_P_ATALK); eah->pa_type = htons(ETH_P_ATALK);
eah->hw_len = ETH_ALEN; eah->hw_len = ETH_ALEN;
eah->pa_len = AARP_PA_ALEN; eah->pa_len = AARP_PA_ALEN;
eah->function = htons(AARP_REPLY); eah->function = htons(AARP_REPLY);
memcpy(eah->hw_src, dev->dev_addr, ETH_ALEN); memcpy(eah->hw_src, dev->dev_addr, ETH_ALEN);
eah->pa_src_zero= 0; eah->pa_src_zero = 0;
eah->pa_src_net = us->s_net; eah->pa_src_net = us->s_net;
eah->pa_src_node= us->s_node; eah->pa_src_node = us->s_node;
if (!sha) if (!sha)
memset(eah->hw_dst, '\0', ETH_ALEN); memset(eah->hw_dst, '\0', ETH_ALEN);
else else
memcpy(eah->hw_dst, sha, ETH_ALEN); memcpy(eah->hw_dst, sha, ETH_ALEN);
eah->pa_dst_zero= 0; eah->pa_dst_zero = 0;
eah->pa_dst_net = them->s_net; eah->pa_dst_net = them->s_net;
eah->pa_dst_node= them->s_node; eah->pa_dst_node = them->s_node;
/* Add ELAP headers and set target to the AARP multicast */ /* Add ELAP headers and set target to the AARP multicast */
aarp_dl->datalink_header(aarp_dl, skb, sha); 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, ...@@ -229,44 +224,42 @@ static void aarp_send_reply(struct net_device *dev, struct at_addr *us,
* aarp_proxy_probe_network. * 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; 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) if (!skb)
return; return;
/* Set up the buffer */ /* Set up the buffer */
skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length); skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length);
eah = (struct elapaarp *)skb_put(skb, skb->nh.raw = skb->h.raw = skb_put(skb, sizeof(*eah));
sizeof(struct elapaarp)); skb->protocol = htons(ETH_P_ATALK);
skb->protocol = htons(ETH_P_ATALK); skb->dev = dev;
skb->nh.raw = skb->h.raw = (void *) eah; eah = aarp_hdr(skb);
skb->dev = dev;
/* Set up the ARP */ /* Set up the ARP */
eah->hw_type = htons(AARP_HW_TYPE_ETHERNET); eah->hw_type = htons(AARP_HW_TYPE_ETHERNET);
eah->pa_type = htons(ETH_P_ATALK); eah->pa_type = htons(ETH_P_ATALK);
eah->hw_len = ETH_ALEN; eah->hw_len = ETH_ALEN;
eah->pa_len = AARP_PA_ALEN; eah->pa_len = AARP_PA_ALEN;
eah->function = htons(AARP_PROBE); eah->function = htons(AARP_PROBE);
memcpy(eah->hw_src, dev->dev_addr, ETH_ALEN); memcpy(eah->hw_src, dev->dev_addr, ETH_ALEN);
eah->pa_src_zero= 0; eah->pa_src_zero = 0;
eah->pa_src_net = us->s_net; eah->pa_src_net = us->s_net;
eah->pa_src_node= us->s_node; eah->pa_src_node = us->s_node;
memset(eah->hw_dst, '\0', ETH_ALEN); memset(eah->hw_dst, '\0', ETH_ALEN);
eah->pa_dst_zero= 0; eah->pa_dst_zero = 0;
eah->pa_dst_net = us->s_net; eah->pa_dst_net = us->s_net;
eah->pa_dst_node= us->s_node; eah->pa_dst_node = us->s_node;
/* Add ELAP headers and set target to the AARP multicast */ /* Add ELAP headers and set target to the AARP multicast */
aarp_dl->datalink_header(aarp_dl, skb, aarp_eth_multicast); aarp_dl->datalink_header(aarp_dl, skb, aarp_eth_multicast);
...@@ -398,7 +391,7 @@ static struct aarp_entry *aarp_alloc(void) ...@@ -398,7 +391,7 @@ static struct aarp_entry *aarp_alloc(void)
*/ */
static struct aarp_entry *__aarp_find_entry(struct aarp_entry *list, static struct aarp_entry *__aarp_find_entry(struct aarp_entry *list,
struct net_device *dev, struct net_device *dev,
struct at_addr *sat) struct atalk_addr *sat)
{ {
while (list) { while (list) {
if (list->target_addr.s_net == sat->s_net && if (list->target_addr.s_net == sat->s_net &&
...@@ -412,7 +405,7 @@ static struct aarp_entry *__aarp_find_entry(struct aarp_entry *list, ...@@ -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. */ /* 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); int hash = sa->s_node % (AARP_HASH_SIZE - 1);
struct aarp_entry *a; struct aarp_entry *a;
...@@ -427,8 +420,8 @@ void aarp_proxy_remove(struct net_device *dev, struct at_addr *sa) ...@@ -427,8 +420,8 @@ void aarp_proxy_remove(struct net_device *dev, struct at_addr *sa)
} }
/* This must run under aarp_lock. */ /* This must run under aarp_lock. */
static struct at_addr *__aarp_proxy_find(struct net_device *dev, static struct atalk_addr *__aarp_proxy_find(struct net_device *dev,
struct at_addr *sa) struct atalk_addr *sa)
{ {
int hash = sa->s_node % (AARP_HASH_SIZE - 1); int hash = sa->s_node % (AARP_HASH_SIZE - 1);
struct aarp_entry *a = __aarp_find_entry(proxies[hash], dev, sa); struct aarp_entry *a = __aarp_find_entry(proxies[hash], dev, sa);
...@@ -482,7 +475,7 @@ void aarp_probe_network(struct atalk_iface *atif) ...@@ -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; int hash, retval = -EPROTONOSUPPORT;
struct aarp_entry *entry; struct aarp_entry *entry;
...@@ -545,7 +538,7 @@ int aarp_proxy_probe_network(struct atalk_iface *atif, struct at_addr *sa) ...@@ -545,7 +538,7 @@ int aarp_proxy_probe_network(struct atalk_iface *atif, struct at_addr *sa)
/* Send a DDP frame */ /* Send a DDP frame */
int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb, 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] = static char ddp_eth_multicast[ETH_ALEN] =
{ 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF }; { 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF };
...@@ -556,15 +549,15 @@ int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb, ...@@ -556,15 +549,15 @@ int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb,
/* Check for LocalTalk first */ /* Check for LocalTalk first */
if (dev->type == ARPHRD_LOCALTLK) { 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; struct ddpehdr *ddp = (struct ddpehdr *)skb->data;
int ft = 2; int ft = 2;
/* /*
* Compressible ? * Compressible ?
* *
* IFF: src_net==dest_net==device_net * IFF: src_net == dest_net == device_net
* (zero matches anything) * (zero matches anything)
*/ */
if ((!ddp->deh_snet || at->s_net == ddp->deh_snet) && 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, ...@@ -580,15 +573,15 @@ int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb,
ft = 1; ft = 1;
} }
/* /*
* Nice and easy. No AARP type protocols occur here * Nice and easy. No AARP type protocols occur here so we can
* so we can just shovel it out with a 3 byte LLAP header * just shovel it out with a 3 byte LLAP header
*/ */
skb_push(skb, 3); skb_push(skb, 3);
skb->data[0] = sa->s_node; skb->data[0] = sa->s_node;
skb->data[1] = at->s_node; skb->data[1] = at->s_node;
skb->data[2] = ft; skb->data[2] = ft;
skb->dev = dev; skb->dev = dev;
goto sendit; goto sendit;
} }
...@@ -652,8 +645,8 @@ int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb, ...@@ -652,8 +645,8 @@ int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb,
__aarp_send_query(a); __aarp_send_query(a);
/* /*
* Switch to fast timer if needed (That is if this is the * Switch to fast timer if needed (That is if this is the first
* first unresolved entry to get added) * unresolved entry to get added)
*/ */
if (unresolved_count == 1) if (unresolved_count == 1)
...@@ -713,11 +706,11 @@ static void __aarp_resolved(struct aarp_entry **list, struct aarp_entry *a, ...@@ -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, static int aarp_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt) struct packet_type *pt)
{ {
struct elapaarp *ea = (struct elapaarp *)skb->h.raw; struct elapaarp *ea = aarp_hdr(skb);
int hash, ret = 0; int hash, ret = 0;
__u16 function; __u16 function;
struct aarp_entry *a; struct aarp_entry *a;
struct at_addr sa, *ma, da; struct atalk_addr sa, *ma, da;
struct atalk_iface *ifa; struct atalk_iface *ifa;
/* We only do Ethernet SNAP AARP. */ /* We only do Ethernet SNAP AARP. */
...@@ -791,20 +784,21 @@ static int aarp_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -791,20 +784,21 @@ static int aarp_rcv(struct sk_buff *skb, struct net_device *dev,
case AARP_REQUEST: case AARP_REQUEST:
case AARP_PROBE: case AARP_PROBE:
/* /*
* If it is my address set ma to my address and * If it is my address set ma to my address and reply.
* reply. We can treat probe and request the * We can treat probe and request the same. Probe
* same. Probe simply means we shouldn't cache * simply means we shouldn't cache the querying host,
* the querying host, as in a probe they are * as in a probe they are proposing an address not
* proposing an address not using one. * using one.
* *
* Support for proxy-AARP added. We check if the * Support for proxy-AARP added. We check if the
* address is one of our proxies before we toss * address is one of our proxies before we toss the
* the packet out. * packet out.
*/ */
sa.s_node = ea->pa_dst_node; 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. */ /* See if we have a matching proxy. */
ma = __aarp_proxy_find(dev, &sa); ma = __aarp_proxy_find(dev, &sa);
...@@ -817,16 +811,22 @@ static int aarp_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -817,16 +811,22 @@ static int aarp_rcv(struct sk_buff *skb, struct net_device *dev,
} }
if (function == AARP_PROBE) { 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 * 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( struct aarp_entry *a = __aarp_find_entry(
resolved[sa.s_node%(AARP_HASH_SIZE-1)], resolved[sa.s_node %
skb->dev, &sa); (AARP_HASH_SIZE - 1)],
/* Make it expire next tick - that avoids us skb->dev, &sa);
/*
* Make it expire next tick - that avoids us
* getting into a probe/flush/learn/probe/ * getting into a probe/flush/learn/probe/
* flush/learn cycle during probing of a slow * flush/learn cycle during probing of a slow
* to respond host addr. */ * to respond host addr.
*/
if (a) { if (a) {
a->expires_at = jiffies - 1; a->expires_at = jiffies - 1;
mod_timer(&aarp_timer, jiffies + mod_timer(&aarp_timer, jiffies +
...@@ -862,7 +862,7 @@ static struct notifier_block aarp_notifier = { ...@@ -862,7 +862,7 @@ static struct notifier_block aarp_notifier = {
.notifier_call =aarp_device_event, .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) void __init aarp_proto_init(void)
{ {
...@@ -1003,5 +1003,4 @@ void aarp_unregister_proc_fs(void) ...@@ -1003,5 +1003,4 @@ void aarp_unregister_proc_fs(void)
proc_net_remove("aarp"); proc_net_remove("aarp");
} }
#endif #endif
#endif /* CONFIG_ATALK || CONFIG_ATALK_MODULE */
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -49,7 +49,6 @@ ...@@ -49,7 +49,6 @@
*/ */
#include <linux/config.h> #include <linux/config.h>
#if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE)
#include <linux/module.h> #include <linux/module.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -96,8 +95,8 @@ extern void aarp_cleanup_module(void); ...@@ -96,8 +95,8 @@ extern void aarp_cleanup_module(void);
extern void aarp_probe_network(struct atalk_iface *atif); extern void aarp_probe_network(struct atalk_iface *atif);
extern int aarp_proxy_probe_network(struct atalk_iface *atif, extern int aarp_proxy_probe_network(struct atalk_iface *atif,
struct at_addr *sa); struct atalk_addr *sa);
extern void aarp_proxy_remove(struct net_device *dev, struct at_addr *sa); extern void aarp_proxy_remove(struct net_device *dev, struct atalk_addr *sa);
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
extern inline void atalk_register_sysctl(void); extern inline void atalk_register_sysctl(void);
...@@ -332,7 +331,7 @@ static void atif_drop_device(struct net_device *dev) ...@@ -332,7 +331,7 @@ static void atif_drop_device(struct net_device *dev)
} }
static struct atalk_iface *atif_add_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; struct atalk_iface *iface;
...@@ -407,7 +406,7 @@ static int atif_probe_device(struct atalk_iface *atif) ...@@ -407,7 +406,7 @@ static int atif_probe_device(struct atalk_iface *atif)
/* Perform AARP probing for a proxy address */ /* Perform AARP probing for a proxy address */
static int atif_proxy_probe_device(struct atalk_iface *atif, 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) - int netrange = ntohs(atif->nets.nr_lastnet) -
ntohs(atif->nets.nr_firstnet) + 1; ntohs(atif->nets.nr_firstnet) + 1;
...@@ -451,16 +450,16 @@ static int atif_proxy_probe_device(struct atalk_iface *atif, ...@@ -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; struct atalk_iface *iface = dev->atalk_ptr;
return iface ? &iface->address : NULL; 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 atalk_iface *fiface = NULL;
struct at_addr *retval; struct atalk_addr *retval;
struct atalk_iface *iface; struct atalk_iface *iface;
/* /*
...@@ -497,14 +496,17 @@ static struct atalk_iface *atalk_find_anynet(int node, struct net_device *dev) ...@@ -497,14 +496,17 @@ static struct atalk_iface *atalk_find_anynet(int node, struct net_device *dev)
struct atalk_iface *iface = dev->atalk_ptr; struct atalk_iface *iface = dev->atalk_ptr;
if (!iface || iface->status & ATIF_PROBE) if (!iface || iface->status & ATIF_PROBE)
return NULL; goto out_err;
if (node == ATADDR_BCAST || if (node != ATADDR_BCAST &&
iface->address.s_node == node || iface->address.s_node != node &&
node == ATADDR_ANYNODE) node != ATADDR_ANYNODE)
return iface; goto out_err;
out:
return NULL; return iface;
out_err:
iface = NULL;
goto out;
} }
/* Find a match for a specific network:node pair */ /* Find a match for a specific network:node pair */
...@@ -537,7 +539,7 @@ static struct atalk_iface *atalk_find_interface(int net, int node) ...@@ -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 * the socket (later on...). We know about host routes and the fact
* that a route must be direct to broadcast. * 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 * we must search through all routes unless we find a
...@@ -589,7 +591,7 @@ static struct atalk_route *atrtr_find(struct at_addr *target) ...@@ -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 * Given an AppleTalk network, find the device to use. This can be
* a simple lookup. * 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); struct atalk_route *atr = atrtr_find(sa);
return atr ? atr->dev : NULL; return atr ? atr->dev : NULL;
...@@ -598,9 +600,9 @@ struct net_device *atrtr_get_dev(struct at_addr *sa) ...@@ -598,9 +600,9 @@ struct net_device *atrtr_get_dev(struct at_addr *sa)
/* Set up a default router */ /* Set up a default router */
static void atrtr_set_default(struct net_device *dev) static void atrtr_set_default(struct net_device *dev)
{ {
atrtr_default.dev = dev; atrtr_default.dev = dev;
atrtr_default.flags = RTF_UP; atrtr_default.flags = RTF_UP;
atrtr_default.gateway.s_net = htons(0); atrtr_default.gateway.s_net = htons(0);
atrtr_default.gateway.s_node = 0; atrtr_default.gateway.s_node = 0;
} }
...@@ -691,7 +693,7 @@ static int atrtr_create(struct rtentry *r, struct net_device *devhint) ...@@ -691,7 +693,7 @@ static int atrtr_create(struct rtentry *r, struct net_device *devhint)
} }
/* Delete a route. Find it and discard it */ /* 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; struct atalk_route **r = &atalk_router_list;
int retval = 0; int retval = 0;
...@@ -750,7 +752,7 @@ static inline void atalk_dev_down(struct net_device *dev) ...@@ -750,7 +752,7 @@ static inline void atalk_dev_down(struct net_device *dev)
* delete our use of them (iface and route). * delete our use of them (iface and route).
*/ */
static int ddp_device_event(struct notifier_block *this, unsigned long event, static int ddp_device_event(struct notifier_block *this, unsigned long event,
void *ptr) void *ptr)
{ {
if (event == NETDEV_DOWN) if (event == NETDEV_DOWN)
/* Discard any use of this */ /* Discard any use of this */
...@@ -765,7 +767,7 @@ static int atif_ioctl(int cmd, void *arg) ...@@ -765,7 +767,7 @@ static int atif_ioctl(int cmd, void *arg)
{ {
static char aarp_mcast[6] = { 0x09, 0x00, 0x00, 0xFF, 0xFF, 0xFF }; static char aarp_mcast[6] = { 0x09, 0x00, 0x00, 0xFF, 0xFF, 0xFF };
struct ifreq atreq; struct ifreq atreq;
struct netrange *nr; struct atalk_netrange *nr;
struct sockaddr_at *sa; struct sockaddr_at *sa;
struct net_device *dev; struct net_device *dev;
struct atalk_iface *atif; struct atalk_iface *atif;
...@@ -796,7 +798,7 @@ static int atif_ioctl(int cmd, void *arg) ...@@ -796,7 +798,7 @@ static int atif_ioctl(int cmd, void *arg)
dev->type != ARPHRD_PPP) dev->type != ARPHRD_PPP)
return -EPROTONOSUPPORT; return -EPROTONOSUPPORT;
nr = (struct netrange *)&sa->sat_zero[0]; nr = (struct atalk_netrange *)&sa->sat_zero[0];
add_route = 1; add_route = 1;
/* /*
...@@ -936,7 +938,7 @@ static int atif_ioctl(int cmd, void *arg) ...@@ -936,7 +938,7 @@ static int atif_ioctl(int cmd, void *arg)
if (!atif) if (!atif)
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
nr = (struct netrange *)&(atif->nets); nr = (struct atalk_netrange *)&(atif->nets);
/* /*
* Phase 1 is fine on Localtalk but we don't do * Phase 1 is fine on Localtalk but we don't do
* Ethertalk phase 1. Anyone wanting to add it go ahead. * Ethertalk phase 1. Anyone wanting to add it go ahead.
...@@ -982,7 +984,6 @@ static int atif_ioctl(int cmd, void *arg) ...@@ -982,7 +984,6 @@ static int atif_ioctl(int cmd, void *arg)
/* Routing ioctl() calls */ /* Routing ioctl() calls */
static int atrtr_ioctl(unsigned int cmd, void *arg) static int atrtr_ioctl(unsigned int cmd, void *arg)
{ {
struct net_device *dev = NULL;
struct rtentry rt; struct rtentry rt;
if (copy_from_user(&rt, arg, sizeof(rt))) if (copy_from_user(&rt, arg, sizeof(rt)))
...@@ -995,15 +996,19 @@ static int atrtr_ioctl(unsigned int cmd, void *arg) ...@@ -995,15 +996,19 @@ static int atrtr_ioctl(unsigned int cmd, void *arg)
return atrtr_delete(&((struct sockaddr_at *) return atrtr_delete(&((struct sockaddr_at *)
&rt.rt_dst)->sat_addr); &rt.rt_dst)->sat_addr);
case SIOCADDRT: case SIOCADDRT: {
/* FIXME: the name of the device is still in user struct net_device *dev = NULL;
* space, isn't it? */ /*
* FIXME: the name of the device is still in user
* space, isn't it?
*/
if (rt.rt_dev) { if (rt.rt_dev) {
dev = __dev_get_by_name(rt.rt_dev); dev = __dev_get_by_name(rt.rt_dev);
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
} }
return atrtr_create(&rt, dev); return atrtr_create(&rt, dev);
}
} }
return -EINVAL; return -EINVAL;
} }
...@@ -1159,14 +1164,13 @@ static int atalk_release(struct socket *sock) ...@@ -1159,14 +1164,13 @@ static int atalk_release(struct socket *sock)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
if (!sk) if (sk) {
goto out; if (!sk->dead)
if (!sk->dead) sk->state_change(sk);
sk->state_change(sk); sk->dead = 1;
sk->dead = 1; sock->sk = NULL;
sock->sk = NULL; atalk_destroy_socket(sk);
atalk_destroy_socket(sk); }
out:
return 0; return 0;
} }
...@@ -1222,7 +1226,7 @@ static int atalk_autobind(struct sock *sk) ...@@ -1222,7 +1226,7 @@ static int atalk_autobind(struct sock *sk)
{ {
struct atalk_sock *at = at_sk(sk); struct atalk_sock *at = at_sk(sk);
struct sockaddr_at sat; struct sockaddr_at sat;
struct at_addr *ap = atalk_find_primary(); struct atalk_addr *ap = atalk_find_primary();
int n = -EADDRNOTAVAIL; int n = -EADDRNOTAVAIL;
if (!ap || ap->s_net == htons(ATADDR_ANYNET)) 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) ...@@ -1252,7 +1256,7 @@ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
return -EAFNOSUPPORT; return -EAFNOSUPPORT;
if (addr->sat_addr.s_net == htons(ATADDR_ANYNET)) { 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) if (!ap)
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
...@@ -1330,7 +1334,6 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr, ...@@ -1330,7 +1334,6 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr,
return 0; return 0;
} }
/* /*
* Find the name of an AppleTalk socket. Just copy the right * Find the name of an AppleTalk socket. Just copy the right
* fields into the sockaddr. * fields into the sockaddr.
...@@ -1366,22 +1369,140 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr, ...@@ -1366,22 +1369,140 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr,
return 0; 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 * atalk_rcv - Receive a packet (in skb) from device dev
* @skb - packet received * @skb - packet received
* @dev - network device where the packet comes from * @dev - network device where the packet comes from
* @pt - packet type * @pt - packet type
* *
* Receive a packet (in skb) from device dev. This has come from the SNAP * 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 * 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 * header, skb->len is the DDP length. The physical headers have been
* extracted. PPP should probably pass frames marked as for this layer. * extracted. PPP should probably pass frames marked as for this layer.
* [ie ARPHRD_ETHERTALK] * [ie ARPHRD_ETHERTALK]
*/ */
static int atalk_rcv(struct sk_buff *skb, struct net_device *dev, static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt) struct packet_type *pt)
{ {
struct ddpehdr *ddp = (void *)skb->h.raw; struct ddpehdr *ddp = ddp_hdr(skb);
struct sock *sock; struct sock *sock;
struct atalk_iface *atif; struct atalk_iface *atif;
struct sockaddr_at tosat; struct sockaddr_at tosat;
...@@ -1432,106 +1553,13 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -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 */ /* Not ours, so we route the packet via the correct AppleTalk iface */
if (!atif) { if (!atif) {
struct atalk_route *rt; atalk_route_packet(skb, dev, ddp, &ddphv, origlen);
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;
goto out; goto out;
} }
#if defined(CONFIG_IPDDP) || defined(CONFIG_IPDDP_MODULE) /* if IP over DDP is not selected this code will be optimized out */
/* Check if IP-over-DDP */ if (is_ip_over_ddp(skb))
if (skb->data[12] == 22) { return handle_ip_over_ddp(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. */
goto out;
}
#endif
/* /*
* Which socket - atalk_search_socket() looks for a *full match* * Which socket - atalk_search_socket() looks for a *full match*
* of the <net, node, port> tuple. * of the <net, node, port> tuple.
...@@ -1568,7 +1596,7 @@ static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -1568,7 +1596,7 @@ static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev,
if (skb->mac.raw[2] == 1) { if (skb->mac.raw[2] == 1) {
struct ddpehdr *ddp; struct ddpehdr *ddp;
/* Find our address */ /* 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)) if (!ap || skb->len < sizeof(struct ddpshdr))
goto freeit; goto freeit;
...@@ -1674,7 +1702,7 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, int len, ...@@ -1674,7 +1702,7 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, int len,
dev = rt->dev; dev = rt->dev;
} else { } else {
struct at_addr at_hint; struct atalk_addr at_hint;
at_hint.s_node = 0; at_hint.s_node = 0;
at_hint.s_net = at->src_net; at_hint.s_net = at->src_net;
...@@ -1792,7 +1820,7 @@ static int atalk_recvmsg(struct socket *sock, struct msghdr *msg, int size, ...@@ -1792,7 +1820,7 @@ static int atalk_recvmsg(struct socket *sock, struct msghdr *msg, int size,
return err; return err;
/* FIXME: use skb->cb to be able to use shared skbs */ /* 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)); *((__u16 *)&ddphv) = ntohs(*((__u16 *)ddp));
if (sk->type == SOCK_RAW) { if (sk->type == SOCK_RAW) {
...@@ -1833,40 +1861,48 @@ static int atalk_recvmsg(struct socket *sock, struct msghdr *msg, int size, ...@@ -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) static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{ {
long amount = 0; int rc = -EINVAL;
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
switch (cmd) { switch (cmd) {
/* Protocol layer */ /* Protocol layer */
case TIOCOUTQ: case TIOCOUTQ: {
amount = sk->sndbuf - atomic_read(&sk->wmem_alloc); long amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);
if (amount < 0) if (amount < 0)
amount = 0; amount = 0;
rc = put_user(amount, (int *)arg);
break; break;
}
case TIOCINQ: { case TIOCINQ: {
/* /*
* These two are safe on a single CPU system as only * These two are safe on a single CPU system as only
* user tasks fiddle here * user tasks fiddle here
*/ */
struct sk_buff *skb = skb_peek(&sk->receive_queue); struct sk_buff *skb = skb_peek(&sk->receive_queue);
long amount = 0;
if (skb) if (skb)
amount = skb->len - sizeof(struct ddpehdr); amount = skb->len - sizeof(struct ddpehdr);
rc = put_user(amount, (int *)arg);
break; break;
} }
case SIOCGSTAMP: case SIOCGSTAMP:
if (!sk) if (!sk)
return -EINVAL; break;
rc = -ENOENT;
if (!sk->stamp.tv_sec) if (!sk->stamp.tv_sec)
return -ENOENT; break;
return copy_to_user((void *)arg, &sk->stamp, rc = copy_to_user((void *)arg, &sk->stamp,
sizeof(struct timeval)) ? -EFAULT : 0; sizeof(struct timeval)) ? -EFAULT : 0;
break;
/* Routing */ /* Routing */
case SIOCADDRT: case SIOCADDRT:
case SIOCDELRT: case SIOCDELRT:
if (!capable(CAP_NET_ADMIN)) rc = -EPERM;
return -EPERM; if (capable(CAP_NET_ADMIN))
return atrtr_ioctl(cmd, (void *)arg); rc = atrtr_ioctl(cmd, (void *)arg);
break;
/* Interface */ /* Interface */
case SIOCGIFADDR: case SIOCGIFADDR:
case SIOCSIFADDR: case SIOCSIFADDR:
...@@ -1874,15 +1910,11 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -1874,15 +1910,11 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCATALKDIFADDR: case SIOCATALKDIFADDR:
case SIOCDIFADDR: case SIOCDIFADDR:
case SIOCSARP: /* proxy AARP */ case SIOCSARP: /* proxy AARP */
case SIOCDARP: { /* proxy AARP */ case SIOCDARP: /* proxy AARP */
int ret;
rtnl_lock(); rtnl_lock();
ret = atif_ioctl(cmd, (void *)arg); rc = atif_ioctl(cmd, (void *)arg);
rtnl_unlock(); rtnl_unlock();
break;
return ret;
}
/* Physical layer ioctl calls */ /* Physical layer ioctl calls */
case SIOCSIFLINK: case SIOCSIFLINK:
case SIOCGIFHWADDR: case SIOCGIFHWADDR:
...@@ -1896,21 +1928,11 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -1896,21 +1928,11 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCGIFCOUNT: case SIOCGIFCOUNT:
case SIOCGIFINDEX: case SIOCGIFINDEX:
case SIOCGIFNAME: case SIOCGIFNAME:
return dev_ioctl(cmd, (void *)arg); rc = dev_ioctl(cmd, (void *)arg);
case SIOCSIFMETRIC: break;
case SIOCSIFBRDADDR:
case SIOCGIFNETMASK:
case SIOCSIFNETMASK:
case SIOCGIFMEM:
case SIOCSIFMEM:
case SIOCGIFDSTADDR:
case SIOCSIFDSTADDR:
return -EINVAL;
default:
return -EINVAL;
} }
return put_user(amount, (int *)arg); return rc;
} }
static struct net_proto_family atalk_family_ops = { static struct net_proto_family atalk_family_ops = {
...@@ -1955,7 +1977,7 @@ struct packet_type ppptalk_packet_type = { ...@@ -1955,7 +1977,7 @@ struct packet_type ppptalk_packet_type = {
.func = atalk_rcv, .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 symbols for use by drivers when AppleTalk is a module */
EXPORT_SYMBOL(aarp_send_ddp); EXPORT_SYMBOL(aarp_send_ddp);
...@@ -2023,4 +2045,3 @@ static void __exit atalk_exit(void) ...@@ -2023,4 +2045,3 @@ static void __exit atalk_exit(void)
} }
module_exit(atalk_exit); module_exit(atalk_exit);
#endif /* MODULE */ #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