dect
/
libpcap
Archived
13
0
Fork 0

The AVS radio header is variable-length, and fields were added to it

recently, so it's not only variable-length in theory, it's
variable-length in practice.  Treat it as such.
This commit is contained in:
guy 2007-12-29 02:34:23 +00:00
parent 41995a4191
commit 85f4786ac2
1 changed files with 77 additions and 14 deletions

View File

@ -21,7 +21,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.303 2007-11-26 21:17:49 gianluca Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.304 2007-12-29 02:34:23 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -203,6 +203,7 @@ static struct block *gen_ether_linktype(int);
static struct block *gen_linux_sll_linktype(int);
static struct slist *gen_load_radiotap_llprefixlen(void);
static struct slist *gen_load_ppi_llprefixlen(void);
static struct slist *gen_load_avs_llprefixlen(void);
static void insert_compute_vloffsets(struct block *);
static struct slist *gen_llprefixlen(void);
static struct slist *gen_off_macpl(void);
@ -1075,16 +1076,10 @@ init_linktype(p)
* the 802.11 header, containing a bunch of additional
* information including radio-level information.
*
* The header is 64 bytes long, at least in its
* current incarnation.
*
* XXX - same variable-length header problem, only
* more so; this header is also variable-length,
* with the length being the 32-bit big-endian
* number at an offset of 4 from the beginning
* of the radio header. We should handle that the
* same way we handle the length at the beginning
* of the radiotap header.
* The radiotap header is variable length, and we
* generate code to compute its length and store it
* in a register. These offsets are relative to the
* beginning of the 802.11 header.
*
* XXX - in Linux, do any drivers that supply an AVS
* header supply a link-layer type other than
@ -1095,7 +1090,6 @@ init_linktype(p)
* have to check the header in the generated code to
* determine whether it's Prism or AVS.
*/
off_ll = 64;
off_linktype = 24;
off_macpl = 0; /* link-layer header is variable-length */
off_macpl_is_variable = 1;
@ -2262,6 +2256,46 @@ gen_load_ppi_llprefixlen()
return (NULL);
}
static struct slist *
gen_load_avs_llprefixlen()
{
struct slist *s1, *s2;
/*
* Generate code to load the length of the AVS header into
* the register assigned to hold that length, if one has been
* assigned. (If one hasn't been assigned, no code we've
* generated uses that prefix, so we don't need to generate any
* code to load it.)
*/
if (reg_off_ll != -1) {
/*
* The 4 bytes at an offset of 4 from the beginning of
* the AVS header are the length of the AVS header.
* That field is big-endian.
*/
s1 = new_stmt(BPF_LD|BPF_W|BPF_ABS);
s1->s.k = 4;
/*
* Now allocate a register to hold that value and store
* it.
*/
s2 = new_stmt(BPF_ST);
s2->s.k = reg_off_ll;
sappend(s1, s2);
/*
* Now move it into the X register.
*/
s2 = new_stmt(BPF_MISC|BPF_TAX);
sappend(s1, s2);
return (s1);
} else
return (NULL);
}
/*
* Load a value relative to the beginning of the link-layer header after the 802.11
* header, i.e. LLC_SNAP.
@ -2505,6 +2539,10 @@ insert_compute_vloffsets(b)
s = gen_load_ppi_llprefixlen();
break;
case DLT_IEEE802_11_RADIO_AVS:
s = gen_load_avs_llprefixlen();
break;
default:
s = NULL;
break;
@ -2608,7 +2646,29 @@ gen_ppi_llprefixlen(void)
}
/*
* Load the register containing the radiotap length
* Load the register containing the PPI length
* into the X register.
*/
s = new_stmt(BPF_LDX|BPF_MEM);
s->s.k = reg_off_ll;
return s;
}
static struct slist *
gen_avs_llprefixlen(void)
{
struct slist *s;
if (reg_off_ll == -1) {
/*
* We haven't yet assigned a register for the length
* of the radiotap header; allocate one.
*/
reg_off_ll = alloc_reg();
}
/*
* Load the register containing the AVS length
* into the X register.
*/
s = new_stmt(BPF_LDX|BPF_MEM);
@ -2629,10 +2689,13 @@ gen_llprefixlen(void)
case DLT_PPI:
return gen_ppi_llprefixlen();
case DLT_IEEE802_11_RADIO:
return gen_radiotap_llprefixlen();
case DLT_IEEE802_11_RADIO_AVS:
return gen_avs_llprefixlen();
default:
return NULL;
}