netlink-local.h 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. /*
  2. * netlink-local.h Local Netlink Interface
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation version 2.1
  7. * of the License.
  8. *
  9. * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
  10. */
  11. #ifndef NETLINK_LOCAL_H_
  12. #define NETLINK_LOCAL_H_
  13. #include <stdio.h>
  14. #include <errno.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <unistd.h>
  18. #include <fcntl.h>
  19. #include <math.h>
  20. #include <time.h>
  21. #include <stdarg.h>
  22. #include <ctype.h>
  23. #include <sys/types.h>
  24. #include <sys/socket.h>
  25. #include <inttypes.h>
  26. #include <assert.h>
  27. #include <limits.h>
  28. #include <arpa/inet.h>
  29. #include <netdb.h>
  30. #ifndef SOL_NETLINK
  31. #define SOL_NETLINK 270
  32. #endif
  33. #include <linux/types.h>
  34. /* local header copies */
  35. #include <linux/if.h>
  36. #include <linux/if_arp.h>
  37. #include <linux/if_ether.h>
  38. #include <linux/pkt_sched.h>
  39. #include <linux/pkt_cls.h>
  40. #include <linux/gen_stats.h>
  41. #include <linux/ip_mp_alg.h>
  42. #ifndef DISABLE_PTHREADS
  43. #include <pthread.h>
  44. #endif
  45. #include <netlink/netlink.h>
  46. #include <netlink/handlers.h>
  47. #include <netlink/cache.h>
  48. #include <netlink/route/tc.h>
  49. #include <netlink/object-api.h>
  50. #include <netlink/cache-api.h>
  51. #include <netlink-types.h>
  52. struct trans_tbl {
  53. int i;
  54. const char *a;
  55. };
  56. #define __ADD(id, name) { .i = id, .a = #name },
  57. struct trans_list {
  58. int i;
  59. char *a;
  60. struct nl_list_head list;
  61. };
  62. #define NL_DEBUG 1
  63. #define NL_DBG(LVL,FMT,ARG...) \
  64. do { \
  65. if (LVL <= nl_debug) \
  66. fprintf(stderr, "DBG<" #LVL ">: " FMT, ##ARG); \
  67. } while (0)
  68. #define BUG() \
  69. do { \
  70. fprintf(stderr, "BUG: %s:%d\n", \
  71. __FILE__, __LINE__); \
  72. assert(0); \
  73. } while (0)
  74. #define RET_ERR(R, E) \
  75. do { \
  76. errno = E; \
  77. return -R; \
  78. } while (0)
  79. extern int __nl_error(int, const char *, unsigned int,
  80. const char *, const char *, ...);
  81. extern int __nl_read_num_str_file(const char *path,
  82. int (*cb)(long, const char *));
  83. #ifdef NL_ERROR_ASSERT
  84. #include <assert.h>
  85. static inline int __assert_error(const char *file, int line, char *func,
  86. const char *fmt, ...)
  87. {
  88. va_list args;
  89. fprintf(stderr, "%s:%d:%s: ", file, line, func);
  90. va_start(args, fmt);
  91. vfprintf(stderr, fmt, args);
  92. va_end(args);
  93. fprintf(stderr, "\n");
  94. assert(0);
  95. return 0;
  96. }
  97. #define nl_error(E, FMT,ARG...) \
  98. __assert_error(__FILE__, __LINE__, __FUNCTION__, FMT, ##ARG)
  99. #else
  100. #define nl_error(E, FMT,ARG...) \
  101. __nl_error(E, __FILE__, __LINE__, __FUNCTION__, FMT, ##ARG)
  102. #endif
  103. #define nl_errno(E) nl_error(E, NULL)
  104. /* backwards compat */
  105. #define dp_new_line(params, line) nl_new_line(params, line)
  106. #define dp_dump(params, fmt, arg...) nl_dump(params, fmt, ##arg)
  107. static inline int __trans_list_add(int i, const char *a,
  108. struct nl_list_head *head)
  109. {
  110. struct trans_list *tl;
  111. tl = calloc(1, sizeof(*tl));
  112. if (!tl)
  113. return nl_errno(ENOMEM);
  114. tl->i = i;
  115. tl->a = strdup(a);
  116. nl_list_add_tail(&tl->list, head);
  117. return 0;
  118. }
  119. static inline void __trans_list_clear(struct nl_list_head *head)
  120. {
  121. struct trans_list *tl, *next;
  122. nl_list_for_each_entry_safe(tl, next, head, list) {
  123. free(tl->a);
  124. free(tl);
  125. }
  126. }
  127. static inline char *__type2str(int type, char *buf, size_t len,
  128. struct trans_tbl *tbl, size_t tbl_len)
  129. {
  130. int i;
  131. for (i = 0; i < tbl_len; i++) {
  132. if (tbl[i].i == type) {
  133. snprintf(buf, len, "%s", tbl[i].a);
  134. return buf;
  135. }
  136. }
  137. snprintf(buf, len, "0x%x", type);
  138. return buf;
  139. }
  140. static inline char *__list_type2str(int type, char *buf, size_t len,
  141. struct nl_list_head *head)
  142. {
  143. struct trans_list *tl;
  144. nl_list_for_each_entry(tl, head, list) {
  145. if (tl->i == type) {
  146. snprintf(buf, len, "%s", tl->a);
  147. return buf;
  148. }
  149. }
  150. snprintf(buf, len, "0x%x", type);
  151. return buf;
  152. }
  153. static inline char *__flags2str(int flags, char *buf, size_t len,
  154. struct trans_tbl *tbl, size_t tbl_len)
  155. {
  156. int i;
  157. int tmp = flags;
  158. memset(buf, 0, len);
  159. for (i = 0; i < tbl_len; i++) {
  160. if (tbl[i].i & tmp) {
  161. tmp &= ~tbl[i].i;
  162. strncat(buf, tbl[i].a, len - strlen(buf) - 1);
  163. if ((tmp & flags))
  164. strncat(buf, ",", len - strlen(buf) - 1);
  165. }
  166. }
  167. return buf;
  168. }
  169. static inline int __str2type(const char *buf, struct trans_tbl *tbl,
  170. size_t tbl_len)
  171. {
  172. unsigned long l;
  173. char *end;
  174. int i;
  175. if (*buf == '\0')
  176. return -1;
  177. for (i = 0; i < tbl_len; i++)
  178. if (!strcasecmp(tbl[i].a, buf))
  179. return tbl[i].i;
  180. l = strtoul(buf, &end, 0);
  181. if (l == ULONG_MAX || *end != '\0')
  182. return -1;
  183. return (int) l;
  184. }
  185. static inline int __list_str2type(const char *buf, struct nl_list_head *head)
  186. {
  187. struct trans_list *tl;
  188. unsigned long l;
  189. char *end;
  190. if (*buf == '\0')
  191. return -1;
  192. nl_list_for_each_entry(tl, head, list) {
  193. if (!strcasecmp(tl->a, buf))
  194. return tl->i;
  195. }
  196. l = strtoul(buf, &end, 0);
  197. if (l == ULONG_MAX || *end != '\0')
  198. return -1;
  199. return (int) l;
  200. }
  201. static inline int __str2flags(const char *buf, struct trans_tbl *tbl,
  202. size_t tbl_len)
  203. {
  204. int i, flags = 0, len;
  205. char *p = (char *) buf, *t;
  206. for (;;) {
  207. if (*p == ' ')
  208. p++;
  209. t = strchr(p, ',');
  210. len = t ? t - p : strlen(p);
  211. for (i = 0; i < tbl_len; i++)
  212. if (!strncasecmp(tbl[i].a, p, len))
  213. flags |= tbl[i].i;
  214. if (!t)
  215. return flags;
  216. p = ++t;
  217. }
  218. return 0;
  219. }
  220. static inline void __dp_dump(struct nl_dump_params *parms, const char *fmt,
  221. va_list args)
  222. {
  223. if (parms->dp_fd)
  224. vfprintf(parms->dp_fd, fmt, args);
  225. else if (parms->dp_buf || parms->dp_cb) {
  226. char *buf = NULL;
  227. if (vasprintf(&buf, fmt, args) >= 0) {
  228. if (parms->dp_cb)
  229. parms->dp_cb(parms, buf);
  230. else
  231. strncat(parms->dp_buf, buf,
  232. parms->dp_buflen - strlen(parms->dp_buf) - 1);
  233. free(buf);
  234. }
  235. }
  236. }
  237. static inline void dp_dump_line(struct nl_dump_params *parms, int line,
  238. const char *fmt, ...)
  239. {
  240. va_list args;
  241. nl_new_line(parms, line);
  242. va_start(args, fmt);
  243. __dp_dump(parms, fmt, args);
  244. va_end(args);
  245. }
  246. static inline void dump_from_ops(struct nl_object *obj,
  247. struct nl_dump_params *params)
  248. {
  249. int type = params->dp_type;
  250. if (type < 0 || type > NL_DUMP_MAX)
  251. BUG();
  252. if (params->dp_dump_msgtype) {
  253. #if 0
  254. /* XXX */
  255. char buf[64];
  256. dp_dump_line(params, 0, "%s ",
  257. nl_cache_mngt_type2name(obj->ce_ops,
  258. obj->ce_ops->co_protocol,
  259. obj->ce_msgtype,
  260. buf, sizeof(buf)));
  261. #endif
  262. params->dp_pre_dump = 1;
  263. } else
  264. dp_new_line(params, 0);
  265. if (obj->ce_ops->oo_dump[type])
  266. obj->ce_ops->oo_dump[type](obj, params);
  267. }
  268. static inline struct nl_cache *dp_cache(struct nl_object *obj)
  269. {
  270. if (obj->ce_cache == NULL)
  271. return nl_cache_mngt_require(obj->ce_ops->oo_name);
  272. return obj->ce_cache;
  273. }
  274. static inline int nl_cb_call(struct nl_cb *cb, int type, struct nl_msg *msg)
  275. {
  276. return cb->cb_set[type](msg, cb->cb_args[type]);
  277. }
  278. #define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0]))
  279. #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
  280. #define __init __attribute__ ((constructor))
  281. #define __exit __attribute__ ((destructor))
  282. #define P_ACCEPT 0
  283. #define P_IGNORE 0
  284. #define min(x,y) ({ \
  285. typeof(x) _x = (x); \
  286. typeof(y) _y = (y); \
  287. (void) (&_x == &_y); \
  288. _x < _y ? _x : _y; })
  289. #define max(x,y) ({ \
  290. typeof(x) _x = (x); \
  291. typeof(y) _y = (y); \
  292. (void) (&_x == &_y); \
  293. _x > _y ? _x : _y; })
  294. #define min_t(type,x,y) \
  295. ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
  296. #define max_t(type,x,y) \
  297. ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
  298. extern int nl_cache_parse(struct nl_cache_ops *, struct sockaddr_nl *,
  299. struct nlmsghdr *, struct nl_parser_param *);
  300. static inline void rtnl_copy_ratespec(struct rtnl_ratespec *dst,
  301. struct tc_ratespec *src)
  302. {
  303. dst->rs_cell_log = src->cell_log;
  304. dst->rs_feature = src->feature;
  305. dst->rs_addend = src->addend;
  306. dst->rs_mpu = src->mpu;
  307. dst->rs_rate = src->rate;
  308. }
  309. static inline void rtnl_rcopy_ratespec(struct tc_ratespec *dst,
  310. struct rtnl_ratespec *src)
  311. {
  312. dst->cell_log = src->rs_cell_log;
  313. dst->feature = src->rs_feature;
  314. dst->addend = src->rs_addend;
  315. dst->mpu = src->rs_mpu;
  316. dst->rate = src->rs_rate;
  317. }
  318. static inline char *nl_cache_name(struct nl_cache *cache)
  319. {
  320. return cache->c_ops ? cache->c_ops->co_name : "unknown";
  321. }
  322. #define GENL_FAMILY(id, name) \
  323. { \
  324. { id, NL_ACT_UNSPEC, name }, \
  325. END_OF_MSGTYPES_LIST, \
  326. }
  327. #ifndef DISABLE_PTHREADS
  328. #define NL_LOCK(NAME) pthread_mutex_t (NAME) = PTHREAD_MUTEX_INITIALIZER
  329. #define NL_RW_LOCK(NAME) pthread_rwlock_t (NAME) = PTHREAD_RWLOCK_INITIALIZER
  330. static inline void nl_lock(pthread_mutex_t *lock)
  331. {
  332. pthread_mutex_lock(lock);
  333. }
  334. static inline void nl_unlock(pthread_mutex_t *lock)
  335. {
  336. pthread_mutex_unlock(lock);
  337. }
  338. static inline void nl_read_lock(pthread_rwlock_t *lock)
  339. {
  340. pthread_rwlock_rdlock(lock);
  341. }
  342. static inline void nl_read_unlock(pthread_rwlock_t *lock)
  343. {
  344. pthread_rwlock_unlock(lock);
  345. }
  346. static inline void nl_write_lock(pthread_rwlock_t *lock)
  347. {
  348. pthread_rwlock_wrlock(lock);
  349. }
  350. static inline void nl_write_unlock(pthread_rwlock_t *lock)
  351. {
  352. pthread_rwlock_unlock(lock);
  353. }
  354. #else
  355. #define NL_LOCK(NAME) int __unused_lock_ ##NAME __attribute__((unused))
  356. #define NL_RW_LOCK(NAME) int __unused_lock_ ##NAME __attribute__((unused))
  357. #define nl_lock(LOCK) do { } while(0)
  358. #define nl_unlock(LOCK) do { } while(0)
  359. #define nl_read_lock(LOCK) do { } while(0)
  360. #define nl_read_unlock(LOCK) do { } while(0)
  361. #define nl_write_lock(LOCK) do { } while(0)
  362. #define nl_write_unlock(LOCK) do { } while(0)
  363. #endif
  364. #endif