Re: [B.A.T.M.A.N.] general theory question RE: dhcp on a peer only mesh

2009-12-31 Thread Juliusz Chroboczek
 Who provides IP addresses in a truly ad-hoc, truly peer only mesh
 network ?

Nobody, as far as I know.

You may want to have a look at AHCP[1], however.  When configured for
IPv6 only, it gets configuration information (such as the IPv6 prefix
and the name server address) from central servers, but behaves in
a completely stateless manner -- there is no information stored in the
servers.

In IPv4, however, it uses leases, just like DHCP, so it needs to store
state in the servers.

 Please do point me to any writings or information related to this.

Search for draft-bernardos-manet-autoconf-survey.

Juliusz

[1] http://www.pps.jussieu.fr/~jch/software/ahcp/



[B.A.T.M.A.N.] batmand advanced recipe for bitbake

2009-12-31 Thread Conner, Eric
Has anyone created a BATMAN Advanced recipe for bitbake
openembedded.dev?

 

thanks



[B.A.T.M.A.N.] [PATCH 1/3] batman-adv: atomic variable for vis-srv activation

2009-12-31 Thread =?UTF-8?q?Linus=20L=C3=BCssing?=
This fixes the bug discovered by Marek which did not allow turning on
the vis-server before an interface has been added. This is now being
done in a similar way as for (de)activating the aggregation mode with an
atomic variable.

Signed-off-by: Linus Lüssing linus.luess...@web.de
---
 main.c |2 ++
 main.h |1 +
 proc.c |   43 ---
 send.c |2 +-
 vis.c  |   41 +++--
 vis.h  |2 --
 6 files changed, 31 insertions(+), 60 deletions(-)

diff --git a/main.c b/main.c
index c733504..843d552 100644
--- a/main.c
+++ b/main.c
@@ -44,6 +44,7 @@ DEFINE_SPINLOCK(forw_bcast_list_lock);
 
 atomic_t originator_interval;
 atomic_t vis_interval;
+atomic_t vis_srv_enabled;
 atomic_t aggregation_enabled;
 int16_t num_hna;
 int16_t num_ifs;
@@ -84,6 +85,7 @@ int init_module(void)
atomic_set(originator_interval, 1000);
atomic_set(vis_interval, 1000);/* TODO: raise this later, this is only
 * for debugging now. */
+   atomic_set(vis_srv_enabled, 0);
atomic_set(aggregation_enabled, 1);
 
/* the name should not be longer than 10 chars - see
diff --git a/main.h b/main.h
index 3dfe5fe..385818f 100644
--- a/main.h
+++ b/main.h
@@ -130,6 +130,7 @@ extern spinlock_t forw_bcast_list_lock;
 
 extern atomic_t originator_interval;
 extern atomic_t vis_interval;
+extern atomic_t vis_srv_enabled;
 extern atomic_t aggregation_enabled;
 extern int16_t num_hna;
 extern int16_t num_ifs;
diff --git a/proc.c b/proc.c
index 61e1d0d..e7b7bf3 100644
--- a/proc.c
+++ b/proc.c
@@ -325,36 +325,41 @@ static int proc_transt_global_open(struct inode *inode, 
struct file *file)
 static ssize_t proc_vis_srv_write(struct file *file, const char __user * 
buffer,
  size_t count, loff_t *ppos)
 {
-   char *vis_mode_string;
+   char *vis_srv_string;
int not_copied = 0;
+   unsigned long vis_srv_enabled_tmp;
+   int retval;
 
-   vis_mode_string = kmalloc(count, GFP_KERNEL);
+   vis_srv_string = kmalloc(count, GFP_KERNEL);
 
-   if (!vis_mode_string)
+   if (!vis_srv_string)
return -ENOMEM;
 
-   not_copied = copy_from_user(vis_mode_string, buffer, count);
-   vis_mode_string[count - not_copied - 1] = 0;
-
-   if ((strcmp(vis_mode_string, client) == 0) ||
-   (strcmp(vis_mode_string, disabled) == 0)) {
-   printk(KERN_INFO batman-adv:Setting VIS mode to client 
(disabling vis server)\n);
-   vis_set_mode(VIS_TYPE_CLIENT_UPDATE);
-   } else if ((strcmp(vis_mode_string, server) == 0) ||
-   (strcmp(vis_mode_string, enabled) == 0)) {
-   printk(KERN_INFO batman-adv:Setting VIS mode to server 
(enabling vis server)\n);
-   vis_set_mode(VIS_TYPE_SERVER_SYNC);
-   } else
+   not_copied = copy_from_user(vis_srv_string, buffer, count);
+   vis_srv_string[count - not_copied - 1] = 0;
+
+   retval = strict_strtoul(vis_srv_string, 10, vis_srv_enabled_tmp);
+
+   /* Unknown vis mode input? */
+   if (retval == -EINVAL || vis_srv_enabled_tmp  1) {
printk(KERN_ERR batman-adv:Unknown VIS mode: %s\n,
-  vis_mode_string);
+  vis_srv_string);
+   }
+   else {
+   if (vis_srv_enabled_tmp == 0)
+   printk(KERN_INFO batman-adv:Setting VIS mode to client 
(disabling vis server)\n);
+   else
+   printk(KERN_INFO batman-adv:Setting VIS mode to server 
(enabling vis server)\n);
+   atomic_set(vis_srv_enabled, vis_srv_enabled_tmp);
+   }
 
