All of lore.kernel.org
 help / color / mirror / Atom feed
From: thomas@habets.se
To: linux-hams@vger.kernel.org
Subject: Unable to receive UI frames with DGRAM socket
Date: Tue, 21 Sep 2021 11:56:08 -0700	[thread overview]
Message-ID: <CA+kHd+e=XQ6m7YgMGMmK5FjkX=bYVEQ7n57GaY8j0qHtwzZPpg@mail.gmail.com> (raw)

Hi.

I'm trying to send and receive UI frames with a DGRAM socket, but am
not having any success. I've resorted to using bpftrace to find where
the frames are dropped and the code looks very strange to me.

After bind() to an address, netstat -nap shows:

Active AX.25 sockets
Dest       Source     Device  State        Vr/Vs    Send-Q  Recv-Q
*          M6VMB-1    ax0     LISTENING    000/000  0       0

That seems fine, but note the unspecified destination. That's on
purpose, since I want to listen to any and all UI frames going to
M6VMB-1.

But it looks like UI frames will only work when both source and
destination are an exact match.

ax25_get_socket() checks both[1], and it's called from ax25_rcv[2].

And that's where the packet is dropped. With my bpftrace[3] I see this
(annotated. function name means kprobe, tilde-version means kretprobe):

Attaching 11 probes...
ax25_kiss_rcv()        # Packet received
ax25cmp                # Is it our port address?
~ax25cmp 0             # ... yes it is
ax25_send_to_raw(,0xffff9d2078d37e00, f0)
    Type (3 for UI): 3     # UI packet
    Proto: f0              # AX25_P_TEXT
ax25cmp                    # is this socket listening for this?
~ax25cmp 0                 # ... yes, but it's not a raw socket,
                           #     so never mind.
~ax25_send_to_raw
ax25_get_socket(l@,d`g,type=2)   # ok, time to find the right socket
ax25cmp              # does this dst address match local?
~ax25cmp 0           # .. yes it does!
ax25cmp              # does the src match... "*" from netstat?
~ax25cmp 1           # ... of course it doesn't, but why should it?
~ax25_get_socket = (nil)    # found no socket listening :-(
kfree_skb                   # throw packet on the floor
~ax25_kiss_rcv              # give up


Is this a bug? Is it even possible to receive UI frames without a raw
socket?

As a workaround, is it possible to set the destination address for
bind()ing? That'd make it point-to-point UI, so still not great.

By the way, I also found it odd that socket addresses are compared
before socket type. Surely it must be slightly more efficient to check
socket type (SOCK_RAW or DGRAM) first, and only do the address
comparisons after?

The packet looks fine on the receive side in axlisten:

radio6: fm 2E0VMB-3 to M6VMB-1 ctl UI^ pid=F0(Text) len 5 19:43:32.787076
0000  hello

[1] https://elixir.bootlin.com/linux/latest/source/net/ax25/af_ax25.c#L179
[2] https://elixir.bootlin.com/linux/latest/source/net/ax25/ax25_in.c#L260
[3] #!/bin/bpftrace

#include <linux/skbuff.h>
#include <uapi/linux/ax25.h>

kprobe:ax25_kiss_rcv {@t[tid]=1; printf("ax25_kiss_rcv()\n");}
kretprobe:ax25_kiss_rcv {delete(@t[tid]); printf("~ax25_kiss_rcv\n");}


kprobe:ax25_send_to_raw /@t[tid]==1/ {
  $skb = (struct sk_buff*)arg1;
  printf("ax25_send_to_raw(,%p, %x)\n", $skb, arg2);
  printf("    Type (3 for UI): %x\n", *$skb->data);
  printf("    Proto: %x\n", arg2);
}
kretprobe:ax25_send_to_raw /@t[tid]==1/ {
  printf("~ax25_send_to_raw\n");
}

kprobe:netif_rx /@t[tid]==1/ {  printf("netif_rx\n");}

kprobe:ax25cmp /@t[tid]==1/ {  printf("ax25cmp\n");}
kretprobe:ax25cmp /@t[tid]==1/ {
  printf("~ax25cmp %d\n", retval);
}


kprobe:ax25_get_socket /@t[tid]==1/ {
  $a = (ax25_address*)arg0;
  $b = (ax25_address*)arg1;
  printf("ax25_get_socket(%s,%s,type=%x)\n",
        $a->ax25_call,
        $b->ax25_call,
        arg2);
  @oride[tid] = 1;
}
kretprobe:ax25_get_socket /@t[tid]==1/ {
  printf("~ax25_get_socket = %p\n", retval);
  delete(@oride[tid]);
}

kretprobe:ax25_listen_mine /@t[tid]==1/ {  printf("~ax25_listen_mine
%d\n", retval);}

kprobe:kfree_skb /@t[tid]==1/ {  printf("kfree_skb\n");}


--
typedef struct me_s {
  char name[]      = { "Thomas Habets" };
  char email[]     = { "thomas@habets.se" };
  char kernel[]    = { "Linux" };
  char *pgpKey[]   = { "http://www.habets.pp.se/pubkey.txt" };
  char pgp[] = { "9907 8698 8A24 F52F 1C2E  87F6 39A4 9EEA 460A 0169" };
  char coolcmd[]   = { "echo '. ./_&. ./_'>_;. ./_" };
} me_t;

             reply	other threads:[~2021-09-21 18:56 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-21 18:56 thomas [this message]
2021-09-22 15:36 ` Unable to receive UI frames with DGRAM socket David Ranch
     [not found] ` <e235ee10-5774-f690-0c5e-5dc575482936@trinnet.net>
2021-09-22 21:11   ` thomas
2021-09-24 17:29     ` thomas
2021-09-24 18:18       ` David Ranch
2021-09-25 11:27         ` thomas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CA+kHd+e=XQ6m7YgMGMmK5FjkX=bYVEQ7n57GaY8j0qHtwzZPpg@mail.gmail.com' \
    --to=thomas@habets.se \
    --cc=linux-hams@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.