144d362409d5469aed47d19e7908d19bd194493aThomas Graf/*
244d362409d5469aed47d19e7908d19bd194493aThomas Graf * lib/utils.c		Utility Functions
344d362409d5469aed47d19e7908d19bd194493aThomas Graf *
444d362409d5469aed47d19e7908d19bd194493aThomas Graf *	This library is free software; you can redistribute it and/or
544d362409d5469aed47d19e7908d19bd194493aThomas Graf *	modify it under the terms of the GNU Lesser General Public
644d362409d5469aed47d19e7908d19bd194493aThomas Graf *	License as published by the Free Software Foundation version 2.1
744d362409d5469aed47d19e7908d19bd194493aThomas Graf *	of the License.
844d362409d5469aed47d19e7908d19bd194493aThomas Graf *
98a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
1044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1144d362409d5469aed47d19e7908d19bd194493aThomas Graf
1244d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
136782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf * @ingroup core
1444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @defgroup utils Utilities
1544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
1644d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1744d362409d5469aed47d19e7908d19bd194493aThomas Graf
1844d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink-local.h>
1944d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netlink.h>
2044d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/utils.h>
2144d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <linux/socket.h>
2244d362409d5469aed47d19e7908d19bd194493aThomas Graf
2344d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
2444d362409d5469aed47d19e7908d19bd194493aThomas Graf * Debug level
2544d362409d5469aed47d19e7908d19bd194493aThomas Graf */
2644d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_debug = 0;
2744d362409d5469aed47d19e7908d19bd194493aThomas Graf
2844d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_dump_params nl_debug_dp = {
29d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	.dp_type = NL_DUMP_DETAILS,
3044d362409d5469aed47d19e7908d19bd194493aThomas Graf};
3144d362409d5469aed47d19e7908d19bd194493aThomas Graf
323c56ed5787481a06703ffb25561df3dd56b447bdThomas Grafstatic void __init nl_debug_init(void)
3344d362409d5469aed47d19e7908d19bd194493aThomas Graf{
343c56ed5787481a06703ffb25561df3dd56b447bdThomas Graf	char *nldbg, *end;
353c56ed5787481a06703ffb25561df3dd56b447bdThomas Graf
363c56ed5787481a06703ffb25561df3dd56b447bdThomas Graf	if ((nldbg = getenv("NLDBG"))) {
373c56ed5787481a06703ffb25561df3dd56b447bdThomas Graf		long level = strtol(nldbg, &end, 0);
383c56ed5787481a06703ffb25561df3dd56b447bdThomas Graf		if (nldbg != end)
393c56ed5787481a06703ffb25561df3dd56b447bdThomas Graf			nl_debug = level;
403c56ed5787481a06703ffb25561df3dd56b447bdThomas Graf	}
413c56ed5787481a06703ffb25561df3dd56b447bdThomas Graf
4244d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_debug_dp.dp_fd = stderr;
4344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
4444d362409d5469aed47d19e7908d19bd194493aThomas Graf
4544d362409d5469aed47d19e7908d19bd194493aThomas Grafint __nl_read_num_str_file(const char *path, int (*cb)(long, const char *))
4644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
4744d362409d5469aed47d19e7908d19bd194493aThomas Graf	FILE *fd;
4844d362409d5469aed47d19e7908d19bd194493aThomas Graf	char buf[128];
4944d362409d5469aed47d19e7908d19bd194493aThomas Graf
5044d362409d5469aed47d19e7908d19bd194493aThomas Graf	fd = fopen(path, "r");
5144d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (fd == NULL)
528a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return -nl_syserr2nlerr(errno);
5344d362409d5469aed47d19e7908d19bd194493aThomas Graf
5444d362409d5469aed47d19e7908d19bd194493aThomas Graf	while (fgets(buf, sizeof(buf), fd)) {
5544d362409d5469aed47d19e7908d19bd194493aThomas Graf		int goodlen, err;
5644d362409d5469aed47d19e7908d19bd194493aThomas Graf		long num;
5744d362409d5469aed47d19e7908d19bd194493aThomas Graf		char *end;
5844d362409d5469aed47d19e7908d19bd194493aThomas Graf
5944d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (*buf == '#' || *buf == '\n' || *buf == '\r')
6044d362409d5469aed47d19e7908d19bd194493aThomas Graf			continue;
6144d362409d5469aed47d19e7908d19bd194493aThomas Graf
6244d362409d5469aed47d19e7908d19bd194493aThomas Graf		num = strtol(buf, &end, 0);
6344d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (end == buf)
648a3efffa5b3fde252675239914118664d36a2c24Thomas Graf			return -NLE_INVAL;
6544d362409d5469aed47d19e7908d19bd194493aThomas Graf
6644d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (num == LONG_MIN || num == LONG_MAX)
678a3efffa5b3fde252675239914118664d36a2c24Thomas Graf			return -NLE_RANGE;
6844d362409d5469aed47d19e7908d19bd194493aThomas Graf
6944d362409d5469aed47d19e7908d19bd194493aThomas Graf		while (*end == ' ' || *end == '\t')
7044d362409d5469aed47d19e7908d19bd194493aThomas Graf			end++;
7144d362409d5469aed47d19e7908d19bd194493aThomas Graf
7244d362409d5469aed47d19e7908d19bd194493aThomas Graf		goodlen = strcspn(end, "#\r\n\t ");
7344d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (goodlen == 0)
748a3efffa5b3fde252675239914118664d36a2c24Thomas Graf			return -NLE_INVAL;
7544d362409d5469aed47d19e7908d19bd194493aThomas Graf
7644d362409d5469aed47d19e7908d19bd194493aThomas Graf		end[goodlen] = '\0';
7744d362409d5469aed47d19e7908d19bd194493aThomas Graf
7844d362409d5469aed47d19e7908d19bd194493aThomas Graf		err = cb(num, end);
7944d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (err < 0)
8044d362409d5469aed47d19e7908d19bd194493aThomas Graf			return err;
8144d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
8244d362409d5469aed47d19e7908d19bd194493aThomas Graf
8344d362409d5469aed47d19e7908d19bd194493aThomas Graf	fclose(fd);
8444d362409d5469aed47d19e7908d19bd194493aThomas Graf
8544d362409d5469aed47d19e7908d19bd194493aThomas Graf	return 0;
8644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
8744d362409d5469aed47d19e7908d19bd194493aThomas Graf
8844d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
8944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Unit Pretty-Printing
9044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
9144d362409d5469aed47d19e7908d19bd194493aThomas Graf */
9244d362409d5469aed47d19e7908d19bd194493aThomas Graf
9344d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
9444d362409d5469aed47d19e7908d19bd194493aThomas Graf * Cancel down a byte counter
9544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg	l		byte counter
9644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg	unit		destination unit pointer
9744d362409d5469aed47d19e7908d19bd194493aThomas Graf *
9844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Cancels down a byte counter until it reaches a reasonable
9944d362409d5469aed47d19e7908d19bd194493aThomas Graf * unit. The chosen unit is assigned to \a unit.
10044d362409d5469aed47d19e7908d19bd194493aThomas Graf *
10144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return The cancelled down byte counter in the new unit.
10244d362409d5469aed47d19e7908d19bd194493aThomas Graf */
10344d362409d5469aed47d19e7908d19bd194493aThomas Grafdouble nl_cancel_down_bytes(unsigned long long l, char **unit)
10444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
10544d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (l >= 1099511627776LL) {
10644d362409d5469aed47d19e7908d19bd194493aThomas Graf		*unit = "TiB";
10744d362409d5469aed47d19e7908d19bd194493aThomas Graf		return ((double) l) / 1099511627776LL;
10844d362409d5469aed47d19e7908d19bd194493aThomas Graf	} else if (l >= 1073741824) {
10944d362409d5469aed47d19e7908d19bd194493aThomas Graf		*unit = "GiB";
11044d362409d5469aed47d19e7908d19bd194493aThomas Graf		return ((double) l) / 1073741824;
11144d362409d5469aed47d19e7908d19bd194493aThomas Graf	} else if (l >= 1048576) {
11244d362409d5469aed47d19e7908d19bd194493aThomas Graf		*unit = "MiB";
11344d362409d5469aed47d19e7908d19bd194493aThomas Graf		return ((double) l) / 1048576;
11444d362409d5469aed47d19e7908d19bd194493aThomas Graf	} else if (l >= 1024) {
11544d362409d5469aed47d19e7908d19bd194493aThomas Graf		*unit = "KiB";
11644d362409d5469aed47d19e7908d19bd194493aThomas Graf		return ((double) l) / 1024;
11744d362409d5469aed47d19e7908d19bd194493aThomas Graf	} else {
11844d362409d5469aed47d19e7908d19bd194493aThomas Graf		*unit = "B";
11944d362409d5469aed47d19e7908d19bd194493aThomas Graf		return (double) l;
12044d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
12144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
12244d362409d5469aed47d19e7908d19bd194493aThomas Graf
12344d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
12444d362409d5469aed47d19e7908d19bd194493aThomas Graf * Cancel down a bit counter
12544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg	l		bit counter
12644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg unit		destination unit pointer
12744d362409d5469aed47d19e7908d19bd194493aThomas Graf *
12844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Cancels downa bit counter until it reaches a reasonable
12944d362409d5469aed47d19e7908d19bd194493aThomas Graf * unit. The chosen unit is assigned to \a unit.
13044d362409d5469aed47d19e7908d19bd194493aThomas Graf *
13144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return The cancelled down bit counter in the new unit.
13244d362409d5469aed47d19e7908d19bd194493aThomas Graf */
13344d362409d5469aed47d19e7908d19bd194493aThomas Grafdouble nl_cancel_down_bits(unsigned long long l, char **unit)
13444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
13544d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (l >= 1099511627776ULL) {
13644d362409d5469aed47d19e7908d19bd194493aThomas Graf		*unit = "Tbit";
13744d362409d5469aed47d19e7908d19bd194493aThomas Graf		return ((double) l) / 1099511627776ULL;
13844d362409d5469aed47d19e7908d19bd194493aThomas Graf	} else if (l >= 1073741824) {
13944d362409d5469aed47d19e7908d19bd194493aThomas Graf		*unit = "Gbit";
14044d362409d5469aed47d19e7908d19bd194493aThomas Graf		return ((double) l) / 1073741824;
14144d362409d5469aed47d19e7908d19bd194493aThomas Graf	} else if (l >= 1048576) {
14244d362409d5469aed47d19e7908d19bd194493aThomas Graf		*unit = "Mbit";
14344d362409d5469aed47d19e7908d19bd194493aThomas Graf		return ((double) l) / 1048576;
14444d362409d5469aed47d19e7908d19bd194493aThomas Graf	} else if (l >= 1024) {
14544d362409d5469aed47d19e7908d19bd194493aThomas Graf		*unit = "Kbit";
14644d362409d5469aed47d19e7908d19bd194493aThomas Graf		return ((double) l) / 1024;
14744d362409d5469aed47d19e7908d19bd194493aThomas Graf	} else {
14844d362409d5469aed47d19e7908d19bd194493aThomas Graf		*unit = "bit";
14944d362409d5469aed47d19e7908d19bd194493aThomas Graf		return (double) l;
15044d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
15144d362409d5469aed47d19e7908d19bd194493aThomas Graf
15244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
15344d362409d5469aed47d19e7908d19bd194493aThomas Graf
15444d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
15544d362409d5469aed47d19e7908d19bd194493aThomas Graf * Cancel down a micro second value
15644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg	l		micro seconds
15744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg unit		destination unit pointer
15844d362409d5469aed47d19e7908d19bd194493aThomas Graf *
15944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Cancels down a microsecond counter until it reaches a
16044d362409d5469aed47d19e7908d19bd194493aThomas Graf * reasonable unit. The chosen unit is assigned to \a unit.
16144d362409d5469aed47d19e7908d19bd194493aThomas Graf *
16244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return The cancelled down microsecond in the new unit
16344d362409d5469aed47d19e7908d19bd194493aThomas Graf */
16444d362409d5469aed47d19e7908d19bd194493aThomas Grafdouble nl_cancel_down_us(uint32_t l, char **unit)
16544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
16644d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (l >= 1000000) {
16744d362409d5469aed47d19e7908d19bd194493aThomas Graf		*unit = "s";
16844d362409d5469aed47d19e7908d19bd194493aThomas Graf		return ((double) l) / 1000000;
16944d362409d5469aed47d19e7908d19bd194493aThomas Graf	} else if (l >= 1000) {
17044d362409d5469aed47d19e7908d19bd194493aThomas Graf		*unit = "ms";
17144d362409d5469aed47d19e7908d19bd194493aThomas Graf		return ((double) l) / 1000;
17244d362409d5469aed47d19e7908d19bd194493aThomas Graf	} else {
17344d362409d5469aed47d19e7908d19bd194493aThomas Graf		*unit = "us";
17444d362409d5469aed47d19e7908d19bd194493aThomas Graf		return (double) l;
17544d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
17644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
17744d362409d5469aed47d19e7908d19bd194493aThomas Graf
17844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
17944d362409d5469aed47d19e7908d19bd194493aThomas Graf
18044d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
18144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Generic Unit Translations
18244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
18344d362409d5469aed47d19e7908d19bd194493aThomas Graf */
18444d362409d5469aed47d19e7908d19bd194493aThomas Graf
18544d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
18644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Convert a character string to a size
18744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg str		size encoded as character string
18844d362409d5469aed47d19e7908d19bd194493aThomas Graf *
18944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Converts the specified size as character to the corresponding
19044d362409d5469aed47d19e7908d19bd194493aThomas Graf * number of bytes.
19144d362409d5469aed47d19e7908d19bd194493aThomas Graf *
19244d362409d5469aed47d19e7908d19bd194493aThomas Graf * Supported formats are:
19344d362409d5469aed47d19e7908d19bd194493aThomas Graf *  - b,kb/k,m/mb,gb/g for bytes
19444d362409d5469aed47d19e7908d19bd194493aThomas Graf *  - bit,kbit/mbit/gbit
19544d362409d5469aed47d19e7908d19bd194493aThomas Graf *
19644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return The number of bytes or -1 if the string is unparseable
19744d362409d5469aed47d19e7908d19bd194493aThomas Graf */
19844d362409d5469aed47d19e7908d19bd194493aThomas Graflong nl_size2int(const char *str)
19944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
20044d362409d5469aed47d19e7908d19bd194493aThomas Graf	char *p;
20144d362409d5469aed47d19e7908d19bd194493aThomas Graf	long l = strtol(str, &p, 0);
20244d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (p == str)
20300466b0f95af19623c6536edafca6904945ced83Thomas Graf		return -NLE_INVAL;
20444d362409d5469aed47d19e7908d19bd194493aThomas Graf
20544d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (*p) {
20644d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (!strcasecmp(p, "kb") || !strcasecmp(p, "k"))
20744d362409d5469aed47d19e7908d19bd194493aThomas Graf			l *= 1024;
20844d362409d5469aed47d19e7908d19bd194493aThomas Graf		else if (!strcasecmp(p, "gb") || !strcasecmp(p, "g"))
20944d362409d5469aed47d19e7908d19bd194493aThomas Graf			l *= 1024*1024*1024;
21044d362409d5469aed47d19e7908d19bd194493aThomas Graf		else if (!strcasecmp(p, "gbit"))
21144d362409d5469aed47d19e7908d19bd194493aThomas Graf			l *= 1024*1024*1024/8;
21244d362409d5469aed47d19e7908d19bd194493aThomas Graf		else if (!strcasecmp(p, "mb") || !strcasecmp(p, "m"))
21344d362409d5469aed47d19e7908d19bd194493aThomas Graf			l *= 1024*1024;
21444d362409d5469aed47d19e7908d19bd194493aThomas Graf		else if (!strcasecmp(p, "mbit"))
21544d362409d5469aed47d19e7908d19bd194493aThomas Graf			l *= 1024*1024/8;
21644d362409d5469aed47d19e7908d19bd194493aThomas Graf		else if (!strcasecmp(p, "kbit"))
21744d362409d5469aed47d19e7908d19bd194493aThomas Graf			l *= 1024/8;
21844d362409d5469aed47d19e7908d19bd194493aThomas Graf		else if (!strcasecmp(p, "bit"))
21944d362409d5469aed47d19e7908d19bd194493aThomas Graf			l /= 8;
22044d362409d5469aed47d19e7908d19bd194493aThomas Graf		else if (strcasecmp(p, "b") != 0)
22100466b0f95af19623c6536edafca6904945ced83Thomas Graf			return -NLE_INVAL;
22244d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
22344d362409d5469aed47d19e7908d19bd194493aThomas Graf
22444d362409d5469aed47d19e7908d19bd194493aThomas Graf	return l;
22544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
22644d362409d5469aed47d19e7908d19bd194493aThomas Graf
22744d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
22844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Convert a character string to a probability
22944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg str		probability encoded as character string
23044d362409d5469aed47d19e7908d19bd194493aThomas Graf *
23144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Converts the specified probability as character to the
23244d362409d5469aed47d19e7908d19bd194493aThomas Graf * corresponding probability number.
23344d362409d5469aed47d19e7908d19bd194493aThomas Graf *
23444d362409d5469aed47d19e7908d19bd194493aThomas Graf * Supported formats are:
23544d362409d5469aed47d19e7908d19bd194493aThomas Graf *  - 0.0-1.0
23644d362409d5469aed47d19e7908d19bd194493aThomas Graf *  - 0%-100%
23744d362409d5469aed47d19e7908d19bd194493aThomas Graf *
23844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return The probability relative to NL_PROB_MIN and NL_PROB_MAX
23944d362409d5469aed47d19e7908d19bd194493aThomas Graf */
24044d362409d5469aed47d19e7908d19bd194493aThomas Graflong nl_prob2int(const char *str)
24144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
24244d362409d5469aed47d19e7908d19bd194493aThomas Graf	char *p;
24344d362409d5469aed47d19e7908d19bd194493aThomas Graf	double d = strtod(str, &p);
24444d362409d5469aed47d19e7908d19bd194493aThomas Graf
24544d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (p == str)
24600466b0f95af19623c6536edafca6904945ced83Thomas Graf		return -NLE_INVAL;
24744d362409d5469aed47d19e7908d19bd194493aThomas Graf
24844d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (d > 1.0)
24944d362409d5469aed47d19e7908d19bd194493aThomas Graf		d /= 100.0f;
25044d362409d5469aed47d19e7908d19bd194493aThomas Graf
25144d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (d > 1.0f || d < 0.0f)
25200466b0f95af19623c6536edafca6904945ced83Thomas Graf		return -NLE_RANGE;
25344d362409d5469aed47d19e7908d19bd194493aThomas Graf
25444d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (*p && strcmp(p, "%") != 0)
25500466b0f95af19623c6536edafca6904945ced83Thomas Graf		return -NLE_INVAL;
25644d362409d5469aed47d19e7908d19bd194493aThomas Graf
25744d362409d5469aed47d19e7908d19bd194493aThomas Graf	return rint(d * NL_PROB_MAX);
25844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
25944d362409d5469aed47d19e7908d19bd194493aThomas Graf
26044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
26144d362409d5469aed47d19e7908d19bd194493aThomas Graf
26244d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
26344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Time Translations
26444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
26544d362409d5469aed47d19e7908d19bd194493aThomas Graf */
26644d362409d5469aed47d19e7908d19bd194493aThomas Graf
26744d362409d5469aed47d19e7908d19bd194493aThomas Graf#ifdef USER_HZ
26844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic uint32_t user_hz = USER_HZ;
26944d362409d5469aed47d19e7908d19bd194493aThomas Graf#else
27044d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic uint32_t user_hz = 100;
27144d362409d5469aed47d19e7908d19bd194493aThomas Graf#endif
27244d362409d5469aed47d19e7908d19bd194493aThomas Graf
27344d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic double ticks_per_usec = 1.0f;
27444d362409d5469aed47d19e7908d19bd194493aThomas Graf
27544d362409d5469aed47d19e7908d19bd194493aThomas Graf/* Retrieves the configured HZ and ticks/us value in the kernel.
27644d362409d5469aed47d19e7908d19bd194493aThomas Graf * The value is cached. Supported ways of getting it:
27744d362409d5469aed47d19e7908d19bd194493aThomas Graf *
27844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 1) environment variable
27944d362409d5469aed47d19e7908d19bd194493aThomas Graf * 2) /proc/net/psched and sysconf
28044d362409d5469aed47d19e7908d19bd194493aThomas Graf *
28144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Supports the environment variables:
28244d362409d5469aed47d19e7908d19bd194493aThomas Graf *   PROC_NET_PSCHED  - may point to psched file in /proc
28344d362409d5469aed47d19e7908d19bd194493aThomas Graf *   PROC_ROOT        - may point to /proc fs */
28444d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void __init get_psched_settings(void)
28544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
28644d362409d5469aed47d19e7908d19bd194493aThomas Graf	char name[FILENAME_MAX];
28744d362409d5469aed47d19e7908d19bd194493aThomas Graf	FILE *fd;
28852d6b8b9ee21b4bc112cc8a5d6f440536dd7fde0Jose Ignacio Naranjo Hernández	int got_hz = 0;
28944d362409d5469aed47d19e7908d19bd194493aThomas Graf
29044d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (getenv("HZ")) {
29144d362409d5469aed47d19e7908d19bd194493aThomas Graf		long hz = strtol(getenv("HZ"), NULL, 0);
29244d362409d5469aed47d19e7908d19bd194493aThomas Graf
29344d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (LONG_MIN != hz && LONG_MAX != hz) {
29444d362409d5469aed47d19e7908d19bd194493aThomas Graf			user_hz = hz;
29544d362409d5469aed47d19e7908d19bd194493aThomas Graf			got_hz = 1;
29644d362409d5469aed47d19e7908d19bd194493aThomas Graf		}
29744d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
29844d362409d5469aed47d19e7908d19bd194493aThomas Graf
29944d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (!got_hz)
30044d362409d5469aed47d19e7908d19bd194493aThomas Graf		user_hz = sysconf(_SC_CLK_TCK);
30144d362409d5469aed47d19e7908d19bd194493aThomas Graf
30244d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (getenv("TICKS_PER_USEC")) {
30344d362409d5469aed47d19e7908d19bd194493aThomas Graf		double t = strtod(getenv("TICKS_PER_USEC"), NULL);
30444d362409d5469aed47d19e7908d19bd194493aThomas Graf		ticks_per_usec = t;
30544d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
30652d6b8b9ee21b4bc112cc8a5d6f440536dd7fde0Jose Ignacio Naranjo Hernández	else {
30752d6b8b9ee21b4bc112cc8a5d6f440536dd7fde0Jose Ignacio Naranjo Hernández		if (getenv("PROC_NET_PSCHED"))
30852d6b8b9ee21b4bc112cc8a5d6f440536dd7fde0Jose Ignacio Naranjo Hernández			snprintf(name, sizeof(name), "%s", getenv("PROC_NET_PSCHED"));
30952d6b8b9ee21b4bc112cc8a5d6f440536dd7fde0Jose Ignacio Naranjo Hernández		else if (getenv("PROC_ROOT"))
31052d6b8b9ee21b4bc112cc8a5d6f440536dd7fde0Jose Ignacio Naranjo Hernández			snprintf(name, sizeof(name), "%s/net/psched",
31152d6b8b9ee21b4bc112cc8a5d6f440536dd7fde0Jose Ignacio Naranjo Hernández				 getenv("PROC_ROOT"));
31252d6b8b9ee21b4bc112cc8a5d6f440536dd7fde0Jose Ignacio Naranjo Hernández		else
31352d6b8b9ee21b4bc112cc8a5d6f440536dd7fde0Jose Ignacio Naranjo Hernández			strncpy(name, "/proc/net/psched", sizeof(name) - 1);
31444d362409d5469aed47d19e7908d19bd194493aThomas Graf
31552d6b8b9ee21b4bc112cc8a5d6f440536dd7fde0Jose Ignacio Naranjo Hernández		if ((fd = fopen(name, "r"))) {
31652d6b8b9ee21b4bc112cc8a5d6f440536dd7fde0Jose Ignacio Naranjo Hernández			uint32_t tick, us;
31752d6b8b9ee21b4bc112cc8a5d6f440536dd7fde0Jose Ignacio Naranjo Hernández			/* the file contains 4 hexadecimals, but we just use
31852d6b8b9ee21b4bc112cc8a5d6f440536dd7fde0Jose Ignacio Naranjo Hernández			   the first two of them */
3190fa04772ab1e092fce34b658d6cc4e6f6b59be1dThomas Graf			fscanf(fd, "%08x %08x", &tick, &us);
32044d362409d5469aed47d19e7908d19bd194493aThomas Graf			ticks_per_usec = (double)tick/(double)us;
32152d6b8b9ee21b4bc112cc8a5d6f440536dd7fde0Jose Ignacio Naranjo Hernández			fclose(fd);
32252d6b8b9ee21b4bc112cc8a5d6f440536dd7fde0Jose Ignacio Naranjo Hernández		}
32344d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
32444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
32544d362409d5469aed47d19e7908d19bd194493aThomas Graf
32644d362409d5469aed47d19e7908d19bd194493aThomas Graf
32744d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
32844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Return the value of HZ
32944d362409d5469aed47d19e7908d19bd194493aThomas Graf */
33044d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_get_hz(void)
33144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
33244d362409d5469aed47d19e7908d19bd194493aThomas Graf	return user_hz;
33344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
33444d362409d5469aed47d19e7908d19bd194493aThomas Graf
33544d362409d5469aed47d19e7908d19bd194493aThomas Graf
33644d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
33744d362409d5469aed47d19e7908d19bd194493aThomas Graf * Convert micro seconds to ticks
33844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg us		micro seconds
33944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return number of ticks
34044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
34144d362409d5469aed47d19e7908d19bd194493aThomas Grafuint32_t nl_us2ticks(uint32_t us)
34244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
34344d362409d5469aed47d19e7908d19bd194493aThomas Graf	return us * ticks_per_usec;
34444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
34544d362409d5469aed47d19e7908d19bd194493aThomas Graf
34644d362409d5469aed47d19e7908d19bd194493aThomas Graf
34744d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
34844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Convert ticks to micro seconds
34944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg ticks		number of ticks
35044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return microseconds
35144d362409d5469aed47d19e7908d19bd194493aThomas Graf */
35244d362409d5469aed47d19e7908d19bd194493aThomas Grafuint32_t nl_ticks2us(uint32_t ticks)
35344d362409d5469aed47d19e7908d19bd194493aThomas Graf{
35444d362409d5469aed47d19e7908d19bd194493aThomas Graf	return ticks / ticks_per_usec;
35544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
35644d362409d5469aed47d19e7908d19bd194493aThomas Graf
357c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Grafint nl_str2msec(const char *str, uint64_t *result)
35844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
359c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf	uint64_t total = 0, l;
360c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf	int plen;
36144d362409d5469aed47d19e7908d19bd194493aThomas Graf	char *p;
36244d362409d5469aed47d19e7908d19bd194493aThomas Graf
363c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf	do {
364c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf		l = strtoul(str, &p, 0);
365c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf		if (p == str)
36600466b0f95af19623c6536edafca6904945ced83Thomas Graf			return -NLE_INVAL;
367c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf		else if (*p) {
368c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf			plen = strcspn(p, " \t");
369c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf
370c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf			if (!plen)
371c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf				total += l;
372c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf			else if (!strncasecmp(p, "sec", plen))
373c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf				total += (l * 1000);
374c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf			else if (!strncasecmp(p, "min", plen))
375c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf				total += (l * 1000*60);
376c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf			else if (!strncasecmp(p, "hour", plen))
377c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf				total += (l * 1000*60*60);
378c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf			else if (!strncasecmp(p, "day", plen))
379c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf				total += (l * 1000*60*60*24);
380c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf			else
381c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf				return -NLE_INVAL;
382c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf
383c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf			str = p + plen;
384c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf		} else
385c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf			total += l;
386c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf	} while (*str && *p);
387c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf
388c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf	*result = total;
38944d362409d5469aed47d19e7908d19bd194493aThomas Graf
390c48a17694b6719606fa76fdad8a5cef3289cb42cThomas Graf	return 0;
39144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
39244d362409d5469aed47d19e7908d19bd194493aThomas Graf
39344d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
39444d362409d5469aed47d19e7908d19bd194493aThomas Graf * Convert milliseconds to a character string
39544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg msec		number of milliseconds
39644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg buf		destination buffer
39744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg len		buffer length
39844d362409d5469aed47d19e7908d19bd194493aThomas Graf *
39944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Converts milliseconds to a character string split up in days, hours,
40044d362409d5469aed47d19e7908d19bd194493aThomas Graf * minutes, seconds, and milliseconds and stores it in the specified
40144d362409d5469aed47d19e7908d19bd194493aThomas Graf * destination buffer.
40244d362409d5469aed47d19e7908d19bd194493aThomas Graf *
40344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return The destination buffer.
40444d362409d5469aed47d19e7908d19bd194493aThomas Graf */
40544d362409d5469aed47d19e7908d19bd194493aThomas Grafchar * nl_msec2str(uint64_t msec, char *buf, size_t len)
40644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
40744d362409d5469aed47d19e7908d19bd194493aThomas Graf	int i, split[5];
40844d362409d5469aed47d19e7908d19bd194493aThomas Graf	char *units[] = {"d", "h", "m", "s", "msec"};
40944d362409d5469aed47d19e7908d19bd194493aThomas Graf
41044d362409d5469aed47d19e7908d19bd194493aThomas Graf#define _SPLIT(idx, unit) if ((split[idx] = msec / unit) > 0) msec %= unit
41144d362409d5469aed47d19e7908d19bd194493aThomas Graf	_SPLIT(0, 86400000);	/* days */
41244d362409d5469aed47d19e7908d19bd194493aThomas Graf	_SPLIT(1, 3600000);	/* hours */
41344d362409d5469aed47d19e7908d19bd194493aThomas Graf	_SPLIT(2, 60000);	/* minutes */
41444d362409d5469aed47d19e7908d19bd194493aThomas Graf	_SPLIT(3, 1000);	/* seconds */
41544d362409d5469aed47d19e7908d19bd194493aThomas Graf#undef  _SPLIT
41644d362409d5469aed47d19e7908d19bd194493aThomas Graf	split[4] = msec;
41744d362409d5469aed47d19e7908d19bd194493aThomas Graf
41844d362409d5469aed47d19e7908d19bd194493aThomas Graf	memset(buf, 0, len);
41944d362409d5469aed47d19e7908d19bd194493aThomas Graf
42044d362409d5469aed47d19e7908d19bd194493aThomas Graf	for (i = 0; i < ARRAY_SIZE(split); i++) {
42144d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (split[i] > 0) {
42244d362409d5469aed47d19e7908d19bd194493aThomas Graf			char t[64];
42344d362409d5469aed47d19e7908d19bd194493aThomas Graf			snprintf(t, sizeof(t), "%s%d%s",
42444d362409d5469aed47d19e7908d19bd194493aThomas Graf				 strlen(buf) ? " " : "", split[i], units[i]);
42544d362409d5469aed47d19e7908d19bd194493aThomas Graf			strncat(buf, t, len - strlen(buf) - 1);
42644d362409d5469aed47d19e7908d19bd194493aThomas Graf		}
42744d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
42844d362409d5469aed47d19e7908d19bd194493aThomas Graf
42944d362409d5469aed47d19e7908d19bd194493aThomas Graf	return buf;
43044d362409d5469aed47d19e7908d19bd194493aThomas Graf}
43144d362409d5469aed47d19e7908d19bd194493aThomas Graf
43244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
43344d362409d5469aed47d19e7908d19bd194493aThomas Graf
43444d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
4356782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf * @name Netlink Family Translations
4366782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf * @{
4376782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf */
4386782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf
4396782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Grafstatic struct trans_tbl nlfamilies[] = {
4406782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf	__ADD(NETLINK_ROUTE,route)
4416782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf	__ADD(NETLINK_USERSOCK,usersock)
4426782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf	__ADD(NETLINK_FIREWALL,firewall)
4436782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf	__ADD(NETLINK_INET_DIAG,inetdiag)
4446782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf	__ADD(NETLINK_NFLOG,nflog)
4456782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf	__ADD(NETLINK_XFRM,xfrm)
4466782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf	__ADD(NETLINK_SELINUX,selinux)
4476782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf	__ADD(NETLINK_ISCSI,iscsi)
4486782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf	__ADD(NETLINK_AUDIT,audit)
4496782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf	__ADD(NETLINK_FIB_LOOKUP,fib_lookup)
4506782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf	__ADD(NETLINK_CONNECTOR,connector)
4516782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf	__ADD(NETLINK_NETFILTER,netfilter)
4526782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf	__ADD(NETLINK_IP6_FW,ip6_fw)
4536782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf	__ADD(NETLINK_DNRTMSG,dnrtmsg)
4546782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf	__ADD(NETLINK_KOBJECT_UEVENT,kobject_uevent)
4556782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf	__ADD(NETLINK_GENERIC,generic)
4566782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf	__ADD(NETLINK_SCSITRANSPORT,scsitransport)
4576782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf	__ADD(NETLINK_ECRYPTFS,ecryptfs)
4586782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf};
4596782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf
4606782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Grafchar * nl_nlfamily2str(int family, char *buf, size_t size)
4616782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf{
4626782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf	return __type2str(family, buf, size, nlfamilies,
4636782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf			  ARRAY_SIZE(nlfamilies));
4646782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf}
4656782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf
4666782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Grafint nl_str2nlfamily(const char *name)
4676782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf{
4686782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf	return __str2type(name, nlfamilies, ARRAY_SIZE(nlfamilies));
4696782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf}
4706782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf
4716782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf/**
4726782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf * @}
4736782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf */
4746782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf
4756782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf/**
47644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Link Layer Protocol Translations
47744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
47844d362409d5469aed47d19e7908d19bd194493aThomas Graf */
47944d362409d5469aed47d19e7908d19bd194493aThomas Graf
48044d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct trans_tbl llprotos[] = {
48144d362409d5469aed47d19e7908d19bd194493aThomas Graf	{0, "generic"},
48244d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_ETHER,ether)
48344d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_EETHER,eether)
48444d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_AX25,ax25)
48544d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_PRONET,pronet)
48644d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_CHAOS,chaos)
48744d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_IEEE802,ieee802)
48844d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_ARCNET,arcnet)
48944d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_APPLETLK,atalk)
49044d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_DLCI,dlci)
49144d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_ATM,atm)
49244d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_METRICOM,metricom)
49344d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_IEEE1394,ieee1394)
49444d362409d5469aed47d19e7908d19bd194493aThomas Graf#ifdef ARPHRD_EUI64
49544d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_EUI64,eui64)
49644d362409d5469aed47d19e7908d19bd194493aThomas Graf#endif
49744d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_INFINIBAND,infiniband)
49844d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_SLIP,slip)
49944d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_CSLIP,cslip)
50044d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_SLIP6,slip6)
50144d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_CSLIP6,cslip6)
50244d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_RSRVD,rsrvd)
50344d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_ADAPT,adapt)
50444d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_ROSE,rose)
50544d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_X25,x25)
50644d362409d5469aed47d19e7908d19bd194493aThomas Graf#ifdef ARPHRD_HWX25
50744d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_HWX25,hwx25)
50844d362409d5469aed47d19e7908d19bd194493aThomas Graf#endif
50944d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_PPP,ppp)
51044d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_HDLC,hdlc)
51144d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_LAPB,lapb)
51244d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_DDCMP,ddcmp)
51344d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_RAWHDLC,rawhdlc)
51444d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_TUNNEL,ipip)
51544d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_TUNNEL6,tunnel6)
51644d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_FRAD,frad)
51744d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_SKIP,skip)
51844d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_LOOPBACK,loopback)
51944d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_LOCALTLK,localtlk)
52044d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_FDDI,fddi)
52144d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_BIF,bif)
52244d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_SIT,sit)
52344d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_IPDDP,ip/ddp)
52444d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_IPGRE,gre)
52544d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_PIMREG,pimreg)
52644d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_HIPPI,hippi)
52744d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_ASH,ash)
52844d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_ECONET,econet)
52944d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_IRDA,irda)
53044d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_FCPP,fcpp)
53144d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_FCAL,fcal)
53244d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_FCPL,fcpl)
53344d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_FCFABRIC,fcfb_0)
53444d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_FCFABRIC+1,fcfb_1)
53544d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_FCFABRIC+2,fcfb_2)
53644d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_FCFABRIC+3,fcfb_3)
53744d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_FCFABRIC+4,fcfb_4)
53844d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_FCFABRIC+5,fcfb_5)
53944d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_FCFABRIC+6,fcfb_6)
54044d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_FCFABRIC+7,fcfb_7)
54144d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_FCFABRIC+8,fcfb_8)
54244d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_FCFABRIC+9,fcfb_9)
54344d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_FCFABRIC+10,fcfb_10)
54444d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_FCFABRIC+11,fcfb_11)
54544d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_FCFABRIC+12,fcfb_12)
54644d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_IEEE802_TR,tr)
54744d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_IEEE80211,ieee802.11)
54844d362409d5469aed47d19e7908d19bd194493aThomas Graf#ifdef ARPHRD_IEEE80211_PRISM
54944d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_IEEE80211_PRISM, ieee802.11_prism)
55044d362409d5469aed47d19e7908d19bd194493aThomas Graf#endif
55144d362409d5469aed47d19e7908d19bd194493aThomas Graf#ifdef ARPHRD_VOID
55244d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ARPHRD_VOID,void)
55344d362409d5469aed47d19e7908d19bd194493aThomas Graf#endif
55444d362409d5469aed47d19e7908d19bd194493aThomas Graf};
55544d362409d5469aed47d19e7908d19bd194493aThomas Graf
55644d362409d5469aed47d19e7908d19bd194493aThomas Grafchar * nl_llproto2str(int llproto, char *buf, size_t len)
55744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
55844d362409d5469aed47d19e7908d19bd194493aThomas Graf	return __type2str(llproto, buf, len, llprotos, ARRAY_SIZE(llprotos));
55944d362409d5469aed47d19e7908d19bd194493aThomas Graf}
56044d362409d5469aed47d19e7908d19bd194493aThomas Graf
56144d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_str2llproto(const char *name)
56244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
56344d362409d5469aed47d19e7908d19bd194493aThomas Graf	return __str2type(name, llprotos, ARRAY_SIZE(llprotos));
56444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
56544d362409d5469aed47d19e7908d19bd194493aThomas Graf
56644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
56744d362409d5469aed47d19e7908d19bd194493aThomas Graf
56844d362409d5469aed47d19e7908d19bd194493aThomas Graf
56944d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
57044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Ethernet Protocol Translations
57144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
57244d362409d5469aed47d19e7908d19bd194493aThomas Graf */
57344d362409d5469aed47d19e7908d19bd194493aThomas Graf
57444d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct trans_tbl ether_protos[] = {
57544d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_LOOP,loop)
57644d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_PUP,pup)
57744d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_PUPAT,pupat)
57844d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_IP,ip)
57944d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_X25,x25)
58044d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_ARP,arp)
58144d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_BPQ,bpq)
58244d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_IEEEPUP,ieeepup)
58344d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_IEEEPUPAT,ieeepupat)
58444d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_DEC,dec)
58544d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_DNA_DL,dna_dl)
58644d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_DNA_RC,dna_rc)
58744d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_DNA_RT,dna_rt)
58844d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_LAT,lat)
58944d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_DIAG,diag)
59044d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_CUST,cust)
59144d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_SCA,sca)
59244d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_RARP,rarp)
59344d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_ATALK,atalk)
59444d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_AARP,aarp)
59544d362409d5469aed47d19e7908d19bd194493aThomas Graf#ifdef ETH_P_8021Q
59644d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_8021Q,802.1q)
59744d362409d5469aed47d19e7908d19bd194493aThomas Graf#endif
59844d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_IPX,ipx)
59944d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_IPV6,ipv6)
60044d362409d5469aed47d19e7908d19bd194493aThomas Graf#ifdef ETH_P_WCCP
60144d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_WCCP,wccp)
60244d362409d5469aed47d19e7908d19bd194493aThomas Graf#endif
60344d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_PPP_DISC,ppp_disc)
60444d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_PPP_SES,ppp_ses)
60544d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_MPLS_UC,mpls_uc)
60644d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_MPLS_MC,mpls_mc)
60744d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_ATMMPOA,atmmpoa)
60844d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_ATMFATE,atmfate)
60944d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_EDP2,edp2)
61044d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_802_3,802.3)
61144d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_AX25,ax25)
61244d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_ALL,all)
61344d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_802_2,802.2)
61444d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_SNAP,snap)
61544d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_DDCMP,ddcmp)
61644d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_WAN_PPP,wan_ppp)
61744d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_PPP_MP,ppp_mp)
61844d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_LOCALTALK,localtalk)
61944d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_PPPTALK,ppptalk)
62044d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_TR_802_2,tr_802.2)
62144d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_MOBITEX,mobitex)
62244d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_CONTROL,control)
62344d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_IRDA,irda)
62444d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_ECONET,econet)
62544d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(ETH_P_HDLC,hdlc)
62644d362409d5469aed47d19e7908d19bd194493aThomas Graf};
62744d362409d5469aed47d19e7908d19bd194493aThomas Graf
62844d362409d5469aed47d19e7908d19bd194493aThomas Grafchar *nl_ether_proto2str(int eproto, char *buf, size_t len)
62944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
63044d362409d5469aed47d19e7908d19bd194493aThomas Graf	return __type2str(eproto, buf, len, ether_protos,
63144d362409d5469aed47d19e7908d19bd194493aThomas Graf			    ARRAY_SIZE(ether_protos));
63244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
63344d362409d5469aed47d19e7908d19bd194493aThomas Graf
63444d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_str2ether_proto(const char *name)
63544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
63644d362409d5469aed47d19e7908d19bd194493aThomas Graf	return __str2type(name, ether_protos, ARRAY_SIZE(ether_protos));
63744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
63844d362409d5469aed47d19e7908d19bd194493aThomas Graf
63944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
64044d362409d5469aed47d19e7908d19bd194493aThomas Graf
64144d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
64244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name IP Protocol Translations
64344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
64444d362409d5469aed47d19e7908d19bd194493aThomas Graf */
64544d362409d5469aed47d19e7908d19bd194493aThomas Graf
64644d362409d5469aed47d19e7908d19bd194493aThomas Grafchar *nl_ip_proto2str(int proto, char *buf, size_t len)
64744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
64844d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct protoent *p = getprotobynumber(proto);
64944d362409d5469aed47d19e7908d19bd194493aThomas Graf
65044d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (p) {
65144d362409d5469aed47d19e7908d19bd194493aThomas Graf		snprintf(buf, len, "%s", p->p_name);
65244d362409d5469aed47d19e7908d19bd194493aThomas Graf		return buf;
65344d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
65444d362409d5469aed47d19e7908d19bd194493aThomas Graf
65544d362409d5469aed47d19e7908d19bd194493aThomas Graf	snprintf(buf, len, "0x%x", proto);
65644d362409d5469aed47d19e7908d19bd194493aThomas Graf	return buf;
65744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
65844d362409d5469aed47d19e7908d19bd194493aThomas Graf
65944d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_str2ip_proto(const char *name)
66044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
66144d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct protoent *p = getprotobyname(name);
66244d362409d5469aed47d19e7908d19bd194493aThomas Graf	unsigned long l;
66344d362409d5469aed47d19e7908d19bd194493aThomas Graf	char *end;
66444d362409d5469aed47d19e7908d19bd194493aThomas Graf
66544d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (p)
66644d362409d5469aed47d19e7908d19bd194493aThomas Graf		return p->p_proto;
66744d362409d5469aed47d19e7908d19bd194493aThomas Graf
66844d362409d5469aed47d19e7908d19bd194493aThomas Graf	l = strtoul(name, &end, 0);
66944d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (l == ULONG_MAX || *end != '\0')
67000466b0f95af19623c6536edafca6904945ced83Thomas Graf		return -NLE_OBJ_NOTFOUND;
67144d362409d5469aed47d19e7908d19bd194493aThomas Graf
67244d362409d5469aed47d19e7908d19bd194493aThomas Graf	return (int) l;
67344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
67444d362409d5469aed47d19e7908d19bd194493aThomas Graf
67544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
67644d362409d5469aed47d19e7908d19bd194493aThomas Graf
677508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf/**
678508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf * @name Dumping Helpers
679508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf * @{
680508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf */
681508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf
682508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf/**
683508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf * Handle a new line while dumping
684508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf * @arg params		Dumping parameters
685508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf *
686508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf * This function must be called before dumping any onto a
687508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf * new line. It will ensure proper prefixing as specified
688508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf * by the dumping parameters.
689508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf *
690508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf * @note This function will NOT dump any newlines itself
691508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf */
692662887c052f0fcd98287e2a7fa5843a4f66ca256Thomas Grafvoid nl_new_line(struct nl_dump_params *params)
693508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf{
694662887c052f0fcd98287e2a7fa5843a4f66ca256Thomas Graf	params->dp_line++;
695662887c052f0fcd98287e2a7fa5843a4f66ca256Thomas Graf
696508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf	if (params->dp_prefix) {
697508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf		int i;
698508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf		for (i = 0; i < params->dp_prefix; i++) {
699508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf			if (params->dp_fd)
700508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf				fprintf(params->dp_fd, " ");
701508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf			else if (params->dp_buf)
702508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf				strncat(params->dp_buf, " ",
703508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf					params->dp_buflen -
704508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf					sizeof(params->dp_buf) - 1);
705508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf		}
706508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf	}
707508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf
708508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf	if (params->dp_nl_cb)
709662887c052f0fcd98287e2a7fa5843a4f66ca256Thomas Graf		params->dp_nl_cb(params, params->dp_line);
710508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf}
711508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf
7128cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Grafstatic void dump_one(struct nl_dump_params *parms, const char *fmt,
7138cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		     va_list args)
7148cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf{
7158cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	if (parms->dp_fd)
7168cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		vfprintf(parms->dp_fd, fmt, args);
7178cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	else if (parms->dp_buf || parms->dp_cb) {
7188cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		char *buf = NULL;
7198cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		vasprintf(&buf, fmt, args);
7208cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		if (parms->dp_cb)
7218cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf			parms->dp_cb(parms, buf);
7228cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		else
7238cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf			strncat(parms->dp_buf, buf,
7248cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf			        parms->dp_buflen - strlen(parms->dp_buf) - 1);
7258cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		free(buf);
7268cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	}
7278cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf}
7288cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
7298cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
730508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf/**
731508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf * Dump a formatted character string
732508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf * @arg params		Dumping parameters
733508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf * @arg fmt		printf style formatting string
734508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf * @arg ...		Arguments to formatting string
735508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf *
736508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf * Dumps a printf style formatting string to the output device
737508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf * as specified by the dumping parameters.
738508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf */
739508685c269275cb7ba3471c75abc689b4e3839b1Thomas Grafvoid nl_dump(struct nl_dump_params *params, const char *fmt, ...)
740508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf{
741508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf	va_list args;
742508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf
743508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf	va_start(args, fmt);
7448cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	dump_one(params, fmt, args);
745508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf	va_end(args);
746508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf}
747508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf
748662887c052f0fcd98287e2a7fa5843a4f66ca256Thomas Grafvoid nl_dump_line(struct nl_dump_params *parms, const char *fmt, ...)
749662887c052f0fcd98287e2a7fa5843a4f66ca256Thomas Graf{
750662887c052f0fcd98287e2a7fa5843a4f66ca256Thomas Graf	va_list args;
751662887c052f0fcd98287e2a7fa5843a4f66ca256Thomas Graf
752662887c052f0fcd98287e2a7fa5843a4f66ca256Thomas Graf	nl_new_line(parms);
753662887c052f0fcd98287e2a7fa5843a4f66ca256Thomas Graf
754662887c052f0fcd98287e2a7fa5843a4f66ca256Thomas Graf	va_start(args, fmt);
7558cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	dump_one(parms, fmt, args);
756662887c052f0fcd98287e2a7fa5843a4f66ca256Thomas Graf	va_end(args);
757662887c052f0fcd98287e2a7fa5843a4f66ca256Thomas Graf}
758662887c052f0fcd98287e2a7fa5843a4f66ca256Thomas Graf
759662887c052f0fcd98287e2a7fa5843a4f66ca256Thomas Graf
760508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf/** @} */
761508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf
7628cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf/** @cond SKIP */
7638cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
7648cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Grafint __trans_list_add(int i, const char *a, struct nl_list_head *head)
7658cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf{
7668cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	struct trans_list *tl;
7678cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
7688cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	tl = calloc(1, sizeof(*tl));
7698cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	if (!tl)
7708cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		return -NLE_NOMEM;
7718cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
7728cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	tl->i = i;
7738cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	tl->a = strdup(a);
7748cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
7758cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	nl_list_add_tail(&tl->list, head);
7768cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
7778cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	return 0;
7788cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf}
7798cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
7808cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Grafvoid __trans_list_clear(struct nl_list_head *head)
7818cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf{
7828cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	struct trans_list *tl, *next;
7838cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
7848cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	nl_list_for_each_entry_safe(tl, next, head, list) {
7858cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		free(tl->a);
7868cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		free(tl);
7878cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	}
7888cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf}
7898cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
7908cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Grafchar *__type2str(int type, char *buf, size_t len, struct trans_tbl *tbl,
7918cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		 size_t tbl_len)
7928cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf{
7938cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	int i;
7948cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	for (i = 0; i < tbl_len; i++) {
7958cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		if (tbl[i].i == type) {
7968cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf			snprintf(buf, len, "%s", tbl[i].a);
7978cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf			return buf;
7988cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		}
7998cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	}
8008cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
8018cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	snprintf(buf, len, "0x%x", type);
8028cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	return buf;
8038cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf}
8048cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
8058cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Grafchar *__list_type2str(int type, char *buf, size_t len,
8068cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		      struct nl_list_head *head)
8078cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf{
8088cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	struct trans_list *tl;
8098cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
8108cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	nl_list_for_each_entry(tl, head, list) {
8118cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		if (tl->i == type) {
8128cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf			snprintf(buf, len, "%s", tl->a);
8138cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf			return buf;
8148cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		}
8158cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	}
8168cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
8178cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	snprintf(buf, len, "0x%x", type);
8188cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	return buf;
8198cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf}
8208cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
8218cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Grafchar *__flags2str(int flags, char *buf, size_t len,
8228cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		  struct trans_tbl *tbl, size_t tbl_len)
8238cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf{
8248cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	int i;
8258cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	int tmp = flags;
8268cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
8278cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	memset(buf, 0, len);
8288cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
8298cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	for (i = 0; i < tbl_len; i++) {
8308cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		if (tbl[i].i & tmp) {
8318cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf			tmp &= ~tbl[i].i;
8328cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf			strncat(buf, tbl[i].a, len - strlen(buf) - 1);
8338cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf			if ((tmp & flags))
8348cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf				strncat(buf, ",", len - strlen(buf) - 1);
8358cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		}
8368cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	}
8378cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
8388cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	return buf;
8398cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf}
8408cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
8418cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Grafint __str2type(const char *buf, struct trans_tbl *tbl, size_t tbl_len)
8428cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf{
8438cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	unsigned long l;
8448cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	char *end;
8458cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	int i;
8468cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
8478cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	if (*buf == '\0')
84800466b0f95af19623c6536edafca6904945ced83Thomas Graf		return -NLE_INVAL;
8498cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
8508cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	for (i = 0; i < tbl_len; i++)
8518cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		if (!strcasecmp(tbl[i].a, buf))
8528cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf			return tbl[i].i;
8538cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
8548cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	l = strtoul(buf, &end, 0);
8558cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	if (l == ULONG_MAX || *end != '\0')
85600466b0f95af19623c6536edafca6904945ced83Thomas Graf		return -NLE_OBJ_NOTFOUND;
8578cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
8588cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	return (int) l;
8598cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf}
8608cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
8618cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Grafint __list_str2type(const char *buf, struct nl_list_head *head)
8628cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf{
8638cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	struct trans_list *tl;
8648cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	unsigned long l;
8658cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	char *end;
8668cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
8678cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	if (*buf == '\0')
86800466b0f95af19623c6536edafca6904945ced83Thomas Graf		return -NLE_INVAL;
8698cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
8708cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	nl_list_for_each_entry(tl, head, list) {
8718cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		if (!strcasecmp(tl->a, buf))
8728cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf			return tl->i;
8738cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	}
8748cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
8758cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	l = strtoul(buf, &end, 0);
8768cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	if (l == ULONG_MAX || *end != '\0')
87700466b0f95af19623c6536edafca6904945ced83Thomas Graf		return -NLE_OBJ_NOTFOUND;
8788cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
8798cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	return (int) l;
8808cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf}
8818cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
8828cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Grafint __str2flags(const char *buf, struct trans_tbl *tbl, size_t tbl_len)
8838cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf{
8848cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	int i, flags = 0, len;
8858cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	char *p = (char *) buf, *t;
8868cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
8878cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	for (;;) {
8888cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		if (*p == ' ')
8898cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf			p++;
8908cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
8918cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		t = strchr(p, ',');
8928cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		len = t ? t - p : strlen(p);
8938cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		for (i = 0; i < tbl_len; i++)
8948cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf			if (!strncasecmp(tbl[i].a, p, len))
8958cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf				flags |= tbl[i].i;
8968cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
8978cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		if (!t)
8988cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf			return flags;
8998cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
9008cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		p = ++t;
9018cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	}
9028cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
9038cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	return 0;
9048cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf}
9058cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
9068cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Grafvoid dump_from_ops(struct nl_object *obj, struct nl_dump_params *params)
9078cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf{
9088cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	int type = params->dp_type;
9098cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
9108cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	if (type < 0 || type > NL_DUMP_MAX)
9118cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		BUG();
9128cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
9138cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	params->dp_line = 0;
9148cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
9158cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	if (params->dp_dump_msgtype) {
9168cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf#if 0
9178cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		/* XXX */
9188cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		char buf[64];
9198cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
9208cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		dp_dump_line(params, 0, "%s ",
9218cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf			     nl_cache_mngt_type2name(obj->ce_ops,
9228cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf			     			     obj->ce_ops->co_protocol,
9238cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf						     obj->ce_msgtype,
9248cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf						     buf, sizeof(buf)));
9258cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf#endif
9268cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		params->dp_pre_dump = 1;
927d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	}
9288cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
9298cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf	if (obj->ce_ops->oo_dump[type])
9308cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf		obj->ce_ops->oo_dump[type](obj, params);
9318cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf}
9328cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
9338cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf/** @endcond */
9348cd39c9f4ca8731279ea6467a9d489902fcae7f9Thomas Graf
93544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
936