-   kfree(vis_mode_string);
+   kfree(vis_srv_string);
return count;
 }
 
 static int proc_vis_srv_read(struct seq_file *seq, void *offset)
 {
-   int vis_server = is_vis_server();
+   int vis_server = atomic_read(vis_srv_enabled);
 
seq_printf(seq, [%c] client mode (server disabled) \n,
(!vis_server) ? 'x' : ' ');
@@ -380,7 +385,7 @@ static int proc_vis_data_read(struct seq_file *seq, void 
*offset)
unsigned long flags;
 
rcu_read_lock();
-   if (list_empty(if_list) || (!is_vis_server())) {
+   if (list_empty(if_list) || (!atomic_read(vis_srv_enabled))) {
rcu_read_unlock();
goto end;
}
diff --git a/send.c b/send.c
index fd48f3f..92d14a6 100644
--- a/send.c
+++ b/send.c
@@ -279,7 +279,7 @@ void schedule_own_packet(struct batman_if *batman_if)
/* change sequence number to network order */
batman_packet-seqno = htons((uint16_t)atomic_read(batman_if-seqno));
 
-   if (is_vis_server())
+   if (atomic_read(vis_srv_enabled))
batman_packet-flags = VIS_SERVER;
else
batman_packet-flags = 0;
diff --git a/vis.c b/vis.c
index fa8afdb..e7c14b5 100644
--- a/vis.c
+++ b/vis.c

[B.A.T.M.A.N.] [PATCH 2/3] batman-adv: No deact of aggregation on wrong input

2009-12-31 Thread =?UTF-8?q?Linus=20L=C3=BCssing?=
A non-integer changes the aggregation mode. Therefore this patch changes
the behaviour to explicitly check strict_strtoul()'s return code.

Signed-off-by: Linus Lüssing linus.luess...@web.de
---
 proc.c |   24 
 1 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/proc.c b/proc.c
index e7b7bf3..232efe3 100644
--- a/proc.c
+++ b/proc.c
@@ -433,6 +433,7 @@ static ssize_t proc_aggr_write(struct file *file, const 
char __user *buffer,
char *aggr_string;
int not_copied = 0;
unsigned long aggregation_enabled_tmp;
+   int retval;
 
aggr_string = kmalloc(count, GFP_KERNEL);
 
@@ -442,22 +443,21 @@ static ssize_t proc_aggr_write(struct file *file, const 
char __user *buffer,
not_copied = copy_from_user(aggr_string, buffer, count);
aggr_string[count - not_copied - 1] = 0;
 
-   strict_strtoul(aggr_string, 10, aggregation_enabled_tmp);
+   retval = strict_strtoul(aggr_string, 10, aggregation_enabled_tmp);
 
-   if ((aggregation_enabled_tmp != 0)  (aggregation_enabled_tmp != 1)) {
+   if (retval == -EINVAL || aggregation_enabled_tmp  1) {
printk(KERN_ERR batman-adv:Aggregation can only be enabled (1) 
or disabled (0), given value: %li\n, aggregation_enabled_tmp);
-   goto end;
+   }
+   else {
+   printk(KERN_INFO batman-adv:Changing aggregation from: %s (%i) 
to: %s (%li)\n,
+  (atomic_read(aggregation_enabled) == 1 ?
+   enabled : disabled),
+  atomic_read(aggregation_enabled),
+  (aggregation_enabled_tmp == 1 ? enabled : disabled),
+  aggregation_enabled_tmp);
+   atomic_set(aggregation_enabled, 
(unsigned)aggregation_enabled_tmp);
}
 
-   printk(KERN_INFO batman-adv:Changing aggregation from: %s (%i) to: %s 
(%li)\n,
-  (atomic_read(aggregation_enabled) == 1 ?
-   enabled : disabled),
-  atomic_read(aggregation_enabled),
-  (aggregation_enabled_tmp == 1 ? enabled : disabled),
-  aggregation_enabled_tmp);
-
-   atomic_set(aggregation_enabled, (unsigned)aggregation_enabled_tmp);
-end:
kfree(aggr_string);
return count;
 }
-- 
1.6.5.7



[B.A.T.M.A.N.] [PATCH 3/3] batman-adv: Remove unused variable

2009-12-31 Thread =?UTF-8?q?Linus=20L=C3=BCssing?=
The variable 'flag' is never being used in this function, therefore
removing it.

Signed-off-by: Linus Lüssing linus.luess...@web.de
---
 soft-interface.c |1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/soft-interface.c b/soft-interface.c
index 4d4d542..bc0217b 100644
--- a/soft-interface.c
+++ b/soft-interface.c
@@ -148,7 +148,6 @@ struct net_device_stats *interface_stats(struct net_device 
*dev)
 int interface_set_mac_addr(struct net_device *dev, void *p)
 {
struct sockaddr *addr = p;
-   unsigned long flags;
 
if (!is_valid_ether_addr(addr-sa_data))
return -EADDRNOTAVAIL;
-- 
1.6.5.7



[B.A.T.M.A.N.] [Patch 1/1] Staging: batman-adv: Use printk(%pM) for MAC addresses

2009-12-31 Thread Andrew Lunn
printk() since kernel version 2.6.29 has supported printing MAC
addresses directly, as an extension to the %p processing. This patch
makes use of this for printk() and bat_dbg(). This will remove the
overhead of using addr_to_string() which is normally never actually
output.

For kernels older than 2.6.29 the printk support from 2.6.31 has been
imported into batman-adv and will be used for formatting the output
before passing it onto the native printk() function.

Fix the typo found by Gus Wirth.
grep pMs suggests the typo only occurred once.

Stripped out all unneeded %pX functionality in bat_printk.c so that
the code is more likely to build with older kernels. 

Only build bat_printk.c with kernels that require it, thanks to Simon
Wunderlich Makefile.kbuild patch.

Signed-off-by: Andrew Lunn and...@lunn.ch
Index: Makefile.kbuild
===
--- Makefile.kbuild (revision 1524)
+++ Makefile.kbuild (working copy)
@@ -32,4 +32,4 @@
 endif
 
 obj-m += batman-adv.o
-batman-adv-objs := main.o proc.o send.o routing.o soft-interface.o device.o 
translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o 
aggregation.o originator.o
+batman-adv-objs := main.o proc.o send.o routing.o soft-interface.o device.o 
translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o 
aggregation.o originator.o $(shell [ 2 -eq $(VERSION) ]  [ 6 -eq 
$(PATCHLEVEL) ]  [ $(SUBLEVEL) -le 28 ]  echo bat_printk.o)
Index: translation-table.c
===
--- translation-table.c (revision 1524)
+++ translation-table.c (working copy)
@@ -61,7 +61,6 @@
struct hna_local_entry *hna_local_entry;
struct hna_global_entry *hna_global_entry;
struct hashtable_t *swaphash;
-   char hna_str[ETH_STR_LEN];
unsigned long flags;
 
spin_lock_irqsave(hna_local_hash_lock, flags);
@@ -74,19 +73,17 @@
return;
}
 
-   addr_to_string(hna_str, addr);
-
/* only announce as many hosts as possible in the batman-packet and
   space in batman_packet-num_hna That also should give a limit to
   MAC-flooding. */
if ((num_hna + 1  (ETH_DATA_LEN - BAT_PACKET_LEN) / ETH_ALEN) ||
(num_hna + 1  255)) {
-   bat_dbg(DBG_ROUTES, Can't add new local hna entry (%s): number 
of local hna entries exceeds packet size \n, hna_str);
+   bat_dbg(DBG_ROUTES, Can't add new local hna entry (%pM): 
number of local hna entries exceeds packet size \n, addr);
return;
}
 
-   bat_dbg(DBG_ROUTES, Creating new local hna entry: %s \n,
-   hna_str);
+   bat_dbg(DBG_ROUTES, Creating new local hna entry: %pM \n,
+   addr);
 
hna_local_entry = kmalloc(sizeof(struct hna_local_entry), GFP_ATOMIC);
if (!hna_local_entry)
@@ -201,12 +198,9 @@
 static void hna_local_del(struct hna_local_entry *hna_local_entry,
  char *message)
 {
-   char hna_str[ETH_STR_LEN];
+   bat_dbg(DBG_ROUTES, Deleting local hna entry (%pM): %s \n,
+   hna_local_entry-addr, message);
 
-   addr_to_string(hna_str, hna_local_entry-addr);
-   bat_dbg(DBG_ROUTES, Deleting local hna entry (%s): %s \n,
-   hna_str, message);
-
hash_remove(hna_local_hash, hna_local_entry-addr);
_hna_local_del(hna_local_entry);
 }
@@ -278,13 +272,10 @@
struct hna_global_entry *hna_global_entry;
struct hna_local_entry *hna_local_entry;
struct hashtable_t *swaphash;
-   char hna_str[ETH_STR_LEN], orig_str[ETH_STR_LEN];
int hna_buff_count = 0;
unsigned long flags;
unsigned char *hna_ptr;
 
-   addr_to_string(orig_str, orig_node-orig);
-
while ((hna_buff_count + 1) * ETH_ALEN = hna_buff_len) {
spin_lock_irqsave(hna_global_hash_lock, flags);
 
@@ -304,10 +295,9 @@
 
memcpy(hna_global_entry-addr, hna_ptr, ETH_ALEN);
 
-   addr_to_string(hna_str, hna_global_entry-addr);
bat_dbg(DBG_ROUTES,
-   Creating new global hna entry: %s (via %s)\n,
-   hna_str, orig_str);
+   Creating new global hna entry: %pM (via 
%pM)\n,
+   hna_global_entry-addr, orig_node-orig);
 
spin_lock_irqsave(hna_global_hash_lock, flags);
hash_add(hna_global_hash, hna_global_entry);
@@ -399,14 +389,10 @@
 void _hna_global_del_orig(struct hna_global_entry *hna_global_entry,
  char *message)
 {
-   char hna_str[ETH_STR_LEN], orig_str[ETH_STR_LEN];
+   bat_dbg(DBG_ROUTES, Deleting global hna entry %pM (via %pM): %s \n,
+   hna_global_entry-addr, hna_global_entry-orig_node-orig,
+   message);
 
-   

Re: [B.A.T.M.A.N.] [patchv2] batman-adv: Use printk(%pM) for MAC addres

2009-12-31 Thread Andrew Lunn
On Sun, Dec 13, 2009 at 08:01:49PM +0100, Simon Wunderlich wrote:
 Hello Andrew,
 
 i've checked your patch against older kernel, and there seem to be some
 compile problems. E.g. compiling against 2.6.26, i find:
 
   CC [M]  /home/dotslash/msrc/batman-svn/batman-adv-kernelland/bat_printk.o
 /home/dotslash/msrc/batman-svn/batman-adv-kernelland/bat_printk.c: In 
 function ???pointer???:
 /home/dotslash/msrc/batman-svn/batman-adv-kernelland/bat_printk.c:564: error: 
 implicit declaration of function ???dereference_function_descriptor???
 /home/dotslash/msrc/batman-svn/batman-adv-kernelland/bat_printk.c:564: 
 warning: assignment makes pointer from integer without a cast
 
 against 2.6.21, there are a lot more lines of warnings and errors, while 
 2.6.20 works mostly fine. Could you please review your patch in this regard? 
 I have nearly all kernels installed so i can give you a list of compile logs 
 if you
 are interested.

Hi Simon

I just posted an updated version of the patch. It would be great if
you could test it on a few different kernels. I tried
2.6.21. bat_printk.c now compiles, but other parts of batman-adv fail.
I think it was your skbuff patches which broke it, but i could be
wrong.

Andrew  


Re: [B.A.T.M.A.N.] [PATCHv2 no pgp] batman-adv: receive packets directly using skbs

2009-12-31 Thread Andrew Lunn
 I try to summarize where each lock is used so we can decide if it is ok to
 revert some of them to spin_lock again. This should also resolve a request I
 got from Andrew some time ago.

Hi Sven

Thanks for this.

[...]

 So it is complete correct to use irqsave everywhere (as you have commited it
 now).

This also means we don't need to worry about the order we take
spinlocks in resulting in deadlocks. Since we disable interrupts, it
is not possible for some other thread to be holding a lock we need.

   Andrew


[B.A.T.M.A.N.] Coccinelle tests?

2009-12-31 Thread Andrew Lunn
Hi Folks

I asked Julai Lawall to run her Coccinelle
(http://coccinelle.lip6.fr/) test suite on batman-adv. Here are her
results. Some of these issues are already fixed in subversion, others
are real bugs, and some are nice to fix.

Andrew

- Forwarded message from Julia Lawall ju...@diku.dk -

Date: Thu, 31 Dec 2009 17:40:21 +0100 (CET)
From: Julia Lawall ju...@diku.dk
To: Andrew Lunn and...@lunn.ch
Subject: Re: Standard coccinelle tests?
X-Spam-Status: No, score=-2.6 required=4.0 tests=BAYES_00 autolearn=ham
version=3.2.5

I ran all of my tests on your code, and came up with the following 
results.  Search for *** to see my comments about what I think should be 
done.  It is only the first one that seems like a serious bug.  Actually, 
I worked on that problem quite recently, but it must have been just before 
your code showed up, or I missed it for some other reason, because I don't 
have a record of having submitted a patch for that issue for your code.

julia

dev_addr.cocci

***dev-dev_addr is a pointer.  The size of an address is probably 6.  dev
has an addr_len field that might be initialized.

diff -u -p /var/linuxes/linux-next/drivers/staging/batman-adv/soft-interface.c 
/tmp/nothing
--- /var/linuxes/linux-next/drivers/staging/batman-adv/soft-interface.c 
2009-12-19 09:38:58.0 +0100
@@ -121,7 +121,7 @@ void interface_setup(struct net_device *
 
/* generate random address */
random_ether_addr(dev_addr);
-   memcpy(dev-dev_addr, dev_addr, sizeof(dev-dev_addr));
 
SET_ETHTOOL_OPS(dev, bat_ethtool_ops);
 
kmalmem.cocci

*** Use kzalloc instead of kmalloc + memset.  Also consider testing the result
of the kmaloc for NULL.

diff -u -p a/originator.c b/originator.c
--- a/originator.c 2009-12-19 09:38:58.0 +0100
+++ b/originator.c 2009-12-31 14:56:59.0 +0100
@@ -76,8 +76,7 @@ create_neighbor(struct orig_node *orig_n
 
bat_dbg(DBG_BATMAN, Creating new last-hop neighbour of originator\n);
 
-   neigh_node = kmalloc(sizeof(struct neigh_node), GFP_ATOMIC);
-   memset(neigh_node, 0, sizeof(struct neigh_node));
+   neigh_node = kzalloc(sizeof(struct neigh_node), GFP_ATOMIC);
INIT_LIST_HEAD(neigh_node-list);
 
memcpy(neigh_node-addr, neigh, ETH_ALEN);
@@ -126,8 +125,7 @@ struct orig_node *get_orig_node(uint8_t 
addr_to_string(orig_str, addr);
bat_dbg(DBG_BATMAN, Creating new originator: %s \n, orig_str);
 
-   orig_node = kmalloc(sizeof(struct orig_node), GFP_ATOMIC);
-   memset(orig_node, 0, sizeof(struct orig_node));
+   orig_node = kzalloc(sizeof(struct orig_node), GFP_ATOMIC);
INIT_LIST_HEAD(orig_node-neigh_list);
 
memcpy(orig_node-orig, addr, ETH_ALEN);
@@ -137,12 +135,10 @@ struct orig_node *get_orig_node(uint8_t 
 
size = num_ifs * sizeof(TYPE_OF_WORD) * NUM_WORDS;
 
-   orig_node-bcast_own = kmalloc(size, GFP_ATOMIC);
-   memset(orig_node-bcast_own, 0, size);
+   orig_node-bcast_own = kzalloc(size, GFP_ATOMIC);
 
size = num_ifs * sizeof(uint8_t);
-   orig_node-bcast_own_sum = kmalloc(size, GFP_ATOMIC);
-   memset(orig_node-bcast_own_sum, 0, size);
+   orig_node-bcast_own_sum = kzalloc(size, GFP_ATOMIC);
 
hash_add(orig_hash, orig_node);
 

kmbfree.cocci

*** As far as I can tell, in the following, the if after the out label is not
needed.

diff -u -p /var/linuxes/linux-next/drivers/staging/batman-adv/hard-interface.c 
/tmp/nothing
--- /var/linuxes/linux-next/drivers/staging/batman-adv/hard-interface.c 
2009-12-19 09:38:58.0 +0100
@@ -335,7 +335,7 @@ int hardif_add_interface(char *dev, int 
else
batman_if-packet_len = BAT_PACKET_LEN;
 
-   batman_if-packet_buff = kmalloc(batman_if-packet_len, GFP_KERNEL);
 
if (!batman_if-packet_buff) {
printk(KERN_ERR batman-adv:Can't add interface packet (%s): 
out of memory\n, dev);
@@ -401,7 +401,7 @@ int hardif_add_interface(char *dev, int 
 out:
if (batman_if-packet_buff)
kfree(batman_if-packet_buff);
-   kfree(batman_if);
kfree(dev);
return -1;
 }

kmtest.cocci

*** the result of kmalloc should be tested for NULL

diff -u -p /var/linuxes/linux-next/drivers/staging/batman-adv/hash.c 
/tmp/nothing
--- /var/linuxes/linux-next/drivers/staging/batman-adv/hash.c   2009-11-23 
22:35:21.0 +0100
@@ -76,7 +76,7 @@ struct hash_it_t *hash_iterate(struct ha
 
if (iter_in == NULL) {
iter = kmalloc(sizeof(struct hash_it_t), GFP_ATOMIC);
-   iter-index = -1;
iter-bucket = NULL;
iter-prev_bucket = NULL;
} else {
diff -u -p 
/var/linuxes/linux-next/drivers/staging/batman-adv/translation-table.c 
/tmp/nothing
--- /var/linuxes/linux-next/drivers/staging/batman-adv/translation-table.c  
2009-12-19 09:38:58.0 +0100
@@ -322,7 +322,6 @@ void hna_global_add_orig(struct orig_nod
if 

[B.A.T.M.A.N.] Changeset 1519

2009-12-31 Thread Gus Wirth
I'm looking at changeset 1519 and have a question about the patch to
routing.c

On line 158 there is:

if (neigh_node)

but later at line 179 there is:

if (!neigh_node)

for essential the same functionality.

Am I confused or is one of these wrong (most likely the first one)?

Gus


Re: [B.A.T.M.A.N.] Changeset 1519

2009-12-31 Thread Gus Wirth
On 12/31/2009 10:37 AM, Gus Wirth wrote:
 I'm looking at changeset 1519 and have a question about the patch to
 routing.c
 
 On line 158 there is:
 
 if (neigh_node)
 
 but later at line 179 there is:
 
 if (!neigh_node)
 
 for essential the same functionality.
 
 Am I confused or is one of these wrong (most likely the first one)?

Never mind. It was fixed in 1520.

Gus


Re: [B.A.T.M.A.N.] Changeset 1519

2009-12-31 Thread Sven Eckelmann
On Thu, Dec 31, 2009 at 10:37:29AM -0800, Gus Wirth wrote:
 I'm looking at changeset 1519 and have a question about the patch to
 routing.c
 
 On line 158 there is:
 
 if (neigh_node)
 
 but later at line 179 there is:
 
 if (!neigh_node)
 
 for essential the same functionality.
 
 Am I confused or is one of these wrong (most likely the first one)?

Please also look at 1520 and 1524.

Best regards,
Sven


signature.asc
Description: Digital signature