* Format and print bootp packets.
*/
#ifndef lint
-static const char rcsid[] =
- "@(#) $Header: /tcpdump/master/tcpdump/print-bootp.c,v 1.69 2002-12-18 08:53:20 guy Exp $ (LBL)";
+static const char rcsid[] _U_ =
+ "@(#) $Header: /tcpdump/master/tcpdump/print-bootp.c,v 1.79 2005-04-20 10:30:52 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
static char tstr[] = " [|bootp]";
+static const struct tok bootp_flag_values[] = {
+ { 0x8000, "Broadcast" },
+ { 0, NULL}
+};
+
+static const struct tok bootp_op_values[] = {
+ { BOOTPREQUEST, "Request" },
+ { BOOTPREPLY, "Reply" },
+ { 0, NULL}
+};
+
/*
* Print bootp requests
*/
void
-bootp_print(register const u_char *cp, u_short sport, u_short dport, u_int length)
+bootp_print(register const u_char *cp, u_int length)
{
register const struct bootp *bp;
static const u_char vm_cmu[4] = VM_CMU;
static const u_char vm_rfc1048[4] = VM_RFC1048;
- printf("BOOTP/DHCP, length: %u",length);
-
- if (!vflag)
- return;
-
bp = (const struct bootp *)cp;
TCHECK(bp->bp_op);
- switch (bp->bp_op) {
-
- case BOOTREQUEST:
- /* Usually, a request goes from a client to a server */
- if (sport == IPPORT_BOOTPC && dport == IPPORT_BOOTPS)
- printf("\n\tRequest");
- break;
-
- case BOOTREPLY:
- /* Usually, a reply goes from a server to a client */
- if (sport == IPPORT_BOOTPS && dport == IPPORT_BOOTPC)
- printf("\n\tReply");
- break;
-
- default:
- printf("\n\tbootp-#%d", bp->bp_op);
- break;
+
+ printf("BOOTP/DHCP, %s",
+ tok2str(bootp_op_values, "unknown (0x%02x)", bp->bp_op));
+
+ if (bp->bp_htype == 1 && bp->bp_hlen == 6 && bp->bp_op == BOOTPREQUEST) {
+ TCHECK2(bp->bp_chaddr[0], 6);
+ printf(" from %s", etheraddr_string(bp->bp_chaddr));
}
+ printf(", length: %u", length);
+
+ if (!vflag)
+ return;
+
TCHECK(bp->bp_secs);
/* The usual hardware address type is 1 (10Mb Ethernet) */
printf(", xid:0x%x", EXTRACT_32BITS(&bp->bp_xid));
if (bp->bp_secs)
printf(", secs:%d", EXTRACT_16BITS(&bp->bp_secs));
- if (bp->bp_flags)
- printf(", flags:0x%x", EXTRACT_16BITS(&bp->bp_flags));
+
+ printf(", flags: [%s]",
+ bittok2str(bootp_flag_values, "none", EXTRACT_16BITS(&bp->bp_flags)));
+ if (vflag>1)
+ printf( " (0x%04x)", EXTRACT_16BITS(&bp->bp_flags));
/* Client's ip address */
TCHECK(bp->bp_ciaddr);
}
putchar('"');
}
- TCHECK2(bp->bp_sname[0], 1); /* check first char only */
+ TCHECK2(bp->bp_file[0], 1); /* check first char only */
if (*bp->bp_file) {
printf("\n\t file \"");
if (fn_print(bp->bp_file, snapend)) {
{ TAG_NS_SEARCH, "sNSSEARCH" }, /* XXX 's' */
/* RFC 3011 */
{ TAG_IP4_SUBNET_SELECT, "iSUBNET" },
-/* ftp://ftp.isi.edu/.../assignments/bootp-dhcp-extensions */
+/* http://www.iana.org/assignments/bootp-dhcp-extensions/index.htm */
{ TAG_USER_CLASS, "aCLASS" },
{ TAG_SLP_NAMING_AUTH, "aSLP-NA" },
{ TAG_CLIENT_FQDN, "$FQDN" },
}
len = *bp++;
if (bp + len >= snapend) {
- fputs(tstr, stdout);
+ printf("[|bootp %u]", len);
return;
}
break;
case TAG_CLIENT_FQDN:
+ /* option 81 should be at least 4 bytes long */
+ if (len < 4) {
+ printf("ERROR: options 81 len %u < 4 bytes", len);
+ break;
+ }
if (*bp++)
printf("[svrreg]");
if (*bp)
putchar('"');
(void)fn_printn(bp, size, NULL);
putchar('"');
+ bp += size;
+ size = 0;
break;
} else {
printf("[%s]", tok2str(arp2str, "type-%d", type));
break;
}
/* Data left over? */
- if (size)
+ if (size) {
printf("[len %u]", len);
+ bp += size;
+ }
}
return;
trunc: