Commit f7402dc4 authored by Linus Torvalds's avatar Linus Torvalds

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

parents e72225d1 832079d2
......@@ -191,6 +191,8 @@ static unsigned int cbc_process_encrypt(const struct cipher_desc *desc,
u8 *iv = desc->info;
unsigned int done = 0;
nbytes -= bsize;
do {
xor(iv, src);
fn(crypto_tfm_ctx(tfm), dst, iv);
......@@ -198,7 +200,7 @@ static unsigned int cbc_process_encrypt(const struct cipher_desc *desc,
src += bsize;
dst += bsize;
} while ((done += bsize) < nbytes);
} while ((done += bsize) <= nbytes);
return done;
}
......@@ -219,6 +221,8 @@ static unsigned int cbc_process_decrypt(const struct cipher_desc *desc,
u8 *iv = desc->info;
unsigned int done = 0;
nbytes -= bsize;
do {
u8 *tmp_dst = *dst_p;
......@@ -230,7 +234,7 @@ static unsigned int cbc_process_decrypt(const struct cipher_desc *desc,
src += bsize;
dst += bsize;
} while ((done += bsize) < nbytes);
} while ((done += bsize) <= nbytes);
return done;
}
......@@ -243,12 +247,14 @@ static unsigned int ecb_process(const struct cipher_desc *desc, u8 *dst,
void (*fn)(void *, u8 *, const u8 *) = desc->crfn;
unsigned int done = 0;
nbytes -= bsize;
do {
fn(crypto_tfm_ctx(tfm), dst, src);
src += bsize;
dst += bsize;
} while ((done += bsize) < nbytes);
} while ((done += bsize) <= nbytes);
return done;
}
......
......@@ -597,7 +597,7 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
struct ArcProto *proto;
int txbuf;
unsigned long flags;
int freeskb = 0;
int freeskb, retval;
BUGMSG(D_DURING,
"transmit requested (status=%Xh, txbufs=%d/%d, len=%d, protocol %x)\n",
......@@ -615,7 +615,7 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
if (skb->len - ARC_HDR_SIZE > XMTU && !proto->continue_tx) {
BUGMSG(D_NORMAL, "fixme: packet too large: compensating badly!\n");
dev_kfree_skb(skb);
return 0; /* don't try again */
return NETDEV_TX_OK; /* don't try again */
}
/* We're busy transmitting a packet... */
......@@ -623,8 +623,11 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
spin_lock_irqsave(&lp->lock, flags);
AINTMASK(0);
txbuf = get_arcbuf(dev);
if(lp->next_tx == -1)
txbuf = get_arcbuf(dev);
else {
txbuf = -1;
}
if (txbuf != -1) {
if (proto->prepare_tx(dev, pkt, skb->len, txbuf) &&
!proto->ack_tx) {
......@@ -638,6 +641,8 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
lp->outgoing.skb = skb;
lp->outgoing.pkt = pkt;
freeskb = 0;
if (proto->continue_tx &&
proto->continue_tx(dev, txbuf)) {
BUGMSG(D_NORMAL,
......@@ -645,10 +650,12 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
"(proto='%c')\n", proto->suffix);
}
}
retval = NETDEV_TX_OK;
dev->trans_start = jiffies;
lp->next_tx = txbuf;
} else {
freeskb = 1;
retval = NETDEV_TX_BUSY;
freeskb = 0;
}
BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__FUNCTION__,ASTATUS());
......@@ -664,7 +671,7 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
if (freeskb) {
dev_kfree_skb(skb);
}
return 0; /* no need to try again */
return retval; /* no need to try again */
}
......@@ -690,7 +697,6 @@ static int go_tx(struct net_device *dev)
/* start sending */
ACOMMAND(TXcmd | (lp->cur_tx << 3));
dev->trans_start = jiffies;
lp->stats.tx_packets++;
lp->lasttrans_dest = lp->lastload_dest;
lp->lastload_dest = 0;
......@@ -917,6 +923,9 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
BUGMSG(D_RECON, "Network reconfiguration detected (status=%Xh)\n",
status);
/* MYRECON bit is at bit 7 of diagstatus */
if(diagstatus & 0x80)
BUGMSG(D_RECON,"Put out that recon myself\n");
/* is the RECON info empty or old? */
if (!lp->first_recon || !lp->last_recon ||
......
......@@ -263,6 +263,9 @@ struct ip_conntrack_expect
/* Unique ID */
unsigned int id;
/* Flags */
unsigned int flags;
#ifdef CONFIG_IP_NF_NAT_NEEDED
/* This is the original per-proto part, used to map the
* expected connection the way the recipient expects. */
......@@ -272,6 +275,8 @@ struct ip_conntrack_expect
#endif
};
#define IP_CT_EXPECT_PERMANENT 0x1
static inline struct ip_conntrack *
tuplehash_to_ctrack(const struct ip_conntrack_tuple_hash *hash)
{
......
......@@ -52,7 +52,7 @@ static inline int ip_conntrack_confirm(struct sk_buff **pskb)
return ret;
}
extern void __ip_ct_expect_unlink_destroy(struct ip_conntrack_expect *exp);
extern void ip_ct_unlink_expect(struct ip_conntrack_expect *exp);
extern struct list_head *ip_conntrack_hash;
extern struct list_head ip_conntrack_expect_list;
......
......@@ -19,5 +19,10 @@ extern unsigned int
alloc_null_binding(struct ip_conntrack *conntrack,
struct ip_nat_info *info,
unsigned int hooknum);
extern unsigned int
alloc_null_binding_confirmed(struct ip_conntrack *conntrack,
struct ip_nat_info *info,
unsigned int hooknum);
#endif
#endif /* _IP_NAT_RULE_H */
......@@ -1251,7 +1251,7 @@ extern void skb_add_mtu(int mtu);
* This function converts the offset back to a struct timeval and stores
* it in stamp.
*/
static inline void skb_get_timestamp(struct sk_buff *skb, struct timeval *stamp)
static inline void skb_get_timestamp(const struct sk_buff *skb, struct timeval *stamp)
{
stamp->tv_sec = skb->tstamp.off_sec;
stamp->tv_usec = skb->tstamp.off_usec;
......@@ -1270,7 +1270,7 @@ static inline void skb_get_timestamp(struct sk_buff *skb, struct timeval *stamp)
* This function converts a struct timeval to an offset and stores
* it in the skb.
*/
static inline void skb_set_timestamp(struct sk_buff *skb, struct timeval *stamp)
static inline void skb_set_timestamp(struct sk_buff *skb, const struct timeval *stamp)
{
skb->tstamp.off_sec = stamp->tv_sec - skb_tv_base.tv_sec;
skb->tstamp.off_usec = stamp->tv_usec - skb_tv_base.tv_usec;
......
......@@ -257,7 +257,7 @@ extern struct sock *ax25_make_new(struct sock *, struct ax25_dev *);
/* ax25_addr.c */
extern ax25_address null_ax25_address;
extern char *ax2asc(ax25_address *);
extern char *ax2asc(char *buf, ax25_address *);
extern ax25_address *asc2ax(char *);
extern int ax25cmp(ax25_address *, ax25_address *);
extern int ax25digicmp(ax25_digi *, ax25_digi *);
......
......@@ -1874,6 +1874,7 @@ static void ax25_info_stop(struct seq_file *seq, void *v)
static int ax25_info_show(struct seq_file *seq, void *v)
{
ax25_cb *ax25 = v;
char buf[11];
int k;
......@@ -1885,13 +1886,13 @@ static int ax25_info_show(struct seq_file *seq, void *v)
seq_printf(seq, "%8.8lx %s %s%s ",
(long) ax25,
ax25->ax25_dev == NULL? "???" : ax25->ax25_dev->dev->name,
ax2asc(&ax25->source_addr),
ax2asc(buf, &ax25->source_addr),
ax25->iamdigi? "*":"");
seq_printf(seq, "%s", ax2asc(&ax25->dest_addr));
seq_printf(seq, "%s", ax2asc(buf, &ax25->dest_addr));
for (k=0; (ax25->digipeat != NULL) && (k < ax25->digipeat->ndigi); k++) {
seq_printf(seq, ",%s%s",
ax2asc(&ax25->digipeat->calls[k]),
ax2asc(buf, &ax25->digipeat->calls[k]),
ax25->digipeat->repeated[k]? "*":"");
}
......
......@@ -36,9 +36,8 @@ ax25_address null_ax25_address = {{0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00}};
/*
* ax25 -> ascii conversion
*/
char *ax2asc(ax25_address *a)
char *ax2asc(char *buf, ax25_address *a)
{
static char buf[11];
char c, *s;
int n;
......
......@@ -298,6 +298,8 @@ static void ax25_rt_seq_stop(struct seq_file *seq, void *v)
static int ax25_rt_seq_show(struct seq_file *seq, void *v)
{
char buf[11];
if (v == SEQ_START_TOKEN)
seq_puts(seq, "callsign dev mode digipeaters\n");
else {
......@@ -308,7 +310,7 @@ static int ax25_rt_seq_show(struct seq_file *seq, void *v)
if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0)
callsign = "default";
else
callsign = ax2asc(&ax25_rt->callsign);
callsign = ax2asc(buf, &ax25_rt->callsign);
seq_printf(seq, "%-9s %-4s",
callsign,
......@@ -328,7 +330,8 @@ static int ax25_rt_seq_show(struct seq_file *seq, void *v)
if (ax25_rt->digipeat != NULL)
for (i = 0; i < ax25_rt->digipeat->ndigi; i++)
seq_printf(seq, " %s", ax2asc(&ax25_rt->digipeat->calls[i]));
seq_printf(seq, " %s",
ax2asc(buf, &ax25_rt->digipeat->calls[i]));
seq_puts(seq, "\n");
}
......
......@@ -168,12 +168,14 @@ static void ax25_uid_seq_stop(struct seq_file *seq, void *v)
static int ax25_uid_seq_show(struct seq_file *seq, void *v)
{
char buf[11];
if (v == SEQ_START_TOKEN)
seq_printf(seq, "Policy: %d\n", ax25_uid_policy);
else {
struct ax25_uid_assoc *pt = v;
seq_printf(seq, "%6d %s\n", pt->uid, ax2asc(&pt->call));
seq_printf(seq, "%6d %s\n", pt->uid, ax2asc(buf, &pt->call));
}
return 0;
}
......
......@@ -341,11 +341,11 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
sock_reset_flag(sk, SOCK_LINGER);
else {
#if (BITS_PER_LONG == 32)
if (ling.l_linger >= MAX_SCHEDULE_TIMEOUT/HZ)
if ((unsigned int)ling.l_linger >= MAX_SCHEDULE_TIMEOUT/HZ)
sk->sk_lingertime = MAX_SCHEDULE_TIMEOUT;
else
#endif
sk->sk_lingertime = ling.l_linger * HZ;
sk->sk_lingertime = (unsigned int)ling.l_linger * HZ;
sock_set_flag(sk, SOCK_LINGER);
}
break;
......@@ -1529,6 +1529,8 @@ EXPORT_SYMBOL(proto_register);
void proto_unregister(struct proto *prot)
{
write_lock(&proto_list_lock);
list_del(&prot->node);
write_unlock(&proto_list_lock);
if (prot->slab != NULL) {
kmem_cache_destroy(prot->slab);
......@@ -1550,9 +1552,6 @@ void proto_unregister(struct proto *prot)
kfree(name);
prot->twsk_slab = NULL;
}
list_del(&prot->node);
write_unlock(&proto_list_lock);
}
EXPORT_SYMBOL(proto_unregister);
......
......@@ -457,7 +457,7 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
if (pskb_pull(skb, ihl) == NULL)
goto err;
if (pskb_trim(skb, end-offset))
if (pskb_trim_rcsum(skb, end-offset))
goto err;
/* Find out which fragments are in front and at the back of us
......
......@@ -34,6 +34,7 @@ config IP_NF_CT_ACCT
config IP_NF_CONNTRACK_MARK
bool 'Connection mark tracking support'
depends on IP_NF_CONNTRACK
help
This option enables support for connection marks, used by the
`CONNMARK' target and `connmark' match. Similar to the mark value
......@@ -85,6 +86,25 @@ config IP_NF_IRC
To compile it as a module, choose M here. If unsure, say Y.
config IP_NF_NETBIOS_NS
tristate "NetBIOS name service protocol support (EXPERIMENTAL)"
depends on IP_NF_CONNTRACK && EXPERIMENTAL
help
NetBIOS name service requests are sent as broadcast messages from an
unprivileged port and responded to with unicast messages to the
same port. This make them hard to firewall properly because connection
tracking doesn't deal with broadcasts. This helper tracks locally
originating NetBIOS name service requests and the corresponding
responses. It relies on correct IP address configuration, specifically
netmask and broadcast address. When properly configured, the output
of "ip address show" should look similar to this:
$ ip -4 address show eth0
4: eth0: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 1000
inet 172.16.2.252/24 brd 172.16.2.255 scope global eth0
To compile it as a module, choose M here. If unsure, say N.
config IP_NF_TFTP
tristate "TFTP protocol support"
depends on IP_NF_CONNTRACK
......
......@@ -21,6 +21,7 @@ obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o
# NAT helpers
obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
......
......@@ -108,6 +108,7 @@ static int help(struct sk_buff **pskb,
}
exp->expectfn = NULL;
exp->flags = 0;
exp->tuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
exp->tuple.src.u.tcp.port = 0;
......
......@@ -197,7 +197,7 @@ ip_ct_invert_tuple(struct ip_conntrack_tuple *inverse,
/* ip_conntrack_expect helper functions */
static void unlink_expect(struct ip_conntrack_expect *exp)
void ip_ct_unlink_expect(struct ip_conntrack_expect *exp)
{
ASSERT_WRITE_LOCK(&ip_conntrack_lock);
IP_NF_ASSERT(!timer_pending(&exp->timeout));
......@@ -207,18 +207,12 @@ static void unlink_expect(struct ip_conntrack_expect *exp)
ip_conntrack_expect_put(exp);
}
void __ip_ct_expect_unlink_destroy(struct ip_conntrack_expect *exp)
{
unlink_expect(exp);
ip_conntrack_expect_put(exp);
}
static void expectation_timed_out(unsigned long ul_expect)
{
struct ip_conntrack_expect *exp = (void *)ul_expect;
write_lock_bh(&ip_conntrack_lock);
unlink_expect(exp);
ip_ct_unlink_expect(exp);
write_unlock_bh(&ip_conntrack_lock);
ip_conntrack_expect_put(exp);
}
......@@ -264,10 +258,14 @@ find_expectation(const struct ip_conntrack_tuple *tuple)
master ct never got confirmed, we'd hold a reference to it
and weird things would happen to future packets). */
if (ip_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)
&& is_confirmed(i->master)
&& del_timer(&i->timeout)) {
unlink_expect(i);
return i;
&& is_confirmed(i->master)) {
if (i->flags & IP_CT_EXPECT_PERMANENT) {
atomic_inc(&i->use);
return i;
} else if (del_timer(&i->timeout)) {
ip_ct_unlink_expect(i);
return i;
}
}
}
return NULL;
......@@ -284,7 +282,7 @@ void ip_ct_remove_expectations(struct ip_conntrack *ct)
list_for_each_entry_safe(i, tmp, &ip_conntrack_expect_list, list) {
if (i->master == ct && del_timer(&i->timeout)) {
unlink_expect(i);
ip_ct_unlink_expect(i);
ip_conntrack_expect_put(i);
}
}
......@@ -925,7 +923,7 @@ void ip_conntrack_unexpect_related(struct ip_conntrack_expect *exp)
/* choose the the oldest expectation to evict */
list_for_each_entry_reverse(i, &ip_conntrack_expect_list, list) {
if (expect_matches(i, exp) && del_timer(&i->timeout)) {
unlink_expect(i);
ip_ct_unlink_expect(i);
write_unlock_bh(&ip_conntrack_lock);
ip_conntrack_expect_put(i);
return;
......@@ -934,6 +932,9 @@ void ip_conntrack_unexpect_related(struct ip_conntrack_expect *exp)
write_unlock_bh(&ip_conntrack_lock);
}
/* We don't increase the master conntrack refcount for non-fulfilled
* conntracks. During the conntrack destruction, the expectations are
* always killed before the conntrack itself */
struct ip_conntrack_expect *ip_conntrack_expect_alloc(struct ip_conntrack *me)
{
struct ip_conntrack_expect *new;
......@@ -944,17 +945,14 @@ struct ip_conntrack_expect *ip_conntrack_expect_alloc(struct ip_conntrack *me)
return NULL;
}
new->master = me;
atomic_inc(&new->master->ct_general.use);
atomic_set(&new->use, 1);
return new;
}
void ip_conntrack_expect_put(struct ip_conntrack_expect *exp)
{
if (atomic_dec_and_test(&exp->use)) {
ip_conntrack_put(exp->master);
if (atomic_dec_and_test(&exp->use))
kmem_cache_free(ip_conntrack_expect_cachep, exp);
}
}
static void ip_conntrack_expect_insert(struct ip_conntrack_expect *exp)
......@@ -982,7 +980,7 @@ static void evict_oldest_expect(struct ip_conntrack *master)
list_for_each_entry_reverse(i, &ip_conntrack_expect_list, list) {
if (i->master == master) {
if (del_timer(&i->timeout)) {
unlink_expect(i);
ip_ct_unlink_expect(i);
ip_conntrack_expect_put(i);
}
break;
......@@ -1099,7 +1097,7 @@ void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me)
/* Get rid of expectations */
list_for_each_entry_safe(exp, tmp, &ip_conntrack_expect_list, list) {
if (exp->master->helper == me && del_timer(&exp->timeout)) {
unlink_expect(exp);
ip_ct_unlink_expect(exp);
ip_conntrack_expect_put(exp);
}
}
......
......@@ -421,6 +421,7 @@ static int help(struct sk_buff **pskb,
{ 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFF }});
exp->expectfn = NULL;
exp->flags = 0;
/* Now, NAT might want to mangle the packet, and register the
* (possibly changed) expectation itself. */
......
......@@ -221,6 +221,7 @@ static int help(struct sk_buff **pskb,
{ { 0, { 0 } },
{ 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFF }});
exp->expectfn = NULL;
exp->flags = 0;
if (ip_nat_irc_hook)
ret = ip_nat_irc_hook(pskb, ctinfo,
addr_beg_p - ib_ptr,
......
/*
* NetBIOS name service broadcast connection tracking helper
*
* (c) 2005 Patrick McHardy <kaber@trash.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
/*
* This helper tracks locally originating NetBIOS name service
* requests by issuing permanent expectations (valid until
* timing out) matching all reply connections from the
* destination network. The only NetBIOS specific thing is
* actually the port number.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/inetdevice.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <net/route.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv4/ip_conntrack.h>
#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
MODULE_DESCRIPTION("NetBIOS name service broadcast connection tracking helper");
MODULE_LICENSE("GPL");
static unsigned int timeout = 3;
module_param(timeout, int, 0600);
MODULE_PARM_DESC(timeout, "timeout for master connection/replies in seconds");
static int help(struct sk_buff **pskb,
struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
{
struct ip_conntrack_expect *exp;
struct iphdr *iph = (*pskb)->nh.iph;
struct udphdr _uh, *uh;
struct rtable *rt = (struct rtable *)(*pskb)->dst;
struct in_device *in_dev;
u_int32_t mask = 0;
/* we're only interested in locally generated packets */
if ((*pskb)->sk == NULL)
goto out;
if (rt == NULL || !(rt->rt_flags & RTCF_BROADCAST))
goto out;
if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
goto out;
rcu_read_lock();
in_dev = __in_dev_get(rt->u.dst.dev);
if (in_dev != NULL) {
for_primary_ifa(in_dev) {
if (ifa->ifa_broadcast == iph->daddr) {
mask = ifa->ifa_mask;
break;
}
} endfor_ifa(in_dev);
}
rcu_read_unlock();
if (mask == 0)
goto out;
uh = skb_header_pointer(*pskb, iph->ihl * 4, sizeof(_uh), &_uh);
BUG_ON(uh == NULL);
exp = ip_conntrack_expect_alloc(ct);
if (exp == NULL)
goto out;
memset(&exp->tuple, 0, sizeof(exp->tuple));
exp->tuple.src.ip = iph->daddr & mask;
exp->tuple.dst.ip = iph->saddr;
exp->tuple.dst.u.udp.port = uh->source;
exp->tuple.dst.protonum = IPPROTO_UDP;
memset(&exp->mask, 0, sizeof(exp->mask));
exp->mask.src.ip = mask;
exp->mask.dst.ip = 0xFFFFFFFF;
exp->mask.dst.u.udp.port = 0xFFFF;
exp->mask.dst.protonum = 0xFF;
exp->expectfn = NULL;
exp->flags = IP_CT_EXPECT_PERMANENT;
ip_conntrack_expect_related(exp);
ip_conntrack_expect_put(exp);
ip_ct_refresh_acct(ct, ctinfo, NULL, timeout * HZ);
out:
return NF_ACCEPT;
}
static struct ip_conntrack_helper helper = {
.name = "netbios-ns",
.tuple = {
.src.u.udp.port = __constant_htons(137),
.dst.protonum = IPPROTO_UDP,
},
.mask = {
.src.u.udp.port = 0xFFFF,
.dst.protonum = 0xFF,
},
.max_expected = 1,
.me = THIS_MODULE,
.help = help,
};
static int __init init(void)
{
helper.timeout = timeout;
return ip_conntrack_helper_register(&helper);
}
static void __exit fini(void)
{
ip_conntrack_helper_unregister(&helper);
}
module_init(init);
module_exit(fini);
......@@ -1349,8 +1349,10 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
list_for_each_entry_safe(exp, tmp, &ip_conntrack_expect_list,
list) {
if (exp->master->helper == h
&& del_timer(&exp->timeout))
__ip_ct_expect_unlink_destroy(exp);
&& del_timer(&exp->timeout)) {
ip_ct_unlink_expect(exp);
ip_conntrack_expect_put(exp);
}
}
write_unlock(&ip_conntrack_lock);
} else {
......@@ -1358,8 +1360,10 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
write_lock_bh(&ip_conntrack_lock);
list_for_each_entry_safe(exp, tmp, &ip_conntrack_expect_list,
list) {
if (del_timer(&exp->timeout))
__ip_ct_expect_unlink_destroy(exp);
if (del_timer(&exp->timeout)) {
ip_ct_unlink_expect(exp);
ip_conntrack_expect_put(exp);
}
}
write_unlock_bh(&ip_conntrack_lock);
}
......@@ -1413,6 +1417,7 @@ ctnetlink_create_expect(struct nfattr *cda[])
}
exp->expectfn = NULL;
exp->flags = 0;
exp->master = ct;
memcpy(&exp->tuple, &tuple, sizeof(struct ip_conntrack_tuple));
memcpy(&exp->mask, &mask, sizeof(struct ip_conntrack_tuple));
......
......@@ -349,6 +349,7 @@ static int tcp_to_nfattr(struct sk_buff *skb, struct nfattr *nfa,
return 0;
nfattr_failure:
read_unlock_bh(&tcp_lock);
return -1;
}
#endif
......
......@@ -998,7 +998,7 @@ EXPORT_SYMBOL(ip_conntrack_expect_related);
EXPORT_SYMBOL(ip_conntrack_unexpect_related);
EXPORT_SYMBOL_GPL(ip_conntrack_expect_list);
EXPORT_SYMBOL_GPL(__ip_conntrack_expect_find);
EXPORT_SYMBOL_GPL(__ip_ct_expect_unlink_destroy);
EXPORT_SYMBOL_GPL(ip_ct_unlink_expect);
EXPORT_SYMBOL(ip_conntrack_tuple_taken);
EXPORT_SYMBOL(ip_ct_gather_frags);
......
......@@ -75,6 +75,7 @@ static int tftp_help(struct sk_buff **pskb,
exp->mask.dst.u.udp.port = 0xffff;
exp->mask.dst.protonum = 0xff;
exp->expectfn = NULL;
exp->flags = 0;
DEBUGP("expect: ");
DUMP_TUPLE(&exp->tuple);
......
......@@ -255,6 +255,27 @@ alloc_null_binding(struct ip_conntrack *conntrack,
return ip_nat_setup_info(conntrack, &range, hooknum);
}
unsigned int
alloc_null_binding_confirmed(struct ip_conntrack *conntrack,
struct ip_nat_info *info,
unsigned int hooknum)
{
u_int32_t ip
= (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
? conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip
: conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip);
u_int16_t all
= (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
? conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.all
: conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.all);
struct ip_nat_range range
= { IP_NAT_RANGE_MAP_IPS, ip, ip, { all }, { all } };
DEBUGP("Allocating NULL binding for confirmed %p (%u.%u.%u.%u)\n",
conntrack, NIPQUAD(ip));
return ip_nat_setup_info(conntrack, &range, hooknum);
}
int ip_nat_rule_find(struct sk_buff **pskb,
unsigned int hooknum,
const struct net_device *in,
......
......@@ -123,8 +123,12 @@ ip_nat_fn(unsigned int hooknum,
if (!ip_nat_initialized(ct, maniptype)) {
unsigned int ret;
/* LOCAL_IN hook doesn't have a chain! */
if (hooknum == NF_IP_LOCAL_IN)
if (unlikely(is_confirmed(ct)))
/* NAT module was loaded late */
ret = alloc_null_binding_confirmed(ct, info,
hooknum);
else if (hooknum == NF_IP_LOCAL_IN)
/* LOCAL_IN hook doesn't have a chain! */
ret = alloc_null_binding(ct, info, hooknum);
else
ret = ip_nat_rule_find(pskb, hooknum,
......
......@@ -371,6 +371,12 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
break;
case NFQNL_COPY_PACKET:
if (entry->skb->ip_summed == CHECKSUM_HW &&
(*errp = skb_checksum_help(entry->skb,
entry->info->outdev == NULL))) {
spin_unlock_bh(&queue->lock);
return NULL;
}
if (queue->copy_range == 0
|| queue->copy_range > entry->skb->len)
data_len = entry->skb->len;
......@@ -636,7 +642,7 @@ nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e)
if (!skb_make_writable(&e->skb, data_len))
return -ENOMEM;
memcpy(e->skb->data, data, data_len);
e->skb->ip_summed = CHECKSUM_NONE;
return 0;
}
......
......@@ -398,24 +398,13 @@ static int netlink_create(struct socket *sock, int protocol)
if (nl_table[protocol].registered &&
try_module_get(nl_table[protocol].module))
module = nl_table[protocol].module;
else
err = -EPROTONOSUPPORT;
groups = nl_table[protocol].groups;
netlink_unlock_table();
if (err || (err = __netlink_create(sock, protocol) < 0))
if ((err = __netlink_create(sock, protocol) < 0))
goto out_module;
nlk = nlk_sk(sock->sk);
nlk->groups = kmalloc(NLGRPSZ(groups), GFP_KERNEL);
if (nlk->groups == NULL) {
err = -ENOMEM;
goto out_module;
}
memset(nlk->groups, 0, NLGRPSZ(groups));
nlk->ngroups = groups;
nlk->module = module;
out:
return err;
......@@ -534,6 +523,29 @@ netlink_update_subscriptions(struct sock *sk, unsigned int subscriptions)
nlk->subscriptions = subscriptions;
}
static int netlink_alloc_groups(struct sock *sk)
{
struct netlink_sock *nlk = nlk_sk(sk);
unsigned int groups;
int err = 0;
netlink_lock_table();
groups = nl_table[sk->sk_protocol].groups;
if (!nl_table[sk->sk_protocol].registered)
err = -ENOENT;
netlink_unlock_table();
if (err)
return err;
nlk->groups = kmalloc(NLGRPSZ(groups), GFP_KERNEL);
if (nlk->groups == NULL)
return -ENOMEM;
memset(nlk->groups, 0, NLGRPSZ(groups));
nlk->ngroups = groups;
return 0;
}
static int netlink_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
{
struct sock *sk = sock->sk;
......@@ -545,8 +557,15 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, int addr_len
return -EINVAL;
/* Only superuser is allowed to listen multicasts */
if (nladdr->nl_groups && !netlink_capable(sock, NL_NONROOT_RECV))
return -EPERM;
if (nladdr->nl_groups) {
if (!netlink_capable(sock, NL_NONROOT_RECV))
return -EPERM;
if (nlk->groups == NULL) {
err = netlink_alloc_groups(sk);
if (err)
return err;
}
}
if (nlk->pid) {
if (nladdr->nl_pid != nlk->pid)
......@@ -559,7 +578,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, int addr_len
return err;
}
if (!nladdr->nl_groups && !(u32)nlk->groups[0])
if (!nladdr->nl_groups && (nlk->groups == NULL || !(u32)nlk->groups[0]))
return 0;
netlink_table_grab();
......@@ -620,7 +639,7 @@ static int netlink_getname(struct socket *sock, struct sockaddr *addr, int *addr
nladdr->nl_groups = netlink_group_mask(nlk->dst_group);
} else {
nladdr->nl_pid = nlk->pid;
nladdr->nl_groups = nlk->groups[0];
nladdr->nl_groups = nlk->groups ? nlk->groups[0] : 0;
}
return 0;
}
......@@ -976,6 +995,11 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname,
if (!netlink_capable(sock, NL_NONROOT_RECV))
return -EPERM;
if (nlk->groups == NULL) {
err = netlink_alloc_groups(sk);
if (err)
return err;
}
if (!val || val - 1 >= nlk->ngroups)
return -EINVAL;
netlink_table_grab();
......@@ -1483,8 +1507,7 @@ static int netlink_seq_show(struct seq_file *seq, void *v)
s,
s->sk_protocol,
nlk->pid,
nlk->flags & NETLINK_KERNEL_SOCKET ?
0 : (unsigned int)nlk->groups[0],
nlk->groups ? (u32)nlk->groups[0] : 0,
atomic_read(&s->sk_rmem_alloc),
atomic_read(&s->sk_wmem_alloc),
nlk->cb,
......
......@@ -1261,6 +1261,7 @@ static int nr_info_show(struct seq_file *seq, void *v)
struct net_device *dev;
struct nr_sock *nr;
const char *devname;
char buf[11];
if (v == SEQ_START_TOKEN)
seq_puts(seq,
......@@ -1276,11 +1277,11 @@ static int nr_info_show(struct seq_file *seq, void *v)
else
devname = dev->name;
seq_printf(seq, "%-9s ", ax2asc(&nr->user_addr));
seq_printf(seq, "%-9s ", ax2asc(&nr->dest_addr));
seq_printf(seq, "%-9s ", ax2asc(buf, &nr->user_addr));
seq_printf(seq, "%-9s ", ax2asc(buf, &nr->dest_addr));
seq_printf(seq,
"%-9s %-3s %02X/%02X %02X/%02X %2d %3d %3d %3d %3lu/%03lu %2lu/%02lu %3lu/%03lu %3lu/%03lu %2d/%02d %3d %5d %5d %ld\n",
ax2asc(&nr->source_addr),
ax2asc(buf, &nr->source_addr),
devname,
nr->my_index,
nr->my_id,
......
......@@ -881,6 +881,7 @@ static void nr_node_stop(struct seq_file *seq, void *v)
static int nr_node_show(struct seq_file *seq, void *v)
{
char buf[11];
int i;
if (v == SEQ_START_TOKEN)
......@@ -890,7 +891,7 @@ static int nr_node_show(struct seq_file *seq, void *v)
struct nr_node *nr_node = v;
nr_node_lock(nr_node);
seq_printf(seq, "%-9s %-7s %d %d",
ax2asc(&nr_node->callsign),
ax2asc(buf, &nr_node->callsign),
(nr_node->mnemonic[0] == '\0') ? "*" : nr_node->mnemonic,
nr_node->which + 1,
nr_node->count);
......@@ -964,6 +965,7 @@ static void nr_neigh_stop(struct seq_file *seq, void *v)
static int nr_neigh_show(struct seq_file *seq, void *v)
{
char buf[11];
int i;
if (v == SEQ_START_TOKEN)
......@@ -973,7 +975,7 @@ static int nr_neigh_show(struct seq_file *seq, void *v)
seq_printf(seq, "%05d %-9s %-4s %3d %d %3d %3d",
nr_neigh->number,
ax2asc(&nr_neigh->callsign),
ax2asc(buf, &nr_neigh->callsign),
nr_neigh->dev ? nr_neigh->dev->name : "???",
nr_neigh->quality,
nr_neigh->locked,
......@@ -983,7 +985,7 @@ static int nr_neigh_show(struct seq_file *seq, void *v)
if (nr_neigh->digipeat != NULL) {
for (i = 0; i < nr_neigh->digipeat->ndigi; i++)
seq_printf(seq, " %s",
ax2asc(&nr_neigh->digipeat->calls[i]));
ax2asc(buf, &nr_neigh->digipeat->calls[i]));
}
seq_puts(seq, "\n");
......
......@@ -1535,8 +1535,7 @@ static unsigned int packet_poll(struct file * file, struct socket *sock,
static void packet_mm_open(struct vm_area_struct *vma)
{
struct file *file = vma->vm_file;
struct inode *inode = file->f_dentry->d_inode;
struct socket * sock = SOCKET_I(inode);
struct socket * sock = file->private_data;
struct sock *sk = sock->sk;
if (sk)
......@@ -1546,8 +1545,7 @@ static void packet_mm_open(struct vm_area_struct *vma)
static void packet_mm_close(struct vm_area_struct *vma)
{
struct file *file = vma->vm_file;
struct inode *inode = file->f_dentry->d_inode;
struct socket * sock = SOCKET_I(inode);
struct socket * sock = file->private_data;
struct sock *sk = sock->sk;
if (sk)
......
......@@ -1363,6 +1363,8 @@ static void rose_info_stop(struct seq_file *seq, void *v)
static int rose_info_show(struct seq_file *seq, void *v)
{
char buf[11];
if (v == SEQ_START_TOKEN)
seq_puts(seq,
"dest_addr dest_call src_addr src_call dev lci neigh st vs vr va t t1 t2 t3 hb idle Snd-Q Rcv-Q inode\n");
......@@ -1380,12 +1382,12 @@ static int rose_info_show(struct seq_file *seq, void *v)
seq_printf(seq, "%-10s %-9s ",
rose2asc(&rose->dest_addr),
ax2asc(&rose->dest_call));
ax2asc(buf, &rose->dest_call));
if (ax25cmp(&rose->source_call, &null_ax25_address) == 0)
callsign = "??????-?";
else
callsign = ax2asc(&rose->source_call);
callsign = ax2asc(buf, &rose->source_call);
seq_printf(seq,
"%-10s %-9s %-5s %3.3X %05d %d %d %d %d %3lu %3lu %3lu %3lu %3lu %3lu/%03lu %5d %5d %ld\n",
......
......@@ -851,6 +851,7 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
unsigned char cause, diagnostic;
struct net_device *dev;
int len, res = 0;
char buf[11];
#if 0
if (call_in_firewall(PF_ROSE, skb->dev, skb->data, NULL, &skb) != FW_ACCEPT)
......@@ -876,7 +877,7 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
if (rose_neigh == NULL) {
printk("rose_route : unknown neighbour or device %s\n",
ax2asc(&ax25->dest_addr));
ax2asc(buf, &ax25->dest_addr));
goto out;
}
......@@ -1178,6 +1179,7 @@ static void rose_neigh_stop(struct seq_file *seq, void *v)
static int rose_neigh_show(struct seq_file *seq, void *v)
{
char buf[11];
int i;
if (v == SEQ_START_TOKEN)
......@@ -1189,7 +1191,7 @@ static int rose_neigh_show(struct seq_file *seq, void *v)
/* if (!rose_neigh->loopback) { */
seq_printf(seq, "%05d %-9s %-4s %3d %3d %3s %3s %3lu %3lu",
rose_neigh->number,
(rose_neigh->loopback) ? "RSLOOP-0" : ax2asc(&rose_neigh->callsign),
(rose_neigh->loopback) ? "RSLOOP-0" : ax2asc(buf, &rose_neigh->callsign),
rose_neigh->dev ? rose_neigh->dev->name : "???",
rose_neigh->count,
rose_neigh->use,
......@@ -1200,7 +1202,7 @@ static int rose_neigh_show(struct seq_file *seq, void *v)
if (rose_neigh->digipeat != NULL) {
for (i = 0; i < rose_neigh->digipeat->ndigi; i++)
seq_printf(seq, " %s", ax2asc(&rose_neigh->digipeat->calls[i]));
seq_printf(seq, " %s", ax2asc(buf, &rose_neigh->digipeat->calls[i]));
}
seq_puts(seq, "\n");
......@@ -1260,6 +1262,8 @@ static void rose_route_stop(struct seq_file *seq, void *v)
static int rose_route_show(struct seq_file *seq, void *v)
{
char buf[11];
if (v == SEQ_START_TOKEN)
seq_puts(seq,
"lci address callsign neigh <-> lci address callsign neigh\n");
......@@ -1271,7 +1275,7 @@ static int rose_route_show(struct seq_file *seq, void *v)
"%3.3X %-10s %-9s %05d ",
rose_route->lci1,
rose2asc(&rose_route->src_addr),
ax2asc(&rose_route->src_call),
ax2asc(buf, &rose_route->src_call),
rose_route->neigh1->number);
else
seq_puts(seq,
......@@ -1282,7 +1286,7 @@ static int rose_route_show(struct seq_file *seq, void *v)
"%3.3X %-10s %-9s %05d\n",
rose_route->lci2,
rose2asc(&rose_route->dest_addr),
ax2asc(&rose_route->dest_call),
ax2asc(buf, &rose_route->dest_call),
rose_route->neigh2->number);
else
seq_puts(seq,
......
......@@ -400,6 +400,7 @@ static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose)
{
unsigned char *p = buffer + 1;
char *callsign;
char buf[11];
int len, nb;
/* National Facilities */
......@@ -456,7 +457,7 @@ static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose)
*p++ = FAC_CCITT_DEST_NSAP;
callsign = ax2asc(&rose->dest_call);
callsign = ax2asc(buf, &rose->dest_call);
*p++ = strlen(callsign) + 10;
*p++ = (strlen(callsign) + 9) * 2; /* ??? */
......@@ -471,7 +472,7 @@ static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose)
*p++ = FAC_CCITT_SRC_NSAP;
callsign = ax2asc(&rose->source_call);
callsign = ax2asc(buf, &rose->source_call);
*p++ = strlen(callsign) + 10;
*p++ = (strlen(callsign) + 9) * 2; /* ??? */
......
......@@ -667,7 +667,7 @@ static ssize_t sock_aio_read(struct kiocb *iocb, char __user *ubuf,
}
iocb->private = x;
x->kiocb = iocb;
sock = SOCKET_I(iocb->ki_filp->f_dentry->d_inode);
sock = iocb->ki_filp->private_data;
x->async_msg.msg_name = NULL;
x->async_msg.msg_namelen = 0;
......@@ -709,7 +709,7 @@ static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *ubuf,
}
iocb->private = x;
x->kiocb = iocb;
sock = SOCKET_I(iocb->ki_filp->f_dentry->d_inode);
sock = iocb->ki_filp->private_data;
x->async_msg.msg_name = NULL;
x->async_msg.msg_namelen = 0;
......@@ -732,7 +732,7 @@ static ssize_t sock_sendpage(struct file *file, struct page *page,
struct socket *sock;
int flags;
sock = SOCKET_I(file->f_dentry->d_inode);
sock = file->private_data;
flags = !(file->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT;
if (more)
......@@ -741,14 +741,14 @@ static ssize_t sock_sendpage(struct file *file, struct page *page,
return sock->ops->sendpage(sock, page, offset, size, flags);
}
static int sock_readv_writev(int type, struct inode * inode,
static int sock_readv_writev(int type,
struct file * file, const struct iovec * iov,
long count, size_t size)
{
struct msghdr msg;
struct socket *sock;
sock = SOCKET_I(inode);
sock = file->private_data;
msg.msg_name = NULL;
msg.msg_namelen = 0;
......@@ -775,7 +775,7 @@ static ssize_t sock_readv(struct file *file, const struct iovec *vector,
int i;
for (i = 0 ; i < count ; i++)
tot_len += vector[i].iov_len;
return sock_readv_writev(VERIFY_WRITE, file->f_dentry->d_inode,
return sock_readv_writev(VERIFY_WRITE,
file, vector, count, tot_len);
}
......@@ -786,7 +786,7 @@ static ssize_t sock_writev(struct file *file, const struct iovec *vector,
int i;
for (i = 0 ; i < count ; i++)
tot_len += vector[i].iov_len;
return sock_readv_writev(VERIFY_READ, file->f_dentry->d_inode,
return sock_readv_writev(VERIFY_READ,
file, vector, count, tot_len);
}
......@@ -840,7 +840,7 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
void __user *argp = (void __user *)arg;
int pid, err;
sock = SOCKET_I(file->f_dentry->d_inode);
sock = file->private_data;
if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
err = dev_ioctl(cmd, argp);
} else
......@@ -939,13 +939,13 @@ static unsigned int sock_poll(struct file *file, poll_table * wait)
/*
* We can't return errors to poll, so it's either yes or no.
*/
sock = SOCKET_I(file->f_dentry->d_inode);
sock = file->private_data;
return sock->ops->poll(file, sock, wait);
}
static int sock_mmap(struct file * file, struct vm_area_struct * vma)
{
struct socket *sock = SOCKET_I(file->f_dentry->d_inode);
struct socket *sock = file->private_data;
return sock->ops->mmap(file, sock, vma);
}
......@@ -995,7 +995,7 @@ static int sock_fasync(int fd, struct file *filp, int on)
return -ENOMEM;
}
sock = SOCKET_I(filp->f_dentry->d_inode);
sock = filp->private_data;
if ((sk=sock->sk) == NULL) {
kfree(fna);
......
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