patch-2.0.12 linux/net/ax25/ax25_in.c

Next file: linux/net/ax25/ax25_out.c
Previous file: linux/net/ax25/af_ax25.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.0.11/linux/net/ax25/ax25_in.c linux/net/ax25/ax25_in.c
@@ -1,5 +1,5 @@
 /*
- *	AX.25 release 031
+ *	AX.25 release 032
  *
  *	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. 
@@ -32,6 +32,8 @@
  *			Joerg(DL1BKE)   Renamed it to "IDLE" with a slightly
  *					different behaviour. Fixed defrag
  *					routine (I hope)
+ *	AX.25 032	Jonathan(G4KLX)	Remove auto-router.
+ *			Darryl(G7LED)	AX.25 segmentation fixed.
  */
 
 #include <linux/config.h>
@@ -70,66 +72,57 @@
 static int ax25_rx_fragment(ax25_cb *ax25, struct sk_buff *skb)
 {
 	struct sk_buff *skbn, *skbo;
-	int hdrlen;
+	int hdrlen, nhdrlen;
 	
 	if (ax25->fragno != 0) {
 		if (!(*skb->data & SEG_FIRST)) {
 			if ((ax25->fragno - 1) == (*skb->data & SEG_REM)) {
-			
-				/* enqueue fragment */
-				
+				/* Enqueue fragment */
 				ax25->fragno = *skb->data & SEG_REM;
 				skb_pull(skb, 1);	/* skip fragno */
 				ax25->fraglen += skb->len;
 				skb_queue_tail(&ax25->frag_queue, skb);
-				
-				/* last fragment received? */
 
+				/* Last fragment received ? */
 				if (ax25->fragno == 0) {
-					if ((skbn = alloc_skb(AX25_MAX_HEADER_LEN + ax25->fraglen, GFP_ATOMIC)) == NULL)
-						return 0;
+					if ((skbn = alloc_skb(AX25_MAX_HEADER_LEN + ax25->fraglen, GFP_ATOMIC)) == NULL) {
+						while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL)
+							kfree_skb(skbo, FREE_READ);
+						return 1;
+					}
 
 					skbn->free = 1;
 					skbn->arp  = 1;
-					skbn->dev  = skb->dev;
+					skbn->dev  = ax25->device;
 
 					if (ax25->sk != NULL) {
 						skbn->sk = ax25->sk;
 						atomic_add(skbn->truesize, &ax25->sk->rmem_alloc);
 					}
 
-					/* get first fragment from queue */
-					
-					skbo = skb_dequeue(&ax25->frag_queue);
-					hdrlen = skbo->data - skbo->h.raw - 2;	/* skip PID & fragno */
-					
-					skb_push(skbo, hdrlen + 2);		/* start of address field */
-					skbn->data = skb_put(skbn, hdrlen);	/* get space for info */
-					memcpy(skbn->data, skbo->data, hdrlen);	/* copy address field */
-					skb_pull(skbo, hdrlen + 2);		/* start of data */
-					skb_pull(skbn, hdrlen + 1);		/* ditto */
+					skb_reserve(skbn, AX25_MAX_HEADER_LEN);
 
-					/* copy data from first fragment */
+					/* Get first fragment from queue */
+					skbo = skb_dequeue(&ax25->frag_queue);
+					hdrlen  = skbo->data - skbo->h.raw;
+					nhdrlen = hdrlen - 2;
 
-					memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len);
-					kfree_skb(skbo, FREE_READ);
-					
-					/* add other fragment's data */
+					skb_push(skbo, hdrlen);
+					skb_push(skbn, nhdrlen);
+					skbn->h.raw = skbn->data;
+
+					/* Copy AX.25 headers */
+					memcpy(skbn->data, skbo->data, nhdrlen);
+					skb_pull(skbn, nhdrlen);
+					skb_pull(skbo, hdrlen);
 
-					while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL) {
+					/* Copy data from the fragments */
+					do {
 						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;		/* reset counter */
-					
-					/* 
-					 * mysteriously we need to re-adjust skb->data.
-					 * Anyway, it seems to work. Do we have the address fields
-					 * encoded TWICE in one sk_buff?
-					 */
-					
-					skb_pull(skbn, hdrlen);
+					ax25->fraglen = 0;
 
 					if (ax25_rx_iframe(ax25, skbn) == 0)
 						kfree_skb(skbn, FREE_READ);
@@ -139,9 +132,10 @@
 			}
 		}
 	} else {
-		/* first fragment received? */
-
+		/* First fragment received */
 		if (*skb->data & SEG_FIRST) {
+			while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL)
+				kfree_skb(skbo, FREE_READ);
 			ax25->fragno = *skb->data & SEG_REM;
 			skb_pull(skb, 1);		/* skip fragno */
 			ax25->fraglen = skb->len;
@@ -181,7 +175,6 @@
 		case AX25_P_IP:
 			skb_pull(skb, 1);	/* Remove PID */
 			skb->h.raw = skb->data;
-			ax25_ip_mode_set(&ax25->dest_addr, ax25->device, 'V');
 			ip_rcv(skb, ax25->device, NULL);	/* Wrong ptype */
 			queued = 1;
 			break;
@@ -273,7 +266,7 @@
 			break;
 
 		default:
-			if (dama && pf)	/* dl1bke 960116 */
+			if (dama && pf)
 				ax25_send_control(ax25, SABM, POLLON, C_COMMAND);
 			break;
 	}
@@ -490,7 +483,7 @@
 			}
 			if (ax25->condition & OWN_RX_BUSY_CONDITION) {
 				if (pf)	{
-					if (ax25->dama_slave)	/* dl1bke 960114 */
+					if (ax25->dama_slave)
 						dama_enquiry_response(ax25);
 					else
 						ax25_enquiry_response(ax25);
@@ -498,20 +491,21 @@
 				break;
 			}
 			if (ns == ax25->vr) {
+				ax25->vr = (ax25->vr + 1) % ax25->modulus;
 				queued = ax25_rx_iframe(ax25, skb);
 				if (ax25->condition & OWN_RX_BUSY_CONDITION) {
+					ax25->vr = ns;	/* ax25->vr - 1 */
 					if (pf) {
-						if (ax25->dama_slave)	/* dl1bke 960114 */
+						if (ax25->dama_slave)
 							dama_enquiry_response(ax25);
 						else
 							ax25_enquiry_response(ax25);
 					}
 					break;
 				}
-				ax25->vr = (ax25->vr + 1) % ax25->modulus;
 				ax25->condition &= ~REJECT_CONDITION;
 				if (pf) {
-					if (ax25->dama_slave)	/* dl1bke 960114 */
+					if (ax25->dama_slave)
 						dama_enquiry_response(ax25);
 					else
 						ax25_enquiry_response(ax25);
@@ -524,14 +518,14 @@
 			} else {
 				if (ax25->condition & REJECT_CONDITION) {
 					if (pf) {
-						if (ax25->dama_slave)	/* dl1bke 960114 */
+						if (ax25->dama_slave)
 							dama_enquiry_response(ax25);
 						else
 							ax25_enquiry_response(ax25);
 					}
 				} else {
 					ax25->condition |= REJECT_CONDITION;
-					if (ax25->dama_slave)		/* dl1bke 960114 */
+					if (ax25->dama_slave)
 						dama_enquiry_response(ax25);
 					else
 						ax25_send_control(ax25, REJ, pf, C_RESPONSE);
@@ -660,7 +654,7 @@
 			
 		case RR:
 			ax25->condition &= ~PEER_RX_BUSY_CONDITION;
-			if ( pf && (type == C_RESPONSE || (ax25->dama_slave && type == C_COMMAND)) ) {
+			if (pf && (type == C_RESPONSE || (ax25->dama_slave && type == C_COMMAND))) {
 				ax25->t1timer = 0;
 				if (ax25_validate_nr(ax25, nr)) {
 					ax25_frames_acked(ax25, nr);
@@ -691,7 +685,7 @@
 
 		case REJ:
 			ax25->condition &= ~PEER_RX_BUSY_CONDITION;
-			if ( pf && (type == C_RESPONSE || (ax25->dama_slave && type == C_COMMAND)) ) {
+			if (pf && (type == C_RESPONSE || (ax25->dama_slave && type == C_COMMAND))) {
 				ax25->t1timer = 0;
 				if (ax25_validate_nr(ax25, nr)) {
 					ax25_frames_acked(ax25, nr);
@@ -735,7 +729,7 @@
 			}
 			ax25_frames_acked(ax25, nr);
 			if (ax25->condition & OWN_RX_BUSY_CONDITION) {
-				if (pf) {	/* dl1bke 960114 */
+				if (pf) {
 					if (ax25->dama_slave)
 						ax25_enquiry_response(ax25);
 					else
@@ -744,9 +738,11 @@
 				break;
 			}
 			if (ns == ax25->vr) {
+				ax25->vr = (ax25->vr + 1) % ax25->modulus;
 				queued = ax25_rx_iframe(ax25, skb);
 				if (ax25->condition & OWN_RX_BUSY_CONDITION) {
-					if (pf) {	/* dl1bke 960114 */
+					ax25->vr = ns;	/* ax25->vr - 1 */
+					if (pf) {
 						if (ax25->dama_slave)
 							dama_enquiry_response(ax25);
 						else
@@ -754,10 +750,9 @@
 					}
 					break;
 				}
-				ax25->vr = (ax25->vr + 1) % ax25->modulus;
 				ax25->condition &= ~REJECT_CONDITION;
 				if (pf) {
-					if (ax25->dama_slave) 	/* dl1bke 960114 */
+					if (ax25->dama_slave)
 						dama_enquiry_response(ax25);
 					else
 						ax25_enquiry_response(ax25);
@@ -769,7 +764,7 @@
 				}
 			} else {
 				if (ax25->condition & REJECT_CONDITION) {
-					if (pf) { 	/* dl1bke 960114 */
+					if (pf) {
 						if (ax25->dama_slave)
 							dama_enquiry_response(ax25);
 						else
@@ -777,7 +772,7 @@
 					}
 				} else {
 					ax25->condition |= REJECT_CONDITION;
-					if (ax25->dama_slave)		/* dl1bke 960114 */
+					if (ax25->dama_slave)
 						dama_enquiry_response(ax25);
 					else
 						ax25_send_control(ax25, REJ, pf, C_RESPONSE);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov