[B.A.T.M.A.N.] [PATCH next] batman-adv: fix usage and declaration of batadv_bandwidth_units
by Antonio Quartulli
Name in declaration does not reflect the one reporte din the kernel doc.
Moreover a variable storing an enum should be of type enum rather than
int (this helps the compiler to spott possible mistakes)
Introduced by 0853ec7fafe0a195754454832993c6b35e22b842
("batman-adv: tvlv - gateway download/upload bandwidth container")
Signed-off-by: Antonio Quartulli <antonio(a)meshcoding.com>
---
gateway_common.c | 3 ++-
gateway_common.h | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/gateway_common.c b/gateway_common.c
index ab9a5ac..b211b0f 100644
--- a/gateway_common.c
+++ b/gateway_common.c
@@ -34,9 +34,10 @@
static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff,
uint32_t *down, uint32_t *up)
{
- int ret, bw_unit_type = BATADV_BW_UNIT_KBIT;
+ enum batadv_bandwidth_units bw_unit_type = BATADV_BW_UNIT_KBIT;
char *slash_ptr, *tmp_ptr;
long ldown, lup;
+ int ret;
slash_ptr = strchr(buff, '/');
if (slash_ptr)
diff --git a/gateway_common.h b/gateway_common.h
index 368d50e..56384a4 100644
--- a/gateway_common.h
+++ b/gateway_common.h
@@ -31,7 +31,7 @@ enum batadv_gw_modes {
* @BATADV_BW_UNIT_KBIT: unit type kbit
* @BATADV_BW_UNIT_MBIT: unit type mbit
*/
-enum batadv_bandwidth_types {
+enum batadv_bandwidth_units {
BATADV_BW_UNIT_KBIT,
BATADV_BW_UNIT_MBIT,
};
--
1.8.1.5
7 years, 5 months
[B.A.T.M.A.N.] [PATCH 1/2 next] batman-adv: fix orig capabilities numbering
by Antonio Quartulli
Let's start the capabilities from bit 0.
Introduced by 2b1c07b918d2acc41555bbde9d538179acb308b4
("batman-adv: tvlv - add distributed arp table container")
Signed-off-by: Antonio Quartulli <antonio(a)meshcoding.com>
---
types.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/types.h b/types.h
index f323822..8465a55 100644
--- a/types.h
+++ b/types.h
@@ -246,7 +246,7 @@ struct batadv_orig_node {
* @BATADV_ORIG_CAPA_HAS_NC: orig node has network coding enabled
*/
enum batadv_orig_capabilities {
- BATADV_ORIG_CAPA_HAS_DAT = BIT(1),
+ BATADV_ORIG_CAPA_HAS_DAT = BIT(0),
BATADV_ORIG_CAPA_HAS_NC = BIT(2),
};
--
1.8.1.5
7 years, 5 months
[B.A.T.M.A.N.] [PATCH next] batman-adv: no need for return in void functions
by Antonio Quartulli
Only network-coding.h is using "return;" inside void stub
functions. This is not a consistent with the rest of the code,
therefore don't continue to do as such.
(Other stub functions will be cleaned later)
Introduced by 7dd9d8992b0c197ba656a6d9a70966cea10fc2d9
("batman-adv: tvlv - add network coding container")
Signed-off-by: Antonio Quartulli <antonio(a)meshcoding.com>
---
network-coding.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/network-coding.h b/network-coding.h
index 8a97b40..d2f110c 100644
--- a/network-coding.h
+++ b/network-coding.h
@@ -49,7 +49,6 @@ int batadv_nc_init_debugfs(struct batadv_priv *bat_priv);
static inline void batadv_nc_status_update(struct net_device *net_dev)
{
- return;
}
static inline int batadv_nc_init(struct batadv_priv *bat_priv)
--
1.8.1.5
7 years, 5 months
[B.A.T.M.A.N.] [PATCH next] batman-adv: fix wrong kernel doc
by Antonio Quartulli
The name of the function does not match the kernel doc. Fix it.
Introduced by 6228419df3a53d09a2ba1f3e7b32bcd7cd59c968
("batman-adv: tvlv - convert tt query packet to use tvlv unicast packets")
Signed-off-by: Antonio Quartulli <antonio(a)meshcoding.com>
---
translation-table.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/translation-table.c b/translation-table.c
index 1198aea..d1840dd 100644
--- a/translation-table.c
+++ b/translation-table.c
@@ -2729,7 +2729,7 @@ out:
}
/**
- * batadv_dat_status_update - process incoming tt reply
+ * batadv_handle_tt_response - process incoming tt reply
* @bat_priv: the bat priv with all the soft interface information
* @tt_data: tt data containing the tt request information
* @resp_src: mac address of tt reply sender
--
1.8.1.5
7 years, 5 months
[B.A.T.M.A.N.] [RFCv3] [batctl] add IPv6 support to tcpdump parser
by Marco Dalla Torre
Extends 'tcpdump' functionality in 'batctl' to parse and report IPv6
communications. 'batctl' now recognizes TCP, UDP packets and the most
common ICMPv6 packet types:
-ECHO request and ECHO reply
-unreachable destination and subcases
-time exceeded
-neighbor discovery protocol 'solicit' and 'advert'
TCP and UDP parsing code has been moved from the IPv4 specific
codepath to separate functions in order to allow reuse regardless
the underlying protocol.
Signed-off-by: Marco Dalla Torre <marco.dallato(a)gmail.com>
---
CHANGE FROM V2
-rebased on fix "batctl tcpdump: Fix reported length of TCP payload"
tcpdump.c | 232 ++++++++++++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 187 insertions(+), 45 deletions(-)
diff --git a/tcpdump.c b/tcpdump.c
index e6f8f7d..9432ecb 100644
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -32,9 +32,11 @@
#include <net/if_arp.h>
#include <netinet/in.h>
#include <netinet/ip.h>
+#include <netinet/ip6.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
+#include <netinet/icmp6.h>
#include <netinet/if_ether.h>
#include "main.h"
@@ -47,6 +49,8 @@
#define ETH_P_BATMAN 0x4305
#endif /* ETH_P_BATMAN */
+#define IPV6_MIN_MTU 1280
+
#define LEN_CHECK(buff_len, check_len, desc) \
if ((size_t)(buff_len) < (check_len)) { \
fprintf(stderr, "Warning - dropping received %s packet as it is smaller than expected (%zu): %zu\n", \
@@ -188,13 +192,181 @@ static void dump_arp(unsigned char *packet_buff, ssize_t buff_len,
}
}
-static void dump_ip(unsigned char *packet_buff, ssize_t buff_len, int time_printed)
+static void dump_tcp(const char ip_string[], unsigned char *packet_buff,
+ ssize_t buff_len, size_t ip6_header_len, char *src_addr,
+ char *dst_addr)
{
- struct iphdr *iphdr, *tmp_iphdr;
+ uint16_t tcp_header_len;
struct tcphdr *tcphdr;
- struct udphdr *udphdr, *tmp_udphdr;
+
+ LEN_CHECK((size_t)buff_len - ip6_header_len,
+ sizeof(struct tcphdr), "TCP");
+ tcphdr = (struct tcphdr *)(packet_buff + ip6_header_len);
+ tcp_header_len = tcphdr->doff * 4;
+ printf("%s %s.%i > ", ip_string, src_addr, ntohs(tcphdr->source));
+ printf("%s.%i: TCP, Flags [%c%c%c%c%c%c], length %zu\n",
+ dst_addr, ntohs(tcphdr->dest),
+ (tcphdr->fin ? 'F' : '.'), (tcphdr->syn ? 'S' : '.'),
+ (tcphdr->rst ? 'R' : '.'), (tcphdr->psh ? 'P' : '.'),
+ (tcphdr->ack ? 'A' : '.'), (tcphdr->urg ? 'U' : '.'),
+ (size_t)buff_len - ip6_header_len - tcp_header_len);
+}
+
+static void dump_udp(const char ip_string[], unsigned char *packet_buff,
+ ssize_t buff_len, size_t ip6_header_len, char *src_addr,
+ char *dst_addr)
+{
+ struct udphdr *udphdr;
+
+ LEN_CHECK((size_t)buff_len - ip6_header_len, sizeof(struct udphdr),
+ "UDP");
+ udphdr = (struct udphdr *)(packet_buff + ip6_header_len);
+ printf("%s %s.%i > ", ip_string, src_addr, ntohs(udphdr->source));
+
+ switch (ntohs(udphdr->dest)) {
+ case 67:
+ LEN_CHECK((size_t)buff_len - ip6_header_len -
+ sizeof(struct udphdr), (size_t) 44, "DHCP");
+ printf("%s.67: BOOTP/DHCP, Request from %s, length %zu\n",
+ dst_addr,
+ ether_ntoa_long((struct ether_addr *)(((char *)udphdr) +
+ sizeof(struct udphdr) + 28)),
+ (size_t)buff_len - ip6_header_len -
+ sizeof(struct udphdr));
+ break;
+ case 68:
+ printf("%s.68: BOOTP/DHCP, Reply, length %zu\n", dst_addr,
+ (size_t)buff_len - ip6_header_len -
+ sizeof(struct udphdr));
+ break;
+ default:
+ printf("%s.%i: UDP, length %zu\n", dst_addr,
+ ntohs(udphdr->dest),
+ (size_t)buff_len - ip6_header_len -
+ sizeof(struct udphdr));
+ break;
+ }
+}
+
+static void dump_ipv6(unsigned char *packet_buff, ssize_t buff_len,
+ int time_printed)
+{
+ struct ip6_hdr *iphdr;
+ struct icmp6_hdr *icmphdr;
+
+ char ipv6_addr_src[40], ipv6_addr_dst[40];
+ char ip_saddr[40], ip_daddr[40], nd_nas_target[40];
+ struct nd_neighbor_solicit *nd_neigh_sol;
+ struct nd_neighbor_advert *nd_advert;
+ const char ip_string[] = "IP6";
+
+ iphdr = (struct ip6_hdr *)packet_buff;
+ LEN_CHECK((size_t)buff_len, (size_t)(sizeof(struct ip6_hdr)), "IP6");
+
+ if (!time_printed)
+ print_time();
+
+ inet_ntop(AF_INET6, &(iphdr->ip6_src), ipv6_addr_src, 40);
+ inet_ntop(AF_INET6, &(iphdr->ip6_dst), ipv6_addr_dst, 40);
+
+ switch (iphdr->ip6_nxt) {
+ case IPPROTO_ICMPV6:
+ LEN_CHECK((size_t)buff_len - (size_t)(sizeof(struct ip6_hdr)),
+ sizeof(struct icmp6_hdr), "ICMPv6");
+ icmphdr = (struct icmp6_hdr *)(packet_buff +
+ sizeof(struct ip6_hdr));
+
+ printf("IP6 %s > %s ", ipv6_addr_src, ipv6_addr_dst);
+ if (icmphdr->icmp6_type < ICMP6_INFOMSG_MASK &&
+ (size_t)(buff_len) > IPV6_MIN_MTU) {
+ fprintf(stderr,
+ "Warning - dropping received 'ICMPv6 destination unreached' packet as it is bigger than maximum allowed size (%u): %zu\n",
+ IPV6_MIN_MTU, (size_t)(buff_len));
+ return;
+ }
+
+ printf("ICMP6");
+ switch (icmphdr->icmp6_type) {
+ case ICMP6_DST_UNREACH:
+ switch (icmphdr->icmp6_code) {
+ case ICMP6_DST_UNREACH_NOROUTE:
+ printf(", unreachable route\n");
+ break;
+ case ICMP6_DST_UNREACH_ADMIN:
+ printf(", unreachable prohibited\n");
+ break;
+ case ICMP6_DST_UNREACH_ADDR:
+ printf(", unreachable address\n");
+ break;
+ case ICMP6_DST_UNREACH_BEYONDSCOPE:
+ printf(", beyond scope\n");
+ break;
+ case ICMP6_DST_UNREACH_NOPORT:
+ printf(", unreachable port\n");
+ break;
+ default:
+ printf("unknown unreach code (%u)\n",
+ icmphdr->icmp6_code);
+ }
+ break;
+ case ICMP6_ECHO_REQUEST:
+ printf(" echo request, id: %d, seq: %d, length: %hu\n",
+ icmphdr->icmp6_id, icmphdr->icmp6_seq,
+ iphdr->ip6_plen);
+ break;
+ case ICMP6_ECHO_REPLY:
+ printf(" echo reply, id: %d, seq: %d, length: %hu\n",
+ icmphdr->icmp6_id, icmphdr->icmp6_seq,
+ iphdr->ip6_plen);
+ break;
+ case ICMP6_TIME_EXCEEDED:
+ printf(" time exceeded in-transit, length %zu\n",
+ (size_t)buff_len - sizeof(struct icmp6_hdr));
+ break;
+ case ND_NEIGHBOR_SOLICIT:
+ nd_neigh_sol = (struct nd_neighbor_solicit *)icmphdr;
+ inet_ntop(AF_INET6, &(nd_neigh_sol->nd_ns_target),
+ nd_nas_target, 40);
+ printf(" neighbor solicitation, who has %s, length %zd\n",
+ nd_nas_target, buff_len);
+ break;
+ case ND_NEIGHBOR_ADVERT:
+ nd_advert = (struct nd_neighbor_advert *)icmphdr;
+ inet_ntop(AF_INET6, &(nd_advert->nd_na_target),
+ nd_nas_target, 40);
+ printf(" neighbor advertisement, tgt is %s, length %zd\n",
+ nd_nas_target, buff_len);
+ break;
+ default:
+ printf(", destination unreachable, unknown icmp6 type (%u)\n",
+ icmphdr->icmp6_type);
+ break;
+ }
+ break;
+ case IPPROTO_TCP:
+ inet_ntop(AF_INET6, &(iphdr->ip6_src), ip_saddr, 40);
+ inet_ntop(AF_INET6, &(iphdr->ip6_dst), ip_daddr, 40);
+ dump_tcp(ip_string, packet_buff, buff_len,
+ sizeof(struct ip6_hdr), ip_saddr, ip_daddr);
+ break;
+ case IPPROTO_UDP:
+ inet_ntop(AF_INET6, &(iphdr->ip6_src), ip_saddr, 40);
+ inet_ntop(AF_INET6, &(iphdr->ip6_dst), ip_daddr, 40);
+ dump_udp(ip_string, packet_buff, buff_len,
+ sizeof(struct ip6_hdr), ip_saddr, ip_daddr);
+ break;
+ default:
+ printf(" IPv6 unknown protocol: %i\n", iphdr->ip6_nxt);
+ }
+}
+
+static void dump_ip(unsigned char *packet_buff, ssize_t buff_len,
+ int time_printed)
+{
+ struct iphdr *iphdr, *tmp_iphdr;
+ struct udphdr *tmp_udphdr;
struct icmphdr *icmphdr;
- uint16_t tcp_header_len;
+ const char ip_string[] = "IP";
iphdr = (struct iphdr *)packet_buff;
LEN_CHECK((size_t)buff_len, (size_t)(iphdr->ihl * 4), "IP");
@@ -255,51 +427,16 @@ static void dump_ip(unsigned char *packet_buff, ssize_t buff_len, int time_print
(size_t)buff_len - (iphdr->ihl * 4));
break;
}
-
break;
case IPPROTO_TCP:
- tcphdr = (struct tcphdr *)(packet_buff + (iphdr->ihl * 4));
- tcp_header_len = tcphdr->doff * 4;
- LEN_CHECK((size_t)buff_len - (iphdr->ihl * 4),
- (size_t)tcp_header_len, "TCP");
-
- printf("IP %s.%i > ", inet_ntoa(*(struct in_addr *)&iphdr->saddr), ntohs(tcphdr->source));
- printf("%s.%i: TCP, flags [%c%c%c%c%c%c], length %zu\n",
- inet_ntoa(*(struct in_addr *)&iphdr->daddr), ntohs(tcphdr->dest),
- (tcphdr->fin ? 'F' : '.'), (tcphdr->syn ? 'S' : '.'),
- (tcphdr->rst ? 'R' : '.'), (tcphdr->psh ? 'P' : '.'),
- (tcphdr->ack ? 'A' : '.'), (tcphdr->urg ? 'U' : '.'),
- (size_t)buff_len - (iphdr->ihl * 4) - tcp_header_len);
+ dump_tcp(ip_string, packet_buff, buff_len, iphdr->ihl * 4,
+ inet_ntoa(*(struct in_addr *)&iphdr->saddr),
+ inet_ntoa(*(struct in_addr *)&iphdr->daddr));
break;
case IPPROTO_UDP:
- LEN_CHECK((size_t)buff_len - (iphdr->ihl * 4), sizeof(struct udphdr), "UDP");
-
- udphdr = (struct udphdr *)(packet_buff + (iphdr->ihl * 4));
- printf("IP %s.%i > ", inet_ntoa(*(struct in_addr *)&iphdr->saddr), ntohs(udphdr->source));
-
- switch (ntohs(udphdr->dest)) {
- case 67:
- LEN_CHECK((size_t)buff_len - (iphdr->ihl * 4) - sizeof(struct udphdr), (size_t) 44, "DHCP");
- printf("%s.67: BOOTP/DHCP, Request from %s, length %zu\n",
- inet_ntoa(*(struct in_addr *)&iphdr->daddr),
- ether_ntoa_long((struct ether_addr *)(((char *)udphdr) + sizeof(struct udphdr) + 28)),
- (size_t)buff_len - (iphdr->ihl * 4) - sizeof(struct udphdr));
- break;
- case 68:
- printf("%s.68: BOOTP/DHCP, Reply, length %zu\n",
- inet_ntoa(*(struct in_addr *)&iphdr->daddr),
- (size_t)buff_len - (iphdr->ihl * 4) - sizeof(struct udphdr));
- break;
- default:
- printf("%s.%i: UDP, length %zu\n",
- inet_ntoa(*(struct in_addr *)&iphdr->daddr), ntohs(udphdr->dest),
- (size_t)buff_len - (iphdr->ihl * 4) - sizeof(struct udphdr));
- break;
- }
-
- break;
- case IPPROTO_IPV6:
- printf("IP6: not implemented yet\n");
+ dump_udp(ip_string, packet_buff, buff_len, iphdr->ihl * 4,
+ inet_ntoa(*(struct in_addr *)&iphdr->saddr),
+ inet_ntoa(*(struct in_addr *)&iphdr->daddr));
break;
default:
printf("IP unknown protocol: %i\n", iphdr->protocol);
@@ -500,6 +637,11 @@ static void parse_eth_hdr(unsigned char *packet_buff, ssize_t buff_len, int read
if ((dump_level & DUMP_TYPE_NONBAT) || (time_printed))
dump_ip(packet_buff + ETH_HLEN, buff_len - ETH_HLEN, time_printed);
break;
+ case ETH_P_IPV6:
+ if ((dump_level & DUMP_TYPE_NONBAT) || (time_printed))
+ dump_ipv6(packet_buff + ETH_HLEN, buff_len - ETH_HLEN,
+ time_printed);
+ break;
case ETH_P_8021Q:
if ((dump_level & DUMP_TYPE_NONBAT) || (time_printed))
dump_vlan(packet_buff, buff_len, read_opt, time_printed);
--
1.8.3.2
7 years, 5 months
[B.A.T.M.A.N.] [PATCH next] batman-adv: properly format kernel doc
by Antonio Quartulli
Introduced by: 0b6aa0d43767889eeda43a132cf5e73df4e63bf2
("batman-adv: tvlv - basic infrastructure")
Signed-off-by: Antonio Quartulli <antonio(a)meshcoding.com>
---
main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/main.c b/main.c
index 5c5e64b..7cf6ccd 100644
--- a/main.c
+++ b/main.c
@@ -1015,7 +1015,7 @@ void batadv_tvlv_ogm_receive(struct batadv_priv *bat_priv,
* @bat_priv: the bat priv with all the soft interface information
* @optr: ogm tvlv handler callback function. This function receives the orig
* node, flags and the tvlv content as argument to process.
- * uptr: unicast tvlv handler callback function. This function receives the
+ * @uptr: unicast tvlv handler callback function. This function receives the
* source & destination of the unicast packet as well as the tvlv content
* to process.
* @type: tvlv handler type to be registered
--
1.8.1.5
7 years, 5 months
[B.A.T.M.A.N.] [RFCv3] [batctl] add IPv6 support to tcpdump parser
by Marco Dalla Torre
Extends 'tcpdump' functionality in 'batctl' to parse and report IPv6
communications. 'batctl' now recognizes TCP, UDP packets and the most
common ICMPv6 packet types:
-ECHO request and ECHO reply
-unreachable destination and subcases
-time exceeded
-neighbor discovery protocol 'solicit' and 'advert'
TCP and UDP parsing code has been moved from the IPv4 specific
codepath to separate functions in order to allow reuse regardless
the underlying protocol.
This patch additionaly fixes the erratic report of TCP header
length, which was considered fixed size. This is actually not the case
given the variable length (or no presence at all) of the options field.
Signed-off-by: Marco Dalla Torre <marco.dallato(a)gmail.com>
---
CHANGES FROM v2
-code style corrections
-changed function names from parse_tcp, parse_udp to dump_tcp, dump_udp
-sticking to "tcpdump" output style whenever possible (that is without
having to completely alter the code already in place before this patch)
tcpdump.c | 229 ++++++++++++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 187 insertions(+), 42 deletions(-)
diff --git a/tcpdump.c b/tcpdump.c
index 7e0987b..9432ecb 100644
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -32,9 +32,11 @@
#include <net/if_arp.h>
#include <netinet/in.h>
#include <netinet/ip.h>
+#include <netinet/ip6.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
+#include <netinet/icmp6.h>
#include <netinet/if_ether.h>
#include "main.h"
@@ -47,6 +49,8 @@
#define ETH_P_BATMAN 0x4305
#endif /* ETH_P_BATMAN */
+#define IPV6_MIN_MTU 1280
+
#define LEN_CHECK(buff_len, check_len, desc) \
if ((size_t)(buff_len) < (check_len)) { \
fprintf(stderr, "Warning - dropping received %s packet as it is smaller than expected (%zu): %zu\n", \
@@ -188,12 +192,181 @@ static void dump_arp(unsigned char *packet_buff, ssize_t buff_len,
}
}
-static void dump_ip(unsigned char *packet_buff, ssize_t buff_len, int time_printed)
+static void dump_tcp(const char ip_string[], unsigned char *packet_buff,
+ ssize_t buff_len, size_t ip6_header_len, char *src_addr,
+ char *dst_addr)
{
- struct iphdr *iphdr, *tmp_iphdr;
+ uint16_t tcp_header_len;
struct tcphdr *tcphdr;
- struct udphdr *udphdr, *tmp_udphdr;
+
+ LEN_CHECK((size_t)buff_len - ip6_header_len,
+ sizeof(struct tcphdr), "TCP");
+ tcphdr = (struct tcphdr *)(packet_buff + ip6_header_len);
+ tcp_header_len = tcphdr->doff * 4;
+ printf("%s %s.%i > ", ip_string, src_addr, ntohs(tcphdr->source));
+ printf("%s.%i: TCP, Flags [%c%c%c%c%c%c], length %zu\n",
+ dst_addr, ntohs(tcphdr->dest),
+ (tcphdr->fin ? 'F' : '.'), (tcphdr->syn ? 'S' : '.'),
+ (tcphdr->rst ? 'R' : '.'), (tcphdr->psh ? 'P' : '.'),
+ (tcphdr->ack ? 'A' : '.'), (tcphdr->urg ? 'U' : '.'),
+ (size_t)buff_len - ip6_header_len - tcp_header_len);
+}
+
+static void dump_udp(const char ip_string[], unsigned char *packet_buff,
+ ssize_t buff_len, size_t ip6_header_len, char *src_addr,
+ char *dst_addr)
+{
+ struct udphdr *udphdr;
+
+ LEN_CHECK((size_t)buff_len - ip6_header_len, sizeof(struct udphdr),
+ "UDP");
+ udphdr = (struct udphdr *)(packet_buff + ip6_header_len);
+ printf("%s %s.%i > ", ip_string, src_addr, ntohs(udphdr->source));
+
+ switch (ntohs(udphdr->dest)) {
+ case 67:
+ LEN_CHECK((size_t)buff_len - ip6_header_len -
+ sizeof(struct udphdr), (size_t) 44, "DHCP");
+ printf("%s.67: BOOTP/DHCP, Request from %s, length %zu\n",
+ dst_addr,
+ ether_ntoa_long((struct ether_addr *)(((char *)udphdr) +
+ sizeof(struct udphdr) + 28)),
+ (size_t)buff_len - ip6_header_len -
+ sizeof(struct udphdr));
+ break;
+ case 68:
+ printf("%s.68: BOOTP/DHCP, Reply, length %zu\n", dst_addr,
+ (size_t)buff_len - ip6_header_len -
+ sizeof(struct udphdr));
+ break;
+ default:
+ printf("%s.%i: UDP, length %zu\n", dst_addr,
+ ntohs(udphdr->dest),
+ (size_t)buff_len - ip6_header_len -
+ sizeof(struct udphdr));
+ break;
+ }
+}
+
+static void dump_ipv6(unsigned char *packet_buff, ssize_t buff_len,
+ int time_printed)
+{
+ struct ip6_hdr *iphdr;
+ struct icmp6_hdr *icmphdr;
+
+ char ipv6_addr_src[40], ipv6_addr_dst[40];
+ char ip_saddr[40], ip_daddr[40], nd_nas_target[40];
+ struct nd_neighbor_solicit *nd_neigh_sol;
+ struct nd_neighbor_advert *nd_advert;
+ const char ip_string[] = "IP6";
+
+ iphdr = (struct ip6_hdr *)packet_buff;
+ LEN_CHECK((size_t)buff_len, (size_t)(sizeof(struct ip6_hdr)), "IP6");
+
+ if (!time_printed)
+ print_time();
+
+ inet_ntop(AF_INET6, &(iphdr->ip6_src), ipv6_addr_src, 40);
+ inet_ntop(AF_INET6, &(iphdr->ip6_dst), ipv6_addr_dst, 40);
+
+ switch (iphdr->ip6_nxt) {
+ case IPPROTO_ICMPV6:
+ LEN_CHECK((size_t)buff_len - (size_t)(sizeof(struct ip6_hdr)),
+ sizeof(struct icmp6_hdr), "ICMPv6");
+ icmphdr = (struct icmp6_hdr *)(packet_buff +
+ sizeof(struct ip6_hdr));
+
+ printf("IP6 %s > %s ", ipv6_addr_src, ipv6_addr_dst);
+ if (icmphdr->icmp6_type < ICMP6_INFOMSG_MASK &&
+ (size_t)(buff_len) > IPV6_MIN_MTU) {
+ fprintf(stderr,
+ "Warning - dropping received 'ICMPv6 destination unreached' packet as it is bigger than maximum allowed size (%u): %zu\n",
+ IPV6_MIN_MTU, (size_t)(buff_len));
+ return;
+ }
+
+ printf("ICMP6");
+ switch (icmphdr->icmp6_type) {
+ case ICMP6_DST_UNREACH:
+ switch (icmphdr->icmp6_code) {
+ case ICMP6_DST_UNREACH_NOROUTE:
+ printf(", unreachable route\n");
+ break;
+ case ICMP6_DST_UNREACH_ADMIN:
+ printf(", unreachable prohibited\n");
+ break;
+ case ICMP6_DST_UNREACH_ADDR:
+ printf(", unreachable address\n");
+ break;
+ case ICMP6_DST_UNREACH_BEYONDSCOPE:
+ printf(", beyond scope\n");
+ break;
+ case ICMP6_DST_UNREACH_NOPORT:
+ printf(", unreachable port\n");
+ break;
+ default:
+ printf("unknown unreach code (%u)\n",
+ icmphdr->icmp6_code);
+ }
+ break;
+ case ICMP6_ECHO_REQUEST:
+ printf(" echo request, id: %d, seq: %d, length: %hu\n",
+ icmphdr->icmp6_id, icmphdr->icmp6_seq,
+ iphdr->ip6_plen);
+ break;
+ case ICMP6_ECHO_REPLY:
+ printf(" echo reply, id: %d, seq: %d, length: %hu\n",
+ icmphdr->icmp6_id, icmphdr->icmp6_seq,
+ iphdr->ip6_plen);
+ break;
+ case ICMP6_TIME_EXCEEDED:
+ printf(" time exceeded in-transit, length %zu\n",
+ (size_t)buff_len - sizeof(struct icmp6_hdr));
+ break;
+ case ND_NEIGHBOR_SOLICIT:
+ nd_neigh_sol = (struct nd_neighbor_solicit *)icmphdr;
+ inet_ntop(AF_INET6, &(nd_neigh_sol->nd_ns_target),
+ nd_nas_target, 40);
+ printf(" neighbor solicitation, who has %s, length %zd\n",
+ nd_nas_target, buff_len);
+ break;
+ case ND_NEIGHBOR_ADVERT:
+ nd_advert = (struct nd_neighbor_advert *)icmphdr;
+ inet_ntop(AF_INET6, &(nd_advert->nd_na_target),
+ nd_nas_target, 40);
+ printf(" neighbor advertisement, tgt is %s, length %zd\n",
+ nd_nas_target, buff_len);
+ break;
+ default:
+ printf(", destination unreachable, unknown icmp6 type (%u)\n",
+ icmphdr->icmp6_type);
+ break;
+ }
+ break;
+ case IPPROTO_TCP:
+ inet_ntop(AF_INET6, &(iphdr->ip6_src), ip_saddr, 40);
+ inet_ntop(AF_INET6, &(iphdr->ip6_dst), ip_daddr, 40);
+ dump_tcp(ip_string, packet_buff, buff_len,
+ sizeof(struct ip6_hdr), ip_saddr, ip_daddr);
+ break;
+ case IPPROTO_UDP:
+ inet_ntop(AF_INET6, &(iphdr->ip6_src), ip_saddr, 40);
+ inet_ntop(AF_INET6, &(iphdr->ip6_dst), ip_daddr, 40);
+ dump_udp(ip_string, packet_buff, buff_len,
+ sizeof(struct ip6_hdr), ip_saddr, ip_daddr);
+ break;
+ default:
+ printf(" IPv6 unknown protocol: %i\n", iphdr->ip6_nxt);
+ }
+}
+
+static void dump_ip(unsigned char *packet_buff, ssize_t buff_len,
+ int time_printed)
+{
+ struct iphdr *iphdr, *tmp_iphdr;
+ struct udphdr *tmp_udphdr;
struct icmphdr *icmphdr;
+ const char ip_string[] = "IP";
iphdr = (struct iphdr *)packet_buff;
LEN_CHECK((size_t)buff_len, (size_t)(iphdr->ihl * 4), "IP");
@@ -254,49 +427,16 @@ static void dump_ip(unsigned char *packet_buff, ssize_t buff_len, int time_print
(size_t)buff_len - (iphdr->ihl * 4));
break;
}
-
break;
case IPPROTO_TCP:
- LEN_CHECK((size_t)buff_len - (iphdr->ihl * 4), sizeof(struct tcphdr), "TCP");
-
- tcphdr = (struct tcphdr *)(packet_buff + (iphdr->ihl * 4));
- printf("IP %s.%i > ", inet_ntoa(*(struct in_addr *)&iphdr->saddr), ntohs(tcphdr->source));
- printf("%s.%i: TCP, flags [%c%c%c%c%c%c], length %zu\n",
- inet_ntoa(*(struct in_addr *)&iphdr->daddr), ntohs(tcphdr->dest),
- (tcphdr->fin ? 'F' : '.'), (tcphdr->syn ? 'S' : '.'),
- (tcphdr->rst ? 'R' : '.'), (tcphdr->psh ? 'P' : '.'),
- (tcphdr->ack ? 'A' : '.'), (tcphdr->urg ? 'U' : '.'),
- (size_t)buff_len - (iphdr->ihl * 4) - sizeof(struct tcphdr));
+ dump_tcp(ip_string, packet_buff, buff_len, iphdr->ihl * 4,
+ inet_ntoa(*(struct in_addr *)&iphdr->saddr),
+ inet_ntoa(*(struct in_addr *)&iphdr->daddr));
break;
case IPPROTO_UDP:
- LEN_CHECK((size_t)buff_len - (iphdr->ihl * 4), sizeof(struct udphdr), "UDP");
-
- udphdr = (struct udphdr *)(packet_buff + (iphdr->ihl * 4));
- printf("IP %s.%i > ", inet_ntoa(*(struct in_addr *)&iphdr->saddr), ntohs(udphdr->source));
-
- switch (ntohs(udphdr->dest)) {
- case 67:
- LEN_CHECK((size_t)buff_len - (iphdr->ihl * 4) - sizeof(struct udphdr), (size_t) 44, "DHCP");
- printf("%s.67: BOOTP/DHCP, Request from %s, length %zu\n",
- inet_ntoa(*(struct in_addr *)&iphdr->daddr),
- ether_ntoa_long((struct ether_addr *)(((char *)udphdr) + sizeof(struct udphdr) + 28)),
- (size_t)buff_len - (iphdr->ihl * 4) - sizeof(struct udphdr));
- break;
- case 68:
- printf("%s.68: BOOTP/DHCP, Reply, length %zu\n",
- inet_ntoa(*(struct in_addr *)&iphdr->daddr),
- (size_t)buff_len - (iphdr->ihl * 4) - sizeof(struct udphdr));
- break;
- default:
- printf("%s.%i: UDP, length %zu\n",
- inet_ntoa(*(struct in_addr *)&iphdr->daddr), ntohs(udphdr->dest),
- (size_t)buff_len - (iphdr->ihl * 4) - sizeof(struct udphdr));
- break;
- }
-
- break;
- case IPPROTO_IPV6:
- printf("IP6: not implemented yet\n");
+ dump_udp(ip_string, packet_buff, buff_len, iphdr->ihl * 4,
+ inet_ntoa(*(struct in_addr *)&iphdr->saddr),
+ inet_ntoa(*(struct in_addr *)&iphdr->daddr));
break;
default:
printf("IP unknown protocol: %i\n", iphdr->protocol);
@@ -497,6 +637,11 @@ static void parse_eth_hdr(unsigned char *packet_buff, ssize_t buff_len, int read
if ((dump_level & DUMP_TYPE_NONBAT) || (time_printed))
dump_ip(packet_buff + ETH_HLEN, buff_len - ETH_HLEN, time_printed);
break;
+ case ETH_P_IPV6:
+ if ((dump_level & DUMP_TYPE_NONBAT) || (time_printed))
+ dump_ipv6(packet_buff + ETH_HLEN, buff_len - ETH_HLEN,
+ time_printed);
+ break;
case ETH_P_8021Q:
if ((dump_level & DUMP_TYPE_NONBAT) || (time_printed))
dump_vlan(packet_buff, buff_len, read_opt, time_printed);
--
1.8.3.2
7 years, 5 months
[B.A.T.M.A.N.] [PATCH] batman-adv: Generalize DAT in order to support any type of key/value, not only IPv4 and MAC
by Mihail Costea
Mades DAT support more types by making its key and value a void* and
by adding type field to dat_entry.
This change is needed in order to make DAT support any type of keys,
like IPv6 too.
Adds generic function for transforming any data to string.
The function is used in order to avoid defining different debug messages
for different DAT key/value types. For example, if we had IPv6 as a DAT key,
then "%pI4" should be "%pI6c", but all the other text of the debug message
would be the same.
Also everything is memorized in a struct in order to avoid further
switch cases for all types.
Signed-off-by: Mihail Costea <mihail.costea90(a)gmail.com>
Signed-off-by: Stefan Popa <Stefan.A.Popa(a)intel.com>
Reviewed-by: Stefan Popa <Stefan.A.Popa(a)intel.com>
---
compat.c | 2 +
distributed-arp-table.c | 219 +++++++++++++++++++++++++++++++++++------------
distributed-arp-table.h | 2 +
types.h | 32 ++++++-
4 files changed, 195 insertions(+), 60 deletions(-)
diff --git a/compat.c b/compat.c
index 68c2258..6496c00 100644
--- a/compat.c
+++ b/compat.c
@@ -97,6 +97,8 @@ void batadv_free_rcu_dat_entry(struct rcu_head *rcu)
struct batadv_dat_entry *dat_entry;
dat_entry = container_of(rcu, struct batadv_dat_entry, rcu);
+ kfree(dat_entry->value);
+ kfree(dat_entry->key);
kfree(dat_entry);
}
#endif
diff --git a/distributed-arp-table.c b/distributed-arp-table.c
index 6c8c393..28e513f 100644
--- a/distributed-arp-table.c
+++ b/distributed-arp-table.c
@@ -33,6 +33,31 @@
static void batadv_dat_purge(struct work_struct *work);
+static struct batadv_dat_type_info batadv_dat_types_info[] = {
+ {
+ .key_size = sizeof(__be32),
+ .key_str_fmt = "%pI4",
+ .value_size = ETH_ALEN,
+ .value_str_fmt = "%pM",
+ },
+};
+
+/**
+ * batadv_dat_data_to_str: transforms a given data to a string using str_fmt
+ * @data: the data to transform
+ * @str_fmt: string format
+ * @buf: the buf where the key string is stored
+ * @buf_len: buf length
+ *
+ * Returns buf.
+ */
+static char *batadv_dat_data_to_str(void *data, char *str_fmt,
+ char *buf, size_t buf_len)
+{
+ snprintf(buf, buf_len, str_fmt, data);
+ return buf;
+}
+
/**
* batadv_dat_start_timer - initialise the DAT periodic worker
* @bat_priv: the bat priv with all the soft interface information
@@ -132,16 +157,24 @@ static void batadv_dat_purge(struct work_struct *work)
/**
* batadv_compare_dat - comparing function used in the local DAT hash table
* @node: node in the local table
- * @data2: second object to compare the node to
+ * @key2: second object to compare the node to
*
* Returns 1 if the two entries are the same, 0 otherwise.
*/
-static int batadv_compare_dat(const struct hlist_node *node, const void *data2)
+static int batadv_compare_dat(const struct hlist_node *node, const void *key2)
{
- const void *data1 = container_of(node, struct batadv_dat_entry,
- hash_entry);
+ const struct batadv_dat_entry *dat_entry1, *dat_entry2;
+ size_t key_size;
- return (memcmp(data1, data2, sizeof(__be32)) == 0 ? 1 : 0);
+ dat_entry1 = container_of(node, struct batadv_dat_entry, hash_entry);
+ dat_entry2 = container_of(key2, struct batadv_dat_entry, key);
+
+ if (dat_entry1->type != dat_entry2->type)
+ return 0;
+
+ key_size = batadv_dat_types_info[dat_entry1->type].key_size;
+ return (memcmp(dat_entry1->key, dat_entry2->key, key_size) == 0 ?
+ 1 : 0);
}
/**
@@ -198,7 +231,7 @@ static __be32 batadv_arp_ip_dst(struct sk_buff *skb, int hdr_size)
}
/**
- * batadv_hash_dat - compute the hash value for an IP address
+ * batadv_hash_dat - compute the hash value for a DAT key
* @data: data to hash
* @size: size of the hash table
*
@@ -209,7 +242,8 @@ static uint32_t batadv_hash_dat(const void *data, uint32_t size)
uint32_t hash = 0;
const struct batadv_dat_entry *dat = data;
- hash = batadv_hash_bytes(hash, &dat->ip, sizeof(dat->ip));
+ hash = batadv_hash_bytes(hash, dat->key,
+ batadv_dat_types_info[dat->type].key_size);
hash = batadv_hash_bytes(hash, &dat->vid, sizeof(dat->vid));
hash += (hash << 3);
@@ -223,24 +257,26 @@ static uint32_t batadv_hash_dat(const void *data, uint32_t size)
* batadv_dat_entry_hash_find - look for a given dat_entry in the local hash
* table
* @bat_priv: the bat priv with all the soft interface information
- * @ip: search key
+ * @key: search key
+ * @entry_type: type of the entry
* @vid: VLAN identifier
*
* Returns the dat_entry if found, NULL otherwise.
*/
static struct batadv_dat_entry *
-batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, __be32 ip,
- unsigned short vid)
+batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, void *key,
+ uint8_t entry_type, unsigned short vid)
{
struct hlist_head *head;
struct batadv_dat_entry to_find, *dat_entry, *dat_entry_tmp = NULL;
struct batadv_hashtable *hash = bat_priv->dat.hash;
- uint32_t index;
+ uint32_t index, key_size = batadv_dat_types_info[entry_type].key_size;
if (!hash)
return NULL;
- to_find.ip = ip;
+ to_find.key = key;
+ to_find.type = entry_type;
to_find.vid = vid;
index = batadv_hash_dat(&to_find, hash->size);
@@ -248,7 +284,9 @@ batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, __be32 ip,
rcu_read_lock();
hlist_for_each_entry_rcu(dat_entry, head, hash_entry) {
- if (dat_entry->ip != ip)
+ if (dat_entry->type != entry_type)
+ continue;
+ if (memcmp(dat_entry->key, key, key_size))
continue;
if (!atomic_inc_not_zero(&dat_entry->refcount))
@@ -265,36 +303,62 @@ batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, __be32 ip,
/**
* batadv_dat_entry_add - add a new dat entry or update it if already exists
* @bat_priv: the bat priv with all the soft interface information
- * @ip: ipv4 to add/edit
- * @mac_addr: mac address to assign to the given ipv4
+ * @key: the key to add/edit
+ * @entry_type: type of the key added to DAT
+ * @value: the value to assign to the given key
* @vid: VLAN identifier
*/
-static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip,
- uint8_t *mac_addr, unsigned short vid)
+static void batadv_dat_entry_add(struct batadv_priv *bat_priv, void *key,
+ uint8_t entry_type, void *value,
+ unsigned short vid)
{
struct batadv_dat_entry *dat_entry;
int hash_added;
+ char dbg_key[BATADV_DAT_KEY_MAX_LEN];
+ char dbg_value[BATADV_DAT_VALUE_MAX_LEN];
+ size_t key_size = batadv_dat_types_info[entry_type].key_size;
+ size_t value_size = batadv_dat_types_info[entry_type].value_size;
+ char *key_str_fmt = batadv_dat_types_info[entry_type].key_str_fmt;
+ char *value_str_fmt = batadv_dat_types_info[entry_type].value_str_fmt;
- dat_entry = batadv_dat_entry_hash_find(bat_priv, ip, vid);
+ dat_entry = batadv_dat_entry_hash_find(bat_priv, key, entry_type, vid);
/* if this entry is already known, just update it */
if (dat_entry) {
- if (!batadv_compare_eth(dat_entry->mac_addr, mac_addr))
- memcpy(dat_entry->mac_addr, mac_addr, ETH_ALEN);
+ if (memcmp(dat_entry->value, value, value_size))
+ memcpy(dat_entry->value, value, value_size);
dat_entry->last_update = jiffies;
batadv_dbg(BATADV_DBG_DAT, bat_priv,
- "Entry updated: %pI4 %pM (vid: %d)\n",
- &dat_entry->ip, dat_entry->mac_addr,
+ "Entry updated: %s %s (vid: %d)\n",
+ batadv_dat_data_to_str(dat_entry->key, key_str_fmt,
+ dbg_key, sizeof(dbg_key)),
+ batadv_dat_data_to_str(dat_entry->value,
+ value_str_fmt,
+ dbg_value,
+ sizeof(dbg_value)),
BATADV_PRINT_VID(vid));
goto out;
}
+
dat_entry = kmalloc(sizeof(*dat_entry), GFP_ATOMIC);
if (!dat_entry)
goto out;
- dat_entry->ip = ip;
+ /* Assignment needed for correct free if next allocation fails. */
+ dat_entry->value = NULL;
+ dat_entry->key = kmalloc(key_size, GFP_ATOMIC);
+ if (!dat_entry->key)
+ goto out;
+ memcpy(dat_entry->key, key, key_size);
+
+ dat_entry->value = kmalloc(value_size, GFP_ATOMIC);
+ if (!dat_entry->value)
+ goto out;
+ memcpy(dat_entry->value, value, value_size);
+
+ dat_entry->type = entry_type;
dat_entry->vid = vid;
- memcpy(dat_entry->mac_addr, mac_addr, ETH_ALEN);
+
dat_entry->last_update = jiffies;
atomic_set(&dat_entry->refcount, 2);
@@ -308,8 +372,12 @@ static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip,
goto out;
}
- batadv_dbg(BATADV_DBG_DAT, bat_priv, "New entry added: %pI4 %pM (vid: %d)\n",
- &dat_entry->ip, dat_entry->mac_addr, BATADV_PRINT_VID(vid));
+ batadv_dbg(BATADV_DBG_DAT, bat_priv, "New entry added: %s %s (vid: %d)\n",
+ batadv_dat_data_to_str(dat_entry->key, key_str_fmt,
+ dbg_key, sizeof(dbg_key)),
+ batadv_dat_data_to_str(dat_entry->value, value_str_fmt,
+ dbg_value, sizeof(dbg_value)),
+ BATADV_PRINT_VID(vid));
out:
if (dat_entry)
@@ -521,7 +589,8 @@ static void batadv_choose_next_candidate(struct batadv_priv *bat_priv,
* batadv_dat_select_candidates - select the nodes which the DHT message has to
* be sent to
* @bat_priv: the bat priv with all the soft interface information
- * @ip_dst: ipv4 to look up in the DHT
+ * @key: key to look up in the DHT
+ * @entry_type: type of the key
*
* An originator O is selected if and only if its DHT_ID value is one of three
* closest values (from the LEFT, with wrap around if needed) then the hash
@@ -530,11 +599,15 @@ static void batadv_choose_next_candidate(struct batadv_priv *bat_priv,
* Returns the candidate array of size BATADV_DAT_CANDIDATE_NUM.
*/
static struct batadv_dat_candidate *
-batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst)
+batadv_dat_select_candidates(struct batadv_priv *bat_priv, void *key,
+ uint8_t entry_type)
{
int select;
- batadv_dat_addr_t last_max = BATADV_DAT_ADDR_MAX, ip_key;
+ batadv_dat_addr_t last_max = BATADV_DAT_ADDR_MAX, dat_key;
struct batadv_dat_candidate *res;
+ struct batadv_dat_entry to_find;
+ char dbg_key[BATADV_DAT_KEY_MAX_LEN];
+ char *key_str_fmt = batadv_dat_types_info[entry_type].key_str_fmt;
if (!bat_priv->orig_hash)
return NULL;
@@ -543,15 +616,19 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst)
if (!res)
return NULL;
- ip_key = (batadv_dat_addr_t)batadv_hash_dat(&ip_dst,
- BATADV_DAT_ADDR_MAX);
+ to_find.key = key;
+ to_find.type = entry_type;
+ dat_key = (batadv_dat_addr_t)batadv_hash_dat(&to_find,
+ BATADV_DAT_ADDR_MAX);
batadv_dbg(BATADV_DBG_DAT, bat_priv,
- "dat_select_candidates(): IP=%pI4 hash(IP)=%u\n", &ip_dst,
- ip_key);
+ "dat_select_candidates(): KEY=%s hash(KEY)=%u\n",
+ batadv_dat_data_to_str(key, key_str_fmt, dbg_key,
+ sizeof(dbg_key)),
+ dat_key);
for (select = 0; select < BATADV_DAT_CANDIDATES_NUM; select++)
- batadv_choose_next_candidate(bat_priv, res, select, ip_key,
+ batadv_choose_next_candidate(bat_priv, res, select, dat_key,
&last_max);
return res;
@@ -561,7 +638,8 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst)
* batadv_dat_send_data - send a payload to the selected candidates
* @bat_priv: the bat priv with all the soft interface information
* @skb: payload to send
- * @ip: the DHT key
+ * @key: the DHT key
+ * @entry_type: type of the key
* @packet_subtype: unicast4addr packet subtype to use
*
* This function copies the skb with pskb_copy() and is sent as unicast packet
@@ -571,8 +649,8 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst)
* otherwise.
*/
static bool batadv_dat_send_data(struct batadv_priv *bat_priv,
- struct sk_buff *skb, __be32 ip,
- int packet_subtype)
+ struct sk_buff *skb, void *key,
+ uint8_t entry_type, int packet_subtype)
{
int i;
bool ret = false;
@@ -580,12 +658,16 @@ static bool batadv_dat_send_data(struct batadv_priv *bat_priv,
struct batadv_neigh_node *neigh_node = NULL;
struct sk_buff *tmp_skb;
struct batadv_dat_candidate *cand;
+ char dbg_key[BATADV_DAT_KEY_MAX_LEN];
+ char *key_str_fmt = batadv_dat_types_info[entry_type].key_str_fmt;
- cand = batadv_dat_select_candidates(bat_priv, ip);
+ cand = batadv_dat_select_candidates(bat_priv, key, entry_type);
if (!cand)
goto out;
- batadv_dbg(BATADV_DBG_DAT, bat_priv, "DHT_SEND for %pI4\n", &ip);
+ batadv_dbg(BATADV_DBG_DAT, bat_priv, "DHT_SEND for %s\n",
+ batadv_dat_data_to_str(key, key_str_fmt, dbg_key,
+ sizeof(dbg_key)));
for (i = 0; i < BATADV_DAT_CANDIDATES_NUM; i++) {
if (cand[i].type == BATADV_DAT_CANDIDATE_NOT_FOUND)
@@ -755,6 +837,9 @@ int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset)
unsigned long last_seen_jiffies;
int last_seen_msecs, last_seen_secs, last_seen_mins;
uint32_t i;
+ char dbg_key[BATADV_DAT_KEY_MAX_LEN];
+ char dbg_value[BATADV_DAT_VALUE_MAX_LEN];
+ char *key_str_fmt, *value_str_fmt;
primary_if = batadv_seq_print_text_primary_if_get(seq);
if (!primary_if)
@@ -775,8 +860,20 @@ int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset)
last_seen_msecs = last_seen_msecs % 60000;
last_seen_secs = last_seen_msecs / 1000;
- seq_printf(seq, " * %15pI4 %14pM %4i %6i:%02i\n",
- &dat_entry->ip, dat_entry->mac_addr,
+ key_str_fmt = batadv_dat_types_info[dat_entry->type]
+ .key_str_fmt;
+ value_str_fmt = batadv_dat_types_info[dat_entry->type]
+ .value_str_fmt;
+
+ seq_printf(seq, " * %15s %14s %4i %6i:%02i\n",
+ batadv_dat_data_to_str(dat_entry->key,
+ key_str_fmt,
+ dbg_key,
+ sizeof(dbg_key)),
+ batadv_dat_data_to_str(dat_entry->value,
+ value_str_fmt,
+ dbg_value,
+ sizeof(dbg_value)),
BATADV_PRINT_VID(dat_entry->vid),
last_seen_mins, last_seen_secs);
}
@@ -929,9 +1026,10 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
hw_src = batadv_arp_hw_src(skb, hdr_size);
ip_dst = batadv_arp_ip_dst(skb, hdr_size);
- batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid);
+ batadv_dat_entry_add(bat_priv, &ip_src, BATADV_DAT_IPV4, hw_src, vid);
- dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst, vid);
+ dat_entry = batadv_dat_entry_hash_find(bat_priv, &ip_dst,
+ BATADV_DAT_IPV4, vid);
if (dat_entry) {
/* If the ARP request is destined for a local client the local
* client will answer itself. DAT would only generate a
@@ -940,8 +1038,11 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
* Moreover, if the soft-interface is enslaved into a bridge, an
* additional DAT answer may trigger kernel warnings about
* a packet coming from the wrong port.
+ *
+ * Entry value is the same as mac_addr, so it can be used
+ * directly.
*/
- if (batadv_is_my_client(bat_priv, dat_entry->mac_addr,
+ if (batadv_is_my_client(bat_priv, dat_entry->value,
BATADV_NO_FLAGS)) {
ret = true;
goto out;
@@ -949,7 +1050,7 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src,
bat_priv->soft_iface, ip_dst, hw_src,
- dat_entry->mac_addr, hw_src);
+ dat_entry->value, hw_src);
if (!skb_new)
goto out;
@@ -969,7 +1070,8 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
ret = true;
} else {
/* Send the request to the DHT */
- ret = batadv_dat_send_data(bat_priv, skb, ip_dst,
+ ret = batadv_dat_send_data(bat_priv, skb, &ip_dst,
+ BATADV_DAT_IPV4,
BATADV_P_DAT_DHT_GET);
}
out:
@@ -1015,15 +1117,17 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
batadv_dbg_arp(bat_priv, skb, type, hdr_size,
"Parsing incoming ARP REQUEST");
- batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid);
+ batadv_dat_entry_add(bat_priv, &ip_src, BATADV_DAT_IPV4, hw_src, vid);
- dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst, vid);
+ dat_entry = batadv_dat_entry_hash_find(bat_priv, &ip_dst,
+ BATADV_DAT_IPV4, vid);
if (!dat_entry)
goto out;
+ /* Entry value is the same as mac_addr, so it can be used directly. */
skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src,
bat_priv->soft_iface, ip_dst, hw_src,
- dat_entry->mac_addr, hw_src);
+ dat_entry->value, hw_src);
if (!skb_new)
goto out;
@@ -1086,14 +1190,16 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
hw_dst = batadv_arp_hw_dst(skb, hdr_size);
ip_dst = batadv_arp_ip_dst(skb, hdr_size);
- batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid);
- batadv_dat_entry_add(bat_priv, ip_dst, hw_dst, vid);
+ batadv_dat_entry_add(bat_priv, &ip_src, BATADV_DAT_IPV4, hw_src, vid);
+ batadv_dat_entry_add(bat_priv, &ip_dst, BATADV_DAT_IPV4, hw_dst, vid);
/* Send the ARP reply to the candidates for both the IP addresses that
* the node obtained from the ARP reply
*/
- batadv_dat_send_data(bat_priv, skb, ip_src, BATADV_P_DAT_DHT_PUT);
- batadv_dat_send_data(bat_priv, skb, ip_dst, BATADV_P_DAT_DHT_PUT);
+ batadv_dat_send_data(bat_priv, skb, &ip_src, BATADV_DAT_IPV4,
+ BATADV_P_DAT_DHT_PUT);
+ batadv_dat_send_data(bat_priv, skb, &ip_dst, BATADV_DAT_IPV4,
+ BATADV_P_DAT_DHT_PUT);
}
/**
* batadv_dat_snoop_incoming_arp_reply - snoop the ARP reply and fill the local
@@ -1131,8 +1237,8 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
/* Update our internal cache with both the IP addresses the node got
* within the ARP reply
*/
- batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid);
- batadv_dat_entry_add(bat_priv, ip_dst, hw_dst, vid);
+ batadv_dat_entry_add(bat_priv, &ip_src, BATADV_DAT_IPV4, hw_src, vid);
+ batadv_dat_entry_add(bat_priv, &ip_dst, BATADV_DAT_IPV4, hw_dst, vid);
/* if this REPLY is directed to a client of mine, let's deliver the
* packet to the interface
@@ -1179,7 +1285,8 @@ bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv,
goto out;
ip_dst = batadv_arp_ip_dst(forw_packet->skb, hdr_size);
- dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst, vid);
+ dat_entry = batadv_dat_entry_hash_find(bat_priv, &ip_dst,
+ BATADV_DAT_IPV4, vid);
/* check if the node already got this entry */
if (!dat_entry) {
batadv_dbg(BATADV_DBG_DAT, bat_priv,
diff --git a/distributed-arp-table.h b/distributed-arp-table.h
index 60d853b..a60619d 100644
--- a/distributed-arp-table.h
+++ b/distributed-arp-table.h
@@ -28,6 +28,8 @@
#include <linux/if_arp.h>
#define BATADV_DAT_ADDR_MAX ((batadv_dat_addr_t)~(batadv_dat_addr_t)0)
+#define BATADV_DAT_KEY_MAX_LEN 16
+#define BATADV_DAT_VALUE_MAX_LEN 18
void batadv_dat_status_update(struct net_device *net_dev);
bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
diff --git a/types.h b/types.h
index f323822..239a95e 100644
--- a/types.h
+++ b/types.h
@@ -1031,8 +1031,9 @@ struct batadv_algo_ops {
/**
* struct batadv_dat_entry - it is a single entry of batman-adv ARP backend. It
* is used to stored ARP entries needed for the global DAT cache
- * @ip: the IPv4 corresponding to this DAT/ARP entry
- * @mac_addr: the MAC address associated to the stored IPv4
+ * @key: the key corresponding to this DAT entry
+ * @value: the value corresponding to this DAT entry
+ * @type: the type of the DAT entry
* @vid: the vlan ID associated to this entry
* @last_update: time in jiffies when this entry was refreshed last time
* @hash_entry: hlist node for batadv_priv_dat::hash
@@ -1040,8 +1041,9 @@ struct batadv_algo_ops {
* @rcu: struct used for freeing in an RCU-safe manner
*/
struct batadv_dat_entry {
- __be32 ip;
- uint8_t mac_addr[ETH_ALEN];
+ void *key;
+ void *value;
+ uint8_t type;
unsigned short vid;
unsigned long last_update;
struct hlist_node hash_entry;
@@ -1050,6 +1052,28 @@ struct batadv_dat_entry {
};
/**
+ * batadv_dat_types - possible types for DAT entries
+ * @BATADV_DAT_IPV4: IPv4 address type
+ */
+enum batadv_dat_types {
+ BATADV_DAT_IPV4 = 0,
+};
+
+/**
+ * batadv_dat_type_info - info needed for a DAT type
+ * @key_size: the size of the DAT entry key
+ * @key_str_fmt: string format used by key
+ * @value_size: the size of the value
+ * @value_str_fmt: string format used by value
+ */
+struct batadv_dat_type_info {
+ size_t key_size;
+ char *key_str_fmt;
+ size_t value_size;
+ char *value_str_fmt;
+};
+
+/**
* struct batadv_dat_candidate - candidate destination for DAT operations
* @type: the type of the selected candidate. It can one of the following:
* - BATADV_DAT_CANDIDATE_NOT_FOUND
--
1.7.10.4
7 years, 5 months
[B.A.T.M.A.N.] pull request net: batman-adv 2013-09-18
by Antonio Quartulli
Hello David,
this is a very small (but important) fix intended for net/linux-3.{11,12} (since
3.12-rc1 is out I guess this patch needs to be enqueued for stable in order to
reach 3.11?)
This change fixes a regression introduced in 3.11 that prevents the Bridge Loop
Avoidance component from correctly operate on VLANs.
Please pull or let me know of any problem.
Thank you,
Antonio
The following changes since commit 1ef68ec462571955f2a667ddf1ffe279848709d7:
Merge branch 'sfc-3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc (2013-09-16 21:43:54 -0400)
are available in the git repository at:
git://git.open-mesh.org/linux-merge.git tags/batman-adv-fix-for-davem
for you to fetch changes up to 4c18c425b2d228415b635e97a64737d7f27c5536:
batman-adv: set the TAG flag for the vid passed to BLA (2013-09-17 21:15:16 +0200)
----------------------------------------------------------------
Included change:
- fix the Bridge Loop Avoidance component by marking the variables containing
the VLAN ID with the HAS_TAG flag when needed.
----------------------------------------------------------------
Antonio Quartulli (1):
batman-adv: set the TAG flag for the vid passed to BLA
net/batman-adv/soft-interface.c | 2 ++
1 file changed, 2 insertions(+)
7 years, 5 months
[B.A.T.M.A.N.] Where can i see, sequence number, eq, rq for an originator?
by Eugenio Carocci
Hello everybody,
first of all, i want to excuse myself, if i write something wrong for
my horrible english. I am writing my thesis of Information Engineering
about your protocol. So, as i wrote in the object of the
message, i want to see where BATMAN-adv save the last sequence number
saved for a generic originator, and also
where it puts all the information act to evaluate the TQ toward each
originator of the mesh.
Thanks you for attenction
--
Eugenio Carocci
7 years, 5 months