blob: e5d8a53649241bc3b7228e71793dfee8019c5159 [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001%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 %{
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
30 void free_dump_params(struct nl_dump_params *dp)
31 {
32 free(dp);
33 }
34%};
35
36/* <netlink/types.h> */
37
38enum 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
45struct 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> */
123extern unsigned int if_nametoindex(const char *ifname);
124
125/* <netlink/errno.h> */
126extern const char *nl_geterror(int);
127
128/* <netlink/utils.h> */
129
130extern double nl_cancel_down_bytes(unsigned long long, char **);
131extern double nl_cancel_down_bits(unsigned long long, char **);
132%cstring_output_maxsize(char *buf, size_t len)
133extern int nl_rate2str(unsigned long long rate, int type, char *buf, size_t len);
134extern double nl_cancel_down_us(uint32_t, char **);
135
136extern long nl_size2int(const char *);
137%cstring_output_maxsize(char *buf, const size_t len)
138extern char *nl_size2str(const size_t, char *buf, const size_t len);
139extern long nl_prob2int(const char *);
140
141extern int nl_get_user_hz(void);
142extern uint32_t nl_us2ticks(uint32_t);
143extern uint32_t nl_ticks2us(uint32_t);
144extern int nl_str2msec(const char *, uint64_t *);
145
146%cstring_output_maxsize(char *buf, size_t len)
147extern char *nl_msec2str(uint64_t, char *buf, size_t len);
148
149%cstring_output_maxsize(char *buf, size_t len)
150extern char *nl_llproto2str(int, char *buf, size_t len);
151extern int nl_str2llproto(const char *);
152
153%cstring_output_maxsize(char *buf, size_t len)
154extern char *nl_ether_proto2str(int, char *buf, size_t len);
155extern int nl_str2ether_proto(const char *);
156
157%cstring_output_maxsize(char *buf, size_t len)
158extern char *nl_ip_proto2str(int, char *buf, size_t len);
159extern int nl_str2ip_proto(const char *);
160
161extern void nl_new_line(struct nl_dump_params *);
162extern void nl_dump(struct nl_dump_params *, const char *, ...);
163extern void nl_dump_line(struct nl_dump_params *, const char *, ...);
164
165/* <netlink/netlink.h> */
166extern struct nl_dump_params *alloc_dump_params(void);
167extern void free_dump_params(struct nl_dump_params *);
168
169extern int nl_connect(struct nl_sock *, int);
170extern void nl_close(struct nl_sock *);
171
172/* <netlink/socket.h> */
173extern struct nl_sock *nl_socket_alloc(void);
174extern struct nl_sock *nl_socket_alloc_cb(struct nl_cb *);
175extern void nl_socket_free(struct nl_sock *);
176
177extern uint32_t nl_socket_get_local_port(const struct nl_sock *);
178extern void nl_socket_set_local_port(struct nl_sock *, uint32_t);
179
180extern uint32_t nl_socket_get_peer_port(const struct nl_sock *);
181extern void nl_socket_set_peer_port(struct nl_sock *, uint32_t);
182
183extern uint32_t nl_socket_get_peer_groups(const struct nl_sock *sk);
184extern void nl_socket_set_peer_groups(struct nl_sock *sk, uint32_t groups);
185
186extern int nl_socket_set_buffer_size(struct nl_sock *, int, int);
187extern void nl_socket_set_cb(struct nl_sock *, struct nl_cb *);
188
189extern int nl_send_auto_complete(struct nl_sock *, struct nl_msg *);
190extern int nl_recvmsgs(struct nl_sock *, struct nl_cb *);
191
192/* <netlink/msg.h> */
193extern int nlmsg_size(int);
194extern int nlmsg_total_size(int);
195extern int nlmsg_padlen(int);
196
197extern void * nlmsg_data(const struct nlmsghdr *);
198extern int nlmsg_datalen(const struct nlmsghdr *);
199extern void * nlmsg_tail(const struct nlmsghdr *);
200
201/* attribute access */
202extern struct nlattr * nlmsg_attrdata(const struct nlmsghdr *, int);
203extern int nlmsg_attrlen(const struct nlmsghdr *, int);
204
205/* message parsing */
206extern int nlmsg_valid_hdr(const struct nlmsghdr *, int);
207extern int nlmsg_ok(const struct nlmsghdr *, int);
208extern struct nlmsghdr * nlmsg_next(struct nlmsghdr *, int *);
209extern int nlmsg_parse(struct nlmsghdr *, int, struct nlattr **,
210 int, struct nla_policy *);
211extern struct nlattr * nlmsg_find_attr(struct nlmsghdr *, int, int);
212extern int nlmsg_validate(struct nlmsghdr *, int, int,
213 struct nla_policy *);
214
215extern struct nl_msg * nlmsg_alloc(void);
216extern struct nl_msg * nlmsg_alloc_size(size_t);
217extern struct nl_msg * nlmsg_alloc_simple(int, int);
218extern void nlmsg_set_default_size(size_t);
219extern struct nl_msg * nlmsg_inherit(struct nlmsghdr *);
220extern struct nl_msg * nlmsg_convert(struct nlmsghdr *);
221extern void * nlmsg_reserve(struct nl_msg *, size_t, int);
222extern int nlmsg_append(struct nl_msg *, void *, size_t, int);
223extern int nlmsg_expand(struct nl_msg *, size_t);
224
225extern struct nlmsghdr * nlmsg_put(struct nl_msg *, uint32_t, uint32_t,
226 int, int, int);
227extern struct nlmsghdr * nlmsg_hdr(struct nl_msg *);
228extern void nlmsg_get(struct nl_msg *);
229extern void nlmsg_free(struct nl_msg *);
230
231/* attribute modification */
232extern void nlmsg_set_proto(struct nl_msg *, int);
233extern int nlmsg_get_proto(struct nl_msg *);
234extern size_t nlmsg_get_max_size(struct nl_msg *);
235extern void nlmsg_set_src(struct nl_msg *, struct sockaddr_nl *);
236extern struct sockaddr_nl *nlmsg_get_src(struct nl_msg *);
237extern void nlmsg_set_dst(struct nl_msg *, struct sockaddr_nl *);
238extern struct sockaddr_nl *nlmsg_get_dst(struct nl_msg *);
239extern void nlmsg_set_creds(struct nl_msg *, struct ucred *);
240extern struct ucred * nlmsg_get_creds(struct nl_msg *);
241
242extern char * nl_nlmsgtype2str(int, char *, size_t);
243extern int nl_str2nlmsgtype(const char *);
244
245extern char * nl_nlmsg_flags2str(int, char *, size_t);
246
247extern int nl_msg_parse(struct nl_msg *,
248 void (*cb)(struct nl_object *, void *),
249 void *);
250
251extern void nl_msg_dump(struct nl_msg *, FILE *);
252
253%inline %{
254 struct nl_object *cast_obj(void *obj)
255 {
256 return (struct nl_object *) obj;
257 }
258
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
270extern struct nl_object *nl_object_alloc(struct nl_object_ops *);
271extern void nl_object_free(struct nl_object *);
272extern struct nl_object *nl_object_clone(struct nl_object *);
273extern void nl_object_get(struct nl_object *);
274extern void nl_object_put(struct nl_object *);
275extern int nl_object_shared(struct nl_object *);
276
277%cstring_output_maxsize(char *buf, size_t len)
278extern void nl_object_dump_buf(struct nl_object *, char *buf, size_t len);
279
280extern void nl_object_dump(struct nl_object *, struct nl_dump_params *);
281
282extern int nl_object_identical(struct nl_object *, struct nl_object *);
283extern uint32_t nl_object_diff(struct nl_object *, struct nl_object *);
284extern int nl_object_match_filter(struct nl_object *, struct nl_object *);
285
286%cstring_output_maxsize(char *buf, size_t len)
287extern char *nl_object_attrs2str(struct nl_object *, uint32_t, char *buf, size_t len);
288
289%cstring_output_maxsize(char *buf, size_t len)
290extern char *nl_object_attr_list(struct nl_object *, char *buf, size_t len);
291
292extern void nl_object_mark(struct nl_object *);
293extern void nl_object_unmark(struct nl_object *);
294extern int nl_object_is_marked(struct nl_object *);
295
296extern int nl_object_get_refcnt(struct nl_object *);
297
298/* <netlink/cache.h> */
299
300typedef void (*change_func_t)(struct nl_cache *, struct nl_object *, int, void *);
301
302%inline %{
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
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
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 */
336extern int nl_cache_nitems(struct nl_cache *);
337extern int nl_cache_nitems_filter(struct nl_cache *,
338 struct nl_object *);
339extern struct nl_cache_ops * nl_cache_get_ops(struct nl_cache *);
340extern struct nl_object * nl_cache_get_first(struct nl_cache *);
341extern struct nl_object * nl_cache_get_last(struct nl_cache *);
342extern struct nl_object * nl_cache_get_next(struct nl_object *);
343extern struct nl_object * nl_cache_get_prev(struct nl_object *);
344
345extern struct nl_cache * nl_cache_alloc(struct nl_cache_ops *);
346extern struct nl_cache * nl_cache_subset(struct nl_cache *,
347 struct nl_object *);
348extern void nl_cache_clear(struct nl_cache *);
349extern void nl_cache_free(struct nl_cache *);
350
351/* Cache modification */
352extern int nl_cache_add(struct nl_cache *,
353 struct nl_object *);
354extern int nl_cache_parse_and_add(struct nl_cache *,
355 struct nl_msg *);
356extern void nl_cache_remove(struct nl_object *);
357extern int nl_cache_refill(struct nl_sock *,
358 struct nl_cache *);
359extern int nl_cache_pickup(struct nl_sock *,
360 struct nl_cache *);
361extern int nl_cache_resync(struct nl_sock *,
362 struct nl_cache *,
363 change_func_t,
364 void *);
365extern int nl_cache_include(struct nl_cache *,
366 struct nl_object *,
367 change_func_t,
368 void *);
369extern void nl_cache_set_arg1(struct nl_cache *, int);
370extern void nl_cache_set_arg2(struct nl_cache *, int);
371
372/* General */
373extern int nl_cache_is_empty(struct nl_cache *);
374extern struct nl_object * nl_cache_search(struct nl_cache *,
375 struct nl_object *);
376extern void nl_cache_mark_all(struct nl_cache *);
377
378/* Dumping */
379extern void nl_cache_dump(struct nl_cache *,
380 struct nl_dump_params *);
381extern void nl_cache_dump_filter(struct nl_cache *,
382 struct nl_dump_params *,
383 struct nl_object *);
384
385/* Iterators */
386extern void nl_cache_foreach(struct nl_cache *,
387 void (*cb)(struct nl_object *,
388 void *),
389 void *arg);
390extern 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 */
400extern struct nl_cache_ops * nl_cache_ops_lookup(const char *);
401extern struct nl_cache_ops * nl_cache_ops_associate(int, int);
402extern struct nl_msgtype * nl_msgtype_lookup(struct nl_cache_ops *, int);
403extern void nl_cache_ops_foreach(void (*cb)(struct nl_cache_ops *, void *), void *);
404extern int nl_cache_mngt_register(struct nl_cache_ops *);
405extern int nl_cache_mngt_unregister(struct nl_cache_ops *);
406
407/* Global cache provisioning/requiring */
408extern void nl_cache_mngt_provide(struct nl_cache *);
409extern void nl_cache_mngt_unprovide(struct nl_cache *);
410extern struct nl_cache * nl_cache_mngt_require(const char *);
411
412struct nl_cache_mngr;
413
414#define NL_AUTO_PROVIDE 1
415
416extern int nl_cache_mngr_get_fd(struct nl_cache_mngr *);
417extern int nl_cache_mngr_poll(struct nl_cache_mngr *,
418 int);
419extern int nl_cache_mngr_data_ready(struct nl_cache_mngr *);
420extern void nl_cache_mngr_free(struct nl_cache_mngr *);
421
422/* <netlink/addr.h> */
423%inline %{
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
435extern struct nl_addr *nl_addr_alloc(size_t);
436extern struct nl_addr *nl_addr_alloc_attr(struct nlattr *, int);
437extern struct nl_addr *nl_addr_build(int, void *, size_t);
438extern struct nl_addr *nl_addr_clone(struct nl_addr *);
439
440extern struct nl_addr *nl_addr_get(struct nl_addr *);
441extern void nl_addr_put(struct nl_addr *);
442extern int nl_addr_shared(struct nl_addr *);
443
444extern int nl_addr_cmp(struct nl_addr *, struct nl_addr *);
445extern int nl_addr_cmp_prefix(struct nl_addr *, struct nl_addr *);
446extern int nl_addr_iszero(struct nl_addr *);
447extern int nl_addr_valid(char *, int);
448extern int nl_addr_guess_family(struct nl_addr *);
449extern int nl_addr_fill_sockaddr(struct nl_addr *, struct sockaddr *, socklen_t *);
450extern int nl_addr_info(struct nl_addr *, struct addrinfo **);
451extern int nl_addr_resolve(struct nl_addr *addr, char *host, size_t hostlen);
452
453extern void nl_addr_set_family(struct nl_addr *, int);
454extern int nl_addr_get_family(struct nl_addr *);
455extern int nl_addr_set_binary_addr(struct nl_addr *, void *, size_t);
456
457extern void *nl_addr_get_binary_addr(struct nl_addr *);
458extern unsigned int nl_addr_get_len(struct nl_addr *);
459extern void nl_addr_set_prefixlen(struct nl_addr *, int);
460extern unsigned int nl_addr_get_prefixlen(struct nl_addr *);
461
462%cstring_output_maxsize(char *buf, size_t len)
463extern char *nl_af2str(int, char *buf, size_t len);
464extern int nl_str2af(const char *);
465
466%cstring_output_maxsize(char *buf, size_t len)
467extern 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 */
474enum 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 */
487enum 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 */
505enum 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
533extern struct nl_cb *nl_cb_alloc(enum nl_cb_kind);
534extern struct nl_cb *nl_cb_clone(struct nl_cb *);
535
536struct nlmsgerr {
537 int error;
538};
539
540%{
541
542struct pynl_callback {
543 PyObject *cbf;
544 PyObject *cba;
545};
546
547struct 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
554LIST_HEAD(callback_list);
555
556static 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
574static 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
593static 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);
628done:
629 pynl_dbg("result=%d\n", result);
630 return result;
631}
632
633static 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 %{
670struct 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
695void 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
717int 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
743int 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
772int 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}
807extern void *nla_data(struct nlattr *);
808%typemap(out) void *;
809extern int nla_type(const struct nlattr *);
810
811/* Integer attribute */
812extern uint8_t nla_get_u8(struct nlattr *);
813extern int nla_put_u8(struct nl_msg *, int, uint8_t);
814extern uint16_t nla_get_u16(struct nlattr *);
815extern int nla_put_u16(struct nl_msg *, int, uint16_t);
816extern uint32_t nla_get_u32(struct nlattr *);
817extern int nla_put_u32(struct nl_msg *, int, uint32_t);
818extern uint64_t nla_get_u64(struct nlattr *);
819extern int nla_put_u64(struct nl_msg *, int, uint64_t);
820
821/* String attribute */
822extern char * nla_get_string(struct nlattr *);
823extern char * nla_strdup(struct nlattr *);
824extern int nla_put_string(struct nl_msg *, int, const char *);
825
826/* Flag attribute */
827extern int nla_get_flag(struct nlattr *);
828extern int nla_put_flag(struct nl_msg *, int);
829
830/* Msec attribute */
831extern unsigned long nla_get_msecs(struct nlattr *);
832extern int nla_put_msecs(struct nl_msg *, int, unsigned long);
833
834/* Attribute nesting */
835extern int nla_put_nested(struct nl_msg *, int, struct nl_msg *);
836extern struct nlattr * nla_nest_start(struct nl_msg *, int);
837extern int nla_nest_end(struct nl_msg *, struct nlattr *);
838%inline %{
839PyObject *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 }
877fail:
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 */
890PyObject *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 */
913enum {
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 */
936struct 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 %{
948PyObject *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%}