Commit 1e96b980 authored by David S. Miller's avatar David S. Miller

Merge nuts.ninka.net:/home/davem/src/BK/network-2.5

into nuts.ninka.net:/home/davem/src/BK/net-2.5
parents 461a50a3 b5fbb36c
......@@ -240,8 +240,8 @@ L: linux-net@vger.kernel.org
S: Maintained
AX.25 NETWORK LAYER
P: Matthias Welwarsky
M: dg2fef@afthd.tu-darmstadt.de
P: Ralf Baechle
M: ralf@linux-mips.org
L: linux-hams@vger.kernel.org
S: Maintained
......@@ -1113,8 +1113,8 @@ L: netfilter-devel@lists.netfilter.org
S: Supported
NETROM NETWORK LAYER
P: Tomi Manninen
M: Tomi.Manninen@hut.fi
P: Ralf Baechle
M: ralf@linux-mips.org
L: linux-hams@vger.kernel.org
S: Maintained
......@@ -1363,8 +1363,8 @@ W: http://www.namesys.com
S: Supported
ROSE NETWORK LAYER
P: Jean-Paul Roubelat
M: jpr@f6fbb.org
P: Ralf Baechle
M: ralf@linux-mips.org
L: linux-hams@vger.kernel.org
S: Maintained
......
......@@ -2033,57 +2033,103 @@ static __u32 twothirdsMD4Transform (__u32 const buf[4], __u32 const in[12])
/* This should not be decreased so low that ISNs wrap too fast. */
#define REKEY_INTERVAL 300
/*
* Bit layout of the tcp sequence numbers (before adding current time):
* bit 24-31: increased after every key exchange
* bit 0-23: hash(source,dest)
*
* The implementation is similar to the algorithm described
* in the Appendix of RFC 1185, except that
* - it uses a 1 MHz clock instead of a 250 kHz clock
* - it performs a rekey every 5 minutes, which is equivalent
* to a (source,dest) tulple dependent forward jump of the
* clock by 0..2^(HASH_BITS+1)
*
* Thus the average ISN wraparound time is 68 minutes instead of
* 4.55 hours.
*
* SMP cleanup and lock avoidance with poor man's RCU.
* Manfred Spraul <manfred@colorfullife.com>
*
*/
#define COUNT_BITS 8
#define COUNT_MASK ( (1<<COUNT_BITS)-1)
#define HASH_BITS 24
#define HASH_MASK ( (1<<HASH_BITS)-1 )
static struct keydata {
time_t rekey_time;
__u32 count; // already shifted to the final position
__u32 secret[12];
} ____cacheline_aligned ip_keydata[2];
static spinlock_t ip_lock = SPIN_LOCK_UNLOCKED;
static unsigned int ip_cnt;
static struct keydata *__check_and_rekey(time_t time)
{
struct keydata *keyptr;
spin_lock(&ip_lock);
keyptr = &ip_keydata[ip_cnt&1];
if (!keyptr->rekey_time || (time - keyptr->rekey_time) > REKEY_INTERVAL) {
keyptr = &ip_keydata[1^(ip_cnt&1)];
keyptr->rekey_time = time;
get_random_bytes(keyptr->secret, sizeof(keyptr->secret));
keyptr->count = (ip_cnt&COUNT_MASK)<<HASH_BITS;
mb();
ip_cnt++;
}
spin_unlock(&ip_lock);
return keyptr;
}
static inline struct keydata *check_and_rekey(time_t time)
{
struct keydata *keyptr = &ip_keydata[ip_cnt&1];
rmb();
if (!keyptr->rekey_time || (time - keyptr->rekey_time) > REKEY_INTERVAL) {
keyptr = __check_and_rekey(time);
}
return keyptr;
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
__u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr,
__u16 sport, __u16 dport)
{
static __u32 rekey_time;
static __u32 count;
static __u32 secret[12];
struct timeval tv;
__u32 seq;
__u32 hash[12];
struct keydata *keyptr;
/* The procedure is the same as for IPv4, but addresses are longer. */
/* The procedure is the same as for IPv4, but addresses are longer.
* Thus we must use twothirdsMD4Transform.
*/
do_gettimeofday(&tv); /* We need the usecs below... */
keyptr = check_and_rekey(tv.tv_sec);
if (!rekey_time || (tv.tv_sec - rekey_time) > REKEY_INTERVAL) {
rekey_time = tv.tv_sec;
/* First five words are overwritten below. */
get_random_bytes(&secret[5], sizeof(secret)-5*4);
count = (tv.tv_sec/REKEY_INTERVAL) << HASH_BITS;
}
memcpy(secret, saddr, 16);
secret[4]=(sport << 16) + dport;
seq = (twothirdsMD4Transform(daddr, secret) &
((1<<HASH_BITS)-1)) + count;
memcpy(hash, saddr, 16);
hash[4]=(sport << 16) + dport;
memcpy(&hash[5],keyptr->secret,sizeof(__u32)*7);
seq = twothirdsMD4Transform(daddr, hash) & HASH_MASK;
seq += keyptr->count;
seq += tv.tv_usec + tv.tv_sec*1000000;
return seq;
}
EXPORT_SYMBOL(secure_tcpv6_sequence_number);
__u32 secure_ipv6_id(__u32 *daddr)
{
static time_t rekey_time;
static __u32 secret[12];
time_t t;
struct keydata *keyptr;
/*
* Pick a random secret every REKEY_INTERVAL seconds.
*/
t = CURRENT_TIME;
if (!rekey_time || (t - rekey_time) > REKEY_INTERVAL) {
rekey_time = t;
/* First word is overwritten below. */
get_random_bytes(secret, sizeof(secret));
}
keyptr = check_and_rekey(CURRENT_TIME);
return twothirdsMD4Transform(daddr, secret);
return halfMD4Transform(daddr, keyptr->secret);
}
EXPORT_SYMBOL(secure_ipv6_id);
......@@ -2093,40 +2139,30 @@ EXPORT_SYMBOL(secure_ipv6_id);
__u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
__u16 sport, __u16 dport)
{
static __u32 rekey_time;
static __u32 count;
static __u32 secret[12];
struct timeval tv;
__u32 seq;
__u32 hash[4];
struct keydata *keyptr;
/*
* Pick a random secret every REKEY_INTERVAL seconds.
*/
do_gettimeofday(&tv); /* We need the usecs below... */
if (!rekey_time || (tv.tv_sec - rekey_time) > REKEY_INTERVAL) {
rekey_time = tv.tv_sec;
/* First three words are overwritten below. */
get_random_bytes(&secret[3], sizeof(secret)-12);
count = (tv.tv_sec/REKEY_INTERVAL) << HASH_BITS;
}
keyptr = check_and_rekey(tv.tv_sec);
/*
* Pick a unique starting offset for each TCP connection endpoints
* (saddr, daddr, sport, dport).
* Note that the words are placed into the first words to be
* mixed in with the halfMD4. This is because the starting
* vector is also a random secret (at secret+8), and further
* hashing fixed data into it isn't going to improve anything,
* so we should get started with the variable data.
* Note that the words are placed into the starting vector, which is
* then mixed with a partial MD4 over random data.
*/
secret[0]=saddr;
secret[1]=daddr;
secret[2]=(sport << 16) + dport;
seq = (halfMD4Transform(secret+8, secret) &
((1<<HASH_BITS)-1)) + count;
hash[0]=saddr;
hash[1]=daddr;
hash[2]=(sport << 16) + dport;
hash[3]=keyptr->secret[11];
seq = halfMD4Transform(hash, keyptr->secret) & HASH_MASK;
seq += keyptr->count;
/*
* As close as possible to RFC 793, which
* suggests using a 250 kHz clock.
......@@ -2148,31 +2184,22 @@ __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
*/
__u32 secure_ip_id(__u32 daddr)
{
static time_t rekey_time;
static __u32 secret[12];
time_t t;
struct keydata *keyptr;
__u32 hash[4];
/*
* Pick a random secret every REKEY_INTERVAL seconds.
*/
t = CURRENT_TIME;
if (!rekey_time || (t - rekey_time) > REKEY_INTERVAL) {
rekey_time = t;
/* First word is overwritten below. */
get_random_bytes(secret+1, sizeof(secret)-4);
}
keyptr = check_and_rekey(CURRENT_TIME);
/*
* Pick a unique starting offset for each IP destination.
* Note that the words are placed into the first words to be
* mixed in with the halfMD4. This is because the starting
* vector is also a random secret (at secret+8), and further
* hashing fixed data into it isn't going to improve anything,
* so we should get started with the variable data.
* The dest ip address is placed in the starting vector,
* which is then hashed with random data.
*/
secret[0]=daddr;
hash[0] = daddr;
hash[1] = keyptr->secret[9];
hash[2] = keyptr->secret[10];
hash[3] = keyptr->secret[11];
return halfMD4Transform(secret+8, secret);
return halfMD4Transform(hash, keyptr->secret);
}
#ifdef CONFIG_SYN_COOKIES
......
......@@ -23,6 +23,8 @@
#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/if_vlan.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <asm/system.h>
#include <asm/io.h>
......@@ -49,7 +51,9 @@
#endif
#ifdef NETIF_F_TSO
/* XXX some bug in tso firmware hangs tx cpu, disabled until fixed */
/* XXX Works but still disabled, decreases TCP performance to 7MB/sec even
* XXX over gigabit.
*/
#define TG3_DO_TSO 0
#else
#define TG3_DO_TSO 0
......@@ -2390,9 +2394,20 @@ static int tg3_start_xmit_4gbug(struct sk_buff *skb, struct net_device *dev)
if (skb->ip_summed == CHECKSUM_HW)
base_flags |= TXD_FLAG_TCPUDP_CSUM;
#if TG3_DO_TSO != 0
if ((mss = skb_shinfo(skb)->tso_size) != 0)
if ((mss = skb_shinfo(skb)->tso_size) != 0) {
static int times = 0;
mss += ((skb->h.th->doff * 4) - 20);
base_flags |= (TXD_FLAG_CPU_PRE_DMA |
TXD_FLAG_CPU_POST_DMA);
if (times++ < 5) {
printk("tg3_xmit: tso_size[%u] tso_segs[%u] len[%u]\n",
(unsigned int) skb_shinfo(skb)->tso_size,
(unsigned int) skb_shinfo(skb)->tso_segs,
skb->len);
}
}
#else
mss = 0;
#endif
......@@ -2443,7 +2458,7 @@ static int tg3_start_xmit_4gbug(struct sk_buff *skb, struct net_device *dev)
}
tg3_set_txd(tp, entry, mapping, len,
base_flags, (i == last) | (mss << 1));
base_flags, (i == last));
entry = NEXT_TX(entry);
}
......@@ -2555,9 +2570,24 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb->ip_summed == CHECKSUM_HW)
base_flags |= TXD_FLAG_TCPUDP_CSUM;
#if TG3_DO_TSO != 0
if ((mss = skb_shinfo(skb)->tso_size) != 0)
if ((mss = skb_shinfo(skb)->tso_size) != 0) {
static int times = 0;
/* TSO firmware wants TCP options included in
* tx descriptor MSS value.
*/
mss += ((skb->h.th->doff * 4) - 20);
base_flags |= (TXD_FLAG_CPU_PRE_DMA |
TXD_FLAG_CPU_POST_DMA);
if (times++ < 5) {
printk("tg3_xmit: tso_size[%u] tso_segs[%u] len[%u]\n",
(unsigned int) skb_shinfo(skb)->tso_size,
(unsigned int) skb_shinfo(skb)->tso_segs,
skb->len);
}
}
#else
mss = 0;
#endif
......@@ -2597,7 +2627,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
tg3_set_txd(tp, entry, mapping, len,
base_flags, (i == last) | (mss << 1));
base_flags, (i == last));
entry = NEXT_TX(entry);
}
......@@ -4329,9 +4359,11 @@ static int tg3_reset_hw(struct tg3 *tp)
}
#if TG3_DO_TSO != 0
if (tp->dev->features & NETIF_F_TSO) {
err = tg3_load_tso_firmware(tp);
if (err)
return err;
}
#endif
tp->tx_mode = TX_MODE_ENABLE;
......@@ -6752,9 +6784,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
dev->vlan_rx_register = tg3_vlan_rx_register;
dev->vlan_rx_kill_vid = tg3_vlan_rx_kill_vid;
#endif
#if TG3_DO_TSO != 0
dev->features |= NETIF_F_TSO;
#endif
tp = dev->priv;
tp->pdev = pdev;
......@@ -6855,6 +6884,17 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
} else
tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS;
#if TG3_DO_TSO != 0
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 &&
tp->pci_chip_rev_id <= CHIPREV_ID_5701_B2)) {
/* Not TSO capable. */
dev->features &= ~NETIF_F_TSO;
} else {
dev->features |= NETIF_F_TSO;
}
#endif
err = register_netdev(dev);
if (err) {
printk(KERN_ERR PFX "Cannot register net device, "
......
......@@ -275,7 +275,7 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun,
total += sizeof(pi);
}
len = min(skb->len, len);
len = min_t(int, skb->len, len);
skb_copy_datagram_iovec(skb, 0, iv, len);
total += len;
......@@ -306,6 +306,8 @@ static ssize_t tun_chr_readv(struct file *file, const struct iovec *iv,
return -EFAULT;
len += iv[i].iov_len;
}
if (len < 0)
return -EINVAL;
add_wait_queue(&tun->read_wait, &wait);
while (len) {
......
......@@ -3,11 +3,14 @@
*
* Alan Cox (GW4PTS) 10/11/93
*/
#ifndef _AX25_H
#define _AX25_H
#include <linux/config.h>
#include <linux/ax25.h>
#include <linux/spinlock.h>
#include <linux/timer.h>
#include <asm/atomic.h>
#define AX25_T1CLAMPLO 1
#define AX25_T1CLAMPHI (30 * HZ)
......@@ -66,6 +69,8 @@
#define AX25_UA 0x63 /* Unnumbered acknowledge */
#define AX25_FRMR 0x87 /* Frame reject */
#define AX25_UI 0x03 /* Unnumbered information */
#define AX25_XID 0xaf /* Exchange information */
#define AX25_TEST 0xe3 /* Test */
#define AX25_PF 0x10 /* Poll/final bit for standard AX.25 */
#define AX25_EPF 0x01 /* Poll/final bit for extended AX.25 */
......@@ -147,10 +152,12 @@ typedef struct {
typedef struct ax25_route {
struct ax25_route *next;
atomic_t ref;
ax25_address callsign;
struct net_device *dev;
ax25_digi *digipeat;
char ip_mode;
struct timer_list timer;
} ax25_route;
typedef struct {
......@@ -197,11 +204,12 @@ typedef struct ax25_cb {
#define ax25_sk(__sk) ((ax25_cb *)(__sk)->protinfo)
/* af_ax25.c */
extern ax25_cb *volatile ax25_list;
extern ax25_cb *ax25_list;
extern spinlock_t ax25_list_lock;
extern void ax25_free_cb(ax25_cb *);
extern void ax25_insert_socket(ax25_cb *);
struct sock *ax25_find_listener(ax25_address *, int, struct net_device *, int);
struct sock *ax25_find_socket(ax25_address *, ax25_address *, int);
struct sock *ax25_get_socket(ax25_address *, ax25_address *, int);
extern ax25_cb *ax25_find_cb(ax25_address *, ax25_address *, ax25_digi *, struct net_device *);
extern struct sock *ax25_addr_match(ax25_address *);
extern void ax25_send_to_raw(struct sock *, struct sk_buff *, int);
......@@ -224,6 +232,7 @@ extern void ax25_digi_invert(ax25_digi *, ax25_digi *);
/* ax25_dev.c */
extern ax25_dev *ax25_dev_list;
extern spinlock_t ax25_dev_lock;
extern ax25_dev *ax25_dev_ax25dev(struct net_device *);
extern ax25_dev *ax25_addr_ax25dev(ax25_address *);
extern void ax25_dev_device_up(struct net_device *);
......@@ -286,10 +295,16 @@ extern void ax25_rt_device_down(struct net_device *);
extern int ax25_rt_ioctl(unsigned int, void *);
extern int ax25_rt_get_info(char *, char **, off_t, int);
extern int ax25_rt_autobind(ax25_cb *, ax25_address *);
extern ax25_route *ax25_rt_find_route(ax25_address *, struct net_device *);
extern ax25_route *ax25_rt_find_route(ax25_route *, ax25_address *,
struct net_device *);
extern struct sk_buff *ax25_rt_build_path(struct sk_buff *, ax25_address *, ax25_address *, ax25_digi *);
extern void ax25_rt_free(void);
static inline void ax25_put_route(ax25_route *ax25_rt)
{
atomic_dec(&ax25_rt->ref);
}
/* ax25_std_in.c */
extern int ax25_std_frame_in(ax25_cb *, struct sk_buff *, int);
......
......@@ -45,4 +45,5 @@ extern int llc_station_ac_report_status(struct llc_station *station,
struct sk_buff *skb);
extern int llc_station_ac_report_status(struct llc_station *station,
struct sk_buff *skb);
extern void llc_station_ack_tmr_cb(unsigned long timeout_data);
#endif /* LLC_ACTN_H */
......@@ -211,4 +211,9 @@ extern int llc_conn_ac_send_i_rsp_f_set_ackpf(struct sock* sk,
struct sk_buff *skb);
extern int llc_conn_ac_send_i_rsp_as_ack(struct sock* sk, struct sk_buff *skb);
extern int llc_conn_ac_send_i_as_ack(struct sock* sk, struct sk_buff *skb);
extern void llc_conn_busy_tmr_cb(unsigned long timeout_data);
extern void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data);
extern void llc_conn_ack_tmr_cb(unsigned long timeout_data);
extern void llc_conn_rej_tmr_cb(unsigned long timeout_data);
#endif /* LLC_C_AC_H */
......@@ -11,6 +11,9 @@
*
* See the GNU General Public License for more details.
*/
#include <net/sock.h>
/* Connection component state transition event qualifiers */
/* Types of events (possible values in 'ev->type') */
#define LLC_CONN_EV_TYPE_SIMPLE 1
......@@ -293,4 +296,10 @@ extern int llc_conn_ev_qlfy_set_status_conflict(struct sock *sk,
struct sk_buff *skb);
extern int llc_conn_ev_qlfy_set_status_rst_done(struct sock *sk,
struct sk_buff *skb);
static __inline__ int llc_conn_space(struct sock *sk, struct sk_buff *skb)
{
return atomic_read(&sk->rmem_alloc) + skb->truesize <
(unsigned)sk->rcvbuf;
}
#endif /* LLC_C_EV_H */
......@@ -16,7 +16,7 @@
#define LLC_TYPE_1 1
#define LLC_TYPE_2 2
#define LLC_P_TIME 2
#define LLC_ACK_TIME 3
#define LLC_ACK_TIME 1
#define LLC_REJ_TIME 3
#define LLC_BUSY_TIME 3
#define LLC_DEST_INVALID 0 /* Invalid LLC PDU type */
......
Do the ax25_list_lock, ax25_dev_lock, linkfail_lockreally, ax25_frag_lock and
listen_lock have to be bh-safe?
Do the netrom and rose locks have to be bh-safe?
A device might be deleted after lookup in the SIOCADDRT ioctl but before it's
being used.
Routes to a device being taken down might be deleted by ax25_rt_device_down
but added by somebody else before the device has been deleted fully.
Massive amounts of lock_kernel / unlock_kernel are just a temporary solution to
get around the removal of SOCKOPS_WRAP. A serious locking strategy has to be
implemented.
The ax25_rt_find_route synopsys is pervert but I somehow had to deal with
the race caused by the static variable in it's previous implementation.
Implement proper socket locking in netrom and rose.
Check socket locking when ax25_rcv is sending to raw sockets. In particular
ax25_send_to_raw() seems fishy. Heck - ax25_rcv is fishy.
Handle XID and TEST frames properly.
This diff is collapsed.
/*
* AX.25 release 037
* 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 code REQUIRES 2.1.15 or higher/ NET3.038
*
* This module:
* This module 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.
*
* Most of this code is based on the SDL diagrams published in the 7th
* ARRL Computer Networking Conference papers. The diagrams have mistakes
* in them, but are mostly correct. Before you modify the code could you
* read the SDL diagrams as the code is not obvious and probably very
* easy to break;
*
* History
* AX.25 036 Jonathan(G4KLX) Split from ax25_subr.c.
* Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
*/
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
......
/*
* AX.25 release 037
* 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 code REQUIRES 2.1.15 or higher/ NET3.038
*
* This module:
* This module 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.
*
* Other kernels modules in this kit are generally BSD derived. See the copyright headers.
*
*
* History
* AX.25 036 Jonathan(G4KLX) Split from ax25_route.c.
* Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
*/
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/types.h>
......@@ -27,6 +17,7 @@
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/net.h>
#include <linux/spinlock.h>
#include <net/ax25.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
......@@ -41,27 +32,35 @@
#include <linux/init.h>
ax25_dev *ax25_dev_list;
spinlock_t ax25_dev_lock = SPIN_LOCK_UNLOCKED;
ax25_dev *ax25_dev_ax25dev(struct net_device *dev)
{
ax25_dev *ax25_dev;
ax25_dev *ax25_dev, *res = NULL;
spin_lock_bh(&ax25_dev_lock);
for (ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next)
if (ax25_dev->dev == dev)
return ax25_dev;
if (ax25_dev->dev == dev) {
res = ax25_dev;
break;
}
spin_unlock_bh(&ax25_dev_lock);
return NULL;
return res;
}
ax25_dev *ax25_addr_ax25dev(ax25_address *addr)
{
ax25_dev *ax25_dev;
ax25_dev *ax25_dev, *res = NULL;
spin_lock_bh(&ax25_dev_lock);
for (ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next)
if (ax25cmp(addr, (ax25_address *)ax25_dev->dev->dev_addr) == 0)
return ax25_dev;
if (ax25cmp(addr, (ax25_address *)ax25_dev->dev->dev_addr) == 0) {
res = ax25_dev;
}
spin_unlock_bh(&ax25_dev_lock);
return NULL;
return res;
}
/*
......@@ -71,7 +70,6 @@ ax25_dev *ax25_addr_ax25dev(ax25_address *addr)
void ax25_dev_device_up(struct net_device *dev)
{
ax25_dev *ax25_dev;
unsigned long flags;
if ((ax25_dev = kmalloc(sizeof(*ax25_dev), GFP_ATOMIC)) == NULL) {
printk(KERN_ERR "AX.25: ax25_dev_device_up - out of memory\n");
......@@ -100,10 +98,10 @@ void ax25_dev_device_up(struct net_device *dev)
ax25_dev->values[AX25_VALUES_PROTOCOL] = AX25_DEF_PROTOCOL;
ax25_dev->values[AX25_VALUES_DS_TIMEOUT]= AX25_DEF_DS_TIMEOUT;
save_flags(flags); cli();
spin_lock_bh(&ax25_dev_lock);
ax25_dev->next = ax25_dev_list;
ax25_dev_list = ax25_dev;
restore_flags(flags);
spin_unlock_bh(&ax25_dev_lock);
ax25_register_sysctl();
}
......@@ -111,14 +109,13 @@ void ax25_dev_device_up(struct net_device *dev)
void ax25_dev_device_down(struct net_device *dev)
{
ax25_dev *s, *ax25_dev;
unsigned long flags;
if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
return;
ax25_unregister_sysctl();
save_flags(flags); cli();
spin_lock_bh(&ax25_dev_lock);
#ifdef CONFIG_AX25_DAMA_SLAVE
ax25_ds_del_timer(ax25_dev);
......@@ -133,7 +130,7 @@ void ax25_dev_device_down(struct net_device *dev)
if ((s = ax25_dev_list) == ax25_dev) {
ax25_dev_list = s->next;
restore_flags(flags);
spin_unlock_bh(&ax25_dev_lock);
kfree(ax25_dev);
ax25_register_sysctl();
return;
......@@ -142,7 +139,7 @@ void ax25_dev_device_down(struct net_device *dev)
while (s != NULL && s->next != NULL) {
if (s->next == ax25_dev) {
s->next = ax25_dev->next;
restore_flags(flags);
spin_unlock_bh(&ax25_dev_lock);
kfree(ax25_dev);
ax25_register_sysctl();
return;
......@@ -150,8 +147,8 @@ void ax25_dev_device_down(struct net_device *dev)
s = s->next;
}
spin_unlock_bh(&ax25_dev_lock);
restore_flags(flags);
ax25_register_sysctl();
}
......@@ -202,12 +199,16 @@ struct net_device *ax25_fwd_dev(struct net_device *dev)
*/
void __exit ax25_dev_free(void)
{
ax25_dev *s, *ax25_dev = ax25_dev_list;
ax25_dev *s, *ax25_dev;
spin_lock_bh(&ax25_dev_lock);
ax25_dev = ax25_dev_list;
while (ax25_dev != NULL) {
s = ax25_dev;
ax25_dev = ax25_dev->next;
kfree(s);
}
ax25_dev_list = NULL;
spin_unlock_bh(&ax25_dev_lock);
}
/*
* AX.25 release 037
* 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 code REQUIRES 2.1.15 or higher/ NET3.038
*
* This module:
* This module 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.
*
* Most of this code is based on the SDL diagrams published in the 7th
* ARRL Computer Networking Conference papers. The diagrams have mistakes
* in them, but are mostly correct. Before you modify the code could you
* read the SDL diagrams as the code is not obvious and probably very
* easy to break;
*
* History
* AX.25 036 Jonathan(G4KLX) Cloned from ax25_in.c
* Joerg(DL1BKE) Fixed it.
* AX.25 037 Jonathan(G4KLX) New timer architecture.
* Joerg(DL1BKE) ax25->n2count never got reset
* Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
* Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)
*/
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
......@@ -95,11 +80,13 @@ static int ax25_ds_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int framet
break;
case AX25_DM:
if (pf) ax25_disconnect(ax25, ECONNREFUSED);
if (pf)
ax25_disconnect(ax25, ECONNREFUSED);
break;
default:
if (pf) ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND);
if (pf)
ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND);
break;
}
......
/*
* AX.25 release 037
* 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 code REQUIRES 2.1.15 or higher/ NET3.038
*
* This module:
* This module 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.
*
* Most of this code is based on the SDL diagrams published in the 7th
* ARRL Computer Networking Conference papers. The diagrams have mistakes
* in them, but are mostly correct. Before you modify the code could you
* read the SDL diagrams as the code is not obvious and probably very
* easy to break;
*
* History
* AX.25 036 Jonathan(G4KLX) Cloned from ax25_out.c and ax25_subr.c.
* Joerg(DL1BKE) Changed ax25_ds_enquiry_response(),
* fixed ax25_dama_on() and ax25_dama_off().
* AX.25 037 Jonathan(G4KLX) New timer architecture.
* Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
* Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)
*/
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
......@@ -31,6 +16,7 @@
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/spinlock.h>
#include <linux/net.h>
#include <net/ax25.h>
#include <linux/inet.h>
......@@ -93,6 +79,7 @@ void ax25_ds_enquiry_response(ax25_cb *ax25)
ax25_start_t3timer(ax25);
ax25_ds_set_timer(ax25->ax25_dev);
spin_lock_bh(&ax25_list_lock);
for (ax25o = ax25_list; ax25o != NULL; ax25o = ax25o->next) {
if (ax25o == ax25)
continue;
......@@ -118,6 +105,7 @@ void ax25_ds_enquiry_response(ax25_cb *ax25)
if (ax25o->state != AX25_STATE_0)
ax25_start_t3timer(ax25o);
}
spin_unlock_bh(&ax25_list_lock);
}
void ax25_ds_establish_data_link(ax25_cb *ax25)
......@@ -171,12 +159,17 @@ static void ax25_kiss_cmd(ax25_dev *ax25_dev, unsigned char cmd, unsigned char p
static int ax25_check_dama_slave(ax25_dev *ax25_dev)
{
ax25_cb *ax25;
int res = 0;
spin_lock_bh(&ax25_list_lock);
for (ax25 = ax25_list; ax25 != NULL ; ax25 = ax25->next)
if (ax25->ax25_dev == ax25_dev && (ax25->condition & AX25_COND_DAMA_MODE) && ax25->state > AX25_STATE_1)
return 1;
if (ax25->ax25_dev == ax25_dev && (ax25->condition & AX25_COND_DAMA_MODE) && ax25->state > AX25_STATE_1) {
res = 1;
break;
}
spin_unlock_bh(&ax25_list_lock);
return 0;
return res;
}
void ax25_dev_dama_on(ax25_dev *ax25_dev)
......
/*
* AX.25 release 037
* 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 code REQUIRES 2.1.15 or higher/ NET3.038
*
* This module:
* This module 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.
*
* History
* AX.25 036 Jonathan(G4KLX) Cloned from ax25_timer.c.
* Joerg(DL1BKE) Added DAMA Slave Timeout timer
* AX.25 037 Jonathan(G4KLX) New timer architecture.
* Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
* Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)
*/
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/spinlock.h>
#include <linux/in.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
......@@ -58,7 +51,8 @@ static void ax25_ds_add_timer(ax25_dev *ax25_dev)
void ax25_ds_del_timer(ax25_dev *ax25_dev)
{
if (ax25_dev) del_timer(&ax25_dev->dama.slave_timer);
if (ax25_dev)
del_timer(&ax25_dev->dama.slave_timer);
}
void ax25_ds_set_timer(ax25_dev *ax25_dev)
......@@ -89,6 +83,7 @@ static void ax25_ds_timeout(unsigned long arg)
return;
}
spin_lock_bh(&ax25_list_lock);
for (ax25=ax25_list; ax25 != NULL; ax25 = ax25->next) {
if (ax25->ax25_dev != ax25_dev || !(ax25->condition & AX25_COND_DAMA_MODE))
continue;
......@@ -96,6 +91,7 @@ static void ax25_ds_timeout(unsigned long arg)
ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
ax25_disconnect(ax25, ETIMEDOUT);
}
spin_unlock_bh(&ax25_list_lock);
ax25_dev_dama_off(ax25_dev);
}
......@@ -178,7 +174,6 @@ void ax25_ds_idletimer_expiry(ax25_cb *ax25)
void ax25_ds_t1_timeout(ax25_cb *ax25)
{
switch (ax25->state) {
case AX25_STATE_1:
if (ax25->n2count == ax25->n2) {
if (ax25->modulus == AX25_MODULUS) {
......
/*
* AX.25 release 037
* 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 code REQUIRES 2.1.15 or higher/ NET3.038
*
* This module:
* This module 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.
*
* History
* AX.25 036 Jonathan(G4KLX) Split from ax25_timer.c.
* Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
*/
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/types.h>
......@@ -20,6 +13,7 @@
#include <linux/in.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/sockios.h>
......@@ -40,22 +34,25 @@ static struct protocol_struct {
unsigned int pid;
int (*func)(struct sk_buff *, ax25_cb *);
} *protocol_list;
static rwlock_t protocol_list_lock = RW_LOCK_UNLOCKED;
static struct linkfail_struct {
struct linkfail_struct *next;
void (*func)(ax25_cb *, int);
} *linkfail_list;
static spinlock_t linkfail_lock = SPIN_LOCK_UNLOCKED;
static struct listen_struct {
struct listen_struct *next;
ax25_address callsign;
struct net_device *dev;
} *listen_list;
static spinlock_t listen_lock = SPIN_LOCK_UNLOCKED;
int ax25_protocol_register(unsigned int pid, int (*func)(struct sk_buff *, ax25_cb *))
int ax25_protocol_register(unsigned int pid,
int (*func)(struct sk_buff *, ax25_cb *))
{
struct protocol_struct *protocol;
unsigned long flags;
if (pid == AX25_P_TEXT || pid == AX25_P_SEGMENT)
return 0;
......@@ -69,31 +66,28 @@ int ax25_protocol_register(unsigned int pid, int (*func)(struct sk_buff *, ax25_
protocol->pid = pid;
protocol->func = func;
save_flags(flags);
cli();
write_lock(&protocol_list_lock);
protocol->next = protocol_list;
protocol_list = protocol;
restore_flags(flags);
write_unlock(&protocol_list_lock);
return 1;
}
void ax25_protocol_release(unsigned int pid)
{
struct protocol_struct *s, *protocol = protocol_list;
unsigned long flags;
struct protocol_struct *s, *protocol;
if (protocol == NULL)
write_lock(&protocol_list_lock);
protocol = protocol_list;
if (protocol == NULL) {
write_unlock(&protocol_list_lock);
return;
save_flags(flags);
cli();
}
if (protocol->pid == pid) {
protocol_list = protocol->next;
restore_flags(flags);
write_unlock(&protocol_list_lock);
kfree(protocol);
return;
}
......@@ -102,52 +96,45 @@ void ax25_protocol_release(unsigned int pid)
if (protocol->next->pid == pid) {
s = protocol->next;
protocol->next = protocol->next->next;
restore_flags(flags);
write_unlock(&protocol_list_lock);
kfree(s);
return;
}
protocol = protocol->next;
}
restore_flags(flags);
write_unlock(&protocol_list_lock);
}
int ax25_linkfail_register(void (*func)(ax25_cb *, int))
{
struct linkfail_struct *linkfail;
unsigned long flags;
if ((linkfail = kmalloc(sizeof(*linkfail), GFP_ATOMIC)) == NULL)
return 0;
linkfail->func = func;
save_flags(flags);
cli();
spin_lock_bh(&linkfail_lock);
linkfail->next = linkfail_list;
linkfail_list = linkfail;
restore_flags(flags);
spin_unlock_bh(&linkfail_lock);
return 1;
}
void ax25_linkfail_release(void (*func)(ax25_cb *, int))
{
struct linkfail_struct *s, *linkfail = linkfail_list;
unsigned long flags;
struct linkfail_struct *s, *linkfail;
spin_lock_bh(&linkfail_lock);
linkfail = linkfail_list;
if (linkfail == NULL)
return;
save_flags(flags);
cli();
if (linkfail->func == func) {
linkfail_list = linkfail->next;
restore_flags(flags);
spin_unlock_bh(&linkfail_lock);
kfree(linkfail);
return;
}
......@@ -156,21 +143,19 @@ void ax25_linkfail_release(void (*func)(ax25_cb *, int))
if (linkfail->next->func == func) {
s = linkfail->next;
linkfail->next = linkfail->next->next;
restore_flags(flags);
spin_unlock_bh(&linkfail_lock);
kfree(s);
return;
}
linkfail = linkfail->next;
}
restore_flags(flags);
spin_unlock_bh(&linkfail_lock);
}
int ax25_listen_register(ax25_address *callsign, struct net_device *dev)
{
struct listen_struct *listen;
unsigned long flags;
if (ax25_listen_mine(callsign, dev))
return 0;
......@@ -181,31 +166,26 @@ int ax25_listen_register(ax25_address *callsign, struct net_device *dev)
listen->callsign = *callsign;
listen->dev = dev;
save_flags(flags);
cli();
spin_lock_bh(&listen_lock);
listen->next = listen_list;
listen_list = listen;
restore_flags(flags);
spin_unlock_bh(&listen_lock);
return 1;
}
void ax25_listen_release(ax25_address *callsign, struct net_device *dev)
{
struct listen_struct *s, *listen = listen_list;
unsigned long flags;
struct listen_struct *s, *listen;
spin_lock_bh(&listen_lock);
listen = listen_list;
if (listen == NULL)
return;
save_flags(flags);
cli();
if (ax25cmp(&listen->callsign, callsign) == 0 && listen->dev == dev) {
listen_list = listen->next;
restore_flags(flags);
spin_unlock_bh(&listen_lock);
kfree(listen);
return;
}
......@@ -214,35 +194,41 @@ void ax25_listen_release(ax25_address *callsign, struct net_device *dev)
if (ax25cmp(&listen->next->callsign, callsign) == 0 && listen->next->dev == dev) {
s = listen->next;
listen->next = listen->next->next;
restore_flags(flags);
spin_unlock_bh(&listen_lock);
kfree(s);
return;
}
listen = listen->next;
}
restore_flags(flags);
spin_unlock_bh(&listen_lock);
}
int (*ax25_protocol_function(unsigned int pid))(struct sk_buff *, ax25_cb *)
{
int (*res)(struct sk_buff *, ax25_cb *) = NULL;
struct protocol_struct *protocol;
read_lock(&protocol_list_lock);
for (protocol = protocol_list; protocol != NULL; protocol = protocol->next)
if (protocol->pid == pid)
return protocol->func;
if (protocol->pid == pid) {
res = protocol->func;
break;
}
read_unlock(&protocol_list_lock);
return NULL;
return res;
}
int ax25_listen_mine(ax25_address *callsign, struct net_device *dev)
{
struct listen_struct *listen;
spin_lock_bh(&listen_lock);
for (listen = listen_list; listen != NULL; listen = listen->next)
if (ax25cmp(&listen->callsign, callsign) == 0 && (listen->dev == dev || listen->dev == NULL))
return 1;
spin_unlock_bh(&listen_lock);
return 0;
}
......@@ -251,18 +237,24 @@ void ax25_link_failed(ax25_cb *ax25, int reason)
{
struct linkfail_struct *linkfail;
spin_lock_bh(&linkfail_lock);
for (linkfail = linkfail_list; linkfail != NULL; linkfail = linkfail->next)
(linkfail->func)(ax25, reason);
spin_unlock_bh(&linkfail_lock);
}
int ax25_protocol_is_registered(unsigned int pid)
{
struct protocol_struct *protocol;
int res = 0;
read_lock(&protocol_list_lock);
for (protocol = protocol_list; protocol != NULL; protocol = protocol->next)
if (protocol->pid == pid)
return 1;
if (protocol->pid == pid) {
res = 1;
break;
}
read_unlock(&protocol_list_lock);
return 0;
return res;
}
/*
* AX.25 release 037
* 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 code REQUIRES 2.1.15 or higher/ NET3.038
*
* This module:
* This module 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.
*
* Most of this code is based on the SDL diagrams published in the 7th
* ARRL Computer Networking Conference papers. The diagrams have mistakes
* in them, but are mostly correct. Before you modify the code could you
* read the SDL diagrams as the code is not obvious and probably very
* easy to break;
*
* History
* AX.25 028a Jonathan(G4KLX) New state machine based on SDL diagrams.
* AX.25 028b Jonathan(G4KLX) Extracted AX25 control block from
* the sock structure.
* AX.25 029 Alan(GW4PTS) Switched to KA9Q constant names.
* Jonathan(G4KLX) Added IP mode registration.
* AX.25 030 Jonathan(G4KLX) Added AX.25 fragment reception.
* Upgraded state machine for SABME.
* Added arbitrary protocol id support.
* AX.25 031 Joerg(DL1BKE) Added DAMA support
* HaJo(DD8NE) Added Idle Disc Timer T5
* Joerg(DL1BKE) Renamed it to "IDLE" with a slightly
* different behaviour. Fixed defrag
* routine (I hope)
* AX.25 032 Darryl(G7LED) AX.25 segmentation fixed.
* AX.25 033 Jonathan(G4KLX) Remove auto-router.
* Modularisation changes.
* AX.25 035 Hans(PE1AYX) Fixed interface to IP layer.
* AX.25 036 Jonathan(G4KLX) Move DAMA code into own file.
* Joerg(DL1BKE) Fixed DAMA Slave.
* AX.25 037 Jonathan(G4KLX) New timer architecture.
* Thomas(DL9SAU) Fixed missing initialization of skb->protocol.
* Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)
* Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
* Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)
* Copyright (C) Hans-Joachim Hetscher DD8NE (dd8ne@bnv-bamberg.de)
*/
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/types.h>
......@@ -217,19 +187,15 @@ static int ax25_process_rx_frame(ax25_cb *ax25, struct sk_buff *skb, int type, i
return queued;
}
static int ax25_rcv(struct sk_buff *skb, struct net_device *dev, ax25_address *dev_addr, struct packet_type *ptype)
static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
ax25_address *dev_addr, struct packet_type *ptype)
{
struct sock *make;
struct sock *sk;
int type = 0;
ax25_address src, dest, *next_digi = NULL;
int type = 0, mine = 0, dama;
struct sock *make, *sk, *raw;
ax25_digi dp, reverse_dp;
ax25_cb *ax25;
ax25_address src, dest;
ax25_address *next_digi = NULL;
ax25_dev *ax25_dev;
struct sock *raw;
int mine = 0;
int dama;
/*
* Process the AX.25/LAPB frame.
......@@ -274,8 +240,10 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev, ax25_address *d
if ((*skb->data & ~0x10) == AX25_UI && dp.lastrepeat + 1 == dp.ndigi) {
skb->h.raw = skb->data + 2; /* skip control and pid */
if ((raw = ax25_addr_match(&dest)) != NULL)
if ((raw = ax25_addr_match(&dest)) != NULL) {
ax25_send_to_raw(raw, skb, skb->data[1]);
release_sock(raw);
}
if (!mine && ax25cmp(&dest, (ax25_address *)dev->broadcast) != 0) {
kfree_skb(skb);
......@@ -307,7 +275,8 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev, ax25_address *d
#endif
case AX25_P_TEXT:
/* Now find a suitable dgram socket */
if ((sk = ax25_find_socket(&dest, &src, SOCK_DGRAM)) != NULL) {
sk = ax25_get_socket(&dest, &src, SOCK_DGRAM);
if (sk != NULL) {
if (atomic_read(&sk->rmem_alloc) >= sk->rcvbuf) {
kfree_skb(skb);
} else {
......@@ -318,6 +287,7 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev, ax25_address *d
if (sock_queue_rcv_skb(sk, skb) != 0)
kfree_skb(skb);
}
release_sock(sk);
} else {
kfree_skb(skb);
}
......@@ -349,9 +319,10 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev, ax25_address *d
if ((ax25 = ax25_find_cb(&dest, &src, &reverse_dp, dev)) != NULL) {
/*
* Process the frame. If it is queued up internally it returns one otherwise we
* free it immediately. This routine itself wakes the user context layers so we
* do no further work
* Process the frame. If it is queued up internally it
* returns one otherwise we free it immediately. This
* routine itself wakes the user context layers so we do
* no further work
*/
if (ax25_process_rx_frame(ax25, skb, type, dama) == 0)
kfree_skb(skb);
......@@ -363,7 +334,8 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev, ax25_address *d
/* a) received not a SABM(E) */
if ((*skb->data & ~AX25_PF) != AX25_SABM && (*skb->data & ~AX25_PF) != AX25_SABME) {
if ((*skb->data & ~AX25_PF) != AX25_SABM &&
(*skb->data & ~AX25_PF) != AX25_SABME) {
/*
* Never reply to a DM. Also ignore any connects for
* addresses that are not our interfaces and not a socket.
......@@ -383,9 +355,12 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev, ax25_address *d
sk = ax25_find_listener(next_digi, 1, dev, SOCK_SEQPACKET);
if (sk != NULL) {
if (sk->ack_backlog == sk->max_ack_backlog || (make = ax25_make_new(sk, ax25_dev)) == NULL) {
if (mine) ax25_return_dm(dev, &src, &dest, &dp);
if (sk->ack_backlog == sk->max_ack_backlog ||
(make = ax25_make_new(sk, ax25_dev)) == NULL) {
if (mine)
ax25_return_dm(dev, &src, &dest, &dp);
kfree_skb(skb);
return 0;
}
......@@ -486,4 +461,3 @@ int ax25_kiss_rcv(struct sk_buff *skb, struct net_device *dev,
return ax25_rcv(skb, dev, (ax25_address *)dev->dev_addr, ptype);
}
/*
* AX.25 release 037
* 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 code REQUIRES 2.1.15 or higher/ NET3.038
*
* This module:
* This module 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.
*
* History
* AX.25 036 Jonathan(G4KLX) Split from af_ax25.c.
* Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
*/
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/types.h>
......@@ -112,8 +105,8 @@ int ax25_rebuild_header(struct sk_buff *skb)
unsigned char *bp = skb->data;
struct net_device *dev;
ax25_address *src, *dst;
ax25_route *route;
ax25_dev *ax25_dev;
ax25_route _route, *route = &_route;
dst = (ax25_address *)(bp + 1);
src = (ax25_address *)(bp + 8);
......@@ -121,14 +114,15 @@ int ax25_rebuild_header(struct sk_buff *skb)
if (arp_find(bp + 1, skb))
return 1;
route = ax25_rt_find_route(dst, NULL);
route = ax25_rt_find_route(route, dst, NULL);
dev = route->dev;
if (dev == NULL)
dev = skb->dev;
if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
return 1;
if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL) {
goto put;
}
if (bp[16] == AX25_P_IP) {
if (route->ip_mode == 'V' || (route->ip_mode == ' ' && ax25_dev->values[AX25_VALUES_IPDEFMODE])) {
......@@ -153,7 +147,7 @@ int ax25_rebuild_header(struct sk_buff *skb)
if ((ourskb = skb_copy(skb, GFP_ATOMIC)) == NULL) {
kfree_skb(skb);
return 1;
goto put;
}
if (skb->sk != NULL)
......@@ -170,7 +164,7 @@ int ax25_rebuild_header(struct sk_buff *skb)
ax25_send_frame(ourskb, ax25_dev->values[AX25_VALUES_PACLEN], &src_c,
&dst_c, route->digipeat, dev);
return 1;
goto put;
}
}
......@@ -187,7 +181,7 @@ int ax25_rebuild_header(struct sk_buff *skb)
if (route->digipeat != NULL) {
if ((ourskb = ax25_rt_build_path(skb, src, dst, route->digipeat)) == NULL) {
kfree_skb(skb);
return 1;
goto put;
}
skb = ourskb;
......@@ -197,6 +191,9 @@ int ax25_rebuild_header(struct sk_buff *skb)
ax25_queue_xmit(skb);
put:
ax25_put_route(route);
return 1;
}
......
/*
* AX.25 release 037
* 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 code REQUIRES 2.1.15 or higher/ NET3.038
*
* This module:
* This module 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.
*
* Most of this code is based on the SDL diagrams published in the 7th
* ARRL Computer Networking Conference papers. The diagrams have mistakes
* in them, but are mostly correct. Before you modify the code could you
* read the SDL diagrams as the code is not obvious and probably very
* easy to break;
*
* History
* AX.25 028a Jonathan(G4KLX) New state machine based on SDL diagrams.
* AX.25 029 Alan(GW4PTS) Switched to KA9Q constant names.
* Jonathan(G4KLX) Only poll when window is full.
* AX.25 030 Jonathan(G4KLX) Added fragmentation to ax25_output.
* Added support for extended AX.25.
* AX.25 031 Joerg(DL1BKE) Added DAMA support
* Joerg(DL1BKE) Modified fragmenter to fragment vanilla
* AX.25 I-Frames. Added PACLEN parameter.
* Joerg(DL1BKE) Fixed a problem with buffer allocation
* for fragments.
* AX.25 037 Jonathan(G4KLX) New timer architecture.
* Joerg(DL1BKE) Fixed DAMA Slave mode: will work
* on non-DAMA interfaces like AX25L2V2
* again (this behaviour is _required_).
* Joerg(DL1BKE) ax25_check_iframes_acked() returns a
* value now (for DAMA n2count handling)
* Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)
* Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
* Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)
*/
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/types.h>
......@@ -44,6 +18,7 @@
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/spinlock.h>
#include <linux/net.h>
#include <net/ax25.h>
#include <linux/inet.h>
......@@ -57,6 +32,8 @@
#include <linux/mm.h>
#include <linux/interrupt.h>
static spinlock_t ax25_frag_lock = SPIN_LOCK_UNLOCKED;
ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, ax25_address *src, ax25_address *dest, ax25_digi *digi, struct net_device *dev)
{
ax25_dev *ax25_dev;
......@@ -138,7 +115,6 @@ void ax25_output(ax25_cb *ax25, int paclen, struct sk_buff *skb)
struct sk_buff *skbn;
unsigned char *p;
int frontlen, len, fragno, ka9qfrag, first = 1;
long flags;
if ((skb->len - 1) > paclen) {
if (*skb->data == AX25_P_TEXT) {
......@@ -155,11 +131,9 @@ void ax25_output(ax25_cb *ax25, int paclen, struct sk_buff *skb)
frontlen = skb_headroom(skb); /* Address space + CTRL */
while (skb->len > 0) {
save_flags(flags);
cli();
spin_lock_bh(&ax25_frag_lock);
if ((skbn = alloc_skb(paclen + 2 + frontlen, GFP_ATOMIC)) == NULL) {
restore_flags(flags);
spin_unlock_bh(&ax25_frag_lock);
printk(KERN_CRIT "AX.25: ax25_output - out of memory\n");
return;
}
......@@ -167,7 +141,7 @@ void ax25_output(ax25_cb *ax25, int paclen, struct sk_buff *skb)
if (skb->sk != NULL)
skb_set_owner_w(skbn, skb->sk);
restore_flags(flags);
spin_unlock_bh(&ax25_frag_lock);
len = (paclen > skb->len) ? skb->len : paclen;
......
This diff is collapsed.
/*
* AX.25 release 037
* 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 code REQUIRES 2.1.15 or higher/ NET3.038
* Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)
* Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
* Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)
* Copyright (C) Hans-Joachim Hetscher DD8NE (dd8ne@bnv-bamberg.de)
*
* This module:
* This module 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.
*
* Most of this code is based on the SDL diagrams published in the 7th
* ARRL Computer Networking Conference papers. The diagrams have mistakes
* in them, but are mostly correct. Before you modify the code could you
* read the SDL diagrams as the code is not obvious and probably very
* easy to break;
*
* History
* AX.25 028a Jonathan(G4KLX) New state machine based on SDL diagrams.
* AX.25 028b Jonathan(G4KLX) Extracted AX25 control block from
* the sock structure.
* AX.25 029 Alan(GW4PTS) Switched to KA9Q constant names.
* Jonathan(G4KLX) Added IP mode registration.
* AX.25 030 Jonathan(G4KLX) Added AX.25 fragment reception.
* Upgraded state machine for SABME.
* Added arbitrary protocol id support.
* AX.25 031 Joerg(DL1BKE) Added DAMA support
* HaJo(DD8NE) Added Idle Disc Timer T5
* Joerg(DL1BKE) Renamed it to "IDLE" with a slightly
* different behaviour. Fixed defrag
* routine (I hope)
* AX.25 032 Darryl(G7LED) AX.25 segmentation fixed.
* AX.25 033 Jonathan(G4KLX) Remove auto-router.
* Modularisation changes.
* AX.25 035 Hans(PE1AYX) Fixed interface to IP layer.
* AX.25 036 Jonathan(G4KLX) Cloned from ax25_in.c.
* AX.25 037 Jonathan(G4KLX) New timer architecture.
* Most of this code is based on the SDL diagrams published in the 7th ARRL
* Computer Networking Conference papers. The diagrams have mistakes in them,
* but are mostly correct. Before you modify the code could you read the SDL
* diagrams as the code is not obvious and probably very easy to break.
*/
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
......@@ -142,7 +119,8 @@ static int ax25_std_state2_machine(ax25_cb *ax25, struct sk_buff *skb, int frame
case AX25_DM:
case AX25_UA:
if (pf) ax25_disconnect(ax25, 0);
if (pf)
ax25_disconnect(ax25, 0);
break;
case AX25_I:
......@@ -397,7 +375,8 @@ static int ax25_std_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frame
}
ax25_frames_acked(ax25, nr);
if (ax25->condition & AX25_COND_OWN_RX_BUSY) {
if (pf) ax25_std_enquiry_response(ax25);
if (pf)
ax25_std_enquiry_response(ax25);
break;
}
if (ns == ax25->vr) {
......
/*
* AX.25 release 037
* 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 code REQUIRES 2.1.15 or higher/ NET3.038
*
* This module:
* This module 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.
*
* Most of this code is based on the SDL diagrams published in the 7th
* ARRL Computer Networking Conference papers. The diagrams have mistakes
* in them, but are mostly correct. Before you modify the code could you
* read the SDL diagrams as the code is not obvious and probably very
* easy to break;
*
* History
* AX.25 036 Jonathan(G4KLX) Split from ax25_out.c.
* AX.25 037 Jonathan(G4KLX) New timer architecture.
* Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
*/
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
......
/*
* AX.25 release 037
* 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 code REQUIRES 2.1.15 or higher/ NET3.038
*
* This module:
* This module 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.
*
* History
* AX.25 028a Jonathan(G4KLX) New state machine based on SDL diagrams.
* AX.25 028b Jonathan(G4KLX) Extracted AX25 control block from the
* sock structure.
* AX.25 029 Alan(GW4PTS) Switched to KA9Q constant names.
* AX.25 031 Joerg(DL1BKE) Added DAMA support
* AX.25 032 Joerg(DL1BKE) Fixed DAMA timeout bug
* AX.25 033 Jonathan(G4KLX) Modularisation functions.
* AX.25 035 Frederic(F1OAT) Support for pseudo-digipeating.
* AX.25 036 Jonathan(G4KLX) Split from ax25_timer.c.
* AX.25 037 Jonathan(G4KLX) New timer architecture.
* Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)
* Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
* Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)
* Copyright (C) Frederic Rible F1OAT (frible@teaser.fr)
*/
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
......@@ -47,7 +34,6 @@
void ax25_std_heartbeat_expiry(ax25_cb *ax25)
{
switch (ax25->state) {
case AX25_STATE_0:
/* Magic here: If we listen() and a new link dies before it
is accepted() it isn't 'dead' so doesn't get removed. */
......
/*
* AX.25 release 037
* 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 code REQUIRES 2.1.15 or higher/ NET3.038
*
* This module:
* This module 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.
*
* Most of this code is based on the SDL diagrams published in the 7th
* ARRL Computer Networking Conference papers. The diagrams have mistakes
* in them, but are mostly correct. Before you modify the code could you
* read the SDL diagrams as the code is not obvious and probably very
* easy to break;
*
* History
* AX.25 029 Alan(GW4PTS) Switched to KA9Q constant names. Removed
* old BSD code.
* AX.25 030 Jonathan(G4KLX) Added support for extended AX.25.
* Added fragmentation support.
* Darryl(G7LED) Added function ax25_requeue_frames() to split
* it up from ax25_frames_acked().
* AX.25 031 Joerg(DL1BKE) DAMA needs KISS Fullduplex ON/OFF.
* Thus we have ax25_kiss_cmd() now... ;-)
* Dave Brown(N2RJT)
* Killed a silly bug in the DAMA code.
* Joerg(DL1BKE) Found the real bug in ax25.h, sri.
* AX.25 032 Joerg(DL1BKE) Added ax25_queue_length to count the number of
* enqueued buffers of a socket..
* AX.25 035 Frederic(F1OAT) Support for pseudo-digipeating.
* AX.25 037 Jonathan(G4KLX) New timer architecture.
* Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)
* Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
* Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)
* Copyright (C) Frederic Rible F1OAT (frible@teaser.fr)
*/
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
......
/*
* AX.25 release 037
* 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 code REQUIRES 2.1.15 or higher/ NET3.038
*
* This module:
* This module 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.
*
* History
* AX.25 028a Jonathan(G4KLX) New state machine based on SDL diagrams.
* AX.25 028b Jonathan(G4KLX) Extracted AX25 control block from the
* sock structure.
* AX.25 029 Alan(GW4PTS) Switched to KA9Q constant names.
* AX.25 031 Joerg(DL1BKE) Added DAMA support
* AX.25 032 Joerg(DL1BKE) Fixed DAMA timeout bug
* AX.25 033 Jonathan(G4KLX) Modularisation functions.
* AX.25 035 Frederic(F1OAT) Support for pseudo-digipeating.
* AX.25 036 Jonathan(G4KLX) Split Standard and DAMA code into separate files.
* Joerg(DL1BKE) Fixed DAMA Slave. We are *required* to start with
* standard AX.25 mode.
* AX.25 037 Jonathan(G4KLX) New timer architecture.
* Tomi(OH2BNS) Fixed heartbeat expiry (check ax25_dev).
* Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)
* Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
* Copyright (C) Tomi Manninen OH2BNS (oh2bns@sral.fi)
* Copyright (C) Darryl Miles G7LED (dlm@g7led.demon.co.uk)
* Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)
* Copyright (C) Frederic Rible F1OAT (frible@teaser.fr)
* Copyright (C) 2002 Ralf Baechle DO1GRB (ralf@gnu.org)
*/
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/types.h>
......@@ -152,12 +139,15 @@ unsigned long ax25_display_timer(struct timer_list *timer)
static void ax25_heartbeat_expiry(unsigned long param)
{
ax25_cb *ax25 = (ax25_cb *)param;
int proto = AX25_PROTO_STD_SIMPLEX;
ax25_cb *ax25 = (ax25_cb *)param;
struct sock *sk = ax25->sk;
if (ax25->ax25_dev)
proto = ax25->ax25_dev->values[AX25_VALUES_PROTOCOL];
bh_lock_sock(sk);
switch (proto) {
case AX25_PROTO_STD_SIMPLEX:
case AX25_PROTO_STD_DUPLEX:
......@@ -173,12 +163,15 @@ static void ax25_heartbeat_expiry(unsigned long param)
break;
#endif
}
bh_unlock_sock(sk);
}
static void ax25_t1timer_expiry(unsigned long param)
{
ax25_cb *ax25 = (ax25_cb *)param;
struct sock *sk = ax25->sk;
bh_lock_sock(sk);
switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
case AX25_PROTO_STD_SIMPLEX:
case AX25_PROTO_STD_DUPLEX:
......@@ -192,12 +185,15 @@ static void ax25_t1timer_expiry(unsigned long param)
break;
#endif
}
bh_unlock_sock(sk);
}
static void ax25_t2timer_expiry(unsigned long param)
{
ax25_cb *ax25 = (ax25_cb *)param;
struct sock *sk = ax25->sk;
bh_lock_sock(sk);
switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
case AX25_PROTO_STD_SIMPLEX:
case AX25_PROTO_STD_DUPLEX:
......@@ -211,12 +207,15 @@ static void ax25_t2timer_expiry(unsigned long param)
break;
#endif
}
bh_unlock_sock(sk);
}
static void ax25_t3timer_expiry(unsigned long param)
{
ax25_cb *ax25 = (ax25_cb *)param;
struct sock *sk = ax25->sk;
bh_lock_sock(sk);
switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
case AX25_PROTO_STD_SIMPLEX:
case AX25_PROTO_STD_DUPLEX:
......@@ -232,12 +231,15 @@ static void ax25_t3timer_expiry(unsigned long param)
break;
#endif
}
bh_unlock_sock(sk);
}
static void ax25_idletimer_expiry(unsigned long param)
{
ax25_cb *ax25 = (ax25_cb *)param;
struct sock *sk = ax25->sk;
bh_lock_sock(sk);
switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
case AX25_PROTO_STD_SIMPLEX:
case AX25_PROTO_STD_DUPLEX:
......@@ -253,4 +255,5 @@ static void ax25_idletimer_expiry(unsigned long param)
break;
#endif
}
bh_unlock_sock(sk);
}
/*
* AX.25 release 037
* 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 code REQUIRES 2.1.15 or higher/ NET3.038
*
* This module:
* This module 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.
*
* History
* AX.25 036 Jonathan(G4KLX) Split from af_ax25.c.
* Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
*/
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
......@@ -23,6 +16,7 @@
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/net.h>
#include <linux/spinlock.h>
#include <net/ax25.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
......@@ -47,17 +41,23 @@
*/
static ax25_uid_assoc *ax25_uid_list;
static rwlock_t ax25_uid_lock = RW_LOCK_UNLOCKED;
int ax25_uid_policy = 0;
ax25_address *ax25_findbyuid(uid_t uid)
{
ax25_uid_assoc *ax25_uid;
ax25_address *res = NULL;
read_lock(&ax25_uid_lock);
for (ax25_uid = ax25_uid_list; ax25_uid != NULL; ax25_uid = ax25_uid->next) {
if (ax25_uid->uid == uid)
return &ax25_uid->call;
if (ax25_uid->uid == uid) {
res = &ax25_uid->call;
break;
}
}
read_unlock(&ax25_uid_lock);
return NULL;
}
......@@ -65,15 +65,21 @@ ax25_address *ax25_findbyuid(uid_t uid)
int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
{
ax25_uid_assoc *s, *ax25_uid;
unsigned long flags;
unsigned long res;
switch (cmd) {
case SIOCAX25GETUID:
res = -ENOENT;
read_lock(&ax25_uid_lock);
for (ax25_uid = ax25_uid_list; ax25_uid != NULL; ax25_uid = ax25_uid->next) {
if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0)
return ax25_uid->uid;
if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0) {
res = ax25_uid->uid;
break;
}
return -ENOENT;
}
read_unlock(&ax25_uid_lock);
return res;
case SIOCAX25ADDUID:
if (!capable(CAP_NET_ADMIN))
......@@ -84,40 +90,48 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
return -EINVAL;
if ((ax25_uid = kmalloc(sizeof(*ax25_uid), GFP_KERNEL)) == NULL)
return -ENOMEM;
ax25_uid->uid = sax->sax25_uid;
ax25_uid->call = sax->sax25_call;
save_flags(flags); cli();
write_lock(&ax25_uid_lock);
ax25_uid->next = ax25_uid_list;
ax25_uid_list = ax25_uid;
restore_flags(flags);
write_unlock(&ax25_uid_lock);
return 0;
case SIOCAX25DELUID:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
write_lock(&ax25_uid_lock);
for (ax25_uid = ax25_uid_list; ax25_uid != NULL; ax25_uid = ax25_uid->next) {
if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0)
if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0) {
break;
}
if (ax25_uid == NULL)
}
if (ax25_uid == NULL) {
write_unlock(&ax25_uid_lock);
return -ENOENT;
save_flags(flags); cli();
}
if ((s = ax25_uid_list) == ax25_uid) {
ax25_uid_list = s->next;
restore_flags(flags);
write_unlock(&ax25_uid_lock);
kfree(ax25_uid);
return 0;
}
while (s != NULL && s->next != NULL) {
if (s->next == ax25_uid) {
s->next = ax25_uid->next;
restore_flags(flags);
write_unlock(&ax25_uid_lock);
kfree(ax25_uid);
return 0;
}
s = s->next;
}
restore_flags(flags);
write_unlock(&ax25_uid_lock);
return -ENOENT;
default:
......@@ -134,8 +148,7 @@ int ax25_uid_get_info(char *buffer, char **start, off_t offset, int length)
off_t pos = 0;
off_t begin = 0;
cli();
read_lock(&ax25_uid_lock);
len += sprintf(buffer, "Policy: %d\n", ax25_uid_policy);
for (pt = ax25_uid_list; pt != NULL; pt = pt->next) {
......@@ -151,13 +164,13 @@ int ax25_uid_get_info(char *buffer, char **start, off_t offset, int length)
if (pos > offset + length)
break;
}
sti();
read_unlock(&ax25_uid_lock);
*start = buffer + (offset - begin);
len -= offset - begin;
if (len > length) len = length;
if (len > length)
len = length;
return len;
}
......@@ -167,12 +180,16 @@ int ax25_uid_get_info(char *buffer, char **start, off_t offset, int length)
*/
void __exit ax25_uid_free(void)
{
ax25_uid_assoc *s, *ax25_uid = ax25_uid_list;
ax25_uid_assoc *s, *ax25_uid;
write_lock(&ax25_uid_lock);
ax25_uid = ax25_uid_list;
while (ax25_uid != NULL) {
s = ax25_uid;
ax25_uid = ax25_uid->next;
kfree(s);
}
ax25_uid_list = NULL;
write_unlock(&ax25_uid_lock);
}
/* -*- linux-c -*-
* sysctl_net_ax25.c: sysctl interface to net AX.25 subsystem.
/*
* 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.
*
* Begun April 1, 1996, Mike Shaver.
* Added /proc/sys/net/ax25 directory entry (empty =) ). [MS]
* Copyright (C) 1996 Mike Shaver (shaver@zeroknowledge.com)
*/
#include <linux/config.h>
#include <linux/mm.h>
#include <linux/sysctl.h>
#include <linux/spinlock.h>
#include <net/ax25.h>
static int min_ipdefmode[] = {0}, max_ipdefmode[] = {1};
......@@ -105,6 +107,7 @@ void ax25_register_sysctl(void)
ax25_dev *ax25_dev;
int n, k;
spin_lock_bh(&ax25_dev_lock);
for (ax25_table_size = sizeof(ctl_table), ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next)
ax25_table_size += sizeof(ctl_table);
......@@ -119,6 +122,7 @@ void ax25_register_sysctl(void)
while (n--)
kfree(ax25_table[n].child);
kfree(ax25_table);
spin_unlock_bh(&ax25_dev_lock);
return;
}
memcpy(child, ax25_param_table, sizeof(ax25_param_table));
......@@ -144,6 +148,7 @@ void ax25_register_sysctl(void)
n++;
}
spin_unlock_bh(&ax25_dev_lock);
ax25_dir_table[0].child = ax25_table;
......
......@@ -24,16 +24,10 @@
#include <net/llc_pdu.h>
#include <net/llc_mac.h>
static void llc_station_ack_tmr_callback(unsigned long timeout_data);
int llc_station_ac_start_ack_timer(struct llc_station *station,
struct sk_buff *skb)
{
del_timer(&station->ack_timer);
station->ack_timer.expires = jiffies + LLC_ACK_TIME * HZ;
station->ack_timer.data = (unsigned long)station;
station->ack_timer.function = llc_station_ack_tmr_callback;
add_timer(&station->ack_timer);
mod_timer(&station->ack_timer, jiffies + LLC_ACK_TIME * HZ);
return 0;
}
......@@ -130,7 +124,7 @@ int llc_station_ac_report_status(struct llc_station *station,
return 0;
}
static void llc_station_ack_tmr_callback(unsigned long timeout_data)
void llc_station_ack_tmr_cb(unsigned long timeout_data)
{
struct llc_station *station = (struct llc_station *)timeout_data;
struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
......
......@@ -28,10 +28,6 @@
#include <net/llc_pdu.h>
#include <net/llc_mac.h>
static void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data);
static void llc_conn_ack_tmr_cb(unsigned long timeout_data);
static void llc_conn_rej_tmr_cb(unsigned long timeout_data);
static void llc_conn_busy_tmr_cb(unsigned long timeout_data);
static int llc_conn_ac_inc_vs_by_1(struct sock *sk, struct sk_buff *skb);
static void llc_process_tmr_ev(struct sock *sk, struct sk_buff *skb);
static int llc_conn_ac_data_confirm(struct sock *sk, struct sk_buff *ev);
......@@ -664,11 +660,8 @@ int llc_conn_ac_set_remote_busy(struct sock *sk, struct sk_buff *skb)
if (!llc->remote_busy_flag) {
llc->remote_busy_flag = 1;
llc->busy_state_timer.timer.expires = jiffies +
llc->busy_state_timer.expire * HZ;
llc->busy_state_timer.timer.data = (unsigned long)sk;
llc->busy_state_timer.timer.function = llc_conn_busy_tmr_cb;
add_timer(&llc->busy_state_timer.timer);
mod_timer(&llc->busy_state_timer.timer,
jiffies + llc->busy_state_timer.expire * HZ);
}
return 0;
}
......@@ -905,12 +898,8 @@ int llc_conn_ac_start_p_timer(struct sock *sk, struct sk_buff *skb)
struct llc_opt *llc = llc_sk(sk);
llc->p_flag = 1;
del_timer(&llc->pf_cycle_timer.timer);
llc->pf_cycle_timer.timer.expires = jiffies +
llc->pf_cycle_timer.expire * HZ;
llc->pf_cycle_timer.timer.data = (unsigned long)sk;
llc->pf_cycle_timer.timer.function = llc_conn_pf_cycle_tmr_cb;
add_timer(&llc->pf_cycle_timer.timer);
mod_timer(&llc->pf_cycle_timer.timer,
jiffies + llc->pf_cycle_timer.expire * HZ);
return 0;
}
......@@ -1181,11 +1170,7 @@ int llc_conn_ac_start_ack_timer(struct sock *sk, struct sk_buff *skb)
{
struct llc_opt *llc = llc_sk(sk);
del_timer(&llc->ack_timer.timer);
llc->ack_timer.timer.expires = jiffies + llc->ack_timer.expire * HZ;
llc->ack_timer.timer.data = (unsigned long)sk;
llc->ack_timer.timer.function = llc_conn_ack_tmr_cb;
add_timer(&llc->ack_timer.timer);
mod_timer(&llc->ack_timer.timer, jiffies + llc->ack_timer.expire * HZ);
return 0;
}
......@@ -1193,12 +1178,8 @@ int llc_conn_ac_start_rej_timer(struct sock *sk, struct sk_buff *skb)
{
struct llc_opt *llc = llc_sk(sk);
del_timer(&llc->rej_sent_timer.timer);
llc->rej_sent_timer.timer.expires = jiffies +
llc->rej_sent_timer.expire * HZ;
llc->rej_sent_timer.timer.data = (unsigned long)sk;
llc->rej_sent_timer.timer.function = llc_conn_rej_tmr_cb;
add_timer(&llc->rej_sent_timer.timer);
mod_timer(&llc->rej_sent_timer.timer,
jiffies + llc->rej_sent_timer.expire * HZ);
return 0;
}
......@@ -1207,13 +1188,9 @@ int llc_conn_ac_start_ack_tmr_if_not_running(struct sock *sk,
{
struct llc_opt *llc = llc_sk(sk);
if (!timer_pending(&llc->ack_timer.timer)) {
llc->ack_timer.timer.expires = jiffies +
llc->ack_timer.expire * HZ;
llc->ack_timer.timer.data = (unsigned long)sk;
llc->ack_timer.timer.function = llc_conn_ack_tmr_cb;
add_timer(&llc->ack_timer.timer);
}
if (!timer_pending(&llc->ack_timer.timer))
mod_timer(&llc->ack_timer.timer,
jiffies + llc->ack_timer.expire * HZ);
return 0;
}
......@@ -1260,13 +1237,9 @@ int llc_conn_ac_upd_nr_received(struct sock *sk, struct sk_buff *skb)
llc->failed_data_req = 0;
llc_conn_ac_data_confirm(sk, skb);
}
if (unacked) {
llc->ack_timer.timer.expires = jiffies +
llc->ack_timer.expire * HZ;
llc->ack_timer.timer.data = (unsigned long)sk;
llc->ack_timer.timer.function = llc_conn_ack_tmr_cb;
add_timer(&llc->ack_timer.timer);
}
if (unacked)
mod_timer(&llc->ack_timer.timer,
jiffies + llc->ack_timer.expire * HZ);
} else if (llc->failed_data_req) {
llc_pdu_decode_pf_bit(skb, &fbit);
if (fbit == 1) {
......@@ -1413,7 +1386,7 @@ void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data)
bh_unlock_sock(sk);
}
static void llc_conn_busy_tmr_cb(unsigned long timeout_data)
void llc_conn_busy_tmr_cb(unsigned long timeout_data)
{
struct sock *sk = (struct sock *)timeout_data;
struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
......@@ -1445,7 +1418,7 @@ void llc_conn_ack_tmr_cb(unsigned long timeout_data)
bh_unlock_sock(sk);
}
static void llc_conn_rej_tmr_cb(unsigned long timeout_data)
void llc_conn_rej_tmr_cb(unsigned long timeout_data)
{
struct sock *sk = (struct sock *)timeout_data;
struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
......
......@@ -194,7 +194,8 @@ int llc_conn_ev_rx_i_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
{
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_I(pdu) &&
return llc_conn_space(sk, skb) &&
!LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_I(pdu) &&
!LLC_I_PF_IS_0(pdu) &&
LLC_I_GET_NS(pdu) == llc_sk(sk)->vR ? 0 : 1;
}
......@@ -203,7 +204,8 @@ int llc_conn_ev_rx_i_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
{
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_I(pdu) &&
return llc_conn_space(sk, skb) &&
!LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_I(pdu) &&
!LLC_I_PF_IS_1(pdu) &&
LLC_I_GET_NS(pdu) == llc_sk(sk)->vR ? 0 : 1;
}
......@@ -250,7 +252,8 @@ int llc_conn_ev_rx_i_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
{
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_I(pdu) &&
return llc_conn_space(sk, skb) &&
!LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_I(pdu) &&
!LLC_I_PF_IS_0(pdu) &&
LLC_I_GET_NS(pdu) == llc_sk(sk)->vR ? 0 : 1;
}
......@@ -268,7 +271,8 @@ int llc_conn_ev_rx_i_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
{
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_I(pdu) &&
return llc_conn_space(sk, skb) &&
!LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_I(pdu) &&
LLC_I_GET_NS(pdu) == llc_sk(sk)->vR ? 0 : 1;
}
......@@ -423,7 +427,8 @@ int llc_conn_ev_rx_rr_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
{
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_S(pdu) &&
return llc_conn_space(sk, skb) &&
!LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_S(pdu) &&
!LLC_S_PF_IS_0(pdu) &&
LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_RR ? 0 : 1;
}
......@@ -432,7 +437,8 @@ int llc_conn_ev_rx_rr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
{
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_S(pdu) &&
return llc_conn_space(sk, skb) &&
!LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_S(pdu) &&
!LLC_S_PF_IS_1(pdu) &&
LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_RR ? 0 : 1;
}
......
......@@ -184,19 +184,32 @@ int llc_sk_init(struct sock* sk)
goto out;
memset(llc, 0, sizeof(*llc));
rc = 0;
llc->sk = sk;
llc->state = LLC_CONN_STATE_ADM;
llc->inc_cntr = llc->dec_cntr = 2;
llc->dec_step = llc->connect_step = 1;
llc->ack_timer.expire = LLC_ACK_TIME;
llc->ack_timer.timer.data = (unsigned long)sk;
llc->ack_timer.timer.function = llc_conn_ack_tmr_cb;
llc->pf_cycle_timer.expire = LLC_P_TIME;
llc->pf_cycle_timer.timer.data = (unsigned long)sk;
llc->pf_cycle_timer.timer.function = llc_conn_pf_cycle_tmr_cb;
llc->rej_sent_timer.expire = LLC_REJ_TIME;
llc->rej_sent_timer.timer.data = (unsigned long)sk;
llc->rej_sent_timer.timer.function = llc_conn_rej_tmr_cb;
llc->busy_state_timer.expire = LLC_BUSY_TIME;
llc->busy_state_timer.timer.data = (unsigned long)sk;
llc->busy_state_timer.timer.function = llc_conn_busy_tmr_cb;
llc->n2 = 2; /* max retransmit */
llc->k = 2; /* tx win size, will adjust dynam */
llc->rw = 128; /* rx win size (opt and equal to
* tx_win of remote LLC)
*/
* tx_win of remote LLC) */
skb_queue_head_init(&llc->pdu_unack_q);
sk->backlog_rcv = llc_backlog_rcv;
llc_sk(sk) = llc;
......@@ -534,6 +547,21 @@ struct sk_buff *llc_alloc_frame(void)
return skb;
}
static char *llc_conn_state_names[] = {
[LLC_CONN_STATE_ADM] = "adm",
[LLC_CONN_STATE_SETUP] = "setup",
[LLC_CONN_STATE_NORMAL] = "normal",
[LLC_CONN_STATE_BUSY] = "busy",
[LLC_CONN_STATE_REJ] = "rej",
[LLC_CONN_STATE_AWAIT] = "await",
[LLC_CONN_STATE_AWAIT_BUSY] = "await_busy",
[LLC_CONN_STATE_AWAIT_REJ] = "await_rej",
[LLC_CONN_STATE_D_CONN] = "d_conn",
[LLC_CONN_STATE_RESET] = "reset",
[LLC_CONN_STATE_ERROR] = "error",
[LLC_CONN_STATE_TEMP] = "temp",
};
static int llc_proc_get_info(char *bf, char **start, off_t offset, int length)
{
struct llc_opt *llc;
......@@ -546,19 +574,34 @@ static int llc_proc_get_info(char *bf, char **start, off_t offset, int length)
struct llc_sap *sap = list_entry(sap_entry, struct llc_sap,
node);
len += sprintf(bf + len, "lsap=%d\n", sap->laddr.lsap);
len += sprintf(bf + len, "lsap=%02X\n", sap->laddr.lsap);
spin_lock_bh(&sap->sk_list.lock);
if (list_empty(&sap->sk_list.list)) {
len += sprintf(bf + len, "no connections\n");
goto unlock;
}
len += sprintf(bf + len,
"connection list:\nstate retr txwin rxwin\n");
len += sprintf(bf + len, "connection list:\n"
"dsap state retr txw rxw "
"pf ff sf df rs cs "
"tack tpfc trs tbs blog busr\n");
list_for_each(llc_entry, &sap->sk_list.list) {
llc = list_entry(llc_entry, struct llc_opt, node);
len += sprintf(bf + len, " %-5d%-5d%-6d%-5d\n",
llc->state, llc->retry_count, llc->k,
llc->rw);
len += sprintf(bf + len, " %02X %-10s %3d %3d %3d "
"%2d %2d %2d "
"%2d %2d %2d "
"%4d %4d %3d %3d %4d %4d\n",
llc->daddr.lsap,
llc_conn_state_names[llc->state],
llc->retry_count, llc->k, llc->rw,
llc->p_flag, llc->f_flag, llc->s_flag,
llc->data_flag, llc->remote_busy_flag,
llc->cause_flag,
timer_pending(&llc->ack_timer.timer),
timer_pending(&llc->pf_cycle_timer.timer),
timer_pending(&llc->rej_sent_timer.timer),
timer_pending(&llc->busy_state_timer.timer),
!!llc->sk->backlog.tail,
llc->sk->lock.users);
}
unlock:
spin_unlock_bh(&sap->sk_list.lock);
......@@ -608,6 +651,9 @@ static int __init llc_init(void)
skb_queue_head_init(&llc_main_station.mac_pdu_q);
skb_queue_head_init(&llc_main_station.ev_q.list);
spin_lock_init(&llc_main_station.ev_q.lock);
llc_main_station.ack_timer.data = (unsigned long)&llc_main_station;
llc_main_station.ack_timer.function = llc_station_ack_tmr_cb;
skb = alloc_skb(0, GFP_ATOMIC);
if (!skb)
goto err;
......
......@@ -360,11 +360,11 @@ static int llc_ui_release(struct socket *sock)
llc->laddr.lsap, llc->daddr.lsap);
if (!llc_send_disc(sk))
llc_ui_wait_for_disc(sk, sk->rcvtimeo);
release_sock(sk);
if (!sk->zapped) {
llc_sap_unassign_sock(llc->sap, sk);
llc_ui_remove_socket(sk);
}
release_sock(sk);
if (llc->sap && list_empty(&llc->sap->sk_list.list))
llc_sap_close(llc->sap);
sock_put(sk);
......@@ -484,10 +484,10 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr)
llc->daddr.lsap = addr->sllc_dsap;
memcpy(llc->daddr.mac, addr->sllc_dmac, IFHWADDRLEN);
memcpy(&llc->addr, addr, sizeof(llc->addr));
rc = sk->zapped = 0;
llc_ui_insert_socket(sk);
/* assign new connection to it's SAP */
llc_sap_assign_sock(sap, sk);
rc = sk->zapped = 0;
out:
return rc;
}
......@@ -952,7 +952,9 @@ static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, int len,
if (size > dev->mtu)
size = dev->mtu;
copied = size - hdrlen;
release_sock(sk);
skb = sock_alloc_send_skb(sk, size, noblock, &rc);
lock_sock(sk);
if (!skb)
goto release;
skb->sk = sk;
......
This diff is collapsed.
/*
* NET/ROM release 007
* 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 code REQUIRES 2.1.15 or higher/ NET3.038
*
* This module:
* This module 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.
*
* History
* NET/ROM 001 Jonathan(G4KLX) Cloned from loopback.c
* NET/ROM 002 Steve Whitehouse(GW7RRM) fixed the set_mac_address
* NET/ROM 003 Jonathan(G4KLX) Put nr_rebuild_header into line with
* ax25_rebuild_header
* NET/ROM 004 Jonathan(G4KLX) Callsign registration with AX.25.
* NET/ROM 006 Hans(PE1AYX) Fixed interface to IP layer.
* Copyright Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
*/
#include <linux/config.h>
#define __NO_VERSION__
#include <linux/module.h>
......
/*
* NET/ROM release 007
* 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 code REQUIRES 2.1.15 or higher/ NET3.038
*
* This module:
* This module 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.
*
* Most of this code is based on the SDL diagrams published in the 7th
* ARRL Computer Networking Conference papers. The diagrams have mistakes
* in them, but are mostly correct. Before you modify the code could you
* read the SDL diagrams as the code is not obvious and probably very
* easy to break;
*
* History
* NET/ROM 001 Jonathan(G4KLX) Cloned from ax25_in.c
* NET/ROM 003 Jonathan(G4KLX) Added NET/ROM fragment reception.
* Darryl(G7LED) Added missing INFO with NAK case, optimized
* INFOACK handling, removed reconnect on error.
* NET/ROM 006 Jonathan(G4KLX) Hdrincl removal changes.
* NET/ROM 007 Jonathan(G4KLX) New timer architecture.
* Copyright Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
* Copyright Darryl Miles G7LED (dlm@g7led.demon.co.uk)
*/
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
......@@ -88,10 +71,10 @@ static int nr_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more)
* The handling of the timer(s) is in file nr_timer.c.
* Handling of state 0 and connection release is in netrom.c.
*/
static int nr_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype)
static int nr_state1_machine(struct sock *sk, struct sk_buff *skb,
int frametype)
{
switch (frametype) {
case NR_CONNACK: {
nr_cb *nr = nr_sk(sk);
......@@ -128,10 +111,10 @@ static int nr_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype
* The handling of the timer(s) is in file nr_timer.c
* Handling of state 0 and connection release is in netrom.c.
*/
static int nr_state2_machine(struct sock *sk, struct sk_buff *skb, int frametype)
static int nr_state2_machine(struct sock *sk, struct sk_buff *skb,
int frametype)
{
switch (frametype) {
case NR_CONNACK | NR_CHOKE_FLAG:
nr_disconnect(sk, ECONNRESET);
break;
......@@ -168,7 +151,6 @@ static int nr_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype
ns = skb->data[17];
switch (frametype) {
case NR_CONNREQ:
nr_write_internal(sk, NR_CONNACK);
break;
......
/*
* NET/ROM release 007
*
* This code REQUIRES 2.1.15 or higher/ NET3.038
*
* This module:
* This module 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.
*
* History
* NET/ROM 007 Tomi(OH2BNS) Created this file.
* Small change in nr_loopback_queue().
* 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.
*
* Copyright Tomi Manninen OH2BNS (oh2bns@sral.fi)
*/
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/timer.h>
......
/*
* NET/ROM release 007
* 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 code REQUIRES 2.1.15 or higher/ NET3.038
*
* This module:
* This module 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.
*
* History
* NET/ROM 001 Jonathan(G4KLX) Cloned from ax25_out.c
* NET/ROM 003 Jonathan(G4KLX) Added NET/ROM fragmentation.
* Darryl(G7LED) Fixed NAK, to give out correct reponse.
* NET/ROM 007 Jonathan(G4KLX) New timer architecture.
* Copyright Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
* Copyright Darryl Miles G7LED (dlm@g7led.demon.co.uk)
*/
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
......@@ -196,7 +187,7 @@ void nr_kick(struct sock *sk)
void nr_transmit_buffer(struct sock *sk, struct sk_buff *skb)
{
nr_cb *nr = nr;
nr_cb *nr = nr_sk(sk);
unsigned char *dptr;
/*
......
This diff is collapsed.
/*
* NET/ROM release 007
* 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 code REQUIRES 2.1.15 or higher/ NET3.038
*
* This module:
* This module 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.
*
* History
* NET/ROM 001 Jonathan(G4KLX) Cloned from ax25_subr.c
* NET/ROM 003 Jonathan(G4KLX) Added G8BPQ NET/ROM extensions.
* NET/ROM 007 Jonathan(G4KLX) New timer architecture.
* Copyright Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
*/
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
......@@ -165,7 +156,6 @@ void nr_write_internal(struct sock *sk, int frametype)
dptr = skb_put(skb, skb_tailroom(skb));
switch (frametype & 0x0F) {
case NR_CONNREQ:
timeout = nr->t1 / HZ;
*dptr++ = nr->my_index;
......
This diff is collapsed.
/* -*- linux-c -*-
* sysctl_net_netrom.c: sysctl interface to net NET/ROM subsystem.
/*
* 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.
*
* Begun April 1, 1996, Mike Shaver.
* Added /proc/sys/net/netrom directory entry (empty =) ). [MS]
* Copyright (C) 1996 Mike Shaver (shaver@zeroknowledge.com)
*/
#include <linux/mm.h>
#include <linux/sysctl.h>
#include <linux/init.h>
......
This diff is collapsed.
/*
* ROSE release 003
* 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 code REQUIRES 2.1.15 or higher/ NET3.038
*
* This module:
* This module 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.
*
* History
* ROSE 001 Jonathan(G4KLX) Cloned from nr_dev.c.
* Hans(PE1AYX) Fixed interface to IP layer.
* Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
*/
#include <linux/config.h>
#define __NO_VERSION__
#include <linux/module.h>
......@@ -29,7 +21,7 @@
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/in.h>
#include <linux/if_ether.h> /* For the statistics structure. */
#include <linux/if_ether.h>
#include <asm/system.h>
#include <asm/io.h>
......
This diff is collapsed.
/*
* ROSE release 003
* 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 code REQUIRES 2.1.15 or higher/ NET3.038
*
* This module:
* This module 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.
*
* History
* ROSE 001 Jonathan(G4KLX) Cloned from rose_timer.c
* ROSE 003 Jonathan(G4KLX) New timer architecture.
* Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
*/
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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