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