The LLC header:
struct snap_llc_header
{
u_int8_t dsap;
u_int8_t ssap;
u_int8_t ctl;
u_int16_t org;
u_int8_t org2;
u_int16_t ether_type; /* ethernet type */
};
is wrong. C compilers will, by default, attempt to properly align integral and floating-point values longer than 1 byte on the appropriate boundary; this means that the u_int16_t
values will be aligned on 2-byte boundaries, with added padding.
Therefore, the structure will actually look like:
struct snap_llc_header
{
u_int8_t dsap;
u_int8_t ssap;
u_int8_t ctl;
u_int8_t pad1;
u_int16_t org;
u_int8_t org2;
u_int8_t pad2;
u_int16_t ether_type; /* ethernet type */
};
and it will be 2 bytes longer than an actual 802.2 LLC+SNAP header.
The quick-and-dirty fix, which will work only with GCC and GCC-compatible compilers, is to mark the structure as "packed", so that the values won't be aligned:
struct snap_llc_header
{
u_int8_t dsap;
u_int8_t ssap;
u_int8_t ctl;
u_int8_t pad1;
u_int16_t org;
u_int8_t org2;
u_int8_t pad2;
u_int16_t ether_type; /* ethernet type */
} __attribute__((packed));
If you want to make this work on compilers that don't support the GCC __attribute__((packed))
extension, you'll have to do more work.
(Note also that your code is assuming that it's running on a little-endian machine - if you're running it on a personal computer, it probably is, but if you're running it on a non-x86 and non-ARM server, it probably isn't. It's also assuming that it can safely refer to unaligned data - if you're running it on something other than a SPARC machine, it probably can, but if you're running it on a SPARC machine, it can't. Fixing that involves still more work.)
(Another potential issue is that if the 802.11 frames were captured from an Atheros network device, there might be some padding between the 802.11 header and the payload; see the "frame has padding between 802.11 header and payload (to 32-bit boundary)" flag in the radiotap flags field. That, unfortunately, will require you to parse the radiotap header.)
(And if you want to handle packets other than data frames with a SNAP header, you will need to check the DSAP and SSAP and, if they're not both 0xAA, process them without the 3-byte OUI and 2-byte protocol ID of the SNAP header. If they are both 0xAA, note that the 2-byte protocol ID is an Ethernet type only if all three bytes of the OUI are zero.)