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