firmware-utils: move bcm_tag.h here
[openwrt.git] / package / libnl-tiny / src / handlers.c
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 /**
13  * @ingroup core
14  * @defgroup cb Callbacks/Customization
15  *
16  * @details
17  * @par 1) Setting up a callback set
18  * @code
19  * // Allocate a callback set and initialize it to the verbose default set
20  * struct nl_cb *cb = nl_cb_alloc(NL_CB_VERBOSE);
21  *
22  * // Modify the set to call my_func() for all valid messages
23  * nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, my_func, NULL);
24  *
25  * // Set the error message handler to the verbose default implementation
26  * // and direct it to print all errors to the given file descriptor.
27  * FILE *file = fopen(...);
28  * nl_cb_err(cb, NL_CB_VERBOSE, NULL, file);
29  * @endcode
30  * @{
31  */
32
33 #include <netlink-local.h>
34 #include <netlink/netlink.h>
35 #include <netlink/utils.h>
36 #include <netlink/msg.h>
37 #include <netlink/handlers.h>
38
39 /**
40  * @name Callback Handle Management
41  * @{
42  */
43
44 /**
45  * Allocate a new callback handle
46  * @arg kind            callback kind to be used for initialization
47  * @return Newly allocated callback handle or NULL
48  */
49 struct nl_cb *nl_cb_alloc(enum nl_cb_kind kind)
50 {
51         int i;
52         struct nl_cb *cb;
53
54         if (kind < 0 || kind > NL_CB_KIND_MAX)
55                 return NULL;
56
57         cb = calloc(1, sizeof(*cb));
58         if (!cb)
59                 return NULL;
60
61         cb->cb_refcnt = 1;
62
63         for (i = 0; i <= NL_CB_TYPE_MAX; i++)
64                 nl_cb_set(cb, i, kind, NULL, NULL);
65
66         nl_cb_err(cb, kind, NULL, NULL);
67
68         return cb;
69 }
70
71 /**
72  * Clone an existing callback handle
73  * @arg orig            original callback handle
74  * @return Newly allocated callback handle being a duplicate of
75  *         orig or NULL
76  */
77 struct nl_cb *nl_cb_clone(struct nl_cb *orig)
78 {
79         struct nl_cb *cb;
80         
81         cb = nl_cb_alloc(NL_CB_DEFAULT);
82         if (!cb)
83                 return NULL;
84
85         memcpy(cb, orig, sizeof(*orig));
86         cb->cb_refcnt = 1;
87
88         return cb;
89 }
90
91 void nl_cb_put(struct nl_cb *cb)
92 {
93         if (!cb)
94                 return;
95
96         cb->cb_refcnt--;
97
98         if (cb->cb_refcnt < 0)
99                 BUG();
100
101         if (cb->cb_refcnt <= 0)
102                 free(cb);
103 }
104
105 /** @} */
106
107 /**
108  * @name Callback Setup
109  * @{
110  */
111
112 /**
113  * Set up a callback 
114  * @arg cb              callback set
115  * @arg type            callback to modify
116  * @arg kind            kind of implementation
117  * @arg func            callback function (NL_CB_CUSTOM)
118  * @arg arg             argument passed to callback
119  *
120  * @return 0 on success or a negative error code
121  */
122 int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind,
123               nl_recvmsg_msg_cb_t func, void *arg)
124 {
125         if (type < 0 || type > NL_CB_TYPE_MAX)
126                 return -NLE_RANGE;
127
128         if (kind < 0 || kind > NL_CB_KIND_MAX)
129                 return -NLE_RANGE;
130
131         if (kind == NL_CB_CUSTOM) {
132                 cb->cb_set[type] = func;
133                 cb->cb_args[type] = arg;
134         }
135
136         return 0;
137 }
138
139 /**
140  * Set up an error callback
141  * @arg cb              callback set
142  * @arg kind            kind of callback
143  * @arg func            callback function
144  * @arg arg             argument to be passed to callback function
145  */
146 int nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind,
147               nl_recvmsg_err_cb_t func, void *arg)
148 {
149         if (kind < 0 || kind > NL_CB_KIND_MAX)
150                 return -NLE_RANGE;
151
152         if (kind == NL_CB_CUSTOM) {
153                 cb->cb_err = func;
154                 cb->cb_err_arg = arg;
155         }
156
157         return 0;
158 }
159
160 /** @} */
161
162 /** @} */