1 %module capi
2 %{
3 #include <netlink/netlink.h>
4 #include <netlink/types.h>
5 #include <netlink/socket.h>
6 #include <netlink/msg.h>
7 #include <netlink/object.h>
8 #include <netlink/cache.h>
9 #include <netlink/attr.h>
10 #include <net/if.h>
11
12 #define DEBUG
13 #include "utils.h"
14 %}
15
16 %include <stdint.i>
17 %include <cstring.i>
18 %include <cpointer.i>
19
20 %inline %{
alloc_dump_params(void)21 struct nl_dump_params *alloc_dump_params(void)
22 {
23 struct nl_dump_params *dp;
24 if (!(dp = calloc(1, sizeof(*dp))))
25 return NULL;
26 dp->dp_fd = stdout;
27 return dp;
28 }
29
free_dump_params(struct nl_dump_params * dp)30 void free_dump_params(struct nl_dump_params *dp)
31 {
32 free(dp);
33 }
34 %};
35
36 /* <netlink/types.h> */
37
38 enum nl_dump_type {
39 NL_DUMP_LINE, /**< Dump object briefly on one line */
40 NL_DUMP_DETAILS, /**< Dump all attributes but no statistics */
41 NL_DUMP_STATS, /**< Dump all attributes including statistics */
42 __NL_DUMP_MAX,
43 };
44
45 struct nl_dump_params
46 {
47 /**
48 * Specifies the type of dump that is requested.
49 */
50 enum nl_dump_type dp_type;
51
52 /**
53 * Specifies the number of whitespaces to be put in front
54 * of every new line (indentation).
55 */
56 int dp_prefix;
57
58 /**
59 * Causes the cache index to be printed for each element.
60 */
61 int dp_print_index;
62
63 /**
64 * Causes each element to be prefixed with the message type.
65 */
66 int dp_dump_msgtype;
67
68 /**
69 * A callback invoked for output
70 *
71 * Passed arguments are:
72 * - dumping parameters
73 * - string to append to the output
74 */
75 void (*dp_cb)(struct nl_dump_params *, char *);
76
77 /**
78 * A callback invoked for every new line, can be used to
79 * customize the indentation.
80 *
81 * Passed arguments are:
82 * - dumping parameters
83 * - line number starting from 0
84 */
85 void (*dp_nl_cb)(struct nl_dump_params *, int);
86
87 /**
88 * User data pointer, can be used to pass data to callbacks.
89 */
90 void *dp_data;
91
92 /**
93 * File descriptor the dumping output should go to
94 */
95 FILE * dp_fd;
96
97 /**
98 * Alternatively the output may be redirected into a buffer
99 */
100 char * dp_buf;
101
102 /**
103 * Length of the buffer dp_buf
104 */
105 size_t dp_buflen;
106
107 /**
108 * PRIVATE
109 * Set if a dump was performed prior to the actual dump handler.
110 */
111 int dp_pre_dump;
112
113 /**
114 * PRIVATE
115 * Owned by the current caller
116 */
117 int dp_ivar;
118
119 unsigned int dp_line;
120 };
121
122 /* <net/if.h> */
123 extern unsigned int if_nametoindex(const char *ifname);
124
125 /* <netlink/errno.h> */
126 extern const char *nl_geterror(int);
127
128 /* <netlink/utils.h> */
129
130 extern double nl_cancel_down_bytes(unsigned long long, char **);
131 extern double nl_cancel_down_bits(unsigned long long, char **);
132 %cstring_output_maxsize(char *buf, size_t len)
133 extern int nl_rate2str(unsigned long long rate, int type, char *buf, size_t len);
134 extern double nl_cancel_down_us(uint32_t, char **);
135
136 extern long nl_size2int(const char *);
137 %cstring_output_maxsize(char *buf, const size_t len)
138 extern char *nl_size2str(const size_t, char *buf, const size_t len);
139 extern long nl_prob2int(const char *);
140
141 extern int nl_get_user_hz(void);
142 extern uint32_t nl_us2ticks(uint32_t);
143 extern uint32_t nl_ticks2us(uint32_t);
144 extern int nl_str2msec(const char *, uint64_t *);
145
146 %cstring_output_maxsize(char *buf, size_t len)
147 extern char *nl_msec2str(uint64_t, char *buf, size_t len);
148
149 %cstring_output_maxsize(char *buf, size_t len)
150 extern char *nl_llproto2str(int, char *buf, size_t len);
151 extern int nl_str2llproto(const char *);
152
153 %cstring_output_maxsize(char *buf, size_t len)
154 extern char *nl_ether_proto2str(int, char *buf, size_t len);
155 extern int nl_str2ether_proto(const char *);
156
157 %cstring_output_maxsize(char *buf, size_t len)
158 extern char *nl_ip_proto2str(int, char *buf, size_t len);
159 extern int nl_str2ip_proto(const char *);
160
161 extern void nl_new_line(struct nl_dump_params *);
162 extern void nl_dump(struct nl_dump_params *, const char *, ...);
163 extern void nl_dump_line(struct nl_dump_params *, const char *, ...);
164
165 /* <netlink/netlink.h> */
166 extern struct nl_dump_params *alloc_dump_params(void);
167 extern void free_dump_params(struct nl_dump_params *);
168
169 extern int nl_connect(struct nl_sock *, int);
170 extern void nl_close(struct nl_sock *);
171
172 /* <netlink/socket.h> */
173 extern struct nl_sock *nl_socket_alloc(void);
174 extern struct nl_sock *nl_socket_alloc_cb(struct nl_cb *);
175 extern void nl_socket_free(struct nl_sock *);
176
177 extern uint32_t nl_socket_get_local_port(const struct nl_sock *);
178 extern void nl_socket_set_local_port(struct nl_sock *, uint32_t);
179
180 extern uint32_t nl_socket_get_peer_port(const struct nl_sock *);
181 extern void nl_socket_set_peer_port(struct nl_sock *, uint32_t);
182
183 extern uint32_t nl_socket_get_peer_groups(const struct nl_sock *sk);
184 extern void nl_socket_set_peer_groups(struct nl_sock *sk, uint32_t groups);
185
186 extern int nl_socket_set_buffer_size(struct nl_sock *, int, int);
187 extern void nl_socket_set_cb(struct nl_sock *, struct nl_cb *);
188
189 extern int nl_send_auto_complete(struct nl_sock *, struct nl_msg *);
190 extern int nl_recvmsgs(struct nl_sock *, struct nl_cb *);
191
192 /* <netlink/msg.h> */
193 extern int nlmsg_size(int);
194 extern int nlmsg_total_size(int);
195 extern int nlmsg_padlen(int);
196
197 extern void * nlmsg_data(const struct nlmsghdr *);
198 extern int nlmsg_datalen(const struct nlmsghdr *);
199 extern void * nlmsg_tail(const struct nlmsghdr *);
200
201 /* attribute access */
202 extern struct nlattr * nlmsg_attrdata(const struct nlmsghdr *, int);
203 extern int nlmsg_attrlen(const struct nlmsghdr *, int);
204
205 /* message parsing */
206 extern int nlmsg_valid_hdr(const struct nlmsghdr *, int);
207 extern int nlmsg_ok(const struct nlmsghdr *, int);
208 extern struct nlmsghdr * nlmsg_next(struct nlmsghdr *, int *);
209 extern int nlmsg_parse(struct nlmsghdr *, int, struct nlattr **,
210 int, struct nla_policy *);
211 extern struct nlattr * nlmsg_find_attr(struct nlmsghdr *, int, int);
212 extern int nlmsg_validate(struct nlmsghdr *, int, int,
213 struct nla_policy *);
214
215 extern struct nl_msg * nlmsg_alloc(void);
216 extern struct nl_msg * nlmsg_alloc_size(size_t);
217 extern struct nl_msg * nlmsg_alloc_simple(int, int);
218 extern void nlmsg_set_default_size(size_t);
219 extern struct nl_msg * nlmsg_inherit(struct nlmsghdr *);
220 extern struct nl_msg * nlmsg_convert(struct nlmsghdr *);
221 extern void * nlmsg_reserve(struct nl_msg *, size_t, int);
222 extern int nlmsg_append(struct nl_msg *, void *, size_t, int);
223 extern int nlmsg_expand(struct nl_msg *, size_t);
224
225 extern struct nlmsghdr * nlmsg_put(struct nl_msg *, uint32_t, uint32_t,
226 int, int, int);
227 extern struct nlmsghdr * nlmsg_hdr(struct nl_msg *);
228 extern void nlmsg_get(struct nl_msg *);
229 extern void nlmsg_free(struct nl_msg *);
230
231 /* attribute modification */
232 extern void nlmsg_set_proto(struct nl_msg *, int);
233 extern int nlmsg_get_proto(struct nl_msg *);
234 extern size_t nlmsg_get_max_size(struct nl_msg *);
235 extern void nlmsg_set_src(struct nl_msg *, struct sockaddr_nl *);
236 extern struct sockaddr_nl *nlmsg_get_src(struct nl_msg *);
237 extern void nlmsg_set_dst(struct nl_msg *, struct sockaddr_nl *);
238 extern struct sockaddr_nl *nlmsg_get_dst(struct nl_msg *);
239 extern void nlmsg_set_creds(struct nl_msg *, struct ucred *);
240 extern struct ucred * nlmsg_get_creds(struct nl_msg *);
241
242 extern char * nl_nlmsgtype2str(int, char *, size_t);
243 extern int nl_str2nlmsgtype(const char *);
244
245 extern char * nl_nlmsg_flags2str(int, char *, size_t);
246
247 extern int nl_msg_parse(struct nl_msg *,
248 void (*cb)(struct nl_object *, void *),
249 void *);
250
251 extern void nl_msg_dump(struct nl_msg *, FILE *);
252
253 %inline %{
cast_obj(void * obj)254 struct nl_object *cast_obj(void *obj)
255 {
256 return (struct nl_object *) obj;
257 }
258
object_alloc_name(const char * name)259 struct nl_object *object_alloc_name(const char *name)
260 {
261 struct nl_object *obj;
262
263 if (nl_object_alloc_name(name, &obj) < 0)
264 return NULL;
265
266 return obj;
267 }
268 %};
269
270 extern struct nl_object *nl_object_alloc(struct nl_object_ops *);
271 extern void nl_object_free(struct nl_object *);
272 extern struct nl_object *nl_object_clone(struct nl_object *);
273 extern void nl_object_get(struct nl_object *);
274 extern void nl_object_put(struct nl_object *);
275 extern int nl_object_shared(struct nl_object *);
276
277 %cstring_output_maxsize(char *buf, size_t len)
278 extern void nl_object_dump_buf(struct nl_object *, char *buf, size_t len);
279
280 extern void nl_object_dump(struct nl_object *, struct nl_dump_params *);
281
282 extern int nl_object_identical(struct nl_object *, struct nl_object *);
283 extern uint32_t nl_object_diff(struct nl_object *, struct nl_object *);
284 extern int nl_object_match_filter(struct nl_object *, struct nl_object *);
285
286 %cstring_output_maxsize(char *buf, size_t len)
287 extern char *nl_object_attrs2str(struct nl_object *, uint32_t, char *buf, size_t len);
288
289 %cstring_output_maxsize(char *buf, size_t len)
290 extern char *nl_object_attr_list(struct nl_object *, char *buf, size_t len);
291
292 extern void nl_object_mark(struct nl_object *);
293 extern void nl_object_unmark(struct nl_object *);
294 extern int nl_object_is_marked(struct nl_object *);
295
296 extern int nl_object_get_refcnt(struct nl_object *);
297
298 /* <netlink/cache.h> */
299
300 typedef void (*change_func_t)(struct nl_cache *, struct nl_object *, int, void *);
301
302 %inline %{
alloc_cache_name(const char * name)303 struct nl_cache *alloc_cache_name(const char *name)
304 {
305 struct nl_cache *c;
306 if (nl_cache_alloc_name(name, &c) < 0)
307 return NULL;
308 return c;
309 }
310
alloc_cache_mngr(struct nl_sock * sock,int protocol,int flags)311 struct nl_cache_mngr *alloc_cache_mngr(struct nl_sock *sock,
312 int protocol, int flags)
313 {
314 struct nl_cache_mngr *mngr;
315
316 if (nl_cache_mngr_alloc(sock, protocol, flags, &mngr) < 0)
317 return NULL;
318
319 return mngr;
320 }
321
cache_mngr_add(struct nl_cache_mngr * mngr,const char * name,change_func_t func,void * arg)322 struct nl_cache *cache_mngr_add(struct nl_cache_mngr *mngr,
323 const char *name, change_func_t func,
324 void *arg)
325 {
326 struct nl_cache *cache;
327
328 if (nl_cache_mngr_add(mngr, name, func, arg, &cache) < 0)
329 return NULL;
330
331 return cache;
332 }
333 %}
334
335 /* Access Functions */
336 extern int nl_cache_nitems(struct nl_cache *);
337 extern int nl_cache_nitems_filter(struct nl_cache *,
338 struct nl_object *);
339 extern struct nl_cache_ops * nl_cache_get_ops(struct nl_cache *);
340 extern struct nl_object * nl_cache_get_first(struct nl_cache *);
341 extern struct nl_object * nl_cache_get_last(struct nl_cache *);
342 extern struct nl_object * nl_cache_get_next(struct nl_object *);
343 extern struct nl_object * nl_cache_get_prev(struct nl_object *);
344
345 extern struct nl_cache * nl_cache_alloc(struct nl_cache_ops *);
346 extern struct nl_cache * nl_cache_subset(struct nl_cache *,
347 struct nl_object *);
348 extern void nl_cache_clear(struct nl_cache *);
349 extern void nl_cache_free(struct nl_cache *);
350
351 /* Cache modification */
352 extern int nl_cache_add(struct nl_cache *,
353 struct nl_object *);
354 extern int nl_cache_parse_and_add(struct nl_cache *,
355 struct nl_msg *);
356 extern void nl_cache_remove(struct nl_object *);
357 extern int nl_cache_refill(struct nl_sock *,
358 struct nl_cache *);
359 extern int nl_cache_pickup(struct nl_sock *,
360 struct nl_cache *);
361 extern int nl_cache_resync(struct nl_sock *,
362 struct nl_cache *,
363 change_func_t,
364 void *);
365 extern int nl_cache_include(struct nl_cache *,
366 struct nl_object *,
367 change_func_t,
368 void *);
369 extern void nl_cache_set_arg1(struct nl_cache *, int);
370 extern void nl_cache_set_arg2(struct nl_cache *, int);
371
372 /* General */
373 extern int nl_cache_is_empty(struct nl_cache *);
374 extern struct nl_object * nl_cache_search(struct nl_cache *,
375 struct nl_object *);
376 extern void nl_cache_mark_all(struct nl_cache *);
377
378 /* Dumping */
379 extern void nl_cache_dump(struct nl_cache *,
380 struct nl_dump_params *);
381 extern void nl_cache_dump_filter(struct nl_cache *,
382 struct nl_dump_params *,
383 struct nl_object *);
384
385 /* Iterators */
386 extern void nl_cache_foreach(struct nl_cache *,
387 void (*cb)(struct nl_object *,
388 void *),
389 void *arg);
390 extern void nl_cache_foreach_filter(struct nl_cache *,
391 struct nl_object *,
392 void (*cb)(struct
393 nl_object *,
394 void *),
395 void *arg);
396
397 /* --- cache management --- */
398
399 /* Cache type management */
400 extern struct nl_cache_ops * nl_cache_ops_lookup(const char *);
401 extern struct nl_cache_ops * nl_cache_ops_associate(int, int);
402 extern struct nl_msgtype * nl_msgtype_lookup(struct nl_cache_ops *, int);
403 extern void nl_cache_ops_foreach(void (*cb)(struct nl_cache_ops *, void *), void *);
404 extern int nl_cache_mngt_register(struct nl_cache_ops *);
405 extern int nl_cache_mngt_unregister(struct nl_cache_ops *);
406
407 /* Global cache provisioning/requiring */
408 extern void nl_cache_mngt_provide(struct nl_cache *);
409 extern void nl_cache_mngt_unprovide(struct nl_cache *);
410 extern struct nl_cache * nl_cache_mngt_require(const char *);
411
412 struct nl_cache_mngr;
413
414 #define NL_AUTO_PROVIDE 1
415
416 extern int nl_cache_mngr_get_fd(struct nl_cache_mngr *);
417 extern int nl_cache_mngr_poll(struct nl_cache_mngr *,
418 int);
419 extern int nl_cache_mngr_data_ready(struct nl_cache_mngr *);
420 extern void nl_cache_mngr_free(struct nl_cache_mngr *);
421
422 /* <netlink/addr.h> */
423 %inline %{
addr_parse(const char * addr,int guess)424 struct nl_addr *addr_parse(const char *addr, int guess)
425 {
426 struct nl_addr *result;
427
428 if (nl_addr_parse(addr, guess, &result) < 0)
429 return NULL;
430
431 return result;
432 }
433 %};
434
435 extern struct nl_addr *nl_addr_alloc(size_t);
436 extern struct nl_addr *nl_addr_alloc_attr(struct nlattr *, int);
437 extern struct nl_addr *nl_addr_build(int, void *, size_t);
438 extern struct nl_addr *nl_addr_clone(struct nl_addr *);
439
440 extern struct nl_addr *nl_addr_get(struct nl_addr *);
441 extern void nl_addr_put(struct nl_addr *);
442 extern int nl_addr_shared(struct nl_addr *);
443
444 extern int nl_addr_cmp(struct nl_addr *, struct nl_addr *);
445 extern int nl_addr_cmp_prefix(struct nl_addr *, struct nl_addr *);
446 extern int nl_addr_iszero(struct nl_addr *);
447 extern int nl_addr_valid(char *, int);
448 extern int nl_addr_guess_family(struct nl_addr *);
449 extern int nl_addr_fill_sockaddr(struct nl_addr *, struct sockaddr *, socklen_t *);
450 extern int nl_addr_info(struct nl_addr *, struct addrinfo **);
451 extern int nl_addr_resolve(struct nl_addr *addr, char *host, size_t hostlen);
452
453 extern void nl_addr_set_family(struct nl_addr *, int);
454 extern int nl_addr_get_family(struct nl_addr *);
455 extern int nl_addr_set_binary_addr(struct nl_addr *, void *, size_t);
456
457 extern void *nl_addr_get_binary_addr(struct nl_addr *);
458 extern unsigned int nl_addr_get_len(struct nl_addr *);
459 extern void nl_addr_set_prefixlen(struct nl_addr *, int);
460 extern unsigned int nl_addr_get_prefixlen(struct nl_addr *);
461
462 %cstring_output_maxsize(char *buf, size_t len)
463 extern char *nl_af2str(int, char *buf, size_t len);
464 extern int nl_str2af(const char *);
465
466 %cstring_output_maxsize(char *buf, size_t len)
467 extern char *nl_addr2str(struct nl_addr *, char *buf, size_t len);
468
469 /* Message Handlers <netlink/handlers.h> */
470 /**
471 * Callback actions
472 * @ingroup cb
473 */
474 enum nl_cb_action {
475 /** Proceed with wathever would come next */
476 NL_OK,
477 /** Skip this message */
478 NL_SKIP,
479 /** Stop parsing altogether and discard remaining messages */
480 NL_STOP,
481 };
482
483 /**
484 * Callback kinds
485 * @ingroup cb
486 */
487 enum nl_cb_kind {
488 /** Default handlers (quiet) */
489 NL_CB_DEFAULT,
490 /** Verbose default handlers (error messages printed) */
491 NL_CB_VERBOSE,
492 /** Debug handlers for debugging */
493 NL_CB_DEBUG,
494 /** Customized handler specified by the user */
495 NL_CB_CUSTOM,
496 __NL_CB_KIND_MAX,
497 };
498
499 #define NL_CB_KIND_MAX (__NL_CB_KIND_MAX - 1)
500
501 /**
502 * Callback types
503 * @ingroup cb
504 */
505 enum nl_cb_type {
506 /** Message is valid */
507 NL_CB_VALID,
508 /** Last message in a series of multi part messages received */
509 NL_CB_FINISH,
510 /** Report received that data was lost */
511 NL_CB_OVERRUN,
512 /** Message wants to be skipped */
513 NL_CB_SKIPPED,
514 /** Message is an acknowledge */
515 NL_CB_ACK,
516 /** Called for every message received */
517 NL_CB_MSG_IN,
518 /** Called for every message sent out except for nl_sendto() */
519 NL_CB_MSG_OUT,
520 /** Message is malformed and invalid */
521 NL_CB_INVALID,
522 /** Called instead of internal sequence number checking */
523 NL_CB_SEQ_CHECK,
524 /** Sending of an acknowledge message has been requested */
525 NL_CB_SEND_ACK,
526 /** Flag NLM_F_DUMP_INTR is set in message */
527 NL_CB_DUMP_INTR,
528 __NL_CB_TYPE_MAX,
529 };
530
531 #define NL_CB_TYPE_MAX (__NL_CB_TYPE_MAX - 1)
532
533 extern struct nl_cb *nl_cb_alloc(enum nl_cb_kind);
534 extern struct nl_cb *nl_cb_clone(struct nl_cb *);
535
536 struct nlmsgerr {
537 int error;
538 };
539
540 %{
541
542 struct pynl_callback {
543 PyObject *cbf;
544 PyObject *cba;
545 };
546
547 struct pynl_cbinfo {
548 struct nl_cb *cb;
549 struct pynl_callback cbtype[NL_CB_TYPE_MAX+1];
550 struct pynl_callback cberr;
551 struct list_head list;
552 };
553
554 LIST_HEAD(callback_list);
555
pynl_find_cbinfo(struct nl_cb * cb,int unlink)556 static struct pynl_cbinfo *pynl_find_cbinfo(struct nl_cb *cb, int unlink)
557 {
558 struct list_head *pos, *prev;
559 struct pynl_cbinfo *info;
560
561 list_for_each_safe(pos, prev, &callback_list) {
562 info = container_of(pos, struct pynl_cbinfo, list);
563 if (info->cb == cb) {
564 if (unlink)
565 list_del(pos, prev);
566 pynl_dbg("cb=%p: found=%p\n", cb, info);
567 return info;
568 }
569 }
570 pynl_dbg("cb=%p: not found\n", cb);
571 return NULL;
572 }
573
pynl_get_cbinfo(struct nl_cb * cb,int unlink)574 static struct pynl_cbinfo *pynl_get_cbinfo(struct nl_cb *cb, int unlink)
575 {
576 struct pynl_cbinfo *info;
577
578 info = pynl_find_cbinfo(cb, unlink);
579
580 if (info || unlink) {
581 /* found or no need to allocate a new one */
582 pynl_dbg("cb=%p: done\n", cb);
583 return info;
584 }
585
586 info = calloc(1, sizeof(*info));
587 info->cb = cb;
588 list_add(&info->list, &callback_list);
589 pynl_dbg("cb=%p: added %p\n", cb, info);
590 return info;
591 }
592
nl_recv_msg_handler(struct nl_msg * msg,void * arg)593 static int nl_recv_msg_handler(struct nl_msg *msg, void *arg)
594 {
595 struct pynl_callback *cbd = arg;
596 PyObject *msgobj;
597 PyObject *cbparobj;
598 PyObject *resobj;
599 PyObject *funcobj;
600 int result;
601
602 if (!cbd) {
603 result = NL_STOP;
604 goto done;
605 }
606 msgobj = SWIG_NewPointerObj(SWIG_as_voidptr(msg),
607 SWIGTYPE_p_nl_msg, 0 | 0 );
608 /* add selfobj if callback is a method */
609 if (cbd->cbf && PyMethod_Check(cbd->cbf)) {
610 PyObject *selfobj = PyMethod_Self(cbd->cbf);
611 cbparobj = Py_BuildValue("(OOO)", selfobj ? selfobj : cbd->cba,
612 msgobj, cbd->cba);
613 funcobj = PyMethod_Function(cbd->cbf);
614 pynl_dbg("callback %sbounded instance method %p\n",
615 selfobj ? "" : "un", funcobj);
616 } else {
617 cbparobj = Py_BuildValue("(OO)", msgobj, cbd->cba);
618 funcobj = cbd->cbf;
619 pynl_dbg("callback function %p\n", funcobj);
620 }
621 resobj = PyObject_CallObject(funcobj, cbparobj);
622 Py_DECREF(cbparobj);
623 if (resobj && PyInt_Check(resobj))
624 result = (int)PyInt_AsLong(resobj);
625 else
626 result = NL_STOP;
627 Py_XDECREF(resobj);
628 done:
629 pynl_dbg("result=%d\n", result);
630 return result;
631 }
632
nl_recv_err_handler(struct sockaddr_nl * nla,struct nlmsgerr * err,void * arg)633 static int nl_recv_err_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
634 void *arg)
635 {
636 struct pynl_callback *cbd = arg;
637 PyObject *errobj;
638 PyObject *cbparobj;
639 PyObject *resobj;
640 PyObject *funcobj;
641 int result;
642
643 if (!cbd)
644 return NL_STOP;
645 errobj = SWIG_NewPointerObj(SWIG_as_voidptr(err),
646 SWIGTYPE_p_nlmsgerr, 0 | 0 );
647 /* add selfobj if callback is a method */
648 if (cbd->cbf && PyMethod_Check(cbd->cbf)) {
649 PyObject *selfobj = PyMethod_Self(cbd->cbf);
650 cbparobj = Py_BuildValue("(OOO)", selfobj ? selfobj : cbd->cba,
651 errobj, cbd->cba);
652 funcobj = PyMethod_Function(cbd->cbf);
653 } else {
654 cbparobj = Py_BuildValue("(OO)", errobj, cbd->cba);
655 funcobj = cbd->cbf;
656 }
657 resobj = PyObject_CallObject(funcobj, cbparobj);
658 Py_DECREF(cbparobj);
659 if (resobj && PyInt_Check(resobj))
660 result = (int)PyInt_AsLong(resobj);
661 else
662 result = NL_STOP;
663 Py_XDECREF(resobj);
664 pynl_dbg("error: err=%d ret=%d\n", err->error, result);
665 return result;
666 }
667
668 %}
669 %inline %{
py_nl_cb_clone(struct nl_cb * cb)670 struct nl_cb *py_nl_cb_clone(struct nl_cb *cb)
671 {
672 struct pynl_cbinfo *info, *clone_info;
673 struct nl_cb *clone;
674 int i;
675
676 clone = nl_cb_clone(cb);
677 info = pynl_find_cbinfo(cb, 0);
678 if (info) {
679 clone_info = pynl_get_cbinfo(clone, 0);
680 /* increase refcnt to callback parameters and copy them */
681 for (i = 0; info && i <= NL_CB_TYPE_MAX; i++) {
682 Py_XINCREF(info->cbtype[i].cbf);
683 Py_XINCREF(info->cbtype[i].cba);
684 clone_info->cbtype[i].cbf = info->cbtype[i].cbf;
685 clone_info->cbtype[i].cba = info->cbtype[i].cba;
686 }
687 Py_XINCREF(info->cberr.cbf);
688 Py_XINCREF(info->cberr.cba);
689 clone_info->cberr.cbf = info->cberr.cbf;
690 clone_info->cberr.cba = info->cberr.cba;
691 }
692 return clone;
693 }
694
py_nl_cb_put(struct nl_cb * cb)695 void py_nl_cb_put(struct nl_cb *cb)
696 {
697 struct pynl_cbinfo *info;
698 int i;
699
700 /* obtain callback info (and unlink) */
701 info = pynl_get_cbinfo(cb, 1);
702 pynl_dbg("cb=%p, info=%p\n", cb, info);
703 /* decrease refcnt for callback type handlers */
704 for (i = 0; info && i <= NL_CB_TYPE_MAX; i++) {
705 Py_XDECREF(info->cbtype[i].cbf);
706 Py_XDECREF(info->cbtype[i].cba);
707 }
708 /* decrease refcnt for error handler and free callback info */
709 if (info) {
710 Py_XDECREF(info->cberr.cbf);
711 Py_XDECREF(info->cberr.cba);
712 free(info);
713 }
714 nl_cb_put(cb);
715 }
716
py_nl_cb_set(struct nl_cb * cb,enum nl_cb_type t,enum nl_cb_kind k,PyObject * func,PyObject * a)717 int py_nl_cb_set(struct nl_cb *cb, enum nl_cb_type t, enum nl_cb_kind k,
718 PyObject *func, PyObject *a)
719 {
720 struct pynl_cbinfo *info;
721
722 /* obtain callback info */
723 info = pynl_get_cbinfo(cb, 0);
724
725 /* clear existing handlers (if any) */
726 Py_XDECREF(info->cbtype[t].cbf);
727 Py_XDECREF(info->cbtype[t].cba);
728 info->cbtype[t].cbf = NULL;
729 info->cbtype[t].cba = NULL;
730 pynl_dbg("cb=%p, info=%p, type=%d, kind=%d\n", cb, info, t, k);
731 /* handle custom callback */
732 if (k == NL_CB_CUSTOM) {
733 Py_XINCREF(func);
734 Py_XINCREF(a);
735 info->cbtype[t].cbf = func;
736 info->cbtype[t].cba = a;
737 return nl_cb_set(cb, t, k,
738 nl_recv_msg_handler, &info->cbtype[t]);
739 }
740 return nl_cb_set(cb, t, k, NULL, NULL);
741 }
742
py_nl_cb_set_all(struct nl_cb * cb,enum nl_cb_kind k,PyObject * func,PyObject * a)743 int py_nl_cb_set_all(struct nl_cb *cb, enum nl_cb_kind k,
744 PyObject *func , PyObject *a)
745 {
746 struct pynl_cbinfo *info;
747 int t;
748
749 info = pynl_get_cbinfo(cb, 0);
750 pynl_dbg("cb=%p, info=%p, kind=%d\n", cb, info, k);
751 for (t = 0; t <= NL_CB_TYPE_MAX; t++) {
752 /* (possibly) free existing handler */
753 Py_XDECREF(info->cbtype[t].cbf);
754 Py_XDECREF(info->cbtype[t].cba);
755 info->cbtype[t].cbf = NULL;
756 info->cbtype[t].cba = NULL;
757 if (k == NL_CB_CUSTOM) {
758 Py_XINCREF(func);
759 Py_XINCREF(a);
760 info->cbtype[t].cbf = func;
761 info->cbtype[t].cba = a;
762 }
763 }
764 if (k == NL_CB_CUSTOM)
765 /* callback argument is same for all so using idx 0 here */
766 return nl_cb_set_all(cb, k, nl_recv_msg_handler,
767 &info->cbtype[0]);
768 else
769 return nl_cb_set_all(cb, k, NULL, NULL);
770 }
771
py_nl_cb_err(struct nl_cb * cb,enum nl_cb_kind k,PyObject * func,PyObject * a)772 int py_nl_cb_err(struct nl_cb *cb, enum nl_cb_kind k,
773 PyObject *func, PyObject *a)
774 {
775 struct pynl_cbinfo *info;
776
777 /* obtain callback info */
778 info = pynl_get_cbinfo(cb, 0);
779 pynl_dbg("cb=%p, info=%p, kind=%d\n", cb, info, k);
780 /* clear existing handlers (if any) */
781 Py_XDECREF(info->cberr.cbf);
782 Py_XDECREF(info->cberr.cba);
783 info->cberr.cbf = NULL;
784 info->cberr.cba = NULL;
785
786 /* handle custom callback */
787 if (k == NL_CB_CUSTOM) {
788 Py_XINCREF(func);
789 Py_XINCREF(a);
790 info->cberr.cbf = func;
791 info->cberr.cba = a;
792 return nl_cb_err(cb, k,
793 nl_recv_err_handler, &info->cberr);
794 }
795 return nl_cb_err(cb, k, NULL, NULL);
796 }
797 %}
798
799 /* Attributes <netlink/attr.h> */
800 /*
801 * This typemap is a bit tricky as it uses arg1, which is knowledge about
802 * the SWIGged wrapper output.
803 */
804 %typemap(out) void * {
805 $result = PyByteArray_FromStringAndSize($1, nla_len(arg1));
806 }
807 extern void *nla_data(struct nlattr *);
808 %typemap(out) void *;
809 extern int nla_type(const struct nlattr *);
810
811 /* Integer attribute */
812 extern uint8_t nla_get_u8(struct nlattr *);
813 extern int nla_put_u8(struct nl_msg *, int, uint8_t);
814 extern uint16_t nla_get_u16(struct nlattr *);
815 extern int nla_put_u16(struct nl_msg *, int, uint16_t);
816 extern uint32_t nla_get_u32(struct nlattr *);
817 extern int nla_put_u32(struct nl_msg *, int, uint32_t);
818 extern uint64_t nla_get_u64(struct nlattr *);
819 extern int nla_put_u64(struct nl_msg *, int, uint64_t);
820
821 /* String attribute */
822 extern char * nla_get_string(struct nlattr *);
823 extern char * nla_strdup(struct nlattr *);
824 extern int nla_put_string(struct nl_msg *, int, const char *);
825
826 /* Flag attribute */
827 extern int nla_get_flag(struct nlattr *);
828 extern int nla_put_flag(struct nl_msg *, int);
829
830 /* Msec attribute */
831 extern unsigned long nla_get_msecs(struct nlattr *);
832 extern int nla_put_msecs(struct nl_msg *, int, unsigned long);
833
834 /* Attribute nesting */
835 extern int nla_put_nested(struct nl_msg *, int, struct nl_msg *);
836 extern struct nlattr * nla_nest_start(struct nl_msg *, int);
837 extern int nla_nest_end(struct nl_msg *, struct nlattr *);
838 %inline %{
py_nla_parse_nested(int max,struct nlattr * nest_attr,PyObject * p)839 PyObject *py_nla_parse_nested(int max, struct nlattr *nest_attr, PyObject *p)
840 {
841 struct nlattr *tb_msg[max + 1];
842 struct nla_policy *policy = NULL;
843 void *pol;
844 PyObject *attrs = Py_None;
845 PyObject *k;
846 PyObject *v;
847 PyObject *resobj;
848 int err;
849 int i;
850
851 if (p != Py_None) {
852 PyObject *pobj;
853
854 if (!PyList_Check(p)) {
855 fprintf(stderr, "expected list object\n");
856 err = -1;
857 goto fail;
858 }
859 pobj = PyList_GetItem(p, 0);
860 err = SWIG_ConvertPtr(pobj, &pol, SWIGTYPE_p_nla_policy, 0 | 0 );
861 if (!SWIG_IsOK(err))
862 goto fail;
863 policy = pol;
864 }
865 err = nla_parse_nested(tb_msg, max, nest_attr, policy);
866 if (err < 0) {
867 fprintf(stderr, "Failed to parse response message\n");
868 } else {
869 attrs = PyDict_New();
870 for (i = 0; i <= max; i++)
871 if (tb_msg[i]) {
872 k = PyInt_FromLong((long)i);
873 v = SWIG_NewPointerObj(SWIG_as_voidptr(tb_msg[i]), SWIGTYPE_p_nlattr, 0 | 0 );
874 PyDict_SetItem(attrs, k, v);
875 }
876 }
877 fail:
878 if (attrs == Py_None)
879 Py_INCREF(attrs);
880 resobj = Py_BuildValue("(iO)", err, attrs);
881 return resobj;
882 }
883
884 /*
885 * nla_get_nested() - get list of nested attributes.
886 *
887 * nla_for_each_<nested|attr>() is a macro construct that needs another approach
888 * for Python. Create and return list of nested attributes.
889 */
nla_get_nested(struct nlattr * nest_attr)890 PyObject *nla_get_nested(struct nlattr *nest_attr)
891 {
892 PyObject *listobj;
893 PyObject *nestattrobj;
894 struct nlattr *pos;
895 int rem;
896
897 listobj = PyList_New(0);
898 nla_for_each_nested(pos, nest_attr, rem) {
899 nestattrobj = SWIG_NewPointerObj(SWIG_as_voidptr(pos),
900 SWIGTYPE_p_nlattr, 0 | 0 );
901 PyList_Append(listobj, nestattrobj);
902 }
903 return listobj;
904 }
905 %}
906
907 /**
908 * @ingroup attr
909 * Basic attribute data types
910 *
911 * See \ref attr_datatypes for more details.
912 */
913 enum {
914 NLA_UNSPEC, /**< Unspecified type, binary data chunk */
915 NLA_U8, /**< 8 bit integer */
916 NLA_U16, /**< 16 bit integer */
917 NLA_U32, /**< 32 bit integer */
918 NLA_U64, /**< 64 bit integer */
919 NLA_STRING, /**< NUL terminated character string */
920 NLA_FLAG, /**< Flag */
921 NLA_MSECS, /**< Micro seconds (64bit) */
922 NLA_NESTED, /**< Nested attributes */
923 __NLA_TYPE_MAX,
924 };
925
926 #define NLA_TYPE_MAX (__NLA_TYPE_MAX - 1)
927
928 /** @} */
929
930 /**
931 * @ingroup attr
932 * Attribute validation policy.
933 *
934 * See \ref attr_datatypes for more details.
935 */
936 struct nla_policy {
937 /** Type of attribute or NLA_UNSPEC */
938 uint16_t type;
939
940 /** Minimal length of payload required */
941 uint16_t minlen;
942
943 /** Maximal length of payload allowed */
944 uint16_t maxlen;
945 };
946
947 %inline %{
nla_policy_array(int n_items)948 PyObject *nla_policy_array(int n_items)
949 {
950 struct nla_policy *policies;
951 PyObject *listobj;
952 PyObject *polobj;
953 int i;
954
955 policies = calloc(n_items, sizeof(*policies));
956 listobj = PyList_New(n_items);
957 for (i = 0; i < n_items; i++) {
958 polobj = SWIG_NewPointerObj(SWIG_as_voidptr(&policies[i]),
959 SWIGTYPE_p_nla_policy, 0 | 0 );
960 PyList_SetItem(listobj, i, polobj);
961 }
962 return listobj;
963 }
964 %}
965