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/netrom/af_netrom.c | |
parent | 7206675c40394c78a90e74812bbdbf8cf3cca1be (diff) |
Import of Linux/MIPS 2.1.36
Diffstat (limited to 'net/netrom/af_netrom.c')
-rw-r--r-- | net/netrom/af_netrom.c | 641 |
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 |