handlers.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. /*
  2. * lib/handlers.c default netlink message handlers
  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-2008 Thomas Graf <tgraf@suug.ch>
  10. */
  11. /**
  12. * @ingroup core
  13. * @defgroup cb Callbacks/Customization
  14. *
  15. * Related sections in the development guide:
  16. * - @core_doc{core_cb, Callback Configuration}
  17. *
  18. * @{
  19. *
  20. * Header
  21. * ------
  22. * ~~~~{.c}
  23. * #include <netlink/handlers.h>
  24. * ~~~~
  25. */
  26. #include <netlink-private/netlink.h>
  27. #include <netlink/netlink.h>
  28. #include <netlink/utils.h>
  29. #include <netlink/msg.h>
  30. #include <netlink/handlers.h>
  31. static void print_header_content(FILE *ofd, struct nlmsghdr *n)
  32. {
  33. char flags[128];
  34. char type[32];
  35. fprintf(ofd, "type=%s length=%u flags=<%s> sequence-nr=%u pid=%u",
  36. nl_nlmsgtype2str(n->nlmsg_type, type, sizeof(type)),
  37. n->nlmsg_len, nl_nlmsg_flags2str(n->nlmsg_flags, flags,
  38. sizeof(flags)), n->nlmsg_seq, n->nlmsg_pid);
  39. }
  40. static int nl_valid_handler_verbose(struct nl_msg *msg, void *arg)
  41. {
  42. FILE *ofd = arg ? arg : stdout;
  43. fprintf(ofd, "-- Warning: unhandled valid message: ");
  44. print_header_content(ofd, nlmsg_hdr(msg));
  45. fprintf(ofd, "\n");
  46. return NL_OK;
  47. }
  48. static int nl_invalid_handler_verbose(struct nl_msg *msg, void *arg)
  49. {
  50. FILE *ofd = arg ? arg : stderr;
  51. fprintf(ofd, "-- Error: Invalid message: ");
  52. print_header_content(ofd, nlmsg_hdr(msg));
  53. fprintf(ofd, "\n");
  54. return NL_STOP;
  55. }
  56. static int nl_overrun_handler_verbose(struct nl_msg *msg, void *arg)
  57. {
  58. FILE *ofd = arg ? arg : stderr;
  59. fprintf(ofd, "-- Error: Netlink Overrun: ");
  60. print_header_content(ofd, nlmsg_hdr(msg));
  61. fprintf(ofd, "\n");
  62. return NL_STOP;
  63. }
  64. static int nl_error_handler_verbose(struct sockaddr_nl *who,
  65. struct nlmsgerr *e, void *arg)
  66. {
  67. FILE *ofd = arg ? arg : stderr;
  68. char buf[256];
  69. fprintf(ofd, "-- Error received: %s\n-- Original message: ",
  70. strerror_r(-e->error, buf, sizeof(buf)));
  71. print_header_content(ofd, &e->msg);
  72. fprintf(ofd, "\n");
  73. return -nl_syserr2nlerr(e->error);
  74. }
  75. static int nl_valid_handler_debug(struct nl_msg *msg, void *arg)
  76. {
  77. FILE *ofd = arg ? arg : stderr;
  78. fprintf(ofd, "-- Debug: Unhandled Valid message: ");
  79. print_header_content(ofd, nlmsg_hdr(msg));
  80. fprintf(ofd, "\n");
  81. return NL_OK;
  82. }
  83. static int nl_finish_handler_debug(struct nl_msg *msg, void *arg)
  84. {
  85. FILE *ofd = arg ? arg : stderr;
  86. fprintf(ofd, "-- Debug: End of multipart message block: ");
  87. print_header_content(ofd, nlmsg_hdr(msg));
  88. fprintf(ofd, "\n");
  89. return NL_STOP;
  90. }
  91. static int nl_msg_in_handler_debug(struct nl_msg *msg, void *arg)
  92. {
  93. FILE *ofd = arg ? arg : stderr;
  94. fprintf(ofd, "-- Debug: Received Message:\n");
  95. nl_msg_dump(msg, ofd);
  96. return NL_OK;
  97. }
  98. static int nl_msg_out_handler_debug(struct nl_msg *msg, void *arg)
  99. {
  100. FILE *ofd = arg ? arg : stderr;
  101. fprintf(ofd, "-- Debug: Sent Message:\n");
  102. nl_msg_dump(msg, ofd);
  103. return NL_OK;
  104. }
  105. static int nl_skipped_handler_debug(struct nl_msg *msg, void *arg)
  106. {
  107. FILE *ofd = arg ? arg : stderr;
  108. fprintf(ofd, "-- Debug: Skipped message: ");
  109. print_header_content(ofd, nlmsg_hdr(msg));
  110. fprintf(ofd, "\n");
  111. return NL_SKIP;
  112. }
  113. static int nl_ack_handler_debug(struct nl_msg *msg, void *arg)
  114. {
  115. FILE *ofd = arg ? arg : stderr;
  116. fprintf(ofd, "-- Debug: ACK: ");
  117. print_header_content(ofd, nlmsg_hdr(msg));
  118. fprintf(ofd, "\n");
  119. return NL_STOP;
  120. }
  121. static nl_recvmsg_msg_cb_t cb_def[NL_CB_TYPE_MAX+1][NL_CB_KIND_MAX+1] = {
  122. [NL_CB_VALID] = {
  123. [NL_CB_VERBOSE] = nl_valid_handler_verbose,
  124. [NL_CB_DEBUG] = nl_valid_handler_debug,
  125. },
  126. [NL_CB_FINISH] = {
  127. [NL_CB_DEBUG] = nl_finish_handler_debug,
  128. },
  129. [NL_CB_INVALID] = {
  130. [NL_CB_VERBOSE] = nl_invalid_handler_verbose,
  131. [NL_CB_DEBUG] = nl_invalid_handler_verbose,
  132. },
  133. [NL_CB_MSG_IN] = {
  134. [NL_CB_DEBUG] = nl_msg_in_handler_debug,
  135. },
  136. [NL_CB_MSG_OUT] = {
  137. [NL_CB_DEBUG] = nl_msg_out_handler_debug,
  138. },
  139. [NL_CB_OVERRUN] = {
  140. [NL_CB_VERBOSE] = nl_overrun_handler_verbose,
  141. [NL_CB_DEBUG] = nl_overrun_handler_verbose,
  142. },
  143. [NL_CB_SKIPPED] = {
  144. [NL_CB_DEBUG] = nl_skipped_handler_debug,
  145. },
  146. [NL_CB_ACK] = {
  147. [NL_CB_DEBUG] = nl_ack_handler_debug,
  148. },
  149. };
  150. static nl_recvmsg_err_cb_t cb_err_def[NL_CB_KIND_MAX+1] = {
  151. [NL_CB_VERBOSE] = nl_error_handler_verbose,
  152. [NL_CB_DEBUG] = nl_error_handler_verbose,
  153. };
  154. /**
  155. * @name Callback Handle Management
  156. * @{
  157. */
  158. /**
  159. * Allocate a new callback handle
  160. * @arg kind callback kind to be used for initialization
  161. * @return Newly allocated callback handle or NULL
  162. */
  163. struct nl_cb *nl_cb_alloc(enum nl_cb_kind kind)
  164. {
  165. int i;
  166. struct nl_cb *cb;
  167. if (kind < 0 || kind > NL_CB_KIND_MAX)
  168. return NULL;
  169. cb = calloc(1, sizeof(*cb));
  170. if (!cb)
  171. return NULL;
  172. cb->cb_refcnt = 1;
  173. cb->cb_active = NL_CB_TYPE_MAX + 1;
  174. for (i = 0; i <= NL_CB_TYPE_MAX; i++)
  175. nl_cb_set(cb, i, kind, NULL, NULL);
  176. nl_cb_err(cb, kind, NULL, NULL);
  177. return cb;
  178. }
  179. /**
  180. * Clone an existing callback handle
  181. * @arg orig original callback handle
  182. * @return Newly allocated callback handle being a duplicate of
  183. * orig or NULL
  184. */
  185. struct nl_cb *nl_cb_clone(struct nl_cb *orig)
  186. {
  187. struct nl_cb *cb;
  188. cb = nl_cb_alloc(NL_CB_DEFAULT);
  189. if (!cb)
  190. return NULL;
  191. memcpy(cb, orig, sizeof(*orig));
  192. cb->cb_refcnt = 1;
  193. return cb;
  194. }
  195. struct nl_cb *nl_cb_get(struct nl_cb *cb)
  196. {
  197. cb->cb_refcnt++;
  198. return cb;
  199. }
  200. void nl_cb_put(struct nl_cb *cb)
  201. {
  202. if (!cb)
  203. return;
  204. cb->cb_refcnt--;
  205. if (cb->cb_refcnt < 0)
  206. BUG();
  207. if (cb->cb_refcnt <= 0)
  208. free(cb);
  209. }
  210. /**
  211. * Obtain type of current active callback
  212. * @arg cb callback to query
  213. *
  214. * @return type or __NL_CB_TYPE_MAX if none active
  215. */
  216. enum nl_cb_type nl_cb_active_type(struct nl_cb *cb)
  217. {
  218. return cb->cb_active;
  219. }
  220. /** @} */
  221. /**
  222. * @name Callback Setup
  223. * @{
  224. */
  225. /**
  226. * Set up a callback
  227. * @arg cb callback set
  228. * @arg type callback to modify
  229. * @arg kind kind of implementation
  230. * @arg func callback function (NL_CB_CUSTOM)
  231. * @arg arg argument passed to callback
  232. *
  233. * @return 0 on success or a negative error code
  234. */
  235. int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind,
  236. nl_recvmsg_msg_cb_t func, void *arg)
  237. {
  238. if (type < 0 || type > NL_CB_TYPE_MAX)
  239. return -NLE_RANGE;
  240. if (kind < 0 || kind > NL_CB_KIND_MAX)
  241. return -NLE_RANGE;
  242. if (kind == NL_CB_CUSTOM) {
  243. cb->cb_set[type] = func;
  244. cb->cb_args[type] = arg;
  245. } else {
  246. cb->cb_set[type] = cb_def[type][kind];
  247. cb->cb_args[type] = arg;
  248. }
  249. return 0;
  250. }
  251. /**
  252. * Set up a all callbacks
  253. * @arg cb callback set
  254. * @arg kind kind of callback
  255. * @arg func callback function
  256. * @arg arg argument to be passwd to callback function
  257. *
  258. * @return 0 on success or a negative error code
  259. */
  260. int nl_cb_set_all(struct nl_cb *cb, enum nl_cb_kind kind,
  261. nl_recvmsg_msg_cb_t func, void *arg)
  262. {
  263. int i, err;
  264. for (i = 0; i <= NL_CB_TYPE_MAX; i++) {
  265. err = nl_cb_set(cb, i, kind, func, arg);
  266. if (err < 0)
  267. return err;
  268. }
  269. return 0;
  270. }
  271. /**
  272. * Set up an error callback
  273. * @arg cb callback set
  274. * @arg kind kind of callback
  275. * @arg func callback function
  276. * @arg arg argument to be passed to callback function
  277. */
  278. int nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind,
  279. nl_recvmsg_err_cb_t func, void *arg)
  280. {
  281. if (kind < 0 || kind > NL_CB_KIND_MAX)
  282. return -NLE_RANGE;
  283. if (kind == NL_CB_CUSTOM) {
  284. cb->cb_err = func;
  285. cb->cb_err_arg = arg;
  286. } else {
  287. cb->cb_err = cb_err_def[kind];
  288. cb->cb_err_arg = arg;
  289. }
  290. return 0;
  291. }
  292. /** @} */
  293. /**
  294. * @name Overwriting
  295. * @{
  296. */
  297. /**
  298. * Overwrite internal calls to nl_recvmsgs()
  299. * @arg cb callback set
  300. * @arg func replacement callback for nl_recvmsgs()
  301. */
  302. void nl_cb_overwrite_recvmsgs(struct nl_cb *cb,
  303. int (*func)(struct nl_sock *, struct nl_cb *))
  304. {
  305. cb->cb_recvmsgs_ow = func;
  306. }
  307. /**
  308. * Overwrite internal calls to nl_recv()
  309. * @arg cb callback set
  310. * @arg func replacement callback for nl_recv()
  311. */
  312. void nl_cb_overwrite_recv(struct nl_cb *cb,
  313. int (*func)(struct nl_sock *, struct sockaddr_nl *,
  314. unsigned char **, struct ucred **))
  315. {
  316. cb->cb_recv_ow = func;
  317. }
  318. /**
  319. * Overwrite internal calls to nl_send()
  320. * @arg cb callback set
  321. * @arg func replacement callback for nl_send()
  322. */
  323. void nl_cb_overwrite_send(struct nl_cb *cb,
  324. int (*func)(struct nl_sock *, struct nl_msg *))
  325. {
  326. cb->cb_send_ow = func;
  327. }
  328. /** @} */
  329. /** @} */