Commit b015a5c0 authored by David S. Miller's avatar David S. Miller

Merge nuts.davemloft.net:/disk1/BK/net-exp-2.6

into nuts.davemloft.net:/disk1/BK/net-2.6
parents 101c46b5 b9b78dbe
......@@ -182,7 +182,7 @@ config CRYPTO_TEA
many rounds for security. It is very fast and uses
little memory.
Xtendend Tiny Encryption Algorithm is a modifcation to
Xtendend Tiny Encryption Algorithm is a modification to
the TEA algorithm to address a potential key weakness
in the TEA algorithm.
......
......@@ -160,7 +160,7 @@ gen_tabs (void)
u8 p, q;
/* log and power tables for GF(2**8) finite field with
0x011b as modular polynomial - the simplest prmitive
0x011b as modular polynomial - the simplest primitive
root is 0x03, used here to generate the tables */
for (i = 0, p = 1; i < 256; ++i) {
......
......@@ -3,7 +3,7 @@
*
* ARC4 Cipher Algorithm
*
* Jon Oberheide <jon@focalhost.com>
* Jon Oberheide <jon@oberheide.org>
*
* 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
......@@ -100,4 +100,4 @@ module_exit(arc4_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("ARC4 Cipher Algorithm");
MODULE_AUTHOR("Jon Oberheide <jon@focalhost.com>");
MODULE_AUTHOR("Jon Oberheide <jon@oberheide.org>");
......@@ -3,9 +3,9 @@
*
* Blowfish Cipher Algorithm, by Bruce Schneier.
* http://www.counterpane.com/blowfish.html
*
* Adapated from Kerneli implementation.
*
*
* Adapted from Kerneli implementation.
*
* Copyright (c) Herbert Valerio Riedel <hvr@hvrlab.org>
* Copyright (c) Kyle McMartin <kyle@debian.org>
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
......
......@@ -70,7 +70,7 @@ static void scatterwalk_pagedone(struct scatter_walk *walk, int out,
{
/* walk->data may be pointing the first byte of the next page;
however, we know we transfered at least one byte. So,
walk->data - 1 will be a virutual address in the mapped page. */
walk->data - 1 will be a virtual address in the mapped page. */
if (out)
flush_dcache_page(walk->page);
......
......@@ -1186,7 +1186,7 @@ struct cipher_testvec tf_cbc_dec_tv_template[] = {
/*
* Serpent test vectors. These are backwards because Serpent writes
* octect sequences in right-to-left mode.
* octet sequences in right-to-left mode.
*/
#define SERPENT_ENC_TEST_VECTORS 4
#define SERPENT_DEC_TEST_VECTORS 4
......
/*
* Twofish for CryptoAPI
*
* Originaly Twofish for GPG
* Originally Twofish for GPG
* By Matthew Skala <mskala@ansuz.sooke.bc.ca>, July 26, 1998
* 256-bit key length added March 20, 1999
* Some modifications to reduce the text size by Werner Koch, April, 1998
......@@ -514,7 +514,7 @@ static const u8 calc_sb_tbl[512] = {
* preprocessed through q0 and q1 respectively; for longer keys they are the
* output of previous stages. j is the index of the first key byte to use.
* CALC_K computes a pair of subkeys for 128-bit Twofish, by calling CALC_K_2
* twice, doing the Psuedo-Hadamard Transform, and doing the necessary
* twice, doing the Pseudo-Hadamard Transform, and doing the necessary
* rotations. Its parameters are: a, the array to write the results into,
* j, the index of the first output entry, k and l, the preprocessed indices
* for index 2i, and m and n, the preprocessed indices for index 2i+1.
......
......@@ -50,6 +50,7 @@
#include <linux/random.h>
#include <linux/pkt_sched.h>
#include <linux/spinlock.h>
#include <linux/rcupdate.h>
#include <net/syncppp.h>
......@@ -767,9 +768,9 @@ static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb)
struct in_ifaddr *ifa;
u32 addr = 0, mask = ~0; /* FIXME: is the mask correct? */
#ifdef CONFIG_INET
if ((in_dev=in_dev_get(dev)) != NULL)
rcu_read_lock();
if ((in_dev = __in_dev_get(dev)) != NULL)
{
read_lock(&in_dev->lock);
for (ifa=in_dev->ifa_list; ifa != NULL;
ifa=ifa->ifa_next) {
if (strcmp(dev->name, ifa->ifa_label) == 0)
......@@ -779,9 +780,8 @@ static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb)
break;
}
}
read_unlock(&in_dev->lock);
in_dev_put(in_dev);
}
rcu_read_unlock();
#endif
/* I hope both addr and mask are in the net order */
sppp_cisco_send (sp, CISCO_ADDR_REPLY, addr, mask);
......
......@@ -106,6 +106,7 @@ static const char StripVersion[] = "1.3A-STUART.CHESHIRE";
#include <linux/seq_file.h>
#include <linux/serial.h>
#include <linux/serialP.h>
#include <linux/rcupdate.h>
#include <net/arp.h>
#include <linux/ip.h>
......@@ -1348,14 +1349,17 @@ static unsigned char *strip_make_packet(unsigned char *buffer,
*/
if (haddr.c[0] == 0xFF) {
u32 brd = 0;
struct in_device *in_dev = in_dev_get(strip_info->dev);
if (in_dev == NULL)
struct in_device *in_dev;
rcu_read_lock();
in_dev = __in_dev_get(strip_info->dev);
if (in_dev == NULL) {
rcu_read_unlock();
return NULL;
read_lock(&in_dev->lock);
}
if (in_dev->ifa_list)
brd = in_dev->ifa_list->ifa_broadcast;
read_unlock(&in_dev->lock);
in_dev_put(in_dev);
rcu_read_unlock();
/* arp_query returns 1 if it succeeds in looking up the address, 0 if it fails */
if (!arp_query(haddr.c, brd, strip_info->dev)) {
......@@ -1500,17 +1504,18 @@ static void strip_send(struct strip *strip_info, struct sk_buff *skb)
}
if (1) {
struct in_device *in_dev = in_dev_get(strip_info->dev);
struct in_device *in_dev;
brd = addr = 0;
rcu_read_lock();
in_dev = __in_dev_get(strip_info->dev);
if (in_dev) {
read_lock(&in_dev->lock);
if (in_dev->ifa_list) {
brd = in_dev->ifa_list->ifa_broadcast;
addr = in_dev->ifa_list->ifa_local;
}
read_unlock(&in_dev->lock);
in_dev_put(in_dev);
}
rcu_read_unlock();
}
......
......@@ -1002,7 +1002,7 @@ lcs_register_mc_addresses(void *data)
in4_dev = in_dev_get(card->dev);
if (in4_dev == NULL)
return 0;
read_lock(&in4_dev->lock);
read_lock(&in4_dev->mc_list_lock);
spin_lock(&card->ipm_lock);
/* Check for multicast addresses to be removed. */
list_for_each(l, &card->ipm_list) {
......@@ -1046,7 +1046,7 @@ lcs_register_mc_addresses(void *data)
list_add(&ipm->list, &card->ipm_list);
}
spin_unlock(&card->ipm_lock);
read_unlock(&in4_dev->lock);
read_unlock(&in4_dev->mc_list_lock);
in_dev_put(in4_dev);
lcs_fix_multicast_list(card);
return 0;
......
......@@ -73,6 +73,7 @@ qeth_eyecatcher(void)
#include <linux/reboot.h>
#include <asm/qeth.h>
#include <linux/mii.h>
#include <linux/rcupdate.h>
#include "qeth.h"
#include "qeth_mpc.h"
......@@ -4733,9 +4734,10 @@ qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid)
QETH_DBF_TEXT(trace, 4, "frvaddr4");
if (!card->vlangrp)
return;
in_dev = in_dev_get(card->vlangrp->vlan_devices[vid]);
rcu_read_lock();
in_dev = __in_dev_get(card->vlangrp->vlan_devices[vid]);
if (!in_dev)
return;
goto out;
for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next){
addr = qeth_get_addr_buffer(QETH_PROT_IPV4);
if (addr){
......@@ -4746,7 +4748,8 @@ qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid)
kfree(addr);
}
}
in_dev_put(in_dev);
out:
rcu_read_unlock();
}
static void
......@@ -4918,9 +4921,9 @@ qeth_add_vlan_mc(struct qeth_card *card)
in_dev = in_dev_get(vg->vlan_devices[i]);
if (!in_dev)
continue;
read_lock(&in_dev->lock);
read_lock(&in_dev->mc_list_lock);
qeth_add_mc(card,in_dev);
read_unlock(&in_dev->lock);
read_unlock(&in_dev->mc_list_lock);
in_dev_put(in_dev);
}
#endif
......@@ -4935,10 +4938,10 @@ qeth_add_multicast_ipv4(struct qeth_card *card)
in4_dev = in_dev_get(card->dev);
if (in4_dev == NULL)
return;
read_lock(&in4_dev->lock);
read_lock(&in4_dev->mc_list_lock);
qeth_add_mc(card, in4_dev);
qeth_add_vlan_mc(card);
read_unlock(&in4_dev->lock);
read_unlock(&in4_dev->mc_list_lock);
in_dev_put(in4_dev);
}
......
......@@ -3,6 +3,8 @@
#ifdef __KERNEL__
#include <linux/rcupdate.h>
struct ipv4_devconf
{
int accept_redirects;
......@@ -31,13 +33,13 @@ extern struct ipv4_devconf ipv4_devconf;
struct in_device
{
struct net_device *dev;
struct net_device *dev;
atomic_t refcnt;
rwlock_t lock;
int dead;
struct in_ifaddr *ifa_list; /* IP ifaddr chain */
rwlock_t mc_list_lock;
struct ip_mc_list *mc_list; /* IP multicast filter chain */
rwlock_t mc_lock; /* for mc_tomb */
spinlock_t mc_tomb_lock;
struct ip_mc_list *mc_tomb;
unsigned long mr_v1_seen;
unsigned long mr_v2_seen;
......@@ -50,6 +52,7 @@ struct in_device
struct neigh_parms *arp_parms;
struct ipv4_devconf cnf;
struct rcu_head rcu_head;
};
#define IN_DEV_FORWARD(in_dev) ((in_dev)->cnf.forwarding)
......@@ -80,6 +83,7 @@ struct in_ifaddr
{
struct in_ifaddr *ifa_next;
struct in_device *ifa_dev;
struct rcu_head rcu_head;
u32 ifa_local;
u32 ifa_address;
u32 ifa_mask;
......@@ -133,19 +137,16 @@ static __inline__ int bad_mask(u32 mask, u32 addr)
#define endfor_ifa(in_dev) }
extern rwlock_t inetdev_lock;
static __inline__ struct in_device *
in_dev_get(const struct net_device *dev)
{
struct in_device *in_dev;
read_lock(&inetdev_lock);
rcu_read_lock();
in_dev = dev->ip_ptr;
if (in_dev)
atomic_inc(&in_dev->refcnt);
read_unlock(&inetdev_lock);
rcu_read_unlock();
return in_dev;
}
......@@ -157,8 +158,7 @@ __in_dev_get(const struct net_device *dev)
extern void in_dev_finish_destroy(struct in_device *idev);
static __inline__ void
in_dev_put(struct in_device *idev)
static inline void in_dev_put(struct in_device *idev)
{
if (atomic_dec_and_test(&idev->refcnt))
in_dev_finish_destroy(idev);
......
......@@ -169,6 +169,7 @@ extern struct socket *sockfd_lookup(int fd, int *err);
extern int net_ratelimit(void);
extern unsigned long net_random(void);
extern void net_srandom(unsigned long);
extern void net_random_init(void);
extern int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
struct kvec *vec, size_t num, size_t len);
......
......@@ -242,7 +242,6 @@ extern u32 fib_rules_map_destination(u32 daddr, struct fib_result *res);
#ifdef CONFIG_NET_CLS_ROUTE
extern u32 fib_rules_tclass(struct fib_result *res);
#endif
extern u32 fib_rules_policy(u32 saddr, struct fib_result *res, unsigned *flags);
extern void fib_rules_init(void);
#endif
......
......@@ -73,11 +73,6 @@ struct rtable
/* Miscellaneous cached information */
__u32 rt_spec_dst; /* RFC1122 specific destination */
struct inet_peer *peer; /* long-living peer info */
#ifdef CONFIG_IP_ROUTE_NAT
__u32 rt_src_map;
__u32 rt_dst_map;
#endif
};
struct ip_rt_acct
......
......@@ -21,13 +21,14 @@
#include <linux/if_ether.h>
#include <linux/if_vlan.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/netfilter_bridge/ebtables.h>
#include <linux/netfilter_bridge/ebt_vlan.h>
static unsigned char debug;
static int debug;
#define MODULE_VERS "0.6"
MODULE_PARM(debug, "0-1b");
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "debug=1 is turn on debug messages");
MODULE_AUTHOR("Nick Fedchik <nick@fedchik.org.ua>");
MODULE_DESCRIPTION("802.1Q match module (ebtables extension), v"
......
......@@ -3280,6 +3280,8 @@ static int __init net_dev_init(void)
BUG_ON(!dev_boot_phase);
net_random_init();
if (dev_proc_init())
goto out;
......
......@@ -18,6 +18,7 @@
#include <linux/interrupt.h>
#include <linux/netpoll.h>
#include <linux/sched.h>
#include <linux/rcupdate.h>
#include <net/tcp.h>
#include <net/udp.h>
......@@ -572,16 +573,18 @@ int netpoll_setup(struct netpoll *np)
memcpy(np->local_mac, ndev->dev_addr, 6);
if (!np->local_ip) {
in_dev = in_dev_get(ndev);
rcu_read_lock();
in_dev = __in_dev_get(ndev);
if (!in_dev) {
rcu_read_unlock();
printk(KERN_ERR "%s: no IP address for %s, aborting\n",
np->name, np->dev_name);
goto release;
}
np->local_ip = ntohl(in_dev->ifa_list->ifa_local);
in_dev_put(in_dev);
rcu_read_unlock();
printk(KERN_INFO "%s: local IP %d.%d.%d.%d\n",
np->name, HIPQUAD(np->local_ip));
}
......
......@@ -70,6 +70,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/inet.h>
#include <linux/rcupdate.h>
#include <asm/byteorder.h>
#include <asm/bitops.h>
#include <asm/io.h>
......@@ -263,14 +264,17 @@ static struct net_device *setup_inject(struct pktgen_info* info)
info->saddr_min = 0;
info->saddr_max = 0;
if (strlen(info->src_min) == 0) {
struct in_device *in_dev = in_dev_get(odev);
struct in_device *in_dev;
rcu_read_lock();
in_dev = __in_dev_get(odev);
if (in_dev) {
if (in_dev->ifa_list) {
info->saddr_min = in_dev->ifa_list->ifa_address;
info->saddr_max = info->saddr_min;
}
in_dev_put(in_dev);
}
rcu_read_unlock();
}
else {
info->saddr_min = in_aton(info->src_min);
......
......@@ -19,22 +19,116 @@
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/random.h>
#include <linux/percpu.h>
#include <asm/system.h>
#include <asm/uaccess.h>
static unsigned long net_rand_seed = 152L;
/*
This is a maximally equidistributed combined Tausworthe generator
based on code from GNU Scientific Library 1.5 (30 Jun 2004)
x_n = (s1_n ^ s2_n ^ s3_n)
s1_{n+1} = (((s1_n & 4294967294) <<12) ^ (((s1_n <<13) ^ s1_n) >>19))
s2_{n+1} = (((s2_n & 4294967288) << 4) ^ (((s2_n << 2) ^ s2_n) >>25))
s3_{n+1} = (((s3_n & 4294967280) <<17) ^ (((s3_n << 3) ^ s3_n) >>11))
The period of this generator is about 2^88.
From: P. L'Ecuyer, "Maximally Equidistributed Combined Tausworthe
Generators", Mathematics of Computation, 65, 213 (1996), 203--213.
This is available on the net from L'Ecuyer's home page,
http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps
ftp://ftp.iro.umontreal.ca/pub/simulation/lecuyer/papers/tausme.ps
There is an erratum in the paper "Tables of Maximally
Equidistributed Combined LFSR Generators", Mathematics of
Computation, 68, 225 (1999), 261--269:
http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme2.ps
... the k_j most significant bits of z_j must be non-
zero, for each j. (Note: this restriction also applies to the
computer code given in [4], but was mistakenly not mentioned in
that paper.)
This affects the seeding procedure by imposing the requirement
s1 > 1, s2 > 7, s3 > 15.
*/
struct nrnd_state {
u32 s1, s2, s3;
};
static DEFINE_PER_CPU(struct nrnd_state, net_rand_state);
static u32 __net_random(struct nrnd_state *state)
{
#define TAUSWORTHE(s,a,b,c,d) ((s&c)<<d) ^ (((s <<a) ^ s)>>b)
state->s1 = TAUSWORTHE(state->s1, 13, 19, 4294967294UL, 12);
state->s2 = TAUSWORTHE(state->s2, 2, 25, 4294967288UL, 4);
state->s3 = TAUSWORTHE(state->s3, 3, 11, 4294967280UL, 17);
return (state->s1 ^ state->s2 ^ state->s3);
}
static void __net_srandom(struct nrnd_state *state, unsigned long entropy)
{
u32 s = state->s1 ^ entropy;
if (s == 0)
s = 1; /* default seed is 1 */
#define LCG(n) (69069 * n)
state->s1 = LCG(s);
state->s2 = LCG(state->s1);
state->s3 = LCG(state->s2);
/* "warm it up" */
__net_random(state);
__net_random(state);
__net_random(state);
__net_random(state);
__net_random(state);
__net_random(state);
}
unsigned long net_random(void)
{
net_rand_seed=net_rand_seed*69069L+1;
return net_rand_seed^jiffies;
unsigned long r;
struct nrnd_state *state = &get_cpu_var(net_rand_state);
r = __net_random(state);
put_cpu_var(state);
return r;
}
void net_srandom(unsigned long entropy)
{
net_rand_seed ^= entropy;
net_random();
struct nrnd_state *state = &get_cpu_var(net_rand_state);
__net_srandom(state, entropy);
put_cpu_var(state);
}
void __init net_random_init(void)
{
int i;
unsigned long seed[NR_CPUS];
get_random_bytes(seed, sizeof(seed));
for (i = 0; i < NR_CPUS; i++) {
struct nrnd_state *state = &per_cpu(net_rand_state,i);
memset(state, 0, sizeof(*state));
__net_srandom(state, seed[i]);
}
}
int net_msg_cost = 5*HZ;
......
......@@ -39,6 +39,7 @@
#include <net/udp.h>
#include <net/ip.h>
#include <linux/spinlock.h>
#include <linux/rcupdate.h>
#include <asm/uaccess.h>
#include <asm/system.h>
......@@ -401,16 +402,17 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
y.x maps to IP a.b.c.x. This should be replaced with something
more flexible and more aware of subnet masks. */
{
struct in_device *idev = in_dev_get(dev);
struct in_device *idev;
unsigned long network = 0;
rcu_read_lock();
idev = __in_dev_get(dev);
if (idev) {
read_lock(&idev->lock);
if (idev->ifa_list)
network = ntohl(idev->ifa_list->ifa_address) &
0xffffff00; /* !!! */
read_unlock(&idev->lock);
in_dev_put(idev);
}
rcu_read_unlock();
udpdest.sin_addr.s_addr = htonl(network | addr.station);
}
......
......@@ -82,16 +82,6 @@ config IP_ROUTE_FWMARK
If you say Y here, you will be able to specify different routes for
packets with different mark values (see iptables(8), MARK target).
config IP_ROUTE_NAT
bool "IP: fast network address translation"
depends on IP_MULTIPLE_TABLES
help
If you say Y here, your router will be able to modify source and
destination addresses of packets that pass through it, in a manner
you specify. General information about Network Address Translation
can be gotten from the document
<http://www.hasenstein.com/linux-ip-nat/diplom/nat.html>.
config IP_ROUTE_MULTIPATH
bool "IP: equal cost multipath"
depends on IP_ADVANCED_ROUTER
......
......@@ -88,31 +88,31 @@ static void devinet_sysctl_register(struct in_device *in_dev,
static void devinet_sysctl_unregister(struct ipv4_devconf *p);
#endif
int inet_ifa_count;
int inet_dev_count;
/* Locks all the inet devices. */
rwlock_t inetdev_lock = RW_LOCK_UNLOCKED;
static struct in_ifaddr *inet_alloc_ifa(void)
{
struct in_ifaddr *ifa = kmalloc(sizeof(*ifa), GFP_KERNEL);
if (ifa) {
memset(ifa, 0, sizeof(*ifa));
inet_ifa_count++;
INIT_RCU_HEAD(&ifa->rcu_head);
}
return ifa;
}
static __inline__ void inet_free_ifa(struct in_ifaddr *ifa)
static void inet_rcu_free_ifa(struct rcu_head *head)
{
struct in_ifaddr *ifa = container_of(head, struct in_ifaddr, rcu_head);
if (ifa->ifa_dev)
__in_dev_put(ifa->ifa_dev);
in_dev_put(ifa->ifa_dev);
kfree(ifa);
inet_ifa_count--;
}
static inline void inet_free_ifa(struct in_ifaddr *ifa)
{
call_rcu(&ifa->rcu_head, inet_rcu_free_ifa);
}
void in_dev_finish_destroy(struct in_device *idev)
......@@ -129,7 +129,6 @@ void in_dev_finish_destroy(struct in_device *idev)
if (!idev->dead)
printk("Freeing alive in_device %p\n", idev);
else {
inet_dev_count--;
kfree(idev);
}
}
......@@ -144,24 +143,24 @@ struct in_device *inetdev_init(struct net_device *dev)
if (!in_dev)
goto out;
memset(in_dev, 0, sizeof(*in_dev));
in_dev->lock = RW_LOCK_UNLOCKED;
INIT_RCU_HEAD(&in_dev->rcu_head);
memcpy(&in_dev->cnf, &ipv4_devconf_dflt, sizeof(in_dev->cnf));
in_dev->cnf.sysctl = NULL;
in_dev->dev = dev;
if ((in_dev->arp_parms = neigh_parms_alloc(dev, &arp_tbl)) == NULL)
goto out_kfree;
inet_dev_count++;
/* Reference in_dev->dev */
dev_hold(dev);
#ifdef CONFIG_SYSCTL
neigh_sysctl_register(dev, in_dev->arp_parms, NET_IPV4,
NET_IPV4_NEIGH, "ipv4", NULL);
#endif
write_lock_bh(&inetdev_lock);
dev->ip_ptr = in_dev;
/* Account for reference dev->ip_ptr */
in_dev_hold(in_dev);
write_unlock_bh(&inetdev_lock);
smp_wmb();
dev->ip_ptr = in_dev;
#ifdef CONFIG_SYSCTL
devinet_sysctl_register(in_dev, &in_dev->cnf);
#endif
......@@ -176,6 +175,12 @@ struct in_device *inetdev_init(struct net_device *dev)
goto out;
}
static void in_dev_rcu_put(struct rcu_head *head)
{
struct in_device *idev = container_of(head, struct in_device, rcu_head);
in_dev_put(idev);
}
static void inetdev_destroy(struct in_device *in_dev)
{
struct in_ifaddr *ifa;
......@@ -194,30 +199,28 @@ static void inetdev_destroy(struct in_device *in_dev)
#ifdef CONFIG_SYSCTL
devinet_sysctl_unregister(&in_dev->cnf);
#endif
write_lock_bh(&inetdev_lock);
in_dev->dev->ip_ptr = NULL;
/* in_dev_put following below will kill the in_device */
write_unlock_bh(&inetdev_lock);
#ifdef CONFIG_SYSCTL
neigh_sysctl_unregister(in_dev->arp_parms);
#endif
neigh_parms_release(&arp_tbl, in_dev->arp_parms);
in_dev_put(in_dev);
call_rcu(&in_dev->rcu_head, in_dev_rcu_put);
}
int inet_addr_onlink(struct in_device *in_dev, u32 a, u32 b)
{
read_lock(&in_dev->lock);
rcu_read_lock();
for_primary_ifa(in_dev) {
if (inet_ifa_match(a, ifa)) {
if (!b || inet_ifa_match(b, ifa)) {
read_unlock(&in_dev->lock);
rcu_read_unlock();
return 1;
}
}
} endfor_ifa(in_dev);
read_unlock(&in_dev->lock);
rcu_read_unlock();
return 0;
}
......@@ -241,9 +244,8 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
ifap1 = &ifa->ifa_next;
continue;
}
write_lock_bh(&in_dev->lock);
*ifap1 = ifa->ifa_next;
write_unlock_bh(&in_dev->lock);
rtmsg_ifa(RTM_DELADDR, ifa);
notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa);
......@@ -253,9 +255,7 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
/* 2. Unlink it */
write_lock_bh(&in_dev->lock);
*ifap = ifa1->ifa_next;
write_unlock_bh(&in_dev->lock);
/* 3. Announce address deletion */
......@@ -317,9 +317,7 @@ static int inet_insert_ifa(struct in_ifaddr *ifa)
}
ifa->ifa_next = *ifap;
write_lock_bh(&in_dev->lock);
*ifap = ifa;
write_unlock_bh(&in_dev->lock);
/* Send message first, then call notifier.
Notifier will trigger FIB update, so that
......@@ -771,12 +769,11 @@ u32 inet_select_addr(const struct net_device *dev, u32 dst, int scope)
u32 addr = 0;
struct in_device *in_dev;
read_lock(&inetdev_lock);
rcu_read_lock();
in_dev = __in_dev_get(dev);
if (!in_dev)
goto out_unlock_inetdev;
goto no_in_dev;
read_lock(&in_dev->lock);
for_primary_ifa(in_dev) {
if (ifa->ifa_scope > scope)
continue;
......@@ -787,8 +784,8 @@ u32 inet_select_addr(const struct net_device *dev, u32 dst, int scope)
if (!addr)
addr = ifa->ifa_local;
} endfor_ifa(in_dev);
read_unlock(&in_dev->lock);
read_unlock(&inetdev_lock);
no_in_dev:
rcu_read_unlock();
if (addr)
goto out;
......@@ -798,30 +795,24 @@ u32 inet_select_addr(const struct net_device *dev, u32 dst, int scope)
in dev_base list.
*/
read_lock(&dev_base_lock);
read_lock(&inetdev_lock);
rcu_read_lock();
for (dev = dev_base; dev; dev = dev->next) {
if ((in_dev = __in_dev_get(dev)) == NULL)
continue;
read_lock(&in_dev->lock);
for_primary_ifa(in_dev) {
if (ifa->ifa_scope != RT_SCOPE_LINK &&
ifa->ifa_scope <= scope) {
read_unlock(&in_dev->lock);
addr = ifa->ifa_local;
goto out_unlock_both;
}
} endfor_ifa(in_dev);
read_unlock(&in_dev->lock);
}
out_unlock_both:
read_unlock(&inetdev_lock);
read_unlock(&dev_base_lock);
rcu_read_unlock();
out:
return addr;
out_unlock_inetdev:
read_unlock(&inetdev_lock);
goto out;
}
static u32 confirm_addr_indev(struct in_device *in_dev, u32 dst,
......@@ -874,29 +865,24 @@ u32 inet_confirm_addr(const struct net_device *dev, u32 dst, u32 local, int scop
struct in_device *in_dev;
if (dev) {
read_lock(&inetdev_lock);
if ((in_dev = __in_dev_get(dev))) {
read_lock(&in_dev->lock);
rcu_read_lock();
if ((in_dev = __in_dev_get(dev)))
addr = confirm_addr_indev(in_dev, dst, local, scope);
read_unlock(&in_dev->lock);
}
read_unlock(&inetdev_lock);
rcu_read_unlock();
return addr;
}
read_lock(&dev_base_lock);
read_lock(&inetdev_lock);
rcu_read_lock();
for (dev = dev_base; dev; dev = dev->next) {
if ((in_dev = __in_dev_get(dev))) {
read_lock(&in_dev->lock);
addr = confirm_addr_indev(in_dev, dst, local, scope);
read_unlock(&in_dev->lock);
if (addr)
break;
}
}
read_unlock(&inetdev_lock);
rcu_read_unlock();
read_unlock(&dev_base_lock);
return addr;
......@@ -1065,12 +1051,12 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
continue;
if (idx > s_idx)
s_ip_idx = 0;
read_lock(&inetdev_lock);
rcu_read_lock();
if ((in_dev = __in_dev_get(dev)) == NULL) {
read_unlock(&inetdev_lock);
rcu_read_unlock();
continue;
}
read_lock(&in_dev->lock);
for (ifa = in_dev->ifa_list, ip_idx = 0; ifa;
ifa = ifa->ifa_next, ip_idx++) {
if (ip_idx < s_ip_idx)
......@@ -1078,13 +1064,11 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq,
RTM_NEWADDR) <= 0) {
read_unlock(&in_dev->lock);
read_unlock(&inetdev_lock);
rcu_read_unlock();
goto done;
}
}
read_unlock(&in_dev->lock);
read_unlock(&inetdev_lock);
rcu_read_unlock();
}
done:
......@@ -1138,11 +1122,11 @@ void inet_forward_change(void)
read_lock(&dev_base_lock);
for (dev = dev_base; dev; dev = dev->next) {
struct in_device *in_dev;
read_lock(&inetdev_lock);
rcu_read_lock();
in_dev = __in_dev_get(dev);
if (in_dev)
in_dev->cnf.forwarding = on;
read_unlock(&inetdev_lock);
rcu_read_unlock();
}
read_unlock(&dev_base_lock);
......@@ -1508,6 +1492,5 @@ EXPORT_SYMBOL(devinet_ioctl);
EXPORT_SYMBOL(in_dev_finish_destroy);
EXPORT_SYMBOL(inet_select_addr);
EXPORT_SYMBOL(inetdev_by_index);
EXPORT_SYMBOL(inetdev_lock);
EXPORT_SYMBOL(register_inetaddr_notifier);
EXPORT_SYMBOL(unregister_inetaddr_notifier);
......@@ -172,13 +172,13 @@ int fib_validate_source(u32 src, u32 dst, u8 tos, int oif,
int ret;
no_addr = rpf = 0;
read_lock(&inetdev_lock);
rcu_read_lock();
in_dev = __in_dev_get(dev);
if (in_dev) {
no_addr = in_dev->ifa_list == NULL;
rpf = IN_DEV_RPFILTER(in_dev);
}
read_unlock(&inetdev_lock);
rcu_read_unlock();
if (in_dev == NULL)
goto e_inval;
......
......@@ -176,7 +176,7 @@ int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
table_id = rtm->rtm_table;
if (table_id == RT_TABLE_UNSPEC) {
struct fib_table *table;
if (rtm->rtm_type == RTN_UNICAST || rtm->rtm_type == RTN_NAT) {
if (rtm->rtm_type == RTN_UNICAST) {
if ((table = fib_empty_table()) == NULL)
return -ENOBUFS;
table_id = table->tb_id;
......@@ -251,26 +251,6 @@ u32 fib_rules_map_destination(u32 daddr, struct fib_result *res)
return (daddr&~mask)|res->fi->fib_nh->nh_gw;
}
u32 fib_rules_policy(u32 saddr, struct fib_result *res, unsigned *flags)
{
struct fib_rule *r = res->r;
if (r->r_action == RTN_NAT) {
int addrtype = inet_addr_type(r->r_srcmap);
if (addrtype == RTN_NAT) {
/* Packet is from translated source; remember it */
saddr = (saddr&~r->r_srcmask)|r->r_srcmap;
*flags |= RTCF_SNAT;
} else if (addrtype == RTN_LOCAL || r->r_srcmap == 0) {
/* Packet is from masqueraded source; remember it */
saddr = r->r_srcmap;
*flags |= RTCF_MASQ;
}
}
return saddr;
}
#ifdef CONFIG_NET_CLS_ROUTE
u32 fib_rules_tclass(struct fib_result *res)
{
......@@ -334,7 +314,6 @@ FRprintk("Lookup: %u.%u.%u.%u <- %u.%u.%u.%u ",
FRprintk("tb %d r %d ", r->r_table, r->r_action);
switch (r->r_action) {
case RTN_UNICAST:
case RTN_NAT:
policy = r;
break;
case RTN_UNREACHABLE:
......
......@@ -124,17 +124,10 @@ static struct
.error = -EAGAIN,
.scope = RT_SCOPE_UNIVERSE,
}, /* RTN_THROW */
#ifdef CONFIG_IP_ROUTE_NAT
{
.error = 0,
.scope = RT_SCOPE_HOST,
}, /* RTN_NAT */
#else
{
.error = -EINVAL,
.scope = RT_SCOPE_NOWHERE,
}, /* RTN_NAT */
#endif
{
.error = -EINVAL,
.scope = RT_SCOPE_NOWHERE,
......@@ -543,15 +536,6 @@ fib_create_info(const struct rtmsg *r, struct kern_rta *rta,
#endif
}
#ifdef CONFIG_IP_ROUTE_NAT
if (r->rtm_type == RTN_NAT) {
if (rta->rta_gw == NULL || nhs != 1 || rta->rta_oif)
goto err_inval;
memcpy(&fi->fib_nh->nh_gw, rta->rta_gw, 4);
goto link_it;
}
#endif
if (fib_props[r->rtm_type].error) {
if (rta->rta_gw || rta->rta_oif || rta->rta_mp)
goto err_inval;
......@@ -629,12 +613,6 @@ fib_semantic_match(int type, struct fib_info *fi, const struct flowi *flp, struc
res->fi = fi;
switch (type) {
#ifdef CONFIG_IP_ROUTE_NAT
case RTN_NAT:
FIB_RES_RESET(*res);
atomic_inc(&fi->fib_clntref);
return 0;
#endif
case RTN_UNICAST:
case RTN_LOCAL:
case RTN_BROADCAST:
......
......@@ -508,16 +508,6 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info)
* Construct source address and options.
*/
#ifdef CONFIG_IP_ROUTE_NAT
/*
* Restore original addresses if packet has been translated.
*/
if (rt->rt_flags & RTCF_NAT && IPCB(skb_in)->flags & IPSKB_TRANSLATED) {
iph->daddr = rt->fl.fl4_dst;
iph->saddr = rt->fl.fl4_src;
}
#endif
saddr = iph->daddr;
if (!(rt->rt_flags & RTCF_LOCAL))
saddr = 0;
......@@ -892,7 +882,7 @@ static void icmp_address_reply(struct sk_buff *skb)
in_dev = in_dev_get(dev);
if (!in_dev)
goto out;
read_lock(&in_dev->lock);
rcu_read_lock();
if (in_dev->ifa_list &&
IN_DEV_LOG_MARTIANS(in_dev) &&
IN_DEV_FORWARD(in_dev)) {
......@@ -912,7 +902,7 @@ static void icmp_address_reply(struct sk_buff *skb)
NIPQUAD(*mp), dev->name, NIPQUAD(rt->rt_src));
}
}
read_unlock(&in_dev->lock);
rcu_read_unlock();
in_dev_put(in_dev);
out:;
}
......
This diff is collapsed.
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Dumb Network Address Translation.
*
* Version: $Id: ip_nat_dumb.c,v 1.11 2000/12/13 18:31:48 davem Exp $
*
* Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
*
* 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.
*
* Fixes:
* Rani Assaf : A zero checksum is a special case
* only in UDP
* Rani Assaf : Added ICMP messages rewriting
* Rani Assaf : Repaired wrong changes, made by ANK.
*
*
* NOTE: It is just working model of real NAT.
*/
#include <linux/config.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <linux/icmp.h>
#include <linux/netdevice.h>
#include <net/sock.h>
#include <net/ip.h>
#include <net/icmp.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <net/checksum.h>
#include <linux/route.h>
#include <net/route.h>
#include <net/ip_fib.h>
int
ip_do_nat(struct sk_buff *skb)
{
struct rtable *rt = (struct rtable*)skb->dst;
struct iphdr *iph = skb->nh.iph;
u32 odaddr = iph->daddr;
u32 osaddr = iph->saddr;
u16 check;
IPCB(skb)->flags |= IPSKB_TRANSLATED;
/* Rewrite IP header */
iph->daddr = rt->rt_dst_map;
iph->saddr = rt->rt_src_map;
iph->check = 0;
iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
/* If it is the first fragment, rewrite protocol headers */
if (!(iph->frag_off & htons(IP_OFFSET))) {
u16 *cksum;
switch(iph->protocol) {
case IPPROTO_TCP:
cksum = (u16*)&((struct tcphdr*)(((char*)iph) + (iph->ihl<<2)))->check;
if ((u8*)(cksum+1) > skb->tail)
goto truncated;
check = *cksum;
if (skb->ip_summed != CHECKSUM_HW)
check = ~check;
check = csum_tcpudp_magic(iph->saddr, iph->daddr, 0, 0, check);
check = csum_tcpudp_magic(~osaddr, ~odaddr, 0, 0, ~check);
if (skb->ip_summed == CHECKSUM_HW)
check = ~check;
*cksum = check;
break;
case IPPROTO_UDP:
cksum = (u16*)&((struct udphdr*)(((char*)iph) + (iph->ihl<<2)))->check;
if ((u8*)(cksum+1) > skb->tail)
goto truncated;
if ((check = *cksum) != 0) {
check = csum_tcpudp_magic(iph->saddr, iph->daddr, 0, 0, ~check);
check = csum_tcpudp_magic(~osaddr, ~odaddr, 0, 0, ~check);
*cksum = check ? : 0xFFFF;
}
break;
case IPPROTO_ICMP:
{
struct icmphdr *icmph = (struct icmphdr*)((char*)iph + (iph->ihl<<2));
struct iphdr *ciph;
u32 idaddr, isaddr;
int updated;
if ((icmph->type != ICMP_DEST_UNREACH) &&
(icmph->type != ICMP_TIME_EXCEEDED) &&
(icmph->type != ICMP_PARAMETERPROB))
break;
ciph = (struct iphdr *) (icmph + 1);
if ((u8*)(ciph+1) > skb->tail)
goto truncated;
isaddr = ciph->saddr;
idaddr = ciph->daddr;
updated = 0;
if (rt->rt_flags&RTCF_DNAT && ciph->saddr == odaddr) {
ciph->saddr = iph->daddr;
updated = 1;
}
if (rt->rt_flags&RTCF_SNAT) {
if (ciph->daddr != osaddr) {
struct fib_result res;
unsigned flags = 0;
struct flowi fl = {
.iif = skb->dev->ifindex,
.nl_u =
{ .ip4_u =
{ .daddr = ciph->saddr,
.saddr = ciph->daddr,
#ifdef CONFIG_IP_ROUTE_TOS
.tos = RT_TOS(ciph->tos)
#endif
} },
.proto = ciph->protocol };
/* Use fib_lookup() until we get our own
* hash table of NATed hosts -- Rani
*/
if (fib_lookup(&fl, &res) == 0) {
if (res.r) {
ciph->daddr = fib_rules_policy(ciph->daddr, &res, &flags);
if (ciph->daddr != idaddr)
updated = 1;
}
fib_res_put(&res);
}
} else {
ciph->daddr = iph->saddr;
updated = 1;
}
}
if (updated) {
cksum = &icmph->checksum;
/* Using tcpudp primitive. Why not? */
check = csum_tcpudp_magic(ciph->saddr, ciph->daddr, 0, 0, ~(*cksum));
*cksum = csum_tcpudp_magic(~isaddr, ~idaddr, 0, 0, ~check);
}
break;
}
default:
break;
}
}
return NET_RX_SUCCESS;
truncated:
/* should be return NET_RX_BAD; */
return -EINVAL;
}
......@@ -1390,13 +1390,7 @@ void ip_rt_get_source(u8 *addr, struct rtable *rt)
if (rt->fl.iif == 0)
src = rt->rt_src;
else if (fib_lookup(&rt->fl, &res) == 0) {
#ifdef CONFIG_IP_ROUTE_NAT
if (res.type == RTN_NAT)
src = inet_select_addr(rt->u.dst.dev, rt->rt_gateway,
RT_SCOPE_UNIVERSE);
else
#endif
src = FIB_RES_PREFSRC(res);
src = FIB_RES_PREFSRC(res);
fib_res_put(&res);
} else
src = inet_select_addr(rt->u.dst.dev, rt->rt_gateway,
......@@ -1500,10 +1494,6 @@ static int ip_route_input_mc(struct sk_buff *skb, u32 daddr, u32 saddr,
#endif
rth->fl.fl4_src = saddr;
rth->rt_src = saddr;
#ifdef CONFIG_IP_ROUTE_NAT
rth->rt_dst_map = daddr;
rth->rt_src_map = saddr;
#endif
#ifdef CONFIG_NET_CLS_ROUTE
rth->u.dst.tclassid = itag;
#endif
......@@ -1613,31 +1603,6 @@ static int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr,
RT_CACHE_STAT_INC(in_slow_tot);
#ifdef CONFIG_IP_ROUTE_NAT
/* Policy is applied before mapping destination,
but rerouting after map should be made with old source.
*/
if (1) {
u32 src_map = saddr;
if (res.r)
src_map = fib_rules_policy(saddr, &res, &flags);
if (res.type == RTN_NAT) {
fl.fl4_dst = fib_rules_map_destination(daddr, &res);
fib_res_put(&res);
free_res = 0;
if (fib_lookup(&fl, &res))
goto e_inval;
free_res = 1;
if (res.type != RTN_UNICAST)
goto e_inval;
flags |= RTCF_DNAT;
}
fl.fl4_src = src_map;
}
#endif
if (res.type == RTN_BROADCAST)
goto brd_input;
......@@ -1711,12 +1676,6 @@ static int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr,
rth->fl.fl4_src = saddr;
rth->rt_src = saddr;
rth->rt_gateway = daddr;
#ifdef CONFIG_IP_ROUTE_NAT
rth->rt_src_map = fl.fl4_src;
rth->rt_dst_map = fl.fl4_dst;
if (flags&RTCF_DNAT)
rth->rt_gateway = fl.fl4_dst;
#endif
rth->rt_iif =
rth->fl.iif = dev->ifindex;
rth->u.dst.dev = out_dev->dev;
......@@ -1779,10 +1738,6 @@ out: return err;
#endif
rth->fl.fl4_src = saddr;
rth->rt_src = saddr;
#ifdef CONFIG_IP_ROUTE_NAT
rth->rt_dst_map = fl.fl4_dst;
rth->rt_src_map = fl.fl4_src;
#endif
#ifdef CONFIG_NET_CLS_ROUTE
rth->u.dst.tclassid = itag;
#endif
......@@ -1903,7 +1858,7 @@ int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,
if (MULTICAST(daddr)) {
struct in_device *in_dev;
read_lock(&inetdev_lock);
rcu_read_lock();
if ((in_dev = __in_dev_get(dev)) != NULL) {
int our = ip_check_mc(in_dev, daddr, saddr,
skb->nh.iph->protocol);
......@@ -1912,12 +1867,12 @@ int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,
|| (!LOCAL_MCAST(daddr) && IN_DEV_MFORWARD(in_dev))
#endif
) {
read_unlock(&inetdev_lock);
rcu_read_unlock();
return ip_route_input_mc(skb, daddr, saddr,
tos, dev, our);
}
}
read_unlock(&inetdev_lock);
rcu_read_unlock();
return -EINVAL;
}
return ip_route_input_slow(skb, daddr, saddr, tos, dev);
......@@ -2075,9 +2030,6 @@ static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp)
}
free_res = 1;
if (res.type == RTN_NAT)
goto e_inval;
if (res.type == RTN_LOCAL) {
if (!fl.fl4_src)
fl.fl4_src = fl.fl4_dst;
......@@ -2167,10 +2119,6 @@ static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp)
#endif
rth->rt_dst = fl.fl4_dst;
rth->rt_src = fl.fl4_src;
#ifdef CONFIG_IP_ROUTE_NAT
rth->rt_dst_map = fl.fl4_dst;
rth->rt_src_map = fl.fl4_src;
#endif
rth->rt_iif = oldflp->oif ? : dev_out->ifindex;
rth->u.dst.dev = dev_out;
dev_hold(dev_out);
......
......@@ -303,10 +303,10 @@ void irlan_eth_send_gratuitous_arp(struct net_device *dev)
*/
#ifdef CONFIG_INET
IRDA_DEBUG(4, "IrLAN: Sending gratuitous ARP\n");
in_dev = in_dev_get(dev);
rcu_read_lock();
in_dev = __in_dev_get(dev);
if (in_dev == NULL)
return;
read_lock(&in_dev->lock);
goto out;
if (in_dev->ifa_list)
arp_send(ARPOP_REQUEST, ETH_P_ARP,
......@@ -314,8 +314,8 @@ void irlan_eth_send_gratuitous_arp(struct net_device *dev)
dev,
in_dev->ifa_list->ifa_address,
NULL, dev->dev_addr, NULL);
read_unlock(&in_dev->lock);
in_dev_put(in_dev);
out:
rcu_read_unlock();
#endif /* CONFIG_INET */
}
......
......@@ -148,13 +148,12 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist,
struct in_ifaddr *ifa;
struct sctp_sockaddr_entry *addr;
read_lock(&inetdev_lock);
rcu_read_lock();
if ((in_dev = __in_dev_get(dev)) == NULL) {
read_unlock(&inetdev_lock);
rcu_read_unlock();
return;
}
read_lock(&in_dev->lock);
for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
/* Add the address to the local list. */
addr = t_new(struct sctp_sockaddr_entry, GFP_ATOMIC);
......@@ -166,8 +165,7 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist,
}
}
read_unlock(&in_dev->lock);
read_unlock(&inetdev_lock);
rcu_read_unlock();
}
/* Extract our IP addresses from the system and stash them in the
......
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