/* * netsniff-ng - the packet sniffing beast * Subject to the GPL, version 2. */ #include #include "str.h" #include "xmalloc.h" #include "built_in.h" #include "trafgen_l7.h" #include "trafgen_proto.h" static struct proto_field dns_fields[] = { { .id = DNS_ID, .len = 2, .offset = 0 }, { .id = DNS_QR, .len = 2, .offset = 2, .shift = 15, .mask = 0x8000 }, { .id = DNS_OPCODE, .len = 2, .offset = 2, .shift = 11, .mask = 0x7800 }, { .id = DNS_AA, .len = 2, .offset = 2, .shift = 10, .mask = 0x0400 }, { .id = DNS_TC, .len = 2, .offset = 2, .shift = 9, .mask = 0x0200 }, { .id = DNS_RD, .len = 2, .offset = 2, .shift = 8, .mask = 0x0100 }, { .id = DNS_RA, .len = 2, .offset = 2, .shift = 7, .mask = 0x80 }, { .id = DNS_ZERO, .len = 2, .offset = 2, .shift = 4, .mask = 0x30 }, { .id = DNS_RCODE, .len = 2, .offset = 2, .shift = 0, .mask = 0xf }, { .id = DNS_QD_COUNT, .len = 2, .offset = 4, }, { .id = DNS_AN_COUNT, .len = 2, .offset = 6, }, { .id = DNS_NS_COUNT, .len = 2, .offset = 8, }, { .id = DNS_AR_COUNT, .len = 2, .offset = 10, }, }; static struct proto_field dns_query_fields[] = { { .id = DNS_QUERY_NAME, .len = 0, .offset = 0 }, { .id = DNS_QUERY_TYPE, .len = 2, .offset = 0 }, { .id = DNS_QUERY_CLASS, .len = 2, .offset = 2 }, }; static void dns_query_header_init(struct proto_hdr *hdr) { proto_header_fields_add(hdr, dns_query_fields, array_size(dns_query_fields)); } static void dns_query_header_finish(struct proto_hdr *hdr) { proto_hdr_field_set_default_string(hdr, DNS_QUERY_NAME, "www.netsniff-ng.com"); proto_hdr_field_set_default_be16(hdr, DNS_QUERY_CLASS, 1); proto_hdr_field_set_default_be16(hdr, DNS_QUERY_TYPE, 1); } static const struct proto_ops dns_proto_query_ops = { .header_init = dns_query_header_init, .header_finish = dns_query_header_finish, }; static struct proto_field dns_rrecord_fields[] = { { .id = DNS_RRECORD_NAME, .len = 0, .offset = 0 }, { .id = DNS_RRECORD_TYPE, .len = 2, .offset = 0 }, { .id = DNS_RRECORD_CLASS, .len = 2, .offset = 2 }, { .id = DNS_RRECORD_TTL, .len = 4, .offset = 4 }, { .id = DNS_RRECORD_LEN, .len = 2, .offset = 8 }, { .id = DNS_RRECORD_DATA, .len = 0, .offset = 10 }, }; static void dns_rrecord_header_init(struct proto_hdr *hdr) { proto_header_fields_add(hdr, dns_rrecord_fields, array_size(dns_rrecord_fields)); } static void dns_rrecord_header_finish(struct proto_hdr *hdr) { struct proto_field *data = proto_hdr_field_by_id(hdr, DNS_RRECORD_DATA); proto_hdr_field_set_default_be32(hdr, DNS_RRECORD_TTL, 1); proto_hdr_field_set_default_be16(hdr, DNS_RRECORD_CLASS, 1); proto_hdr_field_set_default_be16(hdr, DNS_RRECORD_LEN, data->len); } static const struct proto_ops dns_proto_rrecord_ops = { .header_init = dns_rrecord_header_init, .header_finish = dns_rrecord_header_finish, }; static void dns_header_init(struct proto_hdr *hdr) { proto_lower_default_add(hdr, PROTO_UDP); proto_header_fields_add(hdr, dns_fields, array_size(dns_fields)); } static void dns_sort_headers(struct proto_hdr *hdr, uint32_t id, int index) { int i; for (i = index; i < hdr->sub_headers_count; i++) { struct proto_hdr *sub_hdr = hdr->sub_headers[i]; if (sub_hdr->id == id && sub_hdr->index != index) { proto_hdr_move_sub_header(hdr, sub_hdr, hdr->sub_headers[index]); index++; } } } static void dns_header_finish(struct proto_hdr *hdr) { size_t ar_count = 0; size_t ns_count = 0; size_t qd_count = 0; size_t an_count = 0; int i; for (i = 0; i < hdr->sub_headers_count; i++) { struct proto_hdr *sub_hdr = hdr->sub_headers[i]; switch (sub_hdr->id) { case DNS_QUERY_HDR: qd_count++; break; case DNS_ANSWER_HDR: an_count++; break; case DNS_AUTH_HDR: ns_count++; break; case DNS_ADD_HDR: ar_count++; break; } } dns_sort_headers(hdr, DNS_QUERY_HDR, 0); dns_sort_headers(hdr, DNS_ANSWER_HDR, qd_count); dns_sort_headers(hdr, DNS_AUTH_HDR, qd_count + an_count); dns_sort_headers(hdr, DNS_ADD_HDR, qd_count + an_count + ns_count); proto_hdr_field_set_default_be16(hdr, DNS_QD_COUNT, qd_count); proto_hdr_field_set_default_be16(hdr, DNS_AN_COUNT, an_count); proto_hdr_field_set_default_be16(hdr, DNS_NS_COUNT, ns_count); proto_hdr_field_set_default_be16(hdr, DNS_AR_COUNT, ar_count); if (an_count) proto_hdr_field_set_default_be16(hdr, DNS_QR, 1); } static void dns_push_sub_header(struct proto_hdr *hdr, struct proto_hdr *sub_hdr) { switch (sub_hdr->id) { case DNS_QUERY_HDR: sub_hdr->ops = &dns_proto_query_ops; break; case DNS_ANSWER_HDR: case DNS_AUTH_HDR: case DNS_ADD_HDR: sub_hdr->ops = &dns_proto_rrecord_ops; break; default: bug(); } } static const struct proto_ops dns_proto_ops = { .id = PROTO_DNS, .layer = PROTO_L7, .header_init = dns_header_init, .header_finish = dns_header_finish, .push_sub_header = dns_push_sub_header, }; void protos_l7_init(void) { proto_ops_register(&dns_proto_ops); } amount of required memory. This provides an order of the set representation scalability in terms of memory. The size field is still left in place so use this if the userspace provides no explicit number of elements, so we cannot calculate the real memory that this set needs. This also helps us break ties in the set backend selection routine, eg. two backend implementations provide the same performance. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> 2017-02-08netfilter: nf_tables: rename struct nft_set_estimate class fieldPablo Neira Ayuso4-10/+10 Use lookup as field name instead, to prepare the introduction of the memory class in a follow up patch. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> 2017-02-08netfilter: nf_tables: add flush field to struct nft_set_iterPablo Neira Ayuso2-0/+5 This provides context to walk callback iterator, thus, we know if the walk happens from the set flush path. This is required by the new bitmap set type coming in a follow up patch which has no real struct nft_set_ext, so it has to allocate it based on the two bit compact element representation. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> 2017-02-08netfilter: nf_tables: rename deactivate_one() to flush()Pablo Neira Ayuso4-13/+13 Although semantics are similar to deactivate() with no implicit element lookup, this is only called from the set flush path, so better rename this to flush(). Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> 2017-02-08netfilter: nf_tables: use struct nft_set_iter in set element flushPablo Neira Ayuso1-7/+5 Instead of struct nft_set_dump_args, remove unnecessary wrapper structure. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> 2017-02-08netfilter: nf_tables: pass netns to set->ops->remove()Pablo Neira Ayuso4-6/+9 This new parameter is required by the new bitmap set type that comes in a follow up patch. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> 2017-02-08netfilter: nft_exthdr: Add support for existence checkPhil Sutter2-2/+26 If NFT_EXTHDR_F_PRESENT is set, exthdr will not copy any header field data into *dest, but instead set it to 1 if the header is found and 0 otherwise. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> 2017-02-03net: skb_needs_check() accepts CHECKSUM_NONE for txEric Dumazet1-3/+4 My recent change missed fact that UFO would perform a complete UDP checksum before segmenting in frags. In this case skb->ip_summed is set to CHECKSUM_NONE. We need to add this valid case to skb_needs_check() Fixes: b2504a5dbef3 ("net: reduce skb_warn_bad_offload() noise") Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Willem de Bruijn <willemb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net> 2017-02-03net: remove support for per driver ndo_busy_poll()Eric Dumazet4-21/+0 We added generic support for busy polling in NAPI layer in linux-4.5 No network driver uses ndo_busy_poll() anymore, we can get rid of the pointer in struct net_device_ops, and its use in sk_busy_loop() Saves NETIF_F_BUSY_POLL features bit. Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net> 2017-02-03enic: Remove local ndo_busy_poll() implementation.David S. Miller