Home | History | Annotate | Download | only in netlink
      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 %{
     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 
     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 %{
    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 
    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 %{
    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 */
    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 %{
    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 
    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 
    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 
    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 
    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 %{
    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 
    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 
    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 
    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 
    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 %{
    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  */
    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 %{
    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