=head1 NAME

B<dhcpdump> - DHCP packet dumper

=head1 SYNOPSIS

B<dhcpdump> [B<-h> I<regular-expression>] [B<-H>] [B<-t>] [B<-Z> I<user>] B<-i> I<interface>

B<dhcpdump> [B<-h> I<regular-expression>] [B<-H>] [B<-t>] [B<-Z> I<user>] B<-r> I<pcapfile>

=head1 DESCRIPTION

This command listens on a network interface to display the dhcp-packets for
easier checking and debugging.

=head1 USAGE

S<dhcpdump -i eth0>

If you want to filter a specific Client Hardware Address (CHADDR), then
you can specify it as a regular expression:

S<dhcpdump -i eth0 -h ^00:c0:4f>

This will display only the packets with Client Hardware Addresses
which start with 00:c0:4f.

The expression is matched against the full 16 byte CHADDR field formatted
as colon separated hex pairs, so a 6 byte Ethernet address is followed by
ten C<:00> pairs; anchored expressions need to account for that (C<^00:c0:4f>
matches, C<4f:82:ac:7f$> does not).

Option B<-H> will additionally show full packet hex dump.

Instead of getting live data from an interface, a pcap dump file can be
used:

S<dhcpdump -r pcapfile>

Opening an interface needs privileges, but decoding packets does not, and
those packets come from anyone able to reach the network. Option B<-Z> drops
to an unprivileged user once the capture handle is open, so the decoder never
runs as root:

S<dhcpdump -i eth0 -Z nobody>

The supplementary groups, the group id and the user id are all changed, and
the drop is verified to be irreversible before any packet is read.

=head1 TUI (SESSION TRACKING)

Option B<-t> switches to an interactive full-screen view that groups packets
into sessions by client hardware address, and within each client into
transactions by transaction id (XID). Each transaction lists its messages
(for example DISCOVER, OFFER, REQUEST, ACK) and a derived, colour coded state:
I<wait> (a request is still awaiting its reply), I<offered>, I<complete>
(bound), I<NAK>, I<declined> (the client refused the address, e.g. found it
in use), or I<timeout> (a reply never arrived in time). Repeated
retransmissions are collapsed with a count, and an offer from a server the
client did not ultimately pick is shown in yellow.

With B<-i> the view updates live as packets arrive; with B<-r> the whole
capture is loaded first and then browsed. The B<-h> filter applies here too,
restricting which clients are tracked. Clients are shown in a stable
first-seen order so the list does not reshuffle as traffic arrives.

The view has two panes. In the client list on the left/top select a client,
then move into the detail pane to pick one of its packets, then open the full
decode of that packet - the same detail the line mode prints.

The following keys are available:

=over

=item B<q>, B<Ctrl-C> - quit (from any view)

=item B<h>, B<H>, B<?>, B<F1> - toggle a help dialog listing the keys for the current pane

=item B<v>, B<V> - toggle between side-by-side and top/bottom layouts

=item B<u> / B<a> - use UTF-8 box glyphs / plain ASCII

=item B<Ctrl-L> - redraw the screen

=item B<Ctrl-Z> - suspend; resume with the shell's job control (fg)

=back

In the client list:

=over

=item B<j> / B<k>, B<Down> / B<Up> - select a client

=item B<g> / B<G>, B<Home> / B<End>, B<PgUp> / B<PgDn> - jump / page

=item B<Right>, B<Enter> - move into the detail pane

=item B<Tab>, B<Shift-Tab> - move into the detail pane

=back

In the detail pane:

=over

=item B<j> / B<k>, B<Down> / B<Up>, B<PgUp> / B<PgDn> - select a packet

=item B<Left>, B<Esc>, B<Backspace> - back to the client list

=item B<Tab>, B<Shift-Tab> - back to the client list

=item B<Right>, B<Enter> - open the full decode of the selected packet

=back

In the packet decode:

=over

=item B<Left> / B<Right> - previous / next packet

=item B<Up> / B<Down>, B<PgUp> / B<PgDn> - scroll

=item B<< < >> / B<< > >> - pan horizontally when the decode is wider than the screen

=item B<Esc>, B<Backspace> - back to the detail pane

=back

=head1 OUTPUT

  TIME: 2026-08-02 15:45:02.084
    IP: 0.0.0.0 (00:c0:4f:82:ac:7f) > 255.255.255.255 (ff:ff:ff:ff:ff:ff)
    OP: 1 (BOOTPREQUEST)
 HTYPE: 1 (Ethernet)
  HLEN: 6
  HOPS: 0
   XID: 28f61b03
  SECS: 0
 FLAGS: 0
CIADDR: 0.0.0.0
YIADDR: 0.0.0.0
SIADDR: 0.0.0.0
GIADDR: 0.0.0.0
CHADDR: 00:c0:4f:82:ac:7f:00:00:00:00:00:00:00:00:00:00
 SNAME:
 FNAME:
OPTION:  53 (  1) DHCP message type         3 (DHCPREQUEST)
OPTION:  54 (  4) DHCP Server identifier    130.139.64.101
OPTION:  50 (  4) Requested IP address      130.139.64.143
OPTION:  55 (  4) Parameter Request List
                  1   (Subnet mask)
                  3   (Router)
                  58  (Renewal Time T1)
                  59  (Rebinding Time T2)

At the option field, the first field is the value of the option,
the second one (between brackets) is the length of the option-datafield,
the third field is the name of the option, the fourth field is the
data of the option.

=head1 RETURN VALUES

0 on a normal run, 1 on any error: bad usage, capture setup failure, or a
live capture that dies mid-run.

=head1 NOTES

Privileged access is often needed for accessing the interface. Use B<-Z> to
give those privileges up again as soon as the interface is open.

Only Ethernet captures are supported. Notably, the Linux B<any>
pseudo-interface does not capture in Ethernet framing and is rejected;
capture on a specific interface instead.

=head1 BUGS

Not all the parameter options are printed verbose, because of lack of
documentation. Not all the options are tested, because of lack of
clients/servers with these options. If you have a dump of one of
them, please send them to me and I'll incorporate them.

=head1 THANKS TO

Ralph Droms and Ted Lemons "The DHCP Handbook", ISBN 1-57870-137-6.

Peter Apian-Bennewitz <apian@ise.fhg.de> for his Client Hardware
Address filtering

=head1 AUTHOR

Edwin Groothuis, edwin@mavetju.org (http://www.mavetju.org)

=head1 SEE ALSO

dhcpd(8), tcpdump(1), RFC2132
