Commit 5c1f4cac authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6

parents c6a519d2 56e9b263
...@@ -31,16 +31,19 @@ ...@@ -31,16 +31,19 @@
#include <linux/connector.h> #include <linux/connector.h>
#include <linux/delay.h> #include <linux/delay.h>
static void cn_queue_wrapper(void *data) void cn_queue_wrapper(void *data)
{ {
struct cn_callback_entry *cbq = data; struct cn_callback_data *d = data;
cbq->cb->callback(cbq->cb->priv); d->callback(d->callback_priv);
cbq->destruct_data(cbq->ddata);
cbq->ddata = NULL; d->destruct_data(d->ddata);
d->ddata = NULL;
kfree(d->free);
} }
static struct cn_callback_entry *cn_queue_alloc_callback_entry(struct cn_callback *cb) static struct cn_callback_entry *cn_queue_alloc_callback_entry(char *name, struct cb_id *id, void (*callback)(void *))
{ {
struct cn_callback_entry *cbq; struct cn_callback_entry *cbq;
...@@ -50,8 +53,11 @@ static struct cn_callback_entry *cn_queue_alloc_callback_entry(struct cn_callbac ...@@ -50,8 +53,11 @@ static struct cn_callback_entry *cn_queue_alloc_callback_entry(struct cn_callbac
return NULL; return NULL;
} }
cbq->cb = cb; snprintf(cbq->id.name, sizeof(cbq->id.name), "%s", name);
INIT_WORK(&cbq->work, &cn_queue_wrapper, cbq); memcpy(&cbq->id.id, id, sizeof(struct cb_id));
cbq->data.callback = callback;
INIT_WORK(&cbq->work, &cn_queue_wrapper, &cbq->data);
return cbq; return cbq;
} }
...@@ -68,12 +74,12 @@ int cn_cb_equal(struct cb_id *i1, struct cb_id *i2) ...@@ -68,12 +74,12 @@ int cn_cb_equal(struct cb_id *i1, struct cb_id *i2)
return ((i1->idx == i2->idx) && (i1->val == i2->val)); return ((i1->idx == i2->idx) && (i1->val == i2->val));
} }
int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb) int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id, void (*callback)(void *))
{ {
struct cn_callback_entry *cbq, *__cbq; struct cn_callback_entry *cbq, *__cbq;
int found = 0; int found = 0;
cbq = cn_queue_alloc_callback_entry(cb); cbq = cn_queue_alloc_callback_entry(name, id, callback);
if (!cbq) if (!cbq)
return -ENOMEM; return -ENOMEM;
...@@ -82,7 +88,7 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb) ...@@ -82,7 +88,7 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb)
spin_lock_bh(&dev->queue_lock); spin_lock_bh(&dev->queue_lock);
list_for_each_entry(__cbq, &dev->queue_list, callback_entry) { list_for_each_entry(__cbq, &dev->queue_list, callback_entry) {
if (cn_cb_equal(&__cbq->cb->id, &cb->id)) { if (cn_cb_equal(&__cbq->id.id, id)) {
found = 1; found = 1;
break; break;
} }
...@@ -99,7 +105,7 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb) ...@@ -99,7 +105,7 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb)
cbq->nls = dev->nls; cbq->nls = dev->nls;
cbq->seq = 0; cbq->seq = 0;
cbq->group = cbq->cb->id.idx; cbq->group = cbq->id.id.idx;
return 0; return 0;
} }
...@@ -111,7 +117,7 @@ void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id) ...@@ -111,7 +117,7 @@ void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id)
spin_lock_bh(&dev->queue_lock); spin_lock_bh(&dev->queue_lock);
list_for_each_entry_safe(cbq, n, &dev->queue_list, callback_entry) { list_for_each_entry_safe(cbq, n, &dev->queue_list, callback_entry) {
if (cn_cb_equal(&cbq->cb->id, id)) { if (cn_cb_equal(&cbq->id.id, id)) {
list_del(&cbq->callback_entry); list_del(&cbq->callback_entry);
found = 1; found = 1;
break; break;
......
...@@ -84,7 +84,7 @@ int cn_netlink_send(struct cn_msg *msg, u32 __group, int gfp_mask) ...@@ -84,7 +84,7 @@ int cn_netlink_send(struct cn_msg *msg, u32 __group, int gfp_mask)
spin_lock_bh(&dev->cbdev->queue_lock); spin_lock_bh(&dev->cbdev->queue_lock);
list_for_each_entry(__cbq, &dev->cbdev->queue_list, list_for_each_entry(__cbq, &dev->cbdev->queue_list,
callback_entry) { callback_entry) {
if (cn_cb_equal(&__cbq->cb->id, &msg->id)) { if (cn_cb_equal(&__cbq->id.id, &msg->id)) {
found = 1; found = 1;
group = __cbq->group; group = __cbq->group;
} }
...@@ -127,42 +127,56 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v ...@@ -127,42 +127,56 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v
{ {
struct cn_callback_entry *__cbq; struct cn_callback_entry *__cbq;
struct cn_dev *dev = &cdev; struct cn_dev *dev = &cdev;
int found = 0; int err = -ENODEV;
spin_lock_bh(&dev->cbdev->queue_lock); spin_lock_bh(&dev->cbdev->queue_lock);
list_for_each_entry(__cbq, &dev->cbdev->queue_list, callback_entry) { list_for_each_entry(__cbq, &dev->cbdev->queue_list, callback_entry) {
if (cn_cb_equal(&__cbq->cb->id, &msg->id)) { if (cn_cb_equal(&__cbq->id.id, &msg->id)) {
/*
* Let's scream if there is some magic and the
* data will arrive asynchronously here.
* [i.e. netlink messages will be queued].
* After the first warning I will fix it
* quickly, but now I think it is
* impossible. --zbr (2004_04_27).
*/
if (likely(!test_bit(0, &__cbq->work.pending) && if (likely(!test_bit(0, &__cbq->work.pending) &&
__cbq->ddata == NULL)) { __cbq->data.ddata == NULL)) {
__cbq->cb->priv = msg; __cbq->data.callback_priv = msg;
__cbq->ddata = data; __cbq->data.ddata = data;
__cbq->destruct_data = destruct_data; __cbq->data.destruct_data = destruct_data;
if (queue_work(dev->cbdev->cn_queue, if (queue_work(dev->cbdev->cn_queue,
&__cbq->work)) &__cbq->work))
found = 1; err = 0;
} else { } else {
printk("%s: cbq->data=%p, " struct work_struct *w;
"work->pending=%08lx.\n", struct cn_callback_data *d;
__func__, __cbq->ddata,
__cbq->work.pending); w = kzalloc(sizeof(*w) + sizeof(*d), GFP_ATOMIC);
WARN_ON(1); if (w) {
d = (struct cn_callback_data *)(w+1);
d->callback_priv = msg;
d->callback = __cbq->data.callback;
d->ddata = data;
d->destruct_data = destruct_data;
d->free = w;
INIT_LIST_HEAD(&w->entry);
w->pending = 0;
w->func = &cn_queue_wrapper;
w->data = d;
init_timer(&w->timer);
if (queue_work(dev->cbdev->cn_queue, w))
err = 0;
else {
kfree(w);
err = -EINVAL;
}
} else
err = -ENOMEM;
} }
break; break;
} }
} }
spin_unlock_bh(&dev->cbdev->queue_lock); spin_unlock_bh(&dev->cbdev->queue_lock);
return found ? 0 : -ENODEV; return err;
} }
/* /*
...@@ -291,22 +305,10 @@ int cn_add_callback(struct cb_id *id, char *name, void (*callback)(void *)) ...@@ -291,22 +305,10 @@ int cn_add_callback(struct cb_id *id, char *name, void (*callback)(void *))
{ {
int err; int err;
struct cn_dev *dev = &cdev; struct cn_dev *dev = &cdev;
struct cn_callback *cb;
cb = kzalloc(sizeof(*cb), GFP_KERNEL);
if (!cb)
return -ENOMEM;
scnprintf(cb->name, sizeof(cb->name), "%s", name);
memcpy(&cb->id, id, sizeof(cb->id)); err = cn_queue_add_callback(dev->cbdev, name, id, callback);
cb->callback = callback; if (err)
err = cn_queue_add_callback(dev->cbdev, cb);
if (err) {
kfree(cb);
return err; return err;
}
cn_notify(id, 0); cn_notify(id, 0);
......
...@@ -104,12 +104,19 @@ struct cn_queue_dev { ...@@ -104,12 +104,19 @@ struct cn_queue_dev {
struct sock *nls; struct sock *nls;
}; };
struct cn_callback { struct cn_callback_id {
unsigned char name[CN_CBQ_NAMELEN]; unsigned char name[CN_CBQ_NAMELEN];
struct cb_id id; struct cb_id id;
};
struct cn_callback_data {
void (*destruct_data) (void *);
void *ddata;
void *callback_priv;
void (*callback) (void *); void (*callback) (void *);
void *priv;
void *free;
}; };
struct cn_callback_entry { struct cn_callback_entry {
...@@ -118,8 +125,8 @@ struct cn_callback_entry { ...@@ -118,8 +125,8 @@ struct cn_callback_entry {
struct work_struct work; struct work_struct work;
struct cn_queue_dev *pdev; struct cn_queue_dev *pdev;
void (*destruct_data) (void *); struct cn_callback_id id;
void *ddata; struct cn_callback_data data;
int seq, group; int seq, group;
struct sock *nls; struct sock *nls;
...@@ -144,7 +151,7 @@ int cn_add_callback(struct cb_id *, char *, void (*callback) (void *)); ...@@ -144,7 +151,7 @@ int cn_add_callback(struct cb_id *, char *, void (*callback) (void *));
void cn_del_callback(struct cb_id *); void cn_del_callback(struct cb_id *);
int cn_netlink_send(struct cn_msg *, u32, int); int cn_netlink_send(struct cn_msg *, u32, int);
int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb); int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id, void (*callback)(void *));
void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id); void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id);
struct cn_queue_dev *cn_queue_alloc_dev(char *name, struct sock *); struct cn_queue_dev *cn_queue_alloc_dev(char *name, struct sock *);
...@@ -152,6 +159,8 @@ void cn_queue_free_dev(struct cn_queue_dev *dev); ...@@ -152,6 +159,8 @@ void cn_queue_free_dev(struct cn_queue_dev *dev);
int cn_cb_equal(struct cb_id *, struct cb_id *); int cn_cb_equal(struct cb_id *, struct cb_id *);
void cn_queue_wrapper(void *data);
extern int cn_already_initialized; extern int cn_already_initialized;
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -5,16 +5,14 @@ ...@@ -5,16 +5,14 @@
/* This header used to share core functionality between the standalone /* This header used to share core functionality between the standalone
NAT module, and the compatibility layer's use of NAT for masquerading. */ NAT module, and the compatibility layer's use of NAT for masquerading. */
extern int ip_nat_init(void);
extern void ip_nat_cleanup(void);
extern unsigned int nat_packet(struct ip_conntrack *ct, extern unsigned int ip_nat_packet(struct ip_conntrack *ct,
enum ip_conntrack_info conntrackinfo, enum ip_conntrack_info conntrackinfo,
unsigned int hooknum, unsigned int hooknum,
struct sk_buff **pskb); struct sk_buff **pskb);
extern int icmp_reply_translation(struct sk_buff **pskb, extern int ip_nat_icmp_reply_translation(struct sk_buff **pskb,
struct ip_conntrack *ct, struct ip_conntrack *ct,
enum ip_nat_manip_type manip, enum ip_nat_manip_type manip,
enum ip_conntrack_dir dir); enum ip_conntrack_dir dir);
#endif /* _IP_NAT_CORE_H */ #endif /* _IP_NAT_CORE_H */
...@@ -202,7 +202,8 @@ enum ...@@ -202,7 +202,8 @@ enum
NET_TR=14, NET_TR=14,
NET_DECNET=15, NET_DECNET=15,
NET_ECONET=16, NET_ECONET=16,
NET_SCTP=17, NET_SCTP=17,
NET_LLC=18,
}; };
/* /proc/sys/kernel/random */ /* /proc/sys/kernel/random */
...@@ -522,6 +523,29 @@ enum { ...@@ -522,6 +523,29 @@ enum {
NET_IPX_FORWARDING=2 NET_IPX_FORWARDING=2
}; };
/* /proc/sys/net/llc */
enum {
NET_LLC2=1,
NET_LLC_STATION=2,
};
/* /proc/sys/net/llc/llc2 */
enum {
NET_LLC2_TIMEOUT=1,
};
/* /proc/sys/net/llc/station */
enum {
NET_LLC_STATION_ACK_TIMEOUT=1,
};
/* /proc/sys/net/llc/llc2/timeout */
enum {
NET_LLC2_ACK_TIMEOUT=1,
NET_LLC2_P_TIMEOUT=2,
NET_LLC2_REJ_TIMEOUT=3,
NET_LLC2_BUSY_TIMEOUT=4,
};
/* /proc/sys/net/appletalk */ /* /proc/sys/net/appletalk */
enum { enum {
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <asm/atomic.h>
struct net_device; struct net_device;
struct packet_type; struct packet_type;
struct sk_buff; struct sk_buff;
...@@ -44,6 +46,7 @@ struct llc_sap { ...@@ -44,6 +46,7 @@ struct llc_sap {
unsigned char state; unsigned char state;
unsigned char p_bit; unsigned char p_bit;
unsigned char f_bit; unsigned char f_bit;
atomic_t refcnt;
int (*rcv_func)(struct sk_buff *skb, int (*rcv_func)(struct sk_buff *skb,
struct net_device *dev, struct net_device *dev,
struct packet_type *pt, struct packet_type *pt,
...@@ -81,13 +84,27 @@ extern struct llc_sap *llc_sap_open(unsigned char lsap, ...@@ -81,13 +84,27 @@ extern struct llc_sap *llc_sap_open(unsigned char lsap,
struct net_device *dev, struct net_device *dev,
struct packet_type *pt, struct packet_type *pt,
struct net_device *orig_dev)); struct net_device *orig_dev));
static inline void llc_sap_hold(struct llc_sap *sap)
{
atomic_inc(&sap->refcnt);
}
extern void llc_sap_close(struct llc_sap *sap); extern void llc_sap_close(struct llc_sap *sap);
static inline void llc_sap_put(struct llc_sap *sap)
{
if (atomic_dec_and_test(&sap->refcnt))
llc_sap_close(sap);
}
extern struct llc_sap *llc_sap_find(unsigned char sap_value); extern struct llc_sap *llc_sap_find(unsigned char sap_value);
extern int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb, extern int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb,
unsigned char *dmac, unsigned char dsap); unsigned char *dmac, unsigned char dsap);
extern void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb);
extern void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb);
extern int llc_station_init(void); extern int llc_station_init(void);
extern void llc_station_exit(void); extern void llc_station_exit(void);
...@@ -98,4 +115,17 @@ extern void llc_proc_exit(void); ...@@ -98,4 +115,17 @@ extern void llc_proc_exit(void);
#define llc_proc_init() (0) #define llc_proc_init() (0)
#define llc_proc_exit() do { } while(0) #define llc_proc_exit() do { } while(0)
#endif /* CONFIG_PROC_FS */ #endif /* CONFIG_PROC_FS */
#ifdef CONFIG_SYSCTL
extern int llc_sysctl_init(void);
extern void llc_sysctl_exit(void);
extern int sysctl_llc2_ack_timeout;
extern int sysctl_llc2_busy_timeout;
extern int sysctl_llc2_p_timeout;
extern int sysctl_llc2_rej_timeout;
extern int sysctl_llc_station_ack_timeout;
#else
#define llc_sysctl_init() (0)
#define llc_sysctl_exit() do { } while(0)
#endif /* CONFIG_SYSCTL */
#endif /* LLC_H */ #endif /* LLC_H */
...@@ -19,14 +19,14 @@ ...@@ -19,14 +19,14 @@
#define LLC_EVENT 1 #define LLC_EVENT 1
#define LLC_PACKET 2 #define LLC_PACKET 2
#define LLC_P_TIME 2 #define LLC2_P_TIME 2
#define LLC_ACK_TIME 1 #define LLC2_ACK_TIME 1
#define LLC_REJ_TIME 3 #define LLC2_REJ_TIME 3
#define LLC_BUSY_TIME 3 #define LLC2_BUSY_TIME 3
struct llc_timer { struct llc_timer {
struct timer_list timer; struct timer_list timer;
u16 expire; /* timer expire time */ unsigned long expire; /* timer expire time */
}; };
struct llc_sock { struct llc_sock {
...@@ -38,6 +38,7 @@ struct llc_sock { ...@@ -38,6 +38,7 @@ struct llc_sock {
struct llc_addr laddr; /* lsap/mac pair */ struct llc_addr laddr; /* lsap/mac pair */
struct llc_addr daddr; /* dsap/mac pair */ struct llc_addr daddr; /* dsap/mac pair */
struct net_device *dev; /* device to send to remote */ struct net_device *dev; /* device to send to remote */
u32 copied_seq; /* head of yet unread data */
u8 retry_count; /* number of retries */ u8 retry_count; /* number of retries */
u8 ack_must_be_send; u8 ack_must_be_send;
u8 first_pdu_Ns; u8 first_pdu_Ns;
...@@ -92,7 +93,8 @@ static __inline__ char llc_backlog_type(struct sk_buff *skb) ...@@ -92,7 +93,8 @@ static __inline__ char llc_backlog_type(struct sk_buff *skb)
return skb->cb[sizeof(skb->cb) - 1]; return skb->cb[sizeof(skb->cb) - 1];
} }
extern struct sock *llc_sk_alloc(int family, int priority, struct proto *prot); extern struct sock *llc_sk_alloc(int family, unsigned int __nocast priority,
struct proto *prot);
extern void llc_sk_free(struct sock *sk); extern void llc_sk_free(struct sock *sk);
extern void llc_sk_reset(struct sock *sk); extern void llc_sk_reset(struct sock *sk);
...@@ -115,5 +117,4 @@ extern void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk); ...@@ -115,5 +117,4 @@ extern void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk);
extern u8 llc_data_accept_state(u8 state); extern u8 llc_data_accept_state(u8 state);
extern void llc_build_offset_table(void); extern void llc_build_offset_table(void);
extern int llc_release_sockets(struct llc_sap *sap);
#endif /* LLC_CONN_H */ #endif /* LLC_CONN_H */
...@@ -12,11 +12,15 @@ ...@@ -12,11 +12,15 @@
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
*/ */
struct llc_sap; struct llc_sap;
struct net_device;
struct sk_buff; struct sk_buff;
struct sock;
extern void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb); extern void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb);
extern void llc_save_primitive(struct sk_buff* skb, unsigned char prim); extern void llc_save_primitive(struct sock *sk, struct sk_buff* skb,
extern struct sk_buff *llc_alloc_frame(void); unsigned char prim);
extern struct sk_buff *llc_alloc_frame(struct sock *sk,
struct net_device *dev);
extern void llc_build_and_send_test_pkt(struct llc_sap *sap, extern void llc_build_and_send_test_pkt(struct llc_sap *sap,
struct sk_buff *skb, struct sk_buff *skb,
......
...@@ -56,7 +56,7 @@ struct datalink_proto *register_8022_client(unsigned char type, ...@@ -56,7 +56,7 @@ struct datalink_proto *register_8022_client(unsigned char type,
void unregister_8022_client(struct datalink_proto *proto) void unregister_8022_client(struct datalink_proto *proto)
{ {
llc_sap_close(proto->sap); llc_sap_put(proto->sap);
kfree(proto); kfree(proto);
} }
......
...@@ -106,7 +106,7 @@ module_init(snap_init); ...@@ -106,7 +106,7 @@ module_init(snap_init);
static void __exit snap_exit(void) static void __exit snap_exit(void)
{ {
llc_sap_close(snap_sap); llc_sap_put(snap_sap);
} }
module_exit(snap_exit); module_exit(snap_exit);
......
...@@ -238,7 +238,7 @@ unsigned short tr_type_trans(struct sk_buff *skb, struct net_device *dev) ...@@ -238,7 +238,7 @@ unsigned short tr_type_trans(struct sk_buff *skb, struct net_device *dev)
return trllc->ethertype; return trllc->ethertype;
} }
return ntohs(ETH_P_802_2); return ntohs(ETH_P_TR_802_2);
} }
/* /*
......
...@@ -574,6 +574,8 @@ struct net_device *dev_getbyhwaddr(unsigned short type, char *ha) ...@@ -574,6 +574,8 @@ struct net_device *dev_getbyhwaddr(unsigned short type, char *ha)
return dev; return dev;
} }
EXPORT_SYMBOL(dev_getbyhwaddr);
struct net_device *dev_getfirstbyhwtype(unsigned short type) struct net_device *dev_getfirstbyhwtype(unsigned short type)
{ {
struct net_device *dev; struct net_device *dev;
......
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
# objects for the standalone - connection tracking / NAT # objects for the standalone - connection tracking / NAT
ip_conntrack-objs := ip_conntrack_standalone.o ip_conntrack_core.o ip_conntrack_proto_generic.o ip_conntrack_proto_tcp.o ip_conntrack_proto_udp.o ip_conntrack_proto_icmp.o ip_conntrack-objs := ip_conntrack_standalone.o ip_conntrack_core.o ip_conntrack_proto_generic.o ip_conntrack_proto_tcp.o ip_conntrack_proto_udp.o ip_conntrack_proto_icmp.o
iptable_nat-objs := ip_nat_standalone.o ip_nat_rule.o ip_nat_core.o ip_nat_helper.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o ip_nat-objs := ip_nat_core.o ip_nat_helper.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o
iptable_nat-objs := ip_nat_rule.o ip_nat_standalone.o
ip_conntrack_pptp-objs := ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o ip_conntrack_pptp-objs := ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o
ip_nat_pptp-objs := ip_nat_helper_pptp.o ip_nat_proto_gre.o ip_nat_pptp-objs := ip_nat_helper_pptp.o ip_nat_proto_gre.o
...@@ -40,7 +41,7 @@ obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o ...@@ -40,7 +41,7 @@ obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
# the three instances of ip_tables # the three instances of ip_tables
obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o
obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o
obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o ip_nat.o
obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
# matches # matches
......
...@@ -74,12 +74,14 @@ ip_nat_proto_find_get(u_int8_t protonum) ...@@ -74,12 +74,14 @@ ip_nat_proto_find_get(u_int8_t protonum)
return p; return p;
} }
EXPORT_SYMBOL_GPL(ip_nat_proto_find_get);
void void
ip_nat_proto_put(struct ip_nat_protocol *p) ip_nat_proto_put(struct ip_nat_protocol *p)
{ {
module_put(p->me); module_put(p->me);
} }
EXPORT_SYMBOL_GPL(ip_nat_proto_put);
/* We keep an extra hash for each conntrack, for fast searching. */ /* We keep an extra hash for each conntrack, for fast searching. */
static inline unsigned int static inline unsigned int
...@@ -111,6 +113,7 @@ ip_nat_cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck) ...@@ -111,6 +113,7 @@ ip_nat_cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck)
return csum_fold(csum_partial((char *)diffs, sizeof(diffs), return csum_fold(csum_partial((char *)diffs, sizeof(diffs),
oldcheck^0xFFFF)); oldcheck^0xFFFF));
} }
EXPORT_SYMBOL(ip_nat_cheat_check);
/* Is this tuple already taken? (not by us) */ /* Is this tuple already taken? (not by us) */
int int
...@@ -127,6 +130,7 @@ ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple, ...@@ -127,6 +130,7 @@ ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple,
invert_tuplepr(&reply, tuple); invert_tuplepr(&reply, tuple);
return ip_conntrack_tuple_taken(&reply, ignored_conntrack); return ip_conntrack_tuple_taken(&reply, ignored_conntrack);
} }
EXPORT_SYMBOL(ip_nat_used_tuple);
/* If we source map this tuple so reply looks like reply_tuple, will /* If we source map this tuple so reply looks like reply_tuple, will
* that meet the constraints of range. */ * that meet the constraints of range. */
...@@ -347,6 +351,7 @@ ip_nat_setup_info(struct ip_conntrack *conntrack, ...@@ -347,6 +351,7 @@ ip_nat_setup_info(struct ip_conntrack *conntrack,
return NF_ACCEPT; return NF_ACCEPT;
} }
EXPORT_SYMBOL(ip_nat_setup_info);
/* Returns true if succeeded. */ /* Returns true if succeeded. */
static int static int
...@@ -387,10 +392,10 @@ manip_pkt(u_int16_t proto, ...@@ -387,10 +392,10 @@ manip_pkt(u_int16_t proto,
} }
/* Do packet manipulations according to ip_nat_setup_info. */ /* Do packet manipulations according to ip_nat_setup_info. */
unsigned int nat_packet(struct ip_conntrack *ct, unsigned int ip_nat_packet(struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo, enum ip_conntrack_info ctinfo,
unsigned int hooknum, unsigned int hooknum,
struct sk_buff **pskb) struct sk_buff **pskb)
{ {
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
unsigned long statusbit; unsigned long statusbit;
...@@ -417,12 +422,13 @@ unsigned int nat_packet(struct ip_conntrack *ct, ...@@ -417,12 +422,13 @@ unsigned int nat_packet(struct ip_conntrack *ct,
} }
return NF_ACCEPT; return NF_ACCEPT;
} }
EXPORT_SYMBOL_GPL(ip_nat_packet);
/* Dir is direction ICMP is coming from (opposite to packet it contains) */ /* Dir is direction ICMP is coming from (opposite to packet it contains) */
int icmp_reply_translation(struct sk_buff **pskb, int ip_nat_icmp_reply_translation(struct sk_buff **pskb,
struct ip_conntrack *ct, struct ip_conntrack *ct,
enum ip_nat_manip_type manip, enum ip_nat_manip_type manip,
enum ip_conntrack_dir dir) enum ip_conntrack_dir dir)
{ {
struct { struct {
struct icmphdr icmp; struct icmphdr icmp;
...@@ -509,6 +515,7 @@ int icmp_reply_translation(struct sk_buff **pskb, ...@@ -509,6 +515,7 @@ int icmp_reply_translation(struct sk_buff **pskb,
return 1; return 1;
} }
EXPORT_SYMBOL_GPL(ip_nat_icmp_reply_translation);
/* Protocol registration. */ /* Protocol registration. */
int ip_nat_protocol_register(struct ip_nat_protocol *proto) int ip_nat_protocol_register(struct ip_nat_protocol *proto)
...@@ -525,6 +532,7 @@ int ip_nat_protocol_register(struct ip_nat_protocol *proto) ...@@ -525,6 +532,7 @@ int ip_nat_protocol_register(struct ip_nat_protocol *proto)
write_unlock_bh(&ip_nat_lock); write_unlock_bh(&ip_nat_lock);
return ret; return ret;
} }
EXPORT_SYMBOL(ip_nat_protocol_register);
/* Noone stores the protocol anywhere; simply delete it. */ /* Noone stores the protocol anywhere; simply delete it. */
void ip_nat_protocol_unregister(struct ip_nat_protocol *proto) void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)
...@@ -536,6 +544,7 @@ void ip_nat_protocol_unregister(struct ip_nat_protocol *proto) ...@@ -536,6 +544,7 @@ void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)
/* Someone could be still looking at the proto in a bh. */ /* Someone could be still looking at the proto in a bh. */
synchronize_net(); synchronize_net();
} }
EXPORT_SYMBOL(ip_nat_protocol_unregister);
#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \ #if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE) defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
...@@ -582,7 +591,7 @@ EXPORT_SYMBOL_GPL(ip_nat_port_nfattr_to_range); ...@@ -582,7 +591,7 @@ EXPORT_SYMBOL_GPL(ip_nat_port_nfattr_to_range);
EXPORT_SYMBOL_GPL(ip_nat_port_range_to_nfattr); EXPORT_SYMBOL_GPL(ip_nat_port_range_to_nfattr);
#endif #endif
int __init ip_nat_init(void) static int __init ip_nat_init(void)
{ {
size_t i; size_t i;
...@@ -624,10 +633,14 @@ static int clean_nat(struct ip_conntrack *i, void *data) ...@@ -624,10 +633,14 @@ static int clean_nat(struct ip_conntrack *i, void *data)
return 0; return 0;
} }
/* Not __exit: called from ip_nat_standalone.c:init_or_cleanup() --RR */ static void __exit ip_nat_cleanup(void)
void ip_nat_cleanup(void)
{ {
ip_ct_iterate_cleanup(&clean_nat, NULL); ip_ct_iterate_cleanup(&clean_nat, NULL);
ip_conntrack_destroyed = NULL; ip_conntrack_destroyed = NULL;
vfree(bysource); vfree(bysource);
} }
MODULE_LICENSE("GPL");
module_init(ip_nat_init);
module_exit(ip_nat_cleanup);
...@@ -199,6 +199,7 @@ ip_nat_mangle_tcp_packet(struct sk_buff **pskb, ...@@ -199,6 +199,7 @@ ip_nat_mangle_tcp_packet(struct sk_buff **pskb,
} }
return 1; return 1;
} }
EXPORT_SYMBOL(ip_nat_mangle_tcp_packet);
/* Generic function for mangling variable-length address changes inside /* Generic function for mangling variable-length address changes inside
* NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
...@@ -256,6 +257,7 @@ ip_nat_mangle_udp_packet(struct sk_buff **pskb, ...@@ -256,6 +257,7 @@ ip_nat_mangle_udp_packet(struct sk_buff **pskb,
return 1; return 1;
} }
EXPORT_SYMBOL(ip_nat_mangle_udp_packet);
/* Adjust one found SACK option including checksum correction */ /* Adjust one found SACK option including checksum correction */
static void static void
...@@ -399,6 +401,7 @@ ip_nat_seq_adjust(struct sk_buff **pskb, ...@@ -399,6 +401,7 @@ ip_nat_seq_adjust(struct sk_buff **pskb,
return 1; return 1;
} }
EXPORT_SYMBOL(ip_nat_seq_adjust);
/* Setup NAT on this expected conntrack so it follows master. */ /* Setup NAT on this expected conntrack so it follows master. */
/* If we fail to get a free NAT slot, we'll get dropped on confirm */ /* If we fail to get a free NAT slot, we'll get dropped on confirm */
...@@ -425,3 +428,4 @@ void ip_nat_follow_master(struct ip_conntrack *ct, ...@@ -425,3 +428,4 @@ void ip_nat_follow_master(struct ip_conntrack *ct,
/* hook doesn't matter, but it has to do destination manip */ /* hook doesn't matter, but it has to do destination manip */
ip_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING); ip_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);
} }
EXPORT_SYMBOL(ip_nat_follow_master);
...@@ -108,8 +108,8 @@ ip_nat_fn(unsigned int hooknum, ...@@ -108,8 +108,8 @@ ip_nat_fn(unsigned int hooknum,
case IP_CT_RELATED: case IP_CT_RELATED:
case IP_CT_RELATED+IP_CT_IS_REPLY: case IP_CT_RELATED+IP_CT_IS_REPLY:
if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) { if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {
if (!icmp_reply_translation(pskb, ct, maniptype, if (!ip_nat_icmp_reply_translation(pskb, ct, maniptype,
CTINFO2DIR(ctinfo))) CTINFO2DIR(ctinfo)))
return NF_DROP; return NF_DROP;
else else
return NF_ACCEPT; return NF_ACCEPT;
...@@ -152,7 +152,7 @@ ip_nat_fn(unsigned int hooknum, ...@@ -152,7 +152,7 @@ ip_nat_fn(unsigned int hooknum,
} }
IP_NF_ASSERT(info); IP_NF_ASSERT(info);
return nat_packet(ct, ctinfo, hooknum, pskb); return ip_nat_packet(ct, ctinfo, hooknum, pskb);
} }
static unsigned int static unsigned int
...@@ -325,15 +325,10 @@ static int init_or_cleanup(int init) ...@@ -325,15 +325,10 @@ static int init_or_cleanup(int init)
printk("ip_nat_init: can't setup rules.\n"); printk("ip_nat_init: can't setup rules.\n");
goto cleanup_nothing; goto cleanup_nothing;
} }
ret = ip_nat_init();
if (ret < 0) {
printk("ip_nat_init: can't setup rules.\n");
goto cleanup_rule_init;
}
ret = nf_register_hook(&ip_nat_in_ops); ret = nf_register_hook(&ip_nat_in_ops);
if (ret < 0) { if (ret < 0) {
printk("ip_nat_init: can't register in hook.\n"); printk("ip_nat_init: can't register in hook.\n");
goto cleanup_nat; goto cleanup_rule_init;
} }
ret = nf_register_hook(&ip_nat_out_ops); ret = nf_register_hook(&ip_nat_out_ops);
if (ret < 0) { if (ret < 0) {
...@@ -374,8 +369,6 @@ static int init_or_cleanup(int init) ...@@ -374,8 +369,6 @@ static int init_or_cleanup(int init)
nf_unregister_hook(&ip_nat_out_ops); nf_unregister_hook(&ip_nat_out_ops);
cleanup_inops: cleanup_inops:
nf_unregister_hook(&ip_nat_in_ops); nf_unregister_hook(&ip_nat_in_ops);
cleanup_nat:
ip_nat_cleanup();
cleanup_rule_init: cleanup_rule_init:
ip_nat_rule_cleanup(); ip_nat_rule_cleanup();
cleanup_nothing: cleanup_nothing:
...@@ -395,14 +388,4 @@ static void __exit fini(void) ...@@ -395,14 +388,4 @@ static void __exit fini(void)
module_init(init); module_init(init);
module_exit(fini); module_exit(fini);
EXPORT_SYMBOL(ip_nat_setup_info);
EXPORT_SYMBOL(ip_nat_protocol_register);
EXPORT_SYMBOL(ip_nat_protocol_unregister);
EXPORT_SYMBOL_GPL(ip_nat_proto_find_get);
EXPORT_SYMBOL_GPL(ip_nat_proto_put);
EXPORT_SYMBOL(ip_nat_cheat_check);
EXPORT_SYMBOL(ip_nat_mangle_tcp_packet);
EXPORT_SYMBOL(ip_nat_mangle_udp_packet);
EXPORT_SYMBOL(ip_nat_used_tuple);
EXPORT_SYMBOL(ip_nat_follow_master);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -3520,6 +3520,8 @@ int __init addrconf_init(void) ...@@ -3520,6 +3520,8 @@ int __init addrconf_init(void)
if (err) if (err)
return err; return err;
ip6_null_entry.rt6i_idev = in6_dev_get(&loopback_dev);
register_netdevice_notifier(&ipv6_dev_notf); register_netdevice_notifier(&ipv6_dev_notf);
#ifdef CONFIG_IPV6_PRIVACY #ifdef CONFIG_IPV6_PRIVACY
......
...@@ -22,3 +22,4 @@ llc2-y := llc_if.o llc_c_ev.o llc_c_ac.o llc_conn.o llc_c_st.o llc_pdu.o \ ...@@ -22,3 +22,4 @@ llc2-y := llc_if.o llc_c_ev.o llc_c_ac.o llc_conn.o llc_c_st.o llc_pdu.o \
llc_sap.o llc_s_ac.o llc_s_ev.o llc_s_st.o af_llc.o llc_station.o llc_sap.o llc_s_ac.o llc_s_ev.o llc_s_st.o af_llc.o llc_station.o
llc2-$(CONFIG_PROC_FS) += llc_proc.o llc2-$(CONFIG_PROC_FS) += llc_proc.o
llc2-$(CONFIG_SYSCTL) += sysctl_net_llc.o
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -40,6 +40,7 @@ static struct llc_sap *llc_sap_alloc(void) ...@@ -40,6 +40,7 @@ static struct llc_sap *llc_sap_alloc(void)
sap->state = LLC_SAP_STATE_ACTIVE; sap->state = LLC_SAP_STATE_ACTIVE;
memcpy(sap->laddr.mac, llc_station_mac_sa, ETH_ALEN); memcpy(sap->laddr.mac, llc_station_mac_sa, ETH_ALEN);
rwlock_init(&sap->sk_list.lock); rwlock_init(&sap->sk_list.lock);
atomic_set(&sap->refcnt, 1);
} }
return sap; return sap;
} }
...@@ -52,9 +53,7 @@ static struct llc_sap *llc_sap_alloc(void) ...@@ -52,9 +53,7 @@ static struct llc_sap *llc_sap_alloc(void)
*/ */
static void llc_add_sap(struct llc_sap *sap) static void llc_add_sap(struct llc_sap *sap)
{ {
write_lock_bh(&llc_sap_list_lock);
list_add_tail(&sap->node, &llc_sap_list); list_add_tail(&sap->node, &llc_sap_list);
write_unlock_bh(&llc_sap_list_lock);
} }
/** /**
...@@ -70,11 +69,25 @@ static void llc_del_sap(struct llc_sap *sap) ...@@ -70,11 +69,25 @@ static void llc_del_sap(struct llc_sap *sap)
write_unlock_bh(&llc_sap_list_lock); write_unlock_bh(&llc_sap_list_lock);
} }
static struct llc_sap *__llc_sap_find(unsigned char sap_value)
{
struct llc_sap* sap;
list_for_each_entry(sap, &llc_sap_list, node)
if (sap->laddr.lsap == sap_value)
goto out;
sap = NULL;
out:
return sap;
}
/** /**
* llc_sap_find - searchs a SAP in station * llc_sap_find - searchs a SAP in station
* @sap_value: sap to be found * @sap_value: sap to be found
* *
* Searchs for a sap in the sap list of the LLC's station upon the sap ID. * Searchs for a sap in the sap list of the LLC's station upon the sap ID.
* If the sap is found it will be refcounted and the user will have to do
* a llc_sap_put after use.
* Returns the sap or %NULL if not found. * Returns the sap or %NULL if not found.
*/ */
struct llc_sap *llc_sap_find(unsigned char sap_value) struct llc_sap *llc_sap_find(unsigned char sap_value)
...@@ -82,11 +95,9 @@ struct llc_sap *llc_sap_find(unsigned char sap_value) ...@@ -82,11 +95,9 @@ struct llc_sap *llc_sap_find(unsigned char sap_value)
struct llc_sap* sap; struct llc_sap* sap;
read_lock_bh(&llc_sap_list_lock); read_lock_bh(&llc_sap_list_lock);
list_for_each_entry(sap, &llc_sap_list, node) sap = __llc_sap_find(sap_value);
if (sap->laddr.lsap == sap_value) if (sap)
goto out; llc_sap_hold(sap);
sap = NULL;
out:
read_unlock_bh(&llc_sap_list_lock); read_unlock_bh(&llc_sap_list_lock);
return sap; return sap;
} }
...@@ -106,19 +117,20 @@ struct llc_sap *llc_sap_open(unsigned char lsap, ...@@ -106,19 +117,20 @@ struct llc_sap *llc_sap_open(unsigned char lsap,
struct packet_type *pt, struct packet_type *pt,
struct net_device *orig_dev)) struct net_device *orig_dev))
{ {
struct llc_sap *sap = llc_sap_find(lsap); struct llc_sap *sap = NULL;
if (sap) { /* SAP already exists */ write_lock_bh(&llc_sap_list_lock);
sap = NULL; if (__llc_sap_find(lsap)) /* SAP already exists */
goto out; goto out;
}
sap = llc_sap_alloc(); sap = llc_sap_alloc();
if (!sap) if (!sap)
goto out; goto out;
sap->laddr.lsap = lsap; sap->laddr.lsap = lsap;
sap->rcv_func = func; sap->rcv_func = func;
llc_sap_hold(sap);
llc_add_sap(sap); llc_add_sap(sap);
out: out:
write_unlock_bh(&llc_sap_list_lock);
return sap; return sap;
} }
......
...@@ -47,14 +47,11 @@ int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb) ...@@ -47,14 +47,11 @@ int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb)
int rc = -ECONNABORTED; int rc = -ECONNABORTED;
struct llc_sock *llc = llc_sk(sk); struct llc_sock *llc = llc_sk(sk);
if (llc->state == LLC_CONN_STATE_ADM) if (unlikely(llc->state == LLC_CONN_STATE_ADM))
goto out; goto out;
rc = -EBUSY; rc = -EBUSY;
if (llc_data_accept_state(llc->state)) { /* data_conn_refuse */ if (unlikely(llc_data_accept_state(llc->state) || /* data_conn_refuse */
llc->failed_data_req = 1; llc->p_flag)) {
goto out;
}
if (llc->p_flag) {
llc->failed_data_req = 1; llc->failed_data_req = 1;
goto out; goto out;
} }
...@@ -110,6 +107,7 @@ int llc_establish_connection(struct sock *sk, u8 *lmac, u8 *dmac, u8 dsap) ...@@ -110,6 +107,7 @@ int llc_establish_connection(struct sock *sk, u8 *lmac, u8 *dmac, u8 dsap)
ev->type = LLC_CONN_EV_TYPE_PRIM; ev->type = LLC_CONN_EV_TYPE_PRIM;
ev->prim = LLC_CONN_PRIM; ev->prim = LLC_CONN_PRIM;
ev->prim_type = LLC_PRIM_TYPE_REQ; ev->prim_type = LLC_PRIM_TYPE_REQ;
skb_set_owner_w(skb, sk);
rc = llc_conn_state_process(sk, skb); rc = llc_conn_state_process(sk, skb);
} }
out_put: out_put:
...@@ -144,6 +142,7 @@ int llc_send_disc(struct sock *sk) ...@@ -144,6 +142,7 @@ int llc_send_disc(struct sock *sk)
skb = alloc_skb(0, GFP_ATOMIC); skb = alloc_skb(0, GFP_ATOMIC);
if (!skb) if (!skb)
goto out; goto out;
skb_set_owner_w(skb, sk);
sk->sk_state = TCP_CLOSING; sk->sk_state = TCP_CLOSING;
ev = llc_conn_ev(skb); ev = llc_conn_ev(skb);
ev->type = LLC_CONN_EV_TYPE_PRIM; ev->type = LLC_CONN_EV_TYPE_PRIM;
......
...@@ -99,15 +99,19 @@ static __inline__ int llc_pdu_type(struct sk_buff *skb) ...@@ -99,15 +99,19 @@ static __inline__ int llc_pdu_type(struct sk_buff *skb)
static inline int llc_fixup_skb(struct sk_buff *skb) static inline int llc_fixup_skb(struct sk_buff *skb)
{ {
u8 llc_len = 2; u8 llc_len = 2;
struct llc_pdu_sn *pdu; struct llc_pdu_un *pdu;
if (!pskb_may_pull(skb, sizeof(*pdu))) if (unlikely(!pskb_may_pull(skb, sizeof(*pdu))))
return 0; return 0;
pdu = (struct llc_pdu_sn *)skb->data; pdu = (struct llc_pdu_un *)skb->data;
if ((pdu->ctrl_1 & LLC_PDU_TYPE_MASK) == LLC_PDU_TYPE_U) if ((pdu->ctrl_1 & LLC_PDU_TYPE_MASK) == LLC_PDU_TYPE_U)
llc_len = 1; llc_len = 1;
llc_len += 2; llc_len += 2;
if (unlikely(!pskb_may_pull(skb, llc_len)))
return 0;
skb->h.raw += llc_len; skb->h.raw += llc_len;
skb_pull(skb, llc_len); skb_pull(skb, llc_len);
if (skb->protocol == htons(ETH_P_802_2)) { if (skb->protocol == htons(ETH_P_802_2)) {
...@@ -166,17 +170,22 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -166,17 +170,22 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,
*/ */
if (sap->rcv_func) { if (sap->rcv_func) {
sap->rcv_func(skb, dev, pt, orig_dev); sap->rcv_func(skb, dev, pt, orig_dev);
goto out; goto out_put;
} }
dest = llc_pdu_type(skb); dest = llc_pdu_type(skb);
if (unlikely(!dest || !llc_type_handlers[dest - 1])) if (unlikely(!dest || !llc_type_handlers[dest - 1]))
goto drop; goto drop_put;
llc_type_handlers[dest - 1](sap, skb); llc_type_handlers[dest - 1](sap, skb);
out_put:
llc_sap_put(sap);
out: out:
return 0; return 0;
drop: drop:
kfree_skb(skb); kfree_skb(skb);
goto out; goto out;
drop_put:
kfree_skb(skb);
goto out_put;
handle_station: handle_station:
if (!llc_station_handler) if (!llc_station_handler)
goto drop; goto drop;
......
...@@ -98,7 +98,7 @@ int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb, ...@@ -98,7 +98,7 @@ int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb,
dsap, LLC_PDU_CMD); dsap, LLC_PDU_CMD);
llc_pdu_init_as_ui_cmd(skb); llc_pdu_init_as_ui_cmd(skb);
rc = llc_mac_hdr_init(skb, skb->dev->dev_addr, dmac); rc = llc_mac_hdr_init(skb, skb->dev->dev_addr, dmac);
if (!rc) if (likely(!rc))
rc = dev_queue_xmit(skb); rc = dev_queue_xmit(skb);
return rc; return rc;
} }
......
...@@ -134,7 +134,7 @@ static int llc_seq_socket_show(struct seq_file *seq, void *v) ...@@ -134,7 +134,7 @@ static int llc_seq_socket_show(struct seq_file *seq, void *v)
llc_ui_format_mac(seq, llc->daddr.mac); llc_ui_format_mac(seq, llc->daddr.mac);
seq_printf(seq, "@%02X %8d %8d %2d %3d %4d\n", llc->daddr.lsap, seq_printf(seq, "@%02X %8d %8d %2d %3d %4d\n", llc->daddr.lsap,
atomic_read(&sk->sk_wmem_alloc), atomic_read(&sk->sk_wmem_alloc),
atomic_read(&sk->sk_rmem_alloc), atomic_read(&sk->sk_rmem_alloc) - llc->copied_seq,
sk->sk_state, sk->sk_state,
sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : -1, sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : -1,
llc->link); llc->link);
......
...@@ -58,7 +58,7 @@ int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb) ...@@ -58,7 +58,7 @@ int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb)
ev->daddr.lsap, LLC_PDU_CMD); ev->daddr.lsap, LLC_PDU_CMD);
llc_pdu_init_as_ui_cmd(skb); llc_pdu_init_as_ui_cmd(skb);
rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac); rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac);
if (!rc) if (likely(!rc))
rc = dev_queue_xmit(skb); rc = dev_queue_xmit(skb);
return rc; return rc;
} }
...@@ -81,7 +81,7 @@ int llc_sap_action_send_xid_c(struct llc_sap *sap, struct sk_buff *skb) ...@@ -81,7 +81,7 @@ int llc_sap_action_send_xid_c(struct llc_sap *sap, struct sk_buff *skb)
ev->daddr.lsap, LLC_PDU_CMD); ev->daddr.lsap, LLC_PDU_CMD);
llc_pdu_init_as_xid_cmd(skb, LLC_XID_NULL_CLASS_2, 0); llc_pdu_init_as_xid_cmd(skb, LLC_XID_NULL_CLASS_2, 0);
rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac); rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac);
if (!rc) if (likely(!rc))
rc = dev_queue_xmit(skb); rc = dev_queue_xmit(skb);
return rc; return rc;
} }
...@@ -103,15 +103,14 @@ int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb) ...@@ -103,15 +103,14 @@ int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb)
llc_pdu_decode_sa(skb, mac_da); llc_pdu_decode_sa(skb, mac_da);
llc_pdu_decode_da(skb, mac_sa); llc_pdu_decode_da(skb, mac_sa);
llc_pdu_decode_ssap(skb, &dsap); llc_pdu_decode_ssap(skb, &dsap);
nskb = llc_alloc_frame(); nskb = llc_alloc_frame(NULL, skb->dev);
if (!nskb) if (!nskb)
goto out; goto out;
nskb->dev = skb->dev;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap, llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap,
LLC_PDU_RSP); LLC_PDU_RSP);
llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 0); llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 0);
rc = llc_mac_hdr_init(nskb, mac_sa, mac_da); rc = llc_mac_hdr_init(nskb, mac_sa, mac_da);
if (!rc) if (likely(!rc))
rc = dev_queue_xmit(nskb); rc = dev_queue_xmit(nskb);
out: out:
return rc; return rc;
...@@ -135,7 +134,7 @@ int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb) ...@@ -135,7 +134,7 @@ int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb)
ev->daddr.lsap, LLC_PDU_CMD); ev->daddr.lsap, LLC_PDU_CMD);
llc_pdu_init_as_test_cmd(skb); llc_pdu_init_as_test_cmd(skb);
rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac); rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac);
if (!rc) if (likely(!rc))
rc = dev_queue_xmit(skb); rc = dev_queue_xmit(skb);
return rc; return rc;
} }
...@@ -149,15 +148,14 @@ int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb) ...@@ -149,15 +148,14 @@ int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb)
llc_pdu_decode_sa(skb, mac_da); llc_pdu_decode_sa(skb, mac_da);
llc_pdu_decode_da(skb, mac_sa); llc_pdu_decode_da(skb, mac_sa);
llc_pdu_decode_ssap(skb, &dsap); llc_pdu_decode_ssap(skb, &dsap);
nskb = llc_alloc_frame(); nskb = llc_alloc_frame(NULL, skb->dev);
if (!nskb) if (!nskb)
goto out; goto out;
nskb->dev = skb->dev;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap, llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap,
LLC_PDU_RSP); LLC_PDU_RSP);
llc_pdu_init_as_test_rsp(nskb, skb); llc_pdu_init_as_test_rsp(nskb, skb);
rc = llc_mac_hdr_init(nskb, mac_sa, mac_da); rc = llc_mac_hdr_init(nskb, mac_sa, mac_da);
if (!rc) if (likely(!rc))
rc = dev_queue_xmit(nskb); rc = dev_queue_xmit(nskb);
out: out:
return rc; return rc;
......
...@@ -26,11 +26,12 @@ ...@@ -26,11 +26,12 @@
/** /**
* llc_alloc_frame - allocates sk_buff for frame * llc_alloc_frame - allocates sk_buff for frame
* @dev: network device this skb will be sent over
* *
* Allocates an sk_buff for frame and initializes sk_buff fields. * Allocates an sk_buff for frame and initializes sk_buff fields.
* Returns allocated skb or %NULL when out of memory. * Returns allocated skb or %NULL when out of memory.
*/ */
struct sk_buff *llc_alloc_frame(void) struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev)
{ {
struct sk_buff *skb = alloc_skb(128, GFP_ATOMIC); struct sk_buff *skb = alloc_skb(128, GFP_ATOMIC);
...@@ -38,18 +39,23 @@ struct sk_buff *llc_alloc_frame(void) ...@@ -38,18 +39,23 @@ struct sk_buff *llc_alloc_frame(void)
skb_reserve(skb, 50); skb_reserve(skb, 50);
skb->nh.raw = skb->h.raw = skb->data; skb->nh.raw = skb->h.raw = skb->data;
skb->protocol = htons(ETH_P_802_2); skb->protocol = htons(ETH_P_802_2);
skb->dev = dev_base->next; skb->dev = dev;
skb->mac.raw = skb->head; skb->mac.raw = skb->head;
if (sk != NULL)
skb_set_owner_w(skb, sk);
} }
return skb; return skb;
} }
void llc_save_primitive(struct sk_buff* skb, u8 prim) void llc_save_primitive(struct sock *sk, struct sk_buff* skb, u8 prim)
{ {
struct sockaddr_llc *addr = llc_ui_skb_cb(skb); struct sockaddr_llc *addr;
if (skb->sk->sk_type == SOCK_STREAM) /* See UNIX98 */
return;
/* save primitive for use by the user. */ /* save primitive for use by the user. */
addr->sllc_family = skb->sk->sk_family; addr = llc_ui_skb_cb(skb);
addr->sllc_family = sk->sk_family;
addr->sllc_arphrd = skb->dev->type; addr->sllc_arphrd = skb->dev->type;
addr->sllc_test = prim == LLC_TEST_PRIM; addr->sllc_test = prim == LLC_TEST_PRIM;
addr->sllc_xid = prim == LLC_XID_PRIM; addr->sllc_xid = prim == LLC_XID_PRIM;
...@@ -189,7 +195,7 @@ static void llc_sap_state_process(struct llc_sap *sap, struct sk_buff *skb) ...@@ -189,7 +195,7 @@ static void llc_sap_state_process(struct llc_sap *sap, struct sk_buff *skb)
if (skb->sk->sk_state == TCP_LISTEN) if (skb->sk->sk_state == TCP_LISTEN)
kfree_skb(skb); kfree_skb(skb);
else { else {
llc_save_primitive(skb, ev->prim); llc_save_primitive(skb->sk, skb, ev->prim);
/* queue skb to the user. */ /* queue skb to the user. */
if (sock_queue_rcv_skb(skb->sk, skb)) if (sock_queue_rcv_skb(skb->sk, skb))
...@@ -308,7 +314,7 @@ void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb) ...@@ -308,7 +314,7 @@ void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb)
sk = llc_lookup_dgram(sap, &laddr); sk = llc_lookup_dgram(sap, &laddr);
if (sk) { if (sk) {
skb->sk = sk; skb_set_owner_r(skb, sk);
llc_sap_rcv(sap, skb); llc_sap_rcv(sap, skb);
sock_put(sk); sock_put(sk);
} else } else
......
...@@ -50,6 +50,10 @@ struct llc_station { ...@@ -50,6 +50,10 @@ struct llc_station {
struct sk_buff_head mac_pdu_q; struct sk_buff_head mac_pdu_q;
}; };
#define LLC_STATION_ACK_TIME (3 * HZ)
int sysctl_llc_station_ack_timeout = LLC_STATION_ACK_TIME;
/* Types of events (possible values in 'ev->type') */ /* Types of events (possible values in 'ev->type') */
#define LLC_STATION_EV_TYPE_SIMPLE 1 #define LLC_STATION_EV_TYPE_SIMPLE 1
#define LLC_STATION_EV_TYPE_CONDITION 2 #define LLC_STATION_EV_TYPE_CONDITION 2
...@@ -218,7 +222,8 @@ static void llc_station_send_pdu(struct sk_buff *skb) ...@@ -218,7 +222,8 @@ static void llc_station_send_pdu(struct sk_buff *skb)
static int llc_station_ac_start_ack_timer(struct sk_buff *skb) static int llc_station_ac_start_ack_timer(struct sk_buff *skb)
{ {
mod_timer(&llc_main_station.ack_timer, jiffies + LLC_ACK_TIME * HZ); mod_timer(&llc_main_station.ack_timer,
jiffies + sysctl_llc_station_ack_timeout);
return 0; return 0;
} }
...@@ -249,14 +254,14 @@ static int llc_station_ac_inc_xid_r_cnt_by_1(struct sk_buff *skb) ...@@ -249,14 +254,14 @@ static int llc_station_ac_inc_xid_r_cnt_by_1(struct sk_buff *skb)
static int llc_station_ac_send_null_dsap_xid_c(struct sk_buff *skb) static int llc_station_ac_send_null_dsap_xid_c(struct sk_buff *skb)
{ {
int rc = 1; int rc = 1;
struct sk_buff *nskb = llc_alloc_frame(); struct sk_buff *nskb = llc_alloc_frame(NULL, skb->dev);
if (!nskb) if (!nskb)
goto out; goto out;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, 0, LLC_PDU_CMD); llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, 0, LLC_PDU_CMD);
llc_pdu_init_as_xid_cmd(nskb, LLC_XID_NULL_CLASS_2, 127); llc_pdu_init_as_xid_cmd(nskb, LLC_XID_NULL_CLASS_2, 127);
rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, llc_station_mac_sa); rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, llc_station_mac_sa);
if (rc) if (unlikely(rc))
goto free; goto free;
llc_station_send_pdu(nskb); llc_station_send_pdu(nskb);
out: out:
...@@ -270,18 +275,17 @@ static int llc_station_ac_send_xid_r(struct sk_buff *skb) ...@@ -270,18 +275,17 @@ static int llc_station_ac_send_xid_r(struct sk_buff *skb)
{ {
u8 mac_da[ETH_ALEN], dsap; u8 mac_da[ETH_ALEN], dsap;
int rc = 1; int rc = 1;
struct sk_buff* nskb = llc_alloc_frame(); struct sk_buff* nskb = llc_alloc_frame(NULL, skb->dev);
if (!nskb) if (!nskb)
goto out; goto out;
rc = 0; rc = 0;
nskb->dev = skb->dev;
llc_pdu_decode_sa(skb, mac_da); llc_pdu_decode_sa(skb, mac_da);
llc_pdu_decode_ssap(skb, &dsap); llc_pdu_decode_ssap(skb, &dsap);
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP); llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP);
llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 127); llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 127);
rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, mac_da); rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, mac_da);
if (rc) if (unlikely(rc))
goto free; goto free;
llc_station_send_pdu(nskb); llc_station_send_pdu(nskb);
out: out:
...@@ -295,18 +299,17 @@ static int llc_station_ac_send_test_r(struct sk_buff *skb) ...@@ -295,18 +299,17 @@ static int llc_station_ac_send_test_r(struct sk_buff *skb)
{ {
u8 mac_da[ETH_ALEN], dsap; u8 mac_da[ETH_ALEN], dsap;
int rc = 1; int rc = 1;
struct sk_buff *nskb = llc_alloc_frame(); struct sk_buff *nskb = llc_alloc_frame(NULL, skb->dev);
if (!nskb) if (!nskb)
goto out; goto out;
rc = 0; rc = 0;
nskb->dev = skb->dev;
llc_pdu_decode_sa(skb, mac_da); llc_pdu_decode_sa(skb, mac_da);
llc_pdu_decode_ssap(skb, &dsap); llc_pdu_decode_ssap(skb, &dsap);
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP); llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP);
llc_pdu_init_as_test_rsp(nskb, skb); llc_pdu_init_as_test_rsp(nskb, skb);
rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, mac_da); rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, mac_da);
if (rc) if (unlikely(rc))
goto free; goto free;
llc_station_send_pdu(nskb); llc_station_send_pdu(nskb);
out: out:
...@@ -689,7 +692,8 @@ int __init llc_station_init(void) ...@@ -689,7 +692,8 @@ int __init llc_station_init(void)
init_timer(&llc_main_station.ack_timer); init_timer(&llc_main_station.ack_timer);
llc_main_station.ack_timer.data = (unsigned long)&llc_main_station; llc_main_station.ack_timer.data = (unsigned long)&llc_main_station;
llc_main_station.ack_timer.function = llc_station_ack_tmr_cb; llc_main_station.ack_timer.function = llc_station_ack_tmr_cb;
llc_main_station.ack_timer.expires = jiffies +
sysctl_llc_station_ack_timeout;
skb = alloc_skb(0, GFP_ATOMIC); skb = alloc_skb(0, GFP_ATOMIC);
if (!skb) if (!skb)
goto out; goto out;
...@@ -697,7 +701,6 @@ int __init llc_station_init(void) ...@@ -697,7 +701,6 @@ int __init llc_station_init(void)
llc_set_station_handler(llc_station_rcv); llc_set_station_handler(llc_station_rcv);
ev = llc_station_ev(skb); ev = llc_station_ev(skb);
memset(ev, 0, sizeof(*ev)); memset(ev, 0, sizeof(*ev));
llc_main_station.ack_timer.expires = jiffies + 3 * HZ;
llc_main_station.maximum_retry = 1; llc_main_station.maximum_retry = 1;
llc_main_station.state = LLC_STATION_STATE_DOWN; llc_main_station.state = LLC_STATION_STATE_DOWN;
ev->type = LLC_STATION_EV_TYPE_SIMPLE; ev->type = LLC_STATION_EV_TYPE_SIMPLE;
......
/*
* sysctl_net_llc.c: sysctl interface to LLC net subsystem.
*
* Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*/
#include <linux/config.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/sysctl.h>
#include <net/llc.h>
#ifndef CONFIG_SYSCTL
#error This file should not be compiled without CONFIG_SYSCTL defined
#endif
static struct ctl_table llc2_timeout_table[] = {
{
.ctl_name = NET_LLC2_ACK_TIMEOUT,
.procname = "ack",
.data = &sysctl_llc2_ack_timeout,
.maxlen = sizeof(long),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
.strategy = &sysctl_jiffies,
},
{
.ctl_name = NET_LLC2_BUSY_TIMEOUT,
.procname = "busy",
.data = &sysctl_llc2_busy_timeout,
.maxlen = sizeof(long),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
.strategy = &sysctl_jiffies,
},
{
.ctl_name = NET_LLC2_P_TIMEOUT,
.procname = "p",
.data = &sysctl_llc2_p_timeout,
.maxlen = sizeof(long),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
.strategy = &sysctl_jiffies,
},
{
.ctl_name = NET_LLC2_REJ_TIMEOUT,
.procname = "rej",
.data = &sysctl_llc2_rej_timeout,
.maxlen = sizeof(long),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
.strategy = &sysctl_jiffies,
},
{ 0 },
};
static struct ctl_table llc_station_table[] = {
{
.ctl_name = NET_LLC_STATION_ACK_TIMEOUT,
.procname = "ack_timeout",
.data = &sysctl_llc_station_ack_timeout,
.maxlen = sizeof(long),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
.strategy = &sysctl_jiffies,
},
{ 0 },
};
static struct ctl_table llc2_dir_timeout_table[] = {
{
.ctl_name = NET_LLC2,
.procname = "timeout",
.mode = 0555,
.child = llc2_timeout_table,
},
{ 0 },
};
static struct ctl_table llc_table[] = {
{
.ctl_name = NET_LLC2,
.procname = "llc2",
.mode = 0555,
.child = llc2_dir_timeout_table,
},
{
.ctl_name = NET_LLC_STATION,
.procname = "station",
.mode = 0555,
.child = llc_station_table,
},
{ 0 },
};
static struct ctl_table llc_dir_table[] = {
{
.ctl_name = NET_LLC,
.procname = "llc",
.mode = 0555,
.child = llc_table,
},
{ 0 },
};
static struct ctl_table llc_root_table[] = {
{
.ctl_name = CTL_NET,
.procname = "net",
.mode = 0555,
.child = llc_dir_table,
},
{ 0 },
};
static struct ctl_table_header *llc_table_header;
int __init llc_sysctl_init(void)
{
llc_table_header = register_sysctl_table(llc_root_table, 1);
return llc_table_header ? 0 : -ENOMEM;
}
void llc_sysctl_exit(void)
{
if (llc_table_header) {
unregister_sysctl_table(llc_table_header);
llc_table_header = NULL;
}
}
...@@ -761,12 +761,6 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -761,12 +761,6 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock,
if (dev->hard_header) { if (dev->hard_header) {
int res; int res;
err = -EINVAL; err = -EINVAL;
if (saddr) {
if (saddr->sll_halen != dev->addr_len)
goto out_free;
if (saddr->sll_hatype != dev->type)
goto out_free;
}
res = dev->hard_header(skb, dev, ntohs(proto), addr, NULL, len); res = dev->hard_header(skb, dev, ntohs(proto), addr, NULL, len);
if (sock->type != SOCK_DGRAM) { if (sock->type != SOCK_DGRAM) {
skb->tail = skb->data; skb->tail = skb->data;
......
...@@ -1700,7 +1700,9 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags) ...@@ -1700,7 +1700,9 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
struct socket *sock; struct socket *sock;
char address[MAX_SOCK_ADDR]; char address[MAX_SOCK_ADDR];
struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
unsigned char ctl[sizeof(struct cmsghdr) + 20]; /* 20 is size of ipv6_pktinfo */ unsigned char ctl[sizeof(struct cmsghdr) + 20]
__attribute__ ((aligned (sizeof(__kernel_size_t))));
/* 20 is size of ipv6_pktinfo */
unsigned char *ctl_buf = ctl; unsigned char *ctl_buf = ctl;
struct msghdr msg_sys; struct msghdr msg_sys;
int err, ctl_len, iov_size, total_len; int err, ctl_len, iov_size, total_len;
......
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