handlers.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  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-2006 Thomas Graf <tgraf@suug.ch>
  10. */
  11. /**
  12. * @ingroup nl
  13. * @defgroup cb Callbacks/Customization
  14. * @brief
  15. *
  16. * Callbacks and overwriting capabilities are provided to take influence
  17. * in various control flows inside the library. All callbacks are packed
  18. * together in struct nl_cb which is then attached to a netlink socket or
  19. * passed on to the respective functions directly.
  20. *
  21. * Callbacks can control the flow of the underlying layer by returning
  22. * the appropriate error codes:
  23. * @code
  24. * Action ID | Description
  25. * -----------------+-------------------------------------------------------
  26. * NL_OK | Proceed with whatever comes next.
  27. * NL_SKIP | Skip message currently being processed and continue
  28. * | with next message.
  29. * NL_STOP | Stop parsing and discard all remaining messages in
  30. * | this set of messages.
  31. * @endcode
  32. *
  33. * All callbacks are optional and a default action is performed if no
  34. * application specific implementation is provided:
  35. *
  36. * @code
  37. * Callback ID | Default Return Value
  38. * ------------------+----------------------
  39. * NL_CB_VALID | NL_OK
  40. * NL_CB_FINISH | NL_STOP
  41. * NL_CB_OVERRUN | NL_STOP
  42. * NL_CB_SKIPPED | NL_SKIP
  43. * NL_CB_ACK | NL_STOP
  44. * NL_CB_MSG_IN | NL_OK
  45. * NL_CB_MSG_OUT | NL_OK
  46. * NL_CB_INVALID | NL_STOP
  47. * NL_CB_SEQ_CHECK | NL_OK
  48. * NL_CB_SEND_ACK | NL_OK
  49. * |
  50. * Error Callback | NL_STOP
  51. * @endcode
  52. *
  53. * In order to simplify typical usages of the library, different sets of
  54. * default callback implementations exist:
  55. * @code
  56. * NL_CB_DEFAULT: No additional actions
  57. * NL_CB_VERBOSE: Automatically print warning and error messages to a file
  58. * descriptor as appropriate. This is useful for CLI based
  59. * applications.
  60. * NL_CB_DEBUG: Print informal debugging information for each message
  61. * received. This will result in every message beint sent or
  62. * received to be printed to the screen in a decoded,
  63. * human-readable format.
  64. * @endcode
  65. *
  66. * @par 1) Setting up a callback set
  67. * @code
  68. * // Allocate a callback set and initialize it to the verbose default set
  69. * struct nl_cb *cb = nl_cb_alloc(NL_CB_VERBOSE);
  70. *
  71. * // Modify the set to call my_func() for all valid messages
  72. * nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, my_func, NULL);
  73. *
  74. * // Set the error message handler to the verbose default implementation
  75. * // and direct it to print all errors to the given file descriptor.
  76. * FILE *file = fopen(...);
  77. * nl_cb_err(cb, NL_CB_VERBOSE, NULL, file);
  78. * @endcode
  79. * @{
  80. */
  81. #include <netlink-local.h>
  82. #include <netlink/netlink.h>
  83. #include <netlink/utils.h>
  84. #include <netlink/msg.h>
  85. #include <netlink/handlers.h>
  86. static void print_header_content(FILE *ofd, struct nlmsghdr *n)
  87. {
  88. char flags[128];
  89. char type[32];
  90. fprintf(ofd, "type=%s length=%u flags=<%s> sequence-nr=%u pid=%u",
  91. nl_nlmsgtype2str(n->nlmsg_type, type, sizeof(type)),
  92. n->nlmsg_len, nl_nlmsg_flags2str(n->nlmsg_flags, flags,
  93. sizeof(flags)), n->nlmsg_seq, n->nlmsg_pid);
  94. }
  95. static int nl_valid_handler_verbose(struct nl_msg *msg, void *arg)
  96. {
  97. FILE *ofd = arg ? arg : stdout;
  98. fprintf(ofd, "-- Warning: unhandled valid message: ");
  99. print_header_content(ofd, nlmsg_hdr(msg));
  100. fprintf(ofd, "\n");
  101. return NL_OK;
  102. }
  103. static int nl_invalid_handler_verbose(struct nl_msg *msg, void *arg)
  104. {
  105. FILE *ofd = arg ? arg : stderr;
  106. fprintf(ofd, "-- Error: Invalid message: ");
  107. print_header_content(ofd, nlmsg_hdr(msg));
  108. fprintf(ofd, "\n");
  109. return NL_STOP;
  110. }
  111. static int nl_overrun_handler_verbose(struct nl_msg *msg, void *arg)
  112. {
  113. FILE *ofd = arg ? arg : stderr;
  114. fprintf(ofd, "-- Error: Netlink Overrun: ");
  115. print_header_content(ofd, nlmsg_hdr(msg));
  116. fprintf(ofd, "\n");
  117. return NL_STOP;
  118. }
  119. static int nl_error_handler_verbose(struct sockaddr_nl *who,
  120. struct nlmsgerr *e, void *arg)
  121. {
  122. FILE *ofd = arg ? arg : stderr;
  123. char buf[256];
  124. fprintf(ofd, "-- Error received: %s\n-- Original message: ",
  125. strerror_r(-e->error, buf, sizeof(buf)));
  126. print_header_content(ofd, &e->msg);
  127. fprintf(ofd, "\n");
  128. return e->error;
  129. }
  130. static int nl_valid_handler_debug(struct nl_msg *msg, void *arg)
  131. {
  132. FILE *ofd = arg ? arg : stderr;
  133. fprintf(ofd, "-- Debug: Unhandled Valid message: ");
  134. print_header_content(ofd, nlmsg_hdr(msg));
  135. fprintf(ofd, "\n");
  136. return NL_OK;
  137. }
  138. static int nl_finish_handler_debug(struct nl_msg *msg, void *arg)
  139. {
  140. FILE *ofd = arg ? arg : stderr;
  141. fprintf(ofd, "-- Debug: End of multipart message block: ");
  142. print_header_content(ofd, nlmsg_hdr(msg));
  143. fprintf(ofd, "\n");
  144. return NL_STOP;
  145. }
  146. static int nl_msg_in_handler_debug(struct nl_msg *msg, void *arg)
  147. {
  148. FILE *ofd = arg ? arg : stderr;
  149. fprintf(ofd, "-- Debug: Received Message:\n");
  150. nl_msg_dump(msg, ofd);
  151. return NL_OK;
  152. }
  153. static int nl_msg_out_handler_debug(struct nl_msg *msg, void *arg)
  154. {
  155. FILE *ofd = arg ? arg : stderr;
  156. fprintf(ofd, "-- Debug: Sent Message:\n");
  157. nl_msg_dump(msg, ofd);
  158. return NL_OK;
  159. }
  160. static int nl_skipped_handler_debug(struct nl_msg *msg, void *arg)
  161. {
  162. FILE *ofd = arg ? arg : stderr;
  163. fprintf(ofd, "-- Debug: Skipped message: ");
  164. print_header_content(ofd, nlmsg_hdr(msg));
  165. fprintf(ofd, "\n");
  166. return NL_SKIP;
  167. }
  168. static int nl_ack_handler_debug(struct nl_msg *msg, void *arg)
  169. {
  170. FILE *ofd = arg ? arg : stderr;
  171. fprintf(ofd, "-- Debug: ACK: ");
  172. print_header_content(ofd, nlmsg_hdr(msg));
  173. fprintf(ofd, "\n");
  174. return NL_STOP;
  175. }
  176. static nl_recvmsg_msg_cb_t cb_def[NL_CB_TYPE_MAX+1][NL_CB_KIND_MAX+1] = {
  177. [NL_CB_VALID] = {
  178. [NL_CB_VERBOSE] = nl_valid_handler_verbose,
  179. [NL_CB_DEBUG] = nl_valid_handler_debug,
  180. },
  181. [NL_CB_FINISH] = {
  182. [NL_CB_DEBUG] = nl_finish_handler_debug,
  183. },
  184. [NL_CB_INVALID] = {
  185. [NL_CB_VERBOSE] = nl_invalid_handler_verbose,
  186. [NL_CB_DEBUG] = nl_invalid_handler_verbose,
  187. },
  188. [NL_CB_MSG_IN] = {
  189. [NL_CB_DEBUG] = nl_msg_in_handler_debug,
  190. },
  191. [NL_CB_MSG_OUT] = {
  192. [NL_CB_DEBUG] = nl_msg_out_handler_debug,
  193. },
  194. [NL_CB_OVERRUN] = {
  195. [NL_CB_VERBOSE] = nl_overrun_handler_verbose,
  196. [NL_CB_DEBUG] = nl_overrun_handler_verbose,
  197. },
  198. [NL_CB_SKIPPED] = {
  199. [NL_CB_DEBUG] = nl_skipped_handler_debug,
  200. },
  201. [NL_CB_ACK] = {
  202. [NL_CB_DEBUG] = nl_ack_handler_debug,
  203. },
  204. };
  205. static nl_recvmsg_err_cb_t cb_err_def[NL_CB_KIND_MAX+1] = {
  206. [NL_CB_VERBOSE] = nl_error_handler_verbose,
  207. [NL_CB_DEBUG] = nl_error_handler_verbose,
  208. };
  209. /**
  210. * @name Callback Handle Management
  211. * @{
  212. */
  213. /**
  214. * Allocate a new callback handle
  215. * @arg kind callback kind to be used for initialization
  216. * @return Newly allocated callback handle or NULL
  217. */
  218. struct nl_cb *nl_cb_alloc(enum nl_cb_kind kind)
  219. {
  220. int i;
  221. struct nl_cb *cb;
  222. if (kind < 0 || kind > NL_CB_KIND_MAX)
  223. return NULL;
  224. cb = calloc(1, sizeof(*cb));
  225. if (!cb) {
  226. nl_errno(ENOMEM);
  227. return NULL;
  228. }
  229. cb->cb_refcnt = 1;
  230. for (i = 0; i <= NL_CB_TYPE_MAX; i++)
  231. nl_cb_set(cb, i, kind, NULL, NULL);
  232. nl_cb_err(cb, kind, NULL, NULL);
  233. return cb;
  234. }
  235. /**
  236. * Clone an existing callback handle
  237. * @arg orig original callback handle
  238. * @return Newly allocated callback handle being a duplicate of
  239. * orig or NULL
  240. */
  241. struct nl_cb *nl_cb_clone(struct nl_cb *orig)
  242. {
  243. struct nl_cb *cb;
  244. cb = nl_cb_alloc(NL_CB_DEFAULT);
  245. if (!cb)
  246. return NULL;
  247. memcpy(cb, orig, sizeof(*orig));
  248. cb->cb_refcnt = 1;
  249. return cb;
  250. }
  251. struct nl_cb *nl_cb_get(struct nl_cb *cb)
  252. {
  253. cb->cb_refcnt++;
  254. return cb;
  255. }
  256. void nl_cb_put(struct nl_cb *cb)
  257. {
  258. if (!cb)
  259. return;
  260. cb->cb_refcnt--;
  261. if (cb->cb_refcnt < 0)
  262. BUG();
  263. if (cb->cb_refcnt <= 0)
  264. free(cb);
  265. }
  266. /** @} */
  267. /**
  268. * @name Callback Setup
  269. * @{
  270. */
  271. /**
  272. * Set up a callback
  273. * @arg cb callback set
  274. * @arg type callback to modify
  275. * @arg kind kind of implementation
  276. * @arg func callback function (NL_CB_CUSTOM)
  277. * @arg arg argument passed to callback
  278. *
  279. * @return 0 on success or a negative error code
  280. */
  281. int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind,
  282. nl_recvmsg_msg_cb_t func, void *arg)
  283. {
  284. if (type < 0 || type > NL_CB_TYPE_MAX)
  285. return nl_error(ERANGE, "Callback type out of range");
  286. if (kind < 0 || kind > NL_CB_KIND_MAX)
  287. return nl_error(ERANGE, "Callback kind out of range");
  288. if (kind == NL_CB_CUSTOM) {
  289. cb->cb_set[type] = func;
  290. cb->cb_args[type] = arg;
  291. } else {
  292. cb->cb_set[type] = cb_def[type][kind];
  293. cb->cb_args[type] = arg;
  294. }
  295. return 0;
  296. }
  297. /**
  298. * Set up a all callbacks
  299. * @arg cb callback set
  300. * @arg kind kind of callback
  301. * @arg func callback function
  302. * @arg arg argument to be passwd to callback function
  303. *
  304. * @return 0 on success or a negative error code
  305. */
  306. int nl_cb_set_all(struct nl_cb *cb, enum nl_cb_kind kind,
  307. nl_recvmsg_msg_cb_t func, void *arg)
  308. {
  309. int i, err;
  310. for (i = 0; i <= NL_CB_TYPE_MAX; i++) {
  311. err = nl_cb_set(cb, i, kind, func, arg);
  312. if (err < 0)
  313. return err;
  314. }
  315. return 0;
  316. }
  317. /**
  318. * Set up an error callback
  319. * @arg cb callback set
  320. * @arg kind kind of callback
  321. * @arg func callback function
  322. * @arg arg argument to be passed to callback function
  323. */
  324. int nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind,
  325. nl_recvmsg_err_cb_t func, void *arg)
  326. {
  327. if (kind < 0 || kind > NL_CB_KIND_MAX)
  328. return nl_error(ERANGE, "Callback kind out of range");
  329. if (kind == NL_CB_CUSTOM) {
  330. cb->cb_err = func;
  331. cb->cb_err_arg = arg;
  332. } else {
  333. cb->cb_err = cb_err_def[kind];
  334. cb->cb_err_arg = arg;
  335. }
  336. return 0;
  337. }
  338. /** @} */
  339. /**
  340. * @name Overwriting
  341. * @{
  342. */
  343. /**
  344. * Overwrite internal calls to nl_recvmsgs()
  345. * @arg cb callback set
  346. * @arg func replacement callback for nl_recvmsgs()
  347. */
  348. void nl_cb_overwrite_recvmsgs(struct nl_cb *cb,
  349. int (*func)(struct nl_handle *, struct nl_cb *))
  350. {
  351. cb->cb_recvmsgs_ow = func;
  352. }
  353. /**
  354. * Overwrite internal calls to nl_recv()
  355. * @arg cb callback set
  356. * @arg func replacement callback for nl_recv()
  357. */
  358. void nl_cb_overwrite_recv(struct nl_cb *cb,
  359. int (*func)(struct nl_handle *, struct sockaddr_nl *,
  360. unsigned char **, struct ucred **))
  361. {
  362. cb->cb_recv_ow = func;
  363. }
  364. /**
  365. * Overwrite internal calls to nl_send()
  366. * @arg cb callback set
  367. * @arg func replacement callback for nl_send()
  368. */
  369. void nl_cb_overwrite_send(struct nl_cb *cb,
  370. int (*func)(struct nl_handle *, struct nl_msg *))
  371. {
  372. cb->cb_send_ow = func;
  373. }
  374. /** @} */
  375. /** @} */