2001-12-28 21:01:50

by Henk de Groot

[permalink] [raw]
Subject: AX25/socket kernel PATCHes

Hello all,

I just downloaded the latest 2.4.17 kernel and I still do not see the
patches of Jeroen Vreeken, PE1RXQ, applied. Anybody know the reason why?

Without these patches the 2.4 kernel completely locks-up my machine as soon
as I start the FBB AX.25 BBS. Also other unrelated AX.25 tools do this,
although they can run for a while until this happens. With the patches
applied it is again rock solid as it was with earlier kernels.

I don't want credit for this, Jeroen Vreeken, PE1RXQ, found the problems
and designed these patches, but I would like to have this - or another fix
for the kernel lockup with AX.25 - in the stock kernel so everybody will
benefit. I just assembled the patches, made them work (they were somewhat
damaged) and adjusted them for the 2.4.17 kernel.

Kind regards,

Henk.

P.S. I'm not subscribed to linux-kernel, please forward if posting by
non-members is not permitted.

diff -ruN linux/net/ax25/af_ax25.c linux/net/ax25/af_ax25.c
--- linux/net/ax25/af_ax25.c Fri Dec 28 21:25:36 2001
+++ linux/net/ax25/af_ax25.c Fri Dec 28 21:26:35 2001
@@ -102,6 +102,7 @@
* Joerg(DL1BKE) Added support for SO_BINDTODEVICE
* Arnaldo C. Melo s/suser/capable(CAP_NET_ADMIN)/, some more cleanups
* Michal Ostrowski Module initialization cleanup.
+ * Jeroen(PE1RXQ) Use sock_orphan to set sk->dead.
*/

#include <linux/config.h>
@@ -423,7 +424,7 @@
if (ax25->sk != NULL) {
while ((skb = skb_dequeue(&ax25->sk->receive_queue)) != NULL) {
if (skb->sk != ax25->sk) { /* A pending connection */
- skb->sk->dead = 1; /* Queue the unaccepted socket for death */
+ sock_orphan(skb->sk); /* Queue the unaccepted socket for death */
ax25_start_heartbeat(skb->sk->protinfo.ax25);
skb->sk->protinfo.ax25->state = AX25_STATE_0;
}
@@ -1018,7 +1019,7 @@
sk->state = TCP_CLOSE;
sk->shutdown |= SEND_SHUTDOWN;
sk->state_change(sk);
- sk->dead = 1;
+ sock_orphan(sk);
sk->destroy = 1;
break;

@@ -1029,7 +1030,7 @@
sk->state = TCP_CLOSE;
sk->shutdown |= SEND_SHUTDOWN;
sk->state_change(sk);
- sk->dead = 1;
+ sock_orphan(sk);
ax25_destroy_socket(sk->protinfo.ax25);
}

diff -ruN linux/net/core/datagram.c linux/net/core/datagram.c
--- linux/net/core/datagram.c Fri Dec 28 21:25:36 2001
+++ linux/net/core/datagram.c Fri Dec 28 21:26:35 2001
@@ -442,7 +442,8 @@
if (sock_writeable(sk))
mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
else
- set_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags);
+ if(sk->socket)
+ set_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags);

return mask;
}
diff -ruN linux/net/ax25/ax25_ds_timer.c linux/net/ax25/ax25_ds_timer.c
--- linux/net/ax25/ax25_ds_timer.c Fri Dec 28 21:25:36 2001
+++ linux/net/ax25/ax25_ds_timer.c Fri Dec 28 21:26:35 2001
@@ -162,7 +162,7 @@
ax25->sk->shutdown |= SEND_SHUTDOWN;
if (!ax25->sk->dead)
ax25->sk->state_change(ax25->sk);
- ax25->sk->dead = 1;
+ sock_orphan(ax25->sk);
}
}

diff -ruN linux/net/ax25/ax25_std_timer.c linux/net/ax25/ax25_std_timer.c
--- linux/net/ax25/ax25_std_timer.c Fri Dec 28 21:25:36 2001
+++ linux/net/ax25/ax25_std_timer.c Fri Dec 28 21:26:35 2001
@@ -109,7 +109,7 @@
ax25->sk->shutdown |= SEND_SHUTDOWN;
if (!ax25->sk->dead)
ax25->sk->state_change(ax25->sk);
- ax25->sk->dead = 1;
+ sock_orphan(ax25->sk);
}
}

diff -ruN linux/net/ax25/ax25_subr.c linux/net/ax25/ax25_subr.c
--- linux/net/ax25/ax25_subr.c Fri Dec 28 21:25:36 2001
+++ linux/net/ax25/ax25_subr.c Fri Dec 28 21:26:35 2001
@@ -310,6 +310,6 @@
ax25->sk->shutdown |= SEND_SHUTDOWN;
if (!ax25->sk->dead)
ax25->sk->state_change(ax25->sk);
- ax25->sk->dead = 1;
+ sock_orphan(ax25->sk);
}
}
diff -ruN linux/net/netrom/af_netrom.c linux/net/netrom/af_netrom.c
--- linux/net/netrom/af_netrom.c Fri Dec 28 21:25:36 2001
+++ linux/net/netrom/af_netrom.c Fri Dec 28 21:26:35 2001
@@ -31,6 +31,7 @@
* NET/ROM 007 Jonathan(G4KLX) New timer architecture.
* Impmented Idle timer.
* Arnaldo C. Melo s/suser/capable/, micro cleanups
+ * Jeroen (PE1RXQ) Use sock_orphan to set sk->dead.
*/

#include <linux/config.h>
@@ -316,7 +317,7 @@

while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) {
if (skb->sk != sk) { /* A pending connection */
- skb->sk->dead = 1; /* Queue the unaccepted socket for death */
+ sock_orphan(skb->sk); /* Queue the unaccepted socket for death */
nr_start_heartbeat(skb->sk);
skb->sk->protinfo.nr->state = NR_STATE_0;
}
@@ -572,9 +573,8 @@
sk->state = TCP_CLOSE;
sk->shutdown |= SEND_SHUTDOWN;
sk->state_change(sk);
- sk->dead = 1;
+ sock_orphan(sk);
sk->destroy = 1;
- sk->socket = NULL;
break;

default:
diff -ruN linux/net/netrom/nr_subr.c linux/net/netrom/nr_subr.c
--- linux/net/netrom/nr_subr.c Fri Dec 28 21:25:36 2001
+++ linux/net/netrom/nr_subr.c Fri Dec 28 21:26:35 2001
@@ -284,5 +284,5 @@
if (!sk->dead)
sk->state_change(sk);

- sk->dead = 1;
+ sock_orphan(sk);
}
diff -ruN linux/net/netrom/nr_timer.c linux/net/netrom/nr_timer.c
--- linux/net/netrom/nr_timer.c Fri Dec 28 21:25:37 2001
+++ linux/net/netrom/nr_timer.c Fri Dec 28 21:26:35 2001
@@ -201,7 +201,7 @@
if (!sk->dead)
sk->state_change(sk);

