int hna_global_seq_print_text(struct seq_file *seq, void *offset)
{
	struct net_device *net_dev = (struct net_device *)seq->private;
	struct bat_priv *bat_priv = netdev_priv(net_dev);
	struct hna_global_entry *hna_global_entry;
	HASHIT(hashit);
	HASHIT(hashit_count);
	unsigned long flags;
	size_t buf_size, pos;
	char *buff;

	if (!bat_priv->primary_if) {
		return seq_printf(seq, "BATMAN mesh %s disabled - "
				  "please specify interfaces to enable it\n",
				  net_dev->name);
	}

	seq_printf(seq, "Globally announced HNAs received via the mesh %s\n",
		   net_dev->name);

	spin_lock_irqsave(&bat_priv->hna_ghash_lock, flags);

	buf_size = 1;
	/* Estimate length for: " * xx:xx:xx:xx:xx:xx via xx:xx:xx:xx:xx:xx\n"*/
	while (hash_iterate(bat_priv->hna_global_hash, &hashit_count))
		buf_size += 43;

	buff = kmalloc(buf_size, GFP_ATOMIC);
	if (!buff) {
		spin_unlock_irqrestore(&bat_priv->hna_ghash_lock, flags);
		return -ENOMEM;
	}
	buff[0] = '\0';
	pos = 0;

	while (hash_iterate(bat_priv->hna_global_hash, &hashit)) {
		hna_global_entry = hashit.bucket->data;

		pos += snprintf(buff + pos, 44,
				" * %pM via %pM\n", hna_global_entry->addr,
				hna_global_entry->orig_node->orig);
	}

	spin_unlock_irqrestore(&bat_priv->hna_ghash_lock, flags);

	seq_printf(seq, "%s", buff);
	kfree(buff);
	return 0;
}
static void hna_local_purge(struct work_struct *work)
{
	struct delayed_work *delayed_work =
		container_of(work, struct delayed_work, work);
	struct bat_priv *bat_priv =
		container_of(delayed_work, struct bat_priv, hna_work);
	struct hna_local_entry *hna_local_entry;
	HASHIT(hashit);
	unsigned long flags;
	unsigned long timeout;

	spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags);

	while (hash_iterate(bat_priv->hna_local_hash, &hashit)) {
		hna_local_entry = hashit.bucket->data;

		timeout = hna_local_entry->last_seen + LOCAL_HNA_TIMEOUT * HZ;

		if ((!hna_local_entry->never_purge) &&
		    time_after(jiffies, timeout))
			hna_local_del(bat_priv, hna_local_entry,
				      "address timed out");
	}

	spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags);
	hna_local_start_timer(bat_priv);
}
int hna_local_fill_buffer(struct bat_priv *bat_priv,
			  unsigned char *buff, int buff_len)
{
	struct hna_local_entry *hna_local_entry;
	HASHIT(hashit);
	int i = 0;
	unsigned long flags;

	spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags);

	while (hash_iterate(bat_priv->hna_local_hash, &hashit)) {

		if (buff_len < (i + 1) * ETH_ALEN)
			break;

		hna_local_entry = hashit.bucket->data;
		memcpy(buff + (i * ETH_ALEN), hna_local_entry->addr, ETH_ALEN);

		i++;
	}

	/* if we did not get all new local hnas see you next time  ;-) */
	if (i == bat_priv->num_local_hna)
		atomic_set(&bat_priv->hna_local_changed, 0);

	spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags);
	return i;
}
int hna_global_fill_buffer_text(struct net_device *net_dev, char *buff,
				size_t count, loff_t off)
{
	struct bat_priv *bat_priv = netdev_priv(net_dev);
	struct hna_global_entry *hna_global_entry;
	HASHIT(hashit);
	int bytes_written = 0;
	unsigned long flags;
	size_t hdr_len;

	if (!bat_priv->primary_if) {
		if (off == 0)
			return sprintf(buff,
				     "BATMAN mesh %s disabled - "
				     "please specify interfaces to enable it\n",
				     net_dev->name);

		return 0;
	}

	hdr_len = sprintf(buff,
			  "Globally announced HNAs received via the mesh %s "
			  "(translation table):\n",
			  net_dev->name);

	if (off < hdr_len)
		bytes_written = hdr_len;

	spin_lock_irqsave(&hna_global_hash_lock, flags);

	while (hash_iterate(hna_global_hash, &hashit)) {
		hdr_len += 43;

		if (count < bytes_written + 44)
			break;

		if (off >= hdr_len)
			continue;

		hna_global_entry = hashit.bucket->data;

		bytes_written += snprintf(buff + bytes_written, 44,
					  " * " MAC_FMT " via " MAC_FMT "\n",
					  hna_global_entry->addr[0],
					  hna_global_entry->addr[1],
					  hna_global_entry->addr[2],
					  hna_global_entry->addr[3],
					  hna_global_entry->addr[4],
					  hna_global_entry->addr[5],
					  hna_global_entry->orig_node->orig[0],
					  hna_global_entry->orig_node->orig[1],
					  hna_global_entry->orig_node->orig[2],
					  hna_global_entry->orig_node->orig[3],
					  hna_global_entry->orig_node->orig[4],
					  hna_global_entry->orig_node->orig[5]);
	}

	spin_unlock_irqrestore(&hna_global_hash_lock, flags);
	return bytes_written;
}
int hna_local_fill_buffer_text(struct net_device *net_dev, char *buff,
			       size_t count, loff_t off)
{
	struct bat_priv *bat_priv = netdev_priv(net_dev);
	struct hna_local_entry *hna_local_entry;
	HASHIT(hashit);
	int bytes_written = 0;
	unsigned long flags;
	size_t hdr_len;

	if (!bat_priv->primary_if) {
		if (off == 0)
			return sprintf(buff,
				     "BATMAN mesh %s disabled - "
				     "please specify interfaces to enable it\n",
				     net_dev->name);

		return 0;
	}

	hdr_len = sprintf(buff,
			  "Locally retrieved addresses (from %s) "
			  "announced via HNA:\n",
			  net_dev->name);

	if (off < hdr_len)
		bytes_written = hdr_len;

	spin_lock_irqsave(&hna_local_hash_lock, flags);

	while (hash_iterate(hna_local_hash, &hashit)) {
		hdr_len += 21;

		if (count < bytes_written + 22)
			break;

		if (off >= hdr_len)
			continue;

		hna_local_entry = hashit.bucket->data;

		bytes_written += snprintf(buff + bytes_written, 22,
					  " * " MAC_FMT "\n",
					  hna_local_entry->addr[0],
					  hna_local_entry->addr[1],
					  hna_local_entry->addr[2],
					  hna_local_entry->addr[3],
					  hna_local_entry->addr[4],
					  hna_local_entry->addr[5]);
	}

	spin_unlock_irqrestore(&hna_local_hash_lock, flags);
	return bytes_written;
}
void hna_local_purge(struct work_struct *work)
{
	struct hna_local_entry *hna_local_entry;
	HASHIT(hashit);
	unsigned long flags;
	unsigned long timeout;

	spin_lock_irqsave(&hna_local_hash_lock, flags);

	while (hash_iterate(hna_local_hash, &hashit)) {
		hna_local_entry = hashit.bucket->data;

		timeout = hna_local_entry->last_seen +
			((LOCAL_HNA_TIMEOUT / 1000) * HZ);
		if ((!hna_local_entry->never_purge) &&
		    time_after(jiffies, timeout))
			hna_local_del(hna_local_entry, "address timed out");
	}

	spin_unlock_irqrestore(&hna_local_hash_lock, flags);
	hna_local_start_timer();
}