At least some versions of GCC will, on SPARC, generate code for
if (bp->bp_htype == 1 && bp->bp_hlen == 6 && bp->bp_op == BOOTPREQUEST) {
where bp is a pointer to a struct bootp, that loads the first 4-byte
word in that structure, masks out the field in that structure that's not
being compared, and compares against a word with the appropriate values
in the other fields. That won't work, because there's no guarantee that
bp points to a value aligned on a 4-byte boundary.
Declaring "struct bootp" to be packed appears to keep at least GCC 4.2.4
from performing that optimization; we define an "UNALIGNED" tag to apply
to structures to prevent that optimization, and apply that tag to the
structures in bootp.h. (We'll apply it to other structures as we
discover the need for it.)
option (RFC 3442).
Just modify the "len" variable as we parse an option - no need for a
separate variable representing the amount of data left (I suspect that's
why the wrong variable appears to have been used in the "trailing data
length" message; I'd expect that message to indicate how much *extra*
data there was in the option, not how much *total* data there was in the
option).
Add checks for too-short options in some cases where they were missing.
In the check for the Client FQDN option, skip past what data there is in
the option if it's too short, so it doesn't show up as extra data in the
option.
For the Agent Circuit option, for each suboption:
check to make sure the suboption length doesn't go past what's
left in the option;
don't reject options with an option type or length of 0 (neither
are forbidden by RFC 3046, and, in fact, RFC 3046 says "a
sub-option length may be zero");
use fn_printn() to print the Agent Circuit ID suboption, rather
than doing the equivalent ourselves with a safeputchar() loop.
out of "bootp.h" into "print-bootp.c", so we don't get unused copies of
them in files other than "print-bootp.c" that include "bootp.h", and so
we don't get warnings from GCC 3.3 about those unused copies.
compile with Sun C, as "interface.h" isn't being included before the
structures are being declared.
Furthermore, in the files that Sun C *can* compile, it doesn't cause Sun
C to generate code that's safe with unaligned accesses, as
"__attribute__" is defined as a do-nothing macro with compilers that
don't support it.
Therefore, we get rid of that tag on the structures to which it was
added, and instead use "EXTRACT_16BIT()" and "EXTRACT_32BIT()" to fetch
16-bit and 32-bit big-endian quantities from packets. We also fix some
other references to multi-byte quantities to get rid of code that tries
to do unaligned loads on platforms that don't support them.
We also throw in a hack that makes those macros use
"__attribute__((packed))" on structures containing only one 16-bit or
32-bit integer to get the compiler to generate unaligned-safe code
rather than doing it by hand. (GCC on SPARC produces the same code that
doing it by hand does; I don't know if GCC on any other big-endian
strict-alignment processor generates better code for that case. On
little-endian processors, as "ntohs()" and "ntohl()" might be functions,
that might actually produce worse code.)
Fix some places to use "%u" rather than "%d" to print unsigned
quantities.