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