Commit 060de20e authored by Linus Torvalds's avatar Linus Torvalds
parents b7c84c6a 2c4ee8f9
This diff is collapsed.
This diff is collapsed.
...@@ -1109,8 +1109,7 @@ struct net_device * __init ltpc_probe(void) ...@@ -1109,8 +1109,7 @@ struct net_device * __init ltpc_probe(void)
inb_p(io+1); inb_p(io+1);
inb_p(io+3); inb_p(io+3);
set_current_state(TASK_UNINTERRUPTIBLE); msleep(20);
schedule_timeout(2*HZ/100);
inb_p(io+0); inb_p(io+0);
inb_p(io+2); inb_p(io+2);
...@@ -1120,8 +1119,7 @@ struct net_device * __init ltpc_probe(void) ...@@ -1120,8 +1119,7 @@ struct net_device * __init ltpc_probe(void)
inb_p(io+5); /* enable dma */ inb_p(io+5); /* enable dma */
inb_p(io+6); /* tri-state interrupt line */ inb_p(io+6); /* tri-state interrupt line */
set_current_state(TASK_UNINTERRUPTIBLE); ssleep(1);
schedule_timeout(HZ);
/* now, figure out which dma channel we're using, unless it's /* now, figure out which dma channel we're using, unless it's
already been specified */ already been specified */
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
struct divert_blk; struct divert_blk;
struct vlan_group; struct vlan_group;
struct ethtool_ops; struct ethtool_ops;
struct netpoll; struct netpoll_info;
/* source back-compat hooks */ /* source back-compat hooks */
#define SET_ETHTOOL_OPS(netdev,ops) \ #define SET_ETHTOOL_OPS(netdev,ops) \
( (netdev)->ethtool_ops = (ops) ) ( (netdev)->ethtool_ops = (ops) )
...@@ -468,7 +468,7 @@ struct net_device ...@@ -468,7 +468,7 @@ struct net_device
unsigned char *haddr); unsigned char *haddr);
int (*neigh_setup)(struct net_device *dev, struct neigh_parms *); int (*neigh_setup)(struct net_device *dev, struct neigh_parms *);
#ifdef CONFIG_NETPOLL #ifdef CONFIG_NETPOLL
struct netpoll *np; struct netpoll_info *npinfo;
#endif #endif
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
void (*poll_controller)(struct net_device *dev); void (*poll_controller)(struct net_device *dev);
......
...@@ -18,7 +18,6 @@ struct clusterip_config; ...@@ -18,7 +18,6 @@ struct clusterip_config;
struct ipt_clusterip_tgt_info { struct ipt_clusterip_tgt_info {
u_int32_t flags; u_int32_t flags;
struct clusterip_config *config;
/* only relevant for new ones */ /* only relevant for new ones */
u_int8_t clustermac[6]; u_int8_t clustermac[6];
...@@ -27,6 +26,8 @@ struct ipt_clusterip_tgt_info { ...@@ -27,6 +26,8 @@ struct ipt_clusterip_tgt_info {
u_int16_t local_nodes[CLUSTERIP_MAX_NODES]; u_int16_t local_nodes[CLUSTERIP_MAX_NODES];
enum clusterip_hashmode hash_mode; enum clusterip_hashmode hash_mode;
u_int32_t hash_initval; u_int32_t hash_initval;
struct clusterip_config *config;
}; };
#endif /*_IPT_CLUSTERIP_H_target*/ #endif /*_IPT_CLUSTERIP_H_target*/
...@@ -16,14 +16,19 @@ struct netpoll; ...@@ -16,14 +16,19 @@ struct netpoll;
struct netpoll { struct netpoll {
struct net_device *dev; struct net_device *dev;
char dev_name[16], *name; char dev_name[16], *name;
int rx_flags;
void (*rx_hook)(struct netpoll *, int, char *, int); void (*rx_hook)(struct netpoll *, int, char *, int);
void (*drop)(struct sk_buff *skb); void (*drop)(struct sk_buff *skb);
u32 local_ip, remote_ip; u32 local_ip, remote_ip;
u16 local_port, remote_port; u16 local_port, remote_port;
unsigned char local_mac[6], remote_mac[6]; unsigned char local_mac[6], remote_mac[6];
};
struct netpoll_info {
spinlock_t poll_lock; spinlock_t poll_lock;
int poll_owner; int poll_owner;
int rx_flags;
spinlock_t rx_lock;
struct netpoll *rx_np; /* netpoll that registered an rx_hook */
}; };
void netpoll_poll(struct netpoll *np); void netpoll_poll(struct netpoll *np);
...@@ -39,22 +44,35 @@ void netpoll_queue(struct sk_buff *skb); ...@@ -39,22 +44,35 @@ void netpoll_queue(struct sk_buff *skb);
#ifdef CONFIG_NETPOLL #ifdef CONFIG_NETPOLL
static inline int netpoll_rx(struct sk_buff *skb) static inline int netpoll_rx(struct sk_buff *skb)
{ {
return skb->dev->np && skb->dev->np->rx_flags && __netpoll_rx(skb); struct netpoll_info *npinfo = skb->dev->npinfo;
unsigned long flags;
int ret = 0;
if (!npinfo || (!npinfo->rx_np && !npinfo->rx_flags))
return 0;
spin_lock_irqsave(&npinfo->rx_lock, flags);
/* check rx_flags again with the lock held */
if (npinfo->rx_flags && __netpoll_rx(skb))
ret = 1;
spin_unlock_irqrestore(&npinfo->rx_lock, flags);
return ret;
} }
static inline void netpoll_poll_lock(struct net_device *dev) static inline void netpoll_poll_lock(struct net_device *dev)
{ {
if (dev->np) { if (dev->npinfo) {
spin_lock(&dev->np->poll_lock); spin_lock(&dev->npinfo->poll_lock);
dev->np->poll_owner = smp_processor_id(); dev->npinfo->poll_owner = smp_processor_id();
} }
} }
static inline void netpoll_poll_unlock(struct net_device *dev) static inline void netpoll_poll_unlock(struct net_device *dev)
{ {
if (dev->np) { if (dev->npinfo) {
spin_unlock(&dev->np->poll_lock); dev->npinfo->poll_owner = -1;
dev->np->poll_owner = -1; spin_unlock(&dev->npinfo->poll_lock);
} }
} }
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
* History * History
* mar/20/00 Daniela Squassoni Disabling/enabling of facilities * mar/20/00 Daniela Squassoni Disabling/enabling of facilities
* negotiation. * negotiation.
* apr/02/05 Shaun Pereira Selective sub address matching with
* call user data
*/ */
#ifndef X25_KERNEL_H #ifndef X25_KERNEL_H
...@@ -16,6 +18,9 @@ ...@@ -16,6 +18,9 @@
#define SIOCX25GCALLUSERDATA (SIOCPROTOPRIVATE + 4) #define SIOCX25GCALLUSERDATA (SIOCPROTOPRIVATE + 4)
#define SIOCX25SCALLUSERDATA (SIOCPROTOPRIVATE + 5) #define SIOCX25SCALLUSERDATA (SIOCPROTOPRIVATE + 5)
#define SIOCX25GCAUSEDIAG (SIOCPROTOPRIVATE + 6) #define SIOCX25GCAUSEDIAG (SIOCPROTOPRIVATE + 6)
#define SIOCX25SCUDMATCHLEN (SIOCPROTOPRIVATE + 7)
#define SIOCX25CALLACCPTAPPRV (SIOCPROTOPRIVATE + 8)
#define SIOCX25SENDCALLACCPT (SIOCPROTOPRIVATE + 9)
/* /*
* Values for {get,set}sockopt. * Values for {get,set}sockopt.
...@@ -109,4 +114,11 @@ struct x25_causediag { ...@@ -109,4 +114,11 @@ struct x25_causediag {
unsigned char diagnostic; unsigned char diagnostic;
}; };
/*
* Further optional call user data match length selection
*/
struct x25_subaddr {
unsigned int cudmatchlength;
};
#endif #endif
...@@ -79,6 +79,8 @@ enum { ...@@ -79,6 +79,8 @@ enum {
#define X25_DEFAULT_PACKET_SIZE X25_PS128 /* Default Packet Size */ #define X25_DEFAULT_PACKET_SIZE X25_PS128 /* Default Packet Size */
#define X25_DEFAULT_THROUGHPUT 0x0A /* Deafult Throughput */ #define X25_DEFAULT_THROUGHPUT 0x0A /* Deafult Throughput */
#define X25_DEFAULT_REVERSE 0x00 /* Default Reverse Charging */ #define X25_DEFAULT_REVERSE 0x00 /* Default Reverse Charging */
#define X25_DENY_ACCPT_APPRV 0x01 /* Default value */
#define X25_ALLOW_ACCPT_APPRV 0x00 /* Control enabled */
#define X25_SMODULUS 8 #define X25_SMODULUS 8
#define X25_EMODULUS 128 #define X25_EMODULUS 128
...@@ -94,7 +96,7 @@ enum { ...@@ -94,7 +96,7 @@ enum {
#define X25_FAC_CLASS_C 0x80 #define X25_FAC_CLASS_C 0x80
#define X25_FAC_CLASS_D 0xC0 #define X25_FAC_CLASS_D 0xC0
#define X25_FAC_REVERSE 0x01 #define X25_FAC_REVERSE 0x01 /* also fast select */
#define X25_FAC_THROUGHPUT 0x02 #define X25_FAC_THROUGHPUT 0x02
#define X25_FAC_PACKET_SIZE 0x42 #define X25_FAC_PACKET_SIZE 0x42
#define X25_FAC_WINDOW_SIZE 0x43 #define X25_FAC_WINDOW_SIZE 0x43
...@@ -134,8 +136,8 @@ struct x25_sock { ...@@ -134,8 +136,8 @@ struct x25_sock {
struct sock sk; struct sock sk;
struct x25_address source_addr, dest_addr; struct x25_address source_addr, dest_addr;
struct x25_neigh *neighbour; struct x25_neigh *neighbour;
unsigned int lci; unsigned int lci, cudmatchlength;
unsigned char state, condition, qbitincl, intflag; unsigned char state, condition, qbitincl, intflag, accptapprv;
unsigned short vs, vr, va, vl; unsigned short vs, vr, va, vl;
unsigned long t2, t21, t22, t23; unsigned long t2, t21, t22, t23;
unsigned short fraglen; unsigned short fraglen;
...@@ -242,7 +244,6 @@ extern int x25_validate_nr(struct sock *, unsigned short); ...@@ -242,7 +244,6 @@ extern int x25_validate_nr(struct sock *, unsigned short);
extern void x25_write_internal(struct sock *, int); extern void x25_write_internal(struct sock *, int);
extern int x25_decode(struct sock *, struct sk_buff *, int *, int *, int *, int *, int *); extern int x25_decode(struct sock *, struct sk_buff *, int *, int *, int *, int *, int *);
extern void x25_disconnect(struct sock *, int, unsigned char, unsigned char); extern void x25_disconnect(struct sock *, int, unsigned char, unsigned char);
extern int x25_check_calluserdata(struct x25_calluserdata *,struct x25_calluserdata *);
/* x25_timer.c */ /* x25_timer.c */
extern void x25_start_heartbeat(struct sock *); extern void x25_start_heartbeat(struct sock *);
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <net/datalink.h> #include <net/datalink.h>
#include <net/psnap.h> #include <net/psnap.h>
#include <linux/atalk.h> #include <linux/atalk.h>
#include <linux/delay.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
...@@ -462,8 +463,7 @@ void aarp_probe_network(struct atalk_iface *atif) ...@@ -462,8 +463,7 @@ void aarp_probe_network(struct atalk_iface *atif)
aarp_send_probe(atif->dev, &atif->address); aarp_send_probe(atif->dev, &atif->address);
/* Defer 1/10th */ /* Defer 1/10th */
current->state = TASK_INTERRUPTIBLE; msleep(100);
schedule_timeout(HZ / 10);
if (atif->status & ATIF_PROBE_FAIL) if (atif->status & ATIF_PROBE_FAIL)
break; break;
...@@ -510,9 +510,8 @@ int aarp_proxy_probe_network(struct atalk_iface *atif, struct atalk_addr *sa) ...@@ -510,9 +510,8 @@ int aarp_proxy_probe_network(struct atalk_iface *atif, struct atalk_addr *sa)
aarp_send_probe(atif->dev, sa); aarp_send_probe(atif->dev, sa);
/* Defer 1/10th */ /* Defer 1/10th */
current->state = TASK_INTERRUPTIBLE;
write_unlock_bh(&aarp_lock); write_unlock_bh(&aarp_lock);
schedule_timeout(HZ / 10); msleep(100);
write_lock_bh(&aarp_lock); write_lock_bh(&aarp_lock);
if (entry->status & ATIF_PROBE_FAIL) if (entry->status & ATIF_PROBE_FAIL)
......
...@@ -859,8 +859,7 @@ static int translate_table(struct ebt_replace *repl, ...@@ -859,8 +859,7 @@ static int translate_table(struct ebt_replace *repl,
if (repl->valid_hooks & (1 << i)) if (repl->valid_hooks & (1 << i))
if (check_chainloops(newinfo->hook_entry[i], if (check_chainloops(newinfo->hook_entry[i],
cl_s, udc_cnt, i, newinfo->entries)) { cl_s, udc_cnt, i, newinfo->entries)) {
if (cl_s) vfree(cl_s);
vfree(cl_s);
return -EINVAL; return -EINVAL;
} }
...@@ -883,8 +882,7 @@ static int translate_table(struct ebt_replace *repl, ...@@ -883,8 +882,7 @@ static int translate_table(struct ebt_replace *repl,
EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
ebt_cleanup_entry, &i); ebt_cleanup_entry, &i);
} }
if (cl_s) vfree(cl_s);
vfree(cl_s);
return ret; return ret;
} }
...@@ -1030,8 +1028,7 @@ static int do_replace(void __user *user, unsigned int len) ...@@ -1030,8 +1028,7 @@ static int do_replace(void __user *user, unsigned int len)
} }
vfree(table); vfree(table);
if (counterstmp) vfree(counterstmp);
vfree(counterstmp);
return ret; return ret;
free_unlock: free_unlock:
...@@ -1040,8 +1037,7 @@ static int do_replace(void __user *user, unsigned int len) ...@@ -1040,8 +1037,7 @@ static int do_replace(void __user *user, unsigned int len)
EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
ebt_cleanup_entry, NULL); ebt_cleanup_entry, NULL);
free_counterstmp: free_counterstmp:
if (counterstmp) vfree(counterstmp);
vfree(counterstmp);
/* can be initialized in translate_table() */ /* can be initialized in translate_table() */
if (newinfo->chainstack) { if (newinfo->chainstack) {
for (i = 0; i < num_possible_cpus(); i++) for (i = 0; i < num_possible_cpus(); i++)
...@@ -1049,11 +1045,9 @@ static int do_replace(void __user *user, unsigned int len) ...@@ -1049,11 +1045,9 @@ static int do_replace(void __user *user, unsigned int len)
vfree(newinfo->chainstack); vfree(newinfo->chainstack);
} }
free_entries: free_entries:
if (newinfo->entries) vfree(newinfo->entries);
vfree(newinfo->entries);
free_newinfo: free_newinfo:
if (newinfo) vfree(newinfo);
vfree(newinfo);
return ret; return ret;
} }
...@@ -1213,8 +1207,7 @@ void ebt_unregister_table(struct ebt_table *table) ...@@ -1213,8 +1207,7 @@ void ebt_unregister_table(struct ebt_table *table)
down(&ebt_mutex); down(&ebt_mutex);
LIST_DELETE(&ebt_tables, table); LIST_DELETE(&ebt_tables, table);
up(&ebt_mutex); up(&ebt_mutex);
if (table->private->entries) vfree(table->private->entries);
vfree(table->private->entries);
if (table->private->chainstack) { if (table->private->chainstack) {
for (i = 0; i < num_possible_cpus(); i++) for (i = 0; i < num_possible_cpus(); i++)
vfree(table->private->chainstack[i]); vfree(table->private->chainstack[i]);
......
...@@ -130,19 +130,20 @@ static int checksum_udp(struct sk_buff *skb, struct udphdr *uh, ...@@ -130,19 +130,20 @@ static int checksum_udp(struct sk_buff *skb, struct udphdr *uh,
*/ */
static void poll_napi(struct netpoll *np) static void poll_napi(struct netpoll *np)
{ {
struct netpoll_info *npinfo = np->dev->npinfo;
int budget = 16; int budget = 16;
if (test_bit(__LINK_STATE_RX_SCHED, &np->dev->state) && if (test_bit(__LINK_STATE_RX_SCHED, &np->dev->state) &&
np->poll_owner != smp_processor_id() && npinfo->poll_owner != smp_processor_id() &&
spin_trylock(&np->poll_lock)) { spin_trylock(&npinfo->poll_lock)) {
np->rx_flags |= NETPOLL_RX_DROP; npinfo->rx_flags |= NETPOLL_RX_DROP;
atomic_inc(&trapped); atomic_inc(&trapped);
np->dev->poll(np->dev, &budget); np->dev->poll(np->dev, &budget);
atomic_dec(&trapped); atomic_dec(&trapped);
np->rx_flags &= ~NETPOLL_RX_DROP; npinfo->rx_flags &= ~NETPOLL_RX_DROP;
spin_unlock(&np->poll_lock); spin_unlock(&npinfo->poll_lock);
} }
} }
...@@ -245,6 +246,7 @@ static struct sk_buff * find_skb(struct netpoll *np, int len, int reserve) ...@@ -245,6 +246,7 @@ static struct sk_buff * find_skb(struct netpoll *np, int len, int reserve)
static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
{ {
int status; int status;
struct netpoll_info *npinfo;
repeat: repeat:
if(!np || !np->dev || !netif_running(np->dev)) { if(!np || !np->dev || !netif_running(np->dev)) {
...@@ -253,8 +255,9 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) ...@@ -253,8 +255,9 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
} }
/* avoid recursion */ /* avoid recursion */
if(np->poll_owner == smp_processor_id() || npinfo = np->dev->npinfo;
np->dev->xmit_lock_owner == smp_processor_id()) { if (npinfo->poll_owner == smp_processor_id() ||
np->dev->xmit_lock_owner == smp_processor_id()) {
if (np->drop) if (np->drop)
np->drop(skb); np->drop(skb);
else else
...@@ -341,14 +344,22 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len) ...@@ -341,14 +344,22 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
static void arp_reply(struct sk_buff *skb) static void arp_reply(struct sk_buff *skb)
{ {
struct netpoll_info *npinfo = skb->dev->npinfo;
struct arphdr *arp; struct arphdr *arp;
unsigned char *arp_ptr; unsigned char *arp_ptr;
int size, type = ARPOP_REPLY, ptype = ETH_P_ARP; int size, type = ARPOP_REPLY, ptype = ETH_P_ARP;
u32 sip, tip; u32 sip, tip;
unsigned long flags;
struct sk_buff *send_skb; struct sk_buff *send_skb;
struct netpoll *np = skb->dev->np; struct netpoll *np = NULL;
spin_lock_irqsave(&npinfo->rx_lock, flags);
if (npinfo->rx_np && npinfo->rx_np->dev == skb->dev)
np = npinfo->rx_np;
spin_unlock_irqrestore(&npinfo->rx_lock, flags);
if (!np) return; if (!np)
return;
/* No arp on this interface */ /* No arp on this interface */
if (skb->dev->flags & IFF_NOARP) if (skb->dev->flags & IFF_NOARP)
...@@ -429,9 +440,9 @@ int __netpoll_rx(struct sk_buff *skb) ...@@ -429,9 +440,9 @@ int __netpoll_rx(struct sk_buff *skb)
int proto, len, ulen; int proto, len, ulen;
struct iphdr *iph; struct iphdr *iph;
struct udphdr *uh; struct udphdr *uh;
struct netpoll *np = skb->dev->np; struct netpoll *np = skb->dev->npinfo->rx_np;
if (!np->rx_hook) if (!np)
goto out; goto out;
if (skb->dev->type != ARPHRD_ETHER) if (skb->dev->type != ARPHRD_ETHER)
goto out; goto out;
...@@ -611,9 +622,8 @@ int netpoll_setup(struct netpoll *np) ...@@ -611,9 +622,8 @@ int netpoll_setup(struct netpoll *np)
{ {
struct net_device *ndev = NULL; struct net_device *ndev = NULL;
struct in_device *in_dev; struct in_device *in_dev;
struct netpoll_info *npinfo;
np->poll_lock = SPIN_LOCK_UNLOCKED; unsigned long flags;
np->poll_owner = -1;
if (np->dev_name) if (np->dev_name)
ndev = dev_get_by_name(np->dev_name); ndev = dev_get_by_name(np->dev_name);
...@@ -624,7 +634,17 @@ int netpoll_setup(struct netpoll *np) ...@@ -624,7 +634,17 @@ int netpoll_setup(struct netpoll *np)
} }
np->dev = ndev; np->dev = ndev;
ndev->np = np; if (!ndev->npinfo) {
npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL);
if (!npinfo)
goto release;
npinfo->rx_np = NULL;
npinfo->poll_lock = SPIN_LOCK_UNLOCKED;
npinfo->poll_owner = -1;
npinfo->rx_lock = SPIN_LOCK_UNLOCKED;
} else
npinfo = ndev->npinfo;
if (!ndev->poll_controller) { if (!ndev->poll_controller) {
printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n", printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n",
...@@ -692,13 +712,20 @@ int netpoll_setup(struct netpoll *np) ...@@ -692,13 +712,20 @@ int netpoll_setup(struct netpoll *np)
np->name, HIPQUAD(np->local_ip)); np->name, HIPQUAD(np->local_ip));
} }
if(np->rx_hook) if (np->rx_hook) {
np->rx_flags = NETPOLL_RX_ENABLED; spin_lock_irqsave(&npinfo->rx_lock, flags);
npinfo->rx_flags |= NETPOLL_RX_ENABLED;
npinfo->rx_np = np;
spin_unlock_irqrestore(&npinfo->rx_lock, flags);
}
/* last thing to do is link it to the net device structure */
ndev->npinfo = npinfo;
return 0; return 0;
release: release:
ndev->np = NULL; if (!ndev->npinfo)
kfree(npinfo);
np->dev = NULL; np->dev = NULL;
dev_put(ndev); dev_put(ndev);
return -1; return -1;
...@@ -706,9 +733,20 @@ int netpoll_setup(struct netpoll *np) ...@@ -706,9 +733,20 @@ int netpoll_setup(struct netpoll *np)
void netpoll_cleanup(struct netpoll *np) void netpoll_cleanup(struct netpoll *np)
{ {
if (np->dev) struct netpoll_info *npinfo;
np->dev->np = NULL; unsigned long flags;
dev_put(np->dev);
if (np->dev) {
npinfo = np->dev->npinfo;
if (npinfo && npinfo->rx_np == np) {
spin_lock_irqsave(&npinfo->rx_lock, flags);
npinfo->rx_np = NULL;
npinfo->rx_flags &= ~NETPOLL_RX_ENABLED;
spin_unlock_irqrestore(&npinfo->rx_lock, flags);
}
dev_put(np->dev);
}
np->dev = NULL; np->dev = NULL;
} }
......
...@@ -339,7 +339,7 @@ target(struct sk_buff **pskb, ...@@ -339,7 +339,7 @@ target(struct sk_buff **pskb,
* error messages (RELATED) and information requests (see below) */ * error messages (RELATED) and information requests (see below) */
if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP
&& (ctinfo == IP_CT_RELATED && (ctinfo == IP_CT_RELATED
|| ctinfo == IP_CT_IS_REPLY+IP_CT_IS_REPLY)) || ctinfo == IP_CT_RELATED+IP_CT_IS_REPLY))
return IPT_CONTINUE; return IPT_CONTINUE;
/* ip_conntrack_icmp guarantees us that we only have ICMP_ECHO, /* ip_conntrack_icmp guarantees us that we only have ICMP_ECHO,
......
...@@ -1767,7 +1767,7 @@ static inline int ip_mkroute_input_def(struct sk_buff *skb, ...@@ -1767,7 +1767,7 @@ static inline int ip_mkroute_input_def(struct sk_buff *skb,
struct in_device *in_dev, struct in_device *in_dev,
u32 daddr, u32 saddr, u32 tos) u32 daddr, u32 saddr, u32 tos)
{ {
struct rtable* rth; struct rtable* rth = NULL;
int err; int err;
unsigned hash; unsigned hash;
...@@ -1794,7 +1794,7 @@ static inline int ip_mkroute_input(struct sk_buff *skb, ...@@ -1794,7 +1794,7 @@ static inline int ip_mkroute_input(struct sk_buff *skb,
u32 daddr, u32 saddr, u32 tos) u32 daddr, u32 saddr, u32 tos)
{ {
#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
struct rtable* rth; struct rtable* rth = NULL;
unsigned char hop, hopcount, lasthop; unsigned char hop, hopcount, lasthop;
int err = -EINVAL; int err = -EINVAL;
unsigned int hash; unsigned int hash;
...@@ -2239,7 +2239,7 @@ static inline int ip_mkroute_output_def(struct rtable **rp, ...@@ -2239,7 +2239,7 @@ static inline int ip_mkroute_output_def(struct rtable **rp,
struct net_device *dev_out, struct net_device *dev_out,
unsigned flags) unsigned flags)
{ {
struct rtable *rth; struct rtable *rth = NULL;
int err = __mkroute_output(&rth, res, fl, oldflp, dev_out, flags); int err = __mkroute_output(&rth, res, fl, oldflp, dev_out, flags);
unsigned hash; unsigned hash;
if (err == 0) { if (err == 0) {
...@@ -2267,7 +2267,7 @@ static inline int ip_mkroute_output(struct rtable** rp, ...@@ -2267,7 +2267,7 @@ static inline int ip_mkroute_output(struct rtable** rp,
unsigned char hop; unsigned char hop;
unsigned hash; unsigned hash;
int err = -EINVAL; int err = -EINVAL;
struct rtable *rth; struct rtable *rth = NULL;
if (res->fi && res->fi->fib_nhs > 1) { if (res->fi && res->fi->fib_nhs > 1) {
unsigned char hopcount = res->fi->fib_nhs; unsigned char hopcount = res->fi->fib_nhs;
......
...@@ -383,9 +383,8 @@ int sock_map_fd(struct socket *sock) ...@@ -383,9 +383,8 @@ int sock_map_fd(struct socket *sock)
goto out; goto out;
} }
sprintf(name, "[%lu]", SOCK_INODE(sock)->i_ino); this.len = sprintf(name, "[%lu]", SOCK_INODE(sock)->i_ino);
this.name = name; this.name = name;
this.len = strlen(name);
this.hash = SOCK_INODE(sock)->i_ino; this.hash = SOCK_INODE(sock)->i_ino;
file->f_dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this); file->f_dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this);
......
...@@ -29,6 +29,10 @@ ...@@ -29,6 +29,10 @@
* 2000-11-14 Henner Eisen Closing datalink from NETDEV_GOING_DOWN * 2000-11-14 Henner Eisen Closing datalink from NETDEV_GOING_DOWN
* 2002-10-06 Arnaldo C. Melo Get rid of cli/sti, move proc stuff to * 2002-10-06 Arnaldo C. Melo Get rid of cli/sti, move proc stuff to
* x25_proc.c, using seq_file * x25_proc.c, using seq_file
* 2005-04-02 Shaun Pereira Selective sub address matching
* with call user data
* 2005-04-15 Shaun Pereira Fast select with no restriction on
* response
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -219,7 +223,8 @@ static void x25_insert_socket(struct sock *sk) ...@@ -219,7 +223,8 @@ static void x25_insert_socket(struct sock *sk)
* Note: if a listening socket has cud set it must only get calls * Note: if a listening socket has cud set it must only get calls
* with matching cud. * with matching cud.
*/ */
static struct sock *x25_find_listener(struct x25_address *addr, struct x25_calluserdata *calluserdata) static struct sock *x25_find_listener(struct x25_address *addr,
struct sk_buff *skb)
{ {
struct sock *s; struct sock *s;
struct sock *next_best; struct sock *next_best;
...@@ -230,22 +235,23 @@ static struct sock *x25_find_listener(struct x25_address *addr, struct x25_callu ...@@ -230,22 +235,23 @@ static struct sock *x25_find_listener(struct x25_address *addr, struct x25_callu
sk_for_each(s, node, &x25_list) sk_for_each(s, node, &x25_list)
if ((!strcmp(addr->x25_addr, if ((!strcmp(addr->x25_addr,
x25_sk(s)->source_addr.x25_addr) || x25_sk(s)->source_addr.x25_addr) ||
!strcmp(addr->x25_addr, !strcmp(addr->x25_addr,
null_x25_address.x25_addr)) && null_x25_address.x25_addr)) &&
s->sk_state == TCP_LISTEN) { s->sk_state == TCP_LISTEN) {
/* /*
* Found a listening socket, now check the incoming * Found a listening socket, now check the incoming
* call user data vs this sockets call user data * call user data vs this sockets call user data
*/ */
if (x25_check_calluserdata(&x25_sk(s)->calluserdata, calluserdata)) { if(skb->len > 0 && x25_sk(s)->cudmatchlength > 0) {
sock_hold(s); if((memcmp(x25_sk(s)->calluserdata.cuddata,
goto found; skb->data,
} x25_sk(s)->cudmatchlength)) == 0) {
if (x25_sk(s)->calluserdata.cudlength == 0) { sock_hold(s);
goto found;
}
} else
next_best = s; next_best = s;
}
} }
if (next_best) { if (next_best) {
s = next_best; s = next_best;
...@@ -497,6 +503,9 @@ static int x25_create(struct socket *sock, int protocol) ...@@ -497,6 +503,9 @@ static int x25_create(struct socket *sock, int protocol)
x25->t23 = sysctl_x25_clear_request_timeout; x25->t23 = sysctl_x25_clear_request_timeout;
x25->t2 = sysctl_x25_ack_holdback_timeout; x25->t2 = sysctl_x25_ack_holdback_timeout;
x25->state = X25_STATE_0; x25->state = X25_STATE_0;
x25->cudmatchlength = 0;
x25->accptapprv = X25_DENY_ACCPT_APPRV; /* normally no cud */
/* on call accept */
x25->facilities.winsize_in = X25_DEFAULT_WINDOW_SIZE; x25->facilities.winsize_in = X25_DEFAULT_WINDOW_SIZE;
x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE; x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE;
...@@ -545,6 +554,8 @@ static struct sock *x25_make_new(struct sock *osk) ...@@ -545,6 +554,8 @@ static struct sock *x25_make_new(struct sock *osk)
x25->t2 = ox25->t2; x25->t2 = ox25->t2;
x25->facilities = ox25->facilities; x25->facilities = ox25->facilities;
x25->qbitincl = ox25->qbitincl; x25->qbitincl = ox25->qbitincl;
x25->cudmatchlength = ox25->cudmatchlength;
x25->accptapprv = ox25->accptapprv;
x25_init_timers(sk); x25_init_timers(sk);
out: out:
...@@ -822,7 +833,6 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, ...@@ -822,7 +833,6 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
struct x25_sock *makex25; struct x25_sock *makex25;
struct x25_address source_addr, dest_addr; struct x25_address source_addr, dest_addr;
struct x25_facilities facilities; struct x25_facilities facilities;
struct x25_calluserdata calluserdata;
int len, rc; int len, rc;
/* /*
...@@ -844,20 +854,11 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, ...@@ -844,20 +854,11 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
len = skb->data[0] + 1; len = skb->data[0] + 1;
skb_pull(skb,len); skb_pull(skb,len);
/*
* Incoming Call User Data.
*/
if (skb->len >= 0) {
memcpy(calluserdata.cuddata, skb->data, skb->len);
calluserdata.cudlength = skb->len;
}
skb_push(skb,len);
/* /*
* Find a listener for the particular address/cud pair. * Find a listener for the particular address/cud pair.
*/ */
sk = x25_find_listener(&source_addr,&calluserdata); sk = x25_find_listener(&source_addr,skb);
skb_push(skb,len);
/* /*
* We can't accept the Call Request. * We can't accept the Call Request.
...@@ -900,11 +901,23 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, ...@@ -900,11 +901,23 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
makex25->neighbour = nb; makex25->neighbour = nb;
makex25->facilities = facilities; makex25->facilities = facilities;
makex25->vc_facil_mask = x25_sk(sk)->vc_facil_mask; makex25->vc_facil_mask = x25_sk(sk)->vc_facil_mask;
makex25->calluserdata = calluserdata; /* ensure no reverse facil on accept */
makex25->vc_facil_mask &= ~X25_MASK_REVERSE;
x25_write_internal(make, X25_CALL_ACCEPTED); makex25->cudmatchlength = x25_sk(sk)->cudmatchlength;
/* Normally all calls are accepted immediatly */
if(makex25->accptapprv & X25_DENY_ACCPT_APPRV) {
x25_write_internal(make, X25_CALL_ACCEPTED);
makex25->state = X25_STATE_3;
}
makex25->state = X25_STATE_3; /*
* Incoming Call User Data.
*/
if (skb->len >= 0) {
memcpy(makex25->calluserdata.cuddata, skb->data, skb->len);
makex25->calluserdata.cudlength = skb->len;
}
sk->sk_ack_backlog++; sk->sk_ack_backlog++;
...@@ -1288,7 +1301,8 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -1288,7 +1301,8 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
if (facilities.throughput < 0x03 || if (facilities.throughput < 0x03 ||
facilities.throughput > 0xDD) facilities.throughput > 0xDD)
break; break;
if (facilities.reverse && facilities.reverse != 1) if (facilities.reverse &&
(facilities.reverse | 0x81)!= 0x81)
break; break;
x25->facilities = facilities; x25->facilities = facilities;
rc = 0; rc = 0;
...@@ -1325,6 +1339,44 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -1325,6 +1339,44 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
break; break;
} }
case SIOCX25SCUDMATCHLEN: {
struct x25_subaddr sub_addr;
rc = -EINVAL;
if(sk->sk_state != TCP_CLOSE)
break;
rc = -EFAULT;
if (copy_from_user(&sub_addr, argp,
sizeof(sub_addr)))
break;
rc = -EINVAL;
if(sub_addr.cudmatchlength > X25_MAX_CUD_LEN)
break;
x25->cudmatchlength = sub_addr.cudmatchlength;
rc = 0;
break;
}
case SIOCX25CALLACCPTAPPRV: {
rc = -EINVAL;
if (sk->sk_state != TCP_CLOSE)
break;
x25->accptapprv = X25_ALLOW_ACCPT_APPRV;
rc = 0;
break;
}
case SIOCX25SENDCALLACCPT: {
rc = -EINVAL;
if (sk->sk_state != TCP_ESTABLISHED)
break;
if (x25->accptapprv) /* must call accptapprv above */
break;
x25_write_internal(sk, X25_CALL_ACCEPTED);
x25->state = X25_STATE_3;
rc = 0;
break;
}
default: default:
rc = dev_ioctl(cmd, argp); rc = dev_ioctl(cmd, argp);
break; break;
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
* X.25 001 Split from x25_subr.c * X.25 001 Split from x25_subr.c
* mar/20/00 Daniela Squassoni Disabling/enabling of facilities * mar/20/00 Daniela Squassoni Disabling/enabling of facilities
* negotiation. * negotiation.
* apr/14/05 Shaun Pereira - Allow fast select with no restriction
* on response.
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -43,9 +45,31 @@ int x25_parse_facilities(struct sk_buff *skb, ...@@ -43,9 +45,31 @@ int x25_parse_facilities(struct sk_buff *skb,
case X25_FAC_CLASS_A: case X25_FAC_CLASS_A:
switch (*p) { switch (*p) {
case X25_FAC_REVERSE: case X25_FAC_REVERSE:
facilities->reverse = p[1] & 0x01; if((p[1] & 0x81) == 0x81) {
*vc_fac_mask |= X25_MASK_REVERSE; facilities->reverse = p[1] & 0x81;
break; *vc_fac_mask |= X25_MASK_REVERSE;
break;
}
if((p[1] & 0x01) == 0x01) {
facilities->reverse = p[1] & 0x01;
*vc_fac_mask |= X25_MASK_REVERSE;
break;
}
if((p[1] & 0x80) == 0x80) {
facilities->reverse = p[1] & 0x80;
*vc_fac_mask |= X25_MASK_REVERSE;
break;
}
if(p[1] == 0x00) {
facilities->reverse
= X25_DEFAULT_REVERSE;
*vc_fac_mask |= X25_MASK_REVERSE;
break;
}
case X25_FAC_THROUGHPUT: case X25_FAC_THROUGHPUT:
facilities->throughput = p[1]; facilities->throughput = p[1];
*vc_fac_mask |= X25_MASK_THROUGHPUT; *vc_fac_mask |= X25_MASK_THROUGHPUT;
...@@ -122,7 +146,7 @@ int x25_create_facilities(unsigned char *buffer, ...@@ -122,7 +146,7 @@ int x25_create_facilities(unsigned char *buffer,
if (facilities->reverse && (facil_mask & X25_MASK_REVERSE)) { if (facilities->reverse && (facil_mask & X25_MASK_REVERSE)) {
*p++ = X25_FAC_REVERSE; *p++ = X25_FAC_REVERSE;
*p++ = !!facilities->reverse; *p++ = facilities->reverse;
} }
if (facilities->throughput && (facil_mask & X25_MASK_THROUGHPUT)) { if (facilities->throughput && (facil_mask & X25_MASK_THROUGHPUT)) {
...@@ -171,7 +195,7 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, ...@@ -171,7 +195,7 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk,
/* /*
* They want reverse charging, we won't accept it. * They want reverse charging, we won't accept it.
*/ */
if (theirs.reverse && ours->reverse) { if ((theirs.reverse & 0x01 ) && (ours->reverse & 0x01)) {
SOCK_DEBUG(sk, "X.25: rejecting reverse charging request"); SOCK_DEBUG(sk, "X.25: rejecting reverse charging request");
return -1; return -1;
} }
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
* mar/20/00 Daniela Squassoni Disabling/enabling of facilities * mar/20/00 Daniela Squassoni Disabling/enabling of facilities
* negotiation. * negotiation.
* jun/24/01 Arnaldo C. Melo use skb_queue_purge, cleanups * jun/24/01 Arnaldo C. Melo use skb_queue_purge, cleanups
* apr/04/15 Shaun Pereira Fast select with no
* restriction on response.
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -127,8 +129,12 @@ void x25_write_internal(struct sock *sk, int frametype) ...@@ -127,8 +129,12 @@ void x25_write_internal(struct sock *sk, int frametype)
len += 1 + X25_ADDR_LEN + X25_MAX_FAC_LEN + len += 1 + X25_ADDR_LEN + X25_MAX_FAC_LEN +
X25_MAX_CUD_LEN; X25_MAX_CUD_LEN;
break; break;
case X25_CALL_ACCEPTED: case X25_CALL_ACCEPTED: /* fast sel with no restr on resp */
len += 1 + X25_MAX_FAC_LEN + X25_MAX_CUD_LEN; if(x25->facilities.reverse & 0x80) {
len += 1 + X25_MAX_FAC_LEN + X25_MAX_CUD_LEN;
} else {
len += 1 + X25_MAX_FAC_LEN;
}
break; break;
case X25_CLEAR_REQUEST: case X25_CLEAR_REQUEST:
case X25_RESET_REQUEST: case X25_RESET_REQUEST:
...@@ -203,9 +209,16 @@ void x25_write_internal(struct sock *sk, int frametype) ...@@ -203,9 +209,16 @@ void x25_write_internal(struct sock *sk, int frametype)
x25->vc_facil_mask); x25->vc_facil_mask);
dptr = skb_put(skb, len); dptr = skb_put(skb, len);
memcpy(dptr, facilities, len); memcpy(dptr, facilities, len);
dptr = skb_put(skb, x25->calluserdata.cudlength);
memcpy(dptr, x25->calluserdata.cuddata, /* fast select with no restriction on response
x25->calluserdata.cudlength); allows call user data. Userland must
ensure it is ours and not theirs */
if(x25->facilities.reverse & 0x80) {
dptr = skb_put(skb,
x25->calluserdata.cudlength);
memcpy(dptr, x25->calluserdata.cuddata,
x25->calluserdata.cudlength);
}
x25->calluserdata.cudlength = 0; x25->calluserdata.cudlength = 0;
break; break;
...@@ -354,21 +367,3 @@ void x25_check_rbuf(struct sock *sk) ...@@ -354,21 +367,3 @@ void x25_check_rbuf(struct sock *sk)
} }
} }
/*
* Compare 2 calluserdata structures, used to find correct listening sockets
* when call user data is used.
*/
int x25_check_calluserdata(struct x25_calluserdata *ours, struct x25_calluserdata *theirs)
{
int i;
if (ours->cudlength != theirs->cudlength)
return 0;
for (i=0;i<ours->cudlength;i++) {
if (ours->cuddata[i] != theirs->cuddata[i]) {
return 0;
}
}
return 1;
}
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