diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-04-29 21:13:14 +0000 |
---|---|---|
committer | <ralf@linux-mips.org> | 1997-04-29 21:13:14 +0000 |
commit | 19c9bba94152148523ba0f7ef7cffe3d45656b11 (patch) | |
tree | 40b1cb534496a7f1ca0f5c314a523c69f1fee464 /net/rose | |
parent | 7206675c40394c78a90e74812bbdbf8cf3cca1be (diff) |
Import of Linux/MIPS 2.1.36
Diffstat (limited to 'net/rose')
-rw-r--r-- | net/rose/Makefile | 6 | ||||
-rw-r--r-- | net/rose/af_rose.c | 765 | ||||
-rw-r--r-- | net/rose/rose_dev.c | 128 | ||||
-rw-r--r-- | net/rose/rose_in.c | 73 | ||||
-rw-r--r-- | net/rose/rose_link.c | 131 | ||||
-rw-r--r-- | net/rose/rose_out.c | 78 | ||||
-rw-r--r-- | net/rose/rose_route.c | 194 | ||||
-rw-r--r-- | net/rose/rose_subr.c | 121 | ||||
-rw-r--r-- | net/rose/rose_timer.c | 45 | ||||
-rw-r--r-- | net/rose/sysctl_net_rose.c | 19 |
10 files changed, 734 insertions, 826 deletions
diff --git a/net/rose/Makefile b/net/rose/Makefile index 0d71de9cf..7eb55881e 100644 --- a/net/rose/Makefile +++ b/net/rose/Makefile @@ -8,9 +8,13 @@ # Note 2! The CFLAGS definition is now in the main makefile... O_TARGET := rose.o -O_OBJS := af_rose.o sysctl_net_rose.o rose_dev.o rose_in.o rose_link.o rose_out.o rose_route.o rose_subr.o rose_timer.o +O_OBJS := af_rose.o rose_dev.o rose_in.o rose_link.o rose_out.o rose_route.o rose_subr.o rose_timer.o M_OBJS := $(O_TARGET) +ifeq ($(CONFIG_SYSCTL),y) +O_OBJS += sysctl_net_rose.o +endif + include $(TOPDIR)/Rules.make tar: diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 4b8acd3f8..f173dedaf 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -4,7 +4,7 @@ * This is ALPHA test software. This code may break your machine, randomly fail to work with new * releases, misbehave and/or generally screw up. It might even work. * - * This code REQUIRES 2.1.0 or higher/ NET3.029 + * This code REQUIRES 2.1.15 or higher/ NET3.038 * * This module: * This module is free software; you can redistribute it and/or @@ -14,10 +14,14 @@ * * History * Rose 001 Jonathan(G4KLX) Cloned from af_netrom.c. + * Alan(GW4PTS) Hacked up for newer API stuff + * Terry (VK2KTJ) Added support for variable length + * address masks. */ - + #include <linux/config.h> #if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE) +#include <linux/module.h> #include <linux/errno.h> #include <linux/types.h> #include <linux/socket.h> @@ -54,12 +58,18 @@ int sysctl_rose_call_request_timeout = ROSE_DEFAULT_T1; int sysctl_rose_reset_request_timeout = ROSE_DEFAULT_T2; int sysctl_rose_clear_request_timeout = ROSE_DEFAULT_T3; int sysctl_rose_no_activity_timeout = ROSE_DEFAULT_IDLE; -int sysctl_rose_routing_control = 1; +int sysctl_rose_ack_hold_back_timeout = ROSE_DEFAULT_HB; +int sysctl_rose_routing_control = ROSE_DEFAULT_ROUTING; +int sysctl_rose_link_fail_timeout = ROSE_DEFAULT_FAIL_TIMEOUT; static unsigned int lci = 1; static struct sock *volatile rose_list = NULL; +static struct proto_ops rose_proto_ops; + +ax25_address rose_callsign; + /* * Convert a Rose address into text. */ @@ -92,10 +102,67 @@ int rosecmp(rose_address *addr1, rose_address *addr2) for (i = 0; i < 5; i++) if (addr1->rose_addr[i] != addr2->rose_addr[i]) return 1; - + + return 0; +} + +/* + * Compare two Rose addresses for only mask digits, 0 == equal. + */ +int rosecmpm(rose_address *addr1, rose_address *addr2, unsigned short mask) +{ + int i, j; + + if (mask > 10) + return 1; + + for (i = 0; i < mask; i++) { + j = i / 2; + + if ((i % 2) != 0) { + if ((addr1->rose_addr[j] & 0x0F) != (addr2->rose_addr[j] & 0x0F)) + return 1; + } else { + if ((addr1->rose_addr[j] & 0xF0) != (addr2->rose_addr[j] & 0xF0)) + return 1; + } + } + return 0; } +static void rose_free_sock(struct sock *sk) +{ + kfree_s(sk->protinfo.rose, sizeof(*sk->protinfo.rose)); + + sk_free(sk); + + MOD_DEC_USE_COUNT; +} + +static struct sock *rose_alloc_sock(void) +{ + struct sock *sk; + rose_cb *rose; + + if ((sk = sk_alloc(GFP_ATOMIC)) == NULL) + return NULL; + + if ((rose = (rose_cb *)kmalloc(sizeof(*rose), GFP_ATOMIC)) == NULL) { + sk_free(sk); + return NULL; + } + + MOD_INC_USE_COUNT; + + memset(rose, 0x00, sizeof(*rose)); + + sk->protinfo.rose = rose; + rose->sk = sk; + + return sk; +} + /* * Socket removal during an interrupt is now safe. */ @@ -103,7 +170,7 @@ static void rose_remove_socket(struct sock *sk) { struct sock *s; unsigned long flags; - + save_flags(flags); cli(); @@ -155,11 +222,11 @@ static int rose_device_event(struct notifier_block *this, unsigned long event, v if (event != NETDEV_DOWN) return NOTIFY_DONE; - + rose_kill_by_device(dev); rose_rt_device_down(dev); rose_link_device_down(dev); - + return NOTIFY_DONE; } @@ -173,8 +240,8 @@ static void rose_insert_socket(struct sock *sk) save_flags(flags); cli(); - sk->next = rose_list; - rose_list = sk; + sk->next = rose_list; + rose_list = sk; restore_flags(flags); } @@ -271,15 +338,15 @@ void rose_destroy_socket(struct sock *sk) /* Not static as it's used by the time { struct sk_buff *skb; unsigned long flags; - + save_flags(flags); cli(); - + del_timer(&sk->timer); - + rose_remove_socket(sk); rose_clear_queues(sk); /* Flush the queues */ - + while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) { if (skb->sk != sk) { /* A pending connection */ skb->sk->dead = 1; /* Queue the unaccepted socket for death */ @@ -289,16 +356,16 @@ void rose_destroy_socket(struct sock *sk) /* Not static as it's used by the time kfree_skb(skb, FREE_READ); } - - if (sk->wmem_alloc || sk->rmem_alloc) { /* Defer: outstanding buffers */ + + if (atomic_read(&sk->wmem_alloc) != 0 || atomic_read(&sk->rmem_alloc) != 0) { + /* Defer: outstanding buffers */ init_timer(&sk->timer); sk->timer.expires = jiffies + 10 * HZ; sk->timer.function = rose_destroy_timer; sk->timer.data = (unsigned long)sk; add_timer(&sk->timer); } else { - kfree_s(sk->protinfo.rose, sizeof(*sk->protinfo.rose)); - sk_free(sk); + rose_free_sock(sk); } restore_flags(flags); @@ -308,11 +375,6 @@ void rose_destroy_socket(struct sock *sk) /* Not static as it's used by the time * Handling for system calls applied via the various interfaces to a * Rose socket object. */ - -static int rose_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg) -{ - return -EINVAL; -} /* * dl1bke 960311: set parameters for existing Rose connections, @@ -352,21 +414,11 @@ static int rose_ctl_ioctl(const unsigned int cmd, void *arg) rose_set_timer(sk); break; - case ROSE_T0: - if (rose_ctl.arg < 1) - return -EINVAL; - if (sk->protinfo.rose->neighbour != NULL) { - save_flags(flags); cli(); - sk->protinfo.rose->neighbour->t0 = rose_ctl.arg * PR_SLOWHZ; - restore_flags(flags); - } - break; - case ROSE_T1: if (rose_ctl.arg < 1) return -EINVAL; save_flags(flags); cli(); - sk->protinfo.rose->t1 = rose_ctl.arg * PR_SLOWHZ; + sk->protinfo.rose->t1 = rose_ctl.arg * ROSE_SLOWHZ; restore_flags(flags); break; @@ -374,7 +426,7 @@ static int rose_ctl_ioctl(const unsigned int cmd, void *arg) if (rose_ctl.arg < 1) return -EINVAL; save_flags(flags); cli(); - sk->protinfo.rose->t2 = rose_ctl.arg * PR_SLOWHZ; + sk->protinfo.rose->t2 = rose_ctl.arg * ROSE_SLOWHZ; restore_flags(flags); break; @@ -382,7 +434,15 @@ static int rose_ctl_ioctl(const unsigned int cmd, void *arg) if (rose_ctl.arg < 1) return -EINVAL; save_flags(flags); cli(); - sk->protinfo.rose->t3 = rose_ctl.arg * PR_SLOWHZ; + sk->protinfo.rose->t3 = rose_ctl.arg * ROSE_SLOWHZ; + restore_flags(flags); + break; + + case ROSE_HOLDBACK: + if (rose_ctl.arg < 1) + return -EINVAL; + save_flags(flags); cli(); + sk->protinfo.rose->hb = rose_ctl.arg * ROSE_SLOWHZ; restore_flags(flags); break; @@ -390,7 +450,7 @@ static int rose_ctl_ioctl(const unsigned int cmd, void *arg) if (rose_ctl.arg < 1) return -EINVAL; save_flags(flags); cli(); - sk->protinfo.rose->idle = rose_ctl.arg * 60 * PR_SLOWHZ; + sk->protinfo.rose->idle = rose_ctl.arg * 60 * ROSE_SLOWHZ; restore_flags(flags); break; @@ -404,57 +464,49 @@ static int rose_ctl_ioctl(const unsigned int cmd, void *arg) static int rose_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen) { - struct sock *sk; - int err, opt; - - sk = (struct sock *)sock->data; - - if (level == SOL_SOCKET) - return sock_setsockopt(sk, level, optname, optval, optlen); + struct sock *sk = sock->sk; + int opt; if (level != SOL_ROSE) - return -EOPNOTSUPP; + return -ENOPROTOOPT; - if (optval == NULL) + if (optlen < sizeof(int)) return -EINVAL; - if ((err = verify_area(VERIFY_READ, optval, sizeof(int))) != 0) - return err; + if (get_user(opt, (int *)optval)) + return -EFAULT; - get_user(opt, (int *)optval); - switch (optname) { - case ROSE_T0: + case ROSE_T1: if (opt < 1) return -EINVAL; - if (sk->protinfo.rose->neighbour != NULL) - sk->protinfo.rose->neighbour->t0 = opt * PR_SLOWHZ; + sk->protinfo.rose->t1 = opt * ROSE_SLOWHZ; return 0; - case ROSE_T1: + case ROSE_T2: if (opt < 1) return -EINVAL; - sk->protinfo.rose->t1 = opt * PR_SLOWHZ; + sk->protinfo.rose->t2 = opt * ROSE_SLOWHZ; return 0; - case ROSE_T2: + case ROSE_T3: if (opt < 1) return -EINVAL; - sk->protinfo.rose->t2 = opt * PR_SLOWHZ; + sk->protinfo.rose->t3 = opt * ROSE_SLOWHZ; return 0; - - case ROSE_T3: + + case ROSE_HOLDBACK: if (opt < 1) return -EINVAL; - sk->protinfo.rose->t3 = opt * PR_SLOWHZ; + sk->protinfo.rose->hb = opt * ROSE_SLOWHZ; return 0; - + case ROSE_IDLE: if (opt < 1) return -EINVAL; - sk->protinfo.rose->idle = opt * 60 * PR_SLOWHZ; + sk->protinfo.rose->idle = opt * 60 * ROSE_SLOWHZ; return 0; - + case ROSE_HDRINCL: sk->protinfo.rose->hdrincl = opt ? 1 : 0; return 0; @@ -467,42 +519,37 @@ static int rose_setsockopt(struct socket *sock, int level, int optname, static int rose_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen) { - struct sock *sk; + struct sock *sk = sock->sk; int val = 0; - int err; + int len; - sk = (struct sock *)sock->data; - - if (level == SOL_SOCKET) - return sock_getsockopt(sk, level, optname, optval, optlen); - if (level != SOL_ROSE) - return -EOPNOTSUPP; + return -ENOPROTOOPT; + + if (get_user(len, optlen)) + return -EFAULT; switch (optname) { - case ROSE_T0: - if (sk->protinfo.rose->neighbour != NULL) - val = sk->protinfo.rose->neighbour->t0 / PR_SLOWHZ; - else - val = sysctl_rose_restart_request_timeout / PR_SLOWHZ; - break; - case ROSE_T1: - val = sk->protinfo.rose->t1 / PR_SLOWHZ; + val = sk->protinfo.rose->t1 / ROSE_SLOWHZ; break; - + case ROSE_T2: - val = sk->protinfo.rose->t2 / PR_SLOWHZ; + val = sk->protinfo.rose->t2 / ROSE_SLOWHZ; break; - + case ROSE_T3: - val = sk->protinfo.rose->t3 / PR_SLOWHZ; + val = sk->protinfo.rose->t3 / ROSE_SLOWHZ; break; - + + case ROSE_HOLDBACK: + val = sk->protinfo.rose->hb / ROSE_SLOWHZ; + break; + case ROSE_IDLE: - val = sk->protinfo.rose->idle / (PR_SLOWHZ * 60); + val = sk->protinfo.rose->idle / (ROSE_SLOWHZ * 60); break; - + case ROSE_HDRINCL: val = sk->protinfo.rose->hdrincl; break; @@ -511,22 +558,20 @@ static int rose_getsockopt(struct socket *sock, int level, int optname, return -ENOPROTOOPT; } - if ((err = verify_area(VERIFY_WRITE, optlen, sizeof(int))) != 0) - return err; - - put_user(sizeof(int), (unsigned long *)optlen); + len = min(len, sizeof(int)); - if ((err = verify_area(VERIFY_WRITE, optval, sizeof(int))) != 0) - return err; + if (put_user(len, optlen)) + return -EFAULT; - put_user(val, (unsigned long *)optval); + if (copy_to_user(optval, &val, len)) + return -EFAULT; return 0; } static int rose_listen(struct socket *sock, int backlog) { - struct sock *sk = (struct sock *)sock->data; + struct sock *sk = sock->sk; if (sk->state != TCP_LISTEN) { sk->protinfo.rose->dest_ndigis = 0; @@ -541,18 +586,6 @@ static int rose_listen(struct socket *sock, int backlog) return -EOPNOTSUPP; } -static void def_callback1(struct sock *sk) -{ - if (!sk->dead) - wake_up_interruptible(sk->sleep); -} - -static void def_callback2(struct sock *sk, int len) -{ - if (!sk->dead) - wake_up_interruptible(sk->sleep); -} - static int rose_create(struct socket *sock, int protocol) { struct sock *sk; @@ -561,77 +594,26 @@ static int rose_create(struct socket *sock, int protocol) if (sock->type != SOCK_SEQPACKET || protocol != 0) return -ESOCKTNOSUPPORT; - if ((sk = sk_alloc(GFP_ATOMIC)) == NULL) + if ((sk = rose_alloc_sock()) == NULL) return -ENOMEM; - if ((rose = (rose_cb *)kmalloc(sizeof(*rose), GFP_ATOMIC)) == NULL) { - sk_free(sk); - return -ENOMEM; - } + rose = sk->protinfo.rose; - skb_queue_head_init(&sk->receive_queue); - skb_queue_head_init(&sk->write_queue); - skb_queue_head_init(&sk->back_log); - - init_timer(&sk->timer); - - sk->socket = sock; - sk->type = sock->type; - sk->protocol = protocol; - sk->allocation = GFP_KERNEL; - sk->rcvbuf = SK_RMEM_MAX; - sk->sndbuf = SK_WMEM_MAX; - sk->state = TCP_CLOSE; - sk->priority = SOPRI_NORMAL; - sk->mtu = ROSE_MTU; /* 128 */ - sk->zapped = 1; - sk->window = ROSE_DEFAULT_WINDOW; - - sk->state_change = def_callback1; - sk->data_ready = def_callback2; - sk->write_space = def_callback1; - sk->error_report = def_callback1; - - if (sock != NULL) { - sock->data = (void *)sk; - sk->sleep = sock->wait; - } + sock_init_data(sock, sk); + + sock->ops = &rose_proto_ops; + sk->protocol = protocol; + sk->mtu = ROSE_MTU; /* 128 */ - skb_queue_head_init(&rose->ack_queue); skb_queue_head_init(&rose->frag_queue); - rose->lci = 0; - - rose->t1 = sysctl_rose_call_request_timeout; - rose->t2 = sysctl_rose_reset_request_timeout; - rose->t3 = sysctl_rose_clear_request_timeout; - rose->idle = sysctl_rose_no_activity_timeout; - - rose->timer = 0; - - rose->va = 0; - rose->vr = 0; - rose->vs = 0; - rose->vl = 0; + rose->t1 = sysctl_rose_call_request_timeout; + rose->t2 = sysctl_rose_reset_request_timeout; + rose->t3 = sysctl_rose_clear_request_timeout; + rose->hb = sysctl_rose_ack_hold_back_timeout; + rose->idle = sysctl_rose_no_activity_timeout; - rose->fraglen = 0; - rose->hdrincl = 0; - rose->state = ROSE_STATE_0; - rose->neighbour = NULL; - rose->device = NULL; - - rose->source_ndigis = 0; - rose->dest_ndigis = 0; - - memset(&rose->source_addr, '\0', ROSE_ADDR_LEN); - memset(&rose->dest_addr, '\0', ROSE_ADDR_LEN); - memset(&rose->source_call, '\0', AX25_ADDR_LEN); - memset(&rose->dest_call, '\0', AX25_ADDR_LEN); - memset(&rose->source_digi, '\0', AX25_ADDR_LEN); - memset(&rose->dest_digi, '\0', AX25_ADDR_LEN); - - rose->sk = sk; - sk->protinfo.rose = rose; + rose->state = ROSE_STATE_0; return 0; } @@ -644,73 +626,52 @@ static struct sock *rose_make_new(struct sock *osk) if (osk->type != SOCK_SEQPACKET) return NULL; - if ((sk = (struct sock *)sk_alloc(GFP_ATOMIC)) == NULL) + if ((sk = rose_alloc_sock()) == NULL) return NULL; - if ((rose = (rose_cb *)kmalloc(sizeof(*rose), GFP_ATOMIC)) == NULL) { - sk_free(sk); - return NULL; - } + rose = sk->protinfo.rose; - skb_queue_head_init(&sk->receive_queue); - skb_queue_head_init(&sk->write_queue); - skb_queue_head_init(&sk->back_log); - - init_timer(&sk->timer); - - sk->type = osk->type; - sk->socket = osk->socket; - sk->priority = osk->priority; - sk->protocol = osk->protocol; - sk->rcvbuf = osk->rcvbuf; - sk->sndbuf = osk->sndbuf; - sk->debug = osk->debug; - sk->state = TCP_ESTABLISHED; - sk->window = osk->window; - sk->mtu = osk->mtu; - sk->sleep = osk->sleep; - sk->zapped = osk->zapped; - - sk->state_change = def_callback1; - sk->data_ready = def_callback2; - sk->write_space = def_callback1; - sk->error_report = def_callback1; - - skb_queue_head_init(&rose->ack_queue); - skb_queue_head_init(&rose->frag_queue); + sock_init_data(NULL, sk); - rose->t1 = osk->protinfo.rose->t1; - rose->t2 = osk->protinfo.rose->t2; - rose->t3 = osk->protinfo.rose->t3; - rose->idle = osk->protinfo.rose->idle; + sk->type = osk->type; + sk->socket = osk->socket; + sk->priority = osk->priority; + sk->protocol = osk->protocol; + sk->rcvbuf = osk->rcvbuf; + sk->sndbuf = osk->sndbuf; + sk->debug = osk->debug; + sk->state = TCP_ESTABLISHED; + sk->mtu = osk->mtu; + sk->sleep = osk->sleep; + sk->zapped = osk->zapped; - rose->device = osk->protinfo.rose->device; - rose->hdrincl = osk->protinfo.rose->hdrincl; - rose->fraglen = 0; + skb_queue_head_init(&rose->frag_queue); - rose->timer = 0; + rose->t1 = osk->protinfo.rose->t1; + rose->t2 = osk->protinfo.rose->t2; + rose->t3 = osk->protinfo.rose->t3; + rose->hb = osk->protinfo.rose->hb; + rose->idle = osk->protinfo.rose->idle; - rose->va = 0; - rose->vr = 0; - rose->vs = 0; - rose->vl = 0; - - sk->protinfo.rose = rose; - rose->sk = sk; + rose->device = osk->protinfo.rose->device; + rose->hdrincl = osk->protinfo.rose->hdrincl; return sk; } static int rose_dup(struct socket *newsock, struct socket *oldsock) { - struct sock *sk = (struct sock *)oldsock->data; + struct sock *sk = oldsock->sk; + + if (sk == NULL || newsock == NULL) + return -EINVAL; return rose_create(newsock, sk->protocol); } static int rose_release(struct socket *sock, struct socket *peer) { - struct sock *sk = (struct sock *)sock->data; + struct sock *sk = sock->sk; if (sk == NULL) return 0; @@ -724,15 +685,6 @@ static int rose_release(struct socket *sock, struct socket *peer) rose_destroy_socket(sk); break; - case ROSE_STATE_1: - sk->protinfo.rose->state = ROSE_STATE_0; - sk->state = TCP_CLOSE; - sk->shutdown |= SEND_SHUTDOWN; - sk->state_change(sk); - sk->dead = 1; - rose_destroy_socket(sk); - break; - case ROSE_STATE_2: sk->protinfo.rose->state = ROSE_STATE_0; sk->state = TCP_CLOSE; @@ -742,6 +694,7 @@ static int rose_release(struct socket *sock, struct socket *peer) rose_destroy_socket(sk); break; + case ROSE_STATE_1: case ROSE_STATE_3: case ROSE_STATE_4: rose_clear_queues(sk); @@ -759,7 +712,7 @@ static int rose_release(struct socket *sock, struct socket *peer) break; } - sock->data = NULL; + sock->sk = NULL; sk->socket = NULL; /* Not used, but we should do this. **/ return 0; @@ -767,22 +720,22 @@ static int rose_release(struct socket *sock, struct socket *peer) static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { - struct sock *sk; + struct sock *sk = sock->sk; struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr; struct device *dev; ax25_address *user, *source; - - sk = (struct sock *)sock->data; if (sk->zapped == 0) return -EINVAL; - + if (addr_len != sizeof(struct sockaddr_rose)) return -EINVAL; + if (addr->srose_family != AF_ROSE) + return -EINVAL; + if ((dev = rose_dev_get(&addr->srose_addr)) == NULL) { - if (sk->debug) - printk("Rose: bind failed: invalid address\n"); + SOCK_DEBUG(sk, "Rose: bind failed: invalid address\n"); return -EADDRNOTAVAIL; } @@ -806,39 +759,39 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) rose_insert_socket(sk); sk->zapped = 0; - - if (sk->debug) - printk("Rose: socket is bound\n"); - + SOCK_DEBUG(sk, "Rose: socket is bound\n"); return 0; } static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags) { - struct sock *sk = (struct sock *)sock->data; + struct sock *sk = sock->sk; struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr; ax25_address *user; struct device *dev; - + if (sk->state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) { sock->state = SS_CONNECTED; return 0; /* Connect completed during a ERESTARTSYS event */ } - + if (sk->state == TCP_CLOSE && sock->state == SS_CONNECTING) { sock->state = SS_UNCONNECTED; return -ECONNREFUSED; } - + if (sk->state == TCP_ESTABLISHED) return -EISCONN; /* No reconnect on a seqpacket socket */ - - sk->state = TCP_CLOSE; + + sk->state = TCP_CLOSE; sock->state = SS_UNCONNECTED; if (addr_len != sizeof(struct sockaddr_rose)) return -EINVAL; + if (addr->srose_family != AF_ROSE) + return -EINVAL; + if ((sk->protinfo.rose->neighbour = rose_get_neigh(&addr->srose_addr)) == NULL) return -ENETUNREACH; @@ -875,11 +828,11 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le rose_write_internal(sk, ROSE_CALL_REQUEST); rose_set_timer(sk); - + /* Now the loop */ if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) return -EINPROGRESS; - + cli(); /* To avoid races on the sleep */ /* @@ -898,14 +851,14 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le sock->state = SS_UNCONNECTED; return sock_error(sk); /* Always set at this point */ } - + sock->state = SS_CONNECTED; sti(); - + return 0; } - + static int rose_socketpair(struct socket *sock1, struct socket *sock2) { return -EOPNOTSUPP; @@ -917,19 +870,20 @@ static int rose_accept(struct socket *sock, struct socket *newsock, int flags) struct sock *newsk; struct sk_buff *skb; - if (newsock->data) - sk_free(newsock->data); + if (newsock->sk != NULL) + rose_destroy_socket(newsock->sk); - newsock->data = NULL; - - sk = (struct sock *)sock->data; + newsock->sk = NULL; + + if ((sk = sock->sk) == NULL) + return -EINVAL; if (sk->type != SOCK_SEQPACKET) return -EOPNOTSUPP; - + if (sk->state != TCP_LISTEN) return -EINVAL; - + /* * The write queue this time is holding sockets ready to use * hooked into the SABM we saved @@ -939,7 +893,7 @@ static int rose_accept(struct socket *sock, struct socket *newsock, int flags) if ((skb = skb_dequeue(&sk->receive_queue)) == NULL) { if (flags & O_NONBLOCK) { sti(); - return 0; + return -EWOULDBLOCK; } interruptible_sleep_on(sk->sleep); if (current->signal & ~current->blocked) { @@ -957,7 +911,7 @@ static int rose_accept(struct socket *sock, struct socket *newsock, int flags) skb->sk = NULL; kfree_skb(skb, FREE_READ); sk->ack_backlog--; - newsock->data = newsk; + newsock->sk = newsk; return 0; } @@ -966,10 +920,8 @@ static int rose_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer) { struct sockaddr_rose *srose = (struct sockaddr_rose *)uaddr; - struct sock *sk; - - sk = (struct sock *)sock->data; - + struct sock *sk = sock->sk; + if (peer != 0) { if (sk->state != TCP_ESTABLISHED) return -ENOTCONN; @@ -996,11 +948,11 @@ static int rose_getname(struct socket *sock, struct sockaddr *uaddr, return 0; } - + int rose_rx_call_request(struct sk_buff *skb, struct device *dev, struct rose_neigh *neigh, unsigned int lci) { struct sock *sk; - struct sock *make; + struct sock *make; rose_cb rose; skb->sk = NULL; /* Initially we don't know who it's for */ @@ -1015,7 +967,7 @@ int rose_rx_call_request(struct sk_buff *skb, struct device *dev, struct rose_ne if (!rose_parse_facilities(skb, &rose)) { return 0; } - + sk = rose_find_listener(&rose.source_call); /* @@ -1040,7 +992,7 @@ int rose_rx_call_request(struct sk_buff *skb, struct device *dev, struct rose_ne make->protinfo.rose->source_digi = rose.source_digi; make->protinfo.rose->neighbour = neigh; make->protinfo.rose->device = dev; - + rose_write_internal(make, ROSE_CALL_ACCEPTED); make->protinfo.rose->condition = 0x00; @@ -1064,20 +1016,18 @@ int rose_rx_call_request(struct sk_buff *skb, struct device *dev, struct rose_ne return 1; } -static int rose_sendmsg(struct socket *sock, struct msghdr *msg, int len, int noblock, int flags) +static int rose_sendmsg(struct socket *sock, struct msghdr *msg, int len, + struct scm_cookie *scm) { - struct sock *sk = (struct sock *)sock->data; + struct sock *sk = sock->sk; struct sockaddr_rose *usrose = (struct sockaddr_rose *)msg->msg_name; int err; struct sockaddr_rose srose; struct sk_buff *skb; unsigned char *asmptr; int size; - - if (sk->err) - return sock_error(sk); - if (flags) + if (msg->msg_flags & ~MSG_DONTWAIT) return -EINVAL; if (sk->zapped) @@ -1090,8 +1040,8 @@ static int rose_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no if (sk->protinfo.rose->device == NULL) return -ENETUNREACH; - - if (usrose) { + + if (usrose != NULL) { if (msg->msg_namelen < sizeof(srose)) return -EINVAL; srose = *usrose; @@ -1118,42 +1068,30 @@ static int rose_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no srose.srose_digi = sk->protinfo.rose->dest_digi; } } - - if (sk->debug) - printk("Rose: sendto: Addresses built.\n"); + SOCK_DEBUG(sk, "Rose: sendto: Addresses built.\n"); /* Build a packet */ - if (sk->debug) - printk("Rose: sendto: building packet.\n"); - + SOCK_DEBUG(sk, "Rose: sendto: building packet.\n"); size = len + AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN; - if ((skb = sock_alloc_send_skb(sk, size, 0, 0, &err)) == NULL) + if ((skb = sock_alloc_send_skb(sk, size, 0, msg->msg_flags & MSG_DONTWAIT, &err)) == NULL) return err; - skb->sk = sk; - skb->free = 1; - skb->arp = 1; - skb_reserve(skb, size - len); - + /* * Push down the Rose header */ asmptr = skb_push(skb, ROSE_MIN_LEN); - - if (sk->debug) - printk("Building Rose Header.\n"); + SOCK_DEBUG(sk, "Building Rose Header.\n"); /* Build a Rose Transport header */ - *asmptr++ = ((sk->protinfo.rose->lci >> 8) & 0x0F) | GFI; + *asmptr++ = ((sk->protinfo.rose->lci >> 8) & 0x0F) | ROSE_GFI; *asmptr++ = (sk->protinfo.rose->lci >> 0) & 0xFF; *asmptr++ = ROSE_DATA; - - if (sk->debug) - printk("Built header.\n"); + SOCK_DEBUG(sk, "Built header.\n"); /* * Put the data on the end @@ -1162,15 +1100,11 @@ static int rose_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no skb->h.raw = skb_put(skb, len); asmptr = skb->h.raw; - - if (sk->debug) - printk("Rose: Appending user data\n"); + SOCK_DEBUG(sk, "Rose: Appending user data\n"); /* User data follows immediately after the Rose transport header */ memcpy_fromiovec(asmptr, msg->msg_iov, len); - - if (sk->debug) - printk("Rose: Transmitting buffer\n"); + SOCK_DEBUG(sk, "Rose: Transmitting buffer\n"); if (sk->state != TCP_ESTABLISHED) { kfree_skb(skb, FREE_WRITE); @@ -1183,18 +1117,15 @@ static int rose_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no } -static int rose_recvmsg(struct socket *sock, struct msghdr *msg, int size, int noblock, - int flags, int *addr_len) +static int rose_recvmsg(struct socket *sock, struct msghdr *msg, int size, + int flags, struct scm_cookie *scm) { - struct sock *sk = (struct sock *)sock->data; + struct sock *sk = sock->sk; struct sockaddr_rose *srose = (struct sockaddr_rose *)msg->msg_name; int copied; struct sk_buff *skb; int er; - if (addr_len != NULL) - *addr_len = sizeof(*srose); - /* * This works for seqpacket too. The receiver has ordered the queue for * us! We do one quick check first though @@ -1203,7 +1134,7 @@ static int rose_recvmsg(struct socket *sock, struct msghdr *msg, int size, int n return -ENOTCONN; /* Now we can treat all alike */ - if ((skb = skb_recv_datagram(sk, flags, noblock, &er)) == NULL) + if ((skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, flags & MSG_DONTWAIT, &er)) == NULL) return er; if (!sk->protinfo.rose->hdrincl) { @@ -1212,32 +1143,28 @@ static int rose_recvmsg(struct socket *sock, struct msghdr *msg, int size, int n } copied = skb->len; - + if (copied > size) { copied = size; msg->msg_flags |= MSG_TRUNC; } - + skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); - + if (srose != NULL) { - struct sockaddr_rose addr; - - addr.srose_family = AF_ROSE; - addr.srose_addr = sk->protinfo.rose->dest_addr; - addr.srose_call = sk->protinfo.rose->dest_call; - addr.srose_ndigis = 0; + srose->srose_family = AF_ROSE; + srose->srose_addr = sk->protinfo.rose->dest_addr; + srose->srose_call = sk->protinfo.rose->dest_call; + srose->srose_ndigis = 0; if (sk->protinfo.rose->dest_ndigis == 1) { - addr.srose_ndigis = 1; - addr.srose_digi = sk->protinfo.rose->dest_digi; + srose->srose_ndigis = 1; + srose->srose_digi = sk->protinfo.rose->dest_digi; } - - *srose = addr; - - *addr_len = sizeof(*srose); } + msg->msg_namelen = sizeof(struct sockaddr_rose); + skb_free_datagram(sk, skb); return copied; @@ -1248,16 +1175,9 @@ static int rose_shutdown(struct socket *sk, int how) return -EOPNOTSUPP; } -static int rose_select(struct socket *sock , int sel_type, select_table *wait) -{ - struct sock *sk = (struct sock *)sock->data; - - return datagram_select(sk, sel_type, wait); -} - static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { - struct sock *sk = (struct sock *)sock->data; + struct sock *sk = sock->sk; int err; long amount = 0; @@ -1265,7 +1185,7 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case TIOCOUTQ: if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(unsigned int))) != 0) return err; - amount = sk->sndbuf - sk->wmem_alloc; + amount = sk->sndbuf - atomic_read(&sk->wmem_alloc); if (amount < 0) amount = 0; put_user(amount, (unsigned int *)arg); @@ -1310,11 +1230,22 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) if (!suser()) return -EPERM; return rose_rt_ioctl(cmd, (void *)arg); - case SIOCRSCTLCON: + case SIOCRSCTLCON: if (!suser()) return -EPERM; return rose_ctl_ioctl(cmd, (void *)arg); - - default: + + case SIOCRSL2CALL: + if (!suser()) return -EPERM; + if ((err = verify_area(VERIFY_READ, (void *)arg, sizeof(ax25_address))) != 0) + return err; + if (ax25cmp(&rose_callsign, &null_ax25_address) != 0) + ax25_listen_release(&rose_callsign, NULL); + copy_from_user(&rose_callsign, (void *)arg, sizeof(ax25_address)); + if (ax25cmp(&rose_callsign, &null_ax25_address) != 0) + ax25_listen_register(&rose_callsign, NULL); + return 0; + + default: return dev_ioctl(cmd, (void *)arg); } @@ -1330,10 +1261,10 @@ static int rose_get_info(char *buffer, char **start, off_t offset, int length, i int len = 0; off_t pos = 0; off_t begin = 0; - + cli(); - len += sprintf(buffer, "dest_addr dest_call dest_digi src_addr src_call src_digi dev lci st vs vr va t t1 t2 t3 Snd-Q Rcv-Q\n"); + len += sprintf(buffer, "dest_addr dest_call src_addr src_call dev lci st vs vr va t t1 t2 t3 hb Snd-Q Rcv-Q\n"); for (s = rose_list; s != NULL; s = s->next) { if ((dev = s->protinfo.rose->device) == NULL) @@ -1344,35 +1275,31 @@ static int rose_get_info(char *buffer, char **start, off_t offset, int length, i len += sprintf(buffer + len, "%-10s %-9s ", rose2asc(&s->protinfo.rose->dest_addr), ax2asc(&s->protinfo.rose->dest_call)); - len += sprintf(buffer + len, "%-9s ", - ax2asc(&s->protinfo.rose->dest_digi)); if (ax25cmp(&s->protinfo.rose->source_call, &null_ax25_address) == 0) callsign = "??????-?"; else callsign = ax2asc(&s->protinfo.rose->source_call); - len += sprintf(buffer + len, "%-10s %-9s ", - rose2asc(&s->protinfo.rose->source_addr), - callsign); - len += sprintf(buffer + len, "%-9s %-5s %3.3X %d %d %d %d %3d %3d %3d %3d %5d %5d\n", - ax2asc(&s->protinfo.rose->source_digi), + len += sprintf(buffer + len, "%-10s %-9s %-5s %3.3X %d %d %d %d %3d %3d %3d %3d %3d %5d %5d\n", + rose2asc(&s->protinfo.rose->source_addr), callsign, devname, s->protinfo.rose->lci & 0x0FFF, s->protinfo.rose->state, s->protinfo.rose->vs, s->protinfo.rose->vr, s->protinfo.rose->va, - s->protinfo.rose->timer / PR_SLOWHZ, - s->protinfo.rose->t1 / PR_SLOWHZ, - s->protinfo.rose->t2 / PR_SLOWHZ, - s->protinfo.rose->t3 / PR_SLOWHZ, - s->wmem_alloc, s->rmem_alloc); - + s->protinfo.rose->timer / ROSE_SLOWHZ, + s->protinfo.rose->t1 / ROSE_SLOWHZ, + s->protinfo.rose->t2 / ROSE_SLOWHZ, + s->protinfo.rose->t3 / ROSE_SLOWHZ, + s->protinfo.rose->hb / ROSE_SLOWHZ, + atomic_read(&s->wmem_alloc), atomic_read(&s->rmem_alloc)); + pos = begin + len; if (pos < offset) { len = 0; begin = pos; } - + if (pos > offset + length) break; } @@ -1387,10 +1314,14 @@ static int rose_get_info(char *buffer, char **start, off_t offset, int length, i return(len); } -struct proto_ops rose_proto_ops = { +static struct net_proto_family rose_family_ops = { AF_ROSE, - - rose_create, + rose_create +}; + +static struct proto_ops rose_proto_ops = { + AF_ROSE, + rose_dup, rose_release, rose_bind, @@ -1398,62 +1329,132 @@ struct proto_ops rose_proto_ops = { rose_socketpair, rose_accept, rose_getname, - rose_select, + datagram_poll, rose_ioctl, rose_listen, rose_shutdown, rose_setsockopt, rose_getsockopt, - rose_fcntl, + sock_no_fcntl, rose_sendmsg, rose_recvmsg }; -struct notifier_block rose_dev_notifier = { +static struct notifier_block rose_dev_notifier = { rose_device_event, 0 }; +#ifdef CONFIG_PROC_FS +static struct proc_dir_entry proc_net_rose = { + PROC_NET_RS, 4, "rose", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_net_inode_operations, + rose_get_info +}; +static struct proc_dir_entry proc_net_rose_neigh = { + PROC_NET_RS_NEIGH, 10, "rose_neigh", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_net_inode_operations, + rose_neigh_get_info +}; +static struct proc_dir_entry proc_net_rose_nodes = { + PROC_NET_RS_NODES, 10, "rose_nodes", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_net_inode_operations, + rose_nodes_get_info +}; +static struct proc_dir_entry proc_net_rose_routes = { + PROC_NET_RS_ROUTES, 11, "rose_routes", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_net_inode_operations, + rose_routes_get_info +}; +#endif + +static struct device dev_rose[] = { + {"rose0", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, rose_init}, + {"rose1", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, rose_init}, + {"rose2", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, rose_init}, + {"rose3", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, rose_init}, + {"rose4", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, rose_init}, + {"rose5", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, rose_init} +}; + void rose_proto_init(struct net_proto *pro) { - sock_register(rose_proto_ops.family, &rose_proto_ops); + int i; + + rose_callsign = null_ax25_address; + + sock_register(&rose_family_ops); register_netdevice_notifier(&rose_dev_notifier); - printk(KERN_INFO "G4KLX Rose for Linux. Version 0.1 for AX25.034 Linux 2.1\n"); + printk(KERN_INFO "G4KLX Rose for Linux. Version 0.1 for AX25.035 Linux 2.1\n"); if (!ax25_protocol_register(AX25_P_ROSE, rose_route_frame)) printk(KERN_ERR "Rose unable to register protocol with AX.25\n"); if (!ax25_linkfail_register(rose_link_failed)) printk(KERN_ERR "Rose unable to register linkfail handler with AX.25\n"); + for (i = 0; i < 6; i++) + register_netdev(&dev_rose[i]); + +#ifdef CONFIG_SYSCTL rose_register_sysctl(); +#endif #ifdef CONFIG_PROC_FS - proc_net_register(&(struct proc_dir_entry) { - PROC_NET_RS, 4, "rose", - S_IFREG | S_IRUGO, 1, 0, 0, - 0, &proc_net_inode_operations, - rose_get_info - }); - proc_net_register(&(struct proc_dir_entry) { - PROC_NET_RS_NEIGH, 10, "rose_neigh", - S_IFREG | S_IRUGO, 1, 0, 0, - 0, &proc_net_inode_operations, - rose_neigh_get_info - }); - proc_net_register(&(struct proc_dir_entry) { - PROC_NET_RS_NODES, 10, "rose_nodes", - S_IFREG | S_IRUGO, 1, 0, 0, - 0, &proc_net_inode_operations, - rose_nodes_get_info - }); - - proc_net_register(&(struct proc_dir_entry) { - PROC_NET_RS_ROUTES, 11, "rose_routes", - S_IFREG | S_IRUGO, 1, 0, 0, - 0, &proc_net_inode_operations, - rose_routes_get_info - }); -#endif + proc_net_register(&proc_net_rose); + proc_net_register(&proc_net_rose_neigh); + proc_net_register(&proc_net_rose_nodes); + proc_net_register(&proc_net_rose_routes); +#endif +} + +#ifdef MODULE +EXPORT_NO_SYMBOLS; + +int init_module(void) +{ + rose_proto_init(NULL); + + return 0; } +void cleanup_module(void) +{ + int i; + +#ifdef CONFIG_PROC_FS + proc_net_unregister(PROC_NET_RS); + proc_net_unregister(PROC_NET_RS_NEIGH); + proc_net_unregister(PROC_NET_RS_NODES); + proc_net_unregister(PROC_NET_RS_ROUTES); +#endif + rose_rt_free(); + + ax25_protocol_release(AX25_P_ROSE); + ax25_linkfail_release(rose_link_failed); + + if (ax25cmp(&rose_callsign, &null_ax25_address) != 0) + ax25_listen_release(&rose_callsign, NULL); + +#ifdef CONFIG_SYSCTL + rose_unregister_sysctl(); +#endif + unregister_netdevice_notifier(&rose_dev_notifier); + + sock_unregister(AF_ROSE); + + for (i = 0; i < 6; i++) { + if (dev_rose[i].priv != NULL) { + kfree(dev_rose[i].priv); + dev_rose[i].priv = NULL; + unregister_netdev(&dev_rose[i]); + } + } +} + +#endif + #endif diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c index 7fe6a00e6..ebab50e0d 100644 --- a/net/rose/rose_dev.c +++ b/net/rose/rose_dev.c @@ -1,10 +1,10 @@ /* * Rose release 001 * - * This is ALPHA test software. This code may break your machine, randomly fail to work with new - * releases, misbehave and/or generally screw up. It might even work. + * This is ALPHA test software. This code may break your machine, randomly fail to work with new + * releases, misbehave and/or generally screw up. It might even work. * - * This code REQUIRES 2.1.0 or higher/ NET3.029 + * This code REQUIRES 2.1.15 or higher/ NET3.038 * * This module: * This module is free software; you can redistribute it and/or @@ -14,10 +14,12 @@ * * History * Rose 001 Jonathan(G4KLX) Cloned from nr_dev.c. + * Hans(PE1AYX) Fixed interface to IP layer. */ #include <linux/config.h> #if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE) +#define __NO_VERSION__ #include <linux/module.h> #include <linux/proc_fs.h> #include <linux/kernel.h> @@ -55,7 +57,7 @@ int rose_rx_ip(struct sk_buff *skb, struct device *dev) { - struct enet_statistics *stats = (struct enet_statistics *)dev->priv; + struct net_device_stats *stats = (struct net_device_stats *)dev->priv; if (!dev->start) { stats->rx_errors++; @@ -63,12 +65,16 @@ int rose_rx_ip(struct sk_buff *skb, struct device *dev) } stats->rx_packets++; + stats->rx_bytes += skb->len; + skb->protocol = htons(ETH_P_IP); /* Spoof incoming device */ - skb->dev = dev; + skb->dev = dev; + skb->h.raw = skb->data; + skb->nh.raw = skb->data; + skb->pkt_type = PACKET_HOST; - skb->h.raw = skb->data; ip_rcv(skb, skb->dev, NULL); return 1; @@ -79,7 +85,7 @@ static int rose_header(struct sk_buff *skb, struct device *dev, unsigned short t { unsigned char *buff = skb_push(skb, ROSE_MIN_LEN + 2); - *buff++ = GFI | Q_BIT; + *buff++ = ROSE_GFI | ROSE_Q_BIT; *buff++ = 0x00; *buff++ = ROSE_DATA; *buff++ = 0x7F; @@ -87,40 +93,39 @@ static int rose_header(struct sk_buff *skb, struct device *dev, unsigned short t if (daddr != NULL) return 37; - - return -37; + + return -37; } -static int rose_rebuild_header(void *buff, struct device *dev, - unsigned long raddr, struct sk_buff *skb) +static int rose_rebuild_header(struct sk_buff *skb) { - struct enet_statistics *stats = (struct enet_statistics *)dev->priv; - unsigned char *bp = (unsigned char *)buff; + struct device *dev = skb->dev; + struct net_device_stats *stats = (struct net_device_stats *)dev->priv; + unsigned char *bp = (unsigned char *)skb->data; struct sk_buff *skbn; - if (!arp_query(bp + 7, raddr, dev)) { - dev_kfree_skb(skb, FREE_WRITE); + if (!arp_find(bp + 7, skb)) { + kfree_skb(skb, FREE_WRITE); return 1; } if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) { - dev_kfree_skb(skb, FREE_WRITE); + kfree_skb(skb, FREE_WRITE); return 1; } - skbn->sk = skb->sk; - - if (skbn->sk != NULL) - atomic_add(skbn->truesize, &skbn->sk->wmem_alloc); + if (skb->sk != NULL) + skb_set_owner_w(skbn, skb->sk); - dev_kfree_skb(skb, FREE_WRITE); + kfree_skb(skb, FREE_WRITE); if (!rose_route_frame(skbn, NULL)) { - dev_kfree_skb(skbn, FREE_WRITE); + kfree_skb(skbn, FREE_WRITE); stats->tx_errors++; } stats->tx_packets++; + stats->tx_bytes += skbn->len; return 1; } @@ -132,7 +137,7 @@ static int rose_set_mac_address(struct device *dev, void *addr) ax25_listen_release((ax25_address *)dev->dev_addr, NULL); memcpy(dev->dev_addr, sa->sa_data, dev->addr_len); - + ax25_listen_register((ax25_address *)dev->dev_addr, NULL); return 0; @@ -155,16 +160,16 @@ static int rose_close(struct device *dev) dev->tbusy = 1; dev->start = 0; - ax25_listen_release((ax25_address *)dev->dev_addr, NULL); - MOD_DEC_USE_COUNT; + ax25_listen_release((ax25_address *)dev->dev_addr, NULL); + return 0; } static int rose_xmit(struct sk_buff *skb, struct device *dev) { - struct enet_statistics *stats = (struct enet_statistics *)dev->priv; + struct net_device_stats *stats = (struct net_device_stats *)dev->priv; if (skb == NULL || dev == NULL) return 0; @@ -186,7 +191,7 @@ static int rose_xmit(struct sk_buff *skb, struct device *dev) sti(); - dev_kfree_skb(skb, FREE_WRITE); + kfree_skb(skb, FREE_WRITE); stats->tx_errors++; @@ -197,16 +202,14 @@ static int rose_xmit(struct sk_buff *skb, struct device *dev) return 0; } -static struct enet_statistics *rose_get_stats(struct device *dev) +static struct net_device_stats *rose_get_stats(struct device *dev) { - return (struct enet_statistics *)dev->priv; + return (struct net_device_stats *)dev->priv; } int rose_init(struct device *dev) { - int i; - - dev->mtu = ROSE_PACLEN - 2; + dev->mtu = ROSE_MAX_PACKET_SIZE - 2; dev->tbusy = 0; dev->hard_start_xmit = rose_xmit; dev->open = rose_open; @@ -228,71 +231,16 @@ int rose_init(struct device *dev) dev->pa_mask = 0; dev->pa_alen = sizeof(unsigned long); - if ((dev->priv = kmalloc(sizeof(struct enet_statistics), GFP_KERNEL)) == NULL) + if ((dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL)) == NULL) return -ENOMEM; - memset(dev->priv, 0, sizeof(struct enet_statistics)); + memset(dev->priv, 0, sizeof(struct net_device_stats)); dev->get_stats = rose_get_stats; - /* Fill in the generic fields of the device structure. */ - for (i = 0; i < DEV_NUMBUFFS; i++) - skb_queue_head_init(&dev->buffs[i]); + dev_init_buffers(dev); return 0; }; -#ifdef MODULE -extern struct proto_ops rose_proto_ops; -extern struct notifier_block rose_dev_notifier; - -static struct device dev_rose[] = { - {"rose0", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, rose_init}, - {"rose1", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, rose_init} -}; - -int init_module(void) -{ - register_netdev(&dev_rose[0]); - register_netdev(&dev_rose[1]); - - register_symtab(NULL); - - rose_proto_init(NULL); - - return 0; -} - -void cleanup_module(void) -{ - int i; - -#ifdef CONFIG_PROC_FS - proc_net_unregister(PROC_NET_RS); - proc_net_unregister(PROC_NET_RS_NEIGH); - proc_net_unregister(PROC_NET_RS_NODES); - proc_net_unregister(PROC_NET_RS_ROUTES); -#endif - rose_rt_free(); - - ax25_protocol_release(AX25_P_ROSE); - ax25_linkfail_release(rose_link_failed); - - rose_unregister_sysctl(); - - unregister_netdevice_notifier(&rose_dev_notifier); - - sock_unregister(rose_proto_ops.family); - - for (i = 0; i < 2; i++) { - if (dev_rose[i].priv != NULL) { - kfree(dev_rose[i].priv); - dev_rose[i].priv = NULL; - unregister_netdev(&dev_rose[i]); - } - } -} - -#endif - #endif diff --git a/net/rose/rose_in.c b/net/rose/rose_in.c index 20374dbb1..66521efa8 100644 --- a/net/rose/rose_in.c +++ b/net/rose/rose_in.c @@ -1,10 +1,10 @@ /* * Rose release 001 * - * This is ALPHA test software. This code may break your machine, randomly fail to work with new - * releases, misbehave and/or generally screw up. It might even work. + * This is ALPHA test software. This code may break your machine, randomly fail to work with new + * releases, misbehave and/or generally screw up. It might even work. * - * This code REQUIRES 2.1.0 or higher/ NET3.029 + * This code REQUIRES 2.1.15 or higher/ NET3.038 * * This module: * This module is free software; you can redistribute it and/or @@ -56,7 +56,7 @@ static int rose_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more) skb_queue_tail(&sk->protinfo.rose->frag_queue, skb); return 0; } - + if (!more && sk->protinfo.rose->fraglen > 0) { /* End of fragment */ sk->protinfo.rose->fraglen += skb->len; skb_queue_tail(&sk->protinfo.rose->frag_queue, skb); @@ -64,10 +64,6 @@ static int rose_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more) if ((skbn = alloc_skb(sk->protinfo.rose->fraglen, GFP_ATOMIC)) == NULL) return 1; - skbn->free = 1; - skbn->arp = 1; - skbn->sk = sk; - sk->rmem_alloc += skbn->truesize; skbn->h.raw = skbn->data; skbo = skb_dequeue(&sk->protinfo.rose->frag_queue); @@ -96,19 +92,21 @@ static int rose_state1_machine(struct sock *sk, struct sk_buff *skb, int framety switch (frametype) { case ROSE_CALL_ACCEPTED: - sk->protinfo.rose->timer = 0; - sk->protinfo.rose->vs = 0; - sk->protinfo.rose->va = 0; - sk->protinfo.rose->vr = 0; - sk->protinfo.rose->vl = 0; - sk->protinfo.rose->state = ROSE_STATE_3; - sk->state = TCP_ESTABLISHED; + sk->protinfo.rose->condition = 0x00; + sk->protinfo.rose->timer = 0; + sk->protinfo.rose->vs = 0; + sk->protinfo.rose->va = 0; + sk->protinfo.rose->vr = 0; + sk->protinfo.rose->vl = 0; + sk->protinfo.rose->state = ROSE_STATE_3; + sk->state = TCP_ESTABLISHED; if (!sk->dead) sk->state_change(sk); break; case ROSE_CLEAR_REQUEST: rose_clear_queues(sk); + rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); sk->protinfo.rose->state = ROSE_STATE_0; sk->state = TCP_CLOSE; sk->err = ECONNREFUSED; @@ -136,7 +134,9 @@ static int rose_state2_machine(struct sock *sk, struct sk_buff *skb, int framety switch (frametype) { case ROSE_CLEAR_REQUEST: + rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); case ROSE_CLEAR_CONFIRMATION: + rose_clear_queues(sk); sk->protinfo.rose->state = ROSE_STATE_0; sk->state = TCP_CLOSE; sk->err = 0; @@ -166,9 +166,9 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety switch (frametype) { case ROSE_RESET_REQUEST: - rose_clear_queues(sk); rose_write_internal(sk, ROSE_RESET_CONFIRMATION); sk->protinfo.rose->condition = 0x00; + sk->protinfo.rose->timer = 0; sk->protinfo.rose->vs = 0; sk->protinfo.rose->vr = 0; sk->protinfo.rose->va = 0; @@ -189,11 +189,10 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety case ROSE_RR: case ROSE_RNR: - if (frametype == ROSE_RNR) { - sk->protinfo.rose->condition |= PEER_RX_BUSY_CONDITION; - } else { - sk->protinfo.rose->condition &= ~PEER_RX_BUSY_CONDITION; - } + if (frametype == ROSE_RNR) + sk->protinfo.rose->condition |= ROSE_COND_PEER_RX_BUSY; + else + sk->protinfo.rose->condition &= ~ROSE_COND_PEER_RX_BUSY; if (!rose_validate_nr(sk, nr)) { rose_clear_queues(sk); rose_write_internal(sk, ROSE_RESET_REQUEST); @@ -205,16 +204,16 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety sk->protinfo.rose->state = ROSE_STATE_4; sk->protinfo.rose->timer = sk->protinfo.rose->t2; } else { - if (sk->protinfo.rose->condition & PEER_RX_BUSY_CONDITION) { - rose_frames_acked(sk, nr); + if (sk->protinfo.rose->condition & ROSE_COND_PEER_RX_BUSY) { + sk->protinfo.rose->va = nr; } else { rose_check_iframes_acked(sk, nr); } } break; - + case ROSE_DATA: /* XXX */ - sk->protinfo.rose->condition &= ~PEER_RX_BUSY_CONDITION; + sk->protinfo.rose->condition &= ~ROSE_COND_PEER_RX_BUSY; if (!rose_validate_nr(sk, nr)) { rose_clear_queues(sk); rose_write_internal(sk, ROSE_RESET_REQUEST); @@ -227,26 +226,33 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety sk->protinfo.rose->timer = sk->protinfo.rose->t2; break; } - if (sk->protinfo.rose->condition & PEER_RX_BUSY_CONDITION) { - rose_frames_acked(sk, nr); + if (sk->protinfo.rose->condition & ROSE_COND_PEER_RX_BUSY) { + sk->protinfo.rose->va = nr; } else { rose_check_iframes_acked(sk, nr); } - if (sk->protinfo.rose->condition & OWN_RX_BUSY_CONDITION) + if (sk->protinfo.rose->condition & ROSE_COND_OWN_RX_BUSY) break; if (ns == sk->protinfo.rose->vr) { if (rose_queue_rx_frame(sk, skb, m) == 0) { sk->protinfo.rose->vr = (sk->protinfo.rose->vr + 1) % ROSE_MODULUS; queued = 1; } else { - sk->protinfo.rose->condition |= OWN_RX_BUSY_CONDITION; + sk->protinfo.rose->condition |= ROSE_COND_OWN_RX_BUSY; } } /* - * If the window is full, ack the frame. + * If the window is full, ack the frame, else start the + * acknowledge hold back timer. */ - if (((sk->protinfo.rose->vl + sk->window) % ROSE_MODULUS) == sk->protinfo.rose->vr) + if (((sk->protinfo.rose->vl + ROSE_MAX_WINDOW_SIZE) % ROSE_MODULUS) == sk->protinfo.rose->vr) { + sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING; + sk->protinfo.rose->timer = 0; rose_enquiry_response(sk); + } else { + sk->protinfo.rose->condition |= ROSE_COND_ACK_PENDING; + sk->protinfo.rose->timer = sk->protinfo.rose->hb; + } break; default: @@ -266,8 +272,9 @@ static int rose_state4_machine(struct sock *sk, struct sk_buff *skb, int framety { switch (frametype) { - case ROSE_RESET_CONFIRMATION: case ROSE_RESET_REQUEST: + rose_write_internal(sk, ROSE_RESET_CONFIRMATION); + case ROSE_RESET_CONFIRMATION: sk->protinfo.rose->timer = 0; sk->protinfo.rose->condition = 0x00; sk->protinfo.rose->va = 0; @@ -302,7 +309,7 @@ static int rose_state4_machine(struct sock *sk, struct sk_buff *skb, int framety int rose_process_rx_frame(struct sock *sk, struct sk_buff *skb) { int queued = 0, frametype, ns, nr, q, d, m; - + if (sk->protinfo.rose->state == ROSE_STATE_0) return 0; diff --git a/net/rose/rose_link.c b/net/rose/rose_link.c index d0bf308f0..9f1a0c0f5 100644 --- a/net/rose/rose_link.c +++ b/net/rose/rose_link.c @@ -4,7 +4,7 @@ * This is ALPHA test software. This code may break your machine, randomly fail to work with new * releases, misbehave and/or generally screw up. It might even work. * - * This code REQUIRES 2.1.0 or higher/ NET3.029 + * This code REQUIRES 2.1.15 or higher/ NET3.038 * * This module: * This module is free software; you can redistribute it and/or @@ -44,37 +44,20 @@ static void rose_link_timer(unsigned long); /* - * Linux set/reset timer routines + * Linux set timer */ -static void rose_link_set_timer(struct rose_neigh *neigh) +void rose_link_set_timer(struct rose_neigh *neigh) { unsigned long flags; - - save_flags(flags); - cli(); - del_timer(&neigh->timer); - restore_flags(flags); - - neigh->timer.next = neigh->timer.prev = NULL; - neigh->timer.data = (unsigned long)neigh; - neigh->timer.function = &rose_link_timer; - neigh->timer.expires = jiffies + 10; - add_timer(&neigh->timer); -} - -static void rose_link_reset_timer(struct rose_neigh *neigh) -{ - unsigned long flags; - - save_flags(flags); - cli(); + save_flags(flags); cli(); del_timer(&neigh->timer); restore_flags(flags); neigh->timer.data = (unsigned long)neigh; neigh->timer.function = &rose_link_timer; - neigh->timer.expires = jiffies + 10; + neigh->timer.expires = jiffies + (HZ / 10); + add_timer(&neigh->timer); } @@ -88,19 +71,56 @@ static void rose_link_timer(unsigned long param) { struct rose_neigh *neigh = (struct rose_neigh *)param; - if (neigh->t0timer == 0 || --neigh->t0timer > 0) { - rose_link_reset_timer(neigh); - return; + if (neigh->ftimer > 0) + neigh->ftimer--; + + if (neigh->t0timer > 0) { + neigh->t0timer--; + + if (neigh->t0timer == 0) { + rose_transmit_restart_request(neigh); + neigh->t0timer = sysctl_rose_restart_request_timeout; + } } - /* - * T0 for a link has expired. - */ - rose_transmit_restart_request(neigh); + if (neigh->ftimer > 0 || neigh->t0timer > 0) + rose_link_set_timer(neigh); + else + del_timer(&neigh->timer); +} - neigh->t0timer = neigh->t0; +/* + * Interface to ax25_send_frame. Changes my level 2 callsign depending + * on whether we have a global ROSE callsign or use the default port + * callsign. + */ +static int rose_send_frame(struct sk_buff *skb, struct rose_neigh *neigh) +{ + ax25_address *rose_call; + + if (ax25cmp(&rose_callsign, &null_ax25_address) == 0) + rose_call = (ax25_address *)neigh->dev->dev_addr; + else + rose_call = &rose_callsign; + + return ax25_send_frame(skb, 256, rose_call, &neigh->callsign, neigh->digipeat, neigh->dev); +} + +/* + * Interface to ax25_link_up. Changes my level 2 callsign depending + * on whether we have a global ROSE callsign or use the default port + * callsign. + */ +static int rose_link_up(struct rose_neigh *neigh) +{ + ax25_address *rose_call; - rose_link_set_timer(neigh); + if (ax25cmp(&rose_callsign, &null_ax25_address) == 0) + rose_call = (ax25_address *)neigh->dev->dev_addr; + else + rose_call = &rose_callsign; + + return ax25_link_up(rose_call, &neigh->callsign, neigh->digipeat, neigh->dev); } /* @@ -127,7 +147,7 @@ void rose_link_rx_restart(struct sk_buff *skb, struct rose_neigh *neigh, unsigne case ROSE_DIAGNOSTIC: printk(KERN_WARNING "rose: diagnostic #%d\n", skb->data[3]); break; - + default: printk(KERN_WARNING "rose: received unknown %02X with LCI 000\n", frametype); break; @@ -135,7 +155,7 @@ void rose_link_rx_restart(struct sk_buff *skb, struct rose_neigh *neigh, unsigne if (neigh->restarted) { while ((skbn = skb_dequeue(&neigh->queue)) != NULL) - if (!ax25_send_frame(skbn, (ax25_address *)neigh->dev->dev_addr, &neigh->callsign, neigh->digipeat, neigh->dev)) + if (!rose_send_frame(skbn, neigh)) kfree_skb(skbn, FREE_WRITE); } } @@ -159,16 +179,13 @@ void rose_transmit_restart_request(struct rose_neigh *neigh) dptr = skb_put(skb, ROSE_MIN_LEN + 3); *dptr++ = AX25_P_ROSE; - *dptr++ = GFI; + *dptr++ = ROSE_GFI; *dptr++ = 0x00; *dptr++ = ROSE_RESTART_REQUEST; *dptr++ = 0x00; *dptr++ = 0; - skb->free = 1; - skb->sk = NULL; - - if (!ax25_send_frame(skb, (ax25_address *)neigh->dev->dev_addr, &neigh->callsign, neigh->digipeat, neigh->dev)) + if (!rose_send_frame(skb, neigh)) kfree_skb(skb, FREE_WRITE); } @@ -191,14 +208,11 @@ void rose_transmit_restart_confirmation(struct rose_neigh *neigh) dptr = skb_put(skb, ROSE_MIN_LEN + 1); *dptr++ = AX25_P_ROSE; - *dptr++ = GFI; + *dptr++ = ROSE_GFI; *dptr++ = 0x00; *dptr++ = ROSE_RESTART_CONFIRMATION; - skb->free = 1; - skb->sk = NULL; - - if (!ax25_send_frame(skb, (ax25_address *)neigh->dev->dev_addr, &neigh->callsign, neigh->digipeat, neigh->dev)) + if (!rose_send_frame(skb, neigh)) kfree_skb(skb, FREE_WRITE); } @@ -221,15 +235,12 @@ void rose_transmit_diagnostic(struct rose_neigh *neigh, unsigned char diag) dptr = skb_put(skb, ROSE_MIN_LEN + 2); *dptr++ = AX25_P_ROSE; - *dptr++ = GFI; + *dptr++ = ROSE_GFI; *dptr++ = 0x00; *dptr++ = ROSE_DIAGNOSTIC; *dptr++ = diag; - skb->free = 1; - skb->sk = NULL; - - if (!ax25_send_frame(skb, (ax25_address *)neigh->dev->dev_addr, &neigh->callsign, neigh->digipeat, neigh->dev)) + if (!rose_send_frame(skb, neigh)) kfree_skb(skb, FREE_WRITE); } @@ -253,16 +264,13 @@ void rose_transmit_clear_request(struct rose_neigh *neigh, unsigned int lci, uns dptr = skb_put(skb, ROSE_MIN_LEN + 3); *dptr++ = AX25_P_ROSE; - *dptr++ = ((lci >> 8) & 0x0F) | GFI; + *dptr++ = ((lci >> 8) & 0x0F) | ROSE_GFI; *dptr++ = ((lci >> 0) & 0xFF); *dptr++ = ROSE_CLEAR_REQUEST; *dptr++ = cause; *dptr++ = 0x00; - skb->free = 1; - skb->sk = NULL; - - if (!ax25_send_frame(skb, (ax25_address *)neigh->dev->dev_addr, &neigh->callsign, neigh->digipeat, neigh->dev)) + if (!rose_send_frame(skb, neigh)) kfree_skb(skb, FREE_WRITE); } @@ -270,29 +278,24 @@ void rose_transmit_link(struct sk_buff *skb, struct rose_neigh *neigh) { unsigned char *dptr; -#ifdef CONFIG_FIREWALL - if (call_fw_firewall(PF_ROSE, skb->dev, skb->data, NULL) != FW_ACCEPT) + if (call_fw_firewall(PF_ROSE, skb->dev, skb->data, NULL,&skb) != FW_ACCEPT) return; -#endif - if (!ax25_link_up((ax25_address *)neigh->dev->dev_addr, &neigh->callsign, neigh->dev)) + if (!rose_link_up(neigh)) neigh->restarted = 0; dptr = skb_push(skb, 1); *dptr++ = AX25_P_ROSE; - skb->arp = 1; - skb->free = 1; - if (neigh->restarted) { - if (!ax25_send_frame(skb, (ax25_address *)neigh->dev->dev_addr, &neigh->callsign, neigh->digipeat, neigh->dev)) + if (!rose_send_frame(skb, neigh)) kfree_skb(skb, FREE_WRITE); } else { skb_queue_tail(&neigh->queue, skb); - + if (neigh->t0timer == 0) { rose_transmit_restart_request(neigh); - neigh->t0timer = neigh->t0; + neigh->t0timer = sysctl_rose_restart_request_timeout; rose_link_set_timer(neigh); } } diff --git a/net/rose/rose_out.c b/net/rose/rose_out.c index 50b2587f8..8ab4d9325 100644 --- a/net/rose/rose_out.c +++ b/net/rose/rose_out.c @@ -4,7 +4,7 @@ * This is ALPHA test software. This code may break your machine, randomly fail to work with new * releases, misbehave and/or generally screw up. It might even work. * - * This code REQUIRES 2.1.0 or higher/ NET3.029 + * This code REQUIRES 2.1.15 or higher/ NET3.038 * * This module: * This module is free software; you can redistribute it and/or @@ -49,7 +49,7 @@ void rose_output(struct sock *sk, struct sk_buff *skb) unsigned char header[ROSE_MIN_LEN]; int err, frontlen, len; - if (skb->len - ROSE_MIN_LEN > ROSE_PACLEN) { + if (skb->len - ROSE_MIN_LEN > ROSE_MAX_PACKET_SIZE) { /* Save a copy of the Header */ memcpy(header, skb->data, ROSE_MIN_LEN); skb_pull(skb, ROSE_MIN_LEN); @@ -57,16 +57,12 @@ void rose_output(struct sock *sk, struct sk_buff *skb) frontlen = skb_headroom(skb); while (skb->len > 0) { - if ((skbn = sock_alloc_send_skb(sk, frontlen + ROSE_PACLEN, 0, 0, &err)) == NULL) + if ((skbn = sock_alloc_send_skb(sk, frontlen + ROSE_MAX_PACKET_SIZE, 0, 0, &err)) == NULL) return; - skbn->sk = sk; - skbn->free = 1; - skbn->arp = 1; - skb_reserve(skbn, frontlen); - len = (ROSE_PACLEN > skb->len) ? skb->len : ROSE_PACLEN; + len = (ROSE_MAX_PACKET_SIZE > skb->len) ? skb->len : ROSE_MAX_PACKET_SIZE; /* Copy the user data */ memcpy(skb_put(skbn, len), skb->data, len); @@ -77,12 +73,11 @@ void rose_output(struct sock *sk, struct sk_buff *skb) memcpy(skbn->data, header, ROSE_MIN_LEN); if (skb->len > 0) - skbn->data[2] |= M_BIT; - + skbn->data[2] |= ROSE_M_BIT; + skb_queue_tail(&sk->write_queue, skbn); /* Throw it on the queue */ } - - skb->free = 1; + kfree_skb(skb, FREE_WRITE); } else { skb_queue_tail(&sk->write_queue, skb); /* Throw it on the queue */ @@ -109,55 +104,36 @@ static void rose_send_iframe(struct sock *sk, struct sk_buff *skb) void rose_kick(struct sock *sk) { - struct sk_buff *skb, *skbn; - int last = 1; - unsigned short start, end, next; + struct sk_buff *skb; + unsigned short end; del_timer(&sk->timer); - start = (skb_peek(&sk->protinfo.rose->ack_queue) == NULL) ? sk->protinfo.rose->va : sk->protinfo.rose->vs; - end = (sk->protinfo.rose->va + sk->window) % ROSE_MODULUS; + end = (sk->protinfo.rose->va + ROSE_MAX_WINDOW_SIZE) % ROSE_MODULUS; - if (!(sk->protinfo.rose->condition & PEER_RX_BUSY_CONDITION) && - start != end && + if (!(sk->protinfo.rose->condition & ROSE_COND_PEER_RX_BUSY) && + sk->protinfo.rose->vs != end && skb_peek(&sk->write_queue) != NULL) { - - sk->protinfo.rose->vs = start; - /* * Transmit data until either we're out of data to send or * the window is full. */ - /* - * Dequeue the frame and copy it. - */ skb = skb_dequeue(&sk->write_queue); do { - if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) { - skb_queue_head(&sk->write_queue, skb); - break; - } - - next = (sk->protinfo.rose->vs + 1) % ROSE_MODULUS; - last = (next == end); - /* - * Transmit the frame copy. + * Transmit the frame. */ - rose_send_iframe(sk, skbn); - - sk->protinfo.rose->vs = next; + rose_send_iframe(sk, skb); - /* - * Requeue the original data frame. - */ - skb_queue_tail(&sk->protinfo.rose->ack_queue, skb); + sk->protinfo.rose->vs = (sk->protinfo.rose->vs + 1) % ROSE_MODULUS; - } while (!last && (skb = skb_dequeue(&sk->write_queue)) != NULL); + } while (sk->protinfo.rose->vs != end && (skb = skb_dequeue(&sk->write_queue)) != NULL); - sk->protinfo.rose->vl = sk->protinfo.rose->vr; + sk->protinfo.rose->vl = sk->protinfo.rose->vr; + sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING; + sk->protinfo.rose->timer = 0; } rose_set_timer(sk); @@ -170,23 +146,23 @@ void rose_kick(struct sock *sk) void rose_enquiry_response(struct sock *sk) { - if (sk->protinfo.rose->condition & OWN_RX_BUSY_CONDITION) { + if (sk->protinfo.rose->condition & ROSE_COND_OWN_RX_BUSY) rose_write_internal(sk, ROSE_RNR); - } else { + else rose_write_internal(sk, ROSE_RR); - } - sk->protinfo.rose->vl = sk->protinfo.rose->vr; + sk->protinfo.rose->vl = sk->protinfo.rose->vr; + sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING; + sk->protinfo.rose->timer = 0; } void rose_check_iframes_acked(struct sock *sk, unsigned short nr) { if (sk->protinfo.rose->vs == nr) { - rose_frames_acked(sk, nr); + sk->protinfo.rose->va = nr; } else { - if (sk->protinfo.rose->va != nr) { - rose_frames_acked(sk, nr); - } + if (sk->protinfo.rose->va != nr) + sk->protinfo.rose->va = nr; } } diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index 9396831b3..19a53d40d 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c @@ -4,7 +4,7 @@ * This is ALPHA test software. This code may break your machine, randomly fail to work with new * releases, misbehave and/or generally screw up. It might even work. * - * This code REQUIRES 2.1.0 or higher/ NET3.029 + * This code REQUIRES 2.1.15 or higher/ NET3.038 * * This module: * This module is free software; you can redistribute it and/or @@ -14,8 +14,10 @@ * * History * Rose 001 Jonathan(G4KLX) Cloned from nr_route.c. + * Terry(VK2KTJ) Added support for variable length + * address masks. */ - + #include <linux/config.h> #if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE) #include <linux/errno.h> @@ -60,13 +62,13 @@ static void rose_remove_neigh(struct rose_neigh *); */ static int rose_add_node(struct rose_route_struct *rose_route, struct device *dev) { - struct rose_node *rose_node; + struct rose_node *rose_node, *rose_tmpn, *rose_tmpp; struct rose_neigh *rose_neigh; unsigned long flags; int i; for (rose_node = rose_node_list; rose_node != NULL; rose_node = rose_node->next) - if (rosecmp(&rose_route->address, &rose_node->address) == 0) + if ((rose_node->mask == rose_route->mask) && (rosecmpm(&rose_route->address, &rose_node->address, rose_route->mask) == 0)) break; for (rose_neigh = rose_neigh_list; rose_neigh != NULL; rose_neigh = rose_neigh->next) @@ -84,8 +86,8 @@ static int rose_add_node(struct rose_route_struct *rose_route, struct device *de rose_neigh->number = rose_neigh_no++; rose_neigh->restarted = 0; skb_queue_head_init(&rose_neigh->queue); - rose_neigh->t0 = sysctl_rose_restart_request_timeout; rose_neigh->t0timer = 0; + rose_neigh->ftimer = 0; init_timer(&rose_neigh->timer); if (rose_route->ndigis != 0) { @@ -97,40 +99,72 @@ static int rose_add_node(struct rose_route_struct *rose_route, struct device *de for (i = 0; i < rose_route->ndigis; i++) rose_neigh->digipeat->calls[i] = rose_route->digipeaters[i]; } - + save_flags(flags); cli(); rose_neigh->next = rose_neigh_list; rose_neigh_list = rose_neigh; restore_flags(flags); } + /* + * This is a new node to be inserted into the list. Find where it needs + * to be inserted into the list, and insert it. We want to be sure + * to order the list in descending order of mask size to ensure that + * later when we are searching this list the first match will be the + * best match. + */ if (rose_node == NULL) { + rose_tmpn = rose_node_list; + rose_tmpp = NULL; + + while (rose_tmpn != NULL) { + if (rose_tmpn->mask > rose_route->mask) { + rose_tmpp = rose_tmpn; + rose_tmpn = rose_tmpn->next; + } else { + break; + } + } + + /* create new node */ if ((rose_node = (struct rose_node *)kmalloc(sizeof(*rose_node), GFP_ATOMIC)) == NULL) return -ENOMEM; rose_node->address = rose_route->address; - rose_node->which = 0; + rose_node->mask = rose_route->mask; rose_node->count = 1; - rose_node->neighbour[0] = rose_neigh; - + save_flags(flags); cli(); - rose_node->next = rose_node_list; - rose_node_list = rose_node; + + if (rose_tmpn == NULL) { + if (rose_tmpp == NULL) { /* Empty list */ + rose_node_list = rose_node; + rose_node->next = NULL; + } else { + rose_tmpp->next = rose_node; + rose_node->next = NULL; + } + } else { + if (rose_tmpp == NULL) { /* 1st node */ + rose_node->next = rose_node_list; + rose_node_list = rose_node; + } else { + rose_tmpp->next = rose_node; + rose_node->next = rose_tmpn; + } + } + restore_flags(flags); - + rose_neigh->count++; return 0; } - /* We have space at the bottom, slot it in */ + /* We have space, slot it in */ if (rose_node->count < 3) { - rose_node->neighbour[2] = rose_node->neighbour[1]; - rose_node->neighbour[1] = rose_node->neighbour[0]; - - rose_node->neighbour[0] = rose_neigh; - + rose_node->neighbour[rose_node->count] = rose_neigh; rose_node->count++; rose_neigh->count++; } @@ -174,10 +208,10 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh) struct sk_buff *skb; del_timer(&rose_neigh->timer); - + while ((skb = skb_dequeue(&rose_neigh->queue)) != NULL) kfree_skb(skb, FREE_WRITE); - + save_flags(flags); cli(); @@ -244,9 +278,9 @@ static int rose_del_node(struct rose_route_struct *rose_route, struct device *de struct rose_node *rose_node; struct rose_neigh *rose_neigh; int i; - + for (rose_node = rose_node_list; rose_node != NULL; rose_node = rose_node->next) - if (rosecmp(&rose_route->address, &rose_node->address) == 0) + if ((rose_node->mask == rose_route->mask) && (rosecmpm(&rose_route->address, &rose_node->address, rose_route->mask) == 0)) break; if (rose_node == NULL) return -EINVAL; @@ -256,16 +290,16 @@ static int rose_del_node(struct rose_route_struct *rose_route, struct device *de break; if (rose_neigh == NULL) return -EINVAL; - + for (i = 0; i < rose_node->count; i++) { if (rose_node->neighbour[i] == rose_neigh) { rose_neigh->count--; if (rose_neigh->count == 0) rose_remove_neigh(rose_neigh); - + rose_node->count--; - + if (rose_node->count == 0) { rose_remove_node(rose_node); } else { @@ -298,14 +332,14 @@ void rose_rt_device_down(struct device *dev) while (rose_neigh != NULL) { s = rose_neigh; rose_neigh = rose_neigh->next; - + if (s->dev == dev) { rose_node = rose_node_list; while (rose_node != NULL) { t = rose_node; rose_node = rose_node->next; - + for (i = 0; i < t->count; i++) { if (t->neighbour[i] == s) { t->count--; @@ -320,11 +354,11 @@ void rose_rt_device_down(struct device *dev) } } } - + if (t->count <= 0) rose_remove_node(t); } - + rose_remove_neigh(s); } } @@ -340,7 +374,7 @@ void rose_route_device_down(struct device *dev) while (rose_route != NULL) { s = rose_route; rose_route = rose_route->next; - + if (s->neigh1->dev == dev || s->neigh2->dev == dev) rose_remove_route(s); } @@ -397,16 +431,19 @@ struct device *rose_dev_get(rose_address *addr) struct rose_neigh *rose_get_neigh(rose_address *addr) { struct rose_node *node; - + int i; + for (node = rose_node_list; node != NULL; node = node->next) - if (rosecmp(&node->address, addr) == 0) + if (rosecmpm(addr, &node->address, node->mask) == 0) break; - + if (node == NULL) return NULL; - - if (node->which >= node->count) return NULL; - - return node->neighbour[node->which]; + + for (i = 0; i < node->count; i++) + if (node->neighbour[i]->ftimer == 0) + return node->neighbour[i]; + + return NULL; } /* @@ -428,6 +465,9 @@ int rose_rt_ioctl(unsigned int cmd, void *arg) return -EINVAL; if (rose_dev_get(&rose_route.address) != NULL) /* Can't add routes to ourself */ return -EINVAL; + if (rose_route.mask > 10) /* Mask can't be more than 10 digits */ + return -EINVAL; + return rose_add_node(&rose_route, dev); case SIOCDELRT: @@ -452,25 +492,22 @@ int rose_rt_ioctl(unsigned int cmd, void *arg) void rose_link_failed(ax25_address *callsign, struct device *dev) { struct rose_neigh *rose_neigh; - struct rose_node *rose_node; struct sk_buff *skb; for (rose_neigh = rose_neigh_list; rose_neigh != NULL; rose_neigh = rose_neigh->next) if (ax25cmp(&rose_neigh->callsign, callsign) == 0 && rose_neigh->dev == dev) break; - + if (rose_neigh == NULL) return; rose_neigh->restarted = 0; rose_neigh->t0timer = 0; - del_timer(&rose_neigh->timer); + rose_neigh->ftimer = sysctl_rose_link_fail_timeout; + + rose_link_set_timer(rose_neigh); while ((skb = skb_dequeue(&rose_neigh->queue)) != NULL) kfree_skb(skb, FREE_WRITE); - - for (rose_node = rose_node_list; rose_node != NULL; rose_node = rose_node->next) - if (rose_node->which < rose_node->count && rose_node->neighbour[rose_node->which] == rose_neigh) - rose_node->which++; } /* @@ -479,57 +516,56 @@ void rose_link_failed(ax25_address *callsign, struct device *dev) void rose_link_device_down(struct device *dev) { struct rose_neigh *rose_neigh; - struct rose_node *rose_node; struct sk_buff *skb; for (rose_neigh = rose_neigh_list; rose_neigh != NULL; rose_neigh = rose_neigh->next) { if (rose_neigh->dev == dev) { rose_neigh->restarted = 0; rose_neigh->t0timer = 0; + rose_neigh->ftimer = 0; del_timer(&rose_neigh->timer); while ((skb = skb_dequeue(&rose_neigh->queue)) != NULL) kfree_skb(skb, FREE_WRITE); - - for (rose_node = rose_node_list; rose_node != NULL; rose_node = rose_node->next) - if (rose_node->which < rose_node->count && rose_node->neighbour[rose_node->which] == rose_neigh) - rose_node->which++; } } } /* - * Route a frame to an appropriate AX.25 connection. A NULL ax25_cb - * indicates an internally generated frame. + * Route a frame to an appropriate AX.25 connection. */ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) { struct rose_neigh *rose_neigh, *new_neigh; - struct rose_node *rose_node; struct rose_route *rose_route; - rose_address *dest_addr; + rose_address *src_addr, *dest_addr; struct sock *sk; unsigned short frametype; unsigned int lci; struct device *dev; unsigned long flags; -#ifdef CONFIG_FIREWALL - if (call_in_firewall(PF_ROSE, skb->dev, skb->data, NULL) != FW_ACCEPT) + if (call_in_firewall(PF_ROSE, skb->dev, skb->data, NULL, &skb) != FW_ACCEPT) return 0; -#endif frametype = skb->data[2]; lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); + src_addr = (rose_address *)(skb->data + 9); + dest_addr = (rose_address *)(skb->data + 4); for (rose_neigh = rose_neigh_list; rose_neigh != NULL; rose_neigh = rose_neigh->next) - if (ax25cmp(&ax25->dest_addr, &rose_neigh->callsign) == 0 && ax25->device == rose_neigh->dev) + if (ax25cmp(&ax25->dest_addr, &rose_neigh->callsign) == 0 && ax25->ax25_dev->dev == rose_neigh->dev) break; if (rose_neigh == NULL) return 0; /* + * Obviously the link is working, halt the ftimer. + */ + rose_neigh->ftimer = 0; + + /* * LCI of zero is always for us, and its always a restart * frame. */ @@ -549,12 +585,9 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) /* * Is is a Call Request and is it for us ? */ - if (frametype == ROSE_CALL_REQUEST) { - dest_addr = (rose_address *)(skb->data + 4); - + if (frametype == ROSE_CALL_REQUEST) if ((dev = rose_dev_get(dest_addr)) != NULL) return rose_rx_call_request(skb, dev, rose_neigh, lci); - } if (!sysctl_rose_routing_control) { rose_transmit_clear_request(rose_neigh, lci, 0x0D); @@ -598,18 +631,7 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) if (frametype != ROSE_CALL_REQUEST) /* XXX */ return 0; - dest_addr = (rose_address *)(skb->data + 4); - - /* - * Create a new route entry, if we can. - */ - for (rose_node = rose_node_list; rose_node != NULL; rose_node = rose_node->next) - if (rosecmp(&rose_node->address, dest_addr) == 0) - break; - /* - * Its an unknown node, or is unreachable. - */ - if (rose_node == NULL || rose_node->which >= rose_node->count) { + if ((new_neigh = rose_get_neigh(dest_addr)) == NULL) { rose_transmit_clear_request(rose_neigh, lci, 0x0D); return 0; } @@ -619,8 +641,6 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) return 0; } - new_neigh = rose_node->neighbour[rose_node->which]; - rose_route->lci1 = lci; rose_route->neigh1 = rose_neigh; rose_route->lci2 = rose_new_lci(new_neigh->dev); @@ -651,12 +671,12 @@ int rose_nodes_get_info(char *buffer, char **start, off_t offset, cli(); - len += sprintf(buffer, "address w n neigh neigh neigh\n"); + len += sprintf(buffer, "address mask n neigh neigh neigh\n"); for (rose_node = rose_node_list; rose_node != NULL; rose_node = rose_node->next) { - len += sprintf(buffer + len, "%-10s %d %d", + len += sprintf(buffer + len, "%-10s %04d %d", rose2asc(&rose_node->address), - rose_node->which + 1, + rose_node->mask, rose_node->count); for (i = 0; i < rose_node->count; i++) @@ -696,17 +716,17 @@ int rose_neigh_get_info(char *buffer, char **start, off_t offset, cli(); - len += sprintf(buffer, "addr callsign dev count restart t0\n"); + len += sprintf(buffer, "addr callsign dev count restart t0 tf\n"); for (rose_neigh = rose_neigh_list; rose_neigh != NULL; rose_neigh = rose_neigh->next) { - len += sprintf(buffer + len, "%05d %-9s %-4s %3d %3s %3d/%03d\n", + len += sprintf(buffer + len, "%05d %-9s %-4s %3d %3s %3d %3d\n", rose_neigh->number, ax2asc(&rose_neigh->callsign), rose_neigh->dev ? rose_neigh->dev->name : "???", rose_neigh->count, (rose_neigh->restarted) ? "yes" : "no", - rose_neigh->t0timer / PR_SLOWHZ, - rose_neigh->t0 / PR_SLOWHZ); + rose_neigh->t0timer / ROSE_SLOWHZ, + rose_neigh->ftimer / ROSE_SLOWHZ); pos = begin + len; @@ -714,7 +734,7 @@ int rose_neigh_get_info(char *buffer, char **start, off_t offset, len = 0; begin = pos; } - + if (pos > offset + length) break; } @@ -757,7 +777,7 @@ int rose_routes_get_info(char *buffer, char **start, off_t offset, len = 0; begin = pos; } - + if (pos > offset + length) break; } @@ -786,21 +806,21 @@ void rose_rt_free(void) while (rose_neigh != NULL) { s = rose_neigh; rose_neigh = rose_neigh->next; - + rose_remove_neigh(s); } while (rose_node != NULL) { t = rose_node; rose_node = rose_node->next; - + rose_remove_node(t); } while (rose_route != NULL) { u = rose_route; rose_route = rose_route->next; - + rose_remove_route(u); } } diff --git a/net/rose/rose_subr.c b/net/rose/rose_subr.c index 0c1c83fa8..5befcbb60 100644 --- a/net/rose/rose_subr.c +++ b/net/rose/rose_subr.c @@ -4,7 +4,7 @@ * This is ALPHA test software. This code may break your machine, randomly fail to work with new * releases, misbehave and/or generally screw up. It might even work. * - * This code REQUIRES 2.1.0 or higher/ NET3.029 + * This code REQUIRES 2.1.15 or higher/ NET3.038 * * This module: * This module is free software; you can redistribute it and/or @@ -15,7 +15,7 @@ * History * Rose 001 Jonathan(G4KLX) Cloned from nr_subr.c */ - + #include <linux/config.h> #if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE) #include <linux/errno.h> @@ -47,62 +47,11 @@ void rose_clear_queues(struct sock *sk) { struct sk_buff *skb; - while ((skb = skb_dequeue(&sk->write_queue)) != NULL) { - skb->sk = sk; - skb->free = 1; - kfree_skb(skb, FREE_WRITE); - } - - while ((skb = skb_dequeue(&sk->protinfo.rose->ack_queue)) != NULL) { - skb->sk = sk; - skb->free = 1; + while ((skb = skb_dequeue(&sk->write_queue)) != NULL) kfree_skb(skb, FREE_WRITE); - } - while ((skb = skb_dequeue(&sk->protinfo.rose->frag_queue)) != NULL) { + while ((skb = skb_dequeue(&sk->protinfo.rose->frag_queue)) != NULL) kfree_skb(skb, FREE_READ); - } -} - -/* - * This routine purges the input queue of those frames that have been - * acknowledged. This replaces the boxes labelled "V(a) <- N(r)" on the - * SDL diagram. - */ -void rose_frames_acked(struct sock *sk, unsigned short nr) -{ - struct sk_buff *skb; - - /* - * Remove all the ack-ed frames from the ack queue. - */ - if (sk->protinfo.rose->va != nr) { - while (skb_peek(&sk->protinfo.rose->ack_queue) != NULL && sk->protinfo.rose->va != nr) { - skb = skb_dequeue(&sk->protinfo.rose->ack_queue); - skb->sk = sk; - skb->free = 1; - kfree_skb(skb, FREE_WRITE); - sk->protinfo.rose->va = (sk->protinfo.rose->va + 1) % ROSE_MODULUS; - } - } -} - -/* - * Requeue all the un-ack-ed frames on the output queue to be picked - * up by rose_kick called from the timer. This arrangement handles the - * possibility of an empty output queue. - */ -void rose_requeue_frames(struct sock *sk) -{ - struct sk_buff *skb, *skb_prev = NULL; - - while ((skb = skb_dequeue(&sk->protinfo.rose->ack_queue)) != NULL) { - if (skb_prev == NULL) - skb_queue_head(&sk->write_queue, skb); - else - skb_append(skb_prev, skb); - skb_prev = skb; - } } /* @@ -117,7 +66,7 @@ int rose_validate_nr(struct sock *sk, unsigned short nr) if (nr == vc) return 1; vc = (vc + 1) % ROSE_MODULUS; } - + if (nr == sk->protinfo.rose->vs) return 1; return 0; @@ -136,7 +85,7 @@ void rose_write_internal(struct sock *sk, int frametype) int len, faclen = 0; len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN + 1; - + switch (frametype) { case ROSE_CALL_REQUEST: len += 1 + ROSE_ADDR_LEN + ROSE_ADDR_LEN; @@ -153,7 +102,7 @@ void rose_write_internal(struct sock *sk, int frametype) len += 1; break; } - + if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL) return; @@ -168,9 +117,9 @@ void rose_write_internal(struct sock *sk, int frametype) lci2 = (sk->protinfo.rose->lci >> 0) & 0xFF; switch (frametype) { - + case ROSE_CALL_REQUEST: - *dptr++ = GFI | lci1; + *dptr++ = ROSE_GFI | lci1; *dptr++ = lci2; *dptr++ = frametype; *dptr++ = 0xAA; @@ -183,7 +132,7 @@ void rose_write_internal(struct sock *sk, int frametype) break; case ROSE_CALL_ACCEPTED: - *dptr++ = GFI | lci1; + *dptr++ = ROSE_GFI | lci1; *dptr++ = lci2; *dptr++ = frametype; *dptr++ = 0x00; /* Address length */ @@ -192,7 +141,7 @@ void rose_write_internal(struct sock *sk, int frametype) case ROSE_CLEAR_REQUEST: case ROSE_RESET_REQUEST: - *dptr++ = GFI | lci1; + *dptr++ = ROSE_GFI | lci1; *dptr++ = lci2; *dptr++ = frametype; *dptr++ = 0x00; /* XXX */ @@ -200,7 +149,7 @@ void rose_write_internal(struct sock *sk, int frametype) break; case ROSE_INTERRUPT: - *dptr++ = GFI | lci1; + *dptr++ = ROSE_GFI | lci1; *dptr++ = lci2; *dptr++ = frametype; *dptr++ = 0x00; /* XXX */ @@ -209,16 +158,16 @@ void rose_write_internal(struct sock *sk, int frametype) case ROSE_RR: case ROSE_RNR: case ROSE_REJ: - *dptr++ = GFI | lci1; + *dptr++ = ROSE_GFI | lci1; *dptr++ = lci2; *dptr = frametype; *dptr++ |= (sk->protinfo.rose->vr << 5) & 0xE0; break; - + case ROSE_CLEAR_CONFIRMATION: case ROSE_INTERRUPT_CONFIRMATION: case ROSE_RESET_CONFIRMATION: - *dptr++ = GFI | lci1; + *dptr++ = ROSE_GFI | lci1; *dptr++ = lci2; *dptr++ = frametype; break; @@ -235,11 +184,11 @@ void rose_write_internal(struct sock *sk, int frametype) int rose_decode(struct sk_buff *skb, int *ns, int *nr, int *q, int *d, int *m) { unsigned char *frame; - + frame = skb->data; - + *ns = *nr = *q = *d = *m = 0; - + switch (frame[2]) { case ROSE_CALL_REQUEST: case ROSE_CALL_ACCEPTED: @@ -267,14 +216,14 @@ int rose_decode(struct sk_buff *skb, int *ns, int *nr, int *q, int *d, int *m) } if ((frame[2] & 0x01) == ROSE_DATA) { - *q = (frame[0] & Q_BIT) == Q_BIT; - *d = (frame[0] & D_BIT) == D_BIT; - *m = (frame[2] & M_BIT) == M_BIT; + *q = (frame[0] & ROSE_Q_BIT) == ROSE_Q_BIT; + *d = (frame[0] & ROSE_D_BIT) == ROSE_D_BIT; + *m = (frame[2] & ROSE_M_BIT) == ROSE_M_BIT; *nr = (frame[2] >> 5) & 0x07; *ns = (frame[2] >> 1) & 0x07; return ROSE_DATA; } - + return ROSE_ILLEGAL; } @@ -289,7 +238,7 @@ static int rose_parse_national(unsigned char *p, rose_cb *rose, int len) n += 2; len -= 2; break; - + case 0x40: if (*p == FAC_NATIONAL_RAND) rose->rand = ((p[1] << 8) & 0xFF00) + ((p[2] << 0) & 0x00FF); @@ -303,7 +252,7 @@ static int rose_parse_national(unsigned char *p, rose_cb *rose, int len) n += 4; len -= 4; break; - + case 0xC0: l = p[1]; if (*p == FAC_NATIONAL_DEST_DIGI) { @@ -336,7 +285,7 @@ static int rose_parse_ccitt(unsigned char *p, rose_cb *rose, int len) n += 2; len -= 2; break; - + case 0x40: p += 3; n += 3; @@ -348,7 +297,7 @@ static int rose_parse_ccitt(unsigned char *p, rose_cb *rose, int len) n += 4; len -= 4; break; - + case 0xC0: l = p[1]; if (*p == FAC_CCITT_DEST_NSAP) { @@ -386,7 +335,7 @@ int rose_parse_facilities(struct sk_buff *skb, rose_cb *rose) p = skb->data + len + 4; facilities_len = *p++; - + if (facilities_len == 0) return 0; @@ -401,13 +350,13 @@ int rose_parse_facilities(struct sk_buff *skb, rose_cb *rose) facilities_len -= len + 1; p += len + 1; break; - + case FAC_CCITT: /* CCITT */ len = rose_parse_ccitt(p + 1, rose, facilities_len - 1); facilities_len -= len + 1; p += len + 1; break; - + default: printk(KERN_DEBUG "rose_parse_facilities: unknown facilities family %02X\n", *p); facilities_len--; @@ -425,7 +374,7 @@ int rose_create_facilities(unsigned char *buffer, rose_cb *rose) unsigned char *p = buffer + 1; char *callsign; int len; - + /* National Facilities */ if (rose->rand != 0 || rose->source_ndigis == 1 || rose->dest_ndigis == 1) { *p++ = 0x00; @@ -436,7 +385,7 @@ int rose_create_facilities(unsigned char *buffer, rose_cb *rose) *p++ = (rose->rand >> 8) & 0xFF; *p++ = (rose->rand >> 0) & 0xFF; } - + if (rose->source_ndigis == 1) { *p++ = FAC_NATIONAL_SRC_DIGI; *p++ = AX25_ADDR_LEN; @@ -454,9 +403,9 @@ int rose_create_facilities(unsigned char *buffer, rose_cb *rose) *p++ = 0x00; *p++ = FAC_CCITT; - + *p++ = FAC_CCITT_DEST_NSAP; - + callsign = ax2asc(&rose->dest_call); *p++ = strlen(callsign) + 10; @@ -469,7 +418,7 @@ int rose_create_facilities(unsigned char *buffer, rose_cb *rose) memcpy(p, callsign, strlen(callsign)); p += strlen(callsign); - + *p++ = FAC_CCITT_SRC_NSAP; callsign = ax2asc(&rose->source_call); @@ -487,7 +436,7 @@ int rose_create_facilities(unsigned char *buffer, rose_cb *rose) len = p - buffer; buffer[0] = len - 1; - + return len; } diff --git a/net/rose/rose_timer.c b/net/rose/rose_timer.c index 313756847..869f312f5 100644 --- a/net/rose/rose_timer.c +++ b/net/rose/rose_timer.c @@ -4,7 +4,7 @@ * This is ALPHA test software. This code may break your machine, randomly fail to work with new * releases, misbehave and/or generally screw up. It might even work. * - * This code REQUIRES 2.1.0 or higher/ NET3.029 + * This code REQUIRES 2.1.15 or higher/ NET3.038 * * This module: * This module is free software; you can redistribute it and/or @@ -43,37 +43,20 @@ static void rose_timer(unsigned long); /* - * Linux set/reset timer routines + * Linux set timer */ void rose_set_timer(struct sock *sk) { unsigned long flags; - - save_flags(flags); - cli(); - del_timer(&sk->timer); - restore_flags(flags); - - sk->timer.next = sk->timer.prev = NULL; - sk->timer.data = (unsigned long)sk; - sk->timer.function = &rose_timer; - - sk->timer.expires = jiffies + 10; - add_timer(&sk->timer); -} -static void rose_reset_timer(struct sock *sk) -{ - unsigned long flags; - - save_flags(flags); - cli(); + save_flags(flags); cli(); del_timer(&sk->timer); restore_flags(flags); sk->timer.data = (unsigned long)sk; sk->timer.function = &rose_timer; - sk->timer.expires = jiffies + 10; + sk->timer.expires = jiffies + (HZ / 10); + add_timer(&sk->timer); } @@ -102,9 +85,12 @@ static void rose_timer(unsigned long param) /* * Check for the state of the receive buffer. */ - if (sk->rmem_alloc < (sk->rcvbuf / 2) && (sk->protinfo.rose->condition & OWN_RX_BUSY_CONDITION)) { - sk->protinfo.rose->condition &= ~OWN_RX_BUSY_CONDITION; + if (atomic_read(&sk->rmem_alloc) < (sk->rcvbuf / 2) && + (sk->protinfo.rose->condition & ROSE_COND_OWN_RX_BUSY)) { + sk->protinfo.rose->condition &= ~ROSE_COND_OWN_RX_BUSY; + sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING; sk->protinfo.rose->vl = sk->protinfo.rose->vr; + sk->protinfo.rose->timer = 0; rose_write_internal(sk, ROSE_RR); break; } @@ -119,15 +105,22 @@ static void rose_timer(unsigned long param) } if (sk->protinfo.rose->timer == 0 || --sk->protinfo.rose->timer > 0) { - rose_reset_timer(sk); + rose_set_timer(sk); return; } /* - * Timer has expired, it may have been T1, T2, or T3. We can tell + * Timer has expired, it may have been T1, T2, T3 or HB. We can tell * by the socket state. */ switch (sk->protinfo.rose->state) { + case ROSE_STATE_3: /* HB */ + if (sk->protinfo.rose->condition & ROSE_COND_ACK_PENDING) { + sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING; + rose_enquiry_response(sk); + } + break; + case ROSE_STATE_1: /* T1 */ case ROSE_STATE_4: /* T2 */ rose_write_internal(sk, ROSE_CLEAR_REQUEST); diff --git a/net/rose/sysctl_net_rose.c b/net/rose/sysctl_net_rose.c index 558702dbd..c899a1837 100644 --- a/net/rose/sysctl_net_rose.c +++ b/net/rose/sysctl_net_rose.c @@ -10,12 +10,13 @@ #include <net/ax25.h> #include <net/rose.h> -static int min_timer[] = {1 * PR_SLOWHZ}; -static int max_timer[] = {300 * PR_SLOWHZ}; -static int min_idle[] = {0 * PR_SLOWHZ}; -static int max_idle[] = {65535 * PR_SLOWHZ}; -static int min_route[] = {0}; -static int max_route[] = {0}; +static int min_timer[] = {1 * ROSE_SLOWHZ}; +static int max_timer[] = {300 * ROSE_SLOWHZ}; +static int min_idle[] = {0 * ROSE_SLOWHZ}; +static int max_idle[] = {65535 * ROSE_SLOWHZ}; +static int min_route[] = {0}, max_route[] = {1}; +static int min_ftimer[] = {60 * ROSE_SLOWHZ}; +static int max_ftimer[] = {600 * ROSE_SLOWHZ}; static struct ctl_table_header *rose_table_header; @@ -35,9 +36,15 @@ static ctl_table rose_table[] = { {NET_ROSE_NO_ACTIVITY_TIMEOUT, "no_activity_timeout", &sysctl_rose_no_activity_timeout, sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL, &min_idle, &max_idle}, + {NET_ROSE_ACK_HOLD_BACK_TIMEOUT, "acknowledge_hold_back_timeout", + &sysctl_rose_ack_hold_back_timeout, sizeof(int), 0644, NULL, + &proc_dointvec_minmax, &sysctl_intvec, NULL, &min_timer, &max_timer}, {NET_ROSE_ROUTING_CONTROL, "routing_control", &sysctl_rose_routing_control, sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL, &min_route, &max_route}, + {NET_ROSE_LINK_FAIL_TIMEOUT, "link_fail_timeout", + &sysctl_rose_link_fail_timeout, sizeof(int), 0644, NULL, + &proc_dointvec_minmax, &sysctl_intvec, NULL, &min_ftimer, &max_ftimer}, {0} }; |