On 2017-01-30 at 09:33:29 +0100, Vadim Kochan <vadi...@gmail.com> wrote:
> Add trafgen_l7.c module with DNS proto header generation with
> support of filling DNS query/answer/authority/additional sections
> as sub headers.
> 
> Introcuded new concept as 'sub header' which is needed to easy handle
> DNS sections which might be added on-demand, and to simplify using
> sub-header as regular header with a fields, offset, etc. There is a
> parent header which contains array of pointers of sub-headers, and the
> array is ordered as they are located in the parent header. The
> sub-headers mostly encapsulated by the parent header which 'knows'
> the semantic of them. The new proto_hdr->push_sub_header(...) callback
> was added to tell the parent header to push the sub-header's fields,
> sub-header also may have proto_ops which must be filled by the parent.
> This sub-header concept might be used in the future if it will be needed
> to support DHCP, WLAN headers.
> 
> There are 4 kinds of DNS sub-headers - query, answer, authority,
> additional. 'id' of each sub-header is used to only differentiate these
> types of sections. These sections have strict order inside DNS header,
> and there was added the proto_hdr_move_sub_header(...) to sort them in
> required order.

Might be a bit of a naive question: But wouldn't it be possible to
enforce the sub-header order through the parser (i.e. only allow
trafgen scripts which specify the respective sections in the right
order? This would safe us from doing the whole header sorting/moving
dance which looks a bit sacry to me (memmove of payload especially).

A few minor comments inline below.

> Actually there are only 2 proto_hdr's which describes 4 DNS sections -
> query & rrecord, because rrecord covers another 3 - answer, auhority,
> additional which have the same layout.
> 
> Signed-off-by: Vadim Kochan <vadi...@gmail.com>
> ---
>  trafgen/Makefile |   1 +
>  trafgen_l4.c     |  32 ++++++++++
>  trafgen_l7.c     | 175 
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  trafgen_l7.h     |  45 ++++++++++++++
>  trafgen_proto.c  | 128 ++++++++++++++++++++++++++++++++++++++++
>  trafgen_proto.h  |  18 +++++-
>  6 files changed, 398 insertions(+), 1 deletion(-)
>  create mode 100644 trafgen_l7.c
>  create mode 100644 trafgen_l7.h
> 
> diff --git a/trafgen/Makefile b/trafgen/Makefile
> index 876ed93..95a31e0 100644
> --- a/trafgen/Makefile
> +++ b/trafgen/Makefile
> @@ -25,6 +25,7 @@ trafgen-objs =      xmalloc.o \
>               trafgen_l2.o \
>               trafgen_l3.o \
>               trafgen_l4.o \
> +             trafgen_l7.o \
>               trafgen_lexer.yy.o \
>               trafgen_parser.tab.o \
>               trafgen.o
> diff --git a/trafgen_l4.c b/trafgen_l4.c
> index 5a694b3..198d622 100644
> --- a/trafgen_l4.c
> +++ b/trafgen_l4.c
> @@ -80,6 +80,21 @@ static void udp_packet_finish(struct proto_hdr *hdr)
>       udp_csum_update(hdr);
>  }
>  
> +static void udp_set_next_proto(struct proto_hdr *hdr, enum proto_id pid)
> +{
> +     uint16_t dport;
> +
> +     switch (pid) {
> +     case PROTO_DNS:
> +             dport = 53;
> +             break;
> +     default:
> +             bug();
> +     }
> +
> +     proto_hdr_field_set_default_be16(hdr, UDP_DPORT, dport);
> +}
> +
>  static const struct proto_ops udp_proto_ops = {
>       .id             = PROTO_UDP,
>       .layer          = PROTO_L4,
> @@ -87,6 +102,7 @@ static const struct proto_ops udp_proto_ops = {
>       .packet_update  = udp_csum_update,
>       .packet_finish  = udp_packet_finish,
>       .field_changed  = udp_field_changed,
> +     .set_next_proto = udp_set_next_proto,
>  };
>  
>  static struct proto_field tcp_fields[] = {
> @@ -160,6 +176,21 @@ static void tcp_csum_update(struct proto_hdr *hdr)
>       hdr->is_csum_valid = true;
>  }
>  
> +static void tcp_set_next_proto(struct proto_hdr *hdr, enum proto_id pid)
> +{
> +     uint16_t dport;
> +
> +     switch (pid) {
> +     case PROTO_DNS:
> +             dport = 53;
> +             break;
> +     default:
> +             bug();
> +     }
> +
> +     proto_hdr_field_set_default_be16(hdr, TCP_DPORT, dport);
> +}
> +
>  static const struct proto_ops tcp_proto_ops = {
>       .id             = PROTO_TCP,
>       .layer          = PROTO_L4,
> @@ -167,6 +198,7 @@ static const struct proto_ops tcp_proto_ops = {
>       .packet_update  = tcp_csum_update,
>       .packet_finish  = tcp_csum_update,
>       .field_changed  = tcp_field_changed,
> +     .set_next_proto = tcp_set_next_proto,
>  };
>  
>  static struct proto_field icmpv4_fields[] = {
> diff --git a/trafgen_l7.c b/trafgen_l7.c
> new file mode 100644
> index 0000000..1e82ccb
> --- /dev/null
> +++ b/trafgen_l7.c
> @@ -0,0 +1,175 @@
> +/*
> + * netsniff-ng - the packet sniffing beast
> + * Subject to the GPL, version 2.
> + */
> +
> +#include <string.h>
> +
> +#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)

You use an uint32_t id here but changed proto_hdr->i to and int. Why?

In general, please try to be consistent with types and give reasons when
changing them.

> +{
> +     int i;

i and index should be type size_t as hdr->headers_count is size_t

> +
> +     for (i = index; i < hdr->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)
> +{
> +     uint16_t ar_count = 0;
> +     uint16_t ns_count = 0;
> +     uint16_t qd_count = 0;
> +     uint16_t an_count = 0;
> +     int i;

size_t

> +
> +     for (i = 0; i < hdr->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;
> +             }

No empty lines after break please.

> +     }
> +
> +     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();
> +     }

No empty lines after break please.

> +}
> +
> +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);
> +}
> diff --git a/trafgen_l7.h b/trafgen_l7.h
> new file mode 100644
> index 0000000..cf19fa4
> --- /dev/null
> +++ b/trafgen_l7.h
> @@ -0,0 +1,45 @@
> +#ifndef TRAFGEN_L7_H
> +#define TRAFGEN_L7_H
> +
> +enum dns_field {
> +     DNS_ID,
> +     DNS_QR,
> +     DNS_OPCODE,
> +     DNS_AA,
> +     DNS_TC,
> +     DNS_RD,
> +     DNS_RA,
> +     DNS_ZERO,
> +     DNS_RCODE,
> +     DNS_QD_COUNT,
> +     DNS_AN_COUNT,
> +     DNS_NS_COUNT,
> +     DNS_AR_COUNT,
> +};
> +
> +enum dns_header {
> +     DNS_UNDEF_HDR,
> +     DNS_QUERY_HDR,
> +     DNS_ANSWER_HDR,
> +     DNS_AUTH_HDR,
> +     DNS_ADD_HDR,
> +};
> +
> +enum dns_query_field {
> +     DNS_QUERY_NAME,
> +     DNS_QUERY_TYPE,
> +     DNS_QUERY_CLASS,
> +};
> +
> +enum dns_rrecord_field {
> +     DNS_RRECORD_NAME,
> +     DNS_RRECORD_TYPE,
> +     DNS_RRECORD_CLASS,
> +     DNS_RRECORD_TTL,
> +     DNS_RRECORD_LEN,
> +     DNS_RRECORD_DATA,
> +};
> +
> +extern void protos_l7_init(void);
> +
> +#endif /* TRAFGEN_L7_H */
> diff --git a/trafgen_proto.c b/trafgen_proto.c
> index e300e7f..1fa2802 100644
> --- a/trafgen_proto.c
> +++ b/trafgen_proto.c
> @@ -14,6 +14,7 @@
>  #include "trafgen_l2.h"
>  #include "trafgen_l3.h"
>  #include "trafgen_l4.h"
> +#include "trafgen_l7.h"
>  #include "trafgen_proto.h"
>  
>  #define field_shift_and_mask(f, v) (((v) << (f)->shift) & \
> @@ -157,6 +158,112 @@ void proto_header_finish(struct proto_hdr *hdr)
>               hdr->ops->header_finish(hdr);
>  }
>  
> +struct proto_hdr *proto_hdr_push_sub_header(struct proto_hdr *hdr, int id)
> +{
> +     struct proto_hdr *sub_hdr;
> +
> +     sub_hdr = xzmalloc(sizeof(struct proto_hdr));
> +     sub_hdr->index = hdr->headers_count;
> +     sub_hdr->parent = hdr;
> +     sub_hdr->id = id;
> +
> +     hdr->headers_count++;
> +     hdr->sub_headers = xrealloc(hdr->sub_headers,
> +                                 hdr->headers_count * sizeof(struct 
> proto_hdr *));
> +
> +     hdr->sub_headers[hdr->headers_count - 1] = sub_hdr;
> +
> +     if (hdr->ops->push_sub_header)
> +             hdr->ops->push_sub_header(hdr, sub_hdr);
> +
> +     if (sub_hdr->ops->header_init)
> +             sub_hdr->ops->header_init(sub_hdr);
> +
> +     return sub_hdr;
> +}
> +
> +static void __proto_hdr_set_offset(struct proto_hdr *hdr, uint16_t 
> pkt_offset)
> +{
> +     int i;

size_t

> +
> +     hdr->pkt_offset = pkt_offset;
> +
> +     for (i = 0; i < hdr->fields_count; i++) {
> +             struct proto_field *f = &hdr->fields[i];
> +
> +             f->pkt_offset = pkt_offset + f->offset;
> +     }
> +}
> +
> +void proto_hdr_move_sub_header(struct proto_hdr *hdr, struct proto_hdr *from,
> +                            struct proto_hdr *to)
> +{
> +     struct proto_hdr *src_hdr, *dst_hdr, *tmp;
> +     uint8_t *src_ptr, *dst_ptr;
> +     uint16_t to_pkt_offset;
> +     uint16_t to_index;
> +     uint16_t pkt_offset;
> +     int idx_shift;
> +     size_t len = 0;
> +     uint8_t *buf;
> +     int i;
> +
> +     if (hdr->headers_count < 2)
> +             return;
> +     if (from->index == to->index)
> +             return;
> +
> +     buf = xzmalloc(from->len);
> +     memcpy(buf, proto_header_ptr(from), from->len);

Pleae use xmemdupz()

> +
> +     to_pkt_offset = to->pkt_offset;
> +     to_index = to->index;
> +
> +     if (from->index < to->index) {
> +             src_hdr = hdr->sub_headers[from->index + 1];
> +             dst_hdr = to;
> +
> +             src_ptr = proto_header_ptr(src_hdr);
> +             dst_ptr = proto_header_ptr(from);
> +             len = (to->pkt_offset + to->len) - src_hdr->pkt_offset;
> +
> +             pkt_offset = from->pkt_offset;
> +             idx_shift = 1;
> +     } else {
> +             src_hdr = to;
> +             dst_hdr = hdr->sub_headers[from->index - 1];
> +
> +             src_ptr = proto_header_ptr(src_hdr);
> +             dst_ptr = src_ptr + from->len;
> +             len = from->pkt_offset - to->pkt_offset;
> +
> +             pkt_offset = to->pkt_offset + from->len;
> +             idx_shift = -1;
> +     }
> +
> +     hdr->sub_headers[from->index] = to;
> +     hdr->sub_headers[to->index] = from;
> +
> +     for (i = src_hdr->index; i <= dst_hdr->index; i++) {
> +             tmp = hdr->sub_headers[i];
> +
> +             __proto_hdr_set_offset(tmp, pkt_offset);
> +             pkt_offset += tmp->len;
> +     }
> +
> +     for (i = src_hdr->index; i <= dst_hdr->index; i++)
> +             hdr->sub_headers[i]->index = i + idx_shift;
> +
> +     memmove(dst_ptr, src_ptr, len);
> +
> +     from->pkt_offset = to_pkt_offset;
> +     from->index = to_index;
> +
> +     memcpy(proto_header_ptr(from), buf, from->len);
> +
> +     xfree(buf);
> +}
> +
>  struct proto_hdr *proto_lower_default_add(struct proto_hdr *upper,
>                                         enum proto_id pid)
>  {
> @@ -481,6 +588,16 @@ void proto_hdr_field_set_default_dev_ipv6(struct 
> proto_hdr *hdr, uint32_t fid)
>       __proto_hdr_field_set_dev_ipv6(hdr, fid, true);
>  }
>  
> +void proto_hdr_field_set_string(struct proto_hdr *hdr, uint32_t fid, const 
> char *str)
> +{
> +     proto_hdr_field_set_bytes(hdr, fid, (uint8_t *)str, strlen(str) + 1);
> +}
> +
> +void proto_hdr_field_set_default_string(struct proto_hdr *hdr, uint32_t fid, 
> const char *str)
> +{
> +     proto_hdr_field_set_default_bytes(hdr, fid, (uint8_t *)str, strlen(str) 
> + 1);
> +}
> +
>  void proto_field_set_u8(struct proto_field *field, uint8_t val)
>  {
>       __proto_field_set_bytes(field, &val, 1, false, false);
> @@ -532,6 +649,16 @@ void proto_field_set_bytes(struct proto_field *field, 
> const uint8_t *bytes, size
>       __proto_field_set_bytes(field, bytes, len, false, false);
>  }
>  
> +void proto_field_set_string(struct proto_field *field, const char *str)
> +{
> +     proto_field_set_bytes(field, (uint8_t *)str, strlen(str) + 1);
> +}
> +
> +void proto_field_set_default_string(struct proto_field *field, const char 
> *str)
> +{
> +     __proto_field_set_bytes(field, (uint8_t *)str, strlen(str) + 1, true, 
> false);
> +}
> +
>  void protos_init(const char *dev)
>  {
>       ctx.dev = dev;
> @@ -539,6 +666,7 @@ void protos_init(const char *dev)
>       protos_l2_init();
>       protos_l3_init();
>       protos_l4_init();
> +     protos_l7_init();
>  }
>  
>  void proto_packet_update(uint32_t idx)
> diff --git a/trafgen_proto.h b/trafgen_proto.h
> index d9a6a24..8b1d900 100644
> --- a/trafgen_proto.h
> +++ b/trafgen_proto.h
> @@ -19,6 +19,7 @@ enum proto_id {
>       PROTO_ICMP6,
>       PROTO_UDP,
>       PROTO_TCP,
> +     PROTO_DNS,
>       __PROTO_MAX,
>  };
>  
> @@ -27,6 +28,7 @@ enum proto_layer {
>       PROTO_L2,
>       PROTO_L3,
>       PROTO_L4,
> +     PROTO_L7,
>  };
>  
>  struct proto_field;
> @@ -38,6 +40,7 @@ struct proto_ops {
>  
>       void (*header_init)(struct proto_hdr *hdr);
>       void (*header_finish)(struct proto_hdr *hdr);
> +     void (*push_sub_header)(struct proto_hdr *hdr, struct proto_hdr 
> *sub_hdr);
>       void (*field_changed)(struct proto_field *field);
>       void (*packet_finish)(struct proto_hdr *hdr);
>       void (*packet_update)(struct proto_hdr *hdr);
> @@ -46,12 +49,16 @@ struct proto_ops {
>  
>  struct proto_hdr {
>       const struct proto_ops *ops;
> +     struct proto_hdr *parent;
> +     struct proto_hdr **sub_headers;
> +     uint32_t headers_count;

Please rename to sub_headers_count for better grep-ability and
distinction from packet->headers_count

>       uint16_t pkt_offset;
>       uint32_t pkt_id;
> -     uint32_t index;
> +     int index;

As mentioned above: Why the type change?

>       struct proto_field *fields;
>       size_t fields_count;
>       bool is_csum_valid;
> +     uint32_t id;
>       size_t len;
>  };
>  
> @@ -95,6 +102,10 @@ extern void proto_header_finish(struct proto_hdr *hdr);
>  extern void proto_packet_finish(void);
>  extern void proto_packet_update(uint32_t idx);
>  
> +extern struct proto_hdr *proto_hdr_push_sub_header(struct proto_hdr *hdr, 
> int id);
> +extern void proto_hdr_move_sub_header(struct proto_hdr *hdr, struct 
> proto_hdr *from,
> +                                   struct proto_hdr *to);
> +
>  extern struct proto_hdr *proto_lower_default_add(struct proto_hdr *hdr,
>                                                enum proto_id pid);
>  
> @@ -142,6 +153,9 @@ extern void proto_hdr_field_set_default_dev_ipv4(struct 
> proto_hdr *hdr, uint32_t
>  extern void proto_hdr_field_set_dev_ipv6(struct proto_hdr *hdr, uint32_t 
> fid);
>  extern void proto_hdr_field_set_default_dev_ipv6(struct proto_hdr *hdr, 
> uint32_t fid);
>  
> +extern void proto_hdr_field_set_string(struct proto_hdr *hdr, uint32_t fid, 
> const char *str);
> +extern void proto_hdr_field_set_default_string(struct proto_hdr *hdr, 
> uint32_t fid, const char *str);
> +
>  extern void proto_field_dyn_apply(struct proto_field *field);
>  
>  extern struct proto_field *proto_hdr_field_by_id(struct proto_hdr *hdr, 
> uint32_t fid);
> @@ -156,6 +170,8 @@ extern uint32_t proto_field_get_u32(struct proto_field 
> *field);
>  extern void proto_field_set_be16(struct proto_field *field, uint16_t val);
>  extern void proto_field_set_be32(struct proto_field *field, uint32_t val);
>  extern void proto_field_set_bytes(struct proto_field *field, const uint8_t 
> *bytes, size_t len);
> +extern void proto_field_set_string(struct proto_field *field, const char 
> *str);
> +extern void proto_field_set_default_string(struct proto_field *field, const 
> char *str);
>  
>  extern void proto_field_func_add(struct proto_field *field,
>                                struct proto_field_func *func);
> -- 
> 2.11.0
> 

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to