Commit f7402dc4 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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 @@ set_rcvbuf:
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,