- sk->dead = 1;
+ sock_orphan(sk);
}

static void nr_t1timer_expiry(unsigned long param)
diff -ruN linux/net/core/sock.c linux/net/core/sock.c
--- linux/net/core/sock.c Fri Dec 28 21:25:37 2001
+++ linux/net/core/sock.c Fri Dec 28 21:26:35 2001
@@ -81,6 +81,7 @@
* Andi Kleen : Fix write_space callback
* Chris Evans : Security fixes - signedness again
* Arnaldo C. Melo : cleanups, use skb_queue_purge
+ * Jeroen Vreeken : Add check for sk->dead in sock_def_write_space
*
* To Fix:
*
@@ -1146,7 +1147,7 @@
/* Do not wake up a writer until he can make "significant"
* progress. --DaveM
*/
- if((atomic_read(&sk->wmem_alloc) << 1) <= sk->sndbuf) {
+ if(!sk->dead && (atomic_read(&sk->wmem_alloc) << 1) <= sk->sndbuf) {
if (sk->sleep && waitqueue_active(sk->sleep))
wake_up_interruptible(sk->sleep);





2001-12-28 22:59:28

by Alan

[permalink] [raw]
Subject: Re: AX25/socket kernel PATCHes

> I just downloaded the latest 2.4.17 kernel and I still do not see the
> patches of Jeroen Vreeken, PE1RXQ, applied. Anybody know the reason why?

Because it changes core code in a way that shouldn't be needed

> * Arnaldo C. Melo : cleanups, use skb_queue_purge
> + * Jeroen Vreeken : Add check for sk->dead in sock_def_write_space
> *
> * To Fix:
> *
> @@ -1146,7 +1147,7 @@
> /* Do not wake up a writer until he can make "significant"
> * progress. --DaveM
> */
> - if((atomic_read(&sk->wmem_alloc) << 1) <= sk->sndbuf) {
> + if(!sk->dead && (atomic_read(&sk->wmem_alloc) << 1) <= sk->sndbuf) {
> if (sk->sleep && waitqueue_active(sk->sleep))
> wake_up_interruptible(sk->sleep);

Does the fix work without this change ?

2001-12-28 23:13:58

by Jeroen Vreeken

[permalink] [raw]
Subject: Re: AX25/socket kernel PATCHes

On 2001.12.29 00:09:43 +0100 Alan Cox wrote:
> > I just downloaded the latest 2.4.17 kernel and I still do not see the
> > patches of Jeroen Vreeken, PE1RXQ, applied. Anybody know the reason
> why?
>
> Because it changes core code in a way that shouldn't be needed
>
> > * Arnaldo C. Melo : cleanups, use
> skb_queue_purge
> > + * Jeroen Vreeken : Add check for
> sk->dead in sock_def_write_space
> > *
> > * To Fix:
> > *
> > @@ -1146,7 +1147,7 @@
> > /* Do not wake up a writer until he can make "significant"
> > * progress. --DaveM
> > */
> > - if((atomic_read(&sk->wmem_alloc) << 1) <= sk->sndbuf) {
> > + if(!sk->dead && (atomic_read(&sk->wmem_alloc) << 1) <=
> sk->sndbuf) {
> > if (sk->sleep && waitqueue_active(sk->sleep))
> > wake_up_interruptible(sk->sleep);
>
> Does the fix work without this change ?

The simple fix, no...

However I have started to make a patch for ax25 to use sock_orphan, but
recently we had some trouble with 2.4 kernels that might be related to my
changes or the scc driver, so I am now looking at fixing that, as soon as
that is sorted out I will submit a patch that fixes it the right way.

Jeroen


2001-12-29 17:41:18

by Henk de Groot

[permalink] [raw]
Subject: Re: AX25/socket kernel PATCHes

Hello Alan,

At 23:09 28-12-01 +0000, Alan Cox wrote:
>> wake_up_interruptible(sk->sleep);
>
>Does the fix work without this change ?

I haven't tried, but I saw the mail that Jeroen is working on something better so better wait for that. In the meantime I use this intermediate patch on my system because its better than feezing up the system - even if its not the correct way.

One other very long-term issue. When using programs that need raw AX.25 TX access like my program DIGI_NED and net2kiss the kernel outputs a warning "kernel: protocol 0000 is buggy, dev bcsf0" (when using BayCom in this case, other flavors are scc0, yam0 etc.). This messages originates from net/core/dev.c line 901 (2.4.17) and was introduced way back in the 2.1.x kernel (2.0.36 did not have this messages).

From a layman's view it looks like transmitted data is comming back or something like that. I tried to implement the access to the socket from the user point of view (application) the correct way; it looks like a driver problem. The appletalk driver used to have the same problem.

The message doesn't seem to matter but I frequently get messages about this since using the DIGI_NED digipeater provokes a lot of these messages. I attached the code segment I use to interface below (the complete code is available through http://www.qsl.net/digi_ned/).

My proposal is either to fix the drivers to set skb->nh correctly (no idea where and how this should be done, otherwise I would have supplied a patch) or to remove the message (at least for AX.25 use). There must be a reason why this printk is done so the first would be preferred. If there is something I could do at application level than that would be okay to, but I don't see how I could set skb->nh from the application.

Thanks for the excellent work!

Kind regards,

Henk.

Quick guide to the code below to find things:

The sockets are opened in: short init_mac(void)
Writing is done in: short mac_out(frame_t far *frame_p) using sendto
Probing for received data is done in: short mac_avl(void) using select
Reading data is done in: short mac_inp(frame_t far *frame_p)

I think the "buggy" messages are caused directly or indirectly following the sendto call. The way of reception is employed by more programs (listen e.g.) and does not cause problems, net2kiss however uses a similar transmission method and also provokes these "buggy" messages.

/*
* Copyright (C) 2000-2001 Henk de Groot - PE1DNN
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* Please note that the GPL allows you to use the driver, NOT the radio.
* In order to use the radio, you need a license from the communications
* authority of your country.
*/

#ifndef _LINUX_
#include <dos.h>
#endif /* _LINUX_ */
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef _LINUX_
#include <mem.h>
#endif /* _LINUX_ */
#include <string.h>
#ifdef _LINUX_
#include <unistd.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/types.h>
#include <net/if.h>
#include "linux.h"
#endif /* _LINUX_ */
#include "digicons.h"
#include "digitype.h"
#include "genlib.h"
#include "read_ini.h"
#include "mac_if.h"
#include "timer.h"
#include "output.h"
#ifdef _LINUX_
#include <sys/socket.h>
#include <linux/ax25.h>
#include <linux/rose.h>
#include <linux/if_ether.h>
#include <asm/byteorder.h>

#ifdef NEW_AX25
#include <netax25/axlib.h>
#include <netax25/axconfig.h>
#else
#include <ax25/axutils.h>
#include <ax25/axconfig.h>
#endif /* NEW_AX25 */
#endif /* _LINUX_ */

#define MAC_CHECK 1
#define MAC_INPUT 2
#define MAC_OUTPUT 3
#define MAC_PORTS 0x0fb
#define MAC_DEBUG 0x0fd

#ifndef _LINUX_
static unsigned char hdr_mac[] = "??AX25_MAC";
#endif /* _LINUX_ */

unsigned short mac_vector = 0;

#ifdef _LINUX_
typedef struct ports_s {
int s_out;
char *dev_p;
char *port_p;
} ports_t;
static ports_t lnx_port[MAX_PORTS];
static int lnx_port_nr = 0;
static int lnx_s_in;
#endif /* _LINUX_ */

/* AX25_MAC call to check if RX data is available */
short mac_avl(void)
{
#ifndef _LINUX_
union REGS inregs;
union REGS outregs;

if(mac_vector == 0)
return 0;

inregs.h.ah = MAC_CHECK;
int86(mac_vector, &inregs, &outregs);
if(outregs.x.ax == 1)
return 1;
return 0;
#else
struct timeval tv;
fd_set fds;
int retval;

/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&fds);
FD_SET(lnx_s_in, &fds);

/* wait only a short time (not 0, that gives a very high load!) */
tv.tv_sec = 0;
tv.tv_usec = 10;

retval = select(lnx_s_in + 1, &fds, NULL, NULL, &tv);

if (retval != 0)
{
/* data available */
return 1;
}

/* no data */
return 0;
#endif /* _LINUX_ */
}

/* AX25_MAC call to retrieve RX data */
short mac_inp(frame_t far *frame_p)
{
#ifndef _LINUX_
union REGS inregs;
union REGS outregs;
struct SREGS sregs;

if(mac_vector == 0)
return -1;

inregs.h.ah = MAC_INPUT;
sregs.es = FP_SEG(frame_p);
inregs.x.di = FP_OFF(frame_p);

int86x(mac_vector, &inregs, &outregs, &sregs);

return outregs.h.al;
#else
struct sockaddr from;
unsigned int from_len;
char data[MAX_FRAME_LENGTH + 1];
int data_length;
int i;
ports_t *prt_p;

from_len = sizeof(from);
data_length = recvfrom(lnx_s_in, data, MAX_FRAME_LENGTH + 1, 0,
&from, &from_len);

if(data_length < 0) {
if (errno == EWOULDBLOCK)
return -1;
say("Error returned from \"recvfrom\" in function mac_inp()\r\n");
exit(1);
}

if(data_length < 2)
return -1; /* short packet */

if(data[0] != 0)
return -1; /* not a data packet */

data_length--;

memcpy(frame_p->frame, &(data[1]), data_length);
frame_p->len = data_length;

/* find out from which port this came */
for(i = 0; i < lnx_port_nr; i++)
{
prt_p = &(lnx_port[i]);

if(strcmp(prt_p->dev_p, from.sa_data) == 0)
{
/* found it! */
frame_p->port = i;
return 0;
}
}

/* data on a port we don't use for DIGI_NED */
return -1;
#endif /* _LINUX_ */
}

/* AX25_MAC call to put TX data in the MAC layer */
short mac_out(frame_t far *frame_p)
{
#ifndef _LINUX_
union REGS inregs;
union REGS outregs;
struct SREGS sregs;

if(mac_vector == 0)
return 0;

inregs.h.ah = MAC_OUTPUT;
sregs.es = FP_SEG(frame_p);
inregs.x.di = FP_OFF(frame_p);

int86x(mac_vector, &inregs, &outregs, &sregs);

return outregs.h.al;
#else
struct sockaddr to;
char data[MAX_FRAME_LENGTH + 1];
int res;
ports_t *prt_p;

prt_p = &(lnx_port[(short) frame_p->port]);

bzero(&to,sizeof(struct sockaddr));
to.sa_family = AF_INET;
strcpy(to.sa_data, prt_p->dev_p);

data[0] = 0; /* this is data */
memcpy(&data[1], frame_p->frame, frame_p->len);

res = sendto(prt_p->s_out, data, frame_p->len + 1, 0, &to, sizeof(to));
if (res >= 0)
{
return 0;
}
if (errno == EMSGSIZE) {
vsay("Sendto: packet (size %d) too long\r\n", frame_p->len + 1);
return -1;
}
if (errno == EWOULDBLOCK) {
vsay("Sendto: busy\r\n", frame_p->len);
return -1;
}
perror("sendto");
return -1;
#endif /* _LINUX_ */
}

/* AX25_MAC call to retrieve the number of active ports */
short mac_ports(void)
{
#ifndef _LINUX_
union REGS inregs;
union REGS outregs;

if(mac_vector == 0)
return 0;

inregs.h.ah = MAC_PORTS;
int86(mac_vector, &inregs, &outregs);

return (short) outregs.h.al;
#else
return lnx_port_nr;
#endif /* _LINUX_ */
}

/*
* convert a raw AX.25 frame to a disassembled frame structure
*
* returns: 0 if frame could not be decoded
* 1 if frame could be decoded and has a supported PID
* -1 if frame could be decoded but has an unsupported PID
* -2 if frame could be decoded but has an illegal call
*/
static short frame2uidata(frame_t *frame_p, uidata_t *uidata_p)
{
unsigned char i,j;
unsigned short k;
unsigned short ndigi;
unsigned short ssid;
unsigned short len;
unsigned char *bp;
unsigned short pid;
unsigned short call_ok;
char *p;

/* assume all calls are okay */
call_ok = 1;

uidata_p->port = frame_p->port;
len = frame_p->len;
bp = &(frame_p->frame[0]);

if (!bp || !len)
{
vsay("Short packet (no data)\r\n");
return 0;
}

if (len < 15)
{
vsay("Short packet (< 15 bytes)\r\n");
return 0;
}

if (bp[1] & 1) /* Compressed FlexNet Header */
{
vsay("Compressed FlexNet header in packet, not supported\r\n");
return 0;
}

/* cleanup data size before beginning to decode */
uidata_p->size = 0;

/* Destination of frame */
j = 0;
for(i = 0; i < 6; i++)
{
if ((bp[i] &0xfe) != 0x40)
uidata_p->destination[j++] = bp[i] >> 1;
}
ssid = (bp[6] & SSID_MASK) >> 1;
if(ssid != 0)
{
uidata_p->destination[j++] = '-';
if((ssid / 10) != 0)
{
uidata_p->destination[j++] = '1';
}
ssid = (ssid % 10);
uidata_p->destination[j++] = ssid + '0';
}
uidata_p->dest_flags = bp[6] & FLAG_MASK;
uidata_p->destination[j] = '\0';
if(is_call(uidata_p->destination) == 0)
{
vsay("Invalid Destination call in received packet\r\n");
call_ok = 0;
}

bp += 7;
len -= 7;

/* Source of frame */
j = 0;
for(i = 0; i < 6; i++)
{
if ((bp[i] &0xfe) != 0x40)
uidata_p->originator[j++] = bp[i] >> 1;
}
ssid = (bp[6] & SSID_MASK) >> 1;
if(ssid != 0)
{
uidata_p->originator[j++] = '-';
if((ssid / 10) != 0)
{
uidata_p->originator[j++] = '1';
}
ssid = (ssid % 10);
uidata_p->originator[j++] = ssid + '0';
}
uidata_p->orig_flags = bp[6] & FLAG_MASK;
uidata_p->originator[j] = '\0';
if(is_call(uidata_p->originator) == 0)
{
vsay("Invalid Originator call in received packet\r\n");
call_ok = 0;
}

bp += 7;
len -= 7;

/* Digipeaters */
ndigi=0;
while ((!(bp[-1] & END_FLAG)) && (len >= 7))
{
/* Digi of frame */
if(ndigi != 8)
{
j = 0;
for(i = 0; i < 6; i++)
{
if ((bp[i] &0xfe) != 0x40)
uidata_p->digipeater[ndigi][j++] = bp[i] >> 1;
}
if(j == 0)
{
vsay("Short Digipeater call found (0 bytes length)\r\n");
call_ok = 0;
}
uidata_p->digi_flags[ndigi] = (bp[6] & FLAG_MASK);
ssid = (bp[6] & SSID_MASK) >> 1;
if(ssid != 0)
{
uidata_p->digipeater[ndigi][j++] = '-';
if((ssid / 10) != 0)
{
uidata_p->digipeater[ndigi][j++] = '1';
}
ssid = (ssid % 10);
uidata_p->digipeater[ndigi][j++] = ssid + '0';
}
uidata_p->digipeater[ndigi][j] = '\0';
if(is_call(uidata_p->digipeater[ndigi]) == 0)
{
vsay("Invalid Digipeater call in received packet\r\n");
call_ok = 0;
}
ndigi++;
}
bp += 7;
len -= 7;

}
uidata_p->ndigi = ndigi;

/* if at the end, short packet */
if(!len)
{
vsay("Short packet (no primitive found)\r\n");
return 0;
}

/* We are now at the primitive bit */
uidata_p->primitive = *bp;
bp++;
len--;
/* Flag with 0xffff that we don't have a PID */
uidata_p->pid = 0xffff;

/* if there were call decoding problems return now */
if(call_ok == 0)
{
return -2;
}

/*
* Determine if a packet is received LOCAL (i.e. direct) or
* REMOTE (i.e. via a digipeater)
*/
if(uidata_p->ndigi == 0)
{
/* no digipeaters at all, must be LOCAL then */
uidata_p->distance = LOCAL;
}
else
{
/* there are digi's, look if it was repeated at least once */
if((uidata_p->digi_flags[0] & H_FLAG) != 0)
{
/* this packet was digipeated and thus not received localy */
uidata_p->distance = REMOTE;
}
else
{
/*
* Here are the exceptions! With these exceptions no H_FLAG
* is set on the first digipeater although the packet was
* already digipeated one or more times.
*
* These are two types of digipeating use this:
*
* 1) Digipeating on destination-SSID. After the first hop
* the digipeater-call of the first digipeater is added
* without a H_FLAG. Subsequent digipeaters do not change
* this until the SSID reaches 0. When the SSID reaches 0
* the H_FLAG on the existing first digipeater call is set.
*
* Example flow, starting with destination SSID=3
* PE1DNN>APRS-3:>Digipeating... Direct packet
* PE1DNN>APRS-2,PE1DNN-2:>Digipeating... First hop
* PE1DNN>APRS-1,PE1DNN-2:>Digipeating... Second hop
* PE1DNN>APRS,PE1DNN-2*:>Digipeating... Third hop
*
* 2) Intelligent digipeater calls counting down or even
* finished counting down... The H_FLAG may be set when
* the call is completely "used", but this is not always
* the case.
*
* Example flow, starting with destination WIDE3-3
* PE1DNN>APRS,WIDE3-3:>Digipeating... Direct packet
* PE1DNN>APRS,WIDE3-2:>Digipeating... First hop
* PE1DNN>APRS,WIDE3-1:>Digipeating... Second hop
* PE1DNN>APRS,WIDE3*:>Digipeating... Third hop
* (if the packet in the third hop passed a Kantronics TNC
* with NOID set, then the TNC will not mark WIDE3 with a
* H_FLAG,i.e PE1DNN>APRS,WIDE3:>Digipeating...)
*/

/*
* Check if the packet is digipeating on SSID. This is the
* case when the destination SSID is not '0'. We only need
* to find the '-' on the destination call. With SSID = '0'
* the '-' is not present.
*/
p = strchr(uidata_p->destination, '-');
if(p != NULL)
{
/*
* Destination SSID is not '0', assume digipeating on
* destination SSID. I.e the packet was already repeated
* once because there is an unused digipeater call in the
* digipeater list. With digipeating on destination-SSID
* the starting packet should not have any digipeaters at
* all.
*/
uidata_p->distance = REMOTE;
}
else
{
/*
* Check if it is an "Intelligent" digi-call which is in
* progress counting down or is finished.
*/
p = strchr(uidata_p->digipeater[0], '-');
if(p == NULL)
{
/*
* No dash, the SSID of the first digipeater is '0'
*
* Check if the call ends with a digit 1 to 7 so it
* could have been an intelligent digipeater call which
* is finished but not marked as "used".
*/
/*
* Let 'p' point to the last character of the digipeater
* call (using index -1 is save, the length is > 0 which
* has been checked earlier in this function).
*/
p = uidata_p->digipeater[0];
p = &(p[strlen(p) - 1]);

/*
* The last digit of the call shall be between 1 and 7
* to qualify for an intelligent digipeater call
*/
if((*p > '0') && (*p < '8'))
{
/*
* Assume this is a call left behind by a Kantronics
* TNC which did not mark the final WIDEn call with
* a H_FLAG.
*
* Assume this packet has been repeated and is not
* local.
*/
uidata_p->distance = REMOTE;
}
else
{
/*
* not an 'Intelligent' digi call (does not end
* with a digit 1..7), must be local then
*/
uidata_p->distance = LOCAL;
}
}
else
{
/*
* Pointer 'p' is now setup as follows:
*
* p[-1] is the last character of the call
* p[0] is the dash
* p[1] is the SSID
* p[2] is '\0' if the SSID is < 10
*/

/*
* check if the SSID after the dash is a digit which
* can be used for intelligent digipeating (1-7).
* We already checked for 0, so SSID should be one digit
* in size ('\0' should follow) and less than 8
*/
if((p[2] == '\0') && (p[1] < '8'))
{
/*
* The last digit of the call shall be between 1 and 7
* too to qualify for an intelligent digipeater call
*/
if((p[-1] > '0') && (p[-1] < '8'))
{
/*
* if the last digit of the call is bigger than
* the SSID it may be a Intelligent call busy
* counting down.
*/
if(p[-1] > p[1])
{
/*
* Most likely an Intelligent digi-call
* busy counting down
* Assume this has been repeated and is not
* local.
*/
uidata_p->distance = REMOTE;
}
else
{
/*
* A not started intelligent digi call
* countdown or not an intelligent digi
* call at all. Must be local then.
*/
uidata_p->distance = LOCAL;
}
}
else
{
/*
* not an 'Intelligent' digi call (does not end
* with a digit 1..7), must be local then
*/
uidata_p->distance = LOCAL;
}
}
else
{
/*
* SSID > 7, cannot be used for 'intelligent
* digipeating'
*
* This must be a normal call which has not been
* used, the packet is local.
*/
uidata_p->distance = LOCAL;
}
}
}
}
}

/* No data left, ready */
if (!len)
{
/* this is not an UI frame, in kenwood_mode it should be ignored */
if(digi_kenwood_mode == 0)
{
return 1;
}
else
{
return -1;
}
}

/* keep the PID */
pid = ((short) *bp) & 0x00ff;
uidata_p->pid = pid;
bp++;
len--;

k = 0;
while (len)
{
i = *bp++;

if(k < 256) uidata_p->data[k++] = i;

len--;
}
uidata_p->size = k;

if(call_ok == 0)
{
return -2;
}

if(digi_kenwood_mode == 0)
{
/* check PID */
if( (pid != 0xf0) /* normal AX.25 */
&&
(pid != 0xcc) /* not IP datagram */
&&
(pid != 0xcd) /* not ARP */
&&
(pid != 0xcf) /* not NETROM */
)
{
/* only support for AX.25, IP, ARP and NETROM packets, bail out */
return -1;
}
}
else
{
/* only support for normal AX.25 UI frames, if not, bail out */
if(((uidata_p->primitive & ~0x10) != 0x03) || (uidata_p->pid != 0xf0))
{
/* not a normal AX.25 UI frame, bail out */
return -1;
}
}

return 1;
}

/*
* convert a disassembled frame structure to a raw AX.25 frame
*/
static void uidata2frame(uidata_t *uidata_p, frame_t *frame_p)
{
unsigned char i,j;
unsigned short k;
unsigned short ssid;
unsigned short len;
unsigned char *bp;

frame_p->port = uidata_p->port;

bp = &(frame_p->frame[0]);

len = 0; /* begin of frame */

/* Destination of frame */
j = 0;
for(i = 0; i < 6; i++)
{
/* if not end of string or at SSID mark */
if((uidata_p->destination[j] != '\0')
&&
(uidata_p->destination[j] != '-'))
{
bp[i] = (uidata_p->destination[j++] << 1);
}
else
{
bp[i] = 0x40;
}
}
if(uidata_p->destination[j] == '-')
{
/* "j" points to the SSID mark */
j++;

ssid = uidata_p->destination[j++] - '0';
if(uidata_p->destination[j] != '\0')
{
ssid = (10 * ssid) + (uidata_p->destination[j++] - '0');
}
}
else
{
ssid = 0;
}
bp[6] = (ssid << 1) | uidata_p->dest_flags;
bp += 7;
len += 7;

/* Source of frame */
j = 0;
for(i = 0; i < 6; i++)
{
/* if not end of string or at SSID mark */
if((uidata_p->originator[j] != '\0')
&&
(uidata_p->originator[j] != '-'))
{
bp[i] = (uidata_p->originator[j++] << 1);
}
else
{
bp[i] = 0x40;
}
}
if(uidata_p->originator[j] == '-')
{
/* "j" points to the SSID mark */
j++;

ssid = uidata_p->originator[j++] - '0';
if(uidata_p->originator[j] != '\0')
{
ssid = (10 * ssid) + (uidata_p->originator[j++] - '0');
}
}
else
{
ssid = 0;
}
bp[6] = (ssid << 1) | uidata_p->orig_flags;
bp += 7;
len += 7;

/* Digipeaters */
for(k = 0; k < uidata_p->ndigi; k++)
{
/* check if the distribution distance should be LOCAL */
if( uidata_p->distance == LOCAL )
{
/*
* to keep the frame local avoid that it is digipeated after
* we transmitted it, there shall not be any unused digipeater
* in the frame. break out of the loop if an unused digipeater
* is encountered
*
* an unused digipeater doesn't have its H_BIT set in the SSID
*/
if((uidata_p->digi_flags[k] & H_FLAG) == 0)
{
/* don't put "unused" digipeaters in the frame */
break; /* break out of the for loop */
}
}

j = 0;
for(i = 0; i < 6; i++)
{
/* if not end of string or at SSID mark */
if((uidata_p->digipeater[k][j] != '\0')
&&
(uidata_p->digipeater[k][j] != '-'))
{
bp[i] = (uidata_p->digipeater[k][j++] << 1);
}
else
{
bp[i] = 0x40;
}
}
if(uidata_p->digipeater[k][j] == '-')
{
/* "j" points to the SSID mark */
j++;

ssid = uidata_p->digipeater[k][j++] - '0';
if(uidata_p->digipeater[k][j] != '\0')
{
ssid = (10 * ssid) + (uidata_p->digipeater[k][j++] - '0');
}
}
else
{
ssid = 0;
}
bp[6] = (ssid << 1) | uidata_p->digi_flags[k];
bp += 7;
len += 7;
}

/* patch bit 1 on the last address */
bp[-1] = bp[-1] | END_FLAG;

/* We are now at the primitive bit */
*bp = uidata_p->primitive;
bp++;
len++;

/* if PID == 0xffff we don't have a PID */
if(uidata_p->pid == 0xffff)
{
frame_p->len = len;
return;
}

/* set the PID */
*bp = (char) uidata_p->pid;
bp++;
len++;

/* when size == 0 don't copy */
if(uidata_p->size == 0)
{
frame_p->len = len;
return;
}

memcpy(bp, &(uidata_p->data[0]), uidata_p->size);
len += uidata_p->size;

frame_p->len = len;

return;
}

/*
* Check the uidata packet for overrun of a Kenwood tranceiver
*
* Tested for the TH-D7E with version 2.0 prom. Hopefully do
* the other Kenwood tranceivers have the same limit (if any)
*
* Returns:
* 0 - do not transmit this packet
* 1 - okay to transmit this packet
*/
short uidata_kenwood_mode(uidata_t *uidata_p)
{
short budget;
short i;

if((digi_kenwood_mode != 1) && (digi_kenwood_mode != 2))
{
return 1; /* no special handling at all */
}

/*
* The packet is assumed to be internally formatted like this:
*
* SOURCE>ID,PATH,PATH*,PATH:Hey look at me, this is my long ID<CR>
* <--------------------- Max 195 characters --------------------->
*/

/* start budget is 195 bytes, this is including the <CR> */
budget = 195;

/* start to count down */
budget = budget - strlen(uidata_p->originator);

budget--; /* for the '>' sign */

budget = budget - strlen(uidata_p->destination);

if(uidata_p->ndigi > 0)
{
for(i = 0; i < uidata_p->ndigi; i++)
{
budget--; /* for the ',' separator */
budget = budget - strlen(uidata_p->digipeater[i]);
}

/*
* if the first digi indicates 'digipeated' then there must be
* a '*' somewhere...
*/
if((uidata_p->digi_flags[0] & H_FLAG) != 0)
{
budget--; /* for the '*' marking somewhere on one of the digis */
}
}

budget--; /* for the ':' header terminator */

/* see if we have any room left for the payload (we should) */
if(budget <= 0)
{
/* no data to transmit, header took all the space */
return 0;
}

/* look if the packet is too big */
if(uidata_p->size > budget)
{
if(digi_kenwood_mode == 2)
{
/* do not transmit too long packets*/
vsay("Kenwood mode: packet too long, not transmitted\r\n");
return 0;
}
else
{
/* truncate the packet to maximum allowable size */
uidata_p->size = budget;
vsay("Kenwood mode: packet too long, truncated to %d bytes\r\n",
budget);
}
}

/* okay to transmit */
return 1;
}

/*
* get disassembled AX.25 from MAC layer
*
* returns: 0 if no data is received
* 1 data received and put in the uidata_p structure
* 2 data received with unknown PID, data put in the uidata_p struct
* 3 corrupt data frame received, data in uidata_p not complete
* -1 on error (conversion check for debugging)
*/
short get_uidata(uidata_t *uidata_p)
{
frame_t frame;
#ifdef debug
frame_t check_frame;
#endif
short result;

while (mac_avl ())
{
if(mac_inp(&frame) == 0)
{
#ifdef debug
dump_raw(&frame);
#endif

result = frame2uidata(&frame, uidata_p);

/* Write to TNC log (if needed) */
tnc_log(uidata_p, REMOTE);

if(result == 1)
{
/* frame decoded correctly */
#ifdef debug
uidata2frame(uidata_p,&check_frame);
if(frame.port != check_frame.port)
{
vsay("Check: port error, org %d, check %d\r\n",
(short) frame.port + 1, (short) check_frame.port + 1);
dump_raw(&frame);
dump_raw(&check_frame);
dump_uidata_from(uidata_p);
if(frame2uidata(&check_frame, uidata_p) != 0)
{
dump_uidata_from(uidata_p);
}
return -1;
}
if(frame.len != check_frame.len)
{
vsay("Check: len error, org %d, check %d\r\n",
frame.len, check_frame.len);
dump_raw(&frame);
dump_raw(&check_frame);
dump_uidata_from(uidata_p);
if(frame2uidata(&check_frame, uidata_p) != 0)
{
dump_uidata_from(uidata_p);
}
return -1;
}
if(memcmp(&(frame.frame[0]), &(check_frame.frame[0]),
frame.len) != 0)
{
vsay("Check: data error\r\n");
dump_raw(&frame);
dump_raw(&check_frame);
dump_uidata_from(uidata_p);
if(frame2uidata(&check_frame, uidata_p) != 0)
{
dump_uidata_from(uidata_p);
}
return -1;
}
#endif
return 1;
}
else if(result == -1)
{
/* frame decoded but unknown PID */
dump_uidata_from(uidata_p);

if(digi_kenwood_mode == 0)
{
/* only support for AX.25, IP, ARP and NETROM packets */
vsay("Not an AX.25, IP, ARP or NETROM packet "
"(PID=%X), not handled\r\n", uidata_p->pid);
}
else
{
vsay("Kenwood mode: only normal AX.25 UI packets\r\n");
}

return 2;
}
else if(result == -2)
{
/* frame decoded but errors in call */
dump_uidata_from(uidata_p);

/* error in frame decoding */
return 3;
}
else
{
/* error in frame decoding */
return 3;
}
}
}
return 0;
}

/*
* send disassembled AX.25 frame to MAC layer
*
* returns: 0 if MAC layer cannot take the frame
* 1 if data is sucessfully put into the MAC layer
*/
short put_uidata(uidata_t *uidata_p)
{
frame_t frame;

/* Write to TNC log (if needed) */
tnc_log(uidata_p, uidata_p->distance);

/* convert to an AX.25 frame */
uidata2frame(uidata_p, &frame);

#ifdef debug
dump_raw(&frame);
#endif

/* transmit this frame */
if(mac_out(&frame) == 0)
return 1; /* success */

return 0; /* failure */
}

#ifdef _LINUX_
int add_lnx_port(char *port_p)
{
ports_t *prt_p;

if(lnx_port_nr < MAX_PORTS)
{
prt_p = &(lnx_port[lnx_port_nr]);

prt_p->port_p = port_p;

lnx_port_nr++;

/* succesfully added */
return 1;
}
else
{
/* Can't add more ports */
return 0;
}
}
#endif

/*
* Initialize access to MAC layer
*
* returns: 0 if MAC layer cannot be found
* 1 if MAC layer is found in memory
*/
short init_mac(void)
{
#ifndef _LINUX_
unsigned char vector, *p1;
unsigned char far * p2;
unsigned char far * handler;
frame_t frame;

for (vector = 0xFF; vector >= 0x40; vector--)
{
handler = (unsigned char far *) getvect (vector);

p1 = hdr_mac;

for (p2 = handler; *p1 == '?' || *p1 == *p2; p2++)
{
if (!*++p1)
{
mac_vector = ((short) vector) & 0x00ff;

while(mac_avl())
{
/* flush pending input */
(void) mac_inp(&frame);
}

return 1;
}
}
}

return 0;
#else
struct sockaddr sa;
ports_t *prt_p;
short i;

if(geteuid() != 0)
{
display_help_root();
exit(-1);
}

/* general startup, done once */
if (ax25_config_load_ports() == 0) {
say("ERROR: problem with axports file\r\n");
return 0;
}

/* convert axport to device and open transmitter sockets */
for(i = 0; i < lnx_port_nr; i++)
{
prt_p = &(lnx_port[i]);

if ((prt_p->dev_p = ax25_config_get_dev(prt_p->port_p)) == NULL)
{
say("ERROR: invalid port name - %s\r\n", prt_p->port_p);
return 0;
}

/* do transmitter side */
prt_p->s_out = socket(PF_INET, SOCK_PACKET, htons(ETH_P_AX25));
if (prt_p->s_out < 0)
{
perror("tx socket");
return 0;
}

bzero(&sa,sizeof(struct sockaddr));
strcpy(sa.sa_data, prt_p->dev_p);
sa.sa_family = AF_INET;
if (bind(prt_p->s_out, &sa, sizeof(struct sockaddr)) < 0)
{
perror("bind");
close(prt_p->s_out);
return 0;
}
}

/* open receive socket, one receiver will do for al ports */
/*
* Use ETH_P_AX25 because with PF_AX25 we also will read the data
* that we transmit ourselfs, that's useless!
*/
lnx_s_in = socket(PF_INET, SOCK_PACKET, htons(ETH_P_AX25));
if (lnx_s_in < 0)
{
perror("rx socket");
return 0;
}

return 1;
#endif /* _LINUX_ */
}

2001-12-29 17:41:18

by Henk de Groot

[permalink] [raw]
Subject: Re: AX25/socket kernel PATCHes

At 00:15 29-12-01 +0100, Jeroen Vreeken wrote:
>However I have started to make a patch for ax25 to use sock_orphan, but
>recently we had some trouble with 2.4 kernels that might be related to my
>changes or the scc driver, so I am now looking at fixing that, as soon as
>that is sorted out I will submit a patch that fixes it the right way.

Okay, I'll wait for that. In the meantime your patch works for me (with BayCom and YAM modem).

Kind regards,

Henk.

2001-12-29 17:52:38

by Alan

[permalink] [raw]
Subject: Re: AX25/socket kernel PATCHes

> The message doesn't seem to matter but I frequently get messages about this since using the DIGI_NED digipeater provokes a lot of these messages. I attached the code segment I use to interface below (the complete code is available through http://www.qsl.net/digi_ned/).
> My proposal is either to fix the drivers to set skb->nh correctly (no idea where and how this should be done, otherwise I would have supplied a patch) or to remove the message (at least for AX.25 use). There must be a reason why this printk is done so the first would be preferred. If there is something I could do at application level than that would be okay to, but I don't see how I could set skb->nh from the application.

On the receive path skb->nh.raw is set by the kernel core in 2.2 so that
should be ok providing skb->mac.raw is sane. It looks like the ax25 transmit
code isnt setting skb->nh.raw somewhere, or we have an off by one error
handling control messages (which looking at the code seems to be the case)

If you change

if (skb2->nh.raw < skb2->data || skb2->nh.raw >= skb2->...
if (net_ratelimit())

So that it checks
< skb2->data || nh.raw > ..

Let me know if that fixes it. It shouldn't but it would be good to know if
we are picking up header only frames somewhere, or nh.raw has accidentally
been pushed on one header too far.


2001-12-29 20:38:04

by Alexey Kuznetsov

[permalink] [raw]
Subject: Re: AX25/socket kernel PATCHes

Hello!

> So that it checks
> < skb2->data || nh.raw > ..
>
> Let me know if that fixes it. It shouldn't but it would be good to know if
> we are picking up header only frames somewhere, or nh.raw has accidentally
> been pushed on one header too far.

Indeed... This fix would be right in any case.


I want to remind why this check is made: this pointer must not show
to heavens and it must not be NULL. This property was not held in the past,
hence this bug trap was inserted. It can be relaxed, provided it preserves
its sanitizing function.

Also, note that real value of nh.raw is private to protocol.
Particularly, it can be equal to mac.raw. The best thing to do is
to set it to the same position as it would have if the same packet
appeared on input. But it is not an absolute requirement,
as soon as raw packet socket cannot hold it.

Alexey

2001-12-29 23:58:08

by Henk de Groot

[permalink] [raw]
Subject: Re: AX25/socket kernel PATCHes

Hello Alan,

At 18:02 29-12-01 +0000, Alan Cox wrote:
>If you change
>
> if (skb2->nh.raw < skb2->data || skb2->nh.raw >= skb2->...
> if (net_ratelimit())
>
>So that it checks
> < skb2->data || nh.raw > ..
>
>Let me know if that fixes it. It shouldn't but it would be good to know if

I thought I understood but I'm not so sure anymore. I applied the following patch to dev.c:

--------------------------------------------------------------------------
--- linux/net/core/dev.c.orig Sun Dec 30 00:31:43 2001
+++ linux/net/core/dev.c Sun Dec 30 00:33:27 2001
@@ -940,7 +940,7 @@
*/
skb2->mac.raw = skb2->data;

- if (skb2->nh.raw < skb2->data || skb2->nh.raw > skb2->tail) {
+ if (skb2->nh.raw < skb2->data || nh.raw > skb2->tail) {
if (net_ratelimit())
printk(KERN_DEBUG "protocol %04x is buggy, dev %s\n", skb2->protocol, dev->name);
skb2->nh.raw = skb2->data;
--------------------------------------------------------------------------

This however gives compilation errors, 'nh' undeclared. So no buggy messages anymore :-)...

It's easy for me to generate these buggy messages (each raw transmission seems to produce them) so if there is anything I can try out I'll be happy to do it.

Kind regards,

Henk.

P.S. I'm using a SuSE flavour of the kernel so I have to use the linux-2.4.16.tar.bz2 kernel with SuSE's suse-2.4.16-7.bz2 patches as there are no SuSE addaptations for the 2.4.17 kernel yet (at least last time I checked, i.e. yesterday).

2001-12-30 02:17:33

by Alan

[permalink] [raw]
Subject: Re: AX25/socket kernel PATCHes

> > if (skb2->nh.raw < skb2->data || skb2->nh.raw >= skb2->...

> + if (skb2->nh.raw < skb2->data || nh.raw > skb2->tail) {
Add: skb2->

my fault

2001-12-30 17:25:41

by Henk de Groot

[permalink] [raw]
Subject: Re: AX25/socket kernel PATCHes

Hello Allan,

At 02:27 30-12-01 +0000, Alan Cox wrote:
>> > if (skb2->nh.raw < skb2->data || skb2->nh.raw >= skb2->...
>
>> + if (skb2->nh.raw < skb2->data || nh.raw > skb2->tail) {
>Add: skb2->
>
>my fault

To clear this once and for all I applied a brute-force patch:

----------------------------------------------------------------------
--- linux/net/core/dev.c.orig Sun Dec 30 16:57:55 2001
+++ linux/net/core/dev.c Sun Dec 30 17:07:25 2001
@@ -940,9 +940,14 @@
*/
skb2->mac.raw = skb2->data;

- if (skb2->nh.raw < skb2->data || skb2->nh.raw > skb2->tail) {
+ if (skb2->nh.raw < skb2->data || skb2->nh.raw >= skb2->tail) {
if (net_ratelimit())
+ {
printk(KERN_DEBUG "protocol %04x is buggy, dev %s\n", skb2->protocol, dev->name);
+ printk(KERN_DEBUG "PE1DNN: skb2->nh.raw = 0x%08x\n", (unsigned long) skb2->nh.raw);
+ printk(KERN_DEBUG "PE1DNN: skb2->data = 0x%08x\n", (unsigned long) skb2->data);
+ printk(KERN_DEBUG "PE1DNN: skb2->tail = 0x%08x\n", (unsigned long) skb2->tail);
+ }
skb2->nh.raw = skb2->data;
}
----------------------------------------------------------------------

That should provide enough data about this part.. This is the output it creates, its not an off-by-one error...

----------------------------------------------------------------------
Dec 30 17:45:54 pe1dnn kernel: protocol 0000 is buggy, dev bcsf0
Dec 30 17:45:54 pe1dnn kernel: PE1DNN: skb2->nh.raw = 0xc4b0ed40
Dec 30 17:45:54 pe1dnn kernel: PE1DNN: skb2->data = 0xc4b0ece7
Dec 30 17:45:54 pe1dnn kernel: PE1DNN: skb2->tail = 0xc4b0ed11
----------------------------------------------------------------------

nh.raw is pointing way beyond the end of the data; 48 bytes if tail points at the adress just after the data - magic number or any clue why 48 bytes?

According to this the data should be 42 bytes (where data points to the first byte and tail just after the last byte). What is written to the AX.25 socket with 'sendto' is:

1 - KISS discriminator (0 - data) -> 1 byte
1 - AX.25 source address -> 7 bytes
1 - AX.25 destination address -> 7 bytes
2 - Digi paths @ 7bytes -> 14 bytes
1 - control fiels (primitve, UI frame) -> 1 byte
1 - PID (0xF0 normal AX.25 text) -> 1 byte
1 - payload data -> 11 bytes

Total 42 bytes, that seems to add up, only the nh.raw pointer seems to point to nowhere.

Kind regards,

Henk.

2001-12-30 22:16:05

by Henk de Groot

[permalink] [raw]
Subject: Re: AX25/socket kernel PATCHes

Hello Alexey,

At 22:24 30-12-01 +0300, [email protected] wrote:
> skb->data -= dev->hard_header_len;
> skb->tail -= dev->hard_header_len;
>+ if (len < dev->hard_header_len)
>+ skb->nh.raw = skb->data;
> }

I'll try that. I'm currently rebuilding the kernel, APM is working lousy on my Compaq 12LX302 laptop so I'm recompiling without APIC to see if that makes a change. Anyway, that takes a while, I'll report back on this.

>which is sad. Not that it is wrong (it is wrong by design and not repairable
[snip]
>So, leave this as it is and try to switch to packet socket from SOCK_PACKET.

I would be happy to do this if I knew how. I posted the code I use now and I have to say that I'm not familiar with this socket business at all. When I build it I copy-catted it from other programs (mainly net2kiss), did a tidy up on stuff that seemed to be redundant and tried to make is sensible to me.

I also tried to get some information from the Internet about raw access (for the APRS digipeater I need full control over the received and transmitted AX.25 packets) after I got the first buggy message reports from the 2.1.x kernel because I was first convinced I just did something wrong out of ignorance. The only way I found is using SOCK_PACKET. The only deviation with which I was not too happy was having to use protocol family "ETH_P_AX25" instead of "PF_AX25" but with the latter - which seems to be the correct one if I understood all of this correctly - the transmitted data is echoed back to the receive socket which is not desired at all.

But I'm always in for improvements so if there is another way I'll be happy to swap my code for something better. I guess I have to live with SOCK_PACKET for use on older (2.0.36) kernels?

So I require help for this. I guess when a good alternative is known this will also make it to the AX.25 utilities. I've never seen any other way to do it yet, please educate me.

Kind regards,

Henk.

P.S. Maybe the discussion should now be taken of the lists as this is drifting off-topic now, at least for the linux-kernel list which is already loaded enough as it is...

2001-12-30 22:27:15

by Sandor Dibuz

[permalink] [raw]
Subject: Re: AX25/socket kernel PATCHes

On Sun, 30 Dec 2001, Henk de Groot wrote:

> P.S. Maybe the discussion should now be taken of the lists as this is
drifting off-topic now, at least for the linux-kernel list which is
already loaded enough as it is...

But please do keep it on linux-hams. Someone is at least wishing to take
care of the ax25 kernel bugs for final. Thank you and have a prosperious
new year!


73... Sanyi

--
Dibuz Sandor | email: [email protected]
Pecs, Hungary | AX.25: [email protected] | UIN: 81545608


2002-01-01 23:13:19

by Henk de Groot

[permalink] [raw]
Subject: Re: AX25/socket kernel PATCHes

Hello Alexey,

At 23:13 30-12-01 +0100, Henk de Groot wrote:
>At 22:24 30-12-01 +0300, [email protected] wrote:
>>+ if (len < dev->hard_header_len)
>>+ skb->nh.raw = skb->data;
>
>I'll try that. I'm currently rebuilding the kernel, APM is working lousy on my Compaq 12LX302 laptop so I'm recompiling without APIC to see if that makes a change. Anyway, that takes a while, I'll report back on this.

Okay, APM is still a big mess for this Laptop, but I had a chance to try out the above patch. As expected this at least prevents hitting the "protocol is buggy" message in dev.c. If other people want to try, the file af_packet.c located in net/packet (and not in net/core).

I intent to try to dump this depricated socket use in the application, needs some experimentation and testing. So far so good.

Kind regards,

Henk.