[netsniff-ng] Re: about trafgen configuration file dinc question

2019-07-24 Thread Vadim Kochan
Hi,

On Wednesday, July 3, 2019 at 9:51:18 AM UTC+3, 刘伟灿 wrote:
>
> hi,i'm from china.
>
> In my trafgen configuration file, i want to add runtime counter(8 
> bytes).dinc only support 1 byte.
>
> what can i do for this?
>
> thanks regrads!
>
> Weican Liu
>
>
>
Looks like it needs to be implemented.

Regards,
Vadim Kochan
 

-- 
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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/netsniff-ng/e04a3ca0-36bf-4873-94f0-c0ebe183bac5%40googlegroups.com.


Re: [netsniff-ng] Trafgen & mz

2018-04-13 Thread Vadim Kochan
On Fri, Apr 13, 2018 at 8:51 AM, jack scholte <jack.scho...@gmail.com>
wrote:

>
> Hi all,
>
> Great tools but about:
>
> Trafgen, with -b Option i.e. 100 Mbps results in microbursts. Thus a lot
> of packets with a very small intergap (us) and than some msec nothing.
> While testing a shaping policy, the queue couldn’t handle the microbursts.
> Fortunate I was able to use the intergap Option instead of bit rate.
>
> Mausezahn: I was not able to use -a with the -b -A -B Option. Also a L3
> dsfield would-be Nice.
>
> Best regards
>
> Jack
>
> --
> 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.
>

Hi Jack!

Thank you for suggestions and report! Regarding trafgen -b option you mean
that is would be better
if the packets delay was better normalized regarding the rate ?

Regards,
Vadim Kochan

-- 
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.


[netsniff-ng] Re: [PATCH] flowtop: Fix use-after-free on filter reload

2017-12-29 Thread Vadim Kochan
On Tue, Dec 19, 2017 at 12:30 PM, Tobias Klauser <tklau...@distanz.ch>
wrote:

> On 2017-12-19 at 11:24:40 +0100, Vadim Kochan <vadi...@gmail.com> wrote:
> > May it possible that you tried flowtop compiled without the fix ?
>
> No, I made sure to have the patch applied and recompiled flowtop. I can
> still quite reliably reproduce the issue and flowtop sometimes even
> segfaults on startup before displaying anything.
>
> > On Tue, Dec 19, 2017 at 12:18 PM, Vadim Kochan <vadi...@gmail.com>
> wrote:
> >
> > > Thats really strange, because before this patch I really easy triggered
> > > the issue, but
> > > now I cant.
> > >
> > > On Tue, Dec 19, 2017 at 11:12 AM, Tobias Klauser <tklau...@distanz.ch>
> > > wrote:
> > >
> > >> On 2017-12-18 at 23:38:18 +0100, Vadim Kochan <vadi...@gmail.com>
> wrote:
> > >> > There is missing logic which removes flown entry from
> > >> > related proc's entry while destroying global flows list on
> > >> > filter reloading, hence add common __flow_list_del_entry which
> > >> > handles this logic for both cases - when ct destroyed or filter
> > >> > changed.
> > >> >
> > >> > This is a 2nd fix for issue #183.
> > >>
> > >> Thanks for the patch. While it is certainly correct, it unfortunately
> > >> still doesn't fix #183 properly. I can still trigger a segfault by
> > >> repeatedly enabling/disabling TCP, UDP and ICMP flows ('T', 'U' or 'I'
> > >> key).
> > >>
> > >
> > >
>

Hi Tobias,

Looks like https://github.com/netsniff-ng/netsniff-ng/issues/183
is not reproducible, do you still see issues with flowtop ?

Regards,
Vadim Kochan

-- 
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.


[netsniff-ng] Re: [PATCH] flowtop: Fix use-after-free on filter reload

2017-12-19 Thread Vadim Kochan
May it possible that you tried flowtop compiled without the fix ?

On Tue, Dec 19, 2017 at 12:18 PM, Vadim Kochan <vadi...@gmail.com> wrote:

> Thats really strange, because before this patch I really easy triggered
> the issue, but
> now I cant.
>
> On Tue, Dec 19, 2017 at 11:12 AM, Tobias Klauser <tklau...@distanz.ch>
> wrote:
>
>> On 2017-12-18 at 23:38:18 +0100, Vadim Kochan <vadi...@gmail.com> wrote:
>> > There is missing logic which removes flown entry from
>> > related proc's entry while destroying global flows list on
>> > filter reloading, hence add common __flow_list_del_entry which
>> > handles this logic for both cases - when ct destroyed or filter
>> > changed.
>> >
>> > This is a 2nd fix for issue #183.
>>
>> Thanks for the patch. While it is certainly correct, it unfortunately
>> still doesn't fix #183 properly. I can still trigger a segfault by
>> repeatedly enabling/disabling TCP, UDP and ICMP flows ('T', 'U' or 'I'
>> key).
>>
>
>

-- 
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.


[netsniff-ng] Re: [PATCH] flowtop: Fix use-after-free on filter reload

2017-12-19 Thread Vadim Kochan
Thats really strange, because before this patch I really easy triggered the
issue, but
now I cant.

On Tue, Dec 19, 2017 at 11:12 AM, Tobias Klauser <tklau...@distanz.ch>
wrote:

> On 2017-12-18 at 23:38:18 +0100, Vadim Kochan <vadi...@gmail.com> wrote:
> > There is missing logic which removes flown entry from
> > related proc's entry while destroying global flows list on
> > filter reloading, hence add common __flow_list_del_entry which
> > handles this logic for both cases - when ct destroyed or filter
> > changed.
> >
> > This is a 2nd fix for issue #183.
>
> Thanks for the patch. While it is certainly correct, it unfortunately
> still doesn't fix #183 properly. I can still trigger a segfault by
> repeatedly enabling/disabling TCP, UDP and ICMP flows ('T', 'U' or 'I'
> key).
>

-- 
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.


[netsniff-ng] [PATCH] flowtop: Fix use-after-free on filter reload

2017-12-18 Thread Vadim Kochan
There is missing logic which removes flown entry from
related proc's entry while destroying global flows list on
filter reloading, hence add common __flow_list_del_entry which
handles this logic for both cases - when ct destroyed or filter
changed.

This is a 2nd fix for issue #183.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 flowtop.c | 30 --
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/flowtop.c b/flowtop.c
index 8b69d65..7de4d11 100644
--- a/flowtop.c
+++ b/flowtop.c
@@ -470,20 +470,24 @@ static struct flow_entry *flow_list_find_id(struct 
flow_list *fl, uint32_t id)
return NULL;
 }
 
+static void __flow_list_del_entry(struct flow_list *fl, struct flow_entry *n)
+{
+   if (n->proc) {
+   cds_list_del_rcu(>proc_head);
+   n->proc->flows_count--;
+   }
+
+   cds_list_del_rcu(>entry);
+   call_rcu(>rcu, flow_entry_xfree_rcu);
+}
+
 static int flow_list_del_entry(struct flow_list *fl, const struct nf_conntrack 
*ct)
 {
struct flow_entry *n;
 
n = flow_list_find_id(fl, nfct_get_attr_u32(ct, ATTR_ID));
-   if (n) {
-   if (n->proc) {
-   cds_list_del_rcu(>proc_head);
-   n->proc->flows_count--;
-   }
-
-   cds_list_del_rcu(>entry);
-   call_rcu(>rcu, flow_entry_xfree_rcu);
-   }
+   if (n)
+   __flow_list_del_entry(fl, n);
 
return NFCT_CB_CONTINUE;
 }
@@ -492,10 +496,8 @@ static void flow_list_destroy(struct flow_list *fl)
 {
struct flow_entry *n, *tmp;
 
-   cds_list_for_each_entry_safe(n, tmp, >head, entry) {
-   cds_list_del_rcu(>entry);
-   call_rcu(>rcu, flow_entry_xfree_rcu);
-   }
+   cds_list_for_each_entry_safe(n, tmp, >head, entry)
+   __flow_list_del_entry(fl, n);
 }
 
 static void proc_list_init(struct proc_list *proc_list)
@@ -562,7 +564,7 @@ static void flow_entry_find_process(struct flow_entry *n)
p->stat.bytes_dst += n->stat.bytes_dst;
p->flows_count++;
 
-   cds_list_add(>proc_head, >flows);
+   cds_list_add_rcu(>proc_head, >flows);
n->proc = p;
 }
 
-- 
2.14.1

-- 
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.


Re: [netsniff-ng] Re: Trafgen: Warning: Out of Memory

2017-12-18 Thread Vadim Kochan
Hi Chandra,

Sorry for the late response !

Would you please provide commands which did you use ?

Thanks!

On Tue, Dec 5, 2017 at 1:26 PM,  wrote:

> while running trafgen commands , i am getting segmentation fault (cpre
> dump).
>
> can someone please guide me to move further ?
>
> Thanks,
> Chandra
>
> --
> 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.
>

-- 
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.


[netsniff-ng] [PATCH] flowtop: Use RCU flow deletion from process entry

2017-12-17 Thread Vadim Kochan
Use cds_list_del_rcu for safer deletion flow from the process flow
list to prevent possible use-after-free by UI thread when it is
refreshing the processes.

