summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/ax25/af_ax25.c147
-rw-r--r--net/ax25/ax25_addr.c3
-rw-r--r--net/ax25/ax25_dev.c15
-rw-r--r--net/ax25/ax25_ds_in.c240
-rw-r--r--net/ax25/ax25_ds_subr.c29
-rw-r--r--net/ax25/ax25_ds_timer.c23
-rw-r--r--net/ax25/ax25_iface.c15
-rw-r--r--net/ax25/ax25_in.c41
-rw-r--r--net/ax25/ax25_ip.c18
-rw-r--r--net/ax25/ax25_out.c28
-rw-r--r--net/ax25/ax25_route.c49
-rw-r--r--net/ax25/ax25_std_in.c3
-rw-r--r--net/ax25/ax25_std_subr.c3
-rw-r--r--net/ax25/ax25_std_timer.c3
-rw-r--r--net/ax25/ax25_subr.c6
-rw-r--r--net/ax25/ax25_timer.c3
-rw-r--r--net/ax25/ax25_uid.c9
-rw-r--r--net/ax25/sysctl_net_ax25.c5
-rw-r--r--net/lapb/lapb_iface.c7
-rw-r--r--net/netrom/af_netrom.c161
-rw-r--r--net/netrom/nr_dev.c17
-rw-r--r--net/netrom/nr_in.c11
-rw-r--r--net/netrom/nr_out.c3
-rw-r--r--net/netrom/nr_route.c28
-rw-r--r--net/netrom/nr_subr.c5
-rw-r--r--net/netrom/nr_timer.c3
-rw-r--r--net/netsyms.c3
-rw-r--r--net/rose/af_rose.c338
-rw-r--r--net/rose/rose_dev.c21
-rw-r--r--net/rose/rose_in.c20
-rw-r--r--net/rose/rose_link.c24
-rw-r--r--net/rose/rose_out.c11
-rw-r--r--net/rose/rose_route.c263
-rw-r--r--net/rose/rose_subr.c41
-rw-r--r--net/rose/rose_timer.c9
-rw-r--r--net/rose/sysctl_net_rose.c10
-rw-r--r--net/x25/Makefile3
-rw-r--r--net/x25/af_x25.c71
-rw-r--r--net/x25/x25_in.c7
-rw-r--r--net/x25/x25_link.c52
-rw-r--r--net/x25/x25_route.c6
-rw-r--r--net/x25/x25_subr.c102
42 files changed, 713 insertions, 1143 deletions
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index f3692d833..fe5d4dca6 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -1,9 +1,6 @@
/*
* AX.25 release 036
*
- * 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.15 or higher/ NET3.038
*
* This module:
@@ -94,6 +91,7 @@
* Jonathan(G4KLX) Support for packet forwarding.
* AX.25 036 Jonathan(G4KLX) Major restructuring.
* Joerg(DL1BKE) Fixed DAMA Slave.
+ * Jonathan(G4KLX) Fix widlcard listen parameter setting.
*/
#include <linux/config.h>
@@ -141,11 +139,11 @@ static struct proto_ops ax25_proto_ops;
void ax25_free_cb(ax25_cb *ax25)
{
if (ax25->digipeat != NULL) {
- kfree_s(ax25->digipeat, sizeof(ax25_digi));
+ kfree(ax25->digipeat);
ax25->digipeat = NULL;
}
- kfree_s(ax25, sizeof(ax25_cb));
+ kfree(ax25);
MOD_DEC_USE_COUNT;
}
@@ -472,7 +470,6 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void *arg)
if (ax25_dev->dama.slave && ax25->ax25_dev->values[AX25_VALUES_PROTOCOL] == AX25_PROTO_DAMA_SLAVE)
ax25_dama_off(ax25);
#endif
-
if (ax25->sk != NULL) {
ax25->sk->state = TCP_CLOSE;
ax25->sk->err = ENETRESET;
@@ -481,9 +478,8 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void *arg)
ax25->sk->state_change(ax25->sk);
ax25->sk->dead = 1;
}
-
ax25_set_timer(ax25);
- break;
+ break;
case AX25_WINDOW:
if (ax25->modulus == AX25_MODULUS) {
@@ -558,6 +554,51 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void *arg)
}
/*
+ * Fill in a created AX.25 created control block with the default
+ * values for a particular device.
+ */
+void ax25_fillin_cb(ax25_cb *ax25, ax25_dev *ax25_dev)
+{
+ ax25->ax25_dev = ax25_dev;
+
+ if (ax25->ax25_dev != NULL) {
+ ax25->rtt = ax25_dev->values[AX25_VALUES_T1] / 2;
+ ax25->t1 = ax25_dev->values[AX25_VALUES_T1];
+ ax25->t2 = ax25_dev->values[AX25_VALUES_T2];
+ ax25->t3 = ax25_dev->values[AX25_VALUES_T3];
+ ax25->n2 = ax25_dev->values[AX25_VALUES_N2];
+ ax25->paclen = ax25_dev->values[AX25_VALUES_PACLEN];
+ ax25->idle = ax25_dev->values[AX25_VALUES_IDLE];
+ ax25->backoff = ax25_dev->values[AX25_VALUES_BACKOFF];
+
+ if (ax25_dev->values[AX25_VALUES_AXDEFMODE]) {
+ ax25->modulus = AX25_EMODULUS;
+ ax25->window = ax25_dev->values[AX25_VALUES_EWINDOW];
+ } else {
+ ax25->modulus = AX25_MODULUS;
+ ax25->window = ax25_dev->values[AX25_VALUES_WINDOW];
+ }
+ } else {
+ ax25->rtt = AX25_DEF_T1 / 2;
+ ax25->t1 = AX25_DEF_T1;
+ ax25->t2 = AX25_DEF_T2;
+ ax25->t3 = AX25_DEF_T3;
+ ax25->n2 = AX25_DEF_N2;
+ ax25->paclen = AX25_DEF_PACLEN;
+ ax25->idle = AX25_DEF_IDLE;
+ ax25->backoff = AX25_DEF_BACKOFF;
+
+ if (AX25_DEF_AXDEFMODE) {
+ ax25->modulus = AX25_EMODULUS;
+ ax25->window = AX25_DEF_EWINDOW;
+ } else {
+ ax25->modulus = AX25_MODULUS;
+ ax25->window = AX25_DEF_WINDOW;
+ }
+ }
+}
+
+/*
* Create an empty AX.25 control block.
*/
ax25_cb *ax25_create_cb(void)
@@ -578,56 +619,14 @@ ax25_cb *ax25_create_cb(void)
init_timer(&ax25->timer);
- ax25->rtt = AX25_DEF_T1 / 2;
- ax25->t1 = AX25_DEF_T1;
- ax25->t2 = AX25_DEF_T2;
- ax25->t3 = AX25_DEF_T3;
- ax25->n2 = AX25_DEF_N2;
- ax25->paclen = AX25_DEF_PACLEN;
- ax25->idle = AX25_DEF_IDLE;
-
- if (AX25_DEF_AXDEFMODE) {
- ax25->modulus = AX25_EMODULUS;
- ax25->window = AX25_DEF_EWINDOW;
- } else {
- ax25->modulus = AX25_MODULUS;
- ax25->window = AX25_DEF_WINDOW;
- }
+ ax25_fillin_cb(ax25, NULL);
- ax25->backoff = AX25_DEF_BACKOFF;
- ax25->state = AX25_STATE_0;
+ ax25->state = AX25_STATE_0;
return ax25;
}
/*
- * Fill in a created AX.25 created control block with the default
- * values for a particular device.
- */
-void ax25_fillin_cb(ax25_cb *ax25, ax25_dev *ax25_dev)
-{
- ax25->ax25_dev = ax25_dev;
-
- ax25->rtt = ax25_dev->values[AX25_VALUES_T1];
- ax25->t1 = ax25_dev->values[AX25_VALUES_T1];
- ax25->t2 = ax25_dev->values[AX25_VALUES_T2];
- ax25->t3 = ax25_dev->values[AX25_VALUES_T3];
- ax25->n2 = ax25_dev->values[AX25_VALUES_N2];
- ax25->paclen = ax25_dev->values[AX25_VALUES_PACLEN];
- ax25->idle = ax25_dev->values[AX25_VALUES_IDLE];
-
- if (ax25_dev->values[AX25_VALUES_AXDEFMODE]) {
- ax25->modulus = AX25_EMODULUS;
- ax25->window = ax25_dev->values[AX25_VALUES_EWINDOW];
- } else {
- ax25->modulus = AX25_MODULUS;
- ax25->window = ax25_dev->values[AX25_VALUES_WINDOW];
- }
-
- ax25->backoff = ax25_dev->values[AX25_VALUES_BACKOFF];
-}
-
-/*
* Handling for system calls applied via the various interfaces to an
* AX25 socket object
*/
@@ -698,8 +697,8 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, char *op
sk->protinfo.ax25->modulus = opt ? AX25_EMODULUS : AX25_MODULUS;
return 0;
- case AX25_HDRINCL:
- sk->protinfo.ax25->hdrincl = opt ? 1 : 0;
+ case AX25_PIDINCL:
+ sk->protinfo.ax25->pidincl = opt ? 1 : 0;
return 0;
case AX25_IAMDIGI:
@@ -762,8 +761,8 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname, char *op
val = (sk->protinfo.ax25->modulus == AX25_EMODULUS);
break;
- case AX25_HDRINCL:
- val = sk->protinfo.ax25->hdrincl;
+ case AX25_PIDINCL:
+ val = sk->protinfo.ax25->pidincl;
break;
case AX25_IAMDIGI:
@@ -870,7 +869,7 @@ int ax25_create(struct socket *sock, int protocol)
return 0;
}
-struct sock *ax25_make_new(struct sock *osk, struct device *dev)
+struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev)
{
struct sock *sk;
ax25_cb *ax25;
@@ -910,7 +909,7 @@ struct sock *ax25_make_new(struct sock *osk, struct device *dev)
ax25->modulus = osk->protinfo.ax25->modulus;
ax25->backoff = osk->protinfo.ax25->backoff;
- ax25->hdrincl = osk->protinfo.ax25->hdrincl;
+ ax25->pidincl = osk->protinfo.ax25->pidincl;
ax25->iamdigi = osk->protinfo.ax25->iamdigi;
ax25->rtt = osk->protinfo.ax25->rtt;
ax25->t1 = osk->protinfo.ax25->t1;
@@ -921,7 +920,7 @@ struct sock *ax25_make_new(struct sock *osk, struct device *dev)
ax25->paclen = osk->protinfo.ax25->paclen;
ax25->window = osk->protinfo.ax25->window;
- ax25->ax25_dev = osk->protinfo.ax25->ax25_dev;
+ ax25->ax25_dev = ax25_dev;
ax25->source_addr = osk->protinfo.ax25->source_addr;
if (osk->protinfo.ax25->digipeat != NULL) {
@@ -1183,6 +1182,8 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
#ifdef CONFIG_AX25_DAMA_SLAVE
case AX25_PROTO_DAMA_SLAVE:
+ ax25->modulus = AX25_MODULUS;
+ ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
if (sk->protinfo.ax25->ax25_dev->dama.slave)
ax25_ds_establish_data_link(sk->protinfo.ax25);
else
@@ -1406,9 +1407,11 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
/* User data follows immediately after the AX.25 data */
memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
- /* Add the PID, usually AX25_TEXT */
- asmptr = skb_push(skb, 1);
- *asmptr = sk->protocol;
+ /* Add the PID if one is not supplied by the user in the skb */
+ if (!sk->protinfo.ax25->pidincl) {
+ asmptr = skb_push(skb, 1);
+ *asmptr = sk->protocol;
+ }
SOCK_DEBUG(sk, "AX.25: Transmitting buffer\n");
@@ -1455,10 +1458,9 @@ static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, int size, int f
{
struct sock *sk = sock->sk;
struct sockaddr_ax25 *sax = (struct sockaddr_ax25 *)msg->msg_name;
- int copied, length;
+ int copied;
struct sk_buff *skb;
int er;
- int dama;
/*
* This works for seqpacket too. The receiver has ordered the
@@ -1471,16 +1473,11 @@ static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, int size, int f
if ((skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, flags & MSG_DONTWAIT, &er)) == NULL)
return er;
- if (sk->protinfo.ax25->hdrincl) {
- length = skb->len + (skb->data - skb->h.raw);
- } else {
- if (sk->type == SOCK_SEQPACKET)
- skb_pull(skb, 1); /* Remove PID */
- length = skb->len;
- skb->h.raw = skb->data;
- }
+ if (!sk->protinfo.ax25->pidincl)
+ skb_pull(skb, 1); /* Remove PID */
- copied = length;
+ skb->h.raw = skb->data;
+ copied = skb->len;
if (copied > size) {
copied = size;
@@ -1492,6 +1489,7 @@ static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, int size, int f
if (sax != NULL) {
ax25_digi digi;
ax25_address dest;
+ int dama;
ax25_addr_parse(skb->data, skb->len, NULL, &dest, &digi, NULL, &dama);
@@ -1816,6 +1814,9 @@ __initfunc(void ax25_proto_init(struct net_proto *pro))
}
#ifdef MODULE
+MODULE_AUTHOR("Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>");
+MODULE_DESCRIPTION("The amateur radio AX.25 link layer protocol");
+
int init_module(void)
{
ax25_proto_init(NULL);
diff --git a/net/ax25/ax25_addr.c b/net/ax25/ax25_addr.c
index 4c2bd8996..77bfabe73 100644
--- a/net/ax25/ax25_addr.c
+++ b/net/ax25/ax25_addr.c
@@ -1,9 +1,6 @@
/*
* AX.25 release 036
*
- * 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.15 or higher/ NET3.038
*
* This module:
diff --git a/net/ax25/ax25_dev.c b/net/ax25/ax25_dev.c
index 1dc039233..6468faf77 100644
--- a/net/ax25/ax25_dev.c
+++ b/net/ax25/ax25_dev.c
@@ -1,9 +1,6 @@
/*
* AX.25 release 036
*
- * 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.15 or higher/ NET3.038
*
* This module:
@@ -77,7 +74,7 @@ void ax25_dev_device_up(struct device *dev)
unsigned long flags;
if ((ax25_dev = kmalloc(sizeof(*ax25_dev), GFP_ATOMIC)) == NULL) {
- printk(KERN_ERR "ax25_dev_device_up out of memory\n");
+ printk(KERN_ERR "AX.25: ax25_dev_device_up - out of memory\n");
return;
}
@@ -102,11 +99,7 @@ void ax25_dev_device_up(struct device *dev)
ax25_dev->values[AX25_VALUES_IDLE] = AX25_DEF_IDLE;
ax25_dev->values[AX25_VALUES_N2] = AX25_DEF_N2;
ax25_dev->values[AX25_VALUES_PACLEN] = AX25_DEF_PACLEN;
-#ifdef CONFIG_AX25_DAMA_SLAVE
- ax25_dev->values[AX25_VALUES_PROTOCOL] = AX25_PROTO_DAMA_SLAVE;
-#else
ax25_dev->values[AX25_VALUES_PROTOCOL] = AX25_DEF_PROTOCOL;
-#endif
ax25_dev->values[AX25_VALUES_DS_TIMEOUT]= AX25_DEF_DS_TIMEOUT;
save_flags(flags); cli();
@@ -147,7 +140,7 @@ void ax25_dev_device_down(struct device *dev)
if ((s = ax25_dev_list) == ax25_dev) {
ax25_dev_list = s->next;
restore_flags(flags);
- kfree_s(ax25_dev, sizeof(ax25_dev));
+ kfree(ax25_dev);
#ifdef CONFIG_SYSCTL
ax25_register_sysctl();
#endif
@@ -158,7 +151,7 @@ void ax25_dev_device_down(struct device *dev)
if (s->next == ax25_dev) {
s->next = ax25_dev->next;
restore_flags(flags);
- kfree_s(ax25_dev, sizeof(ax25_dev));
+ kfree(ax25_dev);
#ifdef CONFIG_SYSCTL
ax25_register_sysctl();
#endif
@@ -229,7 +222,7 @@ void ax25_dev_free(void)
s = ax25_dev;
ax25_dev = ax25_dev->next;
- kfree_s(s, sizeof(ax25_dev));
+ kfree(s);
}
}
diff --git a/net/ax25/ax25_ds_in.c b/net/ax25/ax25_ds_in.c
index 6af2ba91b..1394c9ab7 100644
--- a/net/ax25/ax25_ds_in.c
+++ b/net/ax25/ax25_ds_in.c
@@ -1,9 +1,6 @@
/*
* AX.25 release 036
*
- * 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.15 or higher/ NET3.038
*
* This module:
@@ -61,12 +58,6 @@ static int ax25_ds_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int framet
ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
break;
- case AX25_SABME:
- ax25->modulus = AX25_EMODULUS;
- ax25->window = ax25->ax25_dev->values[AX25_VALUES_EWINDOW];
- ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
- break;
-
case AX25_DISC:
ax25_send_control(ax25, AX25_DM, pf, AX25_RESPONSE);
break;
@@ -100,20 +91,15 @@ static int ax25_ds_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int framet
case AX25_DM:
if (pf) {
- if (ax25->modulus == AX25_MODULUS) {
- ax25_clear_queues(ax25);
- ax25->state = AX25_STATE_0;
- if (ax25->sk != NULL) {
- ax25->sk->state = TCP_CLOSE;
- ax25->sk->err = ECONNREFUSED;
- ax25->sk->shutdown |= SEND_SHUTDOWN;
- if (!ax25->sk->dead)
- ax25->sk->state_change(ax25->sk);
- ax25->sk->dead = 1;
- }
- } else {
- ax25->modulus = AX25_MODULUS;
- ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
+ ax25_clear_queues(ax25);
+ ax25->state = AX25_STATE_0;
+ if (ax25->sk != NULL) {
+ ax25->sk->state = TCP_CLOSE;
+ ax25->sk->err = ECONNREFUSED;
+ ax25->sk->shutdown |= SEND_SHUTDOWN;
+ if (!ax25->sk->dead)
+ ax25->sk->state_change(ax25->sk);
+ ax25->sk->dead = 1;
}
}
break;
@@ -136,9 +122,7 @@ static int ax25_ds_state2_machine(ax25_cb *ax25, struct sk_buff *skb, int framet
{
switch (frametype) {
case AX25_SABM:
- case AX25_SABME:
ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
- ax25->dama_slave = 0;
ax25_dama_off(ax25);
break;
@@ -146,7 +130,6 @@ static int ax25_ds_state2_machine(ax25_cb *ax25, struct sk_buff *skb, int framet
ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
ax25->state = AX25_STATE_0;
ax25_dama_off(ax25);
-
if (ax25->sk != NULL) {
ax25->sk->state = TCP_CLOSE;
ax25->sk->err = 0;
@@ -162,7 +145,6 @@ static int ax25_ds_state2_machine(ax25_cb *ax25, struct sk_buff *skb, int framet
if (pf) {
ax25->state = AX25_STATE_0;
ax25_dama_off(ax25);
-
if (ax25->sk != NULL) {
ax25->sk->state = TCP_CLOSE;
ax25->sk->err = 0;
@@ -180,7 +162,6 @@ static int ax25_ds_state2_machine(ax25_cb *ax25, struct sk_buff *skb, int framet
case AX25_RR:
if (pf) {
ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
- ax25->dama_slave = 0;
ax25_dama_off(ax25);
}
break;
@@ -203,14 +184,8 @@ static int ax25_ds_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int framet
switch (frametype) {
case AX25_SABM:
- case AX25_SABME:
- if (frametype == AX25_SABM) {
- ax25->modulus = AX25_MODULUS;
- ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
- } else {
- ax25->modulus = AX25_EMODULUS;
- ax25->window = ax25->ax25_dev->values[AX25_VALUES_EWINDOW];
- }
+ ax25->modulus = AX25_MODULUS;
+ ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
ax25->condition = 0x00;
ax25->t1timer = 0;
@@ -229,7 +204,6 @@ static int ax25_ds_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int framet
ax25->t3timer = 0;
ax25->state = AX25_STATE_0;
ax25_dama_off(ax25);
-
if (ax25->sk != NULL) {
ax25->sk->state = TCP_CLOSE;
ax25->sk->err = 0;
@@ -245,7 +219,6 @@ static int ax25_ds_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int framet
ax25->t3timer = 0;
ax25->state = AX25_STATE_0;
ax25_dama_off(ax25);
-
if (ax25->sk != NULL) {
ax25->sk->state = TCP_CLOSE;
ax25->sk->err = ECONNRESET;
@@ -306,193 +279,7 @@ static int ax25_ds_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int framet
break;
}
if (ns == ax25->vr) {
- ax25->vr = (ax25->vr + 1) % ax25->modulus;
- queued = ax25_rx_iframe(ax25, skb);
- if (ax25->condition & AX25_COND_OWN_RX_BUSY) {
- ax25->vr = ns; /* ax25->vr - 1 */
- if (pf) ax25_ds_enquiry_response(ax25);
- break;
- }
- ax25->condition &= ~AX25_COND_REJECT;
- if (pf) {
- ax25_ds_enquiry_response(ax25);
- } else {
- if (!(ax25->condition & AX25_COND_ACK_PENDING)) {
- ax25->t2timer = ax25->t2;
- ax25->condition |= AX25_COND_ACK_PENDING;
- }
- }
- } else {
- if (ax25->condition & AX25_COND_REJECT) {
- if (pf) ax25_ds_enquiry_response(ax25);
- } else {
- ax25->condition |= AX25_COND_REJECT;
- ax25_ds_enquiry_response(ax25);
- ax25->condition &= ~AX25_COND_ACK_PENDING;
- }
- }
- break;
-
- case AX25_FRMR:
- case AX25_ILLEGAL:
- ax25_ds_establish_data_link(ax25);
- ax25->state = AX25_STATE_1;
- break;
-
- default:
- break;
- }
-
- return queued;
-}
-
-/*
- * State machine for state 4, Timer Recovery State.
- * The handling of the timer(s) is in file ax25_timer.c
- * Handling of state 0 and connection release is in ax25.c.
- */
-static int ax25_ds_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int ns, int nr, int pf, int type)
-{
- int queued = 0;
-
- switch (frametype) {
- case AX25_SABM:
- case AX25_SABME:
- if (frametype == AX25_SABM) {
- ax25->modulus = AX25_MODULUS;
- ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
- } else {
- ax25->modulus = AX25_EMODULUS;
- ax25->window = ax25->ax25_dev->values[AX25_VALUES_EWINDOW];
- }
- ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
- ax25->condition = 0x00;
- ax25->t1timer = 0;
- ax25->t3timer = ax25->t3;
- ax25->idletimer = ax25->idle;
- ax25->vs = 0;
- ax25->va = 0;
- ax25->vr = 0;
- ax25->state = AX25_STATE_3;
- ax25->n2count = 0;
- ax25_requeue_frames(ax25);
- ax25_dama_on(ax25);
- break;
-
- case AX25_DISC:
- ax25_clear_queues(ax25);
- ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
- ax25->t3timer = 0;
- ax25->state = AX25_STATE_0;
- ax25_dama_off(ax25);
-
- if (ax25->sk != NULL) {
- ax25->sk->state = TCP_CLOSE;
- ax25->sk->err = 0;
- ax25->sk->shutdown |= SEND_SHUTDOWN;
- if (!ax25->sk->dead)
- ax25->sk->state_change(ax25->sk);
- ax25->sk->dead = 1;
- }
- break;
-
- case AX25_DM:
- ax25_clear_queues(ax25);
- ax25->t3timer = 0;
- ax25->state = AX25_STATE_0;
- ax25_dama_off(ax25);
-
- if (ax25->sk != NULL) {
- ax25->sk->state = TCP_CLOSE;
- ax25->sk->err = ECONNRESET;
- ax25->sk->shutdown |= SEND_SHUTDOWN;
- if (!ax25->sk->dead)
- ax25->sk->state_change(ax25->sk);
- ax25->sk->dead = 1;
- }
- break;
-
- case AX25_RR:
- case AX25_RNR:
- if (frametype == AX25_RR)
- ax25->condition &= ~AX25_COND_PEER_RX_BUSY;
- else
- ax25->condition |= AX25_COND_PEER_RX_BUSY;
- if (type == AX25_RESPONSE && pf) {
- ax25->t1timer = 0;
- if (ax25_validate_nr(ax25, nr)) {
- ax25_frames_acked(ax25, nr);
- ax25->n2count = 0;
- if (ax25->vs == ax25->va) {
- ax25->t3timer = ax25->t3;
- ax25->state = AX25_STATE_3;
- } else {
- ax25_requeue_frames(ax25);
- }
- } else {
- ax25_ds_nr_error_recovery(ax25);
- ax25->state = AX25_STATE_1;
- }
- break;
- }
- if (ax25_validate_nr(ax25, nr)) {
- ax25_frames_acked(ax25, nr);
- ax25->n2count = 0;
- if (type == AX25_COMMAND && pf)
- ax25_ds_enquiry_response(ax25);
- } else {
- ax25_ds_nr_error_recovery(ax25);
- ax25->state = AX25_STATE_1;
- }
- break;
-
- case AX25_REJ:
- ax25->condition &= ~AX25_COND_PEER_RX_BUSY;
- if (pf) {
- ax25->t1timer = 0;
- if (ax25_validate_nr(ax25, nr)) {
- ax25_frames_acked(ax25, nr);
- ax25->n2count = 0;
- if (ax25->vs == ax25->va) {
- ax25->t3timer = ax25->t3;
- ax25->state = AX25_STATE_3;
- } else {
- ax25_requeue_frames(ax25);
- }
- if (type == AX25_COMMAND && pf)
- ax25_ds_enquiry_response(ax25);
- } else {
- ax25_ds_nr_error_recovery(ax25);
- ax25->state = AX25_STATE_1;
- }
- break;
- }
- if (ax25_validate_nr(ax25, nr)) {
- ax25_frames_acked(ax25, nr);
- ax25->n2count = 0;
- ax25_requeue_frames(ax25);
- if (type == AX25_COMMAND && pf)
- ax25_ds_enquiry_response(ax25);
- } else {
- ax25_ds_nr_error_recovery(ax25);
- ax25->state = AX25_STATE_1;
- }
- break;
-
- case AX25_I:
- if (!ax25_validate_nr(ax25, nr)) {
- ax25_ds_nr_error_recovery(ax25);
- ax25->state = AX25_STATE_1;
- break;
- }
- ax25_frames_acked(ax25, nr);
- ax25->n2count = 0;
- if (ax25->condition & AX25_COND_OWN_RX_BUSY) {
- if (pf) ax25_ds_enquiry_response(ax25);
- break;
- }
- if (ns == ax25->vr) {
- ax25->vr = (ax25->vr + 1) % ax25->modulus;
+ ax25->vr = (ax25->vr + 1) % AX25_MODULUS;
queued = ax25_rx_iframe(ax25, skb);
if (ax25->condition & AX25_COND_OWN_RX_BUSY) {
ax25->vr = ns; /* ax25->vr - 1 */
@@ -551,9 +338,6 @@ int ax25_ds_frame_in(ax25_cb *ax25, struct sk_buff *skb, int type)
case AX25_STATE_3:
queued = ax25_ds_state3_machine(ax25, skb, frametype, ns, nr, pf, type);
break;
- case AX25_STATE_4:
- queued = ax25_ds_state4_machine(ax25, skb, frametype, ns, nr, pf, type);
- break;
}
return queued;
diff --git a/net/ax25/ax25_ds_subr.c b/net/ax25/ax25_ds_subr.c
index cc15542ab..6037f16b4 100644
--- a/net/ax25/ax25_ds_subr.c
+++ b/net/ax25/ax25_ds_subr.c
@@ -1,9 +1,6 @@
/*
* AX.25 release 036
*
- * 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.15 or higher/ NET3.038
*
* This module:
@@ -109,9 +106,7 @@ void ax25_ds_enquiry_response(ax25_cb *ax25)
continue;
}
- if (!(ax25o->condition & AX25_COND_PEER_RX_BUSY) &&
- (ax25o->state == AX25_STATE_3 ||
- (ax25o->state == AX25_STATE_4 && ax25o->t1timer == 0))) {
+ if (!(ax25o->condition & AX25_COND_PEER_RX_BUSY) && ax25o->state == AX25_STATE_3) {
ax25_requeue_frames(ax25o);
ax25_kick(ax25o);
}
@@ -125,12 +120,11 @@ void ax25_ds_enquiry_response(ax25_cb *ax25)
void ax25_ds_establish_data_link(ax25_cb *ax25)
{
- ax25->condition = 0x00;
- ax25->n2count = 0;
-
- ax25->t3timer = ax25->t3;
- ax25->t2timer = 0;
- ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
+ ax25->condition &= AX25_COND_DAMA_MODE;
+ ax25->n2count = 0;
+ ax25->t3timer = ax25->t3;
+ ax25->t2timer = 0;
+ ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
}
/*
@@ -139,7 +133,6 @@ void ax25_ds_establish_data_link(ax25_cb *ax25)
* We need a driver level request to switch duplex mode, that does
* either SCC changing, PI config or KISS as required. Currently
* this request isn't reliable.
- *
*/
static void ax25_kiss_cmd(ax25_dev *ax25_dev, unsigned char cmd, unsigned char param)
{
@@ -173,13 +166,12 @@ static void ax25_kiss_cmd(ax25_dev *ax25_dev, unsigned char cmd, unsigned char p
* ax25->dama_slave=1 and look on every disconnect if still slave
* connections exist.
*/
-
static int ax25_check_dama_slave(ax25_dev *ax25_dev)
{
ax25_cb *ax25;
for (ax25 = ax25_list; ax25 != NULL ; ax25 = ax25->next)
- if (ax25->ax25_dev == ax25_dev && ax25->dama_slave && ax25->state > AX25_STATE_1)
+ if (ax25->ax25_dev == ax25_dev && (ax25->condition & AX25_COND_DAMA_MODE) && ax25->state > AX25_STATE_1)
return 1;
return 0;
@@ -202,8 +194,7 @@ void ax25_dev_dama_off(ax25_dev *ax25_dev)
if (ax25_dev == NULL)
return;
- if (ax25_dev->dama.slave && !ax25_check_dama_slave(ax25_dev))
- {
+ if (ax25_dev->dama.slave && !ax25_check_dama_slave(ax25_dev)) {
ax25_kiss_cmd(ax25_dev, 5, 0);
ax25_dev->dama.slave = 0;
ax25_ds_del_timer(ax25_dev);
@@ -213,13 +204,13 @@ void ax25_dev_dama_off(ax25_dev *ax25_dev)
void ax25_dama_on(ax25_cb *ax25)
{
ax25_dev_dama_on(ax25->ax25_dev);
- ax25->dama_slave = 1;
+ ax25->condition |= AX25_COND_DAMA_MODE;
}
void ax25_dama_off(ax25_cb *ax25)
{
ax25_dev_dama_off(ax25->ax25_dev);
- ax25->dama_slave = 0;
+ ax25->condition &= ~AX25_COND_DAMA_MODE;
}
#endif
diff --git a/net/ax25/ax25_ds_timer.c b/net/ax25/ax25_ds_timer.c
index 1b9d3c95f..847be5790 100644
--- a/net/ax25/ax25_ds_timer.c
+++ b/net/ax25/ax25_ds_timer.c
@@ -1,9 +1,6 @@
/*
* AX.25 release 036
*
- * 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.15 or higher/ NET3.038
*
* This module:
@@ -87,15 +84,13 @@ static void ax25_ds_timeout(unsigned long arg)
if (ax25_dev == NULL || !ax25_dev->dama.slave)
return; /* Yikes! */
- if (!ax25_dev->dama.slave_timeout || --ax25_dev->dama.slave_timeout)
- {
+ if (!ax25_dev->dama.slave_timeout || --ax25_dev->dama.slave_timeout) {
ax25_ds_set_timer(ax25_dev);
return;
}
- for (ax25=ax25_list; ax25 != NULL; ax25 = ax25->next)
- {
- if (ax25->ax25_dev != ax25_dev || !ax25->dama_slave)
+ for (ax25=ax25_list; ax25 != NULL; ax25 = ax25->next) {
+ if (ax25->ax25_dev != ax25_dev || !(ax25->condition & AX25_COND_DAMA_MODE))
continue;
ax25_link_failed(&ax25->dest_addr, ax25_dev->dev);
@@ -103,8 +98,7 @@ static void ax25_ds_timeout(unsigned long arg)
ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
ax25->state = AX25_STATE_0;
- if (ax25->sk != NULL)
- {
+ if (ax25->sk != NULL) {
SOCK_DEBUG(ax25->sk, "AX.25 DAMA Slave Timeout\n");
ax25->sk->state = TCP_CLOSE;
ax25->sk->err = ETIMEDOUT;
@@ -120,7 +114,6 @@ static void ax25_ds_timeout(unsigned long arg)
ax25_dev_dama_off(ax25_dev);
}
-
/*
* AX.25 TIMER
*
@@ -141,7 +134,6 @@ void ax25_ds_timer(ax25_cb *ax25)
break;
case AX25_STATE_3:
- case AX25_STATE_4:
/*
* Check the state of the receive buffer.
*/
@@ -279,12 +271,7 @@ void ax25_ds_t1_timeout(ax25_cb *ax25)
}
break;
- case AX25_STATE_3:
- ax25->n2count = 1;
- ax25->state = AX25_STATE_4;
- break;
-
- case AX25_STATE_4:
+ case AX25_STATE_3:
if (ax25->n2count == ax25->n2) {
ax25_link_failed(&ax25->dest_addr, ax25->ax25_dev->dev);
ax25_clear_queues(ax25);
diff --git a/net/ax25/ax25_iface.c b/net/ax25/ax25_iface.c
index 94e62000a..d27a3af23 100644
--- a/net/ax25/ax25_iface.c
+++ b/net/ax25/ax25_iface.c
@@ -1,9 +1,6 @@
/*
* AX.25 release 036
*
- * 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.15 or higher/ NET3.038
*
* This module:
@@ -98,7 +95,7 @@ void ax25_protocol_release(unsigned int pid)
if (protocol->pid == pid) {
protocol_list = protocol->next;
restore_flags(flags);
- kfree_s(protocol, sizeof(struct protocol_struct));
+ kfree(protocol);
return;
}
@@ -107,7 +104,7 @@ void ax25_protocol_release(unsigned int pid)
s = protocol->next;
protocol->next = protocol->next->next;
restore_flags(flags);
- kfree_s(s, sizeof(struct protocol_struct));
+ kfree(s);
return;
}
@@ -152,7 +149,7 @@ void ax25_linkfail_release(void (*func)(ax25_address *, struct device *))
if (linkfail->func == func) {
linkfail_list = linkfail->next;
restore_flags(flags);
- kfree_s(linkfail, sizeof(struct linkfail_struct));
+ kfree(linkfail);
return;
}
@@ -161,7 +158,7 @@ void ax25_linkfail_release(void (*func)(ax25_address *, struct device *))
s = linkfail->next;
linkfail->next = linkfail->next->next;
restore_flags(flags);
- kfree_s(s, sizeof(struct linkfail_struct));
+ kfree(s);
return;
}
@@ -210,7 +207,7 @@ void ax25_listen_release(ax25_address *callsign, struct device *dev)
if (ax25cmp(&listen->callsign, callsign) == 0 && listen->dev == dev) {
listen_list = listen->next;
restore_flags(flags);
- kfree_s(listen, sizeof(struct listen_struct));
+ kfree(listen);
return;
}
@@ -219,7 +216,7 @@ void ax25_listen_release(ax25_address *callsign, struct device *dev)
s = listen->next;
listen->next = listen->next->next;
restore_flags(flags);
- kfree_s(s, sizeof(struct listen_struct));
+ kfree(s);
return;
}
diff --git a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c
index ec9ce4da0..2e6090d76 100644
--- a/net/ax25/ax25_in.c
+++ b/net/ax25/ax25_in.c
@@ -1,9 +1,6 @@
/*
* AX.25 release 036
*
- * 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.15 or higher/ NET3.038
*
* This module:
@@ -73,7 +70,6 @@
static int ax25_rx_fragment(ax25_cb *ax25, struct sk_buff *skb)
{
struct sk_buff *skbn, *skbo;
- int hdrlen, nhdrlen;
if (ax25->fragno != 0) {
if (!(*skb->data & AX25_SEG_FIRST)) {
@@ -92,29 +88,16 @@ static int ax25_rx_fragment(ax25_cb *ax25, struct sk_buff *skb)
return 1;
}
- skbn->dev = ax25->ax25_dev->dev;
-
skb_reserve(skbn, AX25_MAX_HEADER_LEN);
- /* Get first fragment from queue */
- skbo = skb_dequeue(&ax25->frag_queue);
- hdrlen = skbo->data - skbo->h.raw;
- nhdrlen = hdrlen - 2;
-
- skb_push(skbo, hdrlen);
- skb_push(skbn, nhdrlen);
+ skbn->dev = ax25->ax25_dev->dev;
skbn->h.raw = skbn->data;
- /* Copy AX.25 headers */
- memcpy(skbn->data, skbo->data, nhdrlen);
- skb_pull(skbn, nhdrlen);
- skb_pull(skbo, hdrlen);
-
/* Copy data from the fragments */
- do {
+ while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL) {
memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len);
kfree_skb(skbo, FREE_READ);
- } while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL);
+ }
ax25->fraglen = 0;
@@ -188,11 +171,13 @@ int ax25_rx_iframe(ax25_cb *ax25, struct sk_buff *skb)
return (*func)(skb, ax25);
}
- if (ax25->sk != NULL && ax25->ax25_dev->values[AX25_VALUES_CONMODE] == 2 && ax25->sk->protocol == pid) {
- if (sock_queue_rcv_skb(ax25->sk, skb) == 0)
- queued = 1;
- else
- ax25->condition |= AX25_COND_OWN_RX_BUSY;
+ if (ax25->sk != NULL && ax25->ax25_dev->values[AX25_VALUES_CONMODE] == 2) {
+ if ((!ax25->pidincl && ax25->sk->protocol == pid) || ax25->pidincl) {
+ if (sock_queue_rcv_skb(ax25->sk, skb) == 0)
+ queued = 1;
+ else
+ ax25->condition |= AX25_COND_OWN_RX_BUSY;
+ }
}
return queued;
@@ -256,7 +241,7 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a
return 0;
}
- if (call_in_firewall(PF_AX25, skb->dev, skb->h.raw, NULL,&skb) != FW_ACCEPT) {
+ if (call_in_firewall(PF_AX25, skb->dev, skb->h.raw, NULL, &skb) != FW_ACCEPT) {
kfree_skb(skb, FREE_READ);
return 0;
}
@@ -400,7 +385,7 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a
sk = ax25_find_listener(next_digi, 1, dev, SOCK_SEQPACKET);
if (sk != NULL) {
- if (sk->ack_backlog == sk->max_ack_backlog || (make = ax25_make_new(sk, dev)) == NULL) {
+ if (sk->ack_backlog == sk->max_ack_backlog || (make = ax25_make_new(sk, ax25_dev)) == NULL) {
if (mine) ax25_return_dm(dev, &src, &dest, &dp);
kfree_skb(skb, FREE_READ);
return 0;
@@ -445,7 +430,7 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a
if (dp.ndigi == 0) {
if (ax25->digipeat != NULL) {
- kfree_s(ax25->digipeat, sizeof(ax25_digi));
+ kfree(ax25->digipeat);
ax25->digipeat = NULL;
}
} else {
diff --git a/net/ax25/ax25_ip.c b/net/ax25/ax25_ip.c
index ec882c50d..009428fa9 100644
--- a/net/ax25/ax25_ip.c
+++ b/net/ax25/ax25_ip.c
@@ -1,9 +1,6 @@
/*
* AX.25 release 036
*
- * 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.15 or higher/ NET3.038
*
* This module:
@@ -94,7 +91,7 @@ int ax25_encapsulate(struct sk_buff *skb, struct device *dev, unsigned short typ
*buff++ = AX25_P_ARP;
break;
default:
- printk(KERN_ERR "AX.25 wrong protocol type 0x%x2.2\n", type);
+ printk(KERN_ERR "AX.25: ax25_encapsulate - wrong protocol type 0x%x2.2\n", type);
*buff++ = 0;
break;
}
@@ -138,7 +135,7 @@ int ax25_rebuild_header(struct sk_buff *skb)
* gets fixed.
*/
if ((ourskb = skb_copy(skb, GFP_ATOMIC)) == NULL) {
- dev_kfree_skb(skb, FREE_WRITE);
+ kfree_skb(skb, FREE_WRITE);
return 1;
}
@@ -163,12 +160,15 @@ int ax25_rebuild_header(struct sk_buff *skb)
bp[14] |= AX25_EBIT;
bp[14] |= AX25_SSSID_SPARE;
- ax25_dg_build_path(skb, (ax25_address *)(bp + 1), dev);
+ if ((ourskb = ax25_dg_build_path(skb, (ax25_address *)(bp + 1), dev)) == NULL) {
+ kfree_skb(skb, FREE_WRITE);
+ return 1;
+ }
- skb->dev = dev;
- skb->priority = SOPRI_NORMAL;
+ ourskb->dev = dev;
+ ourskb->priority = SOPRI_NORMAL;
- ax25_queue_xmit(skb);
+ ax25_queue_xmit(ourskb);
return 1;
}
diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c
index 7072c632e..db7207b28 100644
--- a/net/ax25/ax25_out.c
+++ b/net/ax25/ax25_out.c
@@ -1,9 +1,6 @@
/*
* AX.25 release 036
*
- * 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.15 or higher/ NET3.038
*
* This module:
@@ -157,7 +154,7 @@ void ax25_output(ax25_cb *ax25, int paclen, struct sk_buff *skb)
if ((skbn = alloc_skb(paclen + 2 + frontlen, GFP_ATOMIC)) == NULL) {
restore_flags(flags);
- printk(KERN_DEBUG "ax25_output: alloc_skb returned NULL\n");
+ printk(KERN_CRIT "AX.25: ax25_output - out of memory\n");
return;
}
@@ -314,7 +311,9 @@ void ax25_kick(ax25_cb *ax25)
void ax25_transmit_buffer(ax25_cb *ax25, struct sk_buff *skb, int type)
{
+ struct sk_buff *skbn;
unsigned char *ptr;
+ int headroom;
if (ax25->ax25_dev == NULL) {
if (ax25->sk != NULL) {
@@ -328,13 +327,24 @@ void ax25_transmit_buffer(ax25_cb *ax25, struct sk_buff *skb, int type)
return;
}
- if (skb_headroom(skb) < ax25_addr_size(ax25->digipeat)) {
- printk(KERN_CRIT "ax25_transmit_buffer: not enough room for digi-peaters\n");
+ headroom = ax25_addr_size(ax25->digipeat);
+
+ if (skb_headroom(skb) < headroom) {
+ if ((skbn = skb_realloc_headroom(skb, headroom)) == NULL) {
+ printk(KERN_CRIT "AX.25: ax25_transmit_buffer - out of memory\n");
+ kfree_skb(skb, FREE_WRITE);
+ return;
+ }
+
+ if (skb->sk != NULL)
+ skb_set_owner_w(skbn, skb->sk);
+
kfree_skb(skb, FREE_WRITE);
- return;
+ skb = skbn;
}
- ptr = skb_push(skb, ax25_addr_size(ax25->digipeat));
+ ptr = skb_push(skb, headroom);
+
ax25_addr_build(ptr, &ax25->source_addr, &ax25->dest_addr, ax25->digipeat, type, ax25->modulus);
skb->dev = ax25->ax25_dev->dev;
@@ -352,7 +362,7 @@ void ax25_queue_xmit(struct sk_buff *skb)
unsigned char *ptr;
if (call_out_firewall(PF_AX25, skb->dev, skb->data, NULL, &skb) != FW_ACCEPT) {
- dev_kfree_skb(skb, FREE_WRITE);
+ kfree_skb(skb, FREE_WRITE);
return;
}
diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c
index 04a7c8542..3cda48a17 100644
--- a/net/ax25/ax25_route.c
+++ b/net/ax25/ax25_route.c
@@ -1,9 +1,6 @@
/*
* AX.25 release 036
*
- * 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.15 or higher/ NET3.038
*
* This module:
@@ -99,15 +96,15 @@ void ax25_rt_device_down(struct device *dev)
if (ax25_route_list == s) {
ax25_route_list = s->next;
if (s->digipeat != NULL)
- kfree_s(s->digipeat, sizeof(ax25_digi));
- kfree_s(s, sizeof(ax25_route));
+ kfree(s->digipeat);
+ kfree(s);
} else {
for (t = ax25_route_list; t != NULL; t = t->next) {
if (t->next == s) {
t->next = s->next;
if (s->digipeat != NULL)
- kfree_s(s->digipeat, sizeof(ax25_digi));
- kfree_s(s, sizeof(ax25_route));
+ kfree(s->digipeat);
+ kfree(s);
break;
}
}
@@ -137,7 +134,7 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg)
for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
if (ax25cmp(&ax25_rt->callsign, &route.dest_addr) == 0 && ax25_rt->dev == ax25_dev->dev) {
if (ax25_rt->digipeat != NULL) {
- kfree_s(ax25_rt->digipeat, sizeof(ax25_digi));
+ kfree(ax25_rt->digipeat);
ax25_rt->digipeat = NULL;
}
if (route.digi_count != 0) {
@@ -161,7 +158,7 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg)
ax25_rt->ip_mode = ' ';
if (route.digi_count != 0) {
if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
- kfree_s(ax25_rt, sizeof(ax25_route));
+ kfree(ax25_rt);
return -ENOMEM;
}
ax25_rt->digipeat->lastrepeat = -1;
@@ -191,15 +188,15 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg)
if (ax25_route_list == s) {
ax25_route_list = s->next;
if (s->digipeat != NULL)
- kfree_s(s->digipeat, sizeof(ax25_digi));
- kfree_s(s, sizeof(ax25_route));
+ kfree(s->digipeat);
+ kfree(s);
} else {
for (t = ax25_route_list; t != NULL; t = t->next) {
if (t->next == s) {
t->next = s->next;
if (s->digipeat != NULL)
- kfree_s(s->digipeat, sizeof(ax25_digi));
- kfree_s(s, sizeof(ax25_route));
+ kfree(s->digipeat);
+ kfree(s);
break;
}
}
@@ -413,8 +410,9 @@ void ax25_rt_build_path(ax25_cb *ax25, ax25_address *addr, struct device *dev)
ax25_adjust_path(addr, ax25->digipeat);
}
-void ax25_dg_build_path(struct sk_buff *skb, ax25_address *addr, struct device *dev)
+struct sk_buff *ax25_dg_build_path(struct sk_buff *skb, ax25_address *addr, struct device *dev)
{
+ struct sk_buff *skbn;
ax25_route *ax25_rt;
ax25_digi digipeat;
ax25_address src, dest;
@@ -424,10 +422,10 @@ void ax25_dg_build_path(struct sk_buff *skb, ax25_address *addr, struct device *
skb_pull(skb, 1); /* skip KISS command */
if ((ax25_rt = ax25_find_route(addr, dev)) == NULL)
- return;
+ return skb;
if (ax25_rt->digipeat == NULL)
- return;
+ return skb;
digipeat = *ax25_rt->digipeat;
@@ -436,8 +434,17 @@ void ax25_dg_build_path(struct sk_buff *skb, ax25_address *addr, struct device *
len = ax25_rt->digipeat->ndigi * AX25_ADDR_LEN;
if (skb_headroom(skb) < len) {
- printk(KERN_CRIT "ax25_dg_build_path: not enough headroom for digis in skb\n");
- return;
+ if ((skbn = skb_realloc_headroom(skb, len)) == NULL) {
+ printk(KERN_CRIT "AX.25: ax25_dg_build_path - out of memory\n");
+ return NULL;
+ }
+
+ if (skb->sk != NULL)
+ skb_set_owner_w(skbn, skb->sk);
+
+ kfree_skb(skb, FREE_WRITE);
+
+ skb = skbn;
}
memcpy(&dest, skb->data + 0, AX25_ADDR_LEN);
@@ -446,6 +453,8 @@ void ax25_dg_build_path(struct sk_buff *skb, ax25_address *addr, struct device *
bp = skb_push(skb, len);
ax25_addr_build(bp, &src, &dest, ax25_rt->digipeat, AX25_COMMAND, AX25_MODULUS);
+
+ return skb;
}
/*
@@ -476,9 +485,9 @@ void ax25_rt_free(void)
ax25_rt = ax25_rt->next;
if (s->digipeat != NULL)
- kfree_s(s->digipeat, sizeof(ax25_digi));
+ kfree(s->digipeat);
- kfree_s(s, sizeof(ax25_route));
+ kfree(s);
}
}
diff --git a/net/ax25/ax25_std_in.c b/net/ax25/ax25_std_in.c
index c4b8914d4..1efe08366 100644
--- a/net/ax25/ax25_std_in.c
+++ b/net/ax25/ax25_std_in.c
@@ -1,9 +1,6 @@
/*
* AX.25 release 036
*
- * 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.15 or higher/ NET3.038
*
* This module:
diff --git a/net/ax25/ax25_std_subr.c b/net/ax25/ax25_std_subr.c
index 46688e3c0..3661a63fb 100644
--- a/net/ax25/ax25_std_subr.c
+++ b/net/ax25/ax25_std_subr.c
@@ -1,9 +1,6 @@
/*
* AX.25 release 036
*
- * 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.15 or higher/ NET3.038
*
* This module:
diff --git a/net/ax25/ax25_std_timer.c b/net/ax25/ax25_std_timer.c
index 5f73caf7b..9a4a34c0f 100644
--- a/net/ax25/ax25_std_timer.c
+++ b/net/ax25/ax25_std_timer.c
@@ -1,9 +1,6 @@
/*
* AX.25 release 036
*
- * 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.15 or higher/ NET3.038
*
* This module:
diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c
index 59e464c1c..ba2c72297 100644
--- a/net/ax25/ax25_subr.c
+++ b/net/ax25/ax25_subr.c
@@ -1,9 +1,6 @@
/*
* AX.25 release 036
*
- * 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.15 or higher/ NET3.038
*
* This module:
@@ -289,6 +286,9 @@ unsigned short ax25_calculate_t1(ax25_cb *ax25)
*/
void ax25_calculate_rtt(ax25_cb *ax25)
{
+ if (ax25->backoff == 0)
+ return;
+
if (ax25->t1timer > 0 && ax25->n2count == 0)
ax25->rtt = (9 * ax25->rtt + ax25->t1 - ax25->t1timer) / 10;
diff --git a/net/ax25/ax25_timer.c b/net/ax25/ax25_timer.c
index a99a02b4a..c0a54da11 100644
--- a/net/ax25/ax25_timer.c
+++ b/net/ax25/ax25_timer.c
@@ -1,9 +1,6 @@
/*
* AX.25 release 036
*
- * 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.15 or higher/ NET3.038
*
* This module:
diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c
index 3325f5056..c5113fce8 100644
--- a/net/ax25/ax25_uid.c
+++ b/net/ax25/ax25_uid.c
@@ -1,9 +1,6 @@
/*
* AX.25 release 036
*
- * 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.15 or higher/ NET3.038
*
* This module:
@@ -110,14 +107,14 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
if ((s = ax25_uid_list) == ax25_uid) {
ax25_uid_list = s->next;
restore_flags(flags);
- kfree_s(ax25_uid, sizeof(ax25_uid_assoc));
+ kfree(ax25_uid);
return 0;
}
while (s != NULL && s->next != NULL) {
if (s->next == ax25_uid) {
s->next = ax25_uid->next;
restore_flags(flags);
- kfree_s(ax25_uid, sizeof(ax25_uid_assoc));
+ kfree(ax25_uid);
return 0;
}
s = s->next;
@@ -180,7 +177,7 @@ void ax25_uid_free(void)
s = ax25_uid;
ax25_uid = ax25_uid->next;
- kfree_s(s, sizeof(ax25_uid_assoc));
+ kfree(s);
}
}
diff --git a/net/ax25/sysctl_net_ax25.c b/net/ax25/sysctl_net_ax25.c
index 02b7fa484..1cf2bab65 100644
--- a/net/ax25/sysctl_net_ax25.c
+++ b/net/ax25/sysctl_net_ax25.c
@@ -5,6 +5,7 @@
* Added /proc/sys/net/ax25 directory entry (empty =) ). [MS]
*/
+#include <linux/config.h>
#include <linux/mm.h>
#include <linux/sysctl.h>
#include <linux/config.h>
@@ -123,7 +124,7 @@ void ax25_register_sysctl(void)
ax25_table[n].proc_handler = NULL;
memcpy(ax25_dev->systable, ax25_param_table, sizeof(ax25_dev->systable));
-
+
#ifndef CONFIG_AX25_DAMA_SLAVE
/*
* We do not wish to have a representation of this parameter
@@ -151,7 +152,7 @@ void ax25_unregister_sysctl(void)
{
unregister_sysctl_table(ax25_table_header);
- kfree_s(ax25_table, ax25_table_size);
+ kfree(ax25_table);
ax25_dir_table[0].child = NULL;
}
diff --git a/net/lapb/lapb_iface.c b/net/lapb/lapb_iface.c
index f28f8fb8d..2be6e565e 100644
--- a/net/lapb/lapb_iface.c
+++ b/net/lapb/lapb_iface.c
@@ -50,7 +50,7 @@ static lapb_cb *volatile lapb_list = NULL;
*/
static void lapb_free_cb(lapb_cb *lapb)
{
- kfree_s(lapb, sizeof(lapb_cb));
+ kfree(lapb);
MOD_DEC_USE_COUNT;
}
@@ -123,7 +123,7 @@ static lapb_cb *lapb_create_cb(void)
{
lapb_cb *lapb;
- if ((lapb = (lapb_cb *)kmalloc(sizeof(*lapb), GFP_ATOMIC)) == NULL)
+ if ((lapb = kmalloc(sizeof(*lapb), GFP_ATOMIC)) == NULL)
return NULL;
MOD_INC_USE_COUNT;
@@ -404,6 +404,9 @@ __initfunc(void lapb_proto_init(struct net_proto *pro))
}
#ifdef MODULE
+MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>");
+MODULE_DESCRIPTION("The X.25 Link Access Procedure B link layer protocol");
+
int init_module(void)
{
lapb_proto_init(NULL);
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index c7383e228..a6af49f15 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -1,9 +1,6 @@
/*
* 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.15 or higher/ NET3.038
*
* This module:
@@ -30,6 +27,7 @@
* NET/ROM 005 Jonathan(G4KLX) Linux 2.1
* Alan(GW4PTS) Started POSIXisms
* NET/ROM 006 Alan(GW4PTS) Brought in line with the ANK changes
+ * Jonathan(G4KLX) Removed hdrincl.
*/
#include <linux/config.h>
@@ -66,6 +64,8 @@
#include <linux/if_arp.h>
#include <linux/init.h>
+int nr_ndevs = 4;
+
int sysctl_netrom_default_path_quality = NR_DEFAULT_QUAL;
int sysctl_netrom_obsolescence_count_initialiser = NR_DEFAULT_OBS;
int sysctl_netrom_network_ttl_initialiser = NR_DEFAULT_TTL;
@@ -86,7 +86,7 @@ static struct proto_ops nr_proto_ops;
static void nr_free_sock(struct sock *sk)
{
- kfree_s(sk->protinfo.nr, sizeof(*sk->protinfo.nr));
+ kfree(sk->protinfo.nr);
sk_free(sk);
@@ -101,7 +101,7 @@ static struct sock *nr_alloc_sock(void)
if ((sk = sk_alloc(GFP_ATOMIC)) == NULL)
return NULL;
- if ((nr = (nr_cb *)kmalloc(sizeof(*nr), GFP_ATOMIC)) == NULL) {
+ if ((nr = kmalloc(sizeof(*nr), GFP_ATOMIC)) == NULL) {
sk_free(sk);
return NULL;
}
@@ -328,94 +328,6 @@ void nr_destroy_socket(struct sock *sk) /* Not static as it's used by the timer
* NET/ROM socket object.
*/
-/*
- * dl1bke 960311: set parameters for existing NET/ROM connections,
- * includes a KILL command to abort any connection.
- * VERY useful for debugging ;-)
- */
-static int nr_ctl_ioctl(const unsigned int cmd, void *arg)
-{
- struct nr_ctl_struct nr_ctl;
- 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;
-
- switch (nr_ctl.cmd) {
- case NETROM_KILL:
- nr_clear_queues(sk);
- nr_write_internal(sk, NR_DISCREQ);
- sk->protinfo.nr->state = NR_STATE_0;
- sk->state = TCP_CLOSE;
- sk->err = ENETRESET;
- sk->shutdown |= SEND_SHUTDOWN;
- if (!sk->dead)
- sk->state_change(sk);
- sk->dead = 1;
- nr_set_timer(sk);
- break;
-
- case NETROM_T1:
- if (nr_ctl.arg < 1)
- return -EINVAL;
- 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;
- restore_flags(flags);
- break;
-
- case NETROM_T2:
- if (nr_ctl.arg < 1)
- return -EINVAL;
- save_flags(flags); cli();
- 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);
- break;
-
- case NETROM_N2:
- if (nr_ctl.arg < 1 || nr_ctl.arg > 10)
- return -EINVAL;
- sk->protinfo.nr->n2count = 0;
- sk->protinfo.nr->n2 = nr_ctl.arg;
- break;
-
- case NETROM_T4:
- if (nr_ctl.arg < 1)
- return -EINVAL;
- save_flags(flags); cli();
- 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);
- break;
-
- case NETROM_IDLE:
- if (nr_ctl.arg < 1)
- return -EINVAL;
- save_flags(flags); cli();
- 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;
-
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
static int nr_setsockopt(struct socket *sock, int level, int optname,
char *optval, int optlen)
{
@@ -462,10 +374,6 @@ static int nr_setsockopt(struct socket *sock, int level, int optname,
sk->protinfo.nr->idle = opt * 60 * NR_SLOWHZ;
return 0;
- case NETROM_HDRINCL:
- sk->protinfo.nr->hdrincl = opt ? 1 : 0;
- return 0;
-
default:
return -ENOPROTOOPT;
}
@@ -505,10 +413,6 @@ static int nr_getsockopt(struct socket *sock, int level, int optname,
val = sk->protinfo.nr->idle / (NR_SLOWHZ * 60);
break;
- case NETROM_HDRINCL:
- val = sk->protinfo.nr->hdrincl;
- break;
-
default:
return -ENOPROTOOPT;
}
@@ -614,7 +518,6 @@ static struct sock *nr_make_new(struct sock *osk)
nr->device = osk->protinfo.nr->device;
nr->bpqext = osk->protinfo.nr->bpqext;
- nr->hdrincl = osk->protinfo.nr->hdrincl;
return sk;
}
@@ -1122,7 +1025,6 @@ static int nr_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct s
return len;
}
-
static int nr_recvmsg(struct socket *sock, struct msghdr *msg, int size,
int flags, struct scm_cookie *scm)
{
@@ -1144,12 +1046,8 @@ static int nr_recvmsg(struct socket *sock, struct msghdr *msg, int size,
if ((skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, flags & MSG_DONTWAIT, &er)) == NULL)
return er;
- if (!sk->protinfo.nr->hdrincl) {
- skb_pull(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN);
- skb->h.raw = skb->data;
- }
-
- copied = skb->len;
+ skb->h.raw = skb->data;
+ copied = skb->len;
if (copied > size) {
copied = size;
@@ -1231,10 +1129,6 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
if (!suser()) return -EPERM;
return nr_rt_ioctl(cmd, (void *)arg);
- case SIOCNRCTLCON:
- if (!suser()) return -EPERM;
- return nr_ctl_ioctl(cmd, (void *)arg);
-
default:
return dev_ioctl(cmd, (void *)arg);
}
@@ -1355,28 +1249,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}
-};
+static struct device *dev_nr;
__initfunc(void nr_proto_init(struct net_proto *pro))
{
int i;
+ if ((dev_nr = kmalloc(nr_ndevs * sizeof(struct device), GFP_KERNEL)) == NULL) {
+ printk(KERN_ERR "NET/ROM: nr_proto_init - unable to allocate device structure\n");
+ return;
+ }
+
+ memset(dev_nr, 0x00, nr_ndevs * sizeof(struct device));
+
+ for (i = 0; i < nr_ndevs; i++) {
+ dev_nr[i].name = kmalloc(20, GFP_KERNEL);
+ sprintf(dev_nr[i].name, "nr%d", i);
+ dev_nr[i].init = nr_init;
+ register_netdev(&dev_nr[i]);
+ }
+
sock_register(&nr_family_ops);
register_netdevice_notifier(&nr_dev_notifier);
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]);
+ ax25_protocol_register(AX25_P_NETROM, nr_route_frame);
+ ax25_linkfail_register(nr_link_failed);
#ifdef CONFIG_SYSCTL
nr_register_sysctl();
@@ -1392,6 +1290,12 @@ __initfunc(void nr_proto_init(struct net_proto *pro))
#ifdef MODULE
EXPORT_NO_SYMBOLS;
+MODULE_PARM(nr_ndevs, "i");
+MODULE_PARM_DESC(nr_ndevs, "number of NET/ROM devices");
+
+MODULE_AUTHOR("Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>");
+MODULE_DESCRIPTION("The amateur radio NET/ROM network and transport layer protocol");
+
int init_module(void)
{
nr_proto_init(NULL);
@@ -1420,13 +1324,16 @@ void cleanup_module(void)
#endif
sock_unregister(AF_NETROM);
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < nr_ndevs; i++) {
if (dev_nr[i].priv != NULL) {
kfree(dev_nr[i].priv);
dev_nr[i].priv = NULL;
unregister_netdev(&dev_nr[i]);
}
+ kfree(dev_nr[i].name);
}
+
+ kfree(dev_nr);
}
#endif
diff --git a/net/netrom/nr_dev.c b/net/netrom/nr_dev.c
index 1387c6c2d..2d88bec2b 100644
--- a/net/netrom/nr_dev.c
+++ b/net/netrom/nr_dev.c
@@ -1,9 +1,6 @@
/*
* 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.15 or higher/ NET3.038
*
* This module:
@@ -123,7 +120,7 @@ static int nr_rebuild_header(struct sk_buff *skb)
struct sk_buff *skbn;
unsigned char *bp = skb->data;
- if (!arp_find(bp + 7, skb)) {
+ if (arp_find(bp + 7, skb)) {
kfree_skb(skb, FREE_WRITE);
return 1;
}
@@ -203,7 +200,7 @@ static int nr_xmit(struct sk_buff *skb, struct device *dev)
return 0;
if (!dev->start) {
- printk(KERN_ERR "netrom: xmit call when iface is down\n");
+ printk(KERN_ERR "NET/ROM: nr_xmit - called when iface is down\n");
return 1;
}
@@ -254,10 +251,12 @@ int nr_init(struct device *dev)
dev->flags = 0;
dev->family = AF_INET;
- dev->pa_addr = 0;
- dev->pa_brdaddr = 0;
- dev->pa_mask = 0;
- dev->pa_alen = sizeof(unsigned long);
+#ifdef CONFIG_INET
+ dev->pa_addr = in_aton("192.168.0.1");
+ dev->pa_brdaddr = in_aton("192.168.0.255");
+ dev->pa_mask = in_aton("255.255.255.0");
+ dev->pa_alen = 4;
+#endif
if ((dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL)) == NULL)
return -ENOMEM;
diff --git a/net/netrom/nr_in.c b/net/netrom/nr_in.c
index cbddc677a..c13e92666 100644
--- a/net/netrom/nr_in.c
+++ b/net/netrom/nr_in.c
@@ -1,9 +1,6 @@
/*
* 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.15 or higher/ NET3.038
*
* This module:
@@ -23,6 +20,7 @@
* NET/ROM 003 Jonathan(G4KLX) Added NET/ROM fragment reception.
* Darryl(G7LED) Added missing INFO with NAK case, optimized
* INFOACK handling, removed reconnect on error.
+ * NET/ROM 006 Jonathan(G4KLX) Hdrincl removal changes.
*/
#include <linux/config.h>
@@ -54,6 +52,8 @@ static int nr_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more)
{
struct sk_buff *skbo, *skbn = skb;
+ skb_pull(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN);
+
if (more) {
sk->protinfo.nr->fraglen += skb->len;
skb_queue_tail(&sk->protinfo.nr->frag_queue, skb);
@@ -69,12 +69,7 @@ static int nr_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more)
skbn->h.raw = skbn->data;
- skbo = skb_dequeue(&sk->protinfo.nr->frag_queue);
- memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len);
- kfree_skb(skbo, FREE_READ);
-
while ((skbo = skb_dequeue(&sk->protinfo.nr->frag_queue)) != NULL) {
- skb_pull(skbo, NR_NETWORK_LEN + NR_TRANSPORT_LEN);
memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len);
kfree_skb(skbo, FREE_READ);
}
diff --git a/net/netrom/nr_out.c b/net/netrom/nr_out.c
index 7ee32c736..7c053b482 100644
--- a/net/netrom/nr_out.c
+++ b/net/netrom/nr_out.c
@@ -1,9 +1,6 @@
/*
* 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.15 or higher/ NET3.038
*
* This module:
diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
index eb8ad7a35..41399a53c 100644
--- a/net/netrom/nr_route.c
+++ b/net/netrom/nr_route.c
@@ -1,9 +1,6 @@
/*
* 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.15 or higher/ NET3.038
*
* This module:
@@ -91,7 +88,7 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2
return 0;
if (nr_neigh == NULL) {
- if ((nr_neigh = (struct nr_neigh *)kmalloc(sizeof(*nr_neigh), GFP_ATOMIC)) == NULL)
+ if ((nr_neigh = kmalloc(sizeof(*nr_neigh), GFP_ATOMIC)) == NULL)
return -ENOMEM;
nr_neigh->callsign = *ax25;
@@ -105,7 +102,7 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2
if (ax25_digi != NULL && ax25_digi->ndigi > 0) {
if ((nr_neigh->digipeat = kmalloc(sizeof(*ax25_digi), GFP_KERNEL)) == NULL) {
- kfree_s(nr_neigh, sizeof(*nr_neigh));
+ kfree(nr_neigh);
return -ENOMEM;
}
*nr_neigh->digipeat = *ax25_digi;
@@ -120,11 +117,11 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2
restore_flags(flags);
}
- if (quality != 0 && ax25cmp(nr, ax25) == 0)
+ if (quality != 0 && ax25cmp(nr, ax25) == 0 && !nr_neigh->locked)
nr_neigh->quality = quality;
if (nr_node == NULL) {
- if ((nr_node = (struct nr_node *)kmalloc(sizeof(*nr_node), GFP_ATOMIC)) == NULL)
+ if ((nr_node = kmalloc(sizeof(*nr_node), GFP_ATOMIC)) == NULL)
return -ENOMEM;
nr_node->callsign = *nr;
@@ -252,7 +249,7 @@ static void nr_remove_node(struct nr_node *nr_node)
if ((s = nr_node_list) == nr_node) {
nr_node_list = nr_node->next;
restore_flags(flags);
- kfree_s(nr_node, sizeof(struct nr_node));
+ kfree(nr_node);
return;
}
@@ -260,7 +257,7 @@ static void nr_remove_node(struct nr_node *nr_node)
if (s->next == nr_node) {
s->next = nr_node->next;
restore_flags(flags);
- kfree_s(nr_node, sizeof(struct nr_node));
+ kfree(nr_node);
return;
}
@@ -282,8 +279,8 @@ static void nr_remove_neigh(struct nr_neigh *nr_neigh)
nr_neigh_list = nr_neigh->next;
restore_flags(flags);
if (nr_neigh->digipeat != NULL)
- kfree_s(nr_neigh->digipeat, sizeof(ax25_digi));
- kfree_s(nr_neigh, sizeof(struct nr_neigh));
+ kfree(nr_neigh->digipeat);
+ kfree(nr_neigh);
return;
}
@@ -292,8 +289,8 @@ static void nr_remove_neigh(struct nr_neigh *nr_neigh)
s->next = nr_neigh->next;
restore_flags(flags);
if (nr_neigh->digipeat != NULL)
- kfree_s(nr_neigh->digipeat, sizeof(ax25_digi));
- kfree_s(nr_neigh, sizeof(struct nr_neigh));
+ kfree(nr_neigh->digipeat);
+ kfree(nr_neigh);
return;
}
@@ -370,7 +367,7 @@ static int nr_add_neigh(ax25_address *callsign, ax25_digi *ax25_digi, struct dev
}
}
- if ((nr_neigh = (struct nr_neigh *)kmalloc(sizeof(*nr_neigh), GFP_ATOMIC)) == NULL)
+ if ((nr_neigh = kmalloc(sizeof(*nr_neigh), GFP_ATOMIC)) == NULL)
return -ENOMEM;
nr_neigh->callsign = *callsign;
@@ -384,7 +381,7 @@ static int nr_add_neigh(ax25_address *callsign, ax25_digi *ax25_digi, struct dev
if (ax25_digi != NULL && ax25_digi->ndigi > 0) {
if ((nr_neigh->digipeat = kmalloc(sizeof(*ax25_digi), GFP_KERNEL)) == NULL) {
- kfree_s(nr_neigh, sizeof(*nr_neigh));
+ kfree(nr_neigh);
return -ENOMEM;
}
*nr_neigh->digipeat = *ax25_digi;
@@ -688,6 +685,7 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
if (ax25 != NULL && call_in_firewall(PF_NETROM, skb->dev, skb->data, NULL, &skb) != FW_ACCEPT)
return 0;
+
if (ax25 == NULL && call_out_firewall(PF_NETROM, skb->dev, skb->data, NULL, &skb) != FW_ACCEPT)
return 0;
diff --git a/net/netrom/nr_subr.c b/net/netrom/nr_subr.c
index eb1b225f8..5eae25279 100644
--- a/net/netrom/nr_subr.c
+++ b/net/netrom/nr_subr.c
@@ -1,9 +1,6 @@
/*
* 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.15 or higher/ NET3.038
*
* This module:
@@ -158,7 +155,7 @@ void nr_write_internal(struct sock *sk, int frametype)
case NR_INFOACK:
break;
default:
- printk(KERN_ERR "nr_write_internal: invalid frame type %d\n", frametype);
+ printk(KERN_ERR "NET/ROM: nr_write_internal - invalid frame type %d\n", frametype);
return;
}
diff --git a/net/netrom/nr_timer.c b/net/netrom/nr_timer.c
index 22d029b43..cc96f26dd 100644
--- a/net/netrom/nr_timer.c
+++ b/net/netrom/nr_timer.c
@@ -1,9 +1,6 @@
/*
* 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.15 or higher/ NET3.038
*
* This module:
diff --git a/net/netsyms.c b/net/netsyms.c
index 118841c32..9f13cabca 100644
--- a/net/netsyms.c
+++ b/net/netsyms.c
@@ -28,6 +28,7 @@
#include <net/route.h>
#include <net/scm.h>
#include <net/inet_common.h>
+#include <linux/inet.h>
#include <linux/net_alias.h>
#include <linux/mroute.h>
@@ -163,6 +164,8 @@ EXPORT_SYMBOL(ip_send_check);
EXPORT_SYMBOL(ip_fragment);
EXPORT_SYMBOL(ip_dev_find_tunnel);
EXPORT_SYMBOL(inet_family_ops);
+EXPORT_SYMBOL(in_aton);
+EXPORT_SYMBOL(in_ntoa);
#ifdef CONFIG_IPV6_MODULE
/* inet functions common to v4 and v6 */
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index f3309ade9..bd0ecd843 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -1,8 +1,5 @@
/*
- * 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.
+ * ROSE release 002
*
* This code REQUIRES 2.1.15 or higher/ NET3.038
*
@@ -13,10 +10,13 @@
* 2 of the License, or (at your option) any later version.
*
* History
- * Rose 001 Jonathan(G4KLX) Cloned from af_netrom.c.
+ * 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.
+ * ROSE 002 Jonathan(G4KLX) Changed hdrincl to qbitincl.
+ * Added random number facilities entry.
+ * Variable number of ROSE devices.
*/
#include <linux/config.h>
@@ -54,6 +54,8 @@
#include <linux/if_arp.h>
#include <linux/init.h>
+int rose_ndevs = 6;
+
int sysctl_rose_restart_request_timeout = ROSE_DEFAULT_T0;
int sysctl_rose_call_request_timeout = ROSE_DEFAULT_T1;
int sysctl_rose_reset_request_timeout = ROSE_DEFAULT_T2;
@@ -62,8 +64,8 @@ int sysctl_rose_no_activity_timeout = ROSE_DEFAULT_IDLE;
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;
+int sysctl_rose_maximum_vcs = ROSE_DEFAULT_MAXVC;
+int sysctl_rose_window_size = ROSE_DEFAULT_WINDOW_SIZE;
static struct sock *volatile rose_list = NULL;
@@ -72,7 +74,7 @@ static struct proto_ops rose_proto_ops;
ax25_address rose_callsign;
/*
- * Convert a Rose address into text.
+ * Convert a ROSE address into text.
*/
char *rose2asc(rose_address *addr)
{
@@ -94,7 +96,7 @@ char *rose2asc(rose_address *addr)
}
/*
- * Compare two Rose addresses, 0 == equal.
+ * Compare two ROSE addresses, 0 == equal.
*/
int rosecmp(rose_address *addr1, rose_address *addr2)
{
@@ -108,7 +110,7 @@ int rosecmp(rose_address *addr1, rose_address *addr2)
}
/*
- * Compare two Rose addresses for only mask digits, 0 == equal.
+ * Compare two ROSE addresses for only mask digits, 0 == equal.
*/
int rosecmpm(rose_address *addr1, rose_address *addr2, unsigned short mask)
{
@@ -134,7 +136,7 @@ int rosecmpm(rose_address *addr1, rose_address *addr2, unsigned short mask)
static void rose_free_sock(struct sock *sk)
{
- kfree_s(sk->protinfo.rose, sizeof(*sk->protinfo.rose));
+ kfree(sk->protinfo.rose);
sk_free(sk);
@@ -149,7 +151,7 @@ static struct sock *rose_alloc_sock(void)
if ((sk = sk_alloc(GFP_ATOMIC)) == NULL)
return NULL;
- if ((rose = (rose_cb *)kmalloc(sizeof(*rose), GFP_ATOMIC)) == NULL) {
+ if ((rose = kmalloc(sizeof(*rose), GFP_ATOMIC)) == NULL) {
sk_free(sk);
return NULL;
}
@@ -195,6 +197,27 @@ static void rose_remove_socket(struct sock *sk)
}
/*
+ * Kill all bound sockets on a broken link layer connection to a
+ * particular neighbour.
+ */
+void rose_kill_by_neigh(struct rose_neigh *neigh)
+{
+ struct sock *s;
+
+ for (s = rose_list; s != NULL; s = s->next) {
+ if (s->protinfo.rose->neighbour == neigh) {
+ s->protinfo.rose->state = ROSE_STATE_0;
+ s->protinfo.rose->neighbour = NULL;
+ s->state = TCP_CLOSE;
+ s->err = ENETUNREACH;
+ s->shutdown |= SEND_SHUTDOWN;
+ s->state_change(s);
+ s->dead = 1;
+ }
+ }
+}
+
+/*
* Kill all bound sockets on a dropped device.
*/
static void rose_kill_by_device(struct device *dev)
@@ -224,9 +247,15 @@ 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);
+ switch (dev->type) {
+ case ARPHRD_ROSE:
+ rose_kill_by_device(dev);
+ break;
+ case ARPHRD_AX25:
+ rose_link_device_down(dev);
+ rose_rt_device_down(dev);
+ break;
+ }
return NOTIFY_DONE;
}
@@ -251,7 +280,7 @@ static void rose_insert_socket(struct sock *sk)
* Find a socket that wants to accept the Call Request we just
* received.
*/
-static struct sock *rose_find_listener(ax25_address *call)
+static struct sock *rose_find_listener(rose_address *addr, ax25_address *call)
{
unsigned long flags;
struct sock *s;
@@ -260,14 +289,14 @@ static struct sock *rose_find_listener(ax25_address *call)
cli();
for (s = rose_list; s != NULL; s = s->next) {
- if (ax25cmp(&s->protinfo.rose->source_call, call) == 0 && s->protinfo.rose->source_ndigis == 0 && s->state == TCP_LISTEN) {
+ if (rosecmp(&s->protinfo.rose->source_addr, addr) == 0 && ax25cmp(&s->protinfo.rose->source_call, call) == 0 && s->protinfo.rose->source_ndigis == 0 && s->state == TCP_LISTEN) {
restore_flags(flags);
return s;
}
}
for (s = rose_list; s != NULL; s = s->next) {
- if (ax25cmp(&s->protinfo.rose->source_call, &null_ax25_address) == 0 && s->state == TCP_LISTEN) {
+ if (rosecmp(&s->protinfo.rose->source_addr, addr) == 0 && ax25cmp(&s->protinfo.rose->source_call, &null_ax25_address) == 0 && s->state == TCP_LISTEN) {
restore_flags(flags);
return s;
}
@@ -278,9 +307,9 @@ static struct sock *rose_find_listener(ax25_address *call)
}
/*
- * Find a connected Rose socket given my LCI and device.
+ * Find a connected ROSE socket given my LCI and device.
*/
-struct sock *rose_find_socket(unsigned int lci, struct device *dev)
+struct sock *rose_find_socket(unsigned int lci, struct rose_neigh *neigh)
{
struct sock *s;
unsigned long flags;
@@ -289,7 +318,7 @@ struct sock *rose_find_socket(unsigned int lci, struct device *dev)
cli();
for (s = rose_list; s != NULL; s = s->next) {
- if (s->protinfo.rose->lci == lci && s->protinfo.rose->neighbour->dev == dev) {
+ if (s->protinfo.rose->lci == lci && s->protinfo.rose->neighbour == neigh) {
restore_flags(flags);
return s;
}
@@ -303,17 +332,21 @@ struct sock *rose_find_socket(unsigned int lci, struct device *dev)
/*
* Find a unique LCI for a given device.
*/
-unsigned int rose_new_lci(struct device *dev)
+unsigned int rose_new_lci(struct rose_neigh *neigh)
{
- lci++;
- if (lci > 4095) lci = 1;
+ int lci;
- while (rose_find_socket(lci, dev) != NULL) {
- lci++;
- if (lci > 4095) lci = 1;
+ if (neigh->dce_mode) {
+ for (lci = 1; lci <= sysctl_rose_maximum_vcs; lci++)
+ if (rose_find_socket(lci, neigh) == NULL && rose_route_free_lci(lci, neigh) == NULL)
+ return lci;
+ } else {
+ for (lci = sysctl_rose_maximum_vcs; lci > 0; lci--)
+ if (rose_find_socket(lci, neigh) == NULL && rose_route_free_lci(lci, neigh) == NULL)
+ return lci;
}
- return lci;
+ return 0;
}
/*
@@ -374,94 +407,9 @@ 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.
+ * ROSE socket object.
*/
-/*
- * dl1bke 960311: set parameters for existing Rose connections,
- * includes a KILL command to abort any connection.
- * VERY useful for debugging ;-)
- */
-static int rose_ctl_ioctl(const unsigned int cmd, void *arg)
-{
- struct rose_ctl_struct rose_ctl;
- struct sock *sk;
- unsigned long flags;
- struct device *dev;
- int err;
-
- if ((err = verify_area(VERIFY_READ, arg, sizeof(rose_ctl))) != 0)
- return err;
-
- copy_from_user(&rose_ctl, arg, sizeof(rose_ctl));
-
- if ((dev = rose_ax25_dev_get(rose_ctl.dev)) == NULL)
- return -EINVAL;
-
- if ((sk = rose_find_socket(rose_ctl.lci, dev)) == NULL)
- return -ENOTCONN;
-
- switch (rose_ctl.cmd) {
- case ROSE_KILL:
- rose_clear_queues(sk);
- rose_write_internal(sk, ROSE_CLEAR_REQUEST);
- sk->protinfo.rose->state = ROSE_STATE_0;
- sk->state = TCP_CLOSE;
- sk->err = ENETRESET;
- sk->shutdown |= SEND_SHUTDOWN;
- if (!sk->dead)
- sk->state_change(sk);
- sk->dead = 1;
- rose_set_timer(sk);
- break;
-
- case ROSE_T1:
- if (rose_ctl.arg < 1)
- return -EINVAL;
- save_flags(flags); cli();
- sk->protinfo.rose->t1 = rose_ctl.arg * ROSE_SLOWHZ;
- restore_flags(flags);
- break;
-
- case ROSE_T2:
- if (rose_ctl.arg < 1)
- return -EINVAL;
- save_flags(flags); cli();
- sk->protinfo.rose->t2 = rose_ctl.arg * ROSE_SLOWHZ;
- restore_flags(flags);
- break;
-
- case ROSE_T3:
- if (rose_ctl.arg < 1)
- return -EINVAL;
- save_flags(flags); cli();
- 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;
-
- case ROSE_IDLE:
- if (rose_ctl.arg < 1)
- return -EINVAL;
- save_flags(flags); cli();
- sk->protinfo.rose->idle = rose_ctl.arg * 60 * ROSE_SLOWHZ;
- restore_flags(flags);
- break;
-
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
static int rose_setsockopt(struct socket *sock, int level, int optname,
char *optval, int optlen)
{
@@ -508,8 +456,8 @@ static int rose_setsockopt(struct socket *sock, int level, int optname,
sk->protinfo.rose->idle = opt * 60 * ROSE_SLOWHZ;
return 0;
- case ROSE_HDRINCL:
- sk->protinfo.rose->hdrincl = opt ? 1 : 0;
+ case ROSE_QBITINCL:
+ sk->protinfo.rose->qbitincl = opt ? 1 : 0;
return 0;
default:
@@ -551,8 +499,8 @@ static int rose_getsockopt(struct socket *sock, int level, int optname,
val = sk->protinfo.rose->idle / (ROSE_SLOWHZ * 60);
break;
- case ROSE_HDRINCL:
- val = sk->protinfo.rose->hdrincl;
+ case ROSE_QBITINCL:
+ val = sk->protinfo.rose->qbitincl;
break;
default:
@@ -654,8 +602,8 @@ static struct sock *rose_make_new(struct sock *osk)
rose->hb = osk->protinfo.rose->hb;
rose->idle = osk->protinfo.rose->idle;
- rose->device = osk->protinfo.rose->device;
- rose->hdrincl = osk->protinfo.rose->hdrincl;
+ rose->device = osk->protinfo.rose->device;
+ rose->qbitincl = osk->protinfo.rose->qbitincl;
return sk;
}
@@ -736,7 +684,7 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
return -EINVAL;
if ((dev = rose_dev_get(&addr->srose_addr)) == NULL) {
- SOCK_DEBUG(sk, "Rose: bind failed: invalid address\n");
+ SOCK_DEBUG(sk, "ROSE: bind failed: invalid address\n");
return -EADDRNOTAVAIL;
}
@@ -760,7 +708,7 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
rose_insert_socket(sk);
sk->zapped = 0;
- SOCK_DEBUG(sk, "Rose: socket is bound\n");
+ SOCK_DEBUG(sk, "ROSE: socket is bound\n");
return 0;
}
@@ -793,7 +741,10 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
if (addr->srose_family != AF_ROSE)
return -EINVAL;
- if ((sk->protinfo.rose->neighbour = rose_get_neigh(&addr->srose_addr)) == NULL)
+ if ((sk->protinfo.rose->neighbour = rose_get_neigh(&addr->srose_addr)) == NULL)
+ return -ENETUNREACH;
+
+ if ((sk->protinfo.rose->lci = rose_new_lci(sk->protinfo.rose->neighbour)) == 0)
return -ENETUNREACH;
if (sk->zapped) { /* Must bind first - autobinding in this may or may not work */
@@ -814,11 +765,12 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
sk->protinfo.rose->dest_addr = addr->srose_addr;
sk->protinfo.rose->dest_call = addr->srose_call;
+ sk->protinfo.rose->rand = ((int)sk->protinfo.rose & 0xFFFF) + sk->protinfo.rose->lci;
+
if (addr->srose_ndigis == 1) {
sk->protinfo.rose->dest_ndigis = 1;
sk->protinfo.rose->dest_digi = addr->srose_digi;
}
- sk->protinfo.rose->lci = rose_new_lci(sk->protinfo.rose->neighbour->dev);
/* Move to connecting socket, start sending Connect Requests */
sock->state = SS_CONNECTING;
@@ -954,7 +906,7 @@ int rose_rx_call_request(struct sk_buff *skb, struct device *dev, struct rose_ne
{
struct sock *sk;
struct sock *make;
- rose_cb rose;
+ struct rose_facilities facilities;
skb->sk = NULL; /* Initially we don't know who it's for */
@@ -965,11 +917,11 @@ int rose_rx_call_request(struct sk_buff *skb, struct device *dev, struct rose_ne
/*
* XXX This is an error.
*/
- if (!rose_parse_facilities(skb, &rose)) {
+ if (!rose_parse_facilities(skb, &facilities)) {
return 0;
}
- sk = rose_find_listener(&rose.source_call);
+ sk = rose_find_listener(&facilities.source_addr, &facilities.source_call);
/*
* We can't accept the Call Request.
@@ -983,14 +935,14 @@ int rose_rx_call_request(struct sk_buff *skb, struct device *dev, struct rose_ne
make->state = TCP_ESTABLISHED;
make->protinfo.rose->lci = lci;
- make->protinfo.rose->dest_addr = rose.dest_addr;
- make->protinfo.rose->dest_call = rose.dest_call;
- make->protinfo.rose->dest_ndigis = rose.dest_ndigis;
- make->protinfo.rose->dest_digi = rose.dest_digi;
- make->protinfo.rose->source_addr = rose.source_addr;
- make->protinfo.rose->source_call = rose.source_call;
- make->protinfo.rose->source_ndigis = rose.source_ndigis;
- make->protinfo.rose->source_digi = rose.source_digi;
+ make->protinfo.rose->dest_addr = facilities.dest_addr;
+ make->protinfo.rose->dest_call = facilities.dest_call;
+ make->protinfo.rose->dest_ndigis = facilities.dest_ndigis;
+ make->protinfo.rose->dest_digi = facilities.dest_digi;
+ make->protinfo.rose->source_addr = facilities.source_addr;
+ make->protinfo.rose->source_call = facilities.source_call;
+ make->protinfo.rose->source_ndigis = facilities.source_ndigis;
+ make->protinfo.rose->source_digi = facilities.source_digi;
make->protinfo.rose->neighbour = neigh;
make->protinfo.rose->device = dev;
@@ -1026,7 +978,7 @@ static int rose_sendmsg(struct socket *sock, struct msghdr *msg, int len,
struct sockaddr_rose srose;
struct sk_buff *skb;
unsigned char *asmptr;
- int size;
+ int size, qbit = 0;
if (msg->msg_flags & ~MSG_DONTWAIT)
return -EINVAL;
@@ -1039,7 +991,7 @@ static int rose_sendmsg(struct socket *sock, struct msghdr *msg, int len,
return -EPIPE;
}
- if (sk->protinfo.rose->device == NULL)
+ if (sk->protinfo.rose->neighbour == NULL || sk->protinfo.rose->device == NULL)
return -ENETUNREACH;
if (usrose != NULL) {
@@ -1069,44 +1021,55 @@ static int rose_sendmsg(struct socket *sock, struct msghdr *msg, int len,
srose.srose_digi = sk->protinfo.rose->dest_digi;
}
}
- SOCK_DEBUG(sk, "Rose: sendto: Addresses built.\n");
+
+ SOCK_DEBUG(sk, "ROSE: sendto: Addresses built.\n");
/* Build a packet */
- SOCK_DEBUG(sk, "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, msg->msg_flags & MSG_DONTWAIT, &err)) == NULL)
return err;
- skb_reserve(skb, size - len);
+ skb_reserve(skb, AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN);
/*
- * Push down the Rose header
+ * Put the data on the end
*/
+ SOCK_DEBUG(sk, "ROSE: Appending user data\n");
- asmptr = skb_push(skb, ROSE_MIN_LEN);
- SOCK_DEBUG(sk, "Building Rose Header.\n");
+ asmptr = skb->h.raw = skb_put(skb, len);
- /* Build a Rose Transport header */
+ memcpy_fromiovec(asmptr, msg->msg_iov, len);
- *asmptr++ = ((sk->protinfo.rose->lci >> 8) & 0x0F) | ROSE_GFI;
- *asmptr++ = (sk->protinfo.rose->lci >> 0) & 0xFF;
- *asmptr++ = ROSE_DATA;
- SOCK_DEBUG(sk, "Built header.\n");
+ /*
+ * If the Q BIT Include socket option is in force, the first
+ * byte of the user data is the logical value of the Q Bit.
+ */
+ if (sk->protinfo.rose->qbitincl) {
+ qbit = skb->data[0];
+ skb_pull(skb, 1);
+ }
/*
- * Put the data on the end
+ * Push down the ROSE header
*/
+ asmptr = skb_push(skb, ROSE_MIN_LEN);
- skb->h.raw = skb_put(skb, len);
+ SOCK_DEBUG(sk, "ROSE: Building Network Header.\n");
- asmptr = skb->h.raw;
- SOCK_DEBUG(sk, "Rose: Appending user data\n");
+ /* Build a ROSE Network header */
+ asmptr[0] = ((sk->protinfo.rose->lci >> 8) & 0x0F) | ROSE_GFI;
+ asmptr[1] = (sk->protinfo.rose->lci >> 0) & 0xFF;
+ asmptr[2] = ROSE_DATA;
- /* User data follows immediately after the Rose transport header */
- memcpy_fromiovec(asmptr, msg->msg_iov, len);
- SOCK_DEBUG(sk, "Rose: Transmitting buffer\n");
+ if (qbit)
+ asmptr[0] |= ROSE_Q_BIT;
+
+ SOCK_DEBUG(sk, "ROSE: Built header.\n");
+ SOCK_DEBUG(sk, "ROSE: Transmitting buffer\n");
+
if (sk->state != TCP_ESTABLISHED) {
kfree_skb(skb, FREE_WRITE);
return -ENOTCONN;
@@ -1123,7 +1086,8 @@ static int rose_recvmsg(struct socket *sock, struct msghdr *msg, int size,
{
struct sock *sk = sock->sk;
struct sockaddr_rose *srose = (struct sockaddr_rose *)msg->msg_name;
- int copied;
+ int copied, qbit;
+ unsigned char *asmptr;
struct sk_buff *skb;
int er;
@@ -1138,12 +1102,17 @@ static int rose_recvmsg(struct socket *sock, struct msghdr *msg, int size,
if ((skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, flags & MSG_DONTWAIT, &er)) == NULL)
return er;
- if (!sk->protinfo.rose->hdrincl) {
- skb_pull(skb, ROSE_MIN_LEN);
- skb->h.raw = skb->data;
+ qbit = (skb->data[0] & ROSE_Q_BIT) == ROSE_Q_BIT;
+
+ skb_pull(skb, ROSE_MIN_LEN);
+
+ if (sk->protinfo.rose->qbitincl) {
+ asmptr = skb_push(skb, 1);
+ *asmptr = qbit;
}
- copied = skb->len;
+ skb->h.raw = skb->data;
+ copied = skb->len;
if (copied > size) {
copied = size;
@@ -1231,10 +1200,6 @@ 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:
- if (!suser()) return -EPERM;
- return rose_ctl_ioctl(cmd, (void *)arg);
-
case SIOCRSL2CALL:
if (!suser()) return -EPERM;
if ((err = verify_area(VERIFY_READ, (void *)arg, sizeof(ax25_address))) != 0)
@@ -1373,14 +1338,7 @@ static struct proc_dir_entry proc_net_rose_routes = {
};
#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}
-};
+static struct device *dev_rose;
__initfunc(void rose_proto_init(struct net_proto *pro))
{
@@ -1388,17 +1346,26 @@ __initfunc(void rose_proto_init(struct net_proto *pro))
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.035 Linux 2.1\n");
+ if ((dev_rose = kmalloc(rose_ndevs * sizeof(struct device), GFP_KERNEL)) == NULL) {
+ printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate device structure\n");
+ return;
+ }
- 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");
+ memset(dev_rose, 0x00, rose_ndevs * sizeof(struct device));
- for (i = 0; i < 6; i++)
+ for (i = 0; i < rose_ndevs; i++) {
+ dev_rose[i].name = kmalloc(20, GFP_KERNEL);
+ sprintf(dev_rose[i].name, "rose%d", i);
+ dev_rose[i].init = rose_init;
register_netdev(&dev_rose[i]);
+ }
+
+ sock_register(&rose_family_ops);
+ register_netdevice_notifier(&rose_dev_notifier);
+ printk(KERN_INFO "G4KLX ROSE for Linux. Version 0.2 for AX25.035 Linux 2.1\n");
+
+ ax25_protocol_register(AX25_P_ROSE, rose_route_frame);
+ ax25_linkfail_register(rose_link_failed);
#ifdef CONFIG_SYSCTL
rose_register_sysctl();
@@ -1415,6 +1382,12 @@ __initfunc(void rose_proto_init(struct net_proto *pro))
#ifdef MODULE
EXPORT_NO_SYMBOLS;
+MODULE_PARM(rose_ndevs, "i");
+MODULE_PARM_DESC(rose_ndevs, "number of ROSE devices");
+
+MODULE_AUTHOR("Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>");
+MODULE_DESCRIPTION("The amateur radio ROSE network layer protocol");
+
int init_module(void)
{
rose_proto_init(NULL);
@@ -1447,13 +1420,16 @@ void cleanup_module(void)
sock_unregister(AF_ROSE);
- for (i = 0; i < 6; i++) {
+ for (i = 0; i < rose_ndevs; i++) {
if (dev_rose[i].priv != NULL) {
kfree(dev_rose[i].priv);
dev_rose[i].priv = NULL;
unregister_netdev(&dev_rose[i]);
}
+ kfree(dev_rose[i].name);
}
+
+ kfree(dev_rose);
}
#endif
diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c
index ebab50e0d..73d0aa552 100644
--- a/net/rose/rose_dev.c
+++ b/net/rose/rose_dev.c
@@ -1,8 +1,5 @@
/*
- * 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.
+ * ROSE release 002
*
* This code REQUIRES 2.1.15 or higher/ NET3.038
*
@@ -13,7 +10,7 @@
* 2 of the License, or (at your option) any later version.
*
* History
- * Rose 001 Jonathan(G4KLX) Cloned from nr_dev.c.
+ * ROSE 001 Jonathan(G4KLX) Cloned from nr_dev.c.
* Hans(PE1AYX) Fixed interface to IP layer.
*/
@@ -52,7 +49,7 @@
#include <net/rose.h>
/*
- * Only allow IP over Rose frames through if the netrom device is up.
+ * Only allow IP over ROSE frames through if the netrom device is up.
*/
int rose_rx_ip(struct sk_buff *skb, struct device *dev)
@@ -175,7 +172,7 @@ static int rose_xmit(struct sk_buff *skb, struct device *dev)
return 0;
if (!dev->start) {
- printk(KERN_ERR "rose: xmit call when iface is down\n");
+ printk(KERN_ERR "ROSE: rose_xmit - called when iface is down\n");
return 1;
}
@@ -226,10 +223,12 @@ int rose_init(struct device *dev)
dev->flags = 0;
dev->family = AF_INET;
- dev->pa_addr = 0;
- dev->pa_brdaddr = 0;
- dev->pa_mask = 0;
- dev->pa_alen = sizeof(unsigned long);
+#ifdef CONFIG_INET
+ dev->pa_addr = in_aton("192.168.0.1");
+ dev->pa_brdaddr = in_aton("192.168.0.255");
+ dev->pa_mask = in_aton("255.255.255.0");
+ dev->pa_alen = 4;
+#endif
if ((dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL)) == NULL)
return -ENOMEM;
diff --git a/net/rose/rose_in.c b/net/rose/rose_in.c
index 66521efa8..3c3e17b2b 100644
--- a/net/rose/rose_in.c
+++ b/net/rose/rose_in.c
@@ -1,8 +1,5 @@
/*
- * 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.
+ * ROSE release 002
*
* This code REQUIRES 2.1.15 or higher/ NET3.038
*
@@ -19,7 +16,7 @@
* easy to break;
*
* History
- * Rose 001 Jonathan(G4KLX) Cloned from nr_in.c
+ * ROSE 001 Jonathan(G4KLX) Cloned from nr_in.c
*/
#include <linux/config.h>
@@ -116,8 +113,7 @@ static int rose_state1_machine(struct sock *sk, struct sk_buff *skb, int framety
sk->dead = 1;
break;
- default: /* XXX */
- printk(KERN_WARNING "rose: unknown %02X in state 1\n", frametype);
+ default:
break;
}
@@ -146,8 +142,7 @@ static int rose_state2_machine(struct sock *sk, struct sk_buff *skb, int framety
sk->dead = 1;
break;
- default: /* XXX */
- printk(KERN_WARNING "rose: unknown %02X in state 2\n", frametype);
+ default:
break;
}
@@ -245,7 +240,7 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety
* If the window is full, ack the frame, else start the
* acknowledge hold back timer.
*/
- if (((sk->protinfo.rose->vl + ROSE_MAX_WINDOW_SIZE) % ROSE_MODULUS) == sk->protinfo.rose->vr) {
+ if (((sk->protinfo.rose->vl + sysctl_rose_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);
@@ -256,7 +251,7 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety
break;
default:
- printk(KERN_WARNING "rose: unknown %02X in state 3\n", frametype);
+ printk(KERN_WARNING "ROSE: unknown %02X in state 3\n", frametype);
break;
}
@@ -297,8 +292,7 @@ static int rose_state4_machine(struct sock *sk, struct sk_buff *skb, int framety
sk->dead = 1;
break;
- default: /* XXX */
- printk(KERN_WARNING "rose: unknown %02X in state 4\n", frametype);
+ default:
break;
}
diff --git a/net/rose/rose_link.c b/net/rose/rose_link.c
index 9f1a0c0f5..86626511e 100644
--- a/net/rose/rose_link.c
+++ b/net/rose/rose_link.c
@@ -1,8 +1,5 @@
/*
- * 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.
+ * ROSE release 002
*
* This code REQUIRES 2.1.15 or higher/ NET3.038
*
@@ -13,7 +10,7 @@
* 2 of the License, or (at your option) any later version.
*
* History
- * Rose 001 Jonathan(G4KLX) Cloned from rose_timer.c
+ * ROSE 001 Jonathan(G4KLX) Cloned from rose_timer.c
*/
#include <linux/config.h>
@@ -62,7 +59,7 @@ void rose_link_set_timer(struct rose_neigh *neigh)
}
/*
- * Rose Link Timer
+ * ROSE Link Timer
*
* This routine is called every 100ms. Decrement timer by this
* amount - if expired then process the event.
@@ -79,7 +76,8 @@ static void rose_link_timer(unsigned long param)
if (neigh->t0timer == 0) {
rose_transmit_restart_request(neigh);
- neigh->t0timer = sysctl_rose_restart_request_timeout;
+ neigh->dce_mode = 0;
+ neigh->t0timer = sysctl_rose_restart_request_timeout;
}
}
@@ -134,6 +132,7 @@ void rose_link_rx_restart(struct sk_buff *skb, struct rose_neigh *neigh, unsigne
case ROSE_RESTART_REQUEST:
neigh->t0timer = 0;
neigh->restarted = 1;
+ neigh->dce_mode = (skb->data[3] == 0x00);
del_timer(&neigh->timer);
rose_transmit_restart_confirmation(neigh);
break;
@@ -145,11 +144,11 @@ void rose_link_rx_restart(struct sk_buff *skb, struct rose_neigh *neigh, unsigne
break;
case ROSE_DIAGNOSTIC:
- printk(KERN_WARNING "rose: diagnostic #%d\n", skb->data[3]);
+ printk(KERN_WARNING "ROSE: received diagnostic #%d - %02X %02X %02X\n", skb->data[3], skb->data[4], skb->data[5], skb->data[6]);
break;
default:
- printk(KERN_WARNING "rose: received unknown %02X with LCI 000\n", frametype);
+ printk(KERN_WARNING "ROSE: received unknown %02X with LCI 000\n", frametype);
break;
}
@@ -278,8 +277,10 @@ void rose_transmit_link(struct sk_buff *skb, struct rose_neigh *neigh)
{
unsigned char *dptr;
- if (call_fw_firewall(PF_ROSE, skb->dev, skb->data, NULL,&skb) != FW_ACCEPT)
+ if (call_fw_firewall(PF_ROSE, skb->dev, skb->data, NULL, &skb) != FW_ACCEPT) {
+ kfree_skb(skb, FREE_WRITE);
return;
+ }
if (!rose_link_up(neigh))
neigh->restarted = 0;
@@ -295,7 +296,8 @@ void rose_transmit_link(struct sk_buff *skb, struct rose_neigh *neigh)
if (neigh->t0timer == 0) {
rose_transmit_restart_request(neigh);
- neigh->t0timer = sysctl_rose_restart_request_timeout;
+ neigh->dce_mode = 0;
+ 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 8ab4d9325..f0e212dc3 100644
--- a/net/rose/rose_out.c
+++ b/net/rose/rose_out.c
@@ -1,8 +1,5 @@
/*
- * 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.
+ * ROSE release 002
*
* This code REQUIRES 2.1.15 or higher/ NET3.038
*
@@ -13,7 +10,7 @@
* 2 of the License, or (at your option) any later version.
*
* History
- * Rose 001 Jonathan(G4KLX) Cloned from nr_out.c
+ * ROSE 001 Jonathan(G4KLX) Cloned from nr_out.c
*/
#include <linux/config.h>
@@ -41,7 +38,7 @@
#include <net/rose.h>
/*
- * This is where all Rose frames pass;
+ * This is where all ROSE frames pass;
*/
void rose_output(struct sock *sk, struct sk_buff *skb)
{
@@ -109,7 +106,7 @@ void rose_kick(struct sock *sk)
del_timer(&sk->timer);
- end = (sk->protinfo.rose->va + ROSE_MAX_WINDOW_SIZE) % ROSE_MODULUS;
+ end = (sk->protinfo.rose->va + sysctl_rose_window_size) % ROSE_MODULUS;
if (!(sk->protinfo.rose->condition & ROSE_COND_PEER_RX_BUSY) &&
sk->protinfo.rose->vs != end &&
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index 19a53d40d..5b1338609 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -1,8 +1,5 @@
/*
- * 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.
+ * ROSE release 002
*
* This code REQUIRES 2.1.15 or higher/ NET3.038
*
@@ -13,9 +10,11 @@
* 2 of the License, or (at your option) any later version.
*
* History
- * Rose 001 Jonathan(G4KLX) Cloned from nr_route.c.
+ * ROSE 001 Jonathan(G4KLX) Cloned from nr_route.c.
* Terry(VK2KTJ) Added support for variable length
* address masks.
+ * ROSE 002 Jonathan(G4KLX) Uprated through routing of packets.
+ * Routing loop detection.
*/
#include <linux/config.h>
@@ -76,13 +75,14 @@ static int rose_add_node(struct rose_route_struct *rose_route, struct device *de
break;
if (rose_neigh == NULL) {
- if ((rose_neigh = (struct rose_neigh *)kmalloc(sizeof(*rose_neigh), GFP_ATOMIC)) == NULL)
+ if ((rose_neigh = kmalloc(sizeof(*rose_neigh), GFP_ATOMIC)) == NULL)
return -ENOMEM;
rose_neigh->callsign = rose_route->neighbour;
rose_neigh->digipeat = NULL;
rose_neigh->dev = dev;
rose_neigh->count = 0;
+ rose_neigh->dce_mode = 0;
rose_neigh->number = rose_neigh_no++;
rose_neigh->restarted = 0;
skb_queue_head_init(&rose_neigh->queue);
@@ -92,7 +92,7 @@ static int rose_add_node(struct rose_route_struct *rose_route, struct device *de
if (rose_route->ndigis != 0) {
if ((rose_neigh->digipeat = kmalloc(sizeof(ax25_digi), GFP_KERNEL)) == NULL) {
- kfree_s(rose_neigh, sizeof(*rose_neigh));
+ kfree(rose_neigh);
return -ENOMEM;
}
rose_neigh->digipeat->ndigi = rose_route->ndigis;
@@ -127,7 +127,7 @@ static int rose_add_node(struct rose_route_struct *rose_route, struct device *de
}
/* create new node */
- if ((rose_node = (struct rose_node *)kmalloc(sizeof(*rose_node), GFP_ATOMIC)) == NULL)
+ if ((rose_node = kmalloc(sizeof(*rose_node), GFP_ATOMIC)) == NULL)
return -ENOMEM;
rose_node->address = rose_route->address;
@@ -183,7 +183,7 @@ static void rose_remove_node(struct rose_node *rose_node)
if ((s = rose_node_list) == rose_node) {
rose_node_list = rose_node->next;
restore_flags(flags);
- kfree_s(rose_node, sizeof(struct rose_node));
+ kfree(rose_node);
return;
}
@@ -191,7 +191,7 @@ static void rose_remove_node(struct rose_node *rose_node)
if (s->next == rose_node) {
s->next = rose_node->next;
restore_flags(flags);
- kfree_s(rose_node, sizeof(struct rose_node));
+ kfree(rose_node);
return;
}
@@ -219,8 +219,8 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh)
rose_neigh_list = rose_neigh->next;
restore_flags(flags);
if (rose_neigh->digipeat != NULL)
- kfree_s(rose_neigh->digipeat, sizeof(ax25_digi));
- kfree_s(rose_neigh, sizeof(struct rose_neigh));
+ kfree(rose_neigh->digipeat);
+ kfree(rose_neigh);
return;
}
@@ -229,8 +229,8 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh)
s->next = rose_neigh->next;
restore_flags(flags);
if (rose_neigh->digipeat != NULL)
- kfree_s(rose_neigh->digipeat, sizeof(ax25_digi));
- kfree_s(rose_neigh, sizeof(struct rose_neigh));
+ kfree(rose_neigh->digipeat);
+ kfree(rose_neigh);
return;
}
@@ -251,7 +251,7 @@ static void rose_remove_route(struct rose_route *rose_route)
if ((s = rose_route_list) == rose_route) {
rose_route_list = rose_route->next;
restore_flags(flags);
- kfree_s(rose_route, sizeof(struct rose_route));
+ kfree(rose_route);
return;
}
@@ -259,7 +259,7 @@ static void rose_remove_route(struct rose_route *rose_route)
if (s->next == rose_route) {
s->next = rose_route->next;
restore_flags(flags);
- kfree_s(rose_route, sizeof(struct rose_route));
+ kfree(rose_route);
return;
}
@@ -372,7 +372,7 @@ void rose_route_device_down(struct device *dev)
struct rose_route *s, *rose_route = rose_route_list;
while (rose_route != NULL) {
- s = rose_route;
+ s = rose_route;
rose_route = rose_route->next;
if (s->neigh1->dev == dev || s->neigh2->dev == dev)
@@ -397,7 +397,7 @@ struct device *rose_ax25_dev_get(char *devname)
}
/*
- * Find the first active Rose device, usually "rose0".
+ * Find the first active ROSE device, usually "rose0".
*/
struct device *rose_dev_first(void)
{
@@ -412,7 +412,7 @@ struct device *rose_dev_first(void)
}
/*
- * Find the Rose device for the given address.
+ * Find the ROSE device for the given address.
*/
struct device *rose_dev_get(rose_address *addr)
{
@@ -425,23 +425,34 @@ struct device *rose_dev_get(rose_address *addr)
return NULL;
}
+struct rose_route *rose_route_free_lci(unsigned int lci, struct rose_neigh *neigh)
+{
+ struct rose_route *rose_route;
+
+ for (rose_route = rose_route_list; rose_route != NULL; rose_route = rose_route->next)
+ if ((rose_route->neigh1 == neigh && rose_route->lci1 == lci) ||
+ (rose_route->neigh2 == neigh && rose_route->lci2 == lci))
+ return rose_route;
+
+ return NULL;
+}
+
/*
- * Find a neighbour given a Rose address.
+ * Find a neighbour given a ROSE address.
*/
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 (rosecmpm(addr, &node->address, node->mask) == 0)
- break;
-
- if (node == NULL) return NULL;
-
- for (i = 0; i < node->count; i++)
- if (node->neighbour[i]->ftimer == 0)
- return node->neighbour[i];
+ for (node = rose_node_list; node != NULL; node = node->next) {
+ if (rosecmpm(addr, &node->address, node->mask) == 0) {
+ for (i = 0; i < node->count; i++) {
+ if (node->neighbour[i]->ftimer == 0)
+ return node->neighbour[i];
+ }
+ }
+ }
return NULL;
}
@@ -485,14 +496,54 @@ int rose_rt_ioctl(unsigned int cmd, void *arg)
return 0;
}
+static void rose_del_route_by_neigh(struct rose_neigh *rose_neigh)
+{
+ struct rose_route *rose_route, *s;
+ struct sk_buff *skb;
+
+ rose_neigh->restarted = 0;
+ rose_neigh->t0timer = 0;
+ 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);
+
+ rose_route = rose_route_list;
+
+ while (rose_route != NULL) {
+ if ((rose_route->neigh1 == rose_neigh && rose_route->neigh2 == rose_neigh) ||
+ (rose_route->neigh1 == rose_neigh && rose_route->neigh2 == NULL) ||
+ (rose_route->neigh2 == rose_neigh && rose_route->neigh1 == NULL)) {
+ s = rose_route->next;
+ rose_remove_route(rose_route);
+ rose_route = s;
+ continue;
+ }
+
+ if (rose_route->neigh1 == rose_neigh) {
+ rose_route->neigh1 = NULL;
+ rose_transmit_clear_request(rose_route->neigh2, rose_route->lci2, 0x0D);
+ }
+
+ if (rose_route->neigh2 == rose_neigh) {
+ rose_route->neigh2 = NULL;
+ rose_transmit_clear_request(rose_route->neigh1, rose_route->lci1, 0x0D);
+ }
+
+ rose_route = rose_route->next;
+ }
+}
+
/*
* A level 2 link has timed out, therefore it appears to be a poor link,
- * then don't use that neighbour until it is reset. XXX others.
+ * then don't use that neighbour until it is reset. Blow away all through
+ * routes and connections using this route.
*/
void rose_link_failed(ax25_address *callsign, struct device *dev)
{
struct rose_neigh *rose_neigh;
- 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)
@@ -500,33 +551,22 @@ void rose_link_failed(ax25_address *callsign, struct device *dev)
if (rose_neigh == NULL) return;
- rose_neigh->restarted = 0;
- rose_neigh->t0timer = 0;
- 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);
+ rose_del_route_by_neigh(rose_neigh);
+ rose_kill_by_neigh(rose_neigh);
}
/*
- * A device has been "downed" remove its link status. XXX others.
+ * A device has been "downed" remove its link status. Blow away all
+ * through routes and connections that use this device.
*/
void rose_link_device_down(struct device *dev)
{
struct rose_neigh *rose_neigh;
- 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);
+ rose_del_route_by_neigh(rose_neigh);
+ rose_kill_by_neigh(rose_neigh);
}
}
}
@@ -538,10 +578,11 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
{
struct rose_neigh *rose_neigh, *new_neigh;
struct rose_route *rose_route;
+ struct rose_facilities facilities;
rose_address *src_addr, *dest_addr;
struct sock *sk;
unsigned short frametype;
- unsigned int lci;
+ unsigned int lci, new_lci;
struct device *dev;
unsigned long flags;
@@ -577,7 +618,7 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
/*
* Find an existing socket.
*/
- if ((sk = rose_find_socket(lci, rose_neigh->dev)) != NULL) {
+ if ((sk = rose_find_socket(lci, rose_neigh)) != NULL) {
skb->h.raw = skb->data;
return rose_process_rx_frame(sk, skb);
}
@@ -597,29 +638,36 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
/*
* Route it to the next in line if we have an entry for it.
*/
-
- /*
- * We should check for the random number in the facilities
- * here. XXX.
- */
for (rose_route = rose_route_list; rose_route != NULL; rose_route = rose_route->next) {
if (rose_route->lci1 == lci && rose_route->neigh1 == rose_neigh) {
- skb->data[0] &= 0xF0;
- skb->data[0] |= (rose_route->lci2 >> 8) & 0x0F;
- skb->data[1] = (rose_route->lci2 >> 0) & 0xFF;
- rose_transmit_link(skb, rose_route->neigh2);
- if (frametype == ROSE_CLEAR_CONFIRMATION)
- rose_remove_route(rose_route);
- return 1;
+ if (rose_route->neigh2 != NULL) {
+ skb->data[0] &= 0xF0;
+ skb->data[0] |= (rose_route->lci2 >> 8) & 0x0F;
+ skb->data[1] = (rose_route->lci2 >> 0) & 0xFF;
+ rose_transmit_link(skb, rose_route->neigh2);
+ if (frametype == ROSE_CLEAR_CONFIRMATION)
+ rose_remove_route(rose_route);
+ return 1;
+ } else {
+ if (frametype == ROSE_CLEAR_CONFIRMATION)
+ rose_remove_route(rose_route);
+ return 0;
+ }
}
if (rose_route->lci2 == lci && rose_route->neigh2 == rose_neigh) {
- skb->data[0] &= 0xF0;
- skb->data[0] |= (rose_route->lci1 >> 8) & 0x0F;
- skb->data[1] = (rose_route->lci1 >> 0) & 0xFF;
- rose_transmit_link(skb, rose_route->neigh1);
- if (frametype == ROSE_CLEAR_CONFIRMATION)
- rose_remove_route(rose_route);
- return 1;
+ if (rose_route->neigh1 != NULL) {
+ skb->data[0] &= 0xF0;
+ skb->data[0] |= (rose_route->lci1 >> 8) & 0x0F;
+ skb->data[1] = (rose_route->lci1 >> 0) & 0xFF;
+ rose_transmit_link(skb, rose_route->neigh1);
+ if (frametype == ROSE_CLEAR_CONFIRMATION)
+ rose_remove_route(rose_route);
+ return 1;
+ } else {
+ if (frametype == ROSE_CLEAR_CONFIRMATION)
+ rose_remove_route(rose_route);
+ return 0;
+ }
}
}
@@ -631,20 +679,49 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
if (frametype != ROSE_CALL_REQUEST) /* XXX */
return 0;
+ rose_parse_facilities(skb, &facilities);
+
+ /*
+ * Check for routing loops.
+ */
+ for (rose_route = rose_route_list; rose_route != NULL; rose_route = rose_route->next) {
+ if (rose_route->rand == facilities.rand &&
+ rosecmp(src_addr, &rose_route->src_addr) == 0 &&
+ ax25cmp(&facilities.dest_call, &rose_route->src_call) == 0 &&
+ ax25cmp(&facilities.source_call, &rose_route->dest_call) == 0) {
+ printk(KERN_DEBUG "ROSE: routing loop from %s\n", rose2asc(src_addr));
+ printk(KERN_DEBUG "ROSE: to %s\n", rose2asc(dest_addr));
+ rose_transmit_clear_request(rose_neigh, lci, 0x0D);
+ return 0;
+ }
+ }
+
if ((new_neigh = rose_get_neigh(dest_addr)) == NULL) {
+ printk(KERN_DEBUG "ROSE: no route to %s\n", rose2asc(dest_addr));
rose_transmit_clear_request(rose_neigh, lci, 0x0D);
return 0;
}
- if ((rose_route = (struct rose_route *)kmalloc(sizeof(*rose_route), GFP_ATOMIC)) == NULL) {
+ if ((new_lci = rose_new_lci(new_neigh)) == 0) {
+ printk(KERN_DEBUG "ROSE: no spare VCs to %s\n", rose2asc(dest_addr));
rose_transmit_clear_request(rose_neigh, lci, 0x0D);
return 0;
}
- rose_route->lci1 = lci;
- rose_route->neigh1 = rose_neigh;
- rose_route->lci2 = rose_new_lci(new_neigh->dev);
- rose_route->neigh2 = new_neigh;
+ if ((rose_route = kmalloc(sizeof(*rose_route), GFP_ATOMIC)) == NULL) {
+ rose_transmit_clear_request(rose_neigh, lci, 0x0D);
+ return 0;
+ }
+
+ rose_route->lci1 = lci;
+ rose_route->src_addr = *src_addr;
+ rose_route->dest_addr = *dest_addr;
+ rose_route->src_call = facilities.dest_call;
+ rose_route->dest_call = facilities.source_call;
+ rose_route->rand = facilities.rand;
+ rose_route->neigh1 = rose_neigh;
+ rose_route->lci2 = new_lci;
+ rose_route->neigh2 = new_neigh;
save_flags(flags); cli();
rose_route->next = rose_route_list;
@@ -716,14 +793,15 @@ int rose_neigh_get_info(char *buffer, char **start, off_t offset,
cli();
- len += sprintf(buffer, "addr callsign dev count restart t0 tf\n");
+ len += sprintf(buffer, "addr callsign dev count mode 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 %3d\n",
+ len += sprintf(buffer + len, "%05d %-9s %-4s %3d %3s %3s %3d %3d\n",
rose_neigh->number,
ax2asc(&rose_neigh->callsign),
rose_neigh->dev ? rose_neigh->dev->name : "???",
rose_neigh->count,
+ (rose_neigh->dce_mode) ? "DCE" : "DTE",
(rose_neigh->restarted) ? "yes" : "no",
rose_neigh->t0timer / ROSE_SLOWHZ,
rose_neigh->ftimer / ROSE_SLOWHZ);
@@ -759,17 +837,28 @@ int rose_routes_get_info(char *buffer, char **start, off_t offset,
cli();
- len += sprintf(buffer, "lci callsign dev <-> lci callsign dev\n");
+ len += sprintf(buffer, "lci address callsign neigh <-> lci address callsign neigh\n");
for (rose_route = rose_route_list; rose_route != NULL; rose_route = rose_route->next) {
- len += sprintf(buffer + len, "%3.3X %-9s %-4s ",
- rose_route->lci1,
- ax2asc(&rose_route->neigh1->callsign),
- rose_route->neigh1->dev ? rose_route->neigh1->dev->name : "???");
- len += sprintf(buffer + len, "%3.3X %-9s %-4s\n",
- rose_route->lci2,
- ax2asc(&rose_route->neigh2->callsign),
- rose_route->neigh2->dev ? rose_route->neigh2->dev->name : "???");
+ if (rose_route->neigh1 != NULL) {
+ len += sprintf(buffer + len, "%3.3X %-10s %-9s %05d ",
+ rose_route->lci1,
+ rose2asc(&rose_route->src_addr),
+ ax2asc(&rose_route->src_call),
+ rose_route->neigh1->number);
+ } else {
+ len += sprintf(buffer + len, "000 * * 00000 ");
+ }
+
+ if (rose_route->neigh2 != NULL) {
+ len += sprintf(buffer + len, "%3.3X %-10s %-9s %05d\n",
+ rose_route->lci2,
+ rose2asc(&rose_route->dest_addr),
+ ax2asc(&rose_route->dest_call),
+ rose_route->neigh2->number);
+ } else {
+ len += sprintf(buffer + len, "000 * * 00000\n");
+ }
pos = begin + len;
@@ -795,7 +884,7 @@ int rose_routes_get_info(char *buffer, char **start, off_t offset,
#ifdef MODULE
/*
- * Release all memory associated with Rose routing structures.
+ * Release all memory associated with ROSE routing structures.
*/
void rose_rt_free(void)
{
@@ -811,7 +900,7 @@ void rose_rt_free(void)
}
while (rose_node != NULL) {
- t = rose_node;
+ t = rose_node;
rose_node = rose_node->next;
rose_remove_node(t);
diff --git a/net/rose/rose_subr.c b/net/rose/rose_subr.c
index 5befcbb60..4e0530cb4 100644
--- a/net/rose/rose_subr.c
+++ b/net/rose/rose_subr.c
@@ -1,8 +1,5 @@
/*
- * 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.
+ * ROSE release 002
*
* This code REQUIRES 2.1.15 or higher/ NET3.038
*
@@ -13,7 +10,7 @@
* 2 of the License, or (at your option) any later version.
*
* History
- * Rose 001 Jonathan(G4KLX) Cloned from nr_subr.c
+ * ROSE 001 Jonathan(G4KLX) Cloned from nr_subr.c
*/
#include <linux/config.h>
@@ -173,7 +170,7 @@ void rose_write_internal(struct sock *sk, int frametype)
break;
default:
- printk(KERN_ERR "rose_write_internal: invalid frametype %02X\n", frametype);
+ printk(KERN_ERR "ROSE: rose_write_internal - invalid frametype %02X\n", frametype);
kfree_skb(skb, FREE_WRITE);
return;
}
@@ -227,7 +224,7 @@ int rose_decode(struct sk_buff *skb, int *ns, int *nr, int *q, int *d, int *m)
return ROSE_ILLEGAL;
}
-static int rose_parse_national(unsigned char *p, rose_cb *rose, int len)
+static int rose_parse_national(unsigned char *p, struct rose_facilities *facilities, int len)
{
unsigned char l, n = 0;
@@ -241,7 +238,7 @@ static int rose_parse_national(unsigned char *p, rose_cb *rose, int len)
case 0x40:
if (*p == FAC_NATIONAL_RAND)
- rose->rand = ((p[1] << 8) & 0xFF00) + ((p[2] << 0) & 0x00FF);
+ facilities->rand = ((p[1] << 8) & 0xFF00) + ((p[2] << 0) & 0x00FF);
p += 3;
n += 3;
len -= 3;
@@ -256,12 +253,12 @@ static int rose_parse_national(unsigned char *p, rose_cb *rose, int len)
case 0xC0:
l = p[1];
if (*p == FAC_NATIONAL_DEST_DIGI) {
- memcpy(&rose->source_digi, p + 2, AX25_ADDR_LEN);
- rose->source_ndigis = 1;
+ memcpy(&facilities->source_digi, p + 2, AX25_ADDR_LEN);
+ facilities->source_ndigis = 1;
}
if (*p == FAC_NATIONAL_SRC_DIGI) {
- memcpy(&rose->dest_digi, p + 2, AX25_ADDR_LEN);
- rose->dest_ndigis = 1;
+ memcpy(&facilities->dest_digi, p + 2, AX25_ADDR_LEN);
+ facilities->dest_ndigis = 1;
}
p += l + 2;
n += l + 2;
@@ -273,7 +270,7 @@ static int rose_parse_national(unsigned char *p, rose_cb *rose, int len)
return n;
}
-static int rose_parse_ccitt(unsigned char *p, rose_cb *rose, int len)
+static int rose_parse_ccitt(unsigned char *p, struct rose_facilities *facilities, int len)
{
unsigned char l, n = 0;
char callsign[11];
@@ -301,16 +298,16 @@ static int rose_parse_ccitt(unsigned char *p, rose_cb *rose, int len)
case 0xC0:
l = p[1];
if (*p == FAC_CCITT_DEST_NSAP) {
- memcpy(&rose->source_addr, p + 7, ROSE_ADDR_LEN);
+ memcpy(&facilities->source_addr, p + 7, ROSE_ADDR_LEN);
memcpy(callsign, p + 12, l - 10);
callsign[l - 10] = '\0';
- rose->source_call = *asc2ax(callsign);
+ facilities->source_call = *asc2ax(callsign);
}
if (*p == FAC_CCITT_SRC_NSAP) {
- memcpy(&rose->dest_addr, p + 7, ROSE_ADDR_LEN);
+ memcpy(&facilities->dest_addr, p + 7, ROSE_ADDR_LEN);
memcpy(callsign, p + 12, l - 10);
callsign[l - 10] = '\0';
- rose->dest_call = *asc2ax(callsign);
+ facilities->dest_call = *asc2ax(callsign);
}
p += l + 2;
n += l + 2;
@@ -322,12 +319,12 @@ static int rose_parse_ccitt(unsigned char *p, rose_cb *rose, int len)
return n;
}
-int rose_parse_facilities(struct sk_buff *skb, rose_cb *rose)
+int rose_parse_facilities(struct sk_buff *skb, struct rose_facilities *facilities)
{
int facilities_len, len;
unsigned char *p;
- memset(rose, 0x00, sizeof(rose_cb));
+ memset(facilities, 0x00, sizeof(struct rose_facilities));
len = (((skb->data[3] >> 4) & 0x0F) + 1) / 2;
len += (((skb->data[3] >> 0) & 0x0F) + 1) / 2;
@@ -346,19 +343,19 @@ int rose_parse_facilities(struct sk_buff *skb, rose_cb *rose)
switch (*p) {
case FAC_NATIONAL: /* National */
- len = rose_parse_national(p + 1, rose, facilities_len - 1);
+ len = rose_parse_national(p + 1, facilities, facilities_len - 1);
facilities_len -= len + 1;
p += len + 1;
break;
case FAC_CCITT: /* CCITT */
- len = rose_parse_ccitt(p + 1, rose, facilities_len - 1);
+ len = rose_parse_ccitt(p + 1, facilities, facilities_len - 1);
facilities_len -= len + 1;
p += len + 1;
break;
default:
- printk(KERN_DEBUG "rose_parse_facilities: unknown facilities family %02X\n", *p);
+ printk(KERN_DEBUG "ROSE: rose_parse_facilities - unknown facilities family %02X\n", *p);
facilities_len--;
p++;
break;
diff --git a/net/rose/rose_timer.c b/net/rose/rose_timer.c
index 869f312f5..572975e5d 100644
--- a/net/rose/rose_timer.c
+++ b/net/rose/rose_timer.c
@@ -1,8 +1,5 @@
/*
- * 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.
+ * ROSE release 002
*
* This code REQUIRES 2.1.15 or higher/ NET3.038
*
@@ -13,7 +10,7 @@
* 2 of the License, or (at your option) any later version.
*
* History
- * Rose 001 Jonathan(G4KLX) Cloned from nr_timer.c
+ * ROSE 001 Jonathan(G4KLX) Cloned from nr_timer.c
*/
#include <linux/config.h>
@@ -61,7 +58,7 @@ void rose_set_timer(struct sock *sk)
}
/*
- * Rose Timer
+ * ROSE Timer
*
* This routine is called every 100ms. Decrement timer by this
* amount - if expired then process the event.
diff --git a/net/rose/sysctl_net_rose.c b/net/rose/sysctl_net_rose.c
index 8cd49695f..409f79b52 100644
--- a/net/rose/sysctl_net_rose.c
+++ b/net/rose/sysctl_net_rose.c
@@ -1,5 +1,5 @@
/* -*- linux-c -*-
- * sysctl_net_rose.c: sysctl interface to net Rose subsystem.
+ * sysctl_net_rose.c: sysctl interface to net ROSE subsystem.
*
* Begun April 1, 1996, Mike Shaver.
* Added /proc/sys/net/rose directory entry (empty =) ). [MS]
@@ -18,6 +18,8 @@ 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 int min_maxvcs[] = {1}, max_maxvcs[] = {254};
+static int min_window[] = {1}, max_window[] = {7};
static struct ctl_table_header *rose_table_header;
@@ -46,6 +48,12 @@ static ctl_table rose_table[] = {
{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},
+ {NET_ROSE_MAX_VCS, "maximum_virtual_circuits",
+ &sysctl_rose_maximum_vcs, sizeof(int), 0644, NULL,
+ &proc_dointvec_minmax, &sysctl_intvec, NULL, &min_maxvcs, &max_maxvcs},
+ {NET_ROSE_WINDOW_SIZE, "window_size",
+ &sysctl_rose_window_size, sizeof(int), 0644, NULL,
+ &proc_dointvec_minmax, &sysctl_intvec, NULL, &min_window, &max_window},
{0}
};
diff --git a/net/x25/Makefile b/net/x25/Makefile
index a215a8ea2..3341a8003 100644
--- a/net/x25/Makefile
+++ b/net/x25/Makefile
@@ -8,7 +8,8 @@
# Note 2! The CFLAGS definition is now in the main makefile...
O_TARGET := x25.o
-O_OBJS := af_x25.o x25_dev.o x25_in.o x25_link.o x25_out.o x25_route.o x25_subr.o x25_timer.o
+O_OBJS := af_x25.o x25_dev.o x25_facilities.o x25_in.o x25_link.o x25_out.o \
+ x25_route.o x25_subr.o x25_timer.o
M_OBJS := $(O_TARGET)
ifeq ($(CONFIG_SYSCTL),y)
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 63a616e89..c7cb33613 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -60,6 +60,8 @@ static struct sock *volatile x25_list = NULL;
static struct proto_ops x25_proto_ops;
+static x25_address null_x25_address = {" "};
+
int x25_addr_ntoa(unsigned char *p, x25_address *called_addr, x25_address *calling_addr)
{
int called_len, calling_len;
@@ -116,16 +118,16 @@ int x25_addr_aton(unsigned char *p, x25_address *called_addr, x25_address *calli
if (i % 2 != 0) {
*p |= (*called++ - '0') << 0;
p++;
- *p = 0x00;
} else {
+ *p = 0x00;
*p |= (*called++ - '0') << 4;
}
} else {
if (i % 2 != 0) {
*p |= (*calling++ - '0') << 0;
p++;
- *p = 0x00;
} else {
+ *p = 0x00;
*p |= (*calling++ - '0') << 4;
}
}
@@ -239,7 +241,9 @@ static struct sock *x25_find_listener(x25_address *addr)
cli();
for (s = x25_list; s != NULL; s = s->next) {
- if (strcmp(s->protinfo.x25->source_addr.x25_addr, addr->x25_addr) == 0 && s->state == TCP_LISTEN) {
+ if ((strcmp(addr->x25_addr, s->protinfo.x25->source_addr.x25_addr) == 0 ||
+ strcmp(addr->x25_addr, null_x25_address.x25_addr) == 0) &&
+ s->state == TCP_LISTEN) {
restore_flags(flags);
return s;
}
@@ -337,7 +341,7 @@ void x25_destroy_socket(struct sock *sk) /* Not static as it's used by the timer
sk->timer.data = (unsigned long)sk;
add_timer(&sk->timer);
} else {
- kfree_s(sk->protinfo.x25, sizeof(*sk->protinfo.x25));
+ kfree(sk->protinfo.x25);
sk_free(sk);
MOD_DEC_USE_COUNT;
}
@@ -430,7 +434,7 @@ static struct sock *x25_alloc_socket(void)
if ((sk = sk_alloc(GFP_ATOMIC)) == NULL)
return NULL;
- if ((x25 = (x25_cb *)kmalloc(sizeof(*x25), GFP_ATOMIC)) == NULL) {
+ if ((x25 = kmalloc(sizeof(*x25), GFP_ATOMIC)) == NULL) {
sk_free(sk);
return NULL;
}
@@ -601,7 +605,9 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
x25_insert_socket(sk);
sk->zapped = 0;
+
SOCK_DEBUG(sk, "x25_bind: socket is bound\n");
+
return 0;
}
@@ -642,6 +648,9 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len
if (sk->zapped) /* Must bind first - autobinding does not work */
return -EINVAL;
+ if (strcmp(sk->protinfo.x25->source_addr.x25_addr, null_x25_address.x25_addr) == 0)
+ memset(&sk->protinfo.x25->source_addr, '\0', X25_ADDR_LEN);
+
sk->protinfo.x25->dest_addr = addr->sx25_addr;
sk->protinfo.x25->lci = x25_new_lci();
@@ -662,7 +671,7 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len
cli(); /* To avoid races on the sleep */
/*
- * A Connect Ack with Choke or timeout or failed routing will go to closed.
+ * A Clear Request or timeout or failed routing will go to closed.
*/
while (sk->state == TCP_SYN_SENT) {
interruptible_sleep_on(sk->sleep);
@@ -767,6 +776,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *neigh, unsigned i
struct sock *make;
x25_address source_addr, dest_addr;
struct x25_facilities facilities;
+ int len;
/*
* Remove the LCI and frame type.
@@ -787,16 +797,31 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *neigh, unsigned i
/*
* We can't accept the Call Request.
*/
- if (sk == NULL || sk->ack_backlog == sk->max_ack_backlog || (make = x25_make_new(sk)) == NULL) {
+ if (sk == NULL || sk->ack_backlog == sk->max_ack_backlog) {
+ x25_transmit_clear_request(neigh, lci, 0x01);
+ return 0;
+ }
+
+ /*
+ * Try to reach a compromise on the requested facilities.
+ */
+ if ((len = x25_negotiate_facilities(skb, sk, &facilities)) == -1) {
+ x25_transmit_clear_request(neigh, lci, 0x01);
+ return 0;
+ }
+
+ /*
+ * Try to create a new socket.
+ */
+ if ((make = x25_make_new(sk)) == NULL) {
x25_transmit_clear_request(neigh, lci, 0x01);
return 0;
}
/*
- * Parse the facilities, and remove them, leaving any Call User
- * Data.
+ * Remove the facilities, leaving any Call User Data.
*/
- skb_pull(skb, x25_parse_facilities(skb, &facilities));
+ skb_pull(skb, len);
skb->sk = make;
make->state = TCP_ESTABLISHED;
@@ -805,11 +830,6 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *neigh, unsigned i
make->protinfo.x25->dest_addr = dest_addr;
make->protinfo.x25->source_addr = source_addr;
make->protinfo.x25->neighbour = neigh;
-
- /*
- * This implies that we accept all the incoming facilities
- * values (if any). This needs fixing. XXX
- */
make->protinfo.x25->facilities = facilities;
x25_write_internal(make, X25_CALL_ACCEPTED);
@@ -883,10 +903,12 @@ static int x25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
sx25.sx25_family = AF_X25;
sx25.sx25_addr = sk->protinfo.x25->dest_addr;
}
+
SOCK_DEBUG(sk, "x25_sendmsg: sendto: Addresses built.\n");
/* Build a packet */
SOCK_DEBUG(sk, "x25_sendmsg: sendto: building packet.\n");
+
if ((msg->msg_flags & MSG_OOB) && len > 32)
len = 32;
@@ -901,8 +923,8 @@ static int x25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
* Put the data on the end
*/
SOCK_DEBUG(sk, "x25_sendmsg: Copying user data\n");
- skb->h.raw = skb_put(skb, len);
- asmptr = skb->h.raw;
+
+ asmptr = skb->h.raw = skb_put(skb, len);
memcpy_fromiovec(asmptr, msg->msg_iov, len);
@@ -919,6 +941,7 @@ static int x25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
* Push down the X.25 header
*/
SOCK_DEBUG(sk, "x25_sendmsg: Building X.25 Header.\n");
+
if (msg->msg_flags & MSG_OOB) {
if (sk->protinfo.x25->neighbour->extended) {
asmptr = skb_push(skb, X25_STD_MIN_LEN);
@@ -950,6 +973,7 @@ static int x25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
if (qbit)
skb->data[0] |= X25_Q_BIT;
}
+
SOCK_DEBUG(sk, "x25_sendmsg: Built header.\n");
SOCK_DEBUG(sk, "x25_sendmsg: Transmitting buffer\n");
@@ -1078,7 +1102,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCGSTAMP:
if (sk != NULL) {
- if (sk->stamp.tv_sec==0)
+ if (sk->stamp.tv_sec == 0)
return -ENOENT;
if ((err = verify_area(VERIFY_WRITE,(void *)arg,sizeof(struct timeval))) != 0)
return err;
@@ -1270,12 +1294,6 @@ static struct proc_dir_entry proc_net_x25 = {
0, &proc_net_inode_operations,
x25_get_info
};
-static struct proc_dir_entry proc_net_x25_links = {
- PROC_NET_X25_LINKS, 9, "x25_links",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- x25_link_get_info
-};
static struct proc_dir_entry proc_net_x25_routes = {
PROC_NET_X25_ROUTES, 10, "x25_routes",
S_IFREG | S_IRUGO, 1, 0, 0,
@@ -1301,7 +1319,6 @@ __initfunc(void x25_proto_init(struct net_proto *pro))
#ifdef CONFIG_PROC_FS
proc_net_register(&proc_net_x25);
- proc_net_register(&proc_net_x25_links);
proc_net_register(&proc_net_x25_routes);
#endif
}
@@ -1309,6 +1326,9 @@ __initfunc(void x25_proto_init(struct net_proto *pro))
#ifdef MODULE
EXPORT_NO_SYMBOLS;
+MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>");
+MODULE_DESCRIPTION("The X.25 Packet Layer network layer protocol");
+
int init_module(void)
{
struct device *dev;
@@ -1334,7 +1354,6 @@ void cleanup_module(void)
#ifdef CONFIG_PROC_FS
proc_net_unregister(PROC_NET_X25);
- proc_net_unregister(PROC_NET_X25_LINKS);
proc_net_unregister(PROC_NET_X25_ROUTES);
#endif
diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c
index 684c841b7..82e5c0817 100644
--- a/net/x25/x25_in.c
+++ b/net/x25/x25_in.c
@@ -84,7 +84,6 @@ static int x25_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more)
static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype)
{
x25_address source_addr, dest_addr;
- struct x25_facilities facilities;
switch (frametype) {
@@ -102,9 +101,8 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp
*/
skb_pull(skb, X25_STD_MIN_LEN);
skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr));
- skb_pull(skb, x25_parse_facilities(skb, &facilities));
+ skb_pull(skb, x25_parse_facilities(skb, &sk->protinfo.x25->facilities));
/*
- * Facilities XXX
* Copy any Call User Data.
*/
if (skb->len >= 0) {
@@ -128,7 +126,6 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp
break;
default:
- printk(KERN_WARNING "x25: unknown %02X in state 1\n", frametype);
break;
}
@@ -158,7 +155,6 @@ static int x25_state2_machine(struct sock *sk, struct sk_buff *skb, int frametyp
break;
default:
- printk(KERN_WARNING "x25: unknown %02X in state 2\n", frametype);
break;
}
@@ -334,7 +330,6 @@ static int x25_state4_machine(struct sock *sk, struct sk_buff *skb, int frametyp
break;
default:
- printk(KERN_WARNING "x25: unknown %02X in state 4\n", frametype);
break;
}
diff --git a/net/x25/x25_link.c b/net/x25/x25_link.c
index b3fce4696..f44c0a2c5 100644
--- a/net/x25/x25_link.c
+++ b/net/x25/x25_link.c
@@ -110,7 +110,7 @@ void x25_link_control(struct sk_buff *skb, struct x25_neigh *neigh, unsigned sho
break;
case X25_DIAGNOSTIC:
- printk(KERN_WARNING "x25: diagnostic #%d\n", skb->data[3]);
+ printk(KERN_WARNING "x25: diagnostic #%d - %02X %02X %02X\n", skb->data[3], skb->data[4], skb->data[5], skb->data[6]);
break;
default:
@@ -240,8 +240,10 @@ void x25_transmit_clear_request(struct x25_neigh *neigh, unsigned int lci, unsig
void x25_transmit_link(struct sk_buff *skb, struct x25_neigh *neigh)
{
- if (call_fw_firewall(PF_X25, skb->dev, skb->data, NULL,&skb) != FW_ACCEPT)
+ if (call_fw_firewall(PF_X25, skb->dev, skb->data, NULL, &skb) != FW_ACCEPT) {
+ kfree_skb(skb, FREE_WRITE);
return;
+ }
switch (neigh->state) {
case X25_LINK_STATE_0:
@@ -294,7 +296,7 @@ void x25_link_device_up(struct device *dev)
struct x25_neigh *x25_neigh;
unsigned long flags;
- if ((x25_neigh = (struct x25_neigh *)kmalloc(sizeof(*x25_neigh), GFP_ATOMIC)) == NULL)
+ if ((x25_neigh = kmalloc(sizeof(*x25_neigh), GFP_ATOMIC)) == NULL)
return;
skb_queue_head_init(&x25_neigh->queue);
@@ -329,7 +331,7 @@ static void x25_remove_neigh(struct x25_neigh *x25_neigh)
if ((s = x25_neigh_list) == x25_neigh) {
x25_neigh_list = x25_neigh->next;
restore_flags(flags);
- kfree_s(x25_neigh, sizeof(struct x25_neigh));
+ kfree(x25_neigh);
return;
}
@@ -337,7 +339,7 @@ static void x25_remove_neigh(struct x25_neigh *x25_neigh)
if (s->next == x25_neigh) {
s->next = x25_neigh->next;
restore_flags(flags);
- kfree_s(x25_neigh, sizeof(struct x25_neigh));
+ kfree(x25_neigh);
return;
}
@@ -420,46 +422,6 @@ int x25_subscr_ioctl(unsigned int cmd, void *arg)
return 0;
}
-int x25_link_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
-{
- struct x25_neigh *x25_neigh;
- int len = 0;
- off_t pos = 0;
- off_t begin = 0;
-
- cli();
-
- len += sprintf(buffer, "device st t20 ext\n");
-
- for (x25_neigh = x25_neigh_list; x25_neigh != NULL; x25_neigh = x25_neigh->next) {
- len += sprintf(buffer + len, "%-6s %2d %3d/%03d %d\n",
- x25_neigh->dev->name,
- x25_neigh->state,
- x25_neigh->t20timer / X25_SLOWHZ,
- x25_neigh->t20 / X25_SLOWHZ,
- x25_neigh->extended);
-
- pos = begin + len;
-
- if (pos < offset) {
- len = 0;
- begin = pos;
- }
-
- if (pos > offset + length)
- break;
- }
-
- sti();
-
- *start = buffer + (offset - begin);
- len -= (offset - begin);
-
- if (len > length) len = length;
-
- return len;
-}
-
#ifdef MODULE
/*
diff --git a/net/x25/x25_route.c b/net/x25/x25_route.c
index fc1bfc54b..820c11cd4 100644
--- a/net/x25/x25_route.c
+++ b/net/x25/x25_route.c
@@ -59,7 +59,7 @@ static int x25_add_route(x25_address *address, unsigned int sigdigits, struct de
if (memcmp(&x25_route->address, address, sigdigits) == 0 && x25_route->sigdigits == sigdigits)
return -EINVAL;
- if ((x25_route = (struct x25_route *)kmalloc(sizeof(*x25_route), GFP_ATOMIC)) == NULL)
+ if ((x25_route = kmalloc(sizeof(*x25_route), GFP_ATOMIC)) == NULL)
return -ENOMEM;
strcpy(x25_route->address.x25_addr, "000000000000000");
@@ -87,7 +87,7 @@ static void x25_remove_route(struct x25_route *x25_route)
if ((s = x25_route_list) == x25_route) {
x25_route_list = x25_route->next;
restore_flags(flags);
- kfree_s(x25_route, sizeof(struct x25_route));
+ kfree(x25_route);
return;
}
@@ -95,7 +95,7 @@ static void x25_remove_route(struct x25_route *x25_route)
if (s->next == x25_route) {
s->next = x25_route->next;
restore_flags(flags);
- kfree_s(x25_route, sizeof(struct x25_route));
+ kfree(x25_route);
return;
}
diff --git a/net/x25/x25_subr.c b/net/x25/x25_subr.c
index 245109ee9..75e58af98 100644
--- a/net/x25/x25_subr.c
+++ b/net/x25/x25_subr.c
@@ -281,106 +281,4 @@ int x25_decode(struct sock *sk, struct sk_buff *skb, int *ns, int *nr, int *q, i
return X25_ILLEGAL;
}
-/*
- * Parse a set of facilities into the facilities structure. Unrecognised
- * facilities are written to the debug log file.
- */
-int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities)
-{
- unsigned int len;
- unsigned char *p = skb->data;
-
- memset(facilities, 0x00, sizeof(struct x25_facilities));
-
- len = *p++;
-
- while (len > 0) {
- switch (*p & X25_FAC_CLASS_MASK) {
- case X25_FAC_CLASS_A:
- switch (*p) {
- case X25_FAC_REVERSE:
- facilities->reverse = (p[1] & 0x01);
- break;
- case X25_FAC_THROUGHPUT:
- facilities->throughput = p[1];
- break;
- default:
- printk(KERN_DEBUG "X.25: unknown facility %02X, value %02X\n", p[0], p[1]);
- break;
- }
- p += 2;
- len -= 2;
- break;
-
- case X25_FAC_CLASS_B:
- switch (*p) {
- case X25_FAC_PACKET_SIZE:
- facilities->pacsize_in = p[1];
- facilities->pacsize_out = p[2];
- break;
- case X25_FAC_WINDOW_SIZE:
- facilities->winsize_in = p[1];
- facilities->winsize_out = p[2];
- break;
- default:
- printk(KERN_DEBUG "X.25: unknown facility %02X, values %02X, %02X\n", p[0], p[1], p[2]);
- break;
- }
- p += 3;
- len -= 3;
- break;
-
- case X25_FAC_CLASS_C:
- printk(KERN_DEBUG "X.25: unknown facility %02X, values %02X, %02X, %02X\n", p[0], p[1], p[2], p[3]);
- p += 4;
- len -= 4;
- break;
-
- case X25_FAC_CLASS_D:
- printk(KERN_DEBUG "X.25: unknown facility %02X, length %d, values %02X, %02X, %02X, %02X\n", p[0], p[1], p[2], p[3], p[4], p[5]);
- p += p[1] + 2;
- len -= p[1] + 2;
- break;
- }
- }
-
- return p - skb->data;
-}
-
-/*
- * Create a set of facilities.
- */
-int x25_create_facilities(unsigned char *buffer, struct x25_facilities *facilities)
-{
- unsigned char *p = buffer + 1;
- int len;
-
- if (facilities->reverse != 0) {
- *p++ = X25_FAC_REVERSE;
- *p++ = (facilities->reverse) ? 0x01 : 0x00;
- }
-
- if (facilities->throughput != 0) {
- *p++ = X25_FAC_THROUGHPUT;
- *p++ = facilities->throughput;
- }
-
- if (facilities->pacsize_in != 0 || facilities->pacsize_out != 0) {
- *p++ = X25_FAC_PACKET_SIZE;
- *p++ = (facilities->pacsize_in == 0) ? facilities->pacsize_out : facilities->pacsize_in;
- *p++ = (facilities->pacsize_out == 0) ? facilities->pacsize_in : facilities->pacsize_out;
- }
-
- if (facilities->winsize_in != 0 || facilities->winsize_out != 0) {
- *p++ = X25_FAC_WINDOW_SIZE;
- *p++ = (facilities->winsize_in == 0) ? facilities->winsize_out : facilities->winsize_in;
- *p++ = (facilities->winsize_out == 0) ? facilities->winsize_in : facilities->winsize_out;
- }
-
- len = p - buffer;
- buffer[0] = len - 1;
-
- return len;
-}
-
#endif