diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-06-03 09:23:20 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1997-06-03 09:23:20 +0000 |
commit | ac5ff8f4a72f7b4e66f73c3c6cb9fe7758cf6f12 (patch) | |
tree | 9fc7f8ce32e0d9a4aa055b2a58a05a5d727b333c /net | |
parent | 52662ff3e66770fd7e4fc508c91056d29c08bff0 (diff) |
Sync with Linux 2.1.42.
Diffstat (limited to 'net')
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 |