It may fix the #183 issue.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 flowtop.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/flowtop.c b/flowtop.c
index 0a3c514..8b69d65 100644
--- a/flowtop.c
+++ b/flowtop.c
@@ -477,7 +477,7 @@ static int flow_list_del_entry(struct flow_list *fl, const 
struct nf_conntrack *
n = flow_list_find_id(fl, nfct_get_attr_u32(ct, ATTR_ID));
if (n) {
if (n->proc) {
-   cds_list_del(>proc_head);
+   cds_list_del_rcu(>proc_head);
n->proc->flows_count--;
}
 
-- 
2.14.1

-- 
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.


Re: [netsniff-ng] Re: [ANNOUNCE] Preparing for netsniff-ng release v0.6.4

2017-12-14 Thread Vadim Kochan
Hi Tobias,

Looks like its data-race issue, can't reproduce it yet, *BUT*, looking
into the code it looks like I missed to remove flow entry from the
proc_entry->flows
list while flow entry is removing & freeing from the global list, plz give
me few more days for testing & fixing
if its possible.

Regards,
Vadim Kochan

On Thu, Dec 14, 2017 at 2:47 PM, Tobias Klauser <tklau...@distanz.ch> wrote:

> On 2017-12-11 at 09:08:15 +0100, Tobias Klauser <tklau...@distanz.ch>
> wrote:
> > On 2017-12-08 at 18:30:24 +0100, Vadim Kochan <vadi...@gmail.com> wrote:
> > > Hi All,
> > >
> > > I just noticed there some bug reports, I will look on them on weekend,
> I
> > > assume it is better
> > > to wait with release unless isues will be fixed ?
> >
> > Yes, in particular https://github.com/netsniff-ng/netsniff-ng/issues/183
> > worries me a bit. Would be nice to get it fixed before the release. If
> > we're not able to find a fix within 2-3 days, I'd say we could still do
> > a release with the current state (as the bug already seems to be present
> > in 0.6.3 anyway) and do another release once we find a fix.
> >
> > Thanks for looking into this!
>
> Vadim, any progress? If not, I'd mention this as a known issue in the
> release notes for now and still go forward with the release (we can
> still do a point release if we find a fix for it soon).
>
> As for the release, I'd like to pull in PR 184 [1] which fixes an
> obvious bug.
>
> [1] https://github.com/netsniff-ng/netsniff-ng/pull/184
>
> Tobias
>

-- 
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.


Re: [netsniff-ng] Re: [ANNOUNCE] Preparing for netsniff-ng release v0.6.4

2017-12-08 Thread Vadim Kochan
Hi All,

I just noticed there some bug reports, I will look on them on weekend, I
assume it is better
to wait with release unless isues will be fixed ?

Regards,
Vadim

On Fri, Dec 8, 2017 at 6:57 PM, @mandarg  wrote:

> On Friday, October 20, 2017 at 9:29:28 AM UTC-4, Tobias Klauser wrote:
> > The final release is planned in two
> > weeks time. Afterwards the tree is open again for new features and more
> > experimental changes.
>
> Is there an estimated date for when the release will be tagged? Asking
> since I'm debating whether to separately pull some patches into my packaged
> version, or just wait for the tagged release.
>
>
> Thanks and regards,
> Mandar
>
> --
> 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.
>

-- 
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.


Re: [netsniff-ng] Re: Cannot get /GeoIP.dat.gz from mirrors!

2017-11-22 Thread Vadim Kochan
Hi Lupe,

Which version do you use ?

Regards,
Vadim Kochan

On Wed, Nov 22, 2017 at 8:43 PM, Lupe Villalpando <
lupe.villalpa...@yardi.com> wrote:

> this is the command i am running
>
> astraceroute -i eth0 -N -S -H netsniff-ng.org
>
>
> --
> *From:* Lupe Villalpando
> *Sent:* Wednesday, November 22, 2017 10:40:52 AM
> *To:* netsniff-ng@googlegroups.com
> *Subject:* Cannot get /GeoIP.dat.gz from mirrors!
>
>
> Hello I am trying to use this astraceroute for my script, but when i run
> it from the command line I get this error :
>
>
>
> Cannot get /GeoIP.dat.gz from mirrors!
>
> --
> 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.
>

-- 
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.


[netsniff-ng] Re: [PATCH] trafgen: fix packet socket initialization with multiple CPUs

2017-09-14 Thread Vadim Kochan
Thanks Paolo! Shame on me, I did not test it properly :(

On Wed, Sep 13, 2017 at 6:54 PM, Paolo Abeni  wrote:

> The commit 78c13b71e196 ("trafgen: Allow to generate packets
> to output pcap file") introduced a regression when output is
> a network device and multiple CPU are in use: the packet
> socket is created before fork() and thus the socket is shared
> among all the processes: all of them except the first will
> fail while setting the tx_ring.
>
> Fix it splitting the io open() helper in a create() op,
> called before forking, and the open() op called by each process.
>
> Fixes: 78c13b71e196 ("trafgen: Allow to generate packets to output pcap
> file")
> Signed-off-by: Paolo Abeni 
> ---
>  trafgen.c |  6 --
>  trafgen_dev.c | 21 +
>  trafgen_dev.h |  4 +++-
>  3 files changed, 20 insertions(+), 11 deletions(-)
>
> diff --git a/trafgen.c b/trafgen.c
> index 9b54399..9c5a9a6 100644
> --- a/trafgen.c
> +++ b/trafgen.c
> @@ -977,6 +977,7 @@ static void main_loop(struct ctx *ctx, char *confname,
> bool slow,
> fflush(stdout);
> }
>
> +   dev_io_open(ctx->dev_out);
> if (dev_io_is_netdev(ctx->dev_out) && ctx->qdisc_path == false)
> set_sock_qdisc_bypass(dev_io_fd_get(ctx->dev_out),
> ctx->verbose);
>
> @@ -1266,12 +1267,13 @@ int main(int argc, char **argv)
> xlockme();
>
> if (ctx.pcap_in) {
> -   ctx.dev_in = dev_io_open(ctx.pcap_in, DEV_IO_IN);
> +   ctx.dev_in = dev_io_create(ctx.pcap_in, DEV_IO_IN);
> if (!ctx.dev_in)
> panic("Failed to open input device\n");
> +   dev_io_open(ctx.dev_in);
> }
>
> -   ctx.dev_out = dev_io_open(ctx.device, DEV_IO_OUT);
> +   ctx.dev_out = dev_io_create(ctx.device, DEV_IO_OUT);
> if (!ctx.dev_out)
> panic("Failed to open output device\n");
>
> diff --git a/trafgen_dev.c b/trafgen_dev.c
> index f65442f..489da98 100644
> --- a/trafgen_dev.c
> +++ b/trafgen_dev.c
> @@ -242,10 +242,11 @@ static const struct dev_io_ops dev_cfg_ops = {
> .close = dev_cfg_close,
>  };
>
> -struct dev_io *dev_io_open(const char *name, enum dev_io_mode_t mode)
> +struct dev_io *dev_io_create(const char *name, enum dev_io_mode_t mode)
>  {
> struct dev_io *dev = xzmalloc(sizeof(struct dev_io));
>
> +   dev->mode = mode;
> if (strstr(name, ".pcap")) {
> dev->name = xstrdup(name);
> dev->ops = _pcap_ops;
> @@ -260,16 +261,20 @@ struct dev_io *dev_io_open(const char *name, enum
> dev_io_mode_t mode)
> return NULL;
> }
>
> -   if (dev->ops->open) {
> -   if (dev->ops->open(dev, name, mode)) {
> -   xfree(dev);
> -   return NULL;
> -   }
> -   }
> -
> return dev;
>  };
>
> +extern void dev_io_open(struct dev_io *dev)
> +{
> +   bug_on(!dev);
> +   bug_on(!dev->ops);
> +
> +   if (dev->ops->open)
> +   if (dev->ops->open(dev, dev->name, dev->mode))
> +   panic("Cannot open io %s mode %d\n", dev->name,
> + dev->mode);
> +}
> +
>  int dev_io_write(struct dev_io *dev, struct packet *pkt)
>  {
> bug_on(!dev);
> diff --git a/trafgen_dev.h b/trafgen_dev.h
> index 80086d7..bcb88f3 100644
> --- a/trafgen_dev.h
> +++ b/trafgen_dev.h
> @@ -24,6 +24,7 @@ struct dev_io {
> uint32_t pcap_magic;
> bool is_initialized;
> enum pcap_mode pcap_mode;
> +   enum dev_io_mode_t mode;
> size_t buf_len;
> uint8_t *buf;
>
> @@ -39,7 +40,8 @@ struct dev_io_ops {
> void(*close) (struct dev_io *dev);
>  };
>
> -extern struct dev_io *dev_io_open(const char *name, enum dev_io_mode_t
> mode);
> +extern struct dev_io *dev_io_create(const char *name, enum dev_io_mode_t
> mode);
> +extern void dev_io_open(struct dev_io *dev);
>  extern int dev_io_write(struct dev_io *dev, struct packet *pkt);
>  extern struct packet *dev_io_read(struct dev_io *dev);
>  extern int dev_io_ifindex_get(struct dev_io *dev);
> --
> 2.13.5
>
>

-- 
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.


[netsniff-ng] [PATCH v2 2/3] trafgen: dev_io: Change read/write to specify struct packet *

2017-07-29 Thread Vadim Kochan
Refactor dev_io_ops read & write to specify struct packet *,
it may simplify a bit a caller logic. And it allow to keep
required members within one struct packet object.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen.c| 25 -
 trafgen_conf.h   |  2 +-
 trafgen_dev.c| 48 +---
 trafgen_dev.h| 12 +++-
 trafgen_parser.y |  6 --
 5 files changed, 49 insertions(+), 44 deletions(-)

diff --git a/trafgen.c b/trafgen.c
index 207b680..97ac046 100644
--- a/trafgen.c
+++ b/trafgen.c
@@ -684,7 +684,7 @@ static void xmit_slowpath_or_die(struct ctx *ctx, unsigned 
int cpu, unsigned lon
while (likely(sigint == 0 && num > 0 && plen > 0)) {
packet_apply_dyn_elements(i);
 retry:
-   ret = dev_io_write(ctx->dev_out, packets[i].payload, 
packets[i].len);
+   ret = dev_io_write(ctx->dev_out, [i]);
if (unlikely(ret < 0)) {
if (errno == ENOBUFS) {
sched_yield();
@@ -937,27 +937,10 @@ static void xmit_packet_precheck(struct ctx *ctx, 
unsigned int cpu)
 
 static void pcap_load_packets(struct dev_io *dev)
 {
-   struct timespec tstamp;
-   size_t buf_len;
-   uint8_t *buf;
-   int pkt_len;
+   struct packet *pkt;
 
-   buf_len = round_up(1024 * 1024, RUNTIME_PAGE_SIZE);
-   buf = xmalloc_aligned(buf_len, CO_CACHE_LINE_SIZE);
-
-   while ((pkt_len = dev_io_read(dev, buf, buf_len, )) > 0) {
-   struct packet *pkt;
-
-   realloc_packet();
-
-   pkt = current_packet();
-   pkt->len = pkt_len;
-   pkt->payload = xzmalloc(pkt_len);
-   memcpy(pkt->payload, buf, pkt_len);
-   memcpy(>tstamp, , sizeof(tstamp));
-   }
-
-   free(buf);
+   while ((pkt = dev_io_read(dev)) != 0)
+   /* nothing to do */;
 }
 
 static void main_loop(struct ctx *ctx, char *confname, bool slow,
diff --git a/trafgen_conf.h b/trafgen_conf.h
index 2af830d..7e922fe 100644
--- a/trafgen_conf.h
+++ b/trafgen_conf.h
@@ -80,6 +80,6 @@ extern void set_fill(uint8_t val, size_t len);
 extern struct packet *current_packet(void);
 extern uint32_t current_packet_id(void);
 extern struct packet *packet_get(uint32_t id);
-extern void realloc_packet(void);
+extern struct packet *realloc_packet(void);
 
 #endif /* TRAFGEN_CONF */
diff --git a/trafgen_dev.c b/trafgen_dev.c
index d7f1cd5..d613cce 100644
--- a/trafgen_dev.c
+++ b/trafgen_dev.c
@@ -19,6 +19,7 @@
 #include "mac80211.h"
 #include "linktype.h"
 #include "trafgen_dev.h"
+#include "trafgen_conf.h"
 
 static int dev_pcap_open(struct dev_io *dev, const char *name, enum 
dev_io_mode_t mode)
 {
@@ -36,6 +37,8 @@ static int dev_pcap_open(struct dev_io *dev, const char 
*name, enum dev_io_mode_
}
 
dev->pcap_mode = PCAP_MODE_RD;
+   dev->buf_len = round_up(1024 * 1024, RUNTIME_PAGE_SIZE);
+   dev->buf = xmalloc_aligned(dev->buf_len, CO_CACHE_LINE_SIZE);
} else if (mode & DEV_IO_OUT) {
if (!strncmp("-", name, strlen("-"))) {
dev->fd = dup_or_die(fileno(stdout));
@@ -69,26 +72,35 @@ static int dev_pcap_open(struct dev_io *dev, const char 
*name, enum dev_io_mode_
return 0;
 }
 
-static int dev_pcap_read(struct dev_io *dev, uint8_t *buf, size_t len,
-struct timespec *tstamp)
+static struct packet *dev_pcap_read(struct dev_io *dev)
 {
+   size_t len = dev->buf_len;
+   uint8_t *buf = dev->buf;
pcap_pkthdr_t phdr;
+   struct packet *pkt;
size_t pkt_len;
 
if (dev->pcap_ops->read_pcap(dev->fd, , dev->pcap_magic, buf, len) 
<= 0)
-   return -1;
+   return NULL;
 
pkt_len = pcap_get_length(, dev->pcap_magic);
if (!pkt_len)
-   return -1;
+   return NULL;
 
-   pcap_get_tstamp(, dev->pcap_magic, tstamp);
+   pkt = realloc_packet();
 
-   return pkt_len;
+   pkt->len = pkt_len;
+   pkt->payload = xzmalloc(pkt_len);
+   memcpy(pkt->payload, buf, pkt_len);
+   pcap_get_tstamp(, dev->pcap_magic, >tstamp);
+
+   return pkt;
 }
 
-static int dev_pcap_write(struct dev_io *dev, const uint8_t *buf, size_t len)
+static int dev_pcap_write(struct dev_io *dev, const struct packet *pkt)
 {
+   uint8_t *buf = pkt->payload;
+   size_t len = pkt->len;
struct timeval time;
pcap_pkthdr_t phdr;
int ret;
@@ -130,8 +142,13 @@ static int dev_pcap_write(struct dev_io *dev, const 
uint8_t *buf, size_t len)
 
 static void dev_pcap_close(struct dev_io *dev)
 {
-   if (dev->pcap_mode == PCAP_MODE_WR)
+   if (dev-

[netsniff-ng] [PATCH v2 3/3] trafgen: Dump proto headers in *.cfg format

2017-07-29 Thread Vadim Kochan
Added trafgen_dump.c module which dumps headers from packet
in .cfg format. Packet is dumped if -o .cfg was specified,
it might be useful to specify *.pcap file as input and convert it
into .cfg file to edit proto fields in human readable format.

To make it possible several main changes were added:

1) packet id is embedded into struct packet.id, and
   it is updated on each realloc_packet()

2) Added new struct proto_hdr.get_next_proto callback
   to make possible apply fields of next header.

3) Added new dev_io ops for writting packets into .cfg file,
   to re-use common dev_io mechsnism for packets dumping.

Before dump the default ETH_PROTO fields are applied as first header and
then next proto_hdr is identified via .get_next_proto(...) callback.

Meanwhile only eth, arp, vlan, ip4, udp, & tcp protos can be dissected
into *.cfg format.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen.8|   4 +-
 trafgen.c|  54 ++--
 trafgen/Makefile |   1 +
 trafgen_conf.h   |   2 +
 trafgen_dev.c|  36 +++-
 trafgen_dev.h|   4 +-
 trafgen_dump.c   | 258 +++
 trafgen_dump.h   |   8 ++
 trafgen_l2.c |  33 +++
 trafgen_l3.c |  21 -
 trafgen_parser.y |   5 ++
 trafgen_proto.c  |  69 +--
 trafgen_proto.h  |   7 ++
 13 files changed, 460 insertions(+), 42 deletions(-)
 create mode 100644 trafgen_dump.c
 create mode 100644 trafgen_dump.h

diff --git a/trafgen.8 b/trafgen.8
index 67aaaf9..f720043 100644
--- a/trafgen.8
+++ b/trafgen.8
@@ -74,9 +74,9 @@ It is also possible to specify PCAP file with .pcap extension 
via -i,--in option
 by default packets will be sent at rate considering timestamp from PCAP file 
which
 might be reset via -b/-t options.
 .PP
-.SS -o <dev|pcap>, -d <dev|pcap>, --out <dev|pcap>, --dev <dev|pcap>
+.SS -o <dev|.pcap|.cfg>, -d <dev|.pcap|.cfg>, --out <dev|.pcap|.cfg>, --dev 
<dev|.pcap|.cfg>
 Defines the outgoing networking device such as eth0, wlan0 and others or
-a pcap file.
+a *.pcap or *.cfg file. Pcap and configuration files are identified by 
extension.
 .PP
 .SS -p, --cpp
 Pass the packet configuration to the C preprocessor before reading it into
diff --git a/trafgen.c b/trafgen.c
index 97ac046..9b54399 100644
--- a/trafgen.c
+++ b/trafgen.c
@@ -185,31 +185,31 @@ static void __noreturn help(void)
puts("http://www.netsniff-ng.org\n\n;
 "Usage: trafgen [options] [packet]\n"
 "Options:\n"
-"  -i|-c|--in|--conf   Packet configuration 
file/stdin\n"
-"  -o|-d|--out|--dev  Networking device i.e., eth0\n"
-"  -p|--cpp   Run packet config through C 
preprocessor\n"
-"  -D|--defineAdd macro/define for C 
preprocessor\n"
-"  -J|--jumbo-support Support 64KB super jumbo frames 
(def: 2048B)\n"
-"  -R|--rfraw Inject raw 802.11 frames\n"
-"  -s|--smoke-test  Probe if machine survived 
fuzz-tested packet\n"
-"  -n|--num Number of packets until exit 
(def: 0)\n"
-"  -r|--rand  Randomize packet selection (def: 
round robin)\n"
-"  -P|--cpusSpecify number of forks(<= CPUs) 
(def: #CPUs)\n"
-"  -t|--gap Set approx. interpacket gap 
(s/ms/us/ns, def: us)\n"
-"  -b|--rateSend traffic at specified rate 
(pps/B/kB/MB/GB/kbit/Mbit/Gbit/KiB/MiB/GiB)\n"
-"  -S|--ring-size   Manually set mmap size 
(KiB/MiB/GiB)\n"
-"  -E|--seedManually set srand(3) seed\n"
-"  -u|--user  Drop privileges and change to 
userid\n"
-"  -g|--groupDrop privileges and change to 
groupid\n"
-"  -H|--prio-high Make this high priority 
process\n"
-"  -A|--no-sock-mem   Don't tune core socket memory\n"
-"  -Q|--notouch-irq   Do not touch IRQ CPU affinity of 
NIC\n"
-"  -q|--qdisc-pathEnable qdisc kernel path 
(default off since 3.14)\n"
-"  -V|--verbose   Be more verbose\n"
-"  -C|--no-cpu-stats  Do not print CPU time statistics 
on exit\n"
-"  -v|--version   Show version and exit\n"
-"  -e|--example   Show built-in packet config 
example\n"
-"  -h|--help  Guess what?!\n\n"
+   

[netsniff-ng] [PATCH 0/3] trafgen: Add dump of proto headers into *.cfg format

2017-07-29 Thread Vadim Kochan
Added trafgen_dump.c module which dumps headers from packet
in .cfg format. Packet is dumped if -o .cfg was specified,
it might be useful to specify *.pcap file as input and convert it
into .cfg file to edit proto fields in human readable format.

To make it possible several main changes were added:

1) packet id is embedded into struct packet.id, and
   it is updated on each realloc_packet()

2) Added new struct proto_hdr.get_next_proto callback
   to make possible apply fields of next header.

3) Added new dev_io ops for writting packets into .cfg file,
   to re-use common dev_io mechsnism for packets dumping.

4) Changed dev_io ops read/write to specify struct packet * instead of
   buf & count.

5) Updated trafgen_proto.c to obtain packet from the header if possible to
   do not depend on last packet, which is not right way to get related 
packet.

Before dump the default ETH_PROTO fields are applied as first header and
then next proto_hdr is identified via .get_next_proto(...) callback.

Meanwhile only eth, arp, vlan, ip4, udp, & tcp protos can be dissected
into *.cfg format.

Vadim Kochan (3):
  trafgen: Get packet from proto_hdr if possible
  trafgen: dev_io: Change read/write to specify struct packet *
  trafgen: Dump proto headers in *.cfg format

 trafgen.8|   4 +-
 trafgen.c|  79 +++--
 trafgen/Makefile |   1 +
 trafgen_conf.h   |   4 +-
 trafgen_dev.c|  78 +
 trafgen_dev.h|  12 +--
 trafgen_dump.c   | 256 +++
 trafgen_dump.h   |   8 ++
 trafgen_l2.c |  33 +++
 trafgen_l3.c |  25 +-
 trafgen_l4.c |   4 +-
 trafgen_parser.y |  11 ++-
 trafgen_proto.c  |  79 +++--
 trafgen_proto.h  |  10 +++
 14 files changed, 517 insertions(+), 87 deletions(-)
 create mode 100644 trafgen_dump.c
 create mode 100644 trafgen_dump.h

-- 
2.9.3

-- 
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.


[netsniff-ng] [PATCH 3/3] trafgen: Dump proto headers in *.cfg format

2017-07-29 Thread Vadim Kochan
Added trafgen_dump.c module which dumps headers from packet
in .cfg format. Packet is dumped if -o .cfg was specified,
it might be useful to specify *.pcap file as input and convert it
into .cfg file to edit proto fields in human readable format.

To make it possible several main changes were added:

1) packet id is embedded into struct packet.id, and
   it is updated on each realloc_packet()

2) Added new struct proto_hdr.get_next_proto callback
   to make possible apply fields of next header.

3) Added new dev_io ops for writting packets into .cfg file,
   to re-use common dev_io mechsnism for packets dumping.

Before dump the default ETH_PROTO fields are applied as first header and
then next proto_hdr is identified via .get_next_proto(...) callback.

Meanwhile only eth, arp, vlan, ip4, udp, & tcp protos can be dissected
into *.cfg format.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen.8|   4 +-
 trafgen.c|  54 ++--
 trafgen/Makefile |   1 +
 trafgen_conf.h   |   2 +
 trafgen_dev.c|  36 +++-
 trafgen_dev.h|   4 +-
 trafgen_dump.c   | 256 +++
 trafgen_dump.h   |   8 ++
 trafgen_l2.c |  33 +++
 trafgen_l3.c |  21 -
 trafgen_parser.y |   5 ++
 trafgen_proto.c  |  69 +--
 trafgen_proto.h  |   7 ++
 13 files changed, 458 insertions(+), 42 deletions(-)
 create mode 100644 trafgen_dump.c
 create mode 100644 trafgen_dump.h

diff --git a/trafgen.8 b/trafgen.8
index 67aaaf9..f720043 100644
--- a/trafgen.8
+++ b/trafgen.8
@@ -74,9 +74,9 @@ It is also possible to specify PCAP file with .pcap extension 
via -i,--in option
 by default packets will be sent at rate considering timestamp from PCAP file 
which
 might be reset via -b/-t options.
 .PP
-.SS -o <dev|pcap>, -d <dev|pcap>, --out <dev|pcap>, --dev <dev|pcap>
+.SS -o <dev|.pcap|.cfg>, -d <dev|.pcap|.cfg>, --out <dev|.pcap|.cfg>, --dev 
<dev|.pcap|.cfg>
 Defines the outgoing networking device such as eth0, wlan0 and others or
-a pcap file.
+a *.pcap or *.cfg file. Pcap and configuration files are identified by 
extension.
 .PP
 .SS -p, --cpp
 Pass the packet configuration to the C preprocessor before reading it into
diff --git a/trafgen.c b/trafgen.c
index 97ac046..9b54399 100644
--- a/trafgen.c
+++ b/trafgen.c
@@ -185,31 +185,31 @@ static void __noreturn help(void)
puts("http://www.netsniff-ng.org\n\n;
 "Usage: trafgen [options] [packet]\n"
 "Options:\n"
-"  -i|-c|--in|--conf   Packet configuration 
file/stdin\n"
-"  -o|-d|--out|--dev  Networking device i.e., eth0\n"
-"  -p|--cpp   Run packet config through C 
preprocessor\n"
-"  -D|--defineAdd macro/define for C 
preprocessor\n"
-"  -J|--jumbo-support Support 64KB super jumbo frames 
(def: 2048B)\n"
-"  -R|--rfraw Inject raw 802.11 frames\n"
-"  -s|--smoke-test  Probe if machine survived 
fuzz-tested packet\n"
-"  -n|--num Number of packets until exit 
(def: 0)\n"
-"  -r|--rand  Randomize packet selection (def: 
round robin)\n"
-"  -P|--cpusSpecify number of forks(<= CPUs) 
(def: #CPUs)\n"
-"  -t|--gap Set approx. interpacket gap 
(s/ms/us/ns, def: us)\n"
-"  -b|--rateSend traffic at specified rate 
(pps/B/kB/MB/GB/kbit/Mbit/Gbit/KiB/MiB/GiB)\n"
-"  -S|--ring-size   Manually set mmap size 
(KiB/MiB/GiB)\n"
-"  -E|--seedManually set srand(3) seed\n"
-"  -u|--user  Drop privileges and change to 
userid\n"
-"  -g|--groupDrop privileges and change to 
groupid\n"
-"  -H|--prio-high Make this high priority 
process\n"
-"  -A|--no-sock-mem   Don't tune core socket memory\n"
-"  -Q|--notouch-irq   Do not touch IRQ CPU affinity of 
NIC\n"
-"  -q|--qdisc-pathEnable qdisc kernel path 
(default off since 3.14)\n"
-"  -V|--verbose   Be more verbose\n"
-"  -C|--no-cpu-stats  Do not print CPU time statistics 
on exit\n"
-"  -v|--version   Show version and exit\n"
-"  -e|--example   Show built-in packet config 
example\n"
-"  -h|--help  Guess what?!\n\n"
+   

[netsniff-ng] [PATCH 1/3] trafgen: Get packet from proto_hdr if possible

2017-07-29 Thread Vadim Kochan
Replace using current_packet() by new proto_hdr_packet(hdr)
function to obtain packet directly from header. This is more
generic and flexible way, because it guarantees that packet really
belongs to the header, which in case in current_packet() is not right
because it means getting of last allocated packet.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen_l3.c|  4 ++--
 trafgen_l4.c|  4 ++--
 trafgen_proto.c | 10 --
 trafgen_proto.h |  3 +++
 4 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/trafgen_l3.c b/trafgen_l3.c
index 7199b89..48790e5 100644
--- a/trafgen_l3.c
+++ b/trafgen_l3.c
@@ -81,7 +81,7 @@ static void ipv4_csum_update(struct proto_hdr *hdr)
 
 static void ipv4_packet_finish(struct proto_hdr *hdr)
 {
-   struct packet *pkt = current_packet();
+   struct packet *pkt = proto_hdr_packet(hdr);
uint16_t total_len;
 
total_len = pkt->len - hdr->pkt_offset;
@@ -166,7 +166,7 @@ static void ipv6_field_changed(struct proto_field *field)
 
 static void ipv6_packet_finish(struct proto_hdr *hdr)
 {
-   struct packet *pkt = current_packet();
+   struct packet *pkt = proto_hdr_packet(hdr);
uint16_t total_len = pkt->len - hdr->pkt_offset - IPV6_HDR_LEN;
 
proto_hdr_field_set_default_be16(hdr, IP6_LEN, total_len);
diff --git a/trafgen_l4.c b/trafgen_l4.c
index 198d622..c596d21 100644
--- a/trafgen_l4.c
+++ b/trafgen_l4.c
@@ -71,7 +71,7 @@ static void udp_csum_update(struct proto_hdr *hdr)
 
 static void udp_packet_finish(struct proto_hdr *hdr)
 {
-   struct packet *pkt = current_packet();
+   struct packet *pkt = proto_hdr_packet(hdr);
uint16_t total_len;
 
total_len = pkt->len - hdr->pkt_offset;
@@ -142,7 +142,7 @@ static void tcp_field_changed(struct proto_field *field)
 static void tcp_csum_update(struct proto_hdr *hdr)
 {
struct proto_hdr *lower = proto_lower_header(hdr);
-   struct packet *pkt = current_packet();
+   struct packet *pkt = proto_hdr_packet(hdr);
uint16_t total_len;
uint16_t csum;
 
diff --git a/trafgen_proto.c b/trafgen_proto.c
index c2cbffb..1d978e3 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -30,6 +30,11 @@ static struct ctx ctx;
 
 static const struct proto_ops *registered_ops[__PROTO_MAX];
 
+struct packet *proto_hdr_packet(struct proto_hdr *hdr)
+{
+   return packet_get(hdr->pkt_id);
+}
+
 struct proto_hdr *proto_lower_header(struct proto_hdr *hdr)
 {
struct packet *pkt = packet_get(hdr->pkt_id);
@@ -266,12 +271,13 @@ void proto_hdr_move_sub_header(struct proto_hdr *hdr, 
struct proto_hdr *from,
 struct proto_hdr *proto_lower_default_add(struct proto_hdr *upper,
  enum proto_id pid)
 {
+   struct packet *pkt = proto_hdr_packet(upper);
+   size_t headers_count = pkt->headers_count;
struct proto_hdr *current;
-   size_t headers_count = current_packet()->headers_count;
const struct proto_ops *ops;
 
if (headers_count > 0) {
-   current = current_packet()->headers[headers_count - 1];
+   current = pkt->headers[headers_count - 1];
ops = current->ops;
 
if (ops->layer >= proto_ops_by_id(pid)->layer)
diff --git a/trafgen_proto.h b/trafgen_proto.h
index d3da963..36b8f2b 100644
--- a/trafgen_proto.h
+++ b/trafgen_proto.h
@@ -7,6 +7,8 @@
 
 #include "trafgen_dev.h"
 
+struct packet;
+
 enum proto_id {
PROTO_NONE = 0,
PROTO_ETH,
@@ -104,6 +106,7 @@ 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 packet *proto_hdr_packet(struct proto_hdr *hdr);
 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);
-- 
2.9.3

-- 
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.


[netsniff-ng] [PATCH 2/3] trafgen: dev_io: Change read/write to specify struct packet *

2017-07-29 Thread Vadim Kochan
Refactor dev_io_ops read & write to specify struct packet *,
it may simplify a bit a caller logic. And it allow to keep
required members within one struct packet object.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen.c| 25 -
 trafgen_conf.h   |  2 +-
 trafgen_dev.c| 48 +---
 trafgen_dev.h| 12 +++-
 trafgen_parser.y |  6 --
 5 files changed, 49 insertions(+), 44 deletions(-)

diff --git a/trafgen.c b/trafgen.c
index 207b680..97ac046 100644
--- a/trafgen.c
+++ b/trafgen.c
@@ -684,7 +684,7 @@ static void xmit_slowpath_or_die(struct ctx *ctx, unsigned 
int cpu, unsigned lon
while (likely(sigint == 0 && num > 0 && plen > 0)) {
packet_apply_dyn_elements(i);
 retry:
-   ret = dev_io_write(ctx->dev_out, packets[i].payload, 
packets[i].len);
+   ret = dev_io_write(ctx->dev_out, [i]);
if (unlikely(ret < 0)) {
if (errno == ENOBUFS) {
sched_yield();
@@ -937,27 +937,10 @@ static void xmit_packet_precheck(struct ctx *ctx, 
unsigned int cpu)
 
 static void pcap_load_packets(struct dev_io *dev)
 {
-   struct timespec tstamp;
-   size_t buf_len;
-   uint8_t *buf;
-   int pkt_len;
+   struct packet *pkt;
 
-   buf_len = round_up(1024 * 1024, RUNTIME_PAGE_SIZE);
-   buf = xmalloc_aligned(buf_len, CO_CACHE_LINE_SIZE);
-
-   while ((pkt_len = dev_io_read(dev, buf, buf_len, )) > 0) {
-   struct packet *pkt;
-
-   realloc_packet();
-
-   pkt = current_packet();
-   pkt->len = pkt_len;
-   pkt->payload = xzmalloc(pkt_len);
-   memcpy(pkt->payload, buf, pkt_len);
-   memcpy(>tstamp, , sizeof(tstamp));
-   }
-
-   free(buf);
+   while ((pkt = dev_io_read(dev)) != 0)
+   /* nothing to do */;
 }
 
 static void main_loop(struct ctx *ctx, char *confname, bool slow,
diff --git a/trafgen_conf.h b/trafgen_conf.h
index 2af830d..7e922fe 100644
--- a/trafgen_conf.h
+++ b/trafgen_conf.h
@@ -80,6 +80,6 @@ extern void set_fill(uint8_t val, size_t len);
 extern struct packet *current_packet(void);
 extern uint32_t current_packet_id(void);
 extern struct packet *packet_get(uint32_t id);
-extern void realloc_packet(void);
+extern struct packet *realloc_packet(void);
 
 #endif /* TRAFGEN_CONF */
diff --git a/trafgen_dev.c b/trafgen_dev.c
index d7f1cd5..d613cce 100644
--- a/trafgen_dev.c
+++ b/trafgen_dev.c
@@ -19,6 +19,7 @@
 #include "mac80211.h"
 #include "linktype.h"
 #include "trafgen_dev.h"
+#include "trafgen_conf.h"
 
 static int dev_pcap_open(struct dev_io *dev, const char *name, enum 
dev_io_mode_t mode)
 {
@@ -36,6 +37,8 @@ static int dev_pcap_open(struct dev_io *dev, const char 
*name, enum dev_io_mode_
}
 
dev->pcap_mode = PCAP_MODE_RD;
+   dev->buf_len = round_up(1024 * 1024, RUNTIME_PAGE_SIZE);
+   dev->buf = xmalloc_aligned(dev->buf_len, CO_CACHE_LINE_SIZE);
} else if (mode & DEV_IO_OUT) {
if (!strncmp("-", name, strlen("-"))) {
dev->fd = dup_or_die(fileno(stdout));
@@ -69,26 +72,35 @@ static int dev_pcap_open(struct dev_io *dev, const char 
*name, enum dev_io_mode_
return 0;
 }
 
-static int dev_pcap_read(struct dev_io *dev, uint8_t *buf, size_t len,
-struct timespec *tstamp)
+static struct packet *dev_pcap_read(struct dev_io *dev)
 {
+   size_t len = dev->buf_len;
+   uint8_t *buf = dev->buf;
pcap_pkthdr_t phdr;
+   struct packet *pkt;
size_t pkt_len;
 
if (dev->pcap_ops->read_pcap(dev->fd, , dev->pcap_magic, buf, len) 
<= 0)
-   return -1;
+   return NULL;
 
pkt_len = pcap_get_length(, dev->pcap_magic);
if (!pkt_len)
-   return -1;
+   return NULL;
 
-   pcap_get_tstamp(, dev->pcap_magic, tstamp);
+   pkt = realloc_packet();
 
-   return pkt_len;
+   pkt->len = pkt_len;
+   pkt->payload = xzmalloc(pkt_len);
+   memcpy(pkt->payload, buf, pkt_len);
+   pcap_get_tstamp(, dev->pcap_magic, >tstamp);
+
+   return pkt;
 }
 
-static int dev_pcap_write(struct dev_io *dev, const uint8_t *buf, size_t len)
+static int dev_pcap_write(struct dev_io *dev, const struct packet *pkt)
 {
+   uint8_t *buf = pkt->payload;
+   size_t len = pkt->len;
struct timeval time;
pcap_pkthdr_t phdr;
int ret;
@@ -130,8 +142,13 @@ static int dev_pcap_write(struct dev_io *dev, const 
uint8_t *buf, size_t len)
 
 static void dev_pcap_close(struct dev_io *dev)
 {
-   if (dev->pcap_mode == PCAP_MODE_WR)
+   if (dev-

Re: [netsniff-ng] Segmentation fault of mausezahn

2017-07-24 Thread Vadim Kochan
Hi Zhouyang Jia,

Your fix looks reasonable.

Would you please send patch in git-format (you can look at
SubmittingPatches file),
or send a pull request ?

Thanks,
Vadim Kochan

On Mon, Jul 24, 2017 at 5:08 PM, Zhouyang Jia <jiazhouyan...@gmail.com>
wrote:

> Hi,
>
> I'm new to netsniff-ng and I find that the component, mausezahn, would
> crash if input a wrong payload file, e.g., "$./mausezahn -f wrong_file"
> will trigger a segfault.
>
> I think it would be better if mausezahn could exit gracefully with proper
> log messages. Attached please find the patch against version
> netsniff-ng-0.6.3. Hopefully, it can solve this problem.
>
> Best,
> Zhouyang
>
> --
> 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.
>

-- 
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.


[netsniff-ng] [PATCH v2] trafgen: Delegate creation of rfraw to dev_io API

2017-07-17 Thread Vadim Kochan
Simplify a bit of creation rfraw device by delegating it to the dev_io
API, also in case the output device is pcap file the --rfraw option
sets the link type to ieee80211 radio tap.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen.8 |  3 ++-
 trafgen.c | 25 +
 trafgen_dev.c | 35 ++-
 trafgen_dev.h |  4 +++-
 4 files changed, 48 insertions(+), 19 deletions(-)

v2:
1) Removed unneeded sleep() call.

diff --git a/trafgen.8 b/trafgen.8
index 50deacf..67aaaf9 100644
--- a/trafgen.8
+++ b/trafgen.8
@@ -98,7 +98,8 @@ a bigger memory footprint for the ring buffer.
 In case the output networking device is a wireless device, it is possible with
 trafgen to turn this into monitor mode and create a mon device that trafgen
 will be transmitting on instead of wlan, for instance. This enables trafgen
-to inject raw 802.11 frames.
+to inject raw 802.11 frames. In case if the output is a pcap file the link type
+is set to 127 (ieee80211 radio tap).
 .PP
 .SS -s , --smoke-test 
 In case this option is enabled, trafgen will perform a smoke test. In other
diff --git a/trafgen.c b/trafgen.c
index 5f3555a..207b680 100644
--- a/trafgen.c
+++ b/trafgen.c
@@ -45,7 +45,6 @@
 #include "lockme.h"
 #include "privs.h"
 #include "proc.h"
-#include "mac80211.h"
 #include "ioops.h"
 #include "irq.h"
 #include "config.h"
@@ -85,7 +84,7 @@ struct ctx {
unsigned long num;
unsigned int cpus;
uid_t uid; gid_t gid;
-   char *device, *device_trans, *rhost;
+   char *device, *rhost;
struct sockaddr_in dest;
struct shaper sh;
char *packet_str;
@@ -1023,7 +1022,7 @@ static unsigned int generate_srand_seed(void)
 
 static void on_panic_del_rfmon(void *arg)
 {
-   leave_rfmon_mac80211(arg);
+   dev_io_close(arg);
 }
 
 int main(int argc, char **argv)
@@ -1283,15 +1282,6 @@ int main(int argc, char **argv)
set_system_socket_memory(vals, array_size(vals));
xlockme();
 
-   if (ctx.rfraw) {
-   ctx.device_trans = xstrdup(ctx.device);
-   xfree(ctx.device);
-
-   enter_rfmon_mac80211(ctx.device_trans, );
-   panic_handler_add(on_panic_del_rfmon, ctx.device);
-   sleep(0);
-   }
-
if (ctx.pcap_in) {
ctx.dev_in = dev_io_open(ctx.pcap_in, DEV_IO_IN);
if (!ctx.dev_in)
@@ -1302,6 +1292,13 @@ int main(int argc, char **argv)
if (!ctx.dev_out)
panic("Failed to open output device\n");
 
+   if (ctx.rfraw) {
+   if (dev_io_link_type_set(ctx.dev_out, 
LINKTYPE_IEEE802_11_RADIOTAP))
+   panic("Failed to setup rfraw device\n");
+
+   panic_handler_add(on_panic_del_rfmon, ctx.dev_out);
+   }
+
protos_init(ctx.dev_out);
 
if (shaper_is_set() || (ctx.dev_in && dev_io_is_pcap(ctx.dev_in))
@@ -1357,9 +1354,6 @@ int main(int argc, char **argv)
die();
}
 
-   if (ctx.rfraw)
-   leave_rfmon_mac80211(ctx.device);
-
if (set_sock_mem)
reset_system_socket_memory(vals, array_size(vals));
 
@@ -1393,7 +1387,6 @@ thread_out:
 
argv_free(cpp_argv);
free(ctx.device);
-   free(ctx.device_trans);
free(ctx.rhost);
free(confname);
free(ctx.packet_str);
diff --git a/trafgen_dev.c b/trafgen_dev.c
index 80e7481..d7f1cd5 100644
--- a/trafgen_dev.c
+++ b/trafgen_dev.c
@@ -16,6 +16,8 @@
 #include "xmalloc.h"
 #include "pcap_io.h"
 #include "built_in.h"
+#include "mac80211.h"
+#include "linktype.h"
 #include "trafgen_dev.h"
 
 static int dev_pcap_open(struct dev_io *dev, const char *name, enum 
dev_io_mode_t mode)
@@ -164,9 +166,34 @@ static int dev_net_write(struct dev_io *dev, const uint8_t 
*buf, size_t len)
return sendto(dev->fd, buf, len, 0, (struct sockaddr *) , 
sizeof(saddr));
 }
 
+static int dev_net_set_link_type(struct dev_io *dev, int link_type)
+{
+   if (link_type != LINKTYPE_IEEE802_11 && link_type != 
LINKTYPE_IEEE802_11_RADIOTAP)
+   return 0;
+
+   dev->trans = xstrdup(dev->name);
+   xfree(dev->name);
+
+   enter_rfmon_mac80211(dev->trans, >name);
+   dev->ifindex = __device_ifindex(dev->name);
+   dev->dev_type = device_type(dev->name);
+
+   return 0;
+}
+
+static void dev_net_close(struct dev_io *dev)
+{
+   if (dev->link_type == LINKTYPE_IEEE802_11 || dev->link_type == 
LINKTYPE_IEEE802_11_RADIOTAP)
+   leave_rfmon_mac80211(dev->name);
+
+   free(dev->trans);
+}
+
 static const struct dev_io_ops dev_net_ops = {
.open = dev_net_open,
.write = dev_net_write,
+   .set_link_type = dev_net_set_lin

[netsniff-ng] [PATCH] trafgen: Delegate creation of rfraw to dev_io API

2017-06-12 Thread Vadim Kochan
Simplify a bit of creation rfraw device by delegating it to the dev_io
API, also in case the output device is pcap file the --rfraw option
sets the link type to ieee80211 radio tap.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen.8 |  3 ++-
 trafgen.c | 25 +
 trafgen_dev.c | 36 +++-
 trafgen_dev.h |  4 +++-
 4 files changed, 49 insertions(+), 19 deletions(-)

diff --git a/trafgen.8 b/trafgen.8
index 50deacf..67aaaf9 100644
--- a/trafgen.8
+++ b/trafgen.8
@@ -98,7 +98,8 @@ a bigger memory footprint for the ring buffer.
 In case the output networking device is a wireless device, it is possible with
 trafgen to turn this into monitor mode and create a mon device that trafgen
 will be transmitting on instead of wlan, for instance. This enables trafgen
-to inject raw 802.11 frames.
+to inject raw 802.11 frames. In case if the output is a pcap file the link type
+is set to 127 (ieee80211 radio tap).
 .PP
 .SS -s , --smoke-test 
 In case this option is enabled, trafgen will perform a smoke test. In other
diff --git a/trafgen.c b/trafgen.c
index 6ae0076..3929734 100644
--- a/trafgen.c
+++ b/trafgen.c
@@ -45,7 +45,6 @@
 #include "lockme.h"
 #include "privs.h"
 #include "proc.h"
-#include "mac80211.h"
 #include "ioops.h"
 #include "irq.h"
 #include "config.h"
@@ -85,7 +84,7 @@ struct ctx {
unsigned long num;
unsigned int cpus;
uid_t uid; gid_t gid;
-   char *device, *device_trans, *rhost;
+   char *device, *rhost;
struct sockaddr_in dest;
struct shaper sh;
char *packet_str;
@@ -1022,7 +1021,7 @@ static unsigned int generate_srand_seed(void)
 
 static void on_panic_del_rfmon(void *arg)
 {
-   leave_rfmon_mac80211(arg);
+   dev_io_close(arg);
 }
 
 int main(int argc, char **argv)
@@ -1282,15 +1281,6 @@ int main(int argc, char **argv)
set_system_socket_memory(vals, array_size(vals));
xlockme();
 
-   if (ctx.rfraw) {
-   ctx.device_trans = xstrdup(ctx.device);
-   xfree(ctx.device);
-
-   enter_rfmon_mac80211(ctx.device_trans, );
-   panic_handler_add(on_panic_del_rfmon, ctx.device);
-   sleep(0);
-   }
-
if (ctx.pcap_in) {
ctx.dev_in = dev_io_open(ctx.pcap_in, DEV_IO_IN);
if (!ctx.dev_in)
@@ -1301,6 +1291,13 @@ int main(int argc, char **argv)
if (!ctx.dev_out)
panic("Failed to open output device\n");
 
+   if (ctx.rfraw) {
+   if (dev_io_link_type_set(ctx.dev_out, 
LINKTYPE_IEEE802_11_RADIOTAP))
+   panic("Failed to setup rfraw device\n");
+
+   panic_handler_add(on_panic_del_rfmon, ctx.dev_out);
+   }
+
protos_init(ctx.dev_out);
 
if (shaper_is_set() || (ctx.dev_in && dev_io_is_pcap(ctx.dev_in))
@@ -1356,9 +1353,6 @@ int main(int argc, char **argv)
die();
}
 
-   if (ctx.rfraw)
-   leave_rfmon_mac80211(ctx.device);
-
if (set_sock_mem)
reset_system_socket_memory(vals, array_size(vals));
 
@@ -1392,7 +1386,6 @@ thread_out:
 
argv_free(cpp_argv);
free(ctx.device);
-   free(ctx.device_trans);
free(ctx.rhost);
free(confname);
free(ctx.packet_str);
diff --git a/trafgen_dev.c b/trafgen_dev.c
index cd99a0c..46fb897 100644
--- a/trafgen_dev.c
+++ b/trafgen_dev.c
@@ -16,6 +16,8 @@
 #include "xmalloc.h"
 #include "pcap_io.h"
 #include "built_in.h"
+#include "mac80211.h"
+#include "linktype.h"
 #include "trafgen_dev.h"
 
 static int dev_pcap_open(struct dev_io *dev, const char *name, enum 
dev_io_mode_t mode)
@@ -164,9 +166,35 @@ static int dev_net_write(struct dev_io *dev, const uint8_t 
*buf, size_t len)
return sendto(dev->fd, buf, len, 0, (struct sockaddr *) , 
sizeof(saddr));
 }
 
+static int dev_net_set_link_type(struct dev_io *dev, int link_type)
+{
+   if (link_type != LINKTYPE_IEEE802_11 && link_type != 
LINKTYPE_IEEE802_11_RADIOTAP)
+   return 0;
+
+   dev->trans = xstrdup(dev->name);
+   xfree(dev->name);
+
+   enter_rfmon_mac80211(dev->trans, >name);
+   dev->ifindex = __device_ifindex(dev->name);
+   dev->dev_type = device_type(dev->name);
+   sleep(0);
+
+   return 0;
+}
+
+static void dev_net_close(struct dev_io *dev)
+{
+   if (dev->link_type == LINKTYPE_IEEE802_11 || dev->link_type == 
LINKTYPE_IEEE802_11_RADIOTAP)
+   leave_rfmon_mac80211(dev->name);
+
+   free(dev->trans);
+}
+
 static const struct dev_io_ops dev_net_ops = {
.open = dev_net_open,
.write = dev_net_write,
+   .set_link_type = dev_net_set_link_type,
+   

[netsniff-ng] [PATCH v2] trafgen: Fix output pcap file name length trimming

2017-06-12 Thread Vadim Kochan
Trim output name to IFNAMSIZ only if the output is a networking device,
otherwise the following error occured if output name is greater then IFNAMSIZ:

~/src/netsniff-ng$ trafgen -n 1 '{ udp() }' -o /tmp/xx.pcap
No networking device or pcap file: /tmp/xx
Failed to open output device
---
v2:
Fixed stupid copy-paste of xtrsndup-ing device name

 trafgen.c | 2 +-
 trafgen_dev.c | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/trafgen.c b/trafgen.c
index 6ae0076..b40d362 100644
--- a/trafgen.c
+++ b/trafgen.c
@@ -1084,7 +1084,7 @@ int main(int argc, char **argv)
break;
case 'd':
case 'o':
-   ctx.device = xstrndup(optarg, IFNAMSIZ);
+   ctx.device = xstrdup(optarg);
break;
case 'H':
prio_high = true;
diff --git a/trafgen_dev.c b/trafgen_dev.c
index cd99a0c..80e7481 100644
--- a/trafgen_dev.c
+++ b/trafgen_dev.c
@@ -174,8 +174,10 @@ struct dev_io *dev_io_open(const char *name, enum 
dev_io_mode_t mode)
struct dev_io *dev = xzmalloc(sizeof(struct dev_io));
 
if (strstr(name, ".pcap")) {
+   dev->name = xstrdup(name);
dev->ops = _pcap_ops;
} else if (device_mtu(name) > 0) {
+   dev->name = xstrndup(name, IFNAMSIZ);
dev->ops = _net_ops;
} else {
fprintf(stderr, "No networking device or pcap file: %s\n", 
name);
@@ -189,7 +191,6 @@ struct dev_io *dev_io_open(const char *name, enum 
dev_io_mode_t mode)
}
}
 
-   dev->name = xstrdup(name);
return dev;
 };
 
-- 
2.9.3

-- 
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.


[netsniff-ng] Re: [PATCH] trafgen: Fix output pcap file name length trimming

2017-06-12 Thread Vadim Kochan
On Mon, Jun 12, 2017 at 11:38 PM, Vadim Kochan <vadi...@gmail.com> wrote:

> Trim output name to IFNAMSIZ only if the output is a networking device,
> otherwise the following error occured if output name is greater then
> IFNAMSIZ:
>
> ~/src/netsniff-ng$ trafgen -n 1 '{ udp() }' -o
> /tmp/xx.pcap
> No networking device or pcap file: /tmp/xx
> Failed to open output device
> ---
>  trafgen.c | 2 +-
>  trafgen_dev.c | 3 ++-
>  2 files changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/trafgen.c b/trafgen.c
> index 6ae0076..b40d362 100644
> --- a/trafgen.c
> +++ b/trafgen.c
> @@ -1084,7 +1084,7 @@ int main(int argc, char **argv)
> break;
> case 'd':
> case 'o':
> -   ctx.device = xstrndup(optarg, IFNAMSIZ);
> +   ctx.device = xstrdup(optarg);
> break;
> case 'H':
> prio_high = true;
> diff --git a/trafgen_dev.c b/trafgen_dev.c
> index cd99a0c..bbe1be8 100644
> --- a/trafgen_dev.c
> +++ b/trafgen_dev.c
> @@ -174,8 +174,10 @@ struct dev_io *dev_io_open(const char *name, enum
> dev_io_mode_t mode)
> struct dev_io *dev = xzmalloc(sizeof(struct dev_io));
>
> if (strstr(name, ".pcap")) {
> +   dev->name = xstrdup(name);
> dev->ops = _pcap_ops;
> } else if (device_mtu(name) > 0) {
> +   dev->name = xstrndup(optarg, IFNAMSIZ);
>
>>>>> Ops, sorry ... too late for fixing ...


> dev->ops = _net_ops;
> } else {
> fprintf(stderr, "No networking device or pcap file: %s\n",
> name);
> @@ -189,7 +191,6 @@ struct dev_io *dev_io_open(const char *name, enum
> dev_io_mode_t mode)
> }
> }
>
> -   dev->name = xstrdup(name);
> return dev;
>  };
>
> --
> 2.9.3
>
>

-- 
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.


[netsniff-ng] [PATCH] trafgen: Fix output pcap file name length trimming

2017-06-12 Thread Vadim Kochan
Trim output name to IFNAMSIZ only if the output is a networking device,
otherwise the following error occured if output name is greater then IFNAMSIZ:

~/src/netsniff-ng$ trafgen -n 1 '{ udp() }' -o /tmp/xx.pcap
No networking device or pcap file: /tmp/xx
Failed to open output device
---
 trafgen.c | 2 +-
 trafgen_dev.c | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/trafgen.c b/trafgen.c
index 6ae0076..b40d362 100644
--- a/trafgen.c
+++ b/trafgen.c
@@ -1084,7 +1084,7 @@ int main(int argc, char **argv)
break;
case 'd':
case 'o':
-   ctx.device = xstrndup(optarg, IFNAMSIZ);
+   ctx.device = xstrdup(optarg);
break;
case 'H':
prio_high = true;
diff --git a/trafgen_dev.c b/trafgen_dev.c
index cd99a0c..bbe1be8 100644
--- a/trafgen_dev.c
+++ b/trafgen_dev.c
@@ -174,8 +174,10 @@ struct dev_io *dev_io_open(const char *name, enum 
dev_io_mode_t mode)
struct dev_io *dev = xzmalloc(sizeof(struct dev_io));
 
if (strstr(name, ".pcap")) {
+   dev->name = xstrdup(name);
dev->ops = _pcap_ops;
} else if (device_mtu(name) > 0) {
+   dev->name = xstrndup(optarg, IFNAMSIZ);
dev->ops = _net_ops;
} else {
fprintf(stderr, "No networking device or pcap file: %s\n", 
name);
@@ -189,7 +191,6 @@ struct dev_io *dev_io_open(const char *name, enum 
dev_io_mode_t mode)
}
}
 
-   dev->name = xstrdup(name);
return dev;
 };
 
-- 
2.9.3

-- 
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.


[netsniff-ng] [PATCH v2] trafgen: Allow to generate packets to output pcap file

2017-06-07 Thread Vadim Kochan
Add trafgen_dev.c module which provides generic way of
reading and writing packets to/from networking device or a pcap file.

Also allow to handle output pcap file via '-o, --out, --dev' option.

It might be useful in future for testing some link protocols which is
not easy to capture (e.g. wlan packets) w/o having some special setup.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
v2:
1) Fixed "Failed ..." -> "Failed to ..." error messages
2) Fixed indentation in dev_io struct at pcap_magic field
3) Removed not needed dev_net_close function
4) Removed spaces in dev_io_ops functions fields

 trafgen.8|   5 +-
 trafgen.c| 102 +-
 trafgen/Makefile |   1 +
 trafgen_dev.c| 258 +++
 trafgen_dev.h|  49 +++
 trafgen_l2.c |   4 +
 trafgen_l3.c |   8 +-
 trafgen_proto.c  |  50 ++-
 trafgen_proto.h  |   6 +-
 9 files changed, 391 insertions(+), 92 deletions(-)
 create mode 100644 trafgen_dev.c
 create mode 100644 trafgen_dev.h

diff --git a/trafgen.8 b/trafgen.8
index fd9788a..50deacf 100644
--- a/trafgen.8
+++ b/trafgen.8
@@ -74,8 +74,9 @@ It is also possible to specify PCAP file with .pcap extension 
via -i,--in option
 by default packets will be sent at rate considering timestamp from PCAP file 
which
 might be reset via -b/-t options.
 .PP
-.SS -o , -d , --out , --dev 
-Defines the outgoing networking device such as eth0, wlan0 and others.
+.SS -o <dev|pcap>, -d <dev|pcap>, --out <dev|pcap>, --dev <dev|pcap>
+Defines the outgoing networking device such as eth0, wlan0 and others or
+a pcap file.
 .PP
 .SS -p, --cpp
 Pass the packet configuration to the C preprocessor before reading it into
diff --git a/trafgen.c b/trafgen.c
index b25760f..ecc7d02 100644
--- a/trafgen.c
+++ b/trafgen.c
@@ -57,6 +57,7 @@
 #include "csum.h"
 #include "trafgen_proto.h"
 #include "pcap_io.h"
+#include "trafgen_dev.h"
 
 enum shaper_type {
SHAPER_NONE,
@@ -79,6 +80,8 @@ struct shaper {
 struct ctx {
bool rand, rfraw, jumbo_support, verbose, smoke_test, enforce, 
qdisc_path;
size_t reserve_size;
+   struct dev_io *dev_out;
+   struct dev_io *dev_in;
unsigned long num;
unsigned int cpus;
uid_t uid; gid_t gid;
@@ -145,7 +148,6 @@ static const char *copyright = "Please report bugs to 
<netsniff-ng@googlegroups.
"This is free software: you are free to change and redistribute it.\n"
"There is NO WARRANTY, to the extent permitted by law.";
 
-static int sock;
 static struct cpu_stats *stats;
 static unsigned int seed;
 
@@ -664,11 +666,6 @@ static void xmit_slowpath_or_die(struct ctx *ctx, unsigned 
int cpu, unsigned lon
unsigned long num = 1, i = 0;
struct timeval start, end, diff;
unsigned long long tx_bytes = 0, tx_packets = 0;
-   struct sockaddr_ll saddr = {
-   .sll_family = PF_PACKET,
-   .sll_halen = ETH_ALEN,
-   .sll_ifindex = device_ifindex(ctx->device),
-   };
 
if (ctx->num > 0)
num = ctx->num;
@@ -688,8 +685,7 @@ static void xmit_slowpath_or_die(struct ctx *ctx, unsigned 
int cpu, unsigned lon
while (likely(sigint == 0 && num > 0 && plen > 0)) {
packet_apply_dyn_elements(i);
 retry:
-   ret = sendto(sock, packets[i].payload, packets[i].len, 0,
-(struct sockaddr *) , sizeof(saddr));
+   ret = dev_io_write(ctx->dev_out, packets[i].payload, 
packets[i].len);
if (unlikely(ret < 0)) {
if (errno == ENOBUFS) {
sched_yield();
@@ -745,15 +741,16 @@ retry:
 
 static void xmit_fastpath_or_die(struct ctx *ctx, unsigned int cpu, unsigned 
long orig_num)
 {
-   int ifindex = device_ifindex(ctx->device);
+   int ifindex = dev_io_ifindex_get(ctx->dev_out);
uint8_t *out = NULL;
unsigned int it = 0;
unsigned long num = 1, i = 0;
-   size_t size = ring_size(ctx->device, ctx->reserve_size);
+   size_t size = ring_size(dev_io_name_get(ctx->dev_out), 
ctx->reserve_size);
struct ring tx_ring;
struct frame_map *hdr;
struct timeval start, end, diff;
unsigned long long tx_bytes = 0, tx_packets = 0;
+   int sock = dev_io_fd_get(ctx->dev_out);
 
set_sock_prio(sock, 512);
 
@@ -938,69 +935,37 @@ static void xmit_packet_precheck(struct ctx *ctx, 
unsigned int cpu)
}
 }
 
-static void pcap_load_packets(const char *path)
+static void pcap_load_packets(struct dev_io *dev)
 {
-   const struct pcap_file_ops *pcap_io = pcap_ops[PCAP_OPS_SG];
-   uint32_t link_type, magic;
-   pcap_pkthdr_t phdr;
+   struct timespec tsta

[netsniff-ng] [PATCH] trafgen: Allow to generate packets to output pcap file

2017-06-06 Thread Vadim Kochan
Add trafgen_dev.c module which provides generic way of
reading and writing packets to/from networking device or a pcap file.

Also allow to handle output pcap file via '-o, --out, --dev' option.

It might be useful in future for testing some link protocols which is
not easy to capture (e.g. wlan packets) w/o having some special setup.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen.8|   5 +-
 trafgen.c| 102 +
 trafgen/Makefile |   1 +
 trafgen_dev.c| 263 +++
 trafgen_dev.h|  49 +++
 trafgen_l2.c |   4 +
 trafgen_l3.c |   8 +-
 trafgen_proto.c  |  50 ++-
 trafgen_proto.h  |   6 +-
 9 files changed, 396 insertions(+), 92 deletions(-)
 create mode 100644 trafgen_dev.c
 create mode 100644 trafgen_dev.h

diff --git a/trafgen.8 b/trafgen.8
index fd9788a..50deacf 100644
--- a/trafgen.8
+++ b/trafgen.8
@@ -74,8 +74,9 @@ It is also possible to specify PCAP file with .pcap extension 
via -i,--in option
 by default packets will be sent at rate considering timestamp from PCAP file 
which
 might be reset via -b/-t options.
 .PP
-.SS -o , -d , --out , --dev 
-Defines the outgoing networking device such as eth0, wlan0 and others.
+.SS -o <dev|pcap>, -d <dev|pcap>, --out <dev|pcap>, --dev <dev|pcap>
+Defines the outgoing networking device such as eth0, wlan0 and others or
+a pcap file.
 .PP
 .SS -p, --cpp
 Pass the packet configuration to the C preprocessor before reading it into
diff --git a/trafgen.c b/trafgen.c
index b25760f..cc54f9e 100644
--- a/trafgen.c
+++ b/trafgen.c
@@ -57,6 +57,7 @@
 #include "csum.h"
 #include "trafgen_proto.h"
 #include "pcap_io.h"
+#include "trafgen_dev.h"
 
 enum shaper_type {
SHAPER_NONE,
@@ -79,6 +80,8 @@ struct shaper {
 struct ctx {
bool rand, rfraw, jumbo_support, verbose, smoke_test, enforce, 
qdisc_path;
size_t reserve_size;
+   struct dev_io *dev_out;
+   struct dev_io *dev_in;
unsigned long num;
unsigned int cpus;
uid_t uid; gid_t gid;
@@ -145,7 +148,6 @@ static const char *copyright = "Please report bugs to 
<netsniff-ng@googlegroups.
"This is free software: you are free to change and redistribute it.\n"
"There is NO WARRANTY, to the extent permitted by law.";
 
-static int sock;
 static struct cpu_stats *stats;
 static unsigned int seed;
 
@@ -664,11 +666,6 @@ static void xmit_slowpath_or_die(struct ctx *ctx, unsigned 
int cpu, unsigned lon
unsigned long num = 1, i = 0;
struct timeval start, end, diff;
unsigned long long tx_bytes = 0, tx_packets = 0;
-   struct sockaddr_ll saddr = {
-   .sll_family = PF_PACKET,
-   .sll_halen = ETH_ALEN,
-   .sll_ifindex = device_ifindex(ctx->device),
-   };
 
if (ctx->num > 0)
num = ctx->num;
@@ -688,8 +685,7 @@ static void xmit_slowpath_or_die(struct ctx *ctx, unsigned 
int cpu, unsigned lon
while (likely(sigint == 0 && num > 0 && plen > 0)) {
packet_apply_dyn_elements(i);
 retry:
-   ret = sendto(sock, packets[i].payload, packets[i].len, 0,
-(struct sockaddr *) , sizeof(saddr));
+   ret = dev_io_write(ctx->dev_out, packets[i].payload, 
packets[i].len);
if (unlikely(ret < 0)) {
if (errno == ENOBUFS) {
sched_yield();
@@ -745,15 +741,16 @@ retry:
 
 static void xmit_fastpath_or_die(struct ctx *ctx, unsigned int cpu, unsigned 
long orig_num)
 {
-   int ifindex = device_ifindex(ctx->device);
+   int ifindex = dev_io_ifindex_get(ctx->dev_out);
uint8_t *out = NULL;
unsigned int it = 0;
unsigned long num = 1, i = 0;
-   size_t size = ring_size(ctx->device, ctx->reserve_size);
+   size_t size = ring_size(dev_io_name_get(ctx->dev_out), 
ctx->reserve_size);
struct ring tx_ring;
struct frame_map *hdr;
struct timeval start, end, diff;
unsigned long long tx_bytes = 0, tx_packets = 0;
+   int sock = dev_io_fd_get(ctx->dev_out);
 
set_sock_prio(sock, 512);
 
@@ -938,69 +935,37 @@ static void xmit_packet_precheck(struct ctx *ctx, 
unsigned int cpu)
}
 }
 
-static void pcap_load_packets(const char *path)
+static void pcap_load_packets(struct dev_io *dev)
 {
-   const struct pcap_file_ops *pcap_io = pcap_ops[PCAP_OPS_SG];
-   uint32_t link_type, magic;
-   pcap_pkthdr_t phdr;
+   struct timespec tstamp;
size_t buf_len;
uint8_t *buf;
-   int ret;
-   int fd;
-
-   fd = open(path, O_RDONLY | O_LARGEFILE | O_NOATIME);
-   if (fd < 0 && errno == EPERM)
-   fd = open_or_die(path, O_RDONLY | O_LARGEFILE);
-   

[netsniff-ng] [PATCH] flowtop: Move out stats fields from flow & proc entry

2017-06-01 Thread Vadim Kochan
Move rate, bytes & pkts stats fields from flow & proc entry
to separate flow_stat struct.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 flowtop.c | 82 +++
 1 file changed, 41 insertions(+), 41 deletions(-)

diff --git a/flowtop.c b/flowtop.c
index 00937e1..0a3c514 100644
--- a/flowtop.c
+++ b/flowtop.c
@@ -52,20 +52,24 @@
 #define USEC_PER_SEC 100L
 #endif
 
+struct flow_stat {
+   uint64_t pkts_src, bytes_src;
+   uint64_t pkts_dst, bytes_dst;
+   double rate_bytes_src;
+   double rate_bytes_dst;
+   double rate_pkts_src;
+   double rate_pkts_dst;
+};
+
 struct proc_entry {
struct cds_list_head entry;
struct cds_list_head flows;
struct rcu_head rcu;
 
struct timeval last_update;
+   struct flow_stat stat;
unsigned int pid;
char name[256];
-   uint64_t pkts_src, bytes_src;
-   uint64_t pkts_dst, bytes_dst;
-   double rate_bytes_src;
-   double rate_bytes_dst;
-   double rate_pkts_src;
-   double rate_pkts_dst;
int flows_count;
 };
 
@@ -80,8 +84,6 @@ struct flow_entry {
uint32_t ip6_src_addr[4], ip6_dst_addr[4];
uint16_t port_src, port_dst;
uint8_t  tcp_state, tcp_flags, sctp_state, dccp_state;
-   uint64_t pkts_src, bytes_src;
-   uint64_t pkts_dst, bytes_dst;
uint64_t timestamp_start, timestamp_stop;
char country_src[128], country_dst[128];
char country_code_src[4], country_code_dst[4];
@@ -92,10 +94,7 @@ struct flow_entry {
bool is_visible;
struct nf_conntrack *ct;
struct timeval last_update;
-   double rate_bytes_src;
-   double rate_bytes_dst;
-   double rate_pkts_src;
-   double rate_pkts_dst;
+   struct flow_stat stat;
 };
 
 struct flow_list {
@@ -379,8 +378,9 @@ static void flow_entry_update_time(struct flow_entry *n)
bug_on(gettimeofday(>last_update, NULL));
 }
 
-#define CALC_RATE(fld) do {
\
-   n->rate_##fld = (((fld) > n->fld) ? (((fld) - n->fld) / sec) : 0);  
\
+#define CALC_RATE(fld) do {\
+   n->stat.rate_##fld = (((fld) > n->stat.fld) ?   \
+   (((fld) - n->stat.fld) / sec) : 0); \
 } while (0)
 
 static void flow_entry_calc_rate(struct flow_entry *n, const struct 
nf_conntrack *ct)
@@ -556,10 +556,10 @@ static void flow_entry_find_process(struct flow_entry *n)
if (snprintf(p->name, sizeof(p->name), "%s", basename(cmdline)) < 0)
p->name[0] = '\0';
 
-   p->pkts_src += n->pkts_src;
-   p->pkts_dst += n->pkts_dst;
-   p->bytes_src += n->bytes_src;
-   p->bytes_dst += n->bytes_dst;
+   p->stat.pkts_src += n->stat.pkts_src;
+   p->stat.pkts_dst += n->stat.pkts_dst;
+   p->stat.bytes_src += n->stat.bytes_src;
+   p->stat.bytes_dst += n->stat.bytes_dst;
p->flows_count++;
 
cds_list_add(>proc_head, >flows);
@@ -619,10 +619,10 @@ static void flow_entry_from_ct(struct flow_entry *n, 
const struct nf_conntrack *
 
/* Update stats diff to the related process entry */
if (n->proc) {
-   n->proc->pkts_src += pkts_src - n->pkts_src;
-   n->proc->pkts_dst += pkts_dst - n->pkts_dst;
-   n->proc->bytes_src += bytes_src - n->bytes_src;
-   n->proc->bytes_dst += bytes_dst - n->bytes_dst;
+   n->proc->stat.pkts_src += pkts_src - n->stat.pkts_src;
+   n->proc->stat.pkts_dst += pkts_dst - n->stat.pkts_dst;
+   n->proc->stat.bytes_src += bytes_src - n->stat.bytes_src;
+   n->proc->stat.bytes_dst += bytes_dst - n->stat.bytes_dst;
}
 
CP_NFCT(l3_proto, ATTR_ORIG_L3PROTO, 8);
@@ -641,11 +641,11 @@ static void flow_entry_from_ct(struct flow_entry *n, 
const struct nf_conntrack *
CP_NFCT(sctp_state, ATTR_SCTP_STATE, 8);
CP_NFCT(dccp_state, ATTR_DCCP_STATE, 8);
 
-   CP_NFCT(pkts_src, ATTR_ORIG_COUNTER_PACKETS, 64);
-   CP_NFCT(bytes_src, ATTR_ORIG_COUNTER_BYTES, 64);
+   CP_NFCT(stat.pkts_src, ATTR_ORIG_COUNTER_PACKETS, 64);
+   CP_NFCT(stat.bytes_src, ATTR_ORIG_COUNTER_BYTES, 64);
 
-   CP_NFCT(pkts_dst, ATTR_REPL_COUNTER_PACKETS, 64);
-   CP_NFCT(bytes_dst, ATTR_REPL_COUNTER_BYTES, 64);
+   CP_NFCT(stat.pkts_dst, ATTR_REPL_COUNTER_PACKETS, 64);
+   CP_NFCT(stat.bytes_dst, ATTR_REPL_COUNTER_BYTES, 64);
 
CP_NFCT(timestamp_start, ATTR_TIMESTAMP_START, 64);
CP_NFCT(timestamp_stop, ATTR_TIMESTAMP_STOP, 64);
@@ -1014,12 +1014,12 @@ static void print_flow_peer_info(const struct 
flow_entry *n, enum flow_direction
 
/* Bytes */
ui_tab

[netsniff-ng] [PATCH 3/4] trafgen: l7: Add DNS header generation API

2017-06-01 Thread Vadim Kochan
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.

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 | 170 +++
 trafgen_l7.h |  45 +++
 trafgen_proto.c  | 127 +
 trafgen_proto.h  |  19 ++-
 6 files changed, 392 insertions(+), 2 deletions(-)
 create mode 100644 trafgen_l7.c
 create mode 100644 trafgen_l7.h

diff --git a/trafgen/Makefile b/trafgen/Makefile
index 3369d4a..d38f0b0 100644
--- a/trafgen/Makefile
+++ b/trafgen/Makefile
@@ -29,6 +29,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 000..f801677
--- /dev/null
+++ b/trafgen_l7.c
@@ -0,0 +1,170 @@
+/*
+ * 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, .

[netsniff-ng] [PATCH 0/4] Add DNS proto header support

2017-06-01 Thread Vadim Kochan
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.

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.

Add new syntax for DNS header generation via 'dns()' proto function.

The fields are supported:

id  - 16 bit identifier
qr  - message is a query(0) or response(1)
op|oper - specified kind of query
aanswer - authoritative answer flag
trunc   - message was truncated flag
rdesired- recursion desired flag
ravail  - recursion available flag
zero- reserved for future use
rcode   - response code
qdcount - number of entries in question section
ancount - number of entries in answer section
nscount - number of entries in authority section
arcount - number of entries in additional section

Also there are functions to generate DNS sections:

'qry()' function to generate separate query entry:

name- variable domain name
type- type of the query
class   - class of the query

'ans()', 'auth()', 'add'  functions to generate separate answer,
authoritative, adidditional entry with the same fields layout:

name- variable domain name
type- resource record type
class   - class of the data
ttl - time interval that the record may be cached
len - length of data
data- variable length of bytes

All the DNS section entries will be automaticlly sorted by DNS proto API
in the way which is required by DNS header:

query entries
answer entries
authoritative entries
additional entries

'name' field in qry/ans/auth/add functions is automatically converted to
FQDN format if it was specified as "string".

There are also added functions to simplify the way of filling
some often used RR types for using them inside ans/auth/add functions:

addr(ipv4_addr | ipv6_addr) - fills the following RR fields:
len  - 4 or 16 depends on IPv4 or IPv6 address was specified
data - is filled with IPv4 or IPv6 address
type - 1 for IPv4 address, 28 - for IPv6

ns(string)
type - 2

cname(string)
type - 5

ptr(string)
type - 12

EXAMPLES:

{
dns(qr=1,
auth(name="ns1", ns("ns1.org")),
ans(name="www.google.com", cname("google.com")),
auth(name="aa", ns("bb")),
qry(name="www.google.com"))
}

{
dns(qr=1, ans(name="www.google.com", addr(1.2.3.4)))
}

{
dns(qr=1, ans(name="www.google.com", addr(1::)))
}

RFC -> PATCH:
1) Removed empty lines after 'break' in switch blocks
2) Use xmemdupz instead malloc + memcpy
    3) Squash commit with 'len' parameter
4) Do not change 'index' field in proto_hdr struct to 'int.

Vadim Kochan (4):
  trafgen: proto: Allow to set field with variable length
  str: Add function for converting string into DNS name
  trafgen: l7: Add DNS header generation API
  trafgen: parser: Add syntax to generate DNS header

 str.c|  37 +
 str.h|   1 +
 trafgen/Makefile |   1 +
 trafgen_l2.c |   6 +-
 trafgen_l4.c |  32 
 trafgen_l7.c | 170 +
 trafgen_l7.h |  45 +++
 trafgen_lexer.l

[netsniff-ng] [PATCH 4/4] trafgen: parser: Add syntax to generate DNS header

2017-06-01 Thread Vadim Kochan
Add new syntax for DNS header generation via 'dns()' proto function.

The fields are supported:

id  - 16 bit identifier
qr  - message is a query(0) or response(1)
op|oper - specified kind of query
aanswer - authoritative answer flag
trunc   - message was truncated flag
rdesired- recursion desired flag
ravail  - recursion available flag
zero- reserved for future use
rcode   - response code
qdcount - number of entries in question section
ancount - number of entries in answer section
nscount - number of entries in authority section
arcount - number of entries in additional section

Also there are functions to generate DNS sections:

'qry()' function to generate separate query entry:

name- variable domain name
type- type of the query
class   - class of the query

'ans()', 'auth()', 'add'  functions to generate separate answer,
authoritative, adidditional entry with the same fields layout:

name- variable domain name
type- resource record type
class   - class of the data
ttl - time interval that the record may be cached
len - length of data
data- variable length of bytes

All the DNS section entries will be automaticlly sorted by DNS proto API
in the way which is required by DNS header:

query entries
answer entries
authoritative entries
additional entries

'name' field in qry/ans/auth/add functions is automatically converted to
FQDN format if it was specified as "string".

There are also added functions to simplify the way of filling
some often used RR types for using them inside ans/auth/add functions:

addr(ipv4_addr | ipv6_addr) - fills the following RR fields:
len  - 4 or 16 depends on IPv4 or IPv6 address was specified
data - is filled with IPv4 or IPv6 address
type - 1 for IPv4 address, 28 - for IPv6

ns(string)
type - 2

cname(string)
type - 5

ptr(string)
type - 12

EXAMPLES:

{
dns(qr=1,
auth(name="ns1", ns("ns1.org")),
ans(name="www.google.com", cname("google.com")),
auth(name="aa", ns("bb")),
qry(name="www.google.com"))
}

{
dns(qr=1, ans(name="www.google.com", addr(1.2.3.4)))
}

{
dns(qr=1, ans(name="www.google.com", addr(1::)))
}

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen_lexer.l  |  24 +++
 trafgen_parser.y | 193 +++
 2 files changed, 217 insertions(+)

diff --git a/trafgen_lexer.l b/trafgen_lexer.l
index cf67c74..da072e1 100644
--- a/trafgen_lexer.l
+++ b/trafgen_lexer.l
@@ -239,6 +239,29 @@ ip6_addr   
({v680}|{v67}|{v66}|{v65}|{v64}|{v63}|{v62}|{v61}|{v60})
 "win"|"window" { return K_WINDOW; }
 "urgptr"   { return K_URG_PTR; }
 
+   /* DNS */
+"qr"   { return K_QR; }
+"aa"|"aanswer" { return K_AANSWER; }
+"trunc"{ return K_TRUNC; }
+"ravail"   { return K_RAVAIL; }
+"rdesired" { return K_RDESIRED; }
+"zero" { return K_ZERO; }
+"rc"|"rcode"   { return K_RCODE; }
+"qdcount"  { return K_QDCOUNT; }
+"ancount"  { return K_ANCOUNT; }
+"nscount"  { return K_NSCOUNT; }
+"arcount"  { return K_ARCOUNT; }
+"name" { return K_NAME; }
+"class"{ return K_CLASS; }
+"data" { return K_DATA; }
+"qry"|"query"  { return K_QUERY; }
+"ans"|"answer" { return K_ANSWER; }
+"auth" { return K_AUTH; }
+"add"  { return K_ADD; }
+"ns"   { return K_NS; }
+"cname"{ return K_CNAME; }
+"ptr"  { return K_PTR; }
+
 "eth"  { return K_ETH; }
 "pause" { return K_PAUSE; }
 "pfc"  { return K_PFC; }
@@ -251,6 +274,7 @@ ip6_addr
({v680}|{v67}|{v66}|{v65}|{v64}|{v63}|{v62}|{v61}|{v60})
 "icmp6"|"icmpv6"   { return K_ICMP6; }
 "udp"  { return K_UDP; }
 "tcp"  { return K_TCP; }
+"dns"  { return K_DNS; }
 
 [ ]*"-"[ ]*{ return '-'; }
 [ ]*"+"[ ]*{ return '+'; }
diff --git a/trafgen_parser.y b/trafgen_parser.y
index b4eedea..656c4f6 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@

[netsniff-ng] [PATCH 1/4] trafgen: proto: Allow to set field with variable length

2017-06-01 Thread Vadim Kochan
It is quite tricky to set field value with a variable length
(i.e. DNS query name), to make it possible the field
needs to be added to header with 'len=0' in that case there
will be no any payload allocation, but only while setting the field
value the packet will be appended with a real length bytes and after
the field needs to be relocated to the right place.

Also add 'len' parameter to *_set_bytes(...) functoins to have better
control over it.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen_l2.c |   6 ++--
 trafgen_parser.y |   4 +--
 trafgen_proto.c  | 102 +--
 trafgen_proto.h  |   7 ++--
 4 files changed, 85 insertions(+), 34 deletions(-)

diff --git a/trafgen_l2.c b/trafgen_l2.c
index 5fc0a0d..427ff9b 100644
--- a/trafgen_l2.c
+++ b/trafgen_l2.c
@@ -69,7 +69,7 @@ static void pause_header_init(struct proto_hdr *hdr)
struct proto_hdr *lower;
 
lower = proto_lower_default_add(hdr, PROTO_ETH);
-   proto_hdr_field_set_default_bytes(lower, ETH_DST_ADDR, eth_dst);
+   proto_hdr_field_set_default_bytes(lower, ETH_DST_ADDR, eth_dst, 6);
 
proto_header_fields_add(hdr, pause_fields, array_size(pause_fields));
proto_hdr_field_set_default_be16(hdr, PAUSE_OPCODE, 0x1);
@@ -109,7 +109,7 @@ static void pfc_header_init(struct proto_hdr *hdr)
struct proto_hdr *lower;
 
lower = proto_lower_default_add(hdr, PROTO_ETH);
-   proto_hdr_field_set_default_bytes(lower, ETH_DST_ADDR, eth_dst);
+   proto_hdr_field_set_default_bytes(lower, ETH_DST_ADDR, eth_dst, 6);
 
proto_header_fields_add(hdr, pfc_fields, array_size(pfc_fields));
proto_hdr_field_set_default_be16(hdr, PFC_OPCODE, 0x0101);
@@ -180,7 +180,7 @@ static void arp_header_init(struct proto_hdr *hdr)
if (lower->ops->id == PROTO_ETH) {
const uint8_t bcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 
-   proto_hdr_field_set_default_bytes(lower, ETH_DST_ADDR, bcast);
+   proto_hdr_field_set_default_bytes(lower, ETH_DST_ADDR, bcast, 
6);
}
 
proto_header_fields_add(hdr, arp_fields, array_size(arp_fields));
diff --git a/trafgen_parser.y b/trafgen_parser.y
index 5a61a3f..b4eedea 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@@ -433,11 +433,11 @@ static void proto_field_expr_eval(void)
else
panic("Invalid value length %zu, can be 1,2 or 4\n", 
field->len);
} else if (field_expr.type & FIELD_EXPR_MAC) {
-   proto_field_set_bytes(field, field_expr.val.mac);
+   proto_field_set_bytes(field, field_expr.val.mac, 6);
} else if (field_expr.type & FIELD_EXPR_IP4_ADDR) {
proto_field_set_u32(field, field_expr.val.ip4_addr.s_addr);
} else if (field_expr.type & FIELD_EXPR_IP6_ADDR) {
-   proto_field_set_bytes(field, (uint8_t 
*)_expr.val.ip6_addr.s6_addr);
+   proto_field_set_bytes(field, (uint8_t 
*)_expr.val.ip6_addr.s6_addr, 16);
} else if ((field_expr.type & FIELD_EXPR_INC) ||
(field_expr.type & FIELD_EXPR_RND)) {
 
diff --git a/trafgen_proto.c b/trafgen_proto.c
index b802a3a..7969b77 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -100,6 +100,9 @@ void proto_header_fields_add(struct proto_hdr *hdr,
f->pkt_offset = hdr->pkt_offset + fields[i].offset;
f->hdr = hdr;
 
+   if (!f->len)
+   continue;
+
if (f->pkt_offset + f->len > pkt->len) {
hdr->len += f->len;
set_fill(0, (f->pkt_offset + f->len) - pkt->len);
@@ -181,9 +184,48 @@ set_proto:
return current;
 }
 
+static void __proto_field_relocate(struct proto_field *field)
+{
+   struct proto_hdr *hdr = field->hdr;
+   struct packet *pkt = packet_get(hdr->pkt_id);
+   uint8_t *from, *to;
+   int i;
+
+   /* If this is a last field then just calculate 'pkt_offset' */
+   if (field->id == hdr->fields_count - 1) {
+   field->pkt_offset = hdr->pkt_offset + hdr->len - field->len;
+   return;
+   }
+
+   /* Use 'pkt_offset' from the 1st real (len > 0) field after the
+* 'target' one */
+   for (i = field->id + 1; i < hdr->fields_count; i++) {
+   if (hdr->fields[i].len == 0)
+   continue;
+
+   field->pkt_offset = hdr->fields[i].pkt_offset;
+   break;
+   }
+
+   /* Move payload of overlapped fields (each after the 'target' field) */
+   from = >payload[field->pkt_offset];
+   to = >payload[field->pkt_offset + field->len];
+   memcpy(to, from, hdr->len - field->len);
+
+   /* Recalculate 'pkt_offset' of the

[netsniff-ng] [PATCH 2/4] str: Add function for converting string into DNS name

2017-06-01 Thread Vadim Kochan
Add str2fqdn for converting hostname string into DNS name notation:

www..yy.com -> 3www42yy3com0

Returned string must be freed after use by the caller.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 str.c | 37 +
 str.h |  1 +
 2 files changed, 38 insertions(+)

diff --git a/str.c b/str.c
index 532058a..1d3e7ac 100644
--- a/str.c
+++ b/str.c
@@ -160,3 +160,40 @@ int str2mac(const char *str, uint8_t *mac, size_t len)
 
return 0;
 }
+
+char *str2fqdn(const char *str)
+{
+   size_t slen = strlen(str);
+   size_t flen = 0;
+   char *fqdn;
+   char *tmp;
+   char *dup;
+   int i = 0;
+   int c = 0;
+
+   dup = xstrdup(str);
+   tmp = dup;
+
+   fqdn = xzmalloc(slen + 2);
+
+   while (tmp <= dup + slen && c++ <= slen) {
+   if (tmp[i] == '.' || tmp[i] == '\0') {
+   size_t dlen;
+
+   tmp[i] = '\0';
+   dlen = strlen(tmp);
+   fqdn[flen] = dlen;
+   memcpy([flen + 1], tmp, dlen);
+   flen += dlen + 1;
+   tmp += dlen + 1;
+   i = 0;
+
+   continue;
+   }
+
+   i++;
+   }
+
+   xfree(dup);
+   return fqdn;
+}
diff --git a/str.h b/str.h
index 7879af6..a362c53 100644
--- a/str.h
+++ b/str.h
@@ -14,5 +14,6 @@ extern char *argv2str(int startind, int argc, char **argv);
 extern char **argv_insert(char **argv, size_t *count, const char *str);
 extern void argv_free(char **argv);
 extern int str2mac(const char *str, uint8_t *mac, size_t len);
+extern char *str2fqdn(const char *str);
 
 #endif /* STR_H */
-- 
2.12.1

-- 
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.


[netsniff-ng] [PATCH] flowtop: Improve and unify up/down scrolling

2017-05-27 Thread Vadim Kochan
Move scrolling logic to the ui.c module, it requires to have
some data iteration provided in flowtop.c and delegated to ui.c part.

So approach is that now flowtop provides 2 additional callbacks for:

1) Iterate over flows/procs list
2) Draw flow/proc on each iteration which is controlled from ui.c

it allows to unify scrolling logic and delegate it to the ui.c, in the
future it should allow to easy handle press event on selected row and
drow some additional information, or draw a cursor line per selected
row.

Also fixed case when down scrolling was bigger that printed rows, not
it is handled by ui part.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 flowtop.c | 166 --
 ui.c  |  70 +-
 ui.h  |  13 +
 3 files changed, 157 insertions(+), 92 deletions(-)

diff --git a/flowtop.c b/flowtop.c
index 1caae9e..00937e1 100644
--- a/flowtop.c
+++ b/flowtop.c
@@ -118,8 +118,6 @@ enum flow_direction {
 # define ATTR_TIMESTAMP_STOP 64
 #endif
 
-#define SCROLL_MAX 1000
-
 #define INCLUDE_IPV4   (1 << 0)
 #define INCLUDE_IPV6   (1 << 1)
 #define INCLUDE_UDP(1 << 2)
@@ -156,7 +154,6 @@ static struct sysctl_params_ctx sysctl = { -1, -1 };
 
 static unsigned int cols, rows;
 static WINDOW *screen;
-static int skip_lines;
 
 static unsigned int interval = 1;
 static bool show_src = false;
@@ -190,12 +187,25 @@ enum tbl_proc_col {
 
 static struct ui_table flows_tbl;
 static struct ui_table procs_tbl;
+static struct ui_table *curr_tbl;
 
 enum tab_entry {
TAB_FLOWS,
TAB_PROCS,
 };
 
+#define list_first_or_next(__ptr, __head, __entry) \
+({ \
+   struct cds_list_head *h; \
+   if (!__ptr) \
+   h = rcu_dereference((__head)->next); \
+   else if (rcu_dereference(__ptr->__entry.next) == (__head)) \
+   return NULL; \
+   else \
+   h = rcu_dereference(__ptr->__entry.next); \
+   cds_list_entry(h, __typeof(* (__ptr)), __entry); \
+})
+
 static const char *short_options = "vhTUsDIS46ut:nGb";
 static const struct option long_options[] = {
{"ipv4",no_argument,NULL, '4'},
@@ -1013,45 +1023,45 @@ static void print_flow_peer_info(const struct 
flow_entry *n, enum flow_direction
   tmp, sizeof(tmp) - 1));
 }
 
-static void draw_flow_entry(const struct flow_entry *n)
+static void draw_flow_entry(struct ui_table *tbl, const void *data)
 {
+   const struct flow_entry *n = data;
char tmp[128];
 
-   ui_table_row_add(_tbl);
+   ui_table_row_add(tbl);
 
/* Application */
-   ui_table_row_col_set(_tbl, TBL_FLOW_PROCESS,
- n->proc ?  n->proc->name : "");
+   ui_table_row_col_set(tbl, TBL_FLOW_PROCESS, n->proc ? n->proc->name : 
"");
 
/* PID */
slprintf(tmp, sizeof(tmp), "%.d", n->proc ? n->proc->pid : 0);
-   ui_table_row_col_set(_tbl, TBL_FLOW_PID, tmp);
+   ui_table_row_col_set(tbl, TBL_FLOW_PID, tmp);
 
/* L4 protocol */
-   ui_table_row_col_set(_tbl, TBL_FLOW_PROTO, 
l4proto2str[n->l4_proto]);
+   ui_table_row_col_set(tbl, TBL_FLOW_PROTO, l4proto2str[n->l4_proto]);
 
/* L4 protocol state */
-   ui_table_row_col_set(_tbl, TBL_FLOW_STATE, flow_state2str(n));
+   ui_table_row_col_set(tbl, TBL_FLOW_STATE, flow_state2str(n));
 
/* Time */
time2str(n->timestamp_start, tmp, sizeof(tmp));
-   ui_table_row_col_set(_tbl, TBL_FLOW_TIME, tmp);
+   ui_table_row_col_set(tbl, TBL_FLOW_TIME, tmp);
 
print_flow_peer_info(n, show_src ? FLOW_DIR_SRC : FLOW_DIR_DST);
 
-   ui_table_row_show(_tbl);
+   ui_table_row_show(tbl);
 
if (show_src) {
-   ui_table_row_add(_tbl);
+   ui_table_row_add(tbl);
 
-   ui_table_row_col_set(_tbl, TBL_FLOW_PROCESS, "");
-   ui_table_row_col_set(_tbl, TBL_FLOW_PID, "");
-   ui_table_row_col_set(_tbl, TBL_FLOW_PROTO, "");
-   ui_table_row_col_set(_tbl, TBL_FLOW_STATE, "");
-   ui_table_row_col_set(_tbl, TBL_FLOW_TIME, "");
+   ui_table_row_col_set(tbl, TBL_FLOW_PROCESS, "");
+   ui_table_row_col_set(tbl, TBL_FLOW_PID, "");
+   ui_table_row_col_set(tbl, TBL_FLOW_PROTO, "");
+   ui_table_row_col_set(tbl, TBL_FLOW_STATE, "");
+   ui_table_row_col_set(tbl, TBL_FLOW_TIME, "");
 
print_flow_peer_info(n, FLOW_DIR_DST);
-   ui_table_row_show(_tbl);
+   ui_table_row_show(tbl);
}
 }
 
@@ -1115,10 +1125,10 @@ static inline bool presenter_flow_wrong_state(struct 
flow_entry *n)
return true;
 }
 
-static void dra

Re: [netsniff-ng] read 802.1q tags fine, fails to write 802.1q tags to save file

2017-05-19 Thread Vadim Kochan
On Fri, May 19, 2017 at 7:04 AM, max bet <6502...@gmail.com> wrote:

> Hi,
>
> Cool tool.
>
> My environment is ubuntu 16.04 and I have built the most recent
> netsniff-ng from source (Git id: v0.6.3-9-gb463e1f). I have noticed that
> although netsniff-ng does correctly interpret vlan tags without any
> trickery or setting of driver flags and so forth, and dumps to the console
> just fine, generating a save file seems to omit vlan tags completely. Can
> anyone comment on why this would seem to be?
>
> -Mike
>
> --
> 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.
>

Hi Mike,

Looks like you are talking when vlan is offloaded ? So netsniff-ng takes
this info from kernel control message,
and I did not put it into pcap because I decided to keep original packet in
pcap file. But may be this is time to change this ?
Looks like it is expectable to see the VLAN within pcap even if it is
offloaded ?

Daniel, Tobias what do you think ?

Regards,
Vadim Kochan

-- 
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.


[netsniff-ng] [PATCH] trafgen: parser: Use proto_field_set_xxx where it is possible

2017-05-13 Thread Vadim Kochan
Use proto_field_set_xxx(field, ...)  instead of
proto_hdr_field_set_xxx(hdr, fid, ...) to be more generic and do not
depent on 'hdr' variable.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen_parser.y | 13 ++---
 trafgen_proto.c  |  5 +
 trafgen_proto.h  |  1 +
 3 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/trafgen_parser.y b/trafgen_parser.y
index 40cd311..5a61a3f 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@@ -425,20 +425,19 @@ static void proto_field_expr_eval(void)
 
if (field_expr.type & FIELD_EXPR_NUMB) {
if (field->len == 1)
-   proto_hdr_field_set_u8(hdr, field->id, 
field_expr.val.number);
+   proto_field_set_u8(field, field_expr.val.number);
else if (field->len == 2)
-   proto_hdr_field_set_be16(hdr, field->id, 
field_expr.val.number);
+   proto_field_set_be16(field, field_expr.val.number);
else if (field->len == 4)
-   proto_hdr_field_set_be32(hdr, field->id, 
field_expr.val.number);
+   proto_field_set_be32(field, field_expr.val.number);
else
panic("Invalid value length %zu, can be 1,2 or 4\n", 
field->len);
} else if (field_expr.type & FIELD_EXPR_MAC) {
-   proto_hdr_field_set_bytes(hdr, field->id, field_expr.val.mac);
+   proto_field_set_bytes(field, field_expr.val.mac);
} else if (field_expr.type & FIELD_EXPR_IP4_ADDR) {
-   proto_hdr_field_set_u32(hdr, field->id, 
field_expr.val.ip4_addr.s_addr);
+   proto_field_set_u32(field, field_expr.val.ip4_addr.s_addr);
} else if (field_expr.type & FIELD_EXPR_IP6_ADDR) {
-   proto_hdr_field_set_bytes(hdr, field->id,
-   (uint8_t *)_expr.val.ip6_addr.s6_addr);
+   proto_field_set_bytes(field, (uint8_t 
*)_expr.val.ip6_addr.s6_addr);
} else if ((field_expr.type & FIELD_EXPR_INC) ||
(field_expr.type & FIELD_EXPR_RND)) {
 
diff --git a/trafgen_proto.c b/trafgen_proto.c
index 5fd9e1c..b802a3a 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -477,6 +477,11 @@ void proto_field_set_be32(struct proto_field *field, 
uint32_t val)
__proto_field_set_bytes(field, (uint8_t *), false, true);
 }
 
+void proto_field_set_bytes(struct proto_field *field, const uint8_t *bytes)
+{
+   __proto_field_set_bytes(field, bytes, false, false);
+}
+
 void protos_init(const char *dev)
 {
ctx.dev = dev;
diff --git a/trafgen_proto.h b/trafgen_proto.h
index d863287..56e7271 100644
--- a/trafgen_proto.h
+++ b/trafgen_proto.h
@@ -155,6 +155,7 @@ extern void proto_field_set_u32(struct proto_field *field, 
uint32_t val);
 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);
 
 extern void proto_field_func_add(struct proto_field *field,
 struct proto_field_func *func);
-- 
2.12.1

-- 
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.


[netsniff-ng] Re: [RFC 6/7] trafgen: l7: Add DNS header generation API

2017-03-14 Thread Vadim Kochan
On Tue, Mar 14, 2017 at 12:21 PM, Tobias Klauser <tklau...@distanz.ch> wrote:
> 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).
>

Well, I was thinking about this and decided to do so because:

1) I really think that there might be in the future libtrafgen
which will handle sub-headers
 automatically (if it is needed by protocol header) both for
the application and trafgen tool (this
 reason might be not so strict).

2) sub-headers might be a generic way for other protocol headers
like DHCP, WLAN.

Yes, the logic which does sub-headers moving is a bit scary as you
said, not sure if I can re-write it
to simplify it, will try.

Regards,
Vadim Kochan

-- 
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.


[netsniff-ng] Re: [RFC 0/7] Add DNS proto header support

2017-02-21 Thread Vadim Kochan
On Mon, Jan 30, 2017 at 10:33 AM, 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.
>
> 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.
>
> Add new syntax for DNS header generation via 'dns()' proto function.
>
> The fields are supported:
>
> id  - 16 bit identifier
> qr  - message is a query(0) or response(1)
> op|oper - specified kind of query
> aanswer - authoritative answer flag
> trunc   - message was truncated flag
> rdesired- recursion desired flag
> ravail  - recursion available flag
> zero- reserved for future use
> rcode   - response code
> qdcount - number of entries in question section
> ancount - number of entries in answer section
> nscount - number of entries in authority section
> arcount - number of entries in additional section
>
> Also there are functions to generate DNS sections:
>
> 'qry()' function to generate separate query entry:
>
> name- variable domain name
> type- type of the query
> class   - class of the query
>
> 'ans()', 'auth()', 'add'  functions to generate separate answer,
> authoritative, adidditional entry with the same fields layout:
>
> name- variable domain name
> type- resource record type
> class   - class of the data
> ttl - time interval that the record may be cached
> len - length of data
> data- variable length of bytes
>
> All the DNS section entries will be automaticlly sorted by DNS proto API
> in the way which is required by DNS header:
>
> query entries
> answer entries
> authoritative entries
> additional entries
>
> 'name' field in qry/ans/auth/add functions is automatically converted to
> FQDN format if it was specified as "string".
>
> There are also added functions to simplify the way of filling
> some often used RR types for using them inside ans/auth/add functions:
>
> addr(ipv4_addr | ipv6_addr) - fills the following RR fields:
> len  - 4 or 16 depends on IPv4 or IPv6 address was specified
> data - is filled with IPv4 or IPv6 address
> type - 1 for IPv4 address, 28 - for IPv6
>
> ns(string)
> type - 2
>
> cname(string)
> type - 5
>
> ptr(string)
> type - 12
>
> EXAMPLES:
>
> {
> dns(qr=1,
> auth(name="ns1", ns("ns1.org")),
> ans(name="www.google.com", cname("google.com")),
> auth(name="aa", ns("bb")),
> qry(name="www.google.com"))
> }
>
> {
> dns(qr=1, ans(name="www.google.com", addr(1.2.3.4)))
> }
>
> {
> dns(qr=1, ans(name="www.google.com", addr(1::)))
> }
>
> Vadim Kochan (7):
>   trafgen: parser: Rename bytes -> mac
>   trafgen: proto: Add 'len' parameter to *_set_bytes(...) functions
>   trafgen: prot

[netsniff-ng] Re: [RFC 4/7] trafgen: parser: Use proto_field_set_xxx where it is possible

2017-02-13 Thread Vadim Kochan
On Mon, Feb 13, 2017 at 11:18 AM, Tobias Klauser <tklau...@distanz.ch> wrote:
> On 2017-01-30 at 09:33:27 +0100, Vadim Kochan <vadi...@gmail.com> wrote:
>> Use proto_field_set_xxx(field, ...)  instead of
>> proto_hdr_field_set_xxx(hdr, fid, ...) to be more generic and do not
>> depent on 'hdr' variable.
>>
>> Signed-off-by: Vadim Kochan <vadi...@gmail.com>
>
> This does not strictly need to be part of this series but the patch in
> itself makes sense. Care to resend it separately based on master?

Hm, it has some dependencies from previous patches in this series so,
may be I will send it after
the series will be appliead, at least the parser's part.

-- 
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.


[netsniff-ng] Re: [RFC 2/7] trafgen: proto: Add 'len' parameter to *_set_bytes(...) functions

2017-02-09 Thread Vadim Kochan
On Thu, Feb 9, 2017 at 1:02 PM, Tobias Klauser <tklau...@distanz.ch> wrote:
> On 2017-01-30 at 09:33:25 +0100, Vadim Kochan <vadi...@gmail.com> wrote:
>> Add 'len' parameter to *_set_bytes(...) functoins to have better
>> control over it.
>
> While this is certainly a good idea (and you are also going to use it in
> the following patch), the current patch doesn't use the passed len
> parameter, so it's rather pointless standalone. I suggest you also use
> it in __proto_field_set_bytes to check against field->len.

Yes, then I will just join it with the next patch.

-- 
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.


[netsniff-ng] [PATCH v2 1/3] pcap_io: Add function to get packet timestamp

2017-02-07 Thread Vadim Kochan
Add pcap_get_tstamp(...) function to get packet's timestamp considering
different packet types & bytes order.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 pcap_io.h | 53 +
 1 file changed, 53 insertions(+)

diff --git a/pcap_io.h b/pcap_io.h
index 4e41362..3d70b21 100644
--- a/pcap_io.h
+++ b/pcap_io.h
@@ -373,6 +373,59 @@ static inline void pcap_set_length(pcap_pkthdr_t *phdr, 
enum pcap_type type, u32
}
 }
 
+static inline void pcap_get_tstamp(pcap_pkthdr_t *phdr, enum pcap_type type,
+  struct timespec *ts)
+{
+   switch (type) {
+   case DEFAULT:
+   case DEFAULT_LL:
+   ts->tv_sec = phdr->ppo.ts.tv_sec;
+   ts->tv_nsec = phdr->ppo.ts.tv_usec * 1000;
+   break;
+
+   case DEFAULT_SWAPPED:
+   case DEFAULT_LL_SWAPPED:
+   ts->tv_sec = ___constant_swab32(phdr->ppo.ts.tv_sec);
+   ts->tv_nsec = ___constant_swab32(phdr->ppo.ts.tv_usec) * 1000;;
+   break;
+
+   case NSEC:
+   case NSEC_LL:
+   ts->tv_sec = phdr->ppn.ts.tv_sec;
+   ts->tv_nsec = phdr->ppn.ts.tv_nsec / 1000;
+   break;
+
+   case NSEC_SWAPPED:
+   case NSEC_LL_SWAPPED:
+   ts->tv_sec = ___constant_swab32(phdr->ppn.ts.tv_sec);
+   ts->tv_nsec = ___constant_swab32(phdr->ppn.ts.tv_nsec);
+   break;
+
+   case KUZNETZOV:
+   ts->tv_sec = phdr->ppk.ts.tv_sec;
+   ts->tv_nsec = phdr->ppk.ts.tv_usec;
+   break;
+
+   case KUZNETZOV_SWAPPED:
+   ts->tv_sec = ___constant_swab32(phdr->ppk.ts.tv_sec);
+   ts->tv_nsec = ___constant_swab32(phdr->ppk.ts.tv_usec);
+   break;
+
+   case BORKMANN:
+   ts->tv_sec = phdr->ppb.ts.tv_sec;
+   ts->tv_nsec = phdr->ppb.ts.tv_nsec;
+   break;
+
+   case BORKMANN_SWAPPED:
+   ts->tv_sec = ___constant_swab32(phdr->ppb.ts.tv_sec);
+   ts->tv_nsec = ___constant_swab32(phdr->ppb.ts.tv_nsec);
+   break;
+
+   default:
+   bug();
+   }
+}
+
 static inline u32 pcap_get_hdr_length(pcap_pkthdr_t *phdr, enum pcap_type type)
 {
switch (type) {
-- 
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.


[netsniff-ng] [PATCH v2 3/3] trafgen: man: Add description with pcap file for -i, --in option

2017-02-07 Thread Vadim Kochan
Update -i, --in option with pcap file as input parameter.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen.8 | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/trafgen.8 b/trafgen.8
index e09b7a0..fd9788a 100644
--- a/trafgen.8
+++ b/trafgen.8
@@ -66,10 +66,13 @@ given scenario.
 .PP
 .SH OPTIONS
 .PP
-.SS -i <cfg|->, -c <cfg|i>, --in <cfg|->, --conf <cfg|->
+.SS -i <cfg|pcap|->, -c <cfg|->, --in <cfg|pcap|->, --conf <cfg|->
 Defines the input configuration file that can either be passed as a normal 
plain
 text file or via stdin (''-''). Note that currently, if a configuration is
 passed through stdin, only 1 CPU will be used.
+It is also possible to specify PCAP file with .pcap extension via -i,--in 
option,
+by default packets will be sent at rate considering timestamp from PCAP file 
which
+might be reset via -b/-t options.
 .PP
 .SS -o , -d , --out , --dev 
 Defines the outgoing networking device such as eth0, wlan0 and others.
-- 
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.


[netsniff-ng] [PATCH v2 0/3] trafgen: Send packets from pcap file

2017-02-07 Thread Vadim Kochan
Allow to send packets at specified rate from ".pcap" file
which might be speified via -i,--in options.

By default packets will be send at original rate considering packet's
timestamp.

v2:
1) Use timespec in pcap_get_tstamp(...)
2) Use ctx.pcap_in char * member to check if input pcap
   file was specified.
3) Replace strcmp("0", ...) to 'if (!rate)'

BTW, shaper still works at usec minimum time precision so I did not convert
it to nsec yet, but I plan to do it in future patches if it is OK.

Vadim Kochan (3):
  pcap_io: Add function to get packet timestamp
  trafgen: Allow send packets from pcap file
  trafgen: man: Add description with pcap file for -i, --in option

 pcap_io.h|  53 ++
 trafgen.8|   5 +-
 trafgen.c| 166 +++
 trafgen/Makefile |   4 ++
 trafgen_conf.h   |   3 +
 trafgen_parser.y |   2 +-
 6 files changed, 197 insertions(+), 36 deletions(-)

-- 
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.


[netsniff-ng] [PATCH v2 2/3] trafgen: Allow send packets from pcap file

2017-02-07 Thread Vadim Kochan
Add ability to send packets from pcap file if it has
".pcap" extension via "-i,--in" option.

By default packet sending is delayed considering original
packets timestamps if no rate or delay is specified via -b/-t options.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen.c| 166 +++
 trafgen/Makefile |   4 ++
 trafgen_conf.h   |   3 +
 trafgen_parser.y |   2 +-
 4 files changed, 140 insertions(+), 35 deletions(-)

diff --git a/trafgen.c b/trafgen.c
index 524b260..b25760f 100644
--- a/trafgen.c
+++ b/trafgen.c
@@ -5,6 +5,8 @@
  * Subject to the GPL, version 2.
  */
 
+#define _GNU_SOURCE
+
 #include 
 #include 
 #include 
@@ -16,7 +18,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -55,27 +56,24 @@
 #include "ring_tx.h"
 #include "csum.h"
 #include "trafgen_proto.h"
-
-#ifndef timeval_to_timespec
-#define timeval_to_timespec(tv, ts) { \
-   (ts)->tv_sec = (tv)->tv_sec;  \
-   (ts)->tv_nsec = (tv)->tv_usec * 1000; \
-}
-#endif
+#include "pcap_io.h"
 
 enum shaper_type {
SHAPER_NONE,
+   SHAPER_DELAY,
SHAPER_PKTS,
SHAPER_BYTES,
+   SHAPER_TSTAMP,
 };
 
 struct shaper {
enum shaper_type type;
unsigned long long sent;
unsigned long long rate;
+   struct timeval tstamp;
+   struct timespec delay;
struct timeval start;
struct timeval end;
-   struct timespec delay;
 };
 
 struct ctx {
@@ -88,6 +86,7 @@ struct ctx {
struct sockaddr_in dest;
struct shaper sh;
char *packet_str;
+   char *pcap_in;
 };
 
 struct cpu_stats {
@@ -556,15 +555,12 @@ static int xmit_smoke_probe(int icmp_sock, struct ctx 
*ctx)
 
 static bool shaper_is_set(struct shaper *sh)
 {
-   if ((sh->delay.tv_sec | sh->delay.tv_nsec) > 0)
-   return true;
-
-   return sh->type != SHAPER_NONE;
+   return sh->type != SHAPER_NONE;
 }
 
 static void shaper_init(struct shaper *sh)
 {
-   if (sh->type == SHAPER_NONE)
+   if (sh->type == SHAPER_NONE || sh->type == SHAPER_DELAY)
return;
 
memset(>delay, 0, sizeof(struct timespec));
@@ -574,6 +570,12 @@ static void shaper_init(struct shaper *sh)
 
 static void shaper_set_delay(struct shaper *sh, time_t sec, long int ns)
 {
+   if (!(sec | ns)) {
+   sh->type = SHAPER_NONE;
+   return;
+   }
+
+   sh->type = SHAPER_DELAY;
sh->delay.tv_sec = sec;
sh->delay.tv_nsec = ns;
 }
@@ -586,23 +588,49 @@ static void shaper_set_rate(struct shaper *sh, unsigned 
long long rate,
sh->type = type;
 }
 
-static void shaper_delay(struct shaper *sh, unsigned long pkt_len)
+static void shaper_set_tstamp(struct shaper *sh, struct timespec *ts)
+{
+   TIMESPEC_TO_TIMEVAL(>tstamp, ts);
+}
+
+static void shaper_delay(struct shaper *sh, struct packet *pkt)
 {
-   if (sh->type != SHAPER_NONE)
+   if (sh->type == SHAPER_BYTES || sh->type == SHAPER_PKTS) {
+   unsigned long pkt_len = pkt->len;
+
sh->sent += sh->type == SHAPER_BYTES ? pkt_len : 1;
 
-   if (sh->sent >= sh->rate && sh->rate > 0) {
-   struct timeval delay_us;
-   struct timeval time_sent;
-   struct timeval time_1s = { .tv_sec = 1 };
+   if (sh->sent >= sh->rate && sh->rate > 0) {
+   struct timeval delay_us;
+   struct timeval time_sent;
+   struct timeval time_1s = { .tv_sec = 1 };
+
+   bug_on(gettimeofday(>end, NULL));
+   timersub(>end, >start, _sent);
+
+   if (timercmp(_1s, _sent, > )) {
+   timersub(_1s, _sent, _us);
+   TIMEVAL_TO_TIMESPEC(_us, >delay);
+   }
+   }
+   } else if (sh->type == SHAPER_TSTAMP) {
+   struct timeval tstamp;
+   struct timeval pkt_diff;
+   struct timeval diff;
 
bug_on(gettimeofday(>end, NULL));
-   timersub(>end, >start, _sent);
+   TIMESPEC_TO_TIMEVAL(, >tstamp);
+   timersub(>end, >start, );
+   timersub(, >tstamp, _diff);
+
+   if (timercmp(, _diff, <)) {
+   struct timeval delay;
 
-   if (timercmp(_1s, _sent, > )) {
-   timersub(_1s, _sent, _us);
-   timeval_to_timespec(_us, >delay);
+   timersub(_diff, , );
+   TIMEVAL_TO_TIMESPEC(, >delay);
}
+
+   memcpy(>tstamp, , sizeof

[netsniff-ng] [PATCH v2] trafgen: l3: Make possible to send frames via tun device

2017-02-06 Thread Vadim Kochan
tun interface does not have Ethernet header so lets push Ethernet
header only if device supports this.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen_l3.c| 15 ---
 trafgen_proto.c |  5 +
 trafgen_proto.h |  2 ++
 3 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/trafgen_l3.c b/trafgen_l3.c
index 70aefb9..7c8a786 100644
--- a/trafgen_l3.c
+++ b/trafgen_l3.c
@@ -3,9 +3,10 @@
  * Subject to the GPL, version 2.
  */
 
-#include 
+#include 
 
 #include "die.h"
+#include "dev.h"
 #include "csum.h"
 #include "built_in.h"
 #include "trafgen_l2.h"
@@ -34,7 +35,11 @@ static struct proto_field ipv4_fields[] = {
 
 static void ipv4_header_init(struct proto_hdr *hdr)
 {
-   proto_lower_default_add(hdr, PROTO_ETH);
+   const char *dev = proto_dev_get();
+
+   /* In case of tun interface we do not need to create Ethernet header */
+   if (dev && device_mtu(dev) && device_type(dev) != ARPHRD_NONE)
+   proto_lower_default_add(hdr, PROTO_ETH);
 
proto_header_fields_add(hdr, ipv4_fields, array_size(ipv4_fields));
 
@@ -135,7 +140,11 @@ static struct proto_field ipv6_fields[] = {
 
 static void ipv6_header_init(struct proto_hdr *hdr)
 {
-   proto_lower_default_add(hdr, PROTO_ETH);
+   const char *dev = proto_dev_get();
+
+   /* In case of tun interface we do not need to create Ethernet header */
+   if (dev && device_mtu(dev) && device_type(dev) != ARPHRD_NONE)
+   proto_lower_default_add(hdr, PROTO_ETH);
 
proto_header_fields_add(hdr, ipv6_fields, array_size(ipv6_fields));
 
diff --git a/trafgen_proto.c b/trafgen_proto.c
index 88e0846..5fd9e1c 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -609,3 +609,8 @@ void proto_field_dyn_apply(struct proto_field *field)
if (field->hdr->ops->field_changed)
field->hdr->ops->field_changed(field);
 }
+
+const char *proto_dev_get(void)
+{
+   return ctx.dev;
+}
diff --git a/trafgen_proto.h b/trafgen_proto.h
index 29d68db..d863287 100644
--- a/trafgen_proto.h
+++ b/trafgen_proto.h
@@ -159,4 +159,6 @@ extern void proto_field_set_be32(struct proto_field *field, 
uint32_t val);
 extern void proto_field_func_add(struct proto_field *field,
 struct proto_field_func *func);
 
+extern const char *proto_dev_get(void);
+
 #endif /* TRAFGEN_PROTO_H */
-- 
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.


[netsniff-ng] [PATCH] geoip: Fix memory leak when using GeoIPRecord

2017-02-04 Thread Vadim Kochan
GeoIP_record_by_ipnum{,_v6} returns allocated pointer to
GeoIPRecord with allocated city, region & postal_code which is
not freed after the call.

Fixed by xstrdup-ing required GeoIPRecord member (city/region) and
after calling GeoIPRecord_delete to free the geoip record.

Ofcourse it is needed to also free obtained city/region in netsniff-ng,
astraceroute & flowtop tools.

Fixes: #169
Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 astraceroute.c |  10 -
 flowtop.c  |   4 +-
 geoip.c| 114 +
 geoip.h|   8 ++--
 proto_ipv4.c   |  19 +++---
 proto_ipv6.c   |  19 +++---
 6 files changed, 141 insertions(+), 33 deletions(-)

diff --git a/astraceroute.c b/astraceroute.c
index 98b97e4..ca47ba0 100644
--- a/astraceroute.c
+++ b/astraceroute.c
@@ -457,7 +457,8 @@ static void handle_ipv4(uint8_t *packet, size_t len 
__maybe_unused,
struct iphdr *iph = (struct iphdr *) packet;
struct sockaddr_in sd;
struct hostent *hent;
-   const char *as, *country, *city;
+   const char *as, *country;
+   char *city;
 
memset(hbuff, 0, sizeof(hbuff));
memset(, 0, sizeof(sd));
@@ -489,6 +490,8 @@ static void handle_ipv4(uint8_t *packet, size_t len 
__maybe_unused,
}
if (latitude)
printf(" (%f/%f)", geoip4_latitude(), geoip4_longitude());
+
+   free(city);
 }
 
 static int check_ipv6(uint8_t *packet, size_t len, int ttl __maybe_unused,
@@ -524,7 +527,8 @@ static void handle_ipv6(uint8_t *packet, size_t len 
__maybe_unused,
struct ip6_hdr *ip6h = (struct ip6_hdr *) packet;
struct sockaddr_in6 sd;
struct hostent *hent;
-   const char *as, *country, *city;
+   const char *as, *country;
+   char *city;
 
memset(hbuff, 0, sizeof(hbuff));
memset(, 0, sizeof(sd));
@@ -556,6 +560,8 @@ static void handle_ipv6(uint8_t *packet, size_t len 
__maybe_unused,
}
if (latitude)
printf(" (%f/%f)", geoip6_latitude(), geoip6_longitude());
+
+   free(city);
 }
 
 static void show_trace_info(struct ctx *ctx, const struct sockaddr_storage *ss,
diff --git a/flowtop.c b/flowtop.c
index 2491de7..1caae9e 100644
--- a/flowtop.c
+++ b/flowtop.c
@@ -682,7 +682,7 @@ flow_entry_geo_city_lookup_generic(struct flow_entry *n,
 {
struct sockaddr_in sa4;
struct sockaddr_in6 sa6;
-   const char *city = NULL;
+   char *city = NULL;
 
switch (n->l3_proto) {
default:
@@ -706,6 +706,8 @@ flow_entry_geo_city_lookup_generic(struct flow_entry *n,
sizeof(n->city_src));
else
SELFLD(dir, city_src, city_dst)[0] = '\0';
+
+   free(city);
 }
 
 static void
diff --git a/geoip.c b/geoip.c
index 917b1a7..d95305c 100644
--- a/geoip.c
+++ b/geoip.c
@@ -73,8 +73,6 @@ static GeoIP *gi4_asname = NULL, *gi6_asname = NULL;
 static GeoIP *gi4_country = NULL, *gi6_country = NULL;
 static GeoIP *gi4_city = NULL, *gi6_city = NULL;
 
-static GeoIPRecord empty = { NULL };
-
 static char *servers[16] = { NULL };
 
 #define CITYV4 (1 << 0)
@@ -261,14 +259,14 @@ static GeoIPRecord *geoip4_get_record(struct sockaddr_in 
*sa)
 {
bug_on(gi4_city == NULL);
 
-   return GeoIP_record_by_ipnum(gi4_city, ntohl(sa->sin_addr.s_addr)) ? : 

+   return GeoIP_record_by_ipnum(gi4_city, ntohl(sa->sin_addr.s_addr));
 }
 
 static GeoIPRecord *geoip6_get_record(struct sockaddr_in6 *sa)
 {
bug_on(gi6_city == NULL);
 
-   return GeoIP_record_by_ipnum_v6(gi6_city, sa->sin6_addr) ? : 
+   return GeoIP_record_by_ipnum_v6(gi6_city, sa->sin6_addr);
 }
 
 const char *geoip4_as_name(struct sockaddr_in *sa)
@@ -287,42 +285,126 @@ const char *geoip6_as_name(struct sockaddr_in6 *sa)
 
 float geoip4_longitude(struct sockaddr_in *sa)
 {
-   return geoip4_get_record(sa)->longitude;
+   GeoIPRecord *record;
+   float longitude;
+
+   record = geoip4_get_record(sa);
+   if (!record)
+   return 0;
+
+   longitude = record->longitude;
+
+   GeoIPRecord_delete(record);
+   return longitude;
 }
 
 float geoip4_latitude(struct sockaddr_in *sa)
 {
-   return geoip4_get_record(sa)->latitude;
+   GeoIPRecord *record;
+   float latitude;
+
+   record = geoip4_get_record(sa);
+   if (!record)
+   return 0;
+
+   latitude = record->latitude;
+
+   GeoIPRecord_delete(record);
+   return latitude;
 }
 
 float geoip6_longitude(struct sockaddr_in6 *sa)
 {
-   return geoip6_get_record(sa)->longitude;
+   GeoIPRecord *record;
+   float longitude;
+
+   record = geoip6_get_record(sa);
+   if (!record)
+   return 0;
+
+   longitude = record->longitude;
+
+   GeoIPRecord_delete(record);
+   return longitude;
 }
 
 float geoip6_latitude(struct sockaddr_in6

[netsniff-ng] Re: [PATCH] trafgen: l3: Make possible to send frames via tun device

2017-02-01 Thread Vadim Kochan
On Thu, Feb 2, 2017 at 6:37 AM, Vadim Kochan <vadi...@gmail.com> wrote:
> tun interface does not have Ethernet header so lets push Ethernet
> header only if device supports this.
>
> Signed-off-by: Vadim Kochan <vadi...@gmail.com>
> ---
>  dev.c   | 18 ++
>  dev.h   |  4 
>  trafgen_l3.c| 15 ---
>  trafgen_proto.c |  5 +
>  trafgen_proto.h |  2 ++
>  5 files changed, 41 insertions(+), 3 deletions(-)
>
> diff --git a/dev.c b/dev.c
> index 2960976..8442c5e 100644
> --- a/dev.c
> +++ b/dev.c
> @@ -430,3 +430,21 @@ const char *device_addr2str(const unsigned char *addr, 
> int alen, int type,
>
> return buf;
>  }
> +
> +bool device_is_ether(const char *ifname)
> +{
> +   switch (device_type(ifname)) {
> +   case ARPHRD_TUNNEL:
> +   case ARPHRD_TUNNEL6:
> +   case ARPHRD_LOOPBACK:
> +   case ARPHRD_SIT:
> +   case ARPHRD_IPDDP:
> +   case ARPHRD_IPGRE:
> +   case ARPHRD_IP6GRE:
> +   case ARPHRD_ETHER:
> +   return true;
> +
> +   default:
> +   return false;
> +   }
> +}
> diff --git a/dev.h b/dev.h
> index 06e51d2..6b56fe0 100644
> --- a/dev.h
> +++ b/dev.h
> @@ -1,6 +1,7 @@
>  #ifndef DEV_H
>  #define DEV_H
>
> +#include 
>  #include 
>  #include "built_in.h"
>
> @@ -19,4 +20,7 @@ extern void device_leave_promiscuous_mode(const char 
> *ifname, short oldflags);
>  extern const char *device_type2str(uint16_t type);
>  extern const char *device_addr2str(const unsigned char *addr, int alen, int 
> type,
>char *buf, int blen);
> +
> +extern bool device_is_ether(const char *ifname);
> +
>  #endif /* DEV_H */
> diff --git a/trafgen_l3.c b/trafgen_l3.c
> index 70aefb9..62a7708 100644
> --- a/trafgen_l3.c
> +++ b/trafgen_l3.c
> @@ -3,9 +3,10 @@
>   * Subject to the GPL, version 2.
>   */
>
> -#include 
> +#include 
>
>  #include "die.h"
> +#include "dev.h"
>  #include "csum.h"
>  #include "built_in.h"
>  #include "trafgen_l2.h"
> @@ -34,7 +35,11 @@ static struct proto_field ipv4_fields[] = {
>
>  static void ipv4_header_init(struct proto_hdr *hdr)
>  {
> -   proto_lower_default_add(hdr, PROTO_ETH);
> +   const char *dev = proto_dev_get();
> +
> +   /* In case of tun interface we do not need to create Ethernet header 
> */
> +   if (dev && device_mtu(dev) && device_is_ether(dev))
> +   proto_lower_default_add(hdr, PROTO_ETH);
>

But may be it is better to just check if device_type(dev) != ARPHRD_NONE ?

-- 
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.


[netsniff-ng] [PATCH] trafgen: l3: Make possible to send frames via tun device

2017-02-01 Thread Vadim Kochan
tun interface does not have Ethernet header so lets push Ethernet
header only if device supports this.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 dev.c   | 18 ++
 dev.h   |  4 
 trafgen_l3.c| 15 ---
 trafgen_proto.c |  5 +
 trafgen_proto.h |  2 ++
 5 files changed, 41 insertions(+), 3 deletions(-)

diff --git a/dev.c b/dev.c
index 2960976..8442c5e 100644
--- a/dev.c
+++ b/dev.c
@@ -430,3 +430,21 @@ const char *device_addr2str(const unsigned char *addr, int 
alen, int type,
 
return buf;
 }
+
+bool device_is_ether(const char *ifname)
+{
+   switch (device_type(ifname)) {
+   case ARPHRD_TUNNEL:
+   case ARPHRD_TUNNEL6:
+   case ARPHRD_LOOPBACK:
+   case ARPHRD_SIT:
+   case ARPHRD_IPDDP:
+   case ARPHRD_IPGRE:
+   case ARPHRD_IP6GRE:
+   case ARPHRD_ETHER:
+   return true;
+
+   default:
+   return false;
+   }
+}
diff --git a/dev.h b/dev.h
index 06e51d2..6b56fe0 100644
--- a/dev.h
+++ b/dev.h
@@ -1,6 +1,7 @@
 #ifndef DEV_H
 #define DEV_H
 
+#include 
 #include 
 #include "built_in.h"
 
@@ -19,4 +20,7 @@ extern void device_leave_promiscuous_mode(const char *ifname, 
short oldflags);
 extern const char *device_type2str(uint16_t type);
 extern const char *device_addr2str(const unsigned char *addr, int alen, int 
type,
   char *buf, int blen);
+
+extern bool device_is_ether(const char *ifname);
+
 #endif /* DEV_H */
diff --git a/trafgen_l3.c b/trafgen_l3.c
index 70aefb9..62a7708 100644
--- a/trafgen_l3.c
+++ b/trafgen_l3.c
@@ -3,9 +3,10 @@
  * Subject to the GPL, version 2.
  */
 
-#include 
+#include 
 
 #include "die.h"
+#include "dev.h"
 #include "csum.h"
 #include "built_in.h"
 #include "trafgen_l2.h"
@@ -34,7 +35,11 @@ static struct proto_field ipv4_fields[] = {
 
 static void ipv4_header_init(struct proto_hdr *hdr)
 {
-   proto_lower_default_add(hdr, PROTO_ETH);
+   const char *dev = proto_dev_get();
+
+   /* In case of tun interface we do not need to create Ethernet header */
+   if (dev && device_mtu(dev) && device_is_ether(dev))
+   proto_lower_default_add(hdr, PROTO_ETH);
 
proto_header_fields_add(hdr, ipv4_fields, array_size(ipv4_fields));
 
@@ -135,7 +140,11 @@ static struct proto_field ipv6_fields[] = {
 
 static void ipv6_header_init(struct proto_hdr *hdr)
 {
-   proto_lower_default_add(hdr, PROTO_ETH);
+   const char *dev = proto_dev_get();
+
+   /* In case of tun interface we do not need to create Ethernet header */
+   if (dev && device_mtu(dev) && device_is_ether(dev))
+   proto_lower_default_add(hdr, PROTO_ETH);
 
proto_header_fields_add(hdr, ipv6_fields, array_size(ipv6_fields));
 
diff --git a/trafgen_proto.c b/trafgen_proto.c
index 88e0846..5fd9e1c 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -609,3 +609,8 @@ void proto_field_dyn_apply(struct proto_field *field)
if (field->hdr->ops->field_changed)
field->hdr->ops->field_changed(field);
 }
+
+const char *proto_dev_get(void)
+{
+   return ctx.dev;
+}
diff --git a/trafgen_proto.h b/trafgen_proto.h
index 29d68db..d863287 100644
--- a/trafgen_proto.h
+++ b/trafgen_proto.h
@@ -159,4 +159,6 @@ extern void proto_field_set_be32(struct proto_field *field, 
uint32_t val);
 extern void proto_field_func_add(struct proto_field *field,
 struct proto_field_func *func);
 
+extern const char *proto_dev_get(void);
+
 #endif /* TRAFGEN_PROTO_H */
-- 
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.


[netsniff-ng] [PATCH 2/3] trafgen: Allow send packets from pcap file

2017-01-31 Thread Vadim Kochan
Add ability to send packets from pcap file if it has
".pcap" extension via "-i,--in" option.

By default packet sending is delayed considering original
packets timestamps if no rate or delay is specified via -b/-t options.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen.c| 155 +--
 trafgen/Makefile |   4 ++
 trafgen_conf.h   |   3 ++
 trafgen_parser.y |   2 +-
 4 files changed, 137 insertions(+), 27 deletions(-)

diff --git a/trafgen.c b/trafgen.c
index 524b260..c0d77a3 100644
--- a/trafgen.c
+++ b/trafgen.c
@@ -5,6 +5,8 @@
  * Subject to the GPL, version 2.
  */
 
+#define _GNU_SOURCE
+
 #include 
 #include 
 #include 
@@ -16,7 +18,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -55,6 +56,7 @@
 #include "ring_tx.h"
 #include "csum.h"
 #include "trafgen_proto.h"
+#include "pcap_io.h"
 
 #ifndef timeval_to_timespec
 #define timeval_to_timespec(tv, ts) { \
@@ -65,14 +67,17 @@
 
 enum shaper_type {
SHAPER_NONE,
+   SHAPER_DELAY,
SHAPER_PKTS,
SHAPER_BYTES,
+   SHAPER_TSTAMP,
 };
 
 struct shaper {
enum shaper_type type;
unsigned long long sent;
unsigned long long rate;
+   struct timeval tstamp;
struct timeval start;
struct timeval end;
struct timespec delay;
@@ -88,6 +93,7 @@ struct ctx {
struct sockaddr_in dest;
struct shaper sh;
char *packet_str;
+   char *pcap_in;
 };
 
 struct cpu_stats {
@@ -556,15 +562,12 @@ static int xmit_smoke_probe(int icmp_sock, struct ctx 
*ctx)
 
 static bool shaper_is_set(struct shaper *sh)
 {
-   if ((sh->delay.tv_sec | sh->delay.tv_nsec) > 0)
-   return true;
-
-   return sh->type != SHAPER_NONE;
+   return sh->type != SHAPER_NONE;
 }
 
 static void shaper_init(struct shaper *sh)
 {
-   if (sh->type == SHAPER_NONE)
+   if (sh->type == SHAPER_NONE || sh->type == SHAPER_DELAY)
return;
 
memset(>delay, 0, sizeof(struct timespec));
@@ -574,6 +577,12 @@ static void shaper_init(struct shaper *sh)
 
 static void shaper_set_delay(struct shaper *sh, time_t sec, long int ns)
 {
+   if (!(sec | ns)) {
+   sh->type = SHAPER_NONE;
+   return;
+   }
+
+   sh->type = SHAPER_DELAY;
sh->delay.tv_sec = sec;
sh->delay.tv_nsec = ns;
 }
@@ -586,23 +595,48 @@ static void shaper_set_rate(struct shaper *sh, unsigned 
long long rate,
sh->type = type;
 }
 
-static void shaper_delay(struct shaper *sh, unsigned long pkt_len)
+static void shaper_set_tstamp(struct shaper *sh, struct timeval *tv)
 {
-   if (sh->type != SHAPER_NONE)
+   sh->tstamp.tv_sec = tv->tv_sec;
+   sh->tstamp.tv_usec = tv->tv_usec;
+}
+
+static void shaper_delay(struct shaper *sh, struct packet *pkt)
+{
+   if (sh->type == SHAPER_BYTES || sh->type == SHAPER_PKTS) {
+   unsigned long pkt_len = pkt->len;
+
sh->sent += sh->type == SHAPER_BYTES ? pkt_len : 1;
 
-   if (sh->sent >= sh->rate && sh->rate > 0) {
-   struct timeval delay_us;
-   struct timeval time_sent;
-   struct timeval time_1s = { .tv_sec = 1 };
+   if (sh->sent >= sh->rate && sh->rate > 0) {
+   struct timeval delay_us;
+   struct timeval time_sent;
+   struct timeval time_1s = { .tv_sec = 1 };
+
+   bug_on(gettimeofday(>end, NULL));
+   timersub(>end, >start, _sent);
+
+   if (timercmp(_1s, _sent, > )) {
+   timersub(_1s, _sent, _us);
+   timeval_to_timespec(_us, >delay);
+   }
+   }
+   } else if (sh->type == SHAPER_TSTAMP) {
+   struct timeval pkt_diff;
+   struct timeval diff;
 
bug_on(gettimeofday(>end, NULL));
-   timersub(>end, >start, _sent);
+   timersub(>end, >start, );
+   timersub(>tstamp, >tstamp, _diff);
+
+   if (timercmp(, _diff, <)) {
+   struct timeval delay;
 
-   if (timercmp(_1s, _sent, > )) {
-   timersub(_1s, _sent, _us);
-   timeval_to_timespec(_us, >delay);
+   timersub(_diff, , );
+   timeval_to_timespec(, >delay);
}
+
+   memcpy(>tstamp, >tstamp, sizeof(sh->tstamp));
}
 
if ((sh->delay.tv_sec | sh->delay.tv_nsec) > 0) {
@@ -698,7 +732,7 @@ retry:
num--;
 
if (shaper_is_set

[netsniff-ng] [PATCH 3/3] trafgen: man: Add description with pcap file for -i, --in option

2017-01-31 Thread Vadim Kochan
Update -i, --in option with pcap file as input parameter.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen.8 | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/trafgen.8 b/trafgen.8
index e09b7a0..fd9788a 100644
--- a/trafgen.8
+++ b/trafgen.8
@@ -66,10 +66,13 @@ given scenario.
 .PP
 .SH OPTIONS
 .PP
-.SS -i <cfg|->, -c <cfg|i>, --in <cfg|->, --conf <cfg|->
+.SS -i <cfg|pcap|->, -c <cfg|->, --in <cfg|pcap|->, --conf <cfg|->
 Defines the input configuration file that can either be passed as a normal 
plain
 text file or via stdin (''-''). Note that currently, if a configuration is
 passed through stdin, only 1 CPU will be used.
+It is also possible to specify PCAP file with .pcap extension via -i,--in 
option,
+by default packets will be sent at rate considering timestamp from PCAP file 
which
+might be reset via -b/-t options.
 .PP
 .SS -o , -d , --out , --dev 
 Defines the outgoing networking device such as eth0, wlan0 and others.
-- 
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.


[netsniff-ng] [PATCH 1/3] pcap_io: Add function to get packet timestamp

2017-01-31 Thread Vadim Kochan
Add pcap_get_tstamp(...) function to get packet's timestamp considering
different packet types & bytes order.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 pcap_io.h | 53 +
 1 file changed, 53 insertions(+)

diff --git a/pcap_io.h b/pcap_io.h
index 4e41362..7bf5fe6 100644
--- a/pcap_io.h
+++ b/pcap_io.h
@@ -373,6 +373,59 @@ static inline void pcap_set_length(pcap_pkthdr_t *phdr, 
enum pcap_type type, u32
}
 }
 
+static inline void pcap_get_tstamp(pcap_pkthdr_t *phdr, enum pcap_type type,
+  struct timeval *tv)
+{
+   switch (type) {
+   case DEFAULT:
+   case DEFAULT_LL:
+   tv->tv_sec = phdr->ppo.ts.tv_sec;
+   tv->tv_usec = phdr->ppo.ts.tv_usec;
+   break;
+
+   case DEFAULT_SWAPPED:
+   case DEFAULT_LL_SWAPPED:
+   tv->tv_sec = ___constant_swab32(phdr->ppo.ts.tv_sec);
+   tv->tv_usec = ___constant_swab32(phdr->ppo.ts.tv_usec);
+   break;
+
+   case NSEC:
+   case NSEC_LL:
+   tv->tv_sec = phdr->ppn.ts.tv_sec;
+   tv->tv_usec = phdr->ppn.ts.tv_nsec / 1000;
+   break;
+
+   case NSEC_SWAPPED:
+   case NSEC_LL_SWAPPED:
+   tv->tv_sec = ___constant_swab32(phdr->ppn.ts.tv_sec);
+   tv->tv_usec = ___constant_swab32(phdr->ppn.ts.tv_nsec) / 1000;
+   break;
+
+   case KUZNETZOV:
+   tv->tv_sec = phdr->ppk.ts.tv_sec;
+   tv->tv_usec = phdr->ppk.ts.tv_usec;
+   break;
+
+   case KUZNETZOV_SWAPPED:
+   tv->tv_sec = ___constant_swab32(phdr->ppk.ts.tv_sec);
+   tv->tv_usec = ___constant_swab32(phdr->ppk.ts.tv_usec);
+   break;
+
+   case BORKMANN:
+   tv->tv_sec = phdr->ppb.ts.tv_sec;
+   tv->tv_usec = phdr->ppb.ts.tv_nsec / 1000;
+   break;
+
+   case BORKMANN_SWAPPED:
+   tv->tv_sec = ___constant_swab32(phdr->ppb.ts.tv_sec);
+   tv->tv_usec = ___constant_swab32(phdr->ppb.ts.tv_nsec) / 1000;
+   break;
+
+   default:
+   bug();
+   }
+}
+
 static inline u32 pcap_get_hdr_length(pcap_pkthdr_t *phdr, enum pcap_type type)
 {
switch (type) {
-- 
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.


Re: [netsniff-ng] Mausezahn - virtual nic "unknown physical layer type"

2017-01-31 Thread Vadim Kochan
BTW I did grep over the kernel and looks like it might the 'tun' device.

On Tue, Jan 31, 2017 at 12:38 PM, Vadim Kochan <vadi...@gmail.com> wrote:
> On Tue, Jan 31, 2017 at 12:36 PM, Vadim Kochan <vadi...@gmail.com> wrote:
>> On Tue, Jan 31, 2017 at 12:47 AM, Jojonix1-Web <jojon...@web.de> wrote:
>>> Hello dear netsniff team
>>>
>>>
>>>
>>> My name is Jonathan, I am an IT specialist from Germany and I have some
>>> difficulties with Mausezahn.
>>>
>>>
>>>
>>> I am running a virtual server with Ubuntu 14.04 LTS. I wanted to test my
>>> DDoS protection, but Mausezahn is unable to send those frames through the
>>> virtual NIC. There is no problem with the Local Loopback. Is this a known
>>> incident? Is there anything I can do to get it running?
>>>
>>>
>>>
>>> I had updated the pcap files before I tried and tshark is able to scan the
>>> virtual NIC without any troubles.
>>>
>>>
>>>
>>> The error message is:
>>>
>>> libnet_init() failed (unknown physical layer type 0x) Invalid command
>>> line parameters!
>>>
>>>
>>>
>>> I am looking forward to your reply.
>>>
>>>
>>>
>>> Greetings from Germany
>>>
>>> Jonathan
>>>
>>> --
>>> 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.
>>
>> Hi Jonathan,
>>
>> 1st thing which comes to mind is that the link type of this interface
>> is "none" or "void", and
>> libnet can't handle it.
>>
>> Could you please give some details about this interface with 'ip link'
>> and ifconfig output ?
>> Also you can try to use trafgen for DDoS testing.
>>
>> Regards,
>> Vadim Kochan
>
> CC Jonathan

-- 
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.


Re: [netsniff-ng] Mausezahn - virtual nic "unknown physical layer type"

2017-01-31 Thread Vadim Kochan
On Tue, Jan 31, 2017 at 12:47 AM, Jojonix1-Web <jojon...@web.de> wrote:
> Hello dear netsniff team
>
>
>
> My name is Jonathan, I am an IT specialist from Germany and I have some
> difficulties with Mausezahn.
>
>
>
> I am running a virtual server with Ubuntu 14.04 LTS. I wanted to test my
> DDoS protection, but Mausezahn is unable to send those frames through the
> virtual NIC. There is no problem with the Local Loopback. Is this a known
> incident? Is there anything I can do to get it running?
>
>
>
> I had updated the pcap files before I tried and tshark is able to scan the
> virtual NIC without any troubles.
>
>
>
> The error message is:
>
> libnet_init() failed (unknown physical layer type 0x) Invalid command
> line parameters!
>
>
>
> I am looking forward to your reply.
>
>
>
> Greetings from Germany
>
> Jonathan
>
> --
> 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.

Hi Jonathan,

1st thing which comes to mind is that the link type of this interface
is "none" or "void", and
libnet can't handle it.

Could you please give some details about this interface with 'ip link'
and ifconfig output ?
Also you can try to use trafgen for DDoS testing.

Regards,
Vadim Kochan

-- 
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.


[netsniff-ng] [RFC 7/7] trafgen: parser: Add syntax to generate DNS header

2017-01-30 Thread Vadim Kochan
Add new syntax for DNS header generation via 'dns()' proto function.

The fields are supported:

id  - 16 bit identifier
qr  - message is a query(0) or response(1)
op|oper - specified kind of query
aanswer - authoritative answer flag
trunc   - message was truncated flag
rdesired- recursion desired flag
ravail  - recursion available flag
zero- reserved for future use
rcode   - response code
qdcount - number of entries in question section
ancount - number of entries in answer section
nscount - number of entries in authority section
arcount - number of entries in additional section

Also there are functions to generate DNS sections:

'qry()' function to generate separate query entry:

name- variable domain name
type- type of the query
class   - class of the query

'ans()', 'auth()', 'add'  functions to generate separate answer,
authoritative, adidditional entry with the same fields layout:

name- variable domain name
type- resource record type
class   - class of the data
ttl - time interval that the record may be cached
len - length of data
data- variable length of bytes

All the DNS section entries will be automaticlly sorted by DNS proto API
in the way which is required by DNS header:

query entries
answer entries
authoritative entries
additional entries

'name' field in qry/ans/auth/add functions is automatically converted to
FQDN format if it was specified as "string".

There are also added functions to simplify the way of filling
some often used RR types for using them inside ans/auth/add functions:

addr(ipv4_addr | ipv6_addr) - fills the following RR fields:
len  - 4 or 16 depends on IPv4 or IPv6 address was specified
data - is filled with IPv4 or IPv6 address
type - 1 for IPv4 address, 28 - for IPv6

ns(string)
type - 2

cname(string)
type - 5

ptr(string)
type - 12

EXAMPLES:

{
dns(qr=1,
auth(name="ns1", ns("ns1.org")),
ans(name="www.google.com", cname("google.com")),
auth(name="aa", ns("bb")),
qry(name="www.google.com"))
}

{
dns(qr=1, ans(name="www.google.com", addr(1.2.3.4)))
}

{
dns(qr=1, ans(name="www.google.com", addr(1::)))
}

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen_lexer.l  |  24 +++
 trafgen_parser.y | 193 +++
 2 files changed, 217 insertions(+)

diff --git a/trafgen_lexer.l b/trafgen_lexer.l
index cf67c74..da072e1 100644
--- a/trafgen_lexer.l
+++ b/trafgen_lexer.l
@@ -239,6 +239,29 @@ ip6_addr   
({v680}|{v67}|{v66}|{v65}|{v64}|{v63}|{v62}|{v61}|{v60})
 "win"|"window" { return K_WINDOW; }
 "urgptr"   { return K_URG_PTR; }
 
+   /* DNS */
+"qr"   { return K_QR; }
+"aa"|"aanswer" { return K_AANSWER; }
+"trunc"{ return K_TRUNC; }
+"ravail"   { return K_RAVAIL; }
+"rdesired" { return K_RDESIRED; }
+"zero" { return K_ZERO; }
+"rc"|"rcode"   { return K_RCODE; }
+"qdcount"  { return K_QDCOUNT; }
+"ancount"  { return K_ANCOUNT; }
+"nscount"  { return K_NSCOUNT; }
+"arcount"  { return K_ARCOUNT; }
+"name" { return K_NAME; }
+"class"{ return K_CLASS; }
+"data" { return K_DATA; }
+"qry"|"query"  { return K_QUERY; }
+"ans"|"answer" { return K_ANSWER; }
+"auth" { return K_AUTH; }
+"add"  { return K_ADD; }
+"ns"   { return K_NS; }
+"cname"{ return K_CNAME; }
+"ptr"  { return K_PTR; }
+
 "eth"  { return K_ETH; }
 "pause" { return K_PAUSE; }
 "pfc"  { return K_PFC; }
@@ -251,6 +274,7 @@ ip6_addr
({v680}|{v67}|{v66}|{v65}|{v64}|{v63}|{v62}|{v61}|{v60})
 "icmp6"|"icmpv6"   { return K_ICMP6; }
 "udp"  { return K_UDP; }
 "tcp"  { return K_TCP; }
+"dns"  { return K_DNS; }
 
 [ ]*"-"[ ]*{ return '-'; }
 [ ]*"+"[ ]*{ return '+'; }
diff --git a/trafgen_parser.y b/trafgen_parser.y
index 4abf778..e128527 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@

[netsniff-ng] [RFC 6/7] trafgen: l7: Add DNS header generation API

2017-01-30 Thread Vadim Kochan
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.

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 000..1e82ccb
--- /dev/null
+++ b/trafgen_l7.c
@@ -0,0 +1,175 @@
+/*
+ * 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, .

[netsniff-ng] [RFC 4/7] trafgen: parser: Use proto_field_set_xxx where it is possible

2017-01-30 Thread Vadim Kochan
Use proto_field_set_xxx(field, ...)  instead of
proto_hdr_field_set_xxx(hdr, fid, ...) to be more generic and do not
depent on 'hdr' variable.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen_parser.y | 13 ++---
 trafgen_proto.c  |  5 +
 trafgen_proto.h  |  1 +
 3 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/trafgen_parser.y b/trafgen_parser.y
index 8e1884e..4abf778 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@@ -427,20 +427,19 @@ static void proto_field_expr_eval(void)
 
if (field_expr.type & FIELD_EXPR_NUMB) {
if (field->len == 1)
-   proto_hdr_field_set_u8(hdr, field->id, 
field_expr.val.number);
+   proto_field_set_u8(field, field_expr.val.number);
else if (field->len == 2)
-   proto_hdr_field_set_be16(hdr, field->id, 
field_expr.val.number);
+   proto_field_set_be16(field, field_expr.val.number);
else if (field->len == 4)
-   proto_hdr_field_set_be32(hdr, field->id, 
field_expr.val.number);
+   proto_field_set_be32(field, field_expr.val.number);
else
panic("Invalid value length %zu, can be 1,2 or 4\n", 
field->len);
} else if (field_expr.type & FIELD_EXPR_MAC) {
-   proto_hdr_field_set_bytes(hdr, field->id, field_expr.val.mac, 
6);
+   proto_field_set_bytes(field, field_expr.val.mac, 6);
} else if (field_expr.type & FIELD_EXPR_IP4_ADDR) {
-   proto_hdr_field_set_u32(hdr, field->id, 
field_expr.val.ip4_addr.s_addr);
+   proto_field_set_u32(field, field_expr.val.ip4_addr.s_addr);
} else if (field_expr.type & FIELD_EXPR_IP6_ADDR) {
-   proto_hdr_field_set_bytes(hdr, field->id,
-   (uint8_t *)_expr.val.ip6_addr.s6_addr, 16);
+   proto_field_set_bytes(field, (uint8_t 
*)_expr.val.ip6_addr.s6_addr, 16);
} else if ((field_expr.type & FIELD_EXPR_INC) ||
(field_expr.type & FIELD_EXPR_RND)) {
 
diff --git a/trafgen_proto.c b/trafgen_proto.c
index 83a6a7e..e300e7f 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -527,6 +527,11 @@ void proto_field_set_be32(struct proto_field *field, 
uint32_t val)
__proto_field_set_bytes(field, (uint8_t *), 4, false, true);
 }
 
+void proto_field_set_bytes(struct proto_field *field, const uint8_t *bytes, 
size_t len)
+{
+   __proto_field_set_bytes(field, bytes, len, false, false);
+}
+
 void protos_init(const char *dev)
 {
ctx.dev = dev;
diff --git a/trafgen_proto.h b/trafgen_proto.h
index fa41d3b..d9a6a24 100644
--- a/trafgen_proto.h
+++ b/trafgen_proto.h
@@ -155,6 +155,7 @@ extern void proto_field_set_u32(struct proto_field *field, 
uint32_t val);
 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_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.


[netsniff-ng] [RFC 1/7] trafgen: parser: Rename bytes -> mac

2017-01-30 Thread Vadim Kochan
Rename  token member to  as it is used only for MAC
address parsing, for dynamic sized bytes array we have an .
Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen_lexer.l  |  2 +-
 trafgen_parser.y | 12 ++--
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/trafgen_lexer.l b/trafgen_lexer.l
index 65ec245..cf67c74 100644
--- a/trafgen_lexer.l
+++ b/trafgen_lexer.l
@@ -300,7 +300,7 @@ ip6_addr
({v680}|{v67}|{v66}|{v65}|{v64}|{v63}|{v62}|{v61}|{v60})
 {number_ascii} { yylval.number = (uint8_t) (*yytext);
  return number; }
 
-{mac}  { if (str2mac(yytext, yylval.bytes, 256))
+{mac}  { if (str2mac(yytext, yylval.mac, 6))
panic("Failed to parse MAC address %s\n", yytext);
  return mac; }
 
diff --git a/trafgen_parser.y b/trafgen_parser.y
index b5fcbc0..f5f2dc4 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@@ -92,7 +92,7 @@ struct proto_field_expr {
struct in_addr ip4_addr;
struct in6_addr ip6_addr;
long long int number;
-   uint8_t bytes[256];
+   uint8_t mac[256];
struct proto_field_func func;
} val;
 };
@@ -433,9 +433,9 @@ static void proto_field_expr_eval(void)
else if (field->len == 4)
proto_hdr_field_set_be32(hdr, field->id, 
field_expr.val.number);
else
-   proto_hdr_field_set_bytes(hdr, field->id, 
field_expr.val.bytes);
+   panic("Invalid value length %zu, can be 1,2 or 4\n", 
field->len);
} else if (field_expr.type & FIELD_EXPR_MAC) {
-   proto_hdr_field_set_bytes(hdr, field->id, field_expr.val.bytes);
+   proto_hdr_field_set_bytes(hdr, field->id, field_expr.val.mac);
} else if (field_expr.type & FIELD_EXPR_IP4_ADDR) {
proto_hdr_field_set_u32(hdr, field->id, 
field_expr.val.ip4_addr.s_addr);
} else if (field_expr.type & FIELD_EXPR_IP6_ADDR) {
@@ -481,7 +481,7 @@ static void field_index_validate(struct proto_field *field, 
uint16_t index, size
struct in_addr ip4_addr;
struct in6_addr ip6_addr;
long long int number;
-   uint8_t bytes[256];
+   uint8_t mac[6];
char *str;
 }
 
@@ -516,7 +516,7 @@ static void field_index_validate(struct proto_field *field, 
uint16_t index, size
 
 %type  number expression
 %type  string
-%type  mac
+%type  mac
 %type  ip4_addr
 %type  ip6_addr
 
@@ -760,7 +760,7 @@ field_value_expr
: number { field_expr.type |= FIELD_EXPR_NUMB;
   field_expr.val.number = $1; }
| mac { field_expr.type |= FIELD_EXPR_MAC;
-   memcpy(field_expr.val.bytes, $1, sizeof(field_expr.val.bytes)); 
}
+   memcpy(field_expr.val.mac, $1, sizeof(field_expr.val.mac)); }
| ip4_addr { field_expr.type |= FIELD_EXPR_IP4_ADDR;
 field_expr.val.ip4_addr = $1; }
| ip6_addr { field_expr.type |= FIELD_EXPR_IP6_ADDR;
-- 
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.


[netsniff-ng] [RFC 0/7] Add DNS proto header support

2017-01-30 Thread Vadim Kochan
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.

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.

Add new syntax for DNS header generation via 'dns()' proto function.

The fields are supported:

id  - 16 bit identifier
qr  - message is a query(0) or response(1)
op|oper - specified kind of query
aanswer - authoritative answer flag
trunc   - message was truncated flag
rdesired- recursion desired flag
ravail  - recursion available flag
zero- reserved for future use
rcode   - response code
qdcount - number of entries in question section
ancount - number of entries in answer section
nscount - number of entries in authority section
arcount - number of entries in additional section

Also there are functions to generate DNS sections:

'qry()' function to generate separate query entry:

name- variable domain name
type- type of the query
class   - class of the query

'ans()', 'auth()', 'add'  functions to generate separate answer,
authoritative, adidditional entry with the same fields layout:

name- variable domain name
type- resource record type
class   - class of the data
ttl - time interval that the record may be cached
len - length of data
data- variable length of bytes

All the DNS section entries will be automaticlly sorted by DNS proto API
in the way which is required by DNS header:

query entries
answer entries
authoritative entries
additional entries

'name' field in qry/ans/auth/add functions is automatically converted to
FQDN format if it was specified as "string".

There are also added functions to simplify the way of filling
some often used RR types for using them inside ans/auth/add functions:

addr(ipv4_addr | ipv6_addr) - fills the following RR fields:
len  - 4 or 16 depends on IPv4 or IPv6 address was specified
data - is filled with IPv4 or IPv6 address
type - 1 for IPv4 address, 28 - for IPv6

ns(string)
type - 2

cname(string)
type - 5

ptr(string)
type - 12

EXAMPLES:

{
dns(qr=1,
auth(name="ns1", ns("ns1.org")),
ans(name="www.google.com", cname("google.com")),
auth(name="aa", ns("bb")),
qry(name="www.google.com"))
}

{
dns(qr=1, ans(name="www.google.com", addr(1.2.3.4)))
}

{
dns(qr=1, ans(name="www.google.com", addr(1::)))
}

Vadim Kochan (7):
  trafgen: parser: Rename bytes -> mac
  trafgen: proto: Add 'len' parameter to *_set_bytes(...) functions
  trafgen: proto: Allow to set field with variable length
  trafgen: parser: Use proto_field_set_xxx where it is possible
  str: Add function for converting string into DNS name
  trafgen: l7: Add DNS header generation API
  trafgen: parser: Add syntax to generate DNS header

 str.c|  37 +
 str.h|   1 +
 trafgen/Makefile |   1 +
 trafgen_l2.c |   6 +-
 trafgen_l4.c |  32 
 trafgen_l7.c | 175 +
 trafgen_l7.h |  45 +++
 trafgen_lexer.l  |  26 ++-
 trafgen_parser.y | 216 ---
 trafgen_p

[netsniff-ng] [RFC 3/7] trafgen: proto: Allow to set field with variable length

2017-01-30 Thread Vadim Kochan
It is quite tricky to set field value with a variable length
(i.e. DNS query name), to make it possible the field
needs to be added to header with 'len=0' in that case there
will be no any payload allocation, but only while setting the field
value the packet will be appended with a real length bytes and after
the field needs to be relocated to the right place.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen_proto.c | 50 ++
 1 file changed, 50 insertions(+)

diff --git a/trafgen_proto.c b/trafgen_proto.c
index 0530032..83a6a7e 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -100,6 +100,9 @@ void proto_header_fields_add(struct proto_hdr *hdr,
f->pkt_offset = hdr->pkt_offset + fields[i].offset;
f->hdr = hdr;
 
+   if (!f->len)
+   continue;
+
if (f->pkt_offset + f->len > pkt->len) {
hdr->len += f->len;
set_fill(0, (f->pkt_offset + f->len) - pkt->len);
@@ -181,6 +184,45 @@ set_proto:
return current;
 }
 
+static void __proto_field_relocate(struct proto_field *field)
+{
+   struct proto_hdr *hdr = field->hdr;
+   struct packet *pkt = packet_get(hdr->pkt_id);
+   uint8_t *from, *to;
+   int i;
+
+   /* If this is a last field then just calculate 'pkt_offset' */
+   if (field->id == hdr->fields_count - 1) {
+   field->pkt_offset = hdr->pkt_offset + hdr->len - field->len;
+   return;
+   }
+
+   /* Use 'pkt_offset' from the 1st real (len > 0) field after the
+* 'target' one */
+   for (i = field->id + 1; i < hdr->fields_count; i++) {
+   if (hdr->fields[i].len == 0)
+   continue;
+
+   field->pkt_offset = hdr->fields[i].pkt_offset;
+   break;
+   }
+
+   /* Move payload of overlapped fields (each after the 'target' field) */
+   from = >payload[field->pkt_offset];
+   to = >payload[field->pkt_offset + field->len];
+   memcpy(to, from, hdr->len - field->len);
+
+   /* Recalculate 'pkt_offset' of the rest fields */
+   for (; i < hdr->fields_count; i++) {
+   struct proto_field *tmp = >fields[i];
+
+   if (tmp->len == 0)
+   continue;
+
+   tmp->pkt_offset += field->len;
+   }
+}
+
 static void __proto_field_set_bytes(struct proto_field *field,
const uint8_t *bytes, size_t len,
bool is_default, bool is_be)
@@ -195,6 +237,14 @@ static void __proto_field_set_bytes(struct proto_field 
*field,
if (is_default && field->is_set)
return;
 
+   if (field->len == 0) {
+   field->hdr->len += len;
+   field->len = len;
+   set_fill(0, len);
+
+   __proto_field_relocate(field);
+   }
+
payload = _get(field->hdr->pkt_id)->payload[field->pkt_offset];
 
if (field->len == 1) {
-- 
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.


[netsniff-ng] [RFC 5/7] str: Add function for converting string into DNS name

2017-01-30 Thread Vadim Kochan
Add str2fqdn for converting hostname string into DNS name notation:

www..yy.com -> 3www42yy3com0

Returned string must be freed after use by the caller.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 str.c | 37 +
 str.h |  1 +
 2 files changed, 38 insertions(+)

diff --git a/str.c b/str.c
index 532058a..1d3e7ac 100644
--- a/str.c
+++ b/str.c
@@ -160,3 +160,40 @@ int str2mac(const char *str, uint8_t *mac, size_t len)
 
return 0;
 }
+
+char *str2fqdn(const char *str)
+{
+   size_t slen = strlen(str);
+   size_t flen = 0;
+   char *fqdn;
+   char *tmp;
+   char *dup;
+   int i = 0;
+   int c = 0;
+
+   dup = xstrdup(str);
+   tmp = dup;
+
+   fqdn = xzmalloc(slen + 2);
+
+   while (tmp <= dup + slen && c++ <= slen) {
+   if (tmp[i] == '.' || tmp[i] == '\0') {
+   size_t dlen;
+
+   tmp[i] = '\0';
+   dlen = strlen(tmp);
+   fqdn[flen] = dlen;
+   memcpy([flen + 1], tmp, dlen);
+   flen += dlen + 1;
+   tmp += dlen + 1;
+   i = 0;
+
+   continue;
+   }
+
+   i++;
+   }
+
+   xfree(dup);
+   return fqdn;
+}
diff --git a/str.h b/str.h
index 7879af6..a362c53 100644
--- a/str.h
+++ b/str.h
@@ -14,5 +14,6 @@ extern char *argv2str(int startind, int argc, char **argv);
 extern char **argv_insert(char **argv, size_t *count, const char *str);
 extern void argv_free(char **argv);
 extern int str2mac(const char *str, uint8_t *mac, size_t len);
+extern char *str2fqdn(const char *str);
 
 #endif /* STR_H */
-- 
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.


[netsniff-ng] Re: [PATCH] trafgen: l3: Fix checksum for UDP/TCP protos

2017-01-25 Thread Vadim Kochan
On Wed, Jan 25, 2017 at 2:24 PM, Tobias Klauser <tklau...@distanz.ch> wrote:
> On 2017-01-23 at 22:49:22 +0100, Vadim Kochan <vadi...@gmail.com> wrote:
>> While fixing the issue with getting of IPv4 address from device,
>> the setting of default src IPv4/IPv6 addresses was moved from
>> hdr->header_init(...) callback to hdr->packet_finish(...), but
>> packet_finish(...) is called in the following order:
>>
>> udp_hdr->packet_finish() - UDP csum calculation over IPv4/6 pseudo header
>> ip4_hdr->packet_finish() - setting default src IPv4 address from dev
>> ...
>>
>> So src IPv4/6 address will be set after UDP/TCP csum calculation which
>> is wrong, so fixed issue by moving it to the hdr->header_init(...) stage
>> as it was before the c4e07d5142c8.
>>
>> Fixes: c4e07d5142c8 ("trafgen: l3: Support interface without IP address")
>> Signed-off-by: Vadim Kochan <vadi...@gmail.com>
>
> Applied, thanks Vadim.

BTW,
We really need some sub-folder with scapy tests to check
trafgen/mausezahn packet's generation.

-- 
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.


[netsniff-ng] [PATCH v2 2/2] flowtop: Add process UI tab entry

2017-01-18 Thread Vadim Kochan
Add process UI tab entry to show flows statistics per pid.

Also changed flow_entry which now has pointer to new struct proc_entry
object which contains process related info.

On each 1 second refresh proc_entry is checked if it exists by checking
/proc/ path, and is deleted if there is no any flows related to it
(flows_count is 0), if the process exists then dst & src rates info is
zeroed and summed from the all related flows which are in the
proc_entry->flows list.

The bytes & pkts amount info is collected during all the time process
exists.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 flowtop.c | 349 +-
 proc.c|  11 ++
 proc.h|   3 +-
 3 files changed, 315 insertions(+), 48 deletions(-)

diff --git a/flowtop.c b/flowtop.c
index 78ac253..2491de7 100644
--- a/flowtop.c
+++ b/flowtop.c
@@ -52,7 +52,25 @@
 #define USEC_PER_SEC 100L
 #endif
 
+struct proc_entry {
+   struct cds_list_head entry;
+   struct cds_list_head flows;
+   struct rcu_head rcu;
+
+   struct timeval last_update;
+   unsigned int pid;
+   char name[256];
+   uint64_t pkts_src, bytes_src;
+   uint64_t pkts_dst, bytes_dst;
+   double rate_bytes_src;
+   double rate_bytes_dst;
+   double rate_pkts_src;
+   double rate_pkts_dst;
+   int flows_count;
+};
+
 struct flow_entry {
+   struct cds_list_head proc_head;
struct cds_list_head entry;
struct rcu_head rcu;
 
@@ -69,9 +87,8 @@ struct flow_entry {
char country_code_src[4], country_code_dst[4];
char city_src[128], city_dst[128];
char rev_dns_src[256], rev_dns_dst[256];
-   char procname[256];
+   struct proc_entry *proc;
int inode;
-   unsigned int procnum;
bool is_visible;
struct nf_conntrack *ct;
struct timeval last_update;
@@ -85,6 +102,10 @@ struct flow_list {
struct cds_list_head head;
 };
 
+struct proc_list {
+   struct cds_list_head head;
+};
+
 enum flow_direction {
FLOW_DIR_SRC,
FLOW_DIR_DST,
@@ -129,6 +150,7 @@ static volatile bool do_reload_flows;
 static volatile bool is_flow_collecting;
 static volatile sig_atomic_t sigint = 0;
 static int what = INCLUDE_IPV4 | INCLUDE_IPV6 | INCLUDE_TCP;
+static struct proc_list proc_list;
 static struct flow_list flow_list;
 static struct sysctl_params_ctx sysctl = { -1, -1 };
 
@@ -156,10 +178,22 @@ enum tbl_flow_col {
TBL_FLOW_RATE,
 };
 
+enum tbl_proc_col {
+   TBL_PROC_NAME,
+   TBL_PROC_PID,
+   TBL_PROC_FLOWS,
+   TBL_PROC_BYTES_SRC,
+   TBL_PROC_RATE_SRC,
+   TBL_PROC_BYTES_DST,
+   TBL_PROC_RATE_DST,
+};
+
 static struct ui_table flows_tbl;
+static struct ui_table procs_tbl;
 
 enum tab_entry {
TAB_FLOWS,
+   TAB_PROCS,
 };
 
 static const char *short_options = "vhTUsDIS46ut:nGb";
@@ -432,6 +466,11 @@ static int flow_list_del_entry(struct flow_list *fl, const 
struct nf_conntrack *
 
n = flow_list_find_id(fl, nfct_get_attr_u32(ct, ATTR_ID));
if (n) {
+   if (n->proc) {
+   cds_list_del(>proc_head);
+   n->proc->flows_count--;
+   }
+
cds_list_del_rcu(>entry);
call_rcu(>rcu, flow_entry_xfree_rcu);
}
@@ -449,22 +488,72 @@ static void flow_list_destroy(struct flow_list *fl)
}
 }
 
+static void proc_list_init(struct proc_list *proc_list)
+{
+   CDS_INIT_LIST_HEAD(_list->head);
+}
+
+static struct proc_entry *proc_list_new_entry(unsigned int pid)
+{
+   struct proc_entry *proc;
+
+   cds_list_for_each_entry(proc, _list.head, entry) {
+   if (proc->pid && proc->pid == pid)
+   return proc;
+   }
+
+   proc = xzmalloc(sizeof(*proc));
+
+   bug_on(gettimeofday(>last_update, NULL));
+   CDS_INIT_LIST_HEAD(>flows);
+   proc->pid = pid;
+
+   cds_list_add_tail(>entry, _list.head);
+
+   return proc;
+}
+
+static void proc_entry_xfree_rcu(struct rcu_head *head)
+{
+   struct proc_entry *p = container_of(head, struct proc_entry, rcu);
+
+   xfree(p);
+}
+
+static void proc_list_destroy(struct proc_list *pl)
+{
+   struct proc_entry *p, *tmp;
+
+   cds_list_for_each_entry_safe(p, tmp, >head, entry) {
+   cds_list_del_rcu(>entry);
+   call_rcu(>rcu, proc_entry_xfree_rcu);
+   }
+}
+
 static void flow_entry_find_process(struct flow_entry *n)
 {
+   struct proc_entry *p;
char cmdline[512];
pid_t pid;
int ret;
 
ret = proc_find_by_inode(n->inode, cmdline, sizeof(cmdline), );
-   if (ret <= 0) {
-   n->procname[0] = '\0';
+   if (ret <= 0)
return;
-   }
 
-   if (snprintf(n->procname, sizeof(n->procname), "%s", basename(cmdline)) 
&

[netsniff-ng] [PATCH v2 1/2] flowtop: Add tab control to switch between tables

2017-01-18 Thread Vadim Kochan
Add ui_tab API to create ui tab control to switch between
different ui tables which may contain different aggregated
info per unique pid/port/proto/dst/src.

Meanwhile there is only 1 ui tab entry for flows table.

Added some missing cds_list_{next,prev,last}_entry functions
into urcu-list-compat.h header.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 flowtop.c  | 26 +--
 ui.c   | 97 --
 ui.h   | 34 +--
 urcu-list-compat.h | 21 
 4 files changed, 171 insertions(+), 7 deletions(-)
 create mode 100644 urcu-list-compat.h

diff --git a/flowtop.c b/flowtop.c
index b2d6546..78ac253 100644
--- a/flowtop.c
+++ b/flowtop.c
@@ -133,6 +133,8 @@ static struct flow_list flow_list;
 static struct sysctl_params_ctx sysctl = { -1, -1 };
 
 static unsigned int cols, rows;
+static WINDOW *screen;
+static int skip_lines;
 
 static unsigned int interval = 1;
 static bool show_src = false;
@@ -156,6 +158,10 @@ enum tbl_flow_col {
 
 static struct ui_table flows_tbl;
 
+enum tab_entry {
+   TAB_FLOWS,
+};
+
 static const char *short_options = "vhTUsDIS46ut:nGb";
 static const struct option long_options[] = {
{"ipv4",no_argument,NULL, '4'},
@@ -1197,11 +1203,15 @@ static void flows_table_init(struct ui_table *tbl)
ui_table_header_color_set(_tbl, COLOR(BLACK, GREEN));
 }
 
+static void tab_main_on_open(struct ui_tab *tab, enum ui_tab_event_t evt, 
uint32_t id)
+{
+   draw_flows(screen, _list, skip_lines);
+}
+
 static void presenter(void)
 {
bool show_help = false;
-   int skip_lines = 0;
-   WINDOW *screen;
+   struct ui_tab *tab_main;
 
lookup_init(LT_PORTS_TCP);
lookup_init(LT_PORTS_UDP);
@@ -1219,6 +1229,12 @@ static void presenter(void)
 
 flows_table_init(_tbl);
 
+   tab_main = ui_tab_create();
+   ui_tab_event_cb_set(tab_main, tab_main_on_open);
+   ui_tab_pos_set(tab_main, 2, 0);
+   ui_tab_active_color_set(tab_main, COLOR(BLACK, GREEN));
+   ui_tab_entry_add(tab_main, TAB_FLOWS, "Flows");
+
rcu_register_thread();
while (!sigint) {
int ch;
@@ -1278,6 +1294,9 @@ static void presenter(void)
show_option_toggle(ch);
do_reload_flows = true;
break;
+   case '\t':
+   ui_tab_event_send(tab_main, UI_EVT_SELECT_NEXT);
+   break;
default:
fflush(stdin);
break;
@@ -1288,13 +1307,14 @@ static void presenter(void)
if (show_help)
draw_help();
else
-   draw_flows(screen, _list, skip_lines);
+   ui_tab_show(tab_main);
 
draw_footer();
}
rcu_unregister_thread();
 
ui_table_uninit(_tbl);
+   ui_tab_destroy(tab_main);
 
screen_end();
lookup_cleanup(LT_PORTS_UDP);
diff --git a/ui.c b/ui.c
index 78d1560..e6d1825 100644
--- a/ui.c
+++ b/ui.c
@@ -7,7 +7,9 @@
 
 #include "ui.h"
 #include "str.h"
+#include "screen.h"
 #include "xmalloc.h"
+#include "urcu-list-compat.h"
 
 static struct ui_text *ui_text_alloc(size_t len)
 {
@@ -62,6 +64,7 @@ void ui_table_init(struct ui_table *tbl)
tbl->height  = LINES - 2;
tbl->col_pad = 1;
tbl->row = ui_text_alloc(tbl->width);
+   tbl->delim   = " ";
 
CDS_INIT_LIST_HEAD(>cols);
 }
@@ -106,7 +109,7 @@ static void __ui_table_pos_update(struct ui_table *tbl)
}
 }
 
-void ui_table_col_add(struct ui_table *tbl, uint32_t id, char *name, uint32_t 
len)
+void ui_table_col_add(struct ui_table *tbl, uint32_t id, const char *name, 
uint32_t len)
 {
struct ui_col *col = xzmalloc(sizeof(*col));
 
@@ -134,6 +137,11 @@ void ui_table_col_align_set(struct ui_table *tbl, int 
col_id, enum ui_align alig
col->align = align;
 }
 
+void ui_table_col_delim_set(struct ui_table *tbl, const char *delim)
+{
+   tbl->delim = delim;
+}
+
 void ui_table_row_add(struct ui_table *tbl)
 {
tbl->rows_y++;
@@ -166,7 +174,7 @@ static void __ui_table_row_print(struct ui_table *tbl, 
struct ui_col *col,
slprintf(tmp, sizeof(tmp), UI_ALIGN_COL(col), col->len, col->len, str);
ui_text_attr_insert(tbl->row, col->pos, color, tmp);
 
-   slprintf(tmp, sizeof(tmp), "%*s", tbl->col_pad, " ");
+   slprintf(tmp, sizeof(tmp), "%*s", tbl->col_pad, tbl->delim);
ui_text_attr_insert(tbl->row, col->pos + col->len, color, tmp);
 }
 
@@ -214,3 +222,88 @@ void ui_table_event_send(struct ui_table *tbl, enum 
ui_event_id evt_id)
tbl->scroll_x = 0;
  

[netsniff-ng] [PATCH v2 0/2] flowtop: Add UI tab control for process stats

2017-01-18 Thread Vadim Kochan
Add UI tab control to switch between tabbed windows for dirrent flows table
statistics info per pid/peer/port.

The tab entries are switched by TAB keypress.

Introduced proc_entry which holds aggregated related flows statistics 
(rate/pkts/bytes),
beside this changed flow_entry to point to proc_entry pid & name info.

Added UI tab for per pid flows info - flows count, bytes, rates. The bytes/pkts 
are collected
during the process living (but proc_entry is not removed till at lest one flow 
points to it),
the rates info refreshes each 1 second per proc_entry.

Re-added list.h which contains just missing cds_list_{next,prev,last}_entry 
functions which
are needed for navigation over UI tab entries.

v2:
1) Constify ui_table.delim & ui_col.name
2) Rename list.h -> urcu-list-compat.h and include urcu/list.h here.
3) Add Signed-off-by into 2nd commit.
4) In flow_entry_find_process(...) use proc_entry->name member instead
of local procname string.
5) Rename proc_exist -> proc_exists
6) Rename proc_entry.procnnum -> pid
7) Rename proc_entry.procname -> name

Vadim Kochan (2):
  flowtop: Add tab control to switch between tables
  flowtop: Add process UI tab entry

 flowtop.c  | 373 ++---
 proc.c |  11 ++
 proc.h |   3 +-
 ui.c   |  97 +-
 ui.h   |  34 -
 urcu-list-compat.h |  21 +++
 6 files changed, 485 insertions(+), 54 deletions(-)
 create mode 100644 urcu-list-compat.h

-- 
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.


[netsniff-ng] [PATCH 1/2] flowtop: Add tab control to switch between tables

2017-01-18 Thread Vadim Kochan
Add ui_tab API to create ui tab control to switch between
different ui tables which may contain different aggregated
info per unique pid/port/proto/dst/src.

Meanwhile there is only 1 ui tab entry for flows table.

Added some missing cds_list_{next,prev,last}_entry functions
into list.h header.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 flowtop.c | 26 +++--
 list.h| 19 +
 ui.c  | 95 ++-
 ui.h  | 30 
 4 files changed, 166 insertions(+), 4 deletions(-)
 create mode 100644 list.h

diff --git a/flowtop.c b/flowtop.c
index b2d6546..78ac253 100644
--- a/flowtop.c
+++ b/flowtop.c
@@ -133,6 +133,8 @@ static struct flow_list flow_list;
 static struct sysctl_params_ctx sysctl = { -1, -1 };
 
 static unsigned int cols, rows;
+static WINDOW *screen;
+static int skip_lines;
 
 static unsigned int interval = 1;
 static bool show_src = false;
@@ -156,6 +158,10 @@ enum tbl_flow_col {
 
 static struct ui_table flows_tbl;
 
+enum tab_entry {
+   TAB_FLOWS,
+};
+
 static const char *short_options = "vhTUsDIS46ut:nGb";
 static const struct option long_options[] = {
{"ipv4",no_argument,NULL, '4'},
@@ -1197,11 +1203,15 @@ static void flows_table_init(struct ui_table *tbl)
ui_table_header_color_set(_tbl, COLOR(BLACK, GREEN));
 }
 
+static void tab_main_on_open(struct ui_tab *tab, enum ui_tab_event_t evt, 
uint32_t id)
+{
+   draw_flows(screen, _list, skip_lines);
+}
+
 static void presenter(void)
 {
bool show_help = false;
-   int skip_lines = 0;
-   WINDOW *screen;
+   struct ui_tab *tab_main;
 
lookup_init(LT_PORTS_TCP);
lookup_init(LT_PORTS_UDP);
@@ -1219,6 +1229,12 @@ static void presenter(void)
 
 flows_table_init(_tbl);
 
+   tab_main = ui_tab_create();
+   ui_tab_event_cb_set(tab_main, tab_main_on_open);
+   ui_tab_pos_set(tab_main, 2, 0);
+   ui_tab_active_color_set(tab_main, COLOR(BLACK, GREEN));
+   ui_tab_entry_add(tab_main, TAB_FLOWS, "Flows");
+
rcu_register_thread();
while (!sigint) {
int ch;
@@ -1278,6 +1294,9 @@ static void presenter(void)
show_option_toggle(ch);
do_reload_flows = true;
break;
+   case '\t':
+   ui_tab_event_send(tab_main, UI_EVT_SELECT_NEXT);
+   break;
default:
fflush(stdin);
break;
@@ -1288,13 +1307,14 @@ static void presenter(void)
if (show_help)
draw_help();
else
-   draw_flows(screen, _list, skip_lines);
+   ui_tab_show(tab_main);
 
draw_footer();
}
rcu_unregister_thread();
 
ui_table_uninit(_tbl);
+   ui_tab_destroy(tab_main);
 
screen_end();
lookup_cleanup(LT_PORTS_UDP);
diff --git a/list.h b/list.h
new file mode 100644
index 000..44dc8a2
--- /dev/null
+++ b/list.h
@@ -0,0 +1,19 @@
+#ifndef LIST_H
+#define LIST_H
+
+#ifndef cds_list_last_entry
+#define cds_list_last_entry(ptr, type, member) \
+   cds_list_entry((ptr)->prev, type, member)
+#endif
+
+#ifndef cds_list_next_entry
+#define cds_list_next_entry(pos, member) \
+   cds_list_entry((pos)->member.next, typeof(*(pos)), member)
+#endif
+
+#ifndef cds_list_prev_entry
+#define cds_list_prev_entry(pos, member) \
+   cds_list_entry((pos)->member.prev, typeof(*(pos)), member)
+#endif
+
+#endif /* LIST_H */
diff --git a/ui.c b/ui.c
index 78d1560..d8e0213 100644
--- a/ui.c
+++ b/ui.c
@@ -7,6 +7,8 @@
 
 #include "ui.h"
 #include "str.h"
+#include "list.h"
+#include "screen.h"
 #include "xmalloc.h"
 
 static struct ui_text *ui_text_alloc(size_t len)
@@ -62,6 +64,7 @@ void ui_table_init(struct ui_table *tbl)
tbl->height  = LINES - 2;
tbl->col_pad = 1;
tbl->row = ui_text_alloc(tbl->width);
+   tbl->delim   = " ";
 
CDS_INIT_LIST_HEAD(>cols);
 }
@@ -134,6 +137,11 @@ void ui_table_col_align_set(struct ui_table *tbl, int 
col_id, enum ui_align alig
col->align = align;
 }
 
+void ui_table_col_delim_set(struct ui_table *tbl, char *delim)
+{
+   tbl->delim = delim;
+}
+
 void ui_table_row_add(struct ui_table *tbl)
 {
tbl->rows_y++;
@@ -166,7 +174,7 @@ static void __ui_table_row_print(struct ui_table *tbl, 
struct ui_col *col,
slprintf(tmp, sizeof(tmp), UI_ALIGN_COL(col), col->len, col->len, str);
ui_text_attr_insert(tbl->row, col->pos, color, tmp);
 
-   slprintf(tmp, sizeof(tmp), "%*s", tbl->col_pad, " ");
+   slprintf(tmp, sizeof(tmp), "%*s", tbl->col_pad, tb

[netsniff-ng] [PATCH 0/2] flowtop: Add UI tab control for process stats

2017-01-18 Thread Vadim Kochan
Add UI tab control to switch between tabbed windows for dirrent flows table
statistics info per pid/peer/port.

The tab entries are switched by TAB keypress.

Introduced proc_entry which holds aggregated related flows statistics 
(rate/pkts/bytes),
beside this changed flow_entry to point to proc_entry pid & name info.

Added UI tab for per pid flows info - flows count, bytes, rates. The bytes/pkts 
are collected
during the process living (but proc_entry is not removed till at lest one flow 
points to it),
the rates info refreshes each 1 second per proc_entry.

Re-added list.h which contains just missing cds_list_{next,prev,last}_entry 
functions which
are needed for navigation over UI tab entries.

Vadim Kochan (2):
  flowtop: Add tab control to switch between tables
  flowtop: Add process UI tab entry

 flowtop.c | 341 +++---
 list.h|  19 
 proc.c|  11 ++
 proc.h|   2 +
 ui.c  |  95 -
 ui.h  |  30 ++
 6 files changed, 463 insertions(+), 35 deletions(-)
 create mode 100644 list.h

-- 
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.


[netsniff-ng] Re: list: Remove cds_list_* wrappers

2017-01-17 Thread Vadim Kochan
On Tue, Jan 17, 2017 at 5:30 PM, Vadim Kochan <vadi...@gmail.com> wrote:
> Hi Tobias,
>
> Just some thoughts from me regarding this commit, if the below
> can make a sense.
>
> In case if list_head (now cds_list_head) will be used by other modules
> and lets imagine that we will get rid of liburcu dependency (for example
> if we can make flowtop single threaded) then we will need to have copy-paste
> cds_* API from urcu or have a wrappers for it, so may be it is better
> to have generic name w/o cds_ prefix ?
>
> Regards,
> Vadim Kochan

Sorry for the noise.

Well now I think that cds_ will be used for RCU like list usage, and
if to use simple list_head then we will need to have
local list.h to do not make dpendencies to liburcu.

-- 
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.


[netsniff-ng] Re: flowtop: Example of UI tabs interface

2017-01-13 Thread Vadim Kochan
On Fri, Jan 13, 2017 at 3:07 PM, Daniel Borkmann <dan...@iogearbox.net> wrote:
> On 01/13/2017 02:02 PM, Vadim Kochan wrote:
>>
>> Hi,
>>
>> I tried to extend flowtop UI to have some aggregated info via tabbed
>> panel interface.
>> Currently there is only 1 new "Process" tab which grouped flows stat info
>> per
>> unique pid (with summed rates & bytes). Plz let me know if it would be
>> good to have.
>
>
> I like that idea! ;) With *_SRC/*_DST you mean in/out?

For me it means amount/rates of traffic originated from source/destination.

>
>
>> Of course other kind of tabs might be added too - per user, proto, dst/src
>> ip.
>>
>> Regards,
>> Vadim Kochan

-- 
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.


[netsniff-ng] Re: [PATCH] flowtop: Replace single linked list by list_head from list.h

2017-01-13 Thread Vadim Kochan
On Thu, Jan 12, 2017 at 5:20 PM, Tobias Klauser <tklau...@distanz.ch> wrote:
> On 2017-01-12 at 15:54:31 +0100, Vadim Kochan <vadi...@gmail.com> wrote:
>> On Thu, Jan 12, 2017 at 4:28 PM, Tobias Klauser <tklau...@distanz.ch> wrote:
> [...]
>> >>  enum flow_direction {
>> >> @@ -355,15 +357,15 @@ static inline struct flow_entry 
>> >> *flow_entry_xalloc(void)
>> >>  static inline void flow_entry_xfree(struct flow_entry *n)
>> >>  {
>> >>   if (n->ct)
>> >> - nfct_destroy(n->ct);
>> >> + xfree(n->ct);
>> >
>> > This would leak memory allocated internally in struct nf_contrack, no?
>> > What's the reason for this change?
>>
>> nfct_destroy(ct) may fail if we free entry after nfct event processing
>> (our free is defered now because of RCU),
>> so using just free(x) is safer because we do just nfct_clone(ct) which
>> just allocated another nfct_conntrack entry for us,
>> but ofcourse it would be better to have something nfct_free(x), so I
>> agree this is not nice but safer.
>
> As long as it causes memory to be leaked IMO it is equally bad.
>
> If flow_entry_xfree() and thus nfct_destroy() is called via the
> call_rcu() wrapper I proposed, it should no longer be unsafe to call
> nfct_destroy()

I send separate v2 (I already send new version but w/o v2 prefix a changelog).

there should be no any leak as now nfct_conntrack will be not freed by
nfct API because I return NFCT_CB_STOLEN,
and it will be freed (destroyed) in defered rcu call.

I checked via valgrind that there is really memleak but after lookup
geoip record which is allocated by
libGeoIP but is not freed by flowtop. But it needs to be fixed in
separate patch.

-- 
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.


[netsniff-ng] [PATCH] flowtop: Replace single linked list by list_head from list.h

2017-01-12 Thread Vadim Kochan
list.h provides generic Linux-like linked list API which also supports
RCU list operations.

Also additionally was removed the spinlock which is not needed for
RCU-list operations, for the list_del_rcu(...) case it is needed
additionally call call_rcu(...) before free the flow entry.

Because of full RCU support now flows are freed after grace-period
(after presenter leaves RCU lock) via calling call_rcu(), because
of that for the new entries we return NFCT_CB_STOLEN to tell conntrack
API do not automatically free received nfct_conntrack object, it will be
freed by us via call_rcu(...) therefor no need to use nfct_clone(n).

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 flowtop.c | 148 --
 1 file changed, 47 insertions(+), 101 deletions(-)

diff --git a/flowtop.c b/flowtop.c
index f48f5c8..3cee0ec 100644
--- a/flowtop.c
+++ b/flowtop.c
@@ -36,7 +36,6 @@
 #include "lookup.h"
 #include "geoip.h"
 #include "built_in.h"
-#include "locking.h"
 #include "pkt_buff.h"
 #include "screen.h"
 #include "proc.h"
@@ -51,6 +50,9 @@
 #endif
 
 struct flow_entry {
+   struct list_head entry;
+   struct rcu_head rcu;
+
uint32_t flow_id, use, status;
uint8_t  l3_proto, l4_proto;
uint32_t ip4_src_addr, ip4_dst_addr;
@@ -65,7 +67,6 @@ struct flow_entry {
char city_src[128], city_dst[128];
char rev_dns_src[256], rev_dns_dst[256];
char procname[256];
-   struct flow_entry *next;
int inode;
unsigned int procnum;
bool is_visible;
@@ -78,8 +79,7 @@ struct flow_entry {
 };
 
 struct flow_list {
-   struct flow_entry *head;
-   struct spinlock lock;
+   struct list_head head;
 };
 
 enum flow_direction {
@@ -360,10 +360,16 @@ static inline void flow_entry_xfree(struct flow_entry *n)
xfree(n);
 }
 
+static void flow_entry_xfree_rcu(struct rcu_head *head)
+{
+   struct flow_entry *n = container_of(head, struct flow_entry, rcu);
+
+   flow_entry_xfree(n);
+}
+
 static inline void flow_list_init(struct flow_list *fl)
 {
-   fl->head = NULL;
-   spinlock_init(>lock);
+   INIT_LIST_HEAD(>head);
 }
 
 static inline bool nfct_is_dns(const struct nf_conntrack *ct)
@@ -374,7 +380,7 @@ static inline bool nfct_is_dns(const struct nf_conntrack 
*ct)
return ntohs(port_src) == 53 || ntohs(port_dst) == 53;
 }
 
-static void flow_list_new_entry(struct flow_list *fl, const struct 
nf_conntrack *ct)
+static int flow_list_new_entry(struct flow_list *fl, struct nf_conntrack *ct)
 {
struct flow_entry *n;
 
@@ -382,94 +388,56 @@ static void flow_list_new_entry(struct flow_list *fl, 
const struct nf_conntrack
 * use it to resolve reverse dns.
 */
if (nfct_is_dns(ct))
-   return;
+   return NFCT_CB_CONTINUE;
 
n = flow_entry_xalloc();
 
-   n->ct = nfct_clone(ct);
+   n->ct = ct;
 
flow_entry_update_time(n);
flow_entry_from_ct(n, ct);
flow_entry_get_extended(n);
 
-   rcu_assign_pointer(n->next, fl->head);
-   rcu_assign_pointer(fl->head, n);
+   list_add_rcu(>entry, >head);
 
n->is_visible = true;
+
+   return NFCT_CB_STOLEN;
 }
 
-static struct flow_entry *flow_list_find_id(struct flow_list *fl,
-   uint32_t id)
+static struct flow_entry *flow_list_find_id(struct flow_list *fl, uint32_t id)
 {
-   struct flow_entry *n = rcu_dereference(fl->head);
+   struct flow_entry *n;
 
-   while (n != NULL) {
+   list_for_each_entry_rcu(n, >head, entry) {
if (n->flow_id == id)
return n;
-
-   n = rcu_dereference(n->next);
}
 
return NULL;
 }
 
-static struct flow_entry *flow_list_find_prev_id(const struct flow_list *fl,
-uint32_t id)
+static int flow_list_del_entry(struct flow_list *fl, const struct nf_conntrack 
*ct)
 {
-   struct flow_entry *prev = rcu_dereference(fl->head), *next;
-
-   if (prev->flow_id == id)
-   return NULL;
-
-   while ((next = rcu_dereference(prev->next)) != NULL) {
-   if (next->flow_id == id)
-   return prev;
+   struct flow_entry *n;
 
-   prev = next;
+   n = flow_list_find_id(fl, nfct_get_attr_u32(ct, ATTR_ID));
+   if (n) {
+   list_del_rcu(>entry);
+   call_rcu(>rcu, flow_entry_xfree_rcu);
}
 
-   return NULL;
-}
-
-static void flow_list_destroy_entry(struct flow_list *fl,
-   const struct nf_conntrack *ct)
-{
-   struct flow_entry *n1, *n2;
-   uint32_t id = nfct_get_attr_u32(ct, ATTR_ID);
-
-   n1 = flow_list_find_id(fl, id);
-   if (n1) {
-

[netsniff-ng] Re: [PATCH] flowtop: Replace single linked list by list_head from list.h

2017-01-12 Thread Vadim Kochan
On Thu, Jan 12, 2017 at 4:28 PM, Tobias Klauser <tklau...@distanz.ch> wrote:
> Thanks for the patch and sorry for the delay in reply.
>
> I'm not too familiar with the RCU list interface, but from a quick
> glance this looks OK in general. A few remarks below.
>
> Daniel, if you have time could you maybe have a quick look?
>
> On 2017-01-09 at 07:26:07 +0100, Vadim Kochan <vadi...@gmail.com> wrote:
>> list.h provides generic Linux-like linked list API which also supports
>> RCU list operations.
>>
>> Also additionally was removed the spinlock which is not needed for
>> RCU-list operations, for the list_del_rcu(...) case it is needed
>> additionally call synchronize_rcu(...) before free the flow entry.
>>
>> Because of full RCU support now flows are freed after grace-period via
>> calling synchronize_rcu() and these removed-and-ready-to-free entries
>> are kept in separate struct list_head.
>
> Do we really need the separate free list? Couldn't we add a struct
> rcu_head to struct flow_entry instead and then use something along the
> lines of:
>
> static void flow_entry_xfree_rcu(struct rcu_head *rcu)
> {
> struct flow_entry *entry = caa_container_of(rcu, struct flow_entry, 
> rcu_head);
> flow_entry_free(entry);
> }
>
> call_rcu(>rcu_head, free_entry_rcu);
>
> to free the entries after the RCU grace period?

Hm, OK I will look at this, for me it was simpler to use separate list head:)

>
>> Signed-off-by: Vadim Kochan <vadi...@gmail.com>
>
>> ---
>>  flowtop.c | 121 
>> +++---
>>  1 file changed, 44 insertions(+), 77 deletions(-)
>>
>> diff --git a/flowtop.c b/flowtop.c
>> index f48f5c8..a5ac2bb 100644
>> --- a/flowtop.c
>>+++ b/flowtop.c
>
> The #include "locking.h" should be removed as non of the symbols defined
> there are used anymore in flowtop.c
>
>> @@ -51,6 +51,9 @@
>>  #endif
>>
>>  struct flow_entry {
>> + struct list_head entry;
>> + struct list_head free;
>> +
>>   uint32_t flow_id, use, status;
>>   uint8_t  l3_proto, l4_proto;
>>   uint32_t ip4_src_addr, ip4_dst_addr;
>> @@ -65,7 +68,6 @@ struct flow_entry {
>>   char city_src[128], city_dst[128];
>>   char rev_dns_src[256], rev_dns_dst[256];
>>   char procname[256];
>> - struct flow_entry *next;
>>   int inode;
>>   unsigned int procnum;
>>   bool is_visible;
>> @@ -78,8 +80,8 @@ struct flow_entry {
>>  };
>>
>>  struct flow_list {
>> - struct flow_entry *head;
>> - struct spinlock lock;
>> + struct list_head head;
>> + struct list_head free;
>>  };
>>
>>  enum flow_direction {
>> @@ -355,15 +357,15 @@ static inline struct flow_entry 
>> *flow_entry_xalloc(void)
>>  static inline void flow_entry_xfree(struct flow_entry *n)
>>  {
>>   if (n->ct)
>> - nfct_destroy(n->ct);
>> + xfree(n->ct);
>
> This would leak memory allocated internally in struct nf_contrack, no?
> What's the reason for this change?

nfct_destroy(ct) may fail if we free entry after nfct event processing
(our free is defered now because of RCU),
so using just free(x) is safer because we do just nfct_clone(ct) which
just allocated another nfct_conntrack entry for us,
but ofcourse it would be better to have something nfct_free(x), so I
agree this is not nice but safer.

>
>>   xfree(n);
>>  }
>>
>>  static inline void flow_list_init(struct flow_list *fl)
>>  {
>> - fl->head = NULL;
>> - spinlock_init(>lock);
>> + INIT_LIST_HEAD(>head);
>> + INIT_LIST_HEAD(>free);
>>  }
>>
>>  static inline bool nfct_is_dns(const struct nf_conntrack *ct)
>> @@ -392,84 +394,60 @@ static void flow_list_new_entry(struct flow_list *fl, 
>> const struct nf_conntrack
>>   flow_entry_from_ct(n, ct);
>>   flow_entry_get_extended(n);
>>
>> - rcu_assign_pointer(n->next, fl->head);
>> - rcu_assign_pointer(fl->head, n);
>> + list_add_rcu(>entry, >head);
>>
>>   n->is_visible = true;
>>  }
>>
>> -static struct flow_entry *flow_list_find_id(struct flow_list *fl,
>> - uint32_t id)
>> +static struct flow_entry *flow_list_find_id(struct flow_list *fl, uint32_t 
>> id)
>>  {
>> - struct flow_entry *n = rcu_dereference(fl->head);
>> + struct flow_entry *n;
>>
&g

[netsniff-ng] Re: [PATCH 0/4] Introduce new pcap io API for pcap r/w accesses

2017-01-12 Thread Vadim Kochan
On Wed, Dec 14, 2016 at 11:33 PM, Vadim Kochan <vadi...@gmail.com> wrote:
> On Wed, Dec 14, 2016 at 11:26 PM, Tobias Klauser <tklau...@distanz.ch> wrote:
>> On 2016-12-12 at 22:09:52 +0100, Vadim Kochan <vadi...@gmail.com> wrote:
>>> Add new pcap io API to make pcap read/write accesses more
>>> simpler and generic. Added pcap_io & pcap_packet struct's to
>>> keep some internal pcap state like magic, link type & packet header
>>> instead of to pass them like parameters and keep it all within 
>>> netsniff-ng.c.
>>>
>>> Also such approach might be used to unify sniffing from ring buffer via
>>> pcap io API similary as it is done with regular files.
>>>
>>> Some fast-path sensitive or setter/getter functions were inlined in 
>>> pcap_io.h.
>>
>> This series touches very sensitive fast-path code. Before even reviewing
>> it, I'd like to see performance measurments proofing that the your
>> patches don't introduce any performance regressions and that inlining of
>> these functions indeed does the job.
>>
>> Thanks!
>
> Hm, yeah, I need to think how to perform this on my laptop ...

I will try to measure time execution of critical code via clock()
syscall for both versions if it will be OK for you, if yes -
would be it OK to add some #IFDEF's (ahhh not too nice probably) to
have such calculation persistent in the code ?

Regards,
Vadim Kochan

-- 
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.


[netsniff-ng] [PATCH] flowtop: Replace single linked list by list_head from list.h

2017-01-08 Thread Vadim Kochan
list.h provides generic Linux-like linked list API which also supports
RCU list operations.

Also additionally was removed the spinlock which is not needed for
RCU-list operations, for the list_del_rcu(...) case it is needed
additionally call synchronize_rcu(...) before free the flow entry.

Because of full RCU support now flows are freed after grace-period via
calling synchronize_rcu() and these removed-and-ready-to-free entries
are kept in separate struct list_head.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 flowtop.c | 121 +++---
 1 file changed, 44 insertions(+), 77 deletions(-)

diff --git a/flowtop.c b/flowtop.c
index f48f5c8..a5ac2bb 100644
--- a/flowtop.c
+++ b/flowtop.c
@@ -51,6 +51,9 @@
 #endif
 
 struct flow_entry {
+   struct list_head entry;
+   struct list_head free;
+
uint32_t flow_id, use, status;
uint8_t  l3_proto, l4_proto;
uint32_t ip4_src_addr, ip4_dst_addr;
@@ -65,7 +68,6 @@ struct flow_entry {
char city_src[128], city_dst[128];
char rev_dns_src[256], rev_dns_dst[256];
char procname[256];
-   struct flow_entry *next;
int inode;
unsigned int procnum;
bool is_visible;
@@ -78,8 +80,8 @@ struct flow_entry {
 };
 
 struct flow_list {
-   struct flow_entry *head;
-   struct spinlock lock;
+   struct list_head head;
+   struct list_head free;
 };
 
 enum flow_direction {
@@ -355,15 +357,15 @@ static inline struct flow_entry *flow_entry_xalloc(void)
 static inline void flow_entry_xfree(struct flow_entry *n)
 {
if (n->ct)
-   nfct_destroy(n->ct);
+   xfree(n->ct);
 
xfree(n);
 }
 
 static inline void flow_list_init(struct flow_list *fl)
 {
-   fl->head = NULL;
-   spinlock_init(>lock);
+   INIT_LIST_HEAD(>head);
+   INIT_LIST_HEAD(>free);
 }
 
 static inline bool nfct_is_dns(const struct nf_conntrack *ct)
@@ -392,84 +394,60 @@ static void flow_list_new_entry(struct flow_list *fl, 
const struct nf_conntrack
flow_entry_from_ct(n, ct);
flow_entry_get_extended(n);
 
-   rcu_assign_pointer(n->next, fl->head);
-   rcu_assign_pointer(fl->head, n);
+   list_add_rcu(>entry, >head);
 
n->is_visible = true;
 }
 
-static struct flow_entry *flow_list_find_id(struct flow_list *fl,
-   uint32_t id)
+static struct flow_entry *flow_list_find_id(struct flow_list *fl, uint32_t id)
 {
-   struct flow_entry *n = rcu_dereference(fl->head);
+   struct flow_entry *n;
 
-   while (n != NULL) {
+   list_for_each_entry_rcu(n, >head, entry) {
if (n->flow_id == id)
return n;
-
-   n = rcu_dereference(n->next);
}
 
return NULL;
 }
 
-static struct flow_entry *flow_list_find_prev_id(const struct flow_list *fl,
-uint32_t id)
+static void flow_list_del_entry(struct flow_list *fl, const struct 
nf_conntrack *ct)
 {
-   struct flow_entry *prev = rcu_dereference(fl->head), *next;
-
-   if (prev->flow_id == id)
-   return NULL;
-
-   while ((next = rcu_dereference(prev->next)) != NULL) {
-   if (next->flow_id == id)
-   return prev;
+   struct flow_entry *n;
 
-   prev = next;
+   n = flow_list_find_id(fl, nfct_get_attr_u32(ct, ATTR_ID));
+   if (n) {
+   list_del_rcu(>entry);
+   list_add_rcu(>free, >free);
}
-
-   return NULL;
 }
 
-static void flow_list_destroy_entry(struct flow_list *fl,
-   const struct nf_conntrack *ct)
+static void flow_list_clear(struct flow_list *fl)
 {
-   struct flow_entry *n1, *n2;
-   uint32_t id = nfct_get_attr_u32(ct, ATTR_ID);
-
-   n1 = flow_list_find_id(fl, id);
-   if (n1) {
-   n2 = flow_list_find_prev_id(fl, id);
-   if (n2) {
-   rcu_assign_pointer(n2->next, n1->next);
-   n1->next = NULL;
-
-   flow_entry_xfree(n1);
-   } else {
-   struct flow_entry *next = fl->head->next;
+   struct flow_entry *n, *tmp;
 
-   flow_entry_xfree(fl->head);
-   fl->head = next;
-   }
+   list_for_each_entry_safe(n, tmp, >head, entry) {
+   list_del_rcu(>entry);
+   list_add_rcu(>free, >free);
}
 }
 
-static void flow_list_destroy(struct flow_list *fl)
+static void flow_list_free(struct flow_list *fl)
 {
-   struct flow_entry *n;
+   struct flow_entry *n, *tmp;
 
synchronize_rcu();
-   spinlock_lock(_list.lock);
 
-   while (fl->head != NULL) {
-   n = r

[netsniff-ng] Re: New trafgen syntax and some ICMP examples

2017-01-05 Thread Vadim Kochan
On Thu, Jan 05, 2017 at 04:00:36PM +0100, Jesper Dangaard Brouer wrote:
> Hi Vadim,
> 
> I just noticed the new trafgen syntax, I really like it.
> 
> I was playing with testing the kernels ICMP handling code and
> validating some change to the icmp rate-limiting, and wrote an trafgen
> conf for generating a "big" enough ping flood (as hping was not fast
> enough, and ping ratelimit itself).
> 
> Old syntax here[1] and new[2].
>  [1] 
> https://github.com/netoptimizer/network-testing/blob/master/trafgen/icmp01_ping_flood.trafgen
>  [2] 
> https://github.com/netoptimizer/network-testing/blob/master/trafgen/icmp02_ping_flood.trafgen
> 
> With the old syntax I could not express the seq number increment
> correctly (only 1 byte updated), with the new syntax I can.  The old
> dinc() is sort of "broken" IHMO.
> 
> Commits[3] showing the transformation:
>  [3] https://github.com/netoptimizer/network-testing/commits/2b26ad7e66
> 
> Thanks!
> -- 
> Best regards,
>   Jesper Dangaard Brouer
>   MSc.CS, Principal Kernel Engineer at Red Hat
>   LinkedIn: http://www.linkedin.com/in/brouer

Hi Jesper,

Yes, while introducing these proto dynamic functions I realized that
logic for the old/low-level "dinc" does not work well, and I tried add
separate implementation for new "dinc", I will try to unify them to use
only one logic.

Thanks!

-- 
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.


[netsniff-ng] [PATCH] flowtop: Minimize delay via halfdelay(1) function

2017-01-02 Thread Vadim Kochan
Use halfdelay(1) to poll keyboard input with delay in 1 tenth of second
and get rid of custom usleep(...) using.

With this approach (it is also used in htop tool) the key events are more
sensitive to user inputs.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 flowtop.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/flowtop.c b/flowtop.c
index f382d6c..f48f5c8 100644
--- a/flowtop.c
+++ b/flowtop.c
@@ -1238,6 +1238,7 @@ static void presenter(void)
 
screen = screen_init(false);
wclear(screen);
+   halfdelay(1);
 
start_color();
INIT_COLOR(RED, BLACK);
@@ -1320,8 +1321,6 @@ static void presenter(void)
draw_flows(screen, _list, skip_lines);
 
draw_footer();
-
-   usleep(8);
}
rcu_unregister_thread();
 
-- 
2.10.2

-- 
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.


Re: [netsniff-ng] trafgen cfg: automatically padding dynamic values to sizes larger than 1 octet

2016-12-21 Thread Vadim Kochan
On Thu, Oct 20, 2016 at 05:58:12AM -0700, Eddy G wrote:
> It does not seem like it is possible to do something like:
> 
> const16(dinc(1,1023))
> 
> because 1) dinc() and ddec() are limited to single octets, and 2) you can't 
> nest dinc() or ddec() inside the c* helpers.
> 
> The above would be useful to allow a dynamic trafgen cfg that iterates 
> through a range of source/destination ports (for example).
> 
> Is expanding dinc()/ddec() to allow values larger than an octet and 
> "nesting" of other helper functions inside the c*() helpers something that 
> has been discussed?
> 
> Or perhaps a plan to add dinc16() / ddec16(), dinc32()/ddec32(), etc.?
> 
> 
> Also, the new protocol header functions are terrific, but are limited by 
> their inability to prevent more complex / partial dynamic configuration 
> parameters as values. For example:
> 
> eth(da=00:53:00:dinc(0,1):drnd(2))
> ipv4(da=1.2.drnd(2))
> 
> Any possibility this is something that has been discussed? Such partial 
> constructs would be *very* useful in generating randomized traffic for 
> testing purposes.
> 
> 
> Thanks,
> Eddy
> 
> -- 
> 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.


Hi Eddy,

I added ability to specify proto function at specified field's offset:

[:]

 - starts from 0 byte in network order

 - length of value which will be used which might be 1,2 or 4
 bytes (default 1 byte).

Changes added already into master, I have sent separate patch for
trafgen's man page regarding these changes. The similar syntax is used
in pcap filter to match headers field by offset & length. Here are some
examples with trafgen and output from netsniff-ng for better understand
how it can be used:


1) trafgen -o lo --cpus 1 -n 1 '{ eth(da[0]=dinc(), da=11:22:33:44:55:66), 
tcp() }'

P lo 54 1482259546s.934331688ns #1 
 [ Eth MAC (00:00:00:00:00:00 => 00:22:33:44:55:66)


2) trafgen -o lo --cpus 1 -n 1 '{ eth(da=11:22:33:44:55:66, da[0]=dinc()), 
tcp() }'

M lo 54 1482259682s.24357875ns #2 
 [ Eth MAC (00:00:00:00:00:00 => 11:22:33:44:55:66)

3) trafgen -o lo --cpus 1 -n 3 '{ eth(da=11:22:33:44:55:66, da[0]=dinc()), 
tcp() }'

M lo 54 1482259851s.161018621ns #3 
 [ Eth MAC (00:00:00:00:00:00 => 11:22:33:44:55:66)

P lo 54 1482259851s.161032201ns #4 
 [ Eth MAC (00:00:00:00:00:00 => 12:22:33:44:55:66)

M lo 54 1482259851s.161033977ns #5 
 [ Eth MAC (00:00:00:00:00:00 => 13:22:33:44:55:66)

4) trafgen -o lo --cpus 1 -n 3 '{ ipv4(da=1.2.3.4, da[0]=dinc()), tcp() }'

< lo 54 1482265434s.453794790ns #1 
 [ IPv4 Addr (127.0.0.1 => 1.2.3.4)

< lo 54 1482265434s.453811528ns #2 
 [ IPv4 Addr (127.0.0.1 => 2.2.3.4)

< lo 54 1482265434s.453815331ns #3 
 [ IPv4 Addr (127.0.0.1 => 3.2.3.4)

5) trafgen -o lo --cpus 1 -n 3 '{ ipv4(da=192.168.1.1, da[1]=dinc()), tcp() }'

< lo 54 1482265603s.917104425ns #4 
 [ IPv4 Addr (127.0.0.1 => 192.168.1.1)

< lo 54 1482265603s.917122777ns #5 
 [ IPv4 Addr (127.0.0.1 => 192.169.1.1)

< lo 54 1482265603s.917127151ns #6 
 [ IPv4 Addr (127.0.0.1 => 192.170.1.1)


As you see you need to 1st set initial field value and then set this
field with dynamic function at specific offset, we will try to implement
some better short alternative syntax.

Let me know if you have some comments/suggestions.

Regards,
Vadim Kochan

-- 
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.


[netsniff-ng] [PATCH v3] man: trafgen: Add short description about field offset using

2016-12-21 Thread Vadim Kochan
Add short note about field offset syntax with an example.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
v2:
Change commit messages and man file that field offset expression
is used with function expression, and added validation for it in trafgen 
parser.

v3:
Add some examples with new field offset syntax.
Mention syntax was used from pcap filter.

 trafgen.8 | 43 +++
 1 file changed, 43 insertions(+)

diff --git a/trafgen.8 b/trafgen.8
index 62716bb..c633398 100644
--- a/trafgen.8
+++ b/trafgen.8
@@ -329,6 +329,49 @@ Example of using dynamic functions:
 .in -4
 
 .sp
+Field might be set with a function at a specific offset within a field:
+.sp
+.in +4
+[] | [:]
+.sp
+.in +4
+ - relative field's offset with range 0.. - 1
+.sp
+ - length/size of the value which will be set - 1,2 or 4 bytes 
(default: 1).
+.in -4
+.sp
+The  starts from the 1st field's byte in the network order.
+.sp
+The syntax is similar which is used in pcap filter (man pcap-filter) for 
matching
+header field at a specified offset.
+.sp
+Examples of using field offset with a shortified output from netsniff-ng tool:
+.sp
+.in +4
+1) trafgen -o lo --cpus 1 -n 3 '{ eth(da=11:22:33:44:55:66, da[0]=dinc()), 
tcp() }'
+
+.in +4
+[ Eth MAC (00:00:00:00:00:00 => 11:22:33:44:55:66)
+
+[ Eth MAC (00:00:00:00:00:00 => 12:22:33:44:55:66)
+
+[ Eth MAC (00:00:00:00:00:00 => 13:22:33:44:55:66)
+.in -4
+
+2) trafgen -o lo --cpus 1 -n 3 '{ ipv4(da=1.2.3.4, da[0]=dinc()), tcp() }'
+
+.in +4
+[ IPv4 Addr (127.0.0.1 => 1.2.3.4)
+
+[ IPv4 Addr (127.0.0.1 => 2.2.3.4)
+
+[ IPv4 Addr (127.0.0.1 => 3.2.3.4)
+.in -4
+
+.in -4
+.in -4
+
+.sp
 All required lower layer headers will be filled automatically if they were not
 specified by the user. The headers will be filled in the order they were
 specified. Each header will be filled with some mimimum required set of fields.
-- 
2.10.2

-- 
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.


[netsniff-ng] Re: [PATCH v2 6/7] trafgen: parser: Allow to set function at field offset

2016-12-21 Thread Vadim Kochan
On Wed, Dec 21, 2016 at 10:17:17AM +0100, Tobias Klauser wrote:
> On 2016-12-20 at 22:10:54 +0100, Vadim Kochan <vadi...@gmail.com> wrote:
> > On Tue, Dec 20, 2016 at 12:33:47PM +0100, Tobias Klauser wrote:
> > > On 2016-12-18 at 10:52:49 +0100, Vadim Kochan <vadi...@gmail.com> wrote:
> > > > Extend proto field expression to:
> > > > 
> > > > proto_field[{index}:{len}] = {func}
> > > 
> > > I like the idea behind this very much, but I'm not particularly happy
> > > with the syntax of this.
> > > 
> > > First, I find it a bit confusing that the length is specified and not
> > > the end index (as at least I would assume it i.e. like array indexing in
> > > Python works).
> > 
> > Well, I do not thing we need to rely on Python's syntax, actually
> > I used such syntax from pcap filter (man pcap-filter):
> 
> No, I don't think we need Python's syntax either. It's just what I'm
> currently more used to - so it was rather a statement of personal
> preference. Annd I didn't really know about the pcap filter synatax. In
> any case, I'm also fine with how you currently implemented it.
> 
> ICould you please mention the fact that it is inspired by pcap
> filter syntax in the man page?
> 
> > ...
> > 
> > To access data inside the packet, use the following syntax:
> > proto [ expr : size ] Proto  is  one  of  ether, fddi, tr, wlan, ppp,
> > slip, link, ip, arp, rarp, tcp, udp, icmp, ip6 or radio, and indicates
> > the protocol layer for the index operation.  (ether, fddi, wlan, tr,
> > ppp, slip and link all  refer to  the  link  layer. radio refers to the
> > "radio header" added to some 802.11 captures.)  Note that tcp, udp and
> > other upper-layer protocol types only apply to IPv4, not IPv6 (this will
> > be fixed in the  future).   The byte offset, relative to the indicated
> > protocol layer, is given by expr.  Size is optional and indicates the
> > number of bytes in the field of interest; it can be either one, two, or
> > four,  and  defaults  to  one.   The length operator, indicated by the
> > keyword len, gives the length of the packet.
> > 
> > ...
> > > 
> > > Second, the need to mention a field twice with
> > > something like:
> > > 
> > >   eth(saddr=aa:bb:cc:dd:ee:ff, saddr[0]=dinc())
> > > 
> > > isn't very intuitive to understand IMO. And moreover, from the existing
> > > syntax I'd assume some kind of function call semantics (like in C) with
> > > the fields being parameters to the function. But indexing a function
> > > parameter isn't really what I'm used to (but then again this is just
> > > personal taste).
> > 
> > Hm, to reduce using field assignment twice I think it is possible to
> > extend proto dynamic functions with default value as parameter then
> > it make possible to have a mix of index + function parameter like:
> > 
> > eth(sa[0]=dinc(11:22:33:44:55:66))
> > 
> > with min & max drnd parameters:
> > 
> > eth(sa[0]=dinc(100, 200, 11:22:33:44:55:66))
> 
> I think these are more confusing than the current solution.
> 
> > If you like it then can we 1st introduce current solution and after
> > just extend this to the above's syntax ?
> 
> Yes, I guess we can introduce your currently proposed solution and then
> extend upon it if need be.
> 
> > > And third, it's not immediately intuitive to which item the index
> > > refers, i.e. is the MAC address ab:bb:cc:dd:ee:ff afterwards or
> > > aa:bb:cc:dd:ee:00?
> > 
> > Indexing starts from 0 byte in the network order, please see a below 
> > examples of
> > trafgen + netsniff-ng outputs:
> 
> Ok. Could you please mention this fact (that indices start from byte 0
> in network order) in the man page?
> 

Hm, actually I did it in the man patch, but may be too shortly ...

> > 1) trafgen -o lo --cpus 1 -n 1 '{ eth(da[0]=dinc(), da=11:22:33:44:55:66), 
> > tcp() }'
> > 
> > P lo 54 1482259546s.934331688ns #1 
> >  [ Eth MAC (00:00:00:00:00:00 => 00:22:33:44:55:66)
> > 
> > Hm, here you can see that if to specify 1st proto function and after a
> > field value then looks like the value will be overwritten by function, not
> > sure if it is a bug or feature ...
> 
> Might be a bit confusing. But I'd say we can currently live with that.
> Maybe it's worth to mention this fact in the man page too, i.e. that
> functions are always applied after setting field values?
> 
> 

[netsniff-ng] Re: [PATCH v2 6/7] trafgen: parser: Allow to set function at field offset

2016-12-20 Thread Vadim Kochan
On Tue, Dec 20, 2016 at 12:33:47PM +0100, Tobias Klauser wrote:
> On 2016-12-18 at 10:52:49 +0100, Vadim Kochan <vadi...@gmail.com> wrote:
> > Extend proto field expression to:
> > 
> > proto_field[{index}:{len}] = {func}
> 
> I like the idea behind this very much, but I'm not particularly happy
> with the syntax of this.
> 
> First, I find it a bit confusing that the length is specified and not
> the end index (as at least I would assume it i.e. like array indexing in
> Python works).

Well, I do not thing we need to rely on Python's syntax, actually
I used such syntax from pcap filter (man pcap-filter):
...

To access data inside the packet, use the following syntax:
proto [ expr : size ] Proto  is  one  of  ether, fddi, tr, wlan, ppp,
slip, link, ip, arp, rarp, tcp, udp, icmp, ip6 or radio, and indicates
the protocol layer for the index operation.  (ether, fddi, wlan, tr,
ppp, slip and link all  refer to  the  link  layer. radio refers to the
"radio header" added to some 802.11 captures.)  Note that tcp, udp and
other upper-layer protocol types only apply to IPv4, not IPv6 (this will
be fixed in the  future).   The byte offset, relative to the indicated
protocol layer, is given by expr.  Size is optional and indicates the
number of bytes in the field of interest; it can be either one, two, or
four,  and  defaults  to  one.   The length operator, indicated by the
keyword len, gives the length of the packet.

...
> 
> Second, the need to mention a field twice with
> something like:
> 
>   eth(saddr=aa:bb:cc:dd:ee:ff, saddr[0]=dinc())
> 
> isn't very intuitive to understand IMO. And moreover, from the existing
> syntax I'd assume some kind of function call semantics (like in C) with
> the fields being parameters to the function. But indexing a function
> parameter isn't really what I'm used to (but then again this is just
> personal taste).

Hm, to reduce using field assignment twice I think it is possible to
extend proto dynamic functions with default value as parameter then
it make possible to have a mix of index + function parameter like:

eth(sa[0]=dinc(11:22:33:44:55:66))

with min & max drnd parameters:

eth(sa[0]=dinc(100, 200, 11:22:33:44:55:66))

If you like it then can we 1st introduce current solution and after
just extend this to the above's syntax ?

> 
> And third, it's not immediately intuitive to which item the index
> refers, i.e. is the MAC address ab:bb:cc:dd:ee:ff afterwards or
> aa:bb:cc:dd:ee:00?

Indexing starts from 0 byte in the network order, please see a below examples of
trafgen + netsniff-ng outputs:

1) trafgen -o lo --cpus 1 -n 1 '{ eth(da[0]=dinc(), da=11:22:33:44:55:66), 
tcp() }'

P lo 54 1482259546s.934331688ns #1 
 [ Eth MAC (00:00:00:00:00:00 => 00:22:33:44:55:66)

Hm, here you can see that if to specify 1st proto function and after a
field value then looks like the value will be overwritten by function, not
sure if it is a bug or feature ...


2) trafgen -o lo --cpus 1 -n 1 '{ eth(da=11:22:33:44:55:66, da[0]=dinc()), 
tcp() }'

M lo 54 1482259682s.24357875ns #2 
 [ Eth MAC (00:00:00:00:00:00 => 11:22:33:44:55:66)

3) trafgen -o lo --cpus 1 -n 3 '{ eth(da=11:22:33:44:55:66, da[0]=dinc()), 
tcp() }'

M lo 54 1482259851s.161018621ns #3 
 [ Eth MAC (00:00:00:00:00:00 => 11:22:33:44:55:66)

P lo 54 1482259851s.161032201ns #4 
 [ Eth MAC (00:00:00:00:00:00 => 12:22:33:44:55:66)

M lo 54 1482259851s.161033977ns #5 
 [ Eth MAC (00:00:00:00:00:00 => 13:22:33:44:55:66)

4) trafgen -o lo --cpus 1 -n 3 '{ ipv4(da=1.2.3.4, da[0]=dinc()), tcp() }'

< lo 54 1482265434s.453794790ns #1 
 [ IPv4 Addr (127.0.0.1 => 1.2.3.4)

< lo 54 1482265434s.453811528ns #2 
 [ IPv4 Addr (127.0.0.1 => 2.2.3.4)

< lo 54 1482265434s.453815331ns #3 
 [ IPv4 Addr (127.0.0.1 => 3.2.3.4)

5) trafgen -o lo --cpus 1 -n 3 '{ ipv4(da=192.168.1.1, da[1]=dinc()), tcp() }'

< lo 54 1482265603s.917104425ns #4 
 [ IPv4 Addr (127.0.0.1 => 192.168.1.1)

< lo 54 1482265603s.917122777ns #5 
 [ IPv4 Addr (127.0.0.1 => 192.169.1.1)

< lo 54 1482265603s.917127151ns #6 
 [ IPv4 Addr (127.0.0.1 => 192.170.1.1)
> 
> But then I currently don't immediately see a better way to implement
> this behavior and I also see why you'd chosen the indexing to work with
> length rather than end index.
> 
> One option might be to let the user specify multi-byte/-word fields as a
> C-array-like initializer list and support function calls therein, i.e.
> the example above could be written as:
> 
>   eth(saddr={ 0xaa, 0xbb, 0xcc, 0xdd, 0xee, drnd() })

Hm, l

[netsniff-ng] [PATCH v2 2/7] trafgen: proto: Change __proto_field_set_bytes(...) to take field

2016-12-18 Thread Vadim Kochan
Change __proto_field_set_bytes(...) function to take struct proto_field
instead of do looup by hdr & fid.

It is needed to able use this function with some custom
modified struct proto_field (len, pkt_offset).

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen_proto.c | 50 +-
 1 file changed, 33 insertions(+), 17 deletions(-)

diff --git a/trafgen_proto.c b/trafgen_proto.c
index 62ac831..05fccb2 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -181,11 +181,10 @@ set_proto:
return current;
 }
 
-static void __proto_field_set_bytes(struct proto_hdr *hdr, uint32_t fid,
+static void __proto_field_set_bytes(struct proto_field *field,
const uint8_t *bytes, bool is_default,
bool is_be)
 {
-   struct proto_field *field;
uint8_t *payload, *p8;
uint16_t *p16;
uint32_t *p32;
@@ -193,12 +192,10 @@ static void __proto_field_set_bytes(struct proto_hdr 
*hdr, uint32_t fid,
uint16_t v16;
uint8_t v8;
 
-   field = proto_field_by_id(hdr, fid);
-
if (is_default && field->is_set)
return;
 
-   payload = _get(hdr->pkt_id)->payload[field->pkt_offset];
+   payload = _get(field->hdr->pkt_id)->payload[field->pkt_offset];
 
if (field->len == 1) {
p8 = payload;
@@ -239,7 +236,7 @@ static void __proto_field_set_bytes(struct proto_hdr *hdr, 
uint32_t fid,
 void proto_field_set_bytes(struct proto_hdr *hdr, uint32_t fid,
   const uint8_t *bytes)
 {
-   __proto_field_set_bytes(hdr, fid, bytes, false, false);
+   __proto_field_set_bytes(proto_field_by_id(hdr, fid), bytes, false, 
false);
 }
 
 static uint8_t *__proto_field_get_bytes(struct proto_field *field)
@@ -289,47 +286,64 @@ uint32_t proto_field_get_u32(struct proto_hdr *hdr, 
uint32_t fid)
 void proto_field_set_default_bytes(struct proto_hdr *hdr, uint32_t fid,
   const uint8_t *bytes)
 {
-   __proto_field_set_bytes(hdr, fid, bytes, true, false);
+   struct proto_field *field = proto_field_by_id(hdr, fid);
+
+   __proto_field_set_bytes(field, bytes, true, false);
 }
 
 void proto_field_set_default_u8(struct proto_hdr *hdr, uint32_t fid, uint8_t 
val)
 {
-   __proto_field_set_bytes(hdr, fid, (uint8_t *), true, false);
+   struct proto_field *field = proto_field_by_id(hdr, fid);
+
+   __proto_field_set_bytes(field, (uint8_t *), true, false);
 }
 
 void proto_field_set_default_u16(struct proto_hdr *hdr, uint32_t fid, uint16_t 
val)
 {
-   __proto_field_set_bytes(hdr, fid, (uint8_t *), true, false);
+   struct proto_field *field = proto_field_by_id(hdr, fid);
+
+   __proto_field_set_bytes(field, (uint8_t *), true, false);
 }
 
 void proto_field_set_default_u32(struct proto_hdr *hdr, uint32_t fid, uint32_t 
val)
 {
-   __proto_field_set_bytes(hdr, fid, (uint8_t *), true, false);
+   struct proto_field *field = proto_field_by_id(hdr, fid);
+
+   __proto_field_set_bytes(field, (uint8_t *), true, false);
 }
 
 void proto_field_set_be16(struct proto_hdr *hdr, uint32_t fid, uint16_t val)
 {
-   __proto_field_set_bytes(hdr, fid, (uint8_t *), false, true);
+   struct proto_field *field = proto_field_by_id(hdr, fid);
+
+   __proto_field_set_bytes(field, (uint8_t *), false, true);
 }
 
 void proto_field_set_be32(struct proto_hdr *hdr, uint32_t fid, uint32_t val)
 {
-   __proto_field_set_bytes(hdr, fid, (uint8_t *), false, true);
+   struct proto_field *field = proto_field_by_id(hdr, fid);
+
+   __proto_field_set_bytes(field, (uint8_t *), false, true);
 }
 
 void proto_field_set_default_be16(struct proto_hdr *hdr, uint32_t fid, 
uint16_t val)
 {
-   __proto_field_set_bytes(hdr, fid, (uint8_t *), true, true);
+   struct proto_field *field = proto_field_by_id(hdr, fid);
+
+   __proto_field_set_bytes(field, (uint8_t *), true, true);
 }
 
 void proto_field_set_default_be32(struct proto_hdr *hdr, uint32_t fid, 
uint32_t val)
 {
-   __proto_field_set_bytes(hdr, fid, (uint8_t *), true, true);
+   struct proto_field *field = proto_field_by_id(hdr, fid);
+
+   __proto_field_set_bytes(field, (uint8_t *), true, true);
 }
 
 static void __proto_field_set_dev_mac(struct proto_hdr *hdr, uint32_t fid,
  bool is_default)
 {
+   struct proto_field *field = proto_field_by_id(hdr, fid);
uint8_t mac[ETH_ALEN];
int ret;
 
@@ -340,7 +354,7 @@ static void __proto_field_set_dev_mac(struct proto_hdr 
*hdr, uint32_t fid,
if (ret < 0)
panic("Could not get device hw address\n");
 
-   __proto_field_set_bytes(hdr, fid, mac, is_default, false);
+   __proto_field_set_bytes(field, mac, is_default, false);
 }
 
 void proto_field_set_dev_mac(struct proto_hdr *hdr, uint32_t fid)
@@ -3

[netsniff-ng] [PATCH v2 4/7] trafgen: proto: Add proto field only setters/getters

2016-12-18 Thread Vadim Kochan
Add proto_field_xxx functions to set/get value via specified
proto_field only.

It is good to have such API in case if application needs to set/get
value for some custom proto_field instance.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen_proto.c | 46 ++
 trafgen_proto.h | 10 ++
 2 files changed, 56 insertions(+)

diff --git a/trafgen_proto.c b/trafgen_proto.c
index f862592..e2b80d4 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -431,6 +431,52 @@ 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_field_set_u8(struct proto_field *field, uint8_t val)
+{
+   __proto_field_set_bytes(field, , false, false);
+}
+
+uint8_t proto_field_get_u8(struct proto_field *field)
+{
+   uint8_t val = *__proto_field_get_bytes(field);
+
+   return field_unmask_and_unshift(field, val);
+}
+
+void proto_field_set_u16(struct proto_field *field, uint16_t val)
+{
+   __proto_field_set_bytes(field, (uint8_t *), false, false);
+}
+
+uint16_t proto_field_get_u16(struct proto_field *field)
+{
+   uint16_t val = *(uint16_t *)__proto_field_get_bytes(field);
+
+   return field_unmask_and_unshift(field, be16_to_cpu(val));
+}
+
+void proto_field_set_u32(struct proto_field *field, uint32_t val)
+{
+   __proto_field_set_bytes(field, (uint8_t *), false, false);
+}
+
+uint32_t proto_field_get_u32(struct proto_field *field)
+{
+   uint32_t val = *(uint32_t *)__proto_field_get_bytes(field);
+
+   return field_unmask_and_unshift(field, be32_to_cpu(val));
+}
+
+void proto_field_set_be16(struct proto_field *field, uint16_t val)
+{
+   __proto_field_set_bytes(field, (uint8_t *), false, true);
+}
+
+void proto_field_set_be32(struct proto_field *field, uint32_t val)
+{
+   __proto_field_set_bytes(field, (uint8_t *), false, true);
+}
+
 void protos_init(const char *dev)
 {
ctx.dev = dev;
diff --git a/trafgen_proto.h b/trafgen_proto.h
index 927fcb1..d4427e6 100644
--- a/trafgen_proto.h
+++ b/trafgen_proto.h
@@ -147,4 +147,14 @@ extern void proto_hdr_field_func_add(struct proto_hdr 
*hdr, uint32_t fid,
 
 extern struct proto_field *proto_hdr_field_by_id(struct proto_hdr *hdr, 
uint32_t fid);
 
+
+extern void proto_field_set_u8(struct proto_field *field, uint8_t val);
+extern uint8_t proto_field_get_u8(struct proto_field *field);
+extern void proto_field_set_u16(struct proto_field *field, uint16_t val);
+extern uint16_t proto_field_get_u16(struct proto_field *field);
+extern void proto_field_set_u32(struct proto_field *field, uint32_t val);
+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);
+
 #endif /* TRAFGEN_PROTO_H */
-- 
2.10.2

-- 
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.


[netsniff-ng] [PATCH v2 5/7] trafgen: parser: Parse IPv6 address by strict match pattern

2016-12-18 Thread Vadim Kochan
Used IPv6 pattern from nftables project to match valid only IPv6
address to do not mess with MAC or other syntax patterns with ':' symbol.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen_lexer.l  | 51 +++
 trafgen_parser.y |  2 +-
 2 files changed, 48 insertions(+), 5 deletions(-)

diff --git a/trafgen_lexer.l b/trafgen_lexer.l
index 025fbfe..ad9dfe7 100644
--- a/trafgen_lexer.l
+++ b/trafgen_lexer.l
@@ -77,13 +77,56 @@ number_bin  ([0]?[b][0-1]+)
 number_dec (([0])|([1-9][0-9]*))
 number_ascii   ([a-zA-Z])
 
+hex4   ([[:xdigit:]]{1,4})
+v680   (({hex4}:){7}{hex4})
+v670   ((:)((:{hex4}){7}))
+v671   ((({hex4}:){1})((:{hex4}){6}))
+v672   ((({hex4}:){2})((:{hex4}){5}))
+v673   ((({hex4}:){3})((:{hex4}){4}))
+v674   ((({hex4}:){4})((:{hex4}){3}))
+v675   ((({hex4}:){5})((:{hex4}){2}))
+v676   ((({hex4}:){6})(:{hex4}{1}))
+v677   ((({hex4}:){7})(:))
+v67({v670}|{v671}|{v672}|{v673}|{v674}|{v675}|{v676}|{v677})
+v660   ((:)((:{hex4}){6}))
+v661   ((({hex4}:){1})((:{hex4}){5}))
+v662   ((({hex4}:){2})((:{hex4}){4}))
+v663   ((({hex4}:){3})((:{hex4}){3}))
+v664   ((({hex4}:){4})((:{hex4}){2}))
+v665   ((({hex4}:){5})((:{hex4}){1}))
+v666   ((({hex4}:){6})(:))
+v66({v660}|{v661}|{v662}|{v663}|{v664}|{v665}|{v666})
+v650   ((:)((:{hex4}){5}))
+v651   ((({hex4}:){1})((:{hex4}){4}))
+v652   ((({hex4}:){2})((:{hex4}){3}))
+v653   ((({hex4}:){3})((:{hex4}){2}))
+v654   ((({hex4}:){4})(:{hex4}{1}))
+v655   ((({hex4}:){5})(:))
+v65({v650}|{v651}|{v652}|{v653}|{v654}|{v655})
+v640   ((:)((:{hex4}){4}))
+v641   ((({hex4}:){1})((:{hex4}){3}))
+v642   ((({hex4}:){2})((:{hex4}){2}))
+v643   ((({hex4}:){3})((:{hex4}){1}))
+v644   ((({hex4}:){4})(:))
+v64({v640}|{v641}|{v642}|{v643}|{v644})
+v630   ((:)((:{hex4}){3}))
+v631   ((({hex4}:){1})((:{hex4}){2}))
+v632   ((({hex4}:){2})((:{hex4}){1}))
+v633   ((({hex4}:){3})(:))
+v63({v630}|{v631}|{v632}|{v633})
+v620   ((:)((:{hex4}){2}))
+v621   ((({hex4}:){1})((:{hex4}){1}))
+v622   ((({hex4}:){2})(:))
+v62({v620}|{v621}|{v622})
+v610   ((:)(:{hex4}{1}))
+v611   ((({hex4}:){1})(:))
+v61({v610}|{v611})
+v60(::)
+
 a_hex  ([a-fA-F0-9]+)
 mac({a_hex}:{a_hex}:{a_hex}:{a_hex}:{a_hex}:{a_hex})
 ip4_addr   ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)
-   /* We're very permissive about IPv6 addresses the grammar accepts, as
-* they can come in various different formats. In any case,
-* inet_pton(AF_INET6, ...) will reject the invalid ones later on. */
-ip6_addr   
(({a_hex}?:)?({a_hex}?:)?({a_hex}?:)?({a_hex}?:)?({a_hex}?:)?({a_hex}?:)?({a_hex}?:)?({a_hex})?)
+ip6_addr   ({v680}|{v67}|{v66}|{v65}|{v64}|{v63}|{v62}|{v61}|{v60})
 
 %%
 
diff --git a/trafgen_parser.y b/trafgen_parser.y
index bfeed2e..a1b8b0c 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@@ -416,7 +416,7 @@ static void proto_field_expr_eval(void)
else if (field->len == 4)
proto_hdr_field_set_be32(hdr, field->id, 
field_expr.val.number);
else
-   bug();
+   proto_hdr_field_set_bytes(hdr, field->id, 
field_expr.val.bytes);
break;
 
case FIELD_EXPR_MAC:
-- 
2.10.2

-- 
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.


[netsniff-ng] [PATCH v2 7/7] man: trafgen: Add short description about field offset using

2016-12-18 Thread Vadim Kochan
Add short note about field offset syntax with an example.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen.8 | 25 +
 1 file changed, 25 insertions(+)

diff --git a/trafgen.8 b/trafgen.8
index 62716bb..d669c2a 100644
--- a/trafgen.8
+++ b/trafgen.8
@@ -329,6 +329,31 @@ Example of using dynamic functions:
 .in -4
 
 .sp
+Field might be set with a function at a specific offset within a field:
+.sp
+.in +4
+[] | [:]
+.sp
+.in +4
+ - relative field's offset with range 0.. - 1
+.sp
+ - length/size of the value which will be set - 1,2 or 4 bytes 
(default: 1).
+.in -4
+.sp
+The  starts from the 1st field's byte in the network order.
+.sp
+Example of using field offset:
+.sp
+{
+.in +2
+eth(saddr=aa:bb:cc:dd:ee:ff, saddr[0]=dinc()),
+ipv4(saddr[0:2]=drnd()),
+udp(),
+.in -2
+}
+.in -4
+
+.sp
 All required lower layer headers will be filled automatically if they were not
 specified by the user. The headers will be filled in the order they were
 specified. Each header will be filled with some mimimum required set of fields.
-- 
2.10.2

-- 
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.


[netsniff-ng] [PATCH v2 3/7] trafgen: proto: Rename proto_field_xxx -> proto_hdr_field_xxx

2016-12-18 Thread Vadim Kochan
Rename all proto_field_xxx(...) functions to proto_hdr_field(...).

It is good for 2 reasons:
1) proto_hdr_field_xxx naming is more consistent as
   it is related to proto_hdr API.

2) It makes possible to introduce proto_field_xxx API
   which will operate only with struct proto_field.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen_l2.c |  44 -
 trafgen_l3.c |  24 +-
 trafgen_l4.c |  28 +--
 trafgen_parser.y |  64 -
 trafgen_proto.c  | 144 ---
 trafgen_proto.h  |  52 ++--
 6 files changed, 179 insertions(+), 177 deletions(-)

diff --git a/trafgen_l2.c b/trafgen_l2.c
index b27c9dd..5fc0a0d 100644
--- a/trafgen_l2.c
+++ b/trafgen_l2.c
@@ -40,14 +40,14 @@ static uint16_t pid_to_eth(enum proto_id pid)
 
 static void eth_set_next_proto(struct proto_hdr *hdr, enum proto_id pid)
 {
-   proto_field_set_default_be16(hdr, ETH_TYPE, pid_to_eth(pid));
+   proto_hdr_field_set_default_be16(hdr, ETH_TYPE, pid_to_eth(pid));
 }
 
 static void eth_header_init(struct proto_hdr *hdr)
 {
proto_header_fields_add(hdr, eth_fields, array_size(eth_fields));
 
-   proto_field_set_default_dev_mac(hdr, ETH_SRC_ADDR);
+   proto_hdr_field_set_default_dev_mac(hdr, ETH_SRC_ADDR);
 }
 
 static const struct proto_ops eth_proto_ops = {
@@ -69,10 +69,10 @@ static void pause_header_init(struct proto_hdr *hdr)
struct proto_hdr *lower;
 
lower = proto_lower_default_add(hdr, PROTO_ETH);
-   proto_field_set_default_bytes(lower, ETH_DST_ADDR, eth_dst);
+   proto_hdr_field_set_default_bytes(lower, ETH_DST_ADDR, eth_dst);
 
proto_header_fields_add(hdr, pause_fields, array_size(pause_fields));
-   proto_field_set_default_be16(hdr, PAUSE_OPCODE, 0x1);
+   proto_hdr_field_set_default_be16(hdr, PAUSE_OPCODE, 0x1);
 }
 
 static struct proto_ops pause_proto_ops = {
@@ -109,10 +109,10 @@ static void pfc_header_init(struct proto_hdr *hdr)
struct proto_hdr *lower;
 
lower = proto_lower_default_add(hdr, PROTO_ETH);
-   proto_field_set_default_bytes(lower, ETH_DST_ADDR, eth_dst);
+   proto_hdr_field_set_default_bytes(lower, ETH_DST_ADDR, eth_dst);
 
proto_header_fields_add(hdr, pfc_fields, array_size(pfc_fields));
-   proto_field_set_default_be16(hdr, PFC_OPCODE, 0x0101);
+   proto_hdr_field_set_default_be16(hdr, PFC_OPCODE, 0x0101);
 }
 
 static struct proto_ops pfc_proto_ops = {
@@ -140,18 +140,18 @@ static void vlan_header_init(struct proto_hdr *hdr)
proto_header_fields_add(hdr, vlan_fields, array_size(vlan_fields));
 
if (lower->ops->id == PROTO_ETH)
-   lower_etype = proto_field_get_u16(lower, ETH_TYPE);
+   lower_etype = proto_hdr_field_get_u16(lower, ETH_TYPE);
else if (lower->ops->id == PROTO_VLAN)
-   lower_etype = proto_field_get_u16(lower, VLAN_ETYPE);
+   lower_etype = proto_hdr_field_get_u16(lower, VLAN_ETYPE);
 
-   proto_field_set_be16(hdr, VLAN_ETYPE, lower_etype);
-   proto_field_set_default_be16(hdr, VLAN_TPID, pid_to_eth(hdr->ops->id));
+   proto_hdr_field_set_be16(hdr, VLAN_ETYPE, lower_etype);
+   proto_hdr_field_set_default_be16(hdr, VLAN_TPID, 
pid_to_eth(hdr->ops->id));
 }
 
 static void vlan_set_next_proto(struct proto_hdr *hdr, enum proto_id pid)
 {
if (pid != PROTO_VLAN)
-   proto_field_set_be16(hdr, VLAN_ETYPE, pid_to_eth(pid));
+   proto_hdr_field_set_be16(hdr, VLAN_ETYPE, pid_to_eth(pid));
 }
 
 static const struct proto_ops vlan_proto_ops = {
@@ -180,20 +180,20 @@ static void arp_header_init(struct proto_hdr *hdr)
if (lower->ops->id == PROTO_ETH) {
const uint8_t bcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 
-   proto_field_set_default_bytes(lower, ETH_DST_ADDR, bcast);
+   proto_hdr_field_set_default_bytes(lower, ETH_DST_ADDR, bcast);
}
 
proto_header_fields_add(hdr, arp_fields, array_size(arp_fields));
 
/* Generate Announce request by default */
-   proto_field_set_default_be16(hdr, ARP_HTYPE, ARPHRD_ETHER);
-   proto_field_set_default_be16(hdr, ARP_PTYPE, ETH_P_IP);
-   proto_field_set_default_u8(hdr, ARP_HLEN, 6);
-   proto_field_set_default_u8(hdr, ARP_PLEN, 4);
-   proto_field_set_default_be16(hdr, ARP_OPER, ARPOP_REQUEST);
-   proto_field_set_default_dev_mac(hdr, ARP_SHA);
-   proto_field_set_default_dev_ipv4(hdr, ARP_SPA);
-   proto_field_set_default_dev_ipv4(hdr, ARP_TPA);
+   proto_hdr_field_set_default_be16(hdr, ARP_HTYPE, ARPHRD_ETHER);
+   proto_hdr_field_set_default_be16(hdr, ARP_PTYPE, ETH_P_IP);
+   proto_hdr_field_set_default_u8(hdr, ARP_HLEN, 6);
+   proto_hdr_field_set_default_u8(hdr, ARP_PLEN, 4);
+   proto_hdr_field_set_defau

[netsniff-ng] [PATCH v2 0/7] trafgen: Allow set proto field function at specific offset

2016-12-18 Thread Vadim Kochan
Extend field expression with the following syntax:

[] | [:]

which allows to specify value or function at specified offset relative to the
field's offset within a header.

The trick to implement this was to use copies of proto_field instances
in the packet_dyn->fields array which allows to specify different functions
for the same field and with different offsets.

It was needed to change IPv6 address rule parsing to more strict rule to allow
parse [:] syntax.

v2:
Change commit messages and man file that field offset expression
is used with function expression, and added validation for it in trafgen 
parser.

Vadim Kochan (7):
  trafgen: parser: Rename field_expr -> field_value_expr rule
  trafgen: proto: Change __proto_field_set_bytes(...) to take field
  trafgen: proto: Rename proto_field_xxx -> proto_hdr_field_xxx
  trafgen: proto: Add proto field only setters/getters
  trafgen: parser: Parse IPv6 address by strict match pattern
  trafgen: parser: Allow to set function at field offset
  man: trafgen: Add short description about field offset using

 trafgen.8|  25 ++
 trafgen_l2.c |  44 +--
 trafgen_l3.c |  24 +++---
 trafgen_l4.c |  28 +++
 trafgen_lexer.l  |  51 +++-
 trafgen_parser.y | 236 ---
 trafgen_proto.c  | 217 +++---
 trafgen_proto.h  |  64 +--
 8 files changed, 450 insertions(+), 239 deletions(-)

-- 
2.10.2

-- 
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.


[netsniff-ng] [PATCH v2 1/7] trafgen: parser: Rename field_expr -> field_value_expr rule

2016-12-18 Thread Vadim Kochan
Rename field_expr rule to field_value_expr to indicate the rule
relates to field value part in case if there will be added field_expr
rule to describe field expression syntax.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen_parser.y | 30 +++---
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/trafgen_parser.y b/trafgen_parser.y
index 1e20cff..7e22a1d 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@@ -718,7 +718,7 @@ proto
| tcp_proto { }
;
 
-field_expr
+field_value_expr
: number { field_expr.type = FIELD_EXPR_NUMB;
   field_expr.val.number = $1; }
| mac { field_expr.type = FIELD_EXPR_MAC;
@@ -783,7 +783,7 @@ eth_field
| eth_type { proto_field_set(ETH_TYPE); }
 
 eth_expr
-   : eth_field skip_white '=' skip_white field_expr
+   : eth_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
;
 
@@ -807,7 +807,7 @@ pause_field
;
 
 pause_expr
-   : pause_field skip_white '=' skip_white field_expr
+   : pause_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
;
 
@@ -843,7 +843,7 @@ pfc_field
;
 
 pfc_expr
-   : pfc_field skip_white '=' skip_white field_expr
+   : pfc_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
;
 
@@ -875,7 +875,7 @@ vlan_field
;
 
 vlan_expr
-   : vlan_field skip_white '=' skip_white field_expr
+   : vlan_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
| K_1Q
{ proto_field_set_be16(hdr, VLAN_TPID, ETH_P_8021Q); }
@@ -910,7 +910,7 @@ mpls_field
;
 
 mpls_expr
-   : mpls_field skip_white '=' skip_white field_expr
+   : mpls_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
 
 arp_proto
@@ -939,9 +939,9 @@ arp_field
;
 
 arp_expr
-   : arp_field skip_white '=' skip_white field_expr
+   : arp_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
-   | K_OPER skip_white '=' skip_white field_expr
+   | K_OPER skip_white '=' skip_white field_value_expr
{ proto_field_set(ARP_OPER);
  proto_field_expr_eval(); }
| K_OPER skip_white '=' skip_white K_REQUEST
@@ -985,7 +985,7 @@ ip4_field
;
 
 ip4_expr
-   : ip4_field skip_white '=' skip_white field_expr
+   : ip4_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
| K_DF  { proto_field_set_be16(hdr, IP4_DF, 1); }
| K_MF  { proto_field_set_be16(hdr, IP4_MF, 1); }
@@ -1022,7 +1022,7 @@ ip6_field
;
 
 ip6_expr
-   : ip6_field skip_white '=' skip_white field_expr
+   : ip6_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
;
 
@@ -1050,7 +1050,7 @@ icmp4_field
;
 
 icmp4_expr
-   : icmp4_field skip_white '=' skip_white field_expr
+   : icmp4_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
| K_ECHO_REQUEST
{ proto_field_set_u8(hdr, ICMPV4_TYPE, ICMP_ECHO);
@@ -1079,9 +1079,9 @@ icmp6_field
;
 
 icmp6_expr
-   : icmp6_field skip_white '=' skip_white field_expr
+   : icmp6_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
-   | K_TYPE skip_white '=' skip_white field_expr
+   | K_TYPE skip_white '=' skip_white field_value_expr
{ proto_field_set(ICMPV6_TYPE);
  proto_field_expr_eval(); }
| K_TYPE skip_white '=' K_ECHO_REQUEST
@@ -1115,7 +1115,7 @@ udp_field
;
 
 udp_expr
-   : udp_field skip_white '=' skip_white field_expr
+   : udp_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
;
 
@@ -1145,7 +1145,7 @@ tcp_field
;
 
 tcp_expr
-   : tcp_field skip_white '=' skip_white field_expr
+   : tcp_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
| K_CWR { proto_field_set_be16(hdr, TCP_CWR, 1); }
| K_ECE { proto_field_set_be16(hdr, TCP_ECE, 1); }
-- 
2.10.2

-- 
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.


[netsniff-ng] Re: [PATCH 0/7] trafgen: Allow set proto field value at specific offset

2016-12-18 Thread Vadim Kochan
On Sat, Dec 17, 2016 at 4:37 PM, Vadim Kochan <vadi...@gmail.com> wrote:
> Extend field expression with the following syntax:
>
> [] | [:]
>
> which allows to specify value or function at specified offset relative to the
> field's offset within a header.
>
> The trick to implement this was to use copies of proto_field instances
> in the packet_dyn->fields array which allows to specify different functions
> for the same field and with different offsets.
>
> Vadim Kochan (7):
>   trafgen: parser: Rename field_expr -> field_value_expr rule
>   trafgen: proto: Change __proto_field_set_bytes(...) to take field
>   trafgen: proto: Rename proto_field_xxx -> proto_hdr_field_xxx
>   trafgen: proto: Add proto field only setters/getters
>   trafgen: parser: Parse IPv6 address by strict match pattern
>   trafgen: parser: Allow to set value/func at field offset
>   man: trafgen: Add short description about field offset using
>
>  trafgen.8|  25 +++
>  trafgen_l2.c |  44 +--
>  trafgen_l3.c |  24 +++---
>  trafgen_l4.c |  28 +++
>  trafgen_lexer.l  |  51 -
>  trafgen_parser.y | 164 +
>  trafgen_proto.c  | 217 
> +++
>  trafgen_proto.h  |  64 +---
>  8 files changed, 412 insertions(+), 205 deletions(-)
>
> --
> 2.10.2
>

Sorry I will resend series as I mistakenly typed that field offset
expression works for both function & value
but really it works only for function expression, so I will update
man, commit messages & add validation.

-- 
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.


[netsniff-ng] [PATCH 2/7] trafgen: proto: Change __proto_field_set_bytes(...) to take field

2016-12-17 Thread Vadim Kochan
Change __proto_field_set_bytes(...) function to take struct proto_field
instead of do looup by hdr & fid.

It is needed to able use this function with some custom
modified struct proto_field (len, pkt_offset).

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen_proto.c | 50 +-
 1 file changed, 33 insertions(+), 17 deletions(-)

diff --git a/trafgen_proto.c b/trafgen_proto.c
index 62ac831..05fccb2 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -181,11 +181,10 @@ set_proto:
return current;
 }
 
-static void __proto_field_set_bytes(struct proto_hdr *hdr, uint32_t fid,
+static void __proto_field_set_bytes(struct proto_field *field,
const uint8_t *bytes, bool is_default,
bool is_be)
 {
-   struct proto_field *field;
uint8_t *payload, *p8;
uint16_t *p16;
uint32_t *p32;
@@ -193,12 +192,10 @@ static void __proto_field_set_bytes(struct proto_hdr 
*hdr, uint32_t fid,
uint16_t v16;
uint8_t v8;
 
-   field = proto_field_by_id(hdr, fid);
-
if (is_default && field->is_set)
return;
 
-   payload = _get(hdr->pkt_id)->payload[field->pkt_offset];
+   payload = _get(field->hdr->pkt_id)->payload[field->pkt_offset];
 
if (field->len == 1) {
p8 = payload;
@@ -239,7 +236,7 @@ static void __proto_field_set_bytes(struct proto_hdr *hdr, 
uint32_t fid,
 void proto_field_set_bytes(struct proto_hdr *hdr, uint32_t fid,
   const uint8_t *bytes)
 {
-   __proto_field_set_bytes(hdr, fid, bytes, false, false);
+   __proto_field_set_bytes(proto_field_by_id(hdr, fid), bytes, false, 
false);
 }
 
 static uint8_t *__proto_field_get_bytes(struct proto_field *field)
@@ -289,47 +286,64 @@ uint32_t proto_field_get_u32(struct proto_hdr *hdr, 
uint32_t fid)
 void proto_field_set_default_bytes(struct proto_hdr *hdr, uint32_t fid,
   const uint8_t *bytes)
 {
-   __proto_field_set_bytes(hdr, fid, bytes, true, false);
+   struct proto_field *field = proto_field_by_id(hdr, fid);
+
+   __proto_field_set_bytes(field, bytes, true, false);
 }
 
 void proto_field_set_default_u8(struct proto_hdr *hdr, uint32_t fid, uint8_t 
val)
 {
-   __proto_field_set_bytes(hdr, fid, (uint8_t *), true, false);
+   struct proto_field *field = proto_field_by_id(hdr, fid);
+
+   __proto_field_set_bytes(field, (uint8_t *), true, false);
 }
 
 void proto_field_set_default_u16(struct proto_hdr *hdr, uint32_t fid, uint16_t 
val)
 {
-   __proto_field_set_bytes(hdr, fid, (uint8_t *), true, false);
+   struct proto_field *field = proto_field_by_id(hdr, fid);
+
+   __proto_field_set_bytes(field, (uint8_t *), true, false);
 }
 
 void proto_field_set_default_u32(struct proto_hdr *hdr, uint32_t fid, uint32_t 
val)
 {
-   __proto_field_set_bytes(hdr, fid, (uint8_t *), true, false);
+   struct proto_field *field = proto_field_by_id(hdr, fid);
+
+   __proto_field_set_bytes(field, (uint8_t *), true, false);
 }
 
 void proto_field_set_be16(struct proto_hdr *hdr, uint32_t fid, uint16_t val)
 {
-   __proto_field_set_bytes(hdr, fid, (uint8_t *), false, true);
+   struct proto_field *field = proto_field_by_id(hdr, fid);
+
+   __proto_field_set_bytes(field, (uint8_t *), false, true);
 }
 
 void proto_field_set_be32(struct proto_hdr *hdr, uint32_t fid, uint32_t val)
 {
-   __proto_field_set_bytes(hdr, fid, (uint8_t *), false, true);
+   struct proto_field *field = proto_field_by_id(hdr, fid);
+
+   __proto_field_set_bytes(field, (uint8_t *), false, true);
 }
 
 void proto_field_set_default_be16(struct proto_hdr *hdr, uint32_t fid, 
uint16_t val)
 {
-   __proto_field_set_bytes(hdr, fid, (uint8_t *), true, true);
+   struct proto_field *field = proto_field_by_id(hdr, fid);
+
+   __proto_field_set_bytes(field, (uint8_t *), true, true);
 }
 
 void proto_field_set_default_be32(struct proto_hdr *hdr, uint32_t fid, 
uint32_t val)
 {
-   __proto_field_set_bytes(hdr, fid, (uint8_t *), true, true);
+   struct proto_field *field = proto_field_by_id(hdr, fid);
+
+   __proto_field_set_bytes(field, (uint8_t *), true, true);
 }
 
 static void __proto_field_set_dev_mac(struct proto_hdr *hdr, uint32_t fid,
  bool is_default)
 {
+   struct proto_field *field = proto_field_by_id(hdr, fid);
uint8_t mac[ETH_ALEN];
int ret;
 
@@ -340,7 +354,7 @@ static void __proto_field_set_dev_mac(struct proto_hdr 
*hdr, uint32_t fid,
if (ret < 0)
panic("Could not get device hw address\n");
 
-   __proto_field_set_bytes(hdr, fid, mac, is_default, false);
+   __proto_field_set_bytes(field, mac, is_default, false);
 }
 
 void proto_field_set_dev_mac(struct proto_hdr *hdr, uint32_t fid)
@@ -3

[netsniff-ng] [PATCH 0/7] trafgen: Allow set proto field value at specific offset

2016-12-17 Thread Vadim Kochan
Extend field expression with the following syntax:

[] | [:]

which allows to specify value or function at specified offset relative to the
field's offset within a header.

The trick to implement this was to use copies of proto_field instances
in the packet_dyn->fields array which allows to specify different functions
for the same field and with different offsets.

Vadim Kochan (7):
  trafgen: parser: Rename field_expr -> field_value_expr rule
  trafgen: proto: Change __proto_field_set_bytes(...) to take field
  trafgen: proto: Rename proto_field_xxx -> proto_hdr_field_xxx
  trafgen: proto: Add proto field only setters/getters
  trafgen: parser: Parse IPv6 address by strict match pattern
  trafgen: parser: Allow to set value/func at field offset
  man: trafgen: Add short description about field offset using

 trafgen.8|  25 +++
 trafgen_l2.c |  44 +--
 trafgen_l3.c |  24 +++---
 trafgen_l4.c |  28 +++
 trafgen_lexer.l  |  51 -
 trafgen_parser.y | 164 +
 trafgen_proto.c  | 217 +++
 trafgen_proto.h  |  64 +---
 8 files changed, 412 insertions(+), 205 deletions(-)

-- 
2.10.2

-- 
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.


[netsniff-ng] [PATCH 1/7] trafgen: parser: Rename field_expr -> field_value_expr rule

2016-12-17 Thread Vadim Kochan
Rename field_expr rule to field_value_expr to indicate the rule
relates to field value part in case if there will be added field_expr
rule to indicate field expression syntax.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen_parser.y | 30 +++---
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/trafgen_parser.y b/trafgen_parser.y
index 1e20cff..7e22a1d 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@@ -718,7 +718,7 @@ proto
| tcp_proto { }
;
 
-field_expr
+field_value_expr
: number { field_expr.type = FIELD_EXPR_NUMB;
   field_expr.val.number = $1; }
| mac { field_expr.type = FIELD_EXPR_MAC;
@@ -783,7 +783,7 @@ eth_field
| eth_type { proto_field_set(ETH_TYPE); }
 
 eth_expr
-   : eth_field skip_white '=' skip_white field_expr
+   : eth_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
;
 
@@ -807,7 +807,7 @@ pause_field
;
 
 pause_expr
-   : pause_field skip_white '=' skip_white field_expr
+   : pause_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
;
 
@@ -843,7 +843,7 @@ pfc_field
;
 
 pfc_expr
-   : pfc_field skip_white '=' skip_white field_expr
+   : pfc_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
;
 
@@ -875,7 +875,7 @@ vlan_field
;
 
 vlan_expr
-   : vlan_field skip_white '=' skip_white field_expr
+   : vlan_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
| K_1Q
{ proto_field_set_be16(hdr, VLAN_TPID, ETH_P_8021Q); }
@@ -910,7 +910,7 @@ mpls_field
;
 
 mpls_expr
-   : mpls_field skip_white '=' skip_white field_expr
+   : mpls_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
 
 arp_proto
@@ -939,9 +939,9 @@ arp_field
;
 
 arp_expr
-   : arp_field skip_white '=' skip_white field_expr
+   : arp_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
-   | K_OPER skip_white '=' skip_white field_expr
+   | K_OPER skip_white '=' skip_white field_value_expr
{ proto_field_set(ARP_OPER);
  proto_field_expr_eval(); }
| K_OPER skip_white '=' skip_white K_REQUEST
@@ -985,7 +985,7 @@ ip4_field
;
 
 ip4_expr
-   : ip4_field skip_white '=' skip_white field_expr
+   : ip4_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
| K_DF  { proto_field_set_be16(hdr, IP4_DF, 1); }
| K_MF  { proto_field_set_be16(hdr, IP4_MF, 1); }
@@ -1022,7 +1022,7 @@ ip6_field
;
 
 ip6_expr
-   : ip6_field skip_white '=' skip_white field_expr
+   : ip6_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
;
 
@@ -1050,7 +1050,7 @@ icmp4_field
;
 
 icmp4_expr
-   : icmp4_field skip_white '=' skip_white field_expr
+   : icmp4_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
| K_ECHO_REQUEST
{ proto_field_set_u8(hdr, ICMPV4_TYPE, ICMP_ECHO);
@@ -1079,9 +1079,9 @@ icmp6_field
;
 
 icmp6_expr
-   : icmp6_field skip_white '=' skip_white field_expr
+   : icmp6_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
-   | K_TYPE skip_white '=' skip_white field_expr
+   | K_TYPE skip_white '=' skip_white field_value_expr
{ proto_field_set(ICMPV6_TYPE);
  proto_field_expr_eval(); }
| K_TYPE skip_white '=' K_ECHO_REQUEST
@@ -1115,7 +1115,7 @@ udp_field
;
 
 udp_expr
-   : udp_field skip_white '=' skip_white field_expr
+   : udp_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
;
 
@@ -1145,7 +1145,7 @@ tcp_field
;
 
 tcp_expr
-   : tcp_field skip_white '=' skip_white field_expr
+   : tcp_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
| K_CWR { proto_field_set_be16(hdr, TCP_CWR, 1); }
| K_ECE { proto_field_set_be16(hdr, TCP_ECE, 1); }
-- 
2.10.2

-- 
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.


[netsniff-ng] [PATCH 5/7] trafgen: parser: Parse IPv6 address by strict match pattern

2016-12-17 Thread Vadim Kochan
Used IPv6 pattern from nftables project to match valid only IPv6
address to do not mess with MAC or other syntax patterns with ':' symbol.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen_lexer.l  | 51 +++
 trafgen_parser.y |  2 +-
 2 files changed, 48 insertions(+), 5 deletions(-)

diff --git a/trafgen_lexer.l b/trafgen_lexer.l
index 025fbfe..ad9dfe7 100644
--- a/trafgen_lexer.l
+++ b/trafgen_lexer.l
@@ -77,13 +77,56 @@ number_bin  ([0]?[b][0-1]+)
 number_dec (([0])|([1-9][0-9]*))
 number_ascii   ([a-zA-Z])
 
+hex4   ([[:xdigit:]]{1,4})
+v680   (({hex4}:){7}{hex4})
+v670   ((:)((:{hex4}){7}))
+v671   ((({hex4}:){1})((:{hex4}){6}))
+v672   ((({hex4}:){2})((:{hex4}){5}))
+v673   ((({hex4}:){3})((:{hex4}){4}))
+v674   ((({hex4}:){4})((:{hex4}){3}))
+v675   ((({hex4}:){5})((:{hex4}){2}))
+v676   ((({hex4}:){6})(:{hex4}{1}))
+v677   ((({hex4}:){7})(:))
+v67({v670}|{v671}|{v672}|{v673}|{v674}|{v675}|{v676}|{v677})
+v660   ((:)((:{hex4}){6}))
+v661   ((({hex4}:){1})((:{hex4}){5}))
+v662   ((({hex4}:){2})((:{hex4}){4}))
+v663   ((({hex4}:){3})((:{hex4}){3}))
+v664   ((({hex4}:){4})((:{hex4}){2}))
+v665   ((({hex4}:){5})((:{hex4}){1}))
+v666   ((({hex4}:){6})(:))
+v66({v660}|{v661}|{v662}|{v663}|{v664}|{v665}|{v666})
+v650   ((:)((:{hex4}){5}))
+v651   ((({hex4}:){1})((:{hex4}){4}))
+v652   ((({hex4}:){2})((:{hex4}){3}))
+v653   ((({hex4}:){3})((:{hex4}){2}))
+v654   ((({hex4}:){4})(:{hex4}{1}))
+v655   ((({hex4}:){5})(:))
+v65({v650}|{v651}|{v652}|{v653}|{v654}|{v655})
+v640   ((:)((:{hex4}){4}))
+v641   ((({hex4}:){1})((:{hex4}){3}))
+v642   ((({hex4}:){2})((:{hex4}){2}))
+v643   ((({hex4}:){3})((:{hex4}){1}))
+v644   ((({hex4}:){4})(:))
+v64({v640}|{v641}|{v642}|{v643}|{v644})
+v630   ((:)((:{hex4}){3}))
+v631   ((({hex4}:){1})((:{hex4}){2}))
+v632   ((({hex4}:){2})((:{hex4}){1}))
+v633   ((({hex4}:){3})(:))
+v63({v630}|{v631}|{v632}|{v633})
+v620   ((:)((:{hex4}){2}))
+v621   ((({hex4}:){1})((:{hex4}){1}))
+v622   ((({hex4}:){2})(:))
+v62({v620}|{v621}|{v622})
+v610   ((:)(:{hex4}{1}))
+v611   ((({hex4}:){1})(:))
+v61({v610}|{v611})
+v60(::)
+
 a_hex  ([a-fA-F0-9]+)
 mac({a_hex}:{a_hex}:{a_hex}:{a_hex}:{a_hex}:{a_hex})
 ip4_addr   ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)
-   /* We're very permissive about IPv6 addresses the grammar accepts, as
-* they can come in various different formats. In any case,
-* inet_pton(AF_INET6, ...) will reject the invalid ones later on. */
-ip6_addr   
(({a_hex}?:)?({a_hex}?:)?({a_hex}?:)?({a_hex}?:)?({a_hex}?:)?({a_hex}?:)?({a_hex}?:)?({a_hex})?)
+ip6_addr   ({v680}|{v67}|{v66}|{v65}|{v64}|{v63}|{v62}|{v61}|{v60})
 
 %%
 
diff --git a/trafgen_parser.y b/trafgen_parser.y
index bfeed2e..a1b8b0c 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@@ -416,7 +416,7 @@ static void proto_field_expr_eval(void)
else if (field->len == 4)
proto_hdr_field_set_be32(hdr, field->id, 
field_expr.val.number);
else
-   bug();
+   proto_hdr_field_set_bytes(hdr, field->id, 
field_expr.val.bytes);
break;
 
case FIELD_EXPR_MAC:
-- 
2.10.2

-- 
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.


[netsniff-ng] [PATCH 7/7] man: trafgen: Add short description about field offset using

2016-12-17 Thread Vadim Kochan
Add short note about field offset syntax with an example.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen.8 | 25 +
 1 file changed, 25 insertions(+)

diff --git a/trafgen.8 b/trafgen.8
index 62716bb..c58d429 100644
--- a/trafgen.8
+++ b/trafgen.8
@@ -329,6 +329,31 @@ Example of using dynamic functions:
 .in -4
 
 .sp
+Field might be set with a value/function at a specific offset within a field:
+.sp
+.in +4
+[] | [:]
+.sp
+.in +4
+ - relative field's offset with range 0.. - 1
+.sp
+ - length/size of the value which will be set - 1,2 or 4 bytes 
(default: 1).
+.in -4
+.sp
+The  starts from the 1st field's byte in the network order.
+.sp
+Example of using field offset:
+.sp
+{
+.in +2
+eth(saddr=aa:bb:cc:dd:ee:ff, saddr[0]=dinc()),
+ipv4(saddr[0:2]=drnd()),
+udp(),
+.in -2
+}
+.in -4
+
+.sp
 All required lower layer headers will be filled automatically if they were not
 specified by the user. The headers will be filled in the order they were
 specified. Each header will be filled with some mimimum required set of fields.
-- 
2.10.2

-- 
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.


[netsniff-ng] [PATCH 6/7] trafgen: parser: Allow to set value/func at field offset

2016-12-17 Thread Vadim Kochan
Extend proto field expression to:

proto_field[{index}:{len}] = {func}

which allows to specify function/value on the part of the field via index
and value length (default is 1 - 1 byte). This rule is optional.

It was needed to keep of proto_field's copies in packet_dyn->fields
instead of original fields which allows to scpecify different functions
on the different parts of same field, also the copy of original
proto_field allows to set custom length/pkt_offset which makes such
field behave as virtual sub-field of the original one with different
length/pkt_offset but point to the same piece of header.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen_parser.y | 96 +++-
 trafgen_proto.c  | 27 +++-
 trafgen_proto.h  |  8 +++--
 3 files changed, 98 insertions(+), 33 deletions(-)

diff --git a/trafgen_parser.y b/trafgen_parser.y
index a1b8b0c..4d570e0 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@@ -387,20 +387,30 @@ static void proto_add(enum proto_id pid)
 
 static void proto_field_set(uint32_t fid)
 {
+   memset(_expr, 0, sizeof(field_expr));
field_expr.field = proto_hdr_field_by_id(hdr, fid);
 }
 
 static void proto_field_func_setup(struct proto_field *field, struct 
proto_field_func *func)
 {
+   struct proto_field *field_copy;
struct packet_dyn *pkt_dyn;
 
-   proto_hdr_field_func_add(field->hdr, field->id, func);
+   field_copy = xmalloc(sizeof(*field));
+   memcpy(field_copy, field, sizeof(*field));
+
+   field_copy->pkt_offset += func->offset;
+   if (func->len)
+   field_copy->len = func->len;
+
+   proto_field_func_add(field_copy, func);
 
pkt_dyn = _dyn[packetd_last];
pkt_dyn->flen++;
pkt_dyn->fields = xrealloc(pkt_dyn->fields, pkt_dyn->flen *
   sizeof(struct proto_field *));
-   pkt_dyn->fields[pkt_dyn->flen - 1] = field;
+
+   pkt_dyn->fields[pkt_dyn->flen - 1] = field_copy;
 }
 
 static void proto_field_expr_eval(void)
@@ -450,6 +460,19 @@ static void proto_field_expr_eval(void)
memset(_expr, 0, sizeof(field_expr));
 }
 
+static void field_index_validate(struct proto_field *field, uint16_t index, 
size_t len)
+{
+   if (field_expr.field->len <= index) {
+   yyerror("Invalid [index] parameter");
+   panic("Index (%u) is bigger than field's length (%zu)\n",
+  index, field->len);
+   }
+   if (len != 1 && len != 2 && len != 4) {
+   yyerror("Invalid [index:len] parameter");
+   panic("Invalid index length - 1,2 or 4 is only allowed\n");
+   }
+}
+
 %}
 
 %union {
@@ -718,6 +741,17 @@ proto
| tcp_proto { }
;
 
+field_expr
+   : '[' skip_white number skip_white ']'
+   { field_index_validate(field_expr.field, $3, 1);
+ field_expr.val.func.offset = $3;
+ field_expr.val.func.len = 1; }
+   | '[' skip_white number skip_white ':' skip_white number skip_white ']'
+   { field_index_validate(field_expr.field, $3, $7);
+ field_expr.val.func.offset = $3;
+ field_expr.val.func.len = $7; }
+   ;
+
 field_value_expr
: number { field_expr.type = FIELD_EXPR_NUMB;
   field_expr.val.number = $1; }
@@ -783,7 +817,9 @@ eth_field
| eth_type { proto_field_set(ETH_TYPE); }
 
 eth_expr
-   : eth_field skip_white '=' skip_white field_value_expr
+   : eth_field field_expr skip_white '=' skip_white field_value_expr
+   { proto_field_expr_eval(); }
+   | eth_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
;
 
@@ -807,7 +843,9 @@ pause_field
;
 
 pause_expr
-   : pause_field skip_white '=' skip_white field_value_expr
+   : pause_field field_expr skip_white '=' skip_white field_value_expr
+   { proto_field_expr_eval(); }
+   | pause_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
;
 
@@ -843,7 +881,9 @@ pfc_field
;
 
 pfc_expr
-   : pfc_field skip_white '=' skip_white field_value_expr
+   : pfc_field field_expr skip_white '=' skip_white field_value_expr
+   { proto_field_expr_eval(); }
+   | pfc_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
;
 
@@ -875,7 +915,9 @@ vlan_field
;
 
 vlan_expr
-   : vlan_field skip_white '=' skip_white field_value_expr
+   : vlan_field field_expr skip_white '=' skip_white field_value_expr
+   { proto_field_expr_eval(); }
+   | vlan_field skip_white '=' skip_white field_value_expr
{ proto_field_expr_eval(); }
| K_1Q
 

[netsniff-ng] [PATCH 3/7] trafgen: proto: Rename proto_field_xxx -> proto_hdr_field_xxx

2016-12-17 Thread Vadim Kochan
Rename all proto_field_xxx(...) functions to proto_hdr_field(...).

It is good for 2 reasons:
1) proto_hdr_field_xxx naming is more consistent as
   it is related to proto_hdr API.

2) It makes possible to introduce proto_field_xxx API
   which will operate only with struct proto_field.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen_l2.c |  44 -
 trafgen_l3.c |  24 +-
 trafgen_l4.c |  28 +--
 trafgen_parser.y |  64 -
 trafgen_proto.c  | 144 ---
 trafgen_proto.h  |  52 ++--
 6 files changed, 179 insertions(+), 177 deletions(-)

diff --git a/trafgen_l2.c b/trafgen_l2.c
index b27c9dd..5fc0a0d 100644
--- a/trafgen_l2.c
+++ b/trafgen_l2.c
@@ -40,14 +40,14 @@ static uint16_t pid_to_eth(enum proto_id pid)
 
 static void eth_set_next_proto(struct proto_hdr *hdr, enum proto_id pid)
 {
-   proto_field_set_default_be16(hdr, ETH_TYPE, pid_to_eth(pid));
+   proto_hdr_field_set_default_be16(hdr, ETH_TYPE, pid_to_eth(pid));
 }
 
 static void eth_header_init(struct proto_hdr *hdr)
 {
proto_header_fields_add(hdr, eth_fields, array_size(eth_fields));
 
-   proto_field_set_default_dev_mac(hdr, ETH_SRC_ADDR);
+   proto_hdr_field_set_default_dev_mac(hdr, ETH_SRC_ADDR);
 }
 
 static const struct proto_ops eth_proto_ops = {
@@ -69,10 +69,10 @@ static void pause_header_init(struct proto_hdr *hdr)
struct proto_hdr *lower;
 
lower = proto_lower_default_add(hdr, PROTO_ETH);
-   proto_field_set_default_bytes(lower, ETH_DST_ADDR, eth_dst);
+   proto_hdr_field_set_default_bytes(lower, ETH_DST_ADDR, eth_dst);
 
proto_header_fields_add(hdr, pause_fields, array_size(pause_fields));
-   proto_field_set_default_be16(hdr, PAUSE_OPCODE, 0x1);
+   proto_hdr_field_set_default_be16(hdr, PAUSE_OPCODE, 0x1);
 }
 
 static struct proto_ops pause_proto_ops = {
@@ -109,10 +109,10 @@ static void pfc_header_init(struct proto_hdr *hdr)
struct proto_hdr *lower;
 
lower = proto_lower_default_add(hdr, PROTO_ETH);
-   proto_field_set_default_bytes(lower, ETH_DST_ADDR, eth_dst);
+   proto_hdr_field_set_default_bytes(lower, ETH_DST_ADDR, eth_dst);
 
proto_header_fields_add(hdr, pfc_fields, array_size(pfc_fields));
-   proto_field_set_default_be16(hdr, PFC_OPCODE, 0x0101);
+   proto_hdr_field_set_default_be16(hdr, PFC_OPCODE, 0x0101);
 }
 
 static struct proto_ops pfc_proto_ops = {
@@ -140,18 +140,18 @@ static void vlan_header_init(struct proto_hdr *hdr)
proto_header_fields_add(hdr, vlan_fields, array_size(vlan_fields));
 
if (lower->ops->id == PROTO_ETH)
-   lower_etype = proto_field_get_u16(lower, ETH_TYPE);
+   lower_etype = proto_hdr_field_get_u16(lower, ETH_TYPE);
else if (lower->ops->id == PROTO_VLAN)
-   lower_etype = proto_field_get_u16(lower, VLAN_ETYPE);
+   lower_etype = proto_hdr_field_get_u16(lower, VLAN_ETYPE);
 
-   proto_field_set_be16(hdr, VLAN_ETYPE, lower_etype);
-   proto_field_set_default_be16(hdr, VLAN_TPID, pid_to_eth(hdr->ops->id));
+   proto_hdr_field_set_be16(hdr, VLAN_ETYPE, lower_etype);
+   proto_hdr_field_set_default_be16(hdr, VLAN_TPID, 
pid_to_eth(hdr->ops->id));
 }
 
 static void vlan_set_next_proto(struct proto_hdr *hdr, enum proto_id pid)
 {
if (pid != PROTO_VLAN)
-   proto_field_set_be16(hdr, VLAN_ETYPE, pid_to_eth(pid));
+   proto_hdr_field_set_be16(hdr, VLAN_ETYPE, pid_to_eth(pid));
 }
 
 static const struct proto_ops vlan_proto_ops = {
@@ -180,20 +180,20 @@ static void arp_header_init(struct proto_hdr *hdr)
if (lower->ops->id == PROTO_ETH) {
const uint8_t bcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 
-   proto_field_set_default_bytes(lower, ETH_DST_ADDR, bcast);
+   proto_hdr_field_set_default_bytes(lower, ETH_DST_ADDR, bcast);
}
 
proto_header_fields_add(hdr, arp_fields, array_size(arp_fields));
 
/* Generate Announce request by default */
-   proto_field_set_default_be16(hdr, ARP_HTYPE, ARPHRD_ETHER);
-   proto_field_set_default_be16(hdr, ARP_PTYPE, ETH_P_IP);
-   proto_field_set_default_u8(hdr, ARP_HLEN, 6);
-   proto_field_set_default_u8(hdr, ARP_PLEN, 4);
-   proto_field_set_default_be16(hdr, ARP_OPER, ARPOP_REQUEST);
-   proto_field_set_default_dev_mac(hdr, ARP_SHA);
-   proto_field_set_default_dev_ipv4(hdr, ARP_SPA);
-   proto_field_set_default_dev_ipv4(hdr, ARP_TPA);
+   proto_hdr_field_set_default_be16(hdr, ARP_HTYPE, ARPHRD_ETHER);
+   proto_hdr_field_set_default_be16(hdr, ARP_PTYPE, ETH_P_IP);
+   proto_hdr_field_set_default_u8(hdr, ARP_HLEN, 6);
+   proto_hdr_field_set_default_u8(hdr, ARP_PLEN, 4);
+   proto_hdr_field_set_defau

[netsniff-ng] Re: [PATCH v2] flowtop: Move & refactor walk_processes(...) to proc.c

2016-12-14 Thread Vadim Kochan
On Wed, Dec 14, 2016 at 11:44 PM, Vadim Kochan <vadi...@gmail.com> wrote:
> Add proc_find_by_inode(...) which finds pid by inode & gets processe's
> command line.
>
> Actually this function was taken from flowtop.c walk_process(...)
> and refactored to look more generic.
>
> Signed-off-by: Vadim Kochan <vadi...@gmail.com>
>
> flowtop: Replace walk_processes(...) by proc_find_by_inode(...)
>
> Use proc_find_by_inode(...) from proc.c to find pid by inode
> and it's command line instead of having own specific process walker.
>
> Signed-off-by: Vadim Kochan <vadi...@gmail.com>
> ---
> v2:
>1) Add static to __match_pid_by_inode(...)
>2) Remove sys/stat.h & dirent.h includes from flowtop.c
>3) Squash changes into one patch
>
>  flowtop.c | 78 
> ---
>  proc.c| 74 +++
>  proc.h|  1 +

Ahhh, I did not correct squash .. will fix it ...

-- 
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.


[netsniff-ng] [PATCH v2] flowtop: Move & refactor walk_processes(...) to proc.c

2016-12-14 Thread Vadim Kochan
Add proc_find_by_inode(...) which finds pid by inode & gets processe's
command line.

Actually this function was taken from flowtop.c walk_process(...)
and refactored to look more generic.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>

flowtop: Replace walk_processes(...) by proc_find_by_inode(...)

Use proc_find_by_inode(...) from proc.c to find pid by inode
and it's command line instead of having own specific process walker.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
v2:
   1) Add static to __match_pid_by_inode(...)
   2) Remove sys/stat.h & dirent.h includes from flowtop.c
   3) Squash changes into one patch

 flowtop.c | 78 ---
 proc.c| 74 +++
 proc.h|  1 +
 3 files changed, 84 insertions(+), 69 deletions(-)

diff --git a/flowtop.c b/flowtop.c
index 4f8cbcf..f382d6c 100644
--- a/flowtop.c
+++ b/flowtop.c
@@ -17,8 +17,6 @@
 #include 
 #include 
 #include 
-#include 
-#include 
 #include 
 #include 
 #include 
@@ -474,80 +472,22 @@ static void flow_list_destroy(struct flow_list *fl)
spinlock_unlock(_list.lock);
 }
 
-static int walk_process(unsigned int pid, struct flow_entry *n)
+static void flow_entry_find_process(struct flow_entry *n)
 {
+   char cmdline[512];
+   pid_t pid;
int ret;
-   DIR *dir;
-   struct dirent *ent;
-   char path[1024];
 
-   if (snprintf(path, sizeof(path), "/proc/%u/fd", pid) == -1)
-   panic("giant process name! %u\n", pid);
-
-   dir = opendir(path);
-   if (!dir)
-   return 0;
-
-   while ((ent = readdir(dir))) {
-   struct stat statbuf;
-
-   if (snprintf(path, sizeof(path), "/proc/%u/fd/%s",
-pid, ent->d_name) < 0)
-   continue;
-
-   if (stat(path, ) < 0)
-   continue;
-
-   if (S_ISSOCK(statbuf.st_mode) && (ino_t) n->inode == 
statbuf.st_ino) {
-   char cmdline[256];
-
-   ret = proc_get_cmdline(pid, cmdline, sizeof(cmdline));
-   if (ret < 0)
-   panic("Failed to get process cmdline: %s\n", 
strerror(errno));
-
-   if (snprintf(n->procname, sizeof(n->procname), "%s", 
basename(cmdline)) < 0)
-   n->procname[0] = '\0';
-   n->procnum = pid;
-   closedir(dir);
-   return 1;
-   }
-   }
-
-   closedir(dir);
-   return 0;
-}
-
-static void walk_processes(struct flow_entry *n)
-{
-   int ret;
-   DIR *dir;
-   struct dirent *ent;
-
-   /* n->inode must be set */
-   if (n->inode <= 0) {
+   ret = proc_find_by_inode(n->inode, cmdline, sizeof(cmdline), );
+   if (ret <= 0) {
n->procname[0] = '\0';
return;
}
 
-   dir = opendir("/proc");
-   if (!dir)
-   panic("Cannot open /proc: %s\n", strerror(errno));
-
-   while ((ent = readdir(dir))) {
-   const char *name = ent->d_name;
-   char *end;
-   unsigned int pid = strtoul(name, , 10);
-
-   /* not a PID */
-   if (pid == 0 && end == name)
-   continue;
-
-   ret = walk_process(pid, n);
-   if (ret > 0)
-   break;
-   }
+   if (snprintf(n->procname, sizeof(n->procname), "%s", basename(cmdline)) 
< 0)
+   n->procname[0] = '\0';
 
-   closedir(dir);
+   n->procnum = pid;
 }
 
 static int get_port_inode(uint16_t port, int proto, bool is_ip6)
@@ -810,7 +750,7 @@ static void flow_entry_get_extended(struct flow_entry *n)
n->inode = get_port_inode(n->port_src, n->l4_proto,
  n->l3_proto == AF_INET6);
if (n->inode > 0)
-   walk_processes(n);
+   flow_entry_find_process(n);
 }
 
 static char *bandw2str(double bytes, char *buf, size_t len)
diff --git a/proc.c b/proc.c
index 76e3c93..f3fcd4b 100644
--- a/proc.c
+++ b/proc.c
@@ -3,11 +3,13 @@
 #endif
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 
 #include "proc.h"
 #include "die.h"
@@ -83,6 +85,78 @@ ssize_t proc_get_cmdline(unsigned int pid, char *cmdline, 
size_t len)
return ret;
 }
 
+static int __match_pid_by_inode(pid_t pid, ino_t ino)
+{
+   struct dirent *ent;
+   char path[1024];
+   DIR *dir;
+
+   if (snprintf(path, sizeof(path), "/proc/%u/fd", pid) == -1)
+   panic("giant process n

[netsniff-ng] Re: [PATCH 0/4] Introduce new pcap io API for pcap r/w accesses

2016-12-14 Thread Vadim Kochan
On Wed, Dec 14, 2016 at 11:26 PM, Tobias Klauser <tklau...@distanz.ch> wrote:
> On 2016-12-12 at 22:09:52 +0100, Vadim Kochan <vadi...@gmail.com> wrote:
>> Add new pcap io API to make pcap read/write accesses more
>> simpler and generic. Added pcap_io & pcap_packet struct's to
>> keep some internal pcap state like magic, link type & packet header
>> instead of to pass them like parameters and keep it all within netsniff-ng.c.
>>
>> Also such approach might be used to unify sniffing from ring buffer via
>> pcap io API similary as it is done with regular files.
>>
>> Some fast-path sensitive or setter/getter functions were inlined in 
>> pcap_io.h.
>
> This series touches very sensitive fast-path code. Before even reviewing
> it, I'd like to see performance measurments proofing that the your
> patches don't introduce any performance regressions and that inlining of
> these functions indeed does the job.
>
> Thanks!

Hm, yeah, I need to think how to perform this on my laptop ...

-- 
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.


[netsniff-ng] Re: [PATCH 0/2] flowtop: Move & refactor walk_processes(...) to proc.c

2016-12-14 Thread Vadim Kochan
Hi Tobias,

On Wed, Dec 14, 2016 at 11:16 PM, Tobias Klauser <tklau...@distanz.ch> wrote:
> On 2016-12-13 at 02:36:00 +0100, Vadim Kochan <vadi...@gmail.com> wrote:
>> Add proc_find_by_inode(...) to find pid & it's command line by inode.
>> The main motivation for this is to have process specific function located
>> in proc.c and only call it from flowtop.c.
>>
>> proc_find_by_inode(...) its just a refactored version of walk_processes(...)
>> from the flowtop.c.
>>
>> Vadim Kochan (2):
>>   proc: Add function for find process by inode
>>   flowtop: Replace walk_processes(...) by proc_find_by_inode(...)
>
> IMO, these could be combined into one patch as this makes it easier to
> immediately verify that the logic of the function wasn't changed.
> Splitting it up into two patches makes this verification unnecessarily
> cumbersome.
>
> Further comments will follows as replies to the individual patches.

Thanks for the review, I will fix comments and squash patches into one.
It is still not easy to learn zen of patch splitting:)

-- 
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.


[netsniff-ng] [PATCH 0/2] flowtop: Move & refactor walk_processes(...) to proc.c

2016-12-12 Thread Vadim Kochan
Add proc_find_by_inode(...) to find pid & it's command line by inode.
The main motivation for this is to have process specific function located
in proc.c and only call it from flowtop.c.

proc_find_by_inode(...) its just a refactored version of walk_processes(...)
from the flowtop.c.

Vadim Kochan (2):
  proc: Add function for find process by inode
  flowtop: Replace walk_processes(...) by proc_find_by_inode(...)

 flowtop.c | 76 ---
 proc.c| 74 +
 proc.h|  1 +
 3 files changed, 84 insertions(+), 67 deletions(-)

-- 
2.10.2

-- 
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.


[netsniff-ng] [PATCH 1/2] proc: Add function for find process by inode

2016-12-12 Thread Vadim Kochan
Add proc_find_by_inode(...) which finds pid by inode & gets processe's
command line.

Actually this function was taken from flowtop.c walk_process(...)
and refactored to look more generic.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 proc.c | 74 ++
 proc.h |  1 +
 2 files changed, 75 insertions(+)

diff --git a/proc.c b/proc.c
index 76e3c93..8119226 100644
--- a/proc.c
+++ b/proc.c
@@ -3,11 +3,13 @@
 #endif
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 
 #include "proc.h"
 #include "die.h"
@@ -83,6 +85,78 @@ ssize_t proc_get_cmdline(unsigned int pid, char *cmdline, 
size_t len)
return ret;
 }
 
+int __match_pid_by_inode(pid_t pid, ino_t ino)
+{
+   struct dirent *ent;
+   char path[1024];
+   DIR *dir;
+
+   if (snprintf(path, sizeof(path), "/proc/%u/fd", pid) == -1)
+   panic("giant process name! %u\n", pid);
+
+   dir = opendir(path);
+   if (!dir)
+   return -1;
+
+   while ((ent = readdir(dir))) {
+   struct stat statbuf;
+
+   if (snprintf(path, sizeof(path), "/proc/%u/fd/%s",
+pid, ent->d_name) < 0)
+   continue;
+
+   if (stat(path, ) < 0)
+   continue;
+
+   if (S_ISSOCK(statbuf.st_mode) && ino == statbuf.st_ino) {
+   closedir(dir);
+   return 0;
+   }
+   }
+
+   closedir(dir);
+   return -1;
+}
+
+int proc_find_by_inode(ino_t ino, char *cmdline, size_t len, pid_t *pid)
+{
+   struct dirent *ent;
+   DIR *dir;
+
+   if (ino <= 0) {
+   cmdline[0] = '\0';
+   return 0;
+   }
+
+   dir = opendir("/proc");
+   if (!dir)
+   panic("Cannot open /proc: %s\n", strerror(errno));
+
+   while ((ent = readdir(dir))) {
+   int ret;
+   char *end;
+   const char *name = ent->d_name;
+   pid_t _pid = strtoul(name, , 10);
+
+   /* not a PID */
+   if (_pid == 0 && end == name)
+   continue;
+
+   ret = __match_pid_by_inode(_pid, ino);
+   if (!ret) {
+   ret = proc_get_cmdline(_pid, cmdline, len);
+   if (ret < 0)
+   panic("Failed to get process cmdline: %s\n", 
strerror(errno));
+
+   *pid = _pid;
+   return ret;
+   }
+   }
+
+   closedir(dir);
+   return -1;
+}
+
 int proc_exec(const char *proc, char *const argv[])
 {
int status;
diff --git a/proc.h b/proc.h
index 9220b2a..6e5f3ac 100644
--- a/proc.h
+++ b/proc.h
@@ -8,5 +8,6 @@ extern int set_proc_prio(int prio);
 extern int set_sched_status(int policy, int priority);
 extern ssize_t proc_get_cmdline(unsigned int pid, char *cmdline, size_t len);
 extern int proc_exec(const char *proc, char *const argv[]);
+extern int proc_find_by_inode(ino_t ino, char *cmdline, size_t len, pid_t 
*pid);
 
 #endif /* PROC_H */
-- 
2.10.2

-- 
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.


[netsniff-ng] [PATCH 1/4] pcap io: Introduce new pcap io API to simplify pcap access

2016-12-12 Thread Vadim Kochan
Add pcap_io object which represent pcap io API to simplify and make
more transparent pcap access.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 pcap_io.c | 190 ++
 pcap_io.h | 143 ++
 2 files changed, 333 insertions(+)
 create mode 100644 pcap_io.c

diff --git a/pcap_io.c b/pcap_io.c
new file mode 100644
index 000..b82792a
--- /dev/null
+++ b/pcap_io.c
@@ -0,0 +1,190 @@
+/*
+ * netsniff-ng - the packet sniffing beast
+ * Subject to the GPL, version 2.
+ */
+
+#define _GNU_SOURCE
+
+#include 
+#include 
+
+#include "bpf.h"
+#include "pcap_io.h"
+#include "xmalloc.h"
+
+void pcap_io_init(struct pcap_io *io, enum pcap_ops_groups ops_type)
+{
+   io->ops = pcap_ops[ops_type];
+   io->ops_type = ops_type;
+   io->bpf_ops = NULL;
+   io->jumbo = false;
+   io->truncated = 0;
+   io->path = NULL;
+   io->fd = -1;
+   
+   bug_on(!io->ops);
+}
+
+void pcap_io_open(struct pcap_io *io, const char *path, enum pcap_mode mode)
+{
+   if (mode == PCAP_MODE_RD) {
+   if (!strncmp("-", path, strlen("-"))) {
+   io->fd = dup_or_die(fileno(stdin));
+   close(fileno(stdin));
+
+   if (io->ops_type == PCAP_OPS_MM)
+   pcap_io_init(io, PCAP_OPS_SG);
+   } else {
+   io->fd = open(path, O_RDONLY | O_LARGEFILE | O_NOATIME);
+   if (io->fd < 0 && errno == EPERM)
+   io->fd = open_or_die(path, O_RDONLY | 
O_LARGEFILE);
+   }
+   } else if (mode == PCAP_MODE_WR) {
+   if (!strncmp("-", path, strlen("-"))) {
+   io->fd = dup_or_die(fileno(stdout));
+   close(fileno(stdout));
+
+   if (io->ops_type == PCAP_OPS_MM)
+   pcap_io_init(io, PCAP_OPS_SG);
+   } else {
+   io->fd = open_or_die_m(path, O_RDWR | O_CREAT | O_TRUNC 
|
+  O_LARGEFILE, DEFFILEMODE);
+   }
+   } else {
+   bug();
+   }
+
+   if (io->fd < 0)
+   panic("pcap_io: Cannot open file %s! %s.\n", path, 
strerror(errno));
+
+   if (io->ops->init_once_pcap)
+   io->ops->init_once_pcap(io->enforce_prio);
+
+   io->path = path;
+   io->mode = mode;
+}
+
+static int pcap_io_prepare_access(struct pcap_io *io)
+{
+   int ret;
+
+   if (io->ops->prepare_access_pcap) {
+   ret = io->ops->prepare_access_pcap(io->fd, io->mode, io->jumbo);
+   if (ret) {
+   fprintf(stderr, "pcap_io: Error prepare %s pcap!\n",
+   io->mode == PCAP_MODE_RD ? "reading" : 
"writing");
+
+   return ret;
+   }
+   }
+
+   return 0;
+}
+
+void pcap_io_header_copy(struct pcap_io *to, struct pcap_io *from)
+{
+   to->link_type = from->link_type;
+   to->magic = from->magic;
+}
+
+int pcap_io_header_read(struct pcap_io *io)
+{
+   int ret;
+
+   ret = io->ops->pull_fhdr_pcap(io->fd, >magic, >link_type);
+   if (ret) {
+   fprintf(stderr, "pcap_io: Error reading pcap header!\n");
+   return ret;
+   }
+
+   return pcap_io_prepare_access(io);
+}
+
+int pcap_io_header_write(struct pcap_io *io)
+{
+   int ret;
+
+   ret = io->ops->push_fhdr_pcap(io->fd, io->magic, io->link_type);
+   if (ret) {
+   fprintf(stderr, "pcap_io: Error writing pcap header!\n");
+   return ret;
+   }
+
+   return pcap_io_prepare_access(io);
+}
+
+int pcap_io_packet_read(struct pcap_io *io, struct pcap_packet *pkt)
+{
+   int ret;
+
+   do {
+   ret = io->ops->read_pcap(io->fd, >phdr, io->magic,
+pkt->buf, pkt->buf_len);
+   if (unlikely(ret < 0)) {
+   return 0;
+   }
+   if (unlikely(pcap_packet_len_get(pkt) == 0)) {
+   pkt->io->truncated++;
+   continue;
+   }
+   if (unlikely(pcap_packet_len_get(pkt) > pkt->buf_len)) {
+   pcap_packet_len_set(pkt, pkt->buf_len);
+   pkt->io->truncated++;
+   }
+   } while (io->bpf_ops &&
+   !bpf_run_filter(io->bpf_ops, pkt->buf,
+pcap_packet_len_get(pkt)));
+

  1   2   3   4   5   6   >