netlink-local.h revision 3040a1d6254465bed9e44e4d1bf279c2c50cd16a
144d362409d5469aed47d19e7908d19bd194493aThomas Graf/*
244d362409d5469aed47d19e7908d19bd194493aThomas Graf * netlink-local.h		Local Netlink Interface
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 *
944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
1044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1144d362409d5469aed47d19e7908d19bd194493aThomas Graf
1244d362409d5469aed47d19e7908d19bd194493aThomas Graf#ifndef NETLINK_LOCAL_H_
1344d362409d5469aed47d19e7908d19bd194493aThomas Graf#define NETLINK_LOCAL_H_
1444d362409d5469aed47d19e7908d19bd194493aThomas Graf
1544d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <stdio.h>
1644d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <errno.h>
1744d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <stdlib.h>
1844d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <string.h>
1944d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <unistd.h>
2044d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <fcntl.h>
2144d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <math.h>
2244d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <time.h>
2344d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <stdarg.h>
2444d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <ctype.h>
2544d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <sys/types.h>
2644d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <sys/socket.h>
2744d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <inttypes.h>
2844d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <assert.h>
2944d362409d5469aed47d19e7908d19bd194493aThomas Graf
3044d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <arpa/inet.h>
3144d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netdb.h>
3244d362409d5469aed47d19e7908d19bd194493aThomas Graf
3344d362409d5469aed47d19e7908d19bd194493aThomas Graf#ifndef SOL_NETLINK
3444d362409d5469aed47d19e7908d19bd194493aThomas Graf#define SOL_NETLINK 270
3544d362409d5469aed47d19e7908d19bd194493aThomas Graf#endif
3644d362409d5469aed47d19e7908d19bd194493aThomas Graf
3744d362409d5469aed47d19e7908d19bd194493aThomas Graftypedef uint8_t		__u8;
3844d362409d5469aed47d19e7908d19bd194493aThomas Graftypedef uint16_t	__u16;
3944d362409d5469aed47d19e7908d19bd194493aThomas Graftypedef int16_t		__s16;
4044d362409d5469aed47d19e7908d19bd194493aThomas Graftypedef uint32_t	__u32;
4144d362409d5469aed47d19e7908d19bd194493aThomas Graftypedef int32_t		__s32;
4244d362409d5469aed47d19e7908d19bd194493aThomas Graftypedef uint64_t	__u64;
4344d362409d5469aed47d19e7908d19bd194493aThomas Graf
4444d362409d5469aed47d19e7908d19bd194493aThomas Graf/* local header copies */
4544d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <linux/if.h>
4644d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <linux/if_arp.h>
4744d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <linux/if_ether.h>
4844d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <linux/pkt_sched.h>
4944d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <linux/pkt_cls.h>
5044d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <linux/gen_stats.h>
5144d362409d5469aed47d19e7908d19bd194493aThomas Graf
5244d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netlink.h>
5344d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/handlers.h>
5444d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/cache.h>
5544d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/tc.h>
56508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf#include <netlink/object-api.h>
573040a1d6254465bed9e44e4d1bf279c2c50cd16aThomas Graf#include <netlink/cache-api.h>
5844d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink-types.h>
5944d362409d5469aed47d19e7908d19bd194493aThomas Graf
6044d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct trans_tbl {
6144d362409d5469aed47d19e7908d19bd194493aThomas Graf	int i;
6244d362409d5469aed47d19e7908d19bd194493aThomas Graf	const char *a;
6344d362409d5469aed47d19e7908d19bd194493aThomas Graf};
6444d362409d5469aed47d19e7908d19bd194493aThomas Graf
6544d362409d5469aed47d19e7908d19bd194493aThomas Graf#define __ADD(id, name) { .i = id, .a = #name },
6644d362409d5469aed47d19e7908d19bd194493aThomas Graf
6744d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct trans_list {
6844d362409d5469aed47d19e7908d19bd194493aThomas Graf	int i;
6944d362409d5469aed47d19e7908d19bd194493aThomas Graf	char *a;
7044d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nl_list_head list;
7144d362409d5469aed47d19e7908d19bd194493aThomas Graf};
7244d362409d5469aed47d19e7908d19bd194493aThomas Graf
7344d362409d5469aed47d19e7908d19bd194493aThomas Graf#define NL_DEBUG	1
7444d362409d5469aed47d19e7908d19bd194493aThomas Graf
7544d362409d5469aed47d19e7908d19bd194493aThomas Graf#define NL_DBG(LVL,FMT,ARG...) \
7644d362409d5469aed47d19e7908d19bd194493aThomas Graf	do {	\
7744d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (LVL <= nl_debug) \
7844d362409d5469aed47d19e7908d19bd194493aThomas Graf			fprintf(stderr, "DBG<" #LVL ">: " FMT, ##ARG); \
7944d362409d5469aed47d19e7908d19bd194493aThomas Graf	} while (0)
8044d362409d5469aed47d19e7908d19bd194493aThomas Graf
8144d362409d5469aed47d19e7908d19bd194493aThomas Graf#define BUG()                            \
8244d362409d5469aed47d19e7908d19bd194493aThomas Graf	do {                                 \
8344d362409d5469aed47d19e7908d19bd194493aThomas Graf		fprintf(stderr, "BUG: %s:%d\n",  \
8444d362409d5469aed47d19e7908d19bd194493aThomas Graf			__FILE__, __LINE__);         \
8544d362409d5469aed47d19e7908d19bd194493aThomas Graf		assert(0);	\
8644d362409d5469aed47d19e7908d19bd194493aThomas Graf	} while (0)
8744d362409d5469aed47d19e7908d19bd194493aThomas Graf
8844d362409d5469aed47d19e7908d19bd194493aThomas Graf#define RET_ERR(R, E)                    \
8944d362409d5469aed47d19e7908d19bd194493aThomas Graf    do {                                 \
9044d362409d5469aed47d19e7908d19bd194493aThomas Graf		errno = E;                       \
9144d362409d5469aed47d19e7908d19bd194493aThomas Graf		return -R;                       \
9244d362409d5469aed47d19e7908d19bd194493aThomas Graf	} while (0)
9344d362409d5469aed47d19e7908d19bd194493aThomas Graf
9444d362409d5469aed47d19e7908d19bd194493aThomas Grafextern int __nl_error(int, const char *, unsigned int,
9544d362409d5469aed47d19e7908d19bd194493aThomas Graf	const char *, const char *, ...);
9644d362409d5469aed47d19e7908d19bd194493aThomas Graf
9744d362409d5469aed47d19e7908d19bd194493aThomas Grafextern int __nl_read_num_str_file(const char *path,
9844d362409d5469aed47d19e7908d19bd194493aThomas Graf				  int (*cb)(long, const char *));
9944d362409d5469aed47d19e7908d19bd194493aThomas Graf
10044d362409d5469aed47d19e7908d19bd194493aThomas Graf#ifdef NL_ERROR_ASSERT
10144d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <assert.h>
10244d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline int __assert_error(const char *file, int line, char *func,
10344d362409d5469aed47d19e7908d19bd194493aThomas Graf	const char *fmt, ...)
10444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
10544d362409d5469aed47d19e7908d19bd194493aThomas Graf	va_list args;
10644d362409d5469aed47d19e7908d19bd194493aThomas Graf	fprintf(stderr, "%s:%d:%s: ", file, line, func);
10744d362409d5469aed47d19e7908d19bd194493aThomas Graf	va_start(args, fmt);
10844d362409d5469aed47d19e7908d19bd194493aThomas Graf	vfprintf(stderr, fmt, args);
10944d362409d5469aed47d19e7908d19bd194493aThomas Graf	va_end(args);
11044d362409d5469aed47d19e7908d19bd194493aThomas Graf	fprintf(stderr, "\n");
11144d362409d5469aed47d19e7908d19bd194493aThomas Graf	assert(0);
11244d362409d5469aed47d19e7908d19bd194493aThomas Graf	return 0;
11344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
11444d362409d5469aed47d19e7908d19bd194493aThomas Graf#define nl_error(E, FMT,ARG...) \
11544d362409d5469aed47d19e7908d19bd194493aThomas Graf	__assert_error(__FILE__, __LINE__, __FUNCTION__, FMT, ##ARG)
11644d362409d5469aed47d19e7908d19bd194493aThomas Graf
11744d362409d5469aed47d19e7908d19bd194493aThomas Graf#else
11844d362409d5469aed47d19e7908d19bd194493aThomas Graf#define nl_error(E, FMT,ARG...) \
11944d362409d5469aed47d19e7908d19bd194493aThomas Graf	__nl_error(E, __FILE__, __LINE__, __FUNCTION__, FMT, ##ARG)
12044d362409d5469aed47d19e7908d19bd194493aThomas Graf
12144d362409d5469aed47d19e7908d19bd194493aThomas Graf#endif
12244d362409d5469aed47d19e7908d19bd194493aThomas Graf
12344d362409d5469aed47d19e7908d19bd194493aThomas Graf#define nl_errno(E)	nl_error(E, NULL)
12444d362409d5469aed47d19e7908d19bd194493aThomas Graf
125508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf/* backwards compat */
126508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf#define dp_new_line(params, line)	nl_new_line(params, line)
127508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf#define dp_dump(params, fmt, arg...)	nl_dump(params, fmt, ##arg)
128508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf
12944d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline int __trans_list_add(int i, const char *a,
13044d362409d5469aed47d19e7908d19bd194493aThomas Graf				   struct nl_list_head *head)
13144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
13244d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct trans_list *tl;
13344d362409d5469aed47d19e7908d19bd194493aThomas Graf
13444d362409d5469aed47d19e7908d19bd194493aThomas Graf	tl = calloc(1, sizeof(*tl));
13544d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (!tl)
13644d362409d5469aed47d19e7908d19bd194493aThomas Graf		return nl_errno(ENOMEM);
13744d362409d5469aed47d19e7908d19bd194493aThomas Graf
13844d362409d5469aed47d19e7908d19bd194493aThomas Graf	tl->i = i;
13944d362409d5469aed47d19e7908d19bd194493aThomas Graf	tl->a = strdup(a);
14044d362409d5469aed47d19e7908d19bd194493aThomas Graf
14144d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_list_add_tail(&tl->list, head);
14244d362409d5469aed47d19e7908d19bd194493aThomas Graf
14344d362409d5469aed47d19e7908d19bd194493aThomas Graf	return 0;
14444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
14544d362409d5469aed47d19e7908d19bd194493aThomas Graf
14644d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline void __trans_list_clear(struct nl_list_head *head)
14744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
14844d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct trans_list *tl, *next;
14944d362409d5469aed47d19e7908d19bd194493aThomas Graf
15044d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_list_for_each_entry_safe(tl, next, head, list) {
15144d362409d5469aed47d19e7908d19bd194493aThomas Graf		free(tl->a);
15244d362409d5469aed47d19e7908d19bd194493aThomas Graf		free(tl);
15344d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
15444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
15544d362409d5469aed47d19e7908d19bd194493aThomas Graf
15644d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline char *__type2str(int type, char *buf, size_t len,
15744d362409d5469aed47d19e7908d19bd194493aThomas Graf			       struct trans_tbl *tbl, size_t tbl_len)
15844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
15944d362409d5469aed47d19e7908d19bd194493aThomas Graf	int i;
16044d362409d5469aed47d19e7908d19bd194493aThomas Graf	for (i = 0; i < tbl_len; i++) {
16144d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (tbl[i].i == type) {
16244d362409d5469aed47d19e7908d19bd194493aThomas Graf			snprintf(buf, len, "%s", tbl[i].a);
16344d362409d5469aed47d19e7908d19bd194493aThomas Graf			return buf;
16444d362409d5469aed47d19e7908d19bd194493aThomas Graf		}
16544d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
16644d362409d5469aed47d19e7908d19bd194493aThomas Graf
16744d362409d5469aed47d19e7908d19bd194493aThomas Graf	snprintf(buf, len, "0x%x", type);
16844d362409d5469aed47d19e7908d19bd194493aThomas Graf	return buf;
16944d362409d5469aed47d19e7908d19bd194493aThomas Graf}
17044d362409d5469aed47d19e7908d19bd194493aThomas Graf
17144d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline char *__list_type2str(int type, char *buf, size_t len,
17244d362409d5469aed47d19e7908d19bd194493aThomas Graf				    struct nl_list_head *head)
17344d362409d5469aed47d19e7908d19bd194493aThomas Graf{
17444d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct trans_list *tl;
17544d362409d5469aed47d19e7908d19bd194493aThomas Graf
17644d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_list_for_each_entry(tl, head, list) {
17744d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (tl->i == type) {
17844d362409d5469aed47d19e7908d19bd194493aThomas Graf			snprintf(buf, len, "%s", tl->a);
17944d362409d5469aed47d19e7908d19bd194493aThomas Graf			return buf;
18044d362409d5469aed47d19e7908d19bd194493aThomas Graf		}
18144d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
18244d362409d5469aed47d19e7908d19bd194493aThomas Graf
18344d362409d5469aed47d19e7908d19bd194493aThomas Graf	snprintf(buf, len, "0x%x", type);
18444d362409d5469aed47d19e7908d19bd194493aThomas Graf	return buf;
18544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
18644d362409d5469aed47d19e7908d19bd194493aThomas Graf
18744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline char *__flags2str(int flags, char *buf, size_t len,
18844d362409d5469aed47d19e7908d19bd194493aThomas Graf				struct trans_tbl *tbl, size_t tbl_len)
18944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
19044d362409d5469aed47d19e7908d19bd194493aThomas Graf	int i;
19144d362409d5469aed47d19e7908d19bd194493aThomas Graf	int tmp = flags;
19244d362409d5469aed47d19e7908d19bd194493aThomas Graf
19344d362409d5469aed47d19e7908d19bd194493aThomas Graf	memset(buf, 0, len);
19444d362409d5469aed47d19e7908d19bd194493aThomas Graf
19544d362409d5469aed47d19e7908d19bd194493aThomas Graf	for (i = 0; i < tbl_len; i++) {
19644d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (tbl[i].i & tmp) {
19744d362409d5469aed47d19e7908d19bd194493aThomas Graf			tmp &= ~tbl[i].i;
19844d362409d5469aed47d19e7908d19bd194493aThomas Graf			strncat(buf, tbl[i].a, len - strlen(buf) - 1);
19944d362409d5469aed47d19e7908d19bd194493aThomas Graf			if ((tmp & flags))
20044d362409d5469aed47d19e7908d19bd194493aThomas Graf				strncat(buf, ",", len - strlen(buf) - 1);
20144d362409d5469aed47d19e7908d19bd194493aThomas Graf		}
20244d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
20344d362409d5469aed47d19e7908d19bd194493aThomas Graf
20444d362409d5469aed47d19e7908d19bd194493aThomas Graf	return buf;
20544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
20644d362409d5469aed47d19e7908d19bd194493aThomas Graf
20744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline int __str2type(const char *buf, struct trans_tbl *tbl,
20844d362409d5469aed47d19e7908d19bd194493aThomas Graf			     size_t tbl_len)
20944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
21044d362409d5469aed47d19e7908d19bd194493aThomas Graf	unsigned long l;
21144d362409d5469aed47d19e7908d19bd194493aThomas Graf	char *end;
21244d362409d5469aed47d19e7908d19bd194493aThomas Graf	int i;
21344d362409d5469aed47d19e7908d19bd194493aThomas Graf
21444d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (*buf == '\0')
21544d362409d5469aed47d19e7908d19bd194493aThomas Graf		return -1;
21644d362409d5469aed47d19e7908d19bd194493aThomas Graf
21744d362409d5469aed47d19e7908d19bd194493aThomas Graf	for (i = 0; i < tbl_len; i++)
21844d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (!strcasecmp(tbl[i].a, buf))
21944d362409d5469aed47d19e7908d19bd194493aThomas Graf			return tbl[i].i;
22044d362409d5469aed47d19e7908d19bd194493aThomas Graf
22144d362409d5469aed47d19e7908d19bd194493aThomas Graf	l = strtoul(buf, &end, 0);
22244d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (l == ULONG_MAX || *end != '\0')
22344d362409d5469aed47d19e7908d19bd194493aThomas Graf		return -1;
22444d362409d5469aed47d19e7908d19bd194493aThomas Graf
22544d362409d5469aed47d19e7908d19bd194493aThomas Graf	return (int) l;
22644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
22744d362409d5469aed47d19e7908d19bd194493aThomas Graf
22844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline int __list_str2type(const char *buf, struct nl_list_head *head)
22944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
23044d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct trans_list *tl;
23144d362409d5469aed47d19e7908d19bd194493aThomas Graf	unsigned long l;
23244d362409d5469aed47d19e7908d19bd194493aThomas Graf	char *end;
23344d362409d5469aed47d19e7908d19bd194493aThomas Graf
23444d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (*buf == '\0')
23544d362409d5469aed47d19e7908d19bd194493aThomas Graf		return -1;
23644d362409d5469aed47d19e7908d19bd194493aThomas Graf
23744d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_list_for_each_entry(tl, head, list) {
23844d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (!strcasecmp(tl->a, buf))
23944d362409d5469aed47d19e7908d19bd194493aThomas Graf			return tl->i;
24044d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
24144d362409d5469aed47d19e7908d19bd194493aThomas Graf
24244d362409d5469aed47d19e7908d19bd194493aThomas Graf	l = strtoul(buf, &end, 0);
24344d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (l == ULONG_MAX || *end != '\0')
24444d362409d5469aed47d19e7908d19bd194493aThomas Graf		return -1;
24544d362409d5469aed47d19e7908d19bd194493aThomas Graf
24644d362409d5469aed47d19e7908d19bd194493aThomas Graf	return (int) l;
24744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
24844d362409d5469aed47d19e7908d19bd194493aThomas Graf
24944d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline int __str2flags(const char *buf, struct trans_tbl *tbl,
25044d362409d5469aed47d19e7908d19bd194493aThomas Graf			      size_t tbl_len)
25144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
25244d362409d5469aed47d19e7908d19bd194493aThomas Graf	int i, flags = 0, len;
25344d362409d5469aed47d19e7908d19bd194493aThomas Graf	char *p = (char *) buf, *t;
25444d362409d5469aed47d19e7908d19bd194493aThomas Graf
25544d362409d5469aed47d19e7908d19bd194493aThomas Graf	for (;;) {
25644d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (*p == ' ')
25744d362409d5469aed47d19e7908d19bd194493aThomas Graf			p++;
25844d362409d5469aed47d19e7908d19bd194493aThomas Graf
25944d362409d5469aed47d19e7908d19bd194493aThomas Graf		t = strchr(p, ',');
26044d362409d5469aed47d19e7908d19bd194493aThomas Graf		len = t ? t - p : strlen(p);
26144d362409d5469aed47d19e7908d19bd194493aThomas Graf		for (i = 0; i < tbl_len; i++)
26244d362409d5469aed47d19e7908d19bd194493aThomas Graf			if (!strncasecmp(tbl[i].a, p, len))
26344d362409d5469aed47d19e7908d19bd194493aThomas Graf				flags |= tbl[i].i;
26444d362409d5469aed47d19e7908d19bd194493aThomas Graf
26544d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (!t)
26644d362409d5469aed47d19e7908d19bd194493aThomas Graf			return flags;
26744d362409d5469aed47d19e7908d19bd194493aThomas Graf
26844d362409d5469aed47d19e7908d19bd194493aThomas Graf		p = ++t;
26944d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
27044d362409d5469aed47d19e7908d19bd194493aThomas Graf
27144d362409d5469aed47d19e7908d19bd194493aThomas Graf	return 0;
27244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
27344d362409d5469aed47d19e7908d19bd194493aThomas Graf
27444d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline void __dp_dump(struct nl_dump_params *parms, const char *fmt,
27544d362409d5469aed47d19e7908d19bd194493aThomas Graf			     va_list args)
27644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
27744d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (parms->dp_fd)
27844d362409d5469aed47d19e7908d19bd194493aThomas Graf		vfprintf(parms->dp_fd, fmt, args);
27944d362409d5469aed47d19e7908d19bd194493aThomas Graf	else if (parms->dp_buf || parms->dp_cb) {
28044d362409d5469aed47d19e7908d19bd194493aThomas Graf		char *buf = NULL;
28144d362409d5469aed47d19e7908d19bd194493aThomas Graf		vasprintf(&buf, fmt, args);
28244d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (parms->dp_cb)
28344d362409d5469aed47d19e7908d19bd194493aThomas Graf			parms->dp_cb(parms, buf);
28444d362409d5469aed47d19e7908d19bd194493aThomas Graf		else
28544d362409d5469aed47d19e7908d19bd194493aThomas Graf			strncat(parms->dp_buf, buf,
28644d362409d5469aed47d19e7908d19bd194493aThomas Graf			        parms->dp_buflen - strlen(parms->dp_buf) - 1);
28744d362409d5469aed47d19e7908d19bd194493aThomas Graf		free(buf);
28844d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
28944d362409d5469aed47d19e7908d19bd194493aThomas Graf}
29044d362409d5469aed47d19e7908d19bd194493aThomas Graf
29144d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline void dp_dump_line(struct nl_dump_params *parms, int line,
29244d362409d5469aed47d19e7908d19bd194493aThomas Graf				const char *fmt, ...)
29344d362409d5469aed47d19e7908d19bd194493aThomas Graf{
29444d362409d5469aed47d19e7908d19bd194493aThomas Graf	va_list args;
29544d362409d5469aed47d19e7908d19bd194493aThomas Graf
296508685c269275cb7ba3471c75abc689b4e3839b1Thomas Graf	nl_new_line(parms, line);
29744d362409d5469aed47d19e7908d19bd194493aThomas Graf
29844d362409d5469aed47d19e7908d19bd194493aThomas Graf	va_start(args, fmt);
29944d362409d5469aed47d19e7908d19bd194493aThomas Graf	__dp_dump(parms, fmt, args);
30044d362409d5469aed47d19e7908d19bd194493aThomas Graf	va_end(args);
30144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
30244d362409d5469aed47d19e7908d19bd194493aThomas Graf
30344d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline void dump_from_ops(struct nl_object *obj,
30444d362409d5469aed47d19e7908d19bd194493aThomas Graf				 struct nl_dump_params *params)
30544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
30644d362409d5469aed47d19e7908d19bd194493aThomas Graf	int type = params->dp_type;
30744d362409d5469aed47d19e7908d19bd194493aThomas Graf
30844d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (type < 0 || type > NL_DUMP_MAX)
30944d362409d5469aed47d19e7908d19bd194493aThomas Graf		BUG();
31044d362409d5469aed47d19e7908d19bd194493aThomas Graf
31144d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (params->dp_dump_msgtype) {
31244d362409d5469aed47d19e7908d19bd194493aThomas Graf#if 0
31344d362409d5469aed47d19e7908d19bd194493aThomas Graf		/* XXX */
31444d362409d5469aed47d19e7908d19bd194493aThomas Graf		char buf[64];
31544d362409d5469aed47d19e7908d19bd194493aThomas Graf
31644d362409d5469aed47d19e7908d19bd194493aThomas Graf		dp_dump_line(params, 0, "%s ",
31744d362409d5469aed47d19e7908d19bd194493aThomas Graf			     nl_cache_mngt_type2name(obj->ce_ops,
31844d362409d5469aed47d19e7908d19bd194493aThomas Graf			     			     obj->ce_ops->co_protocol,
31944d362409d5469aed47d19e7908d19bd194493aThomas Graf						     obj->ce_msgtype,
32044d362409d5469aed47d19e7908d19bd194493aThomas Graf						     buf, sizeof(buf)));
32144d362409d5469aed47d19e7908d19bd194493aThomas Graf#endif
32244d362409d5469aed47d19e7908d19bd194493aThomas Graf		params->dp_pre_dump = 1;
32344d362409d5469aed47d19e7908d19bd194493aThomas Graf	} else
32444d362409d5469aed47d19e7908d19bd194493aThomas Graf		dp_new_line(params, 0);
32544d362409d5469aed47d19e7908d19bd194493aThomas Graf
32644d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (obj->ce_ops->oo_dump[type])
32744d362409d5469aed47d19e7908d19bd194493aThomas Graf		obj->ce_ops->oo_dump[type](obj, params);
32844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
32944d362409d5469aed47d19e7908d19bd194493aThomas Graf
33044d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline struct nl_cache *dp_cache(struct nl_object *obj)
33144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
33244d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (obj->ce_cache == NULL)
33344d362409d5469aed47d19e7908d19bd194493aThomas Graf		return nl_cache_mngt_require(obj->ce_ops->oo_name);
33444d362409d5469aed47d19e7908d19bd194493aThomas Graf
33544d362409d5469aed47d19e7908d19bd194493aThomas Graf	return obj->ce_cache;
33644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
33744d362409d5469aed47d19e7908d19bd194493aThomas Graf
33844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline int nl_cb_call(struct nl_cb *cb, int type, struct nl_msg *msg)
33944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
34044d362409d5469aed47d19e7908d19bd194493aThomas Graf	return cb->cb_set[type](msg, cb->cb_args[type]);
34144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
34244d362409d5469aed47d19e7908d19bd194493aThomas Graf
34344d362409d5469aed47d19e7908d19bd194493aThomas Graf#define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0]))
34444d362409d5469aed47d19e7908d19bd194493aThomas Graf#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
34544d362409d5469aed47d19e7908d19bd194493aThomas Graf
34644d362409d5469aed47d19e7908d19bd194493aThomas Graf#define __init __attribute__ ((constructor))
34744d362409d5469aed47d19e7908d19bd194493aThomas Graf#define __exit __attribute__ ((destructor))
34844d362409d5469aed47d19e7908d19bd194493aThomas Graf
34944d362409d5469aed47d19e7908d19bd194493aThomas Graf#define P_ACCEPT 0
35044d362409d5469aed47d19e7908d19bd194493aThomas Graf#define P_IGNORE 0
35144d362409d5469aed47d19e7908d19bd194493aThomas Graf
35244d362409d5469aed47d19e7908d19bd194493aThomas Graf#define min(x,y) ({ \
35344d362409d5469aed47d19e7908d19bd194493aThomas Graf	typeof(x) _x = (x);	\
35444d362409d5469aed47d19e7908d19bd194493aThomas Graf	typeof(y) _y = (y);	\
35544d362409d5469aed47d19e7908d19bd194493aThomas Graf	(void) (&_x == &_y);		\
35644d362409d5469aed47d19e7908d19bd194493aThomas Graf	_x < _y ? _x : _y; })
35744d362409d5469aed47d19e7908d19bd194493aThomas Graf
35844d362409d5469aed47d19e7908d19bd194493aThomas Graf#define max(x,y) ({ \
35944d362409d5469aed47d19e7908d19bd194493aThomas Graf	typeof(x) _x = (x);	\
36044d362409d5469aed47d19e7908d19bd194493aThomas Graf	typeof(y) _y = (y);	\
36144d362409d5469aed47d19e7908d19bd194493aThomas Graf	(void) (&_x == &_y);		\
36244d362409d5469aed47d19e7908d19bd194493aThomas Graf	_x > _y ? _x : _y; })
36344d362409d5469aed47d19e7908d19bd194493aThomas Graf
36444d362409d5469aed47d19e7908d19bd194493aThomas Graf#define min_t(type,x,y) \
36544d362409d5469aed47d19e7908d19bd194493aThomas Graf	({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
36644d362409d5469aed47d19e7908d19bd194493aThomas Graf#define max_t(type,x,y) \
36744d362409d5469aed47d19e7908d19bd194493aThomas Graf	({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
36844d362409d5469aed47d19e7908d19bd194493aThomas Graf
36944d362409d5469aed47d19e7908d19bd194493aThomas Grafextern int nl_cache_parse(struct nl_cache_ops *, struct sockaddr_nl *,
37044d362409d5469aed47d19e7908d19bd194493aThomas Graf			  struct nlmsghdr *, struct nl_parser_param *);
37144d362409d5469aed47d19e7908d19bd194493aThomas Graf
37244d362409d5469aed47d19e7908d19bd194493aThomas Graf
37344d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline void rtnl_copy_ratespec(struct rtnl_ratespec *dst,
37444d362409d5469aed47d19e7908d19bd194493aThomas Graf				      struct tc_ratespec *src)
37544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
37644d362409d5469aed47d19e7908d19bd194493aThomas Graf	dst->rs_cell_log = src->cell_log;
37744d362409d5469aed47d19e7908d19bd194493aThomas Graf	dst->rs_feature = src->feature;
37844d362409d5469aed47d19e7908d19bd194493aThomas Graf	dst->rs_addend = src->addend;
37944d362409d5469aed47d19e7908d19bd194493aThomas Graf	dst->rs_mpu = src->mpu;
38044d362409d5469aed47d19e7908d19bd194493aThomas Graf	dst->rs_rate = src->rate;
38144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
38244d362409d5469aed47d19e7908d19bd194493aThomas Graf
38344d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline void rtnl_rcopy_ratespec(struct tc_ratespec *dst,
38444d362409d5469aed47d19e7908d19bd194493aThomas Graf				       struct rtnl_ratespec *src)
38544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
38644d362409d5469aed47d19e7908d19bd194493aThomas Graf	dst->cell_log = src->rs_cell_log;
38744d362409d5469aed47d19e7908d19bd194493aThomas Graf	dst->feature = src->rs_feature;
38844d362409d5469aed47d19e7908d19bd194493aThomas Graf	dst->addend = src->rs_addend;
38944d362409d5469aed47d19e7908d19bd194493aThomas Graf	dst->mpu = src->rs_mpu;
39044d362409d5469aed47d19e7908d19bd194493aThomas Graf	dst->rate = src->rs_rate;
39144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
39244d362409d5469aed47d19e7908d19bd194493aThomas Graf
39344d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline char *nl_cache_name(struct nl_cache *cache)
39444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
39544d362409d5469aed47d19e7908d19bd194493aThomas Graf	return cache->c_ops ? cache->c_ops->co_name : "unknown";
39644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
39744d362409d5469aed47d19e7908d19bd194493aThomas Graf
39844d362409d5469aed47d19e7908d19bd194493aThomas Graf#define GENL_FAMILY(id, name) \
39944d362409d5469aed47d19e7908d19bd194493aThomas Graf	{ \
40044d362409d5469aed47d19e7908d19bd194493aThomas Graf		{ id, NL_ACT_UNSPEC, name }, \
40144d362409d5469aed47d19e7908d19bd194493aThomas Graf		END_OF_MSGTYPES_LIST, \
40244d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
40344d362409d5469aed47d19e7908d19bd194493aThomas Graf
40444d362409d5469aed47d19e7908d19bd194493aThomas Graf#endif
405