Commit a3c7a8fa authored by Linus Torvalds's avatar Linus Torvalds

Import 1.3.20

parent 961f4bfa
VERSION = 1
PATCHLEVEL = 3
SUBLEVEL = 19
SUBLEVEL = 20
ARCH = i386
......@@ -113,7 +113,7 @@ include arch/$(ARCH)/Makefile
$(CC) -D__ASSEMBLY__ -traditional -c -o $*.o $<
Version: dummy
rm -f include/linux/version.h
@rm -f include/linux/compile.h
boot: vmlinux
@$(MAKE) -C arch/$(ARCH)/boot
......@@ -140,6 +140,7 @@ linuxsubdirs: dummy
set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i; done
$(TOPDIR)/include/linux/version.h: include/linux/version.h
$(TOPDIR)/include/linux/compile.h: include/linux/compile.h
newversion:
@if [ ! -f .version ]; then \
......@@ -148,8 +149,7 @@ newversion:
expr `cat .version` + 1 > .version; \
fi
include/linux/version.h: $(CONFIGURATION) Makefile newversion
@echo \#define UTS_RELEASE \"$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)\" > .ver
include/linux/compile.h: $(CONFIGURATION) include/linux/version.h newversion
@if [ -f .name ]; then \
echo \#define UTS_VERSION \"\#`cat .version`-`cat .name` `date`\"; \
else \
......@@ -166,10 +166,14 @@ include/linux/version.h: $(CONFIGURATION) Makefile newversion
echo \#define LINUX_COMPILE_DOMAIN ; \
fi >> .ver
@echo \#define LINUX_COMPILER \"`$(HOSTCC) -v 2>&1 | tail -1`\" >> .ver
@mv -f .ver $@
include/linux/version.h: ./Makefile
@echo \#define UTS_RELEASE \"$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)\" > .ver
@echo \#define LINUX_VERSION_CODE `expr $(VERSION) \\* 65536 + $(PATCHLEVEL) \\* 256 + $(SUBLEVEL)` >> .ver
if [ ! -f $@ ]; then mv .ver $@; fi
@mv -f .ver $@
init/version.o: init/version.c include/linux/version.h
init/version.o: init/version.c include/linux/compile.h
$(CC) $(CFLAGS) -DUTS_MACHINE='"$(ARCH)"' -c -o init/version.o init/version.c
init/main.o: init/main.c
......@@ -225,7 +229,7 @@ modules_install:
)
clean: archclean
rm -f kernel/ksyms.lst
rm -f kernel/ksyms.lst include/linux/compile.h
rm -f core `find . -name '*.[oas]' -print`
rm -f core `find . -type f -name 'core' -print`
rm -f vmlinux System.map
......@@ -253,11 +257,9 @@ backup: mrproper
sync
#depend dep: .hdepend
depend dep: archdep .hdepend
touch include/linux/version.h
depend dep: archdep .hdepend include/linux/version.h
awk -f scripts/depend.awk init/*.c > .tmpdepend
set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i fastdep; done
rm -f include/linux/version.h
mv .tmpdepend .depend
ifdef CONFIG_MODVERSIONS
@echo updating $(TOPDIR)/include/linux/modversions.h
......
......@@ -695,7 +695,6 @@ static void msg(int level, const char *fmt, ...)
{
char buf[256];
va_list args;
extern int vsprintf(char *, const char *, va_list);
if (!(sbpcd_debug&(1<<level))) return;
......
......@@ -385,7 +385,7 @@ sl_bump(struct slip *sl)
skb->dev = sl->dev;
memcpy(skb_put(skb,count), sl->rbuff, count);
skb->mac.raw=skb->data;
if(sl->mode&(SL_MODE_AX25|SL_MODE_AX25VC))
if(sl->mode & SL_MODE_AX25)
skb->protocol=htons(ETH_P_AX25);
else
skb->protocol=htons(ETH_P_IP);
......@@ -537,7 +537,7 @@ sl_header(struct sk_buff *skb, struct device *dev, unsigned short type,
#ifdef CONFIG_INET
struct slip *sl = (struct slip*)(dev->priv);
if (((sl->mode & SL_MODE_AX25) || (sl->mode & SL_MODE_AX25VC)) && type != htons(ETH_P_AX25)) {
if (sl->mode & SL_MODE_AX25 && type != htons(ETH_P_AX25)) {
return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
}
#endif
......@@ -555,7 +555,7 @@ sl_rebuild_header(void *buff, struct device *dev, unsigned long raddr,
#ifdef CONFIG_INET
struct slip *sl = (struct slip*)(dev->priv);
if ((sl->mode & SL_MODE_AX25) || (sl->mode & SL_MODE_AX25VC)) {
if (sl->mode & SL_MODE_AX25) {
return ax25_rebuild_header(buff, dev, raddr, skb);
}
#endif
......@@ -752,7 +752,7 @@ slip_open(struct tty_struct *tty)
sl->mode = SL_MODE_DEFAULT;
sl->dev->type = ARPHRD_SLIP + sl->mode;
#ifdef CONFIG_AX25
if (sl->dev->type == 260 || sl->dev->type == 272) { /* KISS */
if (sl->dev->type == 260) { /* KISS */
sl->dev->type = ARPHRD_AX25;
}
#endif
......@@ -1008,14 +1008,6 @@ sl_set_dev_mac_address(struct device *dev, void *addr)
memcpy(dev->dev_addr, addr, AX25_ADDR_LEN);
return 0;
}
int sl_get_ax25_mode(struct device *dev)
{
struct slip *sl = (struct slip*)(dev->priv);
return sl->mode & SL_MODE_AX25VC;
}
#endif /* CONFIG_AX25 */
......@@ -1072,13 +1064,13 @@ slip_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
}
#endif
#ifndef CONFIG_AX25
if ((tmp & SL_MODE_AX25) || (tmp & SL_MODE_AX25VC)) {
if (tmp & SL_MODE_AX25) {
return -EINVAL;
}
#else
if ((tmp & SL_MODE_AX25) || (tmp & SL_MODE_AX25VC)) {
if (tmp & SL_MODE_AX25) {
sl->dev->addr_len=AX25_ADDR_LEN; /* sizeof an AX.25 addr */
sl->dev->hard_header_len=73; /* We don't do digipeaters */
sl->dev->hard_header_len=AX25_KISS_HEADER_LEN + AX25_MAX_HEADER_LEN + 3;
} else {
sl->dev->addr_len=0; /* No mac addr in slip mode */
sl->dev->hard_header_len=0;
......@@ -1087,7 +1079,7 @@ slip_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
sl->mode = tmp;
sl->dev->type = ARPHRD_SLIP+sl->mode;
#ifdef CONFIG_AX25
if (sl->dev->type == 260 || sl->dev->type == 272) {
if (sl->dev->type == 260) {
sl->dev->type = ARPHRD_AX25;
}
#endif
......@@ -1221,7 +1213,7 @@ slip_init(struct device *dev)
dev->addr_len = 0;
dev->type = ARPHRD_SLIP + SL_MODE_DEFAULT;
#ifdef CONFIG_AX25
if (sl->dev->type == 260 || sl->dev->type == 272) {
if (sl->dev->type == 260) {
sl->dev->type = ARPHRD_AX25;
}
memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN); /* Only activated in AX.25 mode */
......
......@@ -95,7 +95,6 @@ struct slip {
#define SL_MODE_CSLIP6 (SL_MODE_SLIP6|SL_MODE_CSLIP)
#define SL_MODE_AX25 4
#define SL_MODE_ADAPTIVE 8
#define SL_MODE_AX25VC 16
};
......
......@@ -36,6 +36,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/if_arp.h>
#include <linux/skbuff.h>
#include <net/ip.h>
......
......@@ -34,7 +34,7 @@ include ../../versions.mk
endif
ifdef CONFIG_SCSI
L_OBJS := hosts.o scsi.o scsi_ioctl.o constants.o scsicam.o scsi_proc.o
L_OBJS += hosts.o scsi.o scsi_ioctl.o constants.o scsicam.o scsi_proc.o
else
ifdef CONFIG_MODVERSIONS
# Create this before we build anything else.
......
......@@ -228,7 +228,7 @@ int fsync_dev(dev_t dev)
asmlinkage int sys_sync(void)
{
sync_dev(0);
fsync_dev(0);
return 0;
}
......@@ -440,6 +440,7 @@ struct buffer_head * get_hash_table(dev_t dev, int block, int size)
for (;;) {
if (!(bh=find_buffer(dev,block,size)))
return NULL;
bh->b_reuse=0;
bh->b_count++;
wait_on_buffer(bh);
if (bh->b_dev == dev && bh->b_blocknr == block && bh->b_size == size)
......@@ -1075,6 +1076,7 @@ static unsigned long try_to_load_aligned(unsigned long address,
arr[block++] = bh;
bh->b_count = 1;
bh->b_dirt = 0;
bh->b_reuse = 0;
bh->b_flushtime = 0;
bh->b_uptodate = 0;
bh->b_req = 0;
......
......@@ -23,6 +23,33 @@
*/
#define mem_write NULL
static int check_range(struct task_struct * tsk, unsigned long addr, int count)
{
struct vm_area_struct *vma;
int retval;
vma = find_vma(tsk, addr);
if (!vma)
return -EACCES;
if (vma->vm_start > addr)
return -EACCES;
if (!(vma->vm_flags & VM_READ))
return -EACCES;
while ((retval = vma->vm_end - addr) < count) {
struct vm_area_struct *next = vma->vm_next;
if (!next)
break;
if (vma->vm_end != next->vm_start)
break;
if (!(next->vm_flags & VM_READ))
break;
vma = next;
}
if (retval > count)
retval = count;
return retval;
}
static int mem_read(struct inode * inode, struct file * file,char * buf, int count)
{
pgd_t *page_dir;
......@@ -47,6 +74,9 @@ static int mem_read(struct inode * inode, struct file * file,char * buf, int cou
if (!tsk)
return -EACCES;
addr = file->f_pos;
count = check_range(tsk, addr, count);
if (count < 0)
return count;
tmp = buf;
while (count > 0) {
if (current->signal & ~current->blocked)
......
......@@ -24,6 +24,14 @@ struct full_sockaddr_ax25
ax25_address fsa_digipeater[AX25_MAX_DIGIS];
};
struct ax25_routes_struct
{
ax25_address port_addr;
ax25_address dest_addr;
unsigned char digi_count;
ax25_address digi_addr[AX25_MAX_DIGIS - 2];
};
#define AX25_WINDOW 1
#define AX25_T1 2
#define AX25_N2 3
......@@ -31,12 +39,35 @@ struct full_sockaddr_ax25
#define AX25_T2 5
#define AX25_BACKOFF 6
#define AX25_EXTSEQ 7
#define AX25_HDRINCL 8
#define SIOCAX25GETUID (SIOCPROTOPRIVATE)
#define SIOCAX25ADDUID (SIOCPROTOPRIVATE+1)
#define SIOCAX25DELUID (SIOCPROTOPRIVATE+2)
#define SIOCAX25NOUID (SIOCPROTOPRIVATE+3)
#define SIOCAX25DIGCTL (SIOCPROTOPRIVATE+4)
#define SIOCAX25GETPARMS (SIOCPROTOPRIVATE+5)
#define SIOCAX25SETPARMS (SIOCPROTOPRIVATE+6)
#define AX25_NOUID_DEFAULT 0
#define AX25_NOUID_BLOCK 1
#define AX25_VALUES_IPDEFMODE 0 /* 'D'=DG 'V'=VC */
#define AX25_VALUES_AXDEFMODE 1 /* 8=Normal 128=Extended Seq Nos */
#define AX25_VALUES_NETROM 2 /* Allow NET/ROM - 0=No 1=Yes */
#define AX25_VALUES_TEXT 3 /* Allow PID=Text - 0=No 1=Yes */
#define AX25_VALUES_BACKOFF 4 /* 'E'=Exponential 'L'=Linear */
#define AX25_VALUES_CONMODE 5 /* Allow connected modes - 0=No 1=Yes */
#define AX25_VALUES_WINDOW 6 /* Default window size for standard AX.25 */
#define AX25_VALUES_EWINDOW 7 /* Default window size for extended AX.25 */
#define AX25_VALUES_T1 8 /* Default T1 timeout value */
#define AX25_VALUES_T2 9 /* Default T2 timeout value */
#define AX25_VALUES_T3 10 /* Default T3 timeout value */
#define AX25_VALUES_N2 11 /* Default N2 value */
#define AX25_MAX_VALUES 20
struct ax25_parms_struct
{
ax25_address port_addr;
unsigned short values[AX25_MAX_VALUES];
};
......@@ -4,6 +4,7 @@
#define NETROM_T1 1
#define NETROM_T2 2
#define NETROM_N2 3
#define NETROM_HDRINCL 4
#define SIOCNRGETPARMS (SIOCPROTOPRIVATE+0)
#define SIOCNRSETPARMS (SIOCPROTOPRIVATE+1)
......
......@@ -101,14 +101,22 @@
#define AX25_STATE_4 4
#define PR_SLOWHZ 10 /* Run timing at 1/10 second - gives us better resolution for 56kbit links */
#define DEFAULT_T1 (10 * PR_SLOWHZ) /* Outstanding frames - 10 seconds */
#define DEFAULT_T2 (3 * PR_SLOWHZ) /* Response delay - 3 seconds */
#define DEFAULT_T3 (300 * PR_SLOWHZ) /* Idle supervision - 300 seconds */
#define DEFAULT_N2 10 /* Number of retries */
#define DEFAULT_WINDOW 2 /* Default window size */
#define MODULUS 8 /* Standard AX.25 modulus */
#define EMODULUS 128 /* Extended AX.25 modulus */
#define AX25_DEF_IPDEFMODE 'D'
#define AX25_DEF_AXDEFMODE 8
#define AX25_DEF_NETROM 1
#define AX25_DEF_TEXT 1
#define AX25_DEF_BACKOFF 'E'
#define AX25_DEF_CONMODE 1
#define AX25_DEF_WINDOW 2
#define AX25_DEF_EWINDOW 32
#define AX25_DEF_T1 10
#define AX25_DEF_T2 3
#define AX25_DEF_T3 300
#define AX25_DEF_N2 10
typedef struct ax25_uid_assoc {
struct ax25_uid_assoc *next;
uid_t uid;
......@@ -126,7 +134,7 @@ typedef struct ax25_cb {
struct ax25_cb *next;
ax25_address source_addr, dest_addr;
struct device *device;
unsigned char state, modulus;
unsigned char state, modulus, hdrincl;
unsigned short vs, vr, va;
unsigned char condition, backoff;
unsigned char n2, n2count;
......@@ -152,7 +160,6 @@ extern struct device *ax25rtr_get_dev(ax25_address *);
extern int ax25_encapsulate(struct sk_buff *, struct device *, unsigned short,
void *, void *, unsigned int);
extern int ax25_rebuild_header(unsigned char *, struct device *, unsigned long, struct sk_buff *);
extern int ax25_get_info(char *, char **, off_t, int, int);
extern ax25_uid_assoc *ax25_uid_list;
extern int ax25_uid_policy;
extern ax25_address *ax25_findbyuid(uid_t);
......@@ -171,17 +178,23 @@ extern void ax25_nr_error_recovery(ax25_cb *);
extern void ax25_establish_data_link(ax25_cb *);
extern void ax25_transmit_enquiry(ax25_cb *);
extern void ax25_enquiry_response(ax25_cb *);
extern void ax25_timeout_response(ax25_cb *);
extern void ax25_check_iframes_acked(ax25_cb *, unsigned short);
extern void ax25_check_need_response(ax25_cb *, int, int);
/* ax25_route.c */
extern void ax25_rt_rx_frame(ax25_address *, struct device *);
extern void ax25_rt_rx_frame(ax25_address *, struct device *, ax25_digi *);
extern int ax25_rt_get_info(char *, char **, off_t, int, int);
extern int ax25_cs_get_info(char *, char **, off_t, int, int);
extern int ax25_rt_autobind(ax25_cb *, ax25_address *);
extern void ax25_rt_device_down(struct device *);
extern int ax25_rt_ioctl(unsigned int, void *);
extern void ax25_ip_mode_set(ax25_address *, struct device *, char);
extern char ax25_ip_mode_get(ax25_address *, struct device *);
extern unsigned short ax25_dev_get_value(struct device *, int);
extern void ax25_dev_device_up(struct device *);
extern void ax25_dev_device_down(struct device *);
extern int ax25_dev_ioctl(unsigned int, void *);
/* ax25_subr.c */
extern void ax25_clear_queues(ax25_cb *);
......@@ -202,7 +215,4 @@ extern void ax25_return_dm(struct device *, ax25_address *, ax25_address *, ax25
/* ax25_timer */
extern void ax25_set_timer(ax25_cb *);
/* slip.c */
extern int sl_get_ax25_mode(struct device *);
#endif
......@@ -48,9 +48,8 @@ typedef struct {
struct device *device;
unsigned char my_index, my_id;
unsigned char your_index, your_id;
unsigned char state, bpqext;
unsigned char state, condition, bpqext, hdrincl;
unsigned short vs, vr, va, vl;
unsigned char condition;
unsigned char n2, n2count;
unsigned short t1, t2, rtt;
unsigned short t1timer, t2timer, t4timer;
......
......@@ -9,6 +9,7 @@
#include <linux/config.h>
#include <linux/utsname.h>
#include <linux/version.h>
#include <linux/compile.h>
struct new_utsname system_utsname = {
UTS_SYSNAME, UTS_NODENAME, UTS_RELEASE, UTS_VERSION,
......
......@@ -14,10 +14,13 @@ O_TARGET := kernel.o
O_OBJS = sched.o dma.o fork.o exec_domain.o panic.o printk.o sys.o \
module.o exit.o signal.o itimer.o info.o time.o softirq.o \
resource.o
SYMTAB_OBJS = ksyms.o
O_OBJS += $(SYMTAB_OBJS)
ifdef CONFIG_MODVERSIONS
$(O_TARGET): $(SYMTAB_OBJS:.o=.ver)
endif
include $(TOPDIR)/Rules.make
......
/**** This file is generated by genksyms DO NOT EDIT! ****/
#if defined(CONFIG_MODVERSIONS) && !defined(__GENKSYMS__)
#ifndef _KSYMS_VER_
#define _KSYMS_VER_
#define rename_module_symbol _set_ver(rename_module_symbol, b81c73c1)
#define register_symtab _set_ver(register_symtab, e910ea66)
#define EISA_bus _set_ver(EISA_bus, 7e37737c)
#define wp_works_ok _set_ver(wp_works_ok, f37f99e9)
#define verify_area _set_ver(verify_area, 4cfda560)
#define do_mmap _set_ver(do_mmap, 677e7ee1)
#define do_munmap _set_ver(do_munmap, 6221f117)
#define zeromap_page_range _set_ver(zeromap_page_range, 7c395a26)
#define unmap_page_range _set_ver(unmap_page_range, 0110085f)
#define insert_vm_struct _set_ver(insert_vm_struct, 1f4e4882)
#define merge_segments _set_ver(merge_segments, 6854be5a)
#define __get_free_pages _set_ver(__get_free_pages, 5243d78b)
#define free_pages _set_ver(free_pages, 96448859)
#define kmalloc _set_ver(kmalloc, d31fb2cb)
#define kfree_s _set_ver(kfree_s, 1e72eb79)
#define vmalloc _set_ver(vmalloc, 667f3e25)
#define vfree _set_ver(vfree, 6df52add)
#define getname _set_ver(getname, 81487159)
#define putname _set_ver(putname, b19e8126)
#define __iget _set_ver(__iget, ee2b6320)
#define iput _set_ver(iput, 59241ced)
#define namei _set_ver(namei, 00478bcd)
#define lnamei _set_ver(lnamei, fcfddbb1)
#define open_namei _set_ver(open_namei, 414b2b0f)
#define close_fp _set_ver(close_fp, 1d4c15d8)
#define check_disk_change _set_ver(check_disk_change, b66ed457)
#define invalidate_buffers _set_ver(invalidate_buffers, c65255f1)
#define fsync_dev _set_ver(fsync_dev, a221190d)
#define permission _set_ver(permission, 0ebf7474)
#define inode_setattr _set_ver(inode_setattr, 0c80a3c1)
#define inode_change_ok _set_ver(inode_change_ok, 5d1cb326)
#define generic_mmap _set_ver(generic_mmap, d4ff59f3)
#define set_blocksize _set_ver(set_blocksize, f45fda38)
#define getblk _set_ver(getblk, d40228ac)
#define bread _set_ver(bread, c73bf0f0)
#define breada _set_ver(breada, eb8e858c)
#define brelse _set_ver(brelse, 4c27ac3d)
#define ll_rw_block _set_ver(ll_rw_block, f3aa4dd3)
#define __wait_on_buffer _set_ver(__wait_on_buffer, e8fcc968)
#define dcache_lookup _set_ver(dcache_lookup, 83336566)
#define dcache_add _set_ver(dcache_add, fe71f11e)
#define register_chrdev _set_ver(register_chrdev, da99513f)
#define unregister_chrdev _set_ver(unregister_chrdev, 61ea5ee8)
#define register_blkdev _set_ver(register_blkdev, 4699a621)
#define unregister_blkdev _set_ver(unregister_blkdev, d39bbca9)
#define tty_register_driver _set_ver(tty_register_driver, fcc8591c)
#define tty_unregister_driver _set_ver(tty_unregister_driver, c78132a8)
#define tty_std_termios _set_ver(tty_std_termios, cf350678)
#define block_read _set_ver(block_read, a7fe4f51)
#define block_write _set_ver(block_write, 902674c9)
#define block_fsync _set_ver(block_fsync, 182888d8)
#define wait_for_request _set_ver(wait_for_request, 9ca2932e)
#define blksize_size _set_ver(blksize_size, dea1eb55)
#define hardsect_size _set_ver(hardsect_size, ed1ee14f)
#define blk_size _set_ver(blk_size, f60b5398)
#define blk_dev _set_ver(blk_dev, dbf5fdd4)
#define is_read_only _set_ver(is_read_only, b0c5f83e)
#define set_device_ro _set_ver(set_device_ro, 8fb69e13)
#define bmap _set_ver(bmap, 73bb8bdd)
#define sync_dev _set_ver(sync_dev, 9bca536d)
#define get_blkfops _set_ver(get_blkfops, 83827791)
#define register_serial _set_ver(register_serial, 3425f38c)
#define unregister_serial _set_ver(unregister_serial, c013d717)
#define tty_hangup _set_ver(tty_hangup, e3487df0)
#define tty_wait_until_sent _set_ver(tty_wait_until_sent, da85d428)
#define tty_check_change _set_ver(tty_check_change, 705eaab0)
#define tty_hung_up_p _set_ver(tty_hung_up_p, f99ac1e4)
#define register_filesystem _set_ver(register_filesystem, 1c7110ef)
#define unregister_filesystem _set_ver(unregister_filesystem, 5e353af7)
#define register_binfmt _set_ver(register_binfmt, 66ece706)
#define unregister_binfmt _set_ver(unregister_binfmt, 41822618)
#define lookup_exec_domain _set_ver(lookup_exec_domain, 32f10d48)
#define register_exec_domain _set_ver(register_exec_domain, eda4711f)
#define unregister_exec_domain _set_ver(unregister_exec_domain, 78ea447c)
#define request_irq _set_ver(request_irq, 9e81629c)
#define free_irq _set_ver(free_irq, f487dc0c)
#define enable_irq _set_ver(enable_irq, 54e09f5f)
#define disable_irq _set_ver(disable_irq, b4449c1f)
#define bh_active _set_ver(bh_active, 98fb5ca1)
#define bh_mask _set_ver(bh_mask, 1abf3d3f)
#define add_timer _set_ver(add_timer, f13cb728)
#define del_timer _set_ver(del_timer, c7aff713)
#define tq_timer _set_ver(tq_timer, 46cf583e)
#define tq_immediate _set_ver(tq_immediate, 46cf583e)
#define tq_scheduler _set_ver(tq_scheduler, 46cf583e)
#define tq_last _set_ver(tq_last, 457cf547)
#define timer_active _set_ver(timer_active, 5a6747ee)
#define timer_table _set_ver(timer_table, 9e03b650)
#define request_dma _set_ver(request_dma, 2a687646)
#define free_dma _set_ver(free_dma, 5d4b914c)
#define disable_hlt _set_ver(disable_hlt, 794487ee)
#define enable_hlt _set_ver(enable_hlt, 9c7077bd)
#define check_region _set_ver(check_region, b91154fb)
#define request_region _set_ver(request_region, 138b0a1e)
#define release_region _set_ver(release_region, f41d6d31)
#define wake_up _set_ver(wake_up, e8d71419)
#define wake_up_interruptible _set_ver(wake_up_interruptible, 64c8cb92)
#define sleep_on _set_ver(sleep_on, 67a00cee)
#define interruptible_sleep_on _set_ver(interruptible_sleep_on, 6a5fc80d)
#define schedule _set_ver(schedule, 01000e51)
#define current _set_ver(current, fc1cb29b)
#define jiffies _set_ver(jiffies, 2f7c7437)
#define xtime _set_ver(xtime, e70c0be0)
#define loops_per_sec _set_ver(loops_per_sec, 40a14192)
#define need_resched _set_ver(need_resched, dfc016ea)
#define kill_proc _set_ver(kill_proc, 911f760a)
#define kill_pg _set_ver(kill_pg, 0a758a45)
#define kill_sl _set_ver(kill_sl, 49625e94)
#define panic _set_ver(panic, 400c0de3)
#define printk _set_ver(printk, ad1148ba)
#define sprintf _set_ver(sprintf, f9003107)
#define vsprintf _set_ver(vsprintf, e605cb6b)
#define simple_strtoul _set_ver(simple_strtoul, bdb8c1e3)
#define system_utsname _set_ver(system_utsname, 066845bc)
#define sys_call_table _set_ver(sys_call_table, 79fa4011)
#define do_signal _set_ver(do_signal, 86f9bc59)
#define send_sig _set_ver(send_sig, 5cddd8d9)
#define setup_arg_pages _set_ver(setup_arg_pages, fe68d94a)
#define copy_strings _set_ver(copy_strings, 232aee96)
#define create_tables _set_ver(create_tables, ba788fa2)
#define do_execve _set_ver(do_execve, 8c99dc0a)
#define flush_old_exec _set_ver(flush_old_exec, c737e178)
#define open_inode _set_ver(open_inode, 27302cb6)
#define read_exec _set_ver(read_exec, a80a2dd0)
#define si_meminfo _set_ver(si_meminfo, bb05fc9a)
#define sock_register _set_ver(sock_register, d68e1649)
#define sock_unregister _set_ver(sock_unregister, 72c332bd)
#define inet_add_protocol _set_ver(inet_add_protocol, 55292121)
#define inet_del_protocol _set_ver(inet_del_protocol, 73908a1b)
#define slhc_init _set_ver(slhc_init, e490a4b8)
#define slhc_free _set_ver(slhc_free, 39ab902b)
#define slhc_remember _set_ver(slhc_remember, db333be6)
#define slhc_compress _set_ver(slhc_compress, e753e2d2)
#define slhc_uncompress _set_ver(slhc_uncompress, 81cc1144)
#define register_netdevice_notifier _set_ver(register_netdevice_notifier, e7aace7c)
#define unregister_netdevice_notifier _set_ver(unregister_netdevice_notifier, be114416)
#define floppy_track_buffer _set_ver(floppy_track_buffer, c6e3f7c2)
#define register_netdev _set_ver(register_netdev, 0d8d1bb4)
#define unregister_netdev _set_ver(unregister_netdev, 25a99579)
#define ether_setup _set_ver(ether_setup, 4eafef91)
#define alloc_skb _set_ver(alloc_skb, b6b523ba)
#define kfree_skb _set_ver(kfree_skb, 0b938572)
#define dev_kfree_skb _set_ver(dev_kfree_skb, aa1fe7f4)
#define netif_rx _set_ver(netif_rx, d8051cb2)
#define dev_rint _set_ver(dev_rint, 040d3f4b)
#define dev_tint _set_ver(dev_tint, 860b350b)
#define irq2dev_map _set_ver(irq2dev_map, 10bdcd8a)
#define dev_add_pack _set_ver(dev_add_pack, 6d7d9be4)
#define dev_remove_pack _set_ver(dev_remove_pack, 784fa59f)
#define dev_get _set_ver(dev_get, 72ed90fd)
#define dev_ioctl _set_ver(dev_ioctl, 08760203)
#define dev_queue_xmit _set_ver(dev_queue_xmit, 4a478225)
#define dev_base _set_ver(dev_base, 0a8809f0)
#define dev_close _set_ver(dev_close, 9bdad56d)
#define arp_find _set_ver(arp_find, a141bd11)
#define n_tty_ioctl _set_ver(n_tty_ioctl, 538e5fa6)
#define tty_register_ldisc _set_ver(tty_register_ldisc, 8fdde939)
#define kill_fasync _set_ver(kill_fasync, 890501b6)
#define in_scan_scsis _set_ver(in_scan_scsis, 21874a88)
#define scsi_register_module _set_ver(scsi_register_module, 8eff1010)
#define scsi_unregister_module _set_ver(scsi_unregister_module, d913b8f0)
#define scsi_free _set_ver(scsi_free, 475dddfa)
#define scsi_malloc _set_ver(scsi_malloc, 1cce3f92)
#define scsi_register _set_ver(scsi_register, d6e77069)
#define scsi_unregister _set_ver(scsi_unregister, 3b0b616b)
#define scsicam_bios_param _set_ver(scsicam_bios_param, 3d965248)
#define scsi_init_malloc _set_ver(scsi_init_malloc, e5167cbc)
#define scsi_init_free _set_ver(scsi_init_free, 8b2721f8)
#define print_command _set_ver(print_command, 6f14cd75)
#define print_msg _set_ver(print_msg, 0465f877)
#define print_status _set_ver(print_status, 32f84646)
#define set_writetime _set_ver(set_writetime, 52131916)
#define sys_tz _set_ver(sys_tz, aa3c9782)
#define __wait_on_super _set_ver(__wait_on_super, 61a5c00a)
#define file_fsync _set_ver(file_fsync, d30a190f)
#define clear_inode _set_ver(clear_inode, da2b0e9f)
#define refile_buffer _set_ver(refile_buffer, 8c69e123)
#define ___strtok _set_ver(___strtok, 8b55d69c)
#define init_fifo _set_ver(init_fifo, 082629c7)
#define super_blocks _set_ver(super_blocks, e1f1ee99)
#define chrdev_inode_operations _set_ver(chrdev_inode_operations, 6ba1faa3)
#define blkdev_inode_operations _set_ver(blkdev_inode_operations, ed443696)
#define read_ahead _set_ver(read_ahead, bbcd3768)
#define get_hash_table _set_ver(get_hash_table, 3b5f3c55)
#define get_empty_inode _set_ver(get_empty_inode, 554bdc75)
#define insert_inode_hash _set_ver(insert_inode_hash, 59b8c371)
#define event _set_ver(event, a6aac9c1)
#define __down _set_ver(__down, 75aa9e96)
#endif /* _KSYMS_VER_ */
#endif /* CONFIG_MODVERSIONS !__GENKSYMS__ */
/**** This file is generated by genksyms DO NOT EDIT! ****/
#if defined(CONFIG_MODVERSIONS) && !defined(__GENKSYMS__)
#ifndef _KSYMS_VER_
#define _KSYMS_VER_
#define rename_module_symbol _set_ver(rename_module_symbol, b81c73c1)
#define register_symtab _set_ver(register_symtab, e910ea66)
#define EISA_bus _set_ver(EISA_bus, 7e37737c)
#define wp_works_ok _set_ver(wp_works_ok, f37f99e9)
#define verify_area _set_ver(verify_area, 4cfda560)
#define do_mmap _set_ver(do_mmap, 677e7ee1)
#define do_munmap _set_ver(do_munmap, 6221f117)
#define zeromap_page_range _set_ver(zeromap_page_range, 7c395a26)
#define unmap_page_range _set_ver(unmap_page_range, 0110085f)
#define insert_vm_struct _set_ver(insert_vm_struct, 1f4e4882)
#define merge_segments _set_ver(merge_segments, 6854be5a)
#define __get_free_pages _set_ver(__get_free_pages, 5243d78b)
#define free_pages _set_ver(free_pages, 96448859)
#define kmalloc _set_ver(kmalloc, d31fb2cb)
#define kfree_s _set_ver(kfree_s, 1e72eb79)
#define vmalloc _set_ver(vmalloc, 667f3e25)
#define vfree _set_ver(vfree, 6df52add)
#define getname _set_ver(getname, 81487159)
#define putname _set_ver(putname, b19e8126)
#define __iget _set_ver(__iget, ee2b6320)
#define iput _set_ver(iput, 59241ced)
#define namei _set_ver(namei, 00478bcd)
#define lnamei _set_ver(lnamei, fcfddbb1)
#define open_namei _set_ver(open_namei, 414b2b0f)
#define close_fp _set_ver(close_fp, 1d4c15d8)
#define check_disk_change _set_ver(check_disk_change, b66ed457)
#define invalidate_buffers _set_ver(invalidate_buffers, c65255f1)
#define fsync_dev _set_ver(fsync_dev, a221190d)
#define permission _set_ver(permission, 0ebf7474)
#define inode_setattr _set_ver(inode_setattr, 0c80a3c1)
#define inode_change_ok _set_ver(inode_change_ok, 5d1cb326)
#define generic_mmap _set_ver(generic_mmap, d4ff59f3)
#define set_blocksize _set_ver(set_blocksize, f45fda38)
#define getblk _set_ver(getblk, d40228ac)
#define bread _set_ver(bread, c73bf0f0)
#define breada _set_ver(breada, eb8e858c)
#define brelse _set_ver(brelse, 4c27ac3d)
#define ll_rw_block _set_ver(ll_rw_block, f3aa4dd3)
#define __wait_on_buffer _set_ver(__wait_on_buffer, e8fcc968)
#define dcache_lookup _set_ver(dcache_lookup, 83336566)
#define dcache_add _set_ver(dcache_add, fe71f11e)
#define register_chrdev _set_ver(register_chrdev, da99513f)
#define unregister_chrdev _set_ver(unregister_chrdev, 61ea5ee8)
#define register_blkdev _set_ver(register_blkdev, 4699a621)
#define unregister_blkdev _set_ver(unregister_blkdev, d39bbca9)
#define tty_register_driver _set_ver(tty_register_driver, fcc8591c)
#define tty_unregister_driver _set_ver(tty_unregister_driver, c78132a8)
#define tty_std_termios _set_ver(tty_std_termios, cf350678)
#define block_read _set_ver(block_read, a7fe4f51)
#define block_write _set_ver(block_write, 902674c9)
#define block_fsync _set_ver(block_fsync, 182888d8)
#define wait_for_request _set_ver(wait_for_request, 9ca2932e)
#define blksize_size _set_ver(blksize_size, dea1eb55)
#define hardsect_size _set_ver(hardsect_size, ed1ee14f)
#define blk_size _set_ver(blk_size, f60b5398)
#define blk_dev _set_ver(blk_dev, dbf5fdd4)
#define is_read_only _set_ver(is_read_only, b0c5f83e)
#define set_device_ro _set_ver(set_device_ro, 8fb69e13)
#define bmap _set_ver(bmap, 73bb8bdd)
#define sync_dev _set_ver(sync_dev, 9bca536d)
#define get_blkfops _set_ver(get_blkfops, 83827791)
#define register_serial _set_ver(register_serial, 3425f38c)
#define unregister_serial _set_ver(unregister_serial, c013d717)
#define tty_hangup _set_ver(tty_hangup, e3487df0)
#define tty_wait_until_sent _set_ver(tty_wait_until_sent, da85d428)
#define tty_check_change _set_ver(tty_check_change, 705eaab0)
#define tty_hung_up_p _set_ver(tty_hung_up_p, f99ac1e4)
#define register_filesystem _set_ver(register_filesystem, 1c7110ef)
#define unregister_filesystem _set_ver(unregister_filesystem, 5e353af7)
#define register_binfmt _set_ver(register_binfmt, 66ece706)
#define unregister_binfmt _set_ver(unregister_binfmt, 41822618)
#define lookup_exec_domain _set_ver(lookup_exec_domain, 32f10d48)
#define register_exec_domain _set_ver(register_exec_domain, eda4711f)
#define unregister_exec_domain _set_ver(unregister_exec_domain, 78ea447c)
#define request_irq _set_ver(request_irq, 9e81629c)
#define free_irq _set_ver(free_irq, f487dc0c)
#define enable_irq _set_ver(enable_irq, 54e09f5f)
#define disable_irq _set_ver(disable_irq, b4449c1f)
#define bh_active _set_ver(bh_active, 98fb5ca1)
#define bh_mask _set_ver(bh_mask, 1abf3d3f)
#define add_timer _set_ver(add_timer, f13cb728)
#define del_timer _set_ver(del_timer, c7aff713)
#define tq_timer _set_ver(tq_timer, 46cf583e)
#define tq_immediate _set_ver(tq_immediate, 46cf583e)
#define tq_scheduler _set_ver(tq_scheduler, 46cf583e)
#define tq_last _set_ver(tq_last, 457cf547)
#define timer_active _set_ver(timer_active, 5a6747ee)
#define timer_table _set_ver(timer_table, 9e03b650)
#define request_dma _set_ver(request_dma, 2a687646)
#define free_dma _set_ver(free_dma, 5d4b914c)
#define disable_hlt _set_ver(disable_hlt, 794487ee)
#define enable_hlt _set_ver(enable_hlt, 9c7077bd)
#define check_region _set_ver(check_region, b91154fb)
#define request_region _set_ver(request_region, 138b0a1e)
#define release_region _set_ver(release_region, f41d6d31)
#define wake_up _set_ver(wake_up, e8d71419)
#define wake_up_interruptible _set_ver(wake_up_interruptible, 64c8cb92)
#define sleep_on _set_ver(sleep_on, 67a00cee)
#define interruptible_sleep_on _set_ver(interruptible_sleep_on, 6a5fc80d)
#define schedule _set_ver(schedule, 01000e51)
#define current _set_ver(current, fc1cb29b)
#define jiffies _set_ver(jiffies, 2f7c7437)
#define xtime _set_ver(xtime, e70c0be0)
#define loops_per_sec _set_ver(loops_per_sec, 40a14192)
#define need_resched _set_ver(need_resched, dfc016ea)
#define kill_proc _set_ver(kill_proc, 911f760a)
#define kill_pg _set_ver(kill_pg, 0a758a45)
#define kill_sl _set_ver(kill_sl, 49625e94)
#define panic _set_ver(panic, 400c0de3)
#define printk _set_ver(printk, ad1148ba)
#define sprintf _set_ver(sprintf, f9003107)
#define vsprintf _set_ver(vsprintf, e605cb6b)
#define simple_strtoul _set_ver(simple_strtoul, bdb8c1e3)
#define system_utsname _set_ver(system_utsname, 066845bc)
#define sys_call_table _set_ver(sys_call_table, 79fa4011)
#define do_signal _set_ver(do_signal, 86f9bc59)
#define send_sig _set_ver(send_sig, 5cddd8d9)
#define setup_arg_pages _set_ver(setup_arg_pages, fe68d94a)
#define copy_strings _set_ver(copy_strings, 232aee96)
#define create_tables _set_ver(create_tables, ba788fa2)
#define do_execve _set_ver(do_execve, 8c99dc0a)
#define flush_old_exec _set_ver(flush_old_exec, c737e178)
#define open_inode _set_ver(open_inode, 27302cb6)
#define read_exec _set_ver(read_exec, a80a2dd0)
#define si_meminfo _set_ver(si_meminfo, bb05fc9a)
#define sock_register _set_ver(sock_register, d68e1649)
#define sock_unregister _set_ver(sock_unregister, 72c332bd)
#define inet_add_protocol _set_ver(inet_add_protocol, 55292121)
#define inet_del_protocol _set_ver(inet_del_protocol, 73908a1b)
#define slhc_init _set_ver(slhc_init, e490a4b8)
#define slhc_free _set_ver(slhc_free, 39ab902b)
#define slhc_remember _set_ver(slhc_remember, db333be6)
#define slhc_compress _set_ver(slhc_compress, e753e2d2)
#define slhc_uncompress _set_ver(slhc_uncompress, 81cc1144)
#define register_netdevice_notifier _set_ver(register_netdevice_notifier, e7aace7c)
#define unregister_netdevice_notifier _set_ver(unregister_netdevice_notifier, be114416)
#define floppy_track_buffer _set_ver(floppy_track_buffer, c6e3f7c2)
#define register_netdev _set_ver(register_netdev, 0d8d1bb4)
#define unregister_netdev _set_ver(unregister_netdev, 25a99579)
#define ether_setup _set_ver(ether_setup, 4eafef91)
#define alloc_skb _set_ver(alloc_skb, b6b523ba)
#define kfree_skb _set_ver(kfree_skb, 0b938572)
#define dev_kfree_skb _set_ver(dev_kfree_skb, aa1fe7f4)
#define netif_rx _set_ver(netif_rx, d8051cb2)
#define dev_rint _set_ver(dev_rint, 040d3f4b)
#define dev_tint _set_ver(dev_tint, 860b350b)
#define irq2dev_map _set_ver(irq2dev_map, 10bdcd8a)
#define dev_add_pack _set_ver(dev_add_pack, 6d7d9be4)
#define dev_remove_pack _set_ver(dev_remove_pack, 784fa59f)
#define dev_get _set_ver(dev_get, 72ed90fd)
#define dev_ioctl _set_ver(dev_ioctl, 08760203)
#define dev_queue_xmit _set_ver(dev_queue_xmit, 4a478225)
#define dev_base _set_ver(dev_base, 0a8809f0)
#define dev_close _set_ver(dev_close, 9bdad56d)
#define arp_find _set_ver(arp_find, a141bd11)
#define n_tty_ioctl _set_ver(n_tty_ioctl, 538e5fa6)
#define tty_register_ldisc _set_ver(tty_register_ldisc, 8fdde939)
#define kill_fasync _set_ver(kill_fasync, 890501b6)
#define in_scan_scsis _set_ver(in_scan_scsis, 21874a88)
#define scsi_register_module _set_ver(scsi_register_module, 8eff1010)
#define scsi_unregister_module _set_ver(scsi_unregister_module, d913b8f0)
#define scsi_free _set_ver(scsi_free, 475dddfa)
#define scsi_malloc _set_ver(scsi_malloc, 1cce3f92)
#define scsi_register _set_ver(scsi_register, d6e77069)
#define scsi_unregister _set_ver(scsi_unregister, 3b0b616b)
#define scsicam_bios_param _set_ver(scsicam_bios_param, 3d965248)
#define scsi_init_malloc _set_ver(scsi_init_malloc, e5167cbc)
#define scsi_init_free _set_ver(scsi_init_free, 8b2721f8)
#define print_command _set_ver(print_command, 6f14cd75)
#define print_msg _set_ver(print_msg, 0465f877)
#define print_status _set_ver(print_status, 32f84646)
#define set_writetime _set_ver(set_writetime, 52131916)
#define sys_tz _set_ver(sys_tz, aa3c9782)
#define __wait_on_super _set_ver(__wait_on_super, 61a5c00a)
#define file_fsync _set_ver(file_fsync, d30a190f)
#define clear_inode _set_ver(clear_inode, da2b0e9f)
#define refile_buffer _set_ver(refile_buffer, 8c69e123)
#define ___strtok _set_ver(___strtok, 8b55d69c)
#define init_fifo _set_ver(init_fifo, 082629c7)
#define super_blocks _set_ver(super_blocks, e1f1ee99)
#define chrdev_inode_operations _set_ver(chrdev_inode_operations, 6ba1faa3)
#define blkdev_inode_operations _set_ver(blkdev_inode_operations, ed443696)
#define read_ahead _set_ver(read_ahead, bbcd3768)
#define get_hash_table _set_ver(get_hash_table, 3b5f3c55)
#define get_empty_inode _set_ver(get_empty_inode, 554bdc75)
#define insert_inode_hash _set_ver(insert_inode_hash, 59b8c371)
#define event _set_ver(event, a6aac9c1)
#define __down _set_ver(__down, 75aa9e96)
#endif /* _KSYMS_VER_ */
#endif /* CONFIG_MODVERSIONS !__GENKSYMS__ */
......@@ -38,6 +38,7 @@
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <linux/inet.h>
#include <linux/notifier.h>
#include <linux/netdevice.h>
......
......@@ -38,6 +38,8 @@
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <linux/route.h>
#include <linux/inet.h>
#include <linux/notifier.h>
#include <linux/netdevice.h>
......@@ -50,6 +52,7 @@
#include <net/sock.h>
#include <linux/atalk.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#ifdef CONFIG_ATALK
......@@ -211,7 +214,7 @@ static void atalk_destroy_socket(atalk_socket *sk)
/* Called from proc fs */
int atalk_get_info(char *buffer, char **start, off_t offset, int length)
int atalk_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
{
atalk_socket *s;
int len=0;
......@@ -813,7 +816,7 @@ static int atrtr_ioctl(unsigned int cmd, void *arg)
/* Called from proc fs - just make it print the ifaces neatly */
int atalk_if_get_info(char *buffer, char **start, off_t offset, int length)
int atalk_if_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
{
struct atalk_iface *iface;
int len=0;
......@@ -846,7 +849,7 @@ int atalk_if_get_info(char *buffer, char **start, off_t offset, int length)
/* Called from proc fs - just make it print the routes neatly */
int atalk_rt_get_info(char *buffer, char **start, off_t offset, int length)
int atalk_rt_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
{
struct atalk_route *rt;
int len=0;
......@@ -1873,6 +1876,7 @@ void atalk_proto_init(struct net_proto *pro)
proc_net_register(&(struct proc_dir_entry) {
PROC_NET_AT_ROUTE, 11,"atalk_route",
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_net_inode_operations,
atalk_rt_get_info
});
proc_net_register(&(struct proc_dir_entry) {
......
......@@ -12,7 +12,7 @@ O_TARGET := ax25.o
O_OBJS := af_ax25.o
ifdef CONFIG_AX25
OBJS += ax25_in.o ax25_out.o ax25_route.o ax25_subr.o ax25_timer.o
O_OBJS += ax25_in.o ax25_out.o ax25_route.o ax25_subr.o ax25_timer.o
endif
include $(TOPDIR)/Rules.make
......
......@@ -63,12 +63,10 @@
* Added AX.25 frame segmentation.
*
* To do:
* Support use as digipeater, including an on/off ioctl
* Restructure the ax25_rcv code to be cleaner/faster and
* copy only when needed.
* Consider better arbitary protocol support.
* Fix non-blocking connect failure.
* VC mode doesnt work on the PI card.
* Settable protocol id for SEQPACKET sockets
*/
......@@ -87,6 +85,7 @@
#include <net/ax25.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/skbuff.h>
#include <net/sock.h>
#include <asm/segment.h>
......@@ -97,6 +96,7 @@
#include <linux/interrupt.h>
#include <linux/notifier.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <net/ip.h>
#include <net/arp.h>
......@@ -213,8 +213,6 @@ static void ax25_kill_by_device(struct device *dev)
}
}
}
ax25_rt_device_down(dev);
}
/*
......@@ -222,10 +220,20 @@ static void ax25_kill_by_device(struct device *dev)
*/
static int ax25_device_event(unsigned long event, void *ptr)
{
if (event != NETDEV_DOWN)
return NOTIFY_DONE;
struct device *dev = (struct device *)ptr;
ax25_kill_by_device(ptr);
switch (event) {
case NETDEV_UP:
ax25_dev_device_up(dev);
break;
case NETDEV_DOWN:
ax25_kill_by_device(dev);
ax25_rt_device_down(dev);
ax25_dev_device_down(dev);
break;
default:
break;
}
return NOTIFY_DONE;
}
......@@ -514,16 +522,17 @@ static ax25_cb *ax25_create_cb(void)
init_timer(&ax25->timer);
ax25->rtt = DEFAULT_T1;
ax25->t1 = DEFAULT_T1;
ax25->t2 = DEFAULT_T2;
ax25->n2 = DEFAULT_N2;
ax25->t3 = DEFAULT_T3;
ax25->rtt = (AX25_DEF_T1 * PR_SLOWHZ) / 2;
ax25->t1 = AX25_DEF_T1 * PR_SLOWHZ;
ax25->t2 = AX25_DEF_T2 * PR_SLOWHZ;
ax25->t3 = AX25_DEF_T3 * PR_SLOWHZ;
ax25->n2 = AX25_DEF_N2;
ax25->modulus = MODULUS;
ax25->modulus = AX25_DEF_AXDEFMODE;
ax25->fragno = 0;
ax25->fraglen = 0;
ax25->backoff = 1;
ax25->hdrincl = 0;
ax25->backoff = AX25_DEF_BACKOFF == 'E';
ax25->condition = 0x00;
ax25->t1timer = 0;
ax25->t2timer = 0;
......@@ -534,7 +543,11 @@ static ax25_cb *ax25_create_cb(void)
ax25->vr = 0;
ax25->vs = 0;
ax25->window = DEFAULT_WINDOW;
if (AX25_DEF_AXDEFMODE == EMODULUS) {
ax25->window = AX25_DEF_EWINDOW;
} else {
ax25->window = AX25_DEF_WINDOW;
}
ax25->device = NULL;
ax25->digipeat = NULL;
ax25->sk = NULL;
......@@ -547,6 +560,31 @@ static ax25_cb *ax25_create_cb(void)
return ax25;
}
/*
* Fill in a created AX.25 created control block with the default
* values for a particular device.
*/
static void ax25_fillin_cb(ax25_cb *ax25, struct device *dev)
{
ax25->device = dev;
ax25->rtt = ax25_dev_get_value(dev, AX25_VALUES_T1);
ax25->t1 = ax25_dev_get_value(dev, AX25_VALUES_T1);
ax25->t2 = ax25_dev_get_value(dev, AX25_VALUES_T2);
ax25->t3 = ax25_dev_get_value(dev, AX25_VALUES_T3);
ax25->n2 = ax25_dev_get_value(dev, AX25_VALUES_N2);
ax25->modulus = ax25_dev_get_value(dev, AX25_VALUES_AXDEFMODE);
if (ax25->modulus == MODULUS) {
ax25->window = ax25_dev_get_value(dev, AX25_VALUES_WINDOW);
} else {
ax25->window = ax25_dev_get_value(dev, AX25_VALUES_EWINDOW);
}
ax25->backoff = ax25_dev_get_value(dev, AX25_VALUES_BACKOFF) == 'E';
}
int ax25_send_frame(struct sk_buff *skb, ax25_address *src, ax25_address *dest,
ax25_digi *digi, struct device *dev)
{
......@@ -571,7 +609,7 @@ int ax25_send_frame(struct sk_buff *skb, ax25_address *src, ax25_address *dest,
if ((ax25 = ax25_create_cb()) == NULL)
return 0;
ax25->device = dev;
ax25_fillin_cb(ax25, dev);
memcpy(&ax25->source_addr, src, sizeof(ax25_address));
memcpy(&ax25->dest_addr, dest, sizeof(ax25_address));
......@@ -709,6 +747,10 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
sk->ax25->modulus = opt ? EMODULUS : MODULUS;
return 0;
case AX25_HDRINCL:
sk->ax25->hdrincl = opt ? 1 : 0;
return 0;
default:
return -ENOPROTOOPT;
}
......@@ -735,7 +777,7 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname,
break;
case AX25_T1:
val = sk->ax25->t1 / PR_SLOWHZ;
val = (sk->ax25->t1 * 2) / PR_SLOWHZ;
break;
case AX25_T2:
......@@ -756,7 +798,11 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname,
case AX25_EXTSEQ:
val = (sk->ax25->modulus == EMODULUS);
return 0;
break;
case AX25_HDRINCL:
val = sk->ax25->hdrincl;
break;
default:
return -ENOPROTOOPT;
......@@ -884,6 +930,8 @@ static struct sock *ax25_make_new(struct sock *osk, struct device *dev)
return NULL;
}
ax25_fillin_cb(ax25, dev);
sk->type = osk->type;
sk->socket = osk->socket;
......@@ -933,6 +981,7 @@ static struct sock *ax25_make_new(struct sock *osk, struct device *dev)
ax25->modulus = osk->ax25->modulus;
ax25->backoff = osk->ax25->backoff;
ax25->hdrincl = osk->ax25->hdrincl;
ax25->rtt = osk->ax25->rtt;
ax25->t1 = osk->ax25->t1;
ax25->t2 = osk->ax25->t2;
......@@ -940,7 +989,6 @@ static struct sock *ax25_make_new(struct sock *osk, struct device *dev)
ax25->n2 = osk->ax25->n2;
ax25->window = osk->ax25->window;
ax25->device = dev;
memcpy(&ax25->source_addr, &osk->ax25->source_addr, sizeof(ax25_address));
......@@ -1073,7 +1121,7 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr,int addr_len)
return -EADDRNOTAVAIL;
}
sk->ax25->device = dev;
ax25_fillin_cb(sk->ax25, dev);
ax25_insert_socket(sk->ax25);
sk->zapped = 0;
......@@ -1298,6 +1346,7 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a
/*
* Process the AX.25/LAPB frame.
*/
skb->h.raw = skb->data;
/*
* Parse the address header.
......@@ -1310,7 +1359,7 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a
/*
* Send the frame to the AX.25 auto-router
*/
ax25_rt_rx_frame(&src, dev);
ax25_rt_rx_frame(&src, dev, &dp);
/*
* Ours perhaps ?
......@@ -1414,6 +1463,16 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a
return 0;
}
/*
* Is connected mode supported on this device ?
* If not, should we DM the incoming frame (except DMs) or
* silently ignore them. For now we stay quiet.
*/
if (!ax25_dev_get_value(dev, AX25_VALUES_CONMODE)) {
kfree_skb(skb, FREE_READ);
return 0;
}
/* LAPB */
if ((ax25 = ax25_find_cb(&dest, &src, dev)) != NULL) {
/*
......@@ -1469,6 +1528,8 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a
kfree_skb(skb, FREE_READ);
return 0;
}
ax25_fillin_cb(ax25, dev);
#else
if (mine)
ax25_return_dm(dev, &src, &dest, &dp);
......@@ -1502,8 +1563,10 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a
if ((*skb->data & ~PF) == SABME) {
ax25->modulus = EMODULUS;
ax25->window = ax25_dev_get_value(dev, AX25_VALUES_EWINDOW);
} else {
ax25->modulus = MODULUS;
ax25->window = ax25_dev_get_value(dev, AX25_VALUES_WINDOW);
}
ax25->device = dev;
......@@ -1733,10 +1796,9 @@ static int ax25_recvfrom(struct socket *sock, void *ubuf, int size, int noblock,
struct sock *sk = (struct sock *)sock->data;
struct sockaddr_ax25 *sax = (struct sockaddr_ax25 *)sip;
char *addrptr = (char *)sip;
int copied = 0;
int copied, length;
struct sk_buff *skb;
int er;
int bias = 0;
if (sk->err) {
er = -sk->err;
......@@ -1747,19 +1809,28 @@ static int ax25_recvfrom(struct socket *sock, void *ubuf, int size, int noblock,
if (addr_len != NULL)
*addr_len = sizeof(*sax);
/* This works for seqpacket too. The receiver has ordered the queue for us! We do one quick check first though */
if (sk->type == SOCK_SEQPACKET) {
if (sk->state != TCP_ESTABLISHED)
/*
* This works for seqpacket too. The receiver has ordered the
* queue for us! We do one quick check first though
*/
if (sk->type == SOCK_SEQPACKET && sk->state != TCP_ESTABLISHED)
return -ENOTCONN;
bias = 1;
}
/* Now we can treat all alike */
if ((skb = skb_recv_datagram(sk, flags, noblock, &er)) == NULL)
return er;
copied = (size < skb->len - bias) ? size : skb->len - bias;
skb_copy_datagram(skb, bias, ubuf, copied);
if (sk->ax25->hdrincl) {
length = skb->len + (skb->data - skb->h.raw);
} else {
if (sk->type == SOCK_SEQPACKET)
skb_pull(skb, 1); /* Remove PID */
length = skb->len;
skb->h.raw = skb->data;
}
copied = (size < length) ? size : length;
skb_copy_datagram(skb, 0, ubuf, copied);
if (sax) {
struct sockaddr_ax25 addr;
......@@ -1887,6 +1958,16 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
ax25_digi_on = amount ? 1 : 0;
return 0;
case SIOCAX25GETPARMS:
case SIOCAX25SETPARMS:
return ax25_dev_ioctl(cmd, (void *)arg);
case SIOCADDRT:
case SIOCDELRT:
if (!suser())
return -EPERM;
return ax25_rt_ioctl(cmd, (void *)arg);
case SIOCGIFADDR:
case SIOCSIFADDR:
case SIOCGIFDSTADDR:
......@@ -1907,7 +1988,7 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
return(0);
}
int ax25_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
static int ax25_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
{
ax25_cb *ax25;
struct device *dev;
......@@ -2050,7 +2131,7 @@ void ax25_proto_init(struct net_proto *pro)
ax25_cs_get_info
});
printk("GW4PTS/G4KLX AX.25 for Linux. Version 0.30 ALPHA for Linux NET3.030 (Linux 1.3.0)\n");
printk("G4KLX/GW4PTS AX.25 for Linux. Version 0.30 ALPHA for Linux NET3.030 (Linux 1.3.20)\n");
}
/*
......@@ -2158,8 +2239,7 @@ int ax25_rebuild_header(unsigned char *bp, struct device *dev, unsigned long des
if (bp[16] == AX25_P_IP) {
mode = ax25_ip_mode_get((ax25_address *)(bp + 1), dev);
if (mode == 'V' || mode == 'v' || (mode == ' ' && sl_get_ax25_mode(dev))) {
if (mode == 'V' || mode == 'v' || (mode == ' ' && ax25_dev_get_value(dev, AX25_VALUES_IPDEFMODE) == 'V')) {
skb_device_unlock(skb);
skb_pull(skb, AX25_HEADER_LEN - 1); /* Keep PID */
ax25_send_frame(skb, (ax25_address *)(bp + 8), (ax25_address *)(bp + 1), NULL, dev);
......
......@@ -64,6 +64,7 @@ static int ax25_rx_iframe(ax25_cb *, struct sk_buff *);
static int ax25_rx_fragment(ax25_cb *ax25, struct sk_buff *skb)
{
struct sk_buff *skbn, *skbo;
int hdrlen;
if (ax25->fragno != 0) {
if (!(*skb->data & SEG_FIRST)) {
......@@ -86,6 +87,14 @@ static int ax25_rx_fragment(ax25_cb *ax25, struct sk_buff *skb)
}
skb_reserve(skbn, AX25_MAX_HEADER_LEN);
skbn->h.raw = skbn->data;
skbo = skb_dequeue(&ax25->frag_queue);
hdrlen = skbo->data - skbo->h.raw;
skb_push(skbo, hdrlen);
memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len);
skb_pull(skbn, hdrlen);
kfree_skb(skbo, FREE_READ);
while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL) {
memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len);
......@@ -122,13 +131,13 @@ static int ax25_rx_iframe(ax25_cb *ax25, struct sk_buff *skb)
{
int queued = 0;
skb->h.raw = skb->data;
switch (*skb->data) {
#ifdef CONFIG_NETROM
case AX25_P_NETROM:
if (ax25_dev_get_value(ax25->device, AX25_VALUES_NETROM)) {
skb_pull(skb, 1); /* Remove PID */
queued = nr_route_frame(skb, ax25);
}
break;
#endif
#ifdef CONFIG_INET
......@@ -141,7 +150,7 @@ static int ax25_rx_iframe(ax25_cb *ax25, struct sk_buff *skb)
break;
#endif
case AX25_P_TEXT:
if (ax25->sk != NULL) {
if (ax25->sk != NULL && ax25_dev_get_value(ax25->device, AX25_VALUES_TEXT)) {
if (sock_queue_rcv_skb(ax25->sk, skb) == 0) {
queued = 1;
} else {
......@@ -172,11 +181,13 @@ static int ax25_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
switch (frametype) {
case SABM:
ax25->modulus = MODULUS;
ax25->window = ax25_dev_get_value(ax25->device, AX25_VALUES_WINDOW);
ax25_send_control(ax25, UA, pf, C_RESPONSE);
break;
case SABME:
ax25->modulus = EMODULUS;
ax25->window = ax25_dev_get_value(ax25->device, AX25_VALUES_EWINDOW);
ax25_send_control(ax25, UA, pf, C_RESPONSE);
break;
......@@ -217,6 +228,7 @@ static int ax25_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
}
} else {
ax25->modulus = MODULUS;
ax25->window = ax25_dev_get_value(ax25->device, AX25_VALUES_WINDOW);
}
}
break;
......@@ -298,6 +310,7 @@ static int ax25_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
switch (frametype) {
case SABM:
ax25->modulus = MODULUS;
ax25->window = ax25_dev_get_value(ax25->device, AX25_VALUES_WINDOW);
ax25_send_control(ax25, UA, pf, C_RESPONSE);
ax25->condition = 0x00;
ax25->t1timer = 0;
......@@ -309,6 +322,7 @@ static int ax25_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
case SABME:
ax25->modulus = EMODULUS;
ax25->window = ax25_dev_get_value(ax25->device, AX25_VALUES_EWINDOW);
ax25_send_control(ax25, UA, pf, C_RESPONSE);
ax25->condition = 0x00;
ax25->t1timer = 0;
......@@ -455,6 +469,7 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
switch (frametype) {
case SABM:
ax25->modulus = MODULUS;
ax25->window = ax25_dev_get_value(ax25->device, AX25_VALUES_WINDOW);
ax25_send_control(ax25, UA, pf, C_RESPONSE);
ax25->condition = 0x00;
ax25->t1timer = 0;
......@@ -468,6 +483,7 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
case SABME:
ax25->modulus = EMODULUS;
ax25->window = ax25_dev_get_value(ax25->device, AX25_VALUES_EWINDOW);
ax25_send_control(ax25, UA, pf, C_RESPONSE);
ax25->condition = 0x00;
ax25->t1timer = 0;
......
......@@ -286,6 +286,16 @@ void ax25_enquiry_response(ax25_cb *ax25)
ax25->condition &= ~ACK_PENDING_CONDITION;
}
void ax25_timeout_response(ax25_cb *ax25)
{
if (ax25->condition & OWN_RX_BUSY_CONDITION)
ax25_send_control(ax25, RNR, POLLOFF, C_RESPONSE);
else
ax25_send_control(ax25, RR, POLLOFF, C_RESPONSE);
ax25->condition &= ~ACK_PENDING_CONDITION;
}
void ax25_check_iframes_acked(ax25_cb *ax25, unsigned short nr)
{
if (ax25->vs == nr) {
......
......@@ -24,6 +24,9 @@
* removes the heard structure.
* AX.25 029 Steven(GW7RRM) Added /proc information for uid/callsign mapping.
* Jonathan(G4KLX) Handling of IP mode in the routing list and /proc entry.
* AX.25 030 Jonathan(G4KLX) Added digi-peaters to routing table, and
* ioctls to manipulate them. Added port
* configuration.
*/
#include <linux/config.h>
......@@ -55,12 +58,19 @@ static struct ax25_route {
struct ax25_route *next;
ax25_address callsign;
struct device *dev;
ax25_digi *digipeat;
struct timeval stamp;
int n;
char ip_mode;
} *ax25_route = NULL;
void ax25_rt_rx_frame(ax25_address *src, struct device *dev)
static struct ax25_dev {
struct ax25_dev *next;
struct device *dev;
unsigned short values[AX25_MAX_VALUES];
} *ax25_device = NULL;
void ax25_rt_rx_frame(ax25_address *src, struct device *dev, ax25_digi *digi)
{
unsigned long flags;
extern struct timeval xtime;
......@@ -72,10 +82,11 @@ void ax25_rt_rx_frame(ax25_address *src, struct device *dev)
oldest = NULL;
for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
if (count == 0 || ax25_rt->stamp.tv_sec < oldest->stamp.tv_sec)
if (count == 0 || (ax25_rt->stamp.tv_sec != 0 && ax25_rt->stamp.tv_sec < oldest->stamp.tv_sec))
oldest = ax25_rt;
if (ax25cmp(&ax25_rt->callsign, src) == 0 && ax25_rt->dev == dev) {
if (ax25_rt->stamp.tv_sec != 0)
ax25_rt->stamp = xtime;
ax25_rt->n++;
return;
......@@ -87,6 +98,10 @@ void ax25_rt_rx_frame(ax25_address *src, struct device *dev)
if (count > AX25_ROUTE_MAX) {
oldest->callsign = *src;
oldest->dev = dev;
if (oldest->digipeat != NULL) {
kfree_s(oldest->digipeat, sizeof(ax25_digi));
oldest->digipeat = NULL;
}
oldest->stamp = xtime;
oldest->n = 1;
oldest->ip_mode = ' ';
......@@ -98,10 +113,19 @@ void ax25_rt_rx_frame(ax25_address *src, struct device *dev)
ax25_rt->callsign = *src;
ax25_rt->dev = dev;
ax25_rt->digipeat = NULL;
ax25_rt->stamp = xtime;
ax25_rt->n = 1;
ax25_rt->ip_mode = ' ';
if (digi != NULL) {
if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
kfree_s(ax25_rt, sizeof(struct ax25_route));
return;
}
memcpy(ax25_rt->digipeat, digi, sizeof(ax25_digi));
}
save_flags(flags);
cli();
......@@ -122,11 +146,15 @@ void ax25_rt_device_down(struct device *dev)
if (s->dev == dev) {
if (ax25_route == s) {
ax25_route = s->next;
if (s->digipeat != NULL)
kfree_s((void *)s->digipeat, sizeof(ax25_digi));
kfree_s((void *)s, (sizeof *s));
} else {
for (t = ax25_route; t != NULL; t = t->next) {
if (t->next == s) {
t->next = s->next;
if (s->digipeat != NULL)
kfree_s((void *)s->digipeat, sizeof(ax25_digi));
kfree_s((void *)s, sizeof(*s));
break;
}
......@@ -136,16 +164,116 @@ void ax25_rt_device_down(struct device *dev)
}
}
int ax25_rt_ioctl(unsigned int cmd, void *arg)
{
unsigned long flags;
struct ax25_route *s, *t, *ax25_rt;
struct ax25_routes_struct route;
struct device *dev;
int i, err;
switch (cmd) {
case SIOCADDRT:
if ((err = verify_area(VERIFY_READ, arg, sizeof(route))) != 0)
return err;
memcpy_fromfs(&route, arg, sizeof(route));
if ((dev = ax25rtr_get_dev(&route.port_addr)) == NULL)
return -EINVAL;
if (route.digi_count > 6)
return -EINVAL;
for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
if (ax25cmp(&ax25_rt->callsign, &route.dest_addr) == 0 && ax25_rt->dev == dev) {
if (ax25_rt->digipeat != NULL) {
kfree_s(ax25_rt->digipeat, sizeof(ax25_digi));
ax25_rt->digipeat = NULL;
}
if (route.digi_count != 0) {
if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL)
return -ENOMEM;
ax25_rt->digipeat->lastrepeat = 0;
ax25_rt->digipeat->ndigi = route.digi_count;
for (i = 0; i < route.digi_count; i++) {
ax25_rt->digipeat->repeated[i] = 0;
ax25_rt->digipeat->calls[i] = route.digi_addr[i];
}
}
ax25_rt->stamp.tv_sec = 0;
return 0;
}
}
if ((ax25_rt = (struct ax25_route *)kmalloc(sizeof(struct ax25_route), GFP_ATOMIC)) == NULL)
return -ENOMEM;
ax25_rt->callsign = route.dest_addr;
ax25_rt->dev = dev;
ax25_rt->digipeat = NULL;
ax25_rt->stamp.tv_sec = 0;
ax25_rt->n = 0;
ax25_rt->ip_mode = ' ';
if (route.digi_count != 0) {
if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
kfree_s(ax25_rt, sizeof(struct ax25_route));
return -ENOMEM;
}
ax25_rt->digipeat->lastrepeat = 0;
ax25_rt->digipeat->ndigi = route.digi_count;
for (i = 0; i < route.digi_count; i++) {
ax25_rt->digipeat->repeated[i] = 0;
ax25_rt->digipeat->calls[i] = route.digi_addr[i];
}
}
save_flags(flags);
cli();
ax25_rt->next = ax25_route;
ax25_route = ax25_rt;
restore_flags(flags);
break;
case SIOCDELRT:
if ((err = verify_area(VERIFY_READ, arg, sizeof(route))) != 0)
return err;
memcpy_fromfs(&route, arg, sizeof(route));
if ((dev = ax25rtr_get_dev(&route.port_addr)) == NULL)
return -EINVAL;
ax25_rt = ax25_route;
while (ax25_rt != NULL) {
s = ax25_rt;
ax25_rt = ax25_rt->next;
if (s->dev == dev && ax25cmp(&route.dest_addr, &s->callsign) == 0) {
if (ax25_route == s) {
ax25_route = s->next;
if (s->digipeat != NULL)
kfree_s((void *)s->digipeat, sizeof(ax25_digi));
kfree_s((void *)s, (sizeof *s));
} else {
for (t = ax25_route; t != NULL; t = t->next) {
if (t->next == s) {
t->next = s->next;
if (s->digipeat != NULL)
kfree_s((void *)s->digipeat, sizeof(ax25_digi));
kfree_s((void *)s, sizeof(*s));
break;
}
}
}
}
}
break;
}
return 0;
}
int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
{
struct ax25_route *ax25_rt;
int len = 0;
off_t pos = 0;
off_t begin = 0;
int i;
cli();
len += sprintf(buffer, "callsign dev count time mode\n");
len += sprintf(buffer, "callsign dev count time mode digipeaters\n");
for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
len += sprintf(buffer + len, "%-9s %-4s %5d %9d",
......@@ -157,17 +285,23 @@ int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length, int d
switch (ax25_rt->ip_mode) {
case 'V':
case 'v':
len += sprintf(buffer + len, " vc\n");
len += sprintf(buffer + len, " vc");
break;
case 'D':
case 'd':
len += sprintf(buffer + len, " dg\n");
len += sprintf(buffer + len, " dg");
break;
default:
len += sprintf(buffer + len, "\n");
len += sprintf(buffer + len, " ");
break;
}
if (ax25_rt->digipeat != NULL)
for (i = 0; i < ax25_rt->digipeat->ndigi; i++)
len += sprintf(buffer + len, " %s", ax2asc(&ax25_rt->digipeat->calls[i]));
len += sprintf(buffer + len, "\n");
pos = begin + len;
if (pos < offset) {
......@@ -245,6 +379,11 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
call = (ax25_address *)ax25->device->dev_addr;
}
memcpy(&ax25->source_addr, call, sizeof(ax25_address));
if (ax25_rt->digipeat != NULL) {
if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL)
return -ENOMEM;
memcpy(ax25->digipeat, ax25_rt->digipeat, sizeof(ax25_digi));
}
if (ax25->sk != NULL)
ax25->sk->zapped = 0;
......@@ -285,4 +424,167 @@ char ax25_ip_mode_get(ax25_address *callsign, struct device *dev)
return ' ';
}
static struct ax25_dev *ax25_dev_get_dev(struct device *dev)
{
struct ax25_dev *s;
for (s = ax25_device; s != NULL; s = s->next)
if (s->dev == dev)
return s;
return NULL;
}
/*
* Wow, a bit of data hiding. Is this C++ or what ?
*/
unsigned short ax25_dev_get_value(struct device *dev, int valueno)
{
struct ax25_dev *ax25_dev;
if ((ax25_dev = ax25_dev_get_dev(dev)) == NULL) {
printk("ax25_dev_get_flag called with invalid device\n");
return 1;
}
return ax25_dev->values[valueno];
}
/*
* This is called when an interface is brought up. These are
* reasonable defaults.
*/
void ax25_dev_device_up(struct device *dev)
{
unsigned long flags;
struct ax25_dev *ax25_dev;
if ((ax25_dev = (struct ax25_dev *)kmalloc(sizeof(struct ax25_dev), GFP_ATOMIC)) == NULL)
return; /* No space */
ax25_dev->dev = dev;
ax25_dev->values[AX25_VALUES_IPDEFMODE] = AX25_DEF_IPDEFMODE;
ax25_dev->values[AX25_VALUES_AXDEFMODE] = AX25_DEF_AXDEFMODE;
ax25_dev->values[AX25_VALUES_NETROM] = AX25_DEF_NETROM;
ax25_dev->values[AX25_VALUES_TEXT] = AX25_DEF_TEXT;
ax25_dev->values[AX25_VALUES_BACKOFF] = AX25_DEF_BACKOFF;
ax25_dev->values[AX25_VALUES_CONMODE] = AX25_DEF_CONMODE;
ax25_dev->values[AX25_VALUES_WINDOW] = AX25_DEF_WINDOW;
ax25_dev->values[AX25_VALUES_EWINDOW] = AX25_DEF_EWINDOW;
ax25_dev->values[AX25_VALUES_T1] = (AX25_DEF_T1 * PR_SLOWHZ) / 2;
ax25_dev->values[AX25_VALUES_T2] = AX25_DEF_T2 * PR_SLOWHZ;
ax25_dev->values[AX25_VALUES_T3] = AX25_DEF_T3 * PR_SLOWHZ;
ax25_dev->values[AX25_VALUES_N2] = AX25_DEF_N2;
save_flags(flags);
cli();
ax25_dev->next = ax25_device;
ax25_device = ax25_dev;
restore_flags(flags);
}
void ax25_dev_device_down(struct device *dev)
{
struct ax25_dev *s, *t, *ax25_dev = ax25_device;
while (ax25_dev != NULL) {
s = ax25_dev;
ax25_dev = ax25_dev->next;
if (s->dev == dev) {
if (ax25_device == s) {
ax25_device = s->next;
kfree_s((void *)s, (sizeof *s));
} else {
for (t = ax25_device; t != NULL; t = t->next) {
if (t->next == s) {
t->next = s->next;
kfree_s((void *)s, sizeof(*s));
break;
}
}
}
}
}
}
int ax25_dev_ioctl(unsigned int cmd, void *arg)
{
struct ax25_parms_struct ax25_parms;
struct device *dev;
struct ax25_dev *ax25_dev;
int err;
switch (cmd) {
case SIOCAX25SETPARMS:
if (!suser())
return -EPERM;
if ((err = verify_area(VERIFY_READ, arg, sizeof(ax25_parms))) != 0)
return err;
memcpy_fromfs(&ax25_parms, arg, sizeof(ax25_parms));
if ((dev = ax25rtr_get_dev(&ax25_parms.port_addr)) == NULL)
return -EINVAL;
if ((ax25_dev = ax25_dev_get_dev(dev)) == NULL)
return -EINVAL;
if (ax25_parms.values[AX25_VALUES_IPDEFMODE] != 'D' &&
ax25_parms.values[AX25_VALUES_IPDEFMODE] != 'V')
return -EINVAL;
if (ax25_parms.values[AX25_VALUES_AXDEFMODE] != MODULUS &&
ax25_parms.values[AX25_VALUES_AXDEFMODE] != EMODULUS)
return -EINVAL;
if (ax25_parms.values[AX25_VALUES_NETROM] != 0 &&
ax25_parms.values[AX25_VALUES_NETROM] != 1)
return -EINVAL;
if (ax25_parms.values[AX25_VALUES_TEXT] != 0 &&
ax25_parms.values[AX25_VALUES_TEXT] != 1)
return -EINVAL;
if (ax25_parms.values[AX25_VALUES_BACKOFF] != 'E' &&
ax25_parms.values[AX25_VALUES_BACKOFF] != 'L')
return -EINVAL;
if (ax25_parms.values[AX25_VALUES_CONMODE] != 0 &&
ax25_parms.values[AX25_VALUES_CONMODE] != 1)
return -EINVAL;
if (ax25_parms.values[AX25_VALUES_WINDOW] < 1 ||
ax25_parms.values[AX25_VALUES_WINDOW] > 7)
return -EINVAL;
if (ax25_parms.values[AX25_VALUES_EWINDOW] < 1 ||
ax25_parms.values[AX25_VALUES_EWINDOW] > 63)
return -EINVAL;
if (ax25_parms.values[AX25_VALUES_T1] < 1)
return -EINVAL;
if (ax25_parms.values[AX25_VALUES_T2] < 1)
return -EINVAL;
if (ax25_parms.values[AX25_VALUES_T3] < 1)
return -EINVAL;
if (ax25_parms.values[AX25_VALUES_N2] < 1 ||
ax25_parms.values[AX25_VALUES_N2] > 31)
return -EINVAL;
memcpy(ax25_dev->values, ax25_parms.values, AX25_MAX_VALUES * sizeof(short));
ax25_dev->values[AX25_VALUES_T1] *= (PR_SLOWHZ / 2);
ax25_dev->values[AX25_VALUES_T2] *= PR_SLOWHZ;
ax25_dev->values[AX25_VALUES_T3] *= PR_SLOWHZ;
break;
case SIOCAX25GETPARMS:
if ((err = verify_area(VERIFY_WRITE, arg, sizeof(struct ax25_parms_struct))) != 0)
return err;
memcpy_fromfs(&ax25_parms, arg, sizeof(ax25_parms));
if ((dev = ax25rtr_get_dev(&ax25_parms.port_addr)) == NULL)
return -EINVAL;
if ((ax25_dev = ax25_dev_get_dev(dev)) == NULL)
return -EINVAL;
memcpy(ax25_parms.values, ax25_dev->values, AX25_MAX_VALUES * sizeof(short));
ax25_parms.values[AX25_VALUES_T1] /= (PR_SLOWHZ * 2);
ax25_parms.values[AX25_VALUES_T2] /= PR_SLOWHZ;
ax25_parms.values[AX25_VALUES_T3] /= PR_SLOWHZ;
memcpy_tofs(arg, &ax25_parms, sizeof(ax25_parms));
break;
}
return 0;
}
#endif
......@@ -130,7 +130,7 @@ static void ax25_timer(unsigned long param)
if (ax25->state == AX25_STATE_3 || ax25->state == AX25_STATE_4) {
if (ax25->condition & ACK_PENDING_CONDITION) {
ax25->condition &= ~ACK_PENDING_CONDITION;
ax25_enquiry_response(ax25);
ax25_timeout_response(ax25);
}
}
}
......@@ -167,7 +167,9 @@ static void ax25_timer(unsigned long param)
}
} else {
ax25->modulus = MODULUS;
ax25->window = ax25_dev_get_value(ax25->device, AX25_VALUES_WINDOW);
ax25->n2count = 0;
ax25_send_control(ax25, SABM, POLLON, C_COMMAND);
}
} else {
ax25->n2count++;
......
......@@ -9,8 +9,10 @@
O_TARGET := core.o
O_OBJS :=
ifdef CONFIG_NET
O_OBJS := sock.o dev.o dev_mcast.o skbuff.o datagram.o iovec.o
O_OBJS += sock.o dev.o dev_mcast.o iovec.o skbuff.o datagram.o
endif
include $(TOPDIR)/Rules.make
......
......@@ -1240,13 +1240,13 @@ static int arp_req_set(struct arpreq *req)
#ifdef CONFIG_AX25
case ARPHRD_AX25:
htype = ARPHRD_AX25;
hlen = 7;
hlen = AX25_ADDR_LEN;
break;
#endif
#ifdef CONFIG_NETROM
case ARPHRD_NETROM:
htype = ARPHRD_NETROM;
hlen = 7;
hlen = AX25_ADDR_LEN;
break;
#endif
case ARPHRD_IEEE802:
......
......@@ -30,6 +30,7 @@
#include <linux/in.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <net/ip.h>
#include <net/protocol.h>
#include <net/route.h>
......
......@@ -127,6 +127,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <net/snmp.h>
#include <net/ip.h>
......@@ -1695,7 +1696,6 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
static void ip_loopback(struct device *old_dev, struct sk_buff *skb)
{
extern struct device loopback_dev;
struct device *dev=&loopback_dev;
int len=skb->len-old_dev->hard_header_len;
struct sk_buff *newskb=dev_alloc_skb(len+dev->hard_header_len+15);
......
......@@ -84,6 +84,7 @@
#include <linux/ip_fw.h>
#include <net/checksum.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
/*
* Implement IP packet firewall
......
......@@ -7,6 +7,8 @@
* Fixes:
* Alan Cox : Merged and made usable non modular (its so tiny its silly as
* a module taking up 2 pages).
* Alan Cox : Fixed bug with 1.3.18 and IPIP not working (now needs to set skb->h.iph)
* to keep ip_forward happy.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -56,6 +58,7 @@ int ipip_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
#ifdef TUNNEL_DEBUG
printk("ipip_rcv: got a packet!\n");
#endif
skb->h.iph=skb->data; /* Correct IP header pointer on to new header */
if(ip_forward(skb, dev, 0, daddr, 0))
kfree_skb(skb, FREE_READ);
MOD_DEC_USE_COUNT;
......
......@@ -66,6 +66,7 @@
#include <net/ax25.h>
#endif
#include <linux/proc_fs.h>
#include <linux/stat.h>
#if defined(CONFIG_INET_RARP) || defined(MODULE)
......
......@@ -60,6 +60,7 @@
#include <linux/ipx.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/route.h>
#include <linux/skbuff.h>
#include <net/sock.h>
#include <asm/segment.h>
......@@ -71,6 +72,7 @@
#include <net/p8022.h>
#include <net/psnap.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#ifdef CONFIG_IPX
/* Configuration Variables */
......
......@@ -50,7 +50,7 @@
#include <linux/interrupt.h>
#include <linux/notifier.h>
#include <net/netrom.h>
#include <linux/proc_fs.h>
#include <net/ip.h>
#include <net/arp.h>
......@@ -115,8 +115,6 @@ static void nr_kill_by_device(struct device *dev)
s->dead = 1;
}
}
nr_rt_device_down(dev);
}
/*
......@@ -124,10 +122,13 @@ static void nr_kill_by_device(struct device *dev)
*/
static int nr_device_event(unsigned long event, void *ptr)
{
struct device *dev = (struct device *)ptr;
if (event != NETDEV_DOWN)
return NOTIFY_DONE;
nr_kill_by_device(ptr);
nr_kill_by_device(dev);
nr_rt_device_down(dev);
return NOTIFY_DONE;
}
......@@ -329,6 +330,10 @@ static int nr_setsockopt(struct socket *sock, int level, int optname,
sk->nr->n2 = opt;
return 0;
case NETROM_HDRINCL:
sk->nr->hdrincl = opt ? 1 : 0;
return 0;
default:
return -ENOPROTOOPT;
}
......@@ -351,7 +356,7 @@ static int nr_getsockopt(struct socket *sock, int level, int optname,
switch (optname) {
case NETROM_T1:
val = sk->nr->t1 / PR_SLOWHZ;
val = (sk->nr->t1 * 2) / PR_SLOWHZ;
break;
case NETROM_T2:
......@@ -362,6 +367,10 @@ static int nr_getsockopt(struct socket *sock, int level, int optname,
val = sk->nr->n2;
break;
case NETROM_HDRINCL:
val = sk->nr->hdrincl;
break;
default:
return -ENOPROTOOPT;
}
......@@ -497,6 +506,7 @@ static int nr_create(struct socket *sock, int protocol)
nr->bpqext = 1;
nr->fraglen = 0;
nr->hdrincl = 0;
nr->state = NR_STATE_0;
nr->device = NULL;
......@@ -580,6 +590,7 @@ static struct sock *nr_make_new(struct sock *osk)
nr->device = osk->nr->device;
nr->bpqext = osk->nr->bpqext;
nr->hdrincl = osk->nr->hdrincl;
nr->fraglen = 0;
nr->t1timer = 0;
......@@ -931,10 +942,9 @@ int nr_rx_frame(struct sk_buff *skb, struct device *dev)
*/
if (((frametype & 0x0F) != NR_CONNREQ && (sk = nr_find_socket(circuit_index, circuit_id, SOCK_SEQPACKET)) != NULL) ||
((frametype & 0x0F) == NR_CONNREQ && (sk = nr_find_peer(circuit_index, circuit_id, SOCK_SEQPACKET)) != NULL)) {
skb_pull(skb, NR_NETWORK_LEN);
skb->h.raw = skb->data + NR_TRANSPORT_LEN;
skb->h.raw = skb->data;
if ((frametype & 0x0F) == NR_CONNACK && skb->len == 7)
if ((frametype & 0x0F) == NR_CONNACK && skb->len == 22)
sk->nr->bpqext = 1;
else
sk->nr->bpqext = 0;
......@@ -1129,7 +1139,7 @@ static int nr_recvfrom(struct socket *sock, void *ubuf, int size, int noblock,
{
struct sock *sk = (struct sock *)sock->data;
struct sockaddr_ax25 *sax = (struct sockaddr_ax25 *)sip;
int copied = 0;
int copied;
struct sk_buff *skb;
int er;
......@@ -1142,7 +1152,10 @@ static int nr_recvfrom(struct socket *sock, void *ubuf, int size, int noblock,
if (addr_len != NULL)
*addr_len = sizeof(*sax);
/* This works for seqpacket too. The receiver has ordered the queue for us! We do one quick check first though */
/*
* This works for seqpacket too. The receiver has ordered the queue for
* us! We do one quick check first though
*/
if (sk->type == SOCK_SEQPACKET && sk->state != TCP_ESTABLISHED)
return -ENOTCONN;
......@@ -1150,8 +1163,12 @@ static int nr_recvfrom(struct socket *sock, void *ubuf, int size, int noblock,
if ((skb = skb_recv_datagram(sk, flags, noblock, &er)) == NULL)
return er;
copied = (size < skb->len - NR_TRANSPORT_LEN) ? size : skb->len - NR_TRANSPORT_LEN;
if (!sk->nr->hdrincl) {
skb_pull(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN);
skb->h.raw = skb->data;
}
copied = (size < skb->len) ? size : skb->len;
skb_copy_datagram(skb, 0, ubuf, copied);
if (sax != NULL) {
......@@ -1286,8 +1303,7 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
return(0);
}
static int nr_get_info(char *buffer, char **start, off_t offset,
int length, int dummy)
static int nr_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
{
struct sock *s;
struct device *dev;
......
......@@ -211,7 +211,7 @@ int nr_init(struct device *dev)
dev->stop = nr_close;
dev->hard_header = nr_header;
dev->hard_header_len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + 2 + NR_NETWORK_LEN + NR_TRANSPORT_LEN;
dev->hard_header_len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + 3 + NR_NETWORK_LEN + NR_TRANSPORT_LEN;
dev->addr_len = AX25_ADDR_LEN;
dev->type = ARPHRD_NETROM;
dev->rebuild_header = nr_rebuild_header;
......
......@@ -68,11 +68,16 @@ static int nr_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more)
skbn->free = 1;
skbn->arp = 1;
skbn->sk = sk;
sk->rmem_alloc += skb->truesize;
sk->rmem_alloc += skbn->truesize;
skbn->h.raw = skbn->data;
while ((skbo = skb_dequeue(&sk->nr->frag_queue)) != NULL) {
skbo = skb_dequeue(&sk->nr->frag_queue);
memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len);
kfree_skb(skbo, FREE_READ);
while ((skbo = skb_dequeue(&sk->nr->frag_queue)) != NULL) {
skb_pull(skbo, NR_NETWORK_LEN + NR_TRANSPORT_LEN);
memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len);
kfree_skb(skbo, FREE_READ);
}
......@@ -93,9 +98,9 @@ static int nr_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype
case NR_CONNACK:
nr_calculate_rtt(sk);
sk->window = skb->data[5];
sk->nr->your_index = skb->data[2];
sk->nr->your_id = skb->data[3];
sk->window = skb->data[20];
sk->nr->your_index = skb->data[17];
sk->nr->your_id = skb->data[18];
sk->nr->t1timer = 0;
sk->nr->t2timer = 0;
sk->nr->t4timer = 0;
......@@ -170,8 +175,8 @@ static int nr_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype
unsigned short nr, ns;
int queued = 0;
nr = skb->data[3];
ns = skb->data[2];
nr = skb->data[18];
ns = skb->data[17];
switch (frametype) {
......@@ -276,7 +281,7 @@ static int nr_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype
do {
save_vr = sk->nr->vr;
while ((skbn = skb_dequeue(&sk->nr->reseq_queue)) != NULL) {
ns = skbn->data[2];
ns = skbn->data[17];
if (ns == sk->nr->vr) {
if (nr_queue_rx_frame(sk, skbn, frametype & NR_MORE_FLAG) == 0) {
sk->nr->vr = (sk->nr->vr + 1) % NR_MODULUS;
......@@ -328,7 +333,7 @@ int nr_process_rx_frame(struct sock *sk, struct sk_buff *skb)
del_timer(&sk->timer);
frametype = skb->data[4];
frametype = skb->data[19];
switch (sk->nr->state)
{
......
......@@ -15,6 +15,8 @@
*
* Fixes:
* Linus Torvalds : Assorted bug cures.
* Niibe Yutaka : async I/O support
* Carsten Paeth : PF_UNIX check, address fixes.
*/
#include <linux/config.h>
......@@ -237,14 +239,26 @@ static void def_callback1(struct sock *sk)
static void def_callback2(struct sock *sk, int len)
{
if(!sk->dead)
{
wake_up_interruptible(sk->sleep);
sock_wake_async(sk->socket, 1);
}
}
static void def_callback3(struct sock *sk)
{
if(!sk->dead)
{
wake_up_interruptible(sk->sleep);
sock_wake_async(sk->socket, 2);
}
}
static int unix_create(struct socket *sock, int protocol)
{
unix_socket *sk;
/* printk("Unix create\n");*/
if(protocol)
if(protocol && protocol != PF_UNIX)
return -EPROTONOSUPPORT;
sk=(unix_socket *)kmalloc(sizeof(*sk),GFP_KERNEL);
if(sk==NULL)
......@@ -289,7 +303,7 @@ static int unix_create(struct socket *sock, int protocol)
sk->shutdown=0;
sk->state_change=def_callback1;
sk->data_ready=def_callback2;
sk->write_space=def_callback1;
sk->write_space=def_callback3;
sk->error_report=def_callback1;
sk->mtu=4096;
sk->socket=sock;
......@@ -410,7 +424,6 @@ static int unix_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
struct sk_buff *skb;
int err;
unix_mkname(sun, addr_len);
if(sk->type==SOCK_STREAM && sk->protinfo.af_unix.other)
{
if(sock->state==SS_CONNECTING && sk->state==TCP_ESTABLISHED)
......@@ -428,9 +441,11 @@ static int unix_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
return -EISCONN;
}
if(sun->sun_family!=AF_UNIX)
if(addr_len < sizeof(sun->sun_family)+1 || sun->sun_family!=AF_UNIX)
return -EINVAL;
unix_mkname(sun, addr_len);
if(sk->type==SOCK_DGRAM && sk->protinfo.af_unix.other)
{
sk->protinfo.af_unix.other->protinfo.af_unix.locks--;
......@@ -440,6 +455,11 @@ static int unix_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
if(sock->type==SOCK_DGRAM)
{
other=unix_find_other(sun->sun_path, &err);
if(other==NULL)
return err;
other->protinfo.af_unix.locks++;
sk->protinfo.af_unix.other=other;
sock->state=SS_CONNECTED;
sk->state=TCP_ESTABLISHED;
return 0; /* Done */
......@@ -601,6 +621,7 @@ static int unix_accept(struct socket *sock, struct socket *newsock, int flags)
tsk->protinfo.af_unix.locks++; /* Back lock */
sti();
tsk->state_change(tsk); /* Wake up any sleeping connect */
sock_wake_async(tsk->socket, 0);
return 0;
}
......@@ -619,10 +640,10 @@ static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_
if(sk->protinfo.af_unix.name==NULL)
{
*sun->sun_path=0;
*uaddr_len=3;
*uaddr_len=sizeof(sun->sun_family)+1;
return 0; /* Not bound */
}
*uaddr_len=sizeof(short)+strlen(sk->protinfo.af_unix.name)+1;
*uaddr_len=sizeof(sun->sun_family)+strlen(sk->protinfo.af_unix.name)+1;
strcpy(sun->sun_path,sk->protinfo.af_unix.name); /* 108 byte limited */
return 0;
}
......@@ -688,6 +709,13 @@ static int unix_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no
if(sun==NULL)
{
other=sk->protinfo.af_unix.other;
if(sock->type==SOCK_DGRAM && other->dead)
{
other->protinfo.af_unix.locks--;
sk->protinfo.af_unix.other=NULL;
sock->state=SS_UNCONNECTED;
return -ECONNRESET;
}
}
else
{
......@@ -761,7 +789,9 @@ static int unix_recvmsg(struct socket *sock, struct msghdr *msg, int size, int n
{
return -EAGAIN;
}
sk->socket->flags |= SO_WAITDATA;
interruptible_sleep_on(sk->sleep);
sk->socket->flags &= ~SO_WAITDATA;
if( current->signal & ~current->blocked)
{
sti();
......
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