summaryrefslogtreecommitdiffstats
path: root/net/netrom/af_netrom.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-04-29 21:13:14 +0000
committer <ralf@linux-mips.org>1997-04-29 21:13:14 +0000
commit19c9bba94152148523ba0f7ef7cffe3d45656b11 (patch)
tree40b1cb534496a7f1ca0f5c314a523c69f1fee464 /net/netrom/af_netrom.c
parent7206675c40394c78a90e74812bbdbf8cf3cca1be (diff)
Import of Linux/MIPS 2.1.36
Diffstat (limited to 'net/netrom/af_netrom.c')
-rw-r--r--net/netrom/af_netrom.c641
1 files changed, 288 insertions, 353 deletions
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index 6eac7e8a8..d66094134 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -1,10 +1,10 @@
/*
- * NET/ROM release 005
+ * NET/ROM release 006
*
* 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.037
+ * This code REQUIRES 2.1.15 or higher/ NET3.038
*
* This module:
* This module is free software; you can redistribute it and/or
@@ -29,10 +29,12 @@
* NET/ROM 004 Jonathan(G4KLX) Converted to module.
* NET/ROM 005 Jonathan(G4KLX) Linux 2.1
* Alan(GW4PTS) Started POSIXisms
+ * NET/ROM 006 Alan(GW4PTS) Brought in line with the ANK changes
*/
-
+
#include <linux/config.h>
#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
+#include <linux/module.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
@@ -72,13 +74,47 @@ int sysctl_netrom_transport_acknowledge_delay = NR_DEFAULT_T2;
int sysctl_netrom_transport_busy_delay = NR_DEFAULT_T4;
int sysctl_netrom_transport_requested_window_size = NR_DEFAULT_WINDOW;
int sysctl_netrom_transport_no_activity_timeout = NR_DEFAULT_IDLE;
-int sysctl_netrom_transport_packet_length = NR_DEFAULT_PACLEN;
-int sysctl_netrom_routing_control = 1;
+int sysctl_netrom_routing_control = NR_DEFAULT_ROUTING;
+int sysctl_netrom_link_fails_count = NR_DEFAULT_FAILS;
static unsigned short circuit = 0x101;
static struct sock *volatile nr_list = NULL;
+static struct proto_ops nr_proto_ops;
+
+static void nr_free_sock(struct sock *sk)
+{
+ kfree_s(sk->protinfo.nr, sizeof(*sk->protinfo.nr));
+
+ sk_free(sk);
+
+ MOD_DEC_USE_COUNT;
+}
+
+static struct sock *nr_alloc_sock(void)
+{
+ struct sock *sk;
+ nr_cb *nr;
+
+ if ((sk = sk_alloc(GFP_ATOMIC)) == NULL)
+ return NULL;
+
+ if ((nr = (nr_cb *)kmalloc(sizeof(*nr), GFP_ATOMIC)) == NULL) {
+ sk_free(sk);
+ return NULL;
+ }
+
+ MOD_INC_USE_COUNT;
+
+ memset(nr, 0x00, sizeof(*nr));
+
+ sk->protinfo.nr = nr;
+ nr->sk = sk;
+
+ return sk;
+}
+
/*
* Socket removal during an interrupt is now safe.
*/
@@ -86,7 +122,7 @@ static void nr_remove_socket(struct sock *sk)
{
struct sock *s;
unsigned long flags;
-
+
save_flags(flags);
cli();
@@ -115,7 +151,7 @@ static void nr_remove_socket(struct sock *sk)
static void nr_kill_by_device(struct device *dev)
{
struct sock *s;
-
+
for (s = nr_list; s != NULL; s = s->next) {
if (s->protinfo.nr->device == dev) {
s->protinfo.nr->state = NR_STATE_0;
@@ -138,7 +174,7 @@ static int nr_device_event(struct notifier_block *this, unsigned long event, voi
if (event != NETDEV_DOWN)
return NOTIFY_DONE;
-
+
nr_kill_by_device(dev);
nr_rt_device_down(dev);
@@ -253,15 +289,15 @@ void nr_destroy_socket(struct sock *sk) /* Not static as it's used by the timer
{
struct sk_buff *skb;
unsigned long flags;
-
+
save_flags(flags);
cli();
-
+
del_timer(&sk->timer);
-
+
nr_remove_socket(sk);
nr_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 */
@@ -271,16 +307,16 @@ void nr_destroy_socket(struct sock *sk) /* Not static as it's used by the timer
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 = nr_destroy_timer;
sk->timer.data = (unsigned long)sk;
add_timer(&sk->timer);
} else {
- kfree_s(sk->protinfo.nr, sizeof(*sk->protinfo.nr));
- sk_free(sk);
+ nr_free_sock(sk);
}
restore_flags(flags);
@@ -290,11 +326,6 @@ void nr_destroy_socket(struct sock *sk) /* Not static as it's used by the timer
* Handling for system calls applied via the various interfaces to a
* NET/ROM socket object.
*/
-
-static int nr_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg)
-{
- return -EINVAL;
-}
/*
* dl1bke 960311: set parameters for existing NET/ROM connections,
@@ -307,12 +338,12 @@ static int nr_ctl_ioctl(const unsigned int cmd, void *arg)
struct sock *sk;
unsigned long flags;
int err;
-
+
if ((err = verify_area(VERIFY_READ, arg, sizeof(nr_ctl))) != 0)
return err;
copy_from_user(&nr_ctl, arg, sizeof(nr_ctl));
-
+
if ((sk = nr_find_socket(nr_ctl.index, nr_ctl.id)) == NULL)
return -ENOTCONN;
@@ -333,8 +364,7 @@ static int nr_ctl_ioctl(const unsigned int cmd, void *arg)
case NETROM_T1:
if (nr_ctl.arg < 1)
return -EINVAL;
- sk->protinfo.nr->rtt = (nr_ctl.arg * PR_SLOWHZ) / 2;
- sk->protinfo.nr->t1 = nr_ctl.arg * PR_SLOWHZ;
+ sk->protinfo.nr->t1 = nr_ctl.arg * NR_SLOWHZ;
save_flags(flags); cli();
if (sk->protinfo.nr->t1timer > sk->protinfo.nr->t1)
sk->protinfo.nr->t1timer = sk->protinfo.nr->t1;
@@ -345,7 +375,7 @@ static int nr_ctl_ioctl(const unsigned int cmd, void *arg)
if (nr_ctl.arg < 1)
return -EINVAL;
save_flags(flags); cli();
- sk->protinfo.nr->t2 = nr_ctl.arg * PR_SLOWHZ;
+ sk->protinfo.nr->t2 = nr_ctl.arg * NR_SLOWHZ;
if (sk->protinfo.nr->t2timer > sk->protinfo.nr->t2)
sk->protinfo.nr->t2timer = sk->protinfo.nr->t2;
restore_flags(flags);
@@ -362,7 +392,7 @@ static int nr_ctl_ioctl(const unsigned int cmd, void *arg)
if (nr_ctl.arg < 1)
return -EINVAL;
save_flags(flags); cli();
- sk->protinfo.nr->t4 = nr_ctl.arg * PR_SLOWHZ;
+ sk->protinfo.nr->t4 = nr_ctl.arg * NR_SLOWHZ;
if (sk->protinfo.nr->t4timer > sk->protinfo.nr->t4)
sk->protinfo.nr->t4timer = sk->protinfo.nr->t4;
restore_flags(flags);
@@ -372,20 +402,12 @@ static int nr_ctl_ioctl(const unsigned int cmd, void *arg)
if (nr_ctl.arg < 1)
return -EINVAL;
save_flags(flags); cli();
- sk->protinfo.nr->idle = nr_ctl.arg * 60 * PR_SLOWHZ;
+ sk->protinfo.nr->idle = nr_ctl.arg * 60 * NR_SLOWHZ;
if (sk->protinfo.nr->idletimer > sk->protinfo.nr->idle)
sk->protinfo.nr->idletimer = sk->protinfo.nr->idle;
restore_flags(flags);
break;
- case NETROM_PACLEN:
- if (nr_ctl.arg < 16 || nr_ctl.arg > 65535)
- return -EINVAL;
- if (nr_ctl.arg > 236) /* we probably want this */
- printk(KERN_WARNING "nr_ctl_ioctl: Warning --- huge paclen %d\n", (int)nr_ctl.arg);
- sk->protinfo.nr->paclen = nr_ctl.arg;
- break;
-
default:
return -EINVAL;
}
@@ -396,66 +418,53 @@ static int nr_ctl_ioctl(const unsigned int cmd, void *arg)
static int nr_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_NETROM)
- 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 NETROM_T1:
if (opt < 1)
return -EINVAL;
- sk->protinfo.nr->rtt = (opt * PR_SLOWHZ) / 2;
+ sk->protinfo.nr->t1 = opt * NR_SLOWHZ;
return 0;
case NETROM_T2:
if (opt < 1)
return -EINVAL;
- sk->protinfo.nr->t2 = opt * PR_SLOWHZ;
+ sk->protinfo.nr->t2 = opt * NR_SLOWHZ;
return 0;
-
+
case NETROM_N2:
if (opt < 1 || opt > 31)
return -EINVAL;
sk->protinfo.nr->n2 = opt;
return 0;
-
+
case NETROM_T4:
if (opt < 1)
return -EINVAL;
- sk->protinfo.nr->t4 = opt * PR_SLOWHZ;
+ sk->protinfo.nr->t4 = opt * NR_SLOWHZ;
return 0;
-
+
case NETROM_IDLE:
if (opt < 1)
return -EINVAL;
- sk->protinfo.nr->idle = opt * 60 * PR_SLOWHZ;
+ sk->protinfo.nr->idle = opt * 60 * NR_SLOWHZ;
return 0;
-
+
case NETROM_HDRINCL:
sk->protinfo.nr->hdrincl = opt ? 1 : 0;
return 0;
- case NETROM_PACLEN:
- if (opt < 1 || opt > 65536)
- return -EINVAL;
- sk->protinfo.nr->paclen = opt;
- return 0;
-
default:
return -ENOPROTOOPT;
}
@@ -464,67 +473,59 @@ static int nr_setsockopt(struct socket *sock, int level, int optname,
static int nr_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_NETROM)
- return -EOPNOTSUPP;
+ return -ENOPROTOOPT;
+ if (get_user(len, optlen))
+ return -EFAULT;
+
switch (optname) {
case NETROM_T1:
- val = (sk->protinfo.nr->t1 * 2) / PR_SLOWHZ;
+ val = (sk->protinfo.nr->t1 * 2) / NR_SLOWHZ;
break;
-
+
case NETROM_T2:
- val = sk->protinfo.nr->t2 / PR_SLOWHZ;
+ val = sk->protinfo.nr->t2 / NR_SLOWHZ;
break;
-
+
case NETROM_N2:
val = sk->protinfo.nr->n2;
break;
-
+
case NETROM_T4:
- val = sk->protinfo.nr->t4 / PR_SLOWHZ;
+ val = sk->protinfo.nr->t4 / NR_SLOWHZ;
break;
-
+
case NETROM_IDLE:
- val = sk->protinfo.nr->idle / (PR_SLOWHZ * 60);
+ val = sk->protinfo.nr->idle / (NR_SLOWHZ * 60);
break;
-
+
case NETROM_HDRINCL:
val = sk->protinfo.nr->hdrincl;
break;
- case NETROM_PACLEN:
- val = sk->protinfo.nr->paclen;
- break;
-
default:
return -ENOPROTOOPT;
}
- if ((err = verify_area(VERIFY_WRITE, optlen, sizeof(int))) != 0)
- return err;
-
- put_user(sizeof(int), 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, (int *)optval);
+ if (copy_to_user(optval, &val, len))
+ return -EFAULT;
return 0;
}
static int nr_listen(struct socket *sock, int backlog)
{
- struct sock *sk = (struct sock *)sock->data;
+ struct sock *sk = sock->sk;
if (sk->state != TCP_LISTEN) {
memset(&sk->protinfo.nr->user_addr, '\0', AX25_ADDR_LEN);
@@ -536,18 +537,6 @@ static int nr_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 nr_create(struct socket *sock, int protocol)
{
struct sock *sk;
@@ -556,85 +545,30 @@ static int nr_create(struct socket *sock, int protocol)
if (sock->type != SOCK_SEQPACKET || protocol != 0)
return -ESOCKTNOSUPPORT;
- if ((sk = sk_alloc(GFP_ATOMIC)) == NULL)
+ if ((sk = nr_alloc_sock()) == NULL)
return -ENOMEM;
- if ((nr = (nr_cb *)kmalloc(sizeof(*nr), GFP_ATOMIC)) == NULL) {
- sk_free(sk);
- return -ENOMEM;
- }
+ nr = sk->protinfo.nr;
- 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 = NETROM_MTU; /* 236 */
- sk->zapped = 1;
- sk->window = sysctl_netrom_transport_requested_window_size;
-
- 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 = &nr_proto_ops;
+ sk->protocol = protocol;
+ sk->mtu = NETROM_MTU; /* 236 */
skb_queue_head_init(&nr->ack_queue);
skb_queue_head_init(&nr->reseq_queue);
skb_queue_head_init(&nr->frag_queue);
- nr->my_index = 0;
- nr->my_id = 0;
- nr->rtt = sysctl_netrom_transport_timeout / 2;
- nr->t1 = sysctl_netrom_transport_timeout;
- nr->t2 = sysctl_netrom_transport_acknowledge_delay;
- nr->n2 = sysctl_netrom_transport_maximum_tries;
- nr->t4 = sysctl_netrom_transport_busy_delay;
- nr->idle = sysctl_netrom_transport_no_activity_timeout;
- nr->paclen = sysctl_netrom_transport_packet_length;
-
- nr->t1timer = 0;
- nr->t2timer = 0;
- nr->t4timer = 0;
- nr->idletimer = 0;
- nr->n2count = 0;
-
- nr->va = 0;
- nr->vr = 0;
- nr->vs = 0;
- nr->vl = 0;
-
- nr->your_index = 0;
- nr->your_id = 0;
-
- nr->my_index = 0;
- nr->my_id = 0;
-
- nr->bpqext = 1;
- nr->fraglen = 0;
- nr->hdrincl = 0;
- nr->state = NR_STATE_0;
- nr->device = NULL;
-
- memset(&nr->source_addr, '\0', AX25_ADDR_LEN);
- memset(&nr->user_addr, '\0', AX25_ADDR_LEN);
- memset(&nr->dest_addr, '\0', AX25_ADDR_LEN);
-
- nr->sk = sk;
- sk->protinfo.nr = nr;
+ nr->t1 = sysctl_netrom_transport_timeout;
+ nr->t2 = sysctl_netrom_transport_acknowledge_delay;
+ nr->n2 = sysctl_netrom_transport_maximum_tries;
+ nr->t4 = sysctl_netrom_transport_busy_delay;
+ nr->idle = sysctl_netrom_transport_no_activity_timeout;
+ nr->window = sysctl_netrom_transport_requested_window_size;
+
+ nr->bpqext = 1;
+ nr->state = NR_STATE_0;
return 0;
}
@@ -647,82 +581,56 @@ static struct sock *nr_make_new(struct sock *osk)
if (osk->type != SOCK_SEQPACKET)
return NULL;
- if ((sk = (struct sock *)sk_alloc(GFP_ATOMIC)) == NULL)
+ if ((sk = nr_alloc_sock()) == NULL)
return NULL;
- if ((nr = (nr_cb *)kmalloc(sizeof(*nr), GFP_ATOMIC)) == NULL) {
- sk_free(sk);
- return NULL;
- }
+ nr = sk->protinfo.nr;
+
+ sock_init_data(NULL, sk);
- 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;
+ 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;
skb_queue_head_init(&nr->ack_queue);
skb_queue_head_init(&nr->reseq_queue);
skb_queue_head_init(&nr->frag_queue);
- nr->rtt = osk->protinfo.nr->rtt;
- nr->t1 = osk->protinfo.nr->t1;
- nr->t2 = osk->protinfo.nr->t2;
- nr->n2 = osk->protinfo.nr->n2;
- nr->t4 = osk->protinfo.nr->t4;
- nr->idle = osk->protinfo.nr->idle;
- nr->paclen = osk->protinfo.nr->paclen;
-
- nr->device = osk->protinfo.nr->device;
- nr->bpqext = osk->protinfo.nr->bpqext;
- nr->hdrincl = osk->protinfo.nr->hdrincl;
- nr->fraglen = 0;
-
- nr->t1timer = 0;
- nr->t2timer = 0;
- nr->t4timer = 0;
- nr->idletimer = 0;
- nr->n2count = 0;
-
- nr->va = 0;
- nr->vr = 0;
- nr->vs = 0;
- nr->vl = 0;
-
- sk->protinfo.nr = nr;
- nr->sk = sk;
+ nr->t1 = osk->protinfo.nr->t1;
+ nr->t2 = osk->protinfo.nr->t2;
+ nr->n2 = osk->protinfo.nr->n2;
+ nr->t4 = osk->protinfo.nr->t4;
+ nr->idle = osk->protinfo.nr->idle;
+ nr->window = osk->protinfo.nr->window;
+
+ nr->device = osk->protinfo.nr->device;
+ nr->bpqext = osk->protinfo.nr->bpqext;
+ nr->hdrincl = osk->protinfo.nr->hdrincl;
return sk;
}
static int nr_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 nr_create(newsock, sk->protocol);
}
static int nr_release(struct socket *sock, struct socket *peer)
{
- struct sock *sk = (struct sock *)sock->data;
+ struct sock *sk = sock->sk;
if (sk == NULL) return 0;
@@ -749,7 +657,7 @@ static int nr_release(struct socket *sock, struct socket *peer)
nr_write_internal(sk, NR_DISCACK);
sk->protinfo.nr->state = NR_STATE_0;
sk->state = TCP_CLOSE;
- sk->shutdown = SEND_SHUTDOWN;
+ sk->shutdown |= SEND_SHUTDOWN;
sk->state_change(sk);
sk->dead = 1;
nr_destroy_socket(sk);
@@ -759,7 +667,7 @@ static int nr_release(struct socket *sock, struct socket *peer)
nr_clear_queues(sk);
sk->protinfo.nr->n2count = 0;
nr_write_internal(sk, NR_DISCREQ);
- sk->protinfo.nr->t1timer = sk->protinfo.nr->t1 = nr_calculate_t1(sk);
+ sk->protinfo.nr->t1timer = sk->protinfo.nr->t1;
sk->protinfo.nr->t2timer = 0;
sk->protinfo.nr->t4timer = 0;
sk->protinfo.nr->state = NR_STATE_2;
@@ -774,30 +682,30 @@ static int nr_release(struct socket *sock, struct socket *peer)
break;
}
- sock->data = NULL;
- sk->socket = NULL; /* Not used, but we should do this. **/
+ sock->sk = NULL;
+ sk->socket = NULL; /* Not used, but we should do this */
return 0;
}
static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
- struct sock *sk;
+ struct sock *sk = sock->sk;
struct full_sockaddr_ax25 *addr = (struct full_sockaddr_ax25 *)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_ax25) && addr_len != sizeof(struct full_sockaddr_ax25))
return -EINVAL;
+ if (addr->fsa_ax25.sax25_family != AF_NETROM)
+ return -EINVAL;
+
if ((dev = nr_dev_get(&addr->fsa_ax25.sax25_call)) == NULL) {
- if (sk->debug)
- printk("NET/ROM: bind failed: invalid node callsign\n");
+ SOCK_DEBUG(sk, "NET/ROM: bind failed: invalid node callsign\n");
return -EADDRNOTAVAIL;
}
@@ -826,40 +734,40 @@ static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
nr_insert_socket(sk);
sk->zapped = 0;
-
- if (sk->debug)
- printk("NET/ROM: socket is bound\n");
-
+ SOCK_DEBUG(sk, "NET/ROM: socket is bound\n");
return 0;
}
static int nr_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_ax25 *addr = (struct sockaddr_ax25 *)uaddr;
ax25_address *user, *source = NULL;
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;
sock->state = SS_UNCONNECTED;
if (addr_len != sizeof(struct sockaddr_ax25) && addr_len != sizeof(struct full_sockaddr_ax25))
return -EINVAL;
+ if (addr->sax25_family != AF_NETROM)
+ return -EINVAL;
+
if (sk->zapped) { /* Must bind first - autobinding in this may or may not work */
sk->zapped = 0;
@@ -890,14 +798,14 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr,
sk->protinfo.nr->my_id = circuit % 256;
circuit++;
-
+
/* Move to connecting socket, start sending Connect Requests */
sock->state = SS_CONNECTING;
sk->state = TCP_SYN_SENT;
nr_establish_data_link(sk);
sk->protinfo.nr->state = NR_STATE_1;
nr_set_timer(sk);
-
+
/* Now the loop */
if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK))
return -EINPROGRESS;
@@ -920,14 +828,14 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr,
sock->state = SS_UNCONNECTED;
return sock_error(sk); /* Always set at this point */
}
-
+
sock->state = SS_CONNECTED;
sti();
-
+
return 0;
}
-
+
static int nr_socketpair(struct socket *sock1, struct socket *sock2)
{
return -EOPNOTSUPP;
@@ -939,19 +847,20 @@ static int nr_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)
+ nr_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
@@ -961,7 +870,7 @@ static int nr_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) {
@@ -979,7 +888,7 @@ static int nr_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;
}
@@ -988,10 +897,8 @@ static int nr_getname(struct socket *sock, struct sockaddr *uaddr,
int *uaddr_len, int peer)
{
struct full_sockaddr_ax25 *sax = (struct full_sockaddr_ax25 *)uaddr;
- struct sock *sk;
-
- sk = (struct sock *)sock->data;
-
+ struct sock *sk = sock->sk;
+
if (peer != 0) {
if (sk->state != TCP_ESTABLISHED)
return -ENOTCONN;
@@ -1009,7 +916,7 @@ static int nr_getname(struct socket *sock, struct sockaddr *uaddr,
return 0;
}
-
+
int nr_rx_frame(struct sk_buff *skb, struct device *dev)
{
struct sock *sk;
@@ -1061,7 +968,7 @@ int nr_rx_frame(struct sk_buff *skb, struct device *dev)
if ((frametype & 0x0F) != NR_CONNREQ)
return 0;
-
+
sk = nr_find_listener(dest);
user = (ax25_address *)(skb->data + 21);
@@ -1086,18 +993,18 @@ int nr_rx_frame(struct sk_buff *skb, struct device *dev)
make->protinfo.nr->my_index = circuit / 256;
make->protinfo.nr->my_id = circuit % 256;
-
+
circuit++;
/* Window negotiation */
- if (window < make->window)
- make->window = window;
+ if (window < make->protinfo.nr->window)
+ make->protinfo.nr->window = window;
/* L4 timeout negotiation */
if (skb->len == 37) {
timeout = skb->data[36] * 256 + skb->data[35];
- if (timeout * PR_SLOWHZ < make->protinfo.nr->rtt * 2)
- make->protinfo.nr->rtt = (timeout * PR_SLOWHZ) / 2;
+ if (timeout * NR_SLOWHZ < make->protinfo.nr->t1)
+ make->protinfo.nr->t1 = timeout * NR_SLOWHZ;
make->protinfo.nr->bpqext = 1;
} else {
make->protinfo.nr->bpqext = 0;
@@ -1126,20 +1033,17 @@ int nr_rx_frame(struct sk_buff *skb, struct device *dev)
return 1;
}
-static int nr_sendmsg(struct socket *sock, struct msghdr *msg, int len, int noblock, int flags)
+static int nr_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_ax25 *usax = (struct sockaddr_ax25 *)msg->msg_name;
int err;
struct sockaddr_ax25 sax;
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)
@@ -1152,7 +1056,7 @@ static int nr_sendmsg(struct socket *sock, struct msghdr *msg, int len, int nobl
if (sk->protinfo.nr->device == NULL)
return -ENETUNREACH;
-
+
if (usax) {
if (msg->msg_namelen < sizeof(sax))
return -EINVAL;
@@ -1167,33 +1071,23 @@ static int nr_sendmsg(struct socket *sock, struct msghdr *msg, int len, int nobl
sax.sax25_family = AF_NETROM;
sax.sax25_call = sk->protinfo.nr->dest_addr;
}
-
- if (sk->debug)
- printk("NET/ROM: sendto: Addresses built.\n");
+ SOCK_DEBUG(sk, "NET/ROM: sendto: Addresses built.\n");
/* Build a packet */
- if (sk->debug)
- printk("NET/ROM: sendto: building packet.\n");
-
+ SOCK_DEBUG(sk, "NET/ROM: sendto: building packet.\n");
size = len + AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + NR_NETWORK_LEN + NR_TRANSPORT_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 NET/ROM header
*/
asmptr = skb_push(skb, NR_TRANSPORT_LEN);
-
- if (sk->debug)
- printk("Building NET/ROM Header.\n");
+ SOCK_DEBUG(sk, "Building NET/ROM Header.\n");
/* Build a NET/ROM Transport header */
@@ -1202,9 +1096,7 @@ static int nr_sendmsg(struct socket *sock, struct msghdr *msg, int len, int nobl
*asmptr++ = 0; /* To be filled in later */
*asmptr++ = 0; /* Ditto */
*asmptr++ = NR_INFO;
-
- if (sk->debug)
- printk("Built header.\n");
+ SOCK_DEBUG(sk, "Built header.\n");
/*
* Put the data on the end
@@ -1213,15 +1105,11 @@ static int nr_sendmsg(struct socket *sock, struct msghdr *msg, int len, int nobl
skb->h.raw = skb_put(skb, len);
asmptr = skb->h.raw;
-
- if (sk->debug)
- printk("NET/ROM: Appending user data\n");
+ SOCK_DEBUG(sk, "NET/ROM: Appending user data\n");
/* User data follows immediately after the NET/ROM transport header */
memcpy_fromiovec(asmptr, msg->msg_iov, len);
-
- if (sk->debug)
- printk("NET/ROM: Transmitting buffer\n");
+ SOCK_DEBUG(sk, "NET/ROM: Transmitting buffer\n");
if (sk->state != TCP_ESTABLISHED) {
kfree_skb(skb, FREE_WRITE);
@@ -1234,18 +1122,15 @@ static int nr_sendmsg(struct socket *sock, struct msghdr *msg, int len, int nobl
}
-static int nr_recvmsg(struct socket *sock, struct msghdr *msg, int size, int noblock,
- int flags, int *addr_len)
+static int nr_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_ax25 *sax = (struct sockaddr_ax25 *)msg->msg_name;
int copied;
struct sk_buff *skb;
int er;
- 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
@@ -1255,7 +1140,7 @@ static int nr_recvmsg(struct socket *sock, struct msghdr *msg, int size, int nob
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.nr->hdrincl) {
@@ -1271,18 +1156,14 @@ static int nr_recvmsg(struct socket *sock, struct msghdr *msg, int size, int nob
}
skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
-
- if (sax != NULL) {
- struct sockaddr_ax25 addr;
-
- addr.sax25_family = AF_NETROM;
- memcpy(&addr.sax25_call, skb->data + 7, AX25_ADDR_LEN);
-
- *sax = addr;
- *addr_len = sizeof(*sax);
+ if (sax != NULL) {
+ sax->sax25_family = AF_NETROM;
+ memcpy(sax->sax25_call.ax25_call, skb->data + 7, AX25_ADDR_LEN);
}
+ msg->msg_namelen = sizeof(*sax);
+
skb_free_datagram(sk, skb);
return copied;
@@ -1293,16 +1174,9 @@ static int nr_shutdown(struct socket *sk, int how)
return -EOPNOTSUPP;
}
-static int nr_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 nr_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;
@@ -1310,7 +1184,7 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case TIOCOUTQ:
if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(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, (int *)arg);
@@ -1376,43 +1250,43 @@ static int nr_get_info(char *buffer, char **start, off_t offset, int length, int
int len = 0;
off_t pos = 0;
off_t begin = 0;
-
+
cli();
- len += sprintf(buffer, "user_addr dest_node src_node dev my your st vs vr va t1 t2 n2 rtt wnd paclen Snd-Q Rcv-Q\n");
+ len += sprintf(buffer, "user_addr dest_node src_node dev my your st vs vr va t1 t2 n2 wnd Snd-Q Rcv-Q\n");
for (s = nr_list; s != NULL; s = s->next) {
if ((dev = s->protinfo.nr->device) == NULL)
devname = "???";
else
devname = dev->name;
-
+
len += sprintf(buffer + len, "%-9s ",
ax2asc(&s->protinfo.nr->user_addr));
len += sprintf(buffer + len, "%-9s ",
ax2asc(&s->protinfo.nr->dest_addr));
- len += sprintf(buffer + len, "%-9s %-3s %02X/%02X %02X/%02X %2d %3d %3d %3d %3d/%03d %2d/%02d %2d/%02d %3d %3d %6d %5d %5d\n",
+ len += sprintf(buffer + len, "%-9s %-3s %02X/%02X %02X/%02X %2d %3d %3d %3d %3d/%03d %2d/%02d %2d/%02d %3d %5d %5d\n",
ax2asc(&s->protinfo.nr->source_addr),
devname, s->protinfo.nr->my_index, s->protinfo.nr->my_id,
s->protinfo.nr->your_index, s->protinfo.nr->your_id,
s->protinfo.nr->state,
s->protinfo.nr->vs, s->protinfo.nr->vr, s->protinfo.nr->va,
- s->protinfo.nr->t1timer / PR_SLOWHZ,
- s->protinfo.nr->t1 / PR_SLOWHZ,
- s->protinfo.nr->t2timer / PR_SLOWHZ,
- s->protinfo.nr->t2 / PR_SLOWHZ,
- s->protinfo.nr->n2count, s->protinfo.nr->n2,
- s->protinfo.nr->rtt / PR_SLOWHZ,
- s->window, s->protinfo.nr->paclen,
- s->wmem_alloc, s->rmem_alloc);
-
+ s->protinfo.nr->t1timer / NR_SLOWHZ,
+ s->protinfo.nr->t1 / NR_SLOWHZ,
+ s->protinfo.nr->t2timer / NR_SLOWHZ,
+ s->protinfo.nr->t2 / NR_SLOWHZ,
+ s->protinfo.nr->n2count,
+ s->protinfo.nr->n2,
+ s->protinfo.nr->window,
+ 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;
}
@@ -1427,10 +1301,15 @@ static int nr_get_info(char *buffer, char **start, off_t offset, int length, int
return(len);
}
-struct proto_ops nr_proto_ops = {
+static struct net_proto_family nr_family_ops =
+{
AF_NETROM,
-
- nr_create,
+ nr_create
+};
+
+static struct proto_ops nr_proto_ops = {
+ AF_NETROM,
+
nr_dup,
nr_release,
nr_bind,
@@ -1438,18 +1317,18 @@ struct proto_ops nr_proto_ops = {
nr_socketpair,
nr_accept,
nr_getname,
- nr_select,
+ datagram_poll,
nr_ioctl,
nr_listen,
nr_shutdown,
nr_setsockopt,
nr_getsockopt,
- nr_fcntl,
+ sock_no_fcntl,
nr_sendmsg,
nr_recvmsg
};
-struct notifier_block nr_dev_notifier = {
+static struct notifier_block nr_dev_notifier = {
nr_device_event,
0
};
@@ -1475,18 +1354,32 @@ static struct proc_dir_entry proc_net_nr_nodes = {
};
#endif
+static struct device dev_nr[] = {
+ {"nr0", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, nr_init},
+ {"nr1", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, nr_init},
+ {"nr2", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, nr_init},
+ {"nr3", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, nr_init}
+};
+
void nr_proto_init(struct net_proto *pro)
{
- sock_register(nr_proto_ops.family, &nr_proto_ops);
+ int i;
+
+ sock_register(&nr_family_ops);
register_netdevice_notifier(&nr_dev_notifier);
- printk(KERN_INFO "G4KLX NET/ROM for Linux. Version 0.5 for AX25.034 Linux 2.1\n");
+ printk(KERN_INFO "G4KLX NET/ROM for Linux. Version 0.6 for AX25.035 Linux 2.1\n");
if (!ax25_protocol_register(AX25_P_NETROM, nr_route_frame))
printk(KERN_ERR "NET/ROM unable to register protocol with AX.25\n");
if (!ax25_linkfail_register(nr_link_failed))
printk(KERN_ERR "NET/ROM unable to register linkfail handler with AX.25\n");
+ for (i = 0; i < 4; i++)
+ register_netdev(&dev_nr[i]);
+
+#ifdef CONFIG_SYSCTL
nr_register_sysctl();
+#endif
#ifdef CONFIG_PROC_FS
proc_net_register(&proc_net_nr);
@@ -1495,4 +1388,46 @@ void nr_proto_init(struct net_proto *pro)
#endif
}
+#ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
+int init_module(void)
+{
+ nr_proto_init(NULL);
+
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ int i;
+
+#ifdef CONFIG_PROC_FS
+ proc_net_unregister(PROC_NET_NR);
+ proc_net_unregister(PROC_NET_NR_NEIGH);
+ proc_net_unregister(PROC_NET_NR_NODES);
+#endif
+ nr_rt_free();
+
+ ax25_protocol_release(AX25_P_NETROM);
+ ax25_linkfail_release(nr_link_failed);
+
+ unregister_netdevice_notifier(&nr_dev_notifier);
+
+#ifdef CONFIG_SYSCTL
+ nr_unregister_sysctl();
+#endif
+ sock_unregister(AF_NETROM);
+
+ for (i = 0; i < 4; i++) {
+ if (dev_nr[i].priv != NULL) {
+ kfree(dev_nr[i].priv);
+ dev_nr[i].priv = NULL;
+ unregister_netdev(&dev_nr[i]);
+ }
+ }
+}
+
+#endif
+
#endif