patch-1.3.20 linux/net/ax25/af_ax25.c

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

diff -u --recursive --new-file v1.3.19/linux/net/ax25/af_ax25.c linux/net/ax25/af_ax25.c
@@ -63,12 +63,10 @@
  *						Added AX.25 frame segmentation.
  *
  *	To do:
- *		Support use as digipeater, including an on/off ioctl
  *		Restructure the ax25_rcv code to be cleaner/faster and
  *		copy only when needed.
  *		Consider better arbitary protocol support.
  *		Fix non-blocking connect failure.
- *		VC mode doesnt work on the PI card.
  *		Settable protocol id for SEQPACKET sockets
  */
  
@@ -87,6 +85,7 @@
 #include <net/ax25.h>
 #include <linux/inet.h>
 #include <linux/netdevice.h>
+#include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/segment.h>
@@ -97,6 +96,7 @@
 #include <linux/interrupt.h>
 #include <linux/notifier.h>
 #include <linux/proc_fs.h>
+#include <linux/stat.h>
 
 #include <net/ip.h>
 #include <net/arp.h>
@@ -213,8 +213,6 @@
 			}
 		}
 	}
-	
-	ax25_rt_device_down(dev);
 }
 
 /*
@@ -222,11 +220,21 @@
  */
 static int ax25_device_event(unsigned long event, void *ptr)
 {
-	if (event != NETDEV_DOWN)
-		return NOTIFY_DONE;
-		
-	ax25_kill_by_device(ptr);
-	
+	struct device *dev = (struct device *)ptr;
+
+	switch (event) {
+		case NETDEV_UP:
+			ax25_dev_device_up(dev);
+			break;
+		case NETDEV_DOWN:
+			ax25_kill_by_device(dev);
+			ax25_rt_device_down(dev);
+			ax25_dev_device_down(dev);
+			break;
+		default:
+			break;
+	}
+
 	return NOTIFY_DONE;
 }
 
@@ -514,16 +522,17 @@
 
 	init_timer(&ax25->timer);
 
-	ax25->rtt     = DEFAULT_T1;
-	ax25->t1      = DEFAULT_T1;
-	ax25->t2      = DEFAULT_T2;
-	ax25->n2      = DEFAULT_N2;
-	ax25->t3      = DEFAULT_T3;
+	ax25->rtt     = (AX25_DEF_T1 * PR_SLOWHZ) / 2;
+	ax25->t1      = AX25_DEF_T1 * PR_SLOWHZ;
+	ax25->t2      = AX25_DEF_T2 * PR_SLOWHZ;
+	ax25->t3      = AX25_DEF_T3 * PR_SLOWHZ;
+	ax25->n2      = AX25_DEF_N2;
 
-	ax25->modulus   = MODULUS;
+	ax25->modulus   = AX25_DEF_AXDEFMODE;
 	ax25->fragno    = 0;
 	ax25->fraglen   = 0;
-	ax25->backoff   = 1;
+	ax25->hdrincl   = 0;
+	ax25->backoff   = AX25_DEF_BACKOFF == 'E';
 	ax25->condition = 0x00;
 	ax25->t1timer   = 0;
 	ax25->t2timer   = 0;
@@ -534,7 +543,11 @@
 	ax25->vr      = 0;
 	ax25->vs      = 0;
 
-	ax25->window   = DEFAULT_WINDOW;
+	if (AX25_DEF_AXDEFMODE == EMODULUS) {
+		ax25->window = AX25_DEF_EWINDOW;
+	} else {
+		ax25->window = AX25_DEF_WINDOW;
+	}
 	ax25->device   = NULL;
 	ax25->digipeat = NULL;
 	ax25->sk       = NULL;
@@ -547,6 +560,31 @@
 	return ax25;
 }
 
+/*
+ *	Fill in a created AX.25 created control block with the default
+ *	values for a particular device.
+ */
+static void ax25_fillin_cb(ax25_cb *ax25, struct device *dev)
+{
+	ax25->device = dev;
+
+	ax25->rtt = ax25_dev_get_value(dev, AX25_VALUES_T1);
+	ax25->t1  = ax25_dev_get_value(dev, AX25_VALUES_T1);
+	ax25->t2  = ax25_dev_get_value(dev, AX25_VALUES_T2);
+	ax25->t3  = ax25_dev_get_value(dev, AX25_VALUES_T3);
+	ax25->n2  = ax25_dev_get_value(dev, AX25_VALUES_N2);
+
+	ax25->modulus = ax25_dev_get_value(dev, AX25_VALUES_AXDEFMODE);
+
+	if (ax25->modulus == MODULUS) {
+		ax25->window = ax25_dev_get_value(dev, AX25_VALUES_WINDOW);
+	} else {
+		ax25->window = ax25_dev_get_value(dev, AX25_VALUES_EWINDOW);
+	}
+
+	ax25->backoff = ax25_dev_get_value(dev, AX25_VALUES_BACKOFF) == 'E';
+}
+
 int ax25_send_frame(struct sk_buff *skb, ax25_address *src, ax25_address *dest,
 	ax25_digi *digi, struct device *dev)
 {
@@ -571,7 +609,7 @@
 	if ((ax25 = ax25_create_cb()) == NULL)
 		return 0;
 
-	ax25->device = dev;
+	ax25_fillin_cb(ax25, dev);
 
 	memcpy(&ax25->source_addr, src,  sizeof(ax25_address));
 	memcpy(&ax25->dest_addr,   dest, sizeof(ax25_address));
@@ -709,6 +747,10 @@
 			sk->ax25->modulus = opt ? EMODULUS : MODULUS;
 			return 0;
 
+		case AX25_HDRINCL:
+			sk->ax25->hdrincl = opt ? 1 : 0;
+			return 0;
+
 		default:
 			return -ENOPROTOOPT;
 	}
@@ -735,7 +777,7 @@
 			break;
 
 		case AX25_T1:
-			val = sk->ax25->t1 / PR_SLOWHZ;
+			val = (sk->ax25->t1 * 2) / PR_SLOWHZ;
 			break;
 
 		case AX25_T2:
@@ -756,7 +798,11 @@
 
 		case AX25_EXTSEQ:
 			val = (sk->ax25->modulus == EMODULUS);
-			return 0;
+			break;
+
+		case AX25_HDRINCL:
+			val = sk->ax25->hdrincl;
+			break;
 
 		default:
 			return -ENOPROTOOPT;
@@ -884,6 +930,8 @@
 		return NULL;
 	}
 
+	ax25_fillin_cb(ax25, dev);
+
 	sk->type   = osk->type;
 	sk->socket = osk->socket;
 
@@ -933,6 +981,7 @@
 
 	ax25->modulus = osk->ax25->modulus;
 	ax25->backoff = osk->ax25->backoff;
+	ax25->hdrincl = osk->ax25->hdrincl;
 	ax25->rtt     = osk->ax25->rtt;
 	ax25->t1      = osk->ax25->t1;
 	ax25->t2      = osk->ax25->t2;
@@ -940,7 +989,6 @@
 	ax25->n2      = osk->ax25->n2;
 
 	ax25->window  = osk->ax25->window;
-	ax25->device  = dev;
 
 	memcpy(&ax25->source_addr, &osk->ax25->source_addr, sizeof(ax25_address));
 	
@@ -1073,7 +1121,7 @@
 		return -EADDRNOTAVAIL;
 	}
 
-	sk->ax25->device = dev;
+	ax25_fillin_cb(sk->ax25, dev);
 	ax25_insert_socket(sk->ax25);
 
 	sk->zapped = 0;
@@ -1298,6 +1346,7 @@
 	/*
 	 *	Process the AX.25/LAPB frame.
 	 */
+	skb->h.raw = skb->data;
 
 	/*
 	 *	Parse the address header.
@@ -1310,7 +1359,7 @@
 	/*
 	 *	Send the frame to the AX.25 auto-router
 	 */
-	ax25_rt_rx_frame(&src, dev);
+	ax25_rt_rx_frame(&src, dev, &dp);
 	
 	/*
 	 *	Ours perhaps ?
@@ -1413,6 +1462,16 @@
 
 		return 0;
 	}
+
+	/*
+	 *	Is connected mode supported on this device ?
+	 *	If not, should we DM the incoming frame (except DMs) or
+	 *	silently ignore them. For now we stay quiet.
+	 */
+	if (!ax25_dev_get_value(dev, AX25_VALUES_CONMODE)) {
+		kfree_skb(skb, FREE_READ);
+		return 0;
+	}
 	
 	/* LAPB */
 	if ((ax25 = ax25_find_cb(&dest, &src, dev)) != NULL) {
@@ -1469,6 +1528,8 @@
 			kfree_skb(skb, FREE_READ);
 			return 0;
 		}
+
+		ax25_fillin_cb(ax25, dev);
 #else
 		if (mine)
 			ax25_return_dm(dev, &src, &dest, &dp);
@@ -1502,8 +1563,10 @@
 
 	if ((*skb->data & ~PF) == SABME) {
 		ax25->modulus = EMODULUS;
+		ax25->window  = ax25_dev_get_value(dev, AX25_VALUES_EWINDOW);
 	} else {
 		ax25->modulus = MODULUS;
+		ax25->window  = ax25_dev_get_value(dev, AX25_VALUES_WINDOW);
 	}
 
 	ax25->device = dev;
@@ -1733,10 +1796,9 @@
 	struct sock *sk = (struct sock *)sock->data;
 	struct sockaddr_ax25 *sax = (struct sockaddr_ax25 *)sip;
 	char *addrptr = (char *)sip;
-	int copied = 0;
+	int copied, length;
 	struct sk_buff *skb;
 	int er;
-	int bias = 0;
 
 	if (sk->err) {
 		er      = -sk->err;
@@ -1747,19 +1809,28 @@
 	if (addr_len != NULL)
 		*addr_len = sizeof(*sax);
 
-	/* This works for seqpacket too. The receiver has ordered the queue for us! We do one quick check first though */
-	if (sk->type == SOCK_SEQPACKET) {
-		if (sk->state != TCP_ESTABLISHED)
-			return -ENOTCONN;
-		bias = 1;
-	}
+	/*
+	 * 	This works for seqpacket too. The receiver has ordered the
+	 *	queue for us! We do one quick check first though
+	 */
+	if (sk->type == SOCK_SEQPACKET && sk->state != TCP_ESTABLISHED)
+		return -ENOTCONN;
 
 	/* Now we can treat all alike */
 	if ((skb = skb_recv_datagram(sk, flags, noblock, &er)) == NULL)
 		return er;
 
-	copied = (size < skb->len - bias) ? size : skb->len - bias;
-	skb_copy_datagram(skb, bias, ubuf, copied);
+	if (sk->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;
+	}
+
+	copied = (size < length) ? size : length;
+	skb_copy_datagram(skb, 0, ubuf, copied);
 	
 	if (sax) {
 		struct sockaddr_ax25 addr;
@@ -1887,6 +1958,16 @@
 			ax25_digi_on = amount ? 1 : 0;
 			return 0;
 
+		case SIOCAX25GETPARMS:
+		case SIOCAX25SETPARMS:
+			return ax25_dev_ioctl(cmd, (void *)arg);
+
+		case SIOCADDRT:
+		case SIOCDELRT:
+			if (!suser())
+				return -EPERM;
+			return ax25_rt_ioctl(cmd, (void *)arg);
+
 		case SIOCGIFADDR:
 		case SIOCSIFADDR:
 		case SIOCGIFDSTADDR:
@@ -1907,7 +1988,7 @@
 	return(0);
 }
 
-int ax25_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+static int ax25_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
 {
 	ax25_cb *ax25;
 	struct device *dev;
@@ -2050,7 +2131,7 @@
 		ax25_cs_get_info
 	});
 
-	printk("GW4PTS/G4KLX AX.25 for Linux. Version 0.30 ALPHA for Linux NET3.030 (Linux 1.3.0)\n");
+	printk("G4KLX/GW4PTS AX.25 for Linux. Version 0.30 ALPHA for Linux NET3.030 (Linux 1.3.20)\n");
 }
 
 /*
@@ -2158,8 +2239,7 @@
 
 	if (bp[16] == AX25_P_IP) {
 		mode = ax25_ip_mode_get((ax25_address *)(bp + 1), dev);
-
-		if (mode == 'V' || mode == 'v' || (mode == ' ' && sl_get_ax25_mode(dev))) {
+		if (mode == 'V' || mode == 'v' || (mode == ' ' && ax25_dev_get_value(dev, AX25_VALUES_IPDEFMODE) == 'V')) {
 			skb_device_unlock(skb);
 			skb_pull(skb, AX25_HEADER_LEN - 1);	/* Keep PID */
 			ax25_send_frame(skb, (ax25_address *)(bp + 8), (ax25_address *)(bp + 1), NULL, dev);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this