Browse Source

Merge pull request #1 from ntop/dev

pull current ntop/n2n dev
pull/218/head
Logan008 5 years ago
committed by GitHub
parent
commit
916902ed57
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      README.md
  2. 59
      doc/MTU.md
  3. 27
      doc/Windows.md
  4. 51
      edge.c
  5. 14
      edge_utils.c
  6. 9
      n2n.h
  7. 18
      sn.c
  8. 9
      wireshark/README.md
  9. 316
      wireshark/n2n.lua

4
README.md

@ -104,11 +104,11 @@ Running edge as a service
edge can also be run as a service instead of cli:
1. Edit `/etc/n2n/edge` with your custom options. See `/etc/n2n/edge.conf.sample`.
1. Edit `/etc/n2n/edge.conf` with your custom options. See `/etc/n2n/edge.conf.sample`.
2. Start the service: `sudo systemctl start edge`
3. Optionally enable edge start on boot: `sudo systemctl enable edge`
You can run multiple edge service instances by creating `/etc/n2n/edge-instance1` and
You can run multiple edge service instances by creating `/etc/n2n/edge-instance1.conf` and
starting it with `sudo systemctl start edge@instance1`.
IPv6 Support

59
doc/MTU.md

@ -0,0 +1,59 @@
MTU
---
The MTU of the VPN interface is set to a lower value (rather than the standard
1500 B value) to avoid excessive fragmentation on the datagram sent on internet.
This is required because n2n adds additional headers to the packets received from
the VPN interface. The size of the final frame sent through the internet interface
must have a size <= the internet interface MTU (usually 1500 B).
As a fragmentation example, suppose that a 3000 B TCP segment should be sent through
the VPN. If the VPN interface MTU is set to 1500, the packet will be split into two
fragments of 1500 B each. However, n2n will add its headers to each fragment, so
each fragment becomes a 1540 B packet. The internet interface mtu, which is 1500 B,
will fragment each packet again in two further fragments (e.g. 1500 + 50 B), so a
total of 4 fragments will be sent over internet. On the other hand, if the VPN interface
MTU was set to 1460 that would result in only 3 fragments sent as the initial segment of
3000 would be split in 1460 + 1460 + 80 B and that would not be further fragmented.
IP packet fragmentation in general is something to avoid, as described in
http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-87-3.pdf . When possible,
the fragmentation should be moved to the TCP layer by a proper MSS value.
This can be forced by mangling the packet MSS, which is called "MSS clamping" (currently not
implemented in n2n). See https://github.com/gsliepen/tinc/blob/228a03aaa707a5fcced9dd5148a4bdb7e5ef025b/src/route.c#L386 .
The exact value to use as a clamp value, however, depends on the PMTU, which is the minimum
MTU of the path between two hosts. Knowing the PMTU is also useful for a sender in order to
avoid fragmentation at the IP level. Trying to find the biggest MTU is useful since it allows to
maximize bandwidth.
PMTU Discovery Failures
-----------------------
Most operating systems try to periodically discover the PMTU by using a PMTU discovery algorithm.
This involves setting the DF (don't fragment) flag on the IP packets. When a large IP packet exceeds
the MTU of a router in the path, an "ICMP Fragmentation Needed" message should be received, which will
help the OS tune the size of the next IP packets. However, some routers do not report such ICMP message,
which results in packets being silently dropped. The `tracepath` tool can be used to detect the PMTU.
The main problem when this situation occurs is that the actual PMTU is unknown, so an automatic
solution is not applicable. The user must manually specify a lower MTU for the VPN interface
in order to solve the issue.
n2n and MTU
-----------
n2n should work by default in different environments. For this reason, the following solution
has been provided:
- PMTU discovery is disabled when possible (via the IP_MTU_DISCOVER socket option). This avoid
silently dropping a oversize packet due to the DF flag, however it possibly increments fragmentation on the path.
- As examplained above, a lower MTU is set on the VPN interface, thus removing excessive fragmentation on
the sender.
- 1400 B is used instead of 1500 B as the reference value for the internet interface MTU.
This essentially avoids fragmentation when the PMTU is >= 1400 B.
This is a conservative solution which should make n2n work by default. The user can manually
specify the MTU and re-enable PMTU discovery via the CLI options.

27
doc/Windows.md

@ -42,3 +42,30 @@ NOTE: if cmake has problems finding the installed OpenSSL library, try to downlo
"C:\Program Files\CMake\bin\cmake"
The compiled exe files should now be available under the Release directory.
# Run
The `edge.exe` program reads the `edge.conf` file located into the current directory if no option is provided.
Here is an example `edge.conf` file:
```
-c=mycommunity
-k=mysecretkey
# supernode IP address
-l=1.2.3.4:5678
# edge IP address
-a=192.168.100.1
```
The `supernode.exe` program reads the `supernode.conf` file located into the current directory if no option is provided.
Here is an example `supernode.conf` file:
```
-l=5678
```
See `edge.exe --help` and `supernode.exe --help` for a list of supported options.

51
edge.c

@ -134,13 +134,16 @@ static void help() {
"[-f]"
#endif /* #ifndef WIN32 */
#ifdef __linux__
"[-T <tos>]"
"[-T <tos>]"
#endif
"[-m <MAC address>] "
"-l <supernode host:port>\n"
" "
"[-p <local port>] [-M <mtu>] "
"[-r] [-E] [-v] [-i <reg_interval>] [-t <mgmt port>] [-b] [-A] [-h]\n\n");
#ifdef __linux__
"[-D] "
#endif
"[-r] [-E] [-v] [-i <reg_interval>] [-t <mgmt port>] [-A] [-h]\n\n");
#if defined(N2N_CAN_NAME_IFACE)
printf("-d <tun device> | tun device name\n");
@ -152,8 +155,6 @@ static void help() {
printf("-s <netmask> | Edge interface netmask in dotted decimal notation (255.255.255.0).\n");
printf("-l <supernode host:port> | Supernode IP:port\n");
printf("-i <reg_interval> | Registration interval, for NAT hole punching (default 20 seconds)\n");
printf("-b | Periodically resolve supernode IP\n");
printf(" | (when supernodes are running on dynamic IPs)\n");
printf("-p <local port> | Fixed local UDP port.\n");
#ifndef WIN32
printf("-u <UID> | User ID (numeric) to use when privileges are dropped.\n");
@ -165,6 +166,10 @@ static void help() {
printf("-m <MAC address> | Fix MAC address for the TAP interface (otherwise it may be random)\n"
" | eg. -m 01:02:03:04:05:06\n");
printf("-M <mtu> | Specify n2n MTU of edge interface (default %d).\n", DEFAULT_MTU);
#ifdef __linux__
printf("-D | Enable PMTU discovery. PMTU discovery can reduce fragmentation but"
" | causes connections stall when not properly supported.\n");
#endif
printf("-r | Enable packet forwarding through n2n community.\n");
#ifdef N2N_HAVE_AES
printf("-A | Use AES CBC for encryption (default=use twofish).\n");
@ -252,6 +257,14 @@ static int setOption(int optkey, char *optargument, n2n_priv_config_t *ec, n2n_e
break;
}
#ifdef __linux__
case 'D' : /* enable PMTU discovery */
{
conf->disable_pmtu_discovery = 0;
break;
}
#endif
case 'k': /* encrypt key */
{
if(conf->encrypt_key) free(conf->encrypt_key);
@ -287,7 +300,7 @@ static int setOption(int optkey, char *optargument, n2n_priv_config_t *ec, n2n_e
}
case 'i': /* supernode registration interval */
conf->register_interval = atoi(optarg);
conf->register_interval = atoi(optargument);
break;
#if defined(N2N_CAN_NAME_IFACE)
@ -299,12 +312,6 @@ static int setOption(int optkey, char *optargument, n2n_priv_config_t *ec, n2n_e
}
#endif
case 'b':
{
conf->re_resolve_supernode_ip = 1;
break;
}
case 'p':
{
conf->local_port = atoi(optargument);
@ -621,9 +628,6 @@ int main(int argc, char* argv[]) {
struct passwd *pw = NULL;
#endif
if(argc == 1)
help();
/* Defaults */
edge_init_conf_defaults(&conf);
memset(&ec, 0, sizeof(ec));
@ -646,18 +650,28 @@ int main(int argc, char* argv[]) {
snprintf(ec.ip_mode, sizeof(ec.ip_mode), "static");
snprintf(ec.netmask, sizeof(ec.netmask), "255.255.255.0");
traceEvent(TRACE_NORMAL, "Starting n2n edge %s %s", PACKAGE_VERSION, PACKAGE_BUILDDATE);
if((argc >= 2) && (argv[1][0] != '-')) {
rc = loadFromFile(argv[1], &conf, &ec);
if(argc > 2)
rc = loadFromCLI(argc, argv, &conf, &ec);
} else
} else if(argc > 1)
rc = loadFromCLI(argc, argv, &conf, &ec);
else
#ifdef WIN32
/* Load from current directory */
rc = loadFromFile("edge.conf", &conf, &ec);
#else
rc = -1;
#endif
if(rc < 0)
help();
if(edge_verify_conf(&conf) != 0)
help();
traceEvent(TRACE_NORMAL, "Starting n2n edge %s %s", PACKAGE_VERSION, PACKAGE_BUILDDATE);
if(0 == strcmp("dhcp", ec.ip_mode)) {
traceEvent(TRACE_NORMAL, "Dynamic IP address assignment enabled.");
@ -665,9 +679,6 @@ int main(int argc, char* argv[]) {
} else
traceEvent(TRACE_NORMAL, "ip_mode='%s'", ec.ip_mode);
if(edge_verify_conf(&conf) != 0)
help();
if(!(
#ifdef __linux__
(ec.tuntap_dev_name[0] != 0) &&

14
edge_utils.c

@ -1573,12 +1573,12 @@ static void readFromIPSocket(n2n_edge_t * eee, int in_sock) {
}
else
{
traceEvent(TRACE_WARNING, "Rx REGISTER_SUPER_ACK with wrong or old cookie.");
traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK with wrong or old cookie.");
}
}
else
{
traceEvent(TRACE_WARNING, "Rx REGISTER_SUPER_ACK with no outstanding REGISTER_SUPER.");
traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK with no outstanding REGISTER_SUPER.");
}
break;
} case MSG_TYPE_PEER_INFO: {
@ -1818,6 +1818,15 @@ static int edge_init_sockets(n2n_edge_t *eee, int udp_local_port, int mgmt_port,
else
traceEvent(TRACE_ERROR, "Could not set TOS 0x%x[%d]: %s", tos, errno, strerror(errno));
}
if(eee->conf.disable_pmtu_discovery) {
int sockopt = 0;
if(setsockopt(eee->udp_sock, IPPROTO_IP, IP_MTU_DISCOVER, &sockopt, sizeof(sockopt)) < 0)
traceEvent(TRACE_WARNING, "Could not disable PMTU discovery[%d]: %s", errno, strerror(errno));
else
traceEvent(TRACE_DEBUG, "PMTU discovery disabled");
}
#endif
eee->udp_mgmt_sock = open_socket(mgmt_port, 0 /* bind LOOPBACK */);
@ -1862,6 +1871,7 @@ void edge_init_conf_defaults(n2n_edge_conf_t *conf) {
conf->transop_id = N2N_TRANSFORM_ID_NULL;
conf->drop_multicast = 1;
conf->allow_p2p = 1;
conf->disable_pmtu_discovery = 1;
conf->register_interval = REGISTER_SUPER_INTERVAL_DFL;
if(getenv("N2N_KEY")) {

9
n2n.h

@ -164,10 +164,11 @@ typedef struct tuntap_dev {
* same value if they are to understand each other. */
#define N2N_COMPRESSION_ENABLED 1
#define DEFAULT_MTU 1390
#define DEFAULT_MTU 1290
/** Uncomment this to enable the MTU check */
//#define MTU_ASSERT_VALUE 1500
/** Uncomment this to enable the MTU check, then try to ssh to generate a fragmented packet. */
/** NOTE: see doc/MTU.md for an explanation on the 1400 value */
//#define MTU_ASSERT_VALUE 1400
/** Common type used to hold stringified IP addresses. */
typedef char ipstr_t[32];
@ -205,10 +206,10 @@ typedef struct n2n_edge_conf {
n2n_sn_name_t sn_ip_array[N2N_EDGE_NUM_SUPERNODES];
n2n_community_t community_name; /**< The community. 16 full octets. */
n2n_transform_t transop_id; /**< The transop to use. */
uint8_t re_resolve_supernode_ip;
uint8_t dyn_ip_mode; /**< Interface IP address is dynamically allocated, eg. DHCP. */
uint8_t allow_routing; /**< Accept packet no to interface address. */
uint8_t drop_multicast; /**< Multicast ethernet addresses. */
uint8_t disable_pmtu_discovery; /**< Disable the Path MTU discovery. */
uint8_t allow_p2p; /**< Allow P2P connection */
uint8_t sn_num; /**< Number of supernode addresses defined. */
uint8_t tos; /** TOS for sent packets */

18
sn.c

@ -746,7 +746,9 @@ static void help() {
printf("supernode ");
printf("-l <lport> ");
printf("-c <path> ");
#if defined(N2N_HAVE_DAEMON)
printf("[-f] ");
#endif
printf("[-v] ");
printf("\n\n");
@ -972,20 +974,24 @@ static void term_handler(int sig)
int main(int argc, char * const argv[]) {
int rc;
if(argc == 1)
help();
init_sn(&sss_node);
if((argc >= 2) && (argv[1][0] != '-')) {
rc = loadFromFile(argv[1], &sss_node);
if(argc > 2)
rc = loadFromCLI(argc, argv, &sss_node);
} else
} else if(argc > 1)
rc = loadFromCLI(argc, argv, &sss_node);
else
#ifdef WIN32
/* Load from current directory */
rc = loadFromFile("supernode.conf", &sss_node);
#else
rc = -1;
#endif
if(rc < 0)
return(-1);
help();
#if defined(N2N_HAVE_DAEMON)
if(sss_node.daemon) {
@ -1119,7 +1125,7 @@ static int run_loop(n2n_sn_t * sss) {
HASH_ITER(hh, sss->communities, comm, tmp) {
purge_expired_registrations( &comm->edges, &last_purge_edges );
if(comm->edges == NULL) {
if((comm->edges == NULL) && (!sss->lock_communities)) {
traceEvent(TRACE_INFO, "Purging idle community %s", comm->community);
HASH_DEL(sss->communities, comm);
free(comm);

9
wireshark/README.md

@ -0,0 +1,9 @@
Wireshark Lua plugin to dissect n2n traffic.
Quick load:
```
wireshark -X lua_script:n2n.lua
```
NOTE: the dissector only decodes traffic on UDP port 50001. In order to decode n2n traffic on another UDP port you can use the "Decode As..." function of wireshark.

316
wireshark/n2n.lua

@ -0,0 +1,316 @@
-- (C) 2019 - ntop.org and contributors
n2n = Proto("n2n", "n2n Protocol")
-- #############################################
PKT_TYPE_PING = 0
PKT_TYPE_REGISTER = 1
PKT_TYPE_DEREGISTER = 2
PKT_TYPE_PACKET = 3
PKT_TYPE_REGISTER_ACK = 4
PKT_TYPE_REGISTER_SUPER = 5
PKT_TYPE_REGISTER_SUPER_ACK = 6
PKT_TYPE_REGISTER_SUPER_NAK = 7
PKT_TYPE_FEDERATION = 8
PKT_TYPE_PEER_INFO = 9
PKT_TYPE_QUERY_PEER = 10
PKT_TRANSFORM_NULL = 1
PKT_TRANSFORM_TWOFISH = 2
PKT_TRANSFORM_AESCBC = 3
FLAG_FROM_SUPERNODE = 0x0020
FLAG_SOCKET = 0x0040
FLAG_OPTIONS = 0x0080
SOCKET_FAMILY_AF_INET = 0x0000
SOCKET_FAMILY_AF_INET6 = 0x8000
-- #############################################
version = ProtoField.uint8("n2n.version", "version", base.DEC)
ttl = ProtoField.uint8("n2n.ttl", "ttl", base.DEC)
packet_type_mask = 0x001f
pkt_type_2_str = {
[PKT_TYPE_PING] = "ping",
[PKT_TYPE_REGISTER] = "register",
[PKT_TYPE_DEREGISTER] = "deregister",
[PKT_TYPE_PACKET] = "packet",
[PKT_TYPE_REGISTER_ACK] = "register_ack",
[PKT_TYPE_REGISTER_SUPER] = "register_super",
[PKT_TYPE_REGISTER_SUPER_ACK] = "register_super_ack",
[PKT_TYPE_REGISTER_SUPER_NAK] = "register_super_nak",
[PKT_TYPE_FEDERATION] = "federation",
[PKT_TYPE_PEER_INFO] = "peer_info",
[PKT_TYPE_QUERY_PEER] = "query_peer",
}
packet_type = ProtoField.uint8("n2n.packet_type", "packetType", base.HEX, pkt_type_2_str, packet_type_mask)
flags_mask = 0xffe0
flags = ProtoField.uint16("n2n.flags", "Flags", base.HEX, nil, flags_mask)
from_supernode_flag = ProtoField.uint16("n2n.flags.from_supernode", "from_supernode", base.BOOLEAN, nil, FLAG_FROM_SUPERNODE)
socket_flag = ProtoField.uint16("n2n.flags.socket", "socket", base.BOOLEAN, nil, FLAG_SOCKET)
options_flag = ProtoField.uint16("n2n.flags.options", "options", base.BOOLEAN, nil, FLAG_OPTIONS)
community = ProtoField.string("n2n.community", "Community", base.ASCII)
-- #############################################
src_mac = ProtoField.ether("n2n.src_mac", "Source")
dst_mac = ProtoField.ether("n2n.dst_mac", "Destination")
socket_info = ProtoField.none("n2n.socket", "Socket Info")
socket_family = ProtoField.uint16("n2n.socket.family", "Family", base.HEX, {
[0] = "AF_INET",
})
socket_port = ProtoField.uint16("n2n.socket.port", "Port")
socket_ipv4 = ProtoField.ipv4("n2n.socket.ipv4", "IPv4")
socket_ipv6 = ProtoField.ipv6("n2n.socket.ipv6", "IPv6")
-- #############################################
peer_info_field = ProtoField.none("n2n.peer_info", "PeerInfo")
peer_info_flags = ProtoField.uint16("n2n.peer_info.flags", "Flags")
peer_info_mac = ProtoField.ether("n2n.peer_info.query_mac", "Query")
query_peer_field = ProtoField.none("n2n.query_peer", "QueryPeer")
-- #############################################
packet_field = ProtoField.none("n2n.packet", "Packet")
packet_transform = ProtoField.uint16("n2n.packet.transform", "Transform", base.HEX, {
[PKT_TRANSFORM_NULL] = "Plaintext",
[PKT_TRANSFORM_TWOFISH] = "TwoFish",
[PKT_TRANSFORM_AESCBC] = "AES CBC",
})
packet_payload = ProtoField.bytes("n2n.packet.payload", "Payload")
-- #############################################
register_field = ProtoField.none("n2n.register", "Register")
register_cookie = ProtoField.uint32("n2n.register.cookie", "Cookie", base.HEX)
register_ack_field = ProtoField.none("n2n.register_ack", "RegisterACK")
register_ack_cookie = ProtoField.uint32("n2n.register_ack.cookie", "Cookie", base.HEX)
register_super_field = ProtoField.none("n2n.register_super", "RegisterSuper")
register_super_cookie = ProtoField.uint32("n2n.register_super.cookie", "Cookie", base.HEX)
register_super_auth_schema = ProtoField.uint16("n2n.register_super.auth.schema", "AuthSchema", base.HEX)
register_super_auth_data = ProtoField.uint16("n2n.register_super.auth.data", "AuthData", base.HEX)
register_super_ack_field = ProtoField.none("n2n.register_super_ack", "RegisterSuperACK")
register_super_ack_cookie = ProtoField.uint32("n2n.register_super_ack.cookie", "Cookie", base.HEX)
register_super_ack_lifetime = ProtoField.uint16("n2n.register_super_ack.lifetime", "Registration Lifetime", base.DEC)
register_super_ack_num_sn = ProtoField.uint8("n2n.register_super_ack.num_sn", "Num Supernodes", base.DEC)
-- #############################################
n2n.fields = {
version, ttl, packet_type,
flags, from_supernode_flag, socket_flag, options_flag,
community,
-- Generic
src_mac, dst_mac,
socket_info, socket_family, socket_port, socket_ipv4, socket_ipv6,
-- PKT_TYPE_REGISTER
register_field, register_cookie,
-- PKT_TYPE_PACKET
packet_field, packet_transform, packet_payload,
-- PKT_TYPE_REGISTER_ACK
register_ack_field, register_ack_cookie,
-- PKT_TYPE_REGISTER_SUPER
register_super_field, register_super_cookie, register_super_auth_schema, register_super_auth_data,
-- PKT_TYPE_REGISTER_SUPER_ACK
register_super_ack_field, register_super_ack_cookie, register_super_ack_lifetime, register_super_ack_num_sn,
-- PKT_TYPE_PEER_INFO
peer_info_field, peer_info_flags, peer_info_mac,
-- PKT_TYPE_QUERY_PEER
query_peer_field,
}
-- #############################################
function dissect_socket(subtree, buffer, offset)
local sock_baselen = 4
local sock_protolen = 0
buffer = buffer(offset)
local sock_family = bit.band(buffer(0,4):uint(), 0xFFFF0000)
if(sock_family == SOCKET_FAMILY_AF_INET) then
sock_protolen = 4
elseif(sock_family == SOCKET_FAMILY_AF_INET6) then
sock_protolen = 16
end
local totlen = sock_baselen + sock_protolen
local socktree = subtree:add(socket_info, buffer(0, totlen))
socktree:add(socket_family, buffer(0, 2))
socktree:add(socket_port, buffer(2, 2))
if(sock_family == SOCKET_FAMILY_AF_INET) then
socktree:add(socket_ipv4, buffer(4, sock_protolen))
elseif(sock_family == SOCKET_FAMILY_AF_INET6) then
socktree:add(socket_ipv6, buffer(4, sock_protolen))
end
return offset+totlen, socktree
end
-- #############################################
function dissect_register(subtree, buffer, flags)
local regtree = subtree:add(register_field, buffer)
regtree:add(register_cookie, buffer(0,4))
regtree:add(src_mac, buffer(4,6))
regtree:add(dst_mac, buffer(10,6))
if(bit.band(flags, FLAG_SOCKET) == FLAG_SOCKET) then
dissect_socket(regtree, buffer, 16)
end
return regtree
end
-- #############################################
function dissect_register_ack(subtree, buffer, flags)
local regtree = subtree:add(register_ack_field, buffer)
regtree:add(register_ack_cookie, buffer(0,4))
regtree:add(src_mac, buffer(4,6))
regtree:add(dst_mac, buffer(10,6))
return regtree
end
-- #############################################
function dissect_packet(subtree, buffer, flags, pinfo)
local pktree = subtree:add(packet_field, buffer)
pktree:add(src_mac, buffer(0,6))
pktree:add(dst_mac, buffer(6,6))
if(bit.band(flags, FLAG_SOCKET) == FLAG_SOCKET) then
idx = dissect_socket(pktree, buffer, 12)
else
idx = 12
end
pktree:add(packet_transform, buffer(idx,2))
local payload = pktree:add(packet_payload, buffer(idx+2))
local transform = buffer(idx,2):uint()
-- Can only dissect unencrypted data
if(transform == PKT_TRANSFORM_NULL) then
Dissector.get("eth_withoutfcs"):call(buffer(idx+2):tvb(), pinfo, payload)
end
return pktree
end
-- #############################################
function dissect_register_super(subtree, buffer, flags)
local regtree = subtree:add(register_super_field, buffer)
regtree:add(register_super_cookie, buffer(0,4))
regtree:add(src_mac, buffer(4,6))
regtree:add(register_super_auth_schema, buffer(10,2))
regtree:add(register_super_auth_data, buffer(12,2))
return regtree
end
-- #############################################
function dissect_register_super_ack(subtree, buffer, flags)
local regtree = subtree:add(register_super_ack_field, buffer)
regtree:add(register_super_ack_cookie, buffer(0,4))
regtree:add(dst_mac, buffer(4,6))
regtree:add(register_super_ack_lifetime, buffer(10,2))
local idx = dissect_socket(regtree, buffer, 12)
regtree:add(register_super_ack_num_sn, buffer(idx, 1))
return regtree
end
-- #############################################
function dissect_peer_info(subtree, buffer, flags)
local peertree = subtree:add(peer_info_field, buffer)
peertree:add(peer_info_flags, buffer(0,2))
peertree:add(peer_info_mac, buffer(2,6))
dissect_socket(peertree, buffer, 8)
return peertree
end
-- #############################################
function dissect_query_peer(subtree, buffer, flags)
local peertree = subtree:add(query_peer_field, buffer)
peertree:add(src_mac, buffer(0,6))
peertree:add(dst_mac, buffer(6,6))
return peertree
end
-- #############################################
function n2n.dissector(buffer, pinfo, tree)
local length = buffer:len()
if length < 20 then return end
pinfo.cols.protocol = n2n.name
local pkt_type = bit.band(buffer(2,2):uint(), packet_type_mask)
local subtree = tree:add(n2n, buffer(), string.format("n2n Protocol, Type: %s", pkt_type_2_str[pkt_type] or "Unknown"))
-- Common
subtree:add(version, buffer(0,1))
subtree:add(ttl, buffer(1,1))
subtree:add(packet_type, buffer(2,2))
local flags_buffer = buffer(2,2)
local flags_tree = subtree:add(flags, flags_buffer)
subtree:add(community, buffer(4,16))
-- Flags
flags_tree:add(from_supernode_flag, flags_buffer)
flags_tree:add(socket_flag, flags_buffer)
flags_tree:add(options_flag, flags_buffer)
-- Packet specific
local flags = bit.band(buffer(2,2):uint(), flags_mask)
local typebuf = buffer(20)
if(pkt_type == PKT_TYPE_REGISTER) then
dissect_register(subtree, typebuf, flags)
elseif(pkt_type == PKT_TYPE_REGISTER) then
dissect_register_ack(subtree, typebuf, flags)
elseif(pkt_type == PKT_TYPE_PACKET) then
dissect_packet(subtree, typebuf, flags, pinfo)
elseif(pkt_type == PKT_TYPE_REGISTER_SUPER) then
dissect_register_super(subtree, typebuf, flags)
elseif(pkt_type == PKT_TYPE_REGISTER_SUPER_ACK) then
dissect_register_super_ack(subtree, typebuf, flags)
elseif(pkt_type == PKT_TYPE_PEER_INFO) then
dissect_peer_info(subtree, typebuf, flags)
elseif(pkt_type == PKT_TYPE_QUERY_PEER) then
dissect_query_peer(subtree, typebuf, flags)
end
end
-- #############################################
local udp_port = DissectorTable.get("udp.port")
udp_port:add(50001, n2n)
Loading…
Cancel
Save