mirror of
https://github.com/zeek/zeek.git
synced 2025-10-03 15:18:20 +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/conn
|
||||||
@load base/protocols/dce-rpc
|
@load base/protocols/dce-rpc
|
||||||
@load base/protocols/dhcp
|
@load base/protocols/dhcp
|
||||||
|
@load base/protocols/dhcpv6
|
||||||
@load base/protocols/dnp3
|
@load base/protocols/dnp3
|
||||||
@load base/protocols/dns
|
@load base/protocols/dns
|
||||||
@load base/protocols/finger
|
@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(conn-size)
|
||||||
add_subdirectory(dce-rpc)
|
add_subdirectory(dce-rpc)
|
||||||
add_subdirectory(dhcp)
|
add_subdirectory(dhcp)
|
||||||
|
add_subdirectory(dhcpv6)
|
||||||
add_subdirectory(dnp3)
|
add_subdirectory(dnp3)
|
||||||
add_subdirectory(dns)
|
add_subdirectory(dns)
|
||||||
add_subdirectory(file)
|
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