mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
dhcpv6: WIP
This commit is contained in:
parent
ffb07ce2bd
commit
c8098fd7fa
8 changed files with 227 additions and 0 deletions
|
@ -53,6 +53,7 @@
|
|||
@load base/protocols/conn
|
||||
@load base/protocols/dce-rpc
|
||||
@load base/protocols/dhcp
|
||||
@load base/protocols/dhcpv6
|
||||
@load base/protocols/dnp3
|
||||
@load base/protocols/dns
|
||||
@load base/protocols/finger
|
||||
|
|
4
scripts/base/protocols/dhcpv6/__load__.zeek
Normal file
4
scripts/base/protocols/dhcpv6/__load__.zeek
Normal file
|
@ -0,0 +1,4 @@
|
|||
@load ./consts
|
||||
@load ./main
|
||||
|
||||
@load-sigs ./dpd.sig
|
12
scripts/base/protocols/dhcpv6/consts.zeek
Normal file
12
scripts/base/protocols/dhcpv6/consts.zeek
Normal file
|
@ -0,0 +1,12 @@
|
|||
module DHCPv6;
|
||||
|
||||
export {
|
||||
const message_types = {
|
||||
[1] = "SOLICIT",
|
||||
} &default = function(n: count): string { return fmt("unknown-message-type-%d", n); };
|
||||
|
||||
## Option types mapped to their names.
|
||||
const option_types = {
|
||||
[1] = "???",
|
||||
} &default = function(n: count): string { return fmt("unknown-option-type-%d", n); };
|
||||
}
|
54
scripts/base/protocols/dhcpv6/main.zeek
Normal file
54
scripts/base/protocols/dhcpv6/main.zeek
Normal file
|
@ -0,0 +1,54 @@
|
|||
@load base/frameworks/cluster
|
||||
@load ./consts
|
||||
|
||||
module DHCPv6;
|
||||
|
||||
export {
|
||||
redef enum Log::ID += { LOG };
|
||||
|
||||
global log_policy: Log::PolicyHook;
|
||||
|
||||
## The record type which contains the column fields of the DHCP log.
|
||||
type Info: record {
|
||||
## The earliest time at which a DHCP message over the
|
||||
## associated connection is observed.
|
||||
ts: time &log;
|
||||
};
|
||||
|
||||
## Event that can be handled to access the DHCP
|
||||
## record as it is sent on to the logging framework.
|
||||
global log_dhcpv6: event(rec: Info);
|
||||
}
|
||||
|
||||
# Add the dhcp info to the connection record.
|
||||
redef record connection += {
|
||||
dhcpv6: Info &optional;
|
||||
};
|
||||
|
||||
const ports = { 546/udp, 547/udp };
|
||||
redef likely_server_ports += { 547/udp };
|
||||
|
||||
event zeek_init() &priority=5
|
||||
{
|
||||
Log::create_stream(DHCP::LOG, [$columns=Info, $ev=log_dhcpv6, $path="dhcpv6", $policy=log_policy]);
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_DHCPV6, ports);
|
||||
}
|
||||
|
||||
|
||||
# Aggregate DHCP messages to the manager.
|
||||
event dhcpv6_message(c: connection, is_orig: bool)
|
||||
{
|
||||
print c$uid, c$id, is_orig;
|
||||
# if ( Cluster::is_enabled() && Cluster::local_node_type() != Cluster::MANAGER )
|
||||
# Broker::publish(Cluster::manager_topic, DHCP::aggregate_msgs,
|
||||
# network_time(), c$id, c$uid, is_orig, msg, options);
|
||||
# else
|
||||
# event DHCP::aggregate_msgs(network_time(), c$id, c$uid, is_orig, msg, options);
|
||||
}
|
||||
|
||||
event zeek_done() &priority=-5
|
||||
{
|
||||
# Log any remaining data that hasn't already been logged!
|
||||
# for ( i in DHCP::join_data )
|
||||
# join_data_expiration(DHCP::join_data, i);
|
||||
}
|
|
@ -4,6 +4,7 @@ add_subdirectory(bittorrent)
|
|||
add_subdirectory(conn-size)
|
||||
add_subdirectory(dce-rpc)
|
||||
add_subdirectory(dhcp)
|
||||
add_subdirectory(dhcpv6)
|
||||
add_subdirectory(dnp3)
|
||||
add_subdirectory(dns)
|
||||
add_subdirectory(file)
|
||||
|
|
1
src/analyzer/protocol/dhcpv6/CMakeLists.txt
Normal file
1
src/analyzer/protocol/dhcpv6/CMakeLists.txt
Normal file
|
@ -0,0 +1 @@
|
|||
spicy_add_analyzer(NAME DHCPv6 SOURCES dhcpv6.spicy dhcpv6.evt)
|
11
src/analyzer/protocol/dhcpv6/dhcpv6.evt
Normal file
11
src/analyzer/protocol/dhcpv6/dhcpv6.evt
Normal file
|
@ -0,0 +1,11 @@
|
|||
# Copyright (c) 2024 by the Zeek Project. See LICENSE for details.
|
||||
|
||||
%doc-id= Zeek::DHCPv6;
|
||||
%doc-description = "DHCPv6 analyzer";
|
||||
|
||||
protocol analyzer DHCPv6 over UDP:
|
||||
parse with DHCPv6::Message;
|
||||
|
||||
import DHCPv6;
|
||||
|
||||
on DHCPv6::Message -> event dhcpv6_message($conn, $is_orig);
|
143
src/analyzer/protocol/dhcpv6/dhcpv6.spicy
Normal file
143
src/analyzer/protocol/dhcpv6/dhcpv6.spicy
Normal file
|
@ -0,0 +1,143 @@
|
|||
# Copyright (c) 2024 by the Zeek Project. See LICENSE for details.
|
||||
|
||||
# https://datatracker.ietf.org/doc/html/rfc8415
|
||||
#
|
||||
# IANA has updated the All_DHCP_Relay_Agents_and_Servers (ff02::1:2)
|
||||
# and All_DHCP_Servers (ff05::1:3) table entries in the "IPv6 Multicast
|
||||
# Address Space Registry" at <https://www.iana.org/assignments/
|
||||
# ipv6-multicast-addresses> to reference this document instead of
|
||||
# [RFC3315].
|
||||
|
||||
module DHCPv6;
|
||||
|
||||
import spicy;
|
||||
|
||||
type MessageType = enum {
|
||||
SOLICIT = 1,
|
||||
ADVERTISE = 2,
|
||||
REQUEST = 3,
|
||||
CONFIRM = 4,
|
||||
RENEW = 5,
|
||||
REBIND = 6,
|
||||
REPLY = 7,
|
||||
RELEASE = 8,
|
||||
DECLINE = 9,
|
||||
RECONFIGURE = 10,
|
||||
INFORMATION_REQUEST = 11,
|
||||
};
|
||||
|
||||
type DDUIDType = enum {
|
||||
LLT = 1, # Link-Layer Address Plus Time https://datatracker.ietf.org/doc/html/rfc8415#section-11.2
|
||||
EN = 2, # Enterprise Number https://datatracker.ietf.org/doc/html/rfc8415#section-11.3
|
||||
LL = 3, # Link-Layer Address https://datatracker.ietf.org/doc/html/rfc8415#section-11.4
|
||||
UUID = 4, # Universally Unique Identifier https://datatracker.ietf.org/doc/html/rfc8415#section-11.5
|
||||
};
|
||||
|
||||
type DUIDOption_LLT = unit {
|
||||
hw_type: uint16;
|
||||
time_: uint32;
|
||||
ll_addr: bytes &eod &convert=spicy::bytes_to_mac($$);
|
||||
};
|
||||
|
||||
type DUIDOption_EN = unit {
|
||||
enterprise_number: uint32; # https://www.iana.org/assignments/enterprise-numbers/, https://www.iana.org/assignments/enterprise-numbers.txt
|
||||
identifier: bytes &eod;
|
||||
};
|
||||
|
||||
type DUIDOption_LL = unit {
|
||||
hw_type: uint16;
|
||||
ll_addr: bytes &eod &convert=spicy::bytes_to_mac($$);
|
||||
};
|
||||
|
||||
type DUIDOption_UUID = unit {
|
||||
uuid: bytes &size=16; # 128 bit UUID
|
||||
};
|
||||
|
||||
type DUIDOption = unit {
|
||||
duid_type: uint16 &convert=DDUIDType($$);
|
||||
switch (self.duid_type) {
|
||||
DDUIDType::LLT -> llt: DUIDOption_LLT;
|
||||
DDUIDType::EN -> en: DUIDOption_EN;
|
||||
DDUIDType::LL -> ll: DUIDOption_LL;
|
||||
DDUIDType::UUID -> uuid: DUIDOption_UUID;
|
||||
};
|
||||
};
|
||||
|
||||
type StatusCode = enum {
|
||||
Success = 0,
|
||||
UnspecFail = 1,
|
||||
NoAddrsAvail = 2,
|
||||
NoBinding = 3,
|
||||
NotOnLink = 4,
|
||||
UseMulticast = 5,
|
||||
NoPrefixAvail = 6,
|
||||
};
|
||||
|
||||
type StatusCodeOption = unit {
|
||||
code: uint16 &convert=StatusCode($$);
|
||||
message: bytes &eod;
|
||||
};
|
||||
|
||||
type IA_NAOption = unit {
|
||||
iaid: uint32;
|
||||
t1: uint32; # seconds
|
||||
t2: uint32; # seconds
|
||||
options: Option[] &eod;
|
||||
};
|
||||
|
||||
type IAADDROption = unit {
|
||||
addr_: addr &ipv6;
|
||||
preferred_lifetime: uint32;
|
||||
valid_lifetime: uint32;
|
||||
options: Option[] &eod;
|
||||
};
|
||||
|
||||
type OptionCode = enum {
|
||||
CLIENTID = 1,
|
||||
SERVERID = 2,
|
||||
IA_NA = 3,
|
||||
IA_TA = 4,
|
||||
IAADDR = 5,
|
||||
STATUS_CODE = 13,
|
||||
};
|
||||
|
||||
type Option = unit {
|
||||
code: uint16 &convert=OptionCode($$);
|
||||
len: uint16;
|
||||
|
||||
switch (self.code) {
|
||||
OptionCode::CLIENTID -> client_id: DUIDOption;
|
||||
OptionCode::SERVERID -> server_id: DUIDOption;
|
||||
OptionCode::IA_NA -> ia_na: IA_NAOption;
|
||||
# IA_TA
|
||||
OptionCode::IAADDR -> iaaddr: IAADDROption;
|
||||
OptionCode::STATUS_CODE -> status_code: StatusCodeOption;
|
||||
* -> unknown: bytes &eod;
|
||||
} &size=self.len;
|
||||
};
|
||||
|
||||
# XXX: 10. Representation and Use of Domain Names
|
||||
# AS in DHCP, but uncompressed!
|
||||
|
||||
public type Message = unit {
|
||||
msg_type: uint8 &convert=MessageType($$);
|
||||
|
||||
# TODO: Handle Relay messages!?
|
||||
# https://datatracker.ietf.org/doc/html/rfc8415#section-9
|
||||
|
||||
transaction_id: uint8[3] &convert=uint32((uint32($$[0]) << 16) + (uint32($$[1]) << 8) + uint32($$[2]));
|
||||
|
||||
options: Option[] &eod;
|
||||
|
||||
# Once the options are parsed, what do we actually want to
|
||||
# send to script land? Maybe a vector with options that have
|
||||
# a lot of optionals?
|
||||
|
||||
on %done {
|
||||
print self.msg_type, self.transaction_id;
|
||||
for (o in self.options) {
|
||||
print o;
|
||||
}
|
||||
spicy::accept_input();
|
||||
}
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue