From c1073d6172223be9837141da149c8876ce46884b Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 22 Mar 2011 00:40:26 +0100 Subject: [PATCH 001/432] Documentation updates Mostly killing doxygen warnings, some doc updates to caching --- include/netlink/cache-api.h | 24 ++++ lib/cache.c | 211 +++++++++++++++++++++++++----------- lib/cache_mngr.c | 4 +- lib/fib_lookup/lookup.c | 3 +- lib/msg.c | 2 +- lib/object.c | 6 +- lib/route/class.c | 3 +- lib/route/link.c | 3 +- lib/route/neigh.c | 2 +- lib/route/pktloc.c | 3 +- lib/route/route.c | 3 +- lib/route/rule.c | 8 +- 12 files changed, 198 insertions(+), 74 deletions(-) diff --git a/include/netlink/cache-api.h b/include/netlink/cache-api.h index 22fc449..efae2ed 100644 --- a/include/netlink/cache-api.h +++ b/include/netlink/cache-api.h @@ -151,21 +151,40 @@ struct nl_af_group #define END_OF_GROUP_LIST AF_UNSPEC, 0 +/** + * Parser parameters + * + * This structure is used to configure what kind of parser to use + * when parsing netlink messages to create objects. + */ struct nl_parser_param { + /** Function to parse netlink messages into objects */ int (*pp_cb)(struct nl_object *, struct nl_parser_param *); + + /** Arbitary argument to be passed to the parser */ void * pp_arg; }; /** * Cache Operations + * + * This structure defines the characterstics of a cache type. It contains + * pointers to functions which implement the specifics of the object type + * the cache can hold. */ struct nl_cache_ops { + /** Name of cache type (must be unique) */ char * co_name; + /** Size of family specific netlink header */ int co_hdrsize; + + /** Netlink protocol */ int co_protocol; + + /** Group definition */ struct nl_af_group * co_groups; /** @@ -182,11 +201,16 @@ struct nl_cache_ops int (*co_msg_parser)(struct nl_cache_ops *, struct sockaddr_nl *, struct nlmsghdr *, struct nl_parser_param *); + /** Object operations */ struct nl_object_ops * co_obj_ops; + /** Internal, do not touch! */ struct nl_cache_ops *co_next; + struct nl_cache *co_major_cache; struct genl_ops * co_genl; + + /* Message type definition */ struct nl_msgtype co_msgtypes[]; }; diff --git a/lib/cache.c b/lib/cache.c index 601dadc..ece354c 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -160,15 +160,18 @@ struct nl_object *nl_cache_get_prev(struct nl_object *obj) /** @} */ /** - * @name Cache Creation/Deletion + * @name Cache Allocation/Deletion * @{ */ /** - * Allocate an empty cache - * @arg ops cache operations to base the cache on - * - * @return A newly allocated and initialized cache. + * Allocate new cache + * @arg ops Cache operations + * + * Allocate and initialize a new cache based on the cache operations + * provided. + * + * @return Allocated cache or NULL if allocation failed. */ struct nl_cache *nl_cache_alloc(struct nl_cache_ops *ops) { @@ -186,6 +189,22 @@ struct nl_cache *nl_cache_alloc(struct nl_cache_ops *ops) return cache; } +/** + * Allocate new cache and fill it + * @arg ops Cache operations + * @arg sock Netlink socket + * @arg result Result pointer + * + * Allocate new cache and fill it. Equivalent to calling: + * @code + * cache = nl_cache_alloc(ops); + * nl_cache_refill(sock, cache); + * @endcode + * + * @see nl_cache_alloc + * + * @return 0 on success or a negative error code. + */ int nl_cache_alloc_and_fill(struct nl_cache_ops *ops, struct nl_sock *sock, struct nl_cache **result) { @@ -205,9 +224,17 @@ int nl_cache_alloc_and_fill(struct nl_cache_ops *ops, struct nl_sock *sock, } /** - * Allocate an empty cache based on type name + * Allocate new cache based on type name * @arg kind Name of cache type - * @return A newly allocated and initialized cache. + * @arg result Result pointer + * + * Lookup cache ops via nl_cache_ops_lookup() and allocate the cache + * by calling nl_cache_alloc(). Stores the allocated cache in the + * result pointer provided. + * + * @see nl_cache_alloc + * + * @return 0 on success or a negative error code. */ int nl_cache_alloc_name(const char *kind, struct nl_cache **result) { @@ -226,9 +253,18 @@ int nl_cache_alloc_name(const char *kind, struct nl_cache **result) } /** - * Allocate a new cache containing a subset of a cache - * @arg orig Original cache to be based on - * @arg filter Filter defining the subset to be filled into new cache + * Allocate new cache containing a subset of an existing cache + * @arg orig Original cache to base new cache on + * @arg filter Filter defining the subset to be filled into the new cache + * + * Allocates a new cache matching the type of the cache specified by + * \p orig. Iterates over the \p orig cache applying the specified + * \p filter and copies all objects that match to the new cache. + * + * The copied objects are clones but do not contain a reference to each + * other. Later modifications to objects in the original cache will + * not affect objects in the new cache. + * * @return A newly allocated cache or NULL. */ struct nl_cache *nl_cache_subset(struct nl_cache *orig, @@ -258,10 +294,15 @@ struct nl_cache *nl_cache_subset(struct nl_cache *orig, } /** - * Clear a cache. - * @arg cache cache to clear + * Remove all objects of a cache. + * @arg cache Cache to clear * - * Removes all elements of a cache. + * The objects are unliked/removed from the cache by calling + * nl_cache_remove() on each object in the cache. If any of the objects + * to not contain any further references to them, those objects will + * be freed. + * + * Unlike with nl_cache_free(), the cache is not freed just emptied. */ void nl_cache_clear(struct nl_cache *cache) { @@ -277,9 +318,10 @@ void nl_cache_clear(struct nl_cache *cache) * Free a cache. * @arg cache Cache to free. * - * Removes all elements of a cache and frees all memory. + * Calls nl_cache_clear() to remove all objects associated with the + * cache and frees the cache afterwards. * - * @note Use this function if you are working with allocated caches. + * @see nl_cache_clear() */ void nl_cache_free(struct nl_cache *cache) { @@ -312,12 +354,24 @@ static int __cache_add(struct nl_cache *cache, struct nl_object *obj) } /** - * Add object to a cache. - * @arg cache Cache to add object to + * Add object to cache. + * @arg cache Cache * @arg obj Object to be added to the cache * - * Adds the given object to the specified cache. The object is cloned - * if it has been added to another cache already. + * Adds the object \p obj to the specified \p cache. In case the object + * is already associated with another cache, the object is cloned before + * adding it to the cache. In this case, the sole reference to the object + * will be the one of the cache. Therefore clearing/freeing the cache + * will result in the object being freed again. + * + * If the object has not been associated with a cache yet, the reference + * counter of the object is incremented to account for the additional + * reference. + * + * The type of the object and cache must match, otherwise an error is + * returned (-NLE_OBJ_MISMATCH). + * + * @see nl_cache_move() * * @return 0 or a negative error code. */ @@ -345,8 +399,16 @@ int nl_cache_add(struct nl_cache *cache, struct nl_object *obj) * @arg cache Cache to move object to. * @arg obj Object subject to be moved * - * Removes the given object from its associated cache if needed - * and adds it to the new cache. + * Removes the the specified object \p obj from its associated cache + * and moves it to another cache. + * + * If the object is not associated with a cache, the function behaves + * just like nl_cache_add(). + * + * The type of the object and cache must match, otherwise an error is + * returned (-NLE_OBJ_MISMATCH). + * + * @see nl_cache_add() * * @return 0 on success or a negative error code. */ @@ -368,12 +430,14 @@ int nl_cache_move(struct nl_cache *cache, struct nl_object *obj) } /** - * Removes an object from a cache. - * @arg obj Object to remove from its cache + * Remove object from cache. + * @arg obj Object to remove from cache * - * Removes the object \c obj from the cache it is assigned to, since - * an object can only be assigned to one cache at a time, the cache - * must ne be passed along with it. + * Removes the object \c obj from the cache it is associated with. The + * reference counter of the object will be decremented. If the reference + * to the object was the only one remaining, the object will be freed. + * + * If no cache is associated with the object, this function is a NOP. */ void nl_cache_remove(struct nl_object *obj) { @@ -391,33 +455,6 @@ void nl_cache_remove(struct nl_object *obj) obj, cache, nl_cache_name(cache)); } -/** - * Search for an object in a cache - * @arg cache Cache to search in. - * @arg needle Object to look for. - * - * Iterates over the cache and looks for an object with identical - * identifiers as the needle. - * - * @return Reference to object or NULL if not found. - * @note The returned object must be returned via nl_object_put(). - */ -struct nl_object *nl_cache_search(struct nl_cache *cache, - struct nl_object *needle) -{ - struct nl_object *obj; - - nl_list_for_each_entry(obj, &cache->c_items, ce_list) { - if (nl_object_identical(obj, needle)) { - nl_object_get(obj); - return obj; - } - } - - return NULL; -} - - /** @} */ /** @@ -426,15 +463,28 @@ struct nl_object *nl_cache_search(struct nl_cache *cache, */ /** - * Request a full dump from the kernel to fill a cache + * Invoke the request-update operation * @arg sk Netlink socket. - * @arg cache Cache subjected to be filled. + * @arg cache Cache * - * Send a dumping request to the kernel causing it to dump all objects - * related to the specified cache to the netlink socket. + * This function causes the \e request-update function of the cache + * operations to be invoked. This usually causes a dump request to + * be sent over the netlink socket which triggers the kernel to dump + * all objects of a specific type to be dumped onto the netlink + * socket for pickup. * - * Use nl_cache_pickup() to read the objects from the socket and fill them - * into a cache. + * The behaviour of this function depends on the implemenation of + * the \e request_update function of each individual type of cache. + * + * This function will not have any effects on the cache (unless the + * request_update implementation of the cache operations does so). + * + * Use nl_cache_pickup() to pick-up (read) the objects from the socket + * and fill them into the cache. + * + * @see nl_cache_pickup(), nl_cache_resync() + * + * @return 0 on success or a negative error code. */ int nl_cache_request_full_dump(struct nl_sock *sk, struct nl_cache *cache) { @@ -461,6 +511,12 @@ static int update_msg_parser(struct nl_msg *msg, void *arg) } /** @endcond */ +/** + * Pick-up a netlink request-update with your own parser + * @arg sk Netlink socket + * @arg cache Cache + * @arg param Parser parameters + */ int __cache_pickup(struct nl_sock *sk, struct nl_cache *cache, struct nl_parser_param *param) { @@ -707,8 +763,41 @@ int nl_cache_refill(struct nl_sock *sk, struct nl_cache *cache) */ /** - * Mark all objects in a cache - * @arg cache Cache to mark all objects in + * Search object in cache + * @arg cache Cache + * @arg needle Object to look for. + * + * Searches the cache for an object which matches the object \p needle. + * The function nl_object_identical() is used to determine if the + * objects match. If a matching object is found, the reference counter + * is incremented and the object is returned. + * + * Therefore, if an object is returned, the reference to the object + * must be returned by calling nl_object_put() after usage. + * + * @return Reference to object or NULL if not found. + */ +struct nl_object *nl_cache_search(struct nl_cache *cache, + struct nl_object *needle) +{ + struct nl_object *obj; + + nl_list_for_each_entry(obj, &cache->c_items, ce_list) { + if (nl_object_identical(obj, needle)) { + nl_object_get(obj); + return obj; + } + } + + return NULL; +} + +/** + * Mark all objects of a cache + * @arg cache Cache + * + * Marks all objects of a cache by calling nl_object_mark() on each + * object associated with the cache. */ void nl_cache_mark_all(struct nl_cache *cache) { diff --git a/lib/cache_mngr.c b/lib/cache_mngr.c index 81052aa..cfa676b 100644 --- a/lib/cache_mngr.c +++ b/lib/cache_mngr.c @@ -143,8 +143,9 @@ found: * @arg sk Netlink socket. * @arg protocol Netlink Protocol this manager is used for * @arg flags Flags + * @arg result Result pointer * - * @return Newly allocated cache manager or NULL on failure. + * @return 0 on success or a negative error code. */ int nl_cache_mngr_alloc(struct nl_sock *sk, int protocol, int flags, struct nl_cache_mngr **result) @@ -196,6 +197,7 @@ errout: * @arg mngr Cache manager. * @arg name Name of cache to keep track of * @arg cb Function to be called upon changes. + * @arg data Argument passed on to change callback * @arg result Pointer to store added cache. * * Allocates a new cache of the specified type and adds it to the manager. diff --git a/lib/fib_lookup/lookup.c b/lib/fib_lookup/lookup.c index ce9c027..61984c7 100644 --- a/lib/fib_lookup/lookup.c +++ b/lib/fib_lookup/lookup.c @@ -192,6 +192,7 @@ struct nl_cache *flnl_result_alloc_cache(void) * Builds a netlink request message to do a lookup * @arg req Requested match. * @arg flags additional netlink message flags + * @arg result Result pointer * * Builds a new netlink message requesting a change of link attributes. * The netlink message header isn't fully equipped with all relevant @@ -201,7 +202,7 @@ struct nl_cache *flnl_result_alloc_cache(void) * and \a tmpl must contain the attributes to be changed set via * \c rtnl_link_set_* functions. * - * @return New netlink message + * @return 0 on success or a negative error code. * @note Not all attributes can be changed, see * \ref link_changeable "Changeable Attributes" for more details. */ diff --git a/lib/msg.c b/lib/msg.c index 5c852c0..62f0911 100644 --- a/lib/msg.c +++ b/lib/msg.c @@ -27,7 +27,7 @@ * Netlink header type \c NLMSG_DONE. * * @par - * The Netlink message header (\link nlmsghdr struct nlmsghdr\endlink) is shown below. + * The Netlink message header (struct nlmsghdr) is shown below. * @code * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 diff --git a/lib/object.c b/lib/object.c index d881ac9..4a1b356 100644 --- a/lib/object.c +++ b/lib/object.c @@ -63,9 +63,11 @@ struct nl_object *nl_object_alloc(struct nl_object_ops *ops) } /** - * Allocate a new object of kind specified by the name + * Allocate new object of kind specified by the name * @arg kind name of object type - * @return The new object or nULL + * @arg result Result pointer + * + * @return 0 on success or a negative error code. */ int nl_object_alloc_name(const char *kind, struct nl_object **result) { diff --git a/lib/route/class.c b/lib/route/class.c index 47356e2..a0f3758 100644 --- a/lib/route/class.c +++ b/lib/route/class.c @@ -309,11 +309,12 @@ void rtnl_class_foreach_cls(struct rtnl_class *class, struct nl_cache *cache, * @arg sk Netlink socket. * @arg ifindex interface index of the link the classes are * attached to. + * @arg result Result pointer * * Allocates a new cache, initializes it properly and updates it to * include all classes attached to the specified interface. * - * @return The cache or NULL if an error has occured. + * @return 0 on success or a negative error code. */ int rtnl_class_alloc_cache(struct nl_sock *sk, int ifindex, struct nl_cache **result) diff --git a/lib/route/link.c b/lib/route/link.c index f9039a1..bfb4150 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -1036,6 +1036,7 @@ struct rtnl_link *rtnl_link_get_by_name(struct nl_cache *cache, * @arg old link to be changed * @arg tmpl template with requested changes * @arg flags additional netlink message flags + * @arg result Result pointer * * Builds a new netlink message requesting a change of link attributes. * The netlink message header isn't fully equipped with all relevant @@ -1045,7 +1046,7 @@ struct rtnl_link *rtnl_link_get_by_name(struct nl_cache *cache, * and \a tmpl must contain the attributes to be changed set via * \c rtnl_link_set_* functions. * - * @return New netlink message + * @return 0 on success or a negative error code. * @note Not all attributes can be changed, see * \ref link_changeable "Changeable Attributes" for more details. */ diff --git a/lib/route/neigh.c b/lib/route/neigh.c index aa19faa..0cd0366 100644 --- a/lib/route/neigh.c +++ b/lib/route/neigh.c @@ -408,7 +408,7 @@ void rtnl_neigh_put(struct rtnl_neigh *neigh) /** * Build a neighbour cache including all neighbours currently configured in the kernel. - * @arg sk Netlink socket. + * @arg sock Netlink socket. * @arg result Pointer to store resulting cache. * * Allocates a new neighbour cache, initializes it properly and updates it diff --git a/lib/route/pktloc.c b/lib/route/pktloc.c index 823a3c7..4d7d9dd 100644 --- a/lib/route/pktloc.c +++ b/lib/route/pktloc.c @@ -20,7 +20,7 @@ * library and provides a well defined set of definitions for most common * protocol fields. * - * @subsection pktloc_examples Examples + * @section pktloc_examples Examples * @par Example 1.1 Looking up a packet location * @code * struct rtnl_pktloc *loc; @@ -151,6 +151,7 @@ errout: /** * Lookup packet location alias * @arg name Name of packet location. + * @arg result Result pointer * * Tries to find a matching packet location alias for the supplied * packet location name. diff --git a/lib/route/route.c b/lib/route/route.c index c85c225..f684f96 100644 --- a/lib/route/route.c +++ b/lib/route/route.c @@ -64,13 +64,14 @@ static int route_request_update(struct nl_cache *c, struct nl_sock *h) * @arg sk Netlink socket. * @arg family Address family of routes to cover or AF_UNSPEC * @arg flags Flags + * @arg result Result pointer * * Allocates a new cache, initializes it properly and updates it to * contain all routes currently configured in the kernel. * * @note The caller is responsible for destroying and freeing the * cache after using it. - * @return The cache or NULL if an error has occured. + * @return 0 on success or a negative error code. */ int rtnl_route_alloc_cache(struct nl_sock *sk, int family, int flags, struct nl_cache **result) diff --git a/lib/route/rule.c b/lib/route/rule.c index 36672d3..8fa54e9 100644 --- a/lib/route/rule.c +++ b/lib/route/rule.c @@ -319,7 +319,7 @@ void rtnl_rule_put(struct rtnl_rule *rule) /** * Build a rule cache including all rules currently configured in the kernel. - * @arg sk Netlink socket. + * @arg sock Netlink socket. * @arg family Address family or AF_UNSPEC. * @arg result Pointer to store resulting cache. * @@ -421,6 +421,7 @@ nla_put_failure: * Build netlink request message to add a new rule * @arg tmpl template with data of new rule * @arg flags additional netlink message flags + * @arg result Result pointer * * Builds a new netlink message requesting a addition of a new * rule. The netlink message header isn't fully equipped with @@ -428,7 +429,7 @@ nla_put_failure: * or supplemented as needed. \a tmpl must contain the attributes of the new * address set via \c rtnl_rule_set_* functions. * - * @return The netlink message + * @return 0 on success or a negative error code. */ int rtnl_rule_build_add_request(struct rtnl_rule *tmpl, int flags, struct nl_msg **result) @@ -476,6 +477,7 @@ int rtnl_rule_add(struct nl_sock *sk, struct rtnl_rule *tmpl, int flags) * Build a netlink request message to delete a rule * @arg rule rule to delete * @arg flags additional netlink message flags + * @arg result Result pointer * * Builds a new netlink message requesting a deletion of a rule. * The netlink message header isn't fully equipped with all relevant @@ -483,7 +485,7 @@ int rtnl_rule_add(struct nl_sock *sk, struct rtnl_rule *tmpl, int flags) * or supplemented as needed. \a rule must point to an existing * address. * - * @return The netlink message + * @return 0 on success or a negative error code. */ int rtnl_rule_build_delete_request(struct rtnl_rule *rule, int flags, struct nl_msg **result) From f0603a467b8c3719b6575d781b43aa0567180603 Mon Sep 17 00:00:00 2001 From: Daniel Walter Date: Tue, 22 Mar 2011 10:45:41 +0100 Subject: [PATCH 002/432] add missing checks for ROUTE_ATTR_MULTIPATH attached patch adds missing checks for ROUTE_ATTR_MULTIPATH when dealing with multipath routing. Affected functions rtnl_route_remove_nexthop rtnl_route_get_nexthops rtnl_route_get_nnexthops --- lib/route/route_obj.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/route/route_obj.c b/lib/route/route_obj.c index 2cbe2ae..d3b09ab 100644 --- a/lib/route/route_obj.c +++ b/lib/route/route_obj.c @@ -687,18 +687,26 @@ void rtnl_route_add_nexthop(struct rtnl_route *route, struct rtnl_nexthop *nh) void rtnl_route_remove_nexthop(struct rtnl_route *route, struct rtnl_nexthop *nh) { - route->rt_nr_nh--; - nl_list_del(&nh->rtnh_list); + if (route->ce_mask & ROUTE_ATTR_MULTIPATH) { + route->rt_nr_nh--; + nl_list_del(&nh->rtnh_list); + } } struct nl_list_head *rtnl_route_get_nexthops(struct rtnl_route *route) { - return &route->rt_nexthops; + if (route->ce_mask & ROUTE_ATTR_MULTIPATH) + return &route->rt_nexthops; + + return NULL; } int rtnl_route_get_nnexthops(struct rtnl_route *route) { - return route->rt_nr_nh; + if (route->ce_mask & ROUTE_ATTR_MULTIPATH) + return route->rt_nr_nh; + + return 0; } void rtnl_route_foreach_nexthop(struct rtnl_route *r, From 38db636f7877c7643463e51178e91695485eda27 Mon Sep 17 00:00:00 2001 From: Daniel Walter Date: Tue, 22 Mar 2011 10:53:51 +0100 Subject: [PATCH 003/432] add missing nl_cache_search in cache.h fix missing declaration of nl_cache_search --- include/netlink/cache.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/netlink/cache.h b/include/netlink/cache.h index c752920..61f94dd 100644 --- a/include/netlink/cache.h +++ b/include/netlink/cache.h @@ -68,6 +68,8 @@ extern int nl_cache_include(struct nl_cache *, /* General */ extern int nl_cache_is_empty(struct nl_cache *); +extern struct nl_object * nl_cache_search(struct nl_cache *, + struct nl_object *); extern void nl_cache_mark_all(struct nl_cache *); /* Dumping */ From a0fe7a1c9abe3ab5bf8c9253fab50e114b02b87b Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 23 Mar 2011 13:39:18 +0100 Subject: [PATCH 004/432] Omit empty nested attributes Check for empty nested attributes in nla_nest_end() and omit the attribute alltogether if is is the case. --- lib/attr.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/lib/attr.c b/lib/attr.c index cccd50d..a045351 100644 --- a/lib/attr.c +++ b/lib/attr.c @@ -1151,10 +1151,22 @@ struct nlattr *nla_nest_start(struct nl_msg *msg, int attrtype) */ int nla_nest_end(struct nl_msg *msg, struct nlattr *start) { - size_t pad; + size_t pad, len; - start->nla_len = (unsigned char *) nlmsg_tail(msg->nm_nlh) - - (unsigned char *) start; + len = (void *) nlmsg_tail(msg->nm_nlh) - (void *) start; + + if (len == NLA_HDRLEN) { + /* + * Kernel can't handle empty nested attributes, trim the + * attribute header again + */ + msg->nm_nlh->nlmsg_len -= NLA_HDRLEN; + memset(nlmsg_tail(msg->nm_nlh), 0, NLA_HDRLEN); + + return 0; + } + + start->nla_len = len; pad = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) - msg->nm_nlh->nlmsg_len; if (pad > 0) { From 913579b460b6e081e119e0ebdb662115857e0b43 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 14 Jan 2011 11:38:05 +0100 Subject: [PATCH 005/432] Fix out-of-tree build. This patch fixes out-of-tree build, that is, when building with $builddir != $srcdir. In such a case, some generated header files are not found because they live in a different tree and can be fixed by adding the directories to the compiler's include search path. --- lib/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Makefile.am b/lib/Makefile.am index ccedf43..5999113 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,6 +1,6 @@ # -*- Makefile -*- -AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -D_GNU_SOURCE -DSYSCONFDIR=\"$(sysconfdir)/libnl\" +AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -I${builddir}/route -I${builddir}/route/cls -D_GNU_SOURCE -DSYSCONFDIR=\"$(sysconfdir)/libnl\" AM_LDFLAGS = -version-info 3:0:0 lib_LTLIBRARIES = \ From 9f1abddb1af5b94d5e82dd12e7fa8ebf18acfc64 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 23 Mar 2011 15:57:52 +0100 Subject: [PATCH 006/432] Fix "make distcheck". This commit adds some missing files (some header files, the files below /etc and the bison/flex files) to the distribution tarball to ensure that libnl can be built from the tarballs created using "make dist". It also adds some incantations to properly generate the flex and bison output since the generated output is no longer shipped in the tarball. --- Makefile.am | 3 +++ include/Makefile.am | 50 +++++++++++++++++++++++++++++++++++++++++++++ lib/Makefile.am | 20 ++++++++++++++++-- 3 files changed, 71 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index 5931a9e..07017c8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -15,6 +15,9 @@ pkgconfig_DATA = libnl-3.0.pc sysconfdir = @sysconfdir@/libnl sysconf_DATA = etc/pktloc etc/classid +EXTRA_DIST = \ + $(sysconf_DATA) + .PHONY: cscope cscope: cscope -b -q -R -Iinclude -slib -ssrc; diff --git a/include/Makefile.am b/include/Makefile.am index e7f1206..50fde24 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,6 +1,17 @@ # -*- Makefile -*- nobase_include_HEADERS = \ + netlink/cli/addr.h \ + netlink/cli/class.h \ + netlink/cli/cls.h \ + netlink/cli/ct.h \ + netlink/cli/link.h \ + netlink/cli/neigh.h \ + netlink/cli/qdisc.h \ + netlink/cli/route.h \ + netlink/cli/rule.h \ + netlink/cli/tc.h \ + netlink/cli/utils.h \ netlink/fib_lookup/lookup.h \ netlink/fib_lookup/request.h \ netlink/genl/ctrl.h \ @@ -28,9 +39,17 @@ nobase_include_HEADERS = \ netlink/netlink.h \ netlink/object-api.h \ netlink/object.h \ + netlink/route/cls/ematch/cmp.h \ + netlink/route/cls/ematch/meta.h \ + netlink/route/cls/ematch/nbyte.h \ + netlink/route/cls/ematch/text.h \ + netlink/route/cls/basic.h \ + netlink/route/cls/cgroup.h \ + netlink/route/cls/ematch.h \ netlink/route/cls/fw.h \ netlink/route/cls/police.h \ netlink/route/cls/u32.h \ + netlink/route/link/api.h \ netlink/route/link/info-api.h \ netlink/route/link/vlan.h \ netlink/route/qdisc/cbq.h \ @@ -49,6 +68,7 @@ nobase_include_HEADERS = \ netlink/route/neighbour.h \ netlink/route/neightbl.h \ netlink/route/nexthop.h \ + netlink/route/pktloc.h \ netlink/route/qdisc.h \ netlink/route/route.h \ netlink/route/rtnl.h \ @@ -59,3 +79,33 @@ nobase_include_HEADERS = \ netlink/types.h \ netlink/utils.h \ netlink/version.h + +noinst_HEADERS = \ + linux/fib_rules.h \ + linux/genetlink.h \ + linux/gen_stats.h \ + linux/if_addr.h \ + linux/if_arp.h \ + linux/if_ether.h \ + linux/if.h \ + linux/if_link.h \ + linux/if_vlan.h \ + linux/inetdevice.h \ + linux/ip_mp_alg.h \ + linux/ipv6.h \ + linux/neighbour.h \ + linux/netfilter.h \ + linux/netfilter/nfnetlink_conntrack.h \ + linux/netfilter/nfnetlink.h \ + linux/netfilter/nfnetlink_log.h \ + linux/netfilter/nfnetlink_queue.h \ + linux/netlink.h \ + linux/pkt_cls.h \ + linux/pkt_sched.h \ + linux/rtnetlink.h \ + linux/snmp.h \ + linux/tc_ematch/tc_em_meta.h \ + netlink-generic.h \ + netlink-local.h \ + netlink-tc.h \ + netlink-types.h diff --git a/lib/Makefile.am b/lib/Makefile.am index 5999113..e8045b7 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -51,7 +51,6 @@ libnl_route_la_SOURCES = \ route/cls/fw.c route/cls/police.c route/cls/u32.c route/cls/basic.c \ route/cls/cgroup.c \ \ - route/cls/ematch_syntax.c route/cls/ematch_grammar.c \ route/cls/ematch.c \ route/cls/ematch/container.c route/cls/ematch/cmp.c \ route/cls/ematch/nbyte.c route/cls/ematch/text.c \ @@ -67,8 +66,25 @@ libnl_route_la_SOURCES = \ \ fib_lookup/lookup.c fib_lookup/request.c \ \ - route/pktloc_syntax.c route/pktloc_grammar.c route/pktloc.c + route/pktloc.c +nodist_libnl_route_la_SOURCES = \ + route/pktloc_syntax.c route/pktloc_syntax.h \ + route/pktloc_grammar.c route/pktloc_grammar.h \ + route/cls/ematch_syntax.c route/cls/ematch_syntax.h \ + route/cls/ematch_grammar.c route/cls/ematch_grammar.h + +BUILT_SOURCES = \ + route/cls/ematch_grammar.c \ + route/cls/ematch_syntax.c \ + route/pktloc_grammar.c \ + route/pktloc_syntax.c + +EXTRA_DIST = \ + route/pktloc_grammar.l \ + route/pktloc_syntax.y \ + route/cls/ematch_grammar.l \ + route/cls/ematch_syntax.y if ENABLE_CLI nobase_pkglib_LTLIBRARIES = \ From 14fa557ba94a4243b5963ea137412c5e1204ecb5 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 24 Mar 2011 12:59:57 +0100 Subject: [PATCH 007/432] Set default MTU to 1500 --- lib/route/tc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/route/tc.c b/lib/route/tc.c index e4faf92..56aa410 100644 --- a/lib/route/tc.c +++ b/lib/route/tc.c @@ -318,7 +318,7 @@ void rtnl_tc_set_mtu(struct rtnl_tc *tc, uint32_t mtu) * Returns the MTU of a traffic control object which has been set via: * -# User specified value set via rtnl_tc_set_mtu() * -# Dervied from link set via rtnl_tc_set_link() - * -# Fall back to default: ethernet = 1600 + * -# Fall back to default: ethernet = 1500 */ uint32_t rtnl_tc_get_mtu(struct rtnl_tc *tc) { @@ -327,7 +327,7 @@ uint32_t rtnl_tc_get_mtu(struct rtnl_tc *tc) else if (tc->ce_mask & TCA_ATTR_LINK) return tc->tc_link->l_mtu; else - return 1600; /* default to ethernet */ + return 1500; /* default to ethernet */ } /** From 93b6c114a8fa21e5e907a5b2415c7ffb441b0a8f Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 24 Mar 2011 16:56:10 +0100 Subject: [PATCH 008/432] Add NLE_NODEV error --- include/netlink/errno.h | 3 ++- lib/error.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/netlink/errno.h b/include/netlink/errno.h index dde12b7..93dc163 100644 --- a/include/netlink/errno.h +++ b/include/netlink/errno.h @@ -47,8 +47,9 @@ extern "C" { #define NLE_PERM 28 #define NLE_PKTLOC_FILE 29 #define NLE_PARSE_ERR 30 +#define NLE_NODEV 31 -#define NLE_MAX NLE_PARSE_ERR +#define NLE_MAX NLE_NODEV extern const char * nl_geterror(int); extern void nl_perror(int, const char *); diff --git a/lib/error.c b/lib/error.c index 02cbbf1..a31461e 100644 --- a/lib/error.c +++ b/lib/error.c @@ -44,6 +44,7 @@ static const char *errmsg[NLE_MAX+1] = { [NLE_PERM] = "Operation not permitted", [NLE_PKTLOC_FILE] = "Unable to open packet location file", [NLE_PARSE_ERR] = "Unable to parse object", +[NLE_NODEV] = "No such device", }; /** @@ -103,6 +104,7 @@ int nl_syserr2nlerr(int error) case EPERM: return NLE_PERM; case EBUSY: return NLE_BUSY; case ERANGE: return NLE_RANGE; + case ENODEV: return NLE_NODEV; default: return NLE_FAILURE; } } From a62bfdb8e0a1dffa7539fe813a96593c9c407686 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 24 Mar 2011 17:00:38 +0100 Subject: [PATCH 009/432] Check if all mandatory attributes are present in rtnl_tc_msg_build() TCA_ATTR_IFINDEX | TCA_ATTR_PARENT | TCA_ATTR_KIND --- lib/route/tc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/route/tc.c b/lib/route/tc.c index 56aa410..09ae044 100644 --- a/lib/route/tc.c +++ b/lib/route/tc.c @@ -189,7 +189,11 @@ int rtnl_tc_msg_build(struct rtnl_tc *tc, int type, int flags, .tcm_handle = tc->tc_handle, .tcm_parent = tc->tc_parent, }; - int err = -NLE_MSGSIZE; + int req, err = -NLE_MSGSIZE; + + req = (TCA_ATTR_IFINDEX | TCA_ATTR_PARENT | TCA_ATTR_KIND); + if ((tc->ce_mask & req) != req) + return -NLE_MISSING_ATTR; msg = nlmsg_alloc_simple(type, flags); if (!msg) From 8d5493418a5a82b5303722cd9b2964300813e693 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 24 Mar 2011 20:57:43 +0100 Subject: [PATCH 010/432] Cleanup - remove dead prototypes - reformat --- include/netlink/route/qdisc.h | 20 +++++++++----------- lib/route/qdisc.c | 3 ++- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/include/netlink/route/qdisc.h b/include/netlink/route/qdisc.h index 966eb44..a08fca1 100644 --- a/include/netlink/route/qdisc.h +++ b/include/netlink/route/qdisc.h @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2011 Thomas Graf */ #ifndef NETLINK_QDISC_H_ @@ -22,15 +22,17 @@ extern "C" { struct rtnl_qdisc; -extern struct nl_object_ops qdisc_obj_ops; - -extern struct rtnl_qdisc *rtnl_qdisc_alloc(void); +extern struct rtnl_qdisc * + rtnl_qdisc_alloc(void); extern void rtnl_qdisc_put(struct rtnl_qdisc *); extern int rtnl_qdisc_alloc_cache(struct nl_sock *, struct nl_cache **); -extern struct rtnl_qdisc *rtnl_qdisc_get(struct nl_cache *, int, uint32_t); -extern struct rtnl_qdisc *rtnl_qdisc_get_by_parent(struct nl_cache *, - int, uint32_t); + +extern struct rtnl_qdisc * + rtnl_qdisc_get(struct nl_cache *, int, uint32_t); + +extern struct rtnl_qdisc * + rtnl_qdisc_get_by_parent(struct nl_cache *, int, uint32_t); extern int rtnl_qdisc_build_add_request(struct rtnl_qdisc *, int, struct nl_msg **); @@ -46,8 +48,6 @@ extern int rtnl_qdisc_build_delete_request(struct rtnl_qdisc *, struct nl_msg **); extern int rtnl_qdisc_delete(struct nl_sock *, struct rtnl_qdisc *); -extern void rtnl_qdisc_set_kind(struct rtnl_qdisc *, const char *); - extern void rtnl_qdisc_foreach_child(struct rtnl_qdisc *, struct nl_cache *, void (*cb)(struct nl_object *, void *), void *); @@ -56,8 +56,6 @@ extern void rtnl_qdisc_foreach_cls(struct rtnl_qdisc *, struct nl_cache *, void (*cb)(struct nl_object *, void *), void *); -extern struct nl_msg * rtnl_qdisc_get_opts(struct rtnl_qdisc *); - #ifdef __cplusplus } #endif diff --git a/lib/route/qdisc.c b/lib/route/qdisc.c index 6ec3a40..d0f2edc 100644 --- a/lib/route/qdisc.c +++ b/lib/route/qdisc.c @@ -93,6 +93,7 @@ #include static struct nl_cache_ops rtnl_qdisc_ops; +static struct nl_object_ops qdisc_obj_ops; static int qdisc_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, struct nlmsghdr *n, struct nl_parser_param *pp) @@ -514,7 +515,7 @@ static struct nl_cache_ops rtnl_qdisc_ops = { .co_obj_ops = &qdisc_obj_ops, }; -struct nl_object_ops qdisc_obj_ops = { +static struct nl_object_ops qdisc_obj_ops = { .oo_name = "route/qdisc", .oo_size = sizeof(struct rtnl_qdisc), .oo_free_data = rtnl_tc_free_data, From f523f297f7fed8b64fe4c2a6e3791d31b2d2448b Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 24 Mar 2011 21:14:52 +0100 Subject: [PATCH 011/432] Allow NLSYSCONFDIR environment variable to overwrite built-in sysconfdir --- include/netlink-local.h | 12 ++++++++++++ lib/route/classid.c | 5 +++-- lib/route/pktloc.c | 3 ++- src/Makefile.am | 2 +- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/include/netlink-local.h b/include/netlink-local.h index 32e8302..9acc0e4 100644 --- a/include/netlink-local.h +++ b/include/netlink-local.h @@ -186,4 +186,16 @@ static inline int wait_for_ack(struct nl_sock *sk) return nl_wait_for_ack(sk); } +static inline int build_sysconf_path(char **strp, const char *filename) +{ + char *sysconfdir; + + sysconfdir = getenv("NLSYSCONFDIR"); + + if (!sysconfdir) + sysconfdir = SYSCONFDIR; + + return asprintf(strp, "%s/%s", sysconfdir, filename); +} + #endif diff --git a/lib/route/classid.c b/lib/route/classid.c index 35cafe6..6af0ee3 100644 --- a/lib/route/classid.c +++ b/lib/route/classid.c @@ -310,7 +310,8 @@ int rtnl_tc_read_classid_file(void) FILE *fd; int err; - asprintf(&path, "%s/classid", SYSCONFDIR); + if (build_sysconf_path(&path, "classid") < 0) + return -NLE_NOMEM; /* if stat fails, just (re-)read the file */ if (stat(path, &st) == 0) { @@ -392,7 +393,7 @@ int rtnl_classid_generate(const char *name, uint32_t *result, uint32_t parent) NL_DBG(2, "Generated new classid %#x\n", classid); - if (asprintf(&path, "%s/classid", SYSCONFDIR) < 0) + if (build_sysconf_path(&path, "classid") < 0) return -NLE_NOMEM; if (!(fd = fopen(path, "a"))) { diff --git a/lib/route/pktloc.c b/lib/route/pktloc.c index 4d7d9dd..b677ab5 100644 --- a/lib/route/pktloc.c +++ b/lib/route/pktloc.c @@ -94,7 +94,8 @@ static int read_pktlocs(void) int i, err; FILE *fd; - asprintf(&path, "%s/pktloc", SYSCONFDIR); + if (build_sysconf_path(&path, "pktloc") < 0) + return -NLE_NOMEM; /* if stat fails, just try to read the file */ if (stat(path, &st) == 0) { diff --git a/src/Makefile.am b/src/Makefile.am index 64d1cce..e196b58 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,7 +2,7 @@ SUBDIRS = lib -AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -D_GNU_SOURCE +AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -D_GNU_SOURCE -DSYSCONFDIR=\"$(sysconfdir)/libnl\" AM_LDFLAGS = -L${top_builddir}/lib -L${top_builddir}/src/lib -lnl-cli -lnl -lnl-nf -lnl-genl -lnl-route sbin_PROGRAMS = \ From e4b507e290475b59b08a022b1805f693d7867355 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 24 Mar 2011 22:50:11 +0100 Subject: [PATCH 012/432] Deprecate rtnl_qdisc_foreach_child() and rtnl_qdisc_foreach_cls() Their usage is not completely safe, it is not possible to handle the out of memory situation of the allocate filter. It is very unlikely for this to cause any problem though. The functions are still accessible but gcc will warn about their deprecation. --- include/netlink/route/qdisc.h | 5 +++-- lib/route/qdisc.c | 31 +++++++++++++------------------ src/nl-tctree-list.c | 18 +++++++++++++++++- 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/include/netlink/route/qdisc.h b/include/netlink/route/qdisc.h index a08fca1..fbff666 100644 --- a/include/netlink/route/qdisc.h +++ b/include/netlink/route/qdisc.h @@ -48,13 +48,14 @@ extern int rtnl_qdisc_build_delete_request(struct rtnl_qdisc *, struct nl_msg **); extern int rtnl_qdisc_delete(struct nl_sock *, struct rtnl_qdisc *); +/* Deprecated functions */ extern void rtnl_qdisc_foreach_child(struct rtnl_qdisc *, struct nl_cache *, void (*cb)(struct nl_object *, void *), - void *); + void *) __attribute__ ((deprecated)); extern void rtnl_qdisc_foreach_cls(struct rtnl_qdisc *, struct nl_cache *, void (*cb)(struct nl_object *, void *), - void *); + void *) __attribute__ ((deprecated)); #ifdef __cplusplus } diff --git a/lib/route/qdisc.c b/lib/route/qdisc.c index d0f2edc..5257b9d 100644 --- a/lib/route/qdisc.c +++ b/lib/route/qdisc.c @@ -429,17 +429,15 @@ void rtnl_qdisc_put(struct rtnl_qdisc *qdisc) /** @} */ /** - * @name Iterators + * @name Deprecated Functions * @{ */ /** - * Call a callback for each child class of a qdisc - * @arg qdisc the parent qdisc - * @arg cache a class cache including all classes of the interface - * the specified qdisc is attached to - * @arg cb callback function - * @arg arg argument to be passed to callback function + * Call a callback for each child class of a qdisc (deprecated) + * + * @deprecated Use of this function is deprecated, it does not allow + * to handle the out of memory situation that can occur. */ void rtnl_qdisc_foreach_child(struct rtnl_qdisc *qdisc, struct nl_cache *cache, void (*cb)(struct nl_object *, void *), void *arg) @@ -460,26 +458,23 @@ void rtnl_qdisc_foreach_child(struct rtnl_qdisc *qdisc, struct nl_cache *cache, } /** - * Call a callback for each filter attached to the qdisc - * @arg qdisc the parent qdisc - * @arg cache a filter cache including at least all the filters - * attached to the specified qdisc - * @arg cb callback function - * @arg arg argument to be passed to callback function + * Call a callback for each filter attached to the qdisc (deprecated) + * + * @deprecated Use of this function is deprecated, it does not allow + * to handle the out of memory situation that can occur. */ void rtnl_qdisc_foreach_cls(struct rtnl_qdisc *qdisc, struct nl_cache *cache, void (*cb)(struct nl_object *, void *), void *arg) { struct rtnl_cls *filter; - filter = rtnl_cls_alloc(); - if (!filter) + if (!(filter = rtnl_cls_alloc())) return; - rtnl_tc_set_ifindex((struct rtnl_tc *) filter, qdisc->q_ifindex); - rtnl_tc_set_parent((struct rtnl_tc *) filter, qdisc->q_parent); + rtnl_tc_set_ifindex(TC_CAST(filter), qdisc->q_ifindex); + rtnl_tc_set_parent(TC_CAST(filter), qdisc->q_parent); - nl_cache_foreach_filter(cache, (struct nl_object *) filter, cb, arg); + nl_cache_foreach_filter(cache, OBJ_CAST(filter), cb, arg); rtnl_cls_put(filter); } diff --git a/src/nl-tctree-list.c b/src/nl-tctree-list.c index 4cd5035..9407345 100644 --- a/src/nl-tctree-list.c +++ b/src/nl-tctree-list.c @@ -12,6 +12,7 @@ #include #include #include +#include #include static struct nl_sock *sock; @@ -60,6 +61,21 @@ static void print_class(struct nl_object *obj, void *arg) nl_cache_free(cls_cache); } +static void print_qdisc_childs(struct rtnl_qdisc *qdisc, void *arg) +{ + struct rtnl_tc *tc = TC_CAST(qdisc); + struct rtnl_class *filter; + + filter = nl_cli_class_alloc(); + + rtnl_tc_set_parent(TC_CAST(filter), rtnl_tc_get_handle(tc)); + rtnl_tc_set_ifindex(TC_CAST(filter), rtnl_tc_get_ifindex(tc)); + + nl_cache_foreach_filter(class_cache, OBJ_CAST(filter), &print_class, arg); + + rtnl_class_put(filter); +} + static void print_qdisc(struct nl_object *obj, void *arg) { struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) obj; @@ -69,7 +85,7 @@ static void print_qdisc(struct nl_object *obj, void *arg) params.dp_prefix = (int)(long) arg; nl_object_dump(obj, ¶ms); - rtnl_qdisc_foreach_child(qdisc, class_cache, &print_class, arg + 2); + print_qdisc_childs(qdisc, arg + 2); if (rtnl_cls_alloc_cache(sock, ifindex, parent, &cls_cache) < 0) return; From 7e9d5f69e54d209955f3a0154751e1a526a69c9f Mon Sep 17 00:00:00 2001 From: Nicolas Sitbon Date: Fri, 25 Mar 2011 15:07:23 +0100 Subject: [PATCH 013/432] correctly handle the object not found case Removing non existent route (both ipv4 and ipv6) using rtnl_route_delete return NLE_FAILURE generic error code. After investigation, it seems the linux kernel return -ESRCH in that case (see http://lxr.linux.no/linux+v2.6.38/net/ipv6/route.c#L1367). Same behaviour apply for removing non existent address. The function nl_syserr2nlerr (lib/error.c) which is responsible for translating from kernel error to libnl error doesn't handle ESRCH. --- lib/error.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/error.c b/lib/error.c index a31461e..b973cdd 100644 --- a/lib/error.c +++ b/lib/error.c @@ -88,6 +88,7 @@ int nl_syserr2nlerr(int error) case EADDRINUSE: return NLE_EXIST; case EEXIST: return NLE_EXIST; case EADDRNOTAVAIL: return NLE_NOADDR; + case ESRCH: /* fall through */ case ENOENT: return NLE_OBJ_NOTFOUND; case EINTR: return NLE_INTR; case EAGAIN: return NLE_AGAIN; From 23845e942cc8fdad05f722b384266cb0a166edc3 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 25 Mar 2011 18:11:52 +0100 Subject: [PATCH 014/432] Add nl_send_sync() Function which sends message using nl_send_auto(), frees the message and waits for ACK/error message (if auto-ack is not disabled). --- include/netlink/netlink.h | 1 + lib/nl.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/include/netlink/netlink.h b/include/netlink/netlink.h index 099a83e..a13c48f 100644 --- a/include/netlink/netlink.h +++ b/include/netlink/netlink.h @@ -59,6 +59,7 @@ extern void nl_auto_complete(struct nl_sock *, extern int nl_send_auto(struct nl_sock *, struct nl_msg *); extern int nl_send_auto_complete(struct nl_sock *, struct nl_msg *); +extern int nl_send_sync(struct nl_sock *, struct nl_msg *); extern int nl_send_simple(struct nl_sock *, int, int, void *, size_t); diff --git a/lib/nl.c b/lib/nl.c index 8f6f5f1..b70242c 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -345,6 +345,37 @@ int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg) return nl_send_auto(sk, msg); } +/** + * Send netlink message and wait for response (sync request-response) + * @arg sk Netlink socket + * @arg msg Netlink message to be sent + * + * This function takes a netlink message and sends it using nl_send_auto(). + * It will then wait for the response (ACK or error message) to be + * received. Threfore this function will block until the operation has + * been completed. + * + * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause + * this function to return immediately after sending. In this case, + * it is the responsibility of the caller to handle any eventual + * error messages returned. + * + * @see nl_send_auto(). + * + * @return 0 on success or a negative error code. + */ +int nl_send_sync(struct nl_sock *sk, struct nl_msg *msg) +{ + int err; + + err = nl_send_auto(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return wait_for_ack(sk); +} + /** * Send simple netlink message using nl_send_auto_complete() * @arg sk Netlink socket. From 747b892c91de7a852664f015405d6d37ea2b66b6 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 25 Mar 2011 18:13:19 +0100 Subject: [PATCH 015/432] Qdisc API improvements and documentation Deprecated the functions rtnl_qdisc_change() and rtnl_qdisc_build_change_request() for their lack of being able to specify flags. The new functions rtnl_qdisc_update() and rtnl_qdisc_build_update_request() may be used instead. The old functions are still available though. However, rtnl_qdisc_update() no longer implies NLM_F_REPLACE, it has to specified implicitely to allow updating a qdisc without risking to replace another qdisc. Included detailed documentation of qdisc addition/update/deletion. Introduced APPBUG() macro to let application developer know of API abuse. --- include/netlink-local.h | 9 +- include/netlink/route/qdisc.h | 29 +- lib/route/qdisc.c | 730 ++++++++++++++++++---------------- lib/route/tc.c | 6 +- 4 files changed, 411 insertions(+), 363 deletions(-) diff --git a/include/netlink-local.h b/include/netlink-local.h index 9acc0e4..63dd661 100644 --- a/include/netlink-local.h +++ b/include/netlink-local.h @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2011 Thomas Graf */ #ifndef NETLINK_LOCAL_H_ @@ -88,6 +88,13 @@ struct trans_list { assert(0); \ } while (0) +#define APPBUG(msg) \ + do { \ + fprintf(stderr, "APPLICATION BUG: %s:%d:%s: %s\n", \ + __FILE__, __LINE__, __PRETTY_FUNCTION__, msg); \ + assert(0); \ + } while(0) + extern int __nl_read_num_str_file(const char *path, int (*cb)(long, const char *)); diff --git a/include/netlink/route/qdisc.h b/include/netlink/route/qdisc.h index fbff666..10b85c5 100644 --- a/include/netlink/route/qdisc.h +++ b/include/netlink/route/qdisc.h @@ -38,24 +38,33 @@ extern int rtnl_qdisc_build_add_request(struct rtnl_qdisc *, int, struct nl_msg **); extern int rtnl_qdisc_add(struct nl_sock *, struct rtnl_qdisc *, int); -extern int rtnl_qdisc_build_change_request(struct rtnl_qdisc *, +extern int rtnl_qdisc_build_update_request(struct rtnl_qdisc *, struct rtnl_qdisc *, - struct nl_msg **); -extern int rtnl_qdisc_change(struct nl_sock *, struct rtnl_qdisc *, - struct rtnl_qdisc *); + int, struct nl_msg **); + +extern int rtnl_qdisc_update(struct nl_sock *, struct rtnl_qdisc *, + struct rtnl_qdisc *, int); extern int rtnl_qdisc_build_delete_request(struct rtnl_qdisc *, struct nl_msg **); extern int rtnl_qdisc_delete(struct nl_sock *, struct rtnl_qdisc *); /* Deprecated functions */ -extern void rtnl_qdisc_foreach_child(struct rtnl_qdisc *, struct nl_cache *, - void (*cb)(struct nl_object *, void *), - void *) __attribute__ ((deprecated)); +extern void rtnl_qdisc_foreach_child(struct rtnl_qdisc *, struct nl_cache *, + void (*cb)(struct nl_object *, void *), + void *) __attribute__ ((deprecated)); -extern void rtnl_qdisc_foreach_cls(struct rtnl_qdisc *, struct nl_cache *, - void (*cb)(struct nl_object *, void *), - void *) __attribute__ ((deprecated)); +extern void rtnl_qdisc_foreach_cls(struct rtnl_qdisc *, struct nl_cache *, + void (*cb)(struct nl_object *, void *), + void *) __attribute__ ((deprecated)); + +extern int rtnl_qdisc_build_change_request(struct rtnl_qdisc *, + struct rtnl_qdisc *, + struct nl_msg **) + __attribute__ ((deprecated)); + +extern int rtnl_qdisc_change(struct nl_sock *, struct rtnl_qdisc *, + struct rtnl_qdisc *) __attribute__ ((deprecated)); #ifdef __cplusplus } diff --git a/lib/route/qdisc.c b/lib/route/qdisc.c index 5257b9d..e5a8aa0 100644 --- a/lib/route/qdisc.c +++ b/lib/route/qdisc.c @@ -12,73 +12,6 @@ /** * @ingroup tc * @defgroup qdisc Queueing Disciplines - * - * @par Qdisc Handles - * In general, qdiscs are identified by the major part of a traffic control - * handle (the upper 16 bits). A few special values exist though: - * - \c TC_H_ROOT: root qdisc (directly attached to the device) - * - \c TC_H_INGRESS: ingress qdisc (directly attached to the device) - * - \c TC_H_UNSPEC: unspecified qdisc (no reference) - * - * @par 1) Adding a Qdisc - * @code - * // Allocate a new empty qdisc to be filled out - * struct rtnl_qdisc *qdisc = rtnl_qdisc_alloc(); - * - * // ... specify the kind of the Qdisc - * rtnl_qdisc_set_kind(qdisc, "pfifo"); - * - * // Specify the device the qdisc should be attached to - * rtnl_qdisc_set_ifindex(qdisc, ifindex); - * - * // ... specify the parent qdisc - * rtnl_qdisc_set_parent(qdisc, TC_H_ROOT); - * - * // Specifying the handle is not required but makes reidentifying easier - * // and may help to avoid adding a qdisc twice. - * rtnl_qdisc_set_handle(qdisc, 0x000A0000); - * - * // Now on to specify the qdisc specific options, see the relevant qdisc - * // modules for documentation, in this example we set the upper limit of - * // the packet fifo qdisc to 64 - * rtnl_qdisc_fifo_set_limit(qdisc, 64); - * - * rtnl_qdisc_add(handle, qdisc, NLM_R_REPLACE); - * - * // Free up the memory - * rtnl_qdisc_put(qdisc); - * @endcode - * - * @par 2) Deleting a Qdisc - * @code - * // Allocate a new empty qdisc to be filled out with the parameters - * // specifying the qdisc to be deleted. Alternatively a fully equiped - * // Qdisc object from a cache can be used. - * struct rtnl_qdisc *qdisc = rtnl_qdisc_alloc(); - * - * // The interface index of the device the qdisc is on and the parent handle - * // are the least required fields to be filled out. - * // Note: Specify TC_H_ROOT or TC_H_INGRESS as parent handle to delete the - * // root respectively root ingress qdisc. - * rtnl_qdisc_set_ifindex(qdisc, ifindex); - * rtnl_qdisc_set_parent(qdisc, parent_handle); - * - * // If required for identification, the handle can be specified as well. - * rtnl_qdisc_set_handle(qdisc, qdisc_handle); - * - * // Not required but maybe helpful as sanity check, the kind of the qdisc - * // can be specified to avoid mistakes. - * rtnl_qdisc_set_kind(qdisc, "pfifo"); - * - * // Finally delete the qdisc with rtnl_qdisc_delete(), alternatively - * // rtnl_qdisc_build_delete_request() can be invoked to generate an - * // appropritate netlink message to send out. - * rtnl_qdisc_delete(handle, qdisc); - * - * // Free up the memory - * rtnl_qdisc_put(qdisc); - * @endcode - * * @{ */ @@ -125,286 +58,6 @@ static int qdisc_request_update(struct nl_cache *c, struct nl_sock *sk) sizeof(tchdr)); } -/** - * @name QDisc Addition - * @{ - */ - -static int qdisc_build(struct rtnl_qdisc *qdisc, int type, int flags, - struct nl_msg **result) -{ - return rtnl_tc_msg_build(TC_CAST(qdisc), type, flags, result); - -#if 0 - /* Some qdiscs don't accept properly nested messages (e.g. netem). To - * accomodate for this, they can complete the message themselves. - */ - else if (qops && qops->qo_build_msg) { - err = qops->qo_build_msg(qdisc, *result); - if (err < 0) - goto errout; - } -#endif -} - -/** - * Build a netlink message to add a new qdisc - * @arg qdisc qdisc to add - * @arg flags additional netlink message flags - * @arg result Pointer to store resulting message. - * - * Builds a new netlink message requesting an addition of a qdisc. - * The netlink message header isn't fully equipped with all relevant - * fields and must be sent out via nl_send_auto_complete() or - * supplemented as needed. - * - * Common message flags used: - * - NLM_F_REPLACE - replace a potential existing qdisc - * - * @return 0 on success or a negative error code. - */ -int rtnl_qdisc_build_add_request(struct rtnl_qdisc *qdisc, int flags, - struct nl_msg **result) -{ - return qdisc_build(qdisc, RTM_NEWQDISC, NLM_F_CREATE | flags, result); -} - -/** - * Add a new qdisc - * @arg sk Netlink socket. - * @arg qdisc qdisc to delete - * @arg flags additional netlink message flags - * - * Builds a netlink message by calling rtnl_qdisc_build_add_request(), - * sends the request to the kernel and waits for the ACK to be - * received and thus blocks until the request has been processed. - * - * Common message flags used: - * - NLM_F_REPLACE - replace a potential existing qdisc - * - * @return 0 on success or a negative error code - */ -int rtnl_qdisc_add(struct nl_sock *sk, struct rtnl_qdisc *qdisc, - int flags) -{ - struct nl_msg *msg; - int err; - - if ((err = rtnl_qdisc_build_add_request(qdisc, flags, &msg)) < 0) - return err; - - err = nl_send_auto_complete(sk, msg); - nlmsg_free(msg); - if (err < 0) - return err; - - return wait_for_ack(sk); -} - -/** @} */ - -/** - * @name QDisc Modification - * @{ - */ - -/** - * Build a netlink message to change attributes of a existing qdisc - * @arg qdisc qdisc to change - * @arg new new qdisc attributes - * @arg result Pointer to store resulting message. - * - * Builds a new netlink message requesting an change of qdisc - * attributes. The netlink message header isn't fully equipped - * with all relevant fields and must be sent out via - * nl_send_auto_complete() or supplemented as needed. - * - * @return 0 on success or a negative error code. - */ -int rtnl_qdisc_build_change_request(struct rtnl_qdisc *qdisc, - struct rtnl_qdisc *new, - struct nl_msg **result) -{ - return qdisc_build(qdisc, RTM_NEWQDISC, NLM_F_REPLACE, result); -} - -/** - * Change attributes of a qdisc - * @arg sk Netlink socket. - * @arg qdisc qdisc to change - * @arg new new qdisc attributes - * - * Builds a netlink message by calling rtnl_qdisc_build_change_request(), - * sends the request to the kernel and waits for the ACK to be - * received and thus blocks until the request has been processed. - * - * @return 0 on success or a negative error code - */ -int rtnl_qdisc_change(struct nl_sock *sk, struct rtnl_qdisc *qdisc, - struct rtnl_qdisc *new) -{ - struct nl_msg *msg; - int err; - - if ((err = rtnl_qdisc_build_change_request(qdisc, new, &msg)) < 0) - return err; - - err = nl_send_auto_complete(sk, msg); - nlmsg_free(msg); - if (err < 0) - return err; - - return wait_for_ack(sk); -} - -/** @} */ - -/** - * @name QDisc Deletion - * @{ - */ - -/** - * Build a netlink request message to delete a qdisc - * @arg qdisc qdisc to delete - * @arg result Pointer to store resulting message. - * - * Builds a new netlink message requesting a deletion of a qdisc. - * The netlink message header isn't fully equipped with all relevant - * fields and must thus be sent out via nl_send_auto_complete() - * or supplemented as needed. - * - * @return 0 on success or a negative error code. - */ -int rtnl_qdisc_build_delete_request(struct rtnl_qdisc *qdisc, - struct nl_msg **result) -{ - struct nl_msg *msg; - struct tcmsg tchdr; - int required = TCA_ATTR_IFINDEX | TCA_ATTR_PARENT; - - if ((qdisc->ce_mask & required) != required) - BUG(); - - msg = nlmsg_alloc_simple(RTM_DELQDISC, 0); - if (!msg) - return -NLE_NOMEM; - - tchdr.tcm_family = AF_UNSPEC; - tchdr.tcm_handle = qdisc->q_handle; - tchdr.tcm_parent = qdisc->q_parent; - tchdr.tcm_ifindex = qdisc->q_ifindex; - if (nlmsg_append(msg, &tchdr, sizeof(tchdr), NLMSG_ALIGNTO) < 0) { - nlmsg_free(msg); - return -NLE_MSGSIZE; - } - - *result = msg; - return 0; -} - -/** - * Delete a qdisc - * @arg sk Netlink socket. - * @arg qdisc qdisc to delete - * - * Builds a netlink message by calling rtnl_qdisc_build_delete_request(), - * sends the request to the kernel and waits for the ACK to be - * received and thus blocks until the request has been processed. - * - * @return 0 on success or a negative error code - */ -int rtnl_qdisc_delete(struct nl_sock *sk, struct rtnl_qdisc *qdisc) -{ - struct nl_msg *msg; - int err; - - if ((err = rtnl_qdisc_build_delete_request(qdisc, &msg)) < 0) - return err; - - err = nl_send_auto_complete(sk, msg); - nlmsg_free(msg); - if (err < 0) - return err; - - return wait_for_ack(sk); -} - -/** @} */ - -/** - * @name Qdisc Cache Management - * @{ - */ - -/** - * Build a qdisc cache including all qdiscs currently configured in - * the kernel - * @arg sk Netlink socket. - * @arg result Pointer to store resulting message. - * - * Allocates a new cache, initializes it properly and updates it to - * include all qdiscs currently configured in the kernel. - * - * @return 0 on success or a negative error code. - */ -int rtnl_qdisc_alloc_cache(struct nl_sock *sk, struct nl_cache **result) -{ - return nl_cache_alloc_and_fill(&rtnl_qdisc_ops, sk, result); -} - -/** - * Look up qdisc by its parent in the provided cache - * @arg cache qdisc cache - * @arg ifindex interface the qdisc is attached to - * @arg parent parent handle - * @return pointer to qdisc inside the cache or NULL if no match was found. - */ -struct rtnl_qdisc * rtnl_qdisc_get_by_parent(struct nl_cache *cache, - int ifindex, uint32_t parent) -{ - struct rtnl_qdisc *q; - - if (cache->c_ops != &rtnl_qdisc_ops) - return NULL; - - nl_list_for_each_entry(q, &cache->c_items, ce_list) { - if (q->q_parent == parent && q->q_ifindex == ifindex) { - nl_object_get((struct nl_object *) q); - return q; - } - } - - return NULL; -} - -/** - * Look up qdisc by its handle in the provided cache - * @arg cache qdisc cache - * @arg ifindex interface the qdisc is attached to - * @arg handle qdisc handle - * @return pointer to qdisc inside the cache or NULL if no match was found. - */ -struct rtnl_qdisc * rtnl_qdisc_get(struct nl_cache *cache, - int ifindex, uint32_t handle) -{ - struct rtnl_qdisc *q; - - if (cache->c_ops != &rtnl_qdisc_ops) - return NULL; - - nl_list_for_each_entry(q, &cache->c_items, ce_list) { - if (q->q_handle == handle && q->q_ifindex == ifindex) { - nl_object_get((struct nl_object *) q); - return q; - } - } - - return NULL; -} - -/** @} */ - /** * @name Allocation/Freeing * @{ @@ -428,6 +81,361 @@ void rtnl_qdisc_put(struct rtnl_qdisc *qdisc) /** @} */ +/** + * @name Addition / Modification / Deletion + * @{ + */ + +static int build_qdisc_msg(struct rtnl_qdisc *qdisc, int type, int flags, + struct nl_msg **result) +{ + if (!(qdisc->ce_mask & TCA_ATTR_IFINDEX)) { + APPBUG("ifindex must be specified"); + return -NLE_MISSING_ATTR; + } + + return rtnl_tc_msg_build(TC_CAST(qdisc), type, flags, result); +} + +/** + * Build a netlink message requesting the addition of a qdisc + * @arg qdisc Qdisc to add + * @arg flags Additional netlink message flags + * @arg result Pointer to store resulting netlink message + * + * The behaviour of this function is identical to rtnl_qdisc_add() with + * the exception that it will not send the message but return it int the + * provided return pointer instead. + * + * @see rtnl_qdisc_add() + * + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_build_add_request(struct rtnl_qdisc *qdisc, int flags, + struct nl_msg **result) +{ + if (!(qdisc->ce_mask & (TCA_ATTR_HANDLE | TCA_ATTR_PARENT))) { + APPBUG("handle or parent must be specified"); + return -NLE_MISSING_ATTR; + } + + return build_qdisc_msg(qdisc, RTM_NEWQDISC, flags, result); +} + +/** + * Add qdisc + * @arg sk Netlink socket + * @arg qdisc Qdisc to add + * @arg flags Additional netlink message flags + * + * Builds a \c RTM_NEWQDISC netlink message requesting the addition + * of a new qdisc and sends the message to the kernel. The configuration + * of the qdisc is derived from the attributes of the specified qdisc. + * + * The following flags may be specified: + * - \c NLM_F_CREATE: Create qdisc if it does not exist, otherwise + * -NLE_OBJ_NOTFOUND is returned. + * - \c NLM_F_REPLACE: If another qdisc is already attached to the + * parent, replace it even if the handles mismatch. + * - \c NLM_F_EXCL: Return -NLE_EXISTS if a qdisc with matching + * handle exists already. + * + * Existing qdiscs with matching handles will be updated, unless the + * flag \c NLM_F_EXCL is specified. If their handles do not match, the + * error -NLE_EXISTS is returned unless the flag \c NLM_F_REPLACE is + * specified in which case the existing qdisc is replaced with the new + * one. If no matching qdisc exists, it will be created if the flag + * \c NLM_F_CREATE is set, otherwise the error -NLE_OBJ_NOTFOUND is + * returned. + * + * After sending, the function will wait for the ACK or an eventual + * error message to be received and will therefore block until the + * operation has been completed. + * + * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause + * this function to return immediately after sending. In this case, + * it is the responsibility of the caller to handle any error + * messages returned. + * + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_add(struct nl_sock *sk, struct rtnl_qdisc *qdisc, int flags) +{ + struct nl_msg *msg; + int err; + + if ((err = rtnl_qdisc_build_add_request(qdisc, flags, &msg)) < 0) + return err; + + return nl_send_sync(sk, msg); +} + +/** + * Build netlink message requesting the update of a qdisc + * @arg qdisc Qdisc to update + * @arg new Qdisc with updated attributes + * @arg flags Additional netlink message flags + * @arg result Pointer to store resulting netlink message + * + * The behaviour of this function is identical to rtnl_qdisc_update() with + * the exception that it will not send the message but return it in the + * provided return pointer instead. + * + * @see rtnl_qdisc_update() + * + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_build_update_request(struct rtnl_qdisc *qdisc, + struct rtnl_qdisc *new, int flags, + struct nl_msg **result) +{ + if (flags & (NLM_F_CREATE | NLM_F_EXCL)) { + APPBUG("NLM_F_CREATE and NLM_F_EXCL may not be used here, " + "use rtnl_qdisc_add()"); + return -NLE_INVAL; + } + + if (!(qdisc->ce_mask & TCA_ATTR_IFINDEX)) { + APPBUG("ifindex must be specified"); + return -NLE_MISSING_ATTR; + } + + if (!(qdisc->ce_mask & (TCA_ATTR_HANDLE | TCA_ATTR_PARENT))) { + APPBUG("handle or parent must be specified"); + return -NLE_MISSING_ATTR; + } + + rtnl_tc_set_ifindex(TC_CAST(new), qdisc->q_ifindex); + + if (qdisc->ce_mask & TCA_ATTR_HANDLE) + rtnl_tc_set_handle(TC_CAST(new), qdisc->q_handle); + + if (qdisc->ce_mask & TCA_ATTR_PARENT) + rtnl_tc_set_parent(TC_CAST(new), qdisc->q_parent); + + return build_qdisc_msg(new, RTM_NEWQDISC, flags, result); +} + +/** + * Update qdisc + * @arg sk Netlink socket + * @arg qdisc Qdisc to update + * @arg new Qdisc with updated attributes + * @arg flags Additional netlink message flags + * + * Builds a \c RTM_NEWQDISC netlink message requesting the update + * of an existing qdisc and sends the message to the kernel. + * + * This function is a varation of rtnl_qdisc_add() to update qdiscs + * if the qdisc to be updated is available as qdisc object. The + * behaviour is identical to the one of rtnl_qdisc_add except that + * before constructing the message, it copies the \c ifindex, + * \c handle, and \c parent from the original \p qdisc to the \p new + * qdisc. + * + * After sending, the function will wait for the ACK or an eventual + * error message to be received and will therefore block until the + * operation has been completed. + * + * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause + * this function to return immediately after sending. In this case, + * it is the responsibility of the caller to handle any error + * messages returned. + * + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_update(struct nl_sock *sk, struct rtnl_qdisc *qdisc, + struct rtnl_qdisc *new, int flags) +{ + struct nl_msg *msg; + int err; + + err = rtnl_qdisc_build_update_request(qdisc, new, flags, &msg); + if (err < 0) + return err; + + return nl_send_sync(sk, msg); +} + +/** + * Build netlink message requesting the deletion of a qdisc + * @arg qdisc Qdisc to delete + * @arg result Pointer to store resulting netlink message + * + * The behaviour of this function is identical to rtnl_qdisc_delete() with + * the exception that it will not send the message but return it in the + * provided return pointer instead. + * + * @see rtnl_qdisc_delete() + * + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_build_delete_request(struct rtnl_qdisc *qdisc, + struct nl_msg **result) +{ + struct nl_msg *msg; + struct tcmsg tchdr; + int required = TCA_ATTR_IFINDEX | TCA_ATTR_PARENT; + + if ((qdisc->ce_mask & required) != required) { + APPBUG("ifindex and parent must be specified"); + return -NLE_MISSING_ATTR; + } + + if (!(msg = nlmsg_alloc_simple(RTM_DELQDISC, 0))) + return -NLE_NOMEM; + + memset(&tchdr, 0, sizeof(tchdr)); + + tchdr.tcm_family = AF_UNSPEC; + tchdr.tcm_ifindex = qdisc->q_ifindex; + tchdr.tcm_parent = qdisc->q_parent; + + if (qdisc->ce_mask & TCA_ATTR_HANDLE) + tchdr.tcm_handle = qdisc->q_handle; + + if (nlmsg_append(msg, &tchdr, sizeof(tchdr), NLMSG_ALIGNTO) < 0) + goto nla_put_failure; + + if (qdisc->ce_mask & TCA_ATTR_KIND) + NLA_PUT_STRING(msg, TCA_KIND, qdisc->q_kind); + + *result = msg; + return 0; + +nla_put_failure: + nlmsg_free(msg); + return -NLE_MSGSIZE; +} + +/** + * Delete qdisc + * @arg sk Netlink socket + * @arg qdisc Qdisc to add + * + * Builds a \c RTM_NEWQDISC netlink message requesting the deletion + * of a qdisc and sends the message to the kernel. + * + * The message is constructed out of the following attributes: + * - \c ifindex and \c parent + * - \c handle (optional, must match if provided) + * - \c kind (optional, must match if provided) + * + * All other qdisc attributes including all qdisc type specific + * attributes are ignored. + * + * After sending, the function will wait for the ACK or an eventual + * error message to be received and will therefore block until the + * operation has been completed. + * + * @note It is not possible to delete default qdiscs. + * + * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause + * this function to return immediately after sending. In this case, + * it is the responsibility of the caller to handle any error + * messages returned. + * + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_delete(struct nl_sock *sk, struct rtnl_qdisc *qdisc) +{ + struct nl_msg *msg; + int err; + + if ((err = rtnl_qdisc_build_delete_request(qdisc, &msg)) < 0) + return err; + + return nl_send_sync(sk, msg); +} + +/** @} */ + +/** + * @name Cache Related Functions + * @{ + */ + +/** + * Allocate a cache and fill it with all configured qdiscs + * @arg sk Netlink socket + * @arg result Pointer to store the created cache + * + * Allocates a new qdisc cache and fills it with a list of all configured + * qdiscs on all network devices. Release the cache with nl_cache_free(). + * + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_alloc_cache(struct nl_sock *sk, struct nl_cache **result) +{ + return nl_cache_alloc_and_fill(&rtnl_qdisc_ops, sk, result); +} + +/** + * Search qdisc by interface index and parent + * @arg cache Qdisc cache + * @arg ifindex Interface index + * @arg parent Handle of parent qdisc + * + * Searches a qdisc cache previously allocated with rtnl_qdisc_alloc_cache() + * and searches for a qdisc matching the interface index and parent qdisc. + * + * The reference counter is incremented before returning the qdisc, therefore + * the reference must be given back with rtnl_qdisc_put() after usage. + * + * @return pointer to qdisc inside the cache or NULL if no match was found. + */ +struct rtnl_qdisc *rtnl_qdisc_get_by_parent(struct nl_cache *cache, + int ifindex, uint32_t parent) +{ + struct rtnl_qdisc *q; + + if (cache->c_ops != &rtnl_qdisc_ops) + return NULL; + + nl_list_for_each_entry(q, &cache->c_items, ce_list) { + if (q->q_parent == parent && q->q_ifindex == ifindex) { + nl_object_get((struct nl_object *) q); + return q; + } + } + + return NULL; +} + +/** + * Search qdisc by interface index and handle + * @arg cache Qdisc cache + * @arg ifindex Interface index + * @arg handle Handle + * + * Searches a qdisc cache previously allocated with rtnl_qdisc_alloc_cache() + * and searches for a qdisc matching the interface index and handle. + * + * The reference counter is incremented before returning the qdisc, therefore + * the reference must be given back with rtnl_qdisc_put() after usage. + * + * @return Qdisc or NULL if no match was found. + */ +struct rtnl_qdisc *rtnl_qdisc_get(struct nl_cache *cache, int ifindex, + uint32_t handle) +{ + struct rtnl_qdisc *q; + + if (cache->c_ops != &rtnl_qdisc_ops) + return NULL; + + nl_list_for_each_entry(q, &cache->c_items, ce_list) { + if (q->q_handle == handle && q->q_ifindex == ifindex) { + nl_object_get((struct nl_object *) q); + return q; + } + } + + return NULL; +} + +/** @} */ + /** * @name Deprecated Functions * @{ @@ -478,6 +486,34 @@ void rtnl_qdisc_foreach_cls(struct rtnl_qdisc *qdisc, struct nl_cache *cache, rtnl_cls_put(filter); } +/** + * Build a netlink message requesting the update of a qdisc + * + * @deprecated Use of this function is deprecated in favour of + * rtnl_qdisc_build_update_request() due to the missing + * possibility of specifying additional flags. + */ +int rtnl_qdisc_build_change_request(struct rtnl_qdisc *qdisc, + struct rtnl_qdisc *new, + struct nl_msg **result) +{ + return rtnl_qdisc_build_update_request(qdisc, new, NLM_F_REPLACE, + result); +} + +/** + * Change attributes of a qdisc + * + * @deprecated Use of this function is deprecated in favour of + * rtnl_qdisc_update() due to the missing possibility of + * specifying additional flags. + */ +int rtnl_qdisc_change(struct nl_sock *sk, struct rtnl_qdisc *qdisc, + struct rtnl_qdisc *new) +{ + return rtnl_qdisc_update(sk, qdisc, new, NLM_F_REPLACE); +} + /** @} */ static void qdisc_dump_details(struct rtnl_tc *tc, struct nl_dump_params *p) diff --git a/lib/route/tc.c b/lib/route/tc.c index 09ae044..56aa410 100644 --- a/lib/route/tc.c +++ b/lib/route/tc.c @@ -189,11 +189,7 @@ int rtnl_tc_msg_build(struct rtnl_tc *tc, int type, int flags, .tcm_handle = tc->tc_handle, .tcm_parent = tc->tc_parent, }; - int req, err = -NLE_MSGSIZE; - - req = (TCA_ATTR_IFINDEX | TCA_ATTR_PARENT | TCA_ATTR_KIND); - if ((tc->ce_mask & req) != req) - return -NLE_MISSING_ATTR; + int err = -NLE_MSGSIZE; msg = nlmsg_alloc_simple(type, flags); if (!msg) From 7c620500bbca24c3d18b731756c375a45bb0fcba Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 29 Mar 2011 12:41:59 +0200 Subject: [PATCH 016/432] trafic class/classifer API improvements and documentation - removed dead functions in header files - deprecated rtnl_class_foreach_*() functions due to their missing handling possibility of OOM situations - improved API documentation --- include/netlink/route/class.h | 32 +- include/netlink/route/classifier.h | 33 +- lib/route/class.c | 466 ++++++++++++++++------------- lib/route/cls.c | 186 +++++++----- src/nl-tctree-list.c | 8 +- 5 files changed, 410 insertions(+), 315 deletions(-) diff --git a/include/netlink/route/class.h b/include/netlink/route/class.h index ad3bacf..e73b60a 100644 --- a/include/netlink/route/class.h +++ b/include/netlink/route/class.h @@ -1,12 +1,12 @@ /* - * netlink/route/class.h Classes + * netlink/route/class.h Traffic Classes * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2011 Thomas Graf */ #ifndef NETLINK_CLASS_H_ @@ -22,14 +22,17 @@ extern "C" { struct rtnl_class; -extern struct rtnl_class * rtnl_class_alloc(void); +extern struct rtnl_class * + rtnl_class_alloc(void); extern void rtnl_class_put(struct rtnl_class *); + extern int rtnl_class_alloc_cache(struct nl_sock *, int, struct nl_cache **); -extern struct rtnl_class *rtnl_class_get(struct nl_cache *, int, uint32_t); +extern struct rtnl_class * + rtnl_class_get(struct nl_cache *, int, uint32_t); -/* leaf qdisc access */ -extern struct rtnl_qdisc * rtnl_class_leaf_qdisc(struct rtnl_class *, +extern struct rtnl_qdisc * + rtnl_class_leaf_qdisc(struct rtnl_class *, struct nl_cache *); extern int rtnl_class_build_add_request(struct rtnl_class *, int, @@ -37,23 +40,24 @@ extern int rtnl_class_build_add_request(struct rtnl_class *, int, extern int rtnl_class_add(struct nl_sock *, struct rtnl_class *, int); -extern int rtnl_class_build_delete_request(struct rtnl_class *, - struct nl_msg **); -extern int rtnl_class_delete(struct nl_sock *, struct rtnl_class *); +extern int rtnl_class_build_delete_request(struct rtnl_class *, + struct nl_msg **); +extern int rtnl_class_delete(struct nl_sock *, + struct rtnl_class *); -extern void rtnl_class_set_kind(struct rtnl_class *, const char *); - -/* iterators */ +/* deprecated functions */ extern void rtnl_class_foreach_child(struct rtnl_class *, struct nl_cache *, void (*cb)(struct nl_object *, void *), - void *); + void *) + __attribute__((deprecated)); extern void rtnl_class_foreach_cls(struct rtnl_class *, struct nl_cache *, void (*cb)(struct nl_object *, void *), - void *); + void *) + __attribute__((deprecated)); #ifdef __cplusplus } diff --git a/include/netlink/route/classifier.h b/include/netlink/route/classifier.h index 23af837..647bf1e 100644 --- a/include/netlink/route/classifier.h +++ b/include/netlink/route/classifier.h @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2010 Thomas Graf + * Copyright (c) 2003-2011 Thomas Graf */ #ifndef NETLINK_CLASSIFIER_H_ @@ -22,26 +22,27 @@ extern "C" { #endif extern struct rtnl_cls *rtnl_cls_alloc(void); -extern void rtnl_cls_put(struct rtnl_cls *); +extern void rtnl_cls_put(struct rtnl_cls *); -extern int rtnl_cls_alloc_cache(struct nl_sock *, int, uint32_t, - struct nl_cache **); +extern int rtnl_cls_alloc_cache(struct nl_sock *, int, uint32_t, + struct nl_cache **); -extern int rtnl_cls_build_add_request(struct rtnl_cls *, int, - struct nl_msg **); -extern int rtnl_cls_add(struct nl_sock *, struct rtnl_cls *, int); +extern int rtnl_cls_build_add_request(struct rtnl_cls *, int, + struct nl_msg **); +extern int rtnl_cls_add(struct nl_sock *, struct rtnl_cls *, int); -extern int rtnl_cls_build_change_request(struct rtnl_cls *, int, - struct nl_msg **); -extern int rtnl_cls_build_delete_request(struct rtnl_cls *, int, - struct nl_msg **); -extern int rtnl_cls_delete(struct nl_sock *, struct rtnl_cls *, int); +extern int rtnl_cls_build_change_request(struct rtnl_cls *, int, + struct nl_msg **); +extern int rtnl_cls_build_delete_request(struct rtnl_cls *, int, + struct nl_msg **); +extern int rtnl_cls_delete(struct nl_sock *, struct rtnl_cls *, + int); -extern void rtnl_cls_set_prio(struct rtnl_cls *, uint16_t); -extern uint16_t rtnl_cls_get_prio(struct rtnl_cls *); +extern void rtnl_cls_set_prio(struct rtnl_cls *, uint16_t); +extern uint16_t rtnl_cls_get_prio(struct rtnl_cls *); -extern void rtnl_cls_set_protocol(struct rtnl_cls *, uint16_t); -extern uint16_t rtnl_cls_get_protocol(struct rtnl_cls *); +extern void rtnl_cls_set_protocol(struct rtnl_cls *, uint16_t); +extern uint16_t rtnl_cls_get_protocol(struct rtnl_cls *); #ifdef __cplusplus } diff --git a/lib/route/class.c b/lib/route/class.c index a0f3758..2a9606b 100644 --- a/lib/route/class.c +++ b/lib/route/class.c @@ -1,17 +1,17 @@ /* - * lib/route/class.c Queueing Classes + * lib/route/class.c Traffic Classes * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2010 Thomas Graf + * Copyright (c) 2003-2011 Thomas Graf */ /** * @ingroup tc - * @defgroup class Queueing Classes + * @defgroup class Traffic Classes * @{ */ @@ -68,126 +68,6 @@ static int class_request_update(struct nl_cache *cache, struct nl_sock *sk) sizeof(tchdr)); } -/** - * @name Addition/Modification - * @{ - */ - -static int class_build(struct rtnl_class *class, int type, int flags, - struct nl_msg **result) -{ - return rtnl_tc_msg_build(TC_CAST(class), type, flags, result); -} - -/** - * Build a netlink message to add a new class - * @arg class class to add - * @arg flags additional netlink message flags - * @arg result Pointer to store resulting message. - * - * Builds a new netlink message requesting an addition of a class. - * The netlink message header isn't fully equipped with all relevant - * fields and must be sent out via nl_send_auto_complete() or - * supplemented as needed. - * - * Common message flags - * - NLM_F_REPLACE - replace possibly existing classes - * - * @return 0 on success or a negative error code. - */ -int rtnl_class_build_add_request(struct rtnl_class *class, int flags, - struct nl_msg **result) -{ - return class_build(class, RTM_NEWTCLASS, NLM_F_CREATE | flags, result); -} - -/** - * Add a new class - * @arg sk Netlink socket. - * @arg class class to delete - * @arg flags additional netlink message flags - * - * Builds a netlink message by calling rtnl_qdisc_build_add_request(), - * sends the request to the kernel and waits for the next ACK to be - * received and thus blocks until the request has been processed. - * - * Common message flags - * - NLM_F_REPLACE - replace possibly existing classes - * - * @return 0 on success or a negative error code - */ -int rtnl_class_add(struct nl_sock *sk, struct rtnl_class *class, int flags) -{ - struct nl_msg *msg; - int err; - - if ((err = rtnl_class_build_add_request(class, flags, &msg)) < 0) - return err; - - err = nl_send_auto_complete(sk, msg); - nlmsg_free(msg); - if (err < 0) - return err; - - return wait_for_ack(sk); -} - -int rtnl_class_build_delete_request(struct rtnl_class *class, - struct nl_msg **result) -{ - struct nl_msg *msg; - struct tcmsg tchdr; - int required = TCA_ATTR_IFINDEX | TCA_ATTR_PARENT; - - if ((class->ce_mask & required) != required) - BUG(); - - msg = nlmsg_alloc_simple(RTM_DELTCLASS, 0); - if (!msg) - return -NLE_NOMEM; - - tchdr.tcm_family = AF_UNSPEC; - tchdr.tcm_handle = class->c_handle; - tchdr.tcm_parent = class->c_parent; - tchdr.tcm_ifindex = class->c_ifindex; - if (nlmsg_append(msg, &tchdr, sizeof(tchdr), NLMSG_ALIGNTO) < 0) { - nlmsg_free(msg); - return -NLE_MSGSIZE; - } - - *result = msg; - return 0; -} - -/** - * Delete a class - * @arg sk Netlink socket. - * @arg class class to delete - * - * Builds a netlink message by calling rtnl_class_build_delete_request(), - * sends the request to the kernel and waits for the ACK to be - * received and thus blocks until the request has been processed. - * - * @return 0 on success or a negative error code - */ -int rtnl_class_delete(struct nl_sock *sk, struct rtnl_class *class) -{ - struct nl_msg *msg; - int err; - - if ((err = rtnl_class_build_delete_request(class, &msg)) < 0) - return err; - - err = nl_send_auto_complete(sk, msg); - nlmsg_free(msg); - if (err < 0) - return err; - - return wait_for_ack(sk); -} - -/** @} */ - /** * @name Allocation/Freeing * @{ @@ -211,17 +91,188 @@ void rtnl_class_put(struct rtnl_class *class) /** @} */ + +/** + * @name Addition/Modification/Deletion + * @{ + */ + +static int class_build(struct rtnl_class *class, int type, int flags, + struct nl_msg **result) +{ + int needed = TCA_ATTR_PARENT | TCA_ATTR_HANDLE; + + if ((class->ce_mask & needed) == needed && + TC_H_MAJ(class->c_parent) && TC_H_MAJ(class->c_handle) && + TC_H_MAJ(class->c_parent) != TC_H_MAJ(class->c_handle)) { + APPBUG("TC_H_MAJ(parent) must match TC_H_MAJ(handle)"); + return -NLE_INVAL; + } + + return rtnl_tc_msg_build(TC_CAST(class), type, flags, result); +} + +/** + * Build a netlink message requesting the addition of a traffic class + * @arg class Traffic class to add + * @arg flags Additional netlink message flags + * @arg result Pointer to store resulting netlink message + * + * The behaviour of this function is identical to rtnl_class_add() with + * the exception that it will not send the message but return it int the + * provided return pointer instead. + * + * @see rtnl_class_add() + * + * @return 0 on success or a negative error code. + */ +int rtnl_class_build_add_request(struct rtnl_class *class, int flags, + struct nl_msg **result) +{ + return class_build(class, RTM_NEWTCLASS, flags, result); +} + +/** + * Add/Update traffic class + * @arg sk Netlink socket + * @arg class Traffic class to add + * @arg flags Additional netlink message flags + * + * Builds a \c RTM_NEWTCLASS netlink message requesting the addition + * of a new traffic class and sends the message to the kernel. The + * configuration of the traffic class is derived from the attributes + * of the specified traffic class. + * + * The following flags may be specified: + * - \c NLM_F_CREATE: Create traffic class if it does not exist, + * otherwise -NLE_OBJ_NOTFOUND is returned. + * - \c NLM_F_EXCL: Return -NLE_EXISTS if a traffic class with + * matching handle exists already. + * + * Existing traffic classes with matching handles will be updated, + * unless the flag \c NLM_F_EXCL is specified. If no matching traffic + * class exists, it will be created if the flag \c NLM_F_CREATE is set, + * otherwise the error -NLE_OBJ_NOTFOUND is returned. + * + * If the parent qdisc does not support classes, the error + * \c NLE_OPNOTSUPP is returned. + * + * After sending, the function will wait for the ACK or an eventual + * error message to be received and will therefore block until the + * operation has been completed. + * + * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause + * this function to return immediately after sending. In this case, + * it is the responsibility of the caller to handle any error + * messages returned. + * + * @return 0 on success or a negative error code. + */ +int rtnl_class_add(struct nl_sock *sk, struct rtnl_class *class, int flags) +{ + struct nl_msg *msg; + int err; + + if ((err = rtnl_class_build_add_request(class, flags, &msg)) < 0) + return err; + + return nl_send_sync(sk, msg); +} + +/** + * Build netlink message requesting the deletion of a traffic class + * @arg class Traffic class to delete + * @arg result Pointer to store resulting netlink message + * + * The behaviour of this function is identical to rtnl_class_delete() with + * the exception that it will not send the message but return it in the + * provided return pointer instead. + * + * @see rtnl_class_delete() + * + * @return 0 on success or a negative error code. + */ +int rtnl_class_build_delete_request(struct rtnl_class *class, struct nl_msg **result) +{ + struct nl_msg *msg; + struct tcmsg tchdr; + int required = TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE; + + if ((class->ce_mask & required) != required) { + APPBUG("ifindex and handle must be specified"); + return -NLE_MISSING_ATTR; + } + + if (!(msg = nlmsg_alloc_simple(RTM_DELTCLASS, 0))) + return -NLE_NOMEM; + + memset(&tchdr, 0, sizeof(tchdr)); + tchdr.tcm_family = AF_UNSPEC; + tchdr.tcm_ifindex = class->c_ifindex; + tchdr.tcm_handle = class->c_handle; + + if (class->ce_mask & TCA_ATTR_PARENT) + tchdr.tcm_parent = class->c_parent; + + if (nlmsg_append(msg, &tchdr, sizeof(tchdr), NLMSG_ALIGNTO) < 0) { + nlmsg_free(msg); + return -NLE_MSGSIZE; + } + + *result = msg; + return 0; +} + +/** + * Delete traffic class + * @arg sk Netlink socket + * @arg class Traffic class to delete + * + * Builds a \c RTM_DELTCLASS netlink message requesting the deletion + * of a traffic class and sends the message to the kernel. + * + * The message is constructed out of the following attributes: + * - \c ifindex and \c handle (required) + * - \c parent (optional, must match if provided) + * + * All other class attributes including all class type specific + * attributes are ignored. + * + * After sending, the function will wait for the ACK or an eventual + * error message to be received and will therefore block until the + * operation has been completed. + * + * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause + * this function to return immediately after sending. In this case, + * it is the responsibility of the caller to handle any error + * messages returned. + * + * @return 0 on success or a negative error code. + */ +int rtnl_class_delete(struct nl_sock *sk, struct rtnl_class *class) +{ + struct nl_msg *msg; + int err; + + if ((err = rtnl_class_build_delete_request(class, &msg)) < 0) + return err; + + return nl_send_sync(sk, msg); +} + +/** @} */ + /** * @name Leaf Qdisc * @{ */ /** - * Lookup the leaf qdisc of a class - * @arg class the parent class - * @arg cache a qdisc cache including at laest all qdiscs of the - * interface the specified class is attached to - * @return The qdisc from the cache or NULL if the class has no leaf qdisc + * Lookup the leaf qdisc of a traffic class + * @arg class the parent traffic class + * @arg cache a qdisc cache allocated using rtnl_qdisc_alloc_cache() + * + * @return Matching Qdisc or NULL if the traffic class has no leaf qdisc */ struct rtnl_qdisc *rtnl_class_leaf_qdisc(struct rtnl_class *class, struct nl_cache *cache) @@ -241,19 +292,93 @@ struct rtnl_qdisc *rtnl_class_leaf_qdisc(struct rtnl_class *class, /** @} */ +/** + * @name Cache Related Functions + * @{ + */ /** - * @name Iterators + * Allocate a cache and fill it with all configured traffic classes + * @arg sk Netlink socket + * @arg ifindex Interface index of the network device + * @arg result Pointer to store the created cache + * + * Allocates a new traffic class cache and fills it with a list of all + * configured traffic classes on a specific network device. Release the + * cache with nl_cache_free(). + * + * @return 0 on success or a negative error code. + */ +int rtnl_class_alloc_cache(struct nl_sock *sk, int ifindex, + struct nl_cache **result) +{ + struct nl_cache * cache; + int err; + + if (!ifindex) { + APPBUG("ifindex must be specified"); + return -NLE_INVAL; + } + + if (!(cache = nl_cache_alloc(&rtnl_class_ops))) + return -NLE_NOMEM; + + cache->c_iarg1 = ifindex; + + if (sk && (err = nl_cache_refill(sk, cache)) < 0) { + nl_cache_free(cache); + return err; + } + + *result = cache; + return 0; +} + +/** + * Search traffic class by interface index and handle + * @arg cache Traffic class cache + * @arg ifindex Interface index + * @arg handle ID of traffic class + * + * Searches a traffic class cache previously allocated with + * rtnl_class_alloc_cache() and searches for a traffi class matching + * the interface index and handle. + * + * The reference counter is incremented before returning the traffic + * class, therefore the reference must be given back with rtnl_class_put() + * after usage. + * + * @return Traffic class or NULL if no match was found. + */ +struct rtnl_class *rtnl_class_get(struct nl_cache *cache, int ifindex, + uint32_t handle) +{ + struct rtnl_class *class; + + if (cache->c_ops != &rtnl_class_ops) + return NULL; + + nl_list_for_each_entry(class, &cache->c_items, ce_list) { + if (class->c_handle == handle && class->c_ifindex == ifindex) { + nl_object_get((struct nl_object *) class); + return class; + } + } + return NULL; +} + +/** @} */ + +/** + * @name Deprecated Functions * @{ */ /** * Call a callback for each child of a class - * @arg class the parent class - * @arg cache a class cache including all classes of the interface - * the specified class is attached to - * @arg cb callback function - * @arg arg argument to be passed to callback function + * + * @deprecated Use of this function is deprecated, it does not allow + * to handle the out of memory situation that can occur. */ void rtnl_class_foreach_child(struct rtnl_class *class, struct nl_cache *cache, void (*cb)(struct nl_object *, void *), void *arg) @@ -274,11 +399,9 @@ void rtnl_class_foreach_child(struct rtnl_class *class, struct nl_cache *cache, /** * Call a callback for each classifier attached to the class - * @arg class the parent class - * @arg cache a filter cache including at least all the filters - * attached to the specified class - * @arg cb callback function - * @arg arg argument to be passed to callback function + * + * @deprecated Use of this function is deprecated, it does not allow + * to handle the out of memory situation that can occur. */ void rtnl_class_foreach_cls(struct rtnl_class *class, struct nl_cache *cache, void (*cb)(struct nl_object *, void *), void *arg) @@ -298,71 +421,6 @@ void rtnl_class_foreach_cls(struct rtnl_class *class, struct nl_cache *cache, /** @} */ - -/** - * @name Cache Management - * @{ - */ - -/** - * Build a class cache including all classes attached to the specified interface - * @arg sk Netlink socket. - * @arg ifindex interface index of the link the classes are - * attached to. - * @arg result Result pointer - * - * Allocates a new cache, initializes it properly and updates it to - * include all classes attached to the specified interface. - * - * @return 0 on success or a negative error code. - */ -int rtnl_class_alloc_cache(struct nl_sock *sk, int ifindex, - struct nl_cache **result) -{ - struct nl_cache * cache; - int err; - - cache = nl_cache_alloc(&rtnl_class_ops); - if (!cache) - return -NLE_NOMEM; - - cache->c_iarg1 = ifindex; - - if (sk && (err = nl_cache_refill(sk, cache)) < 0) { - nl_cache_free(cache); - return err; - } - - *result = cache; - return 0; -} - -/** - * Look up class by its handle in the provided cache - * @arg cache class cache - * @arg ifindex interface the class is attached to - * @arg handle class handle - * @return pointer to class inside the cache or NULL if no match was found. - */ -struct rtnl_class *rtnl_class_get(struct nl_cache *cache, int ifindex, - uint32_t handle) -{ - struct rtnl_class *class; - - if (cache->c_ops != &rtnl_class_ops) - return NULL; - - nl_list_for_each_entry(class, &cache->c_items, ce_list) { - if (class->c_handle == handle && class->c_ifindex == ifindex) { - nl_object_get((struct nl_object *) class); - return class; - } - } - return NULL; -} - -/** @} */ - static struct rtnl_tc_type_ops class_ops = { .tt_type = RTNL_TC_TYPE_CLASS, .tt_dump_prefix = "class", diff --git a/lib/route/cls.c b/lib/route/cls.c index a041baa..aa79b09 100644 --- a/lib/route/cls.c +++ b/lib/route/cls.c @@ -6,21 +6,12 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2009 Thomas Graf + * Copyright (c) 2003-2011 Thomas Graf */ /** * @ingroup tc * @defgroup cls Classifiers - * - * @par Classifier Identification - * - protocol - * - priority - * - parent - * - interface - * - kind - * - handle - * * @{ */ @@ -46,6 +37,12 @@ static int cls_build(struct rtnl_cls *cls, int type, int flags, { int err, prio, proto; struct tcmsg *tchdr; + int required = TCA_ATTR_IFINDEX; + + if ((cls->ce_mask & required) != required) { + APPBUG("ifindex must be specified"); + return -NLE_MISSING_ATTR; + } err = rtnl_tc_msg_build(TC_CAST(cls), type, flags, result); if (err < 0) @@ -119,42 +116,70 @@ uint16_t rtnl_cls_get_protocol(struct rtnl_cls *cls) /** - * @name Classifier Addition/Modification/Deletion + * @name Addition/Modification/Deletion * @{ */ /** - * Build a netlink message to add a new classifier - * @arg cls classifier to add - * @arg flags additional netlink message flags - * @arg result Pointer to store resulting message. + * Build a netlink message requesting the addition of a classifier + * @arg cls Classifier to add + * @arg flags Additional netlink message flags + * @arg result Pointer to store resulting netlink message * - * Builds a new netlink message requesting an addition of a classifier - * The netlink message header isn't fully equipped with all relevant - * fields and must be sent out via nl_send_auto_complete() or - * supplemented as needed. \a classifier must contain the attributes of - * the new classifier set via \c rtnl_cls_set_* functions. \a opts - * may point to the clsasifier specific options. + * The behaviour of this function is identical to rtnl_cls_add() with + * the exception that it will not send the message but return it int the + * provided return pointer instead. + * + * @see rtnl_cls_add() * * @return 0 on success or a negative error code. */ int rtnl_cls_build_add_request(struct rtnl_cls *cls, int flags, struct nl_msg **result) { - return cls_build(cls, RTM_NEWTFILTER, NLM_F_CREATE | flags, result); + if (!(flags & NLM_F_CREATE) && !(cls->ce_mask & CLS_ATTR_PRIO)) { + APPBUG("prio must be specified if not a new classifier"); + return -NLE_MISSING_ATTR; + } + + return cls_build(cls, RTM_NEWTFILTER, flags, result); } /** - * Add a new classifier - * @arg sk Netlink socket. - * @arg cls classifier to add - * @arg flags additional netlink message flags + * Add/Update classifier + * @arg sk Netlink socket + * @arg cls Classifier to add/update + * @arg flags Additional netlink message flags * - * Builds a netlink message by calling rtnl_cls_build_add_request(), - * sends the request to the kernel and waits for the next ACK to be - * received and thus blocks until the request has been processed. + * Builds a \c RTM_NEWTFILTER netlink message requesting the addition + * of a new classifier and sends the message to the kernel. The + * configuration of the classifier is derived from the attributes of + * the specified traffic class. * - * @return 0 on sucess or a negative error if an error occured. + * The following flags may be specified: + * - \c NLM_F_CREATE: Create classifier if it does not exist, + * otherwise -NLE_OBJ_NOTFOUND is returned. + * - \c NLM_F_EXCL: Return -NLE_EXISTS if a classifier with + * matching handle exists already. + * + * Existing classifiers with matching handles will be updated, unless + * the flag \c NLM_F_EXCL is specified. If no matching classifier + * exists, it will be created if the flag \c NLM_F_CREATE is set, + * otherwise the error -NLE_OBJ_NOTFOUND is returned. + * + * If the parent qdisc does not support classes, the error + * \c NLE_OPNOTSUPP is returned. + * + * After sending, the function will wait for the ACK or an eventual + * error message to be received and will therefore block until the + * operation has been completed. + * + * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause + * this function to return immediately after sending. In this case, + * it is the responsibility of the caller to handle any error + * messages returned. + * + * @return 0 on success or a negative error code. */ int rtnl_cls_add(struct nl_sock *sk, struct rtnl_cls *cls, int flags) { @@ -163,13 +188,8 @@ int rtnl_cls_add(struct nl_sock *sk, struct rtnl_cls *cls, int flags) if ((err = rtnl_cls_build_add_request(cls, flags, &msg)) < 0) return err; - - err = nl_send_auto_complete(sk, msg); - nlmsg_free(msg); - if (err < 0) - return err; - return nl_wait_for_ack(sk); + return nl_send_sync(sk, msg); } /** @@ -211,45 +231,64 @@ int rtnl_cls_change(struct nl_sock *sk, struct rtnl_cls *cls, int flags) if ((err = rtnl_cls_build_change_request(cls, flags, &msg)) < 0) return err; - err = nl_send_auto_complete(sk, msg); - nlmsg_free(msg); - if (err < 0) - return err; - - return nl_wait_for_ack(sk); + return nl_send_sync(sk, msg); } /** - * Build a netlink request message to delete a classifier - * @arg cls classifier to delete - * @arg flags additional netlink message flags - * @arg result Pointer to store resulting message. + * Build netlink message requesting the deletion of a classifier + * @arg cls Classifier to delete + * @arg result Pointer to store resulting netlink message * - * Builds a new netlink message requesting a deletion of a classifier. - * The netlink message header isn't fully equipped with all relevant - * fields and must thus be sent out via nl_send_auto_complete() - * or supplemented as needed. + * The behaviour of this function is identical to rtnl_cls_delete() with + * the exception that it will not send the message but return it in the + * provided return pointer instead. + * + * @see rtnl_cls_delete() * * @return 0 on success or a negative error code. */ int rtnl_cls_build_delete_request(struct rtnl_cls *cls, int flags, struct nl_msg **result) { + int required = CLS_ATTR_PRIO; + + if ((cls->ce_mask & required) != required) { + APPBUG("prio must be specified"); + return -NLE_MISSING_ATTR; + } + return cls_build(cls, RTM_DELTFILTER, flags, result); } - /** - * Delete a classifier - * @arg sk Netlink socket. - * @arg cls classifier to delete - * @arg flags additional netlink message flags + * Delete classifier + * @arg sk Netlink socket + * @arg cls Classifier to delete * - * Builds a netlink message by calling rtnl_cls_build_delete_request(), - * sends the request to the kernel and waits for the next ACK to be - * received and thus blocks until the request has been processed. + * Builds a \c RTM_DELTFILTER netlink message requesting the deletion + * of a classifier and sends the message to the kernel. * - * @return 0 on sucess or a negative error if an error occured. + * The message is constructed out of the following attributes: + * - \c ifindex (required) + * - \c prio (required) + * - \c protocol (required) + * - \c handle (required) + * - \c parent (optional, if not specified parent equals root-qdisc) + * - \c kind (optional, must match if provided) + * + * All other classifier attributes including all class type specific + * attributes are ignored. + * + * After sending, the function will wait for the ACK or an eventual + * error message to be received and will therefore block until the + * operation has been completed. + * + * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause + * this function to return immediately after sending. In this case, + * it is the responsibility of the caller to handle any error + * messages returned. + * + * @return 0 on success or a negative error code. */ int rtnl_cls_delete(struct nl_sock *sk, struct rtnl_cls *cls, int flags) { @@ -259,35 +298,28 @@ int rtnl_cls_delete(struct nl_sock *sk, struct rtnl_cls *cls, int flags) if ((err = rtnl_cls_build_delete_request(cls, flags, &msg)) < 0) return err; - err = nl_send_auto_complete(sk, msg); - nlmsg_free(msg); - if (err < 0) - return err; - - return nl_wait_for_ack(sk); + return nl_send_sync(sk, msg); } /** @} */ /** - * @name Cache Management + * @name Cache Related Functions * @{ */ /** - * Build a classifier cache including all classifiers attached to the - * specified class/qdisc on eht specified interface. - * @arg sk Netlink socket. - * @arg ifindex interface index of the link the classes are - * attached to. - * @arg parent parent qdisc/class - * @arg result Pointer to store resulting cache. + * Allocate a cache and fill it with all configured classifiers + * @arg sk Netlink socket + * @arg ifindex Interface index of the network device + * @arg parent Parent qdisc/traffic class class + * @arg result Pointer to store the created cache * - * Allocates a new cache, initializes it properly and updates it to - * include all classes attached to the specified interface. + * Allocates a new classifier cache and fills it with a list of all + * configured classifier attached to the specified parent qdisc/traffic + * class on the specified network device. Release the cache with + * nl_cache_free(). * - * @note The caller is responsible for destroying and freeing the - * cache after using it. * @return 0 on success or a negative error code. */ int rtnl_cls_alloc_cache(struct nl_sock *sk, int ifindex, uint32_t parent, struct nl_cache **result) diff --git a/src/nl-tctree-list.c b/src/nl-tctree-list.c index 9407345..d90cb28 100644 --- a/src/nl-tctree-list.c +++ b/src/nl-tctree-list.c @@ -23,6 +23,7 @@ static struct nl_dump_params params = { static int ifindex; static void print_qdisc(struct nl_object *, void *); +static void print_tc_childs(struct rtnl_tc *, void *); static void print_usage(void) { @@ -51,7 +52,7 @@ static void print_class(struct nl_object *obj, void *arg) if (leaf) print_qdisc((struct nl_object *) leaf, arg + 2); - rtnl_class_foreach_child(class, class_cache, &print_class, arg + 2); + print_tc_childs(TC_CAST(class), arg + 2); if (rtnl_cls_alloc_cache(sock, ifindex, parent, &cls_cache) < 0) return; @@ -61,9 +62,8 @@ static void print_class(struct nl_object *obj, void *arg) nl_cache_free(cls_cache); } -static void print_qdisc_childs(struct rtnl_qdisc *qdisc, void *arg) +static void print_tc_childs(struct rtnl_tc *tc, void *arg) { - struct rtnl_tc *tc = TC_CAST(qdisc); struct rtnl_class *filter; filter = nl_cli_class_alloc(); @@ -85,7 +85,7 @@ static void print_qdisc(struct nl_object *obj, void *arg) params.dp_prefix = (int)(long) arg; nl_object_dump(obj, ¶ms); - print_qdisc_childs(qdisc, arg + 2); + print_tc_childs(TC_CAST(qdisc), arg + 2); if (rtnl_cls_alloc_cache(sock, ifindex, parent, &cls_cache) < 0) return; From 350b15f9d13fdb33e63d2b9cb09872e22bfbe5c9 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 31 Mar 2011 14:25:57 +0200 Subject: [PATCH 017/432] Move to asciidoc The core library documentation has been converted to use asciidoc. It provides better flexibility in creating documentation such as tables and more powerful formatting rules. The doxygen based API reference remains and three scripts have been added to: - gen-tags.sh: extract tag information from doxygen reference - tags2dict.sh: generate a name=link dictionary file - doxygen-link.py: replace all references in the asciidoc documentation refering to API functions, struct, etc. with a link into the doxygen API reference. 'make gendoc' continue to generate all documentation. The following tools are required to generate documentation: - asciidoc - mscgen - asciidoc mscgen plugin - pygments - xmlstarlet --- doc/.gitignore | 2 + doc/Doxyfile.in | 4 +- doc/Makefile.am | 10 +- doc/api/.gitignore | 6 + doc/core.txt | 2802 ++++++++++++++++++++++++++++++ doc/doxygen-link.py | 20 + doc/gen-tags.sh | 20 + doc/html/.gitignore | 1 - doc/images/.gitignore | 1 + doc/images/classful_qdisc.png | Bin 0 -> 31849 bytes doc/images/classless_qdisc.png | Bin 0 -> 15443 bytes doc/images/icons/README | 5 + doc/images/icons/callouts/1.png | Bin 0 -> 329 bytes doc/images/icons/callouts/10.png | Bin 0 -> 361 bytes doc/images/icons/callouts/11.png | Bin 0 -> 565 bytes doc/images/icons/callouts/12.png | Bin 0 -> 617 bytes doc/images/icons/callouts/13.png | Bin 0 -> 623 bytes doc/images/icons/callouts/14.png | Bin 0 -> 411 bytes doc/images/icons/callouts/15.png | Bin 0 -> 640 bytes doc/images/icons/callouts/2.png | Bin 0 -> 353 bytes doc/images/icons/callouts/3.png | Bin 0 -> 350 bytes doc/images/icons/callouts/4.png | Bin 0 -> 345 bytes doc/images/icons/callouts/5.png | Bin 0 -> 348 bytes doc/images/icons/callouts/6.png | Bin 0 -> 355 bytes doc/images/icons/callouts/7.png | Bin 0 -> 344 bytes doc/images/icons/callouts/8.png | Bin 0 -> 357 bytes doc/images/icons/callouts/9.png | Bin 0 -> 357 bytes doc/images/icons/caution.png | Bin 0 -> 2734 bytes doc/images/icons/example.png | Bin 0 -> 2599 bytes doc/images/icons/home.png | Bin 0 -> 1340 bytes doc/images/icons/important.png | Bin 0 -> 2980 bytes doc/images/icons/next.png | Bin 0 -> 1302 bytes doc/images/icons/note.png | Bin 0 -> 2494 bytes doc/images/icons/prev.png | Bin 0 -> 1348 bytes doc/images/icons/tip.png | Bin 0 -> 2718 bytes doc/images/icons/up.png | Bin 0 -> 1320 bytes doc/images/icons/warning.png | Bin 0 -> 3214 bytes doc/images/qdisc_default.png | Bin 0 -> 14571 bytes doc/images/qdisc_mq.png | Bin 0 -> 26121 bytes doc/images/tc_obj.png | Bin 0 -> 30876 bytes doc/images/tc_overview.png | Bin 0 -> 48129 bytes doc/src/core.c | 2303 ------------------------ doc/stylesheets/pygments.css | 62 + doc/stylesheets/xhtml11.css | 428 +++++ doc/tags2dict.sh | 8 + 45 files changed, 3365 insertions(+), 2307 deletions(-) create mode 100644 doc/.gitignore create mode 100644 doc/api/.gitignore create mode 100644 doc/core.txt create mode 100755 doc/doxygen-link.py create mode 100755 doc/gen-tags.sh delete mode 100644 doc/html/.gitignore create mode 100644 doc/images/.gitignore create mode 100644 doc/images/classful_qdisc.png create mode 100644 doc/images/classless_qdisc.png create mode 100644 doc/images/icons/README create mode 100644 doc/images/icons/callouts/1.png create mode 100644 doc/images/icons/callouts/10.png create mode 100644 doc/images/icons/callouts/11.png create mode 100644 doc/images/icons/callouts/12.png create mode 100644 doc/images/icons/callouts/13.png create mode 100644 doc/images/icons/callouts/14.png create mode 100644 doc/images/icons/callouts/15.png create mode 100644 doc/images/icons/callouts/2.png create mode 100644 doc/images/icons/callouts/3.png create mode 100644 doc/images/icons/callouts/4.png create mode 100644 doc/images/icons/callouts/5.png create mode 100644 doc/images/icons/callouts/6.png create mode 100644 doc/images/icons/callouts/7.png create mode 100644 doc/images/icons/callouts/8.png create mode 100644 doc/images/icons/callouts/9.png create mode 100644 doc/images/icons/caution.png create mode 100644 doc/images/icons/example.png create mode 100644 doc/images/icons/home.png create mode 100644 doc/images/icons/important.png create mode 100644 doc/images/icons/next.png create mode 100644 doc/images/icons/note.png create mode 100644 doc/images/icons/prev.png create mode 100644 doc/images/icons/tip.png create mode 100644 doc/images/icons/up.png create mode 100644 doc/images/icons/warning.png create mode 100644 doc/images/qdisc_default.png create mode 100644 doc/images/qdisc_mq.png create mode 100644 doc/images/tc_obj.png create mode 100644 doc/images/tc_overview.png delete mode 100644 doc/src/core.c create mode 100644 doc/stylesheets/pygments.css create mode 100644 doc/stylesheets/xhtml11.css create mode 100755 doc/tags2dict.sh diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 0000000..deffa1d --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1,2 @@ +*.html +libnl.dict diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index aafebbe..9bfb711 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -662,7 +662,7 @@ EXAMPLE_RECURSIVE = NO # directories that contain image that are included in the documentation (see # the \image command). -IMAGE_PATH = src/img +IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program @@ -784,7 +784,7 @@ GENERATE_HTML = YES # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. -HTML_OUTPUT = html +HTML_OUTPUT = api # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank diff --git a/doc/Makefile.am b/doc/Makefile.am index 040ff87..0dd044b 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -2,8 +2,16 @@ .PHONY: gendoc +ASCIIDOCOPTS=-n -a pygments -a toc -a language=c -a icons \ + -a imagesdir="images/" \ + -a stylesdir="${abs_srcdir}/stylesheets/" + gendoc: doxygen Doxyfile; + ./gen-tags.sh | ./tags2dict.sh > libnl.dict + asciidoc $(ASCIIDOCOPTS) core.txt + ./doxygen-link.py libnl.dict core.html > core.tmp.html + mv core.tmp.html core.html distclean-local: - rm -f html/*; + rm -f api/* libnl.tags *.html; diff --git a/doc/api/.gitignore b/doc/api/.gitignore new file mode 100644 index 0000000..18a5fd8 --- /dev/null +++ b/doc/api/.gitignore @@ -0,0 +1,6 @@ +*.html +*.png +*.css +*.map +*.md5 +formula.repository diff --git a/doc/core.txt b/doc/core.txt new file mode 100644 index 0000000..7ae3081 --- /dev/null +++ b/doc/core.txt @@ -0,0 +1,2802 @@ +//// + vim.syntax: asciidoc + + Copyright (c) 2011 Thomas Graf +//// + +Netlink Core Library +==================== +Thomas Graf +3.0, March 30 2011: + +== Introduction + +The core library contains the fundamentals required to communicate +over netlink sockets. It deals with connecting and disconnectng of +sockets, sending and receiving of data, construction and parsing of +messages, provides a customizeable receiving state machine, and +provides a abstract data type framework which eases the implementation +of object based netlink protocols where objects are added, removed, or +modified using a netlink based protocol. + +.Sub Libraries + +Several sub libraries exist which provide APIs to several netlink +protocols: + +- Adresses, Links, Neighbours, Routing & Traffic Control +- Netfilter +- Generic Netlink + ++FIXME+: Add links + + +=== How To Read This Documentation + +The documentation consists of this manual and the API reference pages. +Both contain references to each other and as many examples as +possible. + ++FIXME+ + +=== Linking to this Library + +.Main Header + +The main header is ``. Additional headers need to +be included in your sources depending on the subsystems your program +makes use of. + +[source,c] +----- +#include + +#if LIBNL_VER_NUM >= LIBNL_VER(3,0) + /* include code if compiled with libnl version >= 3.0 */ +#endif +----- + +.Linking to libnl +----- +$ gcc myprogram.c -o myprogram -lnl +----- + +=== Debugging + +The library contains debugging statements which are printed to ++stderr+ if the environment variable +NLDBG+ is set to > 0. + +----- +$ NLDBG=2 ./myprogram +----- + +.Debugging Levels +[options="header", width="80%", cols="1,5", align="center"] +|=============================================================== +| Level | Description +| 0 | Debugging disabled (default) +| 1 | Warnings, important events and notifications +| 2 | More or less important debugging messages +| 3 | Repetitive events causing a flood of debugging messages +| 4 | Even less important messages +|=============================================================== + +.Debugging Netlink Messages + +Often it is useful to peek into the stream of netlink messages +exchanged with other sockets. Setting the environment variable ++NLCB=debug+ will cause the debugging message handlers to be used +causing the netlink messages exchanged to be printed to +stderr+ in a +human readable format: + +----- +$ NLCB=debug ./myprogram +-- Debug: Sent Message: +-------------------------- BEGIN NETLINK MESSAGE --------------------------- + [HEADER] 16 octets + .nlmsg_len = 20 + .nlmsg_type = 18 + .nlmsg_flags = 773 + .nlmsg_seq = 1301410712 + .nlmsg_pid = 20014 + [PAYLOAD] 16 octets + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +--------------------------- END NETLINK MESSAGE --------------------------- +-- Debug: Received Message: +-------------------------- BEGIN NETLINK MESSAGE --------------------------- + [HEADER] 16 octets + .nlmsg_len = 996 + .nlmsg_type = 16 + .nlmsg_flags = 2 + .nlmsg_seq = 1301410712 + .nlmsg_pid = 20014 + [PAYLOAD] 16 octets + 00 00 04 03 01 00 00 00 49 00 01 00 00 00 00 00 ........I....... + [ATTR 03] 3 octets + 6c 6f 00 lo. + [PADDING] 1 octets + 00 . + [ATTR 13] 4 octets + 00 00 00 00 .... + [ATTR 16] 1 octets + 00 . + [PADDING] 3 octets + 00 00 00 ... + [ATTR 17] 1 octets + 00 . + [...] +--------------------------- END NETLINK MESSAGE --------------------------- + +----- + +[[core_prot_fund]] +== Netlink Protocol Fundamentals + +The netlink protocol is a socket based IPC mechanism used for +communication between userspace processes and the kernel or between +userspace processes themselves. The netlink protocol is based on BSD +sockets and uses the +AF_NETLINK+ address family. Every netlink +protocol uses its own protocol number (e.g. +NETLINK_ROUTE+, ++NETLINK_NETFILTER+, etc). Its addressing schema is based on a 32 bit +port number, formerly referred to as PID, which uniquely identifies +each peer. + +[[core_msg_format]] +=== Message Format + +A netlink protocol is typically based on messages and consists of the +netlink message header (+struct nlmsghdr+) plus the payload attached +to it. The payload can consist of arbitary data but usually contains +a fixed size protocol specific header followed by a stream of +attributes. + +.Netlink message header (+struct nlmsghdr+) +[cols="^s,^s", width="40%", align="center"] +|============================================================== +2+| Length +| Type | Flags +2+| Sequence Number +2+| Port (Address) +|============================================================== + + +[[core_msg_types]] +=== Message Types + +Netlink differs between requests, notifications, and replies. Requests +are messages which have the +NLM_F_REQUEST+ flag set and are meant to +request an action from the receiver. A request is typically sent from +a userspace process to the kernel. While not strictly enforced, requests +should carry a sequence number incremented for each request sent. + +Depending on the nature of the request, the receiver may reply to the +request with another netlink message. The sequence number of a reply +must match the sequence number of the request it relates to. + +Notifications are of informal nature and no reply is expected, therefore +the sequence number is typically set to 0. + +["mscgen"] +-------- +msc { + A,B; + A=>B [label="GET (seq=1, NLM_F_REQUEST)"]; + A<=B [label="PUT (seq=1)"]; + ...; + A<=B [label="NOTIFY (seq=0)"]; +} +-------- + + +The type of message is primarly identified by its 16 bit message type set +in the message header. The following standard message types are defined: + +- +NLMSG_NOOP+ - No operation, message must be discarded +- +NLMSG_ERROR+ - Error message or ACK, see <>, respectively <> +- +NLMSG_DONE+ - End of multipart sequence, see <> +- +NLMSG_OVERRUN+ - Overrun notification (Error) + +Every netlink protocol is free to define own message types. Note that +message type values +< NLMSG_MIN_TYPE (0x10)+ are reserved and may +not be used. + +It is common practice to use own message types to implement RPC schemas. +Suppose the goal of the netlink protocol you are implementing is allow +configuration of a particular network device, therefore you want to +provide read/write access to various configuration options. The typical +"netlink way" of doing this would be to define two message types ++MSG_SETCFG+, +MSG_GETCFG+: + +[source,c] +-------- +#define MSG_SETCFG 0x11 +#define MSG_GETCFG 0x12 +-------- + +Sending a +MSG_GETCFG+ request message will typically trigger a reply +with the message type +MSG_SETCFG+ containing the current configuration. +In object oriented terms one would describe this as "the kernel sets +the local copy of the configuration in userspace". + +["mscgen"] +-------- +msc { + A,B; + A=>B [label="MSG_GETCFG (seq=1, NLM_F_REQUEST)"]; + A<=B [label="MSG_SETCFG (seq=1)"]; +} +-------- + +The configuration may be changed by sending a +MSG_SETCFG+ which will +be responded to with either a ACK (see <>) +or a error message (see <>). + +["mscgen"] +-------- +msc { + A,B; + A=>B [label="MSG_SETCFG (seq=1, NLM_F_REQUEST, NLM_F_ACK)"]; + A<=B [label="ACK (seq=1)"]; +} +-------- + +Optionally, the kernel may send out notifications for configuration +changes allowing userspace to listen for changes instead of polling +frequently. Notifications typically reuse an existing message type +and rely on the application using a separate socket to differ between +requests and notifications but you may also specify a separate message +type. + +["mscgen"] +-------- +msc { + A,B; + A<=B [label="MSG_SETCFG (seq=0)"]; +} +-------- + +[[core_multipart]] +==== Multipart Messages + +Although in theory a netlink message can be up to 4GiB in size. The socket +buffers are very likely not large enough to hold message of such sizes. +Therefore it is common to limit messages to one page size (PAGE_SIZE) and +use the multipart mechanism to split large pieces of data into several +messages. A multipart message has the flag +NLM_F_MULTI+ set and the +receiver is expected to continue receiving and parsing until the special +message type +NLMSG_DONE+ is received. + +Multipart messages unlike fragmented ip packets must not be reassmbled +even though it is perfectly legal to do so if the protocols wishes to +work this way. Often multipart message are used to send lists or trees +of objects were each multipart message simply carries multiple objects +allow for each message to be parsed independently. + +["mscgen"] +-------- +msc { + A,B; + A=>B [label="GET (seq=1, NLM_F_REQUEST)"]; + A<=B [label="PUT (seq=1, NLM_F_MULTI)"]; + ...; + A<=B [label="PUT (seq=1, NLM_F_MULTI)"]; + A<=B [label="NLMSG_DONE (seq=1)"]; +} +-------- + +[[core_errmsg]] +==== Error Message + +Error messages can be sent in response to a request. Error messages must +use the standard message type +NLMSG_ERROR+. The payload consists of a +error code and the original netlink mesage header of the request. + +.Netlink Error Message Header (+struct nlmsggerr) +[cols="^,^", width="50%"] +|============================================================== +2+| Length +|.nlmsg_type = NLMSG_ERROR | .nlmsg_flags = 0 +2+| Sequence number of the orig request +2+| Port number of the orig request +2+| Error Code (e.g. EINVAL) +2+| Netlink Message Header of orig. request +|============================================================== + +Error messages should set the sequence number to the sequence number +of the request which caused the error. + +["mscgen"] +-------- +msc { + A,B; + A=>B [label="GET (seq=1, NLM_F_REQUEST)"]; + A<=B [label="NLMSG_ERROR code=EINVAL (seq=1)"]; +} +-------- + +[[core_msg_ack]] +==== ACKs + +A sender can request an ACK message to be sent back for each request +processed by setting the +NLM_F_ACK+ flag in the request. This is typically +used to allow the sender to synchronize further processing until the +request has been processed by the receiver. + +["mscgen"] +-------- +msc { + A,B; + A=>B [label="GET (seq=1, NLM_F_REQUEST | NLM_F_ACK)"]; + A<=B [label="ACK (seq=1)"]; +} +-------- + +ACK messages also use the message type +NLMSG_ERROR+ and payload +format but the error code is set to 0. + +==== Message Flags + +The following standard flags are defined + +[source,c] +-------- +#define NLM_F_REQUEST 1 +#define NLM_F_MULTI 2 +#define NLM_F_ACK 4 +#define NLM_F_ECHO 8 +-------- + +- `NLM_F_REQUEST` - Message is a request, see <>. +- `NLM_F_MULTI` - Multipart message, see <> +- `NLM_F_ACK` - ACK message requested, see <>. +- `NLM_F_ECHO` - Request to echo the request. + +The flag +NLM_F_ECHO+ is similar to the `NLM_F_ACK` flag. It can be +used in combination with `NLM_F_REQUEST` and causes a notification +which is sent as a result of a request to also be sent to the sender +regardless of whether the sender has subscribed to the corresponding +multicast group or not. See <> + +Additional universal message flags are defined which only apply for ++GET+ requests: + +[source,c] +-------- +#define NLM_F_ROOT 0x100 +#define NLM_F_MATCH 0x200 +#define NLM_F_ATOMIC 0x400 +#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH) +-------- + +- `NLM_F_ROOT` - Return based on root of tree. +- `NLM_F_MATCH` - Return all matching entries. +- `NLM_F_ATOMIC` - Obsoleted, once used to request an atomic operation. +- `NLM_F_DUMP` - Return a list of all objects + (`NLM_F_ROOT`|`NLM_F_MATCH`). + +Use of these flags is completely optional and many netlink protocols only +make use of the `NLM_F_DUMP` flag which typically requests the receiver +to send a list of all objects in the context of the message type as a +sequence of multipart messages (see <>). + +Another set of flags exist related to `NEW` or `SET` requests. These +flags are mutually exclusive to the `GET` flags: + +[source,c] +-------- +#define NLM_F_REPLACE 0x100 +#define NLM_F_EXCL 0x200 +#define NLM_F_CREATE 0x400 +#define NLM_F_APPEND 0x800 +-------- + +- `NLM_F_REPLACE` - Replace an existing object if it exists. +- `NLM_F_EXCL` - Do not update object if it exists already. +- `NLM_F_CREATE` - Create object if it does not exist yet. +- `NLM_F_APPEND` - Add object at end of list. + +Behaviour of these flags may differ slightly between different netlink +protocols. + +=== Sequence Numbers + +Netlink allows the use of sequence numbers to help relate replies to +requests. It should be noted that unlike in protocols such as TCP +there is no strict enforcment of the sequence number. The sole purpose +of sequence numbers is to assist a sender in relating replies to the +corresponding requests. See <> for more +information. + +Sequence numbers are managed on a per socket basis, see +<> for more information on +how to use sequence numbers. + +[[core_multicast]] +=== Multicast Groups + +TODO + +See <> + +== Netlink Sockets + +In order to use the netlink protocol, a netlink socket is required. +Each socket defines a completely independent context for sending and +receiving of messages. An application may use multiple sockets for the +same netlink protocol, e.g. one socket to send requests and receive +replies and another socket subscribed to a multicast group to receive +notifications. + +=== Socket Allocation & Freeing + +The netlink socket and all its related attributes are represented by +=struct nl_sock=. + +[source,c] +-------- +#include + +struct nl_sock *nl_socket_alloc(void) +void nl_socket_free(struct nl_sock *sk) +-------- + +[[core_sk_seq_num]] +=== Sequence Numbers + +The library will automatically take care of sequence number handling +for the application. A sequence number counter is stored in struct +nl_sock which is meant to be used when sending messages which will +produce a reply, error or any other message which needs to be +related to the original message. + +The counter can be used directly with the function nl_socket_use_seq() +which will return the current value of the counter and increment it by +one afterwards. + +[source,c] +-------- +#include + +unsigned int nl_socket_use_seq(struct nl_sock *sk); +-------- + +Most applications will not want to deal with sequence number handling +themselves though. When using nl_send_auto() the sequence number is +filled out automatically and matched again on the receiving side. See +<> for more +information. + +This behaviour can and must be disabled if the netlink protocol +implemented does not use a request/reply model, e.g. when a socket is +used to receive notification messages. + +[source,c] +-------- +#include + +void nl_socket_disable_seq_check(struct nl_sock *sk); +-------- + +[[core_sk_multicast]] +=== Multicast Group Subscriptions + +Each socket can subscribe to any number of multicast groups of the +netlink protocol it is connected to. The socket will then receive a +copy of each message sent to any of the groups. Multicast groups are +commonly used to implement event notifications. + +Prior to kernel 2.6.14 the group subscription was performed using a +bitmask which limited the number of groups per protocol family to 32. +This outdated interface can still be accessed via the function +nl_join_groups even though it is not recommended for new code. + +[source,c] +-------- +#include + +void nl_join_groups(struct nl_sock *sk, int bitmask); +-------- + +Starting with 2.6.14 a new method was introduced which supports subscribing +to an almost infinite number of multicast groups. + +[source,c] +-------- +#include + +int nl_socket_add_memberships(struct nl_sock *sk, int group, ...); +int nl_socket_drop_memberships(struct nl_sock *sk, int group, ...); +-------- + +==== Multicast Example + +[source,c] +-------- +#include +#include +#include + +/* + * This function will be called for each valid netlink message received + * in nl_recvmsgs_default() + */ +static int my_func(struct nl_msg *msg, void *arg) +{ + return 0; +} + +struct nl_sock *sk; + +/* Allocate a new socket */ +sk = nl_socket_alloc(); + +/* + * Notifications do not use sequence numbers, disable sequence number + * checking. + */ +nl_socket_disable_seq_check(sk); + +/* + * Define a callback function, which will be called for each notification + * received + */ +nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, my_func, NULL); + +/* Connect to routing netlink protocol */ +nl_connect(sk, NETLINK_ROUTE); + +/* Subscribe to link notifications group */ +nl_socket_add_memberships(sk, RTNLGRP_LINK); + +/* + * Start receiving messages. The function nl_recvmsgs_default() will block + * until one or more netlink messages (notification) are received which + * will be passed on to my_func(). + */ +while (1) + nl_recvmsgs_default(sock); +-------- + +[[core_sk_cb]] +=== Modifiying Socket Callback Configuration + +See <> for more information on +callback hooks and overwriting capabilities. + +Each socket is assigned a callback configuration which controls the +behaviour of the socket. This is f.e. required to have a separate +message receive function per socket. It is perfectly legal to share +callback configurations between sockets though. + +The following functions can be used to access and set the callback +configuration of a socket: + +[source,c] +-------- +#include + +struct nl_cb *nl_socket_get_cb(const struct nl_sock *sk); +void nl_socket_set_cb(struct nl_sock *sk, struct nl_cb *cb); +-------- + +Additionaly a shortcut exists to modify the callback configuration +assigned to a socket directly: + +[source,c] +-------- +#include + +int nl_socket_modify_cb(struct nl_sock *sk, enum nl_cb_type type, enum nl_cb_kind kind, + nl_recvmsg_msg_cb_t func, void *arg); +-------- + +.Example: +[source,c] +-------- +#include + +// Call my_input() for all valid messages received in socket sk +nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, my_input, NULL); +-------- + +=== Socket Attributes + +.Local Port + +The local port number uniquely identifies the socket and is used to +address it. A unique local port is generated automatically when the +socket is allocated. It will consist of the Process ID (22 bits) and a +random number (10 bits) thus allowing up to 1024 sockets per process. + +[source,c] +-------- +#include + +uint32_t nl_socket_get_local_port(const struct nl_sock *sk); +void nl_socket_set_local_port(struct nl_sock *sk, uint32_t port); +-------- + +CAUTION: Overwriting the local port is possible but you have to ensure +that the provided value is unique and no other socket in any other +application is using the same value. + +.Peer Port + +A peer port can be assigned to the socket which will result in all +unicast messages sent over the socket to be addresses to the peer. If +no peer is specified, the message is sent to the kernel which will try +to automatically bind the socket to a kernel side socket of the same +netlink protocol family. It is common practice not to bind the socket +to a peer port as typically only one kernel side socket exists per +netlink protocol family. + +[source,c] +-------- +#include + +uint32_t nl_socket_get_peer_port(const struct nl_sock *sk); +void nl_socket_set_peer_port(struct nl_sock *sk, uint32_t port); +-------- + +.File Descriptor + +Netlink uses the BSD socket interface, therefore a file descriptor is +behind each socket and you may use it directly. + +[source,c] +-------- +#include + +int nl_socket_get_fd(const struct nl_sock *sk); +-------- + +If a socket is used to only receive notifications it usually is best +to put the socket in non-blocking mode and periodically poll for new +notifications. + +[source,c] +-------- +#include + +int nl_socket_set_nonblocking(const struct nl_sock *sk); +-------- + +.Send/Receive Buffer Size + +The socket buffer is used to queue netlink messages between sender and +receiver. The size of these buffers specifies the maximum size you +will be able to write() to a netlink socket, i.e. it will indirectly +define the maximum message size. The default is 32KiB. + +[source,c] +-------- +#include + +int nl_socket_set_buffer_size(struct nl_sock *sk, int rx, int tx); +-------- + +[[core_sk_cred]] +.Enable/Disable Credentials + +TODO + +[source,c] +-------- +#include + +int nl_socket_set_passcred(struct nl_sock *sk, int state); +-------- + +.Enable/Disable Auto-ACK Mode + +The following functions allow to enable/disable Auto-ACK mode on a +socket. See <> for more information on +what implications that has. Auto-ACK mode is enabled by default. + +[source,c] +-------- +#include + +void nl_socket_enable_auto_ack(struct nl_sock *sk); +void nl_socket_disable_auto_ack(struct nl_sock *sk); +-------- + +.Enable/Disable Message Peeking + +If enabled, message peeking causes nl_recv() to try and use MSG_PEEK +to retrieve the size of the next message received and allocate a +buffer of that size. Message peeking is enabled by default but can be +disabled using the following function: + +[source,c] +-------- +#include + +void nl_socket_enable_msg_peek(struct nl_sock *sk); +void nl_socket_disable_msg_peek(struct nl_sock *sk); +-------- + +.Enable/Disable Receival of Packet Information + +If enabled, each received netlink message from the kernel will include +an additional struct nl_pktinfo in the control message. The following +function can be used to enable/disable receival of packet information. + +[source,c] +-------- +#include + +int nl_socket_recv_pktinfo(struct nl_sock *sk, int state); +-------- + +NOTE: Processing of NETLINK_PKTINFO has not been implemented yet. + +[[core_send_recv]] +== Sending and Receiving of Messages / Data + +[[core_send]] +=== Sending Netlink Messages + +The standard method of sending a netlink message over a netlink socket +is to use the function nl_send_auto(). It will automatically complete +the netlink message by filling the missing bits and pieces in the +netlink message header and will deal with addressing based on the +options and address set in the netlink socket. The message is then +passed on to nl_send(). + +If the default sending semantics implemented by nl_send() do not suit +the application, it may overwrite the sending function nl_send() by +specifying an own implementation using the function +nl_cb_overwrite_send(). + +[source,c] +-------- + nl_send_auto(sk, msg) + | + |-----> nl_complete_msg(sk, msg) + | + | + | Own send function specified via nl_cb_overwrite_send() + |- - - - - - - - - - - - - - - - - - - - + v v + nl_send(sk, msg) send_func() +-------- + +.Using nl_send() + +If you do not require any of the automatic message completion +functionality you may use nl_send() directly but beware that any +internal calls to nl_send_auto() by the library to send netlink +messages will still use nl_send(). Therefore if you wish to use any +higher level interfaces and the behaviour of nl_send() is to your +dislike then you must overwrite the nl_send() function via +nl_cb_overwrite_send() + +The purpose of nl_send() is to embed the netlink message into a iovec +structure and pass it on to nl_send_iovec(). + +[source,c] +-------- + nl_send(sk, msg) + | + v + nl_send_iovec(sk, msg, iov, iovlen) +-------- + +.Using nl_send_iovec() + +nl_send_iovec() expects a finalized netlink message and fills out the +struct msghdr used for addressing. It will first check if the struct +nl_msg is addressed to a specific peer (see nlmsg_set_dst()). If not, +it will try to fall back to the peer address specified in the socket +(see nl_socket_set_peer_port(). Otherwise the message will be sent +unaddressed and it is left to the kernel to find the correct peer. + +nl_send_iovec() also adds credentials if present and enabled +(see <>). + +The message is then passed on to nl_sendmsg(). + +[source,c] +-------- + nl_send_iovec(sk, msg, iov, iovlen) + | + v + nl_sendmsg(sk, msg, msghdr) +-------- + +.Using nl_sendmsg() + +nl_sendmsg() expects a finalized netlink message and an optional +struct msghdr containing the peer address. It will copy the local +address as defined in the socket (see nl_socket_set_local_port()) into +the netlink message header. + +At this point, construction of the message finished and it is ready to +be sent. + +[source,c] +-------- + nl_sendmsg(sk, msg, msghdr) + |- - - - - - - - - - - - - - - - - - - - v + | NL_CB_MSG_OUT() + |<- - - - - - - - - - - - - - - - - - - -+ + v + sendmsg() +-------- + +Before sending the application has one last chance to modify the +message. It is passed to the NL_CB_MSG_OUT callback function which +may inspect or modify the message and return an error code. If this +error code is NL_OK the message is sent using sendmsg() resulting in +the number of bytes written being returned. Otherwise the message +sending process is aborted and the error code specified by the +callback function is returned. See <> for more information on how to set callbacks. + +.Sending Raw Data with nl_sendto() + +If you wish to send raw data over a netlink socket, the following +function will pass on any buffer provided to it directly to sendto(): + +[source,c] +-------- +#include + +int nl_sendto(struct nl_sock *sk, void *buf, size_t size); +-------- + +.Sending of Simple Messages + +A special interface exists for sending of trivial messages. The function +expects the netlink message type, optional netlink message flags, and an +optional data buffer and data length. +[source,c] +-------- +#include + +int nl_send_simple(struct nl_sock *sk, int type, int flags, + void *buf, size_t size); +-------- + +The function will construct a netlink message header based on the message +type and flags provided and append the data buffer as message payload. The +newly constructed message is sent with nl_send_auto(). + +The following example will send a netlink request message causing the +kernel to dump a list of all network links to userspace: + +[source,c] +-------- +#include + +struct nl_sock *sk; +struct rtgenmsg rt_hdr = { + .rtgen_family = AF_UNSPEC, +}; + +sk = nl_socket_alloc(); +nl_connect(sk, NETLINK_ROUTE); + +nl_send_simple(sock, RTM_GETLINK, NLM_F_DUMP, &rt_hdr, sizeof(rt_hdr)); +-------- + +[[core_recv]] +=== Receiving Netlink Messages + +The easiest method to receive netlink messages is to call nl_recvmsgs_default(). +It will receive messages based on the semantics defined in the socket. The +application may customize these in detail although the default behaviour will +probably suit most applications. + +nl_recvmsgs_default() will also be called internally by the library whenever +it needs to receive and parse a netlink message. + +The function will fetch the callback configuration stored in the socket and +call nl_recvmsgs(): + +[source,c] +-------- + nl_recvmsgs_default(sk) + | + | cb = nl_socket_get_cb(sk) + v + nl_recvmsgs(sk, cb) +-------- + +.Using nl_recvmsgs() + +nl_recvmsgs() implements the actual receiving loop, it blocks until a +netlink message has been received unless the socket has been put into +non-blocking mode. + +For the unlikely scenario that certain required receive +characteristics can not be achieved by fine tuning the internal +recvmsgs function using the callback configuration (see <>) the application may provide a +complete own implementation of it and overwrite all calls to +nl_recvmsgs() with the function nl_cb_overwrite_recvmsgs(). + +[source,c] +-------- + nl_recvmsgs(sk, cb) + | + | Own recvmsgs function specified via nl_cb_overwrite_recvmsgs() + |- - - - - - - - - - - - - - - - - - - - + v v + internal_recvmsgs() my_recvmsgs() +-------- + +[[core_recv_character]] +.Receive Characteristics + +If the application does not provide its own recvmsgs() implementation +with the function nl_cb_overwrite_recvmsgs() the following characteristics +apply while receiving data from a netlink socket: + +[source,c] +-------- + internal_recvmsgs() + | ++-------------->| Own recv function specified with nl_cb_overwrite_recv() +| |- - - - - - - - - - - - - - - - +| v v +| nl_recv() my_recv() +| |<- - - - - - - - - - - - - - -+ +| |<-------------+ +| v | More data to parse? (nlmsg_next()) +| Parse Message | +| |--------------+ +| v ++------- NLM_F_MULTI set? + | + v + (SUCCESS) +-------- + +The function nl_recv() is invoked first to receive data from the +netlink socket. This function may be overwritten by the application +by an own implementation using the function nl_cb_overwrite_recv(). +This may be useful if the netlink byte stream is in fact not received +from a socket directly but is read from a file or another source. + +If data has been read, it will be attemped to parse the data. This +will be done repeately until the parser returns NL_STOP, an error was +returned or all data has been parsed. + +In case the last message parsed successfully was a multipart message +(see <>) and the parser did not +quit due to either an error or NL_STOP nl_recv() respectively the +applications own implementation will be called again and the parser +starts all over. + +See <> for information on +how to extract valid netlink messages from the parser and on how to +control the behaviour of it. + +[[core_parse_character]] +.Parsing Characteristics + +The internal parser is invoked for each netlink message received from +a netlink socket. It is typically fed by nl_recv() (see +<>). + +The parser will first ensure that the length of the data stream +provided is sufficient to contain a netlink message header and that +the message length as specified in the message header does not exceed +it. + +If this criteria is met, a new struct nl_msg is allocated and the +message is passed on to the the callback function NL_CB_MSG_IN if one +is set. Like any other callback function, it may return NL_SKIP to +skip the current message but continue parsing the next message or +NL_STOP to stop parsing completely. + +The next step is to check the sequence number of the message against +the currently expected sequence number. The application may provide +its own sequence number checking algorithm by setting the callback +function NL_CB_SEQ_CHECK to its own implementation. In fact, calling +nl_socket_disable_seq_check() to disable sequence number checking will +do nothing more than set the NL_CB_SEQ_CHECK hook to a function which +always returns NL_OK. + +Another callback hook NL_CB_SEND_ACK exists which is called if the +message has the NLM_F_ACK flag set. Although I am not aware of any +userspace netlink socket doing this, the application may want to send +an ACK message back to the sender (see <>). + +[source,c] +-------- + parse() + | + v + nlmsg_ok() --> Ignore + | + |- - - - - - - - - - - - - - - v + | NL_CB_MSG_IN() + |<- - - - - - - - - - - - - - -+ + | + |- - - - - - - - - - - - - - - v + Sequence Check NL_CB_SEQ_CHECK() + |<- - - - - - - - - - - - - - -+ + | + | Message has NLM_F_ACK set + |- - - - - - - - - - - - - - - v + | NL_CB_SEND_ACK() + |<- - - - - - - - - - - - - - -+ + | + Handle Message Type +-------- + +[[core_auto_ack]] +=== Auto-ACK Mode + +TODO + +== Netlink Message Parsing & Construction + +=== Message Format + +See <> for an introduction to +the netlink protocol and its message format. + +.Alignment + +Most netlink protocols enforce a strict alignment policy for all +boundries. The alignment value is defined by NLMSG_ALIGNTO and is +fixed to 4 bytes. Therefore all netlink message headers, begin of +payload sections, protocol specific headers, and attribute sections +must start at an offset which is a multiple of NLMSG_ALIGNTO. + +[source,c] +-------- +#include + +int nlmsg_size(int payloadlen); +int nlmsg_total_size(int payloadlen); +-------- + +The library provides a set of function to handle alignment +requirements automatically. The function nlmsg_total_size() returns +the total size of a netlink message including the padding to ensure +the next message header is aligned correctly. + +[source,c] +-------- + <----------- nlmsg_total_size(len) ------------> + <----------- nlmsg_size(len) ------------> + +-------------------+- - -+- - - - - - - - +- - -+-------------------+- - - + | struct nlmsghdr | Pad | Payload | Pad | struct nlsmghdr | + +-------------------+- - -+- - - - - - - - +- - -+-------------------+- - - + <---- NLMSG_HDRLEN -----> <- NLMSG_ALIGN(len) -> <---- NLMSG_HDRLEN --- +-------- + +If you need to know if padding needs to be added at the end of a +message, nlmsg_padlen() returns the number of padding bytes that need +to be added for a specific payload length. + +[source,c] +-------- +#include +int nlmsg_padlen(int payloadlen); +-------- + +=== Parsing a Message + +The library offers two different methods of parsing netlink messages. +It offers a low level interface for applications which want to do all +the parsing manually. This method is described below. Alternatively +the library also offers an interface to implement a parser as part of +a cache operations set which is especially useful when your protocol +deals with objects of any sort such as network links, routes, etc. +This high level interface is described in <> + +.Splitting a byte stream into separate messages + +What you receive from a netlink socket is typically a stream of +messages. You will be given a buffer and its length, the buffer may +contain any number of netlink messages. + +The first message header starts at the beginning of message stream. +Any subsequent message headers are access by calling nlmsg_next() on +the previous header. + +[source,c] +-------- +#include + +struct nlmsghdr *nlmsg_next(struct nlmsghdr *hdr, int *remaining); +-------- + +The function nlmsg_next() will automatically substract the size of the +previous message from the remaining number of bytes. + +Please note, there is no indication in the previous message whether +another message follows or not. You must assume that more messages +follow until all bytes of the message stream have been processed. + +To simplify this, the function nlmsg_ok() exists which returns true if +another message fits into the remaining number of bytes in the message +stream. nlmsg_valid_hdr() is similar, it checks whether a specific +netlink message contains at least a minimum of payload. + +[source,c] +-------- +#include + +int nlmsg_valid_hdr(const struct nlmsghdr *hdr, int payloadlen); +int nlmsg_ok(const struct nlmsghdr *hdr, int remaining); +-------- + +A typical use of these functions looks like this: + +[source,c] +-------- +#include + +void my_parse(void *stream, int length) +{ + struct nlmsghdr *hdr = stream; + + while (nlmsg_ok(hdr, length)) { + // Parse message here + hdr = nlmsg_next(hdr, &length); + } +} +-------- + +CAUTION: nlmsg_ok() only returns true if the *complete* message including + the message payload fits into the remaining buffer length. It will + return false if only a part of it fits. + +The above can also be written using the iterator nlmsg_for_each(): + +[source,c] +-------- +#include + +struct nlmsghdr *hdr; + +nlmsg_for_each(hdr, stream, length) { + /* do something with message */ +} +-------- + +.Message Payload + +The message payload is appended to the message header and is guranteed +to start at a multiple of +NLMSG_ALIGNTO+. Padding at the end of the +message header is added if necessary to ensure this. The function +nlmsg_data() will calculate the necessary offset based on the message +and returns a pointer to the start of the message payload. + +[source,c] +-------- +#include + +void *nlmsg_data(const struct nlmsghdr *nlh); +void *nlmsg_tail(const struct nlmsghdr *nlh); +int nlmsg_datalen(const struct nlmsghdr *nlh); +-------- + +The length of the message payload is returned by nlmsg_datalen(). + +[source,c] +-------- + <--- nlmsg_datalen(nlh) ---> + +-------------------+- - -+----------------------------+- - -+ + | struct nlmsghdr | Pad | Payload | Pad | + +-------------------+- - -+----------------------------+- - -+ +nlmsg_data(nlh) ---------------^ ^ +nlmsg_tail(nlh) --------------------------------------------------^ +-------- + +The payload may consist of arbitary data but may have strict alignment +and formatting rules depening on the actual netlink protocol. + +[[core_msg_attr]] +.Message Attributes + +Most netlink protocols use netlink attributes. It not only makes the +protocol self documenting but also gives flexibility in expanding the +protocol at a later point. New attributes can be added at any time and +older attributes can be obsoleted by newer ones without breaking +binary compatibility of the protocol. + +[source,c] +-------- + <---------------------- payload -------------------------> + <----- hdrlen ----> <- nlmsg_attrlen(nlh, hdrlen) -> + +-------------------+- - -+----- ------------+- - -+--------------------------------+- - -+ + | struct nlmsghdr | Pad | Protocol Header | Pad | Attributes | Pad | + +-------------------+- - -+-------------------+- - -+--------------------------------+- - -+ +nlmsg_attrdata(nlh, hdrlen) -----------------------------^ +-------- + +The function nlmsg_attrdata() returns a pointer to the begin of the +attributes section. The length of the attributes section is returned +by the function nlmsg_attrlen(). + +[source,c] +-------- +#include + +struct nlattr *nlmsg_attrdata(const struct nlmsghdr *hdr, int hdrlen); +int nlmsg_attrlen(const struct nlmsghdr *hdr, int hdrlen); +-------- + +See <> for more information on how to use netlink +attributes. + +.Parsing a Message the Easy Way + +The function nlmsg_parse() validate a complete netlink message in one +step. If +hdrlen > 0+ it will first call nlmsg_valid_hdr() to check +if the protocol header fits into the message. If there is more payload +to parse, it will assume it to be attributes and parse the payload +accordingly. The function behaves exactly like nla_parse() when +parsing attributes, see <>. + +[source,c] +-------- +int nlmsg_parse(struct nlmsghdr *hdr, int hdrlen, struct nlattr **attrs, + int maxtype, struct nla_policy *policy); +-------- + +The function nlmsg_validate() is based on nla_validate() and behaves +exactly the same as nlmsg_parse() except that it only validates and +will not fill a array with pointers to each attribute. + +[source,c] +-------- +int nlmsg_validate(struct nlmsghdr *hdr, int hdrlen, intmaxtype, + struct nla_policy *policy); +-------- + +See <> for an +example and more information on attribute parsing. + +=== Construction of a Message + +See <> for information on the netlink +message format and alignment requirements. + +Message construction is based on struct nl_msg which uses an internal +buffer to store the actual netlink message. struct nl_msg +does not+ +point to the netlink message header. Use nlmsg_hdr() to retrieve a +pointer to the netlink message header. + +At allocation time, a maximum message size is specified. It defaults +to a page (PAGE_SIZE). The application constructing the message will +reserve space out of this maximum message size repeatedly for each +header or attribute added. This allows construction of messages across +various layers of code where lower layers do not need to know about +the space requirements of upper layers. + ++Why is setting the maximum message size necessary?+ This +question is often raised in combination with the proposed solution of +reallocating the message payload buffer on the fly using realloc(). +While it is possible to reallocate the buffer during construction +using nlmsg_expand() it will make all pointers into the message buffer +become stale. This breaks usage of nlmsg_hdr(), nla_nest_start(), and +nla_nest_end() and is therefore not acceptable as default behaviour. + +.Allocating struct nl_msg + +The first step in constructing a new netlink message it to allocate a +`struct nl_msg` to hold the message header and payload. Several +functions exist to simplify various tasks. + +[source,c] +-------- +#include + +struct nl_msg *nlmsg_alloc(void); +void nlmsg_free(struct nl_msg *msg); +-------- + +The function nlmsg_alloc() is the default message allocation function. +It allocates a new message using the default maximum message size which +equals to one page (PAGE_SIZE). The application can change the default +size for messages by calling nlmsg_set_default_size(): + +[source,c] +-------- +void nlmsg_set_default_size(size_t); +-------- + +NOTE: Calling nlmsg_set_default_size() does not change the maximum + message size of already allocated messages. + +[source,c] +-------- +struct nl_msg *nlmsg_alloc_size(size_t max); +-------- + +Instead of changing the default message size, the function +nlmsg_alloc_size() can be used to allocate a message with a individual +maximum message size. + + +If the netlink message header is already known at allocation time, the +application may sue nlmsg_inherit(). It will allocate a message using +the default maximum message size and copy the header into the message. +Calling nlmsg_inherit with +set+ to NULL is equivalent to calling +nlmsg_alloc(). + +[source,c] +-------- +struct nl_msg *nlmsg_inherit(struct nlmsghdr *hdr); +-------- + +Alternatively nlmsg_alloc_simple() takes a netlink message type and +netlink message flags. It is equivalent to nlmsg_inherit() except that it +takes the two common header fields as arguments instead of a complete +header. + +[source,c] +-------- +#include + +struct nl_msg *nlmsg_alloc_simple(int nlmsg_type, int flags); +-------- + +.Appending the netlink message header + +After allocating struct nl_msg, the netlink message header needs to be +added unless one of the function nlmsg_alloc_simple() or nlmsg_inherit() +have been used for allocation in which case this step will replace the +netlink message header already in place. + +[source,c] +-------- +#include + +struct nlmsghdr *nlmsg_put(struct nl_msg *msg, uint32_t port, uint32_t seqnr, + int nlmsg_type, int payload, int nlmsg_flags); +-------- + +The function nlmsg_put() will build a netlink message header out of ++nlmsg_type+, +nlmsg_flags+, +seqnr+, and +port+ and copy it into the +netlink message. +seqnr+ can be set to +NL_AUTO_SEQ+ to indiciate +that the next possible sequence number should be used automatically. +To use this feature, the message must be sent using the function +nl_send_auto(). Like +port+, the argument +seqnr+ can be set to ++NL_AUTO_PORT+ indicating that the local port assigned to the socket +should be used as source port. This is generally a good idea unless +you are replying to a request. See <> for more information on how to fill the header. + +NOTE: The argument +payload+ can be used by the application to reserve + room for additional data after the header. A value of > 0 is + equivalent to calling +nlmsg_reserve(msg, payload, + NLMSG_ALIGNTO)+. See <> for more information on reserving room for + data. + +.Example +[source,c] +-------- +#include + +struct nlmsghdr *hdr; +struct nl_msg *msg; +struct myhdr { + uint32_t foo1, foo2; +} hdr = { 10, 20 }; + +/* Allocate a message with the default maximum message size */ +msg = nlmsg_alloc(); + +/* + * Add header with message type MY_MSGTYPE, the flag NLM_F_CREATE, + * let library fill port and sequence number, and reserve room for + * struct myhdr + */ +hdr = nlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, MY_MSGTYPE, sizeof(hdr), NLM_F_CREATE); + +/* Copy own header into newly reserved payload section */ +memcpy(nlmsg_data(hdr), &hdr, sizeof(hdr)); + +/* + * The message will now look like this: + * +-------------------+- - -+----------------+- - -+ + * | struct nlmsghdr | Pad | struct myhdr | Pad | + * +-------------------+-----+----------------+- - -+ + * nlh -^ / \ + * +--------+---------+ + * | foo1 | foo2 | + * +--------+---------+ + */ +-------- + +[[core_msg_reserve]] +.Reserving room at the end of the message + +Most functions described later on will automatically take care of +reserving room for the data that is added to the end of the netlink +message. In some situations it may be requried for the application +to reserve room directly though. + +[source,c] +-------- +#include + +void *nlmsg_reserve(struct nl_msg *msg, size_t len, int pad); +-------- + +The function nlmsg_reserve() reserves +len+ bytes at the end of the +netlink message and returns a pointer to the start of the reserved area. +The +pad+ argument can be used to request +len+ to be aligned to any +number of bytes prior to reservation. + +The following example requests to reserve a 17 bytes area at the end of +message aligned to 4 bytes. Therefore a total of 20 bytes will be +reserved. + +[source,c] +-------- +#include + +void *buf = nlmsg_reserve(msg, 17, 4); +-------- + +NOTE: `nlmsg_reserve()` will *not* align the start of the buffer. Any + alignment requirements must be provided by the owner of the + previous message section. + +.Appending data at the end of the message + +The function `nlmsg_append()` appends `len` bytes at the end of the +message, padding it if requested and necessary. + +[source,c] +-------- +#include + +int nlmsg_append(struct nl_msg *msg, void *data, size_t len, int pad); +-------- + +It is equivalent to calling `nlmsg_reserve()` and `memcpy()`ing the +data into the freshly reserved data section. + +NOTE: `nlmsg_append()` will *not* align the start of the data. Any + alignment requirements must be provided by the owner of the + previous message section. + +.Adding attribtues to a message + +Construction of attributes and addition of attribtues to the message is +covereted in section <>. + +[[core_attr]] +== Netlink Attributes + +Any form of payload should be encoded as netlink attributes whenever +possible. Use of attributes allows to extend any netlink protocol in +the future without breaking binary compatibility. F.e. Suppose your +device may currently be using 32 bit counters for statistics but years +later the device switches to maintaining 64 bit counters to account +for faster network hardware. If your protocol is using attributes the +move to 64 bit counters is trivial and only involves in sending an +additional attribute containing the 64 bit variants while still +providing the old legacy 32 bit counters. If your protocol is not using +attributes you will not be able to switch data types without breaking +all existing users of the protocol. + +The concept of nested attributes also allows for subsystems of your +protocol to implement and maintain their own attribute schemas. Suppose +a new generation of network device is introduced which requires a +completely new set of configuration settings which was unthinkable when +the netlink protocol was initially designed. Using attributes the new +generation of devices may define a new attribute and fill it with its +own new structure of attributes which extend or even obsolete the old +attributes. + +Therefore, _always_ use attributes even if you are almost certain that +the message format will never ever change in the future. + +[[core_attr_format]] +=== Attribute Format + +Netlink attributes allow for any number of data chunks of arbitary +length to be attached to a netlink message. See <> for more information on where attributes are +stored in the message. + +The format of the attributes data returned by nlmsg_attrdata() is as +follows: + +[source,c] +-------- + <----------- nla_total_size(payload) -----------> + <---------- nla_size(payload) -----------> + +-----------------+- - -+- - - - - - - - - +- - -+-----------------+- - - + | struct nlattr | Pad | Payload | Pad | struct nlattr | + +-----------------+- - -+- - - - - - - - - +- - -+-----------------+- - - + <---- NLA_HDRLEN -----> <--- NLA_ALIGN(len) ---> <---- NLA_HDRLEN --- +-------- + +Every attribute must start at an offset which is a multiple of ++NLA_ALIGNTO+ (4 bytes). If you need to know whether an attribute needs +to be padded at the end, the function nla_padlen() returns the number +of padding bytes that will or need to be added. + +-------- +0 1 2 3 +0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-------------------------------------------------------------+ +| Length | Type | ++------------------------------+------------------------------+ +| Attribute Payload | +. . +. . ++-------------------------------------------------------------+ +-------- + +Every attribute is encoded with a type and length field, both 16 bits, +stored in the attribute header (struct nlattr) preceding the attribute +payload. The length of an attribute is used to calculate the offset to +the next attribute. + +[[core_attr_parse]] +=== Parsing Attributes + +[[core_attr_parse_split]] +.Splitting an Attributes Stream into Attributes + +Although most applications will use one of the functions from the +nlmsg_parse() family (See <>) an interface exists to split the attributes stream +manually. + +As described in <> the attributes +section contains a infinite sequence or stream of attributes. The +pointer returned by nlmsg_attrdata() (See <>) points to the first attribute header. Any subsequent +attribute is accessed with the function nla_next() based on the +previous header. + +[source,c] +-------- +#include + +struct nlattr *nla_next(const struct nlattr *attr, int *remaining); +-------- + +The semantics are equivalent to nlmsg_next() and thus nla_next() will also +subtract the size of the previous attribute from the remaining number of +bytes in the attributes stream. + +Like messages, attributes do not contain an indicator whether another +attribute follows or not. The only indication is the number of bytes left +in the attribute stream. The function nla_ok() exists to determine whether +another attribute fits into the remaining number of bytes or not. + +[source,c] +-------- +#include + +int nla_ok(const struct nlattr *attr, int remaining); +-------- + +A typical use of nla_ok() and nla_next() looks like this: + +.nla_ok()/nla_next() usage +[source,c] +-------- +#include +#include + +struct nlattr *hdr = nlmsg_attrdata(msg, 0); +int remaining = nlmsg_attrlen(msg, 0); + +while (nla_ok(hdr, remaining)) { + /* parse attribute here */ + hdr = nla_next(hdr, &remaining); +}; +-------- + +NOTE: `nla_ok()` only returns true if the *complete* attributes + including the attribute payload fits into the remaining number + of bytes. + +.Accessing Attribute Header and Payload + +Once the individual attributes have been sorted out by either splitting +the attributes stream or using another interface the attribute header +and payload can be accessed. + +[source,c] +-------- + <- nla_len(hdr) -> + +-----------------+- - -+- - - - - - - - - +- - -+ + | struct nlattr | Pad | Payload | Pad | + +-----------------+- - -+- - - - - - - - - +- - -+ +nla_data(hdr) ---------------^ +-------- + +The functions nla_len() and nla_type() can be used to access the attribute +header. nla_len() will return the length of the payload not including +eventual padding bytes. nla_type returns the attribute type. + +[source,c] +-------- +#include + +int nla_len(const struct nlattr *hdr); +int nla_type(const struct nlattr *hdr); +-------- + +The function nla_data() will return a pointer to the attribute +payload. Please note that due to +NLA_ALIGNTO+ being 4 bytes it may +not be safe to cast and dereference the pointer for any datatype +larger than 32 bit depending on the architecture the application is +run on. + +[source,c] +-------- +#include + +void *nla_data(const struct nlattr *hdr); +-------- + +[NOTE] +Never rely on the size of a payload being what you expect it to be. +_Always_ verify the payload size and make sure that it matches your +expectations. See <>. + +[[core_attr_validation]] +.Attribute Validation + +When receiving netlink attributes, the receiver has certain expections +on how the attributes should look like. These expectations must be +defined to make sure the sending side meets our expecations. For this +purpose, a attribute validation interface exists which must be used +prior to accessing any payload. + +All functions providing attribute validation functionality are based +on struct nla_policy: + +[source,c] +-------- +struct nla_policy { + uint16_t type; + uint16_t minlen; + uint16_t maxlen; +}; +-------- + +The +type+ member specifies the datatype of the attribute, e.g. ++NLA_U32+, +NLA_STRING+, +NLA_FLAG+. The default is +NLA_UNSPEC+. The ++minlen+ member defines the minmum payload length of an attribute to +be considered a valid attribute. The value for +minlen+ is implicit +for most basic datatypes such as integers or flags. The +maxlen+ +member can be used to define a maximum payload length for an +attribute to still be considered valid. + +NOTE: Specyfing a maximum payload length is not recommended when + encoding structures in an attribute as it will prevent any + extension of the structure in the future. Something that is + frequently done in netlink protocols and does not break + backwards compatibility. + +One of the functions which use struct nla_policy is nla_validate(). +The function expects an array of struct nla_policy and will access the +array using the attribute type as index. If an attribute type is out +of bounds the attribute is assumed to be valid. This is intentional +behaviour to allow older applications not yet aware of recently +introduced attributes to continue functioning. + +[source,c] +-------- +#include + +int nla_validate(struct nlattr *head, int len, int maxtype, + struct nla_policy *policy); +-------- + +The function nla_validate() returns 0 if all attributes are valid, +otherwise a validation failure specific error code is returned. + +Most applications will rarely use nla_validate() directly but use +nla_parse() instead which takes care of validation in the same way but +also parses the the attributes in the same step. See +<> for an +example and more information. + +The validation process in detail: +-# If attribute type is 0 or exceeds +maxtype+ attribute is + considered valid, 0 is returned. +-# If payload length is < +minlen+, +-NLE_ERANGE+ is returned. +-# If +maxlen+ is defined and payload exceeds it, +-NLE_ERANGE+ + is returned. +-# Datatype specific requirements rules, see + <> +-# If all is ok, 0 is returned. + +[[core_attr_nla_parse]] +.Parsing Attributes the Easy Way + +Most applications will not want to deal with splitting attribute +streams themselves as described in <>. A much easier method is to use +nla_parse(). + +[source,c] +-------- +#include + +int nla_parse(struct nlattr **attrs, int maxtype, struct nlattr *head, + int len, struct nla_policy *policy); +-------- + +The function nla_parse() will iterate over a stream of attributes, +validate each attribute as described in <>. If the validation of all attributes succeeds, +a pointer to each attribute is stored in the +attrs+ array at +`attrs[nla_type(attr)]`. + +As an alernative to nla_parse() the function nlmsg_parse() can be used +to parse the message and its attributes in one step. See +<> for +information on how to use these functions. + +.Example: + +The following example demonstrates how to parse a netlink message sent +over a netlink protocol which does not use protocol headers. The example +does enforce a attribute policy however, the attribute MY_ATTR_FOO must +be a 32 bit integer, and the attribute MY_ATTR_BAR must be a string with +a maximum length of 16 characters. + +[source,c] +--------- +#include +#include + +enum { + MY_ATTR_FOO = 1, + MY_ATTR_BAR, + __MY_ATTR_MAX, +}; + +#define MY_ATTR_MAX (__MY_ATTR_MAX - 1) + +static struct nla_policy my_policy[MY_ATTR_MAX+1] = { + [MY_ATTR_FOO] = { .type = NLA_U32 }, + [MY_ATTR_BAR] = { .type = NLA_STRING, + .maxlen = 16 }, +}; + +void parse_msg(struct nlmsghdr *nlh) +{ + struct nlattr *attrs[MY_ATTR_MAX+1]; + + if (nlmsg_parse(nlh, 0, attrs, MY_ATTR_MAX, my_policy) < 0) + /* error */ + + if (attrs[MY_ATTR_FOO]) { + /* MY_ATTR_FOO is present in message */ + printf("value: %u\n", nla_get_u32(attrs[MY_ATTR_FOO])); + } +} +--------- + +.Locating a Single Attribute + +An application only interested in a single attribute can use one of the +functions nla_find() or nlmsg_find_attr(). These function will iterate +over all attributes, search for a matching attribute and return a pointer +to the corresponding attribute header. + +[source,c] +-------- +#include + +struct nlattr *nla_find(struct nlattr *head, int len, int attrtype); +-------- + +[source,c] +-------- +#include + +struct nlattr *nlmsg_find_attr(struct nlmsghdr *hdr, int hdrlen, int attrtype); +-------- + +NOTE: `nla_find()` and `nlmsg_find_attr()` will *not* search in nested + attributes recursively, see <>. + +==== Iterating over a Stream of Attributes + +In some situations it does not make sense to assign a unique attribute +type to each attribute in the attribute stream. For example a list may +be transferd using a stream of attributes and even if the attribute type +is incremented for each attribute it may not make sense to use the +nlmsg_parse() or nla_parse() function to fill an array. + +Therefore methods exist to iterate over a stream of attributes: + +[source,c] +-------- +#include + +nla_for_each_attr(attr, head, len, remaining) +-------- + +nla_for_each_attr() is a macro which can be used in front of a code +block: + +[source,c] +-------- +#include + +struct nalttr *nla; +int rem; + +nla_for_each_attr(nla, attrstream, streamlen, rem) { + /* validate & parse attribute */ +} + +if (rem > 0) + /* unparsed attribute data */ +-------- + +[[core_attr_constr]] +=== Attribute Construction + +The interface to add attributes to a netlink message is based on the +regular message construction interface. It assumes that the message +header and an eventual protocol header has been added to the message +already. + +[source,c] +-------- +struct nlattr *nla_reserve(struct nl_msg *msg, int attrtype, int len); +-------- + +The function nla_reserve() adds an attribute header at the end of the +message and reserves room for +len+ bytes of payload. The function +returns a pointer to the attribute payload section inside the message. +Padding is added at the end of the attribute to ensure the next +attribute is properly aligned. + +[source,c] +-------- +int nla_put(struct nl_msg *msg, int attrtype, int attrlen, const void *data); +-------- + +The function nla_put() is base don nla_reserve() but takes an additional +pointer +data+ pointing to a buffer containing the attribute payload. +It will copy the buffer into the message automatically. + +.Example: + +[source,c] +-------- +struct my_attr_struct { + uint32_t a; + uint32_t b; +}; + +int my_put(struct nl_msg *msg) +{ + struct my_attr_struct obj = { + .a = 10, + .b = 20, + }; + + return nla_put(msg, ATTR_MY_STRUCT, sizeof(obj), &obj); +} +-------- + +See <> for datatype specific +attribute construction functions. + +.Exception Based Attribute Construction + +Like in the kernel API an exception based construction interface is +provided. The behaviour of the macros is identical to their regular +function counterparts except that in case of an error, the target +`nla_put_failure` is jumped. + +.Example: +[source,c] +-------- +#include +#include + +void construct_attrs(struct nl_msg *msg) +{ + NLA_PUT_STRING(msg, MY_ATTR_FOO1, "some text"); + NLA_PUT_U32(msg, MY_ATTR_FOO1, 0x1010); + NLA_PUT_FLAG(msg, MY_ATTR_FOO3, 1); + + return 0; + +nla_put_failure: + /* NLA_PUT* macros jump here in case of an error */ + return -EMSGSIZE; +} +-------- + +See <> for more information on the +datatype specific exception based variants. + +[[core_attr_types]] +=== Attribute Data Types + +A number of basic data types have been defined to simplify access and +validation of attributes. The datatype is not encoded in the +attribute, therefore bthe sender and receiver are required to use the +same definition on what attribute is of what type. + +[options="header", cols="1m,5"] +|================================================ +| Type | Description +| NLA_UNSPEC | Unspecified attribute +| NLA_U{8\|16\|32} | Integers +| NLA_STRING | String +| NLA_FLAG | Flag +| NLA_NESTED | Nested attribute +|================================================ + +Besides simplified access to the payload of such datatypes, the major +advantage is the automatic validation of each attribute based on a +policy. The validation ensures safe access to the payload by checking +for minimal payload size and can also be used to enforce maximum +payload size for some datatypes. + +==== Integer Attributes + +The most frequently used datatypes are integers. Integers come in four +different sizes: +[horizontal] +NLA_U8:: 8bit integer +NLA_U16:: 16bit integer +NLA_U32:: 32bit integer +NLA_U64:: 64bit integer + +Note that due to the alignment requirements of attributes the integer +attribtue +NLA_u8+ and +NLA_U16+ will not result in space savings in +the netlink message. Their use is intended to limit the range of +values. + +.Parsing Integer Attributes + +[source,c] +-------- +#include + +uint8_t nla_get_u8(struct nlattr *hdr); +uint16_t nla_get_u16(struct nlattr *hdr); +uint32_t nla_get_u32(struct nlattr *hdr); +uint64_t nla_get_u64(struct nlattr *hdr); +-------- + +Example: + +[source,c] +-------- +if (attrs[MY_ATTR_FOO]) + uint32_t val = nla_get_u32(attrs[MY_ATTR_FOO]); +-------- + +.Constructing Integer Attributes + +[source,c] +-------- +#include + +int nla_put_u8(struct nl_msg *msg, int attrtype, uint8_t value); +int nla_put_u16(struct nl_msg *msg, int attrtype, uint16_t value); +int nla_put_u32(struct nl_msg *msg, int attrtype, uint32_t value); +int nla_put_u64(struct nl_msg *msg, int attrtype, uint64_t value); +-------- + +Exception based: + +[source,c] +-------- +NLA_PUT_U8(msg, attrtype, value) +NLA_PUT_U16(msg, attrtype, value) +NLA_PUT_U32(msg, attrtype, value) +NLA_PUT_U64(msg, attrtype, value) +-------- + +.Validation + +Use +NLA_U8+, +NLA_U16+, +NLA_U32+, or +NLA_U64+ to define the type of +integer when filling out a struct nla_policy array. It will +automatically enforce the correct minimum payload length policy. + +Validation does not differ between signed and unsigned integers, only +the size matters. If the appliaction wishes to enforce particular value +ranges it must do so itself. + +[source,c] +-------- +static struct nla_policy my_policy[ATTR_MAX+1] = { + [ATTR_FOO] = { .type = NLA_U32 }, + [ATTR_BAR] = { .type = NLA_U8 }, +}; +-------- + +The above is equivalent to: +[source,c] +-------- +static struct nla_policy my_policy[ATTR_MAX+1] = { + [ATTR_FOO] = { .minlen = sizeof(uint32_t) }, + [ATTR_BAR] = { .minlen = sizeof(uint8_t) }, +}; +-------- + +==== String Attributes + +The string datatype represents a NUL termianted character string of +variable length. It is not intended for binary data streams. + +The payload of string attributes can be accessed with the function +nla_get_string(). nla_strdup() calls strdup() on the payload and returns +the newly allocated string. + +[source,c] +-------- +#include + +char *nla_get_string(struct nlattr *hdr); +char *nla_strdup(struct nlattr *hdr); +-------- + +String attributes are constructed with the function +nla_put_string()+ +respectively +NLA_PUT_STRING()+. The length of the payload will be +strlen()+1, the trailing NUL byte is included. + +[source,c] +-------- +int nla_put_string(struct nl_msg *msg, int attrtype, const char *data); + +NLA_PUT_STRING(msg, attrtype, data) +-------- + +For validation purposes the type +NLA_STRING+ can be used in ++struct nla_policy+ definitions. It implies a minimum payload length +of 1 byte and checks for a trailing NUL byte. Optionally the +maxlen+ +member defines the maximum length of a character string (including the +trailing NUL byte). + +[source,c] +-------- +static struct nla_policy my_policy[] = { + [ATTR_FOO] = { .type = NLA_STRING, + .maxlen = IFNAMSIZ }, +}; +-------- + +==== Flag Attributes + +The flag attribute represents a boolean datatype. The presence of the +attribute implies a value of +true+, the absence of the attribute +implies the value +false+. Therefore the payload length of flag +attributes is always 0. + +[source,c] +-------- +int nla_get_flag(struct nlattr *hdr); +int nla_put_flag(struct nl_msg *msg, int attrtype); +-------- + +The type +NLA_FLAG+ is used for validation purposes. It implies a ++maxlen+ value of 0 and thus enforces a maximum payload length of 0. + +.Example: +[source,c] +-------- +/* nla_put_flag() appends a zero sized attribute to the message. */ +nla_put_flag(msg, ATTR_FLAG); + +/* There is no need for a receival function, the presence is the value. */ +if (attrs[ATTR_FLAG]) + /* flag is present */ +-------- + +[[core_attr_nested]] +==== Nested Attributes + +As described in <>, attributes can be +nested allowing for complex tree structures of attributes. It is +commonly used to delegate the responsibility of a subsection of the +message to a subsystem. Nested attributes are also commonly used for +transmitting list of objects. + +When nesting attributes, the nested attributes are included as payload +of a container attribute. + +NOTE: When validating the attributes using nlmsg_validate(), + nlmsg_parse(), nla_validate(), or nla_parse() only the + attributes on the first level are being validated. None of these + functions will validate attributes recursively. Therefore you + must explicitely call nla_validate() or use nla_parse_nested() + for each level of nested attributes. + +The type +NLA_NESTED+ should be used when defining nested attributes +in a struct nla_policy definition. It will not enforce any minimum +payload length unless +minlen+ is specified explicitely. This is +because some netlink protocols implicitely allow empty container +attributes. + +[source,c] +-------- +static struct nla_policy my_policy[] = { + [ATTR_OPTS] = { .type = NLA_NESTED }, +}; +-------- + +.Parsing of Nested Attributes + +The function nla_parse_nested() is used to parse nested attributes. +Its behaviour is identical to nla_parse() except that it takes a +struct nlattr as argument and will use the payload as stream of +attributes. + +[source,c] +-------- +if (attrs[ATTR_OPTS]) { + struct nlattr *nested[NESTED_MAX+1]; + struct nla_policy nested_policy[] = { + [NESTED_FOO] = { .type = NLA_U32 }, + }; + + if (nla_parse_nested(nested, NESTED_MAX, attrs[ATTR_OPTS], nested_policy) < 0) + /* error */ + + if (nested[NESTED_FOO]) + uint32_t val = nla_get_u32(nested[NESTED_FOO]); +} +-------- + +.Construction of Nested Attributes + +Attributes are nested by surrounding them with calls to nla_nest_start() +and nla_nest_end(). nla_nest_start() will add a attribute header to +the message but no actual payload. All data added to the message from +this point on will be part of the container attribute until nla_nest_end() +is called which "closes" the attribute, correcting its payload length to +include all data length. + +[source,c] +-------- +int put_opts(struct nl_msg *msg) +{ + struct nlattr *opts; + + if (!(opts = nla_nest_start(msg, ATTR_OPTS))) + goto nla_put_failure; + + NLA_PUT_U32(msg, NESTED_FOO, 123); + NLA_PUT_STRING(msg, NESTED_BAR, "some text"); + + nla_nest_end(msg, opts); + return 0; + +nla_put_failure: + return -EMSGSIZE; +} +-------- + +==== Unspecified Attribute + +This is the default attribute type and used when none of the basic +datatypes is suitable. It represents data of arbitary type and length. + +See <> for a more information on +a special interface allowing the allocation of abstract address object +based on netlink attributes which carry some form of network address. + +See <> for more information +on how to allocate abstract data objects based on netlink attributes. + +Use the function nla_get() and nla_put() to access the payload and +construct attributes. See <> +for an example. + +=== Examples + +==== Constructing a Netlink Message with Attributes + +[source,c] +-------- +struct nl_msg *build_msg(int ifindex, struct nl_addr *lladdr, int mtu) +{ + struct nl_msg *msg; + struct nlattr *info, *vlan; + struct ifinfomsg ifi = { + .ifi_family = AF_INET, + .ifi_index = ifindex, + }; + + /* Allocate a default sized netlink message */ + if (!(msg = nlmsg_alloc_simple(RTM_SETLINK, 0))) + return NULL; + + /* Append the protocol specific header (struct ifinfomsg)*/ + if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0) + goto nla_put_failure + + /* Append a 32 bit integer attribute to carry the MTU */ + NLA_PUT_U32(msg, IFLA_MTU, mtu); + + /* Append a unspecific attribute to carry the link layer address */ + NLA_PUT_ADDR(msg, IFLA_ADDRESS, lladdr); + + /* Append a container for nested attributes to carry link information */ + if (!(info = nla_nest_start(msg, IFLA_LINKINFO))) + goto nla_put_failure; + + /* Put a string attribute into the container */ + NLA_PUT_STRING(msg, IFLA_INFO_KIND, "vlan"); + + /* + * Append another container inside the open container to carry + * vlan specific attributes + */ + if (!(vlan = nla_nest_start(msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + /* add vlan specific info attributes here... */ + + /* Finish nesting the vlan attributes and close the second container. */ + nla_nest_end(msg, vlan); + + /* Finish nesting the link info attribute and close the first container. */ + nla_nest_end(msg, info); + + return msg; + +nla_put_failure: + nlmsg_free(msg); + return NULL; +} +------ + +==== Parsing a Netlink Message with Attributes + +[source,c] +-------- +int parse_message(struct nlmsghdr *hdr) +{ + /* + * The policy defines two attributes: a 32 bit integer and a container + * for nested attributes. + */ + struct nla_policy attr_policy[] = { + [ATTR_FOO] = { .type = NLA_U32 }, + [ATTR_BAR] = { .type = NLA_NESTED }, + }; + struct nlattr *attrs[ATTR_MAX+1]; + int err; + + /* + * The nlmsg_parse() function will make sure that the message contains + * enough payload to hold the header (struct my_hdr), validates any + * attributes attached to the messages and stores a pointer to each + * attribute in the attrs[] array accessable by attribute type. + */ + if ((err = nlmsg_parse(hdr, sizeof(struct my_hdr), attrs, ATTR_MAX, + attr_policy)) < 0) + goto errout; + + if (attrs[ATTR_FOO]) { + /* + * It is safe to directly access the attribute payload without + * any further checks since nlmsg_parse() enforced the policy. + */ + uint32_t foo = nla_get_u32(attrs[ATTR_FOO]); + } + + if (attrs[ATTR_BAR]) { + struct *nested[NESTED_MAX+1]; + + /* + * Attributes nested in a container can be parsed the same way + * as top level attributes. + */ + err = nla_parse_nested(nested, NESTED_MAX, attrs[ATTR_BAR], + nested_policy); + if (err < 0) + goto errout; + + // Process nested attributes here. + } + + err = 0; +errout: + return err; +} +-------- + +[[core_cb]] +== Callback Configurations + +Callback hooks and overwriting capabilities are provided in various places +inside library to control the behaviour of several functions. All the +callback and overwrite functions are packed together in struct nl_cb which +is attached to a netlink socket or passed on to functions directly. + +=== Callback Hooks + +Callback hooks are spread across the library to provide entry points for +message processing and to take action upon certain events. + +Callback functions may return the following return codes: +[options="header", cols="1m,4"] +|======================================================================== +| Return Code | Description +| NL_OK | Proceed. +| NL_SKIP | Skip message currently being processed and continue + parsing the receive buffer. +| NL_STOP | Stop parsing and discard all remaining data in the + receive buffer. +|======================================================================== + +.Default Callback Implementations + +The library provides three sets of default callback implementations: +* +NL_CB_DEFAULT+ This is the default set. It implets the default behaviour. + See the table below for more information on the return codes of each + function. +* +NL_CB_VERBOSE+ This set is based on the default set but will cause an + error message to be printed to stderr for error messages, invalid + messages, message overruns and unhandled valid messages. The + +arg+ pointer in nl_cb_set() and nl_cb_err() can be used to + provide a FILE * which overwrites stderr. +* +NL_CB_DEBUG+ This set is intended for debugging purposes. It is + based on the verbose set but will decode and dump each message sent + or received to the console. + +.Message Processing Callbacks + +.nl_sendmsg() callback hooks: +[cols="2m,4e,1m", options="header"] +|============================================================================ +| Callback ID | Description | Default Return Value +| NL_CB_MSG_OUT | Each message sent | NL_OK +|============================================================================ + +Any function called by NL_CB_MSG_OUT may return a negative error code to +prevent the message from being sent and the error code being returned. + +nl_recvmsgs() callback hooks (ordered by priority): +[cols="2m,4e,1m", options="header"] +|============================================================================ +| Callback ID | Description | Default Return Value +| NL_CB_MSG_IN | Each message received | NL_OK +| NL_CB_SEQ_CHECK | May overwrite sequence check algo | NL_OK +| NL_CB_INVALID | Invalid messages | NL_STOP +| NL_CB_SEND_ACK | Messages with NLM_F_ACK flag set | NL_OK +| NL_CB_FINISH | Messages of type NLMSG_DONE | NL_STOP +| NL_CB_SKIPPED | Messages of type NLMSG_NOOP | NL_SKIP +| NL_CB_OVERRUN | Messages of type NLMSG_OVERRUN | NL_STOP +| NL_CB_ACK | ACK Messages | NL_STOP +| NL_CB_VALID | Each valid message | NL_OK +|============================================================================ + +Any of these functions may return NL_OK, NL_SKIP, or NL_STOP. + +Message processing callback functions are set with nl_cb_set(): +[source,c] +-------- +#include + +int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind, + nl_recvmsg_msg_cb_t func, void *cb); + +typedef int (*nl_recvmsg_msg_cb_t)(struct nl_msg *msg, void *arg); +-------- + +.Callback for Error Messages + +A special function prototype is used for the error message callback hook: + +[source,c] +-------- +#include + +int nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind, nl_recvmsg_err_cb_t func, void * arg); + +typedef int(* nl_recvmsg_err_cb_t)(struct sockaddr_nl *nla, struct nlmsgerr *nlerr, void *arg); +-------- + +.Example: Setting up a callback set +[source,c] +-------- +#include + +/* Allocate a callback set and initialize it to the verbose default set */ +struct nl_cb *cb = nl_cb_alloc(NL_CB_VERBOSE); + +/* Modify the set to call my_func() for all valid messages */ +nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, my_func, NULL); + +/* + * Set the error message handler to the verbose default implementation + * and direct it to print all errors to the given file descriptor. + */ +FILE *file = fopen(...); +nl_cb_err(cb, NL_CB_VERBOSE, NULL, file); +-------- + +=== Overwriting of Internal Functions + +When the library needs to send or receive netlink messages in high level +interfaces it does so by calling its own low level API. In the case the +default characteristics are not sufficient for the application, it may +overwrite several internal function calls with own implementations. + +.Overwriting recvmsgs() + +See <> for more information on +how and when recvmsgs() is called internally. + +[source,c] +-------- +#include + +void nl_cb_overwrite_recvmsgs(struct nl_cb *cb, + int (*func)(struct nl_sock *sk, struct nl_cb *cb)); +-------- + +The following criteras must be met if a recvmsgs() implementation is +supposed to work with high level interfaces: + +- MUST respect the callback configuration +cb+, therefore: + - MUST call +NL_CB_VALID+ for all valid messages, passing on + - MUST call +NL_CB_ACK+ for all ACK messages + - MUST correctly handle multipart messages, calling NL_CB_VALID for + each message until a NLMSG_DONE message is received. +- MUST report error code if a NLMSG_ERROR or NLMSG_OVERRUN mesasge is + received. + +.Overwriting nl_recv() + +Often it is sufficient to overwrite `nl_recv()` which is responsible +from receiving the actual data from the socket instead of replacing +the complete `recvmsgs()` logic. + +See <> for more +information on how and when `nl_recv()` is called internally. + +[source,c] +-------- +#include + +void nl_cb_overwrite_recv(struct nl_cb *cb, + int (*func)(struct nl_sock * sk, + struct sockaddr_nl *addr, + unsigned char **buf, + struct ucred **cred)); +-------- + +The following criteras must be met for an own `nl_recv()` +implementation: + + - *MUST* return the number of bytes read or a negative error code if + an error occured. The function may also return 0 to indicate that + no data has been read. + - *MUST* set `*buf` to a buffer containing the data read. It must be + safe for the caller to access the number of bytes read returned as + return code. + - *MAY* fill out `*addr` with the netlink address of the peer the + data has been received from. + - *MAY* set `*cred` to a newly allocated struct ucred containg + credentials. + +.Overwriting nl_send() + +See <> for more information on +how and when nl_send() is called internally. + +[source,c] +-------- +#include + +void nl_cb_overwrite_send(struct nl_cb *cb, int (*func)(struct nl_sock *sk, + struct nl_msg *msg)); +-------- + +Own implementations must send the netlink message and return 0 on success +or a negative error code. + +[[core_cache]] +== Cache System + +=== Allocation of Caches + +Almost all subsystem provide a function to allocate a new cache +of some form. The function usually looks like this: +[source,c] +-------- +struct nl_cache *_alloc_cache(struct nl_sock *sk); +-------- + +These functions allocate a new cache for the own object type, +initializes it properly and updates it to represent the current +state of their master, e.g. a link cache would include all +links currently configured in the kernel. + +Some of the allocation functions may take additional arguments +to further specify what will be part of the cache. + +All such functions return a newly allocated cache or NULL +in case of an error. + +== Abstract Data Types + +A few high level abstract data types which are used by a majority netlink +protocols are implemented in the core library. More may be added in the +future if the need arises. + +=== Abstract Address + +Most netlink protocols deal with networking related topics and thus +dealing with network addresses is a common task. + +Currently the following address families are supported: + + - `AF_INET` + - `AF_INET6` + - `AF_LLC` + - `AF_DECnet` + - `AF_UNSPEC` + +[[core_addr_alloc]] +.Address Allocation + +The function nl_addr_alloc() allocates a new empty address. The ++maxsize+ argument defines the maximum length of an address in bytes. +The size of an address is address family specific. If the address +family and address data are known at allocation time the function +nl_addr_build() can be used alternatively. You may also clone +an address by calling nl_addr_clone() + +[source,c] +-------- +#include + +struct nl_addr *nl_addr_alloc(size_t maxsize); +struct nl_addr *nl_addr_clone(struct nl_addr *addr); +struct nl_addr *nl_addr_build(int family, void *addr, size_t size); +-------- + +If the address is transported in a netlink attribute, the function +nl_addr_alloc_attr() allocates a new address based on the payload +of the attribute provided. The +family+ argument is used to specify +the address family of the address, set to +AF_UNSPEC+ if unknown. + +[source,c] +-------- +#include + +struct nl_addr *nl_addr_alloc_attr(struct nlattr *attr, int family); +-------- + +If the address is provided by a user, it is usually stored in a human +readable format. The function nl_addr_parse() parses a character +string representing an address and allocates a new address based on +it. + +[source,c] +-------- +#include + +int nl_addr_parse(const char *addr, int hint, struct nl_addr **result); +-------- + +If parsing succeeds the function returns 0 and the allocated address +is stored in +*result+. + +NOTE: Make sure to return the reference to an address using + `nl_addr_put()` after usage to allow memory being freed. + +.Address References + +Abstract addresses use reference counting to account for all users of +a particular address. After the last user has returned the reference +the address is freed. + +If you pass on a address object to another function and you are not +sure how long it will be used, make sure to call nl_addr_get() to +acquire an additional reference and have that function or code path +call nl_addr_put() as soon as it has finished using the address. + +[source,c] +-------- +#include + +struct nl_addr *nl_addr_get(struct nl_addr *addr); +void nl_addr_put(struct nl_addr *addr); +int nl_addr_shared(struct nl_addr *addr); +-------- + +You may call nl_addr_shared() at any time to check if you are the only +user of an address. + +.Address Attributes + +The address is usually set at allocation time. If it was unknown at that +time it can be specified later by calling nl_addr_set_family() and is +accessed with the function nl_addr_get_family(). + +[source,c] +-------- +#include + +void nl_addr_set_family(struct nl_addr *addr, int family); +int nl_addr_get_family(struct nl_addr *addr); +-------- + +The same is true for the actual address data. It is typically present +at allocation time. For exceptions it can be specified later or +overwritten with the function `nl_addr_set_binary_addr()`. Beware that +the length of the address may not exceed `maxlen` specified at +allocation time. The address data is returned by the function +`nl_addr_get_binary_addr()` and its length by the function +`nl_addr_get_len()`. + +[source,c] +-------- +#include + +int nl_addr_set_binary_addr(struct nl_addr *addr, void *data, size_t size); +void *nl_addr_get_binary_addr(struct nl_addr *addr); +unsigned int nl_addr_get_len(struct nl_addr *addr); +-------- + +If you only want to check if the address data consists of all zeros +the function `nl_addr_iszero()` is a shortcut to that. + +[source,c] +-------- +#include + +int nl_addr_iszero(struct nl_addr *addr); +-------- + +==== Address Prefix Length + +Although this functionality is somewhat specific to routing it has +been implemented here. Addresses can have a prefix length assigned +which implies that only the first n bits are of importance. This is +f.e. used to implement subnets. + +Use set functions `nl_addr_set_prefixlen()` and +`nl_addr_get_prefixlen()` to work with prefix lengths. + +[source,c] +-------- +#include + +void nl_addr_set_prefixlen(struct nl_addr *addr, int n); +unsigned int nl_addr_get_prefixlen(struct nl_addr *addr); +-------- + +NOTE: The default prefix length is set to (address length * 8) + +.Address Helpers + +Several functions exist to help when dealing with addresses. The +function `nl_addr_cmp()` compares two addresses and returns an integer +less than, equal to or greater than zero without considering the +prefix length at all. If you want to consider the prefix length, use +the function `nl_addr_cmp_prefix()`. + +[source,c] +-------- +#include + +int nl_addr_cmp(struct nl_addr *addr, struct nl_addr *addr); +int nl_addr_cmp_prefix(struct nl_addr *addr, struct nl_addr *addr); +-------- + +If an abstract address needs to presented to the user it should be +done in a human readable format which differs depending on the address +family. The function `nl_addr2str()` takes care of this by calling the +appropriate conversion functions internaly. It expects a `buf` of +length `size` to write the character string into and returns a pointer +to `buf` for easy `printf()` usage. + +[source,c] +-------- +#include + +char *nl_addr2str(struct nl_addr *addr, char *buf, size_t size); +-------- + +If the address family is unknown, the address data will be printed in +hexadecimal format `AA:BB:CC:DD:...` + +Often the only way to figure out the address family is by looking at +the length of the address. The function `nl_addr_guess_family()` does +just this and returns the address family guessed based on the address +size. + +[source,c] +-------- +#include + +int nl_addr_guess_family(struct nl_addr *addr); +-------- + +Before allocating an address you may want to check if the character +string actually represents a valid address of the address family you +are expecting. The function `nl_addr_valid()` can be used for that, it +returns 1 if the supplised `addr` is a valid address in the context of +`family`. See `inet_pton(3)`, `dnet_pton(3)` for more information on +valid adddress formats. + +[source,c] +-------- +#include + +int nl_addr_valid(char *addr, int family); +-------- + +=== Abstract Data + +The abstract data type is a trivial datatype with the primary purpose +to simplify usage of netlink attributes of arbitary length. + +[[core_data_alloc]] +.Allocation of a Data Object +The function `nl_data_alloc()` alloctes a new abstract data object and +fill it with the provided data. `nl_data_alloc_attr()` does the same +but bases the data on the payload of a netlink attribute. New data +objects can also be allocated by cloning existing ones by using +`nl_data_clone()`. + +[source,c] +-------- +struct nl_data *nl_data_alloc(void *buf, size_t size); +struct nl_data *nl_data_alloc_attr(struct nlattr *attr); +struct nl_data *nl_data_clone(struct nl_data *data); +void nl_data_free(struct nl_data *data); +-------- + +.Access to Data + +The function `nl_data_get()` returns a pointer to the data, the size +of data is returned by `nl_data_get_size()`. + +[source,c] +-------- +void *nl_data_get(struct nl_data *data); +size_t nl_data_get_size(struct nl_data *data); +-------- + +.Data Helpers + +The function nl_data_append() reallocates the internal data buffers +and appends the specified `buf` to the existing data. + +[source,c] +-------- +int nl_data_append(struct nl_data *data, void *buf, size_t size); +-------- + +CAUTION: Any call to `nl_data_append()` invalidates all pointers + returned by `nl_data_get()` of the same data object. + +[source,c] +-------- +int nl_data_cmp(struct nl_data *data, struct nl_data *data); +-------- diff --git a/doc/doxygen-link.py b/doc/doxygen-link.py new file mode 100755 index 0000000..fda193c --- /dev/null +++ b/doc/doxygen-link.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python + +import fileinput +import re +import sys + +links = {} + +for line in open(sys.argv[1], 'r'): + m = re.match('^([^=]+)=([^\n]+)$', line); + if m: + link = "" + m.group(1) + "" + links[m.group(1)] = link + +def translate(match): + return links[match.group(0)] + +rc = re.compile('|'.join(map(re.escape, sorted(links, reverse=True)))) +for line in open(sys.argv[2], 'r'): + print rc.sub(translate, line), diff --git a/doc/gen-tags.sh b/doc/gen-tags.sh new file mode 100755 index 0000000..aba6672 --- /dev/null +++ b/doc/gen-tags.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# +# Based on a script found on the englinemtn-devel mailinglist +# written by Carsten Haitzler +# + +echo '' +for f in api/group__*.html +do + bf=$(basename $f) + + grep -oE '' $f | + sed 's//file=\"$bf\" \/>/" | + sed "s/ ref=\"/ href=\"$bf#/" | + sed 's/ member="\([^:]*::\)\([^"]*\)"/ member="\2"/' | + sed 's/ member="\([^"]*\)"/ short="\1"/' +done +echo '' diff --git a/doc/html/.gitignore b/doc/html/.gitignore deleted file mode 100644 index 72e8ffc..0000000 --- a/doc/html/.gitignore +++ /dev/null @@ -1 +0,0 @@ -* diff --git a/doc/images/.gitignore b/doc/images/.gitignore new file mode 100644 index 0000000..8a23fba --- /dev/null +++ b/doc/images/.gitignore @@ -0,0 +1 @@ +core__* diff --git a/doc/images/classful_qdisc.png b/doc/images/classful_qdisc.png new file mode 100644 index 0000000000000000000000000000000000000000..7e77350fc12e5d824d2ff357b1fc2bcebddcea03 GIT binary patch literal 31849 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 Nw77y;xv1g0{{sv5M*#o; literal 0 HcmV?d00001 diff --git a/doc/images/classless_qdisc.png b/doc/images/classless_qdisc.png new file mode 100644 index 0000000000000000000000000000000000000000..bcf2c1ced72641729e9fdd4ed20d78caf5aa453c GIT binary patch literal 15443 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 literal 0 HcmV?d00001 diff --git a/doc/images/icons/README b/doc/images/icons/README new file mode 100644 index 0000000..f12b2a7 --- /dev/null +++ b/doc/images/icons/README @@ -0,0 +1,5 @@ +Replaced the plain DocBook XSL admonition icons with Jimmac's DocBook +icons (http://jimmac.musichall.cz/ikony.php3). I dropped transparency +from the Jimmac icons to get round MS IE and FOP PNG incompatibilies. + +Stuart Rackham diff --git a/doc/images/icons/callouts/1.png b/doc/images/icons/callouts/1.png new file mode 100644 index 0000000000000000000000000000000000000000..7d473430b7bec514f7de12f5769fe7c5859e8c5d GIT binary patch literal 329 zcmeAS@N?(olHy`uVBq!ia0vp^JRr;gBp8b2n5}^nQC}X^4DKU-G|w_t}fLBA)Suv#nrW z!^h2QnY_`l!BOq-UXEX{m2up>JTQkX)2m zTvF+fTUlI^nXH#utd~++ke^qgmzgTe~DWM4ffP81J literal 0 HcmV?d00001 diff --git a/doc/images/icons/callouts/10.png b/doc/images/icons/callouts/10.png new file mode 100644 index 0000000000000000000000000000000000000000..997bbc8246a316e040e0804174ba260e219d7d33 GIT binary patch literal 361 zcmeAS@N?(olHy`uVBq!ia0vp^JRr;gBp8b2n5}^nQWtZ~+OvdJMW|Y+^UT?O-M{rKJsmzxdayJ{ zDCQA!%%@7Jj$q%-wf8e0_jRx8Dqi$}^?K=?6FriQFLv>>oc^CE+aVHhW3=nZ+fQ4!M=ZC7H>3sl|FJr3LwU zC3?yExf6FO?f@F61vV}-Juk7O6lk8Yg;}bFaZ-|HQc7Azopr01?u8M*si- literal 0 HcmV?d00001 diff --git a/doc/images/icons/callouts/11.png b/doc/images/icons/callouts/11.png new file mode 100644 index 0000000000000000000000000000000000000000..ce47dac3f52ac49017749a3fea53db57d006993c GIT binary patch literal 565 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1SD^YpWXnZI14-?iy0V%N{XE z)7O>#600DeuDZ?5tOl@ql94%{~0TwC?8m~C^ZqJRG}m@H-L1 z5L@scq?{XUcxG{OP9jig5ySQaTl#^*93bKF#G<^+ymW>G($Cs~V(bw8rA5i93}62@ zzlJGu&d<$F%`0K}c4pdspcorSSx9C{PAbEScbC)|7#JBmT^vIy=9KoYUDZ+`aP)jU z&ny=ErrK^#Gw!AcR}pdfMERuV^@&0$@(#^6b8c@rn^6RWX3pUb z4*6@PZ+H0#u=rjsXzS?6n6*sBGbHqGTU%mCsH?n#%j;eD^2}qe=iX*J@VQ3BRpz+u z{PX#N(^9X${`$90+;!pWs>o@z_n8G)7Uo7PJz`jrS+)QE@=PWHmc~UIw=WmUe73o7 z>^bR(M752aYoNg~ozu7U7&{(U>{s!;bn#f?ItjL^o`e{*EOQHqO;ccnz9hLK5@2cAyw@AaPFL~Cp#02|E|4xeQteNtB7waMs QVCXP-y85}Sb4q9e0GRUFb^rhX literal 0 HcmV?d00001 diff --git a/doc/images/icons/callouts/12.png b/doc/images/icons/callouts/12.png new file mode 100644 index 0000000000000000000000000000000000000000..31daf4e2f25b6712499ee32de9c2e3b050b691ca GIT binary patch literal 617 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1SD^YpWXnZI14-?iy0V%N{XE z)7O>#600De9$%>2LVd81Yeb1-X-P(Y5yQ%LXFPyHJS9LOm(=3qqRfJl%=|nCVNOM5 zpg0#u+&RCXvM4h>ql94%{~0TwC?8m~C^ZqJRG}m@H-L1 z5L@scq?{XUcxG{OP9jig5ySQaTl#^*93bKF#G<^+ymW>G($Cs~V(bw8rA5i93}62@ zzlJGu&d<$F%`0K}c4pdspcorSSx9C{PAbEScbC)|7#JBmT^vIy=Cn>wTzx1(qV@bS z0hYvspf(--lM>otrqbK$7p{3DzJ|+KN8%5ows)AI?zWk_n>jwEHXrTJecpEW_0xL= z?}N`*R`T~d2{AN${y8T#GEn4hUb&52^}Op@TW4{oc)A6)%$5=G}h# z?O{QLj@aRcAIf&y&OiUN=H2gq=_}V|pWfuReDV|{jwXw~>#w)I|9${XE z)7O>#600Dep5bGK9wD%hYeb1-X-P(Y5yQ%LXFPyHJS9LOm(=3qqRfJl%=|nCVNOM5 zpg0#u+&RCXvM4h>ql94%{~0TwC?8m~C^ZqJRG}m@H-L1 z5L@scq?{XUcxG{OP9jig5ySQaTl#^*93bKF#G<^+ymW>G($Cs~V(bw8rA5i93}62@ zzlJGu&d<$F%`0K}c4pdspcorSSx9C{PAbEScbC)|7#JBmT^vIy=Cn>w>~AWNX^a2R zbkveVY|45D7UnZ&JtjPwvdCCscZp0EA*0()#GOw)UH4-^&)y^E*4%UC)*|J}q_Ss;tN`nd8$>x9$_Xb^O2EpX&@C ZI46EzbLxq-voTO7gQu&X%Q~loCIF_C`w;*D literal 0 HcmV?d00001 diff --git a/doc/images/icons/callouts/14.png b/doc/images/icons/callouts/14.png new file mode 100644 index 0000000000000000000000000000000000000000..64014b75fe2e84d45ed861974c72462727979360 GIT binary patch literal 411 zcmV;M0c8G(P)!ax*-PXaQ9e~6^e1gu=a6a&KSz}bR`+prYG9ayB$BDjWGfIE;t#wl!+ zR3S(jA%y#i_@eOOedXoc%RQe%L;wH~k+s%ZI~)!<=dD%?4MaplaU9QPGski2q3`>r z(}{j@0a$CLl+)={2vLWml*i-oa5#J}DW$gCZB~Z!(!M#)2St|1_V^0qpmCrBof=Y&NUas@LmfSw=)4B4f;8Fu)(eFsv24 zJzXxBrayquXcR?J{XE z)7O>#600De0j~t#c`vY#Yeb1-X-P(Y5yQ%LXFPyHJS9LOm(=3qqRfJl%=|nCVNOM5 zpg0#u+&RCXvM4h>ql94%{~0TwC?8m~C^ZqJRG}m@H-L1 z5L@scq?{XUcxG{OP9jig5ySQaTl#^*93bKF#G<^+ymW>G($Cs~V(bw8rA5i93}62@ zzlJGu&d<$F%`0K}c4pdspcorSSx9C{PAbEScbC)|7#JBmT^vIy=9Eq_Jl&Ka(%QdX zh{H8O%#_7)Tc@t$mM`p4(Ne7omR*~(>gd8_8AZH{=3ms$Fmzm^yL@_+(#aQQ5>7QW z>3g2fIsH(ugM)!V$x4Rr_+!J_XU%4xbz0aE;^N{m@42Z|@0S@TQ=WbP`TMV5Ok;<| z^Ihv+@6tQ{sciRF9dD7Nr=KobwJJ68zJK$<1Pd9rz%4O)*;}Jzj&~nTGMecz>B%lV zK|`fmIc8mp-h8iSXiGFW=C(L+XH4DRxZQX87^-dLuD>odo6YLT@Sw)dfBEIG)v2@6 zR)%mL7GRj1x-&v&+2q@A%a&h0`Lw7|#(w_!tgT!PoJ|+re`lxaY7e*=hH)_rZeB4|imU1$R#1`!P>&$poQl;nzm}mD5ZFopaX|GsS%q*{P~< z;WtmO%lhToBL0i}yfkaOt?EN=nkLNGuU`ywhI5H)L`iUdT1k0gQ7VIjhO(w-Zen_> zZ(@38a<+nro{^q~f~BRtfrY+-p+a&|W^qZSLvCepNoKNMYO!8QX+eHoiC%Jk?!;Y+ zJAlS%fsM;d&r2*R1)67JkeZlkYGj#gX_9E3W@4U_nw*@Ln38B@k(iuhnUeN2eF0kK0(Y1u|9Rc(19XFPiEBhjaDG}zd16s2gM)^$re|(qda7?? zdS-IAf{C7yo`r&?rM`iMzJZ}aa#3b+Nu@(>WpPPnvR-PjUP@^}eqM=Qa(?c_U5Yz^ z#%Y0#%S_KpEGY$=XJL?(l#*ybuErX#^g`ttQfwn3r>K)tuC)r#2`iJ>Prt42#Ndx#Uc~1)>aw z3jE@Q4|!9Z%lVv}- zc=48cF7H)t`(Ck`^+mtha~Np7bBSw2NpOBzNqJ&XDuaWDvZiNlVtT4?VtQtBwt|VC zk)DNurKP@sg}#BILUK`NaY>~^Ze?*vX0l#tv0h4PL4IC|UUGi!#9fLzfW~Qojmu2W zODrh`nrE42VU(7fm~5G9U~HM3l#*m_WNcxOXkuzEX4g z+-vfUhb0A>b04=Im{6XiQd1v%r%>h0$G8U7E1If8OQ!N~xOYY5h0NDT$p9(iZ?Q&e z18-(+l~J8O`)kc}e&uL$eW&>P-#`~Qm$*ih1m~xflqVLYGB{``YkKA;rl!p+yCFkc(+@-h!Xq*<< zxXkpt#FA2=d1VEBsYynrsitN|Y01eJ$;p;U#>wWX2KP5v&I9V=1L+C? fTFYQ)RAFeOZJ=$?lDoSWD8u0C>gTe~DWM4f^}upZ literal 0 HcmV?d00001 diff --git a/doc/images/icons/callouts/6.png b/doc/images/icons/callouts/6.png new file mode 100644 index 0000000000000000000000000000000000000000..0ba694af6c07d947d219b45a629bd32c60a0f5fe GIT binary patch literal 355 zcmeAS@N?(olHy`uVBq!ia0vp^JRr;gBp8b2n5}^nQ*)Bra@SU# zmiz#bR~{$s2si{S(aY|Z}Vd7tb ouUmn-_&~Y>fYve?8dVq?X&Y!8wB+ut1u%w%U~xZhnMEEs6JbBSw2NpOBzNqJ&XDuaWDvZiNlVtT4?VtQtBwt|VC zk)DNurKP@sg}#BILUK`NaY>~^Ze?*vX0l#tv0h4PL4IC|UUGi!#9fLzfW~Qojmu2W zODrh`nrCEbVQgk$XkwI@Y+{_8nv`N>YGIaQkz#0QY@Te9lBQ<)awbq0A4pdK&{_sV bqY6VKZ3AtCmfYR7Kp6&4S3j3^P6u&S`V$cAh@R~F=4@V4jxkzlaQrcFYWK{)(`o5XZnut z=nE4SU2g1ZW%;@@I$>_e3F8a=8WK~|CVXt1DqisQxtIX|`YW_n&?Nh#1gQ}d)$LrYTw(_{nVG)tp2V+#}WG*e^KRLdkoLz7g? qn(IA84Qgo42`r6v<+Hvch>@C7(8A5T-G@yGywn*$#_oy literal 0 HcmV?d00001 diff --git a/doc/images/icons/callouts/9.png b/doc/images/icons/callouts/9.png new file mode 100644 index 0000000000000000000000000000000000000000..a0676d26cc2ff1de12c4ecdeefb44a0d71bc6bde GIT binary patch literal 357 zcmeAS@N?(olHy`uVBq!ia0vp^JRr;gBp8b2n5}^nQNRqa;^5&H%t0&v*|C|wdb9$wI zR@+N9#RIowg@Uqn&z-__Tzhhz!sG|vTxA7?=O|Y?u(d4T{!RM9c7chr6d%1?R=i16 z?@Ic{f32YJFJnVhX)qGzOMplv!L->5yAlT#}irms+fsQd*FoSE84k zpF44v;trs3T43Wc)AJHbN`dAXo0u6Hr<$gkq?lM38ycjV7+5A5Sr{ayr5c%-n;95g pF*H#D>f!_G3IJNmU}#ifXryhRZP1dtyA~+J;OXk;vd$@?2>@J{cB%jX literal 0 HcmV?d00001 diff --git a/doc/images/icons/caution.png b/doc/images/icons/caution.png new file mode 100644 index 0000000000000000000000000000000000000000..9a8c515a109faf9159777ac9e6861c2b8e7df383 GIT binary patch literal 2734 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 literal 0 HcmV?d00001 diff --git a/doc/images/icons/example.png b/doc/images/icons/example.png new file mode 100644 index 0000000000000000000000000000000000000000..1199e864f8502a57c3b8def7c2e1d90c5f760a73 GIT binary patch literal 2599 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 JPDHLkV1oa#`7Hnd literal 0 HcmV?d00001 diff --git a/doc/images/icons/home.png b/doc/images/icons/home.png new file mode 100644 index 0000000000000000000000000000000000000000..37a5231bacc905886c9351a291e0d5eed68dd60e GIT binary patch literal 1340 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 M07*qoM6N<$g4<+Y4gdfE literal 0 HcmV?d00001 diff --git a/doc/images/icons/note.png b/doc/images/icons/note.png new file mode 100644 index 0000000000000000000000000000000000000000..7c1f3e2fa7ef8897bb55ee0e0dda088dc49d6408 GIT binary patch literal 2494 zcmV;v2|@OWP)Dn;hlg!sWaK|u z738H>q0O5&+vt7wuzAz%lqL_6pE$;`=_$TGUSZXTKE{?UTV#Q4eNlNy5f~X6vC;eP zVar?IL^}QqvwNN<9++V9)D&M@mNI(ZJ=}l){r{0jyrc*W4-ebj%iAbbjxqbUooH}4 zuZUNi7mlaxe8H{Yp@$wSHWB%^MdKw!V8@OfbY&U!zwaWH1ECZMSs=**Axr2VTE>nY zJBTp?U=3MN%Nye7^JNh+5usEnkslf-lmqG&b&3m$`XUlKILOS*6L|lEeL0JH(vmpIP@3Z^}f3}I(e8SSttw+1qk&H*S&}e3GMAA ze*25>uxL>y9qlEuEJammu}RJZ5CH{IL<&-v!LqCF#LVnM6r2|T?>)7XyLk5G&`*lKvIwdGy#_(nzjI3(5CqS2q6%0s89LCN8ZARpWMe?PmD9V?HShd%D^46n-da~Q0bB!|EBq>kbB>Eu-+5C=y+<^lE)vp=*IvDh z&wTt&rcO=q;MU#j89PizM@H}-Rga;VI;Lj~b&!c7sK&G4*;xL@AYv=42@Ky5Lkv(r``>09+Sn36l=6 z84v~GqWqsXfEXi~07CEyNgBxW6tgmEaLm=~L<2=p=SYIbsghVP_0%`Ra6A$gv2LUnu6t|!IS4XAcz)5gy2b%K$<2%qgy+N3n``vNcr^Q zmN%H6A>=IzEhvB(BZ#2Rkw+mU4vPUNDKQ4}7*SQ6I$|_XE%HVk!F!HZs!SX_&UNe8 zV*mzw_wDD{i7DQ&ZY_yR5m5{S?2-V?s}HCuqD8fE!Q(XHcTbKIP5Il?2N)Zlp}ni0 za%UfZ+;xO+eeXBy-2EKRC+t6XlI=Ujd1TvD?EA+dL=(RI{a^Cj{$q4^cJkf(9z?V- zy=Zh7FQM}W(AiN&)T2Jd`+%zF=0aLf|5ja=Oj3vEYJhk@_ zcieg%Z{4_#y<_|N!;^pK%{N|)i16Nb-pC`5Zs*$9E@RE=6|KR{@N{=|@#U}mkozBa zj9YHH9ytHdc0QR`4!oEwUD8c=cYEu3QFjMp&rY!6`ZX<(dEW4(%~6}32H?SmA7lON zR&w3Ct9g3QKbfn~0`2E6ziF8+3;xuMO6%lbHX&cK1 zdW%z5qc3DxiJNa&2Ph%Hrs124#YGz`7*fm{3t91PH2%;Sh14O&014#tFeAXyE|BL>6|K8yg#=x3{Y}v$mQ|(ef=8&(R{e zL9_a)N)Z7RXqL$0RL7Y$UOcE4&XC3=YFzLj)09gtqt8D33|9;d6d^{yIQ_RMW=f2X zJSurEg~sANv%)wU9tJ56E=`rjI*mptS^!FtWMKeo-MZDbZTmI1-F7=51=pLSuF;4{ zF{zqqL#5?pYt9WczAK7ZY-vG5hcpI7K^jBj#pRMHG%+#32i|iVi98n4YW;xYr_3{riW@h)^doN%7{9V+h zk6;!#cyN-uUgNL3_Aq(mIDg$ehQ&xndmCL{ZLD10&oygSAp(N~y+srn0E~zbkyt-# zpQs+SIn0db4jg3nt}!Z=%7OqWPF0rk)D zr>8l2s>1lB@$ff)#?*sGJVnVz0zW@d(3twxNo#p`CGHJ_WD_uk{2YrQse z#LSqPnK|p?*UYHb>#ak)bB-iQNRot7sf73b^6y4fwdLW$YlU&m+vcV=Lw@G-xp$l1 z`?IJaBE%S5qeD}ZB)L2a{V&M>_pg-y4e|OV literal 0 HcmV?d00001 diff --git a/doc/images/icons/prev.png b/doc/images/icons/prev.png new file mode 100644 index 0000000000000000000000000000000000000000..3e8f12fe24c6e042bc7ef4badb15449f71529ace GIT binary patch literal 1348 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 AfdBvi literal 0 HcmV?d00001 diff --git a/doc/images/qdisc_default.png b/doc/images/qdisc_default.png new file mode 100644 index 0000000000000000000000000000000000000000..a7ba16789c3c5028775d30d20e8020affaa3ddb7 GIT binary patch literal 14571 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%0Ax=ujDDd)hYKm8B` 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 Zrz?Zs>P#w!pnordNsB9p)ruGf{Xcxg2onGR literal 0 HcmV?d00001 diff --git a/doc/images/qdisc_mq.png b/doc/images/qdisc_mq.png new file mode 100644 index 0000000000000000000000000000000000000000..c6318b288df40522379bde70f0427f40e4f42ed4 GIT binary patch literal 26121 zcma&Nbx)UAv9#a^eVZIB*~!APABYB1#}2V6VXS6ATy#2&g$rvIFoBti6P$69@?6 zIq-J`+UxU93<6@(DJdeT;tqPQ3#p?bjhQMIrvUNwE2L<>cAvm`OlZWjwcy)%O{ozt z?vU+y|HZ?z3f(#4mncf8yf7k|Z9=iyl}(dK-8Q$!jqUf8a2B)a=NbEl4axn3g9Ey| zqG*4I-k)^|J$8!p6o&077Q6gd@UQ7RBY zo$dipT(aukJfd2;oFD2rSe;EPA`G@ zB4P8|v*kg+M(~20Kt;5^L&D8&(N4@Ka0V_w!YM!%5|wu7gU}--3sdk+sE@P#TUcsV zCSH1n#KGgEoAPPT9iJa{Kreo#&AovqI-EHEYLWr+_IU1l@zb`qzqUY7PW;H!7i}}s zSq&+}mza2gMnytKF6QZ_IV?JQS3Xso*LIx|qSxXT`F40HKM4nqLN@iIbaq+&Og~A}l{JVWNhL0Lf5JODjhrIE$-VR<@5OG(Fur`QX;j zWW5bZtaq5C)LU&7vQ?>AYV(&zqCBiK@>DV{=B%K9exSdMb6gIEz&08h)Z%Chl}O8e zY{EGIrjBkhrK@VN2Jw1X8I?r_gKh_%Ruh$Wi}h%QUf0W7qgk;{zepZWdZ>Fgf0=y;G#;73p5C?e!qX*vL_y;s1;)u{wrl9Z- zNG^{Ty2D)b&T;?X^OObOX~yD{vW8mwA;L-A_V<38+*`sj`!<2{->`Vo&>fp8to3wj z7G)utM2;8!gPi>Xnecm@HdRc|+}$0AtAgB)uSK94Osnu6GH$s7nd3(Qm`F~Oc}H@c zC-Me{wzl^3j?c@>+$0&Tn660-?KoqlSdBl(UTiwUZC64H^RlKBku(lIU``Dd9%HD+ z%!NXrVO%acNC_5!AvKljg%3%8iJd5$)+nl@nzUETl}izD+5MH=LUay4{H9L4@qYi- z;2Pr(Yry zYgzO;XvWDW6>>K2;J>*WO%RRYQeS$5g@H-qa-yg}Q{KjIufL9pfj<0Ew5Ibdf50N< zk?|pA{91#gd3Q2N(#B2djH1u5KM3~yoqsq|wV4OcDL-!jmW*w#+tD{?NkQo^37Dw3jSs8#6*M=F<_g$Y z46Aing*T4o?*@M7cJ^gu#qIc&42uGmBDv{y%B{lVC|d&3l^`8nl-Ik5AvJKbu^$x4 zD_5iO0|+?I-+ep_Q!$x8IDNgC((7Ik{C^Sp344KU58T8yq zr!w5%-38p`ho_MbS;C=JuTcr%lXd2f)ps#k_{FyW z@p|>Ay&qC>UY1PJtv8z|P&z42A}P!W$={proc`|jLgHbT^0M!!-$5N1s|KFy@oauj z5QMV_oh2x3dL`Su2sGrWGgeTnH*wOWDoix9_o~@eMGB1S3WgS6~ zzlu`ph!mH|>BhEuDmx;ECb=W;a8fBRYsXX=v%~pk=SE+?hBfT<2Rp+JM!*}xM*jMs zi$12dqyX0J4@?MN-u-X&cQ3b8w_LpjA1X(tdG{3mmzb<*pBa*i*AuP_7vr=K*W3@b zFA8nq3d&5dkoe&a^02vSk&d9SZ~JK7QuaGAIPBJKp7)jv6-okB$Gsl=kND}X(2SY_ zW|JkR3*6_43aF8J2W@^GOpX=yJyq4k-~tYe^CDn4e?^1m-IC_wp2w$XOMVHMPLe7( ztKf6pPm$Qs=2x7ltcpJ|^#tMb`qLex0 zOxN~Hg{r(wnMN%=cqXUN!nZbs(+YKk2L1%2Ar z6k;tdzS~?XUkJ!>C1Ixo53nk#8+-riYWE0Hr70z;(!Y-S0xXiK-&( z-}~mq=;+7qX6xZ$Vd-+GCYm$@Yz)&FmCXkKB_FCY-FE)&`r(;xo$zW_Q!ls2jc#rc z+-j^W(;ZL83Ma~G0#)r|O;wuiWuD&mK)T3>NGl=-yS$sY?@SBwKIj<}F z{L_cfpzK>&Tux$q!VK!cTY=0hNTpeOGcNc+Yca*Hq!>GaRA<~UqnF$pObk@du_B(O z{lU-e^MJVn_h?ULhk>g+LL}OPmqII0{ zy&KVOU3TdOebi?fXtY>}{qXZ$k+h;j?XmRL zXx<7;h_@T4&Hk<0x#^Ff?86hS%hxD=U#Cqxpq}M%f6!9eN(l2nN3c?GiSCO(Z%7Wk zxAQ2Gnw&m=Iv7rah5`r_AMR~9OG5|OcKtykSoLc=5N*n6 zuK;yq-&+Ae~iCPHui+`{rnMEuekX!};~eVYRx&W?g8Z zKs0jC>+R+K@pAj)c833GD%0)X!`~*)d>KiV3*I%S!|hhYSdP}j3W|qL`cB{QOfz1R%u#_ESCaL`07heB z?u{iy^u))ybTgZb`=hEsZ_niNk8pg6oosMKCHIO=xSV(7v}Ce+D-_2$NbyxWtzK6u z*L$95R5eNl9Zcw=1g|KfafSjt<)vXQp447ep{j*A8Q{o&)Gzk9X+ZtLoD}343uj;H zDOm-VopBkbJ;F&7S2;j%v0W%wTq0o3}F16G(9z%kR?5d zAtKfqjkG(DtV7>)T6WLQD$^Kz(C5WNl`bU-3tn`AXMJ1!UYbg`68ThwihAJ7 zcCqdWWWgf3ybVV1w*r}}5f{k1jdp_%)gv+JPuE*(rNDaLpCIncE-!~&m0HlS=b%hF z3@97g%gOsgYoVz(Pl#2ZZ@PZdcSE<4;KjC%rD0jdfxAiSu6L`sk&1HAx+5mgn~Y26A0z5FgqS*D;xKhN>+jZ#LTB83zI zw?Z`#E*McuYkIq0I328u2Z7OUO%8kfZq~SWF6;zFzTn)hOPnOOAjsbv0=$*TC(|{HO;vw1nahZe^R-kyccy0V z=bvh7bY0Pnw*$w=vDepJlam!kN>03(L@{AuJ2XlZy}G4Sri=L2Sqc%_algxlHLB!Q zLt=$+Hf;6}4~yfXNPAy?_x1{;;T7%Fq#Pd~`}_Ng#}e#j1OQk$l~x^b=V&rLaV|7C zxV^1tW2RuT(E3tv1+)`1fPY$pPQUa%HVHDc-IA`_iD{s4YX;+@#WY+X7Zpw&>vVSkN znl0-aO69VZR-i~!ij^O*Fw|e8pmv-BOg(j<%q~O25eaI|R^|4o?5B8~ZB|RNg zFLUQi`tKk`nH=bRf@2Yv+uN{0NCYe-{2`+aPa5?RXYF-Q>Sqy%e`L}ZT z{em`BYoM=#pvD|&pDkuu zGdYM|j?}PoxD$%ylXNC&GLa%0(cJ7(C>FhgG)9-BRxsWb+Rjt?ae8pLaJiR{!0y_f zyYZd>Y!p`oWZlV8I?uB!w2{LCmWIDe^8Iy0uj__U|NW-Z&HYH|GG4xxDRm7u*w_LE z-Jxpd5-m#9Ff#T_-(Jqq>vKP_?;bxcl`Kw>SKh-I2qx<$~zsEj&JMop78ii6e8nJE94;nf%J(FzLWMkEk zwuCO9iTwya-ekjK6ddPlVk@it1c7LK zbwK`+Tjww!22^~qgJOf`FkO0kF!30n#Gl_I1e#4UU}257uoha8KP(lT&! z;NX=KG;El+=`zxV6|_N;;og_Miu8+A_lh0%zG5<%XO;f`0Rp@FAXyX@<$@UYMHMq^zvx4Td%J5%l27?BFb4#)@lgV`*aip~e=j#yeS;vB?mk8YfI+xME z(AVVh9*eR$7yy;nJ7$Zywrr@_)XIn+RxOMslaMk44U1{2>Wlx3R8uc;gi+om!QSq2L#BtQxicQOYPH5l}tA7o-J-BH+x1z^k} zK$&@Q0^-voNa8f%O~?;tMZS}kBD+9w1n0${%!zE15h%d~U3gXF^1KU^uuD*vRzs}f z>+9>=ILruik7xasDWL?%4XPl4fC78Qc64zG+s!mHNp_Y;5$Uv!5fnwr z!HzMS?C}#qhE*v31VvW)BtNfh2OM{|qPI{BGFrgrdJ$wLN+s37H|b&nf+25pPI(B=oHvz7h|kEg~I1L1JNXkv7@ zyeHTB2X~8pa}0tp@~45i*PN{2^(Q(844APe#5{5VN+3@>6l!KhhLHeDX{Cka%XKyT z!1XoVpEvfGp~O}W%zMrmnwJ-P)46zJ-7bpm7`VtNkIXFcXKf=Lvl)jGI~$se(w~(- zJbclQ6wD>RAFl0<{{rMHym_4p73vN7gWcVHZ-?w6vW3FLsS503fNggBCcB-@0XFoW z`eJ`?v5aLhlM<un2C5Q^V+ zL^U>0q+GkzR<&9yIkzl#I7|kq2T9?H10rn`79M`Tw8W)_;(|{fV2Yj>l7}lKS@t8Q zADLK85*{9VdwWJkMglV%c(k;%XlQ6|ZjVn-?&&h~PR!XdAx4s93#2J2`%2HDq* z_WA#|VQF+4citjBv|M9><*!AheLrELzFa7kPgiNQuOwd}-Dn{mBSRjwG#yf!l%-Pw zgMz{`n9eM`dWQaI;JJrtM1D+7V+=8R2h;8%(Xx%4w*Cwe8Ec6hMu@dHZc}6QYo34S}|f?e`NbgZ%ALi2l<*7*KpMfq;{_+Xl~ z8z8@MsADHl5IwuJ+qo9ycP{wvU9@-ignO$s zjNx`6Yq%qmDlMe3K9)?R5ET=19I4~s=I-`=)9OGsZ!nu-$Y!7%8W}NLZ?SQNnNKhF zSO5=r^^tPLY5k>eq92;@%jeqO^wCmn?eB~s_Faxn&+Sz@Z-si1tG>oI3)8DLy%835FpNoCxgNM(G!TP5+k+UbiY72hM`SS2-1rd7B7 zcz@$OiDr?fvj=oefcNlla^ms(Zmh0iVH^Q@9pw_4-8P3iod_{7t#7<&Et}nbCxeS} zUv(yy{F5FTbH5xX-gM%l-FM5I{CE<%iZaE2v%8J@Aoq^M-E0zQ*YYEBlN!09i*(8` z=x@+kTejdwCPem*4!_V{GrtbD3keYmi+F?m_qsNGx00Xx_56I9&ogOeo|&7^*RRWS z*7j_nG%JQuuS;q?fjn1qyk*QwQE`Re_e;&&eiB`b*a(<2cSQn1#I3)9n*ovDFZaF( zqDiniA|@)VV>Z4kwlKlreekK;#lK7bV7PF9iST`V8G5Uf*}%UI zZ6$1nf%vhkPpwb|23AKsiqm#AIx6Oo`IysW>o`M>iDvrG^P8u)*_3G@W=-^h=aDPJ za1=^vaUaMB$Sg3mj9N`F{M0xHGxhxwi~ezOqjuYt2jk6WL+~uZ1Dh^qB&{d)KfZ;B zi|cpoQC+{_q$aVpiG*j*VqjVWT_de``em^iB*(ov%T zD8sLvb4)oxUvBYU$cWCBTnDPdo*J!4f+vFdQ#$oHgga-v#w2M)K7aMSo{x82v#G0i zHs+T@UZ0P5UTSK|Jtmx2ik;n+0?i-jPq+Sh`mOo{hLeZ8U*K?$xm0@i2Fr3e7|~4a zD&lYAUBWQ+wM_a0c-)|HutxI-+xzi2y}f~@U8zu|^%b1LAtla=iD1cb7{_c1`71E9 zO9xZhEP^S-y%H&4ZEhZh{{9^FgjB0qiJ^`c;EY4MiW!3&<2@Wmg@^a2-T8PHRMA=M zJ4}HgOOyFK_Z|dEce578nv9r~TG< zS%QU3HBszzz28HJ%BXsOjK9w)h31AJ;*TE&hlbW_HAh6=fY;R2025hWs7<<8GW_QX z@yW6RC8QQ~JzK4>tgLKR!{@ujajH`?2J4B;$Uns{{!p$1#xHzlrFS=$3y+4!{L{r7 zx>D^EM|iWX7dt~EhYM7>@STMR9R$;N$3^+^Vw08DYfa1db%Y*#w(h$|CE}Ey0Y_rD zk}*-hkc89zBH;lsC7auY##i5JQ36|6Rzjk;E@rT|QHYBrP2j8~w2LtNcZ>apqu&=6 zH=Itql2B^wkNZeXHR+(%X#$OUUu~Iy`jr}_+T6p@zd?7rkt0JRKG)c&aq)Rq+tkbr zdW%a>$8&+@jB4FS(}t%s6vT#y1EKWUSxgrLTcfMaUQp6QwTS9%#u$7~56_6!4KV5; zF&neyVx_`y5wZaep#>N14Mo-g8Ib3Zw~!bToPmM^y)0Y*@_0flY`43kLFCM{dE9L4 zjfR*~qQ04OaB%#JueYYoX0#)or{= z$T4%y#>)JXljeU4y*N5-J=Lt-$uy=~=U!YErrv_+u_Al1%R!0-LH{D>;rv&Bvi4To zJ8gseIs5MsOfDpDkQ5gPtF$03t*K`>1;uI6@;L4N{^{Jdc!_}(Nsovz;Lz`$m}Fva zHk{KM{65|{J6r;P*0I@b{i0SZ7%Y*^G%#n{2Rzd?K&;h&Nk##r;vGnawmTgSXWmDA zr3ECk0Ycb$0x2yHUVL%J-J(ktFHB4^e_X8`Um_DF`@0TlI=8C?G?=HdK87FxU++gzlDh#l`a&Rh5KOBmp<6V}fHOCS*w_R?YMEgm?GYwCK)+BNq&wp1V zMHqA%z4n|AB!~L2@;$z98vav-jZC-^!#9K&Ci~;o{z%kXE*`!5fGt>vZsQ1o++O4C z7ADHzr2MT&^gO9hGWK+CHj!i$5}1VaY+(*z7z| zHK`=tc>e;xz8`vQ@R4F|V=TNl<^E~NU_kgLiUvt1u#lk&2HG zm7m~9$RBx@8@O<S3;*lZGxjoeVY-ItvA0>M{u#5^)~pCjgH$#VAj37O0TGmBX$d zyQ2z3oihdla~80q@XrZQO*k17s4J&YMa~0PQWcc;ZZh^9Tro|j`u5?kVjY;nZj(`6 zJ!@&SnC~Owf=`1cLUIzz< z9;JI~h)suc3<5a|Jdm;?^1a01;9v(lGO$UkU353RL-P3IbpTU!Y<8c_BbwRn?KX~% zVlw!4rGFhByJ({oBW=FT7B@AwzfTt9j7)+}Cx~a)`4c7!T~rb61(h3L(UOI&7AGSg zA}IT{7!#D6h^-3-uKasC0dX_bSOWX!r2JkDV-A&xrOJ#BN)hu%lt>;H8Knj$bc34= zmpHHSb3)fjrbLF0{Z;OJSJFwt&8D-;kpVsfM@$0txgg(x1!0Y)b|8a*0SyKo|4hAo zF4`Xe^%Z)^gp&fWj7p?84MUS=FboDjkOKQKaVv!m65+(3zlZ^7(;j9HiM4$VgprQi4IJ+9y~jwAIh6u;iZfh3 z0^m;|G?JRS5@@nA6e}|?m?aZxF!C(nCx(^RPAm!X_eTaWY~C=DA`Ix8AkgLaCN>Kx z7+^S`4}U=w1q0Rb;Je)UAb4}DcH9lw{H0VfS#o*7U11Ujfh{@|26XOQONQQPR#MiY znMrbScPc^y*00y6vX9eK_>SBq_^EqgNoL-cxoMI`<|~69Seur<3xNl3E*)qN%}I5m zt$=Q%t)LXQnuW^grqw6;_rAXg38haWGIKJ1$FkHJsp_lX~*}yu(^w*sfpfwdZMq@=q`9|^NgqlvDD|%6K-uMZS{fdCDxRKW z!iW`Bu^O(N%*mhKbTSR7kf4#QMFKY1U4AlK)qXmQSp+&YScz7%;9<7aWk-|!MoNka zoO@1NbG!W8S{6>qA9g^l$HvAA4#8*4s+`QXvby<0b)Hrjm!FSf-VzFNRj5-wi6A5G zLj=A?w2W-*$=oU&(dlZlo;POW#_a#w{fi+edm~@#Ei8tOLJK@tF}!<&`QL=U$XIKR z2>j#y{m&G*gTH^u#M-|U)sbQI`@SBGB_=0H_Crx?N}(I0DHGa+RUEO0$;7gACo^1S zv6#i+SoT6eLO^I_n5q|6ZD9l;XaUZ&!{zJ_4loqYr41UYiA@A-42)sMKYKS;{h7I2 zrSiE$k$!Ytefik0bc&(SC4A$R$e5UzXlS?3w`OXCJHnVA{a`4fgXV!C_dCp#eo4X#kFP?7AvlhD8m#&b>p z3|Ef55-REC{jC#^f!ogE;JC&WLlckB+1T^RT;T~5OiWBHJUqN-k6(Bra&;!?%L|WL z?&aAiQ%?uWpYz8F8|^xqB}0IQ4mjrE&di*5H`S?)xrWwOUsrN~!^5*k5UEyh+3$cn zsufFd>6VZ$6i!rU5^UDNG4KvGE4l&!ef7JcmEq+j+T^vqw=s;iJl69eeJWKG$Qu3$ z2Jr%EG;DDZ5lC$)?ga`ANgWS$LXja__IU)Hh#aagHn1J30u%V=M+whR5J}tzB3@DB zH|L3;_Pn>b{ouu!5=8g_uW_(n*wdcQR#Hf__v2lo_3A3Gu9c%p>ZwdC<(LHpSci0& z?z~Ejj1%nN)?5QtVk3l+`fZy<)&tzGF0eQXs26TPJFhX&L%t*i=H^tup35a!(EmmZ z_!^n&T#ut6()NNhujUX2TS<%319{fZey8G?%%n(e8^{ znOfF^8PWR!9SQ3}kOUVJ2>SepVPX7ekpI&soqlI0Lx2HAAptrS6fH)A2DbM}+n?6s zScxD+KD`YJJ5IO^Oc)_B-aR|vd4FVNVz3*T*q)vq7`6oZn;=*;W3#f%3YHynJZvJV zowD`nyRxkB3r_nsDIvV9uY{S@vlsd`hPd2C!l6)v{H75M8P(1MiIkeGHc7;W$K5Nk zv`?05i!!^*t+!W0XXb2;YIUh*o=r-`-^c;iEJP%Y!OXh||9OQ5c$P%iJmut1ie3`> z@=4Tzh>XL|+jkq{6aGGH(vMRTp)VR}qMlH^1QuN!o$cI_mE_;;0?o+B5GoL*8LHQ< z^SmRd_G90{WTInj^-6X1<<4R#i%b2xJ5!gDsBg!65D-q>jHtyM2RZHms^fD5Yal9N%EQm$kag>=; z`nJUEJY+V2tvXfj0YmYa6`m~?OpXY;B9!m#|;D*9w~|7xZ|KTmRYJ&y#At5#UbG8mqD7GU9Z*8 zJe-NGQdF<$eHkPpd&=g|O-f?zluG`EfgzFW{Pt2D7Pe(;E1R7qQqk>Q503PZIcti0 zjyQUAXpg^P{4Lk_|1a>&FVzJH4*^;M&CRdvRo*cdcHlf+wS&xzB#nr?6^Ok+aC-^1DxCOdaE6foy}mgV)uHmp5Df0vs7uZ zUIWthr4DzjcAinPGFGj)bzax2DL$pl4rb1`SDEdFM@>^B?33-TmZ>vwAnv??z#dzj zs|yGx=j}K8oNZfO*SXJ;DbjLM8SACf8;OJpap`IQQswH@TjJiV+C`!Z z>J!h-9InRM0n*HH$$tx_m7JVRKbI-x32bLUcDIhE>8sUjdV}GAOeA6Jx19IFW1jw* zva&TMo1%Q9rl2TS_bJJZ*TTE#>NrT-45mFzsARa*I~n#X?Rt4~SF-1E zrH%2kUx%%3Mby*IBs`QlvENxNSAJb#Fo(N!IGV|kn8)T8LI@|bbd^CQZtl}JC)-Q1*EIr-)>kP)tX^>5kawPF^nuNo+=Olm=-7JU*H z+JV&%Ka6X=xlTN<8$j`ystzuo_iF2*xWzTBw~-ZaLrH6$TCcZM3kE{D z--7i4gCiv+P0!z5aQpk4jgQawa;qyEhfT;6@VMRjzue=2$%ioTv|OqPCe8HBJZ2pL{3}eo*8+D+Wm{<=PL?Uc;WS7r1Q|dyk--L=*w9lssHZbtxdT$7y+j$mC zSu=_*Dtds=&y=gMRwn@ShmrXxZ`No~nm_ zcR|3QT?7OKfD~+#Iy`4b8)y>V% zo<@g#v0s)BnlK`wqFh{DyP48K*!}Q0P}P7x8z;A9x;i7&4wUH|?;mezGGj3n7pvjp zADzIsm<%cJ4)_>eUFESw!umPrI)GVqFF&{4C3%GVaV`iVH&vCxMpxzZtIe<3d`N4a zz1Y~*Cb4L1ibu_Q@o!YKQ2+$_P6m3s z)?$-%upCNTn+xTSP{t@v`Y9Xxxw7~GMf26`{`PUajur~LnEn_pIBcAfU+%U@ush<- z0sc7Ozj^+IhP=KhAjfqEY{;E^l~=vappR5MMkbf}`dNRA2-u{_798Vq)n3>HN-US7ARYWcRh0*QxwPw4c2~eE;e1ZdOwR&e?D~&wu z_QFn4AZ-!rQL0>Jai2mBr&4tkhy<{UHwMirKI1^R#XpXeT7J#`+I&qftVBxFKMX-A%QVR z%}L!lqt$W3n+h?Bj2r3n@C7L`;GQH1n-{F@I}U5EU$-U;^Fy@*?w}b%M4et5!53nm zx0kPf#c zS;}OxPc1KFuwuO>3zz@U1k@EL?=C*^u7R}cbo_~z8GeP0uJ<}m#Ku@rszDUe1?wOQ z;$mh9DT1)zbQsu$fmY6O6*BIOraz2Vz5(hgWdosdzwfT-V~(BGsq6#1gP%@mi&7>1 zu^H&r6G!*7@xtlu3$T8?0~K)Bmfm;Aij%5_Q!(CrzP`R`JgM@9OFGq=IiczwhTsE# z#p#R_m2*kAEmX;)nN~a^3z5mAbVl>%Y$8d;uboXTHukO#4TbyD1P36N0pfbd=s&8{ z30~i9>j~6Y^j`PLg?ZN$8wTcVOKXlgU(R0}C7<=9HsiAs@=y{4<>Yi6N%mA|;yz+U z)>*CL$ofz+$u#pOPupQjTS#VB*$?P{u~&eywKCdAR(J^GAlc46AO#BVi&jizd@^&RlL{Er|lGcdk8JK(R0@g^OzKx ze?ouy77#;>ji-#Hyk_Ypus zz5nJZcX)2L0z$zHRs&<1?Fg|iOCT|~3@i(;O!O|ojf(ARzEojMShwFjtD7K4%Eit> zMDI%4aY@%Op(Y0!kDO-5wBNu*(Q(?awcBoPWF`v~v^%d>#)6{!dzC5wvTJ5$k#!!V zRGM!@l!ujF^`^_xsbpq*ah)x4WlDVqG`OoZ%L1Kskx~s5Ss$yFyB!-Vuin{;sm>n`PCDnYKHxHUJjCKS&e$iLe%#X+f)Ucx zkG<~*xGsc&n#u1=^gy}gRK`?EdamE4RLDIK0?U(6Vn9g}CM4l6L&H{eIVY#AbCwS4 zwJ(X9?;7$U;lw=!335wN&`UQoyJ)F-=Wrm;UtEYV&m^w;ht!bzoBOOVllqBRmFi^C zp&&EoxY%e_%KSO1K*6DQK57*5g@z)&P5{}ha8z;(2Awcb$<@ngMa%Dbx(nbA_1qqM z+a0lXS+rVxkhc@|C?Txv^E*0qWI=g%~W=A@m<+_SNUE9&r5^_MS#RFk^Ol zAK)28x4{Ak2=;*>j`?+o?#IlC0n1sxIIfw=7Y*G)%Q@42Ox1PN{_b8ql?s*c^;_6S z=vu8mfBsloFlP~cF{#mRjbR)EvP|E|lKB06@tOmiC%pj>0^=o1DVs4!x!|sGRswBi z{zcm%gwgF%lOJOgNz*f-xbZLg>I9eY zJeNH)5fSUcz~5Yhb!s}9YHqK0NW3~P+PZ%|Fj*b9KlbII{7HLh+GJ6^*9??bR}oT2 zbuRI5L+-sSrP^vA45pEs_~dYbLdO9u<%Ry(6y&b- z@Rn(s`FlUJHPxxweNh3yaK=@=iVX?|Ktcs+F;p<1%>V%`#IRNg14O?0Q2*}>w+E*u z%3>!!7^CLpYqE#c$PmVjlGv=6F28diIR0tuMZ zhCEK;Bj3W9))68BGk=`*G11K3 zaa=|b96&f>-~lGwZ;6x;f;@}%sq0A!CuRis*L|v9RS!fKFrd7jx?T<|Yq{kA{=?28 z6(=dJM)BXjGB-*6RY|FByWexs`bDeDqZAoPn@-@+l-O1jv}vK$r>?_1k@WDgLeIQF z{p}54^OF1_g8`p~BA*KAc$^|AAYw}J1G2$Nd^ zCwH5=Ykia0q##QLs=#o}zv>y)P=HB}N&2X%X`Xtm5k>Y*#KykV)^z9n(`55d{3iIR z6~s*yJPJV)oO9$)v9ID2#WRMU?NIRB${6)d^2|Q=WzODAyLc|8W8i*_@we$JDUsL? zIn+5Mgq`xn^+N*vv|p!iA|J?>O{ePZQcuNe?6e1KJD`~g9>{v+3?_SQMZiZ=F;{lN8Q_*Kly z6?=jR36TXOp_6n#6wZ;c1N#QMb8yh)d@>JkLM!d#hb1vvPL}4xBMmi_D0sIOgnnsH z-J5c5=c8iC(f>{v}1mz2+RRYxB*mt_5F~9W^J`4;DAb)oP za54&M(x}t1JD5WJK?+f*RX}L;(}~+0{s9vhI#uPwLBv6|4tesaGj9AQUngd2IK=Ty z3WmJF$HiSIzbD2G`jo)pY^im=eL2t@9cUGV$7HbH`qggFrl{Lc{qJWA)~jP%l9_?= z-5CzGP6?G_oHa5C@X8!5)eAW2t5@$a86_ocIE=LdK&AzBnk`j3>By7m$n6`R?5$EGsL^@ApopSbsNxxxFWW zd?wK3lE}~Is29s>3liGM$qkZ(Lj&Xnz*%Vu?y(v0Lo{aS5my?FJwMN*Ur zc&J}|JpGO4h&N1I=XUY3ij?w+JfPn85_A3Dx$s$K zd`Nt?Hw5po_Iol?KJ1=u3obW&-G`=Qkv6AwJSH+A#dO(4s-^PJG8iEp^`hz9$zJuV zxlcz0imD+qZ-FHPF9v&M`qzc6jX@G}|Fu@SvG{Lxf2(g#zR{4VWy{2d;l_$Eo~YQ^ zE6~@X@;SiP2ZgkK8gb17i3K@IuO>FQ+De&LQ@SzKQ1EB=%CHql@(~Tx_5)&F&d|{E z^K`1Q(W9EdqaO;Vi`lxo)(b7zr>K_~FCii%@c8K$y=*E%ZfYJLOqWxsIx zXVL@zb5}#F?@0kk564f*50hYA1wJ6uPUta|LA|o94vq`stv-$F#~`=gySI{(((q#O zl2%m}`o36+c%^J!>EvZkM?q;usr+96*p7peS3#R|WY`69K-!EF%G(7-BH! zGd0nSF(w6b{N+=$ETNV}5fYI3)EoczAI4gki#D=kNJs`88X)-r*%F9FQU9&hMbVgX zl+WCr05FOm|1xBvQgM|j(SFqb-s^ygTPS33REhcTt0KW5T%U`Bn)2U!z~{0ET;dBI z|L0>szK{lD^aMrKDZcK%_wpFP4(`e#@sdgZrynq&io^nPv1J*NLH|pb{OlVHs0#|v z6WxO{yiYBX4s75hcCF{OO#59bL<|aBn`J450&J$RhU3wK2{`V^N}!NB zz%cs)p=rrTe?|!s5fKTHevMx!M8OJ&{m-;~&JGMdsH11lmJk`?fA0ZhgN~l8V5HxO z|2vj^QeZ5z+F=L(xA8?20r$iV$S6L|Mjyue<;7ucS8!%)bIN32h1IUOs$^|TjJM~0 zuPPuQ-!8jn0=;T%C#}2F>L4`?8z1Qule>tXm`LSwGA$?Kbbzk_{|FIWAaV27i+#JC z^Q%gXyWR-wii}09R;~z)9YGGKivU(opakfQdWzVXO?UxwXTarn9Yx1eb$=xiwmw)GG0t< zNa$Ybu-4SZaO7rFH?ucCzzGe*VSTLTI1&koNgOJ+G%B&QxLtNa%7=>`HvHPrk&7Ab z(;kI@G5=4#@&#rQC>5|-Z{d_$T3S-|VGyFRFgDkzF{rkhk?V^2;xu_dLab$^)DMKV zAw1gFT0SKbtD_;v(o5^ci4^ESUJvW+Y{w46HW=2iF-eMH(}2zCL7#s=RR#Mn|7?1> zpwI>|;jq?S3$1)VJUo(GENGpBgvU^+(uki{SYAiWE807_qk=_`2eykpH%ykKPg??T zt`JcEjNAfWPp5j}Og{edRc}Hs(Jz4}D$DeR)(T_d<0mBDb=jW8WR26=ADO^>&w(=O zbXUKaQR*HPwd3SLFr3}?bD`c5(4VvkFf8szhzr{=JUh#7>w=VvebpI`?gkM3KOoP9 z7z&&YXR}(a0!pM0pd8W^fHJ=Y;myyz!i*RID7Gj5xDbrc(rNo>M)F&0FOL^BAELa{ zPXu;}OEnr>G(WUzCQP&iaAr}TzYlxb^-{_8EG@-FuGMD@X(L&5+||P(lGOq&S1 z8kW2tOonvy^vz^nPa~qElV`Fvh@PL0B^kJQJ?CeOD2VgEK{y_c-@m_kMb{@9C8gjd zt@HV%(EWZ{N=o>Nnk2OIP&g~EU(i1=kX(R)6_3XuVUUo(i6abnuV_KZs85)=1F&|~ z3>+-1E9Hd5M9ql$dIupPFn;N0`}f!9dLnT7{o!cMav({~=UyUeChf5nmLS|aNmr@3 zQJc()1!=5#3{KbU3ARFR4E2-*^J6xwIPas*Kg(`0EiG+Sl`>RGF2&i5$MdcX&vP7= z5iFuJ$=!u?>@%s33$w!!GNbl>86Ctw$T*55{c(EbL`|mwk>TD#ud(b3oa|0#$Zu|D z^CND=^C)W^0~J4N96gzPrl5d?1w|kw+MZA>VSZUsgd#7Pg8^GyV+AXmW+E>AKVu0q z45(^0fzQ9C^u`%X`hZL-L_OVmnj6>{yegfxe7EHHR04c%Pp5&-V|(1ltkuq#O>LdP zO&LaGnvzn5eNZq2qY=f0GmW7 z^(V(%Z7fb>NET8>l9X%#qx5?EW4Wn>KjK~+nzfC(53oc4LQEvNc2<^bDFi4ZI1JB( z&eV2Qevz0?_--pLJ^SfPnJu3A*)b+fOj`&vII@qzDmI93Y0kREtUw0D%md z7i`sUTDQs8(mIFU>ft;E(N!%*=9{*(7lhGX;kD20bI&DzSO4|YMcx$vL5HsA zqSCrQ=R5E-wh1zYfBj!>iyDTi-5WRQoFsCEF!w4T5O*+E>2ox!pW!Y;DB%fkNq`4u z276e3wpY46_vz-y%`FF1zmVYf_EzvSUlmgk$j<@_*iW|wMn>{~)b`b3Q3h?l#M0fh zq;!{bgCZ>*f|MwTz=BApbfc0=NTVPjAl)noNC?u>AkESpXVy2)dwtir&N+X4AAi7d zvCr(>^UO1I&;1LK`vL=6ACc`I?uIVRzG{_pdT`w=hSl6d=q9V6U%DKk;|47;Rhmx$%c>6&sZgY*MmjD97R{ z0OW+P)v`t-mrHi!_D#k~N~ENaP5k}+U7ki=z3e1*3uLHN$iGpUy>SOC1}UnYvr69s z?_&PHnLv^XnEY(PEW+To?|u-5794mlJY7Jwfemm5G_`MB#h*2#+p&l235esRIHjeN zKAa5=;zo87*GxqNtoP{=ZKdA&`@KyUpPv5XmaH5_w&1A!BhmPqZ#={Vvm;3{%Ko3( z2XdH>KofT^*jbT5|6|uzQUDn826FcP$CmmNxuvduNF@Jv>Vl1Ghm3|MDKh+Tvheq6 zl>}r`;-aMY&!&(+k`zH?b`M!-|JDBA`SM&!_U7j1GCr$pVUf)T#r;9>aN_8|rmt3- zpkjqo+~&+FK=cixDacAgFW4vHzNbx1O@#uFdHvuK$BZv8vIDu34v1TdeORp5za*N~ zG_Th^kacj*)YaE2!n%-7-v2!OxURKaYE-F@=ipD(L3O(FIUjf5UFMwqRDpDT*)i_0 zww}alBVXNGPgdwmWA?91l6|-o1)z`I&I&;mP5Z<>XmL*QN9-Zi8%4_iE;h{H( zUpyKG?)bsY;8wSImfs6Ti;-bHmG5C?zsQtr+&Vw3$;z4<_(9Gs_f3-~OjPBg26m{- zZ$@_?n>d@fyjv5FoQZlYUn)j=vmyg5#sp?kQ*t)Q3ezy)=X&f+ze3FU_a$+;eP4Of zj(5Jd7y?D>TOuZo7#;mR)T+2fBGO>o?72T_`Js&NL*Ln5pYy%$7xV7{Z~3v)#q^}K zT+4~e_nR6!$7{fLJOd8J6)+>grKp!>v;TAHCfA&T$i zoP{y5t7zzSzC6r1JwH4|%w?LCL7&Uqp6sk_P0;i4eOT#FP0DDJm$}kcLgVNy<}qft zr-}doJy$2ch0oE3e#vW$!zTk5++rR>hij&BamHiCZ^pi3*L&vX-nVRd;b1c&6Bt0J zKPuuf|M+$eZPVG zr)M@#E<~43&Lb{&N)I$08u6But4>dRZf+hok7T-;t;IzW%6t39)JMTrzDW;g@;)>Q zDEqO=scVjnPbXFiQY&OOQ#ZK3+yf5L1*_mRURGP{IbLeo=)Un5uv+nVkg%z4-hCdU z(z;h$;{eCfT{&3oudJ-h$;knJOpt6~KXS(vfLh8Cg!fQ3fYwyeYOcwf3B?tBAIg-T zsI*mm^k@bY8G%ys5OA1)eDjNO`5Zvo@d*e3vVxrEU0o`%yDBOwvD8Aj!-$j3^41$9 z-rN?9t{M-;8O-(ST0BBgUwdnaHsp75$~Dz`|C`X3z?y(wN`lME%w8{jUxWC@@29Xn zbLuSNtN~Euy_{eyQzUC}|4_YK`BMFmid&yx^bwqU;@Wc}df~iN$Sx%#qv>UPF{o8% z&$V~~q{5=RJU+^&)pIKJX$#rnzE#R|XT7*U=zNIp*glgbdl* zuv@gwbx+l+zF~=N0g&bA2%=hfe{S8YnNvg>ZweS{zCfU@J795X&MiLOnzB!DBOZ$EcxW0hh{cQ9l8qwC)#_|dCGf3Oh z=05A@b%U~)kZU-XNLnf&(h<@KLqsfL?r3OeasgKofKpMXxaZ~kyACz0+4r>DfVPCN zOvk{$p!Y3XBWN2?3s~=~sw#t_^z$ap60+?E>~`PdO^hkluMh@`xKVWIqKW1#UAS&K z7k%ILPlSuy*IU`ZpyJ9XhqKPDt0Tpj1k)!~t3?&CqRM{sOYyEc63pNhIJ`slYu|2# z_tVxw*&c+M1nsh{mcRa>h2QA`PRk+X&Au|c&&+JCqO$+`=2(QX=4(yriC0Uv%7?V{ z&eZ8vo3~nnGSr1OUAdP5KoRg*PH-wV73C+6fW8%nh6WW65AS?bY(lDJ@T;RS9`e$3 zY4H}zf~>r>p(XJI$~={k46V3WkFhT?*7+KUxi4OO3)2xqh~*_s0)ir=QWI|9liJEk z&bRX;Z!HB=ljs-MHWegfWT1$TfXp(UK4|-24}U-JN2%ce@+8H}(%&r&D~}L^F?ibZ zQ%_U*h%kK*CZ(iT-8*3<(HtBc>C_)EJfz7^ckqlbFf7wN5o7mCAszO^ZQXblhe@f~ zJj_9Is_)*u6%=NE4p}e(WF*vGY)rH6*mEb&{oZ#;mMl##Kru0*9BDQ1<%_=5+b$7s zHUowvZSKpAdw|CTi{0Md?vAI&Lx8iA12w|hRv!3Js4CXZ_cRG@+Pb(T1U~L2!zhr= z(#e)fPfrh?K@vt*`@*cbaZp2{6z@hmVcS;|eIs|@^V6JQF&g2|t-R#(UtI7J$i8(A zQHTgB>cuAaPSAM{G;(HegAl>qdHpoxuKhWzNX>2@pzI}qPE z>P>R_%(Sy2DsN#o?ej;zsws80H+#jN1z4fzSnsxv@4FmPz;2{)r1bA+&VG z9JMBW(vi>t);z-!ql^q-*#QorV7=q}{n77SuMiD>2J!L2Z-M1pZ;Yl{JVz|qJh6f; zFZaAkU{$ zX;@usyh$zmw0$~Ls^;?irG%{Ww{Q1eybzQ#82b4pj@9~zsLH}KFHd}|G+j#-OZ#z) z-&DRD86l5}o_iJ$?ROH8x~w5-jyy@%wU^Z%j0Uv^Sen{G7>q517Vhp3^hQn_3Z&h* ztJ*SCnfJVClXjMX^^C?jDOL00wrHqg;O$sJ5W2rmEk<}UuDAk=Tf~=g&!rPe3E6{} zG~ySSXw<#n;l~QeHTa}QKr5;+-$}ufiw@Y4|Z(OKJllO~J;)imj-b3hCs9->dHT9YJUdlsQ`)drrSwLq9De3x-LUKbU#2y-` zdB)G{da%+9_8odTKM6~eC_xz{Cx@Bjwe`r(_cwO{&xkZ;luND%OCk06x#Z>g431ND zVAM_9-EPYdE=>V$ba!}6!pJTqahG{k9euGfqN^*^X*NF1edQQgyDe|Y0p?>N0*guR z&}Mh9kl)z95Tda{=gWbk1f>qL0sR9R-WDswc=CA4nZEjr+6F=mirtu)crr4AHSXJE zCAz5s^5<8QH%o1nbb@j8*R-p{t?8yjz^j(Hb-o3xA?ZM;ij z9qRd0olv!<`5&@m_n06EsNoy64YZ^}(neKYTg+OiH#Mt7vAfl7jMT%cD|0*=sxHrI zDJ}(&?IS&V-CGKhjxU++Lm{))}xXjPEx! zSZlFK5%F?8@`VTx6QyA6+0E4-*52~+Z?%UcsXdcS@S0^R{qA7!jZV(3nr=)uvLEh8 zc}30Nht}^`UV&2BFl|T|oB#P4W5rmE$s{s86Hgn| zlt}XNMnF?xOQgvpAo`I+dtlrAB?DLkB@)jv;dd{*Nr8%VkcyaoY?nbA3*<+=K^w04 zn3f&pz=g9Fw<_&*Cd!LHAIUfWW^fw#)48)yK0G8_v;r;)aoH?;6~mbf!JQnO`wZb( z0mME&pstn9lMEH-WPjzL@h4ifMuQ3V=Z{ttxnbTF&O^g~_2GWkke0516sAJ^KP-uR z*E204bRN*(iS;(c#*J39Ovk@+^!kwJ;sXCjGU+IazvYcwYE$Ndf z4$5L-`sp3Niyt+3pr%vFR8y0H;=u=~of!Hu*j7U2Cp`JI!dR#lFdtH~mdv>p&ZEh1 z;yMVnfS4X;S?A>E6F}`*WdSWVS$&srG&}OACq0=A+&Y4Rsr97ilf*xR$}}TFFpAU2Vl@^=`*_PD%ML(TDRE$WYNa>!ESpV920{# zj%O<*T!>xITZ3*RuV?B6H&rBHO4G&}F}=EK`B-x^3xf_uj;;Nar>=eGDWJ1uPE+Dh z0jH07qXVc>PP+?l9F@$~9ojb3irS>~GXe?#kYZ@a$|s=eE%(bisVACqG$F{!BBR=% z6O+feUdX=UG49N#jEszmYh1_lQSO2#4PCiVHjNGZ^!3avBA2Wjq3y#47z0r*MvQUC z^dbUh9{(#fFWt|J&E6zCevt-mASAxKwH}DQT)#h*rT>U(DI=@gQqFXGh10CksJ}&j z=kQvBK^#bn(Rny*qcr_q#D=^pG5&D7`0<(1!zJJ4dH=y}ljwI|O;|q?zmF6YKfYEc zX!WCUI#mru`;aZ;O-UAV2g`A_H{=jUr^TD>YI|yHauWLV>E!5~Xkb8Dl(M|v<}jkjJNbleQD4$aSFRW>@>Qbp+X$0tA!dm7MA;F7es zoC!he=FqUu);Z$ZOkE73_$#UW7GNzaePCij9lwIK5UqSxVAcK_76nAC6&!e~2MZ7E zUKDlQ_l!SZXb%Cj*#N-$18k57=2@>UPn^#5z=HFPuCAd_?x190GMb;srwB`x!?<*- z%KH6$iYYqv#bjRmsO#su2&1oNw)tlR_O|fP4P*+TiMn1|IIo>|J2dyy@WxuK zN<{A=29xJy8pW;q`J{VZf9x@(6=^Vp@5=xRS(@GTs}`tUd|7rJ8TPBQA9hzm#TR%z z#FUrfVky2_%E^nr>?;?or3w}IbVP8YzpY|Tm>D4zy^(9DEHwHE9?6?_Ckh)42r2dgr}c{& zBbT*Q2v7U{sY+#-Yuac?&0Clc%oXC5{jl3pG<~vYNk?U~P|Z+!98Q&NL{W#T{5ruTH`f!C#28YSI*o7onX@vI z+;0zX&J^%4#Wv);m6Pw&*YolV0;fUfOqB=>;ymbcySdS5Y^^r0AOEUDt z3ah9-EuY>=*msV?3Tl$Jo0mjbSnQJVYwb>^Cr_XL zrs>-bQuM%?fJa7(TehC?7{z+aaK4u2^l7ZuYIIeOjehrILlx!GaDC&rR@^|9-9Xmt zNc-Ss&qm?56s~71U0tfnmwyfe=L3Dh$THGx);vGvG1|D>fh3!HFB2vsCGIvPtd|sHk)tFbO>3)d94Pd)&G;)~()`i^CO#9R%j8??_9#yEFz^RwJSO$FunelrCmb@+s# z1b((?S=#3RTeR+7z}(LxXNLr#Xv@ELMC&0;m1pW36m^;Ux(bRAl71COYm=3>+h#Z! zk0W`3fk_4;wkmCLbYYh-{wU>SDO7QpZ4LPV`sr&$AhU>BeBov9_1XTxPF zKxMHRFVOG#49g!8ctCWQ?qJ?){vZ1#uWm=8%$zQR4>qF~01pjzpXJc24zt@1anpV( zC?Gc1SUfcBJt@#_r>hW1{N2{Na=6p>tU!ZmuGw*8CDb|xeR0v`G*2EovGDmFE0;{7 zh`U2`Yrco)>43UnZL*&2D_yax>J)D9P@LGL-fi{f`Z5P^(5(w2Qi7j`Zo~CTh&^Xg z%fzI;%4J?|yYqES2!({na_pngN+lXyBVxNsX#z6qw3QA&(LeQ1SVBGt4c9u)(pEjK zyJYb_*^bNtehsSZ<7F0)tSN-OabWnCWUh4Jv7)stfJdqS(o8RbyJ;PGv|pJtfF#!GvRaYalc=%67;VAm@$>5E6zWV=YHiY{kvlFlt*QwdQ4g=P%nE#Vukcwy{UZH6Jl0Xd>XmZZOJ zsJSXBXhAAIqx5r+@oK{V7OcO^fO>wf%r?LU6f&^aujZ^=#qiX$0A>JmqD87g_f-_Z zYk;aCVPmPFp!eEDgq?ubtefD(LWj`Ah`1@;5j9>5)zJ6hBK zW=8yvyore&Vv|Q!sQH1FJ?dD&2ukH(<6Mjt{WiKG1azrkG$kL0`C}(G{`q{`#Hsw< zFAF7|QqdYU*E#)IEj0CBv%IcRS|gj1$lKDl zq(ef5O|pND|HW(Y85biX`5gZadkq=(8hy|&4uCC;5uY6$FXwiKWHmQ_=umg^((Q8d4%=6c z$L6q$L9xac-hz|wdd8=?is-^)6y9ZIJh6E}Ik}_xyH>!2g51w~uGyHXk`y~n5uHxJ zeL(+lK$!|3fF1ryy+`wiSy+&_`xSAW-?!klfy`-Mu zKkFsx4}AWUxA67GbxWIXYsvXR@7JY`iEXD=#x zXWKVqGZU4;G3cAS{dkwksq%q=j9t5BaTZW@K502O;BJ9CNwsFr`4JOsWvLkT{U8-! zDXe`+BWHyOV+C^?e)hY*Fia)nFd*%Ta48$-8*`04^%)M-h^2!XZ2j8d)1Tfcd+(!$ zK`7QGB+n?k6s7ix%*{=WryjS zXnSFs)njAHER0wC20c@X?H)0jv&CyEi6<0zVIw&)4U%e99PNZVtYInqvsa4t*dz?i zCulv5M4>Bgh}GFk|Ht71T8LdZ1yTM?nnKCg#cjmrO1ZglbA|O!=Tr*k5O%ga`ii~rP*MmD7Q;mm*A~8g}vQUMg0p70ebGU;HBQ)UF*Mr;`#=x32NmiR<;`{Z+ zI?#4_>Lqh)>5-VxQ-A>+0+ZRtCOL_#lNaZ9SElP*4{fvISJMRXl9j)ep39P=ZG=zR7va?3`pjnkh(l(YA%dTh8n3>``_)wHe6W z@*-2aXkyDS@blet>#C{Pd-dLxN<#w#aSB0gT^NOhbS{l9>;cqROfW9uoHe&mM>!Cm zoZ}}_WDl4Wn3$Q4SYe|7{LFJ~Y}xbD0zlRL8%1c)@VmC3D#+eIuvhLd9j#QQa5Mky z9fTA#gQiOMHxQ=81n|xwv(KUb2sGN)#3KBljn>TMzB*cXk-n@Ygee(v!8vz#hjXgrO3|v68 z6<2q7^9J<*_&I{P9`C+=^Tt(1LimT0E6h>Gdo9eqrM_5H{ZrQLY<)4zrfkxzN`pD- ziKiLrUgF3~Jr9F!e5vX077>)Rm2bjCkHT<0geqMs{S6h(Xv=&-CZn}0; zGQ4(DcklUbmn}&SBO;JLTxvo_#*6~{wrXWIU-sn1GWO_{%?o6%LK1MlEV3ADW%9K& z_M^Tn$M3M(aY&>EWpE{C^0(Fc5gD)Gby&^XIaZg;6V8?|tu&F$g{q209|%XPg|=pU zU714a>1aw1hphfY!@$7szuXyUXe@U4zt^m_9AI0RpU=(BwPj*wuY;P5u~{$Q%~u)} z3db7_C7qXYG3?D9UtKv$Ne!j5+jQ%`$_Gs+$`tYj z{okWiQ8t4@@J5dJ_Ds86Q>+*s>^-jcEt{t5?L(S+rKioZ80u#BmqM7`9Un(Z=CL*# zJ)eircUEnt;63>qh+J5|u~O&{U9fqHLDM*&SK3x=xwf?@(O_DIcAu|zJ1Yf2tCFg4 zyp6|771XzQJ7LQeRkiDU26Udi1(Bs*o$0Ek)SqS(>$IYYS9ZKil~Nua)g!lRFlLjN z+#hHrM+YFKSKH3BnbSo@8Z`$s7IV|F!+8;3mUqN7@+1@8ul6QZTRd7?T0kzrs6@`k zi-CelN=nZU*YfRpt3`?hMBL6>lO=@d1f5pixo}|6$4fl89Tucv6U=(@L3eHB^;#XG zaT(5rQX+P@+HBJy7VAZI>50)$0upbBPf8Y#*N1ZqTJ__ln(Q^XGao1Wc~G*6FfejN zPY=TC4e1XgOTH9Lq`Y<<^R{y8CN!3b-tvJ!F&ex|?7MhD5QX0+YA<5~tnQ=ghQfz6 zKll8XXz{<*yV_}uq@~-e9Bdy!1b>c5uUV0duUgq=Ae}Nq7cS6hR?bYJF1Orx-t3%M z9x||?HBQqkWIN1Q1_maYH=uwg@&j60D)MHx{WAUNx~R0gZL5Azoc1&Yb1&fhUXrzY z76>=$A68Lxe|Fm6@@IK(kuMdb{XgkX-n1QM}E@(hpUl`Sx{aG1u`= z7>kFs(e)5KU772)G3Za(L{T&153m zi()QaAj$F$KGPeOa-HYNJSj+!w!;eaecM%QS1_7xt0!kk9Tb|*<#dohqgb)n>h%bG z+}GFVKmqZ67#|;B^Lc%~+Ml}I9qUtzEP=%}v$V2WYw>uW`uuo1mc~j)O8QIpt*8tC z^A!d%hr>>UIDv}YNVUaW8Fhs`esUzRA^1FQET`4f)z@JyY;A3KM>Eug2phS%xNZ(+ z!dXFyM=S(&;g~eA;18J8XAjpF2$dFPe0+S2E>Cyog&^$>mM>pmN;ov=l?p#9QayCf zEN}FL+bq}H?aK6^h*cn$%KZ&q*3r>{NZ8vmBYh^o#H==-p`B%2B7f>;wcU9e;U@un z4V(1;)vyo!MDZ6IA3p^QO3weV6!_DNM^LjI6{)-&($0;o;~>&q5qgZ9C6!S5cNu}s z@EI8m4M#-xyrjfCJj>wVl>VAz zEY(9!H^MZ%1&wMQ#4QO%mTx@F_NFRPnL$PVozvQ!78exd0Oq5TN~+eaE{rPJ?Fd2W zSqRjqxzVZ5sz)}i=o#meO;>pyOysD)z1VK*3N}b*XLxvO*!bKX6aL4`*=Z!0-}UZx zO`1;0R(O5A3pL0Q*K2=hm(Yf&u68s&E$z?ZQmxhX1+HJK=j?#jW+Rt1dhAT{7$p7a z{&Mr(+Y_|D)VG8IqrW*Z#OCHd;4|sJOT5xe0i_pS2xf6KRkh}i!(7miRAMW*6!JW*XvR)I(x9~3IS*&FG9 zjY7b-6@1+ZML()WbUCr3gH}U^dTY-R# zJUyk#E=EN?%1Npq`=(7ckBeF+s8~%!#AwU)?fo+mi}7gxkLWP^1gmTgI?F0N?Xt$ox*-e=@uEgZAO)ea-v$s~a2$$?RJ5)Y!THlSSGlcS@f zb=E5iR=>I2l`Q(5OLRO(YpM2?;>O@30^8c!U_2fR>B26>IJ)VMzUS4eEIF-YvW)k$ zp=?0r97Y$jJ=SE%mR27jqgJa2DLp5pO21k9_i3k#zsPg0qIkE>N2Nls>O%H!WKMr? zK9O=Z=n4xLMvwh=*ljIU6eAi_9CaKNRe-LS8@tdvd5E>QQ zvlmJr!7lhKF?9Em=G$MElXDd>sKY2d+UUTR5L~fXp zHml=t@n7K85r@Nbd8=0&kEGQv5U}%IPLSN@B!5-^M0*!GON!yf>saje7KmCksbh9_ zVIDG7^cu?)Q5Nl_yd?L-1_)nbFAG5~?w1edsULK)_IrxY=wYN!TX&-4!l%t$!t2Ec zJiviBq2%8+jKrGnhULFlGyJ{npga6U!oOQ6oeD3{t9Z9+Ql?FwdtGdeb)d2&wq{kz zo1iLmp{{d2IjdoT#oxSmkn5~Kt`~*(t%qZ8jgnIY--C*)fk;PH>Dp1VrEC~uKUOhU zB!8+{^xZJUWM$=mNcdtTfy>K8PPbI@MqK>VVhvqjpU}Z9iqC`6c|_GZ3BfqEOal(v zv$z3#+QqiZTGK6!UIxec(-}yXz0RwnL;CSHS~xOY^A9SKWMBZ#Ag^So1>>{$rq$c8 z!y(-hIi+WAC%-qIN#y0N&hD3NuFv;(3tSmO%ov!%t21{BCg^+JE<9cDe>vkLFGw24 zvXSFs97?Um8YdIZQ~9iYB@LijJWEsOneH8Ydg9dK?JCy{f#r0+GW`xZEh>`x(|Np9 zXXlMCE4ogK#w|6%U=xBrXrv7MKh+)Z|8G&p$*Or8n|ZSgiz4Rb ztuB+9)9CM~nOx@mDIC;Lb7vkE`0YdA6=9P&b?xhIPp5j*UH+fz%fE=n(=G$Ewa(3x z-;t^!z6I?Q`Gyz@wc`5B8BquOX_H zwwakx&tRwf^t9z7F_=H` zo0r%)%Y;GgFOxuuJiSWoCo~on%{!D$*iLt)D6J~Z^Lu~&vNt$&J9n3OXRH{rw@bKc z3=fY9>bdNZs#?y&+rM@{DJUvB6ulea<>hrK@7BXN#5R*4A_AdJ=-CZ=i7|&e)}n4I zyjw--jLtY~ZKc<4R4UVQ>k2}N#Ag+Z@9!6Hek1N$M0OZh1hK&ZF}uD&j3zKzDsQHh z{xVtL+~0-#fWX2B#PANX_4W0RAxO-1C#FvU(xbgV#6XH@%6b%yum)z2R#_&89ceOt z?t&JuZZoOoPC8$5WU3vFqPe`bb%3=TZK>OV_>o%CPZWqN=1M2~qU#152^ThwnJw$6 z7b#HGCtQp7hIn6;E!^8`WhYg+Jyb~F#`Zb}wl_K*KJKe>>W5;!VLCL!2%U##Va(YE zGSMqgG{+>D8>WogH7dGjbPZ}6lcr)&kW)jxBFBs_qz|1DHSq0@w40M zliFXo4uuo<62&&eOE$j@^vC*Ilk#rNS8hwEF}}Vh;k;nxY>@PWE!y8_{eX4hVz-Zh z?uRduP2ka?d6L%TEF~*zrBXUHI#m*_g+ia%rnRkLt&LBu(_xta$CBL^CT+T0X5V%$ zEprrVXK_Bj?yY&DrlDl}O=UE%!Ue1mb#K{rd~dQGF1(B1^8wQim!~w(+4+ES62YPF z`LV4`y9qRr-E(yGM61Mcb!V5Ap8onrD8#V_7A`HB`cH-zms#TPI7WA?5|TC!M62yE zr3Kfmrh@WQkrm`u-Sk&F#rli7bS?tENe`bkThqRp1s}&?3FU(%h>}#t?k!v&{=Jgm zG?*_$N_L2PSK%E<)T<{gq;hj*Z&xE2Ptp;?jCyfa^gM<(sR0H5FVt(H>h6gSYTuZi zuJ3=2%}pSNZG3~>XVVA?{N^1g$`p=$Pr}%2w(4cEj`lpd3PE7g^qzmjL*f+;EAQK) zY=7M!{baUI{1GQk<_A@|*>ocJlT-B1Kc;Bnsx5nx(WCYns_?PIyy$XR`<;Ow446fD z{?IlDp>f;t6hEjd&IcV9JYkA_oOIGh5PV1#8kXdTiA zz}zlT*V~7O1lZX5*pY&y&1dJD}&5qQU0X*}1-ba#RQ>j^JO~7t# zNd0iN&tf{BRcnP+t|Vu|6cO8uGecPv_PsNrH=8j>)D>P#ZHKp#l9m|MGbFk@lHRw4 zZj8CSy!?@^>`NbPvWeH1VbknvG0W|L-KCuK499>#qA;Ld6McPBzDh>SbT%vf5_50- zUh&m%^AaTy4JWBZS_WAAu+&K1|N)6hIWIIVFxbuMV$OH;XAZ}iLw1*v$o1){3_Qi_-<3y(NsF!ONaFX1I^+2ArRLL zExNO)2=8kz06rRRm7lItO22SALs&o6 z8IQE|Mb!vK@ZXbfjb_}?(}V7mlO+%KJ5VvuSVF88b5rDqq}0?LJoRgHn_T!?Tqn4p zqp(b(9n}WN@1^;Nzy5y0VA?Udr0J&_1_*&IrLbd$Q8@e6ytM^Q@dB8Yz`bf9^tpNu#iJf4Tcjv-atJ7d%&{ zJ>(v1Hf=;`%rj;OAf<)W4||*F#31C429S-wk53&RAkHVtsbaAoz&viBn0jgThjk4U zD)fHb+>HTLMP=x1r{+M(=S@a3p3PnwosLNM`uu_dmJ`?hu$Dx;Xpwa{yzY9_iR{Ws zlH;Z?e*gkvXmdL2hyTm-<0gB1PtW$l^&#YCrbP9lPy?td$aNf^K@a_=b7?RSXcHjr5dCEgx}@#t|*oHw;(8(`)%(n5sQFv=qq$#LE1TV3%Sfys($AkP=A@ zD}*ZmVtZ$lbNd6t=8k|2dK0+tF(GpGec;007sdb>Ok*KAHg}R8EMr0>2DOSe;~qCh z`v(W+jt}rG?aiGL7@8azi1iolEy5>lC_7j?%a?IQ@X!yJe}sa|v>HgKOwFun7XlmH zcCuL+QrQv|Q=FLX>QFbocWVa^UX@77fMyvG<7Z_+Z2M;~yT8A7J#~q%l_$}zE)U=g zw?|c(I$JAc@9ahCraR+zQ>d@+1Y%%W(Cj1{4QaiK#?N}D=-Q_QCrYjCSX$q{3iCag znDax1{*VtbvQ(VLeX@=A%@A5mx$NUOsK=4Lz@b0CI=SB1)*e(+X|5+^YIWc|h(EY? zJ1Y|*s;G2mKVY|zsd_+~!8-jV>v_4@QS=5$WtQ#d`eLd-yv*Zu-TqsT2=$oE%--)% z>5G4}Xmw1auAi6Jyg81Jm|${K1U)kS6 zK1k$?f$! zMS}jYBPe0{KYrH|;MN;~w{z3~r|efgm7_Z%w9J!|w~au6aX8_XvalqV%%J;n zwXcZSNbjy*lKa)L_WU;JV4Q6wcwuPB0@%5e5tXPN`$Eb;fBpnGHd~T_(ZoZ(;d(cJ zFFGgd5*f@|(+R<<=*msFinB@^-JTrcMr}tD<9Stx8qx1L->yehsO=4m{7885klHkl8BO1&g$io>SH)=o_TU)9}NzyS%#S_@C zVeXPT`|2ol&5oBOFm+C$qZ>gkMfz*jLQ_sUx8HM*^ zaUnPenwzWb@L(X^R5v=2P?FbUDGz5hp7cgmJl?jIYTn9tdOq53e`k{xLlG@M*E%BU zNE}&Wy4#8WkSH}>q%~M7<-g9ItwP*@&r|*?cFOm+)17wsfyY(H_H;F8ZOszD@>sIF zw#1I%)1{im*ZG;-?o8Y|Z16m%8v9j|BlX>)e@e1T4w(I-l;_V>{yq1jsYx7a=aK32 zkAY#R3A()@3xo#Dewv<;U`Hie#o*_Bv)!s(Ga1H?ezrZ6UI3nb%+7g?ksw$i8_q-G zq9X4*FAbt0@21Oal9iIKt5R7O@_sb8Jj!tmu=VVdR%@|4v71nkNwi45%cZT_UUU(1 zjzTu~V0dVlWeOTaL+=cmmD+oLBrwoF3nx0*oZ1BY?6AqjJhO7S%RE2SAYmPRByKIS z(kxBfty*V1&3awp%li38@-1(Hkh0cfco6;Z$HlD#VTg6O7FY3em6r1#GlwIY=)<$e zIeuqqd3yfEOm2G|Ft-oq=3>@&q}WI6o7YB~ImGqy=DF93TNa%hkss_JYt`DXFKV|w zwbmm@hZ?npaAdtHc#I8)Tq^CmRX@bk-D2A|DrZg~PBzk!)!U<4POatp#mK%#n;z$H z|8l+x!YyBy{{C%`ayacq@&cX`2oa37n~t~gDRj4|r!3k`z7mFKrO<9 zWE$m(Ary=Tz3b8AUYN%FY7$9%NpAwx>v$-NrOi_6Y}Q_;WcdRF0{#}05`XOB39T0h z;>6n>1EZ-{WxSu6on`yx0FtiC(7|#r-v~AQIgrY3vkGu@o0ZBpS2USYGBPs8=83#c z^uqmH3s|zl3+m-Myg#=PVP>5GnrmZoQ=S;$y}&Xt(uhNu!M&TuC935z5)$YK!l@$| zLv&V_mY=)ix5mKy^fLbbmR-05?(1wOnsWF%NLaKyu4iwo7|m$;n4sS_n7p4{^C_0x z1ZU=k8pQ!1SK{D$)xL@U{CqI*Hz4{H{S`M$~{V9!Gj_aFx~%7i!syCi{4E zeC|&^-J5pz_z0D>exqr0*?l3|yaBuBCSQG8izuE5;^RE z%%oOj{*i4Ro{@=7_G`Hz1JyeIG|XV2Jn%rxIH0-gs!7K1EmP&$chtjGsNlw4A53E& z+76$R8ReLa-?miLO~(hbp~NfWp;iYsr9r>Pd9?p1n$)SIOm$;e0d`W2lU5eRB{V3$ zz!sW=5xfus%4tOw_3gA|obEje>9qX$0DqYNzkb)B2F_>C$C_qG{|wvsS%813F-x2) z#P>Ub9G?^!sv#WuI2_ENiMAX$k+1;%J8JMX*88HB%WMYznn}8IZjtH>iBFNhr=Q@- zFJrz`fy;g}m@+5A!+R6pa)|jnjHs||Ll=TF3E6+ZCX7+yD%lTMBFga%abJNz(RDUH z6$fp}z3%SBS}lz_iM00z(}?^oGSFn_MEaIPfX=<>1>MXl@(n%GF`CLHFd~wXYBV++ zb361Nj-)H?;0`I|x|o_mPutqqyxg6p=O7I@rLM4RP04ck5&q3TVy;tx0dGHx=$W}) z8gqMil;AL|Rtg77g@&4u_DLo?-#wlNOC?QjUppOQdp>a#8A?3bZH~TPO$E<&I>6BO zN4?pG9tl#ir9_VfeptGwDvV(OlaANf)R{ys%*MnRTRIJ4_k?G;VW>!e?a2l1zxEZH zSzgAHm43GtLNOHgy-*MOK^7nC`w4h<$@ZUf+!sh%xxJG@w?cCd1ZN{jQchO?%9S$J4jr$x6z60`ycKKcRz0>Z+= zQJsl&s>Te7yK$z}o>IK!V;cRD4C*!Vk)pt3vv%eYtOHqxBQU3@%zQ2-`!&(fqWk;%59i9;Jnuglkwcl&&o+F%Qb;9re>h*z zG&P@v6#c}-2zyFzSZ;DbW6|pF?iTojk;LP9S7Fc>MZMW_{}tTibXeyRL)PDuva42lHYl!P zz~I8DbB<^jf%x684iX_Im3wb)3k7b6g$j@mP)lKyW4Q+ux!FWabZnL`F(*rkV!@(Nqq8X)g(MRuiRa!-Uh+m#+ zTje7geYeT&#ASg~373QB&FPmgk8{IcE(6%!T^pJFt*&1kfh^pJ%kBA^CAbt~MLYYj zw{Fsk71;0+Nm+V-Mr|~?R4@PS!*|O$2G;GBeJ`IESLU9{LHCZ2V*pv`T7qT3ji!6Y zuB)tqyH zY(wc{AGLU!g|)|vtpVqGm{icXm_(?Q+mY`EQ=YjR?Q?%M#gO0on}0_^*6z>zX^ET1 z9Ndici+6EfI*yECBI}apn3?PY&z2ICa?1RORN&pw9VSuAcfFF}90(OvvN0xo%ZLJ7<+tgA$~u$sNp8iiAa@3>rK& zsecnRIKI~U;raNLFas&--cA=BI#jtox=k&PO|4-*8l|ZfhofUMX;M0W$id9xT(0vDE`#aNvfnbB3vKgzvB zM_sj0sytV&vGuqv$HN|k^za$jglNSJdycefS0#BM%dWXLLQvqv%)vMAwDv*ooL_Q! zoLwv?b^#lCK1LW+WAOozA57fvp1&iYj4?{eL}{*d#J_kh?iG@ZYq!(~pAx~+Gx z#EXq?Mkg*%O)Wr%aMYebxu;Erfr4N2=w=KbVJ(#nFDtUFAensEl7NdSca_%Sd<|r_ z_71WX()@8ikOWC6F41q+P@C#2h!v)whfPFa4*%_L=TiP!X%n< zl>jP>T8p{Sp`q{*#f~+dnClj}fq?;_hLq0haRY#tO66&(p`>pB^YUv)wM+{n?0$PP zQqcL4`4ek5Wwnum?s~`1Kjeuh|9sKeFm%6CqsH81EVBnwuHPh=@FJBex2~=(IvNd3 zDLL&5_(Vj+({fkP6u>&44HT53BN=Ew0Of>EqhqLYn7iBAUl_`S?q)pBQ570bqysL&>4AvAk@OxXDA<+ z7HvHcM**;5li?*AGY#^M@b$C>Hvunh>tmKZ1eu;CZS;H6VO)+wGq*y!o(Qu(yPK@*9Lg|2XpFiaX!ns_BJQ&K`vSy>qlGfs}@ zK$SBsnWL-85}=*Q!;qfYQ`)|aL?L)EIoURj43;;?occ}7Z=FyEJ^pUHSlyn=0$m9> zOLo8W7HqJDL)PNNhc5Acw*?nBrn4D63@uD5e6|FAZ3~JUpDLFa%Q}0m1vDCKK6|Xf%fnX>;?nx9^>+t%kf7 zJr7l$vqb>LpwFVP9g#4473*@#^K~a)ePn#*S`{TUjo^sCXb7KPDA1Sf5TGO4ISA2O z&d+A0+SXC>uO2J_QBGPXr`O-w$WmnhZhp5av~erix?HKV;SIyuT;)>NY?G4hqm{h? zm~6ESOf1$q@8`0|8x$8OE6ttfgl(-I34MJ#4-fB1KMR)o&a@B#az+T=`ZDIeC`L6ryyoqhY7+^DN-`SyObrd}D2?zI>ef($&;^O#8tr!Xq}NtwKoB zelg{S04MP3!;|IG7MOc`#O6Jo5|V1N3<3$>6(}Wjd_OvisO4OW$t7K1Wu=?_RB#R) z?sY|}mzi9efgU%6ppC?NVSnH3rb|g>6B62iS8o>^D~o~g-e`4Ri4EEsld zQU4;;%2C_hij zcgyL?A7Uw|y3dQh^KMg@-Y?TuOUg*-4Lohj67#<>C{&ww)X~zd~Nsp&o5Cf;54=C17)Gg5!~>A ziv`>hMX+#tF5vdkl{g0QSg5jS!KcaJxY;=uhGB|q*QN#~duF94HkB<|&nSnr64Qz~ zI1>6d)E5;4DSSp6OY}?p*d`4kBSKv z5V2P)M9L`hS*%d7lEVtOQ@?YJALEq4hYYjx=(`^;vKncMT+_NY{D1HzpfI#bSv(0) zBS7he-b}G(moiIu&6U_nI?V-%1&c=#^KyOvu2ci+U6dsMp_A@uEQWc0ex4G7>yYs) zhcTc&!+(s83t$|Eu_8(#Re&xF2zhp5IhWvmjl0~z1*m7-3s(k8&@?%W?F}qJ_HjdokY@ zHaZnM0NLhhg9Fv2(w;`CMor9cVYy}<{j1#=cF1hve+Cdf`*U0ln7~sAjaEG)hhSh+ zQ`0!?dhR;Zctk&4P0rGXD=uh8|)dglFq5+F$y&QkwMBnF_iu{CwHdtV-5SVYgUzFwj14{ke0Kp;l@yNTo|Lh zkm&q(5#p267wU>v7DSK!@uDgl4!&Tt_d zdJH*?q_IR$U<4^_8b+4k>~Fl9&#-ai0s~(MDq`e?1sq@#hSOMbu!RNU-chGg;9)ZZ zQ9;HxPTj$H`WJ$D+#3ogd6%FlI?M>79J9sf&q(ZI6JmKGztHeP@A#ll?sE29>eTCB zH^)nVnG6OGL~5QA>D7GAKIIRsp$)hJ-896+{16u42D(|a%TW;)u>aQ$&L`#&1XD4f z8*c0AFa+@^pqnj0L3nhSV+5d^K55$0jZMW86_mr-(w~x&52G2;C#%oXi(Jv*wewO< z0tbxeXW3HqDc^EqO%AsUIDDXBIp|EMJopP}=xb;0w7B6#S1{51PM*{hof1NW&uiCK z6NIntXVCopW%=O@U12rB;^+6kpzK59>;}x7*}`L96PlUotxC)_{z)B?ZiBYo(&vYQFTjO>4v1ic5{$$r}GB^}(kO#BWDD zs@r9^2d^LS`$MxrD9Ajqc98egGX)0 zd_O*;e{1FZ<+1*<6hp-t9ro<>m!?8X6SI(TvMp(^vWT)ube_n4I_BlA(EkNW2$p zOV&g`Q)lC*a{u6jLrpGMN;eDMc;e+(9t^!odO=qc65)ok03xPjb{DH|Dhyt@( zh)y#9Gw7}?GyRLxHuh=Z--bp%f${cskWGd9#sDS}1D_b`8v$7GA%$x?`x=M)Ri=*8 zknVnqN9g75&>G4i5_Zmu%{$TD@BoTW2@ zJ`(V{JDQrBMs;rXMT1|@YjUQir(p#wC;tN&H5{Rr6(9okI9+X7 zsy6dS{z2k)HXA)mK}JT#$>|1wA;6CUbU3q$o6ZmTk{I)as_nMa@bK^DiD)N6wsT4p;KPVd^z{0VU``NQ~G0s$C6- zgan+KX>Dfab}&t2X+Q?e$j}A~WQj(CKtVm0=i|-gyvICghAuN(!p( zPKo&WGVYb607%kPP{c*@OC9$o@6Q3CKzclR;cuT+FWNFR(8n22j!`*J|_T zWoDl2>Jr+MO7bogYy(DdJ;bhgeAkOZuT`(rV2_IkMY_9d_W86rD6|@n{>F=MXy=J#(278U|9rOYVcql*K>w>`L;?V*{l!)m-7(u_b*Ow-segVX1w}&g5gL6%P$Lrf$euo`o9D|Wce1Me$ zr{qhgSDkyFEH|hHj{g0tXQ{mYK~)5f7aa%<7;4Jqb`Dj0FNVL1Hc%L6&zTkWt`DPi z7XE=llduZlr{5 z1a>k+DlIo00XG)dxajMObHW1uHl341ydydc*(YG2A3U`LX2W&j<&Ze8@Ugvw zAx$!3E7VsQc=dmG;}-dtu3x(iLtaz)7A8N6Ri5GO#}r66VEp090gUmnW3H;`6i^6k zVQM81XwT!4zpq|*#p5NtK3$GoRDmHgA;54%>$krBWav(Gd9ts{jN_ydWL}F(o`!bd zJq(^#AGICE?%Olq6dF4;cyC+7v6oS|AjHE9+n;C4q+>^bgSNLS@E4Gn7=cMVhQfIe5e)8#1Lw;No(k#ddlbEy+CaFa8a{^%OhZCPdq z0`}{LS*u`A$+Sg-xk5C+4EFryZoD`=Aqs}q57@4 zy58OOOX>uJ``=B@WE^v;5Dyxy5!L#;A*x$B12ZFDz2c1q)9<^m(1%&=3R$M3Cd+Ug z7O%gdG1r3WQk<#dg~fT7ljppAZ>csya2`u&@s$c! z|ISRkhYL?uzcNbyv-a8}YKa--rdH`?woEk8J4~9#=XQMr>d?=tqfc#zH^efpl&E>? zr)Xljq32H1GuS=bQ9deHe1vw~j3!R~v{De{nbV!kt5xjC-Y%X-(PWvMoRl<#<|Qg? zm?Poj|H=eXjYCAsQFFWLMw8>)`HmBAvp}SMn^}=E+_~+^%5fM)pY_Mp`GuEtxhIzw zlv8c)r9!XQJh4^5uGiz{$gah3F`*`8@Cv{Mt2^oQycUbJR?$1n=M!$LW=g&SvBRe+qtRW+Iz*F&sx|-=ir`sb95DC2>1x9jbd0cVv#&IugSCurun(Y(?P%_k3WX)CVy+{H6%_Dz&@AOm_ z%0)vqQ~*_^6u4ge7cQd+YDi(@$o_XA&Vv;e7M60Gx7W9a!v8*1;k!eaPk1~D`U|ArJk^>{4`rqPlYdw`O4IES4I&*y+KMIJtWn@-st(J}!pbWaL z5i{qTeSp>hJfMdanDkBaCA~pUr=CVJUsy~m=RO3T4EU@!;Y?Oja|uZBY5{G=a)Se_ z#VqCxtecI^>B&k{aA05u@^`;CHq^8T1o~5edU2`7Vt0ERz$0Q~t|1x|#W27$5xlWS z)dr3alCiR~0*AtQc~>SUFQ#dFpmLUm00nTkRL3y11kq>&3aMIxEnx84Y^i4KrNhp! zJY__+EFg`N@_1d&uE2T!J~#-4AU`+vvwR}!Zp#OP>`%~13UYEi`V!#D(9qE6Md7*t zgv!R_U>7YO4Ty)6=~Ph-@?8m5clI~qYvN`Cf`Y1m{hEqg-ghbpa3y!eg>qGf67rF0 zC9SQkF}e5pGu?TrOp?Ye8_H5{3JR0q!*G3tnVFfm#7yEBNwc#g`T<`O=5lmEnC!MaKb1q0Ph0~I%PO;sVlHZPaKw{l{)As@!`{__E>YEcp1|R2;~c1 zTwECBv)|nW8yFY_>Qj?h0rc^Bp*)#NbeGZ*@uqDW+CE2iZxolPl=Iy;b9yc1iE!Ys z+frSaYO-O|+&6O$pt}9kt#|u{gCm`t8o?vCs`VczNw*z+u=B{-L+zuI%{(*4eQ?EF zxPG`6JKe?{$>yVXSik7}C5KkB+fos4UTFA!7$^s4GcN69%@PXaIwM8PfqE-WP-qiVMZYP8h!W_8FE^&^K;D7*@jiBM{0TP(Q+80Jz4I z)Q_AUNJ3b=-iP>x0+?o2^|Od-`qfONyE||KhuJ(qAD&a=X9{4MI=|>@T;NO9p`zxL z`+-evba{qsr+4wUl)^x}0ly^5QrLlpFQfR~Yy^RfO`1AoE6nZRlKwxsDMpc5>VT8n z&C3eNaz(DHKcq$w%f(7FZ#GerK^DDit`@`g%z{-#b$J%Zq0X^cD#GoafCZ<^LIxBu zfK0`51BUW;I2d@6`|dOzRy$Z`@tuq9Aut*CcR5|1iM7U1RV>wD{i#gH;K(d)JZ#zB8f%%B7fU9Vc6Tf8auP|zjg3*n;*~X5 zuFJo&&t@kLh>WlQcKCDtqu3V5$24EYGOsVW>?3mbOVfd~D6}V$7GkR`{CVpG7Zt ztsaP`F^SfufGf3@0E=rjHJ`md7drrb#s{waB3}CMD|kU01QG_}*t%lhJ2G!74f?7r zEOtsOq<}MwK0|Q7idQTpcul4NZ$#qrB(I>R%+vUp#?e=$(a}sIm7L76UWEb2Q8M0b zFaU9cK`Tb);`=X}zG$hwOcW+2?5P4e=x%2#)#}WeZk`gQ!QR7M(21P7Pm@e}t(@fO z#?$lJtQRefg~i=Nb{M?@%9>3rZxDpr7lpCotC`=Z;tZ_7jm;=AL{(BFHc|ZkYRI zwN$-uJb9+LscT(%c1= z%w+<_**se?Q<&86j8|2L|C|Oi{qZ(6LIn>GTRV7WF1tY|U7R9SRjc8bUvd*y--_43 z_K=^o_3_Qoz3xo0xKr(b&Ff34)uQ8S9YgyJmbACc%wWf0v7)OhI1Fp7#WNJ_|B^`V z7#i1p#xynk}ETq+3n1Y%DgXaRB^@ai zDUf^!f1g?&^s$Kfex~|rTF@<#Z(ZghTbpLn<3Aug`4ka-RD z=Vi!3v}$<}zw5`Xbx=H&Y(ukK>d(}#o!PaN4dzB>&wqPRPBhHj2f=;V`gcaG7;Ja0 zN;g(&4MZwdkYnSU<;MH@CxZ#@J{PTHh2qTrS_fFvM3NP6@c%bxbAt84OwxcN!4$#G+0 zk`NF(xR_oL7I?Qdr9nf+(~*~~q|tSeWZ>x|<(u3n9VHEIVuL#yE+ zj9vDRAC$H5M&s+b?2SLa+2e?Fd3`zocR*gBzJYL&GHXir)vFZc#R#n}CB4VpYR+_P zRcYmu>zj7{TDcY`<2(wM1`$4T1`!)oIyE~n%}%bzNk?tegI>QJYx3#tYbabs9(oHl z*i6*SR4*KFk%>&FvbtQ@R@Xh8(hLDiZ zL^UjRm%V#Z&%@Hg-O^f5^n`7`kT{Oa@9B_VBiaog-jI-xkdcvz&7m<0P_$}6j9eTY zLxO`_$hwb5G~29zZFqPhP=>+TqT333`Z?N|IOE7_vXfnorXnNN<7 zXG;wcuh-)fKj<7WzH@Lm1{Sc(v9T4-*=U(@A5aLtU&YdW>ElN-@`XeApedgQ zT!R4Y0CW?^9fbUUT#Z#~r3P#k1@FjmD1x3OJq&1pzhy?a-bNWo z$$W5~fx!x}EOwcf_9>jK|A(1jn?CocghxFZ9yg7#HZ9Yh*%r8#L9`KopWmxGg?d0( zOrH#i`V+&7W|mi)xA`M~YrF>8N|BL~FJHdQVNTUt&!e>ZbRY(NU$q+YjACC2-#rKJ zWxVLfp0>brW|K*g*^H<=JEz@g`5KK1GkK@h<_xka;mI$omZh|#j1CeOn@}qvm8E8D zW1|{?HzJ#XozvjB@q`v+-T?{|`AAFPZGJB;9TpxgD=S-FQSq#D;O<8*sPnU{C<0D= zYR93Jw>PI-Cm^DySI{^6CaOd-{({l2yKZ7?>Ur$0Dc_EYd|3E$tX{fw4FrJ=0Ts7n zN~A)(!X0=x_0heA{qxhyy4k`CaPoRxlrwcH$l083ODHX=+K<)CP4szT(}87ZpuC3f zm5mDg%|%*V=OK*8tQYy|`@$%{MHDI-$)=QwEt2}D%NJs5^$J$WbISPCGD~v;?eUla z)HIRHk;-MH^ux!GLP8P}U&^YcSyZdU@2=g?_}o7}Zt|v`{i21fo}ZqU2ob(ku4d-u zh7VE?(xxU<2rkgBb)b9_u(GnE*4SMMm~fsapgt)9*})>#j?J{&GL?eC(c|6ECsHhu zn5GLmTSq~ZU|NQ`0$7N|^$M4fgYG{5Z!7*{llDFgCG$+Rw!#Y8009SrXZ5Q{xDdPD zAF~n@jV0Qf0}u`&mh;AdA9`3{zkoEmLE1O7dQ){GA-GmJ9QkFQBIoTC4q&Fq6}lKl zdcBHd=1!V2n=T<8R4*Bs=;;YIMlcN6oSUA8X4E|;<`b3((Gq$F^TM3)<;x->x`{&J zg`Pws6Ly^^bL>s&pFfA^Iw&atLdXNhA1I_ zY!zn<0+T!l8Pyfz1Ld5*qwVFwy97#Jz5sqgFf1kpyNYWXDwY9l8Zjc*Y40{;x^-#3 zW53JnBB&V#E3EJiK2re5G!%Iff*_wKK$7jikmZrUDUbj)H{ewSy08Eu)H4nfse}Pb z0}V$BKI?u=_WcpieYt(!(+2rGgGxVA6r)F&!>~Y56A4h@2n(Qqd$KSP%6ySFeZVW9 zkVK)7ksyG36oTMp1mK;ZuSCQU2eD%~a1V{JuN4U#H+W^iqo7O>6880BYb4S^(Fb*c z0Z@EUb33?-i~)H$UnC4zAcli{D3FGy>4TXfFu}Qh4spWbL%2|A|D1-wjDQDaO3cU1 zpZ?wfLoHy)BK8gedN=f$Q6vI}vJE>qh$bjwG0{ z0YU_vOc_0p*7fTb9RXXft-gK&b+~eN?XKc>T(qYswcYM?bd~kPb3D$z&A13yVF4mI zR`z_MV53aI@8Z!>hFvkSU)YR3dmsS_g}Pd1-%p*g@pql{(P*G& z05a4N_#UHV$iCykhW0*sEWE$;aC$OC2f(tPh@UUQ{oi`u+l=RyH@YX|@lLx<7T|Ah z&em0yavN~<-ky#XZjCYS&CiT4BzLV7nn%K54nGGKJ`;&M#quRYzPw3oYXJdVR8>{p ziaUK8g$|eY$Ki#V#G!<4U0qZ|73LFHRpep@AOPubX5mq4;IdE``+}vbb5Z9_ddOFZ z?V<<4GpD`7U(=VD<0v?UAJ1qxoXkY%@_Ds}K*aeuL!H;|^ohT}lBp@R_k-;19o_AL zcaH0U7kt83qHw|HGDD{#e-zNMo57&l+~FiGf(4$y1MZCW_SBlXb!_zhhJ;kz1Z3<% zL`42I!;^B;9#9n&RLeo5Y?(%-QiIJzHuQ!@$wQS_dPbeow?q645-}yFXLPEI^r|)& zjLqY=Q$-XOv(@|#ch>|+F?1V2%1N#J<6D~r>Z-4`4$lu?-7eWXl1|3)1;ap5lK2qx zp(J+-I25?5syG>$$^K95PLn( z>r=_@n%ce9sDi^WS&ldChIEfFgRueL@CC$<7pT-MkxYfah6TPFR(1kRK4LphH1?!aLV=2Rj&nN|z@ER%Izzl~(k}kJ)VdCwf*-G z<&$56XBSJldy9>`^R<=!ujrJzLwIW4&w1qwHSk`O#xov#*dCXhhu108xYw>v6f6@) zt_T11mw!%dzVk~$#VMPq+`)A3NN_aWXqZMxXld!=tbObJBVUds7TVi*(B2MA_- z_Pr0P>$VcUw?`~=0^tRK2_)JolZ*wMjM*a3SVSx)+O#{I7Bd(VMFy5?s03KY87n!1 z!2(6ddhffIVrZQ1xu#x;!(v9Dfr?OKqcHpbl}-Xw;J{YMe}s<)RQRaycH{pmd|27X zTm@v{tE}9B9^qY0-q&L%G;LvR9h;bF5|pwwB{rMPQ+#)~)Lf+HwI1EME(YFx5>lJ= z_Wt&S6y(3fmm?b0+avXVd(+NIq*yF0KnLc9Wk47{=0EZjEK&kcgR{W6XW0K9_yU@z zp`Ri8j}QX&IEBik#x%;#e-BiU0YRZMor{SX!Q>l7Daq${4F9;wYKEDNOprS6D=|MG zC+B5X7y)esB_$;nC#O^rr#*-Y({`9)12Mye^}Q5|>(#@BPvQ60sW2M>1bGw1j44I( zYy2j$-F{a@&ZW6ad7_PPy>9W2fkJ755H`CmI=#5~(#|1+)Kc>;Y40rN1O}`)=J(Qn zl=4%NWuPnq@GFQ8Yu7meMz91fM-wBXH4uZJeg%}aG2ngse(>!Z9vagtkd&XPly{*h zrc|u6Ffd>Zu-Z!=C(^(jzSQ8RSgg|sSh0kpoLE76a4=}Z3G7R4R?A7N=@NbLkkF72 z2(Q~Qpsy*`s)eTJS12#gz{fCv(Eb8ISVvPys}yN%t*wn$+v+-Vu|I}V7d~gyxlQ%H*FSa_%tRxaz=o~G0R8bgl8nbu zq-Ay%pS%|YXREA3N~Lq3WQb%*e7V9s0_vvpFRB;-SN;I>UWTvlc$~MNVPKTl z{SwT^$cT|E-tb~&V86L0W(5ZZHa`@egx0~j&HJU{( z_Ek761tZw%yD}LG515aAuZ@gK*x{3sld-X|hOrRc@SK^_flGd|!L3{>fq6T3)iC_M znv(+$8=EqP&%Q7lxB37#{QA8SbD&xz4--!8ydGLt1Dbf%A-*vJ;lL{QDIhthg>fOb z)A&@pjf^=Zi$F#q27S>R3#0Nbc!0NLHXTfY!f1XdqfW)zzY5LZNWxhE(i_JR(rPl2 zF2acr7QM)M#S7e~P0H%9hy`GCyzCJtT4O_6E|f6QtL2O3C@}M$q3B7qnRQq` zA?EAvEBKzS7@28@^YM||2Wf!LuR+f(P{=}=s{lcv*BLUfssUr8i_Kr_0pbNmj?qSZF!SW zY_6siedEMF35u21)zuYO69qaK7dE(RaD;p=*rybE`Sx~eEGNtw;S2yA!+_Yy#+5(* ztKF>00I5?e7O@LZnm{AGF$CJjU~vq$z%IRX_3%imZuWzm0CFz8mWj%9xQx4b3@t+eo$ zU4Z@lM};GWs&K-Iw|~q3S)qR`tp%<0>qsj8Kjr`P>&M9D01W`hOboe2K|?cQ`}*}O zpt@mDElPUtqXKS@-~$!QA|@}3Kr)hDj@R`v2b1`Gj-DQuK|}aaIWwn{EIi20>oN&O z4C*I`lRyRuavs3U1_D!^lF8)h3uX$-w_sY4k)T4C37M1;1!i|j3$SlK`T2>MR@t-P zY@~V*Ho;Cn{o{zxYe*%G$T8()NOlselLlPu?d2CgRY4!%3{FbE6*MBol#>>4GJy=5 zTaBd^(g}Ir>^tvf zfUGLEt<9mn=*c8C*7=>m-%#L1Or^4XYD%0tK!il65rEKnG=MG$L`EqSRM=cxaZu7J zDUL{tNh2Q>GmnlP*m**4T8^Z%)8w%X%o-39|NXAd>26P1Zz(S`RO!s(z7qS!aTVn5m zaE@YwpKdt$Bhwoo6|8pmYzZX%-|qMMj(NA|h93VYt}ka+ktJ%k#l4dM=*q zP81>R%HBJL_aJqv*8A?Zp>;qZ3j5JRgI4A^wT2lk+swnw3Lr}}+K(~gVh?$SqWXrG zkznE1%1DID+ed)|a~75d-Bn%99#tmSEuHOiRr`0!0L0=i9TWSr@T**v_?UZRT|wR( zfO>Wi_vu>Kg3DY#Ch>_J>KbfvIr&N+Lae3UJH>g=N!Xzc0?1r= zKZYLezDcUY^18=Z4)Jxnjtj}6^E&NNRF9us`n=fedM4$Yo>g;ux9M2#m5Awit>-YR zsWy@6*R0z7CQjwR5mziJ;`AuB<|ZfMB7JCPdUnEWcZY*JSMI26I;>?7zRK&tZS^)l za`_vZ=7sXkhKUhF0p1+)qmyyz4ZSKmOMul8y~l81Hfk>(<0}W$ygX77weH)g*8CoK zB$>Il5AnrH%rgldJ30t{JXHNnVr=x}$TP9~Npdyyxy$=^2*zM~gxoRpJ8z z4@u+;1jWKH5Bw-SXCYrBDY~Rpz%^C`r}-)Z1bsBEB!D zNwO=y0;=mJ zKfG!?yM7h>82&uZ+ARnpTJlBwGRg5>k4M_g@Pl>E7p`qn3z1ZsgQ!8`MFin=--Hl0 zt0nKdBvO*DpX-2wr$mg|>9G46nD6fa1?zs1HSB>DacNDANfa94@#8VoeoT;N%kjWPo5QT~e`I7E&EzFkKDR=8SN1TW1)yc}-N1Wf-U$KHbcD7E5t&EjNxzxoq#-Dm9(ftoxMn{El}v!r$DUNa$eH6=!=b zs;HH8T_OJTIATmep$jlhn(6Af`qbHb*juK&eR(ar0!%(nipvd80^BcMCWM-R4G_)% zd(P9WPh)SX0#Eh##9BX3Ivi#MBUDTg@RVt>z^ObWql>a66?duc;7fZv!aZ2okgR4% zt^nYjM4HMHJ)z^V`l$ePMk3S@v>PH*8+$KJwI$OP<|NMrCe!y1wyLN*@?Cb7Ugr;q zE-!iYwueMm!kdYWQE&S_OT1? zY_xVN&5wo>3hVc>U8yofwrV14ZqKC`(ozoMKVLk$=WS`rB5M5r}$CVTK6@%P_ zCYGkY{f=$kukkf&WfbRKsiJza?ztIw9_(IuO?2!ZlIi|h0f0149NP1hqlLbo7Zj8o ztCL(wUpA&XN1O%cLy#9K?Q68^90o$f1V5>IgoNDPHC@RYDIYn+Qs29yJwF!vh*j^j3#B^I)cs6(5L2OIrKzzov{ZpVDV#+Yh#hvFy-Ow$gWqI+E$(OFb zq`T!EyKX1W1weNlD@Sw$dp7+@Eblg6{DLA3@-e}hG92$VAtU(+$BAyYqd*~}UGwoQ zqLF0{*p_TyhB`~foC0I>`(xPo_|N>!#p`*bl4QayyU@MJg_Qd9U)5&?`lJs&-MoMI zWT;&L(eCci|GOtc{d|-!Nth4F;Xb<-)MDWr$>S8>iot|4luqT`s_O4Qu-w<{^Dnfm zT(!?RHyv`glC3rWN4LPmZGYI{_q=u@dk4=7rI|sKhD7jUGLeC&{s9O7F>WK!!GUsL zLFIpK-O%@7uP1NIDf&}QA0&{B+O=-=T@DATbwYJK02?ly2|CQPBqO1Q16&av$HH$i zlz#+v608mHrViop6%UGNqaeQYAH#E`MBa>k=v zC}$KkX+g~I75WvLeT?#h2ghcjPAmP{rK_YGmsss@I#3vJKz0m+s4M`=HlRC9b%ivZhgHz z00GB-52X@o0@IS1kkDhb3mr;|^?zaYcIWTM&?uefwNc<$0OWo>V3VVgPAt%>9qsAK zvt4Q`IRy5pii%1vw?dANNVr)M{wMBh@j#?+6rg*hnG4opOyCO&3$3lKIjm=mOiib% ztToZ(+s->fo);_SVOfAE`2T97NDFI#rz}ydFBSt9U#Qd+v3+fcpj3&!aqLp$h zD=M7q?7&W|803ktE1vZBcW@gaH1juv9_*z%+h~1KsyEZv7k#;l?Setbk$|g}3ckJx!WUxt3 zpHFOhD0^c#+0fEZz&(aqC9QIbVxyELMmgf};gMek_mv0ChGsBqPl&hy)1V2UJ^y1?X48gB34MOz2{`mS zg0a)i0g&kG__v|KtTXK{*<6{61=O}A!6zmTzxxJwiUheZ-f31fBGD|sV}<^>*vp`f>s_Ju00jnJ zygtFeR-Ng9li2@T-UW_t`WuX>M}HQXo&i|;?4>?YJb%hSk^u99&mRbof0o!csP_&q zk5TPEkuLpC*770MOhF+E1=exV-}Wm|OS!N~mVS$Xv32Y0D=17(sr|+V7dyDRXEN=z zGszIEU{Z&^9j1n#ZAk^?IOfnz(g^6;Sk1S|$f;#Z)N-2l_1SLQp7=6pbc7WJG*W`(E=SmCP`?uji-Ce|5lp`^cp20A#>QD zUh0nmy=L;l#o=!+Qb>VbBZ4H_DLg?xe*wf{v;Sh+XxOlLZG>EYZ>cvSuPUyv$Zv0qXU;pvl zJ6|nI9@l+ga9DIis>4JixQ9{petUac<3cfN^0lw8@9_@FbNCqY<=tIiO0S3W-`5o3 z_ap5vzmti^uyb$#xmfk7sk++Mi;If@XX*@SlRm*1lp~or{II*%a5aTYz6MgqftCan zKJilva7_C7`5C)Zy&<HgI+A!l}j=|(={6ai;_-7K~i2G z_Cg=KEa1mAQunTvAxAx*T>1$nL?k0xQNE@;tTKd9pj!bQ)(bpRZ~`V!g$w>N*?QNc zFD=6f*Pwh9$&&7SvNd;bX?69_#+l02Wr<4onq=#KBxT7LvzFM)E>)!vZHUB}R&elu z?rU8y?pNIziqu7@Sa}uZ*P{v*PCp8)VxyS7*Sh1Fzf-;Z8HV_@tLb8qw$uA{u$Ml~ z+Va**?Zq|jOv(|9m6W{NI&t#buY0Ij-WGgMVx1mbto(;!s^L_M6_j|~7K(E|&0jmM z(MnVt+N+|bRUa&Q)gNQu<;RAESird!{d5a=Gj(pk$K>tkSnvIUqWZS6`s`G=A_r5s zqEl`HiFv}WKl;7K$f?M9-%Qm7$<0$?Wf96Ss>54*edB=l#XF~g6FxncRRN+m;We%N z1G0I!^v_kF%L@~7jKjfVz(9Y>m;zQRIO>}Sf6Mlu$2;wX82+5aki&uPFj0;S(D_@& z5Q8aI=c_L3?JdvCdk~kD>>psDW#pI|bL8N-FkfoQ&&#_-VRZB(=A9-Ws5e}0k?HF4 zZnh_XO}!D1Nv?x(#E--(@I5`9m;PK>_;zcp;9GhboZ=(N=QmA;?q1Vf1&?%3AQ>#F z8>R)RUSEdZ!ND6LDaELY-s-lUIR^I}4ShkCl%_}1a<3#hD}ofR>Za-uJWuK!q*ue{ zRnNA;*0IrbIhXGrL;sm$&+Yx-x|@)C-|eX~JvbvcBp~+6qD@pYkha4_okv0Go`Rm9 zl=0whF!|wUyO3u7dI)!dh=?W74pNif=1a!Y5Lq_Kk!seSpK-i=S;=CD0C$F!n_Hmf zz1yA{%1?dvur_ADWM28hz9Gic{(*B}RYRr0q8C##qv~w(GYtF>Wblz08;uXwzwQdE zH%`@S?8p0_mZ;V~WJA#w4K1_l%w8qqvX%b6TyWltz5IyTnv zcQ!-I%Ez!h<}_<;yyP|N82R|<$;s<$riI0FK4(#OdfiMGUQuB=I6kGKT68-v$Svp} z93BRtD*LZr8=eK@%IeMKAw2tbx5Q;-x=%q^;1_Umy;Tv~WIL;IZ@aQ6Q|I(+Xjx4C z0#)(^{Y*-GmzU}^+16U&%xLw~%DmxJbBOx~n(D(m%;4P{_lpEWLyc8ctGtq@@AENz ziTZ}*^>nUe52}dz{THfSnR6%|ByL$0B_HYYr8YTIUX702^w$chCyrio5%G@q6Mwg@bj3*^7M*7E-+f|gi8>gL3 zMgI9Xbq>?awUqhiIF2lZOwHr7gEbGEgY8RORC!*ZumiMCPFeep2xac=ATbT)-*x$m zHEglHo-t7QPHXkWgdd+^pB!JSYxcpLG!3gEB7PZoJ~mo2&C9}CQIT#?os$#!^+{|G z15JYC8LjR&Szfx==Zzoi4L(0X{EYUC*}VOBN3;6A{^LcFiSj|J$gf{Lj5@o=rxk3u z?sG~?Dqi@QN1j&n(wL_RttqNO!l>i`6@iuPJ}{UbEv2^}m`6V0T;?gXAE65GCRssI zkvSQs7gna4S;DMKJ*xiMzX?!F9B`P(+Mbanwz!=4V zW(%?J1r`3{ zzL!QUPC(NIDxj|Po4sYPd(5IoyFGrc5o2yc^ zydthos%_ud#=%d!e#X_i3PnX#R8%B| zh0)v=?=Q?{b7P5_n*Lm0>$h`RhhvG&alV?ozcY?mEPW7LU@|x-~v}}7Nvc~_VzxfS?eald>3b7 z+Y1Gedf($>WLRq=8X^W$Q=C_`sXl(#h8d&Y3q)5GTpQ-IAq5q@(1%s{SMHec?ew)G za_HO*4P9)m=4(Gkt>z$FFCuES4jrRSBDFT+FtE+yuTlMdOP6y?ulT!-aYV~1`^>$# zbf_+T_3V%~N79@S)mG_&ZOU7x zcq~d0<8}7H{Bv1W_TuY~jH!jgm|_p_wBL*jpJo(_Jp8=H`D2gp7VX!2n~wq{C42Ko z>*IM&u*?UD@H~9uk_D{dDi1!0{d`wdb(TF5AHe_hIwWd{2ID>$|m_($aA9EQMsZ4EFO~CMA>I^+5K(>+GW~`DT&541!t~ z$0){m9{O0N#=I^1gdfDnbGIZXL+@Vm$yDu&WFb6TrNr8L&!J1(64%S>FUdwW>}YpW z{8W0jYHjxuCjY3p{nVnh^I7HAH?Dn`Iweh7SIL?FI<`Uy?0r5i0;j2}WbyUYhT)7i z^Xu%%lsh0V#KV=GhTC#^daxo`TS?CSOo>;dS3mlP3Zs=dd9C^!0pkpx$<1haU&B-M zbNf;&%a{)we)}vrls8efKUo#TQRxDw>3@Dd4a>8BWR#Pn#Wnl8HYTo$gXKiX)UoDH3D6>@-~i;r{uQI?)2+U<8UKX`u^zet7&wmYTo#&$NroP~@hT&Tgx|X6*-jNo> z8GU$Y^R=dqp(##@mVvR@eI8xM896h{=ro105VG`*@J%U~-kyf|84K&}-5tT$<6a-1 z2tYIHbEuGZD&}~%?2Ljbr2o}NL1%;GxelTj);ob0#n{*o5hqOLzYT$b#}|hwt&RLH zhxSjyVBiyjVGJBud_`IQcE#{}(6li40E2(aQa~kyAUpXDRG5!}j6`ZBE0CK5g8Nn_ z4MA|3E&zBiGBToF?}DR3%;jL@?tZ;cuiVV#7cYt_7de&pzECtl)DSVBY(qX$Vb&miK7U61m@9pGmf6MeLoQx8KWpUueF{`g3A&$<@0N&8CFjDVo3o`qo zz!zme(q9IEHfZ%69v%YvphMV{L_AirVUR{>+W##Q0;xCX{F0eTp~0M(kRb2ol9AMQ zea~FiAy@z5Xa&G9&Kb3>Q>zfW3pZ3y_Qs%j^sxXScMp+}YlKjDP?fOm1#&@*{ER8umKi2_R5hKUt)|DwffLhK zZs^7At(*MLq53pY%u@X?pFz;-<*Q6Y+6w7MG`pD9KKN?p zyLYf*Y3b>oOgJjsc|5OKr4#n{_6S%?>R=)Hlqb7|Wy~|wWb%$-BaG=%p4tZaqa!1c zGy;$;X09(fqj&)loP!NmFW@>mI~#Ia;pZ%v6A8vAZxN>NY)kmh67Y0>reW{FIPG$n zk5bHb{yLRQWbgmr$W+jUaWtWO;vXgCBU`pdH%lE`fm*Mco;838F_(1)@Z5@!-~0PA z8@;S^77KN3dppO;E_Qa`!yAChZw!~!+I?*Oq(B{=UpssP@Yz`f;$Qa!ZhF&Fw8f(k9o>-oCz!OZSI+ zPX(Ev_mFv&%YHy!Jdnf{t>Uq4^W~S<#z8*A?s?>b>W|)tqd7|HV zRH?3s=4pUVQ@WG^@b=zDMGj^HU$sBNrcpd9uhu#s!wgW6V8M^2p>gcl#1dkVCg1GL z-(G6wUvlf+9nC_e=5{-#(9M2>%q^YsTs7*+*_M{ie#bhUm)hM*mY0`TLlD-yJRGHw z%!?Xkw0yR1mFeDm36|?2=ipy3XxQyLK`-ZErw66Plo}+5ZP-)SvC#702s2CQ%=JC~ z43lca^R&IJ_tMDEMZY4STi&t5Wa8{);=4cl#P{F8p0<%^C*pR>wc}b$?+R>%?hrm* z7y?$4c#4MK{|HqJL15cSqXpP}`e(N>Lj$`{*c-OTD1SC1Dj;zuI^;H~{@IPd%^1WG z<cbz%w)_`ePSbW)$` z0@A=Pravtj4+Q?6*>5OBe;fqE7+`b2H!wrP{y8yqia2b`m{w#&C~$Y-GU zIhbG!4(O=PMj3GtHBYc}eHcAVDV)*}SXz_fG9$1~6DR^sHIu9Q*6AAMLYB0D9PY9D z7##IO=ss6aSm)hOQQaY~&!2y{+b)~CJ2yJJO&|X{c(L6bPX7Mt@!@0R12R%l0;BYU z(dsZJMscxVnY&yYLmWIAcuI8@9X*%|U9erIuaTJS6}(fLB^_^8QrtlI!*-XX9XW{*D;}kdHg@~r>ab>_I^_Qc+f4ax_#OeJxE&)}n2yWsH ziODS%!p6pC$L||6iJ&hxH@8;%bD|A_l2vzcg49ZTX8``H=gaYz4*j{iY-TJ0#IIy3 z1$<6hT&|> z5XTVms5}pT_CPL@&0YsT=czEMOr=55+FCx;%h**S!VD%s^zLeo&X+0t=IqM&BNm>N z(evj|7X_p)vEVz6VD7ilY}q0(rUMEwlc6EGN@7U*I+~DTj#}2i*VDyR^5VGJ;N=)R zwxXrJu6>*Sv!lEKVt&s$V)a#b_j=;?1@p{SoAeF}^1n9y2&+wYYfB@%qwQ@Do)^`+ zn#Bbd)m00Wiz|&%=GfwlCx7l7rJjHm%@Ck?3PLuRz52&etl%@P~1_ zJU#0h(Gb+y({81_rJLJ|RtLjya47%#2M%!u@TF}1kISAe_EMJ&vI6-GO$LJ^eTcgJ zb$fLrQS)LuTU+Tp)QdL~1O-hCVfn9_cG^9(Uk(oOl1xk-WMn}&p5LB^zWonHVupchoUS0xzuM6|@ zE+YwK)jG}ah={(=*T&;%49m5KwG&lPOj$c4cSrs0F7x@kqDDvLJUpYr!x}lL2cG8l zsa~EeV-E4?l(Ks5&Jx;Ufniy?NijP?YWAU1lzYj;)ET>ZFG!-dP!031=Uv?@hdwAsTwN%`lo*HR+e(fKOr_)T5 ze@hDwmohV>*!_Cmi>Fa7QLEB&nlDk{=Y;ItDbBVSz|GxK4iAfMM(PXB9Yf@Y(>W9E z11IoU5avmjzX>jIWKU<*r`2wtu$ufl8%$r;&ThOrm3&XBDZ2^%0aH96=Yo{_ARKe6 zlo42*lu5v2tB>c9z)yN;qLcU92Q0-ktTw}W; zprt?80o;1XYfmda@15z{@^&ZlN`&+Ja1o(br7!zwzah!AbgsE}vn#ul`U%in)PVNe znA2fit!x^tcz<2a?k+L}My;5!AU+{6!pIh{>)(bLvtP(I~PY>u{Pb)`pIT99cGD#u}fvBXJjPCZPmZvQi4 zhM5HkzPu_`)<1_-l?E*F8^V)rqNTCPF#*G=za(X;W3`%vW}I3q&Ver98^z}#(YdfG zB6aAp2wiE7|BT~7^EM@;3ZT-)8BXUKUB4Fs204OpJ_EdWXR&lx=sPz5*H5X%xvFY= zVx2#%G9lpOoKtF<5?3SZ;KPFL11vd_piux+NDKZfzUgS-xNSZ+1RHo;(lajUbv4~? zc3&D@f}m@`Q*%0LtHb`FUGIJ`cxyXFsp);3xH{anLWC0ceINdbVq(LI3}K@ zQ>UVmbcfBjr>SvM-{Su?%dz%DP!OTlS!xMqsw%b7L_Ac3cn7hA(YYvTF_`073CMpS z5{-;9CD|=gj6o)+5r_Ln#N+zKi$QHlE9;Z?f-;-ucD2<+%IZ zp48U_w1AxbAAGCkv|_UOF$#KW-`jn-q=m%HUx)B{wq%mV-)5Y(TTzOe%$J^_LOPJ;osmq)u zlNQD+^E?a)o#gRN@eFmC$DDg@7LbhuO4r79@JNaV!ost-E=R zT>3H*%p~`0-S3yLI+MVY^opehKsFDX!Xz!+hphL_j&TkB%l$ZAvYvH6xQf;D>|spM zDe`;ia8+E?)He%#3g$*g-3`2z&aZkkf7ZvJN<8XIJld~N9e)ln>`u=GI0omU3RWEFQ_xjg$FmVoiRI{CcJ1Irkbwd z^U2>_ph*~pJq!V7IIG-xvEt+7X^VCd1A{&lN*XN^%QNxn%FCRgtkRMGVc$GRdsf1e z%YI$>bhc2+i=RCMI<3P!u*08zvNrCgf88m!jIReB(c?ke^R;xK5|Y`vtGE69?FYMD zN%>fA3Ppcb9RXTZBqOl!dbTTc#zY$#8MzB_7%s^kn<1JDFP$_@4N3ZBL3vO^v(3s0 zlLKE2mcfXJm-m(xmwKcTJXP>)bZrfH&`RY`Uh7+Hxq+HME+oDK>>nulZV%L-+5$*X zryId}b@fQom+UDfMoHLppvA4Ub#2!g&|(#CT}b=Fu`h`)J(w>}c#T#NgIz}&{ARjD zuPnw#XZZO2jNHO(G=qpBapK&OxiHzju&<+sk^QXPqXN6`I_qcqXr8mz0;TCPrFj5L zmCUNVL*a*63I{ts6;f4TlmvX*M7c^f@fn8t7}sk7Q}jfot9fLZS0p&e++Dy|TBHwr52pFrC3yLNOI@Mz zyb`IDDEdS?3za58>&452d91DDPUg_FrfPxBS6g&sc2PLA#TmVq8U4rz=-mjkF*Q2L z1CwuMn=s1gb|w?^aK9Ii+MpirjKmdP4|$wJ!) zuJWV&D+X1?AaAr8mW+_bEehU2-Q#%17zhvK1AD_2@PF6RHX85C!y&v*;&>hMd!Np2FvVjsd^q* z51F$jyJ{~jBg1A;Fg!2qRa28pNUswhDu3F-aN7^V=tx2QyW-ciHa}SjJU&6yPCz72 zk-6DI3{qNRCAGbiN>K4#g&6QJe!HPc5apBiSuu&OLm7@OeeyTRe<;e|q+=wQAfH=` z|H>)|jH!EAq!JfsVXu7eYh_rW9m8bfgLJK{9`Vssy3%j-S)m|2<#F{I3LE^*W;yQn zG*B;gcBr`d!VMKJ@bBMDi1{QkY)RcQ?6Hw9H*<^ARpc|dY)Z{0B;+}LQOK?hBqD-G z4mKPH&$)g1f5%`3voJ*W_`3S+&|pztBEn7;%sX|eQIXT5faTcHz0P;CoYg9mUZbBs z{Z%}Y*B(7tW>F@2s>#qP4N)^(CP=#=+f^QJ!sZw4y>jH%Qd4%*)4Nl8SxieQET7;6=69F^C)E^N)$ft(U$IOwm)h%^8yV?Ey zo?}8Zm)~m-i~Q0xksKPp*&L~wS1vD;ezW2xKPP2qp};VBd+n@Cq{u1BNIFU^RuByg zSjDh3C)LpR*iB{>-KmD#P3Bd&FuJK1gtO4H8Cm2zQ!oK+w4|-^?%6(tQzmOOYN;I$ z(Q{%aF>1(un5lF%>f^6203znUi{O|4!KAox#o(@1Xq1msd1;|kW*Gp2(?{Vr4&B^y zuO=jaI3QPt4JDCOP4?|V(NB{$r6C$7mxCLUtG$QYYr)i6FVbc$J^f>mwITi9>wDwq z-t%-aUszU#PfWb6=Xqzr6!6s|6<39fyp)hg;pDcrlDX6+X_1g)=X5p=OeCn~@;kiT zbcQ-T&dK?$?6C3K?qaDmnpA6ITHaJ0PYiW1a-)%!Oj@4gjS9Vj4T@k!laG48J}ZBU zI9&$%GB$`NR?(0*X#vcoiHx;Ih%?AxunOk+5)YGvj1%m3TID7XbQAFY*6nu*jCbjO zw_T+Uh(@dVBhnIPGLi(}ZHPL6Wu9#j9{8sv4C{x5re#T;6YBO_8u44w$)B>#knxVo z#Qbo3Z->f!DebhJFb7>7n>9XuUy+}v|2X-5Gp2zDW1Sv3s?!dy##=o(WMs!WO6|_( zGR3kw2hu~rOVm^pz_m5r{0Nb+g}%dYFpRZvabFA7!$SrE>RSIUQp6?L>iHpETNrRP z-U_9*hJY8yaOJ%Ly`_z8wg|dQCN5j!SDUf?0X=QM32G5Pg8zA%UT^n%H`b(JW;fQUn-x}1Z$)o{LAujkPe(GVezbEvCCeT)2vr1x`D#7Fcf_Anly zUfn3B2fd(lUkT4Y=DZ)m4~Y@aw+9HR6Z$&17#Ja*e0-flL*fGoWMa^$$IQkqwCs*D zPwPNnm<3lTDZ!@`Wj3#ytbT2;`FPsda_teTP5whYL&R^F58g{5PoKR?V1&yNRT>T3 z&8~!RJZ>VdXW<`yG8xgH3#)_>v6K2}O5BJrG)3-4x%h#SmbF4Ma+%=dc_pxk*%{h* zK4`|rb%yx1dk;KJu*)BaM27oL#`@Gx`7#C-W7}O`cdw7YbSPkH*l#X}ftEwiAKPhH z{Co!5G+1U<@07Ex5HV$YDPGc=`W1&pG}A~cUn+%G!c<-^6xvl?BaoNvfTG?chWSNG zTixvtxHpvc+ecL>;cgdg$UUiTu+Fhor5L{ZNv0chA3x2pG%Ut@72CN%P7~7eEuVsl zx{8m5;e43tb&0t1&*JgnnJapwvst}(B>KOklynNS&!yXg@%nO`qp2J^%^JkggM)*I z`;+-f&Dw$68SZ|O&Uj)0^cv!=7FQx7(p~}sj!>Lhx>EnfM^{>jZRE-Y<7`2{j_kUN znQ|mFzjNDjuT3@0K^0A=1O1>yr#VkTjRwEB$NzeKI1D{CIncG%;5p5E@8jUuX$Ur+_c@9ac<@m0yM*_+|Ww za%uL7(o$?==vGuCxV5Unh8AA#vzBM;a3g@*K zJ5!!qc8-=r;B9o_j1i=u7zR=gpLPtgXr@@;lSH$#MI_PI@%)h0hK6SuX_?t2ckx0B z5OJ&wLOOLm7<)Kfq8G~DL$KI@jPn@IR2REUaeZswgK6EeQ)QFa5E5Sk9}Ki?Sr>JZrMN3rse^4WJs3?dyh_NT23?t|E;$c)tj3`M%oOkK;RbmwqlA zGVtPo9=2wCcsDN)k~59``*$^aw^~K|Na|RjY@9&S^D4s)p{RrM(CW>QcYM#zw~u=d zj#b_T`oHulVXN5Xi0%qU_Su`4>9Q2Lt+RCJh&TH+=uo_6)vW4MiTLaeM63Gwhe8^} zQ9@(uEZlZ(rKp2*`QNa9V2E<9?b0B@9A<&?hcKbGgAq^H@k#604==>i;N3^M#Z*yZ zF=64ru|c%OgE_*j9zP%FQ^+*V8^s)9A2}C;B=65pk!%v-9tP*D!X*x(W$R=OxZxnh zN_$l;wc!%DPi@&k_%ald71 zz4WR`4GbnqptN^e5PVwV-yUN4^0UV4e!oT$)`ZWe8o*_%v9{hKwW1ZIe*t0cB==}NPOzaU(L z(0O1cDokZiQ~+-EkZV~T2fvNMOuVhhf_~#-Tg809JLx!{FSI7td}{?h?hL}<2}*cX zn8CFa<7sEN>F`V6NQkfzD1;f0e!)^zRAc8Q*~c-2*p!IPtVo^b`RY8&4tj<(J!7$R zsSgUKjU`6W0Tz~ne!IbKXCy5IlR(7JlgP{B3ZH;rt+bWN3yapvd3g+?(z4s<#`CbB z3saErl{S2kyIe4anH8KD7rUy$;U~arhef-=2eS1Xqs17l%386vWBL2z0D$xJ5BFWR zLHjM7K8s`{^FR_RsB90=apcs@t*o1QmsO-owiZmV@vYyxhZC^fm> zcjx|ln;2(qcySpQ(Nd;rqVa!enB^`aPfXwReh zb@Jk|wRSdY4TV177n#zh09fk{4%4?S$Iy)UbC?na++BE2yQu*gGbQ&U0Ze@rubNJo zF7&cOc3O)p2UGnEn+-q;{Ai&DRa9AtB6Ctxicz{h*B1eXj@R^Af-M%c~>9}*THflaTCMAHzF}qSHPOl5E%p@ontiBQ8l?h8N zMPky~op;9M>@>#e?RWR<;z>ri1~v1~+v5d199cGmVh(K{1Ho}wXy_M_P)~{XgA)!D zwArMNkP;Bg4z?^*f!_u|(0VrhjGIZWA+moYW4E7`Z(4 zdIADbW@~NjE^37YP7agg0%oC)h9Zm9hR@-#ki{i+x&s0(FV@Z#6(dL}f3r1~B>_-< z2eX9KTU*EwZKU(2xWoETDb)@sZ8qIDbS_%m6y)~H^_V@rnIY>aH!4OV8}16K-#7%T za^9KKsni>ljWxK&4&m8zgTq<2pSkXHBJ2P5dN}Q|oPJy=pWiv2ZQC~^(OjO4Ctke2 z4g|k&wEksFpX918nfvZL$XcEDAH{w6K*51AIWaTd>%Ghg7qI-LFS}p8T5}4EzaUR< zAV3t5$+v7Z}?*Xy6B&lxY*~B zK8iKMq$8hsbOXa4Wv{ww=P*qxa033OzqhhJD%B%8b=|9vkO%LLwU`WhCKAcRHG=e@ z3EiSGWGoFk)0Tn7GMin}tB=o4gA34aZ*AOd?2L`FS*I4P?en(=f${y$-e@N`aMj_scmQkRFOP?GmK?s%>AceWFu=9ERkO<`ZC{ zgrZLRs&mMznRFNP_muo5;tnWQ6_TSAHj~rtf=P^eBE1adyl_etSJ%RdP%f5BCcSk3 z=Xp|@I4eyST3ua@%BgyTYo=8c9_+7IZvvc2WA8#{WMo`7h~EKc&=MVv;f*1}CxHn; zj4mS}A&Dms2de0&X#UX}8_`xQkBZ_sTE@D%?LJh4R ze45n85gc~b`59OESvz)wQV1gVclV0%C;zkm+2G@${?VaFmi}S{+M10-qU0WW2&X!C=xY z8}iHZDt*ygD*Q#V91LCpjjxCZ6MOs4T)_>M$|cY#aK81Uqkj#%tu^!eUSUvdtE-L8 z0E4o_M3)<#M`verdiYePFJ37`Y5`~s6I*;g8eLjI2^6xr)Mgw%P9Cn$PX8Zh^A3dc zVeSV>&_tS*%xhWJ*=xdvhl@H5(0P46u7+ndDX>#h!}Rz;7x4KmPD(EyVdic2p3>6! zBOt+0Y$p2CBWu`-l#q}xB7CpnPm&Os$jt!9sJVl~bjjp#Ab%B1d?P3@AHnF?*2?B_ zvB-H(LzbYePvaO9?PW5YTQV*1y`jHl&O@&Zu~Ec#j1t@ zs~li2yuNnaheGn1+hZTQdqUYAa$pt7^trmz+P&u&AV9*xa!&xZ-4kV3@wgr=%DjN8*GPRPsA)I#ib_+79!k((EvD!vfeKAp33^^p z5{!F@=j~F6dXWG1HrS3{nA47i2|&L?Wmc(qh$4jzmX*#jfCy zJ5OAWBcS#d_sL(o>CKI>#Mq4)+S?5Q-k;y=)FxGvBL(0vp;|1bb3a~=^1j}-zUq9z zrcOZWkn0*G>VGKQ2Vsrq{&GV%f8q*JZm~Mg+^5he*^>e}DhK@gxCH zmpQGiTzWXU^c9hRV6?DsTS^SPLAmqdJkQa|eCg;}iSNtp07J|KWqyTRldm>e$)&57;=g zJv(K$T`mkA;)E4ljFWSWGZ7rWpGH2JhBOF7c@x}cs*C%HqX7}+Fmc1+$%uqE0hAO! z)Iu|_@j&YjQgmluH+n2!^fe;$=#pexag4}Q^~*npT(=SAFY3&N8HX5lg0!79XG9wqv+$?Zl$Y!F@*Vo zg2JbtOSrLuMnok;atSh6k8$&{!Q}9&BvGrg@AzeZwYQpP+%l@_5V_U}J3JD3F@7ld zuNyEdwuaGG%t<^Xc{}yO+SuymAW?S9Uhl8_RG-z}cPng@Y_%R^sMaZJw|<8>8C}tM z9n}#NczYIH;iT0TYwYt024#5O*KU)=5N$nBV24o5L6@mmLS+Npzh54Vcy{;pFXu~- zzx`XQioanI8iu-4`HOw2FF7|^5ZE;cpxkL~nZClezu|^ut-8r+mEV}_c=!h7 zRne2;+~96FIV|;Hv5J}eH+#6h=~G;J=r&=b`A6}yj-fSo!{_VyaV^RX0r6Lx#p@%9 z47NKAI5&fn#$PczIuvp%!j6u|?L`h;ATT|eCueZL!GUQ{b$)hpg|!adOv_M^&fr2O zaIcfxh3}$qGqM+$RVi3~fd7$IoMp26^H~ zai&v<064CU!t>6)-o^)BdAhNDq78X#v?!YVPQnHb_=U3t9eX#JQmw-J*M-auvi&Z8 z#VCeiy5}c@i)Pg4hs6MnU9-RQqJoAU(X5&I6n)fQCL=$8%v&1UU9>k;Ft?Y7=3k?6 zye=FwtujsnueM~HrJ5@podtlb+HG!2HHW9w#4_R5$KL@*^@0|diBc2$rBjq2 zMEbm^8>E33`!9oZj1*`xGiaK)r~_Kkqe1LYd~6(W*)KKAMG_ykO(%E_N;AUfv;q#M*;FLN%J(^q1d4N`?U?BZ|#{YP{=1xuwq9Z8=_wyS|)6Ff7E-%hw1v9Cu zU@iTDQCbYo#6Y2#%LkH;$+Df5o5)bc)^=nEs$dyR{N8jryu6T_S6x zb?F?d4sIAo&YL-!+V{){t|~M+tlx^1L)2cc9SWEA5DIkKi`X!dDud|yEDeql;`Na- za9Ubq1;WYEb6a&0rx0h=02#Dp^V_j9wQooH6*1{b6v!uCpZEJiB(0-Tl!F{B3w05N z-v?0vHsm#s=PAJqIj#cwntDW@b5;=11o7&;>-pw00Q|IU<-P*POp;S-%X`Fy$s{C% z8AlIec2t@)eQL;Oz<&-0-h<`vc7R}JLaFH%;NW-1Nv5_VXEz%2fHuuWH8w)cUym4& zOY4=9-Y?KWYc736RvHIZE7(}#yeE1T2js)}dmjaNmPIGj+Aj9EcXx2#(+NF|VVR-U z4vRe~)`yNrS7!kBo=6ryPMuqoiFX5nKl?rhuRNtAIQKmqnuza(jI_PJq8T0{PvbjE zxkB&Ec9pvjn4Lw!pmU?QMFITTtgBK1abogOyM=*^<$h1rEk9mg#B7fe)$ee|gECyg zNp`1OwU8~;;R7i;>HF)pW8qWB76T+zyB`Cd9qvox5j>p z(_%DXmh3Uw1RJ%JLgK%c{1tXN>zLEB{DR$uvL? zqT{p$Lm^aP9G{$&Ge!dMQ0vSFUw!846$dLRhA3C~R(IWGhzL-?4NwW7?@Y9QqCnEm z)Q!{)?CClftMjE9R&8n52UQ*46+QIv>YLXK500g9KzM~_Bq?2tj%qsv!gR&}0-^9V zo}8jmSG?ZW%hmCa6f{sJ`oNK*mtxVV!~^lt;QCwl3noWFW(P}U7kY-3DnxC01dwdVyJan%^8{GjpSoz|-F${QKIY&aOu z<>;w8Xs~zY`V19^DDx7P_VsX;{4XNpl|z)j+wYgfG=65o0e2o@Iu%=DSwUNdfH9T%yY2sJybX^Q>2j^e-0(kC-Q z%nPeoucY?in*Mlr{}UVZz~_APasMbm^`r;q#NtQCQ;5>$^q4TUrxCcbxW~tH`{U6B z=Xj%y^+1e^eyz|y^YV69%0XdDs#d?rI%{*qZSo%%dy|OssS{_%VG7P|)Q4);v=hM3=aG?OK*sDenyIL} zsFCwfwlC)$;J68y+L?dcZ{&cMgXs%r-`h0BUe3=o!b(&5oVU<$n1hKG&H#T*-tC3* zd_o>j_V^QONx<_br*6x8O$|E$?J)S;opyu2ilbI^XC5W3w>blBxWpn+PsvW32Em2x zxhBbPOueRqHl%8}qkl-%l3a$%rZU?035T-OLwm)bq|!bJc{z)ZCh@SDJ)i84(j1KOtgMz` z%uEz#>G&=QHBxRZ1l{-58ul8rIU1k*JnPY#h!Q^91x8P2vQdNFy1Y4L?NS%zl><~Q zmAt_zq5^2a4nk6^T6F%3c!c^OVG_WpBkB2lYXhPmA&DY+3#3oPqwT_BP#KkJshHoI zO?bXO*r*KEHCpb3oU8s7GaMS~GbZclY2{Kk(g=eO^~c46+I{>R@2Ew(iu2=|lW}T( zCDWNz6dBg)M%($PaxO2({aNh&aH_XabZr7A$Z;(tN2WkM$5M1rTXOKG42?>$$z=(L zF0<0cPgRthoE%J2yv`xt?xR=qQWD zayX1A#|#LHHzxPU&OTuv-loa4diqdW%9Wc7ip+cQyh_?UD5Vu;WkjiGfh>37$IF^| z0H$*)gA+TLXjUNvzrh~AH)oN+@GKBKh$G}_OU%eKr<{AQ8cIodeS2KIx%b7u@i^J& z1c|>6{`bcVm72tOY)R;EI5gk|O5#I*pPwt*o$UhN+kS0!ROa>7wmPZV zybKfc^%8JZ7a%_)FKWxr&yOb&vKUK|fo=T3f3=5cqv@xw4}-}dyTwkHo6Et^U*^jT z9iMUO?~fuBK;RR1s*L8p6B+BamxsZopP~a`5CiX(5LTp@ITq$mjHhUOu z-9n@P(rC=2`9-sTlRa!?4+>W#NmA#$;xK2^Uk#0oTFNWzc99-^bav6A5-|tasMm;v z44jUT4=D@FALJs@j|pzswNWuc8TS+BOKSt3e=>Mnrn9hU6B2sz??SVLQrGmkQpSQh zD}D_Kgc^OWD~=rf@oRlLfT-eAa@^HvY)**Xu8!nponkC`DiYvzyB!}qL*ZZ`t2!{X z>aFu~%l?C7=eb#d+D!zTX3I>F&U84Y=t#ndA&D0gUI!41k5^%q*plH-E3p}NQrfe- zv;aCrXVG$dt<@n~S72V&2ixc1{%x^jQ6y!K&0LA#3{4_SgAB)@tM2iBVT>vOux4#x zyDiuBo|;|_pt{o*hBQnZ7#yTw4}n2p)cRTf6|>IR{RTLy@vqETr=_&?Q_L1(vV6#} zFOld=5j-1;#JIn6c|2b!RbbmhR^SbqdIj+I12gczlfE0t=7mKe5pp{&RcVugAPwa& z0VK4ko?F~t;_-1*R2(pjH~NVnz;u$A7+|slZTT>R9S}$cYjvw_`Zun-(>j%GE^OaU zGhf)}B)lHJ$%f0jDOZ>8m@8Mk!!h4uxG8K*)G>i!`r_!wUXYJY_aVdN1PM$*5J9U+ zZi96aT$tzAJ#WfwEpA3(&TKSRZy(W7S_D&yj2Y~4bRc$KajjPLn3RUBu3D;=IWD+G zbl|>VG=0?;8hUW~aILB78i|1Hasb*)8=cxDwq!Zxm!I5U)}Cfj*(NEl5RC=GS=ZD~ zxywJ5Vx>(Rl;Id&DaH{m0~E75#}u2 zxkngG_g9B8bR0wwTgo$6?WcRj>2%cyas7RKK!(iicDh?Nbo2>>DG7B}+wPj(+rlDl}>&IrJ+QjS7#Y;`Ki* zT?|nw;pq$(Q2!Ijr87P}Jfx~o^6A1fD6`TWJWnz_8S0bK!IN)oO((vr;qy|5$GFM5 zLlUHsT(&=ZEaPLe^>31~Q7k6IS^gI&jQVMW)Q+oG?vI5H>@mjHoNwUWkjp`d8vnQJJvr+H%X!G)11WwN<3;0qZ#K9+S^v>w9!QH7W2kx&7-orYk^!7Tsp@7#8D9V zh`r8cw`ng$hJ$BTW^h`cEIyC6IZ6M1l$dbsdS)<1-1IbTJOq`gQ$bTsG_0C30 znh#>BU7nNuX$-nGpp}>{p16GYPJ3+3I0Zfc7m(+C0Kbw(&{M_1t6x*YT?iL)Kc*c+ z7_w3{hTyTjzP?}A%DSS2Cm4+ii8n(-GkT0$;6#x&&B}Us@~4d+{VJq_4&VuM1oF)) zU#%uveAmjfx${(H{yS6N_Z;a(`KxrJdTpqrATE|Ws$uoOj0cdZE? zKc+x+u2|8JkD@m4$e8Nm;6s+GKhbwT%aT;&uReYbH0 zVRK_6N0yk^^|)NM6raNyvR9HEiNfrt(b0^jBBg(+r9D0#kti+5Q7(t5W^8qAb-a5! zd&*cP9k~A+63mlv^SU6&Af}B#1!t9x-;>$S1nDZfsQ2?V+A;U5!w_{H?^hyOu34|^ z3HlBh(I5zkMjY3Xu6PPYPtA#zL-15nPuONWH|NE8+M}2AbcRE_9t8J&WR%4n-j*uy z^6>n6tP%7u(EDMSZ+~PYu>~3#iu>HU$q={KJ7NV8({IP6xDO_{RB|YtaQM@fCr|uZ zjDSF5*on=RPV<>&btYK0OK(N zrZTBn(T0RZ~z`9{?t8nct@YD2OYRm;~J zpPu;FdnTU`cW{T8EJ-cdi`1H2k>>YJOT<{nC^+eK0bkm46iJ;-T> z>lV}@rECcWyfOD$Ky^QZ2}{j3%Y8EZI_=H}Q`tO?AT8m&(tAB zk`bNLQ3<+7PCQqx_ZWdg9GMsL21Ls@nuW^u-f^9>NYNbXrxKwE* zNjzR|4?v?loFq^@OWvmS2_*mCz%`p~R>0I&o#3%ntMwSEV5iwF(QdXR85Y+4{ykG6 zN-L=0X*L<({FB@3H%^MQz=u0mk~Chb37_k6o!^`Ly>X>_r6g_|y|V2USl)k#9yH8| zh5QKx5m-Q~==)AMiEtlU$iF&c2tw>&(B=DsDg|I?nG^)&?gujZ?n8v1E;nv^)Sqa1 z{a)GEv2l=QyZ=3F{Em3X4hn%4fo?o*nB*`7+H?9NV1Wc&x-GUDp3-9#hK4sR>FX@LVC=ul`o(73EnHNX2I7Zx zg216*87?=51jiQ_AMTE(cQqnqk|Dq|!eBX=DF_J&=zfyGOzo-$X`4*}K=U>x3Zz?& z-r-_mq&L;0HmgWbIT;!_3(HpQ@$4g%j{31p3ca>UfpfW5gGC^uW@v1!K~rk04;keD zVnPC*sWbwi|4GJjjRew&B%GoL@AOr0K`dyWt(xx zHRE&>|LMNO{8&8+FA9=KmQX}>z5-G{)2Gh4>ua6vX7KP{&d;~DsDEXTF6`CL2@9#|MhkygbLE3$eBMr z->#g8$45H+qP)1w%%wqv8-jjbJ`Xa_?=?|j3bqdBmfy-;vO%sPVog+`p&d9zte3s{?!oS;IT!e=@ z&1q{!V#$zbXY}>f8%Y1_V2?dP)Q2!fe@lHY2vA8=pSK&N(bfDBSv4_O_6B!Dy`HxLXG@s$AR+pFUV7Vjx1F7x0Ryav zcLvMDyspm5GEGuKY!gorF;^omJn#llP>g7^I~2KKsVu5-oFEY5c*FtcCF}qGjK&yq z1U!Xq*{?srsnV=q`)u_tloAYd|s=jmG|8ap0AK*U98vS&ym> z4|h}vKZBz9?(Sr=L!K|1a(=@PTh#3Ar0hwK3twt;Xl0WLCx?Tgeevn4E&947Lor57 zE!fo26#+7qnyUucyN+z!`j%Oc+m)5q92(_&yNErbd9O&C4)5m4rp4Vwp7~jq?1R2 zOR-J%*CpWd(G3Sl3X6=h$YWpk9?gjgnwHc1P_L`=5unPy-)UDkd1e1%t~bZ!xHDjo z>3ARa#!N9nqS=q2eU@@*H8wH{>rp|yE%Jv9L9|?FzV%DmYL10oPjMDIFz^DM7W0auK_VP{?KYG*RTevR&5?MZW9_2sQHYLHE(0g2Qfj~buvorfumAeM zNO?g77#b$#kOKNfG?Gn2@Yq-3ys~KWNt+f!An7}1CjRb~b}nRO_%2jA>IW<_xcEq+ zRQ!GNurnAKi(gtc7!Z)zCBPPDLpROyI`F_nb_A-9xi~*(ror(bWX(=U$XCSktOv>T zJ9TL@GY$@dZWD*-UzC@3w+Cw@*6_BSq3$d^zwkV=pMO@U(YTaHRNb>@PVXZBBLGWe zF&&QJ5E_SFwPySdiqAm=sDz(8EPLkl!ML1|2DXaAuzpw9C;SmfIjyy|6^(xZB!{?| zkK%0WCNISCG1n&f-yaV5{`Egl{y=4Ne&B%nBL|INT2iOlRyL?0{Lz_;cU zD|($)v|TW{P0(+K!e&fZCiZ*!Zv2`fw~POi?S)D5dxa7b?B1na(B^EZTGY8%j98## zPvs~Td51Nc_V*ek!9KcFAT+jvt0+qAS5W$pDjRZkztpX|J+oqAu zQXm+F{7+80Br+r3|M2%a&saB)1@FZW-O4iwlAQYW6a6`b0g{^ZnErtE#-Ge*)kG=- zHLpA>Nl7M$$cgD{_XtghWEt8$vI}&mgQ%S$FGBZ9LI-!2^*<=Nw>rLQiLt4r+1fC2 zX>@8mC#^vFLtUJ`-lmMj6FY_zFkS{hIfrvCNf4k7BqN0apRkk(s+eLeeOSTz$>1=V z7R4bW_PdIpqs)IP8}DHaeb3}y;lGTbC^yW(yK@s*En?6anV*?dR1}m$l<475b|tnN z=SCv6ppv6_?G;FoiQb&H9$^2&a@HfQkMmV`_GV_oq3aH`2Yv7VvG$JPd35g=Xp<&w zY@@Mlqp=#Bjg7{(ZQHip*lE((w(XqB`_un?J=eLee(3XLo|(P(?AiOi*IM_QU>b(l zSow4Po5NC<5_b`LurX+my*jD)c6#xTI;7IC zca_dIuMW$wd78e-Pl z&_f-F$8>*P>eeq308s$-H_TNk#3ir*v_3qDS`v}-VN>&6h$z3ftr*m@g8)8+c6>c& z4L#Z61qz5d$FHw)=-eW0ydF=Eh2>LFhTv+fK)2QIu2FLwLzM*d2M)*}ie`_JVs`aD zpy5YqhoK>!xBaL0Ku2;Hvvm(@&z?I2fOM<;+xYOe?Hma?)=j#cAotEj^>7oqH8_|- zE|w5zRQ^RMsk`gCmft=FYvNMVUa1%V8Mo&dlVknw4W7U<-j1m6FXgMILFT%}+V%1& z_<`OpA2Z2wQYcSkWi|k#eNd#zMjln*s@Ds)xD6{Z9PXznN-q*7=w2v*6YpK_{25C9 z<6(+x40qq6n(^O^w7^RQ4E5hF{wS3jt;*%g*Rke*%h?Q`D z#42M}h7;uH0>;X8P>e6K4pHT1bjX$g3;qu-Avh4OGaTVX(?JwH2zuaW>qOm4YU|s-1wQDcc0}MDYm-5ygTSHgQ9u{} zfBXx80I@ipESx`%v-CMKv(1wY-WUNF@g~gz4@zizJNWnmv;EEj1u}I$?cNhi@)`^X z1Hzx3y1wX1gO8>HA3xeB#hmiNit(EP!x@XEOPU3A7y%iW&wWC1!ylc>7vXo$n$0V} z-KwJyI=^N5qG&nCq{8c^&C==qwsDdgfL_AFj?X@NLWEae%kTv_SGO-B!n!d?`6jFf zsij*sNQ2MpYO&7W?t$2ks|J382N8Eq%u^U}OX|H&g2)Z%aCdhzOOmLxS`@8lyV|d+ zK;R=LRtZ%ax$&S|?{Ma>Gme1NIOA<`*gPvhp4GV1V$MHIKyJgj#lf4_9h#|37@aYz z(H~9*=qY5=GOzOl0{z0m*CN@?@Si~Yr{O_kAIhhWt8CqZ`Rye3vs1pVd*fd=%Pil6 zI`vtkUymLa-SfY2wcP*NMI^#{f_tMX->?7iK8|B=yARdZwtJBeXTFUm2!tY2*+Btg z_QIzN{lE=9@b@O>g~o!>wE3ym#t1H{0^)H!mU9qg4Qz0f=qtHS0`4b^9>)?Y*1ivb z<;m6?>6MQL932A9mvNlsTGcP})F3Qrahe~6d{vn(8wT8vwI94=G#p~|i1A}m)gwTP zp+{MP{4H;}iZ8p?Zwh($<@K`pEZoxHouYvrNsXmi^eanzko7%8o8Sj1;_IOn;D&M_ zW2z<4XJ9iN-f8eYLVMk#-<%$9^six%f277|caX`?1!Nt{aOa>&kyfjH$XwsSRqQWT?>D1vx6yDX(091e-|H@Luz#65 zceWYFWAS*g3i7iI9J@vOT5AZ`#f%m#;SzzdG5iSt6&h;-%)AZbXcX zy9B2rq>u3%7{Yuuu)ce>L)h=iIv>*}`GbCys#jC{czAL?K9KuT^L=omQXiP0cnD+% z6{n)v!fx-eanr=NOgu!V{T>DlF1Ph9RF-)=<#Y99`ka)Y0!CnV14!zy$J|oM>wtBq zpG*+H5B7h*XoZJ~wsAQ&_o=SIVwV)HK1m#dS?cEDhCo1b~(w$*yb$HCFYdc^bnr-woR zfMem@`7ipFn_k$K>Cg7D&(uxnYc~8r^OM*(u}nw3X~M>_cF!mTr{%Q`8aa~?*+l0$ zZC`z_fSg|nSNR-HP{PopqUmy&Y&+6UvOK(*ipA3bm56Xh z!9$SwvB2%VL^2VB@Ox3acct6?8K+?k*)`z6!c0!uGO5m4YdH^DHZ|0<9=D916lIpx zWTTe*r?5q^3TIia-s%yAHONg9us>BLWz$Kx%iHdn2u_vjHhaP#T+>HZe>~(1 zGW+LkYl7NvG8|Y-#3nz6cnMA;IFf*MOhQ_Ez*%|NECOju?~C$es0Xe{Ip=&+Y@M;s zmLD1}XQSz5HEI$1%gTfL!x>x`jqqp~H)?sU=k*EiTdm7e;r@Q#(FebY@G&9C1MOib zw(cS^hY0t%-$1UV-3cyL-5_%B!)f9pr0u&~g|UYJ#ex$7#BRa_0c-UWnU&S5jcsF| zM<56v^-ux{UOucAE@#0h?dN`V_d9@L(lwsc_ImF$tJD;fjNh1TIs+o4qZw1ji;aO) z78h}9a=VX(^7ix7zu&~t>S&NDVXEfX%FQ{(i z#4G8;Nn#>D4$^0l92?(U%r@voyc1ALo3<@4sn^s|wb1f#KTS^6u(CP|V$+Of4x5i( zQs}a={r>Gx#()UZzA-O#xa$QdfgNVcdUbPp0Cc|f@zK)xq1vU>-FUqn({59suH6L^ zAwPrVd>~>~CR1@Z;dp*#Zvk+}3C!e4o1OXvRB|4I)76!dU8`MrXoiSiep91hl+fA0CbCQdG3D`n}b zbSBb$CQ}`5k0O^E`1%K{+@c)^M%tR$zhb8WwWH5jJZ+DgeqM>xell5Wnq|ti5)yfz zzc$X5CVbmqtl~7gQUfCYv+J;WuBt3f$BUx?Cda!wT(?(h3L7R;%wOvHVk|Xv4i5;g z>KWB{N}>~sv*#i^rt}7m6OJbXdwwc&F9?5Vie*3dUHBgP=f^z&jMX9zu1u%rY7Re$ zA_wwdMh;Ja$lRW2)Y8+_+}%z4<))ydPCvRCwz>IU^^WPcRChGyOg^QhEP!hj-P+Pa zMn=x36%)Fl(`-gSK%jTN*f9Nzvd&4;0ich$S5fOLzO0HtrCkK1SFf)fNy<0y8PHg# z<;{J`kQGe^Bhj~4+xpOVuPY4$U{=*m!G&u5ik*lMH<|69d>-E-W%btdZ0s9&3lD2fTByq68UJNl54YQGWfvy zB|IK=661;SC_JvEg=Q{}P3z_D!L!K7=S&LL9+ITI3d=aZuV2wRsN?~Hf)K&`|we3JZi+i*^KW`^Azf5FIfJ5uiL&uC??GlOav~8Y6 zBY+8V^N8;>&M=fG^70Z7o!JU@_wj~x`%qlj_68ipk;!BN{~%@}IIA{$gJjZ+ADoRb zRRrX@@7)Rx61F(#rgjDKdGUI5#R=5v#!^NTe>`8yByfA*3`Af9ie5?uwfrw&2Ag%n zui_@f?Q_JNaA8zt)A`~LxO?`uH6z^-M)hc5pVUv68q8;ka}3$UX!H!?!{LMgdl!iS z`fs%WjIUO=@Z^x$5Qg-OVk_8 zXtdiG*lv4~?{eja^&Ml9^=n*j%^b`=CjzCtM5seT!onOJ9E*zun5eM`Lfk-+$;MC& zkkP9a`&c5()Yd$UBBGWi0{rwe~z_XhBTP8$ExN+7>V2!P?R+tYV+Q)YHM5Tu+!B*f|Nw`M9CoClJjwl2F96-cd@+k?m| zv=S7DKOnBvp7?&1XeAhpFDYZfeR-f3Krj-}=M~E80^N6tJDhM4u~9;4r8-~J)gtgs ze&tuWxS^BxXY}^&CFIV|Lqf(rUGJiCD9#)uqCMT%KtM+)s~o!_0=VmpECBRv$>ed{ z+uY2tlg={`6BpOUW2kf3)d`nRwF)>{X<=e!R&3%9{MEL!oL3Sc4#QhnIm7Tv*i&3; z?EFYVU-RT-YxhYwm@;Joa<9&w)qADoN3{f|Iixi=SAmj>J;tTh`&C{w3KfU63sY?` zsOI}@G2-LyDBv6x)#a|X+`GL$!;x!ZgGjvDzt-2UyOyZ@6VuQABgf#K6o?~LdQF?Y zq`vt&TT^(8Tn00kj82+VsxL`)nfwr`RYT0%b)hz#@ahuIx(YR=t+~3^yG)Pt_W%iq%J$VtQsO=J`b$Sw?S*^?O$K|$)Yf0|#B8DM1va5&_N zMC2yCU+qc)d^H(;dp{`Sh82>=p6bm$%AZR)OErQOlY3(cvk22;6Z(MGs-t@~Y4 zh`%unG#PxM@KSBD)=(j20w}If9HJ09v7m!V?bTJUW$f1tDHHF3;{1&R;vRa)4``@;3Baoo z(0hIV=>tC|h{6*!b2+P}ga&7kt_p`?ff~$5%x{HAUoe@qsS74SpHi5N-ySaY0mfx9?w?4yTHM{Wtd{(irDn3n z2OMC(Q42_=AU@9i?E^x7IxNZx?{YG9b*?OrgaMHh=8v1COyF_5q*kNO-UGIvwwt>O z1}fjX?UvJ+0cyF{+80XWG}g57s06s5q-tzn%unU%9A5RolP+cUy+Sx=PlnV6(Pxnf zOBLz;-$TW9Ar5?jev<=tipX|!PkF}{!3^qY|II6M@g_e7;E$i5y@7Wn%uBWa;e z6I-lJD)Nf5qJTiug^dLlSBC)j=M2NWi&I*7YGZa9iE7zOH6a_a4C3ahq~jIG8O?0+sX9s<0nqU;$~J9++S^ zC_?m{v7w#4d!CuxY*;b|J9YPbf}PQMbu7sg6jeOM-)8Sm#H())490;l_;1CkQ=r~+ zc~B|otFybQH`|T3n@p9w9G6$y+fd+wQ!_oL-I|q7m5aL%%_WW)K zLPpYN7%n%oQ&Kld3TcUd5NVGIt~;(!(fYf;9Chg+-mfU3;4s#g1hV5P(y^|UWMz$NGjlL zP?Cw6!Fb;C&{WZI+VcDrYKOW7V3dIJChpq3rW(1M?Dw$be%NVE0DDmV1PWw;Y@(u- zgB({cElP>hBy~nwaurw`=E|R z4SY~IAX=*H{f<(6!oDOQUdYO)J6S*9a>)w_fd2Um z=c=Ea$%M6RoPsz9xM>hAk&==^DW-8&0Y!Yb(4}p^Ly$=5&!kP9feJR-lF`4_y1f9btZ(ghBCKynpfRPodrz?u zJ8T;{+K;UG_>h~Ir!)XKaQp%6R{GC{A8`{2Za=db`dQoB+6s)KfSomqA*HGV^{Cmy z$A7x_C}}460Zo@a5P9uvlmRjghl4*k{63)EDg9ySUADsec`mQ7uYft`FtVZZA2D9@ z@eVg_T3RLBJz}glIzPKg9Z{S4II^4)CP{{Ql=OeyDo)+DF<&ZE3Y(qn0Kh77L239?#>)u4J)F=}Ubn+p# zHtQh1J45gQC5%r%NLZ|;VJNaKBqA(qN-JijQjlZsF5jo4coJk7qrOY`ZBuiyYt^-VA1Y1rSlKdsSjy9i%n+62gHUkal6{a6N1VnIDRF~r^76=$^ zp)?TF5fcW-ECOm0XrTm3C2k&`?^5aP4CZEEO`dKJKYxKCSE0$*>m!rb2ESlg>x^Rg;jaTC*6NiD7q>SAF2tGT^c&b_v#z`AS! zXd5lH@H#!`S=@-CT?ln*ll$Ary6e_nZewj`Q&v{n<4L(~yC(wxhXmkF(N#rj0vUn7 z*Wp|RcJldZo3XXEjOGGxV@&Q${}$%Z1cG$N5Q*}-ToK>j+kL7v81@xYQBgUn27q+` zyLq72!S(*^M*xO2#-#D=^A~k!RJz{ zj62vW9!MQb)*O%7m?QRG935hvmZdkXo$?(1)el#~XaxujK-2R(Q0@gV5OO#vPL3yg z0w30Dwf}w%^`jIhTg<}@AZ&&uxp}b3(GR{;l$HH6mcsPgn@;+pEBG}bd`2vYyQM^NDU0z9=MuU;sC4)qKeK61U>6&os3bhP4!NKoT zW|1bXBdfxW&{_~1Ogkz`Yp-p?v02dUg9Ju&aKQ z3%|edw4?q=@C8VieDbJasV0bxvX|r;=s2BEUpk2govGvEh&9P+){{) zaY|R(xc>}%0o6~4_9-hj4r3>YwJrpmnEP-i(h47E9Psg~ZbX!XlRG|LZpz~eMjrzl z(uUe)%a=AM@WJ70<0%xrK)YTvAi}}n;Q(uH_$+s_hjN#v2Sv6%uOyV>-!`f6nV)w| zPEFhi!5F_?N~q`AV}ROuw?qA=Xfg%NXjhvgm=} z**g9=RXHS$DqLh5?_D)e)a%D?@1{v z)dEK)tWXi8#Sj?YFe`BpA_lzNNgbc-HgQiJxTl`f1cQ?Qu#n<1VAWc=wadO`sm!KG zho6opR7Nb=0Wo{u*j$2FOf3Sb1{eTKBY_ARBB~DBSh*3WFqEa6X)|~xtQ1X1KPwW; z+DTo=?GgWVjNc}S_^sZ9Jz08K??+EPwVifw9w)_B}%)t#_=tqqpCT$cnHM;fPMA`R| zdiam|8uSA{ zI9ZwHJ~E-@%i9g{rgm3$c4i0g>U#J>R6%~L4;|YS{Mv#Yu3rPYa$4WR2}eT%Mv zfQRS$3IQo^X}rws=OmT;VwM7fPP2b!ilmAmsDP}T1{A;t7R>fX5~%9;iU9Vw1|2@a zK&bB&cWv=ySqT%4JT>uLwD1>`D)ko-2Xj~ILSH1MK4xBMb9NiJ3flyUMCuZp6f6C? z0GX`SLx>7qCy2ei3QIC8OIYfM-lOd}bVn`@eYYrqZ-%i7vAx!oy`I1SHoZn+=OY1J zSM?__K>7yy`Ex=Il}=~7t$}Og_bOSf+tIx$EeeNGGK+SX_u1J&YisaFw!X9Oh|yaS zG;P@ogu^XZwKUt;sg&jep+kG7)SczYNz96Jd!=YocQkxj?RIuxk|vW#CMJX5uz$rV zqI`UMlBlpebf4XffSKKfI< z0Ds*Yci^Qr$DzydwCu3H@3J-Hq^j*KV@Hq2P>^p zXD|O$dmRrBh!R13)BaEH3Y-Phapf#0ohuNqdhY?{JaLH!>>3lIG&%QoP0qR7hoP); z3~~iCE#3eD7yjiq~k#{s#_1VTG7sl&SFRY6Qg7yxpW z`L@))&_32W^#rQ1PUHbvj$_#wB$%N3*rgL%gbZ=RSndEbbg5bz8g>T#2XJrza3TA2e+yml($o%IVe5xg3~-U z*NOj2U^-jE)pn<&-9N58+%*M+Du~-B8%s@RCoe4vQf#!`;f*+8QYUp{_p*Vwf&?|;AyJ3EDxfICd3LJ5?RGlGQhPJ)7#KK}?yv1(U_Sr|>D#p&wSV^N*u1@%#7!OhTJ ziWrxXa7du4wFm)>`H^}D-YP>T7$xOesJ|nrB~X1fFAR3-tKy*4b6}n0UFXFGec@Eu zcD#%GxNnAGWe)$X)qoYk(C~skQFgyEB)Y-xbU8V*`PbpPIR{Bc?)#06_hl~lX3|)? zNXc_y#OOj_JuXCS@;gvhy6rQ&94mN64#2TOJ{HAyK zd5vvSe}uT|wD#8>WMkvCvG&Ia&i1jfPQ4LqsMiNJ%^eLz2+z@?(lif*fFtHJnkZ*PCh%LJ3Jz(q5O=y)4 z3knR^+SR~6HM-+uf2HfvUHkrnQ~BwJ0CE?Fyp7S{!2wlV91}}EWee=#Br)}b`tmK7 zM@07>y9&o^??Ao$xOl0!&GP+7FzrhP=d6MwkE%F~D#ZQ{is}7x)2s(;0;mu_8Ys7u zQ0>nOR!*izfkQtk#VHT4w8@$^(tQY25s?sl!+V?sAFPh!+lk>)JYq8dli zy9=lBJ>96tH{=f7d87UA#g?#}d%7;(y7SFyVO|KLTGJv425TgRI3~}uDHDM5grycK8y_k)ml5^RKx?MNA5zq+99;a#8rK8PclvH3 z1-TJq#|_QQC`E;XtjXt3DOchO4f8h+gSxOdX5x4xA6@$m(f2}#Cs*bFCf^cGhV%?j zOX+ubU>d6|#ZDP1pZon~-G3YDb+GA$#rWait`+g)_EOSwc++ZLrYm{L&|2PosWxww zqe%*F>Kr}>lCyP5ZjzTEmZ43G2382%8RPE$o^Gp3vjd=W9JYoK+3$LE%||N4e-+52 zFd71?{!l8q$yn#J#8gl0y+u1lVqn;xEJb>C*EEzfUr@aSGgn;Dp9xYbcy9ja?-gy; z(>`mKEio!+v81uX-!Fn_?cv?b+2m#)g-pNB4P3V&_HupCM%=kG?inmV1z`HfJm`!Eof*$ zs9ng<<4fuG&xLef3lP1Ipx8uo_0dvwf97*}{*auyqsPWg*9@b9KAh-l!dCt4qsGNq ztv6uwl-o2W#H*jg&;>?ddTznt_1<*vxqo`vXOu(|of&IrX-N~7UmT7fIkxkd%wn-X zFPFciy9=xBZX@Y&z2*=CW}+neA|A~n5~H7Z(om{;B_QSu$YjVo4p35j@6g+fZD&iB z821dnRz2Mw-xn8?T9wdg^E#ca$00#>&*bh)5T>{jvFMHYf;We$Ne#KN~OxOqeiQl*?6fSglGN?Co_S^j9H!ksV3vROwR!bhS#DTys}* zj5Y*xy%bqy8&XkA@R4aV-qj5qC$jy7omIE;3q1!fuQ8kHWI=tEsw>a73ubE;Cp zEFOqaaZim%ZcHc?dZotEcMnl&Egl&;%N$z_&;TZ*Rk#R~#Wu=D6FD}N_--Hx7apW$ zZR>MEW>xA3aU6@4uaXa<1QK}-GYT897)5sdxh#-k>O}IavDs%H58N`O!Xn2Y7pJ$9;)dZ_ z{y3wY^mG%K@wG+C4d*8k00%dkiPc&6_eYD=594R?= z&+f!2?YLu0H5-sGDp9{29zsG?)GO5L3N>3+t{oQ40kF;@8Q!OTpj==o;+D4%(y9bH zpgNR_W{d&)N535SZ)|J0l=Iii)%{hfDzuSAIaK8L%Ok+Jmm>fMgWeliu;~gBziH;` zmx5uXz_&V2Ol9agbrYKkBf~T8U`4}Ga4qz}3Lw*<{}HXQ-g!4IenD>KAKohH8vB9I_znt}SReh`2% zk*stuj@Am=*}2}{6&e_@MmwDau_Ng{Q0|U+srYG7jf{-!`VPe^Q=X{7U&ecYI_GXP zS2!#X2D296F>+YFZ%9FH5wjU2X)U;in4K?vhO2Fv2Xo6tDB^=k5cBINB5hK(9RPx0 ziZ&?9EQpH;?|KGkIN#5p@t&<@cOq17(78o*VWBO4%d_ZT6=f;3mle%uWX{^*yKa?B zlx(0>#udIgL6`U9M1n%KYaLZhqvtF6!D(~GpBl`LjY&z+iDB181Fst5(6U9mI6b6Q z;q^3xf^5xm4LB%?OKTy`9yK0|O~W;uF#xp>tsuSctX-DYPppMhcog!6AddyMtk8UM zLqrh5Yzt6kBZ{ASg?vDGlyb|bZEM#tNl$j7J>E!`P{QY;h^|~XKD zyuE>qR_P(5!L?_Y0(<#qchByIy#0b6o?M1vg{LEW9y7vr=`PcC8W zDWq_Za4)m)A5y)EFkG!0{AW|qQrt&`ROJ_K>C6uxzyQ5|;s!Tlp)-nC5eHdbI@j_z z{XI*bEcuO>mcD`hCZ5{*_Bp+9sHX*$j`(G+E#IHnKsQcm%ntrMHw*$I2^j5wb*GF# zmort@l4BD(5!3;Ey=%GX`R`P5IP;aadcEkwSYQ zgZLl;k3cqV5og1-t6xS4UHo>J;=FTdh!@b@EuAa~AtI~_uxYuYLedDeBY;%0j>545 zudDgNN(Oki@j$5rLJRd)Rhh$rzV#0UXcX1DcLM6K(s&a=3`sL)H(O@$~A- z1hdjY^0 z&U|th6@)Y){J$ZA=gP(?ASTaBQpH`i&S^g@`6+1Z-UwCh;q6PK0TcpAC(xQOYaW3o z1mJE*05fs=Ko$!TAJmFhY?mK>}*~anq%3rt2P`0T%{ec&(2mB^fw1)E9~Vk0nJBxJeYK zbg0r`!QQ?=6AON3E8+mxlpp~XM)^zm&Hryd@TSd>FZ!ALbj03G57>qN-T3cSJp z=l{WVlsI0wMqBTO%}{&;PkL@IzTB5XQQA-vlTU(Eonx{bHod&)@x)XDq2= znO~qJq!A`|<=dTiY`n~D&Fq!PM^{fk@}G;Eu!1~}Q`?lOx5=&Q9MW+{WoD0+6LN5H zPX{Ricjlj_WDkRR4vkG4*vvTopXQ2@@f#)D^Ttd3w*v?u9FWl|BxLL(BLC;RLtr>! zCxYbvPcQJvKtPh!+>)YrY8)V!*lcevLmS+Muv^`RhZMM!!A?9>bM3*WoI^Irn%=bd zI(s(?e$!etkU){s+b;e*5B@rzlog@yGer^QW4!-qB0e=JD19A9_H1gs4sX8N_C#-M zICMPxWmym#l78OqsAS83It<(?Sy@nDhPovf7?U--7vD~YZ`vFTmd}=29-l7@JK?(O zocRSk1h+-HU>d6%y?hB}o?4#e);;D1N?y@J^ ziS7glV*44r26n$h59P8(Lik&x!}_=c5rrm@KR!IAbZ^pxkB73Jun)B-kH12Tp8J1M zG5zCuvE`?}v;_S;>vn%7r)(sWG1sxJzt)J$Jld$}65p-eh8D%%!Stu;JigJ-xGo0e zKmFwgo5}S4IYxcsZ?~)NlM@1xK?z@G&FM1AQe>+n+(vfiu~TlPWZrc0I9j}dDx!G? zyHtO`WvI?IKmOM7GzQ~(qzM^gxN@vFRh?UO-}Uuvp-m45jnK~4_O2>@q4fQx&TS5? zDs9dD>7945AFS%$n&;;i3+nP$n%9mHnJ5NaQQ9|ovzRZqo-z^-%md4=W)uAe!*dqscTa* zXS2^Vq3Z~94%g7)c^$e~&b=g>Pp4;XK#9=p;VHC$z`0}E8=#*`$V`Rt8!Im!j|>ph zcx8R3TQ%@4E-;yS77#A{l|z$XbJ} zlR@J%x(_|_31();2mIg4+@vbA+Eewr<||2v^w))Za(z7l!$sL9HF*2>1$PuMjKftO z&LfqnBz3WQ9oIF~mziRomBYirJpa1>{A5RUxjZz})3mNgtaNds&6vHJVfTCc4Wgeg zPe?bE_`lEcOq4hNIJLdttcYh=RM-7`fxP^SXroHuY4i2oqQ}@bT{b0KJ)FJhQa01B z6RGkVwKEH4p00I-EB2?3@D`k>wl*Ar!ne=^Ur4Z z|9#Z66F=71QL6$GV5$H2lnRjH|1nlR77k2X<#qO&=hLvDltWXSRHff};(sfNsso1@ z2dpa6PpFZhsaQqMK5@7tVdEP9XPmP+z-E4rwLaYMb%8#0^UOZHYt2kg>v5j%0^T=n zu6p;VIQ&1cpG!_ho#=2`bpMi|vwHNh?^H}#od>&YfeC%9EL#{h4*Rub39B*Kjy##vRmdx2sA3aC?-rs+!a)Rn_^!4L!+1wQ`9!9>Q{ z+?EgY^VqQ-A(ExGmI^ zT#P;?H(6K57z1^FI(e?$lS&kcZ(uW;_u}7yy}byTTM^@IbCql-u@N?tlD#<-b3~0P&_MbRAnX# zTiqHreD7i~-|VBy!BsDPPO>KZ;zd@Mt;#FL@lkIXSuTGs?YA~p3%AkrLR}EVOPhd( z7Ym%mhIyl{^QZKBh>_I(hIco2F6jdbx%L4ELq*1pRYv9Y zJN~N8QCZE8SFt`3cv?KO&DXMGYupWNC)0cvu_FtrCxUrp)(F-21j^XJyC&96$86h| zhe+lA9kBp=>>nFYU$(kGUV#Hf&H=KnqH{Ng{_s?OE##43ANM*)t4kmNo0f(n0Y+>; zKi36%P#m)JRkEsHQAO{bf9>S|Jkh{y4|9$A?=piA%1z8~ga*$Qpoj$H;~y_m78T)+ z`Pw~~YvA$~p2*|x{V&9O?To=u#LuY{c66)Jro%6O9r|&+)Cb=PlLKRN-AOJeXe^h; z(uMSQ{&h=BcjqA`W#Vd!tFt?|-OX=zZ#(V}`?0xMc05C&Z^Q}^srw-z z*vGTm=7QpMgxRDY3r}2RzEN>zcfmz(+T=vBPR(n+I&L^^J9jCCCaa8g5xdxf zM2Mju_z$yXEbw@ZG)iU-N$5qa;vio0^X~e*Ni~dfjZ7}wm(cF+J_}bWqD!^1kvd!kl4`3 za(m1pT#ES_D?zxw^YGLq_rAxdyMVz3keMko$YXm1(~OVRazSD z=_%)Yef{mBMs%^3XT<$>XDm_tW5w=+e2GqR*dJM3K)GZLK=}->Ar6Um3;W}*LR@vi zH)}X3aW@97UhDLV2Rot~lTcZ1pYoHj_?t<%{t>kLgH%KJmGq-jY%iXhl16jMWLf&6 zOs{60>C%_7sHmDN2<*`ggU`r<(0ozWU*Qc53dO}~im{04*g+XgP5&&8{Gq2CPsu-+ zQG^h3f8)NsJJm_gcusgeGAYcfyB@f>;GxsDsVy=#)PXk>Rn4RK4e_a&GL#<&haUWOc{H36e0C?s$wXJKNe@dsxtC z|H48tU8i}VA_GrE>vtsWm~+I1)~=a~mMf(w2#~Gbod9Y%cMp%%Swn~N{E(2a6wF55 z{=x!rO*HOrr~#hVs<~jDd9kq^Xy5`6HEAoza{#oF>6+<)jNarv@hckvxB1B z-lXT0E8Aatv~_$VX4}oG?lN^UxX20ytaWJ4 zneRZ|QvZNDHkRJEGV2!G1&An8x5XvS)Z~}*VPqL|^8r%H;jxvQ9j>HN7|ilddLW2Y zfv=-U)&|BwV&ycBAEFi^u(5Ke#Kc`{YWlBx`qq;_pJYOr*BLl6Ak-?4S2pVd6O)Y~>^N*4b85u4UaXWrC-O zqplfnot;+Gcgnwprvh6CCRh_+oc0iWsR@HWayMrI$zRkj2I0_y{UZE=vPgbMX~&@ykB8z)36h!kq)kI3 zqr|pH=_CD33JiwC~Lpp82`$I-#n{6Nu^ol9u!TdhY{Nzk!da!ZD z+lEK(<;KRSf>QA+)v|+#PPwh98XkKZ5D1JuP|qnTF*PwUX=qPEwOVae>To^#lIKqM zE01!Wni~LLMFIMF)B4Ru@T*hn54&RjK>r8O7(XU7GGcAFEAMR_fb5U<^&9c_|gDO^NSRP z2pMDw1X=-taTgI8sZx$)4n>XV0*!z-{APcqnc@4|0y^J{Q-O(RvKmk<$H@B4N^&3f zK&jLj{8!O+ISlv}3BE~Q=wD6?e;wO*&o=pj#M#n-65Ktgs3<(o$J&C-wY@K}^Z>0D z>15Z-`uHx?{NB@z_3IFcb>>~Y@uWSKrRF{?rn@YRJ?`uC!6G_F3rB!mR!oe~A?@aY zWNIlq02Iv>(J8GUage?<|0$OLS@iSVT@D%hK}hLmikVJ4C#KR?1~^+zFtsi~)v7iJ zya${{VCg1GGRt#UnT%aXCTV-VwU_q*`~md2IE)pNl_&6+q-rhK$)6thfrz}txL7!68UJjvsOk-dAd6@I+SHc28 z&Ff%}Bo@<11kcWe*uw%b)eg%dBXF8?_Rh!AeuKO^<=W?!fJvmL(q7&eXu#`l%@xU1 zw-&Cpb9721km{^N5TXXEXom&%ccn8$px-YDu!9&)gd=VfLmniq5JDB#%}6N$LtHMX zG>@}~i#I!4bjh+glaaOR_8Z+@b%%tpj`{5uxi72|u5?BZqJJ6|^G_#*&E4@MW#u}v znFCy`P<=a9CP^q-eXUgjRH{nP2Lw2=ptpU_<8`NV0qw3pK^GOf>k>BWBU5wuGDUF- zf)|;scIP3l0CB+v0sxC!vNzOa^}kD`^z$65h$#G`qjM!ODdF~Xr!2LFjgH-9bxTT_ z$4RN63iea|)MCbDIs&^Q5-%w3ek3u`=4)1R%r8DxRtl!N7Qf!&kpx2vx#L)p1!&jQOw$z3w^Z zm}86yrg^nJl;-B0CjakPE0w_Lat(_u#p!pc0BPeteeuwXMOG*?PTM&mG- zB3EC3>*vp41n59XY!xTtO?%Uq+U;EXm$1qJ(Wn8F4DpOA30FQ9&(_*_!~y!UJ!3{bH{ zEoVv-FzG~2G^>z_MrI}){Rbx&OZDkY(lIaqO}z7)-O{FZouE!v50Bg1+t5xGZA2)X z2ZdKyRdk@jwvK93RnMZ*z$`GfDeZhP9Oe?TNzg!0f8%5v8tq<>_iD0FKAe<4_goa` z6+8^rU_bOKaGgAyE~gY07G_-lN+ICD+{YNVaxLZ~r7d#ix3MKQl(KQg{Vf)rF5ZVG zSqF$CfZ(+=Ia4y$73~->gL!y(FxBW)DWG(@VuSoC{#2x5Z3q@wN&YNdHe=_zk14Na z{q4imY9ug^4C+z~!-i%s;EK&cp#B@USwe$C;jSEpnnqeIC7m+A1Ue4jvfYz$fDuB& zC#y(T6rKKeQK&8@<}kp-H>}(E{<^{AQhPEzJ>A#WcaQlo;rtsFJ)(r+n(BwE$t80eg^w2!4LbA`t5QoGkgJb48S;F`mqc==C(v#DLN)y zmz_i6X-(vamR!De)494zebY!#sHRecMs_sEAsnYq~`xXD$y1DS5`H5m@J$H9k7fsVdB z>F1o$^(XMp8q1A)bGAd{hh7@ssB=7?lvpN=`q|XWOh*~(-#@xPC)%wDLR8JjOR4|( zpA03~GPnd{X(*xMm(Ns$@wh>+dH#`ElN445MzbfBOV z>*yqHZ#O6^HIiV(B&E&w%+$El*sG%Y&77}vQ6)!v}B`K_wzDOcL2K`pu3=0DYY77R{-%%8Jf z;)ZHT(P=3)C~> zmHx~ZDe}YAGt#l~5f{*cN#R@P?3L@*dBG3 zl6u+G6G%Z3=IF#bS!$CLv-^yWiRInsx3@Iz?$)WPOlRj3i%m_xj!hyf%sgW0+v265 z&T0O$@UQ&eEBybgAKfeHR-Q^w+WQPWR>46Es*aWnFcc!*>29|dtb>EUdgDyi1O)_b zkkJ-TS72#9+%<9I$rK%(j7=sg%GsyJcK3IBd)xE!BY|mrVZ$#zUS68fsh(|5IXQ^Z zL2fR!S#UJ-2k2IsPjP8U(f2c-wP*ZzvLOVdy!o{ootg@rvtOBw#amL{@0Yz~i%&{L zL^^vZt(Y#OQ52Aw?}Xqg*UcZRb+eAY`vmomx25=hRI0FZDDtt*F6ye7jl|&&v~bf% zoW@p(C|kQ*&yFrS)n_KQwnRxp8_$nT6fBDxt1nWMx#vT0Ju^~~WofanG)bU9ojRh2 z7>XGb7S{eb@Z#bkE6NXb*J4+basFzukJILL#!tL;691&6G zIP*4Vy`))V@xH;)8q;IMM9dEgN=nt~U!NOg43D2t?H$Z|xLvmuFiwy76O>{!7Qfmr zl2=|I7ytfe7i-3PyaP|zhx^`+ulMN>rFSIjYvJJ$GnWWvh`e3r4hrFRZp+?Cw;)c zV5?-%){U<$Ykrm(*&xiR7q6BBKZ#D-4v4{IX+<~ z4QJAU4(lFk9U+qwF~8!lbFY-BGpfdqGxAv8fy+Po=(9Ay^uJPQI!b9U7B?s+H*4+! zPHa~d*IpNc&6}F$w!e6ADG9Xecot+|ogXa&GZNLxO8KP3W}1}4aM@yNj|UN_xDWSI6g0!&UfZJZs3SS`0}l z`utEFD)WV(=gYXAW3khib9EcCX5cJk{J8+}d(Zit{gRdFY!s*PG;0P*93I?{jC`(g zvS!7Z{|ZeV#7%ktRb$g zw8xC4ExIIt)eQYQp?39n8NNH3fjzXBA|^WK=*gOfzOJsWySuwVp@I+z`6~tO+dgW2 z11=4at}NYZ1*4oUl+q_hwI)lDfw<1dDDN;U&%BNX#m!!M^_My@|GB$99m$rS>18kp_AZ zgN$=m@R=her7tj-?4!G0eT|EYi$cT$oDdv9vAfXdNkocqxoW105JKIoBuQVb%@7Vx z7u*cwigD@{OCexT;sz+G*_v7Os>8DH09)&pw)Jfrg68sJCp(yY4Mj zFCA3{XeNMC-SccKN?cCOnS2KV*>}CzE6rEVS1-|BoQ!XKr=vYBT58CNx_ErQ)L1{o z_sPz!L{~aHi);wjj~@GnYxBnCfmz?Z>6@O;w~!}q#f}VGs`ZtX4*{Eh;zav}euXJQ z9c=nQw3gU-f&HD0FfXg|eS6^Coa@%jtnUI+QQg{&K30RDxVgToqlIPQzLMs88T)Sg zd`VVe>Jdzn;wCBaMeRLT!=`#|4%F zd3zv+l8o}9$u|&Fqg9Y25O+qIs;kEa20mRg?qP>rX!35-sf0Le^ly*Rx|r+& z?cveeyU|?vX?AFK1x*xuHZd*UDUmlntC^h*#9e{o<&QLB4`<-RpCmqg7>q>=2Mdb= z^7WnZLMtk7XhKU!&pedbz(5HKax@3$I?Homj@JHGo^?MKoHxlYbDJAG7p}8tc#eXL znmG#TC_qDyZS^aEcwBbw(uYDOF#YG} zBsUmN0la#?YL~Ah7>Gq!F z)ie4TP5pHJ7aRp+-hwam03`g{zK|C^&uLfL{#R7*{Laj6t=$RF*SQ+`G`m!pS`8>) zdaV3VmZ;)PsUiwPXa~IhUM;DRCk;+?7)oHOd}JgVO^lH}J1DC0tG-6KYumZ zDNfbTWD2ew#ROtpsa335BH1U6f7@(SyF4XwM!;=}O&h26edi5Cb|ytb3&UZK39-h^Q*Fy(Q=McoGn;s(nHOgNvs!N`pz@ECd*bcd%IbMm zIILCpO=TID!uF~Y?qQn~8Zt@Rj9fS{IsrqK8z`gE>D>OI}df0!q>$GPY+ev)rFk(CpXUozbtdsG|vcV84tQJ%}ApSOpkj{z!Nt@2|=Ljt`vGAN4N= zCbQMnM0uHPk^VDGu^)Qa-nU_!^huJju%I5&{rKgQN?hqq$KX>|Q^SAOj^?G1VjOr6 zY|UMF4|RnHn3TNfj&P+9n)8L`+E+i4D)Llrbu~bfGU$Y~77B{iUHY+Jm37OTLVCo* zOdok%&7~^%dWnNA9b05fZAiHNC3@e>wh?bnkesuD85XnH6R1>n{5 zEMeNr->@cF2pN#Szt|%n8Y|J`9ZBFVFGRvi33 z6~3=TU}J;xKxbRMNgF)Vm3?sM5yO{v5X~tLv!kdW*Ku%zDbr2AmU@42JHW6{Wn^`W zNQ5lp<>gsI+D%9W;m>!QVftDEPjs6z@PS1P-J_~px&vKMcFHM0Vg>m@W% z|2lKn$#D?CwuE+&p$f$zpywZ|u7L)f(28awBAD&fak0W;`Cq-rVrdhc1;ii2*vwc9 z9C7ST9rbVMbYB`6N4$(nNZeUn=5PeMY};LxEJ=j%2!5Vas?hm^k&%(<6#xAl(Z*Qc zfpcSH<07GQ#dG`@Z>c!tW8wVGs6plUB}XO#o-U~QYiMXVO25Z=29tro{E77uMx-<{ zQ(2}1r=5bDA|7dd>CH;puh8YdlKwr2i--?@Sx3t+yJjEdIFgP5Vv%;~^v0$!l_6Kn z&0lcto!yMW8n2z|!@1bmTR2`BH&6`dWiyoCw=#MFH~~*_pu5{*wu*j%u^tS%MI-qT z&~TnbUF@0o$Pjs*%Y~j#N|*cUH|>r8X|aO;o>o1Uf=Bso@HQ-Kbuzc&cXL`#hk!bel~ z<1CWwS;Oi4xo*oc3j#45O}&5&;rm-R`jGX31A6_meV0#Jzs z+)kzpVYQ!hsFQBARog5M@?R0CnFX~FkRM?|IocBW2D5Y)ev4&5yhI78r;`m!80+_w zzxSbd!6MJ3$`_@52l1ZE92%xu-eP$^R$*Yk@Ye71=g%-Gv7~XgORzBY%+b4fFSfME z@2fSLY6&lZqwtaG_%o8M;VTb_gXk#PjR)en6f&gz+};|T0dg_#ACwc zy55PewP)%P(2jlRKip392(yjum6wg4Rbd4FY-XjqGb(?$wA)(>!k}Cl!CnODj4i;E za}u9`IS;sNc2eY0^?=u5cV)zknUCAbEmXlK3;Y`x2PHld-+@79+ZwhZEBhs>5Zu|e z)^+QjCmLbrpWtMt^(=?8-lu$lgC1A391iY%*9trdlKc^V__y=_Xf$N8>U!ziAjj1J{9_tMa`QxuG z?>o;#wP>?T`jVJAq|K5!?crvqUAnaPN2m7|20eUt#k?w|8savs4{Oa8JTrY}VH|=~ z_eFAI0qECF!chph;H96p{S-v~6tL;S7ut2rztTs>_vY!$a*cWwdMCFKYJpTvEQ4g_ z5kFH?Qpcud)Vtr?2zs+BhO@xxYi~7#sUtsq|AE6d1U>m}&I5wexB7E^VPCkAD2qc- zztP;n&gjNt9v=T!Eu#MaS&QJ5hHkQ_zK}?N+sAtjJX?;&V9haFtzORszTVUXttLBc zuGh8|=-Ef0C%rM4Cg`-I?&9Lo-W)Cn%{PfoyS&6?dAEdNgBOnh;&jMg@5|nGTh(^O zK21$FX!0UX-#RT3uNNcf1ekxD5_ueeJ`)*C>r7->lD^M*lDzdjNwI^0oQd`# z9-++3uKe##U4O}$da%ybvz~Vt%azeWK)bOJkwFcCK&G!z(GG2S$ldRshS8=nz)K$i z{e3e>18AH=!ZF&uPD$X~(7cYpwWFE1FhOGJFiS-kb#HMF6l7|b=1Za4aMrpXl&{16nb z?R&K8`dPP2QC{;P0i(%WyNKTBmbr3q?cc50Yfei1)cDYBxM%zQq6YUiR*kzp$$@)n z3vYxXzRZK0k2s>|%1quxoh3F-9~KiiQOG}zD}ps_!5KP4EKv(!HnKFISZ*>V0hxy= zW?ha-y}qF#Gb#atr?t(2gW7pD8$%mvYaYpdKWSw79r<&rLQO{th0Xd|n?()&Ye~%n1gYBaV8$KvmyFT?1=@qCK#1-@$S& zk<4Zir7CoqYB^FMt;r0SVzJD)qS$1`1e0&~(hFb-rEA+)69(TE~ z^0=S*x(Vu!o9qOX>uGkvOspgw!r`8s3CSO{8l`ZB5^vR4`jpzMN@v zNukcEoL)jgmwXyCbEAYn#)1r1XiN4te1Q(d0+m{OTIs=h<%bqpFA2d-K%K{eN_ylw zb24B8CSj%uf>E}{=gHEIxWKtt3rnLGE)HSF{q3K6?7=p#tmbMbQVKSh^EWV{%rL=E zL4N#m2?x2_%#A>6>?66wC0+1Vw=M_cXw$lbBZ7jP5Tgizp$VGl@uNG(4-k``E>sH7}IX@$H zr`feN6*uPX!$jP}+&$8ARe$X3JZgvwzr{QCFxlGMoyDG?dUXl!_bsOR(iei7`md^M|t&UPh$(-pB6Pp+R$EEV>Vc;)*yL=@)7_> z&FdZF;gOM-hj6O9kD*WW5pY=l<|xzW&mpoh9oBzCBoPlpbK8R)rcAi6M^RX3`p9Mf zd@~uezmk{)P+;KwUW6IaEqNAL2C%OyQ5Epn2`A)U*^BLZBXf*l_ss1dB5||w<5m;QLOg13>`S6DX!oi6t)->q zn>Y03=)g-h_*fwaJ6leUrIFhIKkzQD^(|a%fn6}PT}{x+rGmlbv|~H4l$8@2G}-wI zo)Xmq%3g&I$i0Z|-%_rQLL{tzbDS?x=OUhEepeZH zXkD*_w4Y<-O6Rr~HUL@g*H7vZ8APl<2hMn89{S@v6Zx(vHP05QktG@Y!H|WZ@<88MK9s4J&&bMJ`r%PfvvMHTu z7b8ou{0u|~uA>I35}7b-yp?PRLbtXhnok*ht5Y?IF2ui4@U2|(6HyL}$qW-uHxv=L zpPiqZ<*%)+QPq`YQcIBTd*eI#k9{;hJg|LjTGKH~UTG18hq9!Bv{3ztac4|T=OjAp zHGuvGb*?TQxbnHb;CiLvUFlP$ z5nY7BP?hk57fE^-yGrW#MO#^SsIPP&Xt6BEw)w?No%{|w6e@Ip)5?Ior%sPShYxi{ zFGy7V)Qw?U-Yc!rs3VH&4|ZSh5mcNEEedhyzR;M74Xl@8#IKGXzLuJsnjC0P)EwI= zZsKnda2}s2g7nH4zPZrecTF}Cp6>Buh%GYy*ds?TBo=pm9YtL|TYBmS@LE1-f=5`XUY#2OPc#UMprt&4-aXi3U|TTMhh|J{8Hqn($&4GD&%sJ#?8MMRs=H=63DA zg@Z}d4P*`a!ab|WRIe5r!wr(t3a4e*_fjQS{A;CxsWV^DO0j^H@z>SH&)6K~w;q+V zq6yX~^3>M*bDz=SveFwPQW939n(Pe^AIu8!^COYe>fGP2_CG(jfdA$Pe-tlf)U7hD zec!ZK&3ZGxwXEIm^xQ?^op1$P{NC`vV4s6|t8+t$TWoZc>1!h(=LFq9y%fQ$Tw6T* zf1-M8ApF0g`palvGU2%InN$pU9rvaQi3(AYV*D_!<`6T8X^TR+OZD2cw!*1#A)i)7 zd{ArCtrxR($(xkfoh?gFXu$;i^y6LM9`9-%cHY#{H_9;)antJ^eGfvnZ4XvpCKes@ zy-7%{dNoU;C+}eW9G9SDbAPACj+`xwKLOZP3I& zrfTQ1Bn+oWXQC%4ecGJIv&qL1DZt*Dq_d5d{dE?Pv8}uu-}>C~Oy81W!>W=M`m?5U^FxODne~p)W$#j9c2p$^kSwmmnB?TheF=T! zRV<+|r6uJS=YO!)wqx&k_TsbwWqMNN?xOCmU7PyIu!pM)hyI_EAZK7vV44xc+ZQZp zsqVm2KJ@e<Bay_6fBIXN48td!_pyYrz>N8pvWs}f??`x^tplKge5 zEK%g_RJW_eV3yuHwQdy}XE^8+!C%%o{#qn*VcFd!095MTT_VRfQ+@qwyX{5jMC)r1 zc9(kva!VGbG$*ICfpE|Rv+qiR)_16b6ZLZNd{`H|vI&(93sDMdJz$Cb^rt2KpBasF z&kD|*+$7P>sXb&J!@)#V6>ts^u%N=Jn*}+Mgh$>aZUWZ$R9$hydM}!r)Hqz^;c-Bs)mEE^r zm3($+kJJ}<*jkDoo^fKVTCbnHp}BBtPFE7;pYT2Y$j_YD`AbV{<%;Ix7>8O&Qheh4 zdS=Z_cAD*jVsBa-n|*`YcEY+sMHK$6_TGA`YX+W;N5t2Ud?ftsTQ;+s^i#Pc5Q&P_2z-gCU^UON$ z{qqDglbx&h4hCaO`_7I}`E2flE(Jjb3F!>0CdT_lJP@X4=0=0jUf0#eKZWt~K?7XMtm%9emDbT)~;X#}_YOPs4ts~ZPHyv(90h1JpvOeTD zel=d}Iy&Ozb#y#~Eb3bUXAe$;7hw^RLZ?RGBb*PqBR#dc z8#hNQ@J5W!d%ruCJIN2o1k~h}l&tFWPg$p&sVlv>Yog{1eeleQCp;PHhu+GXq`80Y zb&W|{*P9T<&M{(Wn^{>Y6{ zreSA_2^T`t3}6^C>&Q>QMwPTlQNOQt!?xj&lf@aJ4l0X?h#)(oqMitQqCCLFo&6w1GD-j!^-aZ4K!yYJ z0i>`|_sE4BT#GOO(b?bnXLWGi22p1layFQ|ZSDxgND8K4*zu+}5U(`GBj~L3(?1WIKY7$O*$|KFZI> zcXi`6pGF@6-#R+*r9O<|ILnm?>%YMl)Bglt<_7TcNgEsc;Z03*S2Ibhj_e(7svWA_ zCKiB&lQ_wGvjja=rF{ivjHqx>ZFE`;_oxf^T#|k7W}9_+mZmDn6A=p;0dy$zVJ6Pq z^UCSeREo5Kspu`kSQ2=OOl0UQ`C-s$0zI2kVMVk~bi3E`Sy;^>vOs*uwTcKky(ByLsq|4xvz#d^hIfF2PpNyn^s zdgT@InPcHe2ji4;`=+KvyYKl_Aj??`_S9$5cU4#4dYf7z(QF#$OScfjK^ZwXYze68N;v@?n2M-rzsBcKk0MZ{!E=s5a!j1RGMX)w{-8kn!2I40BD6I;9Tn9`W@9!f9#kA?~9aotlHKS^kUI#Bbz7&ic zG&7cc_j{-h=4W0^KUk@u3xMx_ZUh?H-oUpQ4D&wi4aGw$dzGlg(D6acx1VW%d@@tq zBiN&I=_E4~y&Vswje-@9gg8AaDL@SsNtdt(6dO+-iztn=vQpiqwS@_-)vOqHJJ{0W zX>9NJw++DLL{ggCzCLnvRUF3aQ}fAsUv7Og0#RQ_$NJOa%sojlUl`l7<(aa%Qwhdt z54tjKh7foQ?B6BPn7-6x`nX+WRH4C`Qe0w$&3x%>JS^T3!|UrEXTozj6_Yr{C#6v) z^XTUL!CK=@-VdPR9NeXbjG;p9J9FEZZUXgic;ha`vk{?@M)WZ07~yMh;H*&#%GOUG ze8AJhmVSiMVQTs2$H`i07W=p4xE5)yfL2MdmoRzC8I8c`cx%gI1bUg?t}OuNw^X+R z{SS5(%_o-Z5WqzVv9zf1YIZtia_b3|S49RD1T00S4n)&;_!Gb(_@Ic0Qh<&2<<3MX zGXd&Zxp^pf>i<<{U_DaQ3waBfp~;4U&38BvZ$Ll*M{Vm)>+7s1XB!zIeDOZsa#2!` zd9?50qso97wU!)IKj`@Q+70ebKj<$nE=ag7V-YQL7{C>gJ)&~pZ5njbg{t8+O9uxc zb}N#5{xuxT>0KX$W?sl*XkFFL7|Zs!IsFR zmwJ{`(U^=X8Y9etT&Xp#sYRA*uZ4-?``jZwVaBQ0k3>?GZWCBC)?jL2qb-`GV*Su~ zS&X^k8spXEXFy4f-JeZicUR+n6*4w9)+W0kM8TNAaO56TNxjz1(3Ax0GO<>!i@FlK zE)5R@1Jj=W{>aMkOd4@n(ZF-Tf})9n{JG08{f;p9dxD+2b#qDn->w^KTDB0O0dmk# z7=w$_{Zq?{{YEmLK9V;_&~jkG! zjn|%0ef#i->tGQ`F~OcWht9Cz3w3pOC{(+G>gnL#xB|Pw>1^ zdaIKA6)SsoPc2tQ-{MImAc`7(B8EO#H(mh^_}t@gd?&&^imRS+HfA<=>QL6}cgu6Ccd zfn4uo*Swsc|AhcbX~(o1%51!O%-^7;5HO;^9TE&0SHtjaDE>;2vh6~wp;s>gGR5OR z?MUlT)>`%I!iBQf^v1zHX?9>dQORJu)6{|HU<7>TLXjWFtJJ9b#a}cj@p&wL{#?Fr z)-+3izkc5o6J2XR7pxU2%7S=sa&~arO-o81#?NC-%$$&6#WvDG#eQQ1d3#;peTL$+ z^PN7Dpw#?wq0PXtRI4Jxo07SNLSFh=o2fR?Y3^tAb$Tnjo5)WtiQ$ildQ^ge-=`St zqox$fw8-xe#waLiH2ZaXUA-yT-9k-a_oDR z_O$<)u(MofkP{pFOAj~okiVRSA_i+L;n{YPjo8B&{}B+aq6703L};$7B0r9a76)kH zK9>kp>u^8uGr`U|mzjUI6+Y!w&lYSo+BK_G#B;WkXTz(nt7#I48D5UI_Du9nb4_j2 zJ+s~=*kap!WM_u&=Qjcyn_z(Z*}sx8920g&(2c^7IJ9A{535 z>~+4vdlU(#hMd&;uWv4?p6vv0PM57~SL0JUzwi3BBx-YmQt+~(Uc-QZKK;*wp)LW? zi3!_0-7BRh&Nw_x`MIX)f*_Chgl_ewS7xZy(#U_ud3CZX_D61ER^YFXP9JwpO4#6ZCYZPJ0Th`h7K_8UX!X>*Rd!enbUvGzW{MP1`eagw{MSVL;TC!Ll zBv`vX81wTmS~On|o71_}(0=4IiVH7H_jmQ zb4O95f$mFpPeZxXukf<<#S%OhpEn4@+n2SR43Rw_vZS<<26yeRp*W^ZweCc)apX( zmno%!@y<^T2u9xTe!5ca4!?9?)(xcl{ znk@H~a|sEoU*l_zG?-t1E+hCkIfr!1rK27ZKuI5&LW1qH*?vFskC+>#oN`pUTG!>a|^00t!DBn2{xk+#LJ#uRiz;F>l+5gg}5u2J94oLK_0AgZdp*RVg+2 zvZv~8dfOI@`+R{C-+rYe!7@TZbLQc>9lRLD78_T3Tmc{5N3S8~+9<*n zH0UGjxTGZJBKcQmym-j~PUw?*)+S)IiLr>fU#QLLGN$3EPSLph*6UZ*n6XxtB`+(M z>z!6A4zn)yzf1?jY#&elRYFwj9rbX5XNO{?#PUT$L@A?^c>T!`r^#ulIgC-2CP%o zrkD}TR%C6nK-l{nIdfJaHemN5_B0-c7q&G+2?B5?Ge553y9K5#_`1kP@ qpiLq4F)VQaul?5tE!cb?{#quw`4pcb9Q*|Q$-YpM{3>qb_kRFBZX(G5 literal 0 HcmV?d00001 diff --git a/doc/src/core.c b/doc/src/core.c deleted file mode 100644 index a173a43..0000000 --- a/doc/src/core.c +++ /dev/null @@ -1,2303 +0,0 @@ -/** - * \cond skip - * vim:syntax=c.doxygen - * \endcond - -\page core_doc Netlink Core Library (-lnl) - -\section core_intro Introduction - -The core library contains the fundamentals required to communicate over -netlink sockets. It deals with connecting and disconnectng of sockets, -sending and receiving of data, construction and parsing of messages, -provides a customizeable receiving state machine, and provides a abstract -data type framework which eases the implementation of object based netlink -protocols where objects are added, removed, or modified with the help of -netlink messages. - -\section core_toc Table of Contents - -- \ref core_lib - - \ref core_lib_howto - - \ref core_lib_link -- \ref proto_fund - - \ref core_format - - \ref core_msg_type - - \ref core_multipart - - \ref core_errmsg - - \ref core_ack - - \ref core_msg_flags - - \ref core_seq - - \ref core_multicast -- \ref sk_doc - - \ref core_sk_alloc - - \ref core_sk_seq_num - - \ref core_sk_groups - - \ref core_sk_cb - - \ref core_sk_attrs - - \ref core_sk_local_port - - \ref core_sk_peer_port - - \ref core_sk_fd - - \ref core_sk_buffer_size - - \ref core_sk_cred - - \ref core_sk_auto_ack - - \ref core_sk_msg_peek - - \ref core_sk_pktinfo -- \ref core_send_recv - - \ref core_send - - \ref core_nl_send - - \ref core_nl_send_iovec - - \ref core_nl_sendmsg - - \ref core_send_raw - - \ref core_send_simple - - \ref core_recv - - \ref core_nl_recvmsgs - - \ref core_recvmsgs - - \ref core_recv_parse - - \ref core_auto_ack -- \ref core_msg - - \ref core_msg_format - - \ref core_msg_fmt_align - - \ref core_msg_parse - - \ref core_msg_split - - \ref core_msg_payload - - \ref core_msg_parse_attr - - \ref core_nlmsg_parse - - \ref core_msg_constr - - \ref core_msg_alloc - - \ref core_msg_nlmsg_put - - \ref core_msg_reserve - - \ref core_msg_append -- \ref core_attr - - \ref core_attr_format - - \ref core_attr_parse - - \ref core_attr_parse_split - - \ref core_attr_payload - - \ref core_attr_validation - - \ref core_attr_nla_parse - - \ref core_attr_find - - \ref core_attr_iterate - - \ref core_attr_constr - - \ref core_attr_exception - - \ref core_attr_data_type - - \ref core_attr_int - - \ref core_attr_string - - \ref core_attr_flag - - \ref core_attr_nested - - \ref core_attr_unspec - - \ref core_attr_examples - - \ref core_attr_example_constr - - \ref core_attr_example_parse -- \ref core_cb - - \ref core_cb_hooks - - \ref core_cb_default - - \ref core_cb_msg_proc - - \ref core_cb_errmsg - - \ref core_cb_example - - \ref core_cb_overwrite - - \ref core_cb_ow_recvmsgs - - \ref core_cb_ow_recv - - \ref core_cb_ow_send -- \ref core_cache -- \ref core_abstract_types - - \ref core_abstract_addr - - \ref core_abstract_addr_alloc - - \ref core_abstract_addr_ref - - \ref core_abstract_addr_attr - - \ref core_abstract_addr_prefix - - \ref core_abstract_addr_helpers - - \ref core_abstract_data - - \ref core_abstract_data_alloc - - \ref core_abstract_data_access - - \ref core_abstract_data_helpers - -\section core_lib 1. Introduction to the Library - -\subsection core_lib_howto 1.1 How To Read This Documentation - -The documentation consists of this manual and the API reference pages. -Both contain references to each other and as many examples as possible. - -Even though the library tries to be as consistent and as intuitive as -possible it may be difficult to understand where to start looking for -information. - - - -\subsection core_lib_link 1.2 Linking to this Library - - -\subsection flags Flags to Character StringTranslations - -All functions converting a set of flags to a character string follow -the same principles, therefore, the following information applies -to all functions convertings flags to a character string and vice versa. - -\subsubsection flags2str Flags to Character String -\code -char *_flags2str(int flags, char *buf, size_t len) -\endcode -\arg flags Flags. -\arg buf Destination buffer. -\arg len Buffer length. - -Converts the specified flags to a character string separated by -commas and stores it in the specified destination buffer. - -\return The destination buffer - -\subsubsection str2flags Character String to Flags -\code -int _str2flags(const char *name) -\endcode -\arg name Name of flag. - -Converts the provided character string specifying a flag -to the corresponding numeric value. - -\return Link flag or a negative value if none was found. - -\subsubsection type2str Type to Character String -\code -char *_2str(int type, char *buf, size_t len) -\endcode -\arg type Type as numeric value -\arg buf Destination buffer. -\arg len Buffer length. - -Converts an identifier (type) to a character string and stores -it in the specified destination buffer. - -\return The destination buffer or the type encoded in hexidecimal - form if the identifier is unknown. - -\subsubsection str2type Character String to Type -\code -int _str2(const char *name) -\endcode -\arg name Name of identifier (type). - -Converts the provided character string specifying a identifier -to the corresponding numeric value. - -\return Identifier as numeric value or a negative value if none was found. - - -\section proto_fund 1. Netlink Protocol Fundamentals - -The netlink protocol is a socket based IPC mechanism used for communication -between userspace processes and the kernel or between userspace processes -themselves. The netlink protocol is based on BSD sockets and uses the -\c AF_NETLINK address family. Every netlink protocol uses its own protocol -number (e.g. NETLINK_ROUTE, NETLINK_NETFILTER, etc). Its addressing schema -is based on a 32 bit port number, formerly referred to as PID, which uniquely -identifies each peer. - -\subsection core_format 1.1 Message Format - -A netlink protocol is typically based on messages and consists of the -netlink message header (struct nlmsghdr) plus the payload attached to it. -The payload can consist of arbitary data but usually contains a fixed -size protocol specific header followed by a stream of attributes. - -The netlink message header (struct nlmsghdr) has the following format: - -\code -0 1 2 3 -0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -+-------------------------------------------------------------+ -| Length | -+------------------------------+------------------------------+ -| Type | Flags | -+------------------------------+------------------------------+ -| Sequence Number | -+-------------------------------------------------------------+ -| Port (Address) | -+-------------------------------------------------------------+ -\endcode - -\subsection core_msg_type 1.2 Message Types - -Netlink differs between requests, notifications, and replies. Requests -are messages which have the \c NLM_F_REQUEST flag set and are meant to -request an action from the receiver. A request is typically sent from -a userspace process to the kernel. While not strictly enforced, requests -should carry a sequence number incremented for each request sent. - -Depending on the nature of the request, the receiver may reply to the -request with another netlink message. The sequence number of a reply -must match the sequence number of the request it relates to. - -Notifications are of informal nature and no reply is expected, therefore -the sequence number is typically set to 0. - -\msc -A,B; -A=>B [label="GET (seq=1, NLM_F_REQUEST)"]; -A<=B [label="PUT (seq=1)"]; -...; -A<=B [label="NOTIFY (seq=0)"]; -\endmsc - -The type of message is primarly identified by its 16 bit message type set -in the message header. The following standard message types are defined: - -- \c NLMSG_NOOP - No operation, message must be discarded -- \c NLMSG_ERROR - Error message or ACK, see \ref core_errmsg, - respectively \ref core_ack -- \c NLMSG_DONE - End of multipart sequence, see \ref core_multipart. -- \c NLMSG_OVERRUN - Overrun notification (Error) - -Every netlink protocol is free to define own message types. Note that -message type values < \c NLMSG_MIN_TYPE (0x10) are reserved and may not -be used. - -It is common practice to use own message types to implement RPC schemas. -Suppose the goal of the netlink protocol you are implementing is allow -configuration of a particular network device, therefore you want to -provide read/write access to various configuration options. The typical -"netlink way" of doing this would be to define two message types -\c MSG_SETCFG, \c MSG_GETCFG: - -\code -#define MSG_SETCFG 0x11 -#define MSG_GETCFG 0x12 -\endcode - -Sending a \c MSG_GETCFG request message will typically trigger a reply -with the message type \c MSG_SETCFG containing the current configuration. -In object oriented terms one would describe this as "the kernel sets -the local copy of the configuration in userspace". - -\msc -A,B; -A=>B [label="MSG_GETCFG (seq=1, NLM_F_REQUEST)"]; -A<=B [label="MSG_SETCFG (seq=1)"]; -\endmsc - -The configuration may be changed by sending a \c MSG_SETCFG which will -be responded to with either a ACK (see \ref core_ack) or a error -message (see \ref core_errmsg). - -\msc -A,B; -A=>B [label="MSG_SETCFG (seq=1, NLM_F_REQUEST, NLM_F_ACK)"]; -A<=B [label="ACK (seq=1)"]; -\endmsc - -Optionally, the kernel may send out notifications for configuration -changes allowing userspace to listen for changes instead of polling -frequently. Notifications typically reuse an existing message type -and rely on the application using a separate socket to differ between -requests and notifications but you may also specify a separate message -type. - -\msc -A,B; -A<=B [label="MSG_SETCFG (seq=0)"]; -\endmsc - -\subsubsection core_multipart 1.2.1 Multipart Messages - -Although in theory a netlink message can be up to 4GiB in size. The socket -buffers are very likely not large enough to hold message of such sizes. -Therefore it is common to limit messages to one page size (PAGE_SIZE) and -use the multipart mechanism to split large pieces of data into several -messages. A multipart message has the \c flag NLM_F_MULTI set and the -receiver is expected to continue receiving and parsing until the special -message type \c NLMSG_DONE is received. - -Multipart messages unlike fragmented ip packets must not be reassmbled -even though it is perfectly legal to do so if the protocols wishes to -work this way. Often multipart message are used to send lists or trees -of objects were each multipart message simply carries multiple objects -allow for each message to be parsed independently. - -\msc -A,B; -A=>B [label="GET (seq=1, NLM_F_REQUEST)"]; -A<=B [label="PUT (seq=1, NLM_F_MULTI)"]; -...; -A<=B [label="PUT (seq=1, NLM_F_MULTI)"]; -A<=B [label="NLMSG_DONE (seq=1)"]; -\endmsc - -\subsubsection core_errmsg 1.2.2 Error Message - -Error messages can be sent in response to a request. Error messages must -use the standard message type \c NLMSG_ERROR. The payload consists of a -error code and the original netlink mesage header of the request. - -\code -0 1 2 3 -0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -+-------------------------------------------------------------+ -| Length | -+------------------------------+------------------------------+ -| .nlmsg_type = NLMSG_ERROR | .nlmsg_flags = 0 | -+------------------------------+------------------------------+ -| Sequence number of the orig request | -+-------------------------------------------------------------+ -| Port number of the orig request | -+-------------------------------------------------------------+ -| Error Code (e.g. EINVAL) | -+-------------------------------------------------------------+ -| Netlink Message Header of orig. request | -. . -. . -+-------------------------------------------------------------+ -\endcode - -Error messages should set the sequence number to the sequence number -of the request which caused the error. - -\msc -A,B; -A=>B [label="GET (seq=1, NLM_F_REQUEST)"]; -A<=B [label="NLMSG_ERROR code=EINVAL (seq=1)"]; -\endmsc - -\subsubsection core_ack 1.2.3 ACKs - -A sender can request an ACK message to be sent back for each request -processed by setting the \c NLM_F_ACK flag in the request. This is typically -used to allow the sender to synchronize further processing until the -request has been processed by the receiver. - -\msc -A,B; -A=>B [label="GET (seq=1, NLM_F_REQUEST | NLM_F_ACK)"]; -A<=B [label="ACK (seq=1)"]; -\endmsc - -ACK messages also use the message type \c NLMSG_ERROR and payload format -but the error code is set to 0. - -\subsubsection core_msg_flags 1.3 Message Flags - -The following standard flags are defined - -\code -#define NLM_F_REQUEST 1 -#define NLM_F_MULTI 2 -#define NLM_F_ACK 4 -#define NLM_F_ECHO 8 -\endcode - -- \c NLM_F_REQUEST - Message is a request, see \ref core_msg_type. -- \c NLM_F_MULTI - Multipart message, see \ref core_multipart. -- \c NLM_F_ACK - ACK message requested, see \ref core_ack. -- \c NLM_F_ECHO - Request to echo the request. - -The flag \c NLM_F_ECHO is similar to the \c NLM_F_ACK flag. It can be -used in combination with \c NLM_F_REQUEST and causes a notification -which is sent as a result of a request to also be sent to the sender -regardless of whether the sender has subscribed to the corresponding -multicast group or not. See \ref core_multicast. - -Additional universal message flags are defined which only apply for -\c GET requests: - -\code -#define NLM_F_ROOT 0x100 -#define NLM_F_MATCH 0x200 -#define NLM_F_ATOMIC 0x400 -#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH) -\endcode - -- \c NLM_F_ROOT - Return based on root of tree. -- \c NLM_F_MATCH - Return all matching entries. -- \c NLM_F_ATOMIC - Obsoleted, once used to request an atomic operation. -- \c NLM_F_DUMP - Return a list of all objects \c (NLM_F_ROOT|NLM_F_MATCH). - -Use of these flags is completely optional and many netlink protocols only -make use of the \c NLM_F_DUMP flag which typically requests the receiver -to send a list of all objects in the context of the message type as a -sequence of multipart messages (see \ref core_multipart). - -Another set of flags exist related to \c NEW or \c SET requests. These -flags are mutually exclusive to the \c GET flags: - -\code -#define NLM_F_REPLACE 0x100 -#define NLM_F_EXCL 0x200 -#define NLM_F_CREATE 0x400 -#define NLM_F_APPEND 0x800 -\endcode - -- \c NLM_F_REPLACE - Replace an existing object if it exists. -- \c NLM_F_EXCL - Do not update object if it exists already. -- \c NLM_F_CREATE - Create object if it does not exist yet. -- \c NLM_F_APPEND - Add object at end of list. - -Behaviour of these flags may differ slightly between different netlink -protocols. - -\subsection core_seq 1.4 Sequence Numbers - -Netlink allows the use of sequence numbers to help relate replies to -requests. It should be noted that unlike in protocols such as TCP there -is no strict enforcment of the sequence number. The sole purpose of -sequence numbers is to assist a sender in relating replies to the -corresponding requests. See \ref core_msg_type for more information. - -Sequence numbers are managed on a per socket basis, see -\ref core_sk_seq_num for more information on how to use sequence numbers. - -\subsection core_multicast 1.5 Multicast Groups - -TODO - -See \ref core_sk_groups. - -\section sk_doc 2. Netlink Sockets - -In order to use the netlink protocol, a netlink socket is required. Each -socket defines a completely independent context for sending and receiving -of messages. An application may use multiple sockets for the same netlink -protocol, e.g. one socket to send requests and receive replies and another -socket subscribed to a multicast group to receive notifications. - -\subsection core_sk_alloc 2.1 Socket Allocation & Freeing - -The netlink socket and all its related attributes are represented by -struct nl_sock. - -\code -#include - -struct nl_sock *nl_socket_alloc(void) -void nl_socket_free(struct nl_sock *sk) -\endcode - -\subsection core_sk_seq_num 2.2 Sequence Numbers - -The library will automatically take care of sequence number handling for -the application. A sequence number counter is stored in struct nl_sock which -is meant to be used when sending messages which will produce a reply, error -or any other message which needs to be related to the original message. - -The counter can be used directly with the function nl_socket_use_seq() -which will return the current value of the counter and increment it by -one afterwards. - -\code -#include - -unsigned int nl_socket_use_seq(struct nl_sock *sk); -\endcode - -Most applications will not want to deal with sequence number handling -themselves though. When using nl_send_auto() the sequence number is -filled out automatically and matched again on the receiving side. See -\ref core_send_recv for more information. - -This behaviour can and must be disabled if the netlink protocol -implemented does not use a request/reply model, e.g. when a socket is -used to receive notification messages. - -\code -#include - -void nl_socket_disable_seq_check(struct nl_sock *sk); -\endcode - -\subsection core_sk_groups 2.3 Multicast Group Subscriptions - -Each socket can subscribe to any number of multicast groups of the -netlink protocol it is connected to. The socket will then receive a copy -of each message sent to any of the groups. Multicast groups are commonly -used to implement event notifications. - -Prior to kernel 2.6.14 the group subscription was performed using a bitmask -which limited the number of groups per protocol family to 32. This outdated -interface can still be accessed via the function nl_join_groups even though -it is not recommended for new code. - -\code -#include - -void nl_join_groups(struct nl_sock *sk, int bitmask); -\endcode - -Starting with 2.6.14 a new method was introduced which supports subscribing -to an almost infinite number of multicast groups. - -\code -#include - -int nl_socket_add_memberships(struct nl_sock *sk, int group, ...); -int nl_socket_drop_memberships(struct nl_sock *sk, int group, ...); -\endcode - -\subsubsection core_sk_group_example 2.3.1 Multicast Example - -\include sk_group_example.c - -\subsection core_sk_cb 2.4 Modifiying Socket Callback Configuration - -See \ref core_cb for more information on callback hooks and overwriting -capabilities - -Each socket is assigned a callback configuration which controls the -behaviour of the socket. This is f.e. required to have a separate message -receive function per socket. It is perfectly legal to share callback -configurations between sockets though. - -The following functions can be used to access and set the callback -configuration of a socket: - -\code -#include - -struct nl_cb *nl_socket_get_cb(const struct nl_sock *sk); -void nl_socket_set_cb(struct nl_sock *sk, struct nl_cb *cb); -\endcode - -Additionaly a shortcut exists to modify the callback configuration assigned -to a socket directly: - -\code -#include - -int nl_socket_modify_cb(struct nl_sock *sk, enum nl_cb_type type, enum nl_cb_kind kind, - nl_recvmsg_msg_cb_t func, void *arg); -\endcode - -Example: -\code -#include - -// Call my_input() for all valid messages received in socket sk -nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, my_input, NULL); -\endcode - -\subsection core_sk_attrs 2.5 Socket Attributes - -\subsubsection core_sk_local_port 2.5.1 Local Port - -The local port number uniquely identifies the socket and is used to -address it. A unique local port is generated automatically when the socket -is allocated. It will consist of the Process ID (22 bits) and a random -number (10 bits) thus allowing up to 1024 sockets per process. - -\code -#include - -uint32_t nl_socket_get_local_port(const struct nl_sock *sk); -void nl_socket_set_local_port(struct nl_sock *sk, uint32_t port); -\endcode - -\b Note: Overwriting the local port is possible but you have to ensure -that the provided value is unique and no other socket in any other -application is using the same value. - -\subsubsection core_sk_peer_port 2.5.2 Peer Port - -A peer port can be assigned to the socket which will result in all unicast -messages sent over the socket to be addresses to the peer. If no peer is -specified, the message is sent to the kernel which will try to automatically -bind the socket to a kernel side socket of the same netlink protocol family. -It is common practice not to bind the socket to a peer port as typically -only one kernel side socket exists per netlink protocol family. - -\code -#include - -uint32_t nl_socket_get_peer_port(const struct nl_sock *sk); -void nl_socket_set_peer_port(struct nl_sock *sk, uint32_t port); -\endcode - -\subsubsection core_sk_fd 2.5.3 File Descriptor - -Netlink uses the BSD socket interface, therefore a file descriptor -is behind each socket and you may use it directly. - -\code -#include - -int nl_socket_get_fd(const struct nl_sock *sk); -\endcode - -If a socket is used to only receive notifications it usually is best -to put the socket in non-blocking mode and periodically poll for new -notifications. - -\code -#include - -int nl_socket_set_nonblocking(const struct nl_sock *sk); -\endcode - -\subsubsection core_sk_buffer_size 2.5.4 Send/Receive Buffer Size - -The socket buffer is used to queue netlink messages between sender -and receiver. The size of these buffers specifies the maximum size -you will be able to write() to a netlink socket, i.e. it will indirectly -define the maximum message size. The default is 32KiB. - -\code -#include - -int nl_socket_set_buffer_size(struct nl_sock *sk, int rx, int tx); -\endcode - - -\subsubsection core_sk_cred 2.5.5 Enable/Disable Credentials - -TODO - -\code -#include - -int nl_socket_set_passcred(struct nl_sock *sk, int state); -\endcode - -\subsubsection core_sk_auto_ack 2.5.6 Enable/Disable Auto-ACK Mode - -The following functions allow to enable/disable Auto-ACK mode on a -socket. See \ref core_auto_ack for more information on what implications -that has. Auto-ACK mode is enabled by default. - -\code -#include - -void nl_socket_enable_auto_ack(struct nl_sock *sk); -void nl_socket_disable_auto_ack(struct nl_sock *sk); -\endcode - -\subsubsection core_sk_msg_peek 2.5.7 Enable/Disable Message Peeking - -If enabled, message peeking causes nl_recv() to try and use MSG_PEEK to -retrieve the size of the next message received and allocate a buffer -of that size. Message peeking is enabled by default but can be disabled -using the following function: - -\code -#include - -void nl_socket_enable_msg_peek(struct nl_sock *sk); -void nl_socket_disable_msg_peek(struct nl_sock *sk); -\endcode - -\subsubsection core_sk_pktinfo 2.5.8 Enable/Disable Receival of Packet Information - -If enabled, each received netlink message from the kernel will include an -additional struct nl_pktinfo in the control message. The following function -can be used to enable/disable receival of packet information. - -\code -#include - -int nl_socket_recv_pktinfo(struct nl_sock *sk, int state); -\endcode - -\b Note: Processing of NETLINK_PKTINFO has not been implemented yet. - -\section core_send_recv 3. Sending and Receiving of Messages / Data - -\subsection core_send 3.1 Sending Netlink Messages - -The standard method of sending a netlink message over a netlink socket -is to use the function nl_send_auto(). It will automatically complete -the netlink message by filling the missing bits and pieces in the -netlink message header and will deal with addressing based on the -options and address set in the netlink socket. The message is then passed -on to nl_send(). - -If the default sending semantics implemented by nl_send() do not suit the -application, it may overwrite the sending function nl_send() by -specifying an own implementation using the function nl_cb_overwrite_send(). - -\code - nl_send_auto(sk, msg) - | - |-----> nl_complete_msg(sk, msg) - | - | - | Own send function specified via nl_cb_overwrite_send() - |- - - - - - - - - - - - - - - - - - - - - v v - nl_send(sk, msg) send_func() -\endcode - -\subsubsection core_nl_send 3.1.1 Using nl_send() - -If you do not require any of the automatic message completion functionality -you may use nl_send() directly but beware that any internal calls to -nl_send_auto() by the library to send netlink messages will still use -nl_send(). Therefore if you wish to use any higher level interfaces and the -behaviour of nl_send() is to your dislike then you must overwrite the -nl_send() function via nl_cb_overwrite_send() - -The purpose of nl_send() is to embed the netlink message into a iovec -structure and pass it on to nl_send_iovec(). - -\code - nl_send(sk, msg) - | - v - nl_send_iovec(sk, msg, iov, iovlen) -\endcode - -\subsubsection core_nl_send_iovec 3.1.2 Using nl_send_iovec() - -nl_send_iovec() expects a finalized netlink message and fills out the -struct msghdr used for addressing. It will first check if the struct nl_msg -is addressed to a specific peer (see nlmsg_set_dst()). If not, it will try -to fall back to the peer address specified in the socket (see -nl_socket_set_peer_port(). Otherwise the message will be sent unaddressed -and it is left to the kernel to find the correct peer. - -nl_send_iovec() also adds credentials if present and enabled -(see \ref core_sk_cred). - -The message is then passed on to nl_sendmsg(). - -\code - nl_send_iovec(sk, msg, iov, iovlen) - | - v - nl_sendmsg(sk, msg, msghdr) -\endcode - -\subsubsection core_nl_sendmsg 3.1.3 Using nl_sendmsg() - -nl_sendmsg() expects a finalized netlink message and an optional struct -msghdr containing the peer address. It will copy the local address as -defined in the socket (see nl_socket_set_local_port()) into the netlink -message header. - -At this point, construction of the message finished and it is ready to -be sent. - -\code - nl_sendmsg(sk, msg, msghdr) - |- - - - - - - - - - - - - - - - - - - - v - | NL_CB_MSG_OUT() - |<- - - - - - - - - - - - - - - - - - - -+ - v - sendmsg() -\endcode - -Before sending the application has one last chance to modify the message. -It is passed to the NL_CB_MSG_OUT callback function which may inspect or -modify the message and return an error code. If this error code is NL_OK -the message is sent using sendmsg() resulting in the number of bytes -written being returned. Otherwise the message sending process is aborted -and the error code specified by the callback function is returned. See -\ref core_sk_cb for more information on how to set callbacks. - -\subsubsection core_send_raw 3.1.4 Sending Raw Data with nl_sendto() - -If you wish to send raw data over a netlink socket, the following -function will pass on any buffer provided to it directly to sendto(): - -\code -#include - -int nl_sendto(struct nl_sock *sk, void *buf, size_t size); -\endcode - -\subsubsection core_send_simple 3.1.5 Sending of Simple Messages - -A special interface exists for sending of trivial messages. The function -expects the netlink message type, optional netlink message flags, and an -optional data buffer and data length. -\code -#include - -int nl_send_simple(struct nl_sock *sk, int type, int flags, - void *buf, size_t size); -\endcode - -The function will construct a netlink message header based on the message -type and flags provided and append the data buffer as message payload. The -newly constructed message is sent with nl_send_auto(). - -The following example will send a netlink request message causing the -kernel to dump a list of all network links to userspace: -\include nl_send_simple.c - -\subsection core_recv 3.2 Receiving Netlink Messages - -The easiest method to receive netlink messages is to call nl_recvmsgs_default(). -It will receive messages based on the semantics defined in the socket. The -application may customize these in detail although the default behaviour will -probably suit most applications. - -nl_recvmsgs_default() will also be called internally by the library whenever -it needs to receive and parse a netlink message. - -The function will fetch the callback configuration stored in the socket and -call nl_recvmsgs(): - -\code - nl_recvmsgs_default(sk) - | - | cb = nl_socket_get_cb(sk) - v - nl_recvmsgs(sk, cb) -\endcode - -\subsubsection core_nl_recvmsgs 3.2.1 Using nl_recvmsgs() - -nl_recvmsgs() implements the actual receiving loop, it blocks until a -netlink message has been received unless the socket has been put into -non-blocking mode. - -See \ref core_recvmsgs for more information on the behaviour of -nl_recvmsgs(). - -For the unlikely scenario that certain required receive characteristics -can not be achieved by fine tuning the internal recvmsgs function using -the callback configuration (see \ref core_sk_cb) the application may -provide a complete own implementation of it and overwrite all calls to -nl_recvmsgs() with the function nl_cb_overwrite_recvmsgs(). - -\code - nl_recvmsgs(sk, cb) - | - | Own recvmsgs function specified via nl_cb_overwrite_recvmsgs() - |- - - - - - - - - - - - - - - - - - - - - v v - internal_recvmsgs() my_recvmsgs() -\endcode - -\subsubsection core_recvmsgs 3.2.2 Receive Characteristics - -If the application does not provide its own recvmsgs() implementation -with the function nl_cb_overwrite_recvmsgs() the following characteristics -apply while receiving data from a netlink socket: - -\code - internal_recvmsgs() - | -+-------------->| Own recv function specified with nl_cb_overwrite_recv() -| |- - - - - - - - - - - - - - - - -| v v -| nl_recv() my_recv() -| |<- - - - - - - - - - - - - - -+ -| |<-------------+ -| v | More data to parse? (nlmsg_next()) -| Parse Message | -| |--------------+ -| v -+------- NLM_F_MULTI set? - | - v - (SUCCESS) -\endcode - -The function nl_recv() is invoked first to receive data from the netlink -socket. This function may be overwritten by the application by an own -implementation using the function nl_cb_overwrite_recv(). This may be -useful if the netlink byte stream is in fact not received from a socket -directly but is read from a file or another source. - -If data has been read, it will be attemped to parse the data -(see \ref core_recv_parse). This will be done repeately until the parser -returns NL_STOP, an error was returned or all data has been parsed. - -In case the last message parsed successfully was a multipart message -(see \ref core_multipart) and the parser did not quit due to either an -error or NL_STOP nl_recv() respectively the applications own implementation -will be called again and the parser starts all over. - -See \ref core_recv_parse for information on how to extract valid netlink -messages from the parser and on how to control the behaviour of it. - -\subsubsection core_recv_parse 3.2.3 Parsing Characteristics - -The internal parser is invoked for each netlink message received from a -netlink socket. It is typically fed by nl_recv() (see \ref core_recvmsgs). - -The parser will first ensure that the length of the data stream provided -is sufficient to contain a netlink message header and that the message -length as specified in the message header does not exceed it. - -If this criteria is met, a new struct nl_msg is allocated and the message -is passed on to the the callback function NL_CB_MSG_IN if one is set. Like -any other callback function, it may return NL_SKIP to skip the current -message but continue parsing the next message or NL_STOP to stop parsing -completely. - -The next step is to check the sequence number of the message against the -currently expected sequence number. The application may provide its own -sequence number checking algorithm by setting the callback function -NL_CB_SEQ_CHECK to its own implementation. In fact, calling -nl_socket_disable_seq_check() to disable sequence number checking will -do nothing more than set the NL_CB_SEQ_CHECK hook to a function which -always returns NL_OK. - -Another callback hook NL_CB_SEND_ACK exists which is called if the -message has the NLM_F_ACK flag set. Although I am not aware of any -userspace netlink socket doing this, the application may want to send -an ACK message back to the sender (see \ref core_ack). - -\code - parse() - | - v - nlmsg_ok() --> Ignore - | - |- - - - - - - - - - - - - - - v - | NL_CB_MSG_IN() - |<- - - - - - - - - - - - - - -+ - | - |- - - - - - - - - - - - - - - v - Sequence Check NL_CB_SEQ_CHECK() - |<- - - - - - - - - - - - - - -+ - | - | Message has NLM_F_ACK set - |- - - - - - - - - - - - - - - v - | NL_CB_SEND_ACK() - |<- - - - - - - - - - - - - - -+ - | - Handle Message Type -\endcode - -\subsection core_auto_ack 3.3 Auto-ACK Mode - -TODO - -\section core_msg 4. Netlink Message Parsing & Construction - -\subsection core_msg_format 4.1 Message Format - -See \ref proto_fund for an introduction to the netlink protocol and its -message format. - -\subsubsection core_msg_fmt_align 4.1.1 Alignment - -Most netlink protocols enforce a strict alignment policy for all boundries. -The alignment value is defined by NLMSG_ALIGNTO and is fixed to 4 bytes. -Therefore all netlink message headers, begin of payload sections, protocol -specific headers, and attribute sections must start at an offset which is -a multiple of NLMSG_ALIGNTO. - -\code -#include - -int nlmsg_size(int payloadlen); -int nlmsg_total_size(int payloadlen); -\endcode - -The library provides a set of function to handle alignment requirements -automatically. The function nlmsg_total_size() returns the total size -of a netlink message including the padding to ensure the next message -header is aligned correctly. - -\code - <----------- nlmsg_total_size(len) ------------> - <----------- nlmsg_size(len) ------------> - +-------------------+- - -+- - - - - - - - +- - -+-------------------+- - - - | struct nlmsghdr | Pad | Payload | Pad | struct nlsmghdr | - +-------------------+- - -+- - - - - - - - +- - -+-------------------+- - - - <---- NLMSG_HDRLEN -----> <- NLMSG_ALIGN(len) -> <---- NLMSG_HDRLEN --- -\endcode - -If you need to know if padding needs to be added at the end of a message, -nlmsg_padlen() returns the number of padding bytes that need to be added -for a specific payload length. - -\code -#include -int nlmsg_padlen(int payloadlen); -\endcode - -\subsection core_msg_parse 4.2 Parsing a Message - -The library offers two different methods of parsing netlink messages. -It offers a low level interface for applications which want to do all -the parsing manually. This method is described below. Alternatively -the library also offers an interface to implement a parser as part of -a cache operations set which is especially useful when your protocol -deals with objects of any sort such as network links, routes, etc. -This high level interface is described in \ref core_cache. - -\subsubsection core_msg_split 4.2.1 Splitting a byte stream into separate messages - -What you receive from a netlink socket is typically a stream of -messages. You will be given a buffer and its length, the buffer may -contain any number of netlink messages. - -The first message header starts at the beginning of message stream. Any -subsequent message headers are access by calling nlmsg_next() on the -previous header. - -\code -#include - -struct nlmsghdr *nlmsg_next(struct nlmsghdr *hdr, int *remaining); -\endcode - -The function nlmsg_next() will automatically substract the size of -the previous message from the remaining number of bytes. - -Please note, there is no indication in the previous message whether -another message follows or not. You must assume that more messages -follow until all bytes of the message stream have been processed. - -To simplify this, the function nlmsg_ok() exists which returns true if -another message fits into the remaining number of bytes in the message -stream. nlmsg_valid_hdr() is similar, it checks whether a specific -netlink message contains at least a minimum of payload. - -\code -#include - -int nlmsg_valid_hdr(const struct nlmsghdr *hdr, int payloadlen); -int nlmsg_ok(const struct nlmsghdr *hdr, int remaining); -\endcode - -A typical use of these functions looks like this: - -\include my_parse.c - -\b Note: nlmsg_ok() only returns true if the \b complete message including - the message payload fits into the remaining buffer length. It will - return false if only a part of it fits. - -The above can also be written using the iterator nlmsg_for_each(): - -\include nlmsg_for_each.c - - -\subsubsection core_msg_payload 4.2.2 Message Payload - -The message payload is appended to the message header and is guranteed -to start at a multiple of NLMSG_ALIGNTO. Padding at the end of the -message header is added if necessary to ensure this. The function -nlmsg_data() will calculate the necessary offset based on the message -and returns a pointer to the start of the message payload. - -\code -#include - -void *nlmsg_data(const struct nlmsghdr *nlh); -void *nlmsg_tail(const struct nlmsghdr *nlh); -int nlmsg_datalen(const struct nlmsghdr *nlh); -\endcode - -The length of the message payload is returned by nlmsg_datalen(). - -\code - <--- nlmsg_datalen(nlh) ---> - +-------------------+- - -+----------------------------+- - -+ - | struct nlmsghdr | Pad | Payload | Pad | - +-------------------+- - -+----------------------------+- - -+ -nlmsg_data(nlh) ---------------^ ^ -nlmsg_tail(nlh) --------------------------------------------------^ -\endcode - -The payload may consist of arbitary data but may have strict alignment -and formatting rules depening on the actual netlink protocol. - -\subsubsection core_msg_parse_attr 4.2.3 Message Attributes - -Most netlink protocols use netlink attributes. It not only makes the -protocol self documenting but also gives flexibility in expanding -the protocol at a later point. New attributes can be added at any time -and older attributes can be obsoleted by newer ones without breaking -binary compatibility of the protocol. - -\code - <---------------------- payload -------------------------> - <----- hdrlen ----> <- nlmsg_attrlen(nlh, hdrlen) -> - +-------------------+- - -+----- ------------+- - -+--------------------------------+- - -+ - | struct nlmsghdr | Pad | Protocol Header | Pad | Attributes | Pad | - +-------------------+- - -+-------------------+- - -+--------------------------------+- - -+ -nlmsg_attrdata(nlh, hdrlen) -----------------------------^ -\endcode - -The function nlmsg_attrdata() returns a pointer to the begin of the -attributes section. The length of the attributes section is returned -by the function nlmsg_attrlen(). - -\code -#include - -struct nlattr *nlmsg_attrdata(const struct nlmsghdr *hdr, int hdrlen); -int nlmsg_attrlen(const struct nlmsghdr *hdr, int hdrlen); -\endcode - -See \ref core_attr for more information on how to use netlink attributes. - -\subsubsection core_nlmsg_parse 4.2.4 Parsing a Message the Easy Way - -The function nlmsg_parse() validate a complete netlink message in -one step. If \p hdrlen > 0 it will first call nlmsg_valid_hdr() to -check if the protocol header fits into the message. If there is -more payload to parse, it will assume it to be attributes and parse -the payload accordingly. The function behaves exactly like nla_parse() -when parsing attributes, see \ref core_attr_nla_parse. - -\code -int nlmsg_parse(struct nlmsghdr *hdr, int hdrlen, struct nlattr **attrs, - int maxtype, struct nla_policy *policy); -\endcode - -The function nlmsg_validate() is based on nla_validate() and behaves -exactly the same as nlmsg_parse() except that it only validates and will -not fill a array with pointers to each attribute. - -\code -int nlmsg_validate(struct nlmsghdr *hdr, int hdrlen, intmaxtype, - struct nla_policy *policy); -\endcode - -See \ref core_attr_nla_parse for an example and more information on -attribute parsing. - -\subsection core_msg_constr 4.3 Construction of a Message - -See \ref core_msg_format for information on the netlink message format -and alignment requirements. - -Message construction is based on struct nl_msg which uses an internal -buffer to store the actual netlink message. struct nl_msg \b does \b not -point to the netlink message header. Use nlmsg_hdr() to retrieve a -pointer to the netlink message header. - -At allocation time, a maximum message size is specified. It defaults to -a page (PAGE_SIZE). The application constructing the message will reserve -space out of this maximum message size repeatedly for each header or -attribute added. This allows construction of messages across various -layers of code where lower layers do not need to know about the space -requirements of upper layers. - -Why is setting the maximum message size necessary? This question -is often raised in combination with the proposed solution of reallocating -the message payload buffer on the fly using realloc(). While it is -possible to reallocate the buffer during construction using nlmsg_expand() -it will make all pointers into the message buffer become stale. This -breaks usage of nlmsg_hdr(), nla_nest_start(), and nla_nest_end() and is -therefore not acceptable as default behaviour. - -\subsubsection core_msg_alloc 4.3.1 Allocating struct nl_msg - -The first step in constructing a new netlink message it to allocate a -\c struct \c nl_msg to hold the message header and payload. Several -functions exist to simplify various tasks. - -\code -#include - -struct nl_msg *nlmsg_alloc(void); -void nlmsg_free(struct nl_msg *msg); -\endcode - -The function nlmsg_alloc() is the default message allocation function. -It allocates a new message using the default maximum message size which -equals to one page (PAGE_SIZE). The application can change the default -size for messages by calling nlmsg_set_default_size(): - -\code -void nlmsg_set_default_size(size_t); -\endcode - -\b Note: Calling nlmsg_set_default_size() does not change the maximum - message size of already allocated messages. - -\code -struct nl_msg *nlmsg_alloc_size(size_t max); -\endcode - -Instead of changing the default message size, the function -nlmsg_alloc_size() can be used to allocate a message with a individual -maximum message size. - - -If the netlink message header is already known at allocation time, the -application may sue nlmsg_inherit(). It will allocate a message using -the default maximum message size and copy the header into the message. -Calling nlmsg_inherit with \p set to NULL is equivalent to calling -nlmsg_alloc(). - -\code -struct nl_msg *nlmsg_inherit(struct nlmsghdr *hdr); -\endcode - -Alternatively nlmsg_alloc_simple() takes a netlink message type and -netlink message flags. It is equivalent to nlmsg_inherit() except that it -takes the two common header fields as arguments instead of a complete -header. - -\code -#include - -struct nl_msg *nlmsg_alloc_simple(int nlmsg_type, int flags); -\endcode - -\subsubsection core_msg_nlmsg_put 4.3.2 Appending the netlink message header - -After allocating struct nl_msg, the netlink message header needs to be -added unless one of the function nlmsg_alloc_simple() or nlmsg_inherit() -have been used for allocation in which case this step will replace the -netlink message header already in place. - -\code -#include - -struct nlmsghdr *nlmsg_put(struct nl_msg *msg, uint32_t port, uint32_t seqnr, - int nlmsg_type, int payload, int nlmsg_flags); -\endcode - -The function nlmsg_put() will build a netlink message header out of -\p nlmsg_type, \p nlmsg_flags, \p seqnr, and \p port and copy it into -the netlink message. \p seqnr can be set to \p NL_AUTO_SEQ to indiciate -that the next possible sequence number should be used automatically. To -use this feature, the message must be sent using the function -nl_send_auto(). Like \p port, the argument \p seqnr can be set to -\c NL_AUTO_PORT indicating that the local port assigned to the socket -should be used as source port. This is generally a good idea unless you -are replying to a request. See \ref proto_fund for more information on -how to fill the header. - -The argument \p payload can be used by the application to reserve room -for additional data after the header. A value of > 0 is equivalent to -calling nlmsg_reserve(msg, payload, NLMSG_ALIGNTO). See -\ref core_msg_reserve for more information on reserving room for data. - -\b Example: -\include nlmsg_put.c - -\subsubsection core_msg_reserve 4.3.3 Reserving room at the end of the message - -Most functions described later on will automatically take care of -reserving room for the data that is added to the end of the netlink -message. In some situations it may be requried for the application -to reserve room directly though. - -\code -#include - -void *nlmsg_reserve(struct nl_msg *msg, size_t len, int pad); -\endcode - -The function nlmsg_reserve() reserves \p len bytes at the end of the -netlink message and returns a pointer to the start of the reserved area. -The \p pad argument can be used to request \p len to be aligned to any -number of bytes prior to reservation. - -The following example requests to reserve a 17 bytes area at the end of -message aligned to 4 bytes. Therefore a total of 20 bytes will be -reserved. - -\code -#include - -void *buf = nlmsg_reserve(msg, 17, 4); -\endcode - -\b Note: nlmsg_reserve() will \b not align the start of the buffer. Any - alignment requirements must be provided by the owner of the - previous message section. - -\subsubsection core_msg_append 4.3.4 Appending data at the end of the message - -The function nlmsg_append() appends \p len bytes at the end of the message, -padding it if requested and necessary. - -\code -#include - -int nlmsg_append(struct nl_msg *msg, void *data, size_t len, int pad); -\endcode - -It is equivalent to calling nlmsg_reserve() and memcpy()ing the data into -the freshly reserved data section. - -\b Note: nlmsg_append() will \b not align the start of the data. Any - alignment requirements must be provided by the owner of the - previous message section. - -\subsubsection core_msg_put_attr 4.3.5 Adding attribtues to a message - -Construction of attributes and addition of attribtues to the message is -covereted in section \ref core_attr. - -\section core_attr 5. Netlink Attributes - -Any form of payload should be encoded as netlink attributes whenever -possible. Use of attributes allows to extend any netlink protocol in -the future without breaking binary compatibility. F.e. Suppose your -device may currently be using 32 bit counters for statistics but years -later the device switches to maintaining 64 bit counters to account -for faster network hardware. If your protocol is using attributes the -move to 64 bit counters is trivial and only involves in sending an -additional attribute containing the 64 bit variants while still -providing the old legacy 32 bit counters. If your protocol is not using -attributes you will not be able to switch data types without breaking -all existing users of the protocol. - -The concept of nested attributes also allows for subsystems of your -protocol to implement and maintain their own attribute schemas. Suppose -a new generation of network device is introduced which requires a -completely new set of configuration settings which was unthinkable when -the netlink protocol was initially designed. Using attributes the new -generation of devices may define a new attribute and fill it with its -own new structure of attributes which extend or even obsolete the old -attributes. - -Therefore, \e always use attributes even if you are almost certain that -the message format will never ever change in the future. - -\subsection core_attr_format 5.1 Attribute Format - -Netlink attributes allow for any number of data chunks of arbitary -length to be attached to a netlink message. See \ref core_msg_parse_attr -for more information on where attributes are stored in the message. - -The format of the attributes data returned by nlmsg_attrdata() is as -follows: - -\code - <----------- nla_total_size(payload) -----------> - <---------- nla_size(payload) -----------> - +-----------------+- - -+- - - - - - - - - +- - -+-----------------+- - - - | struct nlattr | Pad | Payload | Pad | struct nlattr | - +-----------------+- - -+- - - - - - - - - +- - -+-----------------+- - - - <---- NLA_HDRLEN -----> <--- NLA_ALIGN(len) ---> <---- NLA_HDRLEN --- -\endcode - -Every attribute must start at an offset which is a multiple of -\c NLA_ALIGNTO (4 bytes). If you need to know whether an attribute needs -to be padded at the end, the function nla_padlen() returns the number -of padding bytes that will or need to be added. - -\code -0 1 2 3 -0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -+-------------------------------------------------------------+ -| Length | Type | -+------------------------------+------------------------------+ -| Attribute Payload | -. . -. . -+-------------------------------------------------------------+ -\endcode - -Every attribute is encoded with a type and length field, both 16 bits, -stored in the attribute header (struct nlattr) preceding the attribute -payload. The length of an attribute is used to calculate the offset to -the next attribute. - -\subsection core_attr_parse 5.2 Parsing Attributes - -\subsubsection core_attr_parse_split 5.2.1 Splitting an Attributes Stream into Attributes - -Although most applications will use one of the functions from the -nlmsg_parse() family (See \ref core_attr_nla_parse) an interface -exists to split the attributes stream manually. - -As described in \ref core_attr_format the attributes section contains a -infinite sequence or stream of attributes. The pointer returned by -nlmsg_attrdata() (See \ref core_msg_parse_attr) points to the first -attribute header. Any subsequent attribute is accessed with the function -nla_next() based on the previous header. - -\code -#include - -struct nlattr *nla_next(const struct nlattr *attr, int *remaining); -\endcode - -The semantics are equivalent to nlmsg_next() and thus nla_next() will also -subtract the size of the previous attribute from the remaining number of -bytes in the attributes stream. - -Like messages, attributes do not contain an indicator whether another -attribute follows or not. The only indication is the number of bytes left -in the attribute stream. The function nla_ok() exists to determine whether -another attribute fits into the remaining number of bytes or not. - -\code -#include - -int nla_ok(const struct nlattr *attr, int remaining); -\endcode - -A typical use of nla_ok() and nla_next() looks like this: - -\include nla_ok.c - -\b Note: nla_ok() only returns true if the \b complete attributes - including the attribute payload fits into the remaining number - of bytes. - -\subsubsection core_attr_payload 5.2.2 Accessing Attribute Header and Payload - -Once the individual attributes have been sorted out by either splitting -the attributes stream or using another interface the attribute header -and payload can be accessed. - -\code - <- nla_len(hdr) -> - +-----------------+- - -+- - - - - - - - - +- - -+ - | struct nlattr | Pad | Payload | Pad | - +-----------------+- - -+- - - - - - - - - +- - -+ -nla_data(hdr) ---------------^ -\endcode - -The functions nla_len() and nla_type() can be used to access the attribute -header. nla_len() will return the length of the payload not including -eventual padding bytes. nla_type returns the attribute type. - -\code -#include - -int nla_len(const struct nlattr *hdr); -int nla_type(const struct nlattr *hdr); -\endcode - -The function nla_data() will return a pointer to the attribute payload. -Please note that due to NLA_ALIGNTO being 4 bytes it may not be safe to -cast and dereference the pointer for any datatype larger than 32 bit -depending on the architecture the application is run on. - -\code -#include - -void *nla_data(const struct nlattr *hdr); -\endcode - -\b Note: Never rely on the size of a payload being what you expect it to - be. \e Always verify the payload size and make sure that it - matches your expectations. See \ref core_attr_validation. - -\subsubsection core_attr_validation 5.2.3 Attribute Validation - -When receiving netlink attributes, the receiver has certain expections -on how the attributes should look like. These expectations must be -defined to make sure the sending side meets our expecations. For this -purpose, a attribute validation interface exists which must be used -prior to accessing any payload. - -All functions providing attribute validation functionality are based -on struct nla_policy: - -\code -struct nla_policy { - uint16_t type; - uint16_t minlen; - uint16_t maxlen; -}; -\endcode - -The \p type member specifies the datatype of the attribute, e.g. -NLA_U32, NLA_STRING, NLA_FLAG. The default is NLA_UNSPEC. The \p minlen -member defines the minmum payload length of an attribute to be -considered a valid attribute. The value for \p minlen is implicit for -most basic datatypes such as integers or flags. The \p maxlen member -can be used to define a maximum payload length for an attribute to -still be considered valid. - -\b Note: Specyfing a maximum payload length is not recommended when -encoding structures in an attribute as it will prevent any extension of -the structure in the future. Something that is frequently done in -netlink protocols and does not break backwards compatibility. - -One of the functions which use struct nla_policy is nla_validate(). -The function expects an array of struct nla_policy and will access the -array using the attribute type as index. If an attribute type is out -of bounds the attribute is assumed to be valid. This is intentional -behaviour to allow older applications not yet aware of recently -introduced attributes to continue functioning. - -\code -#include - -int nla_validate(struct nlattr *head, int len, int maxtype, - struct nla_policy *policy); -\endcode - -The function nla_validate() returns 0 if all attributes are valid, -otherwise a validation failure specific error code is returned. - -Most applications will rarely use nla_validate() directly but use -nla_parse() instead which takes care of validation in the same way but -also parses the the attributes in the same step. See -\ref core_attr_nla_parse for an example and more information. - -The validation process in detail: --# If attribute type is 0 or exceeds \p maxtype attribute is - considered valid, 0 is returned. --# If payload length is < \p minlen, -NLE_ERANGE is returned. --# If \p maxlen is defined and payload exceeds it, NLE_ERANGE - is returned. --# Datatype specific requirements rules, see \ref core_attr_data_type. --# If all is ok, 0 is returned. - -\subsubsection core_attr_nla_parse 5.2.4 Parsing Attributes the Easy Way - -Most applications will not want to deal with splitting attribute streams -themselves as described in \ref core_attr_parse_split. A much easier -method is to use nla_parse(). - -\code -#include - -int nla_parse(struct nlattr **attrs, int maxtype, struct nlattr *head, - int len, struct nla_policy *policy); -\endcode - -The function nla_parse() will iterate over a stream of attributes, -validate each attribute as described in \ref core_attr_validation. If -the validation of all attributes succeeds, a pointer to each attribute -is stored in the \p attrs array at \c attrs[nla_type(attr)]. - -As an alernative to nla_parse() the function nlmsg_parse() can be used -to parse the message and its attributes in one step. See -\ref core_nlmsg_parse for information on how to use these functions. - -\b Example: - -The following example demonstrates how to parse a netlink message sent -over a netlink protocol which does not use protocol headers. The example -does enforce a attribute policy however, the attribute MY_ATTR_FOO must -be a 32 bit integer, and the attribute MY_ATTR_BAR must be a string with -a maximum length of 16 characters. - -\include nlmsg_parse.c - -\subsubsection core_attr_find 5.2.5 Locating a Single Attribute - -An application only interested in a single attribute can use one of the -functions nla_find() or nlmsg_find_attr(). These function will iterate -over all attributes, search for a matching attribute and return a pointer -to the corresponding attribute header. - -\code -#include - -struct nlattr *nla_find(struct nlattr *head, int len, int attrtype); -\endcode - -\code -#include - -struct nlattr *nlmsg_find_attr(struct nlmsghdr *hdr, int hdrlen, int attrtype); -\endcode - -\b Note: nla_find() and nlmsg_find_attr() will \b not search in nested - attributes recursively, see \ref core_attr_nested. - -\subsubsection core_attr_iterate 5.2.6 Iterating over a Stream of Attributes - -In some situations it does not make sense to assign a unique attribute -type to each attribute in the attribute stream. For example a list may -be transferd using a stream of attributes and even if the attribute type -is incremented for each attribute it may not make sense to use the -nlmsg_parse() or nla_parse() function to fill an array. - -Therefore methods exist to iterate over a stream of attributes: - -\code -#include - -nla_for_each_attr(attr, head, len, remaining) -\endcode - -nla_for_each_attr() is a macro which can be used in front of a code -block: - -\include nla_for_each_attr.c - -\subsection core_attr_constr 5.3 Attribute Construction - -The interface to add attributes to a netlink message is based on the -regular message construction interface. It assumes that the message -header and an eventual protocol header has been added to the message -already. - -\code -struct nlattr *nla_reserve(struct nl_msg *msg, int attrtype, int len); -\endcode - -The function nla_reserve() adds an attribute header at the end of the -message and reserves room for \p len bytes of payload. The function -returns a pointer to the attribute payload section inside the message. -Padding is added at the end of the attribute to ensure the next -attribute is properly aligned. - -\code -int nla_put(struct nl_msg *msg, int attrtype, int attrlen, const void *data); -\endcode - -The function nla_put() is base don nla_reserve() but takes an additional -pointer \p data pointing to a buffer containing the attribute payload. -It will copy the buffer into the message automatically. - -\b Example: - -\include nla_put.c - -See \ref core_attr_data_type for datatype specific attribute construction -functions. - -\subsubsection core_attr_exception 5.3.1 Exception Based Attribute Construction - -Like in the kernel API an exception based construction interface is -provided. The behaviour of the macros is identical to their regular -function counterparts except that in case of an error, the target -\c nla_put_failure is jumped. - -\b Example: - -\include NLA_PUT.c - -See \ref core_attr_data_type for more information on the datatype -specific exception based variants. - -\subsection core_attr_data_type 5.4 Attribute Data Types - -A number of basic data types have been defined to simplify access and -validation of attributes. The datatype is not encoded in the attribute, -therefore bthe sender and receiver are required to use the same -definition on what attribute is of what type. - -Besides simplified access to the payload of such datatypes, the major -advantage is the automatic validation of each attribute based on a -policy. The validation ensures safe access to the payload by checking -for minimal payload size and can also be used to enforce maximum -payload size for some datatypes. - -\subsubsection core_attr_int 5.4.1 Integer Attributes - -The most frequently used datatypes are integers. Integers come in four -different sizes: -- \c NLA_U8 - 8bit integer -- \c NLA_U16 - 16bit integer -- \c NLA_U32 - 32bit integer -- \c NLA_U64 - 64bit integer - -Note that due to the alignment requirements of attributes the integer -attribtue \c NLA_u8 and \c NLA_U16 will not result in space savings in -the netlink message. Their use is intended to limit the range of values. - -Parsing Integer Attributes - -\code -#include - -uint8_t nla_get_u8(struct nlattr *hdr); -uint16_t nla_get_u16(struct nlattr *hdr); -uint32_t nla_get_u32(struct nlattr *hdr); -uint64_t nla_get_u64(struct nlattr *hdr); -\endcode - -Example: - -\code -if (attrs[MY_ATTR_FOO]) - uint32_t val = nla_get_u32(attrs[MY_ATTR_FOO]); -\endcode - -Constructing Integer Attributes - -\code -#include - -int nla_put_u8(struct nl_msg *msg, int attrtype, uint8_t value); -int nla_put_u16(struct nl_msg *msg, int attrtype, uint16_t value); -int nla_put_u32(struct nl_msg *msg, int attrtype, uint32_t value); -int nla_put_u64(struct nl_msg *msg, int attrtype, uint64_t value); -\endcode - -Exception based: - -\code -NLA_PUT_U8(msg, attrtype, value) -NLA_PUT_U16(msg, attrtype, value) -NLA_PUT_U32(msg, attrtype, value) -NLA_PUT_U64(msg, attrtype, value) -\endcode - -Validation - -Use \p NLA_U8, \p NLA_U16, \p NLA_U32, or \p NLA_U64 to define the type -of integer when filling out a struct nla_policy array. It will -automatically enforce the correct minimum payload length policy. - -Validation does not differ between signed and unsigned integers, only -the size matters. If the appliaction wishes to enforce particular value -ranges it must do so itself. - -\code -static struct nla_policy my_policy[ATTR_MAX+1] = { - [ATTR_FOO] = { .type = NLA_U32 }, - [ATTR_BAR] = { .type = NLA_U8 }, -}; -\endcode - -The above is equivalent to: -\code -static struct nla_policy my_policy[ATTR_MAX+1] = { - [ATTR_FOO] = { .minlen = sizeof(uint32_t) }, - [ATTR_BAR] = { .minlen = sizeof(uint8_t) }, -}; -\endcode - -\subsubsection core_attr_string 5.4.2 String Attributes - -The string datatype represents a NUL termianted character string of -variable length. It is not intended for binary data streams. - -The payload of string attributes can be accessed with the function -nla_get_string(). nla_strdup() calls strdup() on the payload and returns -the newly allocated string. - -\code -#include - -char *nla_get_string(struct nlattr *hdr); -char *nla_strdup(struct nlattr *hdr); -\endcode - -String attributes are constructed with the function nla_put_string() -respectively NLA_PUT_STRING(). The length of the payload will be strlen()+1, -the trailing NUL byte is included. - -\code -int nla_put_string(struct nl_msg *msg, int attrtype, const char *data); - -NLA_PUT_STRING(msg, attrtype, data) -\endcode - -For validation purposes the type \p NLA_STRING can be used in -struct nla_policy definitions. It implies a minimum payload length of 1 -byte and checks for a trailing NUL byte. Optionally the \p maxlen member -defines the maximum length of a character string (including the trailing -NUL byte). - -\code -static struct nla_policy my_policy[] = { - [ATTR_FOO] = { .type = NLA_STRING, - .maxlen = IFNAMSIZ }, -}; -\endcode - -\subsubsection core_attr_flag 5.4.3 Flag Attributes - -The flag attribute represents a boolean datatype. The presence of the -attribute implies a value of \p true, the absence of the attribute -implies the value \p false. Therefore the payload length of flag -attributes is always 0. - -\code -int nla_get_flag(struct nlattr *hdr); -int nla_put_flag(struct nl_msg *msg, int attrtype); -\endcode - -The type \p NLA_FLAG is used for validation purposes. It implies a -\p maxlen value of 0 and thus enforces a maximum payload length of 0. - -\b Example: - -\include nla_flag.c - -\subsubsection core_attr_nested 5.4.4 Nested Attributes - -As described in \ref core_attr, attributes can be nested allowing for -complex tree structures of attributes. It is commonly used to delegate -the responsibility of a subsection of the message to a subsystem. -Nested attributes are also commonly used for transmitting list of -objects. - -When nesting attributes, the nested attributes are included as payload -of a container attribute. - -IMPORTANT NOTICE: When validating the attributes using -nlmsg_validate(), nlmsg_parse(), nla_validate(), or nla_parse() only -the attributes on the first level are being validated. None of these -functions will validate attributes recursively. Therefore you must -explicitely call nla_validate() or use nla_parse_nested() for each -level of nested attributes. - -The type \p NLA_NESTED should be used when defining nested attributes -in a struct nla_policy definition. It will not enforce any minimum -payload length unless \p minlen is specified explicitely. This is -because some netlink protocols implicitely allow empty container -attributes. - -\code -static struct nla_policy my_policy[] = { - [ATTR_OPTS] = { .type = NLA_NESTED }, -}; -\endcode - -Parsing of Nested Attributes - -The function nla_parse_nested() is used to parse nested attributes. -Its behaviour is identical to nla_parse() except that it takes a -struct nlattr as argument and will use the payload as stream of -attributes. - -\include nla_parse_nested.c - -Construction of Nested Attributes - -Attributes are nested by surrounding them with calls to nla_nest_start() -and nla_nest_end(). nla_nest_start() will add a attribute header to -the message but no actual payload. All data added to the message from -this point on will be part of the container attribute until nla_nest_end() -is called which "closes" the attribute, correcting its payload length to -include all data length. - -\include nla_nest_start.c - -\subsubsection core_attr_unspec 5.4.5 Unspecified Attribute - -This is the default attribute type and used when none of the basic -datatypes is suitable. It represents data of arbitary type and length. - -See \ref core_abstract_addr_alloc for a more information on a special -interface allowing the allocation of abstract address object based on -netlink attributes which carry some form of network address. - -See \ref core_abstract_data_alloc for more information on how to -allocate abstract data objects based on netlink attributes. - -Use the function nla_get() and nla_put() to access the payload and -construct attributes. See \ref core_attr_constr for an example. - -\subsection core_attr_examples 5.5 Examples - -\subsubsection core_attr_example_constr 5.5.1 Constructing a Netlink Message with Attributes - -\include msg_constr_attr.c - -\subsubsection core_attr_example_parse 5.5.2 Parsing a Netlink Message with Attributes - -\include msg_parse_attr.c - -\section core_cb 6. Callback Configurations - -Callback hooks and overwriting capabilities are provided in various places -inside library to control the behaviour of several functions. All the -callback and overwrite functions are packed together in struct nl_cb which -is attached to a netlink socket or passed on to functions directly. - -\subsection core_cb_hooks 6.1 Callback Hooks - -Callback hooks are spread across the library to provide entry points for -message processing and to take action upon certain events. - -Callback functions may return the following return codes: -\code -Return Code | Description -------------------------------------------------------------------------- -NL_OK | Proceed. -NL_SKIP | Skip message currently being processed and continue - | parsing the receive buffer. -NL_STOP | Stop parsing and discard all remaining data in the - | receive buffer. -\endcode - -\subsubsection core_cb_default 6.1.1 Default Callback Implementations - -The library provides three sets of default callback implementations: -- \b NL_CB_DEFAULT This is the default set. It implets the default behaviour. - See the table below for more information on the return codes of each - function. -- \b NL_CB_VERBOSE This set is based on the default set but will cause an - error message to be printed to stderr for error messages, invalid - messages, message overruns and unhandled valid messages. The \p arg - pointer in nl_cb_set() and nl_cb_err() can be used to provide a FILE * - which overwrites stderr. -- \b NL_CB_DEBUG This set is intended for debugging purposes. It is based - on the verbose set but will decode and dump each message sent or - received to the console. - -\subsubsection core_cb_msg_proc 6.1.2 Message Processing Callbacks - -nl_sendmsg() callback hooks: -\code -Callback ID | Description | Default Return Value ------------------------------------------------------------------------------ -NL_CB_MSG_OUT | Each message sent | NL_OK -\endcode - -Any function called by NL_CB_MSG_OUT may return a negative error code to -prevent the message from being sent and the error code being returned. - -nl_recvmsgs() callback hooks (ordered by priority): -\code -Callback ID | Description | Default Return Value ------------------------------------------------------------------------------ -NL_CB_MSG_IN | Each message received | NL_OK -NL_CB_SEQ_CHECK | May overwrite sequence check algo | NL_OK -NL_CB_INVALID | Invalid messages | NL_STOP -NL_CB_SEND_ACK | Messages with NLM_F_ACK flag set | NL_OK -NL_CB_FINISH | Messages of type NLMSG_DONE | NL_STOP -NL_CB_SKIPPED | Messages of type NLMSG_NOOP | NL_SKIP -NL_CB_OVERRUN | Messages of type NLMSG_OVERRUN | NL_STOP -NL_CB_ACK | ACK Messages | NL_STOP -NL_CB_VALID | Each valid message | NL_OK -\endcode - -Any of these functions may return NL_OK, NL_SKIP, or NL_STOP. - -Message processing callback functions are set with nl_cb_set(): -\code -#include - -int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind, - nl_recvmsg_msg_cb_t func, void *cb); - -typedef int (*nl_recvmsg_msg_cb_t)(struct nl_msg *msg, void *arg); -\endcode - -\subsubsection core_cb_errmsg 6.1.4 Callback for Error Messages - -A special function prototype is used for the error message callback hook: - -\code -#include - -int nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind, nl_recvmsg_err_cb_t func, void * arg); - -typedef int(* nl_recvmsg_err_cb_t)(struct sockaddr_nl *nla, struct nlmsgerr *nlerr, void *arg); -\endcode - -\subsubsection core_cb_example 6.1.4 Example: Setting up a callback set -\include nl_cb_set.c - -\subsection core_cb_overwrite 6.2 Overwriting of Internal Functions - -When the library needs to send or receive netlink messages in high level -interfaces it does so by calling its own low level API. In the case the -default characteristics are not sufficient for the application, it may -overwrite several internal function calls with own implementations. - -\subsubsection core_cb_ow_recvmsgs 6.2.1 Overwriting recvmsgs() - -See \ref core_recv for more information on how and when recvmsgs() is -called internally. - -\code -#include - -void nl_cb_overwrite_recvmsgs(struct nl_cb *cb, - int (*func)(struct nl_sock *sk, struct nl_cb *cb)); -\endcode - -The following criteras must be met if a recvmsgs() implementation is -supposed to work with high level interfaces: -- MUST respect the callback configuration in \c cb, therefore: - - MUST call NL_CB_VALID for all valid messages, passing on - - MUST call NL_CB_ACK for all ACK messages - - MUST correctly handle multipart messages, calling NL_CB_VALID for - each message until a NLMSG_DONE message is received. -- MUST report error code if a NLMSG_ERROR or NLMSG_OVERRUN mesasge is - received. - -\subsubsection core_cb_ow_recv 6.2.2 Overwriting nl_recv() - -Often it is sufficient to overwrite nl_recv() which is responsible from -receiving the actual data from the socket instead of replacing the complete -recvmsgs() logic. - -See \ref core_recvmsgs for more information on how and when nl_recv() -is called internally. - -\code -#include - -void nl_cb_overwrite_recv(struct nl_cb *cb, - int (*func)(struct nl_sock * sk, - struct sockaddr_nl *addr, - unsigned char **buf, - struct ucred **cred)); -\endcode - -The following criteras must be met for an own nl_recv() implementation: -- MUST return the number of bytes read or a negative error code if an - error occured. The function may also return 0 to indicate that no - data has been read. -- MUST set \c *buf to a buffer containing the data read. It must be safe - for the caller to access the number of bytes read returned as return code. -- MAY fill out \c *addr with the netlink address of the peer the data - has been received from. -- MAY set \c *cred to a newly allocated struct ucred containg credentials. - -\subsubsection core_cb_ow_send 6.2.3 Overwriting nl_send() - -See \ref core_send for more information on how and when nl_send() is -called internally. - -\code -#include - -void nl_cb_overwrite_send(struct nl_cb *cb, int (*func)(struct nl_sock *sk, - struct nl_msg *msg)); -\endcode - -Own implementations must send the netlink message and return 0 on success -or a negative error code. - -\section core_cache 7. Cache System - -\subsection cache_alloc 7.1 Allocation of Caches - -Almost all subsystem provide a function to allocate a new cache -of some form. The function usually looks like this: -\code -struct nl_cache *_alloc_cache(struct nl_sock *sk); -\endcode - -These functions allocate a new cache for the own object type, -initializes it properly and updates it to represent the current -state of their master, e.g. a link cache would include all -links currently configured in the kernel. - -Some of the allocation functions may take additional arguments -to further specify what will be part of the cache. - -All such functions return a newly allocated cache or NULL -in case of an error. - -\section core_abstract_types 8. Abstract Data Types - -A few high level abstract data types which are used by a majority netlink -protocols are implemented in the core library. More may be added in the -future if the need arises. - -\subsection core_abstract_addr 8.1 Abstract Address - -Most netlink protocols deal with networking related topics and thus -dealing with network addresses is a common task. - -Currently the following address families are supported: -- AF_INET -- AF_INET6 -- AF_LLC -- AF_DECnet -- AF_UNSPEC - -\subsubsection core_abstract_addr_alloc 8.1.1 Address Allocation - -The function nl_addr_alloc() allocates a new empty address. The -\p maxsize argument defines the maximum length of an address in bytes. -The size of an address is address family specific. If the address -family and address data are known at allocation time the function -nl_addr_build() can be used alternatively. You may also clone -an address by calling nl_addr_clone() - -\code -#include - -struct nl_addr *nl_addr_alloc(size_t maxsize); -struct nl_addr *nl_addr_clone(struct nl_addr *addr); -struct nl_addr *nl_addr_build(int family, void *addr, size_t size); -\endcode - -If the address is transported in a netlink attribute, the function -nl_addr_alloc_attr() allocates a new address based on the payload -of the attribute provided. The \p family argument is used to specify -the address family of the address, set to \p AF_UNSPEC if unknown. - -\code -#include - -struct nl_addr *nl_addr_alloc_attr(struct nlattr *attr, int family); -\endcode - -If the address is provided by a user, it is usually stored in a human -readable format. The function nl_addr_parse() parses a character -string representing an address and allocates a new address based on -it. - -\code -#include - -int nl_addr_parse(const char *addr, int hint, struct nl_addr **result); -\endcode - -If parsing succeeds the function returns 0 and the allocated address -is stored in \p *result. - -\b Note: Make sure to return the reference to an address using - nl_addr_put() after usage to allow memory being freed. - -\subsubsection core_abstract_addr_ref 8.1.2 Address References - -Abstract addresses use reference counting to account for all users of -a particular address. After the last user has returned the reference -the address is freed. - -If you pass on a address object to another function and you are not -sure how long it will be used, make sure to call nl_addr_get() to -acquire an additional reference and have that function or code path -call nl_addr_put() as soon as it has finished using the address. - -\code -#include - -struct nl_addr *nl_addr_get(struct nl_addr *addr); -void nl_addr_put(struct nl_addr *addr); -int nl_addr_shared(struct nl_addr *addr); -\endcode - -You may call nl_addr_shared() at any time to check if you are the only -user of an address. - -\subsubsection core_abstract_addr_attr 8.1.3 Address Attributes - -The address is usually set at allocation time. If it was unknown at that -time it can be specified later by calling nl_addr_set_family() and is -accessed with the function nl_addr_get_family(). - -\code -#include - -void nl_addr_set_family(struct nl_addr *addr, int family); -int nl_addr_get_family(struct nl_addr *addr); -\endcode - -The same is true for the actual address data. It is typically present -at allocation time. For exceptions it can be specified later or -overwritten with the function nl_addr_set_binary_addr(). Beware that -the length of the address may not exceed \p maxlen specified at -allocation time. The address data is returned by the function -nl_addr_get_binary_addr() and its length by the function -nl_addr_get_len(). - -\code -#include - -int nl_addr_set_binary_addr(struct nl_addr *addr, void *data, size_t size); -void *nl_addr_get_binary_addr(struct nl_addr *addr); -unsigned int nl_addr_get_len(struct nl_addr *addr); -\endcode - -If you only want to check if the address data consists of all zeros -the function nl_addr_iszero() is a shortcut to that. - -\code -#include - -int nl_addr_iszero(struct nl_addr *addr); -\endcode - -\subsubsection core_abstract_addr_prefix 8.1.4 Address Prefix Length - -Although this functionality is somewhat specific to routing it has -been implemented here. Addresses can have a prefix length assigned -which implies that only the first n bits are of importance. This -is f.e. used to implement subnets. - -Use set functions nl_addr_set_prefixlen() and nl_addr_get_prefixlen() -to work with prefix lengths. - -\code -#include - -void nl_addr_set_prefixlen(struct nl_addr *addr, int n); -unsigned int nl_addr_get_prefixlen(struct nl_addr *addr); -\endcode - -\b Note: The default prefix length is set to (address length * 8) - -\subsubsection core_abstract_addr_helpers 8.1.5 Address Helpers - -Several functions exist to help when dealing with addresses. The -function nl_addr_cmp() compares two addresses and returns an integer -less than, equal to or greater than zero without considering the prefix -length at all. If you want to consider the prefix length, use the -function nl_addr_cmp_prefix(). - -\code -#include - -int nl_addr_cmp(struct nl_addr *addr, struct nl_addr *addr); -int nl_addr_cmp_prefix(struct nl_addr *addr, struct nl_addr *addr); -\endcode - -If an abstract address needs to presented to the user it should be done -in a human readable format which differs depending on the address -family. The function nl_addr2str() takes care of this by calling the -appropriate conversion functions internaly. It expects a \p buf of -length \p size to write the character string into and returns a pointer -to \p buf for easy printf() usage. - -\code -#include - -char *nl_addr2str(struct nl_addr *addr, char *buf, size_t size); -\endcode - -If the address family is unknown, the address data will be printed in -hexadecimal format AA:BB:CC:DD:... - -Often the only way to figure out the address family is by looking at -the length of the address. The function nl_addr_guess_family() does just -this and returns the address family guessed based on the address size. - -\code -#include - -int nl_addr_guess_family(struct nl_addr *addr); -\endcode - -Before allocating an address you may want to check if the character -string actually represents a valid address of the address family you are -expecting. The function nl_addr_valid() can be used for that, it returns -1 if the supplised \p addr is a valid address in the context of \p family. -See inet_pton(3), dnet_pton(3) for more information on valid adddress -formats. - -\code -#include - -int nl_addr_valid(char *addr, int family); -\endcode - -\subsection core_abstract_data 8.2 Abstract Data - -The abstract data type is a trivial datatype with the primary purpose -to simplify usage of netlink attributes of arbitary length. - -\subsubsection core_abstract_data_alloc 8.2.1 Allocation of a Data Object - -The function nl_data_alloc() alloctes a new abstract data object and -fill it with the provided data. nl_data_alloc_attr() does the same but -bases the data on the payload of a netlink attribute. New data objects -can also be allocated by cloning existing ones by using nl_data_clone(). - -\code -struct nl_data *nl_data_alloc(void *buf, size_t size); -struct nl_data *nl_data_alloc_attr(struct nlattr *attr); -struct nl_data *nl_data_clone(struct nl_data *data); -void nl_data_free(struct nl_data *data); -\endcode - -\subsubsection core_abstract_data_access 8.2.2 Access to Data - -The function nl_data_get() returns a pointer to the data, the size of -data is returned by nl_data_get_size(). - -\code -void *nl_data_get(struct nl_data *data); -size_t nl_data_get_size(struct nl_data *data); -\endcode - -\subsubsection core_abstract_data_helpers 8.2.3 Data Helpers - -The function nl_data_append() reallocates the internal data buffers and -appends the specified \p buf to the existing data. - -\code -int nl_data_append(struct nl_data *data, void *buf, size_t size); -\endcode - -\b Note: Call nl_data_append() invalidates all pointers returned by - nl_data_get(). - -\code -int nl_data_cmp(struct nl_data *data, struct nl_data *data); -\endcode - -*/ diff --git a/doc/stylesheets/pygments.css b/doc/stylesheets/pygments.css new file mode 100644 index 0000000..cd6fdbd --- /dev/null +++ b/doc/stylesheets/pygments.css @@ -0,0 +1,62 @@ +.highlight .hll { background-color: #ffffcc } +.highlight .c { color: #808080 } /* Comment */ +.highlight .err { color: #F00000; background-color: #F0A0A0 } /* Error */ +.highlight .k { color: #008000; font-weight: bold } /* Keyword */ +.highlight .o { color: #303030 } /* Operator */ +.highlight .cm { color: #808080 } /* Comment.Multiline */ +.highlight .cp { color: #507090 } /* Comment.Preproc */ +.highlight .c1 { color: #808080 } /* Comment.Single */ +.highlight .cs { color: #cc0000; font-weight: bold } /* Comment.Special */ +.highlight .gd { color: #A00000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .gr { color: #FF0000 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00A000 } /* Generic.Inserted */ +.highlight .go { color: #808080 } /* Generic.Output */ +.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #0040D0 } /* Generic.Traceback */ +.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #003080; font-weight: bold } /* Keyword.Pseudo */ +.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #303090; font-weight: bold } /* Keyword.Type */ +.highlight .m { color: #6000E0; font-weight: bold } /* Literal.Number */ +.highlight .s { background-color: #fff0f0 } /* Literal.String */ +.highlight .na { color: #0000C0 } /* Name.Attribute */ +.highlight .nb { color: #007020 } /* Name.Builtin */ +.highlight .nc { color: #B00060; font-weight: bold } /* Name.Class */ +.highlight .no { color: #003060; font-weight: bold } /* Name.Constant */ +.highlight .nd { color: #505050; font-weight: bold } /* Name.Decorator */ +.highlight .ni { color: #800000; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #F00000; font-weight: bold } /* Name.Exception */ +.highlight .nf { color: #0060B0; font-weight: bold } /* Name.Function */ +.highlight .nl { color: #907000; font-weight: bold } /* Name.Label */ +.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #007000 } /* Name.Tag */ +.highlight .nv { color: #906030 } /* Name.Variable */ +.highlight .ow { color: #000000; font-weight: bold } /* Operator.Word */ +.highlight .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight .mf { color: #6000E0; font-weight: bold } /* Literal.Number.Float */ +.highlight .mh { color: #005080; font-weight: bold } /* Literal.Number.Hex */ +.highlight .mi { color: #0000D0; font-weight: bold } /* Literal.Number.Integer */ +.highlight .mo { color: #4000E0; font-weight: bold } /* Literal.Number.Oct */ +.highlight .sb { background-color: #fff0f0 } /* Literal.String.Backtick */ +.highlight .sc { color: #0040D0 } /* Literal.String.Char */ +.highlight .sd { color: #D04020 } /* Literal.String.Doc */ +.highlight .s2 { background-color: #fff0f0 } /* Literal.String.Double */ +.highlight .se { color: #606060; font-weight: bold; background-color: #fff0f0 } /* Literal.String.Escape */ +.highlight .sh { background-color: #fff0f0 } /* Literal.String.Heredoc */ +.highlight .si { background-color: #e0e0e0 } /* Literal.String.Interpol */ +.highlight .sx { color: #D02000; background-color: #fff0f0 } /* Literal.String.Other */ +.highlight .sr { color: #000000; background-color: #fff0ff } /* Literal.String.Regex */ +.highlight .s1 { background-color: #fff0f0 } /* Literal.String.Single */ +.highlight .ss { color: #A06000 } /* Literal.String.Symbol */ +.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ +.highlight .vc { color: #306090 } /* Name.Variable.Class */ +.highlight .vg { color: #d07000; font-weight: bold } /* Name.Variable.Global */ +.highlight .vi { color: #3030B0 } /* Name.Variable.Instance */ +.highlight .il { color: #0000D0; font-weight: bold } /* Literal.Number.Integer.Long */ +.highlight .dg { color: #990000; font-weight: bold } diff --git a/doc/stylesheets/xhtml11.css b/doc/stylesheets/xhtml11.css new file mode 100644 index 0000000..39e7b16 --- /dev/null +++ b/doc/stylesheets/xhtml11.css @@ -0,0 +1,428 @@ +/* Sans-serif font. */ +h1, h2, h3, h4, h5, h6, +div.title, caption.title, +thead, p.table.header, +div#toctitle, +span#author, span#revnumber, span#revdate, span#revremark, +div#footer { + font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif; +} + +/* Serif font. */ +div.sectionbody { + font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif; +} + +/* Monospace font. */ +tt { + font-size: inherit; +} + +body { + margin: 1em 5% 1em 5%; +} + +a { + color: #990000; + text-decoration: underline; +} +a:visited { + color: #990000; +} + +.dg { color: #990000; } + +em { + font-style: italic; + /* color: navy; */ +} + +strong { + font-weight: bold; + color: black; + /* color: #083194; */ +} + +tt { + font-size: inherit; + color: navy; +} + +h1, h2, h3, h4, h5, h6 { + color: #990000; + margin-top: 1.2em; + margin-bottom: 0.5em; + line-height: 1.3; +} + +h1 { + border-bottom: 2px solid silver; + color: #990000; +} +h2 { + padding-top: 0.5em; +} +h3 { + float: left; +} +h3 + * { + clear: left; +} + +div.sectionbody { + margin-left: 0; +} + +hr { + border: 1px solid silver; +} + +p { + margin-top: 0.5em; + margin-bottom: 0.5em; +} + +ul, ol, li > p { + margin-top: 0; +} +ul > li { color: #aaa; } +ul > li > * { color: black; } + +pre { + padding: 0; + margin: 0; +} + +span#author { + color: #990000; + font-weight: bold; + font-size: 1.1em; +} +span#email { +} +span#revnumber, span#revdate, span#revremark { +} + +div#footer { + font-size: small; + border-top: 2px solid silver; + padding-top: 0.5em; + margin-top: 4.0em; +} +div#footer-text { + float: left; + padding-bottom: 0.5em; +} +div#footer-badges { + float: right; + padding-bottom: 0.5em; +} + +div#preamble { + margin-top: 1.5em; + margin-bottom: 1.5em; +} +div.tableblock, div.imageblock, div.exampleblock, div.verseblock, +div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock, +div.admonitionblock { + margin-top: 1.0em; + margin-bottom: 1.5em; +} +div.admonitionblock { + margin-top: 2.0em; + margin-bottom: 2.0em; + margin-right: 10%; + color: #606060; +} + +div.content { /* Block element content. */ + padding: 0; +} + +/* Block element titles. */ +div.title, caption.title { + color: #990000; + font-weight: bold; + text-align: left; + margin-top: 1.0em; + margin-bottom: 0.5em; +} +div.title + * { + margin-top: 0; +} + +td div.title:first-child { + margin-top: 0.0em; +} +div.content div.title:first-child { + margin-top: 0.0em; +} +div.content + div.title { + margin-top: 0.0em; +} + +div.sidebarblock > div.content { + background: #ffffee; + border: 1px solid #dddddd; + border-left: 4px solid #f0f0f0; + padding: 0.5em; +} + +div.listingblock > div.content { + border: 1px solid #dddddd; + border-left: 5px solid #f0f0f0; + background: #f8f8f8; + padding: 0.5em; +} + +div.quoteblock, div.verseblock { + padding-left: 1.0em; + margin-left: 1.0em; + margin-right: 10%; + border-left: 5px solid #f0f0f0; + color: #777777; +} + +div.quoteblock > div.attribution { + padding-top: 0.5em; + text-align: right; +} + +div.verseblock > pre.content { + font-family: inherit; + font-size: inherit; +} +div.verseblock > div.attribution { + padding-top: 0.75em; + text-align: left; +} +/* DEPRECATED: Pre version 8.2.7 verse style literal block. */ +div.verseblock + div.attribution { + text-align: left; +} + +div.admonitionblock .icon { + vertical-align: top; + font-size: 1.1em; + font-weight: bold; + text-decoration: underline; + color: #527bbd; + padding-right: 0.5em; +} +div.admonitionblock td.content { + padding-left: 0.5em; + border-left: 3px solid #dddddd; +} + +div.exampleblock > div.content { + border-left: 3px solid #dddddd; + padding-left: 0.5em; +} + +div.imageblock div.content { padding-left: 0; } +span.image img { border-style: none; } +a.image:visited { color: white; } + +dl { + margin-top: 0.8em; + margin-bottom: 0.8em; +} +dt { + margin-top: 0.5em; + margin-bottom: 0; + font-style: normal; + color: #990000; +} +dd > *:first-child { + margin-top: 0.1em; +} + +ul, ol { + list-style-position: outside; +} +ol.arabic { + list-style-type: decimal; +} +ol.loweralpha { + list-style-type: lower-alpha; +} +ol.upperalpha { + list-style-type: upper-alpha; +} +ol.lowerroman { + list-style-type: lower-roman; +} +ol.upperroman { + list-style-type: upper-roman; +} + +div.compact ul, div.compact ol, +div.compact p, div.compact p, +div.compact div, div.compact div { + margin-top: 0.1em; + margin-bottom: 0.1em; +} + +div.tableblock > table { + border: 3px solid #990000; +} +thead, p.table.header { + font-weight: bold; + color: #990000; +} +tfoot { + font-weight: bold; +} +td > div.verse { + white-space: pre; +} +p.table { + margin-top: 0; +} +/* Because the table frame attribute is overriden by CSS in most browsers. */ +div.tableblock > table[frame="void"] { + border-style: none; +} +div.tableblock > table[frame="hsides"] { + border-left-style: none; + border-right-style: none; +} +div.tableblock > table[frame="vsides"] { + border-top-style: none; + border-bottom-style: none; +} + + +div.hdlist { + margin-top: 0.8em; + margin-bottom: 0.8em; +} +div.hdlist tr { + padding-bottom: 15px; +} +dt.hdlist1.strong, td.hdlist1.strong { + font-weight: bold; +} +td.hdlist1 { + vertical-align: top; + font-style: normal; + padding-right: 0.8em; + color: #990000; +} +td.hdlist2 { + vertical-align: top; +} +div.hdlist.compact tr { + margin: 0; + padding-bottom: 0; +} + +.comment { + background: yellow; +} + +.footnote, .footnoteref { + font-size: 0.8em; +} + +span.footnote, span.footnoteref { + vertical-align: super; +} + +#footnotes { + margin: 20px 0 20px 0; + padding: 7px 0 0 0; +} + +#footnotes div.footnote { + margin: 0 0 5px 0; +} + +#footnotes hr { + border: none; + border-top: 1px solid silver; + height: 1px; + text-align: left; + margin-left: 0; + width: 20%; + min-width: 100px; +} + +div.colist td { + padding-right: 0.5em; + padding-bottom: 0.3em; + vertical-align: top; +} +div.colist td img { + margin-top: 0.3em; +} + +@media print { + div#footer-badges { display: none; } +} + +div#toc { + margin-bottom: 2.5em; +} + +div#toctitle { + color: black; + font-size: 1.1em; + font-weight: bold; + margin-top: 1.0em; + margin-bottom: 0.1em; +} + +div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 { + margin-top: 0; + margin-bottom: 0; +} +div.toclevel2 { + margin-left: 2em; + font-size: 0.9em; +} +div.toclevel3 { + margin-left: 4em; + font-size: 0.9em; +} +div.toclevel4 { + margin-left: 6em; + font-size: 0.9em; +} + +span.aqua { color: aqua; } +span.black { color: black; } +span.blue { color: blue; } +span.fuchsia { color: fuchsia; } +span.gray { color: gray; } +span.green { color: green; } +span.lime { color: lime; } +span.maroon { color: maroon; } +span.navy { color: navy; } +span.olive { color: olive; } +span.purple { color: purple; } +span.red { color: red; } +span.silver { color: silver; } +span.teal { color: teal; } +span.white { color: white; } +span.yellow { color: yellow; } + +span.aqua-background { background: aqua; } +span.black-background { background: black; } +span.blue-background { background: blue; } +span.fuchsia-background { background: fuchsia; } +span.gray-background { background: gray; } +span.green-background { background: green; } +span.lime-background { background: lime; } +span.maroon-background { background: maroon; } +span.navy-background { background: navy; } +span.olive-background { background: olive; } +span.purple-background { background: purple; } +span.red-background { background: red; } +span.silver-background { background: silver; } +span.teal-background { background: teal; } +span.white-background { background: white; } +span.yellow-background { background: yellow; } + +span.big { font-size: 2em; } +span.small { font-size: 0.6em; } diff --git a/doc/tags2dict.sh b/doc/tags2dict.sh new file mode 100755 index 0000000..76407af --- /dev/null +++ b/doc/tags2dict.sh @@ -0,0 +1,8 @@ +#!/bin/bash +xmlstarlet sel -t \ + -m "/libnltags/libnltag[@href]" \ + -v "@short" \ + -o "=api/" \ + -v "@href" \ + -n + From 475dffa699da4b3ca722ba7471bce0fdeb6d191e Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 1 Apr 2011 16:25:57 +0200 Subject: [PATCH 018/432] Provide TC_HANDLE(maj, min) macro to generate tc handles --- include/netlink/route/tc.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/netlink/route/tc.h b/include/netlink/route/tc.h index 17021be..6cf8cb8 100644 --- a/include/netlink/route/tc.h +++ b/include/netlink/route/tc.h @@ -23,6 +23,12 @@ extern "C" { #endif +/** + * Compute tc handle based on major and minor parts + * @ingroup tc + */ +#define TC_HANDLE(maj, min) (TC_H_MAJ((maj) << 16) | TC_H_MIN(min)) + /** * Traffic control object * @ingroup tc From 2dbe7d7cfc591e4e279f91409dca92f235b92c1b Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sun, 10 Apr 2011 10:18:04 +0200 Subject: [PATCH 019/432] Initialize dump buffer in case caller missed it (Set an end to all the bug reports of applications failing to do so.) --- lib/utils.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/utils.c b/lib/utils.c index 8756318..4d29ebb 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -1000,6 +1000,9 @@ void dump_from_ops(struct nl_object *obj, struct nl_dump_params *params) params->dp_pre_dump = 1; } + if (params->dp_buf) + memset(params->dp_buf, 0, params->dp_buflen); + if (obj->ce_ops->oo_dump[type]) obj->ce_ops->oo_dump[type](obj, params); } From ef327ffd44dbef02446255fe370d91e256ad927b Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sun, 10 Apr 2011 10:22:01 +0200 Subject: [PATCH 020/432] Provide nl_object_dump_buf() to easily dump to buffers --- include/netlink/object.h | 1 + lib/object.c | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/include/netlink/object.h b/include/netlink/object.h index ef1ed9f..7dc62ac 100644 --- a/include/netlink/object.h +++ b/include/netlink/object.h @@ -36,6 +36,7 @@ extern void nl_object_put(struct nl_object *); extern int nl_object_shared(struct nl_object *); extern void nl_object_dump(struct nl_object *, struct nl_dump_params *); +extern void nl_object_dump_buf(struct nl_object *, char *, size_t); extern int nl_object_identical(struct nl_object *, struct nl_object *); extern uint32_t nl_object_diff(struct nl_object *, diff --git a/lib/object.c b/lib/object.c index 4a1b356..3bf02ea 100644 --- a/lib/object.c +++ b/lib/object.c @@ -250,6 +250,16 @@ void nl_object_dump(struct nl_object *obj, struct nl_dump_params *params) dump_from_ops(obj, params); } +void nl_object_dump_buf(struct nl_object *obj, char *buf, size_t len) +{ + struct nl_dump_params dp = { + .dp_buf = buf, + .dp_buflen = len, + }; + + return nl_object_dump(obj, &dp); +} + /** * Check if the identifiers of two objects are identical * @arg a an object From 23c27b473825f1c7a3651c9aa24afb685a6183a7 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sun, 10 Apr 2011 10:22:27 +0200 Subject: [PATCH 021/432] Provide nl_cache_set_arg{1,2}() to specify cache args Added based on a RFE. This is required if allocation and (re)filling is to be splitted. --- include/netlink/cache.h | 2 ++ lib/cache.c | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/include/netlink/cache.h b/include/netlink/cache.h index 61f94dd..e17b015 100644 --- a/include/netlink/cache.h +++ b/include/netlink/cache.h @@ -65,6 +65,8 @@ extern int nl_cache_include(struct nl_cache *, struct nl_object *, change_func_t, void *); +extern void nl_cache_set_arg1(struct nl_cache *, int); +extern void nl_cache_set_arg2(struct nl_cache *, int); /* General */ extern int nl_cache_is_empty(struct nl_cache *); diff --git a/lib/cache.c b/lib/cache.c index ece354c..7afa42e 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -462,6 +462,32 @@ void nl_cache_remove(struct nl_object *obj) * @{ */ +/** + * Set synchronization arg1 of cache + * @arg cache Cache + * @arg arg argument + * + * Synchronization arguments are used to specify filters when + * requesting dumps from the kernel. + */ +void nl_cache_set_arg1(struct nl_cache *cache, int arg) +{ + cache->c_iarg1 = arg; +} + +/** + * Set synchronization arg2 of cache + * @arg cache Cache + * @arg arg argument + * + * Synchronization arguments are used to specify filters when + * requesting dumps from the kernel. + */ +void nl_cache_set_arg2(struct nl_cache *cache, int arg) +{ + cache->c_iarg2 = arg; +} + /** * Invoke the request-update operation * @arg sk Netlink socket. From 0893aafcec59219e5f125adff1a61e48b63f9c75 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sun, 10 Apr 2011 10:24:12 +0200 Subject: [PATCH 022/432] link: Make return and argument type match --- include/netlink/route/link.h | 4 ++-- lib/route/link.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/netlink/route/link.h b/include/netlink/route/link.h index dcd32f3..6a9d8de 100644 --- a/include/netlink/route/link.h +++ b/include/netlink/route/link.h @@ -114,10 +114,10 @@ extern int rtnl_link_str2stat(const char *); extern char * rtnl_link_flags2str(int, char *, size_t); extern int rtnl_link_str2flags(const char *); -extern char * rtnl_link_operstate2str(int, char *, size_t); +extern char * rtnl_link_operstate2str(uint8_t, char *, size_t); extern int rtnl_link_str2operstate(const char *); -extern char * rtnl_link_mode2str(int, char *, size_t); +extern char * rtnl_link_mode2str(uint8_t, char *, size_t); extern int rtnl_link_str2mode(const char *); /* Access Functions */ diff --git a/lib/route/link.c b/lib/route/link.c index bfb4150..3f0109f 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -1351,7 +1351,7 @@ static const struct trans_tbl link_operstates[] = { __ADD(IF_OPER_UP, up) }; -char *rtnl_link_operstate2str(int st, char *buf, size_t len) +char *rtnl_link_operstate2str(uint8_t st, char *buf, size_t len) { return __type2str(st, buf, len, link_operstates, ARRAY_SIZE(link_operstates)); @@ -1375,7 +1375,7 @@ static const struct trans_tbl link_modes[] = { __ADD(IF_LINK_MODE_DORMANT, dormant) }; -char *rtnl_link_mode2str(int st, char *buf, size_t len) +char *rtnl_link_mode2str(uint8_t st, char *buf, size_t len) { return __type2str(st, buf, len, link_modes, ARRAY_SIZE(link_modes)); } From 41fb241b7bb88d10300145778e401ab34e3bf46b Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sun, 10 Apr 2011 11:02:47 +0200 Subject: [PATCH 023/432] link: Provide rtnl_link_delete() to delete virtual links Takes a link object and extracts ifindex and name to build a deletion request message to delete virtual network links. --- include/netlink/route/link.h | 4 ++ lib/route/link.c | 81 ++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/include/netlink/route/link.h b/include/netlink/route/link.h index 6a9d8de..b9951d6 100644 --- a/include/netlink/route/link.h +++ b/include/netlink/route/link.h @@ -102,6 +102,10 @@ extern int rtnl_link_build_change_request(struct rtnl_link *, extern int rtnl_link_change(struct nl_sock *, struct rtnl_link *, struct rtnl_link *, int); +extern int rtnl_link_build_delete_request(const struct rtnl_link *, + struct nl_msg **); +extern int rtnl_link_delete(struct nl_sock *, const struct rtnl_link *); + /* Name <-> Index Translations */ extern char * rtnl_link_i2name(struct nl_cache *, int, char *, size_t); extern int rtnl_link_name2i(struct nl_cache *, const char *); diff --git a/lib/route/link.c b/lib/route/link.c index 3f0109f..6ecde1d 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -1163,6 +1163,87 @@ int rtnl_link_change(struct nl_sock *sk, struct rtnl_link *old, return wait_for_ack(sk); } +/** + * Build a netlink message requesting the deletion of a link + * @arg link Link to delete + * @arg result Pointer to store resulting netlink message + * + * The behaviour of this function is identical to rtnl_link_delete() with + * the exception that it will not send the message but return it in the + * provided return pointer instead. + * + * @see rtnl_link_delete() + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_build_delete_request(const struct rtnl_link *link, + struct nl_msg **result) +{ + struct nl_msg *msg; + struct ifinfomsg ifi = { + .ifi_index = link->l_index, + }; + + if (!(link->ce_mask & (LINK_ATTR_IFINDEX | LINK_ATTR_IFNAME))) { + APPBUG("ifindex or name must be specified"); + return -NLE_MISSING_ATTR; + } + + if (!(msg = nlmsg_alloc_simple(RTM_DELLINK, 0))) + return -NLE_NOMEM; + + if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0) + goto nla_put_failure; + + if (link->ce_mask & LINK_ATTR_IFNAME) + NLA_PUT_STRING(msg, IFLA_IFNAME, link->l_name); + + *result = msg; + return 0; + +nla_put_failure: + nlmsg_free(msg); + return -NLE_MSGSIZE; +} + +/** + * Delete link + * @arg sk Netlink socket + * @arg link Link to delete + * + * Builds a \c RTM_DELLINK netlink message requesting the deletion of + * a network link which has been previously added to the kernel and + * sends the message to the kernel. + * + * If no matching link exists, the function will return + * -NLE_OBJ_NOTFOUND. + * + * After sending, the function will wait for the ACK or an eventual + * error message to be received and will therefore block until the + * operation has been completed. + * + * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause + * this function to return immediately after sending. In this case, + * it is the responsibility of the caller to handle any error + * messages returned. + * + * @note Only virtual links such as dummy interface or vlan interfaces + * can be deleted. It is not possible to delete physical interfaces + * such as ethernet interfaces or the loopback device. + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_delete(struct nl_sock *sk, const struct rtnl_link *link) +{ + struct nl_msg *msg; + int err; + + if ((err = rtnl_link_build_delete_request(link, &msg)) < 0) + return err; + + return nl_send_sync(sk, msg); +} + /** @} */ /** From 48d543cfdf49aef75b9898ebea379f2303d3935d Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Mon, 11 Apr 2011 12:34:01 +0200 Subject: [PATCH 024/432] API to issue direct GET requests to the kernel Provide nl_pickup() to pick up an answer from a netlink request and parse it using the supplied parser. Add rtnl_link_get_kernel() which sends an RTM_GETLINK to the kernel to fetch a single link directly from the kernel. This can be faster than dumping the whole table, especially if lots of links are configured. --- include/netlink/netlink.h | 8 ++++ include/netlink/route/link.h | 4 ++ lib/nl.c | 70 +++++++++++++++++++++++++++ lib/route/link.c | 93 +++++++++++++++++++++++++++++++++++- 4 files changed, 174 insertions(+), 1 deletion(-) diff --git a/include/netlink/netlink.h b/include/netlink/netlink.h index a13c48f..0768708 100644 --- a/include/netlink/netlink.h +++ b/include/netlink/netlink.h @@ -31,6 +31,8 @@ #include #include #include +#include +#include #ifdef __cplusplus extern "C" { @@ -74,6 +76,12 @@ extern int nl_recvmsgs_default(struct nl_sock *); extern int nl_wait_for_ack(struct nl_sock *); +extern int nl_pickup(struct nl_sock *, + int (*parser)(struct nl_cache_ops *, + struct sockaddr_nl *, + struct nlmsghdr *, + struct nl_parser_param *), + struct nl_object **); /* Netlink Family Translations */ extern char * nl_nlfamily2str(int, char *, size_t); extern int nl_str2nlfamily(const char *); diff --git a/include/netlink/route/link.h b/include/netlink/route/link.h index b9951d6..3790c09 100644 --- a/include/netlink/route/link.h +++ b/include/netlink/route/link.h @@ -105,6 +105,10 @@ extern int rtnl_link_change(struct nl_sock *, struct rtnl_link *, extern int rtnl_link_build_delete_request(const struct rtnl_link *, struct nl_msg **); extern int rtnl_link_delete(struct nl_sock *, const struct rtnl_link *); +extern int rtnl_link_build_get_request(int, const char *, + struct nl_msg **); +extern int rtnl_link_get_kernel(struct nl_sock *, int, const char *, + struct rtnl_link **); /* Name <-> Index Translations */ extern char * rtnl_link_i2name(struct nl_cache *, int, char *, size_t); diff --git a/lib/nl.c b/lib/nl.c index b70242c..f5f94e3 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -799,6 +799,76 @@ int nl_wait_for_ack(struct nl_sock *sk) return err; } +/** @cond SKIP */ +struct pickup_param +{ + int (*parser)(struct nl_cache_ops *, struct sockaddr_nl *, + struct nlmsghdr *, struct nl_parser_param *); + struct nl_object *result; +}; + +static int __store_answer(struct nl_object *obj, struct nl_parser_param *p) +{ + struct pickup_param *pp = p->pp_arg; + /* + * the parser will put() the object at the end, expecting the cache + * to take the reference. + */ + nl_object_get(obj); + pp->result = obj; + + return 0; +} + +static int __pickup_answer(struct nl_msg *msg, void *arg) +{ + struct pickup_param *pp = arg; + struct nl_parser_param parse_arg = { + .pp_cb = __store_answer, + .pp_arg = pp, + }; + + return pp->parser(NULL, &msg->nm_src, msg->nm_nlh, &parse_arg); +} + +/** @endcond */ + +/** + * Pickup netlink answer, parse is and return object + * @arg sk Netlink socket + * @arg parser Parser function to parse answer + * @arg result Result pointer to return parsed object + * + * @return 0 on success or a negative error code. + */ +int nl_pickup(struct nl_sock *sk, + int (*parser)(struct nl_cache_ops *, struct sockaddr_nl *, + struct nlmsghdr *, struct nl_parser_param *), + struct nl_object **result) +{ + struct nl_cb *cb; + int err; + struct pickup_param pp = { + .parser = parser, + }; + + cb = nl_cb_clone(sk->s_cb); + if (cb == NULL) + return -NLE_NOMEM; + + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, __pickup_answer, &pp); + + err = nl_recvmsgs(sk, cb); + if (err < 0) + goto errout; + + *result = pp.result; +errout: + nl_cb_put(cb); + + return err; +} + /** @} */ /** @} */ diff --git a/lib/route/link.c b/lib/route/link.c index 6ecde1d..38b9d82 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -655,7 +655,6 @@ static int link_request_update(struct nl_cache *cache, struct nl_sock *sk) static void link_dump_line(struct nl_object *obj, struct nl_dump_params *p) { char buf[128]; - struct nl_cache *cache = dp_cache(obj); struct rtnl_link *link = (struct rtnl_link *) obj; nl_dump_line(p, "%s %s ", link->l_name, @@ -1244,6 +1243,98 @@ int rtnl_link_delete(struct nl_sock *sk, const struct rtnl_link *link) return nl_send_sync(sk, msg); } + +/** + * Build a netlink message requesting a link + * @arg ifindex Interface index + * @arg name Name of link + * @arg result Pointer to store resulting netlink message + * + * The behaviour of this function is identical to rtnl_link_get_kernel() + * with the exception that it will not send the message but return it in + * the provided return pointer instead. + * + * @see rtnl_link_get_kernel() + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_build_get_request(int ifindex, const char *name, + struct nl_msg **result) +{ + struct ifinfomsg ifi; + struct nl_msg *msg; + + if (ifindex <= 0 && !name) { + APPBUG("ifindex or name must be specified"); + return -NLE_MISSING_ATTR; + } + + memset(&ifi, 0, sizeof(ifi)); + + if (!(msg = nlmsg_alloc_simple(RTM_GETLINK, 0))) + return -NLE_NOMEM; + + if (ifindex > 0) + ifi.ifi_index = ifindex; + + if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0) + goto nla_put_failure; + + if (name) + NLA_PUT_STRING(msg, IFLA_IFNAME, name); + + *result = msg; + return 0; + +nla_put_failure: + nlmsg_free(msg); + return -NLE_MSGSIZE; +} + +/** + * Get a link object directly from the kernel + * @arg sk Netlink socket + * @arg ifindex Interface index + * @arg name name of link + * @arg result result pointer to return link object + * + * This function builds a \c RTM_GETLINK netlink message to request + * a specific link directly from the kernel. The returned answer is + * parsed into a struct rtnl_link object and returned via the result + * pointer or -NLE_OBJ_NOTFOUND is returned if no matching link was + * found. + * + * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause + * this function to return immediately after sending. In this case, + * it is the responsibility of the caller to handle any error + * messages returned. + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_get_kernel(struct nl_sock *sk, int ifindex, const char *name, + struct rtnl_link **result) +{ + struct nl_msg *msg = NULL; + struct nl_object *obj; + int err; + + if ((err = rtnl_link_build_get_request(ifindex, name, &msg)) < 0) + return err; + + err = nl_send_auto(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + if ((err = nl_pickup(sk, link_msg_parser, &obj)) < 0) + return err; + + /* We have used link_msg_parser(), object is definitely a link */ + *result = (struct rtnl_link *) obj; + + return 0; +} + /** @} */ /** From b5918b5ce3c48271abe4c021431f2b978af28f73 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Mon, 11 Apr 2011 12:40:40 +0200 Subject: [PATCH 025/432] fix line removed by mistake This line was removed by mistake in the last commit --- lib/route/link.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/route/link.c b/lib/route/link.c index 38b9d82..5e42ffd 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -655,6 +655,7 @@ static int link_request_update(struct nl_cache *cache, struct nl_sock *sk) static void link_dump_line(struct nl_object *obj, struct nl_dump_params *p) { char buf[128]; + struct nl_cache *cache = dp_cache(obj); struct rtnl_link *link = (struct rtnl_link *) obj; nl_dump_line(p, "%s %s ", link->l_name, From 96bc6d6f66454cba0daa637cbfd714da3539c687 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 13 Apr 2011 16:42:34 +0200 Subject: [PATCH 026/432] Improve rtnl_link_change() behaviour - avoid unncessary name change requests The kernel does not check if the specified IFNAME is different from the current name. It assumes that if IFNAME and ifindex are both specified, a name change is requested. Therefore avoid specyfing IFNAME if ifindex is provided and original and new name are identical. - move link building to own function (to allow link add later on) - error if immutable changes have been made - better documentation --- include/netlink/errno.h | 3 +- lib/error.c | 1 + lib/route/link.c | 203 +++++++++++++++++++++++++--------------- 3 files changed, 132 insertions(+), 75 deletions(-) diff --git a/include/netlink/errno.h b/include/netlink/errno.h index 93dc163..267a745 100644 --- a/include/netlink/errno.h +++ b/include/netlink/errno.h @@ -48,8 +48,9 @@ extern "C" { #define NLE_PKTLOC_FILE 29 #define NLE_PARSE_ERR 30 #define NLE_NODEV 31 +#define NLE_IMMUTABLE 32 -#define NLE_MAX NLE_NODEV +#define NLE_MAX NLE_IMMUTABLE extern const char * nl_geterror(int); extern void nl_perror(int, const char *); diff --git a/lib/error.c b/lib/error.c index b973cdd..8934020 100644 --- a/lib/error.c +++ b/lib/error.c @@ -45,6 +45,7 @@ static const char *errmsg[NLE_MAX+1] = { [NLE_PKTLOC_FILE] = "Unable to open packet location file", [NLE_PARSE_ERR] = "Unable to parse object", [NLE_NODEV] = "No such device", +[NLE_IMMUTABLE] = "Immutable attribute", }; /** diff --git a/lib/route/link.c b/lib/route/link.c index 5e42ffd..3c5b219 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -1031,85 +1031,56 @@ struct rtnl_link *rtnl_link_get_by_name(struct nl_cache *cache, * @{ */ -/** - * Builds a netlink change request message to change link attributes - * @arg old link to be changed - * @arg tmpl template with requested changes - * @arg flags additional netlink message flags - * @arg result Result pointer - * - * Builds a new netlink message requesting a change of link attributes. - * The netlink message header isn't fully equipped with all relevant - * fields and must be sent out via nl_send_auto_complete() or - * supplemented as needed. - * \a old must point to a link currently configured in the kernel - * and \a tmpl must contain the attributes to be changed set via - * \c rtnl_link_set_* functions. - * - * @return 0 on success or a negative error code. - * @note Not all attributes can be changed, see - * \ref link_changeable "Changeable Attributes" for more details. - */ -int rtnl_link_build_change_request(struct rtnl_link *old, - struct rtnl_link *tmpl, int flags, - struct nl_msg **result) +static int build_link_msg(int cmd, struct ifinfomsg *hdr, + struct rtnl_link *link, int flags, struct nl_msg **result) { struct nl_msg *msg; struct nlattr *af_spec; - struct ifinfomsg ifi = { - .ifi_family = old->l_family, - .ifi_index = old->l_index, - }; - if (tmpl->ce_mask & LINK_ATTR_FLAGS) { - ifi.ifi_flags = old->l_flags & ~tmpl->l_flag_mask; - ifi.ifi_flags |= tmpl->l_flags; - } - - msg = nlmsg_alloc_simple(RTM_SETLINK, flags); + msg = nlmsg_alloc_simple(cmd, flags); if (!msg) return -NLE_NOMEM; - if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0) + if (nlmsg_append(msg, hdr, sizeof(*hdr), NLMSG_ALIGNTO) < 0) goto nla_put_failure; - if (tmpl->ce_mask & LINK_ATTR_ADDR) - NLA_PUT_ADDR(msg, IFLA_ADDRESS, tmpl->l_addr); + if (link->ce_mask & LINK_ATTR_ADDR) + NLA_PUT_ADDR(msg, IFLA_ADDRESS, link->l_addr); - if (tmpl->ce_mask & LINK_ATTR_BRD) - NLA_PUT_ADDR(msg, IFLA_BROADCAST, tmpl->l_bcast); + if (link->ce_mask & LINK_ATTR_BRD) + NLA_PUT_ADDR(msg, IFLA_BROADCAST, link->l_bcast); - if (tmpl->ce_mask & LINK_ATTR_MTU) - NLA_PUT_U32(msg, IFLA_MTU, tmpl->l_mtu); + if (link->ce_mask & LINK_ATTR_MTU) + NLA_PUT_U32(msg, IFLA_MTU, link->l_mtu); - if (tmpl->ce_mask & LINK_ATTR_TXQLEN) - NLA_PUT_U32(msg, IFLA_TXQLEN, tmpl->l_txqlen); + if (link->ce_mask & LINK_ATTR_TXQLEN) + NLA_PUT_U32(msg, IFLA_TXQLEN, link->l_txqlen); - if (tmpl->ce_mask & LINK_ATTR_WEIGHT) - NLA_PUT_U32(msg, IFLA_WEIGHT, tmpl->l_weight); + if (link->ce_mask & LINK_ATTR_WEIGHT) + NLA_PUT_U32(msg, IFLA_WEIGHT, link->l_weight); - if (tmpl->ce_mask & LINK_ATTR_IFNAME) - NLA_PUT_STRING(msg, IFLA_IFNAME, tmpl->l_name); + if (link->ce_mask & LINK_ATTR_IFNAME) + NLA_PUT_STRING(msg, IFLA_IFNAME, link->l_name); - if (tmpl->ce_mask & LINK_ATTR_OPERSTATE) - NLA_PUT_U8(msg, IFLA_OPERSTATE, tmpl->l_operstate); + if (link->ce_mask & LINK_ATTR_OPERSTATE) + NLA_PUT_U8(msg, IFLA_OPERSTATE, link->l_operstate); - if (tmpl->ce_mask & LINK_ATTR_LINKMODE) - NLA_PUT_U8(msg, IFLA_LINKMODE, tmpl->l_linkmode); + if (link->ce_mask & LINK_ATTR_LINKMODE) + NLA_PUT_U8(msg, IFLA_LINKMODE, link->l_linkmode); - if (tmpl->ce_mask & LINK_ATTR_IFALIAS) - NLA_PUT_STRING(msg, IFLA_IFALIAS, tmpl->l_ifalias); + if (link->ce_mask & LINK_ATTR_IFALIAS) + NLA_PUT_STRING(msg, IFLA_IFALIAS, link->l_ifalias); - if ((tmpl->ce_mask & LINK_ATTR_LINKINFO) && tmpl->l_info_ops && - tmpl->l_info_ops->io_put_attrs) { + if ((link->ce_mask & LINK_ATTR_LINKINFO) && link->l_info_ops && + link->l_info_ops->io_put_attrs) { struct nlattr *info; if (!(info = nla_nest_start(msg, IFLA_LINKINFO))) goto nla_put_failure; - NLA_PUT_STRING(msg, IFLA_INFO_KIND, tmpl->l_info_ops->io_name); + NLA_PUT_STRING(msg, IFLA_INFO_KIND, link->l_info_ops->io_name); - if (tmpl->l_info_ops->io_put_attrs(msg, tmpl) < 0) + if (link->l_info_ops->io_put_attrs(msg, link) < 0) goto nla_put_failure; nla_nest_end(msg, info); @@ -1118,7 +1089,7 @@ int rtnl_link_build_change_request(struct rtnl_link *old, if (!(af_spec = nla_nest_start(msg, IFLA_AF_SPEC))) goto nla_put_failure; - if (do_foreach_af(tmpl, af_fill, msg) < 0) + if (do_foreach_af(link, af_fill, msg) < 0) goto nla_put_failure; nla_nest_end(msg, af_spec); @@ -1132,35 +1103,119 @@ nla_put_failure: } /** - * Change link attributes - * @arg sk Netlink socket. - * @arg old link to be changed - * @arg tmpl template with requested changes + * Build a netlink message requesting the modification of a link + * @arg orig original link to change + * @arg changes link containing the changes to be made + * @arg flags additional netlink message flags + * @arg result pointer to store resulting netlink message + * + * The behaviour of this function is identical to rtnl_link_change() with + * the exception that it will not send the message but return it in the + * provided return pointer instead. + * + * @see rtnl_link_change() + * + * @note The resulting message will have message type set to RTM_NEWLINK + * which may not work with older kernels. You may have to modify it + * to RTM_SETLINK (does not allow changing link info attributes) to + * have the change request work with older kernels. + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_build_change_request(struct rtnl_link *orig, + struct rtnl_link *changes, int flags, + struct nl_msg **result) +{ + struct ifinfomsg ifi = { + .ifi_family = orig->l_family, + .ifi_index = orig->l_index, + }; + int err; + + if (changes->ce_mask & LINK_ATTR_FLAGS) { + ifi.ifi_flags = orig->l_flags & ~changes->l_flag_mask; + ifi.ifi_flags |= changes->l_flags; + } + + if (changes->l_family && changes->l_family != orig->l_family) { + APPBUG("link change: family is immutable"); + return -NLE_IMMUTABLE; + } + + /* Avoid unnecessary name change requests */ + if (orig->ce_mask & LINK_ATTR_IFINDEX && + orig->ce_mask & LINK_ATTR_IFNAME && + changes->ce_mask & LINK_ATTR_IFNAME && + !strcmp(orig->l_name, changes->l_name)) + changes->ce_mask &= ~LINK_ATTR_IFNAME; + + if ((err = build_link_msg(RTM_NEWLINK, &ifi, changes, flags, result)) < 0) + goto errout; + + return 0; + +errout: + return err; +} + +/** + * Change link + * @arg sk netlink socket. + * @arg orig original link to be changed + * @arg changes link containing the changes to be made * @arg flags additional netlink message flags * - * Builds a new netlink message by calling rtnl_link_build_change_request(), - * sends the request to the kernel and waits for the next ACK to be - * received, i.e. blocks until the request has been processed. + * Builds a \c RTM_NEWLINK netlink message requesting the change of + * a network link. If -EOPNOTSUPP is returned by the kernel, the + * message type will be changed to \c RTM_SETLINK and the message is + * resent to work around older kernel versions. * - * @return 0 on success or a negative error code - * @note Not all attributes can be changed, see - * \ref link_changeable "Changeable Attributes" for more details. + * The link to be changed is looked up based on the interface index + * supplied in the \p orig link. Optionaly the link name is used but + * only if no interface index is provided, otherwise providing an + * link name will result in the link name being changed. + * + * If no matching link exists, the function will return + * -NLE_OBJ_NOTFOUND. + * + * After sending, the function will wait for the ACK or an eventual + * error message to be received and will therefore block until the + * operation has been completed. + * + * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause + * this function to return immediately after sending. In this case, + * it is the responsibility of the caller to handle any error + * messages returned. + * + * @note The link name can only be changed if the link has been put + * in opertional down state. (~IF_UP) + * + * @return 0 on success or a negative error code. */ -int rtnl_link_change(struct nl_sock *sk, struct rtnl_link *old, - struct rtnl_link *tmpl, int flags) +int rtnl_link_change(struct nl_sock *sk, struct rtnl_link *orig, + struct rtnl_link *changes, int flags) { struct nl_msg *msg; int err; - if ((err = rtnl_link_build_change_request(old, tmpl, flags, &msg)) < 0) - return err; - - err = nl_send_auto_complete(sk, msg); - nlmsg_free(msg); + err = rtnl_link_build_change_request(orig, changes, flags, &msg); if (err < 0) return err; - return wait_for_ack(sk); +retry: + err = nl_send_auto_complete(sk, msg); + if (err < 0) + goto errout; + + err = wait_for_ack(sk); + if (err == -NLE_OPNOTSUPP && msg->nm_nlh->nlmsg_type == RTM_NEWLINK) { + msg->nm_nlh->nlmsg_type = RTM_SETLINK; + goto retry; + } + +errout: + nlmsg_free(msg); + return err; } /** From e81814a29fb4a43035112e318cdcc8fb85a28cc8 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 15 Apr 2011 15:30:46 +0200 Subject: [PATCH 027/432] Support for rtnl_link_add() API for adding virtual links --- lib/route/link.c | 79 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 73 insertions(+), 6 deletions(-) diff --git a/lib/route/link.c b/lib/route/link.c index 3c5b219..9dfa5e1 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -303,7 +303,8 @@ static void release_link_info(struct rtnl_link *link) struct rtnl_link_info_ops *io = link->l_info_ops; if (io != NULL) { - io->io_free(link); + if (io->io_free) + io->io_free(link); rtnl_link_info_ops_put(io); link->l_info_ops = NULL; } @@ -599,7 +600,7 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, kind = nla_get_string(li[IFLA_INFO_KIND]); ops = rtnl_link_info_ops_lookup(kind); - if (ops != NULL) { + if (ops && ops->io_parse) { link->l_info_ops = ops; err = ops->io_parse(link, li[IFLA_INFO_DATA], li[IFLA_INFO_XSTATS]); @@ -1071,8 +1072,7 @@ static int build_link_msg(int cmd, struct ifinfomsg *hdr, if (link->ce_mask & LINK_ATTR_IFALIAS) NLA_PUT_STRING(msg, IFLA_IFALIAS, link->l_ifalias); - if ((link->ce_mask & LINK_ATTR_LINKINFO) && link->l_info_ops && - link->l_info_ops->io_put_attrs) { + if ((link->ce_mask & LINK_ATTR_LINKINFO) && link->l_info_ops) { struct nlattr *info; if (!(info = nla_nest_start(msg, IFLA_LINKINFO))) @@ -1080,7 +1080,8 @@ static int build_link_msg(int cmd, struct ifinfomsg *hdr, NLA_PUT_STRING(msg, IFLA_INFO_KIND, link->l_info_ops->io_name); - if (link->l_info_ops->io_put_attrs(msg, link) < 0) + if (link->l_info_ops->io_put_attrs && + link->l_info_ops->io_put_attrs(msg, link) < 0) goto nla_put_failure; nla_nest_end(msg, info); @@ -1102,6 +1103,71 @@ nla_put_failure: return -NLE_MSGSIZE; } +/** + * Build a netlink message requesting the addition of a new virtual link + * @arg link new link to add + * @arg flags additional netlink message flags + * @arg result pointer to store resulting netlink message + * + * The behaviour of this function is identical to rtnl_link_add() with + * the exception that it will not send the message but return it in the + * provided return pointer instead. + * + * @see rtnl_link_add() + * + * @note This operation is not supported on all kernel versions. + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_build_add_request(struct rtnl_link *link, int flags, + struct nl_msg **result) +{ + struct ifinfomsg ifi = { + .ifi_family = link->l_family, + .ifi_index = link->l_index, + .ifi_flags = link->l_flags, + }; + + return build_link_msg(RTM_NEWLINK, &ifi, link, flags, result); +} + +/** + * Add virtual link + * @arg sk netlink socket. + * @arg link new link to add + * @arg flags additional netlink message flags + * + * Builds a \c RTM_NEWLINK netlink message requesting the addition of + * a new virtual link. + * + * After sending, the function will wait for the ACK or an eventual + * error message to be received and will therefore block until the + * operation has been completed. + * + * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause + * this function to return immediately after sending. In this case, + * it is the responsibility of the caller to handle any error + * messages returned. + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_add(struct nl_sock *sk, struct rtnl_link *link, int flags) +{ + struct nl_msg *msg; + int err; + + err = rtnl_link_build_add_request(link, flags, &msg); + if (err < 0) + return err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return wait_for_ack(sk); +} + /** * Build a netlink message requesting the modification of a link * @arg orig original link to change @@ -1928,9 +1994,10 @@ int rtnl_link_set_info_type(struct rtnl_link *link, const char *type) if (link->l_info_ops) release_link_info(link); - if ((err = io->io_alloc(link)) < 0) + if (io->io_alloc && (err = io->io_alloc(link)) < 0) return err; + link->ce_mask |= LINK_ATTR_LINKINFO; link->l_info_ops = io; return 0; From 5a6610190a56c9788b2ba982ae60c93022c6cde1 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 15 Apr 2011 15:31:22 +0200 Subject: [PATCH 028/432] dummy interface support --- lib/Makefile.am | 2 +- lib/route/link/dummy.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 lib/route/link/dummy.c diff --git a/lib/Makefile.am b/lib/Makefile.am index e8045b7..b7f2e31 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -56,7 +56,7 @@ libnl_route_la_SOURCES = \ route/cls/ematch/nbyte.c route/cls/ematch/text.c \ route/cls/ematch/meta.c \ \ - route/link/api.c route/link/vlan.c \ + route/link/api.c route/link/vlan.c route/link/dummy.c \ route/link/bridge.c route/link/inet6.c route/link/inet.c \ \ route/qdisc/blackhole.c route/qdisc/cbq.c route/qdisc/dsmark.c \ diff --git a/lib/route/link/dummy.c b/lib/route/link/dummy.c new file mode 100644 index 0000000..b837f48 --- /dev/null +++ b/lib/route/link/dummy.c @@ -0,0 +1,38 @@ +/* + * lib/route/link/dummy.c Dummy Interfaces + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2011 Thomas Graf + */ + +/** + * @ingroup link + * @defgroup dummy Dummy + * @brief + * + * @{ + */ + +#include +#include +#include + +static struct rtnl_link_info_ops dummy_info_ops = { + .io_name = "dummy", +}; + +static void __init dummy_init(void) +{ + rtnl_link_register_info(&dummy_info_ops); +} + +static void __exit dummy_exit(void) +{ + rtnl_link_unregister_info(&dummy_info_ops); +} + +/** @} */ From 8ffab45698b8bcfb7c861e9bdc9f8e2a279c1183 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 15 Apr 2011 15:31:47 +0200 Subject: [PATCH 029/432] export rtnl_link_add() and rtnl_link_build_add_request() --- include/netlink/route/link.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/netlink/route/link.h b/include/netlink/route/link.h index 3790c09..0dddaf7 100644 --- a/include/netlink/route/link.h +++ b/include/netlink/route/link.h @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2010 Thomas Graf + * Copyright (c) 2003-2011 Thomas Graf */ #ifndef NETLINK_LINK_H_ @@ -96,6 +96,9 @@ extern struct rtnl_link *rtnl_link_get(struct nl_cache *, int); extern struct rtnl_link *rtnl_link_get_by_name(struct nl_cache *, const char *); +extern int rtnl_link_build_add_request(struct rtnl_link *, int, + struct nl_msg **); +extern int rtnl_link_add(struct nl_sock *, struct rtnl_link *, int); extern int rtnl_link_build_change_request(struct rtnl_link *, struct rtnl_link *, int, struct nl_msg **); From 3d70697e4cb35f51f776791590bd6f81a46cc66e Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 19 Apr 2011 09:57:14 +0200 Subject: [PATCH 030/432] Add support for ARPHRD_NONE --- lib/utils.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/utils.c b/lib/utils.c index 4d29ebb..b507608 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -608,6 +608,9 @@ static const struct trans_tbl llprotos[] = { #ifdef ARPHRD_VOID __ADD(ARPHRD_VOID,void) #endif +#ifdef ARPHRD_NONE + __ADD(ARPHRD_NONE,nohdr) +#endif }; char * nl_llproto2str(int llproto, char *buf, size_t len) From 36b04747c72b02a1cd084e77783a9e81c145463b Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 19 Apr 2011 09:57:35 +0200 Subject: [PATCH 031/432] Support link info types with no payload --- lib/route/link.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/route/link.c b/lib/route/link.c index 9dfa5e1..cb92f19 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -593,15 +593,16 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, if (err < 0) goto errout; - if (li[IFLA_INFO_KIND] && - (li[IFLA_INFO_DATA] || li[IFLA_INFO_XSTATS])) { + if (li[IFLA_INFO_KIND]) { struct rtnl_link_info_ops *ops; char *kind; kind = nla_get_string(li[IFLA_INFO_KIND]); ops = rtnl_link_info_ops_lookup(kind); - if (ops && ops->io_parse) { - link->l_info_ops = ops; + link->l_info_ops = ops; + + if (ops && ops->io_parse && + (li[IFLA_INFO_DATA] || li[IFLA_INFO_XSTATS])) { err = ops->io_parse(link, li[IFLA_INFO_DATA], li[IFLA_INFO_XSTATS]); if (err < 0) From 4c6dd3a8bd0c6a69c1f5023fc38e16917bb12754 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 20 Apr 2011 11:53:04 +0200 Subject: [PATCH 032/432] Expose --- include/Makefile.am | 1 + include/netlink/route/link/inet.h | 2 +- lib/route/link/inet.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/Makefile.am b/include/Makefile.am index 50fde24..e9fa8ad 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -51,6 +51,7 @@ nobase_include_HEADERS = \ netlink/route/cls/u32.h \ netlink/route/link/api.h \ netlink/route/link/info-api.h \ + netlink/route/link/inet.h \ netlink/route/link/vlan.h \ netlink/route/qdisc/cbq.h \ netlink/route/qdisc/dsmark.h \ diff --git a/include/netlink/route/link/inet.h b/include/netlink/route/link/inet.h index 9feff37..66419e3 100644 --- a/include/netlink/route/link/inet.h +++ b/include/netlink/route/link/inet.h @@ -19,7 +19,7 @@ extern "C" { #endif extern const char * rtnl_link_inet_devconf2str(int, char *, size_t); -extern unsigned int rtnl_link_inet_str2devconf(const char *); +extern int rtnl_link_inet_str2devconf(const char *); extern int rtnl_link_inet_get_conf(struct rtnl_link *, const unsigned int, uint32_t *); diff --git a/lib/route/link/inet.c b/lib/route/link/inet.c index 9a82a8b..a0e2318 100644 --- a/lib/route/link/inet.c +++ b/lib/route/link/inet.c @@ -166,7 +166,7 @@ const char *rtnl_link_inet_devconf2str(int type, char *buf, size_t len) ARRAY_SIZE(inet_devconf)); } -unsigned int rtnl_link_inet_str2devconf(const char *name) +int rtnl_link_inet_str2devconf(const char *name) { return __str2type(name, inet_devconf, ARRAY_SIZE(inet_devconf)); } From fac48856087d11627bb7c2b78776529ceadc213a Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 20 Apr 2011 16:29:42 +0200 Subject: [PATCH 033/432] Improve readability of classid string representation 1: is more readable than 01: --- lib/route/classid.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/route/classid.c b/lib/route/classid.c index 6af0ee3..abed244 100644 --- a/lib/route/classid.c +++ b/lib/route/classid.c @@ -106,7 +106,7 @@ static char *name_lookup(const uint32_t classid) * @return The destination buffer or the type encoded in hexidecimal * form if no match was found. */ -char * rtnl_tc_handle2str(uint32_t handle, char *buf, size_t len) +char *rtnl_tc_handle2str(uint32_t handle, char *buf, size_t len) { if (TC_H_ROOT == handle) snprintf(buf, len, "root"); @@ -120,11 +120,11 @@ char * rtnl_tc_handle2str(uint32_t handle, char *buf, size_t len) if ((name = name_lookup(handle))) snprintf(buf, len, "%s", name); else if (0 == TC_H_MAJ(handle)) - snprintf(buf, len, ":%02x", TC_H_MIN(handle)); + snprintf(buf, len, ":%x", TC_H_MIN(handle)); else if (0 == TC_H_MIN(handle)) - snprintf(buf, len, "%02x:", TC_H_MAJ(handle) >> 16); + snprintf(buf, len, "%x:", TC_H_MAJ(handle) >> 16); else - snprintf(buf, len, "%02x:%02x", + snprintf(buf, len, "%x:%x", TC_H_MAJ(handle) >> 16, TC_H_MIN(handle)); } From c18730ddf69f70c79ebd77e6b0e173eadce96096 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 20 Apr 2011 16:30:49 +0200 Subject: [PATCH 034/432] Set tc->tc_link if link cache is available When parsing tc objects, lookup link in link cache if such a cache is available. --- lib/route/tc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/route/tc.c b/lib/route/tc.c index 56aa410..0aa44f7 100644 --- a/lib/route/tc.c +++ b/lib/route/tc.c @@ -60,6 +60,7 @@ static struct nla_policy tc_stats2_policy[TCA_STATS_MAX+1] = { int rtnl_tc_msg_parse(struct nlmsghdr *n, struct rtnl_tc *tc) { + struct nl_cache *link_cache; struct rtnl_tc_ops *ops; struct nlattr *tb[TCA_MAX + 1]; char kind[TCKINDSIZ]; @@ -175,6 +176,13 @@ compat_xstats: return err; } + if ((link_cache = nl_cache_mngt_require("route/link"))) { + struct rtnl_link *link; + + if ((link = rtnl_link_get(link_cache, tc->tc_ifindex))) + rtnl_tc_set_link(tc, link); + } + return 0; } From 83f14112e22d3d28dab4c88763136f2321718664 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 21 Apr 2011 14:46:06 +0200 Subject: [PATCH 035/432] Fix clone() of AF specific link data Passed the original link to ao_clone() instead of the new one. --- lib/route/link.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/route/link.c b/lib/route/link.c index cb92f19..0295666 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -216,7 +216,7 @@ static int af_clone(struct rtnl_link *link, struct rtnl_link_af_ops *ops, struct rtnl_link *dst = arg; if (ops->ao_clone && - !(dst->l_af_data[ops->ao_family] = ops->ao_clone(link, data))) + !(dst->l_af_data[ops->ao_family] = ops->ao_clone(dst, data))) return -NLE_NOMEM; return 0; From daefa7695928f90138d4d87c4f88a645c1a5f29b Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 21 Apr 2011 14:48:54 +0200 Subject: [PATCH 036/432] Provide rtnl_tc_get_link() and fix link refcnt Adds rtnl_tc_get_link() returning the link associated with a tc object. Don't clone link associated with tc object when cloning the tc object, refer to same link instead and bump refcnt. Fix refcnt leak when assigning link in msg parser. --- lib/route/tc.c | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/lib/route/tc.c b/lib/route/tc.c index 0aa44f7..03920aa 100644 --- a/lib/route/tc.c +++ b/lib/route/tc.c @@ -179,8 +179,12 @@ compat_xstats: if ((link_cache = nl_cache_mngt_require("route/link"))) { struct rtnl_link *link; - if ((link = rtnl_link_get(link_cache, tc->tc_ifindex))) + if ((link = rtnl_link_get(link_cache, tc->tc_ifindex))) { rtnl_tc_set_link(tc, link); + + /* rtnl_tc_set_link incs refcnt */ + rtnl_link_put(link); + } } return 0; @@ -300,6 +304,33 @@ void rtnl_tc_set_link(struct rtnl_tc *tc, struct rtnl_link *link) tc->ce_mask |= TCA_ATTR_LINK | TCA_ATTR_IFINDEX; } +/** + * Get link of traffic control object + * @arg tc traffic control object + * @arg link link object + * + * Returns the link of a traffic control object. The link is only + * returned if it has been set before via rtnl_tc_set_link() or + * if a link cache was available while parsing the tc object. This + * function may still return NULL even if an ifindex is assigned to + * the tc object. It will _not_ look up the link by itself. + * + * @note The returned link will have its reference counter incremented. + * It is in the responsibility of the caller to return the + * reference. + * + * @return link object or NULL if not set. + */ +struct rtnl_link *rtnl_tc_get_link(struct rtnl_tc *tc) +{ + if (tc->tc_link) { + nl_object_get(OBJ_CAST(tc->tc_link)); + return tc->tc_link; + } + + return NULL; +} + /** * Set the Maximum Transmission Unit (MTU) of traffic control object * @arg tc traffic control object @@ -720,10 +751,8 @@ int rtnl_tc_clone(struct nl_object *dstobj, struct nl_object *srcobj) struct rtnl_tc_ops *ops; if (src->tc_link) { - dst->tc_link = (struct rtnl_link *) - nl_object_clone(OBJ_CAST(src->tc_link)); - if (!dst->tc_link) - return -NLE_NOMEM; + nl_object_get(OBJ_CAST(src->tc_link)); + dst->tc_link = src->tc_link; } if (src->tc_opts) { From cc33b0940f8ca0a34c9fbc085963e7887adc4db7 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 21 Apr 2011 14:58:05 +0200 Subject: [PATCH 037/432] Add missing declaration of rtnl_tc_get_link() --- include/netlink/route/tc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/netlink/route/tc.h b/include/netlink/route/tc.h index 6cf8cb8..50ca6de 100644 --- a/include/netlink/route/tc.h +++ b/include/netlink/route/tc.h @@ -71,6 +71,7 @@ enum rtnl_tc_stat { extern void rtnl_tc_set_ifindex(struct rtnl_tc *, int); extern int rtnl_tc_get_ifindex(struct rtnl_tc *); extern void rtnl_tc_set_link(struct rtnl_tc *, struct rtnl_link *); +extern struct rtnl_link *rtnl_tc_get_link(struct rtnl_tc *); extern void rtnl_tc_set_mtu(struct rtnl_tc *, uint32_t); extern uint32_t rtnl_tc_get_mtu(struct rtnl_tc *); extern void rtnl_tc_set_mpu(struct rtnl_tc *, uint32_t); From cb6a089d80df51f8bcd1a1cf6637174fdf483954 Mon Sep 17 00:00:00 2001 From: Romary Sonrier Date: Tue, 3 May 2011 11:26:21 +0200 Subject: [PATCH 038/432] Adding rule with "From" option doesn't work OK i found the bug, is is the patch !! Can someone push it into the git tree ? Regards, Romary Sonrier ========================= My analysis: I guess that the pay load is *struct fib_rule_hdr* struct fib_rule_hdr { __u8 family; __u8 dst_len; __u8 src_len; __u8 tos; __u8 table; __u8 res1; /* reserved */ __u8 res2; /* reserved */ __u8 action; __u32 flags; }; > [PAYLOAD] 12 octets > 02 00 00 00 0a 00 00 01 00 00 00 00 ............ so family = 02 , fine table = 10, fine but src_len =0 !!!! should be 32 --- lib/route/rule.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/route/rule.c b/lib/route/rule.c index 8fa54e9..1a695cd 100644 --- a/lib/route/rule.c +++ b/lib/route/rule.c @@ -374,18 +374,20 @@ static int build_rule_msg(struct rtnl_rule *tmpl, int cmd, int flags, if (!msg) return -NLE_NOMEM; + if (tmpl->ce_mask & RULE_ATTR_SRC) + frh.src_len = nl_addr_get_prefixlen(tmpl->r_src); + + if (tmpl->ce_mask & RULE_ATTR_DST) + frh.dst_len = nl_addr_get_prefixlen(tmpl->r_dst); + if (nlmsg_append(msg, &frh, sizeof(frh), NLMSG_ALIGNTO) < 0) goto nla_put_failure; - if (tmpl->ce_mask & RULE_ATTR_SRC) { - frh.src_len = nl_addr_get_prefixlen(tmpl->r_src); + if (tmpl->ce_mask & RULE_ATTR_SRC) NLA_PUT_ADDR(msg, FRA_SRC, tmpl->r_src); - } - if (tmpl->ce_mask & RULE_ATTR_DST) { - frh.dst_len = nl_addr_get_prefixlen(tmpl->r_dst); + if (tmpl->ce_mask & RULE_ATTR_DST) NLA_PUT_ADDR(msg, FRA_DST, tmpl->r_dst); - } if (tmpl->ce_mask & RULE_ATTR_IIFNAME) NLA_PUT_STRING(msg, FRA_IIFNAME, tmpl->r_iifname); From d44c31da5f089372f911d498a5051dd7f7c25e3a Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 3 May 2011 11:48:14 +0200 Subject: [PATCH 039/432] addr: store link object and provide rtnl_addr_get() stores rtnl_link object in address if cache is availble. Provide access via rtnl_addr_get_link() and rtnl_addr_set_link(). Add rtnl_addr_get() which searches a address cache for an address matching ifindex and local address. --- include/netlink-types.h | 1 + include/netlink/route/addr.h | 8 +++- lib/route/addr.c | 78 +++++++++++++++++++++++++++++++++++- 3 files changed, 85 insertions(+), 2 deletions(-) diff --git a/include/netlink-types.h b/include/netlink-types.h index 1cb7c0e..f842187 100644 --- a/include/netlink-types.h +++ b/include/netlink-types.h @@ -234,6 +234,7 @@ struct rtnl_addr char a_label[IFNAMSIZ]; uint32_t a_flag_mask; + struct rtnl_link *a_link; }; struct rtnl_nexthop diff --git a/include/netlink/route/addr.h b/include/netlink/route/addr.h index 1381486..df447f7 100644 --- a/include/netlink/route/addr.h +++ b/include/netlink/route/addr.h @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2011 Thomas Graf * Copyright (c) 2003-2006 Baruch Even , * Mediatrix Telecom, inc. */ @@ -29,6 +29,8 @@ extern struct rtnl_addr *rtnl_addr_alloc(void); extern void rtnl_addr_put(struct rtnl_addr *); extern int rtnl_addr_alloc_cache(struct nl_sock *, struct nl_cache **); +extern struct rtnl_addr * + rtnl_addr_get(struct nl_cache *, int, struct nl_addr *); extern int rtnl_addr_build_add_request(struct rtnl_addr *, int, struct nl_msg **); @@ -48,6 +50,10 @@ extern char * rtnl_addr_get_label(struct rtnl_addr *); extern void rtnl_addr_set_ifindex(struct rtnl_addr *, int); extern int rtnl_addr_get_ifindex(struct rtnl_addr *); +extern void rtnl_addr_set_link(struct rtnl_addr *, struct rtnl_link *); +extern struct rtnl_link * + rtnl_addr_get_link(struct rtnl_addr *); + extern void rtnl_addr_set_family(struct rtnl_addr *, int); extern int rtnl_addr_get_family(struct rtnl_addr *); diff --git a/lib/route/addr.c b/lib/route/addr.c index b367883..fa6d76d 100644 --- a/lib/route/addr.c +++ b/lib/route/addr.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2011 Thomas Graf * Copyright (c) 2003-2006 Baruch Even , * Mediatrix Telecom, inc. */ @@ -158,6 +158,11 @@ static int addr_clone(struct nl_object *_dst, struct nl_object *_src) struct rtnl_addr *dst = nl_object_priv(_dst); struct rtnl_addr *src = nl_object_priv(_src); + if (src->a_link) { + nl_object_get(OBJ_CAST(src->a_link)); + dst->a_link = src->a_link; + } + if (src->a_peer) if (!(dst->a_peer = nl_addr_clone(src->a_peer))) return -NLE_NOMEM; @@ -194,6 +199,7 @@ static int addr_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, struct ifaddrmsg *ifa; struct nlattr *tb[IFA_MAX+1]; int err, peer_prefix = 0, family; + struct nl_cache *link_cache; addr = rtnl_addr_alloc(); if (!addr) @@ -288,6 +294,17 @@ static int addr_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, addr->ce_mask |= ADDR_ATTR_ANYCAST; } + if ((link_cache = nl_cache_mngt_require("route/link"))) { + struct rtnl_link *link; + + if ((link = rtnl_link_get(link_cache, addr->a_ifindex))) { + rtnl_addr_set_link(addr, link); + + /* rtnl_addr_set_link incs refcnt */ + rtnl_link_put(link); + } + } + err = pp->pp_cb((struct nl_object *) addr, pp); errout: rtnl_addr_put(addr); @@ -478,6 +495,42 @@ int rtnl_addr_alloc_cache(struct nl_sock *sk, struct nl_cache **result) return nl_cache_alloc_and_fill(&rtnl_addr_ops, sk, result); } +/** + * Search address in cache + * @arg cache Address cache + * @arg ifindex Interface index of address + * @arg addr Local address part + * + * Searches address cache previously allocated with rtnl_addr_alloc_cache() + * for an address with a matching local address. + * + * The reference counter is incremented before returning the address, therefore + * the reference must be given back with rtnl_addr_put() after usage. + * + * @return Address object or NULL if no match was found. + */ +struct rtnl_addr *rtnl_addr_get(struct nl_cache *cache, int ifindex, + struct nl_addr *addr) +{ + struct rtnl_addr *a; + + if (cache->c_ops != &rtnl_addr_ops) + return NULL; + + nl_list_for_each_entry(a, &cache->c_items, ce_list) { + if (ifindex && a->a_ifindex != ifindex) + continue; + + if (a->ce_mask & ADDR_ATTR_LOCAL && + !nl_addr_cmp(a->a_local, addr)) { + nl_object_get((struct nl_object *) a); + return a; + } + } + + return NULL; +} + /** @} */ static int build_addr_msg(struct rtnl_addr *tmpl, int cmd, int flags, @@ -719,6 +772,29 @@ int rtnl_addr_get_ifindex(struct rtnl_addr *addr) return addr->a_ifindex; } +void rtnl_addr_set_link(struct rtnl_addr *addr, struct rtnl_link *link) +{ + rtnl_link_put(addr->a_link); + + if (!link) + return; + + nl_object_get(OBJ_CAST(link)); + addr->a_link = link; + addr->a_ifindex = link->l_index; + addr->ce_mask |= ADDR_ATTR_IFINDEX; +} + +struct rtnl_link *rtnl_addr_get_link(struct rtnl_addr *addr) +{ + if (addr->a_link) { + nl_object_get(OBJ_CAST(addr->a_link)); + return addr->a_link; + } + + return NULL; +} + void rtnl_addr_set_family(struct rtnl_addr *addr, int family) { addr->a_family = family; From 023c66232704a5afe7c0e9e675b389649ea70bd4 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 4 May 2011 17:47:09 +0200 Subject: [PATCH 040/432] Use name "global" instead of "universe" for largest scope This name is more widespread and easier to understand even though it is less correct. --- lib/route/rtnl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/route/rtnl.c b/lib/route/rtnl.c index 26d1f67..e5c0798 100644 --- a/lib/route/rtnl.c +++ b/lib/route/rtnl.c @@ -89,7 +89,7 @@ static const struct trans_tbl scopes[] = { __ADD(254,host) __ADD(253,link) __ADD(200,site) - __ADD(0,universe) + __ADD(0,global) }; char *rtnl_scope2str(int scope, char *buf, size_t size) From f443be6e744ac9be2ad48bd59432d5c2215d4e51 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 10 May 2011 12:17:33 +0200 Subject: [PATCH 041/432] python interface to netlink protocols currently includes experimental support for links, addresses and some traffic control --- configure.in | 5 + m4/ax_pkg_swig.m4 | 135 +++++ m4/ax_python_devel.m4 | 325 +++++++++++ m4/ax_swig_python.m4 | 64 +++ python/doc/conf.py | 216 ++++++++ python/doc/core.rst | 215 ++++++++ python/doc/index.rst | 24 + python/doc/route.rst | 3 + python/doc/route_addr.rst | 47 ++ python/netlink/__init__.py | 0 python/netlink/capi.i | 457 +++++++++++++++ python/netlink/core.py | 737 +++++++++++++++++++++++++ python/netlink/fixes.h | 1 + python/netlink/route/__init__.py | 0 python/netlink/route/address.py | 398 +++++++++++++ python/netlink/route/capi.i | 338 ++++++++++++ python/netlink/route/link.py | 596 ++++++++++++++++++++ python/netlink/route/links/__init__.py | 0 python/netlink/route/links/dummy.py | 21 + python/netlink/route/links/inet.py | 153 +++++ python/netlink/route/links/vlan.py | 62 +++ python/netlink/route/qdisc.py | 185 +++++++ python/netlink/route/tc.py | 357 ++++++++++++ python/netlink/util.py | 146 +++++ python/setup.py | 29 + 25 files changed, 4514 insertions(+) create mode 100644 m4/ax_pkg_swig.m4 create mode 100644 m4/ax_python_devel.m4 create mode 100644 m4/ax_swig_python.m4 create mode 100644 python/doc/conf.py create mode 100644 python/doc/core.rst create mode 100644 python/doc/index.rst create mode 100644 python/doc/route.rst create mode 100644 python/doc/route_addr.rst create mode 100644 python/netlink/__init__.py create mode 100644 python/netlink/capi.i create mode 100644 python/netlink/core.py create mode 100644 python/netlink/fixes.h create mode 100644 python/netlink/route/__init__.py create mode 100644 python/netlink/route/address.py create mode 100644 python/netlink/route/capi.i create mode 100644 python/netlink/route/link.py create mode 100644 python/netlink/route/links/__init__.py create mode 100644 python/netlink/route/links/dummy.py create mode 100644 python/netlink/route/links/inet.py create mode 100644 python/netlink/route/links/vlan.py create mode 100644 python/netlink/route/qdisc.py create mode 100644 python/netlink/route/tc.py create mode 100644 python/netlink/util.py create mode 100644 python/setup.py diff --git a/configure.in b/configure.in index 43150a7..00ad3ee 100644 --- a/configure.in +++ b/configure.in @@ -27,6 +27,11 @@ AM_PROG_LIBTOOL AM_PROG_LEX AC_PROG_YACC +AM_PATH_PYTHON(2.6) +AX_PKG_SWIG +AX_PYTHON_DEVEL +AX_SWIG_PYTHON + AC_C_CONST AC_C_INLINE diff --git a/m4/ax_pkg_swig.m4 b/m4/ax_pkg_swig.m4 new file mode 100644 index 0000000..e112f3d --- /dev/null +++ b/m4/ax_pkg_swig.m4 @@ -0,0 +1,135 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_pkg_swig.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PKG_SWIG([major.minor.micro], [action-if-found], [action-if-not-found]) +# +# DESCRIPTION +# +# This macro searches for a SWIG installation on your system. If found, +# then SWIG is AC_SUBST'd; if not found, then $SWIG is empty. If SWIG is +# found, then SWIG_LIB is set to the SWIG library path, and AC_SUBST'd. +# +# You can use the optional first argument to check if the version of the +# available SWIG is greater than or equal to the value of the argument. It +# should have the format: N[.N[.N]] (N is a number between 0 and 999. Only +# the first N is mandatory.) If the version argument is given (e.g. +# 1.3.17), AX_PKG_SWIG checks that the swig package is this version number +# or higher. +# +# As usual, action-if-found is executed if SWIG is found, otherwise +# action-if-not-found is executed. +# +# In configure.in, use as: +# +# AX_PKG_SWIG(1.3.17, [], [ AC_MSG_ERROR([SWIG is required to build..]) ]) +# AX_SWIG_ENABLE_CXX +# AX_SWIG_MULTI_MODULE_SUPPORT +# AX_SWIG_PYTHON +# +# LICENSE +# +# Copyright (c) 2008 Sebastian Huber +# Copyright (c) 2008 Alan W. Irwin +# Copyright (c) 2008 Rafael Laboissiere +# Copyright (c) 2008 Andrew Collier +# Copyright (c) 2011 Murray Cumming +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 8 + +AC_DEFUN([AX_PKG_SWIG],[ + # Ubuntu has swig 2.0 as /usr/bin/swig2.0 + AC_PATH_PROGS([SWIG],[swig swig2.0]) + if test -z "$SWIG" ; then + m4_ifval([$3],[$3],[:]) + elif test -n "$1" ; then + AC_MSG_CHECKING([SWIG version]) + [swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`] + AC_MSG_RESULT([$swig_version]) + if test -n "$swig_version" ; then + # Calculate the required version number components + [required=$1] + [required_major=`echo $required | sed 's/[^0-9].*//'`] + if test -z "$required_major" ; then + [required_major=0] + fi + [required=`echo $required | sed 's/[0-9]*[^0-9]//'`] + [required_minor=`echo $required | sed 's/[^0-9].*//'`] + if test -z "$required_minor" ; then + [required_minor=0] + fi + [required=`echo $required | sed 's/[0-9]*[^0-9]//'`] + [required_patch=`echo $required | sed 's/[^0-9].*//'`] + if test -z "$required_patch" ; then + [required_patch=0] + fi + # Calculate the available version number components + [available=$swig_version] + [available_major=`echo $available | sed 's/[^0-9].*//'`] + if test -z "$available_major" ; then + [available_major=0] + fi + [available=`echo $available | sed 's/[0-9]*[^0-9]//'`] + [available_minor=`echo $available | sed 's/[^0-9].*//'`] + if test -z "$available_minor" ; then + [available_minor=0] + fi + [available=`echo $available | sed 's/[0-9]*[^0-9]//'`] + [available_patch=`echo $available | sed 's/[^0-9].*//'`] + if test -z "$available_patch" ; then + [available_patch=0] + fi + # Convert the version tuple into a single number for easier comparison. + # Using base 100 should be safe since SWIG internally uses BCD values + # to encode its version number. + required_swig_vernum=`expr $required_major \* 10000 \ + \+ $required_minor \* 100 \+ $required_patch` + available_swig_vernum=`expr $available_major \* 10000 \ + \+ $available_minor \* 100 \+ $available_patch` + + if test $available_swig_vernum -lt $required_swig_vernum; then + AC_MSG_WARN([SWIG version >= $1 is required. You have $swig_version.]) + SWIG='' + m4_ifval([$3],[$3],[]) + else + AC_MSG_CHECKING([for SWIG library]) + SWIG_LIB=`$SWIG -swiglib` + AC_MSG_RESULT([$SWIG_LIB]) + m4_ifval([$2],[$2],[]) + fi + else + AC_MSG_WARN([cannot determine SWIG version]) + SWIG='' + m4_ifval([$3],[$3],[]) + fi + fi + AC_SUBST([SWIG_LIB]) +]) diff --git a/m4/ax_python_devel.m4 b/m4/ax_python_devel.m4 new file mode 100644 index 0000000..a62b860 --- /dev/null +++ b/m4/ax_python_devel.m4 @@ -0,0 +1,325 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_python_devel.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PYTHON_DEVEL([version]) +# +# DESCRIPTION +# +# Note: Defines as a precious variable "PYTHON_VERSION". Don't override it +# in your configure.ac. +# +# This macro checks for Python and tries to get the include path to +# 'Python.h'. It provides the $(PYTHON_CPPFLAGS) and $(PYTHON_LDFLAGS) +# output variables. It also exports $(PYTHON_EXTRA_LIBS) and +# $(PYTHON_EXTRA_LDFLAGS) for embedding Python in your code. +# +# You can search for some particular version of Python by passing a +# parameter to this macro, for example ">= '2.3.1'", or "== '2.4'". Please +# note that you *have* to pass also an operator along with the version to +# match, and pay special attention to the single quotes surrounding the +# version number. Don't use "PYTHON_VERSION" for this: that environment +# variable is declared as precious and thus reserved for the end-user. +# +# This macro should work for all versions of Python >= 2.1.0. As an end +# user, you can disable the check for the python version by setting the +# PYTHON_NOVERSIONCHECK environment variable to something else than the +# empty string. +# +# If you need to use this macro for an older Python version, please +# contact the authors. We're always open for feedback. +# +# LICENSE +# +# Copyright (c) 2009 Sebastian Huber +# Copyright (c) 2009 Alan W. Irwin +# Copyright (c) 2009 Rafael Laboissiere +# Copyright (c) 2009 Andrew Collier +# Copyright (c) 2009 Matteo Settenvini +# Copyright (c) 2009 Horst Knorr +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 8 + +AU_ALIAS([AC_PYTHON_DEVEL], [AX_PYTHON_DEVEL]) +AC_DEFUN([AX_PYTHON_DEVEL],[ + # + # Allow the use of a (user set) custom python version + # + AC_ARG_VAR([PYTHON_VERSION],[The installed Python + version to use, for example '2.3'. This string + will be appended to the Python interpreter + canonical name.]) + + AC_PATH_PROG([PYTHON],[python[$PYTHON_VERSION]]) + if test -z "$PYTHON"; then + AC_MSG_ERROR([Cannot find python$PYTHON_VERSION in your system path]) + PYTHON_VERSION="" + fi + + # + # Check for a version of Python >= 2.1.0 + # + AC_MSG_CHECKING([for a version of Python >= '2.1.0']) + ac_supports_python_ver=`$PYTHON -c "import sys; \ + ver = sys.version.split ()[[0]]; \ + print (ver >= '2.1.0')"` + if test "$ac_supports_python_ver" != "True"; then + if test -z "$PYTHON_NOVERSIONCHECK"; then + AC_MSG_RESULT([no]) + AC_MSG_FAILURE([ +This version of the AC@&t@_PYTHON_DEVEL macro +doesn't work properly with versions of Python before +2.1.0. You may need to re-run configure, setting the +variables PYTHON_CPPFLAGS, PYTHON_LDFLAGS, PYTHON_SITE_PKG, +PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand. +Moreover, to disable this check, set PYTHON_NOVERSIONCHECK +to something else than an empty string. +]) + else + AC_MSG_RESULT([skip at user request]) + fi + else + AC_MSG_RESULT([yes]) + fi + + # + # if the macro parameter ``version'' is set, honour it + # + if test -n "$1"; then + AC_MSG_CHECKING([for a version of Python $1]) + ac_supports_python_ver=`$PYTHON -c "import sys; \ + ver = sys.version.split ()[[0]]; \ + print (ver $1)"` + if test "$ac_supports_python_ver" = "True"; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + AC_MSG_ERROR([this package requires Python $1. +If you have it installed, but it isn't the default Python +interpreter in your system path, please pass the PYTHON_VERSION +variable to configure. See ``configure --help'' for reference. +]) + PYTHON_VERSION="" + fi + fi + + # + # Check if you have distutils, else fail + # + AC_MSG_CHECKING([for the distutils Python package]) + ac_distutils_result=`$PYTHON -c "import distutils" 2>&1` + if test -z "$ac_distutils_result"; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + AC_MSG_ERROR([cannot import Python module "distutils". +Please check your Python installation. The error was: +$ac_distutils_result]) + PYTHON_VERSION="" + fi + + # + # Check for Python include path + # + AC_MSG_CHECKING([for Python include path]) + if test -z "$PYTHON_CPPFLAGS"; then + python_path=`$PYTHON -c "import distutils.sysconfig; \ + print (distutils.sysconfig.get_python_inc ());"` + if test -n "${python_path}"; then + python_path="-I$python_path" + fi + PYTHON_CPPFLAGS=$python_path + fi + AC_MSG_RESULT([$PYTHON_CPPFLAGS]) + AC_SUBST([PYTHON_CPPFLAGS]) + + # + # Check for Python library path + # + AC_MSG_CHECKING([for Python library path]) + if test -z "$PYTHON_LDFLAGS"; then + # (makes two attempts to ensure we've got a version number + # from the interpreter) + ac_python_version=`cat<]], + [[Py_Initialize();]]) + ],[pythonexists=yes],[pythonexists=no]) + AC_LANG_POP([C]) + # turn back to default flags + CPPFLAGS="$ac_save_CPPFLAGS" + LIBS="$ac_save_LIBS" + + AC_MSG_RESULT([$pythonexists]) + + if test ! "x$pythonexists" = "xyes"; then + AC_MSG_FAILURE([ + Could not link test program to Python. Maybe the main Python library has been + installed in some non-standard library path. If so, pass it to configure, + via the LDFLAGS environment variable. + Example: ./configure LDFLAGS="-L/usr/non-standard-path/python/lib" + ============================================================================ + ERROR! + You probably have to install the development version of the Python package + for your distribution. The exact name of this package varies among them. + ============================================================================ + ]) + PYTHON_VERSION="" + fi + + # + # all done! + # +]) diff --git a/m4/ax_swig_python.m4 b/m4/ax_swig_python.m4 new file mode 100644 index 0000000..8fd3df5 --- /dev/null +++ b/m4/ax_swig_python.m4 @@ -0,0 +1,64 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_swig_python.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_SWIG_PYTHON([use-shadow-classes = {no, yes}]) +# +# DESCRIPTION +# +# Checks for Python and provides the $(AX_SWIG_PYTHON_CPPFLAGS), and +# $(AX_SWIG_PYTHON_OPT) output variables. +# +# $(AX_SWIG_PYTHON_OPT) contains all necessary SWIG options to generate +# code for Python. Shadow classes are enabled unless the value of the +# optional first argument is exactly 'no'. If you need multi module +# support (provided by the AX_SWIG_MULTI_MODULE_SUPPORT macro) use +# $(AX_SWIG_PYTHON_LIBS) to link against the appropriate library. It +# contains the SWIG Python runtime library that is needed by the type +# check system for example. +# +# LICENSE +# +# Copyright (c) 2008 Sebastian Huber +# Copyright (c) 2008 Alan W. Irwin +# Copyright (c) 2008 Rafael Laboissiere +# Copyright (c) 2008 Andrew Collier +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 7 + +AU_ALIAS([SWIG_PYTHON], [AX_SWIG_PYTHON]) +AC_DEFUN([AX_SWIG_PYTHON],[ + AC_REQUIRE([AX_PKG_SWIG]) + AC_REQUIRE([AX_PYTHON_DEVEL]) + test "x$1" != "xno" || swig_shadow=" -noproxy" + AC_SUBST([AX_SWIG_PYTHON_OPT],[-python$swig_shadow]) + AC_SUBST([AX_SWIG_PYTHON_CPPFLAGS],[$PYTHON_CPPFLAGS]) +]) diff --git a/python/doc/conf.py b/python/doc/conf.py new file mode 100644 index 0000000..74041f0 --- /dev/null +++ b/python/doc/conf.py @@ -0,0 +1,216 @@ +# -*- coding: utf-8 -*- +# +# libnl-python documentation build configuration file, created by +# sphinx-quickstart on Mon May 9 10:58:58 2011. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.todo', 'sphinx.ext.ifconfig', 'sphinx.ext.viewcode'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'libnl-python' +copyright = u'2011, Thomas Graf ' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '1.0' +# The full version, including alpha/beta/rc tags. +release = '1.0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'libnl-pythondoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'libnl-python.tex', u'libnl-python Documentation', + u'Thomas Graf \\textless{}tgraf@suug.ch\\textgreater{}', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'libnl-python', u'libnl-python Documentation', + [u'Thomas Graf '], 1) +] diff --git a/python/doc/core.rst b/python/doc/core.rst new file mode 100644 index 0000000..012e14c --- /dev/null +++ b/python/doc/core.rst @@ -0,0 +1,215 @@ +******************* +Netlink Core Module +******************* + +.. py:module:: netlink.core + +Examples:: + + import netlink.core as netlink + +=============== +Object +=============== + +.. py:class:: Object + + Base class for all classes representing a cacheable object + + Example:: + obj = netlink.Object("route/link", "link") + + .. py:method:: clone + + Clone the object and return a duplicate (used for COW) + + .. py:method:: dump([params=None]) + + Call the libnl internal dump mechanism to dump the object + according to the parameters specified. + + .. py:method:: apply(attr, val) + + Applies a attribute=value pair and modifies the object accordingly. + Example:: + obj.apply("mtu", 1200) # Sets attribute mtu to 1200 (link obj) + + :raises: KeyError if attribute is unknown + :raises: ImmutableError if attribute is not mutable + + .. py:attribute:: mark + + True if the object is marked, otherwise False. + + .. py:attribute:: shared + + True if the object is used by multiple parties, otherwise False. + + .. py:attribute:: refcnt + + Number of users sharing a reference to the object + :rtype: int + + .. py:attribute:: attrs + + List of attributes + + :rtype: list of strings + +=============== +Cache +=============== + +.. py:class:: Cache + + Base class for all cache implementations. + + A cache is a collection of cacheable objects which is typically used + by netlink protocols which handle any kind of object, e.g. network + links, network addresses, neighbours, ... + + .. py:method:: subset(filter) + + Returns a new cache containing the subset which matches the + provided filter. + + :raises: ValueError if no filter is specified + :rtype: :py:class:`Cache` + + .. py:method:: dump([params=None, filter=None]) + + Calls the libnl internal dump mechanism to dump the cache according + to the parameters and filter specified. + + .. py:method:: clear() + + Remove and possibly destroy all objects in the cache + + .. py:method:: refill([socket=None]) -> :py:class:`Cache` + + Clears and refills the cache with the content which is provided by + the kernel, e.g. for a link cache this would mean refilling the + cache with all configured network links. + + .. py:method:: provide() + + Caches which have been "provided" are made available to other users + (of the same application context) which "require" it. F.e. a link + cache is generally provided to allow others to translate interface + indexes to link names + + + .. py:method:: unprovide() + + No longer make the cache available to others. If the cache has been + handed out already, that reference will still be valid. + +=============== +AbstractAddress +=============== + +.. py:class:: AbstractAddress + + Abstract representation of an address. This class is not to be mistaken + with :py:class:`route.Address` which represents a configured network + address. This class represents the actual address in a family independent + way:: + + addr = netlink.AbstractAddress('127.0.0.1/8') + print addr # => '127.0.0.1/8' + print addr.prefixlen # => '8' + print addr.family # => 'inet' + print len(addr) # => '4' (32bit ipv4 address) + + a = netlink.AbstractAddress('10.0.0.1/24') + b = netlink.AbstractAddress('10.0.0.2/24') + print a == b # => False + + .. py:attribute:: prefixlen + + Length of prefix in number of bits. + + :rtype: int + + .. py:attribute:: family + + The family type of the address. Setting the address family can be + done with a string or a :py:class:`AddressFamily` object. + + :rtype: :py:class:`AddressFamily` + + .. py:attribute:: shared + + True if address is in use by multiple callers, otherwise False + + :rtype: bool + +=============== +AddressFamily +=============== + +.. py:class:: AddressFamily + + Address family representation:: + + af = netlink.AddressFamily('inet6') + # raises: + # - ValueError if family name is not known + # - TypeError if invalid type is specified for family + + print af # => 'inet6' (string representation) + print int(af) # => 10 (numeric representation) + print repr(af) # => AddressFamily('inet6') + +=============== +Exceptions +=============== + +.. py:exception:: NetlinkError + + Generic exception raised by netlink modules. + +.. py:exception:: KernelError + + Raised if an error occured while communicating with the kernel. Contains + the error code returning which is automatically included in the error + message. + +.. py:exception:: ImmutableError + + Raised if an attribute is modified which is marked immutable. + +=============== +Socket +=============== + +.. py:class:: Socket + + Netlink socket. + + Note: It is not required to manually create and connect netlink sockets + when using caches. The caches will automatically lookup or create a + socket as needed. + + .. py:attribute:: local_port + + Local port (address) of netlink socket + + .. py:attribute:: peer_port + + Peer port (remote address) of netlink socket. If set, all messages + will be sent to that peer. + + .. py:method:: connect(proto) + + Connect the netlink socket using the specified netlink protocol:: + sock.connect(netlink.NETLINK_ROUTE) + + .. py:method:: disconnect() + + Disconnect the socket + + .. py:method:: set_bufsize(rx, tx) + + Sets the size of the socket buffer + diff --git a/python/doc/index.rst b/python/doc/index.rst new file mode 100644 index 0000000..8de8ae3 --- /dev/null +++ b/python/doc/index.rst @@ -0,0 +1,24 @@ +.. libnl-python documentation master file, created by + sphinx-quickstart on Mon May 9 10:58:58 2011. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to libnl-python's documentation! +======================================== + +Contents: + +.. toctree:: + :maxdepth: 2 + + core + route + route_addr + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/python/doc/route.rst b/python/doc/route.rst new file mode 100644 index 0000000..0b8f3f9 --- /dev/null +++ b/python/doc/route.rst @@ -0,0 +1,3 @@ +********************** +Routing +********************** diff --git a/python/doc/route_addr.rst b/python/doc/route_addr.rst new file mode 100644 index 0000000..2cfe139 --- /dev/null +++ b/python/doc/route_addr.rst @@ -0,0 +1,47 @@ +================= +Network Addresses +================= + +The **Address** module provides access to the network address configuration +of the kernel. It provides an interface to fetch all configured addresses, +add new addresses and to delete existing addresses. + +Fetching the list of network addresses is achieved by creating a new +address cache:: + + import netlink.route.address as Address + + addr_cache = Address.AddressCache() + addr_cache.refill() + + for addr in addr_cache: + print addr + +.. py:module:: netlink.route.addr + + +AddressCache +------------ + +.. py:class:: AddressCache + + Represents a cache containing all or a subset of network addresses. + + .. py:method:: lookup(ifindex, local) + + Lookup the address which matches ifindex and local address + + :raises: KeyError if address is not found. + +Address +------- + +.. py:class:: Address + + Representation of a configured network address. + + .. py:attribute:: ifindex + + Interface index + + :rtype: int diff --git a/python/netlink/__init__.py b/python/netlink/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python/netlink/capi.i b/python/netlink/capi.i new file mode 100644 index 0000000..d80d87b --- /dev/null +++ b/python/netlink/capi.i @@ -0,0 +1,457 @@ +%module capi +%{ +#include +#include +#include +#include +#include +#include +%} + +%include +%include + +%inline %{ + struct nl_dump_params *alloc_dump_params(void) + { + struct nl_dump_params *dp; + if (!(dp = calloc(1, sizeof(*dp)))) + return NULL; + dp->dp_fd = stdout; + return dp; + } + + void free_dump_params(struct nl_dump_params *dp) + { + free(dp); + } +%}; + +/* */ + +enum nl_dump_type { + NL_DUMP_LINE, /**< Dump object briefly on one line */ + NL_DUMP_DETAILS, /**< Dump all attributes but no statistics */ + NL_DUMP_STATS, /**< Dump all attributes including statistics */ + __NL_DUMP_MAX, +}; + +struct nl_dump_params +{ + /** + * Specifies the type of dump that is requested. + */ + enum nl_dump_type dp_type; + + /** + * Specifies the number of whitespaces to be put in front + * of every new line (indentation). + */ + int dp_prefix; + + /** + * Causes the cache index to be printed for each element. + */ + int dp_print_index; + + /** + * Causes each element to be prefixed with the message type. + */ + int dp_dump_msgtype; + + /** + * A callback invoked for output + * + * Passed arguments are: + * - dumping parameters + * - string to append to the output + */ + void (*dp_cb)(struct nl_dump_params *, char *); + + /** + * A callback invoked for every new line, can be used to + * customize the indentation. + * + * Passed arguments are: + * - dumping parameters + * - line number starting from 0 + */ + void (*dp_nl_cb)(struct nl_dump_params *, int); + + /** + * User data pointer, can be used to pass data to callbacks. + */ + void *dp_data; + + /** + * File descriptor the dumping output should go to + */ + FILE * dp_fd; + + /** + * Alternatively the output may be redirected into a buffer + */ + char * dp_buf; + + /** + * Length of the buffer dp_buf + */ + size_t dp_buflen; + + /** + * PRIVATE + * Set if a dump was performed prior to the actual dump handler. + */ + int dp_pre_dump; + + /** + * PRIVATE + * Owned by the current caller + */ + int dp_ivar; + + unsigned int dp_line; +}; + +/* */ +extern const char *nl_geterror(int); + +/* */ + +extern double nl_cancel_down_bytes(unsigned long long, char **); +extern double nl_cancel_down_bits(unsigned long long, char **); +extern double nl_cancel_down_us(uint32_t, char **); + +extern long nl_size2int(const char *); +%cstring_output_maxsize(char *buf, const size_t len) +extern char *nl_size2str(const size_t, char *buf, const size_t len); +extern long nl_prob2int(const char *); + +extern int nl_get_user_hz(void); +extern uint32_t nl_us2ticks(uint32_t); +extern uint32_t nl_ticks2us(uint32_t); +extern int nl_str2msec(const char *, uint64_t *); + +%cstring_output_maxsize(char *buf, size_t len) +extern char *nl_msec2str(uint64_t, char *buf, size_t len); + +%cstring_output_maxsize(char *buf, size_t len) +extern char *nl_llproto2str(int, char *buf, size_t len); +extern int nl_str2llproto(const char *); + +%cstring_output_maxsize(char *buf, size_t len) +extern char *nl_ether_proto2str(int, char *buf, size_t len); +extern int nl_str2ether_proto(const char *); + +%cstring_output_maxsize(char *buf, size_t len) +extern char *nl_ip_proto2str(int, char *buf, size_t len); +extern int nl_str2ip_proto(const char *); + +extern void nl_new_line(struct nl_dump_params *); +extern void nl_dump(struct nl_dump_params *, const char *, ...); +extern void nl_dump_line(struct nl_dump_params *, const char *, ...); + +/* */ +extern struct nl_dump_params *alloc_dump_params(void); +extern void free_dump_params(struct nl_dump_params *); + +extern int nl_connect(struct nl_sock *, int); +extern void nl_close(struct nl_sock *); +extern int nl_pickup(struct nl_sock *, int (*parser)(struct nl_cache_ops *, + struct sockaddr_nl *, + struct nlmsghdr *, + struct nl_parser_param *), + struct nl_object **); + +/* */ +extern struct nl_sock *nl_socket_alloc(void); +extern struct nl_sock *nl_socket_alloc_cb(struct nl_cb *); +extern void nl_socket_free(struct nl_sock *); + +extern uint32_t nl_socket_get_local_port(const struct nl_sock *); +extern void nl_socket_set_local_port(struct nl_sock *, uint32_t); + +extern uint32_t nl_socket_get_peer_port(const struct nl_sock *); +extern void nl_socket_set_peer_port(struct nl_sock *, uint32_t); + +extern uint32_t nl_socket_get_peer_groups(const struct nl_sock *sk); +extern void nl_socket_set_peer_groups(struct nl_sock *sk, uint32_t groups); + +extern int nl_socket_set_buffer_size(struct nl_sock *, int, int); + +/* */ +extern int nlmsg_size(int); +extern int nlmsg_total_size(int); +extern int nlmsg_padlen(int); + +extern void * nlmsg_data(const struct nlmsghdr *); +extern int nlmsg_datalen(const struct nlmsghdr *); +extern void * nlmsg_tail(const struct nlmsghdr *); + +/* attribute access */ +extern struct nlattr * nlmsg_attrdata(const struct nlmsghdr *, int); +extern int nlmsg_attrlen(const struct nlmsghdr *, int); + +/* message parsing */ +extern int nlmsg_valid_hdr(const struct nlmsghdr *, int); +extern int nlmsg_ok(const struct nlmsghdr *, int); +extern struct nlmsghdr * nlmsg_next(struct nlmsghdr *, int *); +extern int nlmsg_parse(struct nlmsghdr *, int, struct nlattr **, + int, struct nla_policy *); +extern struct nlattr * nlmsg_find_attr(struct nlmsghdr *, int, int); +extern int nlmsg_validate(struct nlmsghdr *, int, int, + struct nla_policy *); + +extern struct nl_msg * nlmsg_alloc(void); +extern struct nl_msg * nlmsg_alloc_size(size_t); +extern struct nl_msg * nlmsg_alloc_simple(int, int); +extern void nlmsg_set_default_size(size_t); +extern struct nl_msg * nlmsg_inherit(struct nlmsghdr *); +extern struct nl_msg * nlmsg_convert(struct nlmsghdr *); +extern void * nlmsg_reserve(struct nl_msg *, size_t, int); +extern int nlmsg_append(struct nl_msg *, void *, size_t, int); +extern int nlmsg_expand(struct nl_msg *, size_t); + +extern struct nlmsghdr * nlmsg_put(struct nl_msg *, uint32_t, uint32_t, + int, int, int); +extern struct nlmsghdr * nlmsg_hdr(struct nl_msg *); +extern void nlmsg_get(struct nl_msg *); +extern void nlmsg_free(struct nl_msg *); + +/* attribute modification */ +extern void nlmsg_set_proto(struct nl_msg *, int); +extern int nlmsg_get_proto(struct nl_msg *); +extern size_t nlmsg_get_max_size(struct nl_msg *); +extern void nlmsg_set_src(struct nl_msg *, struct sockaddr_nl *); +extern struct sockaddr_nl *nlmsg_get_src(struct nl_msg *); +extern void nlmsg_set_dst(struct nl_msg *, struct sockaddr_nl *); +extern struct sockaddr_nl *nlmsg_get_dst(struct nl_msg *); +extern void nlmsg_set_creds(struct nl_msg *, struct ucred *); +extern struct ucred * nlmsg_get_creds(struct nl_msg *); + +extern char * nl_nlmsgtype2str(int, char *, size_t); +extern int nl_str2nlmsgtype(const char *); + +extern char * nl_nlmsg_flags2str(int, char *, size_t); + +extern int nl_msg_parse(struct nl_msg *, + void (*cb)(struct nl_object *, void *), + void *); + +extern void nl_msg_dump(struct nl_msg *, FILE *); + +%inline %{ + struct nl_object *cast_obj(void *obj) + { + return (struct nl_object *) obj; + } + + struct nl_object *object_alloc_name(const char *name) + { + struct nl_object *obj; + + if (nl_object_alloc_name(name, &obj) < 0) + return NULL; + + return obj; + } +%}; + +extern struct nl_object *nl_object_alloc(struct nl_object_ops *); +extern void nl_object_free(struct nl_object *); +extern struct nl_object *nl_object_clone(struct nl_object *); +extern void nl_object_get(struct nl_object *); +extern void nl_object_put(struct nl_object *); +extern int nl_object_shared(struct nl_object *); + +%cstring_output_maxsize(char *buf, size_t len) +extern void nl_object_dump_buf(struct nl_object *, char *buf, size_t len); + +extern void nl_object_dump(struct nl_object *, struct nl_dump_params *); + +extern int nl_object_identical(struct nl_object *, struct nl_object *); +extern uint32_t nl_object_diff(struct nl_object *, struct nl_object *); +extern int nl_object_match_filter(struct nl_object *, struct nl_object *); + +%cstring_output_maxsize(char *buf, size_t len) +extern char *nl_object_attrs2str(struct nl_object *, uint32_t, char *buf, size_t len); + +%cstring_output_maxsize(char *buf, size_t len) +extern char *nl_object_attr_list(struct nl_object *, char *buf, size_t len); + +extern void nl_object_mark(struct nl_object *); +extern void nl_object_unmark(struct nl_object *); +extern int nl_object_is_marked(struct nl_object *); + +extern int nl_object_get_refcnt(struct nl_object *); + +/* */ + +typedef void (*change_func_t)(struct nl_cache *, struct nl_object *, int, void *); + +%inline %{ + struct nl_cache *alloc_cache_name(const char *name) + { + struct nl_cache *c; + if (nl_cache_alloc_name(name, &c) < 0) + return NULL; + return c; + } + + struct nl_cache_mngr *alloc_cache_mngr(struct nl_sock *sock, + int protocol, int flags) + { + struct nl_cache_mngr *mngr; + + if (nl_cache_mngr_alloc(sock, protocol, flags, &mngr) < 0) + return NULL; + + return mngr; + } + + struct nl_cache *cache_mngr_add(struct nl_cache_mngr *mngr, + const char *name, change_func_t func, + void *arg) + { + struct nl_cache *cache; + + if (nl_cache_mngr_add(mngr, name, func, arg, &cache) < 0) + return NULL; + + return cache; + } +%} + +/* Access Functions */ +extern int nl_cache_nitems(struct nl_cache *); +extern int nl_cache_nitems_filter(struct nl_cache *, + struct nl_object *); +extern struct nl_cache_ops * nl_cache_get_ops(struct nl_cache *); +extern struct nl_object * nl_cache_get_first(struct nl_cache *); +extern struct nl_object * nl_cache_get_last(struct nl_cache *); +extern struct nl_object * nl_cache_get_next(struct nl_object *); +extern struct nl_object * nl_cache_get_prev(struct nl_object *); + +extern struct nl_cache * nl_cache_alloc(struct nl_cache_ops *); +extern struct nl_cache * nl_cache_subset(struct nl_cache *, + struct nl_object *); +extern void nl_cache_clear(struct nl_cache *); +extern void nl_cache_free(struct nl_cache *); + +/* Cache modification */ +extern int nl_cache_add(struct nl_cache *, + struct nl_object *); +extern int nl_cache_parse_and_add(struct nl_cache *, + struct nl_msg *); +extern void nl_cache_remove(struct nl_object *); +extern int nl_cache_refill(struct nl_sock *, + struct nl_cache *); +extern int nl_cache_pickup(struct nl_sock *, + struct nl_cache *); +extern int nl_cache_resync(struct nl_sock *, + struct nl_cache *, + change_func_t, + void *); +extern int nl_cache_include(struct nl_cache *, + struct nl_object *, + change_func_t, + void *); +extern void nl_cache_set_arg1(struct nl_cache *, int); +extern void nl_cache_set_arg2(struct nl_cache *, int); + +/* General */ +extern int nl_cache_is_empty(struct nl_cache *); +extern struct nl_object * nl_cache_search(struct nl_cache *, + struct nl_object *); +extern void nl_cache_mark_all(struct nl_cache *); + +/* Dumping */ +extern void nl_cache_dump(struct nl_cache *, + struct nl_dump_params *); +extern void nl_cache_dump_filter(struct nl_cache *, + struct nl_dump_params *, + struct nl_object *); + +/* Iterators */ +extern void nl_cache_foreach(struct nl_cache *, + void (*cb)(struct nl_object *, + void *), + void *arg); +extern void nl_cache_foreach_filter(struct nl_cache *, + struct nl_object *, + void (*cb)(struct + nl_object *, + void *), + void *arg); + +/* --- cache management --- */ + +/* Cache type management */ +extern struct nl_cache_ops * nl_cache_ops_lookup(const char *); +extern struct nl_cache_ops * nl_cache_ops_associate(int, int); +extern struct nl_msgtype * nl_msgtype_lookup(struct nl_cache_ops *, int); +extern void nl_cache_ops_foreach(void (*cb)(struct nl_cache_ops *, void *), void *); +extern int nl_cache_mngt_register(struct nl_cache_ops *); +extern int nl_cache_mngt_unregister(struct nl_cache_ops *); + +/* Global cache provisioning/requiring */ +extern void nl_cache_mngt_provide(struct nl_cache *); +extern void nl_cache_mngt_unprovide(struct nl_cache *); +extern struct nl_cache * nl_cache_mngt_require(const char *); + +struct nl_cache_mngr; + +#define NL_AUTO_PROVIDE 1 + +extern int nl_cache_mngr_get_fd(struct nl_cache_mngr *); +extern int nl_cache_mngr_poll(struct nl_cache_mngr *, + int); +extern int nl_cache_mngr_data_ready(struct nl_cache_mngr *); +extern void nl_cache_mngr_free(struct nl_cache_mngr *); + +/* */ +%inline %{ + struct nl_addr *addr_parse(const char *addr, int guess) + { + struct nl_addr *result; + + if (nl_addr_parse(addr, guess, &result) < 0) + return NULL; + + return result; + } +%}; + +extern struct nl_addr *nl_addr_alloc(size_t); +extern struct nl_addr *nl_addr_alloc_attr(struct nlattr *, int); +extern struct nl_addr *nl_addr_build(int, void *, size_t); +extern struct nl_addr *nl_addr_clone(struct nl_addr *); + +extern struct nl_addr *nl_addr_get(struct nl_addr *); +extern void nl_addr_put(struct nl_addr *); +extern int nl_addr_shared(struct nl_addr *); + +extern int nl_addr_cmp(struct nl_addr *, struct nl_addr *); +extern int nl_addr_cmp_prefix(struct nl_addr *, struct nl_addr *); +extern int nl_addr_iszero(struct nl_addr *); +extern int nl_addr_valid(char *, int); +extern int nl_addr_guess_family(struct nl_addr *); +extern int nl_addr_fill_sockaddr(struct nl_addr *, struct sockaddr *, socklen_t *); +extern int nl_addr_info(struct nl_addr *, struct addrinfo **); +extern int nl_addr_resolve(struct nl_addr *addr, char *host, size_t hostlen); + +extern void nl_addr_set_family(struct nl_addr *, int); +extern int nl_addr_get_family(struct nl_addr *); +extern int nl_addr_set_binary_addr(struct nl_addr *, void *, size_t); + +extern void *nl_addr_get_binary_addr(struct nl_addr *); +extern unsigned int nl_addr_get_len(struct nl_addr *); +extern void nl_addr_set_prefixlen(struct nl_addr *, int); +extern unsigned int nl_addr_get_prefixlen(struct nl_addr *); + +%cstring_output_maxsize(char *buf, size_t len) +extern char *nl_af2str(int, char *buf, size_t len); +extern int nl_str2af(const char *); + +%cstring_output_maxsize(char *buf, size_t len) +extern char *nl_addr2str(struct nl_addr *, char *buf, size_t len); diff --git a/python/netlink/core.py b/python/netlink/core.py new file mode 100644 index 0000000..f97528d --- /dev/null +++ b/python/netlink/core.py @@ -0,0 +1,737 @@ +# +# Netlink interface based on libnl +# +# Copyright (c) 2011 Thomas Graf +# + +"""netlink library based on libnl + +This module provides an interface to netlink sockets + +The module contains the following public classes: + - Socket -- The netlink socket + - Object -- Abstract object (based on struct nl_obect in libnl) used as + base class for all object types which can be put into a Cache + - Cache -- A collection of objects which are derived from the base + class Object. Used for netlink protocols which maintain a list + or tree of objects. + - DumpParams -- + +The following exceptions are defined: + - NetlinkError -- Base exception for all general purpose exceptions raised. + - KernelError -- Raised when the kernel returns an error as response to a + request. + +All other classes or functions in this module are considered implementation +details. +""" + +import capi +import sys +import socket +import struct + +__all__ = ['Message', 'Socket', 'DumpParams', 'Object', 'Cache', 'KernelError', + 'NetlinkError'] +__version__ = "0.1" + +# netlink protocols +NETLINK_ROUTE = 0 +# NETLINK_UNUSED = 1 +NETLINK_USERSOCK = 2 +NETLINK_FIREWALL = 3 +NETLINK_INET_DIAG = 4 +NETLINK_NFLOG = 5 +NETLINK_XFRM = 6 +NETLINK_SELINUX = 7 +NETLINK_ISCSI = 8 +NETLINK_AUDIT = 9 +NETLINK_FIB_LOOKUP = 10 +NETLINK_CONNECTOR = 11 +NETLINK_NETFILTER = 12 +NETLINK_IP6_FW = 13 +NETLINK_DNRTMSG = 14 +NETLINK_KOBJECT_UEVENT = 15 +NETLINK_GENERIC = 16 +NETLINK_SCSITRANSPORT = 18 +NETLINK_ECRYPTFS = 19 + +NL_DONTPAD = 0 +NL_AUTO_PORT = 0 +NL_AUTO_SEQ = 0 + +NL_DUMP_LINE = 0 +NL_DUMP_DETAILS = 1 +NL_DUMP_STATS = 2 + +NLM_F_REQUEST = 1 +NLM_F_MULTI = 2 +NLM_F_ACK = 4 +NLM_F_ECHO = 8 + +NLM_F_ROOT = 0x100 +NLM_F_MATCH = 0x200 +NLM_F_ATOMIC = 0x400 +NLM_F_DUMP = NLM_F_ROOT | NLM_F_MATCH + +NLM_F_REPLACE = 0x100 +NLM_F_EXCL = 0x200 +NLM_F_CREATE = 0x400 +NLM_F_APPEND = 0x800 + +class NetlinkError(Exception): + def __init__(self, error): + self._error = error + self._msg = capi.nl_geterror(error) + + def __str__(self): + return self._msg + +class KernelError(NetlinkError): + def __str__(self): + return "Kernel returned: " + self._msg + +class ImmutableError(NetlinkError): + def __init__(self, msg): + self._msg = msg + + def __str__(self): + return "Immutable attribute: " + self._msg + +class Message(object): + """Netlink message""" + + def __init__(self, size=0): + if size == 0: + self._msg = capi.nlmsg_alloc() + else: + self._msg = capi.nlmsg_alloc_size(size) + + if self._msg is None: + raise Exception("Message allocation returned NULL") + + def __del__(self): + capi.nlmsg_free(self._msg) + + def __len__(self): + return capi.nlmsg_len(nlmsg_hdr(self._msg)) + + @property + def protocol(self): + return capi.nlmsg_get_proto(self._msg) + + @protocol.setter + def protocol(self, value): + capi.nlmsg_set_proto(self._msg, value) + + @property + def maxSize(self): + return capi.nlmsg_get_max_size(self._msg) + + @property + def hdr(self): + return capi.nlmsg_hdr(self._msg) + + @property + def data(self): + return capi.nlmsg_data(self._msg) + + @property + def attrs(self): + return capi.nlmsg_attrdata(self._msg) + + def send(self, socket): + socket.send(self) + +class Socket(object): + """Netlink socket""" + + def __init__(self, cb=None): + if cb is None: + self._sock = capi.nl_socket_alloc() + else: + self._sock = capi.nl_socket_alloc_cb(cb) + + if self._sock is None: + raise Exception("NULL pointer returned while allocating socket") + + def __del__(self): + capi.nl_socket_free(self._sock) + + def __str__(self): + return "nlsock<" + str(self.localPort) + ">" + + @property + def local_port(self): + return capi.nl_socket_get_local_port(self._sock) + + @local_port.setter + def local_port(self, value): + capi.nl_socket_set_local_port(self._sock, int(value)) + + @property + def peer_port(self): + return capi.nl_socket_get_peer_port(self._sock) + + @peer_port.setter + def peer_port(self, value): + capi.nl_socket_set_peer_port(self._sock, int(value)) + + @property + def peer_groups(self): + return capi.nl_socket_get_peer_groups(self._sock) + + @peer_groups.setter + def peer_groups(self, value): + capi.nl_socket_set_peer_groups(self._sock, value) + + def set_bufsize(self, rx, tx): + capi.nl_socket_set_buffer_size(self._sock, rx, tx) + + def connect(self, proto): + capi.nl_connect(self._sock, proto) + return self + + def disconnect(self): + capi.nl_close(self._sock) + + def sendto(self, buf): + ret = capi.nl_sendto(self._sock, buf, len(buf)) + if ret < 0: + raise Exception("Failed to send") + else: + return ret + +_sockets = {} + +def lookup_socket(protocol): + try: + sock = _sockets[protocol] + except KeyError: + sock = Socket() + sock.connect(protocol) + _sockets[protocol] = sock + + return sock + +class DumpParams(object): + """Dumping parameters""" + + def __init__(self, type=NL_DUMP_LINE): + self._dp = capi.alloc_dump_params() + if not self._dp: + raise Exception("Unable to allocate struct nl_dump_params") + + self._dp.dp_type = type + + def __del__(self): + capi.free_dump_params(self._dp) + + @property + def type(self): + return self._dp.dp_type + + @type.setter + def type(self, value): + self._dp.dp_type = value + + @property + def prefix(self): + return self._dp.dp_prefix + + @prefix.setter + def prefix(self, value): + self._dp.dp_prefix = value + +# underscore this to make sure it is deleted first upon module deletion +_defaultDumpParams = DumpParams(type=NL_DUMP_LINE) + +########################################################################### +# Cacheable Object (Base Class) +class Object(object): + """Cacheable object (base class)""" + + def __init__(self, obj_name, name, obj=None): + self._obj_name = obj_name + self._name = name + + if not obj: + obj = capi.object_alloc_name(self._obj_name) + + self._nl_object = obj + + # Create a clone which stores the original state to notice + # modifications + clone_obj = capi.nl_object_clone(self._nl_object) + self._orig = self._obj2type(clone_obj) + + def __del__(self): + if not self._nl_object: + raise ValueError() + + capi.nl_object_put(self._nl_object) + + def __str__(self): + if hasattr(self, 'format'): + return self.format() + else: + return capi.nl_object_dump_buf(self._nl_object, 4096).rstrip() + + def _new_instance(self): + raise NotImplementedError() + + def clone(self): + """Clone object""" + return self._new_instance(capi.nl_object_clone(self._nl_object)) + + def dump(self, params=None): + """Dump object as human readable text""" + if params is None: + params = _defaultDumpParams + + capi.nl_object_dump(self._nl_object, params._dp) + + ##################################################################### + # mark + @property + def mark(self): + if capi.nl_object_is_marked(self.obj): + return True + else: + return False + + @mark.setter + def mark(self, value): + if value: + capi.nl_object_mark(self._nl_object) + else: + capi.nl_object_unmark(self._nl_object) + + ##################################################################### + # shared + @property + def shared(self): + return capi.nl_object_shared(self._nl_object) != 0 + + ##################################################################### + # attrs + @property + def attrs(self): + attr_list = capi.nl_object_attr_list(self._nl_object, 1024) + return re.split('\W+', attr_list[0]) + + ##################################################################### + # refcnt + @property + def refcnt(self): + return capi.nl_object_get_refcnt(self._nl_object) + + # this method resolves multiple levels of sub types to allow + # accessing properties of subclass/subtypes (e.g. link.vlan.id) + def _resolve(self, attr): + obj = self + l = attr.split('.') + while len(l) > 1: + obj = getattr(obj, l.pop(0)) + return (obj, l.pop(0)) + + def _setattr(self, attr, val): + obj, attr = self._resolve(attr) + return setattr(obj, attr, val) + + def _hasattr(self, attr): + obj, attr = self._resolve(attr) + return hasattr(obj, attr) + + def apply(self, attr, val): + try: + d = attrs[self._name + "." + attr] + except KeyError: + raise KeyError("Unknown " + self._name + + " attribute: " + attr) + + if 'immutable' in d: + raise ImmutableError(attr) + + if not self._hasattr(attr): + raise KeyError("Invalid " + self._name + + " attribute: " + attr) + self._setattr(attr, val) + +class ObjIterator(object): + def __init__(self, cache, obj): + self._cache = cache + + capi.nl_object_get(obj) + self._nl_object = obj + + self._first = 1 + self._end = 0 + + def __del__(self): + if self._nl_object: + capi.nl_object_put(self._nl_object) + + def __iter__(self): + return self + + def get_next(self): + return capi.nl_cache_get_next(self._nl_object) + + def next(self): + if self._end: + raise StopIteration() + + if self._first: + ret = self._nl_object + self._first = 0 + else: + ret = self.get_next() + if not ret: + self._end = 1 + raise StopIteration() + + # return ref of previous element and acquire ref of current + # element to have object stay around until we fetched the + # next ptr + capi.nl_object_put(self._nl_object) + capi.nl_object_get(ret) + self._nl_object = ret + + # reference used inside object + capi.nl_object_get(ret) + return self._cache._new_object(ret) + + +class ReverseObjIterator(ObjIterator): + def get_next(self): + return capi.nl_cache_get_prev(self._nl_object) + +########################################################################### +# Cache +class Cache(object): + """Collection of netlink objects""" + def __init__(self): + raise NotImplementedError() + + def __del(self): + capi.nl_cache_free(self._c_cache) + + def __len__(self): + return capi.nl_cache_nitems(self._c_cache) + + def __iter__(self): + obj = capi.nl_cache_get_first(self._c_cache) + return ObjIterator(self, obj) + + def __reversed__(self): + obj = capi.nl_cache_get_last(self._c_cache) + return ReverseObjIterator(self, obj) + + def __contains__(self, item): + obj = capi.nl_cache_search(self._c_cache, item._nl_object) + if obj is None: + return False + else: + capi.nl_object_put(obj) + return True + + # called by sub classes to allocate type specific caches by name + def _alloc_cache_name(self, name): + return capi.alloc_cache_name(name) + + # implemented by sub classes, must return new instasnce of cacheable + # object + def _new_object(self, obj): + raise NotImplementedError() + + # implemented by sub classes, must return instance of sub class + def _new_cache(self, cache): + raise NotImplementedError() + + def subset(self, filter): + """Return new cache containing subset of cache + + Cretes a new cache containing all objects which match the + specified filter. + """ + if not filter: + raise ValueError() + + c = capi.nl_cache_subset(self._c_cache, filter._nl_object) + return self._new_cache(cache=c) + + def dump(self, params=None, filter=None): + """Dump (print) cache as human readable text""" + if not params: + params = _defaultDumpParams + + if filter: + filter = filter._nl_object + + capi.nl_cache_dump_filter(self._c_cache, params._dp, filter) + + def clear(self): + """Remove all cache entries""" + capi.nl_cache_clear(self._c_cache) + + # Called by sub classes to set first cache argument + def _set_arg1(self, arg): + self.arg1 = arg + capi.nl_cache_set_arg1(self._c_cache, arg) + + # Called by sub classes to set second cache argument + def _set_arg2(self, arg): + self.arg2 = arg + capi.nl_cache_set_arg2(self._c_cache, arg) + + def refill(self, socket=None): + """Clear cache and refill it""" + if socket is None: + socket = lookup_socket(self._protocol) + + capi.nl_cache_refill(socket._sock, self._c_cache) + return self + + def resync(self, socket=None, cb=None): + """Synchronize cache with content in kernel""" + if socket is None: + socket = lookup_socket(self._protocol) + + capi.nl_cache_resync(socket._sock, self._c_cache, cb) + + def provide(self): + """Provide this cache to others + + Caches which have been "provided" are made available + to other users (of the same application context) which + "require" it. F.e. a link cache is generally provided + to allow others to translate interface indexes to + link names + """ + + capi.nl_cache_mngt_provide(self._c_cache) + + def unprovide(self): + """Unprovide this cache + + No longer make the cache available to others. If the cache + has been handed out already, that reference will still + be valid. + """ + capi.nl_cache_mngt_unprovide(self._c_cache) + +########################################################################### +# Cache Manager (Work in Progress) +NL_AUTO_PROVIDE = 1 +class CacheManager(object): + def __init__(self, protocol, flags=None): + + self._sock = Socket() + self._sock.connect(protocol) + + if not flags: + flags = NL_AUTO_PROVIDE + + self._mngr = cache_mngr_alloc(self._sock._sock, protocol, flags) + + def __del__(self): + if self._sock: + self._sock.disconnect() + + if self._mngr: + capi.nl_cache_mngr_free(self._mngr) + + def add(self, name): + capi.cache_mngr_add(self._mngr, name, None, None) + +########################################################################### +# Address Family +class AddressFamily(object): + """Address family representation + + af = AddressFamily('inet6') + # raises: + # - ValueError if family name is not known + # - TypeError if invalid type is specified for family + + print af # => 'inet6' (string representation) + print int(af) # => 10 (numeric representation) + print repr(af) # => AddressFamily('inet6') + """ + def __init__(self, family=socket.AF_UNSPEC): + if isinstance(family, str): + family = capi.nl_str2af(family) + if family < 0: + raise ValueError('Unknown family name') + elif not isinstance(family, int): + raise TypeError() + + self._family = family + + def __str__(self): + return capi.nl_af2str(self._family, 32)[0] + + def __len__(self): + return len(str(self)) + + def __int__(self): + return self._family + + def __repr__(self): + return 'AddressFamily(\'' + str(self) + '\')' + + +########################################################################### +# Abstract Address +class AbstractAddress(object): + """Abstract address object + + addr = AbstractAddress('127.0.0.1/8') + print addr # => '127.0.0.1/8' + print addr.prefixlen # => '8' + print addr.family # => 'inet' + print len(addr) # => '4' (32bit ipv4 address) + + a = AbstractAddress('10.0.0.1/24') + b = AbstractAddress('10.0.0.2/24') + print a == b # => False + + + """ + def __init__(self, addr): + self._nl_addr = None + + if isinstance(addr, str): + addr = capi.addr_parse(addr, socket.AF_UNSPEC) + if addr is None: + raise ValueError('Invalid address format') + elif addr: + capi.nl_addr_get(addr) + + self._nl_addr = addr + + def __del__(self): + if self._nl_addr: + capi.nl_addr_put(self._nl_addr) + + def __cmp__(self, other): + if isinstance(other, str): + other = AbstractAddress(other) + + diff = self.prefixlen - other.prefixlen + if diff == 0: + diff = capi.nl_addr_cmp(self._nl_addr, other._nl_addr) + + return diff + + def contains(self, item): + diff = int(self.family) - int(item.family) + if diff: + return False + + if item.prefixlen < self.prefixlen: + return False + + diff = capi.nl_addr_cmp_prefix(self._nl_addr, item._nl_addr) + return diff == 0 + + def __nonzero__(self): + if self._nl_addr: + return not capi.nl_addr_iszero(self._nl_addr) + else: + return False + + def __len__(self): + if self._nl_addr: + return capi.nl_addr_get_len(self._nl_addr) + else: + return 0 + + def __str__(self): + if self._nl_addr: + return capi.nl_addr2str(self._nl_addr, 64)[0] + else: + return "none" + + @property + def shared(self): + """True if address is shared (multiple users)""" + if self._nl_addr: + return capi.nl_addr_shared(self._nl_addr) != 0 + else: + return False + + @property + def prefixlen(self): + """Length of prefix (number of bits)""" + if self._nl_addr: + return capi.nl_addr_get_prefixlen(self._nl_addr) + else: + return 0 + + @prefixlen.setter + def prefixlen(self, value): + if not self._nl_addr: + raise TypeError() + + capi.nl_addr_set_prefixlen(self._nl_addr, int(value)) + + @property + def family(self): + """Address family""" + f = 0 + if self._nl_addr: + f = capi.nl_addr_get_family(self._nl_addr) + + return AddressFamily(f) + + @family.setter + def family(self, value): + if not self._nl_addr: + raise TypeError() + + if not isinstance(value, AddressFamily): + value = AddressFamily(value) + + capi.nl_addr_set_family(self._nl_addr, int(value)) + + +# global dictionay for all object attributes +# +# attrs[type][keyword] : value +# +# keyword: +# type = { int | str } +# immutable = { True | False } +# fmt = func (formatting function) +# +attrs = {} + +def attr(name, **kwds): + attrs[name] = {} + for k in kwds: + attrs[name][k] = kwds[k] + +def nlattr(name, **kwds): + """netlink object attribute decorator + + decorator used to mark mutable and immutable properties + of netlink objects. All properties marked as such are + regarded to be accessable. + + @netlink.nlattr('my_type.my_attr', type=int) + @property + def my_attr(self): + return self._my_attr + + """ + attrs[name] = {} + for k in kwds: + attrs[name][k] = kwds[k] + + def wrap_fn(func): + return func + + return wrap_fn + diff --git a/python/netlink/fixes.h b/python/netlink/fixes.h new file mode 100644 index 0000000..9a6118b --- /dev/null +++ b/python/netlink/fixes.h @@ -0,0 +1 @@ +#include diff --git a/python/netlink/route/__init__.py b/python/netlink/route/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python/netlink/route/address.py b/python/netlink/route/address.py new file mode 100644 index 0000000..c0ce54f --- /dev/null +++ b/python/netlink/route/address.py @@ -0,0 +1,398 @@ +# +# Copyright (c) 2011 Thomas Graf +# + +"""Module providing access to network addresses +""" + +__version__ = "1.0" +__all__ = [ + 'AddressCache', + 'Address'] + +import datetime +import netlink.core as netlink +import netlink.capi as core_capi +import netlink.route.capi as capi +import netlink.route.link as Link +import netlink.util as util + +########################################################################### +# Address Cache +class AddressCache(netlink.Cache): + """Cache containing network addresses""" + + def __init__(self, cache=None): + if not cache: + cache = self._alloc_cache_name("route/addr") + + self._protocol = netlink.NETLINK_ROUTE + self._c_cache = cache + + def __getitem__(self, key): + # Using ifindex=0 here implies that the local address itself + # is unique, otherwise the first occurence is returned. + return self.lookup(0, key) + + def lookup(self, ifindex, local): + if type(local) is str: + local = netlink.AbstractAddress(local) + + addr = capi.rtnl_addr_get(self._c_cache, ifindex, + local._nl_addr) + if addr is None: + raise KeyError() + + return Address._from_capi(addr) + + def _new_object(self, obj): + return Address(obj) + + def _new_cache(self, cache): + return AddressCache(cache=cache) + +########################################################################### +# Address Object +class Address(netlink.Object): + """Network address""" + + def __init__(self, obj=None): + netlink.Object.__init__(self, "route/addr", "address", obj) + self._rtnl_addr = self._obj2type(self._nl_object) + + @classmethod + def _from_capi(cls, obj): + return cls(capi.addr2obj(obj)) + + def _obj2type(self, obj): + return capi.obj2addr(obj) + + def __cmp__(self, other): + # sort by: + # 1. network link + # 2. address family + # 3. local address (including prefixlen) + diff = self.ifindex - other.ifindex + + if diff == 0: + diff = self.family - other.family + if diff == 0: + diff = capi.nl_addr_cmp(self.local, other.local) + + return diff + + def _new_instance(self, obj): + return Address(obj) + + ##################################################################### + # ifindex + @netlink.nlattr('address.ifindex', type=int, immutable=True, + fmt=util.num) + @property + def ifindex(self): + """interface index""" + return capi.rtnl_addr_get_ifindex(self._rtnl_addr) + + @ifindex.setter + def ifindex(self, value): + link = Link.resolve(value) + if not link: + raise ValueError() + + self.link = link + + ##################################################################### + # link + @netlink.nlattr('address.link', type=str, fmt=util.string) + @property + def link(self): + link = capi.rtnl_addr_get_link(self._rtnl_addr) + if not link: + return None + + return Link.Link.from_capi(link) + + @link.setter + def link(self, value): + if type(value) is str: + try: + value = Link.resolve(value) + except KeyError: + raise ValueError() + + capi.rtnl_addr_set_link(self._rtnl_addr, value._rtnl_link) + + # ifindex is immutable but we assume that if _orig does not + # have an ifindex specified, it was meant to be given here + if capi.rtnl_addr_get_ifindex(self._orig) == 0: + capi.rtnl_addr_set_ifindex(self._orig, value.ifindex) + + ##################################################################### + # label + @netlink.nlattr('address.label', type=str, fmt=util.string) + @property + def label(self): + """address label""" + return capi.rtnl_addr_get_label(self._rtnl_addr) + + @label.setter + def label(self, value): + capi.rtnl_addr_set_label(self._rtnl_addr, value) + + ##################################################################### + # flags + @netlink.nlattr('address.flags', type=str, fmt=util.string) + @property + def flags(self): + """Flags""" + flags = capi.rtnl_addr_get_flags(self._rtnl_addr) + return capi.rtnl_addr_flags2str(flags, 256)[0].split(',') + + def _set_flag(self, flag): + if flag[0] == '-': + i = capi.rtnl_addr_str2flags(flag[1:]) + capi.rtnl_addr_unset_flags(self._rtnl_addr, i) + else: + i = capi.rtnl_addr_str2flags(flag[1:]) + capi.rtnl_addr_set_flags(self._rtnl_addr, i) + + @flags.setter + def flags(self, value): + if type(value) is list: + for flag in value: + self._set_flag(flag) + else: + self._set_flag(value) + + ##################################################################### + # family + @netlink.nlattr('address.family', type=int, immutable=True, + fmt=util.num) + @property + def family(self): + """Address family""" + fam = capi.rtnl_addr_get_family(self._rtnl_addr) + return netlink.AddressFamily(fam) + + @family.setter + def family(self, value): + if not isinstance(value, AddressFamily): + value = AddressFamily(value) + + capi.rtnl_addr_set_family(self._rtnl_addr, int(value)) + + ##################################################################### + # scope + @netlink.nlattr('address.scope', type=int, fmt=util.num) + @property + def scope(self): + """Address scope""" + scope = capi.rtnl_addr_get_scope(self._rtnl_addr) + return capi.rtnl_scope2str(scope, 32)[0] + + @scope.setter + def scope(self, value): + if type(value) is str: + value = capi.rtnl_str2scope(value) + capi.rtnl_addr_set_scope(self._rtnl_addr, value) + + ##################################################################### + # local address + @netlink.nlattr('address.local', type=str, immutable=True, + fmt=util.addr) + @property + def local(self): + """Local address""" + a = capi.rtnl_addr_get_local(self._rtnl_addr) + return netlink.AbstractAddress(a) + + @local.setter + def local(self, value): + a = netlink.AbstractAddress(value) + capi.rtnl_addr_set_local(self._rtnl_addr, a._nl_addr) + + # local is immutable but we assume that if _orig does not + # have a local address specified, it was meant to be given here + if capi.rtnl_addr_get_local(self._orig) is None: + capi.rtnl_addr_set_local(self._orig, a._nl_addr) + + ##################################################################### + # Peer address + @netlink.nlattr('address.peer', type=str, fmt=util.addr) + @property + def peer(self): + """Peer address""" + a = capi.rtnl_addr_get_peer(self._rtnl_addr) + return netlink.AbstractAddress(a) + + @peer.setter + def peer(self, value): + a = netlink.AbstractAddress(value) + capi.rtnl_addr_set_peer(self._rtnl_addr, a._nl_addr) + + ##################################################################### + # Broadcast address + @netlink.nlattr('address.broadcast', type=str, fmt=util.addr) + @property + def broadcast(self): + """Broadcast address""" + a = capi.rtnl_addr_get_broadcast(self._rtnl_addr) + return netlink.AbstractAddress(a) + + @broadcast.setter + def broadcast(self, value): + a = netlink.AbstractAddress(value) + capi.rtnl_addr_set_broadcast(self._rtnl_addr, a._nl_addr) + + ##################################################################### + # Multicast address + @netlink.nlattr('address.multicast', type=str, fmt=util.addr) + @property + def multicast(self): + """multicast address""" + a = capi.rtnl_addr_get_multicast(self._rtnl_addr) + return netlink.AbstractAddress(a) + + @multicast.setter + def multicast(self, value): + try: + a = netlink.AbstractAddress(value) + except ValueError as err: + raise AttributeError('multicast', err) + + capi.rtnl_addr_set_multicast(self._rtnl_addr, a._nl_addr) + + ##################################################################### + # Anycast address + @netlink.nlattr('address.anycast', type=str, fmt=util.addr) + @property + def anycast(self): + """anycast address""" + a = capi.rtnl_addr_get_anycast(self._rtnl_addr) + return netlink.AbstractAddress(a) + + @anycast.setter + def anycast(self, value): + a = netlink.AbstractAddress(value) + capi.rtnl_addr_set_anycast(self._rtnl_addr, a._nl_addr) + + ##################################################################### + # Valid lifetime + @netlink.nlattr('address.valid_lifetime', type=int, immutable=True, + fmt=util.num) + @property + def valid_lifetime(self): + """Valid lifetime""" + msecs = capi.rtnl_addr_get_valid_lifetime(self._rtnl_addr) + if msecs == 0xFFFFFFFF: + return None + else: + return datetime.timedelta(seconds=msecs) + + @valid_lifetime.setter + def valid_lifetime(self, value): + capi.rtnl_addr_set_valid_lifetime(self._rtnl_addr, int(value)) + + ##################################################################### + # Preferred lifetime + @netlink.nlattr('address.preferred_lifetime', type=int, + immutable=True, fmt=util.num) + @property + def preferred_lifetime(self): + """Preferred lifetime""" + msecs = capi.rtnl_addr_get_preferred_lifetime(self._rtnl_addr) + if msecs == 0xFFFFFFFF: + return None + else: + return datetime.timedelta(seconds=msecs) + + @preferred_lifetime.setter + def preferred_lifetime(self, value): + capi.rtnl_addr_set_preferred_lifetime(self._rtnl_addr, int(value)) + + ##################################################################### + # Creation Time + @netlink.nlattr('address.create_time', type=int, immutable=True, + fmt=util.num) + @property + def create_time(self): + """Creation time""" + hsec = capi.rtnl_addr_get_create_time(self._rtnl_addr) + return datetime.timedelta(milliseconds=10*hsec) + + ##################################################################### + # Last Update + @netlink.nlattr('address.last_update', type=int, immutable=True, + fmt=util.num) + @property + def last_update(self): + """Last update""" + hsec = capi.rtnl_addr_get_last_update_time(self._rtnl_addr) + return datetime.timedelta(milliseconds=10*hsec) + + ##################################################################### + # add() + def add(self, socket=None, flags=None): + if not socket: + socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) + + if not flags: + flags = netlink.NLM_F_CREATE + + ret = capi.rtnl_addr_add(socket._sock, self._rtnl_addr, flags) + if ret < 0: + raise netlink.KernelError(ret) + + ##################################################################### + # delete() + def delete(self, socket): + """Attempt to delete this link in the kernel""" + ret = capi.rtnl_addr_delete(socket._sock, self._addr) + if ret < 0: + raise netlink.KernelError(ret) + + ################################################################### + # private properties + # + # Used for formatting output. USE AT OWN RISK + @property + def _flags(self): + return ','.join(self.flags) + + ################################################################### + # + # format(details=False, stats=False) + # + def format(self, details=False, stats=False, nodev=False, indent=''): + """Return address as formatted text""" + fmt = util.MyFormatter(self, indent) + + buf = fmt.format('{a|local!b}') + + if not nodev: + buf += fmt.format(' {a|ifindex}') + + buf += fmt.format(' {a|scope}') + + if self.label: + buf += fmt.format(' "{a|label}"') + + buf += fmt.format(' <{a|_flags}>') + + if details: + buf += fmt.nl('\t{t|broadcast} {t|multicast}') \ + + fmt.nl('\t{t|peer} {t|anycast}') + + if self.valid_lifetime: + buf += fmt.nl('\t{s|valid-lifetime!k} '\ + '{a|valid_lifetime}') + + if self.preferred_lifetime: + buf += fmt.nl('\t{s|preferred-lifetime!k} '\ + '{a|preferred_lifetime}') + + if stats and (self.create_time or self.last_update): + buf += self.nl('\t{s|created!k} {a|create_time}'\ + ' {s|last-updated!k} {a|last_update}') + + return buf diff --git a/python/netlink/route/capi.i b/python/netlink/route/capi.i new file mode 100644 index 0000000..abe3cc9 --- /dev/null +++ b/python/netlink/route/capi.i @@ -0,0 +1,338 @@ +%module capi +%{ +#include +#include +#include +#include + +#include +#include + +#include +%} + +%include +%include + +%inline %{ + struct nl_object *link2obj(struct rtnl_link *link) + { + return OBJ_CAST(link); + } + + struct rtnl_link *obj2link(struct nl_object *obj) + { + return (struct rtnl_link *) obj; + } + + struct rtnl_link *get_from_kernel(struct nl_sock *sk, int ifindex, const char *name) + { + struct rtnl_link *link; + if (rtnl_link_get_kernel(sk, ifindex, name, &link) < 0) + return NULL; + return link; + } + + uint32_t inet_get_conf(struct rtnl_link *link, const unsigned int id) + { + uint32_t result; + + if (rtnl_link_inet_get_conf(link, id, &result) < 0) + return 0; + + return result; + } +%}; + +extern struct nl_object *link2obj(struct rtnl_link *); +extern struct rtnl_link *obj2link(struct nl_object *); + +/* */ + +%cstring_output_maxsize(char *buf, size_t len) +extern char * rtnl_scope2str(int, char *buf, size_t len); +extern int rtnl_str2scope(const char *); + +/* */ + +extern struct rtnl_link *rtnl_link_alloc(void); + +extern struct rtnl_link *rtnl_link_get(struct nl_cache *, int); +extern struct rtnl_link *rtnl_link_get_by_name(struct nl_cache *, const char *); + +extern int rtnl_link_build_add_request(struct rtnl_link *, int, struct nl_msg **); +extern int rtnl_link_add(struct nl_sock *, struct rtnl_link *, int); +extern int rtnl_link_build_change_request(struct rtnl_link *, struct rtnl_link *, int, struct nl_msg **); +extern int rtnl_link_change(struct nl_sock *, struct rtnl_link *, struct rtnl_link *, int); + +extern int rtnl_link_build_delete_request(const struct rtnl_link *, struct nl_msg **); +extern int rtnl_link_delete(struct nl_sock *, const struct rtnl_link *); +extern int rtnl_link_build_get_request(int, const char *, struct nl_msg **); + +extern char *rtnl_link_stat2str(int, char *, size_t); +extern int rtnl_link_str2stat(const char *); + +%cstring_output_maxsize(char *buf, size_t len) +extern char *rtnl_link_flags2str(int, char *buf, size_t len); +extern int rtnl_link_str2flags(const char *); + +%cstring_output_maxsize(char *buf, size_t len) +extern char *rtnl_link_operstate2str(uint8_t, char *buf, size_t len); +extern int rtnl_link_str2operstate(const char *); + +%cstring_output_maxsize(char *buf, size_t len) +extern char *rtnl_link_mode2str(uint8_t, char *buf, size_t len); +extern int rtnl_link_str2mode(const char *); + +extern void rtnl_link_set_qdisc(struct rtnl_link *, const char *); +extern char *rtnl_link_get_qdisc(struct rtnl_link *); + +extern void rtnl_link_set_name(struct rtnl_link *, const char *); +extern char *rtnl_link_get_name(struct rtnl_link *); + +extern void rtnl_link_set_flags(struct rtnl_link *, unsigned int); +extern void rtnl_link_unset_flags(struct rtnl_link *, unsigned int); +extern unsigned int rtnl_link_get_flags(struct rtnl_link *); + +extern void rtnl_link_set_mtu(struct rtnl_link *, unsigned int); +extern unsigned int rtnl_link_get_mtu(struct rtnl_link *); + +extern void rtnl_link_set_txqlen(struct rtnl_link *, unsigned int); +extern unsigned int rtnl_link_get_txqlen(struct rtnl_link *); + +extern void rtnl_link_set_weight(struct rtnl_link *, unsigned int); +extern unsigned int rtnl_link_get_weight(struct rtnl_link *); + +extern void rtnl_link_set_ifindex(struct rtnl_link *, int); +extern int rtnl_link_get_ifindex(struct rtnl_link *); + +extern void rtnl_link_set_family(struct rtnl_link *, int); +extern int rtnl_link_get_family(struct rtnl_link *); + +extern void rtnl_link_set_arptype(struct rtnl_link *, unsigned int); +extern unsigned int rtnl_link_get_arptype(struct rtnl_link *); + +extern void rtnl_link_set_addr(struct rtnl_link *, struct nl_addr *); +extern struct nl_addr *rtnl_link_get_addr(struct rtnl_link *); + +extern void rtnl_link_set_broadcast(struct rtnl_link *, struct nl_addr *); +extern struct nl_addr *rtnl_link_get_broadcast(struct rtnl_link *); + +extern void rtnl_link_set_link(struct rtnl_link *, int); +extern int rtnl_link_get_link(struct rtnl_link *); + +extern void rtnl_link_set_master(struct rtnl_link *, int); +extern int rtnl_link_get_master(struct rtnl_link *); + +extern void rtnl_link_set_operstate(struct rtnl_link *, uint8_t); +extern uint8_t rtnl_link_get_operstate(struct rtnl_link *); + +extern void rtnl_link_set_linkmode(struct rtnl_link *, uint8_t); +extern uint8_t rtnl_link_get_linkmode(struct rtnl_link *); + +extern const char *rtnl_link_get_ifalias(struct rtnl_link *); +extern void rtnl_link_set_ifalias(struct rtnl_link *, const char *); + +extern int rtnl_link_get_num_vf(struct rtnl_link *, uint32_t *); + +extern uint64_t rtnl_link_get_stat(struct rtnl_link *, int); +extern int rtnl_link_set_stat(struct rtnl_link *, const unsigned int, const uint64_t); + +extern int rtnl_link_set_info_type(struct rtnl_link *, const char *); +extern char *rtnl_link_get_info_type(struct rtnl_link *); + +/* */ + +struct vlan_map +{ + uint32_t vm_from; + uint32_t vm_to; +}; + +#define VLAN_PRIO_MAX 7 + +%cstring_output_maxsize(char *buf, size_t len) +extern char *rtnl_link_vlan_flags2str(int, char *buf, size_t len); +extern int rtnl_link_vlan_str2flags(const char *); + +extern int rtnl_link_vlan_set_id(struct rtnl_link *, int); +extern int rtnl_link_vlan_get_id(struct rtnl_link *); + +extern int rtnl_link_vlan_set_flags(struct rtnl_link *, unsigned int); +extern int rtnl_link_vlan_unset_flags(struct rtnl_link *, unsigned int); +extern unsigned int rtnl_link_vlan_get_flags(struct rtnl_link *); + +extern int rtnl_link_vlan_set_ingress_map(struct rtnl_link *, int, uint32_t); +extern uint32_t *rtnl_link_vlan_get_ingress_map(struct rtnl_link *); + +extern int rtnl_link_vlan_set_egress_map(struct rtnl_link *, uint32_t, int); +extern struct vlan_map *rtnl_link_vlan_get_egress_map(struct rtnl_link *, int *); + +/* */ +%cstring_output_maxsize(char *buf, size_t len) +extern const char *rtnl_link_inet_devconf2str(int, char *buf, size_t len); +extern unsigned int rtnl_link_inet_str2devconf(const char *); + +extern int rtnl_link_inet_set_conf(struct rtnl_link *, const unsigned int, uint32_t); + +/* */ + +%inline %{ + uint32_t tc_str2handle(const char *name) + { + uint32_t result; + + if (rtnl_tc_str2handle(name, &result) < 0) + return 0; + + return result; + } +%}; + +extern void rtnl_tc_set_ifindex(struct rtnl_tc *, int); +extern int rtnl_tc_get_ifindex(struct rtnl_tc *); +extern void rtnl_tc_set_link(struct rtnl_tc *, struct rtnl_link *); +extern struct rtnl_link *rtnl_tc_get_link(struct rtnl_tc *); +extern void rtnl_tc_set_mtu(struct rtnl_tc *, uint32_t); +extern uint32_t rtnl_tc_get_mtu(struct rtnl_tc *); +extern void rtnl_tc_set_mpu(struct rtnl_tc *, uint32_t); +extern uint32_t rtnl_tc_get_mpu(struct rtnl_tc *); +extern void rtnl_tc_set_overhead(struct rtnl_tc *, uint32_t); +extern uint32_t rtnl_tc_get_overhead(struct rtnl_tc *); +extern void rtnl_tc_set_linktype(struct rtnl_tc *, uint32_t); +extern uint32_t rtnl_tc_get_linktype(struct rtnl_tc *); +extern void rtnl_tc_set_handle(struct rtnl_tc *, uint32_t); +extern uint32_t rtnl_tc_get_handle(struct rtnl_tc *); +extern void rtnl_tc_set_parent(struct rtnl_tc *, uint32_t); +extern uint32_t rtnl_tc_get_parent(struct rtnl_tc *); +extern int rtnl_tc_set_kind(struct rtnl_tc *, const char *); +extern char * rtnl_tc_get_kind(struct rtnl_tc *); +extern uint64_t rtnl_tc_get_stat(struct rtnl_tc *, enum rtnl_tc_stat); + +extern int rtnl_tc_calc_txtime(int, int); +extern int rtnl_tc_calc_bufsize(int, int); +extern int rtnl_tc_calc_cell_log(int); + +extern int rtnl_tc_read_classid_file(void); +%cstring_output_maxsize(char *buf, size_t len) +extern char * rtnl_tc_handle2str(uint32_t, char *buf, size_t len); +extern int rtnl_classid_generate(const char *, uint32_t *, uint32_t); + +/* */ + +%inline %{ + struct nl_object *qdisc2obj(struct rtnl_qdisc *qdisc) + { + return OBJ_CAST(qdisc); + } + + struct rtnl_qdisc *obj2qdisc(struct nl_object *obj) + { + return (struct rtnl_qdisc *) obj; + } + + struct rtnl_tc *obj2tc(struct nl_object *obj) + { + return TC_CAST(obj); + } +%}; +extern struct rtnl_qdisc * + rtnl_qdisc_alloc(void); + +extern struct rtnl_qdisc * + rtnl_qdisc_get(struct nl_cache *, int, uint32_t); + +extern struct rtnl_qdisc * + rtnl_qdisc_get_by_parent(struct nl_cache *, int, uint32_t); + +extern int rtnl_qdisc_build_add_request(struct rtnl_qdisc *, int, + struct nl_msg **); +extern int rtnl_qdisc_add(struct nl_sock *, struct rtnl_qdisc *, int); + +extern int rtnl_qdisc_build_update_request(struct rtnl_qdisc *, + struct rtnl_qdisc *, + int, struct nl_msg **); + +extern int rtnl_qdisc_update(struct nl_sock *, struct rtnl_qdisc *, + struct rtnl_qdisc *, int); + +extern int rtnl_qdisc_build_delete_request(struct rtnl_qdisc *, + struct nl_msg **); +extern int rtnl_qdisc_delete(struct nl_sock *, struct rtnl_qdisc *); + +/* */ + +%inline %{ + struct nl_object *addr2obj(struct rtnl_addr *addr) + { + return OBJ_CAST(addr); + } + + struct rtnl_addr *obj2addr(struct nl_object *obj) + { + return (struct rtnl_addr *) obj; + } +%}; + +extern struct rtnl_addr *rtnl_addr_alloc(void); + +extern struct rtnl_addr * + rtnl_addr_get(struct nl_cache *, int, struct nl_addr *); + +extern int rtnl_addr_build_add_request(struct rtnl_addr *, int, + struct nl_msg **); +extern int rtnl_addr_add(struct nl_sock *, struct rtnl_addr *, int); + +extern int rtnl_addr_build_delete_request(struct rtnl_addr *, int, + struct nl_msg **); +extern int rtnl_addr_delete(struct nl_sock *, + struct rtnl_addr *, int); + +%cstring_output_maxsize(char *buf, size_t len) +extern char * rtnl_addr_flags2str(int, char *buf, size_t len); +extern int rtnl_addr_str2flags(const char *); + +extern int rtnl_addr_set_label(struct rtnl_addr *, const char *); +extern char * rtnl_addr_get_label(struct rtnl_addr *); + +extern void rtnl_addr_set_ifindex(struct rtnl_addr *, int); +extern int rtnl_addr_get_ifindex(struct rtnl_addr *); + +extern void rtnl_addr_set_link(struct rtnl_addr *, struct rtnl_link *); +extern struct rtnl_link * + rtnl_addr_get_link(struct rtnl_addr *); +extern void rtnl_addr_set_family(struct rtnl_addr *, int); +extern int rtnl_addr_get_family(struct rtnl_addr *); + +extern void rtnl_addr_set_prefixlen(struct rtnl_addr *, int); +extern int rtnl_addr_get_prefixlen(struct rtnl_addr *); + +extern void rtnl_addr_set_scope(struct rtnl_addr *, int); +extern int rtnl_addr_get_scope(struct rtnl_addr *); + +extern void rtnl_addr_set_flags(struct rtnl_addr *, unsigned int); +extern void rtnl_addr_unset_flags(struct rtnl_addr *, unsigned int); +extern unsigned int rtnl_addr_get_flags(struct rtnl_addr *); + +extern int rtnl_addr_set_local(struct rtnl_addr *, + struct nl_addr *); +extern struct nl_addr *rtnl_addr_get_local(struct rtnl_addr *); + +extern int rtnl_addr_set_peer(struct rtnl_addr *, struct nl_addr *); +extern struct nl_addr *rtnl_addr_get_peer(struct rtnl_addr *); + +extern int rtnl_addr_set_broadcast(struct rtnl_addr *, struct nl_addr *); +extern struct nl_addr *rtnl_addr_get_broadcast(struct rtnl_addr *); + +extern int rtnl_addr_set_multicast(struct rtnl_addr *, struct nl_addr *); +extern struct nl_addr *rtnl_addr_get_multicast(struct rtnl_addr *); + +extern int rtnl_addr_set_anycast(struct rtnl_addr *, struct nl_addr *); +extern struct nl_addr *rtnl_addr_get_anycast(struct rtnl_addr *); + +extern uint32_t rtnl_addr_get_valid_lifetime(struct rtnl_addr *); +extern void rtnl_addr_set_valid_lifetime(struct rtnl_addr *, uint32_t); +extern uint32_t rtnl_addr_get_preferred_lifetime(struct rtnl_addr *); +extern void rtnl_addr_set_preferred_lifetime(struct rtnl_addr *, uint32_t); +extern uint32_t rtnl_addr_get_create_time(struct rtnl_addr *); +extern uint32_t rtnl_addr_get_last_update_time(struct rtnl_addr *); diff --git a/python/netlink/route/link.py b/python/netlink/route/link.py new file mode 100644 index 0000000..b8e19fa --- /dev/null +++ b/python/netlink/route/link.py @@ -0,0 +1,596 @@ +# +# Copyright (c) 2011 Thomas Graf +# + +"""Module providing access to network links + +This module provides an interface to view configured network links, +modify them and to add and delete virtual network links. + +The following is a basic example: + import netlink.core as netlink + import netlink.route.link as link + + sock = netlink.Socket() + sock.connect(netlink.NETLINK_ROUTE) + + cache = link.LinkCache() # create new empty link cache + cache.refill(sock) # fill cache with all configured links + eth0 = cache['eth0'] # lookup link "eth0" + print eth0 # print basic configuration + +The module contains the following public classes: + + - Link -- Represents a network link. Instances can be created directly + via the constructor (empty link objects) or via the refill() + method of a LinkCache. + - LinkCache -- Derived from netlink.Cache, holds any number of + network links (Link instances). Main purpose is to keep + a local list of all network links configured in the + kernel. + +The following public functions exist: + - get_from_kernel(socket, name) + +""" + +__version__ = "0.1" +__all__ = [ + 'LinkCache', + 'Link', + 'get_from_kernel'] + +import socket +import sys +import netlink.core as netlink +import netlink.capi as core_capi +import netlink.route.capi as capi +import netlink.route.links.inet as inet +import netlink.util as util + +########################################################################### +# Link statistics definitions +RX_PACKETS = 0 +TX_PACKETS = 1 +RX_BYTES = 2 +TX_BYTES = 3 +RX_ERRORS = 4 +TX_ERRORS = 5 +RX_DROPPED = 6 +TX_DROPPED = 7 +RX_COMPRESSED = 8 +TX_COMPRESSED = 9 +RX_FIFO_ERR = 10 +TX_FIFO_ERR = 11 +RX_LEN_ERR = 12 +RX_OVER_ERR = 13 +RX_CRC_ERR = 14 +RX_FRAME_ERR = 15 +RX_MISSED_ERR = 16 +TX_ABORT_ERR = 17 +TX_CARRIER_ERR = 18 +TX_HBEAT_ERR = 19 +TX_WIN_ERR = 20 +COLLISIONS = 21 +MULTICAST = 22 +IP6_INPKTS = 23 +IP6_INHDRERRORS = 24 +IP6_INTOOBIGERRORS = 25 +IP6_INNOROUTES = 26 +IP6_INADDRERRORS = 27 +IP6_INUNKNOWNPROTOS = 28 +IP6_INTRUNCATEDPKTS = 29 +IP6_INDISCARDS = 30 +IP6_INDELIVERS = 31 +IP6_OUTFORWDATAGRAMS = 32 +IP6_OUTPKTS = 33 +IP6_OUTDISCARDS = 34 +IP6_OUTNOROUTES = 35 +IP6_REASMTIMEOUT = 36 +IP6_REASMREQDS = 37 +IP6_REASMOKS = 38 +IP6_REASMFAILS = 39 +IP6_FRAGOKS = 40 +IP6_FRAGFAILS = 41 +IP6_FRAGCREATES = 42 +IP6_INMCASTPKTS = 43 +IP6_OUTMCASTPKTS = 44 +IP6_INBCASTPKTS = 45 +IP6_OUTBCASTPKTS = 46 +IP6_INOCTETS = 47 +IP6_OUTOCTETS = 48 +IP6_INMCASTOCTETS = 49 +IP6_OUTMCASTOCTETS = 50 +IP6_INBCASTOCTETS = 51 +IP6_OUTBCASTOCTETS = 52 +ICMP6_INMSGS = 53 +ICMP6_INERRORS = 54 +ICMP6_OUTMSGS = 55 +ICMP6_OUTERRORS = 56 + +########################################################################### +# Link Cache +class LinkCache(netlink.Cache): + """Cache of network links""" + + def __init__(self, family=socket.AF_UNSPEC, cache=None): + if not cache: + cache = self._alloc_cache_name("route/link") + + self._protocol = netlink.NETLINK_ROUTE + self._c_cache = cache + self._set_arg1(family) + + def __getitem__(self, key): + if type(key) is int: + link = capi.rtnl_link_get(self._c_cache, key) + elif type(key) is str: + link = capi.rtnl_link_get_by_name(self._c_cache, key) + + if link is None: + raise KeyError() + else: + return Link.from_capi(link) + + def _new_object(self, obj): + return Link(obj) + + def _new_cache(self, cache): + return LinkCache(family=self.arg1, cache=cache) + +########################################################################### +# Link Object +class Link(netlink.Object): + """Network link""" + + def __init__(self, obj=None): + netlink.Object.__init__(self, "route/link", "link", obj) + self._rtnl_link = self._obj2type(self._nl_object) + + self._type = None + + if self.type: + self._type_lookup(self.type) + + self.inet = inet.InetLink(self) + self.af = {'inet' : self.inet } + + @classmethod + def from_capi(cls, obj): + return cls(capi.link2obj(obj)) + + def _obj2type(self, obj): + return capi.obj2link(obj) + + def __cmp__(self, other): + return self.ifindex - other.ifindex + + def _new_instance(self, obj): + if not obj: + raise ValueError() + + return Link(obj) + + def _type_lookup(self, name): + rname = 'netlink.route.links.' + name + tmp = __import__(rname) + mod = sys.modules[rname] + + # this will create a type instance and assign it to + # link., e.g. link.vlan.id + self._type = mod.assign_type(self) + + ##################################################################### + # ifindex + @netlink.nlattr('link.ifindex', type=int, immutable=True, fmt=util.num) + @property + def ifindex(self): + """interface index""" + return capi.rtnl_link_get_ifindex(self._rtnl_link) + + @ifindex.setter + def ifindex(self, value): + capi.rtnl_link_set_ifindex(self._rtnl_link, int(value)) + + # ifindex is immutable but we assume that if _orig does not + # have an ifindex specified, it was meant to be given here + if capi.rtnl_link_get_ifindex(self._orig) == 0: + capi.rtnl_link_set_ifindex(self._orig, int(value)) + + ##################################################################### + # name + @netlink.nlattr('link.name', type=str, fmt=util.bold) + @property + def name(self): + """Name of link""" + return capi.rtnl_link_get_name(self._rtnl_link) + + @name.setter + def name(self, value): + capi.rtnl_link_set_name(self._rtnl_link, value) + + # name is the secondary identifier, if _orig does not have + # the name specified yet, assume it was meant to be specified + # here. ifindex will always take priority, therefore if ifindex + # is specified as well, this will be ignored automatically. + if capi.rtnl_link_get_name(self._orig) is None: + capi.rtnl_link_set_name(self._orig, value) + + ##################################################################### + # flags + @netlink.nlattr('link.flags', type=str, fmt=util.string) + @property + def flags(self): + """Flags""" + flags = capi.rtnl_link_get_flags(self._rtnl_link) + return capi.rtnl_link_flags2str(flags, 256)[0].split(',') + + def _set_flag(self, flag): + if flag[0] == '-': + i = capi.rtnl_link_str2flags(flag[1:]) + capi.rtnl_link_unset_flags(self._rtnl_link, i) + else: + i = capi.rtnl_link_str2flags(flag[1:]) + capi.rtnl_link_set_flags(self._rtnl_link, i) + + @flags.setter + def flags(self, value): + if type(value) is list: + for flag in value: + self._set_flag(flag) + else: + self._set_flag(value) + + ##################################################################### + # mtu + @netlink.nlattr('link.mtu', type=int, fmt=util.num) + @property + def mtu(self): + """Maximum Transmission Unit""" + return capi.rtnl_link_get_mtu(self._rtnl_link) + + @mtu.setter + def mtu(self, value): + capi.rtnl_link_set_mtu(self._rtnl_link, int(value)) + + ##################################################################### + # family + @netlink.nlattr('link.family', type=int, immutable=True, fmt=util.num) + @property + def family(self): + """Address family""" + return capi.rtnl_link_get_family(self._rtnl_link) + + @family.setter + def family(self, value): + capi.rtnl_link_set_family(self._rtnl_link, value) + + ##################################################################### + # address + @netlink.nlattr('link.address', type=str, fmt=util.addr) + @property + def address(self): + """Hardware address (MAC address)""" + a = capi.rtnl_link_get_addr(self._rtnl_link) + return netlink.AbstractAddress(a) + + @address.setter + def address(self, value): + capi.rtnl_link_set_addr(self._rtnl_link, value._addr) + + ##################################################################### + # broadcast + @netlink.nlattr('link.broadcast', type=str, fmt=util.addr) + @property + def broadcast(self): + """Hardware broadcast address""" + a = capi.rtnl_link_get_broadcast(self._rtnl_link) + return netlink.AbstractAddress(a) + + @broadcast.setter + def broadcast(self, value): + capi.rtnl_link_set_broadcast(self._rtnl_link, value._addr) + + ##################################################################### + # qdisc + @netlink.nlattr('link.qdisc', type=str, immutable=True, fmt=util.string) + @property + def qdisc(self): + """Name of qdisc (cannot be changed)""" + return capi.rtnl_link_get_qdisc(self._rtnl_link) + + @qdisc.setter + def qdisc(self, value): + capi.rtnl_link_set_qdisc(self._rtnl_link, value) + + ##################################################################### + # txqlen + @netlink.nlattr('link.txqlen', type=int, fmt=util.num) + @property + def txqlen(self): + """"Length of transmit queue""" + return capi.rtnl_link_get_txqlen(self._rtnl_link) + + @txqlen.setter + def txqlen(self, value): + capi.rtnl_link_set_txqlen(self._rtnl_link, int(value)) + + ##################################################################### + # weight + @netlink.nlattr('link.weight', type=str, fmt=util.string) + @property + def weight(self): + """Weight""" + v = capi.rtnl_link_get_weight(self._rtnl_link) + if v == 4294967295: + return 'max' + else: + return str(v) + + @weight.setter + def weight(self, value): + if value == 'max': + v = 4294967295 + else: + v = int(value) + capi.rtnl_link_set_weight(self._rtnl_link, v) + + ##################################################################### + # arptype + @netlink.nlattr('link.arptype', type=str, immutable=True, fmt=util.string) + @property + def arptype(self): + """Type of link (cannot be changed)""" + type = capi.rtnl_link_get_arptype(self._rtnl_link) + return core_capi.nl_llproto2str(type, 64)[0] + + @arptype.setter + def arptype(self, value): + i = core_capi.nl_str2llproto(value) + capi.rtnl_link_set_arptype(self._rtnl_link, i) + + ##################################################################### + # operstate + @netlink.nlattr('link.operstate', type=str, immutable=True, + fmt=util.string, title='state') + @property + def operstate(self): + """Operational status""" + operstate = capi.rtnl_link_get_operstate(self._rtnl_link) + return capi.rtnl_link_operstate2str(operstate, 32)[0] + + @operstate.setter + def operstate(self, value): + i = capi.rtnl_link_str2operstate(flag) + capi.rtnl_link_set_operstate(self._rtnl_link, i) + + ##################################################################### + # mode + @netlink.nlattr('link.mode', type=str, immutable=True, fmt=util.string) + @property + def mode(self): + """Link mode""" + mode = capi.rtnl_link_get_linkmode(self._rtnl_link) + return capi.rtnl_link_mode2str(mode, 32)[0] + + @mode.setter + def mode(self, value): + i = capi.rtnl_link_str2mode(flag) + capi.rtnl_link_set_linkmode(self._rtnl_link, i) + + ##################################################################### + # alias + @netlink.nlattr('link.alias', type=str, fmt=util.string) + @property + def alias(self): + """Interface alias (SNMP)""" + return capi.rtnl_link_get_ifalias(self._rtnl_link) + + @alias.setter + def alias(self, value): + capi.rtnl_link_set_ifalias(self._rtnl_link, value) + + ##################################################################### + # type + @netlink.nlattr('link.type', type=str, fmt=util.string) + @property + def type(self): + """Link type""" + return capi.rtnl_link_get_info_type(self._rtnl_link) + + @type.setter + def type(self, value): + if capi.rtnl_link_set_info_type(self._rtnl_link, value) < 0: + raise NameError("unknown info type") + + self._type_lookup(value) + + ##################################################################### + # get_stat() + def get_stat(self, stat): + """Retrieve statistical information""" + if type(stat) is str: + stat = capi.rtnl_link_str2stat(stat) + if stat < 0: + raise NameError("unknown name of statistic") + + return capi.rtnl_link_get_stat(self._rtnl_link, stat) + + ##################################################################### + # add() + def add(self, socket=None, flags=None): + if not socket: + socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) + + if not flags: + flags = netlink.NLM_F_CREATE + + ret = capi.rtnl_link_add(socket._sock, self._rtnl_link, flags) + if ret < 0: + raise netlink.KernelError(ret) + + ##################################################################### + # change() + def change(self, socket=None, flags=0): + """Commit changes made to the link object""" + if not socket: + socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) + + if not self._orig: + raise NetlinkError("Original link not available") + ret = capi.rtnl_link_change(socket._sock, self._orig, self._rtnl_link, flags) + if ret < 0: + raise netlink.KernelError(ret) + + ##################################################################### + # delete() + def delete(self, socket=None): + """Attempt to delete this link in the kernel""" + if not socket: + socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) + + ret = capi.rtnl_link_delete(socket._sock, self._rtnl_link) + if ret < 0: + raise netlink.KernelError(ret) + + ################################################################### + # private properties + # + # Used for formatting output. USE AT OWN RISK + @property + def _state(self): + if 'up' in self.flags: + buf = util.good('up') + if 'lowerup' not in self.flags: + buf += ' ' + util.bad('no-carrier') + else: + buf = util.bad('down') + return buf + + @property + def _brief(self): + buf = '' + if self.type: + if self._type and hasattr(self._type, 'brief'): + buf += self._type.brief() + else: + buf += util.yellow(self.type) + + return buf + self._foreach_af('brief') + + @property + def _flags(self): + ignore = ['up', 'running', 'lowerup'] + return ','.join([flag for flag in self.flags if flag not in ignore]) + + def _foreach_af(self, name, args=None): + buf = '' + for af in self.af: + try: + func = getattr(self.af[af], name) + s = str(func(args)) + if len(s) > 0: + buf += ' ' + s + except AttributeError: + pass + return buf + + ################################################################### + # + # format(details=False, stats=False) + # + def format(self, details=False, stats=False, indent=''): + """Return link as formatted text""" + fmt = util.MyFormatter(self, indent) + + buf = fmt.format('{a|ifindex} {a|name} {a|arptype} {a|address} '\ + '{a|_state} <{a|_flags}> {a|_brief}') + + if details: + buf += fmt.nl('\t{t|mtu} {t|txqlen} {t|weight} '\ + '{t|qdisc} {t|operstate}') + buf += fmt.nl('\t{t|broadcast} {t|alias}') + + buf += self._foreach_af('details', fmt) + + if stats: + l = [['Packets', RX_PACKETS, TX_PACKETS], + ['Bytes', RX_BYTES, TX_BYTES], + ['Errors', RX_ERRORS, TX_ERRORS], + ['Dropped', RX_DROPPED, TX_DROPPED], + ['Compressed', RX_COMPRESSED, TX_COMPRESSED], + ['FIFO Errors', RX_FIFO_ERR, TX_FIFO_ERR], + ['Length Errors', RX_LEN_ERR, None], + ['Over Errors', RX_OVER_ERR, None], + ['CRC Errors', RX_CRC_ERR, None], + ['Frame Errors', RX_FRAME_ERR, None], + ['Missed Errors', RX_MISSED_ERR, None], + ['Abort Errors', None, TX_ABORT_ERR], + ['Carrier Errors', None, TX_CARRIER_ERR], + ['Heartbeat Errors', None, TX_HBEAT_ERR], + ['Window Errors', None, TX_WIN_ERR], + ['Collisions', None, COLLISIONS], + ['Multicast', None, MULTICAST], + ['', None, None], + ['Ipv6:', None, None], + ['Packets', IP6_INPKTS, IP6_OUTPKTS], + ['Bytes', IP6_INOCTETS, IP6_OUTOCTETS], + ['Discards', IP6_INDISCARDS, IP6_OUTDISCARDS], + ['Multicast Packets', IP6_INMCASTPKTS, IP6_OUTMCASTPKTS], + ['Multicast Bytes', IP6_INMCASTOCTETS, IP6_OUTMCASTOCTETS], + ['Broadcast Packets', IP6_INBCASTPKTS, IP6_OUTBCASTPKTS], + ['Broadcast Bytes', IP6_INBCASTOCTETS, IP6_OUTBCASTOCTETS], + ['Delivers', IP6_INDELIVERS, None], + ['Forwarded', None, IP6_OUTFORWDATAGRAMS], + ['No Routes', IP6_INNOROUTES, IP6_OUTNOROUTES], + ['Header Errors', IP6_INHDRERRORS, None], + ['Too Big Errors', IP6_INTOOBIGERRORS, None], + ['Address Errors', IP6_INADDRERRORS, None], + ['Unknown Protocol', IP6_INUNKNOWNPROTOS, None], + ['Truncated Packets', IP6_INTRUNCATEDPKTS, None], + ['Reasm Timeouts', IP6_REASMTIMEOUT, None], + ['Reasm Requests', IP6_REASMREQDS, None], + ['Reasm Failures', IP6_REASMFAILS, None], + ['Reasm OK', IP6_REASMOKS, None], + ['Frag Created', None, IP6_FRAGCREATES], + ['Frag Failures', None, IP6_FRAGFAILS], + ['Frag OK', None, IP6_FRAGOKS], + ['', None, None], + ['ICMPv6:', None, None], + ['Messages', ICMP6_INMSGS, ICMP6_OUTMSGS], + ['Errors', ICMP6_INERRORS, ICMP6_OUTERRORS]] + + buf += '\n\t%s%s%s%s\n' % (33 * ' ', util.title('RX'), + 15 * ' ', util.title('TX')) + + for row in l: + row[0] = util.kw(row[0]) + row[1] = self.get_stat(row[1]) if row[1] else '' + row[2] = self.get_stat(row[2]) if row[2] else '' + buf += '\t{0:27} {1:>16} {2:>16}\n'.format(*row) + + buf += self._foreach_af('stats') + + return buf + +def get(name, socket=None): + """Lookup Link object directly from kernel""" + if not name: + raise ValueError() + + if not socket: + socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) + + link = capi.get_from_kernel(socket._sock, 0, name) + if not link: + return None + + return Link.from_capi(link) + +link_cache = LinkCache() + +def resolve(name): + socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) + link_cache.refill() + + return link_cache[name] diff --git a/python/netlink/route/links/__init__.py b/python/netlink/route/links/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python/netlink/route/links/dummy.py b/python/netlink/route/links/dummy.py new file mode 100644 index 0000000..495be94 --- /dev/null +++ b/python/netlink/route/links/dummy.py @@ -0,0 +1,21 @@ +# +# Copyright (c) 2011 Thomas Graf +# + +"""Dummy + +""" + +__version__ = "1.0" +__all__ = ['assign_type'] + +import netlink.core as netlink +import netlink.route.capi as capi + +class DummyLink(object): + def __init__(self, link): + self._rtnl_link = link + +def assign_type(link): + link.dummy = DummyLink(link._rtnl_link) + return link.dummy diff --git a/python/netlink/route/links/inet.py b/python/netlink/route/links/inet.py new file mode 100644 index 0000000..63c234f --- /dev/null +++ b/python/netlink/route/links/inet.py @@ -0,0 +1,153 @@ +# +# Copyright (c) 2011 Thomas Graf +# + +"""IPv4 + +""" + +__all__ = [''] + +import netlink.core as netlink +import netlink.route.capi as capi +import netlink.util as util + +DEVCONF_FORWARDING = 1 +DEVCONF_MC_FORWARDING = 2 +DEVCONF_PROXY_ARP = 3 +DEVCONF_ACCEPT_REDIRECTS = 4 +DEVCONF_SECURE_REDIRECTS = 5 +DEVCONF_SEND_REDIRECTS = 6 +DEVCONF_SHARED_MEDIA = 7 +DEVCONF_RP_FILTER = 8 +DEVCONF_ACCEPT_SOURCE_ROUTE = 9 +DEVCONF_BOOTP_RELAY = 10 +DEVCONF_LOG_MARTIANS = 11 +DEVCONF_TAG = 12 +DEVCONF_ARPFILTER = 13 +DEVCONF_MEDIUM_ID = 14 +DEVCONF_NOXFRM = 15 +DEVCONF_NOPOLICY = 16 +DEVCONF_FORCE_IGMP_VERSION = 17 +DEVCONF_ARP_ANNOUNCE = 18 +DEVCONF_ARP_IGNORE = 19 +DEVCONF_PROMOTE_SECONDARIES = 20 +DEVCONF_ARP_ACCEPT = 21 +DEVCONF_ARP_NOTIFY = 22 +DEVCONF_ACCEPT_LOCAL = 23 +DEVCONF_SRC_VMARK = 24 +DEVCONF_PROXY_ARP_PVLAN = 25 +DEVCONF_MAX = DEVCONF_PROXY_ARP_PVLAN + +def _resolve(id): + if type(id) is str: + id = capi.rtnl_link_inet_str2devconf(id)[0] + if id < 0: + raise NameError("unknown configuration id") + return id + +class InetLink(object): + def __init__(self, link): + self._link = link + + def details(self, fmt): + buf = '\n' + fmt.nl('\t%s\n\t' % util.title('Configuration:')) + + for i in range(DEVCONF_FORWARDING,DEVCONF_MAX+1): + if i & 1 and i > 1: + buf += fmt.nl('\t') + txt = util.kw(capi.rtnl_link_inet_devconf2str(i, 32)[0]) + buf += fmt.format('{0:28s} {1:12} ', txt, + self.get_conf(i)) + + + return buf + + def get_conf(self, id): + return capi.inet_get_conf(self._link._rtnl_link, _resolve(id)) + + def set_conf(self, id, value): + return capi.rtnl_link_inet_set_conf(self._link._rtnl_link, + _resolve(id), int(value)) + + @netlink.nlattr('link.inet.forwarding', type=bool, fmt=util.bool) + @property + def forwarding(self): + return bool(self.get_conf(DEVCONF_FORWARDING)) + + @forwarding.setter + def forwarding(self, value): + self.set_conf(DEVCONF_FORWARDING, int(value)) + + @netlink.nlattr('link.inet.mc_forwarding', type=bool, fmt=util.bool) + @property + def mc_forwarding(self): + return bool(self.get_conf(DEVCONF_MC_FORWARDING)) + + @mc_forwarding.setter + def mc_forwarding(self, value): + self.set_conf(DEVCONF_MC_FORWARDING, int(value)) + + @netlink.nlattr('link.inet.proxy_arp', type=bool, fmt=util.bool) + @property + def proxy_arp(self): + return bool(self.get_conf(DEVCONF_PROXY_ARP)) + + @proxy_arp.setter + def proxy_arp(self, value): + self.set_conf(DEVCONF_PROXY_ARP, int(value)) + + @netlink.nlattr('link.inet.accept_redirects', type=bool, fmt=util.bool) + @property + def accept_redirects(self): + return bool(self.get_conf(DEVCONF_ACCEPT_REDIRECTS)) + + @accept_redirects.setter + def accept_redirects(self, value): + self.set_conf(DEVCONF_ACCEPT_REDIRECTS, int(value)) + + @netlink.nlattr('link.inet.secure_redirects', type=bool, fmt=util.bool) + @property + def secure_redirects(self): + return bool(self.get_conf(DEVCONF_SECURE_REDIRECTS)) + + @secure_redirects.setter + def secure_redirects(self, value): + self.set_conf(DEVCONF_SECURE_REDIRECTS, int(value)) + + @netlink.nlattr('link.inet.send_redirects', type=bool, fmt=util.bool) + @property + def send_redirects(self): + return bool(self.get_conf(DEVCONF_SEND_REDIRECTS)) + + @send_redirects.setter + def send_redirects(self, value): + self.set_conf(DEVCONF_SEND_REDIRECTS, int(value)) + + @netlink.nlattr('link.inet.shared_media', type=bool, fmt=util.bool) + @property + def shared_media(self): + return bool(self.get_conf(DEVCONF_SHARED_MEDIA)) + + @shared_media.setter + def shared_media(self, value): + self.set_conf(DEVCONF_SHARED_MEDIA, int(value)) + +# IPV4_DEVCONF_RP_FILTER, +# IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE, +# IPV4_DEVCONF_BOOTP_RELAY, +# IPV4_DEVCONF_LOG_MARTIANS, +# IPV4_DEVCONF_TAG, +# IPV4_DEVCONF_ARPFILTER, +# IPV4_DEVCONF_MEDIUM_ID, +# IPV4_DEVCONF_NOXFRM, +# IPV4_DEVCONF_NOPOLICY, +# IPV4_DEVCONF_FORCE_IGMP_VERSION, +# IPV4_DEVCONF_ARP_ANNOUNCE, +# IPV4_DEVCONF_ARP_IGNORE, +# IPV4_DEVCONF_PROMOTE_SECONDARIES, +# IPV4_DEVCONF_ARP_ACCEPT, +# IPV4_DEVCONF_ARP_NOTIFY, +# IPV4_DEVCONF_ACCEPT_LOCAL, +# IPV4_DEVCONF_SRC_VMARK, +# IPV4_DEVCONF_PROXY_ARP_PVLAN, diff --git a/python/netlink/route/links/vlan.py b/python/netlink/route/links/vlan.py new file mode 100644 index 0000000..1d4e03d --- /dev/null +++ b/python/netlink/route/links/vlan.py @@ -0,0 +1,62 @@ +# +# Copyright (c) 2011 Thomas Graf +# + +"""VLAN network link + +""" + +import netlink.core as netlink +import netlink.route.capi as capi + +class VLANLink(object): + def __init__(self, link): + self._link = link + + ################################################################### + # id + @netlink.nlattr('link.vlan.id', type=int) + @property + def id(self): + """vlan identifier""" + return capi.rtnl_link_vlan_get_id(self._link) + + @id.setter + def id(self, value): + capi.rtnl_link_vlan_set_id(self._link, int(value)) + + ################################################################### + # flags + @netlink.nlattr('link.vlan.flags', type=str) + @property + def flags(self): + """vlan flags""" + flags = capi.rtnl_link_vlan_get_flags(self._link) + return capi.rtnl_link_vlan_flags2str(flags, 256)[0].split(',') + + def _set_flag(self, flag): + i = capi.rtnl_link_vlan_str2flags(flag[1:]) + if flag[0] == '-': + capi.rtnl_link_vlan_unset_flags(self._link, i) + else: + capi.rtnl_link_vlan_set_flags(self._link, i) + + @flags.setter + def flags(self, value): + if type(value) is list: + for flag in value: + self._set_flag(flag) + else: + self._set_flag(value) + + ################################################################### + # TODO: + # - ingress map + # - egress map + + def brief(self): + return 'vlan-id ' + self.id + +def assign_type(link): + link.vlan = VLANLink(link._link) + return link.vlan diff --git a/python/netlink/route/qdisc.py b/python/netlink/route/qdisc.py new file mode 100644 index 0000000..c8a4c6f --- /dev/null +++ b/python/netlink/route/qdisc.py @@ -0,0 +1,185 @@ +# +# Copyright (c) 2011 Thomas Graf +# + +__all__ = [ + 'QdiscCache', + 'Qdisc'] + +import netlink.core as netlink +import netlink.capi as core_capi +import netlink.route.capi as capi +import netlink.util as util +import netlink.route.tc as tc + +########################################################################### +# Link Cache +class QdiscCache(netlink.Cache): + """Cache of qdiscs""" + + def __init__(self, cache=None): + if not cache: + cache = self._alloc_cache_name("route/qdisc") + + self._protocol = netlink.NETLINK_ROUTE + self._c_cache = cache + +# def __getitem__(self, key): +# if type(key) is int: +# link = capi.rtnl_link_get(self._this, key) +# elif type(key) is str: +# link = capi.rtnl_link_get_by_name(self._this, key) +# +# if qdisc is None: +# raise KeyError() +# else: +# return Qdisc._from_capi(capi.qdisc2obj(qdisc)) + + def _new_object(self, obj): + return Qdisc(obj) + + def _new_cache(self, cache): + return QdiscCache(cache=cache) + +########################################################################### +# Qdisc Object +class Qdisc(tc.Tc): + """Network link""" + + def __init__(self, obj=None): + self._name = "qdisc" + self._abbr = "qdisc" + + netlink.Object.__init__(self, "route/qdisc", "qdisc", obj) + self._tc = capi.obj2tc(self._nl_object) + self._rtnl_qdisc = self._obj2type(self._nl_object) + + netlink.attr('qdisc.handle', fmt=util.handle) + netlink.attr('qdisc.parent', fmt=util.handle) + netlink.attr('qdisc.kind', fmt=util.bold) + + def _obj2type(self, obj): + return capi.obj2qdisc(obj) + + def __cmp__(self, other): + return self.handle - other.handle + + def _new_instance(self, obj): + if not obj: + raise ValueError() + + return Qdisc(obj) + +# ##################################################################### +# # add() +# def add(self, socket, flags=None): +# if not flags: +# flags = netlink.NLM_F_CREATE +# +# ret = capi.rtnl_link_add(socket._sock, self._link, flags) +# if ret < 0: +# raise netlink.KernelError(ret) +# +# ##################################################################### +# # change() +# def change(self, socket, flags=0): +# """Commit changes made to the link object""" +# if not self._orig: +# raise NetlinkError("Original link not available") +# ret = capi.rtnl_link_change(socket._sock, self._orig, self._link, flags) +# if ret < 0: +# raise netlink.KernelError(ret) +# +# ##################################################################### +# # delete() +# def delete(self, socket): +# """Attempt to delete this link in the kernel""" +# ret = capi.rtnl_link_delete(socket._sock, self._link) +# if ret < 0: +# raise netlink.KernelError(ret) + + @property + def _dev(self): + buf = util.kw('dev') + ' ' + + if self.link: + return buf + util.string(self.link.name) + else: + return buf + util.num(self.ifindex) + + @property + def _parent(self): + return util.kw('parent') + ' ' + str(self.parent) + + ################################################################### + # + # format(details=False, stats=False) + # + def format(self, details=False, stats=False): + """Return qdisc as formatted text""" + fmt = util.MyFormatter(self) + + buf = fmt.format('qdisc {kind} {handle} {_dev} {_parent}') + + if details: + fmt = util.MyFormatter(self) + buf += fmt.format('\n'\ + '\t{mtu} {mpu} {overhead}\n') + +# if stats: +# l = [['Packets', RX_PACKETS, TX_PACKETS], +# ['Bytes', RX_BYTES, TX_BYTES], +# ['Errors', RX_ERRORS, TX_ERRORS], +# ['Dropped', RX_DROPPED, TX_DROPPED], +# ['Compressed', RX_COMPRESSED, TX_COMPRESSED], +# ['FIFO Errors', RX_FIFO_ERR, TX_FIFO_ERR], +# ['Length Errors', RX_LEN_ERR, None], +# ['Over Errors', RX_OVER_ERR, None], +# ['CRC Errors', RX_CRC_ERR, None], +# ['Frame Errors', RX_FRAME_ERR, None], +# ['Missed Errors', RX_MISSED_ERR, None], +# ['Abort Errors', None, TX_ABORT_ERR], +# ['Carrier Errors', None, TX_CARRIER_ERR], +# ['Heartbeat Errors', None, TX_HBEAT_ERR], +# ['Window Errors', None, TX_WIN_ERR], +# ['Collisions', None, COLLISIONS], +# ['Multicast', None, MULTICAST], +# ['', None, None], +# ['Ipv6:', None, None], +# ['Packets', IP6_INPKTS, IP6_OUTPKTS], +# ['Bytes', IP6_INOCTETS, IP6_OUTOCTETS], +# ['Discards', IP6_INDISCARDS, IP6_OUTDISCARDS], +# ['Multicast Packets', IP6_INMCASTPKTS, IP6_OUTMCASTPKTS], +# ['Multicast Bytes', IP6_INMCASTOCTETS, IP6_OUTMCASTOCTETS], +# ['Broadcast Packets', IP6_INBCASTPKTS, IP6_OUTBCASTPKTS], +# ['Broadcast Bytes', IP6_INBCASTOCTETS, IP6_OUTBCASTOCTETS], +# ['Delivers', IP6_INDELIVERS, None], +# ['Forwarded', None, IP6_OUTFORWDATAGRAMS], +# ['No Routes', IP6_INNOROUTES, IP6_OUTNOROUTES], +# ['Header Errors', IP6_INHDRERRORS, None], +# ['Too Big Errors', IP6_INTOOBIGERRORS, None], +# ['Address Errors', IP6_INADDRERRORS, None], +# ['Unknown Protocol', IP6_INUNKNOWNPROTOS, None], +# ['Truncated Packets', IP6_INTRUNCATEDPKTS, None], +# ['Reasm Timeouts', IP6_REASMTIMEOUT, None], +# ['Reasm Requests', IP6_REASMREQDS, None], +# ['Reasm Failures', IP6_REASMFAILS, None], +# ['Reasm OK', IP6_REASMOKS, None], +# ['Frag Created', None, IP6_FRAGCREATES], +# ['Frag Failures', None, IP6_FRAGFAILS], +# ['Frag OK', None, IP6_FRAGOKS], +# ['', None, None], +# ['ICMPv6:', None, None], +# ['Messages', ICMP6_INMSGS, ICMP6_OUTMSGS], +# ['Errors', ICMP6_INERRORS, ICMP6_OUTERRORS]] +# +# buf += '\n\t%s%s%s%s\n' % (33 * ' ', util.title('RX'), +# 15 * ' ', util.title('TX')) +# +# for row in l: +# row[0] = util.kw(row[0]) +# row[1] = self.get_stat(row[1]) if row[1] else '' +# row[2] = self.get_stat(row[2]) if row[2] else '' +# buf += '\t{0:27} {1:>16} {2:>16}\n'.format(*row) + + return buf diff --git a/python/netlink/route/tc.py b/python/netlink/route/tc.py new file mode 100644 index 0000000..ebe25e1 --- /dev/null +++ b/python/netlink/route/tc.py @@ -0,0 +1,357 @@ + + +# +# Copyright (c) 2011 Thomas Graf +# + +__all__ = [ + 'TcCache', + 'Tc', + 'QdiscCache', + 'Qdisc'] + +import socket +import sys +import netlink.core as netlink +import netlink.capi as core_capi +import netlink.route.capi as capi +import netlink.util as util + +from netlink.route.link import Link + +TC_PACKETS = 0 +TC_BYTES = 1 +TC_RATE_BPS = 2 +TC_RATE_PPS = 3 +TC_QLEN = 4 +TC_BACKLOG = 5 +TC_DROPS = 6 +TC_REQUEUES = 7 +TC_OVERLIMITS = 9 + +TC_H_ROOT = 0xFFFFFFFF +TC_H_INGRESS = 0xFFFFFFF1 + +class Handle(object): + def __init__(self, val=None): + if type(val) is str: + val = capi.tc_str2handle(val) + elif not val: + val = 0 + + self._val = int(val) + + def __int__(self): + return self._val + + def __str__(self): + return capi.rtnl_tc_handle2str(self._val, 64)[0] + + def isroot(self): + return self._val == TC_H_ROOT or self._val == TC_H_INGRESS + +########################################################################### +# TC Cache +class TcCache(netlink.Cache): + """Cache of traffic control object""" + + def __getitem__(self, key): + raise NotImplementedError() + +########################################################################### +# Tc Object +class Tc(netlink.Object): + def __cmp__(self, other): + return self.ifindex - other.ifindex + + def isroot(self): + return self.parent.isroot() + + ##################################################################### + # ifindex + @property + def ifindex(self): + """interface index""" + return capi.rtnl_tc_get_ifindex(self._tc) + + @ifindex.setter + def ifindex(self, value): + capi.rtnl_tc_set_ifindex(self._tc, int(value)) + + ##################################################################### + # link + @property + def link(self): + link = capi.rtnl_tc_get_link(self._tc) + if not link: + return None + else: + return Link._from_capi(link) + + @link.setter + def link(self, value): + capi.rtnl_tc_set_link(self._tc, value._link) + + ##################################################################### + # mtu + @property + def mtu(self): + return capi.rtnl_tc_get_mtu(self._tc) + + @mtu.setter + def mtu(self, value): + capi.rtnl_tc_set_mtu(self._tc, int(value)) + + ##################################################################### + # mpu + @property + def mpu(self): + return capi.rtnl_tc_get_mpu(self._tc) + + @mpu.setter + def mpu(self, value): + capi.rtnl_tc_set_mpu(self._tc, int(value)) + + ##################################################################### + # overhead + @property + def overhead(self): + return capi.rtnl_tc_get_overhead(self._tc) + + @overhead.setter + def overhead(self, value): + capi.rtnl_tc_set_overhead(self._tc, int(value)) + + ##################################################################### + # linktype + @property + def linktype(self): + return capi.rtnl_tc_get_linktype(self._tc) + + @linktype.setter + def linktype(self, value): + capi.rtnl_tc_set_linktype(self._tc, int(value)) + + ##################################################################### + # handle + @property + def handle(self): + return Handle(capi.rtnl_tc_get_handle(self._tc)) + + @handle.setter + def handle(self, value): + capi.rtnl_tc_set_handle(self._tc, int(value)) + + ##################################################################### + # parent + @property + def parent(self): + return Handle(capi.rtnl_tc_get_parent(self._tc)) + + @parent.setter + def parent(self, value): + capi.rtnl_tc_set_parent(self._tc, int(value)) + + ##################################################################### + # kind + @property + def kind(self): + return capi.rtnl_tc_get_kind(self._tc) + + @kind.setter + def kind(self, value): + capi.rtnl_tc_set_kind(self._tc, value) + + def get_stat(self, id): + return capi.rtnl_tc_get_stat(self._tc, id) + +class TcTree(object): + def __init__(self, link, sock): + self._qdisc_cache = QdiscCache().refill(sock) + + def __getitem__(self, key): + pass +# if type(key) is int: +# link = capi.rtnl_link_get(self._this, key) +# elif type(key) is str: +# link = capi.rtnl_link_get_by_name(self._this, key) +# +# if qdisc is None: +# raise KeyError() +# else: +# return Qdisc._from_capi(capi.qdisc2obj(qdisc)) + + + + +########################################################################### +# Link Cache +class QdiscCache(netlink.Cache): + """Cache of qdiscs""" + + def __init__(self, cache=None): + if not cache: + cache = self._alloc_cache_name("route/qdisc") + + self._c_cache = cache + +# def __getitem__(self, key): +# if type(key) is int: +# link = capi.rtnl_link_get(self._this, key) +# elif type(key) is str: +# link = capi.rtnl_link_get_by_name(self._this, key) +# +# if qdisc is None: +# raise KeyError() +# else: +# return Qdisc._from_capi(capi.qdisc2obj(qdisc)) + + def _new_object(self, obj): + return Qdisc(obj) + + def _new_cache(self, cache): + return QdiscCache(cache=cache) + +########################################################################### +# Qdisc Object +class Qdisc(Tc): + """Network link""" + + def __init__(self, obj=None): + self._name = "qdisc" + self._abbr = "qdisc" + + if not obj: + self._qdisc = capi.rtnl_qdisc_alloc() + else: + self._qdisc = capi.obj2qdisc(obj) + + self._obj = capi.qdisc2obj(self._qdisc) + self._orig = capi.obj2qdisc(core_capi.nl_object_clone(self._obj)) + + Tc.__init__(self) + + netlink.attr('qdisc.handle', fmt=util.handle) + netlink.attr('qdisc.parent', fmt=util.handle) + netlink.attr('qdisc.kind', fmt=util.bold) + + def __cmp__(self, other): + return self.handle - other.handle + + def _new_instance(self, obj): + if not obj: raise ValueError() + return Qdisc(obj) + +# ##################################################################### +# # add() +# def add(self, socket, flags=None): +# if not flags: +# flags = netlink.NLM_F_CREATE +# +# ret = capi.rtnl_link_add(socket._sock, self._link, flags) +# if ret < 0: +# raise netlink.KernelError(ret) +# +# ##################################################################### +# # change() +# def change(self, socket, flags=0): +# """Commit changes made to the link object""" +# if not self._orig: +# raise NetlinkError("Original link not available") +# ret = capi.rtnl_link_change(socket._sock, self._orig, self._link, flags) +# if ret < 0: +# raise netlink.KernelError(ret) +# +# ##################################################################### +# # delete() +# def delete(self, socket): +# """Attempt to delete this link in the kernel""" +# ret = capi.rtnl_link_delete(socket._sock, self._link) +# if ret < 0: +# raise netlink.KernelError(ret) + + @property + def _dev(self): + buf = util.kw('dev') + ' ' + + if self.link: + return buf + util.string(self.link.name) + else: + return buf + util.num(self.ifindex) + + @property + def _parent(self): + return util.kw('parent') + ' ' + str(self.parent) + + ################################################################### + # + # format(details=False, stats=False) + # + def format(self, details=False, stats=False): + """Return qdisc as formatted text""" + fmt = util.BriefFormatter(self) + + buf = fmt.format('qdisc {kind} {handle} {_dev} {_parent}') + + if details: + fmt = util.DetailFormatter(self) + buf += fmt.format('\n'\ + '\t{mtu} {mpu} {overhead}\n') + +# if stats: +# l = [['Packets', RX_PACKETS, TX_PACKETS], +# ['Bytes', RX_BYTES, TX_BYTES], +# ['Errors', RX_ERRORS, TX_ERRORS], +# ['Dropped', RX_DROPPED, TX_DROPPED], +# ['Compressed', RX_COMPRESSED, TX_COMPRESSED], +# ['FIFO Errors', RX_FIFO_ERR, TX_FIFO_ERR], +# ['Length Errors', RX_LEN_ERR, None], +# ['Over Errors', RX_OVER_ERR, None], +# ['CRC Errors', RX_CRC_ERR, None], +# ['Frame Errors', RX_FRAME_ERR, None], +# ['Missed Errors', RX_MISSED_ERR, None], +# ['Abort Errors', None, TX_ABORT_ERR], +# ['Carrier Errors', None, TX_CARRIER_ERR], +# ['Heartbeat Errors', None, TX_HBEAT_ERR], +# ['Window Errors', None, TX_WIN_ERR], +# ['Collisions', None, COLLISIONS], +# ['Multicast', None, MULTICAST], +# ['', None, None], +# ['Ipv6:', None, None], +# ['Packets', IP6_INPKTS, IP6_OUTPKTS], +# ['Bytes', IP6_INOCTETS, IP6_OUTOCTETS], +# ['Discards', IP6_INDISCARDS, IP6_OUTDISCARDS], +# ['Multicast Packets', IP6_INMCASTPKTS, IP6_OUTMCASTPKTS], +# ['Multicast Bytes', IP6_INMCASTOCTETS, IP6_OUTMCASTOCTETS], +# ['Broadcast Packets', IP6_INBCASTPKTS, IP6_OUTBCASTPKTS], +# ['Broadcast Bytes', IP6_INBCASTOCTETS, IP6_OUTBCASTOCTETS], +# ['Delivers', IP6_INDELIVERS, None], +# ['Forwarded', None, IP6_OUTFORWDATAGRAMS], +# ['No Routes', IP6_INNOROUTES, IP6_OUTNOROUTES], +# ['Header Errors', IP6_INHDRERRORS, None], +# ['Too Big Errors', IP6_INTOOBIGERRORS, None], +# ['Address Errors', IP6_INADDRERRORS, None], +# ['Unknown Protocol', IP6_INUNKNOWNPROTOS, None], +# ['Truncated Packets', IP6_INTRUNCATEDPKTS, None], +# ['Reasm Timeouts', IP6_REASMTIMEOUT, None], +# ['Reasm Requests', IP6_REASMREQDS, None], +# ['Reasm Failures', IP6_REASMFAILS, None], +# ['Reasm OK', IP6_REASMOKS, None], +# ['Frag Created', None, IP6_FRAGCREATES], +# ['Frag Failures', None, IP6_FRAGFAILS], +# ['Frag OK', None, IP6_FRAGOKS], +# ['', None, None], +# ['ICMPv6:', None, None], +# ['Messages', ICMP6_INMSGS, ICMP6_OUTMSGS], +# ['Errors', ICMP6_INERRORS, ICMP6_OUTERRORS]] +# +# buf += '\n\t%s%s%s%s\n' % (33 * ' ', util.title('RX'), +# 15 * ' ', util.title('TX')) +# +# for row in l: +# row[0] = util.kw(row[0]) +# row[1] = self.get_stat(row[1]) if row[1] else '' +# row[2] = self.get_stat(row[2]) if row[2] else '' +# buf += '\t{0:27} {1:>16} {2:>16}\n'.format(*row) + + return buf diff --git a/python/netlink/util.py b/python/netlink/util.py new file mode 100644 index 0000000..d3d0167 --- /dev/null +++ b/python/netlink/util.py @@ -0,0 +1,146 @@ +# +# Utilities +# +# Copyright (c) 2011 Thomas Graf +# + +"""utility module for netlink + +""" + +import netlink.core as netlink +from string import Formatter + +__version__ = "1.0" + +def _color(t, c): + return chr(0x1b)+"["+str(c)+"m"+str(t)+chr(0x1b)+"[0m" + +def black(t): + return _color(t, 30) + +def red(t): + return _color(t, 31) + +def green(t): + return _color(t, 32) + +def yellow(t): + return _color(t, 33) + +def blue(t): + return _color(t, 34) + +def mangenta(t): + return _color(t, 35) + +def cyan(t): + return _color(t, 36) + +def white(t): + return _color(t, 37) + +def bold(t): + return _color(t, 1) + +def kw(t): + return yellow(t) + +def num(t): + return str(t) + +def string(t): + return t + +def addr(t): + return str(t) + +def bad(t): + return red(t) + +def good(t): + return green(t) + +def title(t): + return t + +def bool(t): + return str(t) + +def handle(t): + return str(t) + +class MyFormatter(Formatter): + def __init__(self, obj, indent=''): + self._obj = obj + self._indent = indent + + def _nlattr(self, key): + value = getattr(self._obj, key) + title = None + + if type(value) == 'instancemethod': + value = value() + + try: + d = netlink.attrs[self._obj._name + '.' + key] + + if 'fmt' in d: + value = d['fmt'](value) + + if 'title' in d: + title = d['title'] + except KeyError: + pass + + return title, str(value) + + def get_value(self, key, args, kwds): + # Let default get_value() handle ints + if not isinstance(key, str): + return Formatter.get_value(self, key, args, kwds) + + # HACK, we allow defining strings via fields to allow + # conversions + if key[:2] == 's|': + return key[2:] + + if key[:2] == 't|': + # title mode ("TITLE ATTR") + include_title = True + elif key[:2] == 'a|': + # plain attribute mode ("ATTR") + include_title = False + else: + # No special field, have default get_value() get it + return Formatter.get_value(self, key, args, kwds) + + key = key[2:] + (title, value) = self._nlattr(key) + + if include_title: + if not title: + title = key # fall back to key as title + value = kw(title) + ' ' + value + + return value + + def convert_field(self, value, conversion): + if conversion == 'r': + return repr(value) + elif conversion == 's': + return str(value) + elif conversion == 'k': + return kw(value) + elif conversion == 'b': + return bold(value) + elif conversion is None: + return value + + raise ValueError("Unknown converion specifier {0!s}".format(conversion)) + + def nl(self): + return '\n' + self._indent + + def nl(self, format_string=''): + return '\n' + self._indent + self.format(format_string) diff --git a/python/setup.py b/python/setup.py new file mode 100644 index 0000000..9ea7c15 --- /dev/null +++ b/python/setup.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python + +from distutils.core import setup, Extension + +opts = ['-O', '-nodefaultctor'] +include = ['../include'] + +netlink_capi = Extension('netlink/_capi', + sources = ['netlink/capi.i'], + include_dirs = include, + swig_opts = opts, + libraries = ['nl'], + ) + +route_capi = Extension('netlink/route/_capi', + sources = ['netlink/route/capi.i'], + include_dirs = include, + swig_opts = opts, + libraries = ['nl', 'nl-route'], + ) + +setup(name = 'netlink', + version = '1.0', + description = 'Python wrapper for netlink protocols', + author = 'Thomas Graf', + author_email = 'tgraf@suug.ch', + ext_modules = [netlink_capi, route_capi], + packages = ['netlink', 'netlink.route', 'netlink.route.links'], + ) From 4cb1666fe19f71c09628615a1c4b6f822b7cd8de Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 11 May 2011 09:33:29 +0200 Subject: [PATCH 042/432] Provide silent variation of nl_cache_require() Use in addr and tc layer to avoid warnings being printed if no cache is available. --- include/netlink/cache.h | 1 + lib/cache_mngt.c | 21 ++++++++++++++------- lib/route/addr.c | 2 +- lib/route/tc.c | 2 +- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/include/netlink/cache.h b/include/netlink/cache.h index e17b015..f8073f0 100644 --- a/include/netlink/cache.h +++ b/include/netlink/cache.h @@ -107,6 +107,7 @@ extern int nl_cache_mngt_unregister(struct nl_cache_ops *); extern void nl_cache_mngt_provide(struct nl_cache *); extern void nl_cache_mngt_unprovide(struct nl_cache *); extern struct nl_cache * nl_cache_mngt_require(const char *); +extern struct nl_cache * __nl_cache_mngt_require(const char *); struct nl_cache_mngr; diff --git a/lib/cache_mngt.c b/lib/cache_mngt.c index d57d836..a9ecf27 100644 --- a/lib/cache_mngt.c +++ b/lib/cache_mngt.c @@ -217,6 +217,17 @@ void nl_cache_mngt_unprovide(struct nl_cache *cache) ops->co_major_cache = NULL; } +struct nl_cache *__nl_cache_mngt_require(const char *name) +{ + struct nl_cache_ops *ops; + + ops = nl_cache_ops_lookup(name); + if (ops) + return ops->co_major_cache; + + return NULL; +} + /** * Demand the use of a global cache * @arg name name of the required object type @@ -229,19 +240,15 @@ void nl_cache_mngt_unprovide(struct nl_cache *cache) */ struct nl_cache *nl_cache_mngt_require(const char *name) { - struct nl_cache_ops *ops; + struct nl_cache *cache; - ops = nl_cache_ops_lookup(name); - if (!ops || !ops->co_major_cache) { + if (!(cache = __nl_cache_mngt_require(name))) fprintf(stderr, "Application BUG: Your application must " "call nl_cache_mngt_provide() and\nprovide a valid " "%s cache to be used for internal lookups.\nSee the " " API documentation for more details.\n", name); - - return NULL; - } - return ops->co_major_cache; + return cache; } /** @} */ diff --git a/lib/route/addr.c b/lib/route/addr.c index fa6d76d..4ca6335 100644 --- a/lib/route/addr.c +++ b/lib/route/addr.c @@ -294,7 +294,7 @@ static int addr_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, addr->ce_mask |= ADDR_ATTR_ANYCAST; } - if ((link_cache = nl_cache_mngt_require("route/link"))) { + if ((link_cache = __nl_cache_mngt_require("route/link"))) { struct rtnl_link *link; if ((link = rtnl_link_get(link_cache, addr->a_ifindex))) { diff --git a/lib/route/tc.c b/lib/route/tc.c index 03920aa..da8c75f 100644 --- a/lib/route/tc.c +++ b/lib/route/tc.c @@ -176,7 +176,7 @@ compat_xstats: return err; } - if ((link_cache = nl_cache_mngt_require("route/link"))) { + if ((link_cache = __nl_cache_mngt_require("route/link"))) { struct rtnl_link *link; if ((link = rtnl_link_get(link_cache, tc->tc_ifindex))) { From ed69b2a79b8e0b71c230b5e75626aa620a0d5ff9 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 9 Jun 2011 12:28:04 +0200 Subject: [PATCH 043/432] Add rtnl_tc_data_check() Behaves like rtnl_tc_data() but verifies that the traffic control object is of the expected type. --- include/netlink/route/tc-api.h | 2 ++ lib/route/tc.c | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/include/netlink/route/tc-api.h b/include/netlink/route/tc-api.h index 8ed940a..d89408f 100644 --- a/include/netlink/route/tc-api.h +++ b/include/netlink/route/tc-api.h @@ -124,6 +124,8 @@ extern int rtnl_tc_compare(struct nl_object *, uint32_t, int); extern void * rtnl_tc_data(struct rtnl_tc *); +extern void * rtnl_tc_data_check(struct rtnl_tc *, + struct rtnl_tc_ops *); extern struct rtnl_tc_ops * rtnl_tc_lookup_ops(enum rtnl_tc_type, const char *); diff --git a/lib/route/tc.c b/lib/route/tc.c index da8c75f..983555a 100644 --- a/lib/route/tc.c +++ b/lib/route/tc.c @@ -1010,6 +1010,21 @@ void *rtnl_tc_data(struct rtnl_tc *tc) return nl_data_get(tc->tc_subdata); } +void *rtnl_tc_data_check(struct rtnl_tc *tc, struct rtnl_tc_ops *ops) +{ + if (tc->tc_ops != ops) { + char buf[64]; + + snprintf(buf, sizeof(buf), + "tc object %p used in %s context but is of type %s", + tc, ops->to_kind, tc->tc_ops->to_kind); + + return NULL; + } + + return rtnl_tc_data(tc); +} + void rtnl_tc_type_register(struct rtnl_tc_type_ops *ops) { if (ops->tt_type > RTNL_TC_TYPE_MAX) From 58e0e1eda9cbb09a56ffdc8ac6934dc5f5f884b2 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 9 Jun 2011 12:29:21 +0200 Subject: [PATCH 044/432] Add nl_rate2str() --- include/netlink/utils.h | 6 ++++++ lib/utils.c | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/include/netlink/utils.h b/include/netlink/utils.h index 309e02f..a1ef82e 100644 --- a/include/netlink/utils.h +++ b/include/netlink/utils.h @@ -38,9 +38,15 @@ extern "C" { /** @} */ +enum { + NL_BYTE_RATE, + NL_BIT_RATE, +}; + /* unit pretty-printing */ extern double nl_cancel_down_bytes(unsigned long long, char **); extern double nl_cancel_down_bits(unsigned long long, char **); +extern int nl_rate2str(unsigned long long, int, char *, size_t); extern double nl_cancel_down_us(uint32_t, char **); /* generic unit translations */ diff --git a/lib/utils.c b/lib/utils.c index b507608..c7d3abd 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -151,6 +151,27 @@ double nl_cancel_down_bits(unsigned long long l, char **unit) } +int nl_rate2str(unsigned long long rate, int type, char *buf, size_t len) +{ + char *unit; + double frac; + + switch (type) { + case NL_BYTE_RATE: + frac = nl_cancel_down_bytes(rate, &unit); + break; + + case NL_BIT_RATE: + frac = nl_cancel_down_bits(rate, &unit); + break; + + default: + BUG(); + } + + return snprintf(buf, len, "%.2f%s/s", frac, unit); +} + /** * Cancel down a micro second value * @arg l micro seconds From aba36899377bfa9dcb9aab431de5a26c3cfeb5ef Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 9 Jun 2011 12:30:15 +0200 Subject: [PATCH 045/432] Provide documentation for rtnl_tc_data() and rtnl_tc_data_check() --- lib/route/tc.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/lib/route/tc.c b/lib/route/tc.c index 983555a..7bd4728 100644 --- a/lib/route/tc.c +++ b/lib/route/tc.c @@ -987,6 +987,15 @@ void rtnl_tc_unregister(struct rtnl_tc_ops *ops) nl_list_del(&ops->to_list); } +/** + * Return pointer to private data of traffic control object + * @arg tc traffic control object + * + * Allocates the private traffic control object data section + * as necessary and returns it. + * + * @return Pointer to private tc data or NULL if allocation failed. + */ void *rtnl_tc_data(struct rtnl_tc *tc) { if (!tc->tc_subdata) { @@ -1010,6 +1019,20 @@ void *rtnl_tc_data(struct rtnl_tc *tc) return nl_data_get(tc->tc_subdata); } +/** + * Check traffic control object type and return private data section + * @arg tc traffic control object + * @arg ops expected traffic control object operations + * + * Checks whether the traffic control object matches the type + * specified with the traffic control object operations. If the + * type matches, the private tc object data is returned. If type + * mismatches, APPBUG() will print a application bug warning. + * + * @see rtnl_tc_data() + * + * @return Pointer to private tc data or NULL if type mismatches. + */ void *rtnl_tc_data_check(struct rtnl_tc *tc, struct rtnl_tc_ops *ops) { if (tc->tc_ops != ops) { @@ -1018,6 +1041,7 @@ void *rtnl_tc_data_check(struct rtnl_tc *tc, struct rtnl_tc_ops *ops) snprintf(buf, sizeof(buf), "tc object %p used in %s context but is of type %s", tc, ops->to_kind, tc->tc_ops->to_kind); + APPBUG(buf); return NULL; } From 053c93fa8ab0047b957c721dfef33ba44443cd0f Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 9 Jun 2011 12:56:52 +0200 Subject: [PATCH 046/432] Update local copies of include/linux --- include/linux/if_addr.h | 6 -- include/linux/if_ether.h | 1 + include/linux/if_link.h | 15 ++--- include/linux/ipv6.h | 38 +++++++++-- include/linux/netlink.h | 128 +------------------------------------- include/linux/pkt_cls.h | 1 + include/linux/pkt_sched.h | 124 +++++++++++++++++++++++++++++++++++- include/linux/snmp.h | 1 + lib/utils.c | 1 + 9 files changed, 166 insertions(+), 149 deletions(-) diff --git a/include/linux/if_addr.h b/include/linux/if_addr.h index 23357ab..c355522 100644 --- a/include/linux/if_addr.h +++ b/include/linux/if_addr.h @@ -52,10 +52,4 @@ struct ifa_cacheinfo { __u32 tstamp; /* updated timestamp, hundredths of seconds */ }; -/* backwards compatibility for userspace */ -#ifndef __KERNEL__ -#define IFA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg)))) -#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg)) -#endif - #endif diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index aead93d..a6af32d 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h @@ -72,6 +72,7 @@ #define ETH_P_MPLS_UC 0x8847 /* MPLS Unicast traffic */ #define ETH_P_MPLS_MC 0x8848 /* MPLS Multicast traffic */ #define ETH_P_ATMMPOA 0x884c /* MultiProtocol Over ATM */ +#define ETH_P_LINK_CTL 0x886c /* HPNA, wlan link local tunnel */ #define ETH_P_ATMFATE 0x8884 /* Frame-based ATM Transport * over Ethernet */ diff --git a/include/linux/if_link.h b/include/linux/if_link.h index b60ff97..8a27d5a 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h @@ -88,12 +88,12 @@ struct rtnl_link_ifmap { * * Example: * [IFLA_AF_SPEC] = { + * [AF_INET] = { + * [IFLA_INET_CONF] = ..., + * }, * [AF_INET6] = { * [IFLA_INET6_FLAGS] = ..., * [IFLA_INET6_CONF] = ..., - * }, - * [AF_BRIDGE] = { - * [IFLA_BRIDGE_PORT] = ... * } * } */ @@ -135,18 +135,14 @@ enum { IFLA_VF_PORTS, IFLA_PORT_SELF, IFLA_AF_SPEC, + IFLA_GROUP, /* Group the device belongs to */ + IFLA_NET_NS_FD, __IFLA_MAX }; #define IFLA_MAX (__IFLA_MAX - 1) -/* backwards compatibility for userspace */ -#ifndef __KERNEL__ -#define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg)))) -#define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg)) -#endif - enum { IFLA_INET_UNSPEC, IFLA_INET_CONF, @@ -259,6 +255,7 @@ enum macvlan_mode { MACVLAN_MODE_PRIVATE = 1, /* don't talk to other macvlans */ MACVLAN_MODE_VEPA = 2, /* talk to other ports through ext bridge */ MACVLAN_MODE_BRIDGE = 4, /* talk to bridge ports directly */ + MACVLAN_MODE_PASSTHRU = 8,/* take over the underlying device */ }; /* SR-IOV virtual function management section */ diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index aa2b67f..f16349d 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -1,6 +1,8 @@ #ifndef _IPV6_H #define _IPV6_H +#include + /* The latest drafts declared increase in minimal mtu up to 1280. */ #define IPV6_MIN_MTU 1280 @@ -12,12 +14,6 @@ */ -struct in6_ifreq { - struct in6_addr ifr6_addr; - __u32 ifr6_prefixlen; - int ifr6_ifindex; -}; - #define IPV6_SRCRT_STRICT 0x01 /* Deprecated; will be removed */ #define IPV6_SRCRT_TYPE_0 0 /* Deprecated; will be removed */ #define IPV6_SRCRT_TYPE_2 2 /* IPv6 type 2 Routing Header */ @@ -49,6 +45,7 @@ struct ipv6_opt_hdr { #define ipv6_destopt_hdr ipv6_opt_hdr #define ipv6_hopopt_hdr ipv6_opt_hdr + /* * routing header type 0 (used in cmsghdr struct) */ @@ -83,6 +80,34 @@ struct ipv6_destopt_hao { struct in6_addr addr; } __attribute__((packed)); +/* + * IPv6 fixed header + * + * BEWARE, it is incorrect. The first 4 bits of flow_lbl + * are glued to priority now, forming "class". + */ + +struct ipv6hdr { +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u8 priority:4, + version:4; +#elif defined(__BIG_ENDIAN_BITFIELD) + __u8 version:4, + priority:4; +#else +#error "Please fix " +#endif + __u8 flow_lbl[3]; + + __be16 payload_len; + __u8 nexthdr; + __u8 hop_limit; + + struct in6_addr saddr; + struct in6_addr daddr; +}; + + /* index values for the variables in ipv6_devconf */ enum { DEVCONF_FORWARDING = 0, @@ -117,4 +142,5 @@ enum { DEVCONF_MAX }; + #endif /* _IPV6_H */ diff --git a/include/linux/netlink.h b/include/linux/netlink.h index e2b9e63..0abcdaf 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -24,6 +24,7 @@ /* leave room for NETLINK_DM (DM Events) */ #define NETLINK_SCSITRANSPORT 18 /* SCSI Transports */ #define NETLINK_ECRYPTFS 19 +#define NETLINK_RDMA 20 #define MAX_LINKS 32 @@ -144,131 +145,4 @@ struct nlattr { #define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1)) #define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr))) -#ifdef __KERNEL__ - -#include -#include - -struct net; - -static inline struct nlmsghdr *nlmsg_hdr(const struct sk_buff *skb) -{ - return (struct nlmsghdr *)skb->data; -} - -struct netlink_skb_parms { - struct ucred creds; /* Skb credentials */ - __u32 pid; - __u32 dst_group; - kernel_cap_t eff_cap; - __u32 loginuid; /* Login (audit) uid */ - __u32 sessionid; /* Session id (audit) */ - __u32 sid; /* SELinux security id */ -}; - -#define NETLINK_CB(skb) (*(struct netlink_skb_parms*)&((skb)->cb)) -#define NETLINK_CREDS(skb) (&NETLINK_CB((skb)).creds) - - -extern void netlink_table_grab(void); -extern void netlink_table_ungrab(void); - -extern struct sock *netlink_kernel_create(struct net *net, - int unit,unsigned int groups, - void (*input)(struct sk_buff *skb), - struct mutex *cb_mutex, - struct module *module); -extern void netlink_kernel_release(struct sock *sk); -extern int __netlink_change_ngroups(struct sock *sk, unsigned int groups); -extern int netlink_change_ngroups(struct sock *sk, unsigned int groups); -extern void __netlink_clear_multicast_users(struct sock *sk, unsigned int group); -extern void netlink_clear_multicast_users(struct sock *sk, unsigned int group); -extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err); -extern int netlink_has_listeners(struct sock *sk, unsigned int group); -extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock); -extern int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 pid, - __u32 group, gfp_t allocation); -extern int netlink_broadcast_filtered(struct sock *ssk, struct sk_buff *skb, - __u32 pid, __u32 group, gfp_t allocation, - int (*filter)(struct sock *dsk, struct sk_buff *skb, void *data), - void *filter_data); -extern int netlink_set_err(struct sock *ssk, __u32 pid, __u32 group, int code); -extern int netlink_register_notifier(struct notifier_block *nb); -extern int netlink_unregister_notifier(struct notifier_block *nb); - -/* finegrained unicast helpers: */ -struct sock *netlink_getsockbyfilp(struct file *filp); -int netlink_attachskb(struct sock *sk, struct sk_buff *skb, - long *timeo, struct sock *ssk); -void netlink_detachskb(struct sock *sk, struct sk_buff *skb); -int netlink_sendskb(struct sock *sk, struct sk_buff *skb); - -/* - * skb should fit one page. This choice is good for headerless malloc. - * But we should limit to 8K so that userspace does not have to - * use enormous buffer sizes on recvmsg() calls just to avoid - * MSG_TRUNC when PAGE_SIZE is very large. - */ -#if PAGE_SIZE < 8192UL -#define NLMSG_GOODSIZE SKB_WITH_OVERHEAD(PAGE_SIZE) -#else -#define NLMSG_GOODSIZE SKB_WITH_OVERHEAD(8192UL) -#endif - -#define NLMSG_DEFAULT_SIZE (NLMSG_GOODSIZE - NLMSG_HDRLEN) - - -struct netlink_callback { - struct sk_buff *skb; - const struct nlmsghdr *nlh; - int (*dump)(struct sk_buff * skb, - struct netlink_callback *cb); - int (*done)(struct netlink_callback *cb); - int family; - long args[6]; -}; - -struct netlink_notify { - struct net *net; - int pid; - int protocol; -}; - -static __inline__ struct nlmsghdr * -__nlmsg_put(struct sk_buff *skb, u32 pid, u32 seq, int type, int len, int flags) -{ - struct nlmsghdr *nlh; - int size = NLMSG_LENGTH(len); - - nlh = (struct nlmsghdr*)skb_put(skb, NLMSG_ALIGN(size)); - nlh->nlmsg_type = type; - nlh->nlmsg_len = size; - nlh->nlmsg_flags = flags; - nlh->nlmsg_pid = pid; - nlh->nlmsg_seq = seq; - if (!__builtin_constant_p(size) || NLMSG_ALIGN(size) - size != 0) - memset(NLMSG_DATA(nlh) + len, 0, NLMSG_ALIGN(size) - size); - return nlh; -} - -#define NLMSG_NEW(skb, pid, seq, type, len, flags) \ -({ if (unlikely(skb_tailroom(skb) < (int)NLMSG_SPACE(len))) \ - goto nlmsg_failure; \ - __nlmsg_put(skb, pid, seq, type, len, flags); }) - -#define NLMSG_PUT(skb, pid, seq, type, len) \ - NLMSG_NEW(skb, pid, seq, type, len, 0) - -extern int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, - const struct nlmsghdr *nlh, - int (*dump)(struct sk_buff *skb, struct netlink_callback*), - int (*done)(struct netlink_callback*)); - - -#define NL_NONROOT_RECV 0x1 -#define NL_NONROOT_SEND 0x2 -extern void netlink_set_nonroot(int protocol, unsigned flag); - -#endif /* __KERNEL__ */ - #endif /* __LINUX_NETLINK_H */ diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h index 7f6ba86..defbde2 100644 --- a/include/linux/pkt_cls.h +++ b/include/linux/pkt_cls.h @@ -332,6 +332,7 @@ enum { FLOW_KEY_SKUID, FLOW_KEY_SKGID, FLOW_KEY_VLAN_TAG, + FLOW_KEY_RXHASH, __FLOW_KEY_MAX, }; diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h index 2cfa4bc..c533670 100644 --- a/include/linux/pkt_sched.h +++ b/include/linux/pkt_sched.h @@ -223,7 +223,7 @@ struct tc_gred_qopt { __u32 limit; /* HARD maximal queue length (bytes) */ __u32 qth_min; /* Min average length threshold (bytes) */ __u32 qth_max; /* Max average length threshold (bytes) */ - __u32 DP; /* upto 2^32 DPs */ + __u32 DP; /* up to 2^32 DPs */ __u32 backlog; __u32 qave; __u32 forced; @@ -247,6 +247,35 @@ struct tc_gred_sopt { __u16 pad1; }; +/* CHOKe section */ + +enum { + TCA_CHOKE_UNSPEC, + TCA_CHOKE_PARMS, + TCA_CHOKE_STAB, + __TCA_CHOKE_MAX, +}; + +#define TCA_CHOKE_MAX (__TCA_CHOKE_MAX - 1) + +struct tc_choke_qopt { + __u32 limit; /* Hard queue length (packets) */ + __u32 qth_min; /* Min average threshold (packets) */ + __u32 qth_max; /* Max average threshold (packets) */ + unsigned char Wlog; /* log(W) */ + unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */ + unsigned char Scell_log; /* cell size for idle damping */ + unsigned char flags; /* see RED flags */ +}; + +struct tc_choke_xstats { + __u32 early; /* Early drops */ + __u32 pdrop; /* Drops due to queue limits */ + __u32 other; /* Drops due to drop() calls */ + __u32 marked; /* Marked packets */ + __u32 matched; /* Drops due to flow match */ +}; + /* HTB section */ #define TC_HTB_NUMPRIO 8 #define TC_HTB_MAXDEPTH 8 @@ -435,6 +464,7 @@ enum { TCA_NETEM_DELAY_DIST, TCA_NETEM_REORDER, TCA_NETEM_CORRUPT, + TCA_NETEM_LOSS, __TCA_NETEM_MAX, }; @@ -465,7 +495,33 @@ struct tc_netem_corrupt { __u32 correlation; }; +enum { + NETEM_LOSS_UNSPEC, + NETEM_LOSS_GI, /* General Intuitive - 4 state model */ + NETEM_LOSS_GE, /* Gilbert Elliot models */ + __NETEM_LOSS_MAX +}; +#define NETEM_LOSS_MAX (__NETEM_LOSS_MAX - 1) + +/* State transition probablities for 4 state model */ +struct tc_netem_gimodel { + __u32 p13; + __u32 p31; + __u32 p32; + __u32 p14; + __u32 p23; +}; + +/* Gilbert-Elliot models */ +struct tc_netem_gemodel { + __u32 p; + __u32 r; + __u32 h; + __u32 k1; +}; + #define NETEM_DIST_SCALE 8192 +#define NETEM_DIST_MAX 16384 /* DRR */ @@ -481,4 +537,70 @@ struct tc_drr_stats { __u32 deficit; }; +/* MQPRIO */ +#define TC_QOPT_BITMASK 15 +#define TC_QOPT_MAX_QUEUE 16 + +struct tc_mqprio_qopt { + __u8 num_tc; + __u8 prio_tc_map[TC_QOPT_BITMASK + 1]; + __u8 hw; + __u16 count[TC_QOPT_MAX_QUEUE]; + __u16 offset[TC_QOPT_MAX_QUEUE]; +}; + +/* SFB */ + +enum { + TCA_SFB_UNSPEC, + TCA_SFB_PARMS, + __TCA_SFB_MAX, +}; + +#define TCA_SFB_MAX (__TCA_SFB_MAX - 1) + +/* + * Note: increment, decrement are Q0.16 fixed-point values. + */ +struct tc_sfb_qopt { + __u32 rehash_interval; /* delay between hash move, in ms */ + __u32 warmup_time; /* double buffering warmup time in ms (warmup_time < rehash_interval) */ + __u32 max; /* max len of qlen_min */ + __u32 bin_size; /* maximum queue length per bin */ + __u32 increment; /* probability increment, (d1 in Blue) */ + __u32 decrement; /* probability decrement, (d2 in Blue) */ + __u32 limit; /* max SFB queue length */ + __u32 penalty_rate; /* inelastic flows are rate limited to 'rate' pps */ + __u32 penalty_burst; +}; + +struct tc_sfb_xstats { + __u32 earlydrop; + __u32 penaltydrop; + __u32 bucketdrop; + __u32 queuedrop; + __u32 childdrop; /* drops in child qdisc */ + __u32 marked; + __u32 maxqlen; + __u32 maxprob; + __u32 avgprob; +}; + +#define SFB_MAX_PROB 0xFFFF + +/* QFQ */ +enum { + TCA_QFQ_UNSPEC, + TCA_QFQ_WEIGHT, + TCA_QFQ_LMAX, + __TCA_QFQ_MAX +}; + +#define TCA_QFQ_MAX (__TCA_QFQ_MAX - 1) + +struct tc_qfq_stats { + __u32 weight; + __u32 lmax; +}; + #endif diff --git a/include/linux/snmp.h b/include/linux/snmp.h index ebb0c80..12b2b18 100644 --- a/include/linux/snmp.h +++ b/include/linux/snmp.h @@ -230,6 +230,7 @@ enum LINUX_MIB_TCPMINTTLDROP, /* RFC 5082 */ LINUX_MIB_TCPDEFERACCEPTDROP, LINUX_MIB_IPRPFILTER, /* IP Reverse Path Filter (rp_filter) */ + LINUX_MIB_TCPTIMEWAITOVERFLOW, /* TCPTimeWaitOverflow */ __LINUX_MIB_MAX }; diff --git a/lib/utils.c b/lib/utils.c index c7d3abd..8eb068a 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -689,6 +689,7 @@ static const struct trans_tbl ether_protos[] = { __ADD(ETH_P_MPLS_UC,mpls_uc) __ADD(ETH_P_MPLS_MC,mpls_mc) __ADD(ETH_P_ATMMPOA,atmmpoa) + __ADD(ETH_P_LINK_CTL,link_ctl) __ADD(ETH_P_ATMFATE,atmfate) __ADD(ETH_P_PAE,pae) __ADD(ETH_P_AOE,aoe) From 09210d96197192b6b1f61756a7e1f39ccbb02e01 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 9 Jun 2011 13:32:13 +0200 Subject: [PATCH 047/432] HTB: Add support for level and direct pkt stats, complete access functions - Adds support for htb class level and direct packet statistics - Complete all get/set access functions - Complete error handling - Documentation --- include/netlink-types.h | 2 + include/netlink/route/qdisc/htb.h | 28 ++- lib/route/qdisc/htb.c | 310 +++++++++++++++++++++++++----- 3 files changed, 280 insertions(+), 60 deletions(-) diff --git a/include/netlink-types.h b/include/netlink-types.h index f842187..750c897 100644 --- a/include/netlink-types.h +++ b/include/netlink-types.h @@ -631,6 +631,7 @@ struct rtnl_htb_qdisc uint32_t qh_rate2quantum; uint32_t qh_defcls; uint32_t qh_mask; + uint32_t qh_direct_pkts; }; struct rtnl_htb_class @@ -642,6 +643,7 @@ struct rtnl_htb_class uint32_t ch_cbuffer; uint32_t ch_quantum; uint32_t ch_mask; + uint32_t ch_level; }; struct rtnl_cbq diff --git a/include/netlink/route/qdisc/htb.h b/include/netlink/route/qdisc/htb.h index 9061b9b..af0287d 100644 --- a/include/netlink/route/qdisc/htb.h +++ b/include/netlink/route/qdisc/htb.h @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2010 Thomas Graf + * Copyright (c) 2003-2011 Thomas Graf * Copyright (c) 2005 Petr Gotthard * Copyright (c) 2005 Siemens AG Oesterreich */ @@ -21,16 +21,24 @@ extern "C" { #endif -extern void rtnl_htb_set_rate2quantum(struct rtnl_qdisc *, uint32_t); -extern void rtnl_htb_set_defcls(struct rtnl_qdisc *, uint32_t); +extern uint32_t rtnl_htb_get_rate2quantum(struct rtnl_qdisc *); +extern int rtnl_htb_set_rate2quantum(struct rtnl_qdisc *, uint32_t); +extern uint32_t rtnl_htb_get_defcls(struct rtnl_qdisc *); +extern int rtnl_htb_set_defcls(struct rtnl_qdisc *, uint32_t); -extern void rtnl_htb_set_prio(struct rtnl_class *, uint32_t); -extern void rtnl_htb_set_rate(struct rtnl_class *, uint32_t); -extern uint32_t rtnl_htb_get_rate(struct rtnl_class *); -extern void rtnl_htb_set_ceil(struct rtnl_class *, uint32_t); -extern void rtnl_htb_set_rbuffer(struct rtnl_class *, uint32_t); -extern void rtnl_htb_set_cbuffer(struct rtnl_class *, uint32_t); -extern void rtnl_htb_set_quantum(struct rtnl_class *, uint32_t quantum); +extern uint32_t rtnl_htb_get_prio(struct rtnl_class *); +extern int rtnl_htb_set_prio(struct rtnl_class *, uint32_t); +extern uint32_t rtnl_htb_get_rate(struct rtnl_class *); +extern int rtnl_htb_set_rate(struct rtnl_class *, uint32_t); +extern uint32_t rtnl_htb_get_ceil(struct rtnl_class *); +extern int rtnl_htb_set_ceil(struct rtnl_class *, uint32_t); +extern uint32_t rtnl_htb_get_rbuffer(struct rtnl_class *); +extern int rtnl_htb_set_rbuffer(struct rtnl_class *, uint32_t); +extern uint32_t rtnl_htb_get_cbuffer(struct rtnl_class *); +extern int rtnl_htb_set_cbuffer(struct rtnl_class *, uint32_t); +extern uint32_t rtnl_htb_get_quantum(struct rtnl_class *); +extern int rtnl_htb_set_quantum(struct rtnl_class *, uint32_t); +extern int rtnl_htb_get_level(struct rtnl_class *); #ifdef __cplusplus } diff --git a/lib/route/qdisc/htb.c b/lib/route/qdisc/htb.c index 94185de..4417b8e 100644 --- a/lib/route/qdisc/htb.c +++ b/lib/route/qdisc/htb.c @@ -39,6 +39,7 @@ #define SCH_HTB_HAS_RBUFFER 0x008 #define SCH_HTB_HAS_CBUFFER 0x010 #define SCH_HTB_HAS_QUANTUM 0x020 +#define SCH_HTB_HAS_LEVEL 0x040 /** @endcond */ static struct nla_policy htb_policy[TCA_HTB_MAX+1] = { @@ -61,6 +62,7 @@ static int htb_qdisc_msg_parser(struct rtnl_tc *tc, void *data) nla_memcpy(&opts, tb[TCA_HTB_INIT], sizeof(opts)); htb->qh_rate2quantum = opts.rate2quantum; htb->qh_defcls = opts.defcls; + htb->qh_direct_pkts = opts.direct_pkts; htb->qh_mask = (SCH_HTB_HAS_RATE2QUANTUM | SCH_HTB_HAS_DEFCLS); } @@ -84,16 +86,20 @@ static int htb_class_msg_parser(struct rtnl_tc *tc, void *data) htb->ch_prio = opts.prio; rtnl_copy_ratespec(&htb->ch_rate, &opts.rate); rtnl_copy_ratespec(&htb->ch_ceil, &opts.ceil); - htb->ch_rbuffer = rtnl_tc_calc_bufsize(opts.buffer, opts.rate.rate); - htb->ch_cbuffer = rtnl_tc_calc_bufsize(opts.cbuffer, opts.ceil.rate); + htb->ch_rbuffer = rtnl_tc_calc_bufsize(opts.buffer, + opts.rate.rate); + htb->ch_cbuffer = rtnl_tc_calc_bufsize(opts.cbuffer, + opts.ceil.rate); htb->ch_quantum = opts.quantum; + htb->ch_level = opts.level; rtnl_tc_set_mpu(tc, htb->ch_rate.rs_mpu); rtnl_tc_set_overhead(tc, htb->ch_rate.rs_overhead); htb->ch_mask = (SCH_HTB_HAS_PRIO | SCH_HTB_HAS_RATE | SCH_HTB_HAS_CEIL | SCH_HTB_HAS_RBUFFER | - SCH_HTB_HAS_CBUFFER | SCH_HTB_HAS_QUANTUM); + SCH_HTB_HAS_CBUFFER | SCH_HTB_HAS_QUANTUM | + SCH_HTB_HAS_LEVEL); } return 0; @@ -111,8 +117,8 @@ static void htb_qdisc_dump_line(struct rtnl_tc *tc, void *data, nl_dump(p, " r2q %u", htb->qh_rate2quantum); if (htb->qh_mask & SCH_HTB_HAS_DEFCLS) { - char buf[32]; - nl_dump(p, " default %s", + char buf[64]; + nl_dump(p, " default-class %s", rtnl_tc_handle2str(htb->qh_defcls, buf, sizeof(buf))); } } @@ -260,20 +266,72 @@ nla_put_failure: return -NLE_MSGSIZE; } +static struct rtnl_tc_ops htb_qdisc_ops; +static struct rtnl_tc_ops htb_class_ops; + +static struct rtnl_htb_qdisc *htb_qdisc_data(struct rtnl_qdisc *qdisc) +{ + return rtnl_tc_data_check(TC_CAST(qdisc), &htb_qdisc_ops); +} + +static struct rtnl_htb_class *htb_class_data(struct rtnl_class *class) +{ + return rtnl_tc_data_check(TC_CAST(class), &htb_class_ops); +} + /** * @name Attribute Modifications * @{ */ -void rtnl_htb_set_rate2quantum(struct rtnl_qdisc *qdisc, uint32_t rate2quantum) +/** + * Return rate/quantum ratio of HTB qdisc + * @arg qdisc htb qdisc object + * + * @return rate/quantum ratio or 0 if unspecified + */ +uint32_t rtnl_htb_get_rate2quantum(struct rtnl_qdisc *qdisc) { struct rtnl_htb_qdisc *htb; - if (!(htb = rtnl_tc_data(TC_CAST(qdisc)))) - BUG(); + if ((htb = htb_qdisc_data(qdisc)) && + htb->qh_mask & SCH_HTB_HAS_RATE2QUANTUM) + return htb->qh_rate2quantum; + + return 0; +} + +int rtnl_htb_set_rate2quantum(struct rtnl_qdisc *qdisc, uint32_t rate2quantum) +{ + struct rtnl_htb_qdisc *htb; + + if (!(htb = htb_qdisc_data(qdisc))) + return -NLE_OPNOTSUPP; htb->qh_rate2quantum = rate2quantum; htb->qh_mask |= SCH_HTB_HAS_RATE2QUANTUM; + + return 0; +} + +/** + * Return default class of HTB qdisc + * @arg qdisc htb qdisc object + * + * Returns the classid of the class where all unclassified traffic + * goes to. + * + * @return classid or TC_H_UNSPEC if unspecified. + */ +uint32_t rtnl_htb_get_defcls(struct rtnl_qdisc *qdisc) +{ + struct rtnl_htb_qdisc *htb; + + if ((htb = htb_qdisc_data(qdisc)) && + htb->qh_mask & SCH_HTB_HAS_DEFCLS) + return htb->qh_defcls; + + return TC_H_UNSPEC; } /** @@ -281,70 +339,131 @@ void rtnl_htb_set_rate2quantum(struct rtnl_qdisc *qdisc, uint32_t rate2quantum) * @arg qdisc qdisc to change * @arg defcls new default class */ -void rtnl_htb_set_defcls(struct rtnl_qdisc *qdisc, uint32_t defcls) +int rtnl_htb_set_defcls(struct rtnl_qdisc *qdisc, uint32_t defcls) { struct rtnl_htb_qdisc *htb; - if (!(htb = rtnl_tc_data(TC_CAST(qdisc)))) - BUG(); + if (!(htb = htb_qdisc_data(qdisc))) + return -NLE_OPNOTSUPP; htb->qh_defcls = defcls; htb->qh_mask |= SCH_HTB_HAS_DEFCLS; + + return 0; } -void rtnl_htb_set_prio(struct rtnl_class *class, uint32_t prio) +uint32_t rtnl_htb_get_prio(struct rtnl_class *class) { struct rtnl_htb_class *htb; - if (!(htb = rtnl_tc_data(TC_CAST(class)))) - BUG(); + if ((htb = htb_class_data(class)) && htb->ch_mask & SCH_HTB_HAS_PRIO) + return htb->ch_prio; + + return 0; +} + +int rtnl_htb_set_prio(struct rtnl_class *class, uint32_t prio) +{ + struct rtnl_htb_class *htb; + + if (!(htb = htb_class_data(class))) + return -NLE_OPNOTSUPP; htb->ch_prio = prio; htb->ch_mask |= SCH_HTB_HAS_PRIO; + + return 0; } /** - * Set rate of HTB class. - * @arg class HTB class to be modified. - * @arg rate New rate in bytes per second. + * Return rate of HTB class + * @arg class htb class object + * + * @return Rate in bytes/s or 0 if unspecified. */ -void rtnl_htb_set_rate(struct rtnl_class *class, uint32_t rate) -{ - struct rtnl_htb_class *htb; - - if (!(htb = rtnl_tc_data(TC_CAST(class)))) - BUG(); - - htb->ch_rate.rs_cell_log = UINT8_MAX; /* use default value */ - htb->ch_rate.rs_rate = rate; - htb->ch_mask |= SCH_HTB_HAS_RATE; -} - uint32_t rtnl_htb_get_rate(struct rtnl_class *class) { struct rtnl_htb_class *htb; - if (!(htb = rtnl_tc_data(TC_CAST(class)))) - return 0; + if ((htb = htb_class_data(class)) && htb->ch_mask & SCH_HTB_HAS_RATE) + return htb->ch_rate.rs_rate; - return htb->ch_rate.rs_rate; + return 0; } /** - * Set ceil of HTB class. - * @arg class HTB class to be modified. - * @arg ceil New ceil in bytes per second. + * Set rate of HTB class + * @arg class htb class object + * @arg rate new rate in bytes per second + * + * @return 0 on success or a negative error code. */ -void rtnl_htb_set_ceil(struct rtnl_class *class, uint32_t ceil) +int rtnl_htb_set_rate(struct rtnl_class *class, uint32_t rate) { struct rtnl_htb_class *htb; - if (!(htb = rtnl_tc_data(TC_CAST(class)))) - BUG(); + if (!(htb = htb_class_data(class))) + return -NLE_OPNOTSUPP; + + htb->ch_rate.rs_cell_log = UINT8_MAX; /* use default value */ + htb->ch_rate.rs_rate = rate; + htb->ch_mask |= SCH_HTB_HAS_RATE; + + return 0; +} + +/** + * Return ceil rate of HTB class + * @arg class htb class object + * + * @return Ceil rate in bytes/s or 0 if unspecified + */ +uint32_t rtnl_htb_get_ceil(struct rtnl_class *class) +{ + struct rtnl_htb_class *htb; + + if ((htb = htb_class_data(class)) && htb->ch_mask & SCH_HTB_HAS_CEIL) + return htb->ch_ceil.rs_rate; + + return 0; +} + +/** + * Set ceil rate of HTB class + * @arg class htb class object + * @arg ceil new ceil rate number of bytes per second + * + * @return 0 on success or a negative error code. + */ +int rtnl_htb_set_ceil(struct rtnl_class *class, uint32_t ceil) +{ + struct rtnl_htb_class *htb; + + if (!(htb = htb_class_data(class))) + return -NLE_OPNOTSUPP; htb->ch_ceil.rs_cell_log = UINT8_MAX; /* use default value */ htb->ch_ceil.rs_rate = ceil; htb->ch_mask |= SCH_HTB_HAS_CEIL; + + return 0; +} + +/** + * Return burst buffer size of HTB class + * @arg class htb class object + * + * @return Burst buffer size or 0 if unspecified + */ +uint32_t rtnl_htb_get_rbuffer(struct rtnl_class *class) +{ + struct rtnl_htb_class *htb; + + if ((htb = htb_class_data(class)) && + htb->ch_mask & SCH_HTB_HAS_RBUFFER) + return htb->ch_rbuffer; + + return 0; } /** @@ -352,15 +471,34 @@ void rtnl_htb_set_ceil(struct rtnl_class *class, uint32_t ceil) * @arg class HTB class to be modified. * @arg rbuffer New size in bytes. */ -void rtnl_htb_set_rbuffer(struct rtnl_class *class, uint32_t rbuffer) +int rtnl_htb_set_rbuffer(struct rtnl_class *class, uint32_t rbuffer) { struct rtnl_htb_class *htb; - if (!(htb = rtnl_tc_data(TC_CAST(class)))) - BUG(); + if (!(htb = htb_class_data(class))) + return -NLE_OPNOTSUPP; htb->ch_rbuffer = rbuffer; htb->ch_mask |= SCH_HTB_HAS_RBUFFER; + + return 0; +} + +/** + * Return ceil burst buffer size of HTB class + * @arg class htb class object + * + * @return Ceil burst buffer size or 0 if unspecified + */ +uint32_t rtnl_htb_get_cbuffer(struct rtnl_class *class) +{ + struct rtnl_htb_class *htb; + + if ((htb = htb_class_data(class)) && + htb->ch_mask & SCH_HTB_HAS_CBUFFER) + return htb->ch_cbuffer; + + return 0; } /** @@ -368,31 +506,103 @@ void rtnl_htb_set_rbuffer(struct rtnl_class *class, uint32_t rbuffer) * @arg class HTB class to be modified. * @arg cbuffer New size in bytes. */ -void rtnl_htb_set_cbuffer(struct rtnl_class *class, uint32_t cbuffer) +int rtnl_htb_set_cbuffer(struct rtnl_class *class, uint32_t cbuffer) { struct rtnl_htb_class *htb; - if (!(htb = rtnl_tc_data(TC_CAST(class)))) - BUG(); + if (!(htb = htb_class_data(class))) + return -NLE_OPNOTSUPP; htb->ch_cbuffer = cbuffer; htb->ch_mask |= SCH_HTB_HAS_CBUFFER; + + return 0; } /** - * Set how much bytes to serve from leaf at once of HTB class {use r2q}. - * @arg class HTB class to be modified. - * @arg quantum New size in bytes. + * Return quantum of HTB class + * @arg class htb class object + * + * See XXX[quantum def] + * + * @return Quantum or 0 if unspecified. */ -void rtnl_htb_set_quantum(struct rtnl_class *class, uint32_t quantum) +uint32_t rtnl_htb_get_quantum(struct rtnl_class *class) { struct rtnl_htb_class *htb; - if (!(htb = rtnl_tc_data(TC_CAST(class)))) - BUG(); + if ((htb = htb_class_data(class)) && + htb->ch_mask & SCH_HTB_HAS_QUANTUM) + return htb->ch_quantum; + + return 0; +} + +/** + * Set quantum of HTB class (overwrites value calculated based on r2q) + * @arg class htb class object + * @arg quantum new quantum in number of bytes + * + * See XXX[quantum def] + * + * @return 0 on success or a negative error code. + */ +int rtnl_htb_set_quantum(struct rtnl_class *class, uint32_t quantum) +{ + struct rtnl_htb_class *htb; + + if (!(htb = htb_class_data(class))) + return -NLE_OPNOTSUPP; htb->ch_quantum = quantum; htb->ch_mask |= SCH_HTB_HAS_QUANTUM; + + return 0; +} + +/** + * Return level of HTB class + * @arg class htb class object + * + * Returns the level of the HTB class. Leaf classes are assigned level + * 0, root classes have level (TC_HTB_MAXDEPTH - 1). Interior classes + * have a level of one less than their parent. + * + * @return Level or -NLE_OPNOTSUPP + */ +int rtnl_htb_get_level(struct rtnl_class *class) +{ + struct rtnl_htb_class *htb; + + if ((htb = htb_class_data(class)) && htb->ch_mask & SCH_HTB_HAS_LEVEL) + return htb->ch_level; + + return -NLE_OPNOTSUPP; +} + +/** + * Set level of HTB class + * @arg class htb class object + * @arg level new level of HTB class + * + * Sets the level of a HTB class. Note that changing the level of a HTB + * class does not change the level of its in kernel counterpart. This + * function is provided only to create HTB objects which can be compared + * against or filtered upon. + * + * @return 0 on success or a negative error code. + */ +int rtnl_htb_set_level(struct rtnl_class *class, int level) +{ + struct rtnl_htb_class *htb; + + if (!(htb = htb_class_data(class))) + return -NLE_OPNOTSUPP; + + htb->ch_level = level; + htb->ch_mask |= SCH_HTB_HAS_LEVEL; + + return 0; } /** @} */ From e56eb065b259069407418d2583ee2ee508bf4d70 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 10 Jun 2011 13:55:29 +0200 Subject: [PATCH 048/432] Work on libnl-python Changes too numerous to describe them --- python/netlink/__init__.pyc | Bin 0 -> 133 bytes python/netlink/capi.i | 2 + python/netlink/capi.py | 773 ++ python/netlink/capi.pyc | Bin 0 -> 35688 bytes python/netlink/capi_wrap.c | 9640 ++++++++++++++++++++++++ python/netlink/core.py | 85 +- python/netlink/core.pyc | Bin 0 -> 28503 bytes python/netlink/route/address.py | 4 +- python/netlink/route/capi.i | 61 + python/netlink/route/capi.py | 830 ++ python/netlink/route/capi_wrap.c | 9514 +++++++++++++++++++++++ python/netlink/route/link.py | 39 +- python/netlink/route/links/dummy.py | 9 +- python/netlink/route/links/vlan.py | 4 +- python/netlink/route/qdisc.py | 185 - python/netlink/route/qdisc/__init__.py | 0 python/netlink/route/qdisc/htb.py | 161 + python/netlink/route/tc.py | 457 +- python/netlink/util.py | 33 + python/setup.py | 3 +- 20 files changed, 21477 insertions(+), 323 deletions(-) create mode 100644 python/netlink/__init__.pyc create mode 100644 python/netlink/capi.py create mode 100644 python/netlink/capi.pyc create mode 100644 python/netlink/capi_wrap.c create mode 100644 python/netlink/core.pyc create mode 100644 python/netlink/route/capi.py create mode 100644 python/netlink/route/capi_wrap.c delete mode 100644 python/netlink/route/qdisc.py create mode 100644 python/netlink/route/qdisc/__init__.py create mode 100644 python/netlink/route/qdisc/htb.py diff --git a/python/netlink/__init__.pyc b/python/netlink/__init__.pyc new file mode 100644 index 0000000000000000000000000000000000000000..54d904888e6d141806eac4bbcfe9d7711e3395f3 GIT binary patch literal 133 zcmcckiI?lw*Ezn)3{b!bq#b~`m<33rFfasbfJFQ>fCK{?QLG0P)6dAyP1P?+FVas* zEz{4*Ov=mAFQ_cZ$j{TyOD)OC%*)n~kI&4@EQycT1B!D1wb= (3,0,0): + new_instancemethod = lambda func, inst, cls: _capi.SWIG_PyInstanceMethod_New(func) +else: + from new import instancemethod as new_instancemethod +if version_info >= (2,6,0): + def swig_import_helper(): + from os.path import dirname + import imp + fp = None + try: + fp, pathname, description = imp.find_module('_capi', [dirname(__file__)]) + except ImportError: + import _capi + return _capi + if fp is not None: + try: + _mod = imp.load_module('_capi', fp, pathname, description) + finally: + fp.close() + return _mod + _capi = swig_import_helper() + del swig_import_helper +else: + import _capi +del version_info +try: + _swig_property = property +except NameError: + pass # Python < 2.2 doesn't have 'property'. +def _swig_setattr_nondynamic(self,class_type,name,value,static=1): + if (name == "thisown"): return self.this.own(value) + if (name == "this"): + if type(value).__name__ == 'SwigPyObject': + self.__dict__[name] = value + return + method = class_type.__swig_setmethods__.get(name,None) + if method: return method(self,value) + if (not static) or hasattr(self,name): + self.__dict__[name] = value + else: + raise AttributeError("You cannot add attributes to %s" % self) + +def _swig_setattr(self,class_type,name,value): + return _swig_setattr_nondynamic(self,class_type,name,value,0) + +def _swig_getattr(self,class_type,name): + if (name == "thisown"): return self.this.own() + method = class_type.__swig_getmethods__.get(name,None) + if method: return method(self) + raise AttributeError(name) + +def _swig_repr(self): + try: strthis = "proxy of " + self.this.__repr__() + except: strthis = "" + return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,) + +try: + _object = object + _newclass = 1 +except AttributeError: + class _object : pass + _newclass = 0 + + +def _swig_setattr_nondynamic_method(set): + def set_attr(self,name,value): + if (name == "thisown"): return self.this.own(value) + if hasattr(self,name) or (name == "this"): + set(self,name,value) + else: + raise AttributeError("You cannot add attributes to %s" % self) + return set_attr + + + +def alloc_dump_params(): + return _capi.alloc_dump_params() +alloc_dump_params = _capi.alloc_dump_params + +def free_dump_params(*args): + return _capi.free_dump_params(*args) +free_dump_params = _capi.free_dump_params +NL_DUMP_LINE = _capi.NL_DUMP_LINE +NL_DUMP_DETAILS = _capi.NL_DUMP_DETAILS +NL_DUMP_STATS = _capi.NL_DUMP_STATS +__NL_DUMP_MAX = _capi.__NL_DUMP_MAX +class nl_dump_params(object): + thisown = _swig_property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag') + def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined") + __repr__ = _swig_repr + dp_type = _swig_property(_capi.nl_dump_params_dp_type_get, _capi.nl_dump_params_dp_type_set) + dp_prefix = _swig_property(_capi.nl_dump_params_dp_prefix_get, _capi.nl_dump_params_dp_prefix_set) + dp_print_index = _swig_property(_capi.nl_dump_params_dp_print_index_get, _capi.nl_dump_params_dp_print_index_set) + dp_dump_msgtype = _swig_property(_capi.nl_dump_params_dp_dump_msgtype_get, _capi.nl_dump_params_dp_dump_msgtype_set) + dp_cb = _swig_property(_capi.nl_dump_params_dp_cb_get, _capi.nl_dump_params_dp_cb_set) + dp_nl_cb = _swig_property(_capi.nl_dump_params_dp_nl_cb_get, _capi.nl_dump_params_dp_nl_cb_set) + dp_data = _swig_property(_capi.nl_dump_params_dp_data_get, _capi.nl_dump_params_dp_data_set) + dp_fd = _swig_property(_capi.nl_dump_params_dp_fd_get, _capi.nl_dump_params_dp_fd_set) + dp_buf = _swig_property(_capi.nl_dump_params_dp_buf_get, _capi.nl_dump_params_dp_buf_set) + dp_buflen = _swig_property(_capi.nl_dump_params_dp_buflen_get, _capi.nl_dump_params_dp_buflen_set) + dp_pre_dump = _swig_property(_capi.nl_dump_params_dp_pre_dump_get, _capi.nl_dump_params_dp_pre_dump_set) + dp_ivar = _swig_property(_capi.nl_dump_params_dp_ivar_get, _capi.nl_dump_params_dp_ivar_set) + dp_line = _swig_property(_capi.nl_dump_params_dp_line_get, _capi.nl_dump_params_dp_line_set) + __swig_destroy__ = _capi.delete_nl_dump_params +nl_dump_params_swigregister = _capi.nl_dump_params_swigregister +nl_dump_params_swigregister(nl_dump_params) + + +def nl_geterror(*args): + return _capi.nl_geterror(*args) +nl_geterror = _capi.nl_geterror + +def nl_cancel_down_bytes(*args): + return _capi.nl_cancel_down_bytes(*args) +nl_cancel_down_bytes = _capi.nl_cancel_down_bytes + +def nl_cancel_down_bits(*args): + return _capi.nl_cancel_down_bits(*args) +nl_cancel_down_bits = _capi.nl_cancel_down_bits + +def nl_rate2str(*args): + return _capi.nl_rate2str(*args) +nl_rate2str = _capi.nl_rate2str + +def nl_cancel_down_us(*args): + return _capi.nl_cancel_down_us(*args) +nl_cancel_down_us = _capi.nl_cancel_down_us + +def nl_size2int(*args): + return _capi.nl_size2int(*args) +nl_size2int = _capi.nl_size2int + +def nl_size2str(*args): + return _capi.nl_size2str(*args) +nl_size2str = _capi.nl_size2str + +def nl_prob2int(*args): + return _capi.nl_prob2int(*args) +nl_prob2int = _capi.nl_prob2int + +def nl_get_user_hz(): + return _capi.nl_get_user_hz() +nl_get_user_hz = _capi.nl_get_user_hz + +def nl_us2ticks(*args): + return _capi.nl_us2ticks(*args) +nl_us2ticks = _capi.nl_us2ticks + +def nl_ticks2us(*args): + return _capi.nl_ticks2us(*args) +nl_ticks2us = _capi.nl_ticks2us + +def nl_str2msec(*args): + return _capi.nl_str2msec(*args) +nl_str2msec = _capi.nl_str2msec + +def nl_msec2str(*args): + return _capi.nl_msec2str(*args) +nl_msec2str = _capi.nl_msec2str + +def nl_llproto2str(*args): + return _capi.nl_llproto2str(*args) +nl_llproto2str = _capi.nl_llproto2str + +def nl_str2llproto(*args): + return _capi.nl_str2llproto(*args) +nl_str2llproto = _capi.nl_str2llproto + +def nl_ether_proto2str(*args): + return _capi.nl_ether_proto2str(*args) +nl_ether_proto2str = _capi.nl_ether_proto2str + +def nl_str2ether_proto(*args): + return _capi.nl_str2ether_proto(*args) +nl_str2ether_proto = _capi.nl_str2ether_proto + +def nl_ip_proto2str(*args): + return _capi.nl_ip_proto2str(*args) +nl_ip_proto2str = _capi.nl_ip_proto2str + +def nl_str2ip_proto(*args): + return _capi.nl_str2ip_proto(*args) +nl_str2ip_proto = _capi.nl_str2ip_proto + +def nl_new_line(*args): + return _capi.nl_new_line(*args) +nl_new_line = _capi.nl_new_line + +def nl_dump(*args): + return _capi.nl_dump(*args) +nl_dump = _capi.nl_dump + +def nl_dump_line(*args): + return _capi.nl_dump_line(*args) +nl_dump_line = _capi.nl_dump_line + +def nl_connect(*args): + return _capi.nl_connect(*args) +nl_connect = _capi.nl_connect + +def nl_close(*args): + return _capi.nl_close(*args) +nl_close = _capi.nl_close + +def nl_pickup(*args): + return _capi.nl_pickup(*args) +nl_pickup = _capi.nl_pickup + +def nl_socket_alloc(): + return _capi.nl_socket_alloc() +nl_socket_alloc = _capi.nl_socket_alloc + +def nl_socket_alloc_cb(*args): + return _capi.nl_socket_alloc_cb(*args) +nl_socket_alloc_cb = _capi.nl_socket_alloc_cb + +def nl_socket_free(*args): + return _capi.nl_socket_free(*args) +nl_socket_free = _capi.nl_socket_free + +def nl_socket_get_local_port(*args): + return _capi.nl_socket_get_local_port(*args) +nl_socket_get_local_port = _capi.nl_socket_get_local_port + +def nl_socket_set_local_port(*args): + return _capi.nl_socket_set_local_port(*args) +nl_socket_set_local_port = _capi.nl_socket_set_local_port + +def nl_socket_get_peer_port(*args): + return _capi.nl_socket_get_peer_port(*args) +nl_socket_get_peer_port = _capi.nl_socket_get_peer_port + +def nl_socket_set_peer_port(*args): + return _capi.nl_socket_set_peer_port(*args) +nl_socket_set_peer_port = _capi.nl_socket_set_peer_port + +def nl_socket_get_peer_groups(*args): + return _capi.nl_socket_get_peer_groups(*args) +nl_socket_get_peer_groups = _capi.nl_socket_get_peer_groups + +def nl_socket_set_peer_groups(*args): + return _capi.nl_socket_set_peer_groups(*args) +nl_socket_set_peer_groups = _capi.nl_socket_set_peer_groups + +def nl_socket_set_buffer_size(*args): + return _capi.nl_socket_set_buffer_size(*args) +nl_socket_set_buffer_size = _capi.nl_socket_set_buffer_size + +def nlmsg_size(*args): + return _capi.nlmsg_size(*args) +nlmsg_size = _capi.nlmsg_size + +def nlmsg_total_size(*args): + return _capi.nlmsg_total_size(*args) +nlmsg_total_size = _capi.nlmsg_total_size + +def nlmsg_padlen(*args): + return _capi.nlmsg_padlen(*args) +nlmsg_padlen = _capi.nlmsg_padlen + +def nlmsg_data(*args): + return _capi.nlmsg_data(*args) +nlmsg_data = _capi.nlmsg_data + +def nlmsg_datalen(*args): + return _capi.nlmsg_datalen(*args) +nlmsg_datalen = _capi.nlmsg_datalen + +def nlmsg_tail(*args): + return _capi.nlmsg_tail(*args) +nlmsg_tail = _capi.nlmsg_tail + +def nlmsg_attrdata(*args): + return _capi.nlmsg_attrdata(*args) +nlmsg_attrdata = _capi.nlmsg_attrdata + +def nlmsg_attrlen(*args): + return _capi.nlmsg_attrlen(*args) +nlmsg_attrlen = _capi.nlmsg_attrlen + +def nlmsg_valid_hdr(*args): + return _capi.nlmsg_valid_hdr(*args) +nlmsg_valid_hdr = _capi.nlmsg_valid_hdr + +def nlmsg_ok(*args): + return _capi.nlmsg_ok(*args) +nlmsg_ok = _capi.nlmsg_ok + +def nlmsg_next(*args): + return _capi.nlmsg_next(*args) +nlmsg_next = _capi.nlmsg_next + +def nlmsg_parse(*args): + return _capi.nlmsg_parse(*args) +nlmsg_parse = _capi.nlmsg_parse + +def nlmsg_find_attr(*args): + return _capi.nlmsg_find_attr(*args) +nlmsg_find_attr = _capi.nlmsg_find_attr + +def nlmsg_validate(*args): + return _capi.nlmsg_validate(*args) +nlmsg_validate = _capi.nlmsg_validate + +def nlmsg_alloc(): + return _capi.nlmsg_alloc() +nlmsg_alloc = _capi.nlmsg_alloc + +def nlmsg_alloc_size(*args): + return _capi.nlmsg_alloc_size(*args) +nlmsg_alloc_size = _capi.nlmsg_alloc_size + +def nlmsg_alloc_simple(*args): + return _capi.nlmsg_alloc_simple(*args) +nlmsg_alloc_simple = _capi.nlmsg_alloc_simple + +def nlmsg_set_default_size(*args): + return _capi.nlmsg_set_default_size(*args) +nlmsg_set_default_size = _capi.nlmsg_set_default_size + +def nlmsg_inherit(*args): + return _capi.nlmsg_inherit(*args) +nlmsg_inherit = _capi.nlmsg_inherit + +def nlmsg_convert(*args): + return _capi.nlmsg_convert(*args) +nlmsg_convert = _capi.nlmsg_convert + +def nlmsg_reserve(*args): + return _capi.nlmsg_reserve(*args) +nlmsg_reserve = _capi.nlmsg_reserve + +def nlmsg_append(*args): + return _capi.nlmsg_append(*args) +nlmsg_append = _capi.nlmsg_append + +def nlmsg_expand(*args): + return _capi.nlmsg_expand(*args) +nlmsg_expand = _capi.nlmsg_expand + +def nlmsg_put(*args): + return _capi.nlmsg_put(*args) +nlmsg_put = _capi.nlmsg_put + +def nlmsg_hdr(*args): + return _capi.nlmsg_hdr(*args) +nlmsg_hdr = _capi.nlmsg_hdr + +def nlmsg_get(*args): + return _capi.nlmsg_get(*args) +nlmsg_get = _capi.nlmsg_get + +def nlmsg_free(*args): + return _capi.nlmsg_free(*args) +nlmsg_free = _capi.nlmsg_free + +def nlmsg_set_proto(*args): + return _capi.nlmsg_set_proto(*args) +nlmsg_set_proto = _capi.nlmsg_set_proto + +def nlmsg_get_proto(*args): + return _capi.nlmsg_get_proto(*args) +nlmsg_get_proto = _capi.nlmsg_get_proto + +def nlmsg_get_max_size(*args): + return _capi.nlmsg_get_max_size(*args) +nlmsg_get_max_size = _capi.nlmsg_get_max_size + +def nlmsg_set_src(*args): + return _capi.nlmsg_set_src(*args) +nlmsg_set_src = _capi.nlmsg_set_src + +def nlmsg_get_src(*args): + return _capi.nlmsg_get_src(*args) +nlmsg_get_src = _capi.nlmsg_get_src + +def nlmsg_set_dst(*args): + return _capi.nlmsg_set_dst(*args) +nlmsg_set_dst = _capi.nlmsg_set_dst + +def nlmsg_get_dst(*args): + return _capi.nlmsg_get_dst(*args) +nlmsg_get_dst = _capi.nlmsg_get_dst + +def nlmsg_set_creds(*args): + return _capi.nlmsg_set_creds(*args) +nlmsg_set_creds = _capi.nlmsg_set_creds + +def nlmsg_get_creds(*args): + return _capi.nlmsg_get_creds(*args) +nlmsg_get_creds = _capi.nlmsg_get_creds + +def nl_nlmsgtype2str(*args): + return _capi.nl_nlmsgtype2str(*args) +nl_nlmsgtype2str = _capi.nl_nlmsgtype2str + +def nl_str2nlmsgtype(*args): + return _capi.nl_str2nlmsgtype(*args) +nl_str2nlmsgtype = _capi.nl_str2nlmsgtype + +def nl_nlmsg_flags2str(*args): + return _capi.nl_nlmsg_flags2str(*args) +nl_nlmsg_flags2str = _capi.nl_nlmsg_flags2str + +def nl_msg_parse(*args): + return _capi.nl_msg_parse(*args) +nl_msg_parse = _capi.nl_msg_parse + +def nl_msg_dump(*args): + return _capi.nl_msg_dump(*args) +nl_msg_dump = _capi.nl_msg_dump + +def cast_obj(*args): + return _capi.cast_obj(*args) +cast_obj = _capi.cast_obj + +def object_alloc_name(*args): + return _capi.object_alloc_name(*args) +object_alloc_name = _capi.object_alloc_name + +def nl_object_alloc(*args): + return _capi.nl_object_alloc(*args) +nl_object_alloc = _capi.nl_object_alloc + +def nl_object_free(*args): + return _capi.nl_object_free(*args) +nl_object_free = _capi.nl_object_free + +def nl_object_clone(*args): + return _capi.nl_object_clone(*args) +nl_object_clone = _capi.nl_object_clone + +def nl_object_get(*args): + return _capi.nl_object_get(*args) +nl_object_get = _capi.nl_object_get + +def nl_object_put(*args): + return _capi.nl_object_put(*args) +nl_object_put = _capi.nl_object_put + +def nl_object_shared(*args): + return _capi.nl_object_shared(*args) +nl_object_shared = _capi.nl_object_shared + +def nl_object_dump_buf(*args): + return _capi.nl_object_dump_buf(*args) +nl_object_dump_buf = _capi.nl_object_dump_buf + +def nl_object_dump(*args): + return _capi.nl_object_dump(*args) +nl_object_dump = _capi.nl_object_dump + +def nl_object_identical(*args): + return _capi.nl_object_identical(*args) +nl_object_identical = _capi.nl_object_identical + +def nl_object_diff(*args): + return _capi.nl_object_diff(*args) +nl_object_diff = _capi.nl_object_diff + +def nl_object_match_filter(*args): + return _capi.nl_object_match_filter(*args) +nl_object_match_filter = _capi.nl_object_match_filter + +def nl_object_attrs2str(*args): + return _capi.nl_object_attrs2str(*args) +nl_object_attrs2str = _capi.nl_object_attrs2str + +def nl_object_attr_list(*args): + return _capi.nl_object_attr_list(*args) +nl_object_attr_list = _capi.nl_object_attr_list + +def nl_object_mark(*args): + return _capi.nl_object_mark(*args) +nl_object_mark = _capi.nl_object_mark + +def nl_object_unmark(*args): + return _capi.nl_object_unmark(*args) +nl_object_unmark = _capi.nl_object_unmark + +def nl_object_is_marked(*args): + return _capi.nl_object_is_marked(*args) +nl_object_is_marked = _capi.nl_object_is_marked + +def nl_object_get_refcnt(*args): + return _capi.nl_object_get_refcnt(*args) +nl_object_get_refcnt = _capi.nl_object_get_refcnt + +def alloc_cache_name(*args): + return _capi.alloc_cache_name(*args) +alloc_cache_name = _capi.alloc_cache_name + +def alloc_cache_mngr(*args): + return _capi.alloc_cache_mngr(*args) +alloc_cache_mngr = _capi.alloc_cache_mngr + +def cache_mngr_add(*args): + return _capi.cache_mngr_add(*args) +cache_mngr_add = _capi.cache_mngr_add + +def nl_cache_nitems(*args): + return _capi.nl_cache_nitems(*args) +nl_cache_nitems = _capi.nl_cache_nitems + +def nl_cache_nitems_filter(*args): + return _capi.nl_cache_nitems_filter(*args) +nl_cache_nitems_filter = _capi.nl_cache_nitems_filter + +def nl_cache_get_ops(*args): + return _capi.nl_cache_get_ops(*args) +nl_cache_get_ops = _capi.nl_cache_get_ops + +def nl_cache_get_first(*args): + return _capi.nl_cache_get_first(*args) +nl_cache_get_first = _capi.nl_cache_get_first + +def nl_cache_get_last(*args): + return _capi.nl_cache_get_last(*args) +nl_cache_get_last = _capi.nl_cache_get_last + +def nl_cache_get_next(*args): + return _capi.nl_cache_get_next(*args) +nl_cache_get_next = _capi.nl_cache_get_next + +def nl_cache_get_prev(*args): + return _capi.nl_cache_get_prev(*args) +nl_cache_get_prev = _capi.nl_cache_get_prev + +def nl_cache_alloc(*args): + return _capi.nl_cache_alloc(*args) +nl_cache_alloc = _capi.nl_cache_alloc + +def nl_cache_subset(*args): + return _capi.nl_cache_subset(*args) +nl_cache_subset = _capi.nl_cache_subset + +def nl_cache_clear(*args): + return _capi.nl_cache_clear(*args) +nl_cache_clear = _capi.nl_cache_clear + +def nl_cache_free(*args): + return _capi.nl_cache_free(*args) +nl_cache_free = _capi.nl_cache_free + +def nl_cache_add(*args): + return _capi.nl_cache_add(*args) +nl_cache_add = _capi.nl_cache_add + +def nl_cache_parse_and_add(*args): + return _capi.nl_cache_parse_and_add(*args) +nl_cache_parse_and_add = _capi.nl_cache_parse_and_add + +def nl_cache_remove(*args): + return _capi.nl_cache_remove(*args) +nl_cache_remove = _capi.nl_cache_remove + +def nl_cache_refill(*args): + return _capi.nl_cache_refill(*args) +nl_cache_refill = _capi.nl_cache_refill + +def nl_cache_pickup(*args): + return _capi.nl_cache_pickup(*args) +nl_cache_pickup = _capi.nl_cache_pickup + +def nl_cache_resync(*args): + return _capi.nl_cache_resync(*args) +nl_cache_resync = _capi.nl_cache_resync + +def nl_cache_include(*args): + return _capi.nl_cache_include(*args) +nl_cache_include = _capi.nl_cache_include + +def nl_cache_set_arg1(*args): + return _capi.nl_cache_set_arg1(*args) +nl_cache_set_arg1 = _capi.nl_cache_set_arg1 + +def nl_cache_set_arg2(*args): + return _capi.nl_cache_set_arg2(*args) +nl_cache_set_arg2 = _capi.nl_cache_set_arg2 + +def nl_cache_is_empty(*args): + return _capi.nl_cache_is_empty(*args) +nl_cache_is_empty = _capi.nl_cache_is_empty + +def nl_cache_search(*args): + return _capi.nl_cache_search(*args) +nl_cache_search = _capi.nl_cache_search + +def nl_cache_mark_all(*args): + return _capi.nl_cache_mark_all(*args) +nl_cache_mark_all = _capi.nl_cache_mark_all + +def nl_cache_dump(*args): + return _capi.nl_cache_dump(*args) +nl_cache_dump = _capi.nl_cache_dump + +def nl_cache_dump_filter(*args): + return _capi.nl_cache_dump_filter(*args) +nl_cache_dump_filter = _capi.nl_cache_dump_filter + +def nl_cache_foreach(*args): + return _capi.nl_cache_foreach(*args) +nl_cache_foreach = _capi.nl_cache_foreach + +def nl_cache_foreach_filter(*args): + return _capi.nl_cache_foreach_filter(*args) +nl_cache_foreach_filter = _capi.nl_cache_foreach_filter + +def nl_cache_ops_lookup(*args): + return _capi.nl_cache_ops_lookup(*args) +nl_cache_ops_lookup = _capi.nl_cache_ops_lookup + +def nl_cache_ops_associate(*args): + return _capi.nl_cache_ops_associate(*args) +nl_cache_ops_associate = _capi.nl_cache_ops_associate + +def nl_msgtype_lookup(*args): + return _capi.nl_msgtype_lookup(*args) +nl_msgtype_lookup = _capi.nl_msgtype_lookup + +def nl_cache_ops_foreach(*args): + return _capi.nl_cache_ops_foreach(*args) +nl_cache_ops_foreach = _capi.nl_cache_ops_foreach + +def nl_cache_mngt_register(*args): + return _capi.nl_cache_mngt_register(*args) +nl_cache_mngt_register = _capi.nl_cache_mngt_register + +def nl_cache_mngt_unregister(*args): + return _capi.nl_cache_mngt_unregister(*args) +nl_cache_mngt_unregister = _capi.nl_cache_mngt_unregister + +def nl_cache_mngt_provide(*args): + return _capi.nl_cache_mngt_provide(*args) +nl_cache_mngt_provide = _capi.nl_cache_mngt_provide + +def nl_cache_mngt_unprovide(*args): + return _capi.nl_cache_mngt_unprovide(*args) +nl_cache_mngt_unprovide = _capi.nl_cache_mngt_unprovide + +def nl_cache_mngt_require(*args): + return _capi.nl_cache_mngt_require(*args) +nl_cache_mngt_require = _capi.nl_cache_mngt_require +NL_AUTO_PROVIDE = _capi.NL_AUTO_PROVIDE + +def nl_cache_mngr_get_fd(*args): + return _capi.nl_cache_mngr_get_fd(*args) +nl_cache_mngr_get_fd = _capi.nl_cache_mngr_get_fd + +def nl_cache_mngr_poll(*args): + return _capi.nl_cache_mngr_poll(*args) +nl_cache_mngr_poll = _capi.nl_cache_mngr_poll + +def nl_cache_mngr_data_ready(*args): + return _capi.nl_cache_mngr_data_ready(*args) +nl_cache_mngr_data_ready = _capi.nl_cache_mngr_data_ready + +def nl_cache_mngr_free(*args): + return _capi.nl_cache_mngr_free(*args) +nl_cache_mngr_free = _capi.nl_cache_mngr_free + +def addr_parse(*args): + return _capi.addr_parse(*args) +addr_parse = _capi.addr_parse + +def nl_addr_alloc(*args): + return _capi.nl_addr_alloc(*args) +nl_addr_alloc = _capi.nl_addr_alloc + +def nl_addr_alloc_attr(*args): + return _capi.nl_addr_alloc_attr(*args) +nl_addr_alloc_attr = _capi.nl_addr_alloc_attr + +def nl_addr_build(*args): + return _capi.nl_addr_build(*args) +nl_addr_build = _capi.nl_addr_build + +def nl_addr_clone(*args): + return _capi.nl_addr_clone(*args) +nl_addr_clone = _capi.nl_addr_clone + +def nl_addr_get(*args): + return _capi.nl_addr_get(*args) +nl_addr_get = _capi.nl_addr_get + +def nl_addr_put(*args): + return _capi.nl_addr_put(*args) +nl_addr_put = _capi.nl_addr_put + +def nl_addr_shared(*args): + return _capi.nl_addr_shared(*args) +nl_addr_shared = _capi.nl_addr_shared + +def nl_addr_cmp(*args): + return _capi.nl_addr_cmp(*args) +nl_addr_cmp = _capi.nl_addr_cmp + +def nl_addr_cmp_prefix(*args): + return _capi.nl_addr_cmp_prefix(*args) +nl_addr_cmp_prefix = _capi.nl_addr_cmp_prefix + +def nl_addr_iszero(*args): + return _capi.nl_addr_iszero(*args) +nl_addr_iszero = _capi.nl_addr_iszero + +def nl_addr_valid(*args): + return _capi.nl_addr_valid(*args) +nl_addr_valid = _capi.nl_addr_valid + +def nl_addr_guess_family(*args): + return _capi.nl_addr_guess_family(*args) +nl_addr_guess_family = _capi.nl_addr_guess_family + +def nl_addr_fill_sockaddr(*args): + return _capi.nl_addr_fill_sockaddr(*args) +nl_addr_fill_sockaddr = _capi.nl_addr_fill_sockaddr + +def nl_addr_info(*args): + return _capi.nl_addr_info(*args) +nl_addr_info = _capi.nl_addr_info + +def nl_addr_resolve(*args): + return _capi.nl_addr_resolve(*args) +nl_addr_resolve = _capi.nl_addr_resolve + +def nl_addr_set_family(*args): + return _capi.nl_addr_set_family(*args) +nl_addr_set_family = _capi.nl_addr_set_family + +def nl_addr_get_family(*args): + return _capi.nl_addr_get_family(*args) +nl_addr_get_family = _capi.nl_addr_get_family + +def nl_addr_set_binary_addr(*args): + return _capi.nl_addr_set_binary_addr(*args) +nl_addr_set_binary_addr = _capi.nl_addr_set_binary_addr + +def nl_addr_get_binary_addr(*args): + return _capi.nl_addr_get_binary_addr(*args) +nl_addr_get_binary_addr = _capi.nl_addr_get_binary_addr + +def nl_addr_get_len(*args): + return _capi.nl_addr_get_len(*args) +nl_addr_get_len = _capi.nl_addr_get_len + +def nl_addr_set_prefixlen(*args): + return _capi.nl_addr_set_prefixlen(*args) +nl_addr_set_prefixlen = _capi.nl_addr_set_prefixlen + +def nl_addr_get_prefixlen(*args): + return _capi.nl_addr_get_prefixlen(*args) +nl_addr_get_prefixlen = _capi.nl_addr_get_prefixlen + +def nl_af2str(*args): + return _capi.nl_af2str(*args) +nl_af2str = _capi.nl_af2str + +def nl_str2af(*args): + return _capi.nl_str2af(*args) +nl_str2af = _capi.nl_str2af + +def nl_addr2str(*args): + return _capi.nl_addr2str(*args) +nl_addr2str = _capi.nl_addr2str + + diff --git a/python/netlink/capi.pyc b/python/netlink/capi.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1b366b4ea2c4b4669d3c6c029cf43293aa48db62 GIT binary patch literal 35688 zcmeI5d7Kp0wZ~7-unn6i2q>tdf{uuQxS`^Lf{Ma`1qxo5wx@3m(@aly+g$?;f})_J zqN1Xr;=ZAR;*N?wlb5`h#3Y)S#Ox+7c`=Dej4^xi@_y%6HO!2H5%2wc-ai@aWA(49 zZhiaSbI)CBd*l6ny~i*7()6q(e|_=)@Hz)lx|^-%mWf%cdQt2E-5xw=>891XX?&EOna(a^cj3Z7342IxpqPPT2T~bC zWssP7VOKG`QW-2}Fc*f18N!93Vup&vX8olRdAIAJ4xGhFOYDtl1bL(CpxccZc=l|9AmDRy@%dr{d-%wA%LQK_X;E2dWL za4LIK*;~xsV)vl350!ny>?3whD*IB|SIoX*_o6a_$_Ozd#MV+7NoAy%kz)6zvLBWG z#Ox<_A1eD(*_JqMRn#$2)juv|am5Ed)ikT>O z0+nN^93$o!u}4xlmddeWjum?pmE))!C+0Y@M^ibT%JE{37dw&4Br21{OcHwxl@q9( zAm#+I$5J_w%86o56nh+%$y6qbnJo5rDpROT5i>>XBq}FSIZ4b(Vo#uQGL@6XoGkW4 zDyL96Ma(H;CsUb9WvZB|Vy93!mCC7NP8E9+mD8x4CgwD;CsUb5Wty02Vo#wmoyv4E z)5T7uQctB`Oug7ssm!1{ZEGl!U%oQ_N>})D$ zQ8`P@Sz^ziVyGA~M(mkX&ZcshtDbHtn@b}p53shlh3T(M_SIgiSDV$Kt5 zsHCZ+#iYfaP33$l=ZiUC>^W32R5D^RV$Y@0K&3%UgV^(^WT|AuWW}bbSSnVG6?;CF zkV+^f6q}*aNTpFsqu2&2^Qg=dGf!-mN)wePF->AEl^m6vn4H*<%6uyG#mpDmNTr!d zvzTVF^Qh#hrBSNV)IlkpmKqj z3&gfiDN`wnDT^&osZgnisfaC7iKs+kBC#bZtyEgYw2Hle$^t42#4He7rm~RALNN=) zR;VnZvPjG#u@RLvDs5ug#I{mdOl7f{#bOswxsb|*VlEWBkjfG&OT;V@yNJqCDoe#I z728JTA}SY&xk&6{Di>3^Sj@#@FQl@J$}%y_#4e$736)F4Tq1TUl}o8yD&|tL7g1SG zWx1H;VlSq$g31apE5t6Nav7D Su!5-OKdxm?WUVlSm~1(hqrTp@Njm6cRhidiXk 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 literal 0 HcmV?d00001 diff --git a/python/netlink/capi_wrap.c b/python/netlink/capi_wrap.c new file mode 100644 index 0000000..5027a75 --- /dev/null +++ b/python/netlink/capi_wrap.c @@ -0,0 +1,9640 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 1.3.40 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + +#define SWIGPYTHON +#define SWIG_PYTHON_NO_BUILD_NONE + +/* ----------------------------------------------------------------------------- + * This section contains generic SWIG labels for method/variable + * declarations/attributes, and other compiler dependent labels. + * ----------------------------------------------------------------------------- */ + +/* template workaround for compilers that cannot correctly implement the C++ standard */ +#ifndef SWIGTEMPLATEDISAMBIGUATOR +# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560) +# define SWIGTEMPLATEDISAMBIGUATOR template +# elif defined(__HP_aCC) +/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */ +/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */ +# define SWIGTEMPLATEDISAMBIGUATOR template +# else +# define SWIGTEMPLATEDISAMBIGUATOR +# endif +#endif + +/* inline attribute */ +#ifndef SWIGINLINE +# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__)) +# define SWIGINLINE inline +# else +# define SWIGINLINE +# endif +#endif + +/* attribute recognised by some compilers to avoid 'unused' warnings */ +#ifndef SWIGUNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +# elif defined(__ICC) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +#endif + +#ifndef SWIG_MSC_UNSUPPRESS_4505 +# if defined(_MSC_VER) +# pragma warning(disable : 4505) /* unreferenced local function has been removed */ +# endif +#endif + +#ifndef SWIGUNUSEDPARM +# ifdef __cplusplus +# define SWIGUNUSEDPARM(p) +# else +# define SWIGUNUSEDPARM(p) p SWIGUNUSED +# endif +#endif + +/* internal SWIG method */ +#ifndef SWIGINTERN +# define SWIGINTERN static SWIGUNUSED +#endif + +/* internal inline SWIG method */ +#ifndef SWIGINTERNINLINE +# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE +#endif + +/* exporting methods */ +#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +# ifndef GCC_HASCLASSVISIBILITY +# define GCC_HASCLASSVISIBILITY +# endif +#endif + +#ifndef SWIGEXPORT +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# if defined(STATIC_LINKED) +# define SWIGEXPORT +# else +# define SWIGEXPORT __declspec(dllexport) +# endif +# else +# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY) +# define SWIGEXPORT __attribute__ ((visibility("default"))) +# else +# define SWIGEXPORT +# endif +# endif +#endif + +/* calling conventions for Windows */ +#ifndef SWIGSTDCALL +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# define SWIGSTDCALL __stdcall +# else +# define SWIGSTDCALL +# endif +#endif + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */ +#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE) +# define _SCL_SECURE_NO_DEPRECATE +#endif + + + +/* Python.h has to appear first */ +#include + +/* ----------------------------------------------------------------------------- + * swigrun.swg + * + * This file contains generic C API SWIG runtime support for pointer + * type checking. + * ----------------------------------------------------------------------------- */ + +/* This should only be incremented when either the layout of swig_type_info changes, + or for whatever reason, the runtime changes incompatibly */ +#define SWIG_RUNTIME_VERSION "4" + +/* define SWIG_TYPE_TABLE_NAME as "SWIG_TYPE_TABLE" */ +#ifdef SWIG_TYPE_TABLE +# define SWIG_QUOTE_STRING(x) #x +# define SWIG_EXPAND_AND_QUOTE_STRING(x) SWIG_QUOTE_STRING(x) +# define SWIG_TYPE_TABLE_NAME SWIG_EXPAND_AND_QUOTE_STRING(SWIG_TYPE_TABLE) +#else +# define SWIG_TYPE_TABLE_NAME +#endif + +/* + You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for + creating a static or dynamic library from the SWIG runtime code. + In 99.9% of the cases, SWIG just needs to declare them as 'static'. + + But only do this if strictly necessary, ie, if you have problems + with your compiler or suchlike. +*/ + +#ifndef SWIGRUNTIME +# define SWIGRUNTIME SWIGINTERN +#endif + +#ifndef SWIGRUNTIMEINLINE +# define SWIGRUNTIMEINLINE SWIGRUNTIME SWIGINLINE +#endif + +/* Generic buffer size */ +#ifndef SWIG_BUFFER_SIZE +# define SWIG_BUFFER_SIZE 1024 +#endif + +/* Flags for pointer conversions */ +#define SWIG_POINTER_DISOWN 0x1 +#define SWIG_CAST_NEW_MEMORY 0x2 + +/* Flags for new pointer objects */ +#define SWIG_POINTER_OWN 0x1 + + +/* + Flags/methods for returning states. + + The SWIG conversion methods, as ConvertPtr, return and integer + that tells if the conversion was successful or not. And if not, + an error code can be returned (see swigerrors.swg for the codes). + + Use the following macros/flags to set or process the returning + states. + + In old versions of SWIG, code such as the following was usually written: + + if (SWIG_ConvertPtr(obj,vptr,ty.flags) != -1) { + // success code + } else { + //fail code + } + + Now you can be more explicit: + + int res = SWIG_ConvertPtr(obj,vptr,ty.flags); + if (SWIG_IsOK(res)) { + // success code + } else { + // fail code + } + + which is the same really, but now you can also do + + Type *ptr; + int res = SWIG_ConvertPtr(obj,(void **)(&ptr),ty.flags); + if (SWIG_IsOK(res)) { + // success code + if (SWIG_IsNewObj(res) { + ... + delete *ptr; + } else { + ... + } + } else { + // fail code + } + + I.e., now SWIG_ConvertPtr can return new objects and you can + identify the case and take care of the deallocation. Of course that + also requires SWIG_ConvertPtr to return new result values, such as + + int SWIG_ConvertPtr(obj, ptr,...) { + if () { + if () { + *ptr = ; + return SWIG_NEWOBJ; + } else { + *ptr = ; + return SWIG_OLDOBJ; + } + } else { + return SWIG_BADOBJ; + } + } + + Of course, returning the plain '0(success)/-1(fail)' still works, but you can be + more explicit by returning SWIG_BADOBJ, SWIG_ERROR or any of the + SWIG errors code. + + Finally, if the SWIG_CASTRANK_MODE is enabled, the result code + allows to return the 'cast rank', for example, if you have this + + int food(double) + int fooi(int); + + and you call + + food(1) // cast rank '1' (1 -> 1.0) + fooi(1) // cast rank '0' + + just use the SWIG_AddCast()/SWIG_CheckState() +*/ + +#define SWIG_OK (0) +#define SWIG_ERROR (-1) +#define SWIG_IsOK(r) (r >= 0) +#define SWIG_ArgError(r) ((r != SWIG_ERROR) ? r : SWIG_TypeError) + +/* The CastRankLimit says how many bits are used for the cast rank */ +#define SWIG_CASTRANKLIMIT (1 << 8) +/* The NewMask denotes the object was created (using new/malloc) */ +#define SWIG_NEWOBJMASK (SWIG_CASTRANKLIMIT << 1) +/* The TmpMask is for in/out typemaps that use temporal objects */ +#define SWIG_TMPOBJMASK (SWIG_NEWOBJMASK << 1) +/* Simple returning values */ +#define SWIG_BADOBJ (SWIG_ERROR) +#define SWIG_OLDOBJ (SWIG_OK) +#define SWIG_NEWOBJ (SWIG_OK | SWIG_NEWOBJMASK) +#define SWIG_TMPOBJ (SWIG_OK | SWIG_TMPOBJMASK) +/* Check, add and del mask methods */ +#define SWIG_AddNewMask(r) (SWIG_IsOK(r) ? (r | SWIG_NEWOBJMASK) : r) +#define SWIG_DelNewMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_NEWOBJMASK) : r) +#define SWIG_IsNewObj(r) (SWIG_IsOK(r) && (r & SWIG_NEWOBJMASK)) +#define SWIG_AddTmpMask(r) (SWIG_IsOK(r) ? (r | SWIG_TMPOBJMASK) : r) +#define SWIG_DelTmpMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_TMPOBJMASK) : r) +#define SWIG_IsTmpObj(r) (SWIG_IsOK(r) && (r & SWIG_TMPOBJMASK)) + +/* Cast-Rank Mode */ +#if defined(SWIG_CASTRANK_MODE) +# ifndef SWIG_TypeRank +# define SWIG_TypeRank unsigned long +# endif +# ifndef SWIG_MAXCASTRANK /* Default cast allowed */ +# define SWIG_MAXCASTRANK (2) +# endif +# define SWIG_CASTRANKMASK ((SWIG_CASTRANKLIMIT) -1) +# define SWIG_CastRank(r) (r & SWIG_CASTRANKMASK) +SWIGINTERNINLINE int SWIG_AddCast(int r) { + return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r; +} +SWIGINTERNINLINE int SWIG_CheckState(int r) { + return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0; +} +#else /* no cast-rank mode */ +# define SWIG_AddCast +# define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0) +#endif + + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void *(*swig_converter_func)(void *, int *); +typedef struct swig_type_info *(*swig_dycast_func)(void **); + +/* Structure to store information on one type */ +typedef struct swig_type_info { + const char *name; /* mangled name of this type */ + const char *str; /* human readable name of this type */ + swig_dycast_func dcast; /* dynamic cast function down a hierarchy */ + struct swig_cast_info *cast; /* linked list of types that can cast into this type */ + void *clientdata; /* language specific type data */ + int owndata; /* flag if the structure owns the clientdata */ +} swig_type_info; + +/* Structure to store a type and conversion function used for casting */ +typedef struct swig_cast_info { + swig_type_info *type; /* pointer to type that is equivalent to this type */ + swig_converter_func converter; /* function to cast the void pointers */ + struct swig_cast_info *next; /* pointer to next cast in linked list */ + struct swig_cast_info *prev; /* pointer to the previous cast */ +} swig_cast_info; + +/* Structure used to store module information + * Each module generates one structure like this, and the runtime collects + * all of these structures and stores them in a circularly linked list.*/ +typedef struct swig_module_info { + swig_type_info **types; /* Array of pointers to swig_type_info structures that are in this module */ + size_t size; /* Number of types in this module */ + struct swig_module_info *next; /* Pointer to next element in circularly linked list */ + swig_type_info **type_initial; /* Array of initially generated type structures */ + swig_cast_info **cast_initial; /* Array of initially generated casting structures */ + void *clientdata; /* Language specific module data */ +} swig_module_info; + +/* + Compare two type names skipping the space characters, therefore + "char*" == "char *" and "Class" == "Class", etc. + + Return 0 when the two name types are equivalent, as in + strncmp, but skipping ' '. +*/ +SWIGRUNTIME int +SWIG_TypeNameComp(const char *f1, const char *l1, + const char *f2, const char *l2) { + for (;(f1 != l1) && (f2 != l2); ++f1, ++f2) { + while ((*f1 == ' ') && (f1 != l1)) ++f1; + while ((*f2 == ' ') && (f2 != l2)) ++f2; + if (*f1 != *f2) return (*f1 > *f2) ? 1 : -1; + } + return (int)((l1 - f1) - (l2 - f2)); +} + +/* + Check type equivalence in a name list like ||... + Return 0 if not equal, 1 if equal +*/ +SWIGRUNTIME int +SWIG_TypeEquiv(const char *nb, const char *tb) { + int equiv = 0; + const char* te = tb + strlen(tb); + const char* ne = nb; + while (!equiv && *ne) { + for (nb = ne; *ne; ++ne) { + if (*ne == '|') break; + } + equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0; + if (*ne) ++ne; + } + return equiv; +} + +/* + Check type equivalence in a name list like ||... + Return 0 if equal, -1 if nb < tb, 1 if nb > tb +*/ +SWIGRUNTIME int +SWIG_TypeCompare(const char *nb, const char *tb) { + int equiv = 0; + const char* te = tb + strlen(tb); + const char* ne = nb; + while (!equiv && *ne) { + for (nb = ne; *ne; ++ne) { + if (*ne == '|') break; + } + equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0; + if (*ne) ++ne; + } + return equiv; +} + + +/* + Check the typename +*/ +SWIGRUNTIME swig_cast_info * +SWIG_TypeCheck(const char *c, swig_type_info *ty) { + if (ty) { + swig_cast_info *iter = ty->cast; + while (iter) { + if (strcmp(iter->type->name, c) == 0) { + if (iter == ty->cast) + return iter; + /* Move iter to the top of the linked list */ + iter->prev->next = iter->next; + if (iter->next) + iter->next->prev = iter->prev; + iter->next = ty->cast; + iter->prev = 0; + if (ty->cast) ty->cast->prev = iter; + ty->cast = iter; + return iter; + } + iter = iter->next; + } + } + return 0; +} + +/* + Identical to SWIG_TypeCheck, except strcmp is replaced with a pointer comparison +*/ +SWIGRUNTIME swig_cast_info * +SWIG_TypeCheckStruct(swig_type_info *from, swig_type_info *ty) { + if (ty) { + swig_cast_info *iter = ty->cast; + while (iter) { + if (iter->type == from) { + if (iter == ty->cast) + return iter; + /* Move iter to the top of the linked list */ + iter->prev->next = iter->next; + if (iter->next) + iter->next->prev = iter->prev; + iter->next = ty->cast; + iter->prev = 0; + if (ty->cast) ty->cast->prev = iter; + ty->cast = iter; + return iter; + } + iter = iter->next; + } + } + return 0; +} + +/* + Cast a pointer up an inheritance hierarchy +*/ +SWIGRUNTIMEINLINE void * +SWIG_TypeCast(swig_cast_info *ty, void *ptr, int *newmemory) { + return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr, newmemory); +} + +/* + Dynamic pointer casting. Down an inheritance hierarchy +*/ +SWIGRUNTIME swig_type_info * +SWIG_TypeDynamicCast(swig_type_info *ty, void **ptr) { + swig_type_info *lastty = ty; + if (!ty || !ty->dcast) return ty; + while (ty && (ty->dcast)) { + ty = (*ty->dcast)(ptr); + if (ty) lastty = ty; + } + return lastty; +} + +/* + Return the name associated with this type +*/ +SWIGRUNTIMEINLINE const char * +SWIG_TypeName(const swig_type_info *ty) { + return ty->name; +} + +/* + Return the pretty name associated with this type, + that is an unmangled type name in a form presentable to the user. +*/ +SWIGRUNTIME const char * +SWIG_TypePrettyName(const swig_type_info *type) { + /* The "str" field contains the equivalent pretty names of the + type, separated by vertical-bar characters. We choose + to print the last name, as it is often (?) the most + specific. */ + if (!type) return NULL; + if (type->str != NULL) { + const char *last_name = type->str; + const char *s; + for (s = type->str; *s; s++) + if (*s == '|') last_name = s+1; + return last_name; + } + else + return type->name; +} + +/* + Set the clientdata field for a type +*/ +SWIGRUNTIME void +SWIG_TypeClientData(swig_type_info *ti, void *clientdata) { + swig_cast_info *cast = ti->cast; + /* if (ti->clientdata == clientdata) return; */ + ti->clientdata = clientdata; + + while (cast) { + if (!cast->converter) { + swig_type_info *tc = cast->type; + if (!tc->clientdata) { + SWIG_TypeClientData(tc, clientdata); + } + } + cast = cast->next; + } +} +SWIGRUNTIME void +SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) { + SWIG_TypeClientData(ti, clientdata); + ti->owndata = 1; +} + +/* + Search for a swig_type_info structure only by mangled name + Search is a O(log #types) + + We start searching at module start, and finish searching when start == end. + Note: if start == end at the beginning of the function, we go all the way around + the circular list. +*/ +SWIGRUNTIME swig_type_info * +SWIG_MangledTypeQueryModule(swig_module_info *start, + swig_module_info *end, + const char *name) { + swig_module_info *iter = start; + do { + if (iter->size) { + register size_t l = 0; + register size_t r = iter->size - 1; + do { + /* since l+r >= 0, we can (>> 1) instead (/ 2) */ + register size_t i = (l + r) >> 1; + const char *iname = iter->types[i]->name; + if (iname) { + register int compare = strcmp(name, iname); + if (compare == 0) { + return iter->types[i]; + } else if (compare < 0) { + if (i) { + r = i - 1; + } else { + break; + } + } else if (compare > 0) { + l = i + 1; + } + } else { + break; /* should never happen */ + } + } while (l <= r); + } + iter = iter->next; + } while (iter != end); + return 0; +} + +/* + Search for a swig_type_info structure for either a mangled name or a human readable name. + It first searches the mangled names of the types, which is a O(log #types) + If a type is not found it then searches the human readable names, which is O(#types). + + We start searching at module start, and finish searching when start == end. + Note: if start == end at the beginning of the function, we go all the way around + the circular list. +*/ +SWIGRUNTIME swig_type_info * +SWIG_TypeQueryModule(swig_module_info *start, + swig_module_info *end, + const char *name) { + /* STEP 1: Search the name field using binary search */ + swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name); + if (ret) { + return ret; + } else { + /* STEP 2: If the type hasn't been found, do a complete search + of the str field (the human readable name) */ + swig_module_info *iter = start; + do { + register size_t i = 0; + for (; i < iter->size; ++i) { + if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name))) + return iter->types[i]; + } + iter = iter->next; + } while (iter != end); + } + + /* neither found a match */ + return 0; +} + +/* + Pack binary data into a string +*/ +SWIGRUNTIME char * +SWIG_PackData(char *c, void *ptr, size_t sz) { + static const char hex[17] = "0123456789abcdef"; + register const unsigned char *u = (unsigned char *) ptr; + register const unsigned char *eu = u + sz; + for (; u != eu; ++u) { + register unsigned char uu = *u; + *(c++) = hex[(uu & 0xf0) >> 4]; + *(c++) = hex[uu & 0xf]; + } + return c; +} + +/* + Unpack binary data from a string +*/ +SWIGRUNTIME const char * +SWIG_UnpackData(const char *c, void *ptr, size_t sz) { + register unsigned char *u = (unsigned char *) ptr; + register const unsigned char *eu = u + sz; + for (; u != eu; ++u) { + register char d = *(c++); + register unsigned char uu; + if ((d >= '0') && (d <= '9')) + uu = ((d - '0') << 4); + else if ((d >= 'a') && (d <= 'f')) + uu = ((d - ('a'-10)) << 4); + else + return (char *) 0; + d = *(c++); + if ((d >= '0') && (d <= '9')) + uu |= (d - '0'); + else if ((d >= 'a') && (d <= 'f')) + uu |= (d - ('a'-10)); + else + return (char *) 0; + *u = uu; + } + return c; +} + +/* + Pack 'void *' into a string buffer. +*/ +SWIGRUNTIME char * +SWIG_PackVoidPtr(char *buff, void *ptr, const char *name, size_t bsz) { + char *r = buff; + if ((2*sizeof(void *) + 2) > bsz) return 0; + *(r++) = '_'; + r = SWIG_PackData(r,&ptr,sizeof(void *)); + if (strlen(name) + 1 > (bsz - (r - buff))) return 0; + strcpy(r,name); + return buff; +} + +SWIGRUNTIME const char * +SWIG_UnpackVoidPtr(const char *c, void **ptr, const char *name) { + if (*c != '_') { + if (strcmp(c,"NULL") == 0) { + *ptr = (void *) 0; + return name; + } else { + return 0; + } + } + return SWIG_UnpackData(++c,ptr,sizeof(void *)); +} + +SWIGRUNTIME char * +SWIG_PackDataName(char *buff, void *ptr, size_t sz, const char *name, size_t bsz) { + char *r = buff; + size_t lname = (name ? strlen(name) : 0); + if ((2*sz + 2 + lname) > bsz) return 0; + *(r++) = '_'; + r = SWIG_PackData(r,ptr,sz); + if (lname) { + strncpy(r,name,lname+1); + } else { + *r = 0; + } + return buff; +} + +SWIGRUNTIME const char * +SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) { + if (*c != '_') { + if (strcmp(c,"NULL") == 0) { + memset(ptr,0,sz); + return name; + } else { + return 0; + } + } + return SWIG_UnpackData(++c,ptr,sz); +} + +#ifdef __cplusplus +} +#endif + +/* Errors in SWIG */ +#define SWIG_UnknownError -1 +#define SWIG_IOError -2 +#define SWIG_RuntimeError -3 +#define SWIG_IndexError -4 +#define SWIG_TypeError -5 +#define SWIG_DivisionByZero -6 +#define SWIG_OverflowError -7 +#define SWIG_SyntaxError -8 +#define SWIG_ValueError -9 +#define SWIG_SystemError -10 +#define SWIG_AttributeError -11 +#define SWIG_MemoryError -12 +#define SWIG_NullReferenceError -13 + + + +/* Compatibility macros for Python 3 */ +#if PY_VERSION_HEX >= 0x03000000 + +#define PyClass_Check(obj) PyObject_IsInstance(obj, (PyObject *)&PyType_Type) +#define PyInt_Check(x) PyLong_Check(x) +#define PyInt_AsLong(x) PyLong_AsLong(x) +#define PyInt_FromLong(x) PyLong_FromLong(x) +#define PyString_Format(fmt, args) PyUnicode_Format(fmt, args) + +#endif + +#ifndef Py_TYPE +# define Py_TYPE(op) ((op)->ob_type) +#endif + +/* SWIG APIs for compatibility of both Python 2 & 3 */ + +#if PY_VERSION_HEX >= 0x03000000 +# define SWIG_Python_str_FromFormat PyUnicode_FromFormat +#else +# define SWIG_Python_str_FromFormat PyString_FromFormat +#endif + + +/* Warning: This function will allocate a new string in Python 3, + * so please call SWIG_Python_str_DelForPy3(x) to free the space. + */ +SWIGINTERN char* +SWIG_Python_str_AsChar(PyObject *str) +{ +#if PY_VERSION_HEX >= 0x03000000 + char *cstr; + char *newstr; + Py_ssize_t len; + str = PyUnicode_AsUTF8String(str); + PyBytes_AsStringAndSize(str, &cstr, &len); + newstr = (char *) malloc(len+1); + memcpy(newstr, cstr, len+1); + Py_XDECREF(str); + return newstr; +#else + return PyString_AsString(str); +#endif +} + +#if PY_VERSION_HEX >= 0x03000000 +# define SWIG_Python_str_DelForPy3(x) free( (void*) (x) ) +#else +# define SWIG_Python_str_DelForPy3(x) +#endif + + +SWIGINTERN PyObject* +SWIG_Python_str_FromChar(const char *c) +{ +#if PY_VERSION_HEX >= 0x03000000 + return PyUnicode_FromString(c); +#else + return PyString_FromString(c); +#endif +} + +/* Add PyOS_snprintf for old Pythons */ +#if PY_VERSION_HEX < 0x02020000 +# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WATCOM) +# define PyOS_snprintf _snprintf +# else +# define PyOS_snprintf snprintf +# endif +#endif + +/* A crude PyString_FromFormat implementation for old Pythons */ +#if PY_VERSION_HEX < 0x02020000 + +#ifndef SWIG_PYBUFFER_SIZE +# define SWIG_PYBUFFER_SIZE 1024 +#endif + +static PyObject * +PyString_FromFormat(const char *fmt, ...) { + va_list ap; + char buf[SWIG_PYBUFFER_SIZE * 2]; + int res; + va_start(ap, fmt); + res = vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + return (res < 0 || res >= (int)sizeof(buf)) ? 0 : PyString_FromString(buf); +} +#endif + +/* Add PyObject_Del for old Pythons */ +#if PY_VERSION_HEX < 0x01060000 +# define PyObject_Del(op) PyMem_DEL((op)) +#endif +#ifndef PyObject_DEL +# define PyObject_DEL PyObject_Del +#endif + +/* A crude PyExc_StopIteration exception for old Pythons */ +#if PY_VERSION_HEX < 0x02020000 +# ifndef PyExc_StopIteration +# define PyExc_StopIteration PyExc_RuntimeError +# endif +# ifndef PyObject_GenericGetAttr +# define PyObject_GenericGetAttr 0 +# endif +#endif + +/* Py_NotImplemented is defined in 2.1 and up. */ +#if PY_VERSION_HEX < 0x02010000 +# ifndef Py_NotImplemented +# define Py_NotImplemented PyExc_RuntimeError +# endif +#endif + +/* A crude PyString_AsStringAndSize implementation for old Pythons */ +#if PY_VERSION_HEX < 0x02010000 +# ifndef PyString_AsStringAndSize +# define PyString_AsStringAndSize(obj, s, len) {*s = PyString_AsString(obj); *len = *s ? strlen(*s) : 0;} +# endif +#endif + +/* PySequence_Size for old Pythons */ +#if PY_VERSION_HEX < 0x02000000 +# ifndef PySequence_Size +# define PySequence_Size PySequence_Length +# endif +#endif + +/* PyBool_FromLong for old Pythons */ +#if PY_VERSION_HEX < 0x02030000 +static +PyObject *PyBool_FromLong(long ok) +{ + PyObject *result = ok ? Py_True : Py_False; + Py_INCREF(result); + return result; +} +#endif + +/* Py_ssize_t for old Pythons */ +/* This code is as recommended by: */ +/* http://www.python.org/dev/peps/pep-0353/#conversion-guidelines */ +#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) +typedef int Py_ssize_t; +# define PY_SSIZE_T_MAX INT_MAX +# define PY_SSIZE_T_MIN INT_MIN +#endif + +/* ----------------------------------------------------------------------------- + * error manipulation + * ----------------------------------------------------------------------------- */ + +SWIGRUNTIME PyObject* +SWIG_Python_ErrorType(int code) { + PyObject* type = 0; + switch(code) { + case SWIG_MemoryError: + type = PyExc_MemoryError; + break; + case SWIG_IOError: + type = PyExc_IOError; + break; + case SWIG_RuntimeError: + type = PyExc_RuntimeError; + break; + case SWIG_IndexError: + type = PyExc_IndexError; + break; + case SWIG_TypeError: + type = PyExc_TypeError; + break; + case SWIG_DivisionByZero: + type = PyExc_ZeroDivisionError; + break; + case SWIG_OverflowError: + type = PyExc_OverflowError; + break; + case SWIG_SyntaxError: + type = PyExc_SyntaxError; + break; + case SWIG_ValueError: + type = PyExc_ValueError; + break; + case SWIG_SystemError: + type = PyExc_SystemError; + break; + case SWIG_AttributeError: + type = PyExc_AttributeError; + break; + default: + type = PyExc_RuntimeError; + } + return type; +} + + +SWIGRUNTIME void +SWIG_Python_AddErrorMsg(const char* mesg) +{ + PyObject *type = 0; + PyObject *value = 0; + PyObject *traceback = 0; + + if (PyErr_Occurred()) PyErr_Fetch(&type, &value, &traceback); + if (value) { + char *tmp; + PyObject *old_str = PyObject_Str(value); + PyErr_Clear(); + Py_XINCREF(type); + + PyErr_Format(type, "%s %s", tmp = SWIG_Python_str_AsChar(old_str), mesg); + SWIG_Python_str_DelForPy3(tmp); + Py_DECREF(old_str); + Py_DECREF(value); + } else { + PyErr_SetString(PyExc_RuntimeError, mesg); + } +} + +#if defined(SWIG_PYTHON_NO_THREADS) +# if defined(SWIG_PYTHON_THREADS) +# undef SWIG_PYTHON_THREADS +# endif +#endif +#if defined(SWIG_PYTHON_THREADS) /* Threading support is enabled */ +# if !defined(SWIG_PYTHON_USE_GIL) && !defined(SWIG_PYTHON_NO_USE_GIL) +# if (PY_VERSION_HEX >= 0x02030000) /* For 2.3 or later, use the PyGILState calls */ +# define SWIG_PYTHON_USE_GIL +# endif +# endif +# if defined(SWIG_PYTHON_USE_GIL) /* Use PyGILState threads calls */ +# ifndef SWIG_PYTHON_INITIALIZE_THREADS +# define SWIG_PYTHON_INITIALIZE_THREADS PyEval_InitThreads() +# endif +# ifdef __cplusplus /* C++ code */ + class SWIG_Python_Thread_Block { + bool status; + PyGILState_STATE state; + public: + void end() { if (status) { PyGILState_Release(state); status = false;} } + SWIG_Python_Thread_Block() : status(true), state(PyGILState_Ensure()) {} + ~SWIG_Python_Thread_Block() { end(); } + }; + class SWIG_Python_Thread_Allow { + bool status; + PyThreadState *save; + public: + void end() { if (status) { PyEval_RestoreThread(save); status = false; }} + SWIG_Python_Thread_Allow() : status(true), save(PyEval_SaveThread()) {} + ~SWIG_Python_Thread_Allow() { end(); } + }; +# define SWIG_PYTHON_THREAD_BEGIN_BLOCK SWIG_Python_Thread_Block _swig_thread_block +# define SWIG_PYTHON_THREAD_END_BLOCK _swig_thread_block.end() +# define SWIG_PYTHON_THREAD_BEGIN_ALLOW SWIG_Python_Thread_Allow _swig_thread_allow +# define SWIG_PYTHON_THREAD_END_ALLOW _swig_thread_allow.end() +# else /* C code */ +# define SWIG_PYTHON_THREAD_BEGIN_BLOCK PyGILState_STATE _swig_thread_block = PyGILState_Ensure() +# define SWIG_PYTHON_THREAD_END_BLOCK PyGILState_Release(_swig_thread_block) +# define SWIG_PYTHON_THREAD_BEGIN_ALLOW PyThreadState *_swig_thread_allow = PyEval_SaveThread() +# define SWIG_PYTHON_THREAD_END_ALLOW PyEval_RestoreThread(_swig_thread_allow) +# endif +# else /* Old thread way, not implemented, user must provide it */ +# if !defined(SWIG_PYTHON_INITIALIZE_THREADS) +# define SWIG_PYTHON_INITIALIZE_THREADS +# endif +# if !defined(SWIG_PYTHON_THREAD_BEGIN_BLOCK) +# define SWIG_PYTHON_THREAD_BEGIN_BLOCK +# endif +# if !defined(SWIG_PYTHON_THREAD_END_BLOCK) +# define SWIG_PYTHON_THREAD_END_BLOCK +# endif +# if !defined(SWIG_PYTHON_THREAD_BEGIN_ALLOW) +# define SWIG_PYTHON_THREAD_BEGIN_ALLOW +# endif +# if !defined(SWIG_PYTHON_THREAD_END_ALLOW) +# define SWIG_PYTHON_THREAD_END_ALLOW +# endif +# endif +#else /* No thread support */ +# define SWIG_PYTHON_INITIALIZE_THREADS +# define SWIG_PYTHON_THREAD_BEGIN_BLOCK +# define SWIG_PYTHON_THREAD_END_BLOCK +# define SWIG_PYTHON_THREAD_BEGIN_ALLOW +# define SWIG_PYTHON_THREAD_END_ALLOW +#endif + +/* ----------------------------------------------------------------------------- + * Python API portion that goes into the runtime + * ----------------------------------------------------------------------------- */ + +#ifdef __cplusplus +extern "C" { +#if 0 +} /* cc-mode */ +#endif +#endif + +/* ----------------------------------------------------------------------------- + * Constant declarations + * ----------------------------------------------------------------------------- */ + +/* Constant Types */ +#define SWIG_PY_POINTER 4 +#define SWIG_PY_BINARY 5 + +/* Constant information structure */ +typedef struct swig_const_info { + int type; + char *name; + long lvalue; + double dvalue; + void *pvalue; + swig_type_info **ptype; +} swig_const_info; + + +/* ----------------------------------------------------------------------------- + * Wrapper of PyInstanceMethod_New() used in Python 3 + * It is exported to the generated module, used for -fastproxy + * ----------------------------------------------------------------------------- */ +SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func) +{ +#if PY_VERSION_HEX >= 0x03000000 + return PyInstanceMethod_New(func); +#else + return NULL; +#endif +} + +#ifdef __cplusplus +#if 0 +{ /* cc-mode */ +#endif +} +#endif + + +/* ----------------------------------------------------------------------------- + * See the LICENSE file for information on copyright, usage and redistribution + * of SWIG, and the README file for authors - http://www.swig.org/release.html. + * + * pyrun.swg + * + * This file contains the runtime support for Python modules + * and includes code for managing global variables and pointer + * type checking. + * + * ----------------------------------------------------------------------------- */ + +/* Common SWIG API */ + +/* for raw pointers */ +#define SWIG_Python_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, 0) +#define SWIG_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtr(obj, pptr, type, flags) +#define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, own) +#define SWIG_NewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(ptr, type, flags) +#define SWIG_CheckImplicit(ty) SWIG_Python_CheckImplicit(ty) +#define SWIG_AcquirePtr(ptr, src) SWIG_Python_AcquirePtr(ptr, src) +#define swig_owntype int + +/* for raw packed data */ +#define SWIG_ConvertPacked(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty) +#define SWIG_NewPackedObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type) + +/* for class or struct pointers */ +#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_ConvertPtr(obj, pptr, type, flags) +#define SWIG_NewInstanceObj(ptr, type, flags) SWIG_NewPointerObj(ptr, type, flags) + +/* for C or C++ function pointers */ +#define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_Python_ConvertFunctionPtr(obj, pptr, type) +#define SWIG_NewFunctionPtrObj(ptr, type) SWIG_Python_NewPointerObj(ptr, type, 0) + +/* for C++ member pointers, ie, member methods */ +#define SWIG_ConvertMember(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty) +#define SWIG_NewMemberObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type) + + +/* Runtime API */ + +#define SWIG_GetModule(clientdata) SWIG_Python_GetModule() +#define SWIG_SetModule(clientdata, pointer) SWIG_Python_SetModule(pointer) +#define SWIG_NewClientData(obj) SwigPyClientData_New(obj) + +#define SWIG_SetErrorObj SWIG_Python_SetErrorObj +#define SWIG_SetErrorMsg SWIG_Python_SetErrorMsg +#define SWIG_ErrorType(code) SWIG_Python_ErrorType(code) +#define SWIG_Error(code, msg) SWIG_Python_SetErrorMsg(SWIG_ErrorType(code), msg) +#define SWIG_fail goto fail + + +/* Runtime API implementation */ + +/* Error manipulation */ + +SWIGINTERN void +SWIG_Python_SetErrorObj(PyObject *errtype, PyObject *obj) { + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + PyErr_SetObject(errtype, obj); + Py_DECREF(obj); + SWIG_PYTHON_THREAD_END_BLOCK; +} + +SWIGINTERN void +SWIG_Python_SetErrorMsg(PyObject *errtype, const char *msg) { + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + PyErr_SetString(errtype, (char *) msg); + SWIG_PYTHON_THREAD_END_BLOCK; +} + +#define SWIG_Python_Raise(obj, type, desc) SWIG_Python_SetErrorObj(SWIG_Python_ExceptionType(desc), obj) + +/* Set a constant value */ + +SWIGINTERN void +SWIG_Python_SetConstant(PyObject *d, const char *name, PyObject *obj) { + PyDict_SetItemString(d, (char*) name, obj); + Py_DECREF(obj); +} + +/* Append a value to the result obj */ + +SWIGINTERN PyObject* +SWIG_Python_AppendOutput(PyObject* result, PyObject* obj) { +#if !defined(SWIG_PYTHON_OUTPUT_TUPLE) + if (!result) { + result = obj; + } else if (result == Py_None) { + Py_DECREF(result); + result = obj; + } else { + if (!PyList_Check(result)) { + PyObject *o2 = result; + result = PyList_New(1); + PyList_SetItem(result, 0, o2); + } + PyList_Append(result,obj); + Py_DECREF(obj); + } + return result; +#else + PyObject* o2; + PyObject* o3; + if (!result) { + result = obj; + } else if (result == Py_None) { + Py_DECREF(result); + result = obj; + } else { + if (!PyTuple_Check(result)) { + o2 = result; + result = PyTuple_New(1); + PyTuple_SET_ITEM(result, 0, o2); + } + o3 = PyTuple_New(1); + PyTuple_SET_ITEM(o3, 0, obj); + o2 = result; + result = PySequence_Concat(o2, o3); + Py_DECREF(o2); + Py_DECREF(o3); + } + return result; +#endif +} + +/* Unpack the argument tuple */ + +SWIGINTERN int +SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, PyObject **objs) +{ + if (!args) { + if (!min && !max) { + return 1; + } else { + PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got none", + name, (min == max ? "" : "at least "), (int)min); + return 0; + } + } + if (!PyTuple_Check(args)) { + PyErr_SetString(PyExc_SystemError, "UnpackTuple() argument list is not a tuple"); + return 0; + } else { + register Py_ssize_t l = PyTuple_GET_SIZE(args); + if (l < min) { + PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", + name, (min == max ? "" : "at least "), (int)min, (int)l); + return 0; + } else if (l > max) { + PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", + name, (min == max ? "" : "at most "), (int)max, (int)l); + return 0; + } else { + register int i; + for (i = 0; i < l; ++i) { + objs[i] = PyTuple_GET_ITEM(args, i); + } + for (; l < max; ++l) { + objs[l] = 0; + } + return i + 1; + } + } +} + +/* A functor is a function object with one single object argument */ +#if PY_VERSION_HEX >= 0x02020000 +#define SWIG_Python_CallFunctor(functor, obj) PyObject_CallFunctionObjArgs(functor, obj, NULL); +#else +#define SWIG_Python_CallFunctor(functor, obj) PyObject_CallFunction(functor, "O", obj); +#endif + +/* + Helper for static pointer initialization for both C and C++ code, for example + static PyObject *SWIG_STATIC_POINTER(MyVar) = NewSomething(...); +*/ +#ifdef __cplusplus +#define SWIG_STATIC_POINTER(var) var +#else +#define SWIG_STATIC_POINTER(var) var = 0; if (!var) var +#endif + +/* ----------------------------------------------------------------------------- + * Pointer declarations + * ----------------------------------------------------------------------------- */ + +/* Flags for new pointer objects */ +#define SWIG_POINTER_NOSHADOW (SWIG_POINTER_OWN << 1) +#define SWIG_POINTER_NEW (SWIG_POINTER_NOSHADOW | SWIG_POINTER_OWN) + +#define SWIG_POINTER_IMPLICIT_CONV (SWIG_POINTER_DISOWN << 1) + +#ifdef __cplusplus +extern "C" { +#if 0 +} /* cc-mode */ +#endif +#endif + +/* How to access Py_None */ +#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# ifndef SWIG_PYTHON_NO_BUILD_NONE +# ifndef SWIG_PYTHON_BUILD_NONE +# define SWIG_PYTHON_BUILD_NONE +# endif +# endif +#endif + +#ifdef SWIG_PYTHON_BUILD_NONE +# ifdef Py_None +# undef Py_None +# define Py_None SWIG_Py_None() +# endif +SWIGRUNTIMEINLINE PyObject * +_SWIG_Py_None(void) +{ + PyObject *none = Py_BuildValue((char*)""); + Py_DECREF(none); + return none; +} +SWIGRUNTIME PyObject * +SWIG_Py_None(void) +{ + static PyObject *SWIG_STATIC_POINTER(none) = _SWIG_Py_None(); + return none; +} +#endif + +/* The python void return value */ + +SWIGRUNTIMEINLINE PyObject * +SWIG_Py_Void(void) +{ + PyObject *none = Py_None; + Py_INCREF(none); + return none; +} + +/* SwigPyClientData */ + +typedef struct { + PyObject *klass; + PyObject *newraw; + PyObject *newargs; + PyObject *destroy; + int delargs; + int implicitconv; +} SwigPyClientData; + +SWIGRUNTIMEINLINE int +SWIG_Python_CheckImplicit(swig_type_info *ty) +{ + SwigPyClientData *data = (SwigPyClientData *)ty->clientdata; + return data ? data->implicitconv : 0; +} + +SWIGRUNTIMEINLINE PyObject * +SWIG_Python_ExceptionType(swig_type_info *desc) { + SwigPyClientData *data = desc ? (SwigPyClientData *) desc->clientdata : 0; + PyObject *klass = data ? data->klass : 0; + return (klass ? klass : PyExc_RuntimeError); +} + + +SWIGRUNTIME SwigPyClientData * +SwigPyClientData_New(PyObject* obj) +{ + if (!obj) { + return 0; + } else { + SwigPyClientData *data = (SwigPyClientData *)malloc(sizeof(SwigPyClientData)); + /* the klass element */ + data->klass = obj; + Py_INCREF(data->klass); + /* the newraw method and newargs arguments used to create a new raw instance */ + if (PyClass_Check(obj)) { + data->newraw = 0; + data->newargs = obj; + Py_INCREF(obj); + } else { +#if (PY_VERSION_HEX < 0x02020000) + data->newraw = 0; +#else + data->newraw = PyObject_GetAttrString(data->klass, (char *)"__new__"); +#endif + if (data->newraw) { + Py_INCREF(data->newraw); + data->newargs = PyTuple_New(1); + PyTuple_SetItem(data->newargs, 0, obj); + } else { + data->newargs = obj; + } + Py_INCREF(data->newargs); + } + /* the destroy method, aka as the C++ delete method */ + data->destroy = PyObject_GetAttrString(data->klass, (char *)"__swig_destroy__"); + if (PyErr_Occurred()) { + PyErr_Clear(); + data->destroy = 0; + } + if (data->destroy) { + int flags; + Py_INCREF(data->destroy); + flags = PyCFunction_GET_FLAGS(data->destroy); +#ifdef METH_O + data->delargs = !(flags & (METH_O)); +#else + data->delargs = 0; +#endif + } else { + data->delargs = 0; + } + data->implicitconv = 0; + return data; + } +} + +SWIGRUNTIME void +SwigPyClientData_Del(SwigPyClientData* data) +{ + Py_XDECREF(data->newraw); + Py_XDECREF(data->newargs); + Py_XDECREF(data->destroy); +} + +/* =============== SwigPyObject =====================*/ + +typedef struct { + PyObject_HEAD + void *ptr; + swig_type_info *ty; + int own; + PyObject *next; +} SwigPyObject; + +SWIGRUNTIME PyObject * +SwigPyObject_long(SwigPyObject *v) +{ + return PyLong_FromVoidPtr(v->ptr); +} + +SWIGRUNTIME PyObject * +SwigPyObject_format(const char* fmt, SwigPyObject *v) +{ + PyObject *res = NULL; + PyObject *args = PyTuple_New(1); + if (args) { + if (PyTuple_SetItem(args, 0, SwigPyObject_long(v)) == 0) { + PyObject *ofmt = SWIG_Python_str_FromChar(fmt); + if (ofmt) { +#if PY_VERSION_HEX >= 0x03000000 + res = PyUnicode_Format(ofmt,args); +#else + res = PyString_Format(ofmt,args); +#endif + Py_DECREF(ofmt); + } + Py_DECREF(args); + } + } + return res; +} + +SWIGRUNTIME PyObject * +SwigPyObject_oct(SwigPyObject *v) +{ + return SwigPyObject_format("%o",v); +} + +SWIGRUNTIME PyObject * +SwigPyObject_hex(SwigPyObject *v) +{ + return SwigPyObject_format("%x",v); +} + +SWIGRUNTIME PyObject * +#ifdef METH_NOARGS +SwigPyObject_repr(SwigPyObject *v) +#else +SwigPyObject_repr(SwigPyObject *v, PyObject *args) +#endif +{ + const char *name = SWIG_TypePrettyName(v->ty); + PyObject *repr = SWIG_Python_str_FromFormat("", name, v); + if (v->next) { +#ifdef METH_NOARGS + PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next); +#else + PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next, args); +#endif +#if PY_VERSION_HEX >= 0x03000000 + PyObject *joined = PyUnicode_Concat(repr, nrep); + Py_DecRef(repr); + Py_DecRef(nrep); + repr = joined; +#else + PyString_ConcatAndDel(&repr,nrep); +#endif + } + return repr; +} + +SWIGRUNTIME int +SwigPyObject_print(SwigPyObject *v, FILE *fp, int SWIGUNUSEDPARM(flags)) +{ + char *str; +#ifdef METH_NOARGS + PyObject *repr = SwigPyObject_repr(v); +#else + PyObject *repr = SwigPyObject_repr(v, NULL); +#endif + if (repr) { + str = SWIG_Python_str_AsChar(repr); + fputs(str, fp); + SWIG_Python_str_DelForPy3(str); + Py_DECREF(repr); + return 0; + } else { + return 1; + } +} + +SWIGRUNTIME PyObject * +SwigPyObject_str(SwigPyObject *v) +{ + char result[SWIG_BUFFER_SIZE]; + return SWIG_PackVoidPtr(result, v->ptr, v->ty->name, sizeof(result)) ? + SWIG_Python_str_FromChar(result) : 0; +} + +SWIGRUNTIME int +SwigPyObject_compare(SwigPyObject *v, SwigPyObject *w) +{ + void *i = v->ptr; + void *j = w->ptr; + return (i < j) ? -1 : ((i > j) ? 1 : 0); +} + +/* Added for Python 3.x, would it also be useful for Python 2.x? */ +SWIGRUNTIME PyObject* +SwigPyObject_richcompare(SwigPyObject *v, SwigPyObject *w, int op) +{ + PyObject* res; + if( op != Py_EQ && op != Py_NE ) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + if( (SwigPyObject_compare(v, w)==0) == (op == Py_EQ) ) + res = Py_True; + else + res = Py_False; + Py_INCREF(res); + return res; +} + + +SWIGRUNTIME PyTypeObject* _PySwigObject_type(void); + +SWIGRUNTIME PyTypeObject* +SwigPyObject_type(void) { + static PyTypeObject *SWIG_STATIC_POINTER(type) = _PySwigObject_type(); + return type; +} + +SWIGRUNTIMEINLINE int +SwigPyObject_Check(PyObject *op) { + return (Py_TYPE(op) == SwigPyObject_type()) + || (strcmp(Py_TYPE(op)->tp_name,"SwigPyObject") == 0); +} + +SWIGRUNTIME PyObject * +SwigPyObject_New(void *ptr, swig_type_info *ty, int own); + +SWIGRUNTIME void +SwigPyObject_dealloc(PyObject *v) +{ + SwigPyObject *sobj = (SwigPyObject *) v; + PyObject *next = sobj->next; + if (sobj->own == SWIG_POINTER_OWN) { + swig_type_info *ty = sobj->ty; + SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0; + PyObject *destroy = data ? data->destroy : 0; + if (destroy) { + /* destroy is always a VARARGS method */ + PyObject *res; + if (data->delargs) { + /* we need to create a temporary object to carry the destroy operation */ + PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0); + res = SWIG_Python_CallFunctor(destroy, tmp); + Py_DECREF(tmp); + } else { + PyCFunction meth = PyCFunction_GET_FUNCTION(destroy); + PyObject *mself = PyCFunction_GET_SELF(destroy); + res = ((*meth)(mself, v)); + } + Py_XDECREF(res); + } +#if !defined(SWIG_PYTHON_SILENT_MEMLEAK) + else { + const char *name = SWIG_TypePrettyName(ty); + printf("swig/python detected a memory leak of type '%s', no destructor found.\n", (name ? name : "unknown")); + } +#endif + } + Py_XDECREF(next); + PyObject_DEL(v); +} + +SWIGRUNTIME PyObject* +SwigPyObject_append(PyObject* v, PyObject* next) +{ + SwigPyObject *sobj = (SwigPyObject *) v; +#ifndef METH_O + PyObject *tmp = 0; + if (!PyArg_ParseTuple(next,(char *)"O:append", &tmp)) return NULL; + next = tmp; +#endif + if (!SwigPyObject_Check(next)) { + return NULL; + } + sobj->next = next; + Py_INCREF(next); + return SWIG_Py_Void(); +} + +SWIGRUNTIME PyObject* +#ifdef METH_NOARGS +SwigPyObject_next(PyObject* v) +#else +SwigPyObject_next(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) +#endif +{ + SwigPyObject *sobj = (SwigPyObject *) v; + if (sobj->next) { + Py_INCREF(sobj->next); + return sobj->next; + } else { + return SWIG_Py_Void(); + } +} + +SWIGINTERN PyObject* +#ifdef METH_NOARGS +SwigPyObject_disown(PyObject *v) +#else +SwigPyObject_disown(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) +#endif +{ + SwigPyObject *sobj = (SwigPyObject *)v; + sobj->own = 0; + return SWIG_Py_Void(); +} + +SWIGINTERN PyObject* +#ifdef METH_NOARGS +SwigPyObject_acquire(PyObject *v) +#else +SwigPyObject_acquire(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) +#endif +{ + SwigPyObject *sobj = (SwigPyObject *)v; + sobj->own = SWIG_POINTER_OWN; + return SWIG_Py_Void(); +} + +SWIGINTERN PyObject* +SwigPyObject_own(PyObject *v, PyObject *args) +{ + PyObject *val = 0; +#if (PY_VERSION_HEX < 0x02020000) + if (!PyArg_ParseTuple(args,(char *)"|O:own",&val)) +#else + if (!PyArg_UnpackTuple(args, (char *)"own", 0, 1, &val)) +#endif + { + return NULL; + } + else + { + SwigPyObject *sobj = (SwigPyObject *)v; + PyObject *obj = PyBool_FromLong(sobj->own); + if (val) { +#ifdef METH_NOARGS + if (PyObject_IsTrue(val)) { + SwigPyObject_acquire(v); + } else { + SwigPyObject_disown(v); + } +#else + if (PyObject_IsTrue(val)) { + SwigPyObject_acquire(v,args); + } else { + SwigPyObject_disown(v,args); + } +#endif + } + return obj; + } +} + +#ifdef METH_O +static PyMethodDef +swigobject_methods[] = { + {(char *)"disown", (PyCFunction)SwigPyObject_disown, METH_NOARGS, (char *)"releases ownership of the pointer"}, + {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_NOARGS, (char *)"aquires ownership of the pointer"}, + {(char *)"own", (PyCFunction)SwigPyObject_own, METH_VARARGS, (char *)"returns/sets ownership of the pointer"}, + {(char *)"append", (PyCFunction)SwigPyObject_append, METH_O, (char *)"appends another 'this' object"}, + {(char *)"next", (PyCFunction)SwigPyObject_next, METH_NOARGS, (char *)"returns the next 'this' object"}, + {(char *)"__repr__",(PyCFunction)SwigPyObject_repr, METH_NOARGS, (char *)"returns object representation"}, + {0, 0, 0, 0} +}; +#else +static PyMethodDef +swigobject_methods[] = { + {(char *)"disown", (PyCFunction)SwigPyObject_disown, METH_VARARGS, (char *)"releases ownership of the pointer"}, + {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_VARARGS, (char *)"aquires ownership of the pointer"}, + {(char *)"own", (PyCFunction)SwigPyObject_own, METH_VARARGS, (char *)"returns/sets ownership of the pointer"}, + {(char *)"append", (PyCFunction)SwigPyObject_append, METH_VARARGS, (char *)"appends another 'this' object"}, + {(char *)"next", (PyCFunction)SwigPyObject_next, METH_VARARGS, (char *)"returns the next 'this' object"}, + {(char *)"__repr__",(PyCFunction)SwigPyObject_repr, METH_VARARGS, (char *)"returns object representation"}, + {0, 0, 0, 0} +}; +#endif + +#if PY_VERSION_HEX < 0x02020000 +SWIGINTERN PyObject * +SwigPyObject_getattr(SwigPyObject *sobj,char *name) +{ + return Py_FindMethod(swigobject_methods, (PyObject *)sobj, name); +} +#endif + +SWIGRUNTIME PyTypeObject* +_PySwigObject_type(void) { + static char swigobject_doc[] = "Swig object carries a C/C++ instance pointer"; + + static PyNumberMethods SwigPyObject_as_number = { + (binaryfunc)0, /*nb_add*/ + (binaryfunc)0, /*nb_subtract*/ + (binaryfunc)0, /*nb_multiply*/ + /* nb_divide removed in Python 3 */ +#if PY_VERSION_HEX < 0x03000000 + (binaryfunc)0, /*nb_divide*/ +#endif + (binaryfunc)0, /*nb_remainder*/ + (binaryfunc)0, /*nb_divmod*/ + (ternaryfunc)0,/*nb_power*/ + (unaryfunc)0, /*nb_negative*/ + (unaryfunc)0, /*nb_positive*/ + (unaryfunc)0, /*nb_absolute*/ + (inquiry)0, /*nb_nonzero*/ + 0, /*nb_invert*/ + 0, /*nb_lshift*/ + 0, /*nb_rshift*/ + 0, /*nb_and*/ + 0, /*nb_xor*/ + 0, /*nb_or*/ +#if PY_VERSION_HEX < 0x03000000 + 0, /*nb_coerce*/ +#endif + (unaryfunc)SwigPyObject_long, /*nb_int*/ +#if PY_VERSION_HEX < 0x03000000 + (unaryfunc)SwigPyObject_long, /*nb_long*/ +#else + 0, /*nb_reserved*/ +#endif + (unaryfunc)0, /*nb_float*/ +#if PY_VERSION_HEX < 0x03000000 + (unaryfunc)SwigPyObject_oct, /*nb_oct*/ + (unaryfunc)SwigPyObject_hex, /*nb_hex*/ +#endif +#if PY_VERSION_HEX >= 0x03000000 /* 3.0 */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index, nb_inplace_divide removed */ +#elif PY_VERSION_HEX >= 0x02050000 /* 2.5.0 */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index */ +#elif PY_VERSION_HEX >= 0x02020000 /* 2.2.0 */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_true_divide */ +#elif PY_VERSION_HEX >= 0x02000000 /* 2.0.0 */ + 0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_or */ +#endif + }; + + static PyTypeObject swigpyobject_type; + static int type_init = 0; + if (!type_init) { + const PyTypeObject tmp + = { + /* PyObject header changed in Python 3 */ +#if PY_VERSION_HEX >= 0x03000000 + PyVarObject_HEAD_INIT(&PyType_Type, 0) +#else + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ +#endif + (char *)"SwigPyObject", /* tp_name */ + sizeof(SwigPyObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)SwigPyObject_dealloc, /* tp_dealloc */ + (printfunc)SwigPyObject_print, /* tp_print */ +#if PY_VERSION_HEX < 0x02020000 + (getattrfunc)SwigPyObject_getattr, /* tp_getattr */ +#else + (getattrfunc)0, /* tp_getattr */ +#endif + (setattrfunc)0, /* tp_setattr */ +#if PY_VERSION_HEX >= 0x03000000 + 0, /* tp_reserved in 3.0.1, tp_compare in 3.0.0 but not used */ +#else + (cmpfunc)SwigPyObject_compare, /* tp_compare */ +#endif + (reprfunc)SwigPyObject_repr, /* tp_repr */ + &SwigPyObject_as_number, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + (hashfunc)0, /* tp_hash */ + (ternaryfunc)0, /* tp_call */ + (reprfunc)SwigPyObject_str, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + swigobject_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + (richcmpfunc)SwigPyObject_richcompare, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ +#if PY_VERSION_HEX >= 0x02020000 + 0, /* tp_iter */ + 0, /* tp_iternext */ + swigobject_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ + 0, /* tp_mro */ + 0, /* tp_cache */ + 0, /* tp_subclasses */ + 0, /* tp_weaklist */ +#endif +#if PY_VERSION_HEX >= 0x02030000 + 0, /* tp_del */ +#endif +#ifdef COUNT_ALLOCS + 0,0,0,0 /* tp_alloc -> tp_next */ +#endif + }; + swigpyobject_type = tmp; + /* for Python 3 we already assigned ob_type in PyVarObject_HEAD_INIT() */ +#if PY_VERSION_HEX < 0x03000000 + swigpyobject_type.ob_type = &PyType_Type; +#endif + type_init = 1; + } + return &swigpyobject_type; +} + +SWIGRUNTIME PyObject * +SwigPyObject_New(void *ptr, swig_type_info *ty, int own) +{ + SwigPyObject *sobj = PyObject_NEW(SwigPyObject, SwigPyObject_type()); + if (sobj) { + sobj->ptr = ptr; + sobj->ty = ty; + sobj->own = own; + sobj->next = 0; + } + return (PyObject *)sobj; +} + +/* ----------------------------------------------------------------------------- + * Implements a simple Swig Packed type, and use it instead of string + * ----------------------------------------------------------------------------- */ + +typedef struct { + PyObject_HEAD + void *pack; + swig_type_info *ty; + size_t size; +} SwigPyPacked; + +SWIGRUNTIME int +SwigPyPacked_print(SwigPyPacked *v, FILE *fp, int SWIGUNUSEDPARM(flags)) +{ + char result[SWIG_BUFFER_SIZE]; + fputs("pack, v->size, 0, sizeof(result))) { + fputs("at ", fp); + fputs(result, fp); + } + fputs(v->ty->name,fp); + fputs(">", fp); + return 0; +} + +SWIGRUNTIME PyObject * +SwigPyPacked_repr(SwigPyPacked *v) +{ + char result[SWIG_BUFFER_SIZE]; + if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))) { + return SWIG_Python_str_FromFormat("", result, v->ty->name); + } else { + return SWIG_Python_str_FromFormat("", v->ty->name); + } +} + +SWIGRUNTIME PyObject * +SwigPyPacked_str(SwigPyPacked *v) +{ + char result[SWIG_BUFFER_SIZE]; + if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))){ + return SWIG_Python_str_FromFormat("%s%s", result, v->ty->name); + } else { + return SWIG_Python_str_FromChar(v->ty->name); + } +} + +SWIGRUNTIME int +SwigPyPacked_compare(SwigPyPacked *v, SwigPyPacked *w) +{ + size_t i = v->size; + size_t j = w->size; + int s = (i < j) ? -1 : ((i > j) ? 1 : 0); + return s ? s : strncmp((char *)v->pack, (char *)w->pack, 2*v->size); +} + +SWIGRUNTIME PyTypeObject* _PySwigPacked_type(void); + +SWIGRUNTIME PyTypeObject* +SwigPyPacked_type(void) { + static PyTypeObject *SWIG_STATIC_POINTER(type) = _PySwigPacked_type(); + return type; +} + +SWIGRUNTIMEINLINE int +SwigPyPacked_Check(PyObject *op) { + return ((op)->ob_type == _PySwigPacked_type()) + || (strcmp((op)->ob_type->tp_name,"SwigPyPacked") == 0); +} + +SWIGRUNTIME void +SwigPyPacked_dealloc(PyObject *v) +{ + if (SwigPyPacked_Check(v)) { + SwigPyPacked *sobj = (SwigPyPacked *) v; + free(sobj->pack); + } + PyObject_DEL(v); +} + +SWIGRUNTIME PyTypeObject* +_PySwigPacked_type(void) { + static char swigpacked_doc[] = "Swig object carries a C/C++ instance pointer"; + static PyTypeObject swigpypacked_type; + static int type_init = 0; + if (!type_init) { + const PyTypeObject tmp + = { + /* PyObject header changed in Python 3 */ +#if PY_VERSION_HEX>=0x03000000 + PyVarObject_HEAD_INIT(&PyType_Type, 0) +#else + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ +#endif + (char *)"SwigPyPacked", /* tp_name */ + sizeof(SwigPyPacked), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)SwigPyPacked_dealloc, /* tp_dealloc */ + (printfunc)SwigPyPacked_print, /* tp_print */ + (getattrfunc)0, /* tp_getattr */ + (setattrfunc)0, /* tp_setattr */ +#if PY_VERSION_HEX>=0x03000000 + 0, /* tp_reserved in 3.0.1 */ +#else + (cmpfunc)SwigPyPacked_compare, /* tp_compare */ +#endif + (reprfunc)SwigPyPacked_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + (hashfunc)0, /* tp_hash */ + (ternaryfunc)0, /* tp_call */ + (reprfunc)SwigPyPacked_str, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + swigpacked_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ +#if PY_VERSION_HEX >= 0x02020000 + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ + 0, /* tp_mro */ + 0, /* tp_cache */ + 0, /* tp_subclasses */ + 0, /* tp_weaklist */ +#endif +#if PY_VERSION_HEX >= 0x02030000 + 0, /* tp_del */ +#endif +#ifdef COUNT_ALLOCS + 0,0,0,0 /* tp_alloc -> tp_next */ +#endif + }; + swigpypacked_type = tmp; + /* for Python 3 the ob_type already assigned in PyVarObject_HEAD_INIT() */ +#if PY_VERSION_HEX < 0x03000000 + swigpypacked_type.ob_type = &PyType_Type; +#endif + type_init = 1; + } + return &swigpypacked_type; +} + +SWIGRUNTIME PyObject * +SwigPyPacked_New(void *ptr, size_t size, swig_type_info *ty) +{ + SwigPyPacked *sobj = PyObject_NEW(SwigPyPacked, SwigPyPacked_type()); + if (sobj) { + void *pack = malloc(size); + if (pack) { + memcpy(pack, ptr, size); + sobj->pack = pack; + sobj->ty = ty; + sobj->size = size; + } else { + PyObject_DEL((PyObject *) sobj); + sobj = 0; + } + } + return (PyObject *) sobj; +} + +SWIGRUNTIME swig_type_info * +SwigPyPacked_UnpackData(PyObject *obj, void *ptr, size_t size) +{ + if (SwigPyPacked_Check(obj)) { + SwigPyPacked *sobj = (SwigPyPacked *)obj; + if (sobj->size != size) return 0; + memcpy(ptr, sobj->pack, size); + return sobj->ty; + } else { + return 0; + } +} + +/* ----------------------------------------------------------------------------- + * pointers/data manipulation + * ----------------------------------------------------------------------------- */ + +SWIGRUNTIMEINLINE PyObject * +_SWIG_This(void) +{ + return SWIG_Python_str_FromChar("this"); +} + +SWIGRUNTIME PyObject * +SWIG_This(void) +{ + static PyObject *SWIG_STATIC_POINTER(swig_this) = _SWIG_This(); + return swig_this; +} + +/* #define SWIG_PYTHON_SLOW_GETSET_THIS */ + +/* TODO: I don't know how to implement the fast getset in Python 3 right now */ +#if PY_VERSION_HEX>=0x03000000 +#define SWIG_PYTHON_SLOW_GETSET_THIS +#endif + +SWIGRUNTIME SwigPyObject * +SWIG_Python_GetSwigThis(PyObject *pyobj) +{ + if (SwigPyObject_Check(pyobj)) { + return (SwigPyObject *) pyobj; + } else { + PyObject *obj = 0; +#if (!defined(SWIG_PYTHON_SLOW_GETSET_THIS) && (PY_VERSION_HEX >= 0x02030000)) + if (PyInstance_Check(pyobj)) { + obj = _PyInstance_Lookup(pyobj, SWIG_This()); + } else { + PyObject **dictptr = _PyObject_GetDictPtr(pyobj); + if (dictptr != NULL) { + PyObject *dict = *dictptr; + obj = dict ? PyDict_GetItem(dict, SWIG_This()) : 0; + } else { +#ifdef PyWeakref_CheckProxy + if (PyWeakref_CheckProxy(pyobj)) { + PyObject *wobj = PyWeakref_GET_OBJECT(pyobj); + return wobj ? SWIG_Python_GetSwigThis(wobj) : 0; + } +#endif + obj = PyObject_GetAttr(pyobj,SWIG_This()); + if (obj) { + Py_DECREF(obj); + } else { + if (PyErr_Occurred()) PyErr_Clear(); + return 0; + } + } + } +#else + obj = PyObject_GetAttr(pyobj,SWIG_This()); + if (obj) { + Py_DECREF(obj); + } else { + if (PyErr_Occurred()) PyErr_Clear(); + return 0; + } +#endif + if (obj && !SwigPyObject_Check(obj)) { + /* a PyObject is called 'this', try to get the 'real this' + SwigPyObject from it */ + return SWIG_Python_GetSwigThis(obj); + } + return (SwigPyObject *)obj; + } +} + +/* Acquire a pointer value */ + +SWIGRUNTIME int +SWIG_Python_AcquirePtr(PyObject *obj, int own) { + if (own == SWIG_POINTER_OWN) { + SwigPyObject *sobj = SWIG_Python_GetSwigThis(obj); + if (sobj) { + int oldown = sobj->own; + sobj->own = own; + return oldown; + } + } + return 0; +} + +/* Convert a pointer value */ + +SWIGRUNTIME int +SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int flags, int *own) { + if (!obj) return SWIG_ERROR; + if (obj == Py_None) { + if (ptr) *ptr = 0; + return SWIG_OK; + } else { + SwigPyObject *sobj = SWIG_Python_GetSwigThis(obj); + if (own) + *own = 0; + while (sobj) { + void *vptr = sobj->ptr; + if (ty) { + swig_type_info *to = sobj->ty; + if (to == ty) { + /* no type cast needed */ + if (ptr) *ptr = vptr; + break; + } else { + swig_cast_info *tc = SWIG_TypeCheck(to->name,ty); + if (!tc) { + sobj = (SwigPyObject *)sobj->next; + } else { + if (ptr) { + int newmemory = 0; + *ptr = SWIG_TypeCast(tc,vptr,&newmemory); + if (newmemory == SWIG_CAST_NEW_MEMORY) { + assert(own); + if (own) + *own = *own | SWIG_CAST_NEW_MEMORY; + } + } + break; + } + } + } else { + if (ptr) *ptr = vptr; + break; + } + } + if (sobj) { + if (own) + *own = *own | sobj->own; + if (flags & SWIG_POINTER_DISOWN) { + sobj->own = 0; + } + return SWIG_OK; + } else { + int res = SWIG_ERROR; + if (flags & SWIG_POINTER_IMPLICIT_CONV) { + SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0; + if (data && !data->implicitconv) { + PyObject *klass = data->klass; + if (klass) { + PyObject *impconv; + data->implicitconv = 1; /* avoid recursion and call 'explicit' constructors*/ + impconv = SWIG_Python_CallFunctor(klass, obj); + data->implicitconv = 0; + if (PyErr_Occurred()) { + PyErr_Clear(); + impconv = 0; + } + if (impconv) { + SwigPyObject *iobj = SWIG_Python_GetSwigThis(impconv); + if (iobj) { + void *vptr; + res = SWIG_Python_ConvertPtrAndOwn((PyObject*)iobj, &vptr, ty, 0, 0); + if (SWIG_IsOK(res)) { + if (ptr) { + *ptr = vptr; + /* transfer the ownership to 'ptr' */ + iobj->own = 0; + res = SWIG_AddCast(res); + res = SWIG_AddNewMask(res); + } else { + res = SWIG_AddCast(res); + } + } + } + Py_DECREF(impconv); + } + } + } + } + return res; + } + } +} + +/* Convert a function ptr value */ + +SWIGRUNTIME int +SWIG_Python_ConvertFunctionPtr(PyObject *obj, void **ptr, swig_type_info *ty) { + if (!PyCFunction_Check(obj)) { + return SWIG_ConvertPtr(obj, ptr, ty, 0); + } else { + void *vptr = 0; + + /* here we get the method pointer for callbacks */ + const char *doc = (((PyCFunctionObject *)obj) -> m_ml -> ml_doc); + const char *desc = doc ? strstr(doc, "swig_ptr: ") : 0; + if (desc) + desc = ty ? SWIG_UnpackVoidPtr(desc + 10, &vptr, ty->name) : 0; + if (!desc) + return SWIG_ERROR; + if (ty) { + swig_cast_info *tc = SWIG_TypeCheck(desc,ty); + if (tc) { + int newmemory = 0; + *ptr = SWIG_TypeCast(tc,vptr,&newmemory); + assert(!newmemory); /* newmemory handling not yet implemented */ + } else { + return SWIG_ERROR; + } + } else { + *ptr = vptr; + } + return SWIG_OK; + } +} + +/* Convert a packed value value */ + +SWIGRUNTIME int +SWIG_Python_ConvertPacked(PyObject *obj, void *ptr, size_t sz, swig_type_info *ty) { + swig_type_info *to = SwigPyPacked_UnpackData(obj, ptr, sz); + if (!to) return SWIG_ERROR; + if (ty) { + if (to != ty) { + /* check type cast? */ + swig_cast_info *tc = SWIG_TypeCheck(to->name,ty); + if (!tc) return SWIG_ERROR; + } + } + return SWIG_OK; +} + +/* ----------------------------------------------------------------------------- + * Create a new pointer object + * ----------------------------------------------------------------------------- */ + +/* + Create a new instance object, without calling __init__, and set the + 'this' attribute. +*/ + +SWIGRUNTIME PyObject* +SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this) +{ +#if (PY_VERSION_HEX >= 0x02020000) + PyObject *inst = 0; + PyObject *newraw = data->newraw; + if (newraw) { + inst = PyObject_Call(newraw, data->newargs, NULL); + if (inst) { +#if !defined(SWIG_PYTHON_SLOW_GETSET_THIS) + PyObject **dictptr = _PyObject_GetDictPtr(inst); + if (dictptr != NULL) { + PyObject *dict = *dictptr; + if (dict == NULL) { + dict = PyDict_New(); + *dictptr = dict; + PyDict_SetItem(dict, SWIG_This(), swig_this); + } + } +#else + PyObject *key = SWIG_This(); + PyObject_SetAttr(inst, key, swig_this); +#endif + } + } else { +#if PY_VERSION_HEX >= 0x03000000 + inst = PyBaseObject_Type.tp_new((PyTypeObject*) data->newargs, Py_None, Py_None); + PyObject_SetAttr(inst, SWIG_This(), swig_this); + Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG; +#else + PyObject *dict = PyDict_New(); + PyDict_SetItem(dict, SWIG_This(), swig_this); + inst = PyInstance_NewRaw(data->newargs, dict); + Py_DECREF(dict); +#endif + } + return inst; +#else +#if (PY_VERSION_HEX >= 0x02010000) + PyObject *inst; + PyObject *dict = PyDict_New(); + PyDict_SetItem(dict, SWIG_This(), swig_this); + inst = PyInstance_NewRaw(data->newargs, dict); + Py_DECREF(dict); + return (PyObject *) inst; +#else + PyInstanceObject *inst = PyObject_NEW(PyInstanceObject, &PyInstance_Type); + if (inst == NULL) { + return NULL; + } + inst->in_class = (PyClassObject *)data->newargs; + Py_INCREF(inst->in_class); + inst->in_dict = PyDict_New(); + if (inst->in_dict == NULL) { + Py_DECREF(inst); + return NULL; + } +#ifdef Py_TPFLAGS_HAVE_WEAKREFS + inst->in_weakreflist = NULL; +#endif +#ifdef Py_TPFLAGS_GC + PyObject_GC_Init(inst); +#endif + PyDict_SetItem(inst->in_dict, SWIG_This(), swig_this); + return (PyObject *) inst; +#endif +#endif +} + +SWIGRUNTIME void +SWIG_Python_SetSwigThis(PyObject *inst, PyObject *swig_this) +{ + PyObject *dict; +#if (PY_VERSION_HEX >= 0x02020000) && !defined(SWIG_PYTHON_SLOW_GETSET_THIS) + PyObject **dictptr = _PyObject_GetDictPtr(inst); + if (dictptr != NULL) { + dict = *dictptr; + if (dict == NULL) { + dict = PyDict_New(); + *dictptr = dict; + } + PyDict_SetItem(dict, SWIG_This(), swig_this); + return; + } +#endif + dict = PyObject_GetAttrString(inst, (char*)"__dict__"); + PyDict_SetItem(dict, SWIG_This(), swig_this); + Py_DECREF(dict); +} + + +SWIGINTERN PyObject * +SWIG_Python_InitShadowInstance(PyObject *args) { + PyObject *obj[2]; + if (!SWIG_Python_UnpackTuple(args,(char*)"swiginit", 2, 2, obj)) { + return NULL; + } else { + SwigPyObject *sthis = SWIG_Python_GetSwigThis(obj[0]); + if (sthis) { + SwigPyObject_append((PyObject*) sthis, obj[1]); + } else { + SWIG_Python_SetSwigThis(obj[0], obj[1]); + } + return SWIG_Py_Void(); + } +} + +/* Create a new pointer object */ + +SWIGRUNTIME PyObject * +SWIG_Python_NewPointerObj(void *ptr, swig_type_info *type, int flags) { + if (!ptr) { + return SWIG_Py_Void(); + } else { + int own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0; + PyObject *robj = SwigPyObject_New(ptr, type, own); + SwigPyClientData *clientdata = type ? (SwigPyClientData *)(type->clientdata) : 0; + if (clientdata && !(flags & SWIG_POINTER_NOSHADOW)) { + PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj); + if (inst) { + Py_DECREF(robj); + robj = inst; + } + } + return robj; + } +} + +/* Create a new packed object */ + +SWIGRUNTIMEINLINE PyObject * +SWIG_Python_NewPackedObj(void *ptr, size_t sz, swig_type_info *type) { + return ptr ? SwigPyPacked_New((void *) ptr, sz, type) : SWIG_Py_Void(); +} + +/* -----------------------------------------------------------------------------* + * Get type list + * -----------------------------------------------------------------------------*/ + +#ifdef SWIG_LINK_RUNTIME +void *SWIG_ReturnGlobalTypeList(void *); +#endif + +SWIGRUNTIME swig_module_info * +SWIG_Python_GetModule(void) { + static void *type_pointer = (void *)0; + /* first check if module already created */ + if (!type_pointer) { +#ifdef SWIG_LINK_RUNTIME + type_pointer = SWIG_ReturnGlobalTypeList((void *)0); +#else + type_pointer = PyCObject_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, + (char*)"type_pointer" SWIG_TYPE_TABLE_NAME); + if (PyErr_Occurred()) { + PyErr_Clear(); + type_pointer = (void *)0; + } +#endif + } + return (swig_module_info *) type_pointer; +} + +#if PY_MAJOR_VERSION < 2 +/* PyModule_AddObject function was introduced in Python 2.0. The following function + is copied out of Python/modsupport.c in python version 2.3.4 */ +SWIGINTERN int +PyModule_AddObject(PyObject *m, char *name, PyObject *o) +{ + PyObject *dict; + if (!PyModule_Check(m)) { + PyErr_SetString(PyExc_TypeError, + "PyModule_AddObject() needs module as first arg"); + return SWIG_ERROR; + } + if (!o) { + PyErr_SetString(PyExc_TypeError, + "PyModule_AddObject() needs non-NULL value"); + return SWIG_ERROR; + } + + dict = PyModule_GetDict(m); + if (dict == NULL) { + /* Internal error -- modules must have a dict! */ + PyErr_Format(PyExc_SystemError, "module '%s' has no __dict__", + PyModule_GetName(m)); + return SWIG_ERROR; + } + if (PyDict_SetItemString(dict, name, o)) + return SWIG_ERROR; + Py_DECREF(o); + return SWIG_OK; +} +#endif + +SWIGRUNTIME void +SWIG_Python_DestroyModule(void *vptr) +{ + swig_module_info *swig_module = (swig_module_info *) vptr; + swig_type_info **types = swig_module->types; + size_t i; + for (i =0; i < swig_module->size; ++i) { + swig_type_info *ty = types[i]; + if (ty->owndata) { + SwigPyClientData *data = (SwigPyClientData *) ty->clientdata; + if (data) SwigPyClientData_Del(data); + } + } + Py_DECREF(SWIG_This()); +} + +SWIGRUNTIME void +SWIG_Python_SetModule(swig_module_info *swig_module) { + static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} };/* Sentinel */ + +#if PY_VERSION_HEX >= 0x03000000 + /* Add a dummy module object into sys.modules */ + PyObject *module = PyImport_AddModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION); +#else + PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, + swig_empty_runtime_method_table); +#endif + PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule); + if (pointer && module) { + PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer); + } else { + Py_XDECREF(pointer); + } +} + +/* The python cached type query */ +SWIGRUNTIME PyObject * +SWIG_Python_TypeCache(void) { + static PyObject *SWIG_STATIC_POINTER(cache) = PyDict_New(); + return cache; +} + +SWIGRUNTIME swig_type_info * +SWIG_Python_TypeQuery(const char *type) +{ + PyObject *cache = SWIG_Python_TypeCache(); + PyObject *key = SWIG_Python_str_FromChar(type); + PyObject *obj = PyDict_GetItem(cache, key); + swig_type_info *descriptor; + if (obj) { + descriptor = (swig_type_info *) PyCObject_AsVoidPtr(obj); + } else { + swig_module_info *swig_module = SWIG_Python_GetModule(); + descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type); + if (descriptor) { + obj = PyCObject_FromVoidPtr(descriptor, NULL); + PyDict_SetItem(cache, key, obj); + Py_DECREF(obj); + } + } + Py_DECREF(key); + return descriptor; +} + +/* + For backward compatibility only +*/ +#define SWIG_POINTER_EXCEPTION 0 +#define SWIG_arg_fail(arg) SWIG_Python_ArgFail(arg) +#define SWIG_MustGetPtr(p, type, argnum, flags) SWIG_Python_MustGetPtr(p, type, argnum, flags) + +SWIGRUNTIME int +SWIG_Python_AddErrMesg(const char* mesg, int infront) +{ + if (PyErr_Occurred()) { + PyObject *type = 0; + PyObject *value = 0; + PyObject *traceback = 0; + PyErr_Fetch(&type, &value, &traceback); + if (value) { + char *tmp; + PyObject *old_str = PyObject_Str(value); + Py_XINCREF(type); + PyErr_Clear(); + if (infront) { + PyErr_Format(type, "%s %s", mesg, tmp = SWIG_Python_str_AsChar(old_str)); + } else { + PyErr_Format(type, "%s %s", tmp = SWIG_Python_str_AsChar(old_str), mesg); + } + SWIG_Python_str_DelForPy3(tmp); + Py_DECREF(old_str); + } + return 1; + } else { + return 0; + } +} + +SWIGRUNTIME int +SWIG_Python_ArgFail(int argnum) +{ + if (PyErr_Occurred()) { + /* add information about failing argument */ + char mesg[256]; + PyOS_snprintf(mesg, sizeof(mesg), "argument number %d:", argnum); + return SWIG_Python_AddErrMesg(mesg, 1); + } else { + return 0; + } +} + +SWIGRUNTIMEINLINE const char * +SwigPyObject_GetDesc(PyObject *self) +{ + SwigPyObject *v = (SwigPyObject *)self; + swig_type_info *ty = v ? v->ty : 0; + return ty ? ty->str : (char*)""; +} + +SWIGRUNTIME void +SWIG_Python_TypeError(const char *type, PyObject *obj) +{ + if (type) { +#if defined(SWIG_COBJECT_TYPES) + if (obj && SwigPyObject_Check(obj)) { + const char *otype = (const char *) SwigPyObject_GetDesc(obj); + if (otype) { + PyErr_Format(PyExc_TypeError, "a '%s' is expected, 'SwigPyObject(%s)' is received", + type, otype); + return; + } + } else +#endif + { + const char *otype = (obj ? obj->ob_type->tp_name : 0); + if (otype) { + PyObject *str = PyObject_Str(obj); + const char *cstr = str ? SWIG_Python_str_AsChar(str) : 0; + if (cstr) { + PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s(%s)' is received", + type, otype, cstr); + SWIG_Python_str_DelForPy3(cstr); + } else { + PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s' is received", + type, otype); + } + Py_XDECREF(str); + return; + } + } + PyErr_Format(PyExc_TypeError, "a '%s' is expected", type); + } else { + PyErr_Format(PyExc_TypeError, "unexpected type is received"); + } +} + + +/* Convert a pointer value, signal an exception on a type mismatch */ +SWIGRUNTIME void * +SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags) { + void *result; + if (SWIG_Python_ConvertPtr(obj, &result, ty, flags) == -1) { + PyErr_Clear(); +#if SWIG_POINTER_EXCEPTION + if (flags) { + SWIG_Python_TypeError(SWIG_TypePrettyName(ty), obj); + SWIG_Python_ArgFail(argnum); + } +#endif + } + return result; +} + + +#ifdef __cplusplus +#if 0 +{ /* cc-mode */ +#endif +} +#endif + + + +#define SWIG_exception_fail(code, msg) do { SWIG_Error(code, msg); SWIG_fail; } while(0) + +#define SWIG_contract_assert(expr, msg) if (!(expr)) { SWIG_Error(SWIG_RuntimeError, msg); SWIG_fail; } else + + + +/* -------- TYPES TABLE (BEGIN) -------- */ + +#define SWIGTYPE_p_FILE swig_types[0] +#define SWIGTYPE_p_char swig_types[1] +#define SWIGTYPE_p_f_p_struct_nl_cache_ops_p_struct_sockaddr_nl_p_struct_nlmsghdr_p_struct_nl_parser_param__int swig_types[2] +#define SWIGTYPE_p_f_p_struct_nl_cache_ops_p_void__void swig_types[3] +#define SWIGTYPE_p_f_p_struct_nl_cache_p_struct_nl_object_int_p_void__void swig_types[4] +#define SWIGTYPE_p_f_p_struct_nl_dump_params_int__void swig_types[5] +#define SWIGTYPE_p_f_p_struct_nl_dump_params_p_char__void swig_types[6] +#define SWIGTYPE_p_f_p_struct_nl_object_p_void__void swig_types[7] +#define SWIGTYPE_p_int swig_types[8] +#define SWIGTYPE_p_long_long swig_types[9] +#define SWIGTYPE_p_nl_addr swig_types[10] +#define SWIGTYPE_p_nl_cache swig_types[11] +#define SWIGTYPE_p_nl_cache_mngr swig_types[12] +#define SWIGTYPE_p_nl_cache_ops swig_types[13] +#define SWIGTYPE_p_nl_cb swig_types[14] +#define SWIGTYPE_p_nl_dump_params swig_types[15] +#define SWIGTYPE_p_nl_msg swig_types[16] +#define SWIGTYPE_p_nl_msgtype swig_types[17] +#define SWIGTYPE_p_nl_object swig_types[18] +#define SWIGTYPE_p_nl_object_ops swig_types[19] +#define SWIGTYPE_p_nl_sock swig_types[20] +#define SWIGTYPE_p_nla_policy swig_types[21] +#define SWIGTYPE_p_nlattr swig_types[22] +#define SWIGTYPE_p_nlmsghdr swig_types[23] +#define SWIGTYPE_p_p_addrinfo swig_types[24] +#define SWIGTYPE_p_p_char swig_types[25] +#define SWIGTYPE_p_p_nl_object swig_types[26] +#define SWIGTYPE_p_p_nlattr swig_types[27] +#define SWIGTYPE_p_short swig_types[28] +#define SWIGTYPE_p_signed_char swig_types[29] +#define SWIGTYPE_p_sockaddr swig_types[30] +#define SWIGTYPE_p_sockaddr_nl swig_types[31] +#define SWIGTYPE_p_socklen_t swig_types[32] +#define SWIGTYPE_p_ucred swig_types[33] +#define SWIGTYPE_p_unsigned_char swig_types[34] +#define SWIGTYPE_p_unsigned_int swig_types[35] +#define SWIGTYPE_p_unsigned_long_long swig_types[36] +#define SWIGTYPE_p_unsigned_short swig_types[37] +#define SWIGTYPE_p_void swig_types[38] +static swig_type_info *swig_types[40]; +static swig_module_info swig_module = {swig_types, 39, 0, 0, 0, 0}; +#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name) +#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name) + +/* -------- TYPES TABLE (END) -------- */ + +#if (PY_VERSION_HEX <= 0x02000000) +# if !defined(SWIG_PYTHON_CLASSIC) +# error "This python version requires swig to be run with the '-classic' option" +# endif +#endif +#if (PY_VERSION_HEX <= 0x02020000) +# error "This python version requires swig to be run with the '-nomodern' option" +#endif +#if (PY_VERSION_HEX <= 0x02020000) +# error "This python version requires swig to be run with the '-nomodernargs' option" +#endif +#ifndef METH_O +# error "This python version requires swig to be run with the '-nofastunpack' option" +#endif +#ifdef SWIG_TypeQuery +# undef SWIG_TypeQuery +#endif +#define SWIG_TypeQuery SWIG_Python_TypeQuery + +/*----------------------------------------------- + @(target):= _capi.so + ------------------------------------------------*/ +#if PY_VERSION_HEX >= 0x03000000 +# define SWIG_init PyInit__capi + +#else +# define SWIG_init init_capi + +#endif +#define SWIG_name "_capi" + +#define SWIGVERSION 0x010340 +#define SWIG_VERSION SWIGVERSION + + +#define SWIG_as_voidptr(a) (void *)((const void *)(a)) +#define SWIG_as_voidptrptr(a) ((void)SWIG_as_voidptr(*a),(void**)(a)) + + +#include +#include +#include +#include +#include +#include + + +#include // Use the C99 official header + + + struct nl_dump_params *alloc_dump_params(void) + { + struct nl_dump_params *dp; + if (!(dp = calloc(1, sizeof(*dp)))) + return NULL; + dp->dp_fd = stdout; + return dp; + } + + void free_dump_params(struct nl_dump_params *dp) + { + free(dp); + } + + + #define SWIG_From_long PyInt_FromLong + + +SWIGINTERNINLINE PyObject * +SWIG_From_int (int value) +{ + return SWIG_From_long (value); +} + + +#include +#if !defined(SWIG_NO_LLONG_MAX) +# if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__) +# define LLONG_MAX __LONG_LONG_MAX__ +# define LLONG_MIN (-LLONG_MAX - 1LL) +# define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL) +# endif +#endif + + +SWIGINTERN int +SWIG_AsVal_double (PyObject *obj, double *val) +{ + int res = SWIG_TypeError; + if (PyFloat_Check(obj)) { + if (val) *val = PyFloat_AsDouble(obj); + return SWIG_OK; + } else if (PyInt_Check(obj)) { + if (val) *val = PyInt_AsLong(obj); + return SWIG_OK; + } else if (PyLong_Check(obj)) { + double v = PyLong_AsDouble(obj); + if (!PyErr_Occurred()) { + if (val) *val = v; + return SWIG_OK; + } else { + PyErr_Clear(); + } + } +#ifdef SWIG_PYTHON_CAST_MODE + { + int dispatch = 0; + double d = PyFloat_AsDouble(obj); + if (!PyErr_Occurred()) { + if (val) *val = d; + return SWIG_AddCast(SWIG_OK); + } else { + PyErr_Clear(); + } + if (!dispatch) { + long v = PyLong_AsLong(obj); + if (!PyErr_Occurred()) { + if (val) *val = v; + return SWIG_AddCast(SWIG_AddCast(SWIG_OK)); + } else { + PyErr_Clear(); + } + } + } +#endif + return res; +} + + +#include + + +#include + + +SWIGINTERNINLINE int +SWIG_CanCastAsInteger(double *d, double min, double max) { + double x = *d; + if ((min <= x && x <= max)) { + double fx = floor(x); + double cx = ceil(x); + double rd = ((x - fx) < 0.5) ? fx : cx; /* simple rint */ + if ((errno == EDOM) || (errno == ERANGE)) { + errno = 0; + } else { + double summ, reps, diff; + if (rd < x) { + diff = x - rd; + } else if (rd > x) { + diff = rd - x; + } else { + return 1; + } + summ = rd + x; + reps = diff/summ; + if (reps < 8*DBL_EPSILON) { + *d = rd; + return 1; + } + } + } + return 0; +} + + +SWIGINTERN int +SWIG_AsVal_long (PyObject *obj, long* val) +{ + if (PyInt_Check(obj)) { + if (val) *val = PyInt_AsLong(obj); + return SWIG_OK; + } else if (PyLong_Check(obj)) { + long v = PyLong_AsLong(obj); + if (!PyErr_Occurred()) { + if (val) *val = v; + return SWIG_OK; + } else { + PyErr_Clear(); + } + } +#ifdef SWIG_PYTHON_CAST_MODE + { + int dispatch = 0; + long v = PyInt_AsLong(obj); + if (!PyErr_Occurred()) { + if (val) *val = v; + return SWIG_AddCast(SWIG_OK); + } else { + PyErr_Clear(); + } + if (!dispatch) { + double d; + int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d)); + if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) { + if (val) *val = (long)(d); + return res; + } + } + } +#endif + return SWIG_TypeError; +} + + +SWIGINTERN int +SWIG_AsVal_int (PyObject * obj, int *val) +{ + long v; + int res = SWIG_AsVal_long (obj, &v); + if (SWIG_IsOK(res)) { + if ((v < INT_MIN || v > INT_MAX)) { + return SWIG_OverflowError; + } else { + if (val) *val = (int)(v); + } + } + return res; +} + + +SWIGINTERN swig_type_info* +SWIG_pchar_descriptor(void) +{ + static int init = 0; + static swig_type_info* info = 0; + if (!init) { + info = SWIG_TypeQuery("_p_char"); + init = 1; + } + return info; +} + + +SWIGINTERN int +SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc) +{ +#if PY_VERSION_HEX>=0x03000000 + if (PyUnicode_Check(obj)) +#else + if (PyString_Check(obj)) +#endif + { + char *cstr; Py_ssize_t len; +#if PY_VERSION_HEX>=0x03000000 + if (!alloc && cptr) { + /* We can't allow converting without allocation, since the internal + representation of string in Python 3 is UCS-2/UCS-4 but we require + a UTF-8 representation. + TODO(bhy) More detailed explanation */ + return SWIG_RuntimeError; + } + obj = PyUnicode_AsUTF8String(obj); + PyBytes_AsStringAndSize(obj, &cstr, &len); + if(alloc) *alloc = SWIG_NEWOBJ; +#else + PyString_AsStringAndSize(obj, &cstr, &len); +#endif + if (cptr) { + if (alloc) { + /* + In python the user should not be able to modify the inner + string representation. To warranty that, if you define + SWIG_PYTHON_SAFE_CSTRINGS, a new/copy of the python string + buffer is always returned. + + The default behavior is just to return the pointer value, + so, be careful. + */ +#if defined(SWIG_PYTHON_SAFE_CSTRINGS) + if (*alloc != SWIG_OLDOBJ) +#else + if (*alloc == SWIG_NEWOBJ) +#endif + { + *cptr = (char *)memcpy((char *)malloc((len + 1)*sizeof(char)), cstr, sizeof(char)*(len + 1)); + *alloc = SWIG_NEWOBJ; + } + else { + *cptr = cstr; + *alloc = SWIG_OLDOBJ; + } + } else { + #if PY_VERSION_HEX>=0x03000000 + assert(0); /* Should never reach here in Python 3 */ + #endif + *cptr = SWIG_Python_str_AsChar(obj); + } + } + if (psize) *psize = len + 1; +#if PY_VERSION_HEX>=0x03000000 + Py_XDECREF(obj); +#endif + return SWIG_OK; + } else { + swig_type_info* pchar_descriptor = SWIG_pchar_descriptor(); + if (pchar_descriptor) { + void* vptr = 0; + if (SWIG_ConvertPtr(obj, &vptr, pchar_descriptor, 0) == SWIG_OK) { + if (cptr) *cptr = (char *) vptr; + if (psize) *psize = vptr ? (strlen((char *)vptr) + 1) : 0; + if (alloc) *alloc = SWIG_OLDOBJ; + return SWIG_OK; + } + } + } + return SWIG_TypeError; +} + + + + + +SWIGINTERNINLINE PyObject * +SWIG_FromCharPtrAndSize(const char* carray, size_t size) +{ + if (carray) { + if (size > INT_MAX) { + swig_type_info* pchar_descriptor = SWIG_pchar_descriptor(); + return pchar_descriptor ? + SWIG_NewPointerObj((char *)(carray), pchar_descriptor, 0) : SWIG_Py_Void(); + } else { +#if PY_VERSION_HEX >= 0x03000000 + return PyUnicode_FromStringAndSize(carray, (int)(size)); +#else + return PyString_FromStringAndSize(carray, (int)(size)); +#endif + } + } else { + return SWIG_Py_Void(); + } +} + + +SWIGINTERNINLINE PyObject * +SWIG_FromCharPtr(const char *cptr) +{ + return SWIG_FromCharPtrAndSize(cptr, (cptr ? strlen(cptr) : 0)); +} + + +SWIGINTERN int +SWIG_AsVal_unsigned_SS_long (PyObject *obj, unsigned long *val) +{ + if (PyInt_Check(obj)) { + long v = PyInt_AsLong(obj); + if (v >= 0) { + if (val) *val = v; + return SWIG_OK; + } else { + return SWIG_OverflowError; + } + } else if (PyLong_Check(obj)) { + unsigned long v = PyLong_AsUnsignedLong(obj); + if (!PyErr_Occurred()) { + if (val) *val = v; + return SWIG_OK; + } else { + PyErr_Clear(); + } + } +#ifdef SWIG_PYTHON_CAST_MODE + { + int dispatch = 0; + unsigned long v = PyLong_AsUnsignedLong(obj); + if (!PyErr_Occurred()) { + if (val) *val = v; + return SWIG_AddCast(SWIG_OK); + } else { + PyErr_Clear(); + } + if (!dispatch) { + double d; + int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d)); + if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ULONG_MAX)) { + if (val) *val = (unsigned long)(d); + return res; + } + } + } +#endif + return SWIG_TypeError; +} + + +SWIGINTERNINLINE int +SWIG_AsVal_size_t (PyObject * obj, size_t *val) +{ + unsigned long v; + int res = SWIG_AsVal_unsigned_SS_long (obj, val ? &v : 0); + if (SWIG_IsOK(res) && val) *val = (size_t)(v); + return res; +} + + +SWIGINTERNINLINE PyObject* +SWIG_From_unsigned_SS_long (unsigned long value) +{ + return (value > LONG_MAX) ? + PyLong_FromUnsignedLong(value) : PyInt_FromLong((long)(value)); +} + + +SWIGINTERNINLINE PyObject * +SWIG_From_size_t (size_t value) +{ + return SWIG_From_unsigned_SS_long ((unsigned long)(value)); +} + + +SWIGINTERN int +SWIG_AsVal_unsigned_SS_int (PyObject * obj, unsigned int *val) +{ + unsigned long v; + int res = SWIG_AsVal_unsigned_SS_long (obj, &v); + if (SWIG_IsOK(res)) { + if ((v > UINT_MAX)) { + return SWIG_OverflowError; + } else { + if (val) *val = (unsigned int)(v); + } + } + return res; +} + + +SWIGINTERNINLINE PyObject * +SWIG_From_unsigned_SS_int (unsigned int value) +{ + return SWIG_From_unsigned_SS_long (value); +} + + +SWIGINTERN int +SWIG_AsVal_unsigned_SS_long_SS_long (PyObject *obj, unsigned long long *val) +{ + int res = SWIG_TypeError; + if (PyLong_Check(obj)) { + unsigned long long v = PyLong_AsUnsignedLongLong(obj); + if (!PyErr_Occurred()) { + if (val) *val = v; + return SWIG_OK; + } else { + PyErr_Clear(); + } + } else { + unsigned long v; + res = SWIG_AsVal_unsigned_SS_long (obj,&v); + if (SWIG_IsOK(res)) { + if (val) *val = v; + return res; + } + } +#ifdef SWIG_PYTHON_CAST_MODE + { + const double mant_max = 1LL << DBL_MANT_DIG; + double d; + res = SWIG_AsVal_double (obj,&d); + if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, mant_max)) { + if (val) *val = (unsigned long long)(d); + return SWIG_AddCast(res); + } + res = SWIG_TypeError; + } +#endif + return res; +} + + + #define SWIG_From_double PyFloat_FromDouble + + + struct nl_object *cast_obj(void *obj) + { + return (struct nl_object *) obj; + } + + struct nl_object *object_alloc_name(const char *name) + { + struct nl_object *obj; + + if (nl_object_alloc_name(name, &obj) < 0) + return NULL; + + return obj; + } + + + struct nl_cache *alloc_cache_name(const char *name) + { + struct nl_cache *c; + if (nl_cache_alloc_name(name, &c) < 0) + return NULL; + return c; + } + + struct nl_cache_mngr *alloc_cache_mngr(struct nl_sock *sock, + int protocol, int flags) + { + struct nl_cache_mngr *mngr; + + if (nl_cache_mngr_alloc(sock, protocol, flags, &mngr) < 0) + return NULL; + + return mngr; + } + + struct nl_cache *cache_mngr_add(struct nl_cache_mngr *mngr, + const char *name, change_func_t func, + void *arg) + { + struct nl_cache *cache; + + if (nl_cache_mngr_add(mngr, name, func, arg, &cache) < 0) + return NULL; + + return cache; + } + + + struct nl_addr *addr_parse(const char *addr, int guess) + { + struct nl_addr *result; + + if (nl_addr_parse(addr, guess, &result) < 0) + return NULL; + + return result; + } + +#ifdef __cplusplus +extern "C" { +#endif +SWIGINTERN PyObject *_wrap_alloc_dump_params(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"alloc_dump_params",0,0,0)) SWIG_fail; + result = (struct nl_dump_params *)alloc_dump_params(); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_dump_params, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_free_dump_params(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "free_dump_params" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + free_dump_params(arg1); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_params_dp_type_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + enum nl_dump_type arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_dump_params_dp_type_set",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_type_set" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_dump_params_dp_type_set" "', argument " "2"" of type '" "enum nl_dump_type""'"); + } + arg2 = (enum nl_dump_type)(val2); + if (arg1) (arg1)->dp_type = arg2; + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_params_dp_type_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + enum nl_dump_type result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_type_get" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + result = (enum nl_dump_type) ((arg1)->dp_type); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_params_dp_prefix_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_dump_params_dp_prefix_set",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_prefix_set" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_dump_params_dp_prefix_set" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + if (arg1) (arg1)->dp_prefix = arg2; + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_params_dp_prefix_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_prefix_get" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + result = (int) ((arg1)->dp_prefix); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_params_dp_print_index_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_dump_params_dp_print_index_set",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_print_index_set" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_dump_params_dp_print_index_set" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + if (arg1) (arg1)->dp_print_index = arg2; + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_params_dp_print_index_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_print_index_get" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + result = (int) ((arg1)->dp_print_index); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_params_dp_dump_msgtype_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_dump_params_dp_dump_msgtype_set",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_dump_msgtype_set" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_dump_params_dp_dump_msgtype_set" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + if (arg1) (arg1)->dp_dump_msgtype = arg2; + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_params_dp_dump_msgtype_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_dump_msgtype_get" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + result = (int) ((arg1)->dp_dump_msgtype); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_params_dp_cb_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + void (*arg2)(struct nl_dump_params *,char *) = (void (*)(struct nl_dump_params *,char *)) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_dump_params_dp_cb_set",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_cb_set" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + { + int res = SWIG_ConvertFunctionPtr(swig_obj[1], (void**)(&arg2), SWIGTYPE_p_f_p_struct_nl_dump_params_p_char__void); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in method '" "nl_dump_params_dp_cb_set" "', argument " "2"" of type '" "void (*)(struct nl_dump_params *,char *)""'"); + } + } + if (arg1) (arg1)->dp_cb = arg2; + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_params_dp_cb_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + void (*result)(struct nl_dump_params *,char *) = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_cb_get" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + result = (void (*)(struct nl_dump_params *,char *)) ((arg1)->dp_cb); + resultobj = SWIG_NewFunctionPtrObj((void *)(result), SWIGTYPE_p_f_p_struct_nl_dump_params_p_char__void); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_params_dp_nl_cb_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + void (*arg2)(struct nl_dump_params *,int) = (void (*)(struct nl_dump_params *,int)) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_dump_params_dp_nl_cb_set",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_nl_cb_set" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + { + int res = SWIG_ConvertFunctionPtr(swig_obj[1], (void**)(&arg2), SWIGTYPE_p_f_p_struct_nl_dump_params_int__void); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in method '" "nl_dump_params_dp_nl_cb_set" "', argument " "2"" of type '" "void (*)(struct nl_dump_params *,int)""'"); + } + } + if (arg1) (arg1)->dp_nl_cb = arg2; + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_params_dp_nl_cb_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + void (*result)(struct nl_dump_params *,int) = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_nl_cb_get" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + result = (void (*)(struct nl_dump_params *,int)) ((arg1)->dp_nl_cb); + resultobj = SWIG_NewFunctionPtrObj((void *)(result), SWIGTYPE_p_f_p_struct_nl_dump_params_int__void); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_params_dp_data_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + void *arg2 = (void *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_dump_params_dp_data_set",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_data_set" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1],SWIG_as_voidptrptr(&arg2), 0, SWIG_POINTER_DISOWN); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_dump_params_dp_data_set" "', argument " "2"" of type '" "void *""'"); + } + if (arg1) (arg1)->dp_data = arg2; + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_params_dp_data_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + void *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_data_get" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + result = (void *) ((arg1)->dp_data); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_void, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_params_dp_fd_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + FILE *arg2 = (FILE *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_dump_params_dp_fd_set",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_fd_set" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_FILE, SWIG_POINTER_DISOWN | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_dump_params_dp_fd_set" "', argument " "2"" of type '" "FILE *""'"); + } + arg2 = (FILE *)(argp2); + if (arg1) (arg1)->dp_fd = arg2; + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_params_dp_fd_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + FILE *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_fd_get" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + result = (FILE *) ((arg1)->dp_fd); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_FILE, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_params_dp_buf_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + char *arg2 = (char *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_dump_params_dp_buf_set",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_buf_set" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_dump_params_dp_buf_set" "', argument " "2"" of type '" "char *""'"); + } + arg2 = (char *)(buf2); + if (arg1->dp_buf) free((char*)arg1->dp_buf); + if (arg2) { + size_t size = strlen((const char *)(arg2)) + 1; + arg1->dp_buf = (char *)(char *)memcpy((char *)malloc((size)*sizeof(char)), (const char *)(arg2), sizeof(char)*(size)); + } else { + arg1->dp_buf = 0; + } + resultobj = SWIG_Py_Void(); + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return resultobj; +fail: + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_params_dp_buf_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + char *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_buf_get" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + result = (char *) ((arg1)->dp_buf); + resultobj = SWIG_FromCharPtr((const char *)result); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_params_dp_buflen_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + size_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + size_t val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_dump_params_dp_buflen_set",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_buflen_set" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + ecode2 = SWIG_AsVal_size_t(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_dump_params_dp_buflen_set" "', argument " "2"" of type '" "size_t""'"); + } + arg2 = (size_t)(val2); + if (arg1) (arg1)->dp_buflen = arg2; + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_params_dp_buflen_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + size_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_buflen_get" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + result = ((arg1)->dp_buflen); + resultobj = SWIG_From_size_t((size_t)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_params_dp_pre_dump_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_dump_params_dp_pre_dump_set",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_pre_dump_set" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_dump_params_dp_pre_dump_set" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + if (arg1) (arg1)->dp_pre_dump = arg2; + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_params_dp_pre_dump_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_pre_dump_get" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + result = (int) ((arg1)->dp_pre_dump); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_params_dp_ivar_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_dump_params_dp_ivar_set",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_ivar_set" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_dump_params_dp_ivar_set" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + if (arg1) (arg1)->dp_ivar = arg2; + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_params_dp_ivar_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_ivar_get" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + result = (int) ((arg1)->dp_ivar); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_params_dp_line_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + unsigned int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_dump_params_dp_line_set",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_line_set" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_dump_params_dp_line_set" "', argument " "2"" of type '" "unsigned int""'"); + } + arg2 = (unsigned int)(val2); + if (arg1) (arg1)->dp_line = arg2; + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_params_dp_line_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + unsigned int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_line_get" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + result = (unsigned int) ((arg1)->dp_line); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_delete_nl_dump_params(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, SWIG_POINTER_DISOWN | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_nl_dump_params" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + free((char *) arg1); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *nl_dump_params_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *obj; + if (!SWIG_Python_UnpackTuple(args,(char*)"swigregister", 1, 1,&obj)) return NULL; + SWIG_TypeNewClientData(SWIGTYPE_p_nl_dump_params, SWIG_NewClientData(obj)); + return SWIG_Py_Void(); +} + +SWIGINTERN PyObject *_wrap_nl_geterror(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + int arg1 ; + int val1 ; + int ecode1 = 0 ; + PyObject *swig_obj[1] ; + char *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_geterror" "', argument " "1"" of type '" "int""'"); + } + arg1 = (int)(val1); + result = (char *)nl_geterror(arg1); + resultobj = SWIG_FromCharPtr((const char *)result); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cancel_down_bytes(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + unsigned long long arg1 ; + char **arg2 = (char **) 0 ; + unsigned long long val1 ; + int ecode1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + double result; + + if (!SWIG_Python_UnpackTuple(args,"nl_cancel_down_bytes",2,2,swig_obj)) SWIG_fail; + ecode1 = SWIG_AsVal_unsigned_SS_long_SS_long(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_cancel_down_bytes" "', argument " "1"" of type '" "unsigned long long""'"); + } + arg1 = (unsigned long long)(val1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_p_char, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cancel_down_bytes" "', argument " "2"" of type '" "char **""'"); + } + arg2 = (char **)(argp2); + result = (double)nl_cancel_down_bytes(arg1,arg2); + resultobj = SWIG_From_double((double)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cancel_down_bits(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + unsigned long long arg1 ; + char **arg2 = (char **) 0 ; + unsigned long long val1 ; + int ecode1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + double result; + + if (!SWIG_Python_UnpackTuple(args,"nl_cancel_down_bits",2,2,swig_obj)) SWIG_fail; + ecode1 = SWIG_AsVal_unsigned_SS_long_SS_long(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_cancel_down_bits" "', argument " "1"" of type '" "unsigned long long""'"); + } + arg1 = (unsigned long long)(val1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_p_char, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cancel_down_bits" "', argument " "2"" of type '" "char **""'"); + } + arg2 = (char **)(argp2); + result = (double)nl_cancel_down_bits(arg1,arg2); + resultobj = SWIG_From_double((double)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_rate2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + unsigned long long arg1 ; + int arg2 ; + char *arg3 = (char *) 0 ; + size_t arg4 ; + unsigned long long val1 ; + int ecode1 = 0 ; + int val2 ; + int ecode2 = 0 ; + int res3 ; + size_t size3 ; + char *buff3 = 0 ; + PyObject *swig_obj[3] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nl_rate2str",3,3,swig_obj)) SWIG_fail; + ecode1 = SWIG_AsVal_unsigned_SS_long_SS_long(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_rate2str" "', argument " "1"" of type '" "unsigned long long""'"); + } + arg1 = (unsigned long long)(val1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_rate2str" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + res3 = SWIG_AsVal_size_t (swig_obj[2], &size3); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "nl_rate2str" "', argument " "3"" of type '" "(char *buf, size_t len)""'"); + } + buff3= (char *)malloc((size3+1)*sizeof(char)); + arg4 = (size_t)(size3); + arg3 = (char *)(buff3); + result = (int)nl_rate2str(arg1,arg2,arg3,arg4); + resultobj = SWIG_From_int((int)(result)); + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg3)); + if (buff3) free((char*)buff3); + return resultobj; +fail: + if (buff3) free((char*)buff3); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cancel_down_us(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + uint32_t arg1 ; + char **arg2 = (char **) 0 ; + unsigned int val1 ; + int ecode1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + double result; + + if (!SWIG_Python_UnpackTuple(args,"nl_cancel_down_us",2,2,swig_obj)) SWIG_fail; + ecode1 = SWIG_AsVal_unsigned_SS_int(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_cancel_down_us" "', argument " "1"" of type '" "uint32_t""'"); + } + arg1 = (uint32_t)(val1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_p_char, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cancel_down_us" "', argument " "2"" of type '" "char **""'"); + } + arg2 = (char **)(argp2); + result = (double)nl_cancel_down_us(arg1,arg2); + resultobj = SWIG_From_double((double)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_size2int(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + char *arg1 = (char *) 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + PyObject *swig_obj[1] ; + long result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_size2int" "', argument " "1"" of type '" "char const *""'"); + } + arg1 = (char *)(buf1); + result = (long)nl_size2int((char const *)arg1); + resultobj = SWIG_From_long((long)(result)); + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_size2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + size_t arg1 ; + char *arg2 = (char *) 0 ; + size_t arg3 ; + size_t val1 ; + int ecode1 = 0 ; + int res2 ; + size_t size2 ; + char *buff2 = 0 ; + PyObject *swig_obj[2] ; + char *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"nl_size2str",2,2,swig_obj)) SWIG_fail; + ecode1 = SWIG_AsVal_size_t(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_size2str" "', argument " "1"" of type '" "size_t""'"); + } + arg1 = (size_t)(val1); + res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_size2str" "', argument " "2"" of type '" "(char *buf, const size_t len)""'"); + } + buff2= (char *)malloc((size2+1)*sizeof(char)); + arg3 = (size_t)(size2); + arg2 = (char *)(buff2); + result = (char *)nl_size2str(arg1,arg2,arg3); + resultobj = SWIG_FromCharPtr((const char *)result); + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); + if (buff2) free((char*)buff2); + return resultobj; +fail: + if (buff2) free((char*)buff2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_prob2int(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + char *arg1 = (char *) 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + PyObject *swig_obj[1] ; + long result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_prob2int" "', argument " "1"" of type '" "char const *""'"); + } + arg1 = (char *)(buf1); + result = (long)nl_prob2int((char const *)arg1); + resultobj = SWIG_From_long((long)(result)); + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_get_user_hz(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nl_get_user_hz",0,0,0)) SWIG_fail; + result = (int)nl_get_user_hz(); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_us2ticks(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + uint32_t arg1 ; + unsigned int val1 ; + int ecode1 = 0 ; + PyObject *swig_obj[1] ; + uint32_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + ecode1 = SWIG_AsVal_unsigned_SS_int(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_us2ticks" "', argument " "1"" of type '" "uint32_t""'"); + } + arg1 = (uint32_t)(val1); + result = (uint32_t)nl_us2ticks(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_ticks2us(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + uint32_t arg1 ; + unsigned int val1 ; + int ecode1 = 0 ; + PyObject *swig_obj[1] ; + uint32_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + ecode1 = SWIG_AsVal_unsigned_SS_int(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_ticks2us" "', argument " "1"" of type '" "uint32_t""'"); + } + arg1 = (uint32_t)(val1); + result = (uint32_t)nl_ticks2us(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_str2msec(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + char *arg1 = (char *) 0 ; + uint64_t *arg2 = (uint64_t *) 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nl_str2msec",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_str2msec" "', argument " "1"" of type '" "char const *""'"); + } + arg1 = (char *)(buf1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_unsigned_long_long, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_str2msec" "', argument " "2"" of type '" "uint64_t *""'"); + } + arg2 = (uint64_t *)(argp2); + result = (int)nl_str2msec((char const *)arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_msec2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + uint64_t arg1 ; + char *arg2 = (char *) 0 ; + size_t arg3 ; + unsigned long long val1 ; + int ecode1 = 0 ; + int res2 ; + size_t size2 ; + char *buff2 = 0 ; + PyObject *swig_obj[2] ; + char *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"nl_msec2str",2,2,swig_obj)) SWIG_fail; + ecode1 = SWIG_AsVal_unsigned_SS_long_SS_long(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_msec2str" "', argument " "1"" of type '" "uint64_t""'"); + } + arg1 = (uint64_t)(val1); + res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_msec2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); + } + buff2= (char *)malloc((size2+1)*sizeof(char)); + arg3 = (size_t)(size2); + arg2 = (char *)(buff2); + result = (char *)nl_msec2str(arg1,arg2,arg3); + resultobj = SWIG_FromCharPtr((const char *)result); + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); + if (buff2) free((char*)buff2); + return resultobj; +fail: + if (buff2) free((char*)buff2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_llproto2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + int arg1 ; + char *arg2 = (char *) 0 ; + size_t arg3 ; + int val1 ; + int ecode1 = 0 ; + int res2 ; + size_t size2 ; + char *buff2 = 0 ; + PyObject *swig_obj[2] ; + char *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"nl_llproto2str",2,2,swig_obj)) SWIG_fail; + ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_llproto2str" "', argument " "1"" of type '" "int""'"); + } + arg1 = (int)(val1); + res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_llproto2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); + } + buff2= (char *)malloc((size2+1)*sizeof(char)); + arg3 = (size_t)(size2); + arg2 = (char *)(buff2); + result = (char *)nl_llproto2str(arg1,arg2,arg3); + resultobj = SWIG_FromCharPtr((const char *)result); + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); + if (buff2) free((char*)buff2); + return resultobj; +fail: + if (buff2) free((char*)buff2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_str2llproto(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + char *arg1 = (char *) 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_str2llproto" "', argument " "1"" of type '" "char const *""'"); + } + arg1 = (char *)(buf1); + result = (int)nl_str2llproto((char const *)arg1); + resultobj = SWIG_From_int((int)(result)); + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_ether_proto2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + int arg1 ; + char *arg2 = (char *) 0 ; + size_t arg3 ; + int val1 ; + int ecode1 = 0 ; + int res2 ; + size_t size2 ; + char *buff2 = 0 ; + PyObject *swig_obj[2] ; + char *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"nl_ether_proto2str",2,2,swig_obj)) SWIG_fail; + ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_ether_proto2str" "', argument " "1"" of type '" "int""'"); + } + arg1 = (int)(val1); + res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_ether_proto2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); + } + buff2= (char *)malloc((size2+1)*sizeof(char)); + arg3 = (size_t)(size2); + arg2 = (char *)(buff2); + result = (char *)nl_ether_proto2str(arg1,arg2,arg3); + resultobj = SWIG_FromCharPtr((const char *)result); + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); + if (buff2) free((char*)buff2); + return resultobj; +fail: + if (buff2) free((char*)buff2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_str2ether_proto(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + char *arg1 = (char *) 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_str2ether_proto" "', argument " "1"" of type '" "char const *""'"); + } + arg1 = (char *)(buf1); + result = (int)nl_str2ether_proto((char const *)arg1); + resultobj = SWIG_From_int((int)(result)); + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_ip_proto2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + int arg1 ; + char *arg2 = (char *) 0 ; + size_t arg3 ; + int val1 ; + int ecode1 = 0 ; + int res2 ; + size_t size2 ; + char *buff2 = 0 ; + PyObject *swig_obj[2] ; + char *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"nl_ip_proto2str",2,2,swig_obj)) SWIG_fail; + ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_ip_proto2str" "', argument " "1"" of type '" "int""'"); + } + arg1 = (int)(val1); + res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_ip_proto2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); + } + buff2= (char *)malloc((size2+1)*sizeof(char)); + arg3 = (size_t)(size2); + arg2 = (char *)(buff2); + result = (char *)nl_ip_proto2str(arg1,arg2,arg3); + resultobj = SWIG_FromCharPtr((const char *)result); + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); + if (buff2) free((char*)buff2); + return resultobj; +fail: + if (buff2) free((char*)buff2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_str2ip_proto(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + char *arg1 = (char *) 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_str2ip_proto" "', argument " "1"" of type '" "char const *""'"); + } + arg1 = (char *)(buf1); + result = (int)nl_str2ip_proto((char const *)arg1); + resultobj = SWIG_From_int((int)(result)); + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_new_line(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_new_line" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + nl_new_line(arg1); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump__varargs__(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *varargs) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + char *arg2 = (char *) 0 ; + void *arg3 = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + + if(!PyArg_UnpackTuple(args,(char *)"nl_dump",2,2,&obj0,&obj1)) SWIG_fail; + res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_dump" "', argument " "2"" of type '" "char const *""'"); + } + arg2 = (char *)(buf2); + nl_dump(arg1,(char const *)arg2,arg3); + resultobj = SWIG_Py_Void(); + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return resultobj; +fail: + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump(PyObject *self, PyObject *args) { + PyObject *resultobj; + PyObject *varargs; + PyObject *newargs; + + newargs = PyTuple_GetSlice(args,0,2); + varargs = PyTuple_GetSlice(args,2,PyTuple_Size(args)+1); + resultobj = _wrap_nl_dump__varargs__(self,newargs,varargs); + Py_XDECREF(newargs); + Py_XDECREF(varargs); + return resultobj; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_line__varargs__(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *varargs) { + PyObject *resultobj = 0; + struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; + char *arg2 = (char *) 0 ; + void *arg3 = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + + if(!PyArg_UnpackTuple(args,(char *)"nl_dump_line",2,2,&obj0,&obj1)) SWIG_fail; + res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_line" "', argument " "1"" of type '" "struct nl_dump_params *""'"); + } + arg1 = (struct nl_dump_params *)(argp1); + res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_dump_line" "', argument " "2"" of type '" "char const *""'"); + } + arg2 = (char *)(buf2); + nl_dump_line(arg1,(char const *)arg2,arg3); + resultobj = SWIG_Py_Void(); + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return resultobj; +fail: + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_dump_line(PyObject *self, PyObject *args) { + PyObject *resultobj; + PyObject *varargs; + PyObject *newargs; + + newargs = PyTuple_GetSlice(args,0,2); + varargs = PyTuple_GetSlice(args,2,PyTuple_Size(args)+1); + resultobj = _wrap_nl_dump_line__varargs__(self,newargs,varargs); + Py_XDECREF(newargs); + Py_XDECREF(varargs); + return resultobj; +} + + +SWIGINTERN PyObject *_wrap_nl_connect(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_sock *arg1 = (struct nl_sock *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nl_connect",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_connect" "', argument " "1"" of type '" "struct nl_sock *""'"); + } + arg1 = (struct nl_sock *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_connect" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + result = (int)nl_connect(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_close(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_sock *arg1 = (struct nl_sock *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_close" "', argument " "1"" of type '" "struct nl_sock *""'"); + } + arg1 = (struct nl_sock *)(argp1); + nl_close(arg1); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_pickup(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_sock *arg1 = (struct nl_sock *) 0 ; + int (*arg2)(struct nl_cache_ops *,struct sockaddr_nl *,struct nlmsghdr *,struct nl_parser_param *) = (int (*)(struct nl_cache_ops *,struct sockaddr_nl *,struct nlmsghdr *,struct nl_parser_param *)) 0 ; + struct nl_object **arg3 = (struct nl_object **) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp3 = 0 ; + int res3 = 0 ; + PyObject *swig_obj[3] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nl_pickup",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_pickup" "', argument " "1"" of type '" "struct nl_sock *""'"); + } + arg1 = (struct nl_sock *)(argp1); + { + int res = SWIG_ConvertFunctionPtr(swig_obj[1], (void**)(&arg2), SWIGTYPE_p_f_p_struct_nl_cache_ops_p_struct_sockaddr_nl_p_struct_nlmsghdr_p_struct_nl_parser_param__int); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in method '" "nl_pickup" "', argument " "2"" of type '" "int (*)(struct nl_cache_ops *,struct sockaddr_nl *,struct nlmsghdr *,struct nl_parser_param *)""'"); + } + } + res3 = SWIG_ConvertPtr(swig_obj[2], &argp3,SWIGTYPE_p_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "nl_pickup" "', argument " "3"" of type '" "struct nl_object **""'"); + } + arg3 = (struct nl_object **)(argp3); + result = (int)nl_pickup(arg1,arg2,arg3); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_socket_alloc(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_sock *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"nl_socket_alloc",0,0,0)) SWIG_fail; + result = (struct nl_sock *)nl_socket_alloc(); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_sock, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_socket_alloc_cb(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cb *arg1 = (struct nl_cb *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_sock *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cb, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_socket_alloc_cb" "', argument " "1"" of type '" "struct nl_cb *""'"); + } + arg1 = (struct nl_cb *)(argp1); + result = (struct nl_sock *)nl_socket_alloc_cb(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_sock, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_socket_free(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_sock *arg1 = (struct nl_sock *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_socket_free" "', argument " "1"" of type '" "struct nl_sock *""'"); + } + arg1 = (struct nl_sock *)(argp1); + nl_socket_free(arg1); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_socket_get_local_port(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_sock *arg1 = (struct nl_sock *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint32_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_socket_get_local_port" "', argument " "1"" of type '" "struct nl_sock const *""'"); + } + arg1 = (struct nl_sock *)(argp1); + result = (uint32_t)nl_socket_get_local_port((struct nl_sock const *)arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_socket_set_local_port(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_sock *arg1 = (struct nl_sock *) 0 ; + uint32_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_socket_set_local_port",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_socket_set_local_port" "', argument " "1"" of type '" "struct nl_sock *""'"); + } + arg1 = (struct nl_sock *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_socket_set_local_port" "', argument " "2"" of type '" "uint32_t""'"); + } + arg2 = (uint32_t)(val2); + nl_socket_set_local_port(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_socket_get_peer_port(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_sock *arg1 = (struct nl_sock *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint32_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_socket_get_peer_port" "', argument " "1"" of type '" "struct nl_sock const *""'"); + } + arg1 = (struct nl_sock *)(argp1); + result = (uint32_t)nl_socket_get_peer_port((struct nl_sock const *)arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_socket_set_peer_port(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_sock *arg1 = (struct nl_sock *) 0 ; + uint32_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_socket_set_peer_port",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_socket_set_peer_port" "', argument " "1"" of type '" "struct nl_sock *""'"); + } + arg1 = (struct nl_sock *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_socket_set_peer_port" "', argument " "2"" of type '" "uint32_t""'"); + } + arg2 = (uint32_t)(val2); + nl_socket_set_peer_port(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_socket_get_peer_groups(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_sock *arg1 = (struct nl_sock *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint32_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_socket_get_peer_groups" "', argument " "1"" of type '" "struct nl_sock const *""'"); + } + arg1 = (struct nl_sock *)(argp1); + result = (uint32_t)nl_socket_get_peer_groups((struct nl_sock const *)arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_socket_set_peer_groups(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_sock *arg1 = (struct nl_sock *) 0 ; + uint32_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_socket_set_peer_groups",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_socket_set_peer_groups" "', argument " "1"" of type '" "struct nl_sock *""'"); + } + arg1 = (struct nl_sock *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_socket_set_peer_groups" "', argument " "2"" of type '" "uint32_t""'"); + } + arg2 = (uint32_t)(val2); + nl_socket_set_peer_groups(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_socket_set_buffer_size(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_sock *arg1 = (struct nl_sock *) 0 ; + int arg2 ; + int arg3 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + int val3 ; + int ecode3 = 0 ; + PyObject *swig_obj[3] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nl_socket_set_buffer_size",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_socket_set_buffer_size" "', argument " "1"" of type '" "struct nl_sock *""'"); + } + arg1 = (struct nl_sock *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_socket_set_buffer_size" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "nl_socket_set_buffer_size" "', argument " "3"" of type '" "int""'"); + } + arg3 = (int)(val3); + result = (int)nl_socket_set_buffer_size(arg1,arg2,arg3); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_size(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + int arg1 ; + int val1 ; + int ecode1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nlmsg_size" "', argument " "1"" of type '" "int""'"); + } + arg1 = (int)(val1); + result = (int)nlmsg_size(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_total_size(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + int arg1 ; + int val1 ; + int ecode1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nlmsg_total_size" "', argument " "1"" of type '" "int""'"); + } + arg1 = (int)(val1); + result = (int)nlmsg_total_size(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_padlen(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + int arg1 ; + int val1 ; + int ecode1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nlmsg_padlen" "', argument " "1"" of type '" "int""'"); + } + arg1 = (int)(val1); + result = (int)nlmsg_padlen(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_data(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nlmsghdr *arg1 = (struct nlmsghdr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + void *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlmsghdr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_data" "', argument " "1"" of type '" "struct nlmsghdr const *""'"); + } + arg1 = (struct nlmsghdr *)(argp1); + result = (void *)nlmsg_data((struct nlmsghdr const *)arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_void, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_datalen(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nlmsghdr *arg1 = (struct nlmsghdr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlmsghdr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_datalen" "', argument " "1"" of type '" "struct nlmsghdr const *""'"); + } + arg1 = (struct nlmsghdr *)(argp1); + result = (int)nlmsg_datalen((struct nlmsghdr const *)arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_tail(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nlmsghdr *arg1 = (struct nlmsghdr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + void *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlmsghdr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_tail" "', argument " "1"" of type '" "struct nlmsghdr const *""'"); + } + arg1 = (struct nlmsghdr *)(argp1); + result = (void *)nlmsg_tail((struct nlmsghdr const *)arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_void, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_attrdata(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nlmsghdr *arg1 = (struct nlmsghdr *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + struct nlattr *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"nlmsg_attrdata",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlmsghdr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_attrdata" "', argument " "1"" of type '" "struct nlmsghdr const *""'"); + } + arg1 = (struct nlmsghdr *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nlmsg_attrdata" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + result = (struct nlattr *)nlmsg_attrdata((struct nlmsghdr const *)arg1,arg2); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nlattr, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_attrlen(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nlmsghdr *arg1 = (struct nlmsghdr *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nlmsg_attrlen",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlmsghdr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_attrlen" "', argument " "1"" of type '" "struct nlmsghdr const *""'"); + } + arg1 = (struct nlmsghdr *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nlmsg_attrlen" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + result = (int)nlmsg_attrlen((struct nlmsghdr const *)arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_valid_hdr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nlmsghdr *arg1 = (struct nlmsghdr *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nlmsg_valid_hdr",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlmsghdr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_valid_hdr" "', argument " "1"" of type '" "struct nlmsghdr const *""'"); + } + arg1 = (struct nlmsghdr *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nlmsg_valid_hdr" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + result = (int)nlmsg_valid_hdr((struct nlmsghdr const *)arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_ok(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nlmsghdr *arg1 = (struct nlmsghdr *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nlmsg_ok",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlmsghdr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_ok" "', argument " "1"" of type '" "struct nlmsghdr const *""'"); + } + arg1 = (struct nlmsghdr *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nlmsg_ok" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + result = (int)nlmsg_ok((struct nlmsghdr const *)arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_next(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nlmsghdr *arg1 = (struct nlmsghdr *) 0 ; + int *arg2 = (int *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + struct nlmsghdr *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"nlmsg_next",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlmsghdr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_next" "', argument " "1"" of type '" "struct nlmsghdr *""'"); + } + arg1 = (struct nlmsghdr *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_int, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nlmsg_next" "', argument " "2"" of type '" "int *""'"); + } + arg2 = (int *)(argp2); + result = (struct nlmsghdr *)nlmsg_next(arg1,arg2); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nlmsghdr, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_parse(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nlmsghdr *arg1 = (struct nlmsghdr *) 0 ; + int arg2 ; + struct nlattr **arg3 = (struct nlattr **) 0 ; + int arg4 ; + struct nla_policy *arg5 = (struct nla_policy *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + void *argp3 = 0 ; + int res3 = 0 ; + int val4 ; + int ecode4 = 0 ; + void *argp5 = 0 ; + int res5 = 0 ; + PyObject *swig_obj[5] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nlmsg_parse",5,5,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlmsghdr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_parse" "', argument " "1"" of type '" "struct nlmsghdr *""'"); + } + arg1 = (struct nlmsghdr *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nlmsg_parse" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + res3 = SWIG_ConvertPtr(swig_obj[2], &argp3,SWIGTYPE_p_p_nlattr, 0 | 0 ); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "nlmsg_parse" "', argument " "3"" of type '" "struct nlattr **""'"); + } + arg3 = (struct nlattr **)(argp3); + ecode4 = SWIG_AsVal_int(swig_obj[3], &val4); + if (!SWIG_IsOK(ecode4)) { + SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "nlmsg_parse" "', argument " "4"" of type '" "int""'"); + } + arg4 = (int)(val4); + res5 = SWIG_ConvertPtr(swig_obj[4], &argp5,SWIGTYPE_p_nla_policy, 0 | 0 ); + if (!SWIG_IsOK(res5)) { + SWIG_exception_fail(SWIG_ArgError(res5), "in method '" "nlmsg_parse" "', argument " "5"" of type '" "struct nla_policy *""'"); + } + arg5 = (struct nla_policy *)(argp5); + result = (int)nlmsg_parse(arg1,arg2,arg3,arg4,arg5); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_find_attr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nlmsghdr *arg1 = (struct nlmsghdr *) 0 ; + int arg2 ; + int arg3 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + int val3 ; + int ecode3 = 0 ; + PyObject *swig_obj[3] ; + struct nlattr *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"nlmsg_find_attr",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlmsghdr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_find_attr" "', argument " "1"" of type '" "struct nlmsghdr *""'"); + } + arg1 = (struct nlmsghdr *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nlmsg_find_attr" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "nlmsg_find_attr" "', argument " "3"" of type '" "int""'"); + } + arg3 = (int)(val3); + result = (struct nlattr *)nlmsg_find_attr(arg1,arg2,arg3); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nlattr, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_validate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nlmsghdr *arg1 = (struct nlmsghdr *) 0 ; + int arg2 ; + int arg3 ; + struct nla_policy *arg4 = (struct nla_policy *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + int val3 ; + int ecode3 = 0 ; + void *argp4 = 0 ; + int res4 = 0 ; + PyObject *swig_obj[4] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nlmsg_validate",4,4,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlmsghdr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_validate" "', argument " "1"" of type '" "struct nlmsghdr *""'"); + } + arg1 = (struct nlmsghdr *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nlmsg_validate" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "nlmsg_validate" "', argument " "3"" of type '" "int""'"); + } + arg3 = (int)(val3); + res4 = SWIG_ConvertPtr(swig_obj[3], &argp4,SWIGTYPE_p_nla_policy, 0 | 0 ); + if (!SWIG_IsOK(res4)) { + SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "nlmsg_validate" "', argument " "4"" of type '" "struct nla_policy *""'"); + } + arg4 = (struct nla_policy *)(argp4); + result = (int)nlmsg_validate(arg1,arg2,arg3,arg4); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_alloc(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_msg *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"nlmsg_alloc",0,0,0)) SWIG_fail; + result = (struct nl_msg *)nlmsg_alloc(); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_msg, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_alloc_size(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + size_t arg1 ; + size_t val1 ; + int ecode1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_msg *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + ecode1 = SWIG_AsVal_size_t(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nlmsg_alloc_size" "', argument " "1"" of type '" "size_t""'"); + } + arg1 = (size_t)(val1); + result = (struct nl_msg *)nlmsg_alloc_size(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_msg, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_alloc_simple(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + int arg1 ; + int arg2 ; + int val1 ; + int ecode1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + struct nl_msg *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"nlmsg_alloc_simple",2,2,swig_obj)) SWIG_fail; + ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nlmsg_alloc_simple" "', argument " "1"" of type '" "int""'"); + } + arg1 = (int)(val1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nlmsg_alloc_simple" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + result = (struct nl_msg *)nlmsg_alloc_simple(arg1,arg2); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_msg, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_set_default_size(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + size_t arg1 ; + size_t val1 ; + int ecode1 = 0 ; + PyObject *swig_obj[1] ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + ecode1 = SWIG_AsVal_size_t(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nlmsg_set_default_size" "', argument " "1"" of type '" "size_t""'"); + } + arg1 = (size_t)(val1); + nlmsg_set_default_size(arg1); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_inherit(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nlmsghdr *arg1 = (struct nlmsghdr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_msg *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlmsghdr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_inherit" "', argument " "1"" of type '" "struct nlmsghdr *""'"); + } + arg1 = (struct nlmsghdr *)(argp1); + result = (struct nl_msg *)nlmsg_inherit(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_msg, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_convert(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nlmsghdr *arg1 = (struct nlmsghdr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_msg *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlmsghdr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_convert" "', argument " "1"" of type '" "struct nlmsghdr *""'"); + } + arg1 = (struct nlmsghdr *)(argp1); + result = (struct nl_msg *)nlmsg_convert(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_msg, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_reserve(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_msg *arg1 = (struct nl_msg *) 0 ; + size_t arg2 ; + int arg3 ; + void *argp1 = 0 ; + int res1 = 0 ; + size_t val2 ; + int ecode2 = 0 ; + int val3 ; + int ecode3 = 0 ; + PyObject *swig_obj[3] ; + void *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"nlmsg_reserve",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_reserve" "', argument " "1"" of type '" "struct nl_msg *""'"); + } + arg1 = (struct nl_msg *)(argp1); + ecode2 = SWIG_AsVal_size_t(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nlmsg_reserve" "', argument " "2"" of type '" "size_t""'"); + } + arg2 = (size_t)(val2); + ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "nlmsg_reserve" "', argument " "3"" of type '" "int""'"); + } + arg3 = (int)(val3); + result = (void *)nlmsg_reserve(arg1,arg2,arg3); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_void, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_append(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_msg *arg1 = (struct nl_msg *) 0 ; + void *arg2 = (void *) 0 ; + size_t arg3 ; + int arg4 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 ; + size_t val3 ; + int ecode3 = 0 ; + int val4 ; + int ecode4 = 0 ; + PyObject *swig_obj[4] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nlmsg_append",4,4,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_append" "', argument " "1"" of type '" "struct nl_msg *""'"); + } + arg1 = (struct nl_msg *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1],SWIG_as_voidptrptr(&arg2), 0, 0); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nlmsg_append" "', argument " "2"" of type '" "void *""'"); + } + ecode3 = SWIG_AsVal_size_t(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "nlmsg_append" "', argument " "3"" of type '" "size_t""'"); + } + arg3 = (size_t)(val3); + ecode4 = SWIG_AsVal_int(swig_obj[3], &val4); + if (!SWIG_IsOK(ecode4)) { + SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "nlmsg_append" "', argument " "4"" of type '" "int""'"); + } + arg4 = (int)(val4); + result = (int)nlmsg_append(arg1,arg2,arg3,arg4); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_expand(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_msg *arg1 = (struct nl_msg *) 0 ; + size_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + size_t val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nlmsg_expand",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_expand" "', argument " "1"" of type '" "struct nl_msg *""'"); + } + arg1 = (struct nl_msg *)(argp1); + ecode2 = SWIG_AsVal_size_t(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nlmsg_expand" "', argument " "2"" of type '" "size_t""'"); + } + arg2 = (size_t)(val2); + result = (int)nlmsg_expand(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_put(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_msg *arg1 = (struct nl_msg *) 0 ; + uint32_t arg2 ; + uint32_t arg3 ; + int arg4 ; + int arg5 ; + int arg6 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + unsigned int val3 ; + int ecode3 = 0 ; + int val4 ; + int ecode4 = 0 ; + int val5 ; + int ecode5 = 0 ; + int val6 ; + int ecode6 = 0 ; + PyObject *swig_obj[6] ; + struct nlmsghdr *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"nlmsg_put",6,6,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_put" "', argument " "1"" of type '" "struct nl_msg *""'"); + } + arg1 = (struct nl_msg *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nlmsg_put" "', argument " "2"" of type '" "uint32_t""'"); + } + arg2 = (uint32_t)(val2); + ecode3 = SWIG_AsVal_unsigned_SS_int(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "nlmsg_put" "', argument " "3"" of type '" "uint32_t""'"); + } + arg3 = (uint32_t)(val3); + ecode4 = SWIG_AsVal_int(swig_obj[3], &val4); + if (!SWIG_IsOK(ecode4)) { + SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "nlmsg_put" "', argument " "4"" of type '" "int""'"); + } + arg4 = (int)(val4); + ecode5 = SWIG_AsVal_int(swig_obj[4], &val5); + if (!SWIG_IsOK(ecode5)) { + SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "nlmsg_put" "', argument " "5"" of type '" "int""'"); + } + arg5 = (int)(val5); + ecode6 = SWIG_AsVal_int(swig_obj[5], &val6); + if (!SWIG_IsOK(ecode6)) { + SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "nlmsg_put" "', argument " "6"" of type '" "int""'"); + } + arg6 = (int)(val6); + result = (struct nlmsghdr *)nlmsg_put(arg1,arg2,arg3,arg4,arg5,arg6); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nlmsghdr, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_hdr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_msg *arg1 = (struct nl_msg *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct nlmsghdr *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_hdr" "', argument " "1"" of type '" "struct nl_msg *""'"); + } + arg1 = (struct nl_msg *)(argp1); + result = (struct nlmsghdr *)nlmsg_hdr(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nlmsghdr, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_msg *arg1 = (struct nl_msg *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_get" "', argument " "1"" of type '" "struct nl_msg *""'"); + } + arg1 = (struct nl_msg *)(argp1); + nlmsg_get(arg1); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_free(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_msg *arg1 = (struct nl_msg *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_free" "', argument " "1"" of type '" "struct nl_msg *""'"); + } + arg1 = (struct nl_msg *)(argp1); + nlmsg_free(arg1); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_set_proto(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_msg *arg1 = (struct nl_msg *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nlmsg_set_proto",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_set_proto" "', argument " "1"" of type '" "struct nl_msg *""'"); + } + arg1 = (struct nl_msg *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nlmsg_set_proto" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + nlmsg_set_proto(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_get_proto(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_msg *arg1 = (struct nl_msg *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_get_proto" "', argument " "1"" of type '" "struct nl_msg *""'"); + } + arg1 = (struct nl_msg *)(argp1); + result = (int)nlmsg_get_proto(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_get_max_size(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_msg *arg1 = (struct nl_msg *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + size_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_get_max_size" "', argument " "1"" of type '" "struct nl_msg *""'"); + } + arg1 = (struct nl_msg *)(argp1); + result = nlmsg_get_max_size(arg1); + resultobj = SWIG_From_size_t((size_t)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_set_src(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_msg *arg1 = (struct nl_msg *) 0 ; + struct sockaddr_nl *arg2 = (struct sockaddr_nl *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nlmsg_set_src",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_set_src" "', argument " "1"" of type '" "struct nl_msg *""'"); + } + arg1 = (struct nl_msg *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_sockaddr_nl, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nlmsg_set_src" "', argument " "2"" of type '" "struct sockaddr_nl *""'"); + } + arg2 = (struct sockaddr_nl *)(argp2); + nlmsg_set_src(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_get_src(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_msg *arg1 = (struct nl_msg *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct sockaddr_nl *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_get_src" "', argument " "1"" of type '" "struct nl_msg *""'"); + } + arg1 = (struct nl_msg *)(argp1); + result = (struct sockaddr_nl *)nlmsg_get_src(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_sockaddr_nl, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_set_dst(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_msg *arg1 = (struct nl_msg *) 0 ; + struct sockaddr_nl *arg2 = (struct sockaddr_nl *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nlmsg_set_dst",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_set_dst" "', argument " "1"" of type '" "struct nl_msg *""'"); + } + arg1 = (struct nl_msg *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_sockaddr_nl, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nlmsg_set_dst" "', argument " "2"" of type '" "struct sockaddr_nl *""'"); + } + arg2 = (struct sockaddr_nl *)(argp2); + nlmsg_set_dst(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_get_dst(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_msg *arg1 = (struct nl_msg *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct sockaddr_nl *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_get_dst" "', argument " "1"" of type '" "struct nl_msg *""'"); + } + arg1 = (struct nl_msg *)(argp1); + result = (struct sockaddr_nl *)nlmsg_get_dst(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_sockaddr_nl, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_set_creds(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_msg *arg1 = (struct nl_msg *) 0 ; + struct ucred *arg2 = (struct ucred *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nlmsg_set_creds",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_set_creds" "', argument " "1"" of type '" "struct nl_msg *""'"); + } + arg1 = (struct nl_msg *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_ucred, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nlmsg_set_creds" "', argument " "2"" of type '" "struct ucred *""'"); + } + arg2 = (struct ucred *)(argp2); + nlmsg_set_creds(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nlmsg_get_creds(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_msg *arg1 = (struct nl_msg *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct ucred *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_get_creds" "', argument " "1"" of type '" "struct nl_msg *""'"); + } + arg1 = (struct nl_msg *)(argp1); + result = (struct ucred *)nlmsg_get_creds(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_ucred, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_nlmsgtype2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + int arg1 ; + char *arg2 = (char *) 0 ; + size_t arg3 ; + int val1 ; + int ecode1 = 0 ; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + size_t val3 ; + int ecode3 = 0 ; + PyObject *swig_obj[3] ; + char *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"nl_nlmsgtype2str",3,3,swig_obj)) SWIG_fail; + ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_nlmsgtype2str" "', argument " "1"" of type '" "int""'"); + } + arg1 = (int)(val1); + res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_nlmsgtype2str" "', argument " "2"" of type '" "char *""'"); + } + arg2 = (char *)(buf2); + ecode3 = SWIG_AsVal_size_t(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "nl_nlmsgtype2str" "', argument " "3"" of type '" "size_t""'"); + } + arg3 = (size_t)(val3); + result = (char *)nl_nlmsgtype2str(arg1,arg2,arg3); + resultobj = SWIG_FromCharPtr((const char *)result); + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return resultobj; +fail: + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_str2nlmsgtype(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + char *arg1 = (char *) 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_str2nlmsgtype" "', argument " "1"" of type '" "char const *""'"); + } + arg1 = (char *)(buf1); + result = (int)nl_str2nlmsgtype((char const *)arg1); + resultobj = SWIG_From_int((int)(result)); + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_nlmsg_flags2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + int arg1 ; + char *arg2 = (char *) 0 ; + size_t arg3 ; + int val1 ; + int ecode1 = 0 ; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + size_t val3 ; + int ecode3 = 0 ; + PyObject *swig_obj[3] ; + char *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"nl_nlmsg_flags2str",3,3,swig_obj)) SWIG_fail; + ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_nlmsg_flags2str" "', argument " "1"" of type '" "int""'"); + } + arg1 = (int)(val1); + res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_nlmsg_flags2str" "', argument " "2"" of type '" "char *""'"); + } + arg2 = (char *)(buf2); + ecode3 = SWIG_AsVal_size_t(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "nl_nlmsg_flags2str" "', argument " "3"" of type '" "size_t""'"); + } + arg3 = (size_t)(val3); + result = (char *)nl_nlmsg_flags2str(arg1,arg2,arg3); + resultobj = SWIG_FromCharPtr((const char *)result); + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return resultobj; +fail: + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_msg_parse(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_msg *arg1 = (struct nl_msg *) 0 ; + void (*arg2)(struct nl_object *,void *) = (void (*)(struct nl_object *,void *)) 0 ; + void *arg3 = (void *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res3 ; + PyObject *swig_obj[3] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nl_msg_parse",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_msg_parse" "', argument " "1"" of type '" "struct nl_msg *""'"); + } + arg1 = (struct nl_msg *)(argp1); + { + int res = SWIG_ConvertFunctionPtr(swig_obj[1], (void**)(&arg2), SWIGTYPE_p_f_p_struct_nl_object_p_void__void); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in method '" "nl_msg_parse" "', argument " "2"" of type '" "void (*)(struct nl_object *,void *)""'"); + } + } + res3 = SWIG_ConvertPtr(swig_obj[2],SWIG_as_voidptrptr(&arg3), 0, 0); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "nl_msg_parse" "', argument " "3"" of type '" "void *""'"); + } + result = (int)nl_msg_parse(arg1,arg2,arg3); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_msg_dump(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_msg *arg1 = (struct nl_msg *) 0 ; + FILE *arg2 = (FILE *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_msg_dump",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_msg_dump" "', argument " "1"" of type '" "struct nl_msg *""'"); + } + arg1 = (struct nl_msg *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_FILE, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_msg_dump" "', argument " "2"" of type '" "FILE *""'"); + } + arg2 = (FILE *)(argp2); + nl_msg_dump(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_cast_obj(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + void *arg1 = (void *) 0 ; + int res1 ; + PyObject *swig_obj[1] ; + struct nl_object *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0],SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "cast_obj" "', argument " "1"" of type '" "void *""'"); + } + result = (struct nl_object *)cast_obj(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_object_alloc_name(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + char *arg1 = (char *) 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_object *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "object_alloc_name" "', argument " "1"" of type '" "char const *""'"); + } + arg1 = (char *)(buf1); + result = (struct nl_object *)object_alloc_name((char const *)arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_object_alloc(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_object_ops *arg1 = (struct nl_object_ops *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_object *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object_ops, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_alloc" "', argument " "1"" of type '" "struct nl_object_ops *""'"); + } + arg1 = (struct nl_object_ops *)(argp1); + result = (struct nl_object *)nl_object_alloc(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_object_free(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_object *arg1 = (struct nl_object *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_free" "', argument " "1"" of type '" "struct nl_object *""'"); + } + arg1 = (struct nl_object *)(argp1); + nl_object_free(arg1); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_object_clone(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_object *arg1 = (struct nl_object *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_object *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_clone" "', argument " "1"" of type '" "struct nl_object *""'"); + } + arg1 = (struct nl_object *)(argp1); + result = (struct nl_object *)nl_object_clone(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_object_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_object *arg1 = (struct nl_object *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_get" "', argument " "1"" of type '" "struct nl_object *""'"); + } + arg1 = (struct nl_object *)(argp1); + nl_object_get(arg1); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_object_put(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_object *arg1 = (struct nl_object *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_put" "', argument " "1"" of type '" "struct nl_object *""'"); + } + arg1 = (struct nl_object *)(argp1); + nl_object_put(arg1); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_object_shared(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_object *arg1 = (struct nl_object *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_shared" "', argument " "1"" of type '" "struct nl_object *""'"); + } + arg1 = (struct nl_object *)(argp1); + result = (int)nl_object_shared(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_object_dump_buf(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_object *arg1 = (struct nl_object *) 0 ; + char *arg2 = (char *) 0 ; + size_t arg3 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 ; + size_t size2 ; + char *buff2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_object_dump_buf",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_dump_buf" "', argument " "1"" of type '" "struct nl_object *""'"); + } + arg1 = (struct nl_object *)(argp1); + res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_object_dump_buf" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); + } + buff2= (char *)malloc((size2+1)*sizeof(char)); + arg3 = (size_t)(size2); + arg2 = (char *)(buff2); + nl_object_dump_buf(arg1,arg2,arg3); + resultobj = SWIG_Py_Void(); + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); + if (buff2) free((char*)buff2); + return resultobj; +fail: + if (buff2) free((char*)buff2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_object_dump(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_object *arg1 = (struct nl_object *) 0 ; + struct nl_dump_params *arg2 = (struct nl_dump_params *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_object_dump",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_dump" "', argument " "1"" of type '" "struct nl_object *""'"); + } + arg1 = (struct nl_object *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_object_dump" "', argument " "2"" of type '" "struct nl_dump_params *""'"); + } + arg2 = (struct nl_dump_params *)(argp2); + nl_object_dump(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_object_identical(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_object *arg1 = (struct nl_object *) 0 ; + struct nl_object *arg2 = (struct nl_object *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nl_object_identical",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_identical" "', argument " "1"" of type '" "struct nl_object *""'"); + } + arg1 = (struct nl_object *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_object_identical" "', argument " "2"" of type '" "struct nl_object *""'"); + } + arg2 = (struct nl_object *)(argp2); + result = (int)nl_object_identical(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_object_diff(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_object *arg1 = (struct nl_object *) 0 ; + struct nl_object *arg2 = (struct nl_object *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + uint32_t result; + + if (!SWIG_Python_UnpackTuple(args,"nl_object_diff",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_diff" "', argument " "1"" of type '" "struct nl_object *""'"); + } + arg1 = (struct nl_object *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_object_diff" "', argument " "2"" of type '" "struct nl_object *""'"); + } + arg2 = (struct nl_object *)(argp2); + result = (uint32_t)nl_object_diff(arg1,arg2); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_object_match_filter(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_object *arg1 = (struct nl_object *) 0 ; + struct nl_object *arg2 = (struct nl_object *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nl_object_match_filter",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_match_filter" "', argument " "1"" of type '" "struct nl_object *""'"); + } + arg1 = (struct nl_object *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_object_match_filter" "', argument " "2"" of type '" "struct nl_object *""'"); + } + arg2 = (struct nl_object *)(argp2); + result = (int)nl_object_match_filter(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_object_attrs2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_object *arg1 = (struct nl_object *) 0 ; + uint32_t arg2 ; + char *arg3 = (char *) 0 ; + size_t arg4 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + int res3 ; + size_t size3 ; + char *buff3 = 0 ; + PyObject *swig_obj[3] ; + char *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"nl_object_attrs2str",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_attrs2str" "', argument " "1"" of type '" "struct nl_object *""'"); + } + arg1 = (struct nl_object *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_object_attrs2str" "', argument " "2"" of type '" "uint32_t""'"); + } + arg2 = (uint32_t)(val2); + res3 = SWIG_AsVal_size_t (swig_obj[2], &size3); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "nl_object_attrs2str" "', argument " "3"" of type '" "(char *buf, size_t len)""'"); + } + buff3= (char *)malloc((size3+1)*sizeof(char)); + arg4 = (size_t)(size3); + arg3 = (char *)(buff3); + result = (char *)nl_object_attrs2str(arg1,arg2,arg3,arg4); + resultobj = SWIG_FromCharPtr((const char *)result); + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg3)); + if (buff3) free((char*)buff3); + return resultobj; +fail: + if (buff3) free((char*)buff3); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_object_attr_list(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_object *arg1 = (struct nl_object *) 0 ; + char *arg2 = (char *) 0 ; + size_t arg3 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 ; + size_t size2 ; + char *buff2 = 0 ; + PyObject *swig_obj[2] ; + char *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"nl_object_attr_list",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_attr_list" "', argument " "1"" of type '" "struct nl_object *""'"); + } + arg1 = (struct nl_object *)(argp1); + res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_object_attr_list" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); + } + buff2= (char *)malloc((size2+1)*sizeof(char)); + arg3 = (size_t)(size2); + arg2 = (char *)(buff2); + result = (char *)nl_object_attr_list(arg1,arg2,arg3); + resultobj = SWIG_FromCharPtr((const char *)result); + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); + if (buff2) free((char*)buff2); + return resultobj; +fail: + if (buff2) free((char*)buff2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_object_mark(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_object *arg1 = (struct nl_object *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_mark" "', argument " "1"" of type '" "struct nl_object *""'"); + } + arg1 = (struct nl_object *)(argp1); + nl_object_mark(arg1); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_object_unmark(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_object *arg1 = (struct nl_object *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_unmark" "', argument " "1"" of type '" "struct nl_object *""'"); + } + arg1 = (struct nl_object *)(argp1); + nl_object_unmark(arg1); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_object_is_marked(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_object *arg1 = (struct nl_object *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_is_marked" "', argument " "1"" of type '" "struct nl_object *""'"); + } + arg1 = (struct nl_object *)(argp1); + result = (int)nl_object_is_marked(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_object_get_refcnt(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_object *arg1 = (struct nl_object *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_get_refcnt" "', argument " "1"" of type '" "struct nl_object *""'"); + } + arg1 = (struct nl_object *)(argp1); + result = (int)nl_object_get_refcnt(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_alloc_cache_name(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + char *arg1 = (char *) 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_cache *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "alloc_cache_name" "', argument " "1"" of type '" "char const *""'"); + } + arg1 = (char *)(buf1); + result = (struct nl_cache *)alloc_cache_name((char const *)arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_cache, 0 | 0 ); + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_alloc_cache_mngr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_sock *arg1 = (struct nl_sock *) 0 ; + int arg2 ; + int arg3 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + int val3 ; + int ecode3 = 0 ; + PyObject *swig_obj[3] ; + struct nl_cache_mngr *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"alloc_cache_mngr",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "alloc_cache_mngr" "', argument " "1"" of type '" "struct nl_sock *""'"); + } + arg1 = (struct nl_sock *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "alloc_cache_mngr" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "alloc_cache_mngr" "', argument " "3"" of type '" "int""'"); + } + arg3 = (int)(val3); + result = (struct nl_cache_mngr *)alloc_cache_mngr(arg1,arg2,arg3); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_cache_mngr, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_cache_mngr_add(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache_mngr *arg1 = (struct nl_cache_mngr *) 0 ; + char *arg2 = (char *) 0 ; + change_func_t arg3 = (change_func_t) 0 ; + void *arg4 = (void *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + int res4 ; + PyObject *swig_obj[4] ; + struct nl_cache *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"cache_mngr_add",4,4,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache_mngr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "cache_mngr_add" "', argument " "1"" of type '" "struct nl_cache_mngr *""'"); + } + arg1 = (struct nl_cache_mngr *)(argp1); + res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "cache_mngr_add" "', argument " "2"" of type '" "char const *""'"); + } + arg2 = (char *)(buf2); + { + int res = SWIG_ConvertFunctionPtr(swig_obj[2], (void**)(&arg3), SWIGTYPE_p_f_p_struct_nl_cache_p_struct_nl_object_int_p_void__void); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in method '" "cache_mngr_add" "', argument " "3"" of type '" "change_func_t""'"); + } + } + res4 = SWIG_ConvertPtr(swig_obj[3],SWIG_as_voidptrptr(&arg4), 0, 0); + if (!SWIG_IsOK(res4)) { + SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "cache_mngr_add" "', argument " "4"" of type '" "void *""'"); + } + result = (struct nl_cache *)cache_mngr_add(arg1,(char const *)arg2,arg3,arg4); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_cache, 0 | 0 ); + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return resultobj; +fail: + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_nitems(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache *arg1 = (struct nl_cache *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_nitems" "', argument " "1"" of type '" "struct nl_cache *""'"); + } + arg1 = (struct nl_cache *)(argp1); + result = (int)nl_cache_nitems(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_nitems_filter(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache *arg1 = (struct nl_cache *) 0 ; + struct nl_object *arg2 = (struct nl_object *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nl_cache_nitems_filter",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_nitems_filter" "', argument " "1"" of type '" "struct nl_cache *""'"); + } + arg1 = (struct nl_cache *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cache_nitems_filter" "', argument " "2"" of type '" "struct nl_object *""'"); + } + arg2 = (struct nl_object *)(argp2); + result = (int)nl_cache_nitems_filter(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_get_ops(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache *arg1 = (struct nl_cache *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_cache_ops *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_get_ops" "', argument " "1"" of type '" "struct nl_cache *""'"); + } + arg1 = (struct nl_cache *)(argp1); + result = (struct nl_cache_ops *)nl_cache_get_ops(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_cache_ops, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_get_first(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache *arg1 = (struct nl_cache *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_object *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_get_first" "', argument " "1"" of type '" "struct nl_cache *""'"); + } + arg1 = (struct nl_cache *)(argp1); + result = (struct nl_object *)nl_cache_get_first(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_get_last(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache *arg1 = (struct nl_cache *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_object *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_get_last" "', argument " "1"" of type '" "struct nl_cache *""'"); + } + arg1 = (struct nl_cache *)(argp1); + result = (struct nl_object *)nl_cache_get_last(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_get_next(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_object *arg1 = (struct nl_object *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_object *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_get_next" "', argument " "1"" of type '" "struct nl_object *""'"); + } + arg1 = (struct nl_object *)(argp1); + result = (struct nl_object *)nl_cache_get_next(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_get_prev(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_object *arg1 = (struct nl_object *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_object *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_get_prev" "', argument " "1"" of type '" "struct nl_object *""'"); + } + arg1 = (struct nl_object *)(argp1); + result = (struct nl_object *)nl_cache_get_prev(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_alloc(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache_ops *arg1 = (struct nl_cache_ops *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_cache *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache_ops, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_alloc" "', argument " "1"" of type '" "struct nl_cache_ops *""'"); + } + arg1 = (struct nl_cache_ops *)(argp1); + result = (struct nl_cache *)nl_cache_alloc(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_cache, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_subset(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache *arg1 = (struct nl_cache *) 0 ; + struct nl_object *arg2 = (struct nl_object *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + struct nl_cache *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"nl_cache_subset",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_subset" "', argument " "1"" of type '" "struct nl_cache *""'"); + } + arg1 = (struct nl_cache *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cache_subset" "', argument " "2"" of type '" "struct nl_object *""'"); + } + arg2 = (struct nl_object *)(argp2); + result = (struct nl_cache *)nl_cache_subset(arg1,arg2); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_cache, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_clear(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache *arg1 = (struct nl_cache *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_clear" "', argument " "1"" of type '" "struct nl_cache *""'"); + } + arg1 = (struct nl_cache *)(argp1); + nl_cache_clear(arg1); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_free(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache *arg1 = (struct nl_cache *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_free" "', argument " "1"" of type '" "struct nl_cache *""'"); + } + arg1 = (struct nl_cache *)(argp1); + nl_cache_free(arg1); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_add(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache *arg1 = (struct nl_cache *) 0 ; + struct nl_object *arg2 = (struct nl_object *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nl_cache_add",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_add" "', argument " "1"" of type '" "struct nl_cache *""'"); + } + arg1 = (struct nl_cache *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cache_add" "', argument " "2"" of type '" "struct nl_object *""'"); + } + arg2 = (struct nl_object *)(argp2); + result = (int)nl_cache_add(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_parse_and_add(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache *arg1 = (struct nl_cache *) 0 ; + struct nl_msg *arg2 = (struct nl_msg *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nl_cache_parse_and_add",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_parse_and_add" "', argument " "1"" of type '" "struct nl_cache *""'"); + } + arg1 = (struct nl_cache *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cache_parse_and_add" "', argument " "2"" of type '" "struct nl_msg *""'"); + } + arg2 = (struct nl_msg *)(argp2); + result = (int)nl_cache_parse_and_add(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_remove(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_object *arg1 = (struct nl_object *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_remove" "', argument " "1"" of type '" "struct nl_object *""'"); + } + arg1 = (struct nl_object *)(argp1); + nl_cache_remove(arg1); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_refill(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_sock *arg1 = (struct nl_sock *) 0 ; + struct nl_cache *arg2 = (struct nl_cache *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nl_cache_refill",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_refill" "', argument " "1"" of type '" "struct nl_sock *""'"); + } + arg1 = (struct nl_sock *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cache_refill" "', argument " "2"" of type '" "struct nl_cache *""'"); + } + arg2 = (struct nl_cache *)(argp2); + result = (int)nl_cache_refill(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_pickup(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_sock *arg1 = (struct nl_sock *) 0 ; + struct nl_cache *arg2 = (struct nl_cache *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nl_cache_pickup",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_pickup" "', argument " "1"" of type '" "struct nl_sock *""'"); + } + arg1 = (struct nl_sock *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cache_pickup" "', argument " "2"" of type '" "struct nl_cache *""'"); + } + arg2 = (struct nl_cache *)(argp2); + result = (int)nl_cache_pickup(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_resync(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_sock *arg1 = (struct nl_sock *) 0 ; + struct nl_cache *arg2 = (struct nl_cache *) 0 ; + change_func_t arg3 = (change_func_t) 0 ; + void *arg4 = (void *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + int res4 ; + PyObject *swig_obj[4] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nl_cache_resync",4,4,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_resync" "', argument " "1"" of type '" "struct nl_sock *""'"); + } + arg1 = (struct nl_sock *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cache_resync" "', argument " "2"" of type '" "struct nl_cache *""'"); + } + arg2 = (struct nl_cache *)(argp2); + { + int res = SWIG_ConvertFunctionPtr(swig_obj[2], (void**)(&arg3), SWIGTYPE_p_f_p_struct_nl_cache_p_struct_nl_object_int_p_void__void); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in method '" "nl_cache_resync" "', argument " "3"" of type '" "change_func_t""'"); + } + } + res4 = SWIG_ConvertPtr(swig_obj[3],SWIG_as_voidptrptr(&arg4), 0, 0); + if (!SWIG_IsOK(res4)) { + SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "nl_cache_resync" "', argument " "4"" of type '" "void *""'"); + } + result = (int)nl_cache_resync(arg1,arg2,arg3,arg4); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_include(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache *arg1 = (struct nl_cache *) 0 ; + struct nl_object *arg2 = (struct nl_object *) 0 ; + change_func_t arg3 = (change_func_t) 0 ; + void *arg4 = (void *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + int res4 ; + PyObject *swig_obj[4] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nl_cache_include",4,4,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_include" "', argument " "1"" of type '" "struct nl_cache *""'"); + } + arg1 = (struct nl_cache *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cache_include" "', argument " "2"" of type '" "struct nl_object *""'"); + } + arg2 = (struct nl_object *)(argp2); + { + int res = SWIG_ConvertFunctionPtr(swig_obj[2], (void**)(&arg3), SWIGTYPE_p_f_p_struct_nl_cache_p_struct_nl_object_int_p_void__void); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in method '" "nl_cache_include" "', argument " "3"" of type '" "change_func_t""'"); + } + } + res4 = SWIG_ConvertPtr(swig_obj[3],SWIG_as_voidptrptr(&arg4), 0, 0); + if (!SWIG_IsOK(res4)) { + SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "nl_cache_include" "', argument " "4"" of type '" "void *""'"); + } + result = (int)nl_cache_include(arg1,arg2,arg3,arg4); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_set_arg1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache *arg1 = (struct nl_cache *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_cache_set_arg1",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_set_arg1" "', argument " "1"" of type '" "struct nl_cache *""'"); + } + arg1 = (struct nl_cache *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_cache_set_arg1" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + nl_cache_set_arg1(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_set_arg2(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache *arg1 = (struct nl_cache *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_cache_set_arg2",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_set_arg2" "', argument " "1"" of type '" "struct nl_cache *""'"); + } + arg1 = (struct nl_cache *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_cache_set_arg2" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + nl_cache_set_arg2(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_is_empty(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache *arg1 = (struct nl_cache *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_is_empty" "', argument " "1"" of type '" "struct nl_cache *""'"); + } + arg1 = (struct nl_cache *)(argp1); + result = (int)nl_cache_is_empty(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_search(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache *arg1 = (struct nl_cache *) 0 ; + struct nl_object *arg2 = (struct nl_object *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + struct nl_object *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"nl_cache_search",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_search" "', argument " "1"" of type '" "struct nl_cache *""'"); + } + arg1 = (struct nl_cache *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cache_search" "', argument " "2"" of type '" "struct nl_object *""'"); + } + arg2 = (struct nl_object *)(argp2); + result = (struct nl_object *)nl_cache_search(arg1,arg2); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_mark_all(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache *arg1 = (struct nl_cache *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_mark_all" "', argument " "1"" of type '" "struct nl_cache *""'"); + } + arg1 = (struct nl_cache *)(argp1); + nl_cache_mark_all(arg1); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_dump(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache *arg1 = (struct nl_cache *) 0 ; + struct nl_dump_params *arg2 = (struct nl_dump_params *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_cache_dump",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_dump" "', argument " "1"" of type '" "struct nl_cache *""'"); + } + arg1 = (struct nl_cache *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cache_dump" "', argument " "2"" of type '" "struct nl_dump_params *""'"); + } + arg2 = (struct nl_dump_params *)(argp2); + nl_cache_dump(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_dump_filter(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache *arg1 = (struct nl_cache *) 0 ; + struct nl_dump_params *arg2 = (struct nl_dump_params *) 0 ; + struct nl_object *arg3 = (struct nl_object *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + void *argp3 = 0 ; + int res3 = 0 ; + PyObject *swig_obj[3] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_cache_dump_filter",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_dump_filter" "', argument " "1"" of type '" "struct nl_cache *""'"); + } + arg1 = (struct nl_cache *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_dump_params, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cache_dump_filter" "', argument " "2"" of type '" "struct nl_dump_params *""'"); + } + arg2 = (struct nl_dump_params *)(argp2); + res3 = SWIG_ConvertPtr(swig_obj[2], &argp3,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "nl_cache_dump_filter" "', argument " "3"" of type '" "struct nl_object *""'"); + } + arg3 = (struct nl_object *)(argp3); + nl_cache_dump_filter(arg1,arg2,arg3); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_foreach(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache *arg1 = (struct nl_cache *) 0 ; + void (*arg2)(struct nl_object *,void *) = (void (*)(struct nl_object *,void *)) 0 ; + void *arg3 = (void *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res3 ; + PyObject *swig_obj[3] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_cache_foreach",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_foreach" "', argument " "1"" of type '" "struct nl_cache *""'"); + } + arg1 = (struct nl_cache *)(argp1); + { + int res = SWIG_ConvertFunctionPtr(swig_obj[1], (void**)(&arg2), SWIGTYPE_p_f_p_struct_nl_object_p_void__void); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in method '" "nl_cache_foreach" "', argument " "2"" of type '" "void (*)(struct nl_object *,void *)""'"); + } + } + res3 = SWIG_ConvertPtr(swig_obj[2],SWIG_as_voidptrptr(&arg3), 0, 0); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "nl_cache_foreach" "', argument " "3"" of type '" "void *""'"); + } + nl_cache_foreach(arg1,arg2,arg3); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_foreach_filter(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache *arg1 = (struct nl_cache *) 0 ; + struct nl_object *arg2 = (struct nl_object *) 0 ; + void (*arg3)(struct nl_object *,void *) = (void (*)(struct nl_object *,void *)) 0 ; + void *arg4 = (void *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + int res4 ; + PyObject *swig_obj[4] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_cache_foreach_filter",4,4,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_foreach_filter" "', argument " "1"" of type '" "struct nl_cache *""'"); + } + arg1 = (struct nl_cache *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cache_foreach_filter" "', argument " "2"" of type '" "struct nl_object *""'"); + } + arg2 = (struct nl_object *)(argp2); + { + int res = SWIG_ConvertFunctionPtr(swig_obj[2], (void**)(&arg3), SWIGTYPE_p_f_p_struct_nl_object_p_void__void); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in method '" "nl_cache_foreach_filter" "', argument " "3"" of type '" "void (*)(struct nl_object *,void *)""'"); + } + } + res4 = SWIG_ConvertPtr(swig_obj[3],SWIG_as_voidptrptr(&arg4), 0, 0); + if (!SWIG_IsOK(res4)) { + SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "nl_cache_foreach_filter" "', argument " "4"" of type '" "void *""'"); + } + nl_cache_foreach_filter(arg1,arg2,arg3,arg4); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_ops_lookup(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + char *arg1 = (char *) 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_cache_ops *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_ops_lookup" "', argument " "1"" of type '" "char const *""'"); + } + arg1 = (char *)(buf1); + result = (struct nl_cache_ops *)nl_cache_ops_lookup((char const *)arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_cache_ops, 0 | 0 ); + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_ops_associate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + int arg1 ; + int arg2 ; + int val1 ; + int ecode1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + struct nl_cache_ops *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"nl_cache_ops_associate",2,2,swig_obj)) SWIG_fail; + ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_cache_ops_associate" "', argument " "1"" of type '" "int""'"); + } + arg1 = (int)(val1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_cache_ops_associate" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + result = (struct nl_cache_ops *)nl_cache_ops_associate(arg1,arg2); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_cache_ops, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_msgtype_lookup(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache_ops *arg1 = (struct nl_cache_ops *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + struct nl_msgtype *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"nl_msgtype_lookup",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache_ops, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_msgtype_lookup" "', argument " "1"" of type '" "struct nl_cache_ops *""'"); + } + arg1 = (struct nl_cache_ops *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_msgtype_lookup" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + result = (struct nl_msgtype *)nl_msgtype_lookup(arg1,arg2); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_msgtype, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_ops_foreach(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + void (*arg1)(struct nl_cache_ops *,void *) = (void (*)(struct nl_cache_ops *,void *)) 0 ; + void *arg2 = (void *) 0 ; + int res2 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_cache_ops_foreach",2,2,swig_obj)) SWIG_fail; + { + int res = SWIG_ConvertFunctionPtr(swig_obj[0], (void**)(&arg1), SWIGTYPE_p_f_p_struct_nl_cache_ops_p_void__void); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in method '" "nl_cache_ops_foreach" "', argument " "1"" of type '" "void (*)(struct nl_cache_ops *,void *)""'"); + } + } + res2 = SWIG_ConvertPtr(swig_obj[1],SWIG_as_voidptrptr(&arg2), 0, 0); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cache_ops_foreach" "', argument " "2"" of type '" "void *""'"); + } + nl_cache_ops_foreach(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_mngt_register(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache_ops *arg1 = (struct nl_cache_ops *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache_ops, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_mngt_register" "', argument " "1"" of type '" "struct nl_cache_ops *""'"); + } + arg1 = (struct nl_cache_ops *)(argp1); + result = (int)nl_cache_mngt_register(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_mngt_unregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache_ops *arg1 = (struct nl_cache_ops *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache_ops, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_mngt_unregister" "', argument " "1"" of type '" "struct nl_cache_ops *""'"); + } + arg1 = (struct nl_cache_ops *)(argp1); + result = (int)nl_cache_mngt_unregister(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_mngt_provide(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache *arg1 = (struct nl_cache *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_mngt_provide" "', argument " "1"" of type '" "struct nl_cache *""'"); + } + arg1 = (struct nl_cache *)(argp1); + nl_cache_mngt_provide(arg1); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_mngt_unprovide(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache *arg1 = (struct nl_cache *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_mngt_unprovide" "', argument " "1"" of type '" "struct nl_cache *""'"); + } + arg1 = (struct nl_cache *)(argp1); + nl_cache_mngt_unprovide(arg1); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_mngt_require(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + char *arg1 = (char *) 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_cache *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_mngt_require" "', argument " "1"" of type '" "char const *""'"); + } + arg1 = (char *)(buf1); + result = (struct nl_cache *)nl_cache_mngt_require((char const *)arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_cache, 0 | 0 ); + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_mngr_get_fd(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache_mngr *arg1 = (struct nl_cache_mngr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache_mngr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_mngr_get_fd" "', argument " "1"" of type '" "struct nl_cache_mngr *""'"); + } + arg1 = (struct nl_cache_mngr *)(argp1); + result = (int)nl_cache_mngr_get_fd(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_mngr_poll(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache_mngr *arg1 = (struct nl_cache_mngr *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nl_cache_mngr_poll",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache_mngr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_mngr_poll" "', argument " "1"" of type '" "struct nl_cache_mngr *""'"); + } + arg1 = (struct nl_cache_mngr *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_cache_mngr_poll" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + result = (int)nl_cache_mngr_poll(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_mngr_data_ready(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache_mngr *arg1 = (struct nl_cache_mngr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache_mngr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_mngr_data_ready" "', argument " "1"" of type '" "struct nl_cache_mngr *""'"); + } + arg1 = (struct nl_cache_mngr *)(argp1); + result = (int)nl_cache_mngr_data_ready(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_cache_mngr_free(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache_mngr *arg1 = (struct nl_cache_mngr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache_mngr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_mngr_free" "', argument " "1"" of type '" "struct nl_cache_mngr *""'"); + } + arg1 = (struct nl_cache_mngr *)(argp1); + nl_cache_mngr_free(arg1); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_addr_parse(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + char *arg1 = (char *) 0 ; + int arg2 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + struct nl_addr *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"addr_parse",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "addr_parse" "', argument " "1"" of type '" "char const *""'"); + } + arg1 = (char *)(buf1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "addr_parse" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + result = (struct nl_addr *)addr_parse((char const *)arg1,arg2); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_addr, 0 | 0 ); + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_addr_alloc(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + size_t arg1 ; + size_t val1 ; + int ecode1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_addr *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + ecode1 = SWIG_AsVal_size_t(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_addr_alloc" "', argument " "1"" of type '" "size_t""'"); + } + arg1 = (size_t)(val1); + result = (struct nl_addr *)nl_addr_alloc(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_addr, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_addr_alloc_attr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nlattr *arg1 = (struct nlattr *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + struct nl_addr *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"nl_addr_alloc_attr",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlattr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_alloc_attr" "', argument " "1"" of type '" "struct nlattr *""'"); + } + arg1 = (struct nlattr *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_addr_alloc_attr" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + result = (struct nl_addr *)nl_addr_alloc_attr(arg1,arg2); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_addr, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_addr_build(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + int arg1 ; + void *arg2 = (void *) 0 ; + size_t arg3 ; + int val1 ; + int ecode1 = 0 ; + int res2 ; + size_t val3 ; + int ecode3 = 0 ; + PyObject *swig_obj[3] ; + struct nl_addr *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"nl_addr_build",3,3,swig_obj)) SWIG_fail; + ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_addr_build" "', argument " "1"" of type '" "int""'"); + } + arg1 = (int)(val1); + res2 = SWIG_ConvertPtr(swig_obj[1],SWIG_as_voidptrptr(&arg2), 0, 0); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_addr_build" "', argument " "2"" of type '" "void *""'"); + } + ecode3 = SWIG_AsVal_size_t(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "nl_addr_build" "', argument " "3"" of type '" "size_t""'"); + } + arg3 = (size_t)(val3); + result = (struct nl_addr *)nl_addr_build(arg1,arg2,arg3); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_addr, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_addr_clone(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_addr *arg1 = (struct nl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_addr *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_clone" "', argument " "1"" of type '" "struct nl_addr *""'"); + } + arg1 = (struct nl_addr *)(argp1); + result = (struct nl_addr *)nl_addr_clone(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_addr, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_addr_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_addr *arg1 = (struct nl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_addr *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_get" "', argument " "1"" of type '" "struct nl_addr *""'"); + } + arg1 = (struct nl_addr *)(argp1); + result = (struct nl_addr *)nl_addr_get(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_addr, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_addr_put(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_addr *arg1 = (struct nl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_put" "', argument " "1"" of type '" "struct nl_addr *""'"); + } + arg1 = (struct nl_addr *)(argp1); + nl_addr_put(arg1); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_addr_shared(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_addr *arg1 = (struct nl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_shared" "', argument " "1"" of type '" "struct nl_addr *""'"); + } + arg1 = (struct nl_addr *)(argp1); + result = (int)nl_addr_shared(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_addr_cmp(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_addr *arg1 = (struct nl_addr *) 0 ; + struct nl_addr *arg2 = (struct nl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nl_addr_cmp",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_cmp" "', argument " "1"" of type '" "struct nl_addr *""'"); + } + arg1 = (struct nl_addr *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_addr_cmp" "', argument " "2"" of type '" "struct nl_addr *""'"); + } + arg2 = (struct nl_addr *)(argp2); + result = (int)nl_addr_cmp(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_addr_cmp_prefix(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_addr *arg1 = (struct nl_addr *) 0 ; + struct nl_addr *arg2 = (struct nl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nl_addr_cmp_prefix",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_cmp_prefix" "', argument " "1"" of type '" "struct nl_addr *""'"); + } + arg1 = (struct nl_addr *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_addr_cmp_prefix" "', argument " "2"" of type '" "struct nl_addr *""'"); + } + arg2 = (struct nl_addr *)(argp2); + result = (int)nl_addr_cmp_prefix(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_addr_iszero(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_addr *arg1 = (struct nl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_iszero" "', argument " "1"" of type '" "struct nl_addr *""'"); + } + arg1 = (struct nl_addr *)(argp1); + result = (int)nl_addr_iszero(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_addr_valid(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + char *arg1 = (char *) 0 ; + int arg2 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nl_addr_valid",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_valid" "', argument " "1"" of type '" "char *""'"); + } + arg1 = (char *)(buf1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_addr_valid" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + result = (int)nl_addr_valid(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_addr_guess_family(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_addr *arg1 = (struct nl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_guess_family" "', argument " "1"" of type '" "struct nl_addr *""'"); + } + arg1 = (struct nl_addr *)(argp1); + result = (int)nl_addr_guess_family(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_addr_fill_sockaddr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_addr *arg1 = (struct nl_addr *) 0 ; + struct sockaddr *arg2 = (struct sockaddr *) 0 ; + socklen_t *arg3 = (socklen_t *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + void *argp3 = 0 ; + int res3 = 0 ; + PyObject *swig_obj[3] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nl_addr_fill_sockaddr",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_fill_sockaddr" "', argument " "1"" of type '" "struct nl_addr *""'"); + } + arg1 = (struct nl_addr *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_sockaddr, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_addr_fill_sockaddr" "', argument " "2"" of type '" "struct sockaddr *""'"); + } + arg2 = (struct sockaddr *)(argp2); + res3 = SWIG_ConvertPtr(swig_obj[2], &argp3,SWIGTYPE_p_socklen_t, 0 | 0 ); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "nl_addr_fill_sockaddr" "', argument " "3"" of type '" "socklen_t *""'"); + } + arg3 = (socklen_t *)(argp3); + result = (int)nl_addr_fill_sockaddr(arg1,arg2,arg3); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_addr_info(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_addr *arg1 = (struct nl_addr *) 0 ; + struct addrinfo **arg2 = (struct addrinfo **) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nl_addr_info",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_info" "', argument " "1"" of type '" "struct nl_addr *""'"); + } + arg1 = (struct nl_addr *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_p_addrinfo, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_addr_info" "', argument " "2"" of type '" "struct addrinfo **""'"); + } + arg2 = (struct addrinfo **)(argp2); + result = (int)nl_addr_info(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_addr_resolve(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_addr *arg1 = (struct nl_addr *) 0 ; + char *arg2 = (char *) 0 ; + size_t arg3 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + size_t val3 ; + int ecode3 = 0 ; + PyObject *swig_obj[3] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nl_addr_resolve",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_resolve" "', argument " "1"" of type '" "struct nl_addr *""'"); + } + arg1 = (struct nl_addr *)(argp1); + res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_addr_resolve" "', argument " "2"" of type '" "char *""'"); + } + arg2 = (char *)(buf2); + ecode3 = SWIG_AsVal_size_t(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "nl_addr_resolve" "', argument " "3"" of type '" "size_t""'"); + } + arg3 = (size_t)(val3); + result = (int)nl_addr_resolve(arg1,arg2,arg3); + resultobj = SWIG_From_int((int)(result)); + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return resultobj; +fail: + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_addr_set_family(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_addr *arg1 = (struct nl_addr *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_addr_set_family",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_set_family" "', argument " "1"" of type '" "struct nl_addr *""'"); + } + arg1 = (struct nl_addr *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_addr_set_family" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + nl_addr_set_family(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_addr_get_family(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_addr *arg1 = (struct nl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_get_family" "', argument " "1"" of type '" "struct nl_addr *""'"); + } + arg1 = (struct nl_addr *)(argp1); + result = (int)nl_addr_get_family(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_addr_set_binary_addr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_addr *arg1 = (struct nl_addr *) 0 ; + void *arg2 = (void *) 0 ; + size_t arg3 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 ; + size_t val3 ; + int ecode3 = 0 ; + PyObject *swig_obj[3] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"nl_addr_set_binary_addr",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_set_binary_addr" "', argument " "1"" of type '" "struct nl_addr *""'"); + } + arg1 = (struct nl_addr *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1],SWIG_as_voidptrptr(&arg2), 0, 0); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_addr_set_binary_addr" "', argument " "2"" of type '" "void *""'"); + } + ecode3 = SWIG_AsVal_size_t(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "nl_addr_set_binary_addr" "', argument " "3"" of type '" "size_t""'"); + } + arg3 = (size_t)(val3); + result = (int)nl_addr_set_binary_addr(arg1,arg2,arg3); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_addr_get_binary_addr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_addr *arg1 = (struct nl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + void *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_get_binary_addr" "', argument " "1"" of type '" "struct nl_addr *""'"); + } + arg1 = (struct nl_addr *)(argp1); + result = (void *)nl_addr_get_binary_addr(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_void, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_addr_get_len(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_addr *arg1 = (struct nl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + unsigned int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_get_len" "', argument " "1"" of type '" "struct nl_addr *""'"); + } + arg1 = (struct nl_addr *)(argp1); + result = (unsigned int)nl_addr_get_len(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_addr_set_prefixlen(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_addr *arg1 = (struct nl_addr *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"nl_addr_set_prefixlen",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_set_prefixlen" "', argument " "1"" of type '" "struct nl_addr *""'"); + } + arg1 = (struct nl_addr *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_addr_set_prefixlen" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + nl_addr_set_prefixlen(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_addr_get_prefixlen(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_addr *arg1 = (struct nl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + unsigned int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_get_prefixlen" "', argument " "1"" of type '" "struct nl_addr *""'"); + } + arg1 = (struct nl_addr *)(argp1); + result = (unsigned int)nl_addr_get_prefixlen(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_af2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + int arg1 ; + char *arg2 = (char *) 0 ; + size_t arg3 ; + int val1 ; + int ecode1 = 0 ; + int res2 ; + size_t size2 ; + char *buff2 = 0 ; + PyObject *swig_obj[2] ; + char *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"nl_af2str",2,2,swig_obj)) SWIG_fail; + ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_af2str" "', argument " "1"" of type '" "int""'"); + } + arg1 = (int)(val1); + res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_af2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); + } + buff2= (char *)malloc((size2+1)*sizeof(char)); + arg3 = (size_t)(size2); + arg2 = (char *)(buff2); + result = (char *)nl_af2str(arg1,arg2,arg3); + resultobj = SWIG_FromCharPtr((const char *)result); + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); + if (buff2) free((char*)buff2); + return resultobj; +fail: + if (buff2) free((char*)buff2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_str2af(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + char *arg1 = (char *) 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_str2af" "', argument " "1"" of type '" "char const *""'"); + } + arg1 = (char *)(buf1); + result = (int)nl_str2af((char const *)arg1); + resultobj = SWIG_From_int((int)(result)); + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_nl_addr2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_addr *arg1 = (struct nl_addr *) 0 ; + char *arg2 = (char *) 0 ; + size_t arg3 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 ; + size_t size2 ; + char *buff2 = 0 ; + PyObject *swig_obj[2] ; + char *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"nl_addr2str",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr2str" "', argument " "1"" of type '" "struct nl_addr *""'"); + } + arg1 = (struct nl_addr *)(argp1); + res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_addr2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); + } + buff2= (char *)malloc((size2+1)*sizeof(char)); + arg3 = (size_t)(size2); + arg2 = (char *)(buff2); + result = (char *)nl_addr2str(arg1,arg2,arg3); + resultobj = SWIG_FromCharPtr((const char *)result); + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); + if (buff2) free((char*)buff2); + return resultobj; +fail: + if (buff2) free((char*)buff2); + return NULL; +} + + +static PyMethodDef SwigMethods[] = { + { (char *)"SWIG_PyInstanceMethod_New", (PyCFunction)SWIG_PyInstanceMethod_New, METH_O, NULL}, + { (char *)"alloc_dump_params", (PyCFunction)_wrap_alloc_dump_params, METH_NOARGS, NULL}, + { (char *)"free_dump_params", (PyCFunction)_wrap_free_dump_params, METH_O, NULL}, + { (char *)"nl_dump_params_dp_type_set", _wrap_nl_dump_params_dp_type_set, METH_VARARGS, NULL}, + { (char *)"nl_dump_params_dp_type_get", (PyCFunction)_wrap_nl_dump_params_dp_type_get, METH_O, NULL}, + { (char *)"nl_dump_params_dp_prefix_set", _wrap_nl_dump_params_dp_prefix_set, METH_VARARGS, NULL}, + { (char *)"nl_dump_params_dp_prefix_get", (PyCFunction)_wrap_nl_dump_params_dp_prefix_get, METH_O, NULL}, + { (char *)"nl_dump_params_dp_print_index_set", _wrap_nl_dump_params_dp_print_index_set, METH_VARARGS, NULL}, + { (char *)"nl_dump_params_dp_print_index_get", (PyCFunction)_wrap_nl_dump_params_dp_print_index_get, METH_O, NULL}, + { (char *)"nl_dump_params_dp_dump_msgtype_set", _wrap_nl_dump_params_dp_dump_msgtype_set, METH_VARARGS, NULL}, + { (char *)"nl_dump_params_dp_dump_msgtype_get", (PyCFunction)_wrap_nl_dump_params_dp_dump_msgtype_get, METH_O, NULL}, + { (char *)"nl_dump_params_dp_cb_set", _wrap_nl_dump_params_dp_cb_set, METH_VARARGS, NULL}, + { (char *)"nl_dump_params_dp_cb_get", (PyCFunction)_wrap_nl_dump_params_dp_cb_get, METH_O, NULL}, + { (char *)"nl_dump_params_dp_nl_cb_set", _wrap_nl_dump_params_dp_nl_cb_set, METH_VARARGS, NULL}, + { (char *)"nl_dump_params_dp_nl_cb_get", (PyCFunction)_wrap_nl_dump_params_dp_nl_cb_get, METH_O, NULL}, + { (char *)"nl_dump_params_dp_data_set", _wrap_nl_dump_params_dp_data_set, METH_VARARGS, NULL}, + { (char *)"nl_dump_params_dp_data_get", (PyCFunction)_wrap_nl_dump_params_dp_data_get, METH_O, NULL}, + { (char *)"nl_dump_params_dp_fd_set", _wrap_nl_dump_params_dp_fd_set, METH_VARARGS, NULL}, + { (char *)"nl_dump_params_dp_fd_get", (PyCFunction)_wrap_nl_dump_params_dp_fd_get, METH_O, NULL}, + { (char *)"nl_dump_params_dp_buf_set", _wrap_nl_dump_params_dp_buf_set, METH_VARARGS, NULL}, + { (char *)"nl_dump_params_dp_buf_get", (PyCFunction)_wrap_nl_dump_params_dp_buf_get, METH_O, NULL}, + { (char *)"nl_dump_params_dp_buflen_set", _wrap_nl_dump_params_dp_buflen_set, METH_VARARGS, NULL}, + { (char *)"nl_dump_params_dp_buflen_get", (PyCFunction)_wrap_nl_dump_params_dp_buflen_get, METH_O, NULL}, + { (char *)"nl_dump_params_dp_pre_dump_set", _wrap_nl_dump_params_dp_pre_dump_set, METH_VARARGS, NULL}, + { (char *)"nl_dump_params_dp_pre_dump_get", (PyCFunction)_wrap_nl_dump_params_dp_pre_dump_get, METH_O, NULL}, + { (char *)"nl_dump_params_dp_ivar_set", _wrap_nl_dump_params_dp_ivar_set, METH_VARARGS, NULL}, + { (char *)"nl_dump_params_dp_ivar_get", (PyCFunction)_wrap_nl_dump_params_dp_ivar_get, METH_O, NULL}, + { (char *)"nl_dump_params_dp_line_set", _wrap_nl_dump_params_dp_line_set, METH_VARARGS, NULL}, + { (char *)"nl_dump_params_dp_line_get", (PyCFunction)_wrap_nl_dump_params_dp_line_get, METH_O, NULL}, + { (char *)"delete_nl_dump_params", (PyCFunction)_wrap_delete_nl_dump_params, METH_O, NULL}, + { (char *)"nl_dump_params_swigregister", nl_dump_params_swigregister, METH_VARARGS, NULL}, + { (char *)"nl_geterror", (PyCFunction)_wrap_nl_geterror, METH_O, NULL}, + { (char *)"nl_cancel_down_bytes", _wrap_nl_cancel_down_bytes, METH_VARARGS, NULL}, + { (char *)"nl_cancel_down_bits", _wrap_nl_cancel_down_bits, METH_VARARGS, NULL}, + { (char *)"nl_rate2str", _wrap_nl_rate2str, METH_VARARGS, NULL}, + { (char *)"nl_cancel_down_us", _wrap_nl_cancel_down_us, METH_VARARGS, NULL}, + { (char *)"nl_size2int", (PyCFunction)_wrap_nl_size2int, METH_O, NULL}, + { (char *)"nl_size2str", _wrap_nl_size2str, METH_VARARGS, NULL}, + { (char *)"nl_prob2int", (PyCFunction)_wrap_nl_prob2int, METH_O, NULL}, + { (char *)"nl_get_user_hz", (PyCFunction)_wrap_nl_get_user_hz, METH_NOARGS, NULL}, + { (char *)"nl_us2ticks", (PyCFunction)_wrap_nl_us2ticks, METH_O, NULL}, + { (char *)"nl_ticks2us", (PyCFunction)_wrap_nl_ticks2us, METH_O, NULL}, + { (char *)"nl_str2msec", _wrap_nl_str2msec, METH_VARARGS, NULL}, + { (char *)"nl_msec2str", _wrap_nl_msec2str, METH_VARARGS, NULL}, + { (char *)"nl_llproto2str", _wrap_nl_llproto2str, METH_VARARGS, NULL}, + { (char *)"nl_str2llproto", (PyCFunction)_wrap_nl_str2llproto, METH_O, NULL}, + { (char *)"nl_ether_proto2str", _wrap_nl_ether_proto2str, METH_VARARGS, NULL}, + { (char *)"nl_str2ether_proto", (PyCFunction)_wrap_nl_str2ether_proto, METH_O, NULL}, + { (char *)"nl_ip_proto2str", _wrap_nl_ip_proto2str, METH_VARARGS, NULL}, + { (char *)"nl_str2ip_proto", (PyCFunction)_wrap_nl_str2ip_proto, METH_O, NULL}, + { (char *)"nl_new_line", (PyCFunction)_wrap_nl_new_line, METH_O, NULL}, + { (char *)"nl_dump", _wrap_nl_dump, METH_VARARGS, NULL}, + { (char *)"nl_dump_line", _wrap_nl_dump_line, METH_VARARGS, NULL}, + { (char *)"nl_connect", _wrap_nl_connect, METH_VARARGS, NULL}, + { (char *)"nl_close", (PyCFunction)_wrap_nl_close, METH_O, NULL}, + { (char *)"nl_pickup", _wrap_nl_pickup, METH_VARARGS, NULL}, + { (char *)"nl_socket_alloc", (PyCFunction)_wrap_nl_socket_alloc, METH_NOARGS, NULL}, + { (char *)"nl_socket_alloc_cb", (PyCFunction)_wrap_nl_socket_alloc_cb, METH_O, NULL}, + { (char *)"nl_socket_free", (PyCFunction)_wrap_nl_socket_free, METH_O, NULL}, + { (char *)"nl_socket_get_local_port", (PyCFunction)_wrap_nl_socket_get_local_port, METH_O, NULL}, + { (char *)"nl_socket_set_local_port", _wrap_nl_socket_set_local_port, METH_VARARGS, NULL}, + { (char *)"nl_socket_get_peer_port", (PyCFunction)_wrap_nl_socket_get_peer_port, METH_O, NULL}, + { (char *)"nl_socket_set_peer_port", _wrap_nl_socket_set_peer_port, METH_VARARGS, NULL}, + { (char *)"nl_socket_get_peer_groups", (PyCFunction)_wrap_nl_socket_get_peer_groups, METH_O, NULL}, + { (char *)"nl_socket_set_peer_groups", _wrap_nl_socket_set_peer_groups, METH_VARARGS, NULL}, + { (char *)"nl_socket_set_buffer_size", _wrap_nl_socket_set_buffer_size, METH_VARARGS, NULL}, + { (char *)"nlmsg_size", (PyCFunction)_wrap_nlmsg_size, METH_O, NULL}, + { (char *)"nlmsg_total_size", (PyCFunction)_wrap_nlmsg_total_size, METH_O, NULL}, + { (char *)"nlmsg_padlen", (PyCFunction)_wrap_nlmsg_padlen, METH_O, NULL}, + { (char *)"nlmsg_data", (PyCFunction)_wrap_nlmsg_data, METH_O, NULL}, + { (char *)"nlmsg_datalen", (PyCFunction)_wrap_nlmsg_datalen, METH_O, NULL}, + { (char *)"nlmsg_tail", (PyCFunction)_wrap_nlmsg_tail, METH_O, NULL}, + { (char *)"nlmsg_attrdata", _wrap_nlmsg_attrdata, METH_VARARGS, NULL}, + { (char *)"nlmsg_attrlen", _wrap_nlmsg_attrlen, METH_VARARGS, NULL}, + { (char *)"nlmsg_valid_hdr", _wrap_nlmsg_valid_hdr, METH_VARARGS, NULL}, + { (char *)"nlmsg_ok", _wrap_nlmsg_ok, METH_VARARGS, NULL}, + { (char *)"nlmsg_next", _wrap_nlmsg_next, METH_VARARGS, NULL}, + { (char *)"nlmsg_parse", _wrap_nlmsg_parse, METH_VARARGS, NULL}, + { (char *)"nlmsg_find_attr", _wrap_nlmsg_find_attr, METH_VARARGS, NULL}, + { (char *)"nlmsg_validate", _wrap_nlmsg_validate, METH_VARARGS, NULL}, + { (char *)"nlmsg_alloc", (PyCFunction)_wrap_nlmsg_alloc, METH_NOARGS, NULL}, + { (char *)"nlmsg_alloc_size", (PyCFunction)_wrap_nlmsg_alloc_size, METH_O, NULL}, + { (char *)"nlmsg_alloc_simple", _wrap_nlmsg_alloc_simple, METH_VARARGS, NULL}, + { (char *)"nlmsg_set_default_size", (PyCFunction)_wrap_nlmsg_set_default_size, METH_O, NULL}, + { (char *)"nlmsg_inherit", (PyCFunction)_wrap_nlmsg_inherit, METH_O, NULL}, + { (char *)"nlmsg_convert", (PyCFunction)_wrap_nlmsg_convert, METH_O, NULL}, + { (char *)"nlmsg_reserve", _wrap_nlmsg_reserve, METH_VARARGS, NULL}, + { (char *)"nlmsg_append", _wrap_nlmsg_append, METH_VARARGS, NULL}, + { (char *)"nlmsg_expand", _wrap_nlmsg_expand, METH_VARARGS, NULL}, + { (char *)"nlmsg_put", _wrap_nlmsg_put, METH_VARARGS, NULL}, + { (char *)"nlmsg_hdr", (PyCFunction)_wrap_nlmsg_hdr, METH_O, NULL}, + { (char *)"nlmsg_get", (PyCFunction)_wrap_nlmsg_get, METH_O, NULL}, + { (char *)"nlmsg_free", (PyCFunction)_wrap_nlmsg_free, METH_O, NULL}, + { (char *)"nlmsg_set_proto", _wrap_nlmsg_set_proto, METH_VARARGS, NULL}, + { (char *)"nlmsg_get_proto", (PyCFunction)_wrap_nlmsg_get_proto, METH_O, NULL}, + { (char *)"nlmsg_get_max_size", (PyCFunction)_wrap_nlmsg_get_max_size, METH_O, NULL}, + { (char *)"nlmsg_set_src", _wrap_nlmsg_set_src, METH_VARARGS, NULL}, + { (char *)"nlmsg_get_src", (PyCFunction)_wrap_nlmsg_get_src, METH_O, NULL}, + { (char *)"nlmsg_set_dst", _wrap_nlmsg_set_dst, METH_VARARGS, NULL}, + { (char *)"nlmsg_get_dst", (PyCFunction)_wrap_nlmsg_get_dst, METH_O, NULL}, + { (char *)"nlmsg_set_creds", _wrap_nlmsg_set_creds, METH_VARARGS, NULL}, + { (char *)"nlmsg_get_creds", (PyCFunction)_wrap_nlmsg_get_creds, METH_O, NULL}, + { (char *)"nl_nlmsgtype2str", _wrap_nl_nlmsgtype2str, METH_VARARGS, NULL}, + { (char *)"nl_str2nlmsgtype", (PyCFunction)_wrap_nl_str2nlmsgtype, METH_O, NULL}, + { (char *)"nl_nlmsg_flags2str", _wrap_nl_nlmsg_flags2str, METH_VARARGS, NULL}, + { (char *)"nl_msg_parse", _wrap_nl_msg_parse, METH_VARARGS, NULL}, + { (char *)"nl_msg_dump", _wrap_nl_msg_dump, METH_VARARGS, NULL}, + { (char *)"cast_obj", (PyCFunction)_wrap_cast_obj, METH_O, NULL}, + { (char *)"object_alloc_name", (PyCFunction)_wrap_object_alloc_name, METH_O, NULL}, + { (char *)"nl_object_alloc", (PyCFunction)_wrap_nl_object_alloc, METH_O, NULL}, + { (char *)"nl_object_free", (PyCFunction)_wrap_nl_object_free, METH_O, NULL}, + { (char *)"nl_object_clone", (PyCFunction)_wrap_nl_object_clone, METH_O, NULL}, + { (char *)"nl_object_get", (PyCFunction)_wrap_nl_object_get, METH_O, NULL}, + { (char *)"nl_object_put", (PyCFunction)_wrap_nl_object_put, METH_O, NULL}, + { (char *)"nl_object_shared", (PyCFunction)_wrap_nl_object_shared, METH_O, NULL}, + { (char *)"nl_object_dump_buf", _wrap_nl_object_dump_buf, METH_VARARGS, NULL}, + { (char *)"nl_object_dump", _wrap_nl_object_dump, METH_VARARGS, NULL}, + { (char *)"nl_object_identical", _wrap_nl_object_identical, METH_VARARGS, NULL}, + { (char *)"nl_object_diff", _wrap_nl_object_diff, METH_VARARGS, NULL}, + { (char *)"nl_object_match_filter", _wrap_nl_object_match_filter, METH_VARARGS, NULL}, + { (char *)"nl_object_attrs2str", _wrap_nl_object_attrs2str, METH_VARARGS, NULL}, + { (char *)"nl_object_attr_list", _wrap_nl_object_attr_list, METH_VARARGS, NULL}, + { (char *)"nl_object_mark", (PyCFunction)_wrap_nl_object_mark, METH_O, NULL}, + { (char *)"nl_object_unmark", (PyCFunction)_wrap_nl_object_unmark, METH_O, NULL}, + { (char *)"nl_object_is_marked", (PyCFunction)_wrap_nl_object_is_marked, METH_O, NULL}, + { (char *)"nl_object_get_refcnt", (PyCFunction)_wrap_nl_object_get_refcnt, METH_O, NULL}, + { (char *)"alloc_cache_name", (PyCFunction)_wrap_alloc_cache_name, METH_O, NULL}, + { (char *)"alloc_cache_mngr", _wrap_alloc_cache_mngr, METH_VARARGS, NULL}, + { (char *)"cache_mngr_add", _wrap_cache_mngr_add, METH_VARARGS, NULL}, + { (char *)"nl_cache_nitems", (PyCFunction)_wrap_nl_cache_nitems, METH_O, NULL}, + { (char *)"nl_cache_nitems_filter", _wrap_nl_cache_nitems_filter, METH_VARARGS, NULL}, + { (char *)"nl_cache_get_ops", (PyCFunction)_wrap_nl_cache_get_ops, METH_O, NULL}, + { (char *)"nl_cache_get_first", (PyCFunction)_wrap_nl_cache_get_first, METH_O, NULL}, + { (char *)"nl_cache_get_last", (PyCFunction)_wrap_nl_cache_get_last, METH_O, NULL}, + { (char *)"nl_cache_get_next", (PyCFunction)_wrap_nl_cache_get_next, METH_O, NULL}, + { (char *)"nl_cache_get_prev", (PyCFunction)_wrap_nl_cache_get_prev, METH_O, NULL}, + { (char *)"nl_cache_alloc", (PyCFunction)_wrap_nl_cache_alloc, METH_O, NULL}, + { (char *)"nl_cache_subset", _wrap_nl_cache_subset, METH_VARARGS, NULL}, + { (char *)"nl_cache_clear", (PyCFunction)_wrap_nl_cache_clear, METH_O, NULL}, + { (char *)"nl_cache_free", (PyCFunction)_wrap_nl_cache_free, METH_O, NULL}, + { (char *)"nl_cache_add", _wrap_nl_cache_add, METH_VARARGS, NULL}, + { (char *)"nl_cache_parse_and_add", _wrap_nl_cache_parse_and_add, METH_VARARGS, NULL}, + { (char *)"nl_cache_remove", (PyCFunction)_wrap_nl_cache_remove, METH_O, NULL}, + { (char *)"nl_cache_refill", _wrap_nl_cache_refill, METH_VARARGS, NULL}, + { (char *)"nl_cache_pickup", _wrap_nl_cache_pickup, METH_VARARGS, NULL}, + { (char *)"nl_cache_resync", _wrap_nl_cache_resync, METH_VARARGS, NULL}, + { (char *)"nl_cache_include", _wrap_nl_cache_include, METH_VARARGS, NULL}, + { (char *)"nl_cache_set_arg1", _wrap_nl_cache_set_arg1, METH_VARARGS, NULL}, + { (char *)"nl_cache_set_arg2", _wrap_nl_cache_set_arg2, METH_VARARGS, NULL}, + { (char *)"nl_cache_is_empty", (PyCFunction)_wrap_nl_cache_is_empty, METH_O, NULL}, + { (char *)"nl_cache_search", _wrap_nl_cache_search, METH_VARARGS, NULL}, + { (char *)"nl_cache_mark_all", (PyCFunction)_wrap_nl_cache_mark_all, METH_O, NULL}, + { (char *)"nl_cache_dump", _wrap_nl_cache_dump, METH_VARARGS, NULL}, + { (char *)"nl_cache_dump_filter", _wrap_nl_cache_dump_filter, METH_VARARGS, NULL}, + { (char *)"nl_cache_foreach", _wrap_nl_cache_foreach, METH_VARARGS, NULL}, + { (char *)"nl_cache_foreach_filter", _wrap_nl_cache_foreach_filter, METH_VARARGS, NULL}, + { (char *)"nl_cache_ops_lookup", (PyCFunction)_wrap_nl_cache_ops_lookup, METH_O, NULL}, + { (char *)"nl_cache_ops_associate", _wrap_nl_cache_ops_associate, METH_VARARGS, NULL}, + { (char *)"nl_msgtype_lookup", _wrap_nl_msgtype_lookup, METH_VARARGS, NULL}, + { (char *)"nl_cache_ops_foreach", _wrap_nl_cache_ops_foreach, METH_VARARGS, NULL}, + { (char *)"nl_cache_mngt_register", (PyCFunction)_wrap_nl_cache_mngt_register, METH_O, NULL}, + { (char *)"nl_cache_mngt_unregister", (PyCFunction)_wrap_nl_cache_mngt_unregister, METH_O, NULL}, + { (char *)"nl_cache_mngt_provide", (PyCFunction)_wrap_nl_cache_mngt_provide, METH_O, NULL}, + { (char *)"nl_cache_mngt_unprovide", (PyCFunction)_wrap_nl_cache_mngt_unprovide, METH_O, NULL}, + { (char *)"nl_cache_mngt_require", (PyCFunction)_wrap_nl_cache_mngt_require, METH_O, NULL}, + { (char *)"nl_cache_mngr_get_fd", (PyCFunction)_wrap_nl_cache_mngr_get_fd, METH_O, NULL}, + { (char *)"nl_cache_mngr_poll", _wrap_nl_cache_mngr_poll, METH_VARARGS, NULL}, + { (char *)"nl_cache_mngr_data_ready", (PyCFunction)_wrap_nl_cache_mngr_data_ready, METH_O, NULL}, + { (char *)"nl_cache_mngr_free", (PyCFunction)_wrap_nl_cache_mngr_free, METH_O, NULL}, + { (char *)"addr_parse", _wrap_addr_parse, METH_VARARGS, NULL}, + { (char *)"nl_addr_alloc", (PyCFunction)_wrap_nl_addr_alloc, METH_O, NULL}, + { (char *)"nl_addr_alloc_attr", _wrap_nl_addr_alloc_attr, METH_VARARGS, NULL}, + { (char *)"nl_addr_build", _wrap_nl_addr_build, METH_VARARGS, NULL}, + { (char *)"nl_addr_clone", (PyCFunction)_wrap_nl_addr_clone, METH_O, NULL}, + { (char *)"nl_addr_get", (PyCFunction)_wrap_nl_addr_get, METH_O, NULL}, + { (char *)"nl_addr_put", (PyCFunction)_wrap_nl_addr_put, METH_O, NULL}, + { (char *)"nl_addr_shared", (PyCFunction)_wrap_nl_addr_shared, METH_O, NULL}, + { (char *)"nl_addr_cmp", _wrap_nl_addr_cmp, METH_VARARGS, NULL}, + { (char *)"nl_addr_cmp_prefix", _wrap_nl_addr_cmp_prefix, METH_VARARGS, NULL}, + { (char *)"nl_addr_iszero", (PyCFunction)_wrap_nl_addr_iszero, METH_O, NULL}, + { (char *)"nl_addr_valid", _wrap_nl_addr_valid, METH_VARARGS, NULL}, + { (char *)"nl_addr_guess_family", (PyCFunction)_wrap_nl_addr_guess_family, METH_O, NULL}, + { (char *)"nl_addr_fill_sockaddr", _wrap_nl_addr_fill_sockaddr, METH_VARARGS, NULL}, + { (char *)"nl_addr_info", _wrap_nl_addr_info, METH_VARARGS, NULL}, + { (char *)"nl_addr_resolve", _wrap_nl_addr_resolve, METH_VARARGS, NULL}, + { (char *)"nl_addr_set_family", _wrap_nl_addr_set_family, METH_VARARGS, NULL}, + { (char *)"nl_addr_get_family", (PyCFunction)_wrap_nl_addr_get_family, METH_O, NULL}, + { (char *)"nl_addr_set_binary_addr", _wrap_nl_addr_set_binary_addr, METH_VARARGS, NULL}, + { (char *)"nl_addr_get_binary_addr", (PyCFunction)_wrap_nl_addr_get_binary_addr, METH_O, NULL}, + { (char *)"nl_addr_get_len", (PyCFunction)_wrap_nl_addr_get_len, METH_O, NULL}, + { (char *)"nl_addr_set_prefixlen", _wrap_nl_addr_set_prefixlen, METH_VARARGS, NULL}, + { (char *)"nl_addr_get_prefixlen", (PyCFunction)_wrap_nl_addr_get_prefixlen, METH_O, NULL}, + { (char *)"nl_af2str", _wrap_nl_af2str, METH_VARARGS, NULL}, + { (char *)"nl_str2af", (PyCFunction)_wrap_nl_str2af, METH_O, NULL}, + { (char *)"nl_addr2str", _wrap_nl_addr2str, METH_VARARGS, NULL}, + { NULL, NULL, 0, NULL } +}; + + +/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */ + +static swig_type_info _swigt__p_FILE = {"_p_FILE", "FILE *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_char = {"_p_char", "char *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_f_p_struct_nl_cache_ops_p_struct_sockaddr_nl_p_struct_nlmsghdr_p_struct_nl_parser_param__int = {"_p_f_p_struct_nl_cache_ops_p_struct_sockaddr_nl_p_struct_nlmsghdr_p_struct_nl_parser_param__int", "int (*)(struct nl_cache_ops *,struct sockaddr_nl *,struct nlmsghdr *,struct nl_parser_param *)", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_f_p_struct_nl_cache_ops_p_void__void = {"_p_f_p_struct_nl_cache_ops_p_void__void", "void (*)(struct nl_cache_ops *,void *)", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_f_p_struct_nl_cache_p_struct_nl_object_int_p_void__void = {"_p_f_p_struct_nl_cache_p_struct_nl_object_int_p_void__void", "void (*)(struct nl_cache *,struct nl_object *,int,void *)|change_func_t", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_f_p_struct_nl_dump_params_int__void = {"_p_f_p_struct_nl_dump_params_int__void", "void (*)(struct nl_dump_params *,int)", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_f_p_struct_nl_dump_params_p_char__void = {"_p_f_p_struct_nl_dump_params_p_char__void", "void (*)(struct nl_dump_params *,char *)", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_f_p_struct_nl_object_p_void__void = {"_p_f_p_struct_nl_object_p_void__void", "void (*)(struct nl_object *,void *)", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_int = {"_p_int", "intptr_t *|int *|int_least32_t *|int_fast32_t *|int32_t *|int_fast16_t *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_long_long = {"_p_long_long", "int_least64_t *|int_fast64_t *|int64_t *|long long *|intmax_t *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_nl_addr = {"_p_nl_addr", "struct nl_addr *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_nl_cache = {"_p_nl_cache", "struct nl_cache *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_nl_cache_mngr = {"_p_nl_cache_mngr", "struct nl_cache_mngr *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_nl_cache_ops = {"_p_nl_cache_ops", "struct nl_cache_ops *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_nl_cb = {"_p_nl_cb", "struct nl_cb *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_nl_dump_params = {"_p_nl_dump_params", "struct nl_dump_params *|nl_dump_params *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_nl_msg = {"_p_nl_msg", "struct nl_msg *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_nl_msgtype = {"_p_nl_msgtype", "struct nl_msgtype *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_nl_object = {"_p_nl_object", "struct nl_object *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_nl_object_ops = {"_p_nl_object_ops", "struct nl_object_ops *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_nl_sock = {"_p_nl_sock", "struct nl_sock *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_nla_policy = {"_p_nla_policy", "struct nla_policy *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_nlattr = {"_p_nlattr", "struct nlattr *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_nlmsghdr = {"_p_nlmsghdr", "struct nlmsghdr *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_p_addrinfo = {"_p_p_addrinfo", "struct addrinfo **", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_p_char = {"_p_p_char", "char **", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_p_nl_object = {"_p_p_nl_object", "struct nl_object **", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_p_nlattr = {"_p_p_nlattr", "struct nlattr **", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_short = {"_p_short", "short *|int_least16_t *|int16_t *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_signed_char = {"_p_signed_char", "signed char *|int_least8_t *|int_fast8_t *|int8_t *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_sockaddr = {"_p_sockaddr", "struct sockaddr *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_sockaddr_nl = {"_p_sockaddr_nl", "struct sockaddr_nl *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_socklen_t = {"_p_socklen_t", "socklen_t *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_ucred = {"_p_ucred", "struct ucred *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_unsigned_char = {"_p_unsigned_char", "unsigned char *|uint_least8_t *|uint_fast8_t *|uint8_t *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_unsigned_int = {"_p_unsigned_int", "uintptr_t *|uint_least32_t *|uint_fast32_t *|uint32_t *|unsigned int *|uint_fast16_t *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_unsigned_long_long = {"_p_unsigned_long_long", "uint_least64_t *|uint_fast64_t *|uint64_t *|unsigned long long *|uintmax_t *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_unsigned_short = {"_p_unsigned_short", "unsigned short *|uint_least16_t *|uint16_t *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_void = {"_p_void", "void *", 0, 0, (void*)0, 0}; + +static swig_type_info *swig_type_initial[] = { + &_swigt__p_FILE, + &_swigt__p_char, + &_swigt__p_f_p_struct_nl_cache_ops_p_struct_sockaddr_nl_p_struct_nlmsghdr_p_struct_nl_parser_param__int, + &_swigt__p_f_p_struct_nl_cache_ops_p_void__void, + &_swigt__p_f_p_struct_nl_cache_p_struct_nl_object_int_p_void__void, + &_swigt__p_f_p_struct_nl_dump_params_int__void, + &_swigt__p_f_p_struct_nl_dump_params_p_char__void, + &_swigt__p_f_p_struct_nl_object_p_void__void, + &_swigt__p_int, + &_swigt__p_long_long, + &_swigt__p_nl_addr, + &_swigt__p_nl_cache, + &_swigt__p_nl_cache_mngr, + &_swigt__p_nl_cache_ops, + &_swigt__p_nl_cb, + &_swigt__p_nl_dump_params, + &_swigt__p_nl_msg, + &_swigt__p_nl_msgtype, + &_swigt__p_nl_object, + &_swigt__p_nl_object_ops, + &_swigt__p_nl_sock, + &_swigt__p_nla_policy, + &_swigt__p_nlattr, + &_swigt__p_nlmsghdr, + &_swigt__p_p_addrinfo, + &_swigt__p_p_char, + &_swigt__p_p_nl_object, + &_swigt__p_p_nlattr, + &_swigt__p_short, + &_swigt__p_signed_char, + &_swigt__p_sockaddr, + &_swigt__p_sockaddr_nl, + &_swigt__p_socklen_t, + &_swigt__p_ucred, + &_swigt__p_unsigned_char, + &_swigt__p_unsigned_int, + &_swigt__p_unsigned_long_long, + &_swigt__p_unsigned_short, + &_swigt__p_void, +}; + +static swig_cast_info _swigc__p_FILE[] = { {&_swigt__p_FILE, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_char[] = { {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_f_p_struct_nl_cache_ops_p_struct_sockaddr_nl_p_struct_nlmsghdr_p_struct_nl_parser_param__int[] = { {&_swigt__p_f_p_struct_nl_cache_ops_p_struct_sockaddr_nl_p_struct_nlmsghdr_p_struct_nl_parser_param__int, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_f_p_struct_nl_cache_ops_p_void__void[] = { {&_swigt__p_f_p_struct_nl_cache_ops_p_void__void, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_f_p_struct_nl_cache_p_struct_nl_object_int_p_void__void[] = { {&_swigt__p_f_p_struct_nl_cache_p_struct_nl_object_int_p_void__void, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_f_p_struct_nl_dump_params_int__void[] = { {&_swigt__p_f_p_struct_nl_dump_params_int__void, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_f_p_struct_nl_dump_params_p_char__void[] = { {&_swigt__p_f_p_struct_nl_dump_params_p_char__void, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_f_p_struct_nl_object_p_void__void[] = { {&_swigt__p_f_p_struct_nl_object_p_void__void, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_int[] = { {&_swigt__p_int, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_long_long[] = { {&_swigt__p_long_long, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_nl_addr[] = { {&_swigt__p_nl_addr, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_nl_cache[] = { {&_swigt__p_nl_cache, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_nl_cache_mngr[] = { {&_swigt__p_nl_cache_mngr, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_nl_cache_ops[] = { {&_swigt__p_nl_cache_ops, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_nl_cb[] = { {&_swigt__p_nl_cb, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_nl_dump_params[] = { {&_swigt__p_nl_dump_params, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_nl_msg[] = { {&_swigt__p_nl_msg, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_nl_msgtype[] = { {&_swigt__p_nl_msgtype, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_nl_object[] = { {&_swigt__p_nl_object, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_nl_object_ops[] = { {&_swigt__p_nl_object_ops, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_nl_sock[] = { {&_swigt__p_nl_sock, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_nla_policy[] = { {&_swigt__p_nla_policy, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_nlattr[] = { {&_swigt__p_nlattr, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_nlmsghdr[] = { {&_swigt__p_nlmsghdr, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_p_addrinfo[] = { {&_swigt__p_p_addrinfo, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_p_char[] = { {&_swigt__p_p_char, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_p_nl_object[] = { {&_swigt__p_p_nl_object, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_p_nlattr[] = { {&_swigt__p_p_nlattr, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_short[] = { {&_swigt__p_short, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_signed_char[] = { {&_swigt__p_signed_char, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_sockaddr[] = { {&_swigt__p_sockaddr, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_sockaddr_nl[] = { {&_swigt__p_sockaddr_nl, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_socklen_t[] = { {&_swigt__p_socklen_t, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_ucred[] = { {&_swigt__p_ucred, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_unsigned_char[] = { {&_swigt__p_unsigned_char, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_unsigned_int[] = { {&_swigt__p_unsigned_int, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_unsigned_long_long[] = { {&_swigt__p_unsigned_long_long, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_unsigned_short[] = { {&_swigt__p_unsigned_short, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_void[] = { {&_swigt__p_void, 0, 0, 0},{0, 0, 0, 0}}; + +static swig_cast_info *swig_cast_initial[] = { + _swigc__p_FILE, + _swigc__p_char, + _swigc__p_f_p_struct_nl_cache_ops_p_struct_sockaddr_nl_p_struct_nlmsghdr_p_struct_nl_parser_param__int, + _swigc__p_f_p_struct_nl_cache_ops_p_void__void, + _swigc__p_f_p_struct_nl_cache_p_struct_nl_object_int_p_void__void, + _swigc__p_f_p_struct_nl_dump_params_int__void, + _swigc__p_f_p_struct_nl_dump_params_p_char__void, + _swigc__p_f_p_struct_nl_object_p_void__void, + _swigc__p_int, + _swigc__p_long_long, + _swigc__p_nl_addr, + _swigc__p_nl_cache, + _swigc__p_nl_cache_mngr, + _swigc__p_nl_cache_ops, + _swigc__p_nl_cb, + _swigc__p_nl_dump_params, + _swigc__p_nl_msg, + _swigc__p_nl_msgtype, + _swigc__p_nl_object, + _swigc__p_nl_object_ops, + _swigc__p_nl_sock, + _swigc__p_nla_policy, + _swigc__p_nlattr, + _swigc__p_nlmsghdr, + _swigc__p_p_addrinfo, + _swigc__p_p_char, + _swigc__p_p_nl_object, + _swigc__p_p_nlattr, + _swigc__p_short, + _swigc__p_signed_char, + _swigc__p_sockaddr, + _swigc__p_sockaddr_nl, + _swigc__p_socklen_t, + _swigc__p_ucred, + _swigc__p_unsigned_char, + _swigc__p_unsigned_int, + _swigc__p_unsigned_long_long, + _swigc__p_unsigned_short, + _swigc__p_void, +}; + + +/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */ + +static swig_const_info swig_const_table[] = { +{0, 0, 0, 0.0, 0, 0}}; + +#ifdef __cplusplus +} +#endif +/* ----------------------------------------------------------------------------- + * Type initialization: + * This problem is tough by the requirement that no dynamic + * memory is used. Also, since swig_type_info structures store pointers to + * swig_cast_info structures and swig_cast_info structures store pointers back + * to swig_type_info structures, we need some lookup code at initialization. + * The idea is that swig generates all the structures that are needed. + * The runtime then collects these partially filled structures. + * The SWIG_InitializeModule function takes these initial arrays out of + * swig_module, and does all the lookup, filling in the swig_module.types + * array with the correct data and linking the correct swig_cast_info + * structures together. + * + * The generated swig_type_info structures are assigned staticly to an initial + * array. We just loop through that array, and handle each type individually. + * First we lookup if this type has been already loaded, and if so, use the + * loaded structure instead of the generated one. Then we have to fill in the + * cast linked list. The cast data is initially stored in something like a + * two-dimensional array. Each row corresponds to a type (there are the same + * number of rows as there are in the swig_type_initial array). Each entry in + * a column is one of the swig_cast_info structures for that type. + * The cast_initial array is actually an array of arrays, because each row has + * a variable number of columns. So to actually build the cast linked list, + * we find the array of casts associated with the type, and loop through it + * adding the casts to the list. The one last trick we need to do is making + * sure the type pointer in the swig_cast_info struct is correct. + * + * First off, we lookup the cast->type name to see if it is already loaded. + * There are three cases to handle: + * 1) If the cast->type has already been loaded AND the type we are adding + * casting info to has not been loaded (it is in this module), THEN we + * replace the cast->type pointer with the type pointer that has already + * been loaded. + * 2) If BOTH types (the one we are adding casting info to, and the + * cast->type) are loaded, THEN the cast info has already been loaded by + * the previous module so we just ignore it. + * 3) Finally, if cast->type has not already been loaded, then we add that + * swig_cast_info to the linked list (because the cast->type) pointer will + * be correct. + * ----------------------------------------------------------------------------- */ + +#ifdef __cplusplus +extern "C" { +#if 0 +} /* c-mode */ +#endif +#endif + +#if 0 +#define SWIGRUNTIME_DEBUG +#endif + + +SWIGRUNTIME void +SWIG_InitializeModule(void *clientdata) { + size_t i; + swig_module_info *module_head, *iter; + int found, init; + + clientdata = clientdata; + + /* check to see if the circular list has been setup, if not, set it up */ + if (swig_module.next==0) { + /* Initialize the swig_module */ + swig_module.type_initial = swig_type_initial; + swig_module.cast_initial = swig_cast_initial; + swig_module.next = &swig_module; + init = 1; + } else { + init = 0; + } + + /* Try and load any already created modules */ + module_head = SWIG_GetModule(clientdata); + if (!module_head) { + /* This is the first module loaded for this interpreter */ + /* so set the swig module into the interpreter */ + SWIG_SetModule(clientdata, &swig_module); + module_head = &swig_module; + } else { + /* the interpreter has loaded a SWIG module, but has it loaded this one? */ + found=0; + iter=module_head; + do { + if (iter==&swig_module) { + found=1; + break; + } + iter=iter->next; + } while (iter!= module_head); + + /* if the is found in the list, then all is done and we may leave */ + if (found) return; + /* otherwise we must add out module into the list */ + swig_module.next = module_head->next; + module_head->next = &swig_module; + } + + /* When multiple interpeters are used, a module could have already been initialized in + a different interpreter, but not yet have a pointer in this interpreter. + In this case, we do not want to continue adding types... everything should be + set up already */ + if (init == 0) return; + + /* Now work on filling in swig_module.types */ +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: size %d\n", swig_module.size); +#endif + for (i = 0; i < swig_module.size; ++i) { + swig_type_info *type = 0; + swig_type_info *ret; + swig_cast_info *cast; + +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name); +#endif + + /* if there is another module already loaded */ + if (swig_module.next != &swig_module) { + type = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, swig_module.type_initial[i]->name); + } + if (type) { + /* Overwrite clientdata field */ +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: found type %s\n", type->name); +#endif + if (swig_module.type_initial[i]->clientdata) { + type->clientdata = swig_module.type_initial[i]->clientdata; +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: found and overwrite type %s \n", type->name); +#endif + } + } else { + type = swig_module.type_initial[i]; + } + + /* Insert casting types */ + cast = swig_module.cast_initial[i]; + while (cast->type) { + /* Don't need to add information already in the list */ + ret = 0; +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: look cast %s\n", cast->type->name); +#endif + if (swig_module.next != &swig_module) { + ret = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, cast->type->name); +#ifdef SWIGRUNTIME_DEBUG + if (ret) printf("SWIG_InitializeModule: found cast %s\n", ret->name); +#endif + } + if (ret) { + if (type == swig_module.type_initial[i]) { +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: skip old type %s\n", ret->name); +#endif + cast->type = ret; + ret = 0; + } else { + /* Check for casting already in the list */ + swig_cast_info *ocast = SWIG_TypeCheck(ret->name, type); +#ifdef SWIGRUNTIME_DEBUG + if (ocast) printf("SWIG_InitializeModule: skip old cast %s\n", ret->name); +#endif + if (!ocast) ret = 0; + } + } + + if (!ret) { +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: adding cast %s\n", cast->type->name); +#endif + if (type->cast) { + type->cast->prev = cast; + cast->next = type->cast; + } + type->cast = cast; + } + cast++; + } + /* Set entry in modules->types array equal to the type */ + swig_module.types[i] = type; + } + swig_module.types[i] = 0; + +#ifdef SWIGRUNTIME_DEBUG + printf("**** SWIG_InitializeModule: Cast List ******\n"); + for (i = 0; i < swig_module.size; ++i) { + int j = 0; + swig_cast_info *cast = swig_module.cast_initial[i]; + printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name); + while (cast->type) { + printf("SWIG_InitializeModule: cast type %s\n", cast->type->name); + cast++; + ++j; + } + printf("---- Total casts: %d\n",j); + } + printf("**** SWIG_InitializeModule: Cast List ******\n"); +#endif +} + +/* This function will propagate the clientdata field of type to +* any new swig_type_info structures that have been added into the list +* of equivalent types. It is like calling +* SWIG_TypeClientData(type, clientdata) a second time. +*/ +SWIGRUNTIME void +SWIG_PropagateClientData(void) { + size_t i; + swig_cast_info *equiv; + static int init_run = 0; + + if (init_run) return; + init_run = 1; + + for (i = 0; i < swig_module.size; i++) { + if (swig_module.types[i]->clientdata) { + equiv = swig_module.types[i]->cast; + while (equiv) { + if (!equiv->converter) { + if (equiv->type && !equiv->type->clientdata) + SWIG_TypeClientData(equiv->type, swig_module.types[i]->clientdata); + } + equiv = equiv->next; + } + } + } +} + +#ifdef __cplusplus +#if 0 +{ + /* c-mode */ +#endif +} +#endif + + + +#ifdef __cplusplus +extern "C" { +#endif + + /* Python-specific SWIG API */ +#define SWIG_newvarlink() SWIG_Python_newvarlink() +#define SWIG_addvarlink(p, name, get_attr, set_attr) SWIG_Python_addvarlink(p, name, get_attr, set_attr) +#define SWIG_InstallConstants(d, constants) SWIG_Python_InstallConstants(d, constants) + + /* ----------------------------------------------------------------------------- + * global variable support code. + * ----------------------------------------------------------------------------- */ + + typedef struct swig_globalvar { + char *name; /* Name of global variable */ + PyObject *(*get_attr)(void); /* Return the current value */ + int (*set_attr)(PyObject *); /* Set the value */ + struct swig_globalvar *next; + } swig_globalvar; + + typedef struct swig_varlinkobject { + PyObject_HEAD + swig_globalvar *vars; + } swig_varlinkobject; + + SWIGINTERN PyObject * + swig_varlink_repr(swig_varlinkobject *SWIGUNUSEDPARM(v)) { +#if PY_VERSION_HEX >= 0x03000000 + return PyUnicode_InternFromString(""); +#else + return PyString_FromString(""); +#endif + } + + SWIGINTERN PyObject * + swig_varlink_str(swig_varlinkobject *v) { +#if PY_VERSION_HEX >= 0x03000000 + PyObject *str = PyUnicode_InternFromString("("); + PyObject *tail; + PyObject *joined; + swig_globalvar *var; + for (var = v->vars; var; var=var->next) { + tail = PyUnicode_FromString(var->name); + joined = PyUnicode_Concat(str, tail); + Py_DecRef(str); + Py_DecRef(tail); + str = joined; + if (var->next) { + tail = PyUnicode_InternFromString(", "); + joined = PyUnicode_Concat(str, tail); + Py_DecRef(str); + Py_DecRef(tail); + str = joined; + } + } + tail = PyUnicode_InternFromString(")"); + joined = PyUnicode_Concat(str, tail); + Py_DecRef(str); + Py_DecRef(tail); + str = joined; +#else + PyObject *str = PyString_FromString("("); + swig_globalvar *var; + for (var = v->vars; var; var=var->next) { + PyString_ConcatAndDel(&str,PyString_FromString(var->name)); + if (var->next) PyString_ConcatAndDel(&str,PyString_FromString(", ")); + } + PyString_ConcatAndDel(&str,PyString_FromString(")")); +#endif + return str; + } + + SWIGINTERN int + swig_varlink_print(swig_varlinkobject *v, FILE *fp, int SWIGUNUSEDPARM(flags)) { + char *tmp; + PyObject *str = swig_varlink_str(v); + fprintf(fp,"Swig global variables "); + fprintf(fp,"%s\n", tmp = SWIG_Python_str_AsChar(str)); + SWIG_Python_str_DelForPy3(tmp); + Py_DECREF(str); + return 0; + } + + SWIGINTERN void + swig_varlink_dealloc(swig_varlinkobject *v) { + swig_globalvar *var = v->vars; + while (var) { + swig_globalvar *n = var->next; + free(var->name); + free(var); + var = n; + } + } + + SWIGINTERN PyObject * + swig_varlink_getattr(swig_varlinkobject *v, char *n) { + PyObject *res = NULL; + swig_globalvar *var = v->vars; + while (var) { + if (strcmp(var->name,n) == 0) { + res = (*var->get_attr)(); + break; + } + var = var->next; + } + if (res == NULL && !PyErr_Occurred()) { + PyErr_SetString(PyExc_NameError,"Unknown C global variable"); + } + return res; + } + + SWIGINTERN int + swig_varlink_setattr(swig_varlinkobject *v, char *n, PyObject *p) { + int res = 1; + swig_globalvar *var = v->vars; + while (var) { + if (strcmp(var->name,n) == 0) { + res = (*var->set_attr)(p); + break; + } + var = var->next; + } + if (res == 1 && !PyErr_Occurred()) { + PyErr_SetString(PyExc_NameError,"Unknown C global variable"); + } + return res; + } + + SWIGINTERN PyTypeObject* + swig_varlink_type(void) { + static char varlink__doc__[] = "Swig var link object"; + static PyTypeObject varlink_type; + static int type_init = 0; + if (!type_init) { + const PyTypeObject tmp + = { + /* PyObject header changed in Python 3 */ +#if PY_VERSION_HEX >= 0x03000000 + PyVarObject_HEAD_INIT(&PyType_Type, 0) +#else + PyObject_HEAD_INIT(NULL) + 0, /* Number of items in variable part (ob_size) */ +#endif + (char *)"swigvarlink", /* Type name (tp_name) */ + sizeof(swig_varlinkobject), /* Basic size (tp_basicsize) */ + 0, /* Itemsize (tp_itemsize) */ + (destructor) swig_varlink_dealloc, /* Deallocator (tp_dealloc) */ + (printfunc) swig_varlink_print, /* Print (tp_print) */ + (getattrfunc) swig_varlink_getattr, /* get attr (tp_getattr) */ + (setattrfunc) swig_varlink_setattr, /* Set attr (tp_setattr) */ + 0, /* tp_compare */ + (reprfunc) swig_varlink_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + (reprfunc) swig_varlink_str, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + 0, /* tp_flags */ + varlink__doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ +#if PY_VERSION_HEX >= 0x02020000 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* tp_iter -> tp_weaklist */ +#endif +#if PY_VERSION_HEX >= 0x02030000 + 0, /* tp_del */ +#endif +#ifdef COUNT_ALLOCS + 0,0,0,0 /* tp_alloc -> tp_next */ +#endif + }; + varlink_type = tmp; + /* for Python 3 we already assigned ob_type in PyVarObject_HEAD_INIT() */ +#if PY_VERSION_HEX < 0x03000000 + varlink_type.ob_type = &PyType_Type; +#endif + type_init = 1; + } + return &varlink_type; + } + + /* Create a variable linking object for use later */ + SWIGINTERN PyObject * + SWIG_Python_newvarlink(void) { + swig_varlinkobject *result = PyObject_NEW(swig_varlinkobject, swig_varlink_type()); + if (result) { + result->vars = 0; + } + return ((PyObject*) result); + } + + SWIGINTERN void + SWIG_Python_addvarlink(PyObject *p, char *name, PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p)) { + swig_varlinkobject *v = (swig_varlinkobject *) p; + swig_globalvar *gv = (swig_globalvar *) malloc(sizeof(swig_globalvar)); + if (gv) { + size_t size = strlen(name)+1; + gv->name = (char *)malloc(size); + if (gv->name) { + strncpy(gv->name,name,size); + gv->get_attr = get_attr; + gv->set_attr = set_attr; + gv->next = v->vars; + } + } + v->vars = gv; + } + + SWIGINTERN PyObject * + SWIG_globals(void) { + static PyObject *_SWIG_globals = 0; + if (!_SWIG_globals) _SWIG_globals = SWIG_newvarlink(); + return _SWIG_globals; + } + + /* ----------------------------------------------------------------------------- + * constants/methods manipulation + * ----------------------------------------------------------------------------- */ + + /* Install Constants */ + SWIGINTERN void + SWIG_Python_InstallConstants(PyObject *d, swig_const_info constants[]) { + PyObject *obj = 0; + size_t i; + for (i = 0; constants[i].type; ++i) { + switch(constants[i].type) { + case SWIG_PY_POINTER: + obj = SWIG_NewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0); + break; + case SWIG_PY_BINARY: + obj = SWIG_NewPackedObj(constants[i].pvalue, constants[i].lvalue, *(constants[i].ptype)); + break; + default: + obj = 0; + break; + } + if (obj) { + PyDict_SetItemString(d, constants[i].name, obj); + Py_DECREF(obj); + } + } + } + + /* -----------------------------------------------------------------------------*/ + /* Fix SwigMethods to carry the callback ptrs when needed */ + /* -----------------------------------------------------------------------------*/ + + SWIGINTERN void + SWIG_Python_FixMethods(PyMethodDef *methods, + swig_const_info *const_table, + swig_type_info **types, + swig_type_info **types_initial) { + size_t i; + for (i = 0; methods[i].ml_name; ++i) { + const char *c = methods[i].ml_doc; + if (c && (c = strstr(c, "swig_ptr: "))) { + int j; + swig_const_info *ci = 0; + const char *name = c + 10; + for (j = 0; const_table[j].type; ++j) { + if (strncmp(const_table[j].name, name, + strlen(const_table[j].name)) == 0) { + ci = &(const_table[j]); + break; + } + } + if (ci) { + size_t shift = (ci->ptype) - types; + swig_type_info *ty = types_initial[shift]; + size_t ldoc = (c - methods[i].ml_doc); + size_t lptr = strlen(ty->name)+2*sizeof(void*)+2; + char *ndoc = (char*)malloc(ldoc + lptr + 10); + if (ndoc) { + char *buff = ndoc; + void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue : 0; + if (ptr) { + strncpy(buff, methods[i].ml_doc, ldoc); + buff += ldoc; + strncpy(buff, "swig_ptr: ", 10); + buff += 10; + SWIG_PackVoidPtr(buff, ptr, ty->name, lptr); + methods[i].ml_doc = ndoc; + } + } + } + } + } + } + +#ifdef __cplusplus +} +#endif + +/* -----------------------------------------------------------------------------* + * Partial Init method + * -----------------------------------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" +#endif + +SWIGEXPORT +#if PY_VERSION_HEX >= 0x03000000 +PyObject* +#else +void +#endif +SWIG_init(void) { + PyObject *m, *d; +#if PY_VERSION_HEX >= 0x03000000 + static struct PyModuleDef SWIG_module = { + PyModuleDef_HEAD_INIT, + (char *) SWIG_name, + NULL, + -1, + SwigMethods, + NULL, + NULL, + NULL, + NULL + }; +#endif + + /* Fix SwigMethods to carry the callback ptrs when needed */ + SWIG_Python_FixMethods(SwigMethods, swig_const_table, swig_types, swig_type_initial); + +#if PY_VERSION_HEX >= 0x03000000 + m = PyModule_Create(&SWIG_module); +#else + m = Py_InitModule((char *) SWIG_name, SwigMethods); +#endif + d = PyModule_GetDict(m); + + SWIG_InitializeModule(0); + SWIG_InstallConstants(d,swig_const_table); + + + SWIG_Python_SetConstant(d, "NL_DUMP_LINE",SWIG_From_int((int)(NL_DUMP_LINE))); + SWIG_Python_SetConstant(d, "NL_DUMP_DETAILS",SWIG_From_int((int)(NL_DUMP_DETAILS))); + SWIG_Python_SetConstant(d, "NL_DUMP_STATS",SWIG_From_int((int)(NL_DUMP_STATS))); + SWIG_Python_SetConstant(d, "__NL_DUMP_MAX",SWIG_From_int((int)(__NL_DUMP_MAX))); + SWIG_Python_SetConstant(d, "NL_AUTO_PROVIDE",SWIG_From_int((int)(1))); +#if PY_VERSION_HEX >= 0x03000000 + return m; +#else + return; +#endif +} + diff --git a/python/netlink/core.py b/python/netlink/core.py index f97528d..e311d5f 100644 --- a/python/netlink/core.py +++ b/python/netlink/core.py @@ -254,6 +254,7 @@ class Object(object): def __init__(self, obj_name, name, obj=None): self._obj_name = obj_name self._name = name + self._modules = [] if not obj: obj = capi.object_alloc_name(self._obj_name) @@ -284,6 +285,45 @@ class Object(object): """Clone object""" return self._new_instance(capi.nl_object_clone(self._nl_object)) + def _module_lookup(self, path, constructor=None): + """Lookup object specific module and load it + + Object implementations consisting of multiple types may + offload some type specific code to separate modules which + are loadable on demand, e.g. a VLAN link or a specific + queueing discipline implementation. + + Loads the module `path` and calls the constructor if + supplied or `module`.init() + + The constructor/init function typically assigns a new + object covering the type specific implementation aspects + to the new object, e.g. link.vlan = VLANLink() + """ + try: + tmp = __import__(path) + except ImportError: + return + + module = sys.modules[path] + + if constructor: + ret = getattr(module, constructor)(self) + else: + ret = module.init(self) + + if ret: + self._modules.append(ret) + + def _module_brief(self): + ret = '' + + for module in self._modules: + if hasattr(module, 'brief'): + ret += module.brief() + + return ret + def dump(self, params=None): """Dump object as human readable text""" if params is None: @@ -291,6 +331,7 @@ class Object(object): capi.nl_object_dump(self._nl_object, params._dp) + ##################################################################### # mark @property @@ -361,12 +402,15 @@ class Object(object): class ObjIterator(object): def __init__(self, cache, obj): self._cache = cache + self._nl_object = None - capi.nl_object_get(obj) - self._nl_object = obj - - self._first = 1 - self._end = 0 + if not obj: + self._end = 1 + else: + capi.nl_object_get(obj) + self._nl_object = obj + self._first = 1 + self._end = 0 def __del__(self): if self._nl_object: @@ -415,21 +459,21 @@ class Cache(object): raise NotImplementedError() def __del(self): - capi.nl_cache_free(self._c_cache) + capi.nl_cache_free(self._nl_cache) def __len__(self): - return capi.nl_cache_nitems(self._c_cache) + return capi.nl_cache_nitems(self._nl_cache) def __iter__(self): - obj = capi.nl_cache_get_first(self._c_cache) + obj = capi.nl_cache_get_first(self._nl_cache) return ObjIterator(self, obj) def __reversed__(self): - obj = capi.nl_cache_get_last(self._c_cache) + obj = capi.nl_cache_get_last(self._nl_cache) return ReverseObjIterator(self, obj) def __contains__(self, item): - obj = capi.nl_cache_search(self._c_cache, item._nl_object) + obj = capi.nl_cache_search(self._nl_cache, item._nl_object) if obj is None: return False else: @@ -458,7 +502,7 @@ class Cache(object): if not filter: raise ValueError() - c = capi.nl_cache_subset(self._c_cache, filter._nl_object) + c = capi.nl_cache_subset(self._nl_cache, filter._nl_object) return self._new_cache(cache=c) def dump(self, params=None, filter=None): @@ -469,28 +513,28 @@ class Cache(object): if filter: filter = filter._nl_object - capi.nl_cache_dump_filter(self._c_cache, params._dp, filter) + capi.nl_cache_dump_filter(self._nl_cache, params._dp, filter) def clear(self): """Remove all cache entries""" - capi.nl_cache_clear(self._c_cache) + capi.nl_cache_clear(self._nl_cache) # Called by sub classes to set first cache argument def _set_arg1(self, arg): self.arg1 = arg - capi.nl_cache_set_arg1(self._c_cache, arg) + capi.nl_cache_set_arg1(self._nl_cache, arg) # Called by sub classes to set second cache argument def _set_arg2(self, arg): self.arg2 = arg - capi.nl_cache_set_arg2(self._c_cache, arg) + capi.nl_cache_set_arg2(self._nl_cache, arg) def refill(self, socket=None): """Clear cache and refill it""" if socket is None: socket = lookup_socket(self._protocol) - capi.nl_cache_refill(socket._sock, self._c_cache) + capi.nl_cache_refill(socket._sock, self._nl_cache) return self def resync(self, socket=None, cb=None): @@ -498,7 +542,7 @@ class Cache(object): if socket is None: socket = lookup_socket(self._protocol) - capi.nl_cache_resync(socket._sock, self._c_cache, cb) + capi.nl_cache_resync(socket._sock, self._nl_cache, cb) def provide(self): """Provide this cache to others @@ -510,7 +554,7 @@ class Cache(object): link names """ - capi.nl_cache_mngt_provide(self._c_cache) + capi.nl_cache_mngt_provide(self._nl_cache) def unprovide(self): """Unprovide this cache @@ -519,7 +563,7 @@ class Cache(object): has been handed out already, that reference will still be valid. """ - capi.nl_cache_mngt_unprovide(self._c_cache) + capi.nl_cache_mngt_unprovide(self._nl_cache) ########################################################################### # Cache Manager (Work in Progress) @@ -708,7 +752,7 @@ class AbstractAddress(object): # attrs = {} -def attr(name, **kwds): +def add_attr(name, **kwds): attrs[name] = {} for k in kwds: attrs[name][k] = kwds[k] @@ -726,6 +770,7 @@ def nlattr(name, **kwds): return self._my_attr """ + attrs[name] = {} for k in kwds: attrs[name][k] = kwds[k] diff --git a/python/netlink/core.pyc b/python/netlink/core.pyc new file mode 100644 index 0000000000000000000000000000000000000000..db86228abc28968d27aaaa374391b37ddac119b0 GIT binary patch literal 28503 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 literal 0 HcmV?d00001 diff --git a/python/netlink/route/address.py b/python/netlink/route/address.py index c0ce54f..d70664c 100644 --- a/python/netlink/route/address.py +++ b/python/netlink/route/address.py @@ -27,7 +27,7 @@ class AddressCache(netlink.Cache): cache = self._alloc_cache_name("route/addr") self._protocol = netlink.NETLINK_ROUTE - self._c_cache = cache + self._nl_cache = cache def __getitem__(self, key): # Using ifindex=0 here implies that the local address itself @@ -38,7 +38,7 @@ class AddressCache(netlink.Cache): if type(local) is str: local = netlink.AbstractAddress(local) - addr = capi.rtnl_addr_get(self._c_cache, ifindex, + addr = capi.rtnl_addr_get(self._nl_cache, ifindex, local._nl_addr) if addr is None: raise KeyError() diff --git a/python/netlink/route/capi.i b/python/netlink/route/capi.i index abe3cc9..204f93a 100644 --- a/python/netlink/route/capi.i +++ b/python/netlink/route/capi.i @@ -7,6 +7,10 @@ #include #include +#include +#include + +#include #include %} @@ -231,6 +235,26 @@ extern int rtnl_classid_generate(const char *, uint32_t *, uint32_t); return (struct rtnl_qdisc *) obj; } + struct nl_object *class2obj(struct rtnl_class *cl) + { + return OBJ_CAST(cl); + } + + struct rtnl_class *obj2class(struct nl_object *obj) + { + return (struct rtnl_class *) obj; + } + + struct nl_object *cls2obj(struct rtnl_cls *cls) + { + return OBJ_CAST(cls); + } + + struct rtnl_cls *obj2cls(struct nl_object *obj) + { + return (struct rtnl_cls *) obj; + } + struct rtnl_tc *obj2tc(struct nl_object *obj) { return TC_CAST(obj); @@ -260,6 +284,43 @@ extern int rtnl_qdisc_build_delete_request(struct rtnl_qdisc *, struct nl_msg **); extern int rtnl_qdisc_delete(struct nl_sock *, struct rtnl_qdisc *); +/* */ + +extern struct rtnl_cls *rtnl_cls_alloc(void); +extern void rtnl_cls_put(struct rtnl_cls *); + +extern int rtnl_cls_add(struct nl_sock *, struct rtnl_cls *, int); + +extern int rtnl_cls_delete(struct nl_sock *, struct rtnl_cls *, + int); + +extern void rtnl_cls_set_prio(struct rtnl_cls *, uint16_t); +extern uint16_t rtnl_cls_get_prio(struct rtnl_cls *); + +extern void rtnl_cls_set_protocol(struct rtnl_cls *, uint16_t); +extern uint16_t rtnl_cls_get_protocol(struct rtnl_cls *); + +/* */ + +extern uint32_t rtnl_htb_get_rate2quantum(struct rtnl_qdisc *); +extern int rtnl_htb_set_rate2quantum(struct rtnl_qdisc *, uint32_t); +extern uint32_t rtnl_htb_get_defcls(struct rtnl_qdisc *); +extern int rtnl_htb_set_defcls(struct rtnl_qdisc *, uint32_t); + +extern uint32_t rtnl_htb_get_prio(struct rtnl_class *); +extern int rtnl_htb_set_prio(struct rtnl_class *, uint32_t); +extern uint32_t rtnl_htb_get_rate(struct rtnl_class *); +extern int rtnl_htb_set_rate(struct rtnl_class *, uint32_t); +extern uint32_t rtnl_htb_get_ceil(struct rtnl_class *); +extern int rtnl_htb_set_ceil(struct rtnl_class *, uint32_t); +extern uint32_t rtnl_htb_get_rbuffer(struct rtnl_class *); +extern int rtnl_htb_set_rbuffer(struct rtnl_class *, uint32_t); +extern uint32_t rtnl_htb_get_cbuffer(struct rtnl_class *); +extern int rtnl_htb_set_cbuffer(struct rtnl_class *, uint32_t); +extern uint32_t rtnl_htb_get_quantum(struct rtnl_class *); +extern int rtnl_htb_set_quantum(struct rtnl_class *, uint32_t); +extern int rtnl_htb_get_level(struct rtnl_class *); + /* */ %inline %{ diff --git a/python/netlink/route/capi.py b/python/netlink/route/capi.py new file mode 100644 index 0000000..66356a5 --- /dev/null +++ b/python/netlink/route/capi.py @@ -0,0 +1,830 @@ +# This file was automatically generated by SWIG (http://www.swig.org). +# Version 1.3.40 +# +# Do not make changes to this file unless you know what you are doing--modify +# the SWIG interface file instead. + +from sys import version_info +if version_info >= (3,0,0): + new_instancemethod = lambda func, inst, cls: _capi.SWIG_PyInstanceMethod_New(func) +else: + from new import instancemethod as new_instancemethod +if version_info >= (2,6,0): + def swig_import_helper(): + from os.path import dirname + import imp + fp = None + try: + fp, pathname, description = imp.find_module('_capi', [dirname(__file__)]) + except ImportError: + import _capi + return _capi + if fp is not None: + try: + _mod = imp.load_module('_capi', fp, pathname, description) + finally: + fp.close() + return _mod + _capi = swig_import_helper() + del swig_import_helper +else: + import _capi +del version_info +try: + _swig_property = property +except NameError: + pass # Python < 2.2 doesn't have 'property'. +def _swig_setattr_nondynamic(self,class_type,name,value,static=1): + if (name == "thisown"): return self.this.own(value) + if (name == "this"): + if type(value).__name__ == 'SwigPyObject': + self.__dict__[name] = value + return + method = class_type.__swig_setmethods__.get(name,None) + if method: return method(self,value) + if (not static) or hasattr(self,name): + self.__dict__[name] = value + else: + raise AttributeError("You cannot add attributes to %s" % self) + +def _swig_setattr(self,class_type,name,value): + return _swig_setattr_nondynamic(self,class_type,name,value,0) + +def _swig_getattr(self,class_type,name): + if (name == "thisown"): return self.this.own() + method = class_type.__swig_getmethods__.get(name,None) + if method: return method(self) + raise AttributeError(name) + +def _swig_repr(self): + try: strthis = "proxy of " + self.this.__repr__() + except: strthis = "" + return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,) + +try: + _object = object + _newclass = 1 +except AttributeError: + class _object : pass + _newclass = 0 + + +def _swig_setattr_nondynamic_method(set): + def set_attr(self,name,value): + if (name == "thisown"): return self.this.own(value) + if hasattr(self,name) or (name == "this"): + set(self,name,value) + else: + raise AttributeError("You cannot add attributes to %s" % self) + return set_attr + + + +def link2obj(*args): + return _capi.link2obj(*args) +link2obj = _capi.link2obj + +def obj2link(*args): + return _capi.obj2link(*args) +obj2link = _capi.obj2link + +def get_from_kernel(*args): + return _capi.get_from_kernel(*args) +get_from_kernel = _capi.get_from_kernel + +def inet_get_conf(*args): + return _capi.inet_get_conf(*args) +inet_get_conf = _capi.inet_get_conf + +def rtnl_scope2str(*args): + return _capi.rtnl_scope2str(*args) +rtnl_scope2str = _capi.rtnl_scope2str + +def rtnl_str2scope(*args): + return _capi.rtnl_str2scope(*args) +rtnl_str2scope = _capi.rtnl_str2scope + +def rtnl_link_alloc(): + return _capi.rtnl_link_alloc() +rtnl_link_alloc = _capi.rtnl_link_alloc + +def rtnl_link_get(*args): + return _capi.rtnl_link_get(*args) +rtnl_link_get = _capi.rtnl_link_get + +def rtnl_link_get_by_name(*args): + return _capi.rtnl_link_get_by_name(*args) +rtnl_link_get_by_name = _capi.rtnl_link_get_by_name + +def rtnl_link_build_add_request(*args): + return _capi.rtnl_link_build_add_request(*args) +rtnl_link_build_add_request = _capi.rtnl_link_build_add_request + +def rtnl_link_add(*args): + return _capi.rtnl_link_add(*args) +rtnl_link_add = _capi.rtnl_link_add + +def rtnl_link_build_change_request(*args): + return _capi.rtnl_link_build_change_request(*args) +rtnl_link_build_change_request = _capi.rtnl_link_build_change_request + +def rtnl_link_change(*args): + return _capi.rtnl_link_change(*args) +rtnl_link_change = _capi.rtnl_link_change + +def rtnl_link_build_delete_request(*args): + return _capi.rtnl_link_build_delete_request(*args) +rtnl_link_build_delete_request = _capi.rtnl_link_build_delete_request + +def rtnl_link_delete(*args): + return _capi.rtnl_link_delete(*args) +rtnl_link_delete = _capi.rtnl_link_delete + +def rtnl_link_build_get_request(*args): + return _capi.rtnl_link_build_get_request(*args) +rtnl_link_build_get_request = _capi.rtnl_link_build_get_request + +def rtnl_link_stat2str(*args): + return _capi.rtnl_link_stat2str(*args) +rtnl_link_stat2str = _capi.rtnl_link_stat2str + +def rtnl_link_str2stat(*args): + return _capi.rtnl_link_str2stat(*args) +rtnl_link_str2stat = _capi.rtnl_link_str2stat + +def rtnl_link_flags2str(*args): + return _capi.rtnl_link_flags2str(*args) +rtnl_link_flags2str = _capi.rtnl_link_flags2str + +def rtnl_link_str2flags(*args): + return _capi.rtnl_link_str2flags(*args) +rtnl_link_str2flags = _capi.rtnl_link_str2flags + +def rtnl_link_operstate2str(*args): + return _capi.rtnl_link_operstate2str(*args) +rtnl_link_operstate2str = _capi.rtnl_link_operstate2str + +def rtnl_link_str2operstate(*args): + return _capi.rtnl_link_str2operstate(*args) +rtnl_link_str2operstate = _capi.rtnl_link_str2operstate + +def rtnl_link_mode2str(*args): + return _capi.rtnl_link_mode2str(*args) +rtnl_link_mode2str = _capi.rtnl_link_mode2str + +def rtnl_link_str2mode(*args): + return _capi.rtnl_link_str2mode(*args) +rtnl_link_str2mode = _capi.rtnl_link_str2mode + +def rtnl_link_set_qdisc(*args): + return _capi.rtnl_link_set_qdisc(*args) +rtnl_link_set_qdisc = _capi.rtnl_link_set_qdisc + +def rtnl_link_get_qdisc(*args): + return _capi.rtnl_link_get_qdisc(*args) +rtnl_link_get_qdisc = _capi.rtnl_link_get_qdisc + +def rtnl_link_set_name(*args): + return _capi.rtnl_link_set_name(*args) +rtnl_link_set_name = _capi.rtnl_link_set_name + +def rtnl_link_get_name(*args): + return _capi.rtnl_link_get_name(*args) +rtnl_link_get_name = _capi.rtnl_link_get_name + +def rtnl_link_set_flags(*args): + return _capi.rtnl_link_set_flags(*args) +rtnl_link_set_flags = _capi.rtnl_link_set_flags + +def rtnl_link_unset_flags(*args): + return _capi.rtnl_link_unset_flags(*args) +rtnl_link_unset_flags = _capi.rtnl_link_unset_flags + +def rtnl_link_get_flags(*args): + return _capi.rtnl_link_get_flags(*args) +rtnl_link_get_flags = _capi.rtnl_link_get_flags + +def rtnl_link_set_mtu(*args): + return _capi.rtnl_link_set_mtu(*args) +rtnl_link_set_mtu = _capi.rtnl_link_set_mtu + +def rtnl_link_get_mtu(*args): + return _capi.rtnl_link_get_mtu(*args) +rtnl_link_get_mtu = _capi.rtnl_link_get_mtu + +def rtnl_link_set_txqlen(*args): + return _capi.rtnl_link_set_txqlen(*args) +rtnl_link_set_txqlen = _capi.rtnl_link_set_txqlen + +def rtnl_link_get_txqlen(*args): + return _capi.rtnl_link_get_txqlen(*args) +rtnl_link_get_txqlen = _capi.rtnl_link_get_txqlen + +def rtnl_link_set_weight(*args): + return _capi.rtnl_link_set_weight(*args) +rtnl_link_set_weight = _capi.rtnl_link_set_weight + +def rtnl_link_get_weight(*args): + return _capi.rtnl_link_get_weight(*args) +rtnl_link_get_weight = _capi.rtnl_link_get_weight + +def rtnl_link_set_ifindex(*args): + return _capi.rtnl_link_set_ifindex(*args) +rtnl_link_set_ifindex = _capi.rtnl_link_set_ifindex + +def rtnl_link_get_ifindex(*args): + return _capi.rtnl_link_get_ifindex(*args) +rtnl_link_get_ifindex = _capi.rtnl_link_get_ifindex + +def rtnl_link_set_family(*args): + return _capi.rtnl_link_set_family(*args) +rtnl_link_set_family = _capi.rtnl_link_set_family + +def rtnl_link_get_family(*args): + return _capi.rtnl_link_get_family(*args) +rtnl_link_get_family = _capi.rtnl_link_get_family + +def rtnl_link_set_arptype(*args): + return _capi.rtnl_link_set_arptype(*args) +rtnl_link_set_arptype = _capi.rtnl_link_set_arptype + +def rtnl_link_get_arptype(*args): + return _capi.rtnl_link_get_arptype(*args) +rtnl_link_get_arptype = _capi.rtnl_link_get_arptype + +def rtnl_link_set_addr(*args): + return _capi.rtnl_link_set_addr(*args) +rtnl_link_set_addr = _capi.rtnl_link_set_addr + +def rtnl_link_get_addr(*args): + return _capi.rtnl_link_get_addr(*args) +rtnl_link_get_addr = _capi.rtnl_link_get_addr + +def rtnl_link_set_broadcast(*args): + return _capi.rtnl_link_set_broadcast(*args) +rtnl_link_set_broadcast = _capi.rtnl_link_set_broadcast + +def rtnl_link_get_broadcast(*args): + return _capi.rtnl_link_get_broadcast(*args) +rtnl_link_get_broadcast = _capi.rtnl_link_get_broadcast + +def rtnl_link_set_link(*args): + return _capi.rtnl_link_set_link(*args) +rtnl_link_set_link = _capi.rtnl_link_set_link + +def rtnl_link_get_link(*args): + return _capi.rtnl_link_get_link(*args) +rtnl_link_get_link = _capi.rtnl_link_get_link + +def rtnl_link_set_master(*args): + return _capi.rtnl_link_set_master(*args) +rtnl_link_set_master = _capi.rtnl_link_set_master + +def rtnl_link_get_master(*args): + return _capi.rtnl_link_get_master(*args) +rtnl_link_get_master = _capi.rtnl_link_get_master + +def rtnl_link_set_operstate(*args): + return _capi.rtnl_link_set_operstate(*args) +rtnl_link_set_operstate = _capi.rtnl_link_set_operstate + +def rtnl_link_get_operstate(*args): + return _capi.rtnl_link_get_operstate(*args) +rtnl_link_get_operstate = _capi.rtnl_link_get_operstate + +def rtnl_link_set_linkmode(*args): + return _capi.rtnl_link_set_linkmode(*args) +rtnl_link_set_linkmode = _capi.rtnl_link_set_linkmode + +def rtnl_link_get_linkmode(*args): + return _capi.rtnl_link_get_linkmode(*args) +rtnl_link_get_linkmode = _capi.rtnl_link_get_linkmode + +def rtnl_link_get_ifalias(*args): + return _capi.rtnl_link_get_ifalias(*args) +rtnl_link_get_ifalias = _capi.rtnl_link_get_ifalias + +def rtnl_link_set_ifalias(*args): + return _capi.rtnl_link_set_ifalias(*args) +rtnl_link_set_ifalias = _capi.rtnl_link_set_ifalias + +def rtnl_link_get_num_vf(*args): + return _capi.rtnl_link_get_num_vf(*args) +rtnl_link_get_num_vf = _capi.rtnl_link_get_num_vf + +def rtnl_link_get_stat(*args): + return _capi.rtnl_link_get_stat(*args) +rtnl_link_get_stat = _capi.rtnl_link_get_stat + +def rtnl_link_set_stat(*args): + return _capi.rtnl_link_set_stat(*args) +rtnl_link_set_stat = _capi.rtnl_link_set_stat + +def rtnl_link_set_info_type(*args): + return _capi.rtnl_link_set_info_type(*args) +rtnl_link_set_info_type = _capi.rtnl_link_set_info_type + +def rtnl_link_get_info_type(*args): + return _capi.rtnl_link_get_info_type(*args) +rtnl_link_get_info_type = _capi.rtnl_link_get_info_type +class vlan_map(object): + thisown = _swig_property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag') + def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined") + __repr__ = _swig_repr + vm_from = _swig_property(_capi.vlan_map_vm_from_get, _capi.vlan_map_vm_from_set) + vm_to = _swig_property(_capi.vlan_map_vm_to_get, _capi.vlan_map_vm_to_set) + __swig_destroy__ = _capi.delete_vlan_map +vlan_map_swigregister = _capi.vlan_map_swigregister +vlan_map_swigregister(vlan_map) + +VLAN_PRIO_MAX = _capi.VLAN_PRIO_MAX + +def rtnl_link_vlan_flags2str(*args): + return _capi.rtnl_link_vlan_flags2str(*args) +rtnl_link_vlan_flags2str = _capi.rtnl_link_vlan_flags2str + +def rtnl_link_vlan_str2flags(*args): + return _capi.rtnl_link_vlan_str2flags(*args) +rtnl_link_vlan_str2flags = _capi.rtnl_link_vlan_str2flags + +def rtnl_link_vlan_set_id(*args): + return _capi.rtnl_link_vlan_set_id(*args) +rtnl_link_vlan_set_id = _capi.rtnl_link_vlan_set_id + +def rtnl_link_vlan_get_id(*args): + return _capi.rtnl_link_vlan_get_id(*args) +rtnl_link_vlan_get_id = _capi.rtnl_link_vlan_get_id + +def rtnl_link_vlan_set_flags(*args): + return _capi.rtnl_link_vlan_set_flags(*args) +rtnl_link_vlan_set_flags = _capi.rtnl_link_vlan_set_flags + +def rtnl_link_vlan_unset_flags(*args): + return _capi.rtnl_link_vlan_unset_flags(*args) +rtnl_link_vlan_unset_flags = _capi.rtnl_link_vlan_unset_flags + +def rtnl_link_vlan_get_flags(*args): + return _capi.rtnl_link_vlan_get_flags(*args) +rtnl_link_vlan_get_flags = _capi.rtnl_link_vlan_get_flags + +def rtnl_link_vlan_set_ingress_map(*args): + return _capi.rtnl_link_vlan_set_ingress_map(*args) +rtnl_link_vlan_set_ingress_map = _capi.rtnl_link_vlan_set_ingress_map + +def rtnl_link_vlan_get_ingress_map(*args): + return _capi.rtnl_link_vlan_get_ingress_map(*args) +rtnl_link_vlan_get_ingress_map = _capi.rtnl_link_vlan_get_ingress_map + +def rtnl_link_vlan_set_egress_map(*args): + return _capi.rtnl_link_vlan_set_egress_map(*args) +rtnl_link_vlan_set_egress_map = _capi.rtnl_link_vlan_set_egress_map + +def rtnl_link_vlan_get_egress_map(*args): + return _capi.rtnl_link_vlan_get_egress_map(*args) +rtnl_link_vlan_get_egress_map = _capi.rtnl_link_vlan_get_egress_map + +def rtnl_link_inet_devconf2str(*args): + return _capi.rtnl_link_inet_devconf2str(*args) +rtnl_link_inet_devconf2str = _capi.rtnl_link_inet_devconf2str + +def rtnl_link_inet_str2devconf(*args): + return _capi.rtnl_link_inet_str2devconf(*args) +rtnl_link_inet_str2devconf = _capi.rtnl_link_inet_str2devconf + +def rtnl_link_inet_set_conf(*args): + return _capi.rtnl_link_inet_set_conf(*args) +rtnl_link_inet_set_conf = _capi.rtnl_link_inet_set_conf + +def tc_str2handle(*args): + return _capi.tc_str2handle(*args) +tc_str2handle = _capi.tc_str2handle + +def rtnl_tc_set_ifindex(*args): + return _capi.rtnl_tc_set_ifindex(*args) +rtnl_tc_set_ifindex = _capi.rtnl_tc_set_ifindex + +def rtnl_tc_get_ifindex(*args): + return _capi.rtnl_tc_get_ifindex(*args) +rtnl_tc_get_ifindex = _capi.rtnl_tc_get_ifindex + +def rtnl_tc_set_link(*args): + return _capi.rtnl_tc_set_link(*args) +rtnl_tc_set_link = _capi.rtnl_tc_set_link + +def rtnl_tc_get_link(*args): + return _capi.rtnl_tc_get_link(*args) +rtnl_tc_get_link = _capi.rtnl_tc_get_link + +def rtnl_tc_set_mtu(*args): + return _capi.rtnl_tc_set_mtu(*args) +rtnl_tc_set_mtu = _capi.rtnl_tc_set_mtu + +def rtnl_tc_get_mtu(*args): + return _capi.rtnl_tc_get_mtu(*args) +rtnl_tc_get_mtu = _capi.rtnl_tc_get_mtu + +def rtnl_tc_set_mpu(*args): + return _capi.rtnl_tc_set_mpu(*args) +rtnl_tc_set_mpu = _capi.rtnl_tc_set_mpu + +def rtnl_tc_get_mpu(*args): + return _capi.rtnl_tc_get_mpu(*args) +rtnl_tc_get_mpu = _capi.rtnl_tc_get_mpu + +def rtnl_tc_set_overhead(*args): + return _capi.rtnl_tc_set_overhead(*args) +rtnl_tc_set_overhead = _capi.rtnl_tc_set_overhead + +def rtnl_tc_get_overhead(*args): + return _capi.rtnl_tc_get_overhead(*args) +rtnl_tc_get_overhead = _capi.rtnl_tc_get_overhead + +def rtnl_tc_set_linktype(*args): + return _capi.rtnl_tc_set_linktype(*args) +rtnl_tc_set_linktype = _capi.rtnl_tc_set_linktype + +def rtnl_tc_get_linktype(*args): + return _capi.rtnl_tc_get_linktype(*args) +rtnl_tc_get_linktype = _capi.rtnl_tc_get_linktype + +def rtnl_tc_set_handle(*args): + return _capi.rtnl_tc_set_handle(*args) +rtnl_tc_set_handle = _capi.rtnl_tc_set_handle + +def rtnl_tc_get_handle(*args): + return _capi.rtnl_tc_get_handle(*args) +rtnl_tc_get_handle = _capi.rtnl_tc_get_handle + +def rtnl_tc_set_parent(*args): + return _capi.rtnl_tc_set_parent(*args) +rtnl_tc_set_parent = _capi.rtnl_tc_set_parent + +def rtnl_tc_get_parent(*args): + return _capi.rtnl_tc_get_parent(*args) +rtnl_tc_get_parent = _capi.rtnl_tc_get_parent + +def rtnl_tc_set_kind(*args): + return _capi.rtnl_tc_set_kind(*args) +rtnl_tc_set_kind = _capi.rtnl_tc_set_kind + +def rtnl_tc_get_kind(*args): + return _capi.rtnl_tc_get_kind(*args) +rtnl_tc_get_kind = _capi.rtnl_tc_get_kind + +def rtnl_tc_get_stat(*args): + return _capi.rtnl_tc_get_stat(*args) +rtnl_tc_get_stat = _capi.rtnl_tc_get_stat + +def rtnl_tc_calc_txtime(*args): + return _capi.rtnl_tc_calc_txtime(*args) +rtnl_tc_calc_txtime = _capi.rtnl_tc_calc_txtime + +def rtnl_tc_calc_bufsize(*args): + return _capi.rtnl_tc_calc_bufsize(*args) +rtnl_tc_calc_bufsize = _capi.rtnl_tc_calc_bufsize + +def rtnl_tc_calc_cell_log(*args): + return _capi.rtnl_tc_calc_cell_log(*args) +rtnl_tc_calc_cell_log = _capi.rtnl_tc_calc_cell_log + +def rtnl_tc_read_classid_file(): + return _capi.rtnl_tc_read_classid_file() +rtnl_tc_read_classid_file = _capi.rtnl_tc_read_classid_file + +def rtnl_tc_handle2str(*args): + return _capi.rtnl_tc_handle2str(*args) +rtnl_tc_handle2str = _capi.rtnl_tc_handle2str + +def rtnl_classid_generate(*args): + return _capi.rtnl_classid_generate(*args) +rtnl_classid_generate = _capi.rtnl_classid_generate + +def qdisc2obj(*args): + return _capi.qdisc2obj(*args) +qdisc2obj = _capi.qdisc2obj + +def obj2qdisc(*args): + return _capi.obj2qdisc(*args) +obj2qdisc = _capi.obj2qdisc + +def class2obj(*args): + return _capi.class2obj(*args) +class2obj = _capi.class2obj + +def obj2class(*args): + return _capi.obj2class(*args) +obj2class = _capi.obj2class + +def cls2obj(*args): + return _capi.cls2obj(*args) +cls2obj = _capi.cls2obj + +def obj2cls(*args): + return _capi.obj2cls(*args) +obj2cls = _capi.obj2cls + +def obj2tc(*args): + return _capi.obj2tc(*args) +obj2tc = _capi.obj2tc + +def rtnl_qdisc_alloc(): + return _capi.rtnl_qdisc_alloc() +rtnl_qdisc_alloc = _capi.rtnl_qdisc_alloc + +def rtnl_qdisc_get(*args): + return _capi.rtnl_qdisc_get(*args) +rtnl_qdisc_get = _capi.rtnl_qdisc_get + +def rtnl_qdisc_get_by_parent(*args): + return _capi.rtnl_qdisc_get_by_parent(*args) +rtnl_qdisc_get_by_parent = _capi.rtnl_qdisc_get_by_parent + +def rtnl_qdisc_build_add_request(*args): + return _capi.rtnl_qdisc_build_add_request(*args) +rtnl_qdisc_build_add_request = _capi.rtnl_qdisc_build_add_request + +def rtnl_qdisc_add(*args): + return _capi.rtnl_qdisc_add(*args) +rtnl_qdisc_add = _capi.rtnl_qdisc_add + +def rtnl_qdisc_build_update_request(*args): + return _capi.rtnl_qdisc_build_update_request(*args) +rtnl_qdisc_build_update_request = _capi.rtnl_qdisc_build_update_request + +def rtnl_qdisc_update(*args): + return _capi.rtnl_qdisc_update(*args) +rtnl_qdisc_update = _capi.rtnl_qdisc_update + +def rtnl_qdisc_build_delete_request(*args): + return _capi.rtnl_qdisc_build_delete_request(*args) +rtnl_qdisc_build_delete_request = _capi.rtnl_qdisc_build_delete_request + +def rtnl_qdisc_delete(*args): + return _capi.rtnl_qdisc_delete(*args) +rtnl_qdisc_delete = _capi.rtnl_qdisc_delete + +def rtnl_cls_alloc(): + return _capi.rtnl_cls_alloc() +rtnl_cls_alloc = _capi.rtnl_cls_alloc + +def rtnl_cls_put(*args): + return _capi.rtnl_cls_put(*args) +rtnl_cls_put = _capi.rtnl_cls_put + +def rtnl_cls_add(*args): + return _capi.rtnl_cls_add(*args) +rtnl_cls_add = _capi.rtnl_cls_add + +def rtnl_cls_delete(*args): + return _capi.rtnl_cls_delete(*args) +rtnl_cls_delete = _capi.rtnl_cls_delete + +def rtnl_cls_set_prio(*args): + return _capi.rtnl_cls_set_prio(*args) +rtnl_cls_set_prio = _capi.rtnl_cls_set_prio + +def rtnl_cls_get_prio(*args): + return _capi.rtnl_cls_get_prio(*args) +rtnl_cls_get_prio = _capi.rtnl_cls_get_prio + +def rtnl_cls_set_protocol(*args): + return _capi.rtnl_cls_set_protocol(*args) +rtnl_cls_set_protocol = _capi.rtnl_cls_set_protocol + +def rtnl_cls_get_protocol(*args): + return _capi.rtnl_cls_get_protocol(*args) +rtnl_cls_get_protocol = _capi.rtnl_cls_get_protocol + +def rtnl_htb_get_rate2quantum(*args): + return _capi.rtnl_htb_get_rate2quantum(*args) +rtnl_htb_get_rate2quantum = _capi.rtnl_htb_get_rate2quantum + +def rtnl_htb_set_rate2quantum(*args): + return _capi.rtnl_htb_set_rate2quantum(*args) +rtnl_htb_set_rate2quantum = _capi.rtnl_htb_set_rate2quantum + +def rtnl_htb_get_defcls(*args): + return _capi.rtnl_htb_get_defcls(*args) +rtnl_htb_get_defcls = _capi.rtnl_htb_get_defcls + +def rtnl_htb_set_defcls(*args): + return _capi.rtnl_htb_set_defcls(*args) +rtnl_htb_set_defcls = _capi.rtnl_htb_set_defcls + +def rtnl_htb_get_prio(*args): + return _capi.rtnl_htb_get_prio(*args) +rtnl_htb_get_prio = _capi.rtnl_htb_get_prio + +def rtnl_htb_set_prio(*args): + return _capi.rtnl_htb_set_prio(*args) +rtnl_htb_set_prio = _capi.rtnl_htb_set_prio + +def rtnl_htb_get_rate(*args): + return _capi.rtnl_htb_get_rate(*args) +rtnl_htb_get_rate = _capi.rtnl_htb_get_rate + +def rtnl_htb_set_rate(*args): + return _capi.rtnl_htb_set_rate(*args) +rtnl_htb_set_rate = _capi.rtnl_htb_set_rate + +def rtnl_htb_get_ceil(*args): + return _capi.rtnl_htb_get_ceil(*args) +rtnl_htb_get_ceil = _capi.rtnl_htb_get_ceil + +def rtnl_htb_set_ceil(*args): + return _capi.rtnl_htb_set_ceil(*args) +rtnl_htb_set_ceil = _capi.rtnl_htb_set_ceil + +def rtnl_htb_get_rbuffer(*args): + return _capi.rtnl_htb_get_rbuffer(*args) +rtnl_htb_get_rbuffer = _capi.rtnl_htb_get_rbuffer + +def rtnl_htb_set_rbuffer(*args): + return _capi.rtnl_htb_set_rbuffer(*args) +rtnl_htb_set_rbuffer = _capi.rtnl_htb_set_rbuffer + +def rtnl_htb_get_cbuffer(*args): + return _capi.rtnl_htb_get_cbuffer(*args) +rtnl_htb_get_cbuffer = _capi.rtnl_htb_get_cbuffer + +def rtnl_htb_set_cbuffer(*args): + return _capi.rtnl_htb_set_cbuffer(*args) +rtnl_htb_set_cbuffer = _capi.rtnl_htb_set_cbuffer + +def rtnl_htb_get_quantum(*args): + return _capi.rtnl_htb_get_quantum(*args) +rtnl_htb_get_quantum = _capi.rtnl_htb_get_quantum + +def rtnl_htb_set_quantum(*args): + return _capi.rtnl_htb_set_quantum(*args) +rtnl_htb_set_quantum = _capi.rtnl_htb_set_quantum + +def rtnl_htb_get_level(*args): + return _capi.rtnl_htb_get_level(*args) +rtnl_htb_get_level = _capi.rtnl_htb_get_level + +def addr2obj(*args): + return _capi.addr2obj(*args) +addr2obj = _capi.addr2obj + +def obj2addr(*args): + return _capi.obj2addr(*args) +obj2addr = _capi.obj2addr + +def rtnl_addr_alloc(): + return _capi.rtnl_addr_alloc() +rtnl_addr_alloc = _capi.rtnl_addr_alloc + +def rtnl_addr_get(*args): + return _capi.rtnl_addr_get(*args) +rtnl_addr_get = _capi.rtnl_addr_get + +def rtnl_addr_build_add_request(*args): + return _capi.rtnl_addr_build_add_request(*args) +rtnl_addr_build_add_request = _capi.rtnl_addr_build_add_request + +def rtnl_addr_add(*args): + return _capi.rtnl_addr_add(*args) +rtnl_addr_add = _capi.rtnl_addr_add + +def rtnl_addr_build_delete_request(*args): + return _capi.rtnl_addr_build_delete_request(*args) +rtnl_addr_build_delete_request = _capi.rtnl_addr_build_delete_request + +def rtnl_addr_delete(*args): + return _capi.rtnl_addr_delete(*args) +rtnl_addr_delete = _capi.rtnl_addr_delete + +def rtnl_addr_flags2str(*args): + return _capi.rtnl_addr_flags2str(*args) +rtnl_addr_flags2str = _capi.rtnl_addr_flags2str + +def rtnl_addr_str2flags(*args): + return _capi.rtnl_addr_str2flags(*args) +rtnl_addr_str2flags = _capi.rtnl_addr_str2flags + +def rtnl_addr_set_label(*args): + return _capi.rtnl_addr_set_label(*args) +rtnl_addr_set_label = _capi.rtnl_addr_set_label + +def rtnl_addr_get_label(*args): + return _capi.rtnl_addr_get_label(*args) +rtnl_addr_get_label = _capi.rtnl_addr_get_label + +def rtnl_addr_set_ifindex(*args): + return _capi.rtnl_addr_set_ifindex(*args) +rtnl_addr_set_ifindex = _capi.rtnl_addr_set_ifindex + +def rtnl_addr_get_ifindex(*args): + return _capi.rtnl_addr_get_ifindex(*args) +rtnl_addr_get_ifindex = _capi.rtnl_addr_get_ifindex + +def rtnl_addr_set_link(*args): + return _capi.rtnl_addr_set_link(*args) +rtnl_addr_set_link = _capi.rtnl_addr_set_link + +def rtnl_addr_get_link(*args): + return _capi.rtnl_addr_get_link(*args) +rtnl_addr_get_link = _capi.rtnl_addr_get_link + +def rtnl_addr_set_family(*args): + return _capi.rtnl_addr_set_family(*args) +rtnl_addr_set_family = _capi.rtnl_addr_set_family + +def rtnl_addr_get_family(*args): + return _capi.rtnl_addr_get_family(*args) +rtnl_addr_get_family = _capi.rtnl_addr_get_family + +def rtnl_addr_set_prefixlen(*args): + return _capi.rtnl_addr_set_prefixlen(*args) +rtnl_addr_set_prefixlen = _capi.rtnl_addr_set_prefixlen + +def rtnl_addr_get_prefixlen(*args): + return _capi.rtnl_addr_get_prefixlen(*args) +rtnl_addr_get_prefixlen = _capi.rtnl_addr_get_prefixlen + +def rtnl_addr_set_scope(*args): + return _capi.rtnl_addr_set_scope(*args) +rtnl_addr_set_scope = _capi.rtnl_addr_set_scope + +def rtnl_addr_get_scope(*args): + return _capi.rtnl_addr_get_scope(*args) +rtnl_addr_get_scope = _capi.rtnl_addr_get_scope + +def rtnl_addr_set_flags(*args): + return _capi.rtnl_addr_set_flags(*args) +rtnl_addr_set_flags = _capi.rtnl_addr_set_flags + +def rtnl_addr_unset_flags(*args): + return _capi.rtnl_addr_unset_flags(*args) +rtnl_addr_unset_flags = _capi.rtnl_addr_unset_flags + +def rtnl_addr_get_flags(*args): + return _capi.rtnl_addr_get_flags(*args) +rtnl_addr_get_flags = _capi.rtnl_addr_get_flags + +def rtnl_addr_set_local(*args): + return _capi.rtnl_addr_set_local(*args) +rtnl_addr_set_local = _capi.rtnl_addr_set_local + +def rtnl_addr_get_local(*args): + return _capi.rtnl_addr_get_local(*args) +rtnl_addr_get_local = _capi.rtnl_addr_get_local + +def rtnl_addr_set_peer(*args): + return _capi.rtnl_addr_set_peer(*args) +rtnl_addr_set_peer = _capi.rtnl_addr_set_peer + +def rtnl_addr_get_peer(*args): + return _capi.rtnl_addr_get_peer(*args) +rtnl_addr_get_peer = _capi.rtnl_addr_get_peer + +def rtnl_addr_set_broadcast(*args): + return _capi.rtnl_addr_set_broadcast(*args) +rtnl_addr_set_broadcast = _capi.rtnl_addr_set_broadcast + +def rtnl_addr_get_broadcast(*args): + return _capi.rtnl_addr_get_broadcast(*args) +rtnl_addr_get_broadcast = _capi.rtnl_addr_get_broadcast + +def rtnl_addr_set_multicast(*args): + return _capi.rtnl_addr_set_multicast(*args) +rtnl_addr_set_multicast = _capi.rtnl_addr_set_multicast + +def rtnl_addr_get_multicast(*args): + return _capi.rtnl_addr_get_multicast(*args) +rtnl_addr_get_multicast = _capi.rtnl_addr_get_multicast + +def rtnl_addr_set_anycast(*args): + return _capi.rtnl_addr_set_anycast(*args) +rtnl_addr_set_anycast = _capi.rtnl_addr_set_anycast + +def rtnl_addr_get_anycast(*args): + return _capi.rtnl_addr_get_anycast(*args) +rtnl_addr_get_anycast = _capi.rtnl_addr_get_anycast + +def rtnl_addr_get_valid_lifetime(*args): + return _capi.rtnl_addr_get_valid_lifetime(*args) +rtnl_addr_get_valid_lifetime = _capi.rtnl_addr_get_valid_lifetime + +def rtnl_addr_set_valid_lifetime(*args): + return _capi.rtnl_addr_set_valid_lifetime(*args) +rtnl_addr_set_valid_lifetime = _capi.rtnl_addr_set_valid_lifetime + +def rtnl_addr_get_preferred_lifetime(*args): + return _capi.rtnl_addr_get_preferred_lifetime(*args) +rtnl_addr_get_preferred_lifetime = _capi.rtnl_addr_get_preferred_lifetime + +def rtnl_addr_set_preferred_lifetime(*args): + return _capi.rtnl_addr_set_preferred_lifetime(*args) +rtnl_addr_set_preferred_lifetime = _capi.rtnl_addr_set_preferred_lifetime + +def rtnl_addr_get_create_time(*args): + return _capi.rtnl_addr_get_create_time(*args) +rtnl_addr_get_create_time = _capi.rtnl_addr_get_create_time + +def rtnl_addr_get_last_update_time(*args): + return _capi.rtnl_addr_get_last_update_time(*args) +rtnl_addr_get_last_update_time = _capi.rtnl_addr_get_last_update_time + + diff --git a/python/netlink/route/capi_wrap.c b/python/netlink/route/capi_wrap.c new file mode 100644 index 0000000..f560e01 --- /dev/null +++ b/python/netlink/route/capi_wrap.c @@ -0,0 +1,9514 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 1.3.40 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + +#define SWIGPYTHON +#define SWIG_PYTHON_NO_BUILD_NONE + +/* ----------------------------------------------------------------------------- + * This section contains generic SWIG labels for method/variable + * declarations/attributes, and other compiler dependent labels. + * ----------------------------------------------------------------------------- */ + +/* template workaround for compilers that cannot correctly implement the C++ standard */ +#ifndef SWIGTEMPLATEDISAMBIGUATOR +# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560) +# define SWIGTEMPLATEDISAMBIGUATOR template +# elif defined(__HP_aCC) +/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */ +/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */ +# define SWIGTEMPLATEDISAMBIGUATOR template +# else +# define SWIGTEMPLATEDISAMBIGUATOR +# endif +#endif + +/* inline attribute */ +#ifndef SWIGINLINE +# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__)) +# define SWIGINLINE inline +# else +# define SWIGINLINE +# endif +#endif + +/* attribute recognised by some compilers to avoid 'unused' warnings */ +#ifndef SWIGUNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +# elif defined(__ICC) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +#endif + +#ifndef SWIG_MSC_UNSUPPRESS_4505 +# if defined(_MSC_VER) +# pragma warning(disable : 4505) /* unreferenced local function has been removed */ +# endif +#endif + +#ifndef SWIGUNUSEDPARM +# ifdef __cplusplus +# define SWIGUNUSEDPARM(p) +# else +# define SWIGUNUSEDPARM(p) p SWIGUNUSED +# endif +#endif + +/* internal SWIG method */ +#ifndef SWIGINTERN +# define SWIGINTERN static SWIGUNUSED +#endif + +/* internal inline SWIG method */ +#ifndef SWIGINTERNINLINE +# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE +#endif + +/* exporting methods */ +#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +# ifndef GCC_HASCLASSVISIBILITY +# define GCC_HASCLASSVISIBILITY +# endif +#endif + +#ifndef SWIGEXPORT +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# if defined(STATIC_LINKED) +# define SWIGEXPORT +# else +# define SWIGEXPORT __declspec(dllexport) +# endif +# else +# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY) +# define SWIGEXPORT __attribute__ ((visibility("default"))) +# else +# define SWIGEXPORT +# endif +# endif +#endif + +/* calling conventions for Windows */ +#ifndef SWIGSTDCALL +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# define SWIGSTDCALL __stdcall +# else +# define SWIGSTDCALL +# endif +#endif + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */ +#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE) +# define _SCL_SECURE_NO_DEPRECATE +#endif + + + +/* Python.h has to appear first */ +#include + +/* ----------------------------------------------------------------------------- + * swigrun.swg + * + * This file contains generic C API SWIG runtime support for pointer + * type checking. + * ----------------------------------------------------------------------------- */ + +/* This should only be incremented when either the layout of swig_type_info changes, + or for whatever reason, the runtime changes incompatibly */ +#define SWIG_RUNTIME_VERSION "4" + +/* define SWIG_TYPE_TABLE_NAME as "SWIG_TYPE_TABLE" */ +#ifdef SWIG_TYPE_TABLE +# define SWIG_QUOTE_STRING(x) #x +# define SWIG_EXPAND_AND_QUOTE_STRING(x) SWIG_QUOTE_STRING(x) +# define SWIG_TYPE_TABLE_NAME SWIG_EXPAND_AND_QUOTE_STRING(SWIG_TYPE_TABLE) +#else +# define SWIG_TYPE_TABLE_NAME +#endif + +/* + You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for + creating a static or dynamic library from the SWIG runtime code. + In 99.9% of the cases, SWIG just needs to declare them as 'static'. + + But only do this if strictly necessary, ie, if you have problems + with your compiler or suchlike. +*/ + +#ifndef SWIGRUNTIME +# define SWIGRUNTIME SWIGINTERN +#endif + +#ifndef SWIGRUNTIMEINLINE +# define SWIGRUNTIMEINLINE SWIGRUNTIME SWIGINLINE +#endif + +/* Generic buffer size */ +#ifndef SWIG_BUFFER_SIZE +# define SWIG_BUFFER_SIZE 1024 +#endif + +/* Flags for pointer conversions */ +#define SWIG_POINTER_DISOWN 0x1 +#define SWIG_CAST_NEW_MEMORY 0x2 + +/* Flags for new pointer objects */ +#define SWIG_POINTER_OWN 0x1 + + +/* + Flags/methods for returning states. + + The SWIG conversion methods, as ConvertPtr, return and integer + that tells if the conversion was successful or not. And if not, + an error code can be returned (see swigerrors.swg for the codes). + + Use the following macros/flags to set or process the returning + states. + + In old versions of SWIG, code such as the following was usually written: + + if (SWIG_ConvertPtr(obj,vptr,ty.flags) != -1) { + // success code + } else { + //fail code + } + + Now you can be more explicit: + + int res = SWIG_ConvertPtr(obj,vptr,ty.flags); + if (SWIG_IsOK(res)) { + // success code + } else { + // fail code + } + + which is the same really, but now you can also do + + Type *ptr; + int res = SWIG_ConvertPtr(obj,(void **)(&ptr),ty.flags); + if (SWIG_IsOK(res)) { + // success code + if (SWIG_IsNewObj(res) { + ... + delete *ptr; + } else { + ... + } + } else { + // fail code + } + + I.e., now SWIG_ConvertPtr can return new objects and you can + identify the case and take care of the deallocation. Of course that + also requires SWIG_ConvertPtr to return new result values, such as + + int SWIG_ConvertPtr(obj, ptr,...) { + if () { + if () { + *ptr = ; + return SWIG_NEWOBJ; + } else { + *ptr = ; + return SWIG_OLDOBJ; + } + } else { + return SWIG_BADOBJ; + } + } + + Of course, returning the plain '0(success)/-1(fail)' still works, but you can be + more explicit by returning SWIG_BADOBJ, SWIG_ERROR or any of the + SWIG errors code. + + Finally, if the SWIG_CASTRANK_MODE is enabled, the result code + allows to return the 'cast rank', for example, if you have this + + int food(double) + int fooi(int); + + and you call + + food(1) // cast rank '1' (1 -> 1.0) + fooi(1) // cast rank '0' + + just use the SWIG_AddCast()/SWIG_CheckState() +*/ + +#define SWIG_OK (0) +#define SWIG_ERROR (-1) +#define SWIG_IsOK(r) (r >= 0) +#define SWIG_ArgError(r) ((r != SWIG_ERROR) ? r : SWIG_TypeError) + +/* The CastRankLimit says how many bits are used for the cast rank */ +#define SWIG_CASTRANKLIMIT (1 << 8) +/* The NewMask denotes the object was created (using new/malloc) */ +#define SWIG_NEWOBJMASK (SWIG_CASTRANKLIMIT << 1) +/* The TmpMask is for in/out typemaps that use temporal objects */ +#define SWIG_TMPOBJMASK (SWIG_NEWOBJMASK << 1) +/* Simple returning values */ +#define SWIG_BADOBJ (SWIG_ERROR) +#define SWIG_OLDOBJ (SWIG_OK) +#define SWIG_NEWOBJ (SWIG_OK | SWIG_NEWOBJMASK) +#define SWIG_TMPOBJ (SWIG_OK | SWIG_TMPOBJMASK) +/* Check, add and del mask methods */ +#define SWIG_AddNewMask(r) (SWIG_IsOK(r) ? (r | SWIG_NEWOBJMASK) : r) +#define SWIG_DelNewMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_NEWOBJMASK) : r) +#define SWIG_IsNewObj(r) (SWIG_IsOK(r) && (r & SWIG_NEWOBJMASK)) +#define SWIG_AddTmpMask(r) (SWIG_IsOK(r) ? (r | SWIG_TMPOBJMASK) : r) +#define SWIG_DelTmpMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_TMPOBJMASK) : r) +#define SWIG_IsTmpObj(r) (SWIG_IsOK(r) && (r & SWIG_TMPOBJMASK)) + +/* Cast-Rank Mode */ +#if defined(SWIG_CASTRANK_MODE) +# ifndef SWIG_TypeRank +# define SWIG_TypeRank unsigned long +# endif +# ifndef SWIG_MAXCASTRANK /* Default cast allowed */ +# define SWIG_MAXCASTRANK (2) +# endif +# define SWIG_CASTRANKMASK ((SWIG_CASTRANKLIMIT) -1) +# define SWIG_CastRank(r) (r & SWIG_CASTRANKMASK) +SWIGINTERNINLINE int SWIG_AddCast(int r) { + return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r; +} +SWIGINTERNINLINE int SWIG_CheckState(int r) { + return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0; +} +#else /* no cast-rank mode */ +# define SWIG_AddCast +# define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0) +#endif + + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void *(*swig_converter_func)(void *, int *); +typedef struct swig_type_info *(*swig_dycast_func)(void **); + +/* Structure to store information on one type */ +typedef struct swig_type_info { + const char *name; /* mangled name of this type */ + const char *str; /* human readable name of this type */ + swig_dycast_func dcast; /* dynamic cast function down a hierarchy */ + struct swig_cast_info *cast; /* linked list of types that can cast into this type */ + void *clientdata; /* language specific type data */ + int owndata; /* flag if the structure owns the clientdata */ +} swig_type_info; + +/* Structure to store a type and conversion function used for casting */ +typedef struct swig_cast_info { + swig_type_info *type; /* pointer to type that is equivalent to this type */ + swig_converter_func converter; /* function to cast the void pointers */ + struct swig_cast_info *next; /* pointer to next cast in linked list */ + struct swig_cast_info *prev; /* pointer to the previous cast */ +} swig_cast_info; + +/* Structure used to store module information + * Each module generates one structure like this, and the runtime collects + * all of these structures and stores them in a circularly linked list.*/ +typedef struct swig_module_info { + swig_type_info **types; /* Array of pointers to swig_type_info structures that are in this module */ + size_t size; /* Number of types in this module */ + struct swig_module_info *next; /* Pointer to next element in circularly linked list */ + swig_type_info **type_initial; /* Array of initially generated type structures */ + swig_cast_info **cast_initial; /* Array of initially generated casting structures */ + void *clientdata; /* Language specific module data */ +} swig_module_info; + +/* + Compare two type names skipping the space characters, therefore + "char*" == "char *" and "Class" == "Class", etc. + + Return 0 when the two name types are equivalent, as in + strncmp, but skipping ' '. +*/ +SWIGRUNTIME int +SWIG_TypeNameComp(const char *f1, const char *l1, + const char *f2, const char *l2) { + for (;(f1 != l1) && (f2 != l2); ++f1, ++f2) { + while ((*f1 == ' ') && (f1 != l1)) ++f1; + while ((*f2 == ' ') && (f2 != l2)) ++f2; + if (*f1 != *f2) return (*f1 > *f2) ? 1 : -1; + } + return (int)((l1 - f1) - (l2 - f2)); +} + +/* + Check type equivalence in a name list like ||... + Return 0 if not equal, 1 if equal +*/ +SWIGRUNTIME int +SWIG_TypeEquiv(const char *nb, const char *tb) { + int equiv = 0; + const char* te = tb + strlen(tb); + const char* ne = nb; + while (!equiv && *ne) { + for (nb = ne; *ne; ++ne) { + if (*ne == '|') break; + } + equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0; + if (*ne) ++ne; + } + return equiv; +} + +/* + Check type equivalence in a name list like ||... + Return 0 if equal, -1 if nb < tb, 1 if nb > tb +*/ +SWIGRUNTIME int +SWIG_TypeCompare(const char *nb, const char *tb) { + int equiv = 0; + const char* te = tb + strlen(tb); + const char* ne = nb; + while (!equiv && *ne) { + for (nb = ne; *ne; ++ne) { + if (*ne == '|') break; + } + equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0; + if (*ne) ++ne; + } + return equiv; +} + + +/* + Check the typename +*/ +SWIGRUNTIME swig_cast_info * +SWIG_TypeCheck(const char *c, swig_type_info *ty) { + if (ty) { + swig_cast_info *iter = ty->cast; + while (iter) { + if (strcmp(iter->type->name, c) == 0) { + if (iter == ty->cast) + return iter; + /* Move iter to the top of the linked list */ + iter->prev->next = iter->next; + if (iter->next) + iter->next->prev = iter->prev; + iter->next = ty->cast; + iter->prev = 0; + if (ty->cast) ty->cast->prev = iter; + ty->cast = iter; + return iter; + } + iter = iter->next; + } + } + return 0; +} + +/* + Identical to SWIG_TypeCheck, except strcmp is replaced with a pointer comparison +*/ +SWIGRUNTIME swig_cast_info * +SWIG_TypeCheckStruct(swig_type_info *from, swig_type_info *ty) { + if (ty) { + swig_cast_info *iter = ty->cast; + while (iter) { + if (iter->type == from) { + if (iter == ty->cast) + return iter; + /* Move iter to the top of the linked list */ + iter->prev->next = iter->next; + if (iter->next) + iter->next->prev = iter->prev; + iter->next = ty->cast; + iter->prev = 0; + if (ty->cast) ty->cast->prev = iter; + ty->cast = iter; + return iter; + } + iter = iter->next; + } + } + return 0; +} + +/* + Cast a pointer up an inheritance hierarchy +*/ +SWIGRUNTIMEINLINE void * +SWIG_TypeCast(swig_cast_info *ty, void *ptr, int *newmemory) { + return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr, newmemory); +} + +/* + Dynamic pointer casting. Down an inheritance hierarchy +*/ +SWIGRUNTIME swig_type_info * +SWIG_TypeDynamicCast(swig_type_info *ty, void **ptr) { + swig_type_info *lastty = ty; + if (!ty || !ty->dcast) return ty; + while (ty && (ty->dcast)) { + ty = (*ty->dcast)(ptr); + if (ty) lastty = ty; + } + return lastty; +} + +/* + Return the name associated with this type +*/ +SWIGRUNTIMEINLINE const char * +SWIG_TypeName(const swig_type_info *ty) { + return ty->name; +} + +/* + Return the pretty name associated with this type, + that is an unmangled type name in a form presentable to the user. +*/ +SWIGRUNTIME const char * +SWIG_TypePrettyName(const swig_type_info *type) { + /* The "str" field contains the equivalent pretty names of the + type, separated by vertical-bar characters. We choose + to print the last name, as it is often (?) the most + specific. */ + if (!type) return NULL; + if (type->str != NULL) { + const char *last_name = type->str; + const char *s; + for (s = type->str; *s; s++) + if (*s == '|') last_name = s+1; + return last_name; + } + else + return type->name; +} + +/* + Set the clientdata field for a type +*/ +SWIGRUNTIME void +SWIG_TypeClientData(swig_type_info *ti, void *clientdata) { + swig_cast_info *cast = ti->cast; + /* if (ti->clientdata == clientdata) return; */ + ti->clientdata = clientdata; + + while (cast) { + if (!cast->converter) { + swig_type_info *tc = cast->type; + if (!tc->clientdata) { + SWIG_TypeClientData(tc, clientdata); + } + } + cast = cast->next; + } +} +SWIGRUNTIME void +SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) { + SWIG_TypeClientData(ti, clientdata); + ti->owndata = 1; +} + +/* + Search for a swig_type_info structure only by mangled name + Search is a O(log #types) + + We start searching at module start, and finish searching when start == end. + Note: if start == end at the beginning of the function, we go all the way around + the circular list. +*/ +SWIGRUNTIME swig_type_info * +SWIG_MangledTypeQueryModule(swig_module_info *start, + swig_module_info *end, + const char *name) { + swig_module_info *iter = start; + do { + if (iter->size) { + register size_t l = 0; + register size_t r = iter->size - 1; + do { + /* since l+r >= 0, we can (>> 1) instead (/ 2) */ + register size_t i = (l + r) >> 1; + const char *iname = iter->types[i]->name; + if (iname) { + register int compare = strcmp(name, iname); + if (compare == 0) { + return iter->types[i]; + } else if (compare < 0) { + if (i) { + r = i - 1; + } else { + break; + } + } else if (compare > 0) { + l = i + 1; + } + } else { + break; /* should never happen */ + } + } while (l <= r); + } + iter = iter->next; + } while (iter != end); + return 0; +} + +/* + Search for a swig_type_info structure for either a mangled name or a human readable name. + It first searches the mangled names of the types, which is a O(log #types) + If a type is not found it then searches the human readable names, which is O(#types). + + We start searching at module start, and finish searching when start == end. + Note: if start == end at the beginning of the function, we go all the way around + the circular list. +*/ +SWIGRUNTIME swig_type_info * +SWIG_TypeQueryModule(swig_module_info *start, + swig_module_info *end, + const char *name) { + /* STEP 1: Search the name field using binary search */ + swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name); + if (ret) { + return ret; + } else { + /* STEP 2: If the type hasn't been found, do a complete search + of the str field (the human readable name) */ + swig_module_info *iter = start; + do { + register size_t i = 0; + for (; i < iter->size; ++i) { + if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name))) + return iter->types[i]; + } + iter = iter->next; + } while (iter != end); + } + + /* neither found a match */ + return 0; +} + +/* + Pack binary data into a string +*/ +SWIGRUNTIME char * +SWIG_PackData(char *c, void *ptr, size_t sz) { + static const char hex[17] = "0123456789abcdef"; + register const unsigned char *u = (unsigned char *) ptr; + register const unsigned char *eu = u + sz; + for (; u != eu; ++u) { + register unsigned char uu = *u; + *(c++) = hex[(uu & 0xf0) >> 4]; + *(c++) = hex[uu & 0xf]; + } + return c; +} + +/* + Unpack binary data from a string +*/ +SWIGRUNTIME const char * +SWIG_UnpackData(const char *c, void *ptr, size_t sz) { + register unsigned char *u = (unsigned char *) ptr; + register const unsigned char *eu = u + sz; + for (; u != eu; ++u) { + register char d = *(c++); + register unsigned char uu; + if ((d >= '0') && (d <= '9')) + uu = ((d - '0') << 4); + else if ((d >= 'a') && (d <= 'f')) + uu = ((d - ('a'-10)) << 4); + else + return (char *) 0; + d = *(c++); + if ((d >= '0') && (d <= '9')) + uu |= (d - '0'); + else if ((d >= 'a') && (d <= 'f')) + uu |= (d - ('a'-10)); + else + return (char *) 0; + *u = uu; + } + return c; +} + +/* + Pack 'void *' into a string buffer. +*/ +SWIGRUNTIME char * +SWIG_PackVoidPtr(char *buff, void *ptr, const char *name, size_t bsz) { + char *r = buff; + if ((2*sizeof(void *) + 2) > bsz) return 0; + *(r++) = '_'; + r = SWIG_PackData(r,&ptr,sizeof(void *)); + if (strlen(name) + 1 > (bsz - (r - buff))) return 0; + strcpy(r,name); + return buff; +} + +SWIGRUNTIME const char * +SWIG_UnpackVoidPtr(const char *c, void **ptr, const char *name) { + if (*c != '_') { + if (strcmp(c,"NULL") == 0) { + *ptr = (void *) 0; + return name; + } else { + return 0; + } + } + return SWIG_UnpackData(++c,ptr,sizeof(void *)); +} + +SWIGRUNTIME char * +SWIG_PackDataName(char *buff, void *ptr, size_t sz, const char *name, size_t bsz) { + char *r = buff; + size_t lname = (name ? strlen(name) : 0); + if ((2*sz + 2 + lname) > bsz) return 0; + *(r++) = '_'; + r = SWIG_PackData(r,ptr,sz); + if (lname) { + strncpy(r,name,lname+1); + } else { + *r = 0; + } + return buff; +} + +SWIGRUNTIME const char * +SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) { + if (*c != '_') { + if (strcmp(c,"NULL") == 0) { + memset(ptr,0,sz); + return name; + } else { + return 0; + } + } + return SWIG_UnpackData(++c,ptr,sz); +} + +#ifdef __cplusplus +} +#endif + +/* Errors in SWIG */ +#define SWIG_UnknownError -1 +#define SWIG_IOError -2 +#define SWIG_RuntimeError -3 +#define SWIG_IndexError -4 +#define SWIG_TypeError -5 +#define SWIG_DivisionByZero -6 +#define SWIG_OverflowError -7 +#define SWIG_SyntaxError -8 +#define SWIG_ValueError -9 +#define SWIG_SystemError -10 +#define SWIG_AttributeError -11 +#define SWIG_MemoryError -12 +#define SWIG_NullReferenceError -13 + + + +/* Compatibility macros for Python 3 */ +#if PY_VERSION_HEX >= 0x03000000 + +#define PyClass_Check(obj) PyObject_IsInstance(obj, (PyObject *)&PyType_Type) +#define PyInt_Check(x) PyLong_Check(x) +#define PyInt_AsLong(x) PyLong_AsLong(x) +#define PyInt_FromLong(x) PyLong_FromLong(x) +#define PyString_Format(fmt, args) PyUnicode_Format(fmt, args) + +#endif + +#ifndef Py_TYPE +# define Py_TYPE(op) ((op)->ob_type) +#endif + +/* SWIG APIs for compatibility of both Python 2 & 3 */ + +#if PY_VERSION_HEX >= 0x03000000 +# define SWIG_Python_str_FromFormat PyUnicode_FromFormat +#else +# define SWIG_Python_str_FromFormat PyString_FromFormat +#endif + + +/* Warning: This function will allocate a new string in Python 3, + * so please call SWIG_Python_str_DelForPy3(x) to free the space. + */ +SWIGINTERN char* +SWIG_Python_str_AsChar(PyObject *str) +{ +#if PY_VERSION_HEX >= 0x03000000 + char *cstr; + char *newstr; + Py_ssize_t len; + str = PyUnicode_AsUTF8String(str); + PyBytes_AsStringAndSize(str, &cstr, &len); + newstr = (char *) malloc(len+1); + memcpy(newstr, cstr, len+1); + Py_XDECREF(str); + return newstr; +#else + return PyString_AsString(str); +#endif +} + +#if PY_VERSION_HEX >= 0x03000000 +# define SWIG_Python_str_DelForPy3(x) free( (void*) (x) ) +#else +# define SWIG_Python_str_DelForPy3(x) +#endif + + +SWIGINTERN PyObject* +SWIG_Python_str_FromChar(const char *c) +{ +#if PY_VERSION_HEX >= 0x03000000 + return PyUnicode_FromString(c); +#else + return PyString_FromString(c); +#endif +} + +/* Add PyOS_snprintf for old Pythons */ +#if PY_VERSION_HEX < 0x02020000 +# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WATCOM) +# define PyOS_snprintf _snprintf +# else +# define PyOS_snprintf snprintf +# endif +#endif + +/* A crude PyString_FromFormat implementation for old Pythons */ +#if PY_VERSION_HEX < 0x02020000 + +#ifndef SWIG_PYBUFFER_SIZE +# define SWIG_PYBUFFER_SIZE 1024 +#endif + +static PyObject * +PyString_FromFormat(const char *fmt, ...) { + va_list ap; + char buf[SWIG_PYBUFFER_SIZE * 2]; + int res; + va_start(ap, fmt); + res = vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + return (res < 0 || res >= (int)sizeof(buf)) ? 0 : PyString_FromString(buf); +} +#endif + +/* Add PyObject_Del for old Pythons */ +#if PY_VERSION_HEX < 0x01060000 +# define PyObject_Del(op) PyMem_DEL((op)) +#endif +#ifndef PyObject_DEL +# define PyObject_DEL PyObject_Del +#endif + +/* A crude PyExc_StopIteration exception for old Pythons */ +#if PY_VERSION_HEX < 0x02020000 +# ifndef PyExc_StopIteration +# define PyExc_StopIteration PyExc_RuntimeError +# endif +# ifndef PyObject_GenericGetAttr +# define PyObject_GenericGetAttr 0 +# endif +#endif + +/* Py_NotImplemented is defined in 2.1 and up. */ +#if PY_VERSION_HEX < 0x02010000 +# ifndef Py_NotImplemented +# define Py_NotImplemented PyExc_RuntimeError +# endif +#endif + +/* A crude PyString_AsStringAndSize implementation for old Pythons */ +#if PY_VERSION_HEX < 0x02010000 +# ifndef PyString_AsStringAndSize +# define PyString_AsStringAndSize(obj, s, len) {*s = PyString_AsString(obj); *len = *s ? strlen(*s) : 0;} +# endif +#endif + +/* PySequence_Size for old Pythons */ +#if PY_VERSION_HEX < 0x02000000 +# ifndef PySequence_Size +# define PySequence_Size PySequence_Length +# endif +#endif + +/* PyBool_FromLong for old Pythons */ +#if PY_VERSION_HEX < 0x02030000 +static +PyObject *PyBool_FromLong(long ok) +{ + PyObject *result = ok ? Py_True : Py_False; + Py_INCREF(result); + return result; +} +#endif + +/* Py_ssize_t for old Pythons */ +/* This code is as recommended by: */ +/* http://www.python.org/dev/peps/pep-0353/#conversion-guidelines */ +#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) +typedef int Py_ssize_t; +# define PY_SSIZE_T_MAX INT_MAX +# define PY_SSIZE_T_MIN INT_MIN +#endif + +/* ----------------------------------------------------------------------------- + * error manipulation + * ----------------------------------------------------------------------------- */ + +SWIGRUNTIME PyObject* +SWIG_Python_ErrorType(int code) { + PyObject* type = 0; + switch(code) { + case SWIG_MemoryError: + type = PyExc_MemoryError; + break; + case SWIG_IOError: + type = PyExc_IOError; + break; + case SWIG_RuntimeError: + type = PyExc_RuntimeError; + break; + case SWIG_IndexError: + type = PyExc_IndexError; + break; + case SWIG_TypeError: + type = PyExc_TypeError; + break; + case SWIG_DivisionByZero: + type = PyExc_ZeroDivisionError; + break; + case SWIG_OverflowError: + type = PyExc_OverflowError; + break; + case SWIG_SyntaxError: + type = PyExc_SyntaxError; + break; + case SWIG_ValueError: + type = PyExc_ValueError; + break; + case SWIG_SystemError: + type = PyExc_SystemError; + break; + case SWIG_AttributeError: + type = PyExc_AttributeError; + break; + default: + type = PyExc_RuntimeError; + } + return type; +} + + +SWIGRUNTIME void +SWIG_Python_AddErrorMsg(const char* mesg) +{ + PyObject *type = 0; + PyObject *value = 0; + PyObject *traceback = 0; + + if (PyErr_Occurred()) PyErr_Fetch(&type, &value, &traceback); + if (value) { + char *tmp; + PyObject *old_str = PyObject_Str(value); + PyErr_Clear(); + Py_XINCREF(type); + + PyErr_Format(type, "%s %s", tmp = SWIG_Python_str_AsChar(old_str), mesg); + SWIG_Python_str_DelForPy3(tmp); + Py_DECREF(old_str); + Py_DECREF(value); + } else { + PyErr_SetString(PyExc_RuntimeError, mesg); + } +} + +#if defined(SWIG_PYTHON_NO_THREADS) +# if defined(SWIG_PYTHON_THREADS) +# undef SWIG_PYTHON_THREADS +# endif +#endif +#if defined(SWIG_PYTHON_THREADS) /* Threading support is enabled */ +# if !defined(SWIG_PYTHON_USE_GIL) && !defined(SWIG_PYTHON_NO_USE_GIL) +# if (PY_VERSION_HEX >= 0x02030000) /* For 2.3 or later, use the PyGILState calls */ +# define SWIG_PYTHON_USE_GIL +# endif +# endif +# if defined(SWIG_PYTHON_USE_GIL) /* Use PyGILState threads calls */ +# ifndef SWIG_PYTHON_INITIALIZE_THREADS +# define SWIG_PYTHON_INITIALIZE_THREADS PyEval_InitThreads() +# endif +# ifdef __cplusplus /* C++ code */ + class SWIG_Python_Thread_Block { + bool status; + PyGILState_STATE state; + public: + void end() { if (status) { PyGILState_Release(state); status = false;} } + SWIG_Python_Thread_Block() : status(true), state(PyGILState_Ensure()) {} + ~SWIG_Python_Thread_Block() { end(); } + }; + class SWIG_Python_Thread_Allow { + bool status; + PyThreadState *save; + public: + void end() { if (status) { PyEval_RestoreThread(save); status = false; }} + SWIG_Python_Thread_Allow() : status(true), save(PyEval_SaveThread()) {} + ~SWIG_Python_Thread_Allow() { end(); } + }; +# define SWIG_PYTHON_THREAD_BEGIN_BLOCK SWIG_Python_Thread_Block _swig_thread_block +# define SWIG_PYTHON_THREAD_END_BLOCK _swig_thread_block.end() +# define SWIG_PYTHON_THREAD_BEGIN_ALLOW SWIG_Python_Thread_Allow _swig_thread_allow +# define SWIG_PYTHON_THREAD_END_ALLOW _swig_thread_allow.end() +# else /* C code */ +# define SWIG_PYTHON_THREAD_BEGIN_BLOCK PyGILState_STATE _swig_thread_block = PyGILState_Ensure() +# define SWIG_PYTHON_THREAD_END_BLOCK PyGILState_Release(_swig_thread_block) +# define SWIG_PYTHON_THREAD_BEGIN_ALLOW PyThreadState *_swig_thread_allow = PyEval_SaveThread() +# define SWIG_PYTHON_THREAD_END_ALLOW PyEval_RestoreThread(_swig_thread_allow) +# endif +# else /* Old thread way, not implemented, user must provide it */ +# if !defined(SWIG_PYTHON_INITIALIZE_THREADS) +# define SWIG_PYTHON_INITIALIZE_THREADS +# endif +# if !defined(SWIG_PYTHON_THREAD_BEGIN_BLOCK) +# define SWIG_PYTHON_THREAD_BEGIN_BLOCK +# endif +# if !defined(SWIG_PYTHON_THREAD_END_BLOCK) +# define SWIG_PYTHON_THREAD_END_BLOCK +# endif +# if !defined(SWIG_PYTHON_THREAD_BEGIN_ALLOW) +# define SWIG_PYTHON_THREAD_BEGIN_ALLOW +# endif +# if !defined(SWIG_PYTHON_THREAD_END_ALLOW) +# define SWIG_PYTHON_THREAD_END_ALLOW +# endif +# endif +#else /* No thread support */ +# define SWIG_PYTHON_INITIALIZE_THREADS +# define SWIG_PYTHON_THREAD_BEGIN_BLOCK +# define SWIG_PYTHON_THREAD_END_BLOCK +# define SWIG_PYTHON_THREAD_BEGIN_ALLOW +# define SWIG_PYTHON_THREAD_END_ALLOW +#endif + +/* ----------------------------------------------------------------------------- + * Python API portion that goes into the runtime + * ----------------------------------------------------------------------------- */ + +#ifdef __cplusplus +extern "C" { +#if 0 +} /* cc-mode */ +#endif +#endif + +/* ----------------------------------------------------------------------------- + * Constant declarations + * ----------------------------------------------------------------------------- */ + +/* Constant Types */ +#define SWIG_PY_POINTER 4 +#define SWIG_PY_BINARY 5 + +/* Constant information structure */ +typedef struct swig_const_info { + int type; + char *name; + long lvalue; + double dvalue; + void *pvalue; + swig_type_info **ptype; +} swig_const_info; + + +/* ----------------------------------------------------------------------------- + * Wrapper of PyInstanceMethod_New() used in Python 3 + * It is exported to the generated module, used for -fastproxy + * ----------------------------------------------------------------------------- */ +SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func) +{ +#if PY_VERSION_HEX >= 0x03000000 + return PyInstanceMethod_New(func); +#else + return NULL; +#endif +} + +#ifdef __cplusplus +#if 0 +{ /* cc-mode */ +#endif +} +#endif + + +/* ----------------------------------------------------------------------------- + * See the LICENSE file for information on copyright, usage and redistribution + * of SWIG, and the README file for authors - http://www.swig.org/release.html. + * + * pyrun.swg + * + * This file contains the runtime support for Python modules + * and includes code for managing global variables and pointer + * type checking. + * + * ----------------------------------------------------------------------------- */ + +/* Common SWIG API */ + +/* for raw pointers */ +#define SWIG_Python_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, 0) +#define SWIG_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtr(obj, pptr, type, flags) +#define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, own) +#define SWIG_NewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(ptr, type, flags) +#define SWIG_CheckImplicit(ty) SWIG_Python_CheckImplicit(ty) +#define SWIG_AcquirePtr(ptr, src) SWIG_Python_AcquirePtr(ptr, src) +#define swig_owntype int + +/* for raw packed data */ +#define SWIG_ConvertPacked(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty) +#define SWIG_NewPackedObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type) + +/* for class or struct pointers */ +#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_ConvertPtr(obj, pptr, type, flags) +#define SWIG_NewInstanceObj(ptr, type, flags) SWIG_NewPointerObj(ptr, type, flags) + +/* for C or C++ function pointers */ +#define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_Python_ConvertFunctionPtr(obj, pptr, type) +#define SWIG_NewFunctionPtrObj(ptr, type) SWIG_Python_NewPointerObj(ptr, type, 0) + +/* for C++ member pointers, ie, member methods */ +#define SWIG_ConvertMember(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty) +#define SWIG_NewMemberObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type) + + +/* Runtime API */ + +#define SWIG_GetModule(clientdata) SWIG_Python_GetModule() +#define SWIG_SetModule(clientdata, pointer) SWIG_Python_SetModule(pointer) +#define SWIG_NewClientData(obj) SwigPyClientData_New(obj) + +#define SWIG_SetErrorObj SWIG_Python_SetErrorObj +#define SWIG_SetErrorMsg SWIG_Python_SetErrorMsg +#define SWIG_ErrorType(code) SWIG_Python_ErrorType(code) +#define SWIG_Error(code, msg) SWIG_Python_SetErrorMsg(SWIG_ErrorType(code), msg) +#define SWIG_fail goto fail + + +/* Runtime API implementation */ + +/* Error manipulation */ + +SWIGINTERN void +SWIG_Python_SetErrorObj(PyObject *errtype, PyObject *obj) { + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + PyErr_SetObject(errtype, obj); + Py_DECREF(obj); + SWIG_PYTHON_THREAD_END_BLOCK; +} + +SWIGINTERN void +SWIG_Python_SetErrorMsg(PyObject *errtype, const char *msg) { + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + PyErr_SetString(errtype, (char *) msg); + SWIG_PYTHON_THREAD_END_BLOCK; +} + +#define SWIG_Python_Raise(obj, type, desc) SWIG_Python_SetErrorObj(SWIG_Python_ExceptionType(desc), obj) + +/* Set a constant value */ + +SWIGINTERN void +SWIG_Python_SetConstant(PyObject *d, const char *name, PyObject *obj) { + PyDict_SetItemString(d, (char*) name, obj); + Py_DECREF(obj); +} + +/* Append a value to the result obj */ + +SWIGINTERN PyObject* +SWIG_Python_AppendOutput(PyObject* result, PyObject* obj) { +#if !defined(SWIG_PYTHON_OUTPUT_TUPLE) + if (!result) { + result = obj; + } else if (result == Py_None) { + Py_DECREF(result); + result = obj; + } else { + if (!PyList_Check(result)) { + PyObject *o2 = result; + result = PyList_New(1); + PyList_SetItem(result, 0, o2); + } + PyList_Append(result,obj); + Py_DECREF(obj); + } + return result; +#else + PyObject* o2; + PyObject* o3; + if (!result) { + result = obj; + } else if (result == Py_None) { + Py_DECREF(result); + result = obj; + } else { + if (!PyTuple_Check(result)) { + o2 = result; + result = PyTuple_New(1); + PyTuple_SET_ITEM(result, 0, o2); + } + o3 = PyTuple_New(1); + PyTuple_SET_ITEM(o3, 0, obj); + o2 = result; + result = PySequence_Concat(o2, o3); + Py_DECREF(o2); + Py_DECREF(o3); + } + return result; +#endif +} + +/* Unpack the argument tuple */ + +SWIGINTERN int +SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, PyObject **objs) +{ + if (!args) { + if (!min && !max) { + return 1; + } else { + PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got none", + name, (min == max ? "" : "at least "), (int)min); + return 0; + } + } + if (!PyTuple_Check(args)) { + PyErr_SetString(PyExc_SystemError, "UnpackTuple() argument list is not a tuple"); + return 0; + } else { + register Py_ssize_t l = PyTuple_GET_SIZE(args); + if (l < min) { + PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", + name, (min == max ? "" : "at least "), (int)min, (int)l); + return 0; + } else if (l > max) { + PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", + name, (min == max ? "" : "at most "), (int)max, (int)l); + return 0; + } else { + register int i; + for (i = 0; i < l; ++i) { + objs[i] = PyTuple_GET_ITEM(args, i); + } + for (; l < max; ++l) { + objs[l] = 0; + } + return i + 1; + } + } +} + +/* A functor is a function object with one single object argument */ +#if PY_VERSION_HEX >= 0x02020000 +#define SWIG_Python_CallFunctor(functor, obj) PyObject_CallFunctionObjArgs(functor, obj, NULL); +#else +#define SWIG_Python_CallFunctor(functor, obj) PyObject_CallFunction(functor, "O", obj); +#endif + +/* + Helper for static pointer initialization for both C and C++ code, for example + static PyObject *SWIG_STATIC_POINTER(MyVar) = NewSomething(...); +*/ +#ifdef __cplusplus +#define SWIG_STATIC_POINTER(var) var +#else +#define SWIG_STATIC_POINTER(var) var = 0; if (!var) var +#endif + +/* ----------------------------------------------------------------------------- + * Pointer declarations + * ----------------------------------------------------------------------------- */ + +/* Flags for new pointer objects */ +#define SWIG_POINTER_NOSHADOW (SWIG_POINTER_OWN << 1) +#define SWIG_POINTER_NEW (SWIG_POINTER_NOSHADOW | SWIG_POINTER_OWN) + +#define SWIG_POINTER_IMPLICIT_CONV (SWIG_POINTER_DISOWN << 1) + +#ifdef __cplusplus +extern "C" { +#if 0 +} /* cc-mode */ +#endif +#endif + +/* How to access Py_None */ +#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# ifndef SWIG_PYTHON_NO_BUILD_NONE +# ifndef SWIG_PYTHON_BUILD_NONE +# define SWIG_PYTHON_BUILD_NONE +# endif +# endif +#endif + +#ifdef SWIG_PYTHON_BUILD_NONE +# ifdef Py_None +# undef Py_None +# define Py_None SWIG_Py_None() +# endif +SWIGRUNTIMEINLINE PyObject * +_SWIG_Py_None(void) +{ + PyObject *none = Py_BuildValue((char*)""); + Py_DECREF(none); + return none; +} +SWIGRUNTIME PyObject * +SWIG_Py_None(void) +{ + static PyObject *SWIG_STATIC_POINTER(none) = _SWIG_Py_None(); + return none; +} +#endif + +/* The python void return value */ + +SWIGRUNTIMEINLINE PyObject * +SWIG_Py_Void(void) +{ + PyObject *none = Py_None; + Py_INCREF(none); + return none; +} + +/* SwigPyClientData */ + +typedef struct { + PyObject *klass; + PyObject *newraw; + PyObject *newargs; + PyObject *destroy; + int delargs; + int implicitconv; +} SwigPyClientData; + +SWIGRUNTIMEINLINE int +SWIG_Python_CheckImplicit(swig_type_info *ty) +{ + SwigPyClientData *data = (SwigPyClientData *)ty->clientdata; + return data ? data->implicitconv : 0; +} + +SWIGRUNTIMEINLINE PyObject * +SWIG_Python_ExceptionType(swig_type_info *desc) { + SwigPyClientData *data = desc ? (SwigPyClientData *) desc->clientdata : 0; + PyObject *klass = data ? data->klass : 0; + return (klass ? klass : PyExc_RuntimeError); +} + + +SWIGRUNTIME SwigPyClientData * +SwigPyClientData_New(PyObject* obj) +{ + if (!obj) { + return 0; + } else { + SwigPyClientData *data = (SwigPyClientData *)malloc(sizeof(SwigPyClientData)); + /* the klass element */ + data->klass = obj; + Py_INCREF(data->klass); + /* the newraw method and newargs arguments used to create a new raw instance */ + if (PyClass_Check(obj)) { + data->newraw = 0; + data->newargs = obj; + Py_INCREF(obj); + } else { +#if (PY_VERSION_HEX < 0x02020000) + data->newraw = 0; +#else + data->newraw = PyObject_GetAttrString(data->klass, (char *)"__new__"); +#endif + if (data->newraw) { + Py_INCREF(data->newraw); + data->newargs = PyTuple_New(1); + PyTuple_SetItem(data->newargs, 0, obj); + } else { + data->newargs = obj; + } + Py_INCREF(data->newargs); + } + /* the destroy method, aka as the C++ delete method */ + data->destroy = PyObject_GetAttrString(data->klass, (char *)"__swig_destroy__"); + if (PyErr_Occurred()) { + PyErr_Clear(); + data->destroy = 0; + } + if (data->destroy) { + int flags; + Py_INCREF(data->destroy); + flags = PyCFunction_GET_FLAGS(data->destroy); +#ifdef METH_O + data->delargs = !(flags & (METH_O)); +#else + data->delargs = 0; +#endif + } else { + data->delargs = 0; + } + data->implicitconv = 0; + return data; + } +} + +SWIGRUNTIME void +SwigPyClientData_Del(SwigPyClientData* data) +{ + Py_XDECREF(data->newraw); + Py_XDECREF(data->newargs); + Py_XDECREF(data->destroy); +} + +/* =============== SwigPyObject =====================*/ + +typedef struct { + PyObject_HEAD + void *ptr; + swig_type_info *ty; + int own; + PyObject *next; +} SwigPyObject; + +SWIGRUNTIME PyObject * +SwigPyObject_long(SwigPyObject *v) +{ + return PyLong_FromVoidPtr(v->ptr); +} + +SWIGRUNTIME PyObject * +SwigPyObject_format(const char* fmt, SwigPyObject *v) +{ + PyObject *res = NULL; + PyObject *args = PyTuple_New(1); + if (args) { + if (PyTuple_SetItem(args, 0, SwigPyObject_long(v)) == 0) { + PyObject *ofmt = SWIG_Python_str_FromChar(fmt); + if (ofmt) { +#if PY_VERSION_HEX >= 0x03000000 + res = PyUnicode_Format(ofmt,args); +#else + res = PyString_Format(ofmt,args); +#endif + Py_DECREF(ofmt); + } + Py_DECREF(args); + } + } + return res; +} + +SWIGRUNTIME PyObject * +SwigPyObject_oct(SwigPyObject *v) +{ + return SwigPyObject_format("%o",v); +} + +SWIGRUNTIME PyObject * +SwigPyObject_hex(SwigPyObject *v) +{ + return SwigPyObject_format("%x",v); +} + +SWIGRUNTIME PyObject * +#ifdef METH_NOARGS +SwigPyObject_repr(SwigPyObject *v) +#else +SwigPyObject_repr(SwigPyObject *v, PyObject *args) +#endif +{ + const char *name = SWIG_TypePrettyName(v->ty); + PyObject *repr = SWIG_Python_str_FromFormat("", name, v); + if (v->next) { +#ifdef METH_NOARGS + PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next); +#else + PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next, args); +#endif +#if PY_VERSION_HEX >= 0x03000000 + PyObject *joined = PyUnicode_Concat(repr, nrep); + Py_DecRef(repr); + Py_DecRef(nrep); + repr = joined; +#else + PyString_ConcatAndDel(&repr,nrep); +#endif + } + return repr; +} + +SWIGRUNTIME int +SwigPyObject_print(SwigPyObject *v, FILE *fp, int SWIGUNUSEDPARM(flags)) +{ + char *str; +#ifdef METH_NOARGS + PyObject *repr = SwigPyObject_repr(v); +#else + PyObject *repr = SwigPyObject_repr(v, NULL); +#endif + if (repr) { + str = SWIG_Python_str_AsChar(repr); + fputs(str, fp); + SWIG_Python_str_DelForPy3(str); + Py_DECREF(repr); + return 0; + } else { + return 1; + } +} + +SWIGRUNTIME PyObject * +SwigPyObject_str(SwigPyObject *v) +{ + char result[SWIG_BUFFER_SIZE]; + return SWIG_PackVoidPtr(result, v->ptr, v->ty->name, sizeof(result)) ? + SWIG_Python_str_FromChar(result) : 0; +} + +SWIGRUNTIME int +SwigPyObject_compare(SwigPyObject *v, SwigPyObject *w) +{ + void *i = v->ptr; + void *j = w->ptr; + return (i < j) ? -1 : ((i > j) ? 1 : 0); +} + +/* Added for Python 3.x, would it also be useful for Python 2.x? */ +SWIGRUNTIME PyObject* +SwigPyObject_richcompare(SwigPyObject *v, SwigPyObject *w, int op) +{ + PyObject* res; + if( op != Py_EQ && op != Py_NE ) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + if( (SwigPyObject_compare(v, w)==0) == (op == Py_EQ) ) + res = Py_True; + else + res = Py_False; + Py_INCREF(res); + return res; +} + + +SWIGRUNTIME PyTypeObject* _PySwigObject_type(void); + +SWIGRUNTIME PyTypeObject* +SwigPyObject_type(void) { + static PyTypeObject *SWIG_STATIC_POINTER(type) = _PySwigObject_type(); + return type; +} + +SWIGRUNTIMEINLINE int +SwigPyObject_Check(PyObject *op) { + return (Py_TYPE(op) == SwigPyObject_type()) + || (strcmp(Py_TYPE(op)->tp_name,"SwigPyObject") == 0); +} + +SWIGRUNTIME PyObject * +SwigPyObject_New(void *ptr, swig_type_info *ty, int own); + +SWIGRUNTIME void +SwigPyObject_dealloc(PyObject *v) +{ + SwigPyObject *sobj = (SwigPyObject *) v; + PyObject *next = sobj->next; + if (sobj->own == SWIG_POINTER_OWN) { + swig_type_info *ty = sobj->ty; + SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0; + PyObject *destroy = data ? data->destroy : 0; + if (destroy) { + /* destroy is always a VARARGS method */ + PyObject *res; + if (data->delargs) { + /* we need to create a temporary object to carry the destroy operation */ + PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0); + res = SWIG_Python_CallFunctor(destroy, tmp); + Py_DECREF(tmp); + } else { + PyCFunction meth = PyCFunction_GET_FUNCTION(destroy); + PyObject *mself = PyCFunction_GET_SELF(destroy); + res = ((*meth)(mself, v)); + } + Py_XDECREF(res); + } +#if !defined(SWIG_PYTHON_SILENT_MEMLEAK) + else { + const char *name = SWIG_TypePrettyName(ty); + printf("swig/python detected a memory leak of type '%s', no destructor found.\n", (name ? name : "unknown")); + } +#endif + } + Py_XDECREF(next); + PyObject_DEL(v); +} + +SWIGRUNTIME PyObject* +SwigPyObject_append(PyObject* v, PyObject* next) +{ + SwigPyObject *sobj = (SwigPyObject *) v; +#ifndef METH_O + PyObject *tmp = 0; + if (!PyArg_ParseTuple(next,(char *)"O:append", &tmp)) return NULL; + next = tmp; +#endif + if (!SwigPyObject_Check(next)) { + return NULL; + } + sobj->next = next; + Py_INCREF(next); + return SWIG_Py_Void(); +} + +SWIGRUNTIME PyObject* +#ifdef METH_NOARGS +SwigPyObject_next(PyObject* v) +#else +SwigPyObject_next(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) +#endif +{ + SwigPyObject *sobj = (SwigPyObject *) v; + if (sobj->next) { + Py_INCREF(sobj->next); + return sobj->next; + } else { + return SWIG_Py_Void(); + } +} + +SWIGINTERN PyObject* +#ifdef METH_NOARGS +SwigPyObject_disown(PyObject *v) +#else +SwigPyObject_disown(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) +#endif +{ + SwigPyObject *sobj = (SwigPyObject *)v; + sobj->own = 0; + return SWIG_Py_Void(); +} + +SWIGINTERN PyObject* +#ifdef METH_NOARGS +SwigPyObject_acquire(PyObject *v) +#else +SwigPyObject_acquire(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) +#endif +{ + SwigPyObject *sobj = (SwigPyObject *)v; + sobj->own = SWIG_POINTER_OWN; + return SWIG_Py_Void(); +} + +SWIGINTERN PyObject* +SwigPyObject_own(PyObject *v, PyObject *args) +{ + PyObject *val = 0; +#if (PY_VERSION_HEX < 0x02020000) + if (!PyArg_ParseTuple(args,(char *)"|O:own",&val)) +#else + if (!PyArg_UnpackTuple(args, (char *)"own", 0, 1, &val)) +#endif + { + return NULL; + } + else + { + SwigPyObject *sobj = (SwigPyObject *)v; + PyObject *obj = PyBool_FromLong(sobj->own); + if (val) { +#ifdef METH_NOARGS + if (PyObject_IsTrue(val)) { + SwigPyObject_acquire(v); + } else { + SwigPyObject_disown(v); + } +#else + if (PyObject_IsTrue(val)) { + SwigPyObject_acquire(v,args); + } else { + SwigPyObject_disown(v,args); + } +#endif + } + return obj; + } +} + +#ifdef METH_O +static PyMethodDef +swigobject_methods[] = { + {(char *)"disown", (PyCFunction)SwigPyObject_disown, METH_NOARGS, (char *)"releases ownership of the pointer"}, + {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_NOARGS, (char *)"aquires ownership of the pointer"}, + {(char *)"own", (PyCFunction)SwigPyObject_own, METH_VARARGS, (char *)"returns/sets ownership of the pointer"}, + {(char *)"append", (PyCFunction)SwigPyObject_append, METH_O, (char *)"appends another 'this' object"}, + {(char *)"next", (PyCFunction)SwigPyObject_next, METH_NOARGS, (char *)"returns the next 'this' object"}, + {(char *)"__repr__",(PyCFunction)SwigPyObject_repr, METH_NOARGS, (char *)"returns object representation"}, + {0, 0, 0, 0} +}; +#else +static PyMethodDef +swigobject_methods[] = { + {(char *)"disown", (PyCFunction)SwigPyObject_disown, METH_VARARGS, (char *)"releases ownership of the pointer"}, + {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_VARARGS, (char *)"aquires ownership of the pointer"}, + {(char *)"own", (PyCFunction)SwigPyObject_own, METH_VARARGS, (char *)"returns/sets ownership of the pointer"}, + {(char *)"append", (PyCFunction)SwigPyObject_append, METH_VARARGS, (char *)"appends another 'this' object"}, + {(char *)"next", (PyCFunction)SwigPyObject_next, METH_VARARGS, (char *)"returns the next 'this' object"}, + {(char *)"__repr__",(PyCFunction)SwigPyObject_repr, METH_VARARGS, (char *)"returns object representation"}, + {0, 0, 0, 0} +}; +#endif + +#if PY_VERSION_HEX < 0x02020000 +SWIGINTERN PyObject * +SwigPyObject_getattr(SwigPyObject *sobj,char *name) +{ + return Py_FindMethod(swigobject_methods, (PyObject *)sobj, name); +} +#endif + +SWIGRUNTIME PyTypeObject* +_PySwigObject_type(void) { + static char swigobject_doc[] = "Swig object carries a C/C++ instance pointer"; + + static PyNumberMethods SwigPyObject_as_number = { + (binaryfunc)0, /*nb_add*/ + (binaryfunc)0, /*nb_subtract*/ + (binaryfunc)0, /*nb_multiply*/ + /* nb_divide removed in Python 3 */ +#if PY_VERSION_HEX < 0x03000000 + (binaryfunc)0, /*nb_divide*/ +#endif + (binaryfunc)0, /*nb_remainder*/ + (binaryfunc)0, /*nb_divmod*/ + (ternaryfunc)0,/*nb_power*/ + (unaryfunc)0, /*nb_negative*/ + (unaryfunc)0, /*nb_positive*/ + (unaryfunc)0, /*nb_absolute*/ + (inquiry)0, /*nb_nonzero*/ + 0, /*nb_invert*/ + 0, /*nb_lshift*/ + 0, /*nb_rshift*/ + 0, /*nb_and*/ + 0, /*nb_xor*/ + 0, /*nb_or*/ +#if PY_VERSION_HEX < 0x03000000 + 0, /*nb_coerce*/ +#endif + (unaryfunc)SwigPyObject_long, /*nb_int*/ +#if PY_VERSION_HEX < 0x03000000 + (unaryfunc)SwigPyObject_long, /*nb_long*/ +#else + 0, /*nb_reserved*/ +#endif + (unaryfunc)0, /*nb_float*/ +#if PY_VERSION_HEX < 0x03000000 + (unaryfunc)SwigPyObject_oct, /*nb_oct*/ + (unaryfunc)SwigPyObject_hex, /*nb_hex*/ +#endif +#if PY_VERSION_HEX >= 0x03000000 /* 3.0 */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index, nb_inplace_divide removed */ +#elif PY_VERSION_HEX >= 0x02050000 /* 2.5.0 */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index */ +#elif PY_VERSION_HEX >= 0x02020000 /* 2.2.0 */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_true_divide */ +#elif PY_VERSION_HEX >= 0x02000000 /* 2.0.0 */ + 0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_or */ +#endif + }; + + static PyTypeObject swigpyobject_type; + static int type_init = 0; + if (!type_init) { + const PyTypeObject tmp + = { + /* PyObject header changed in Python 3 */ +#if PY_VERSION_HEX >= 0x03000000 + PyVarObject_HEAD_INIT(&PyType_Type, 0) +#else + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ +#endif + (char *)"SwigPyObject", /* tp_name */ + sizeof(SwigPyObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)SwigPyObject_dealloc, /* tp_dealloc */ + (printfunc)SwigPyObject_print, /* tp_print */ +#if PY_VERSION_HEX < 0x02020000 + (getattrfunc)SwigPyObject_getattr, /* tp_getattr */ +#else + (getattrfunc)0, /* tp_getattr */ +#endif + (setattrfunc)0, /* tp_setattr */ +#if PY_VERSION_HEX >= 0x03000000 + 0, /* tp_reserved in 3.0.1, tp_compare in 3.0.0 but not used */ +#else + (cmpfunc)SwigPyObject_compare, /* tp_compare */ +#endif + (reprfunc)SwigPyObject_repr, /* tp_repr */ + &SwigPyObject_as_number, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + (hashfunc)0, /* tp_hash */ + (ternaryfunc)0, /* tp_call */ + (reprfunc)SwigPyObject_str, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + swigobject_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + (richcmpfunc)SwigPyObject_richcompare, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ +#if PY_VERSION_HEX >= 0x02020000 + 0, /* tp_iter */ + 0, /* tp_iternext */ + swigobject_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ + 0, /* tp_mro */ + 0, /* tp_cache */ + 0, /* tp_subclasses */ + 0, /* tp_weaklist */ +#endif +#if PY_VERSION_HEX >= 0x02030000 + 0, /* tp_del */ +#endif +#ifdef COUNT_ALLOCS + 0,0,0,0 /* tp_alloc -> tp_next */ +#endif + }; + swigpyobject_type = tmp; + /* for Python 3 we already assigned ob_type in PyVarObject_HEAD_INIT() */ +#if PY_VERSION_HEX < 0x03000000 + swigpyobject_type.ob_type = &PyType_Type; +#endif + type_init = 1; + } + return &swigpyobject_type; +} + +SWIGRUNTIME PyObject * +SwigPyObject_New(void *ptr, swig_type_info *ty, int own) +{ + SwigPyObject *sobj = PyObject_NEW(SwigPyObject, SwigPyObject_type()); + if (sobj) { + sobj->ptr = ptr; + sobj->ty = ty; + sobj->own = own; + sobj->next = 0; + } + return (PyObject *)sobj; +} + +/* ----------------------------------------------------------------------------- + * Implements a simple Swig Packed type, and use it instead of string + * ----------------------------------------------------------------------------- */ + +typedef struct { + PyObject_HEAD + void *pack; + swig_type_info *ty; + size_t size; +} SwigPyPacked; + +SWIGRUNTIME int +SwigPyPacked_print(SwigPyPacked *v, FILE *fp, int SWIGUNUSEDPARM(flags)) +{ + char result[SWIG_BUFFER_SIZE]; + fputs("pack, v->size, 0, sizeof(result))) { + fputs("at ", fp); + fputs(result, fp); + } + fputs(v->ty->name,fp); + fputs(">", fp); + return 0; +} + +SWIGRUNTIME PyObject * +SwigPyPacked_repr(SwigPyPacked *v) +{ + char result[SWIG_BUFFER_SIZE]; + if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))) { + return SWIG_Python_str_FromFormat("", result, v->ty->name); + } else { + return SWIG_Python_str_FromFormat("", v->ty->name); + } +} + +SWIGRUNTIME PyObject * +SwigPyPacked_str(SwigPyPacked *v) +{ + char result[SWIG_BUFFER_SIZE]; + if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))){ + return SWIG_Python_str_FromFormat("%s%s", result, v->ty->name); + } else { + return SWIG_Python_str_FromChar(v->ty->name); + } +} + +SWIGRUNTIME int +SwigPyPacked_compare(SwigPyPacked *v, SwigPyPacked *w) +{ + size_t i = v->size; + size_t j = w->size; + int s = (i < j) ? -1 : ((i > j) ? 1 : 0); + return s ? s : strncmp((char *)v->pack, (char *)w->pack, 2*v->size); +} + +SWIGRUNTIME PyTypeObject* _PySwigPacked_type(void); + +SWIGRUNTIME PyTypeObject* +SwigPyPacked_type(void) { + static PyTypeObject *SWIG_STATIC_POINTER(type) = _PySwigPacked_type(); + return type; +} + +SWIGRUNTIMEINLINE int +SwigPyPacked_Check(PyObject *op) { + return ((op)->ob_type == _PySwigPacked_type()) + || (strcmp((op)->ob_type->tp_name,"SwigPyPacked") == 0); +} + +SWIGRUNTIME void +SwigPyPacked_dealloc(PyObject *v) +{ + if (SwigPyPacked_Check(v)) { + SwigPyPacked *sobj = (SwigPyPacked *) v; + free(sobj->pack); + } + PyObject_DEL(v); +} + +SWIGRUNTIME PyTypeObject* +_PySwigPacked_type(void) { + static char swigpacked_doc[] = "Swig object carries a C/C++ instance pointer"; + static PyTypeObject swigpypacked_type; + static int type_init = 0; + if (!type_init) { + const PyTypeObject tmp + = { + /* PyObject header changed in Python 3 */ +#if PY_VERSION_HEX>=0x03000000 + PyVarObject_HEAD_INIT(&PyType_Type, 0) +#else + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ +#endif + (char *)"SwigPyPacked", /* tp_name */ + sizeof(SwigPyPacked), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)SwigPyPacked_dealloc, /* tp_dealloc */ + (printfunc)SwigPyPacked_print, /* tp_print */ + (getattrfunc)0, /* tp_getattr */ + (setattrfunc)0, /* tp_setattr */ +#if PY_VERSION_HEX>=0x03000000 + 0, /* tp_reserved in 3.0.1 */ +#else + (cmpfunc)SwigPyPacked_compare, /* tp_compare */ +#endif + (reprfunc)SwigPyPacked_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + (hashfunc)0, /* tp_hash */ + (ternaryfunc)0, /* tp_call */ + (reprfunc)SwigPyPacked_str, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + swigpacked_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ +#if PY_VERSION_HEX >= 0x02020000 + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ + 0, /* tp_mro */ + 0, /* tp_cache */ + 0, /* tp_subclasses */ + 0, /* tp_weaklist */ +#endif +#if PY_VERSION_HEX >= 0x02030000 + 0, /* tp_del */ +#endif +#ifdef COUNT_ALLOCS + 0,0,0,0 /* tp_alloc -> tp_next */ +#endif + }; + swigpypacked_type = tmp; + /* for Python 3 the ob_type already assigned in PyVarObject_HEAD_INIT() */ +#if PY_VERSION_HEX < 0x03000000 + swigpypacked_type.ob_type = &PyType_Type; +#endif + type_init = 1; + } + return &swigpypacked_type; +} + +SWIGRUNTIME PyObject * +SwigPyPacked_New(void *ptr, size_t size, swig_type_info *ty) +{ + SwigPyPacked *sobj = PyObject_NEW(SwigPyPacked, SwigPyPacked_type()); + if (sobj) { + void *pack = malloc(size); + if (pack) { + memcpy(pack, ptr, size); + sobj->pack = pack; + sobj->ty = ty; + sobj->size = size; + } else { + PyObject_DEL((PyObject *) sobj); + sobj = 0; + } + } + return (PyObject *) sobj; +} + +SWIGRUNTIME swig_type_info * +SwigPyPacked_UnpackData(PyObject *obj, void *ptr, size_t size) +{ + if (SwigPyPacked_Check(obj)) { + SwigPyPacked *sobj = (SwigPyPacked *)obj; + if (sobj->size != size) return 0; + memcpy(ptr, sobj->pack, size); + return sobj->ty; + } else { + return 0; + } +} + +/* ----------------------------------------------------------------------------- + * pointers/data manipulation + * ----------------------------------------------------------------------------- */ + +SWIGRUNTIMEINLINE PyObject * +_SWIG_This(void) +{ + return SWIG_Python_str_FromChar("this"); +} + +SWIGRUNTIME PyObject * +SWIG_This(void) +{ + static PyObject *SWIG_STATIC_POINTER(swig_this) = _SWIG_This(); + return swig_this; +} + +/* #define SWIG_PYTHON_SLOW_GETSET_THIS */ + +/* TODO: I don't know how to implement the fast getset in Python 3 right now */ +#if PY_VERSION_HEX>=0x03000000 +#define SWIG_PYTHON_SLOW_GETSET_THIS +#endif + +SWIGRUNTIME SwigPyObject * +SWIG_Python_GetSwigThis(PyObject *pyobj) +{ + if (SwigPyObject_Check(pyobj)) { + return (SwigPyObject *) pyobj; + } else { + PyObject *obj = 0; +#if (!defined(SWIG_PYTHON_SLOW_GETSET_THIS) && (PY_VERSION_HEX >= 0x02030000)) + if (PyInstance_Check(pyobj)) { + obj = _PyInstance_Lookup(pyobj, SWIG_This()); + } else { + PyObject **dictptr = _PyObject_GetDictPtr(pyobj); + if (dictptr != NULL) { + PyObject *dict = *dictptr; + obj = dict ? PyDict_GetItem(dict, SWIG_This()) : 0; + } else { +#ifdef PyWeakref_CheckProxy + if (PyWeakref_CheckProxy(pyobj)) { + PyObject *wobj = PyWeakref_GET_OBJECT(pyobj); + return wobj ? SWIG_Python_GetSwigThis(wobj) : 0; + } +#endif + obj = PyObject_GetAttr(pyobj,SWIG_This()); + if (obj) { + Py_DECREF(obj); + } else { + if (PyErr_Occurred()) PyErr_Clear(); + return 0; + } + } + } +#else + obj = PyObject_GetAttr(pyobj,SWIG_This()); + if (obj) { + Py_DECREF(obj); + } else { + if (PyErr_Occurred()) PyErr_Clear(); + return 0; + } +#endif + if (obj && !SwigPyObject_Check(obj)) { + /* a PyObject is called 'this', try to get the 'real this' + SwigPyObject from it */ + return SWIG_Python_GetSwigThis(obj); + } + return (SwigPyObject *)obj; + } +} + +/* Acquire a pointer value */ + +SWIGRUNTIME int +SWIG_Python_AcquirePtr(PyObject *obj, int own) { + if (own == SWIG_POINTER_OWN) { + SwigPyObject *sobj = SWIG_Python_GetSwigThis(obj); + if (sobj) { + int oldown = sobj->own; + sobj->own = own; + return oldown; + } + } + return 0; +} + +/* Convert a pointer value */ + +SWIGRUNTIME int +SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int flags, int *own) { + if (!obj) return SWIG_ERROR; + if (obj == Py_None) { + if (ptr) *ptr = 0; + return SWIG_OK; + } else { + SwigPyObject *sobj = SWIG_Python_GetSwigThis(obj); + if (own) + *own = 0; + while (sobj) { + void *vptr = sobj->ptr; + if (ty) { + swig_type_info *to = sobj->ty; + if (to == ty) { + /* no type cast needed */ + if (ptr) *ptr = vptr; + break; + } else { + swig_cast_info *tc = SWIG_TypeCheck(to->name,ty); + if (!tc) { + sobj = (SwigPyObject *)sobj->next; + } else { + if (ptr) { + int newmemory = 0; + *ptr = SWIG_TypeCast(tc,vptr,&newmemory); + if (newmemory == SWIG_CAST_NEW_MEMORY) { + assert(own); + if (own) + *own = *own | SWIG_CAST_NEW_MEMORY; + } + } + break; + } + } + } else { + if (ptr) *ptr = vptr; + break; + } + } + if (sobj) { + if (own) + *own = *own | sobj->own; + if (flags & SWIG_POINTER_DISOWN) { + sobj->own = 0; + } + return SWIG_OK; + } else { + int res = SWIG_ERROR; + if (flags & SWIG_POINTER_IMPLICIT_CONV) { + SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0; + if (data && !data->implicitconv) { + PyObject *klass = data->klass; + if (klass) { + PyObject *impconv; + data->implicitconv = 1; /* avoid recursion and call 'explicit' constructors*/ + impconv = SWIG_Python_CallFunctor(klass, obj); + data->implicitconv = 0; + if (PyErr_Occurred()) { + PyErr_Clear(); + impconv = 0; + } + if (impconv) { + SwigPyObject *iobj = SWIG_Python_GetSwigThis(impconv); + if (iobj) { + void *vptr; + res = SWIG_Python_ConvertPtrAndOwn((PyObject*)iobj, &vptr, ty, 0, 0); + if (SWIG_IsOK(res)) { + if (ptr) { + *ptr = vptr; + /* transfer the ownership to 'ptr' */ + iobj->own = 0; + res = SWIG_AddCast(res); + res = SWIG_AddNewMask(res); + } else { + res = SWIG_AddCast(res); + } + } + } + Py_DECREF(impconv); + } + } + } + } + return res; + } + } +} + +/* Convert a function ptr value */ + +SWIGRUNTIME int +SWIG_Python_ConvertFunctionPtr(PyObject *obj, void **ptr, swig_type_info *ty) { + if (!PyCFunction_Check(obj)) { + return SWIG_ConvertPtr(obj, ptr, ty, 0); + } else { + void *vptr = 0; + + /* here we get the method pointer for callbacks */ + const char *doc = (((PyCFunctionObject *)obj) -> m_ml -> ml_doc); + const char *desc = doc ? strstr(doc, "swig_ptr: ") : 0; + if (desc) + desc = ty ? SWIG_UnpackVoidPtr(desc + 10, &vptr, ty->name) : 0; + if (!desc) + return SWIG_ERROR; + if (ty) { + swig_cast_info *tc = SWIG_TypeCheck(desc,ty); + if (tc) { + int newmemory = 0; + *ptr = SWIG_TypeCast(tc,vptr,&newmemory); + assert(!newmemory); /* newmemory handling not yet implemented */ + } else { + return SWIG_ERROR; + } + } else { + *ptr = vptr; + } + return SWIG_OK; + } +} + +/* Convert a packed value value */ + +SWIGRUNTIME int +SWIG_Python_ConvertPacked(PyObject *obj, void *ptr, size_t sz, swig_type_info *ty) { + swig_type_info *to = SwigPyPacked_UnpackData(obj, ptr, sz); + if (!to) return SWIG_ERROR; + if (ty) { + if (to != ty) { + /* check type cast? */ + swig_cast_info *tc = SWIG_TypeCheck(to->name,ty); + if (!tc) return SWIG_ERROR; + } + } + return SWIG_OK; +} + +/* ----------------------------------------------------------------------------- + * Create a new pointer object + * ----------------------------------------------------------------------------- */ + +/* + Create a new instance object, without calling __init__, and set the + 'this' attribute. +*/ + +SWIGRUNTIME PyObject* +SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this) +{ +#if (PY_VERSION_HEX >= 0x02020000) + PyObject *inst = 0; + PyObject *newraw = data->newraw; + if (newraw) { + inst = PyObject_Call(newraw, data->newargs, NULL); + if (inst) { +#if !defined(SWIG_PYTHON_SLOW_GETSET_THIS) + PyObject **dictptr = _PyObject_GetDictPtr(inst); + if (dictptr != NULL) { + PyObject *dict = *dictptr; + if (dict == NULL) { + dict = PyDict_New(); + *dictptr = dict; + PyDict_SetItem(dict, SWIG_This(), swig_this); + } + } +#else + PyObject *key = SWIG_This(); + PyObject_SetAttr(inst, key, swig_this); +#endif + } + } else { +#if PY_VERSION_HEX >= 0x03000000 + inst = PyBaseObject_Type.tp_new((PyTypeObject*) data->newargs, Py_None, Py_None); + PyObject_SetAttr(inst, SWIG_This(), swig_this); + Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG; +#else + PyObject *dict = PyDict_New(); + PyDict_SetItem(dict, SWIG_This(), swig_this); + inst = PyInstance_NewRaw(data->newargs, dict); + Py_DECREF(dict); +#endif + } + return inst; +#else +#if (PY_VERSION_HEX >= 0x02010000) + PyObject *inst; + PyObject *dict = PyDict_New(); + PyDict_SetItem(dict, SWIG_This(), swig_this); + inst = PyInstance_NewRaw(data->newargs, dict); + Py_DECREF(dict); + return (PyObject *) inst; +#else + PyInstanceObject *inst = PyObject_NEW(PyInstanceObject, &PyInstance_Type); + if (inst == NULL) { + return NULL; + } + inst->in_class = (PyClassObject *)data->newargs; + Py_INCREF(inst->in_class); + inst->in_dict = PyDict_New(); + if (inst->in_dict == NULL) { + Py_DECREF(inst); + return NULL; + } +#ifdef Py_TPFLAGS_HAVE_WEAKREFS + inst->in_weakreflist = NULL; +#endif +#ifdef Py_TPFLAGS_GC + PyObject_GC_Init(inst); +#endif + PyDict_SetItem(inst->in_dict, SWIG_This(), swig_this); + return (PyObject *) inst; +#endif +#endif +} + +SWIGRUNTIME void +SWIG_Python_SetSwigThis(PyObject *inst, PyObject *swig_this) +{ + PyObject *dict; +#if (PY_VERSION_HEX >= 0x02020000) && !defined(SWIG_PYTHON_SLOW_GETSET_THIS) + PyObject **dictptr = _PyObject_GetDictPtr(inst); + if (dictptr != NULL) { + dict = *dictptr; + if (dict == NULL) { + dict = PyDict_New(); + *dictptr = dict; + } + PyDict_SetItem(dict, SWIG_This(), swig_this); + return; + } +#endif + dict = PyObject_GetAttrString(inst, (char*)"__dict__"); + PyDict_SetItem(dict, SWIG_This(), swig_this); + Py_DECREF(dict); +} + + +SWIGINTERN PyObject * +SWIG_Python_InitShadowInstance(PyObject *args) { + PyObject *obj[2]; + if (!SWIG_Python_UnpackTuple(args,(char*)"swiginit", 2, 2, obj)) { + return NULL; + } else { + SwigPyObject *sthis = SWIG_Python_GetSwigThis(obj[0]); + if (sthis) { + SwigPyObject_append((PyObject*) sthis, obj[1]); + } else { + SWIG_Python_SetSwigThis(obj[0], obj[1]); + } + return SWIG_Py_Void(); + } +} + +/* Create a new pointer object */ + +SWIGRUNTIME PyObject * +SWIG_Python_NewPointerObj(void *ptr, swig_type_info *type, int flags) { + if (!ptr) { + return SWIG_Py_Void(); + } else { + int own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0; + PyObject *robj = SwigPyObject_New(ptr, type, own); + SwigPyClientData *clientdata = type ? (SwigPyClientData *)(type->clientdata) : 0; + if (clientdata && !(flags & SWIG_POINTER_NOSHADOW)) { + PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj); + if (inst) { + Py_DECREF(robj); + robj = inst; + } + } + return robj; + } +} + +/* Create a new packed object */ + +SWIGRUNTIMEINLINE PyObject * +SWIG_Python_NewPackedObj(void *ptr, size_t sz, swig_type_info *type) { + return ptr ? SwigPyPacked_New((void *) ptr, sz, type) : SWIG_Py_Void(); +} + +/* -----------------------------------------------------------------------------* + * Get type list + * -----------------------------------------------------------------------------*/ + +#ifdef SWIG_LINK_RUNTIME +void *SWIG_ReturnGlobalTypeList(void *); +#endif + +SWIGRUNTIME swig_module_info * +SWIG_Python_GetModule(void) { + static void *type_pointer = (void *)0; + /* first check if module already created */ + if (!type_pointer) { +#ifdef SWIG_LINK_RUNTIME + type_pointer = SWIG_ReturnGlobalTypeList((void *)0); +#else + type_pointer = PyCObject_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, + (char*)"type_pointer" SWIG_TYPE_TABLE_NAME); + if (PyErr_Occurred()) { + PyErr_Clear(); + type_pointer = (void *)0; + } +#endif + } + return (swig_module_info *) type_pointer; +} + +#if PY_MAJOR_VERSION < 2 +/* PyModule_AddObject function was introduced in Python 2.0. The following function + is copied out of Python/modsupport.c in python version 2.3.4 */ +SWIGINTERN int +PyModule_AddObject(PyObject *m, char *name, PyObject *o) +{ + PyObject *dict; + if (!PyModule_Check(m)) { + PyErr_SetString(PyExc_TypeError, + "PyModule_AddObject() needs module as first arg"); + return SWIG_ERROR; + } + if (!o) { + PyErr_SetString(PyExc_TypeError, + "PyModule_AddObject() needs non-NULL value"); + return SWIG_ERROR; + } + + dict = PyModule_GetDict(m); + if (dict == NULL) { + /* Internal error -- modules must have a dict! */ + PyErr_Format(PyExc_SystemError, "module '%s' has no __dict__", + PyModule_GetName(m)); + return SWIG_ERROR; + } + if (PyDict_SetItemString(dict, name, o)) + return SWIG_ERROR; + Py_DECREF(o); + return SWIG_OK; +} +#endif + +SWIGRUNTIME void +SWIG_Python_DestroyModule(void *vptr) +{ + swig_module_info *swig_module = (swig_module_info *) vptr; + swig_type_info **types = swig_module->types; + size_t i; + for (i =0; i < swig_module->size; ++i) { + swig_type_info *ty = types[i]; + if (ty->owndata) { + SwigPyClientData *data = (SwigPyClientData *) ty->clientdata; + if (data) SwigPyClientData_Del(data); + } + } + Py_DECREF(SWIG_This()); +} + +SWIGRUNTIME void +SWIG_Python_SetModule(swig_module_info *swig_module) { + static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} };/* Sentinel */ + +#if PY_VERSION_HEX >= 0x03000000 + /* Add a dummy module object into sys.modules */ + PyObject *module = PyImport_AddModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION); +#else + PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, + swig_empty_runtime_method_table); +#endif + PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule); + if (pointer && module) { + PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer); + } else { + Py_XDECREF(pointer); + } +} + +/* The python cached type query */ +SWIGRUNTIME PyObject * +SWIG_Python_TypeCache(void) { + static PyObject *SWIG_STATIC_POINTER(cache) = PyDict_New(); + return cache; +} + +SWIGRUNTIME swig_type_info * +SWIG_Python_TypeQuery(const char *type) +{ + PyObject *cache = SWIG_Python_TypeCache(); + PyObject *key = SWIG_Python_str_FromChar(type); + PyObject *obj = PyDict_GetItem(cache, key); + swig_type_info *descriptor; + if (obj) { + descriptor = (swig_type_info *) PyCObject_AsVoidPtr(obj); + } else { + swig_module_info *swig_module = SWIG_Python_GetModule(); + descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type); + if (descriptor) { + obj = PyCObject_FromVoidPtr(descriptor, NULL); + PyDict_SetItem(cache, key, obj); + Py_DECREF(obj); + } + } + Py_DECREF(key); + return descriptor; +} + +/* + For backward compatibility only +*/ +#define SWIG_POINTER_EXCEPTION 0 +#define SWIG_arg_fail(arg) SWIG_Python_ArgFail(arg) +#define SWIG_MustGetPtr(p, type, argnum, flags) SWIG_Python_MustGetPtr(p, type, argnum, flags) + +SWIGRUNTIME int +SWIG_Python_AddErrMesg(const char* mesg, int infront) +{ + if (PyErr_Occurred()) { + PyObject *type = 0; + PyObject *value = 0; + PyObject *traceback = 0; + PyErr_Fetch(&type, &value, &traceback); + if (value) { + char *tmp; + PyObject *old_str = PyObject_Str(value); + Py_XINCREF(type); + PyErr_Clear(); + if (infront) { + PyErr_Format(type, "%s %s", mesg, tmp = SWIG_Python_str_AsChar(old_str)); + } else { + PyErr_Format(type, "%s %s", tmp = SWIG_Python_str_AsChar(old_str), mesg); + } + SWIG_Python_str_DelForPy3(tmp); + Py_DECREF(old_str); + } + return 1; + } else { + return 0; + } +} + +SWIGRUNTIME int +SWIG_Python_ArgFail(int argnum) +{ + if (PyErr_Occurred()) { + /* add information about failing argument */ + char mesg[256]; + PyOS_snprintf(mesg, sizeof(mesg), "argument number %d:", argnum); + return SWIG_Python_AddErrMesg(mesg, 1); + } else { + return 0; + } +} + +SWIGRUNTIMEINLINE const char * +SwigPyObject_GetDesc(PyObject *self) +{ + SwigPyObject *v = (SwigPyObject *)self; + swig_type_info *ty = v ? v->ty : 0; + return ty ? ty->str : (char*)""; +} + +SWIGRUNTIME void +SWIG_Python_TypeError(const char *type, PyObject *obj) +{ + if (type) { +#if defined(SWIG_COBJECT_TYPES) + if (obj && SwigPyObject_Check(obj)) { + const char *otype = (const char *) SwigPyObject_GetDesc(obj); + if (otype) { + PyErr_Format(PyExc_TypeError, "a '%s' is expected, 'SwigPyObject(%s)' is received", + type, otype); + return; + } + } else +#endif + { + const char *otype = (obj ? obj->ob_type->tp_name : 0); + if (otype) { + PyObject *str = PyObject_Str(obj); + const char *cstr = str ? SWIG_Python_str_AsChar(str) : 0; + if (cstr) { + PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s(%s)' is received", + type, otype, cstr); + SWIG_Python_str_DelForPy3(cstr); + } else { + PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s' is received", + type, otype); + } + Py_XDECREF(str); + return; + } + } + PyErr_Format(PyExc_TypeError, "a '%s' is expected", type); + } else { + PyErr_Format(PyExc_TypeError, "unexpected type is received"); + } +} + + +/* Convert a pointer value, signal an exception on a type mismatch */ +SWIGRUNTIME void * +SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags) { + void *result; + if (SWIG_Python_ConvertPtr(obj, &result, ty, flags) == -1) { + PyErr_Clear(); +#if SWIG_POINTER_EXCEPTION + if (flags) { + SWIG_Python_TypeError(SWIG_TypePrettyName(ty), obj); + SWIG_Python_ArgFail(argnum); + } +#endif + } + return result; +} + + +#ifdef __cplusplus +#if 0 +{ /* cc-mode */ +#endif +} +#endif + + + +#define SWIG_exception_fail(code, msg) do { SWIG_Error(code, msg); SWIG_fail; } while(0) + +#define SWIG_contract_assert(expr, msg) if (!(expr)) { SWIG_Error(SWIG_RuntimeError, msg); SWIG_fail; } else + + + +/* -------- TYPES TABLE (BEGIN) -------- */ + +#define SWIGTYPE_p_char swig_types[0] +#define SWIGTYPE_p_int swig_types[1] +#define SWIGTYPE_p_long_long swig_types[2] +#define SWIGTYPE_p_nl_addr swig_types[3] +#define SWIGTYPE_p_nl_cache swig_types[4] +#define SWIGTYPE_p_nl_object swig_types[5] +#define SWIGTYPE_p_nl_sock swig_types[6] +#define SWIGTYPE_p_p_nl_msg swig_types[7] +#define SWIGTYPE_p_rtnl_addr swig_types[8] +#define SWIGTYPE_p_rtnl_class swig_types[9] +#define SWIGTYPE_p_rtnl_cls swig_types[10] +#define SWIGTYPE_p_rtnl_link swig_types[11] +#define SWIGTYPE_p_rtnl_qdisc swig_types[12] +#define SWIGTYPE_p_rtnl_tc swig_types[13] +#define SWIGTYPE_p_short swig_types[14] +#define SWIGTYPE_p_signed_char swig_types[15] +#define SWIGTYPE_p_unsigned_char swig_types[16] +#define SWIGTYPE_p_unsigned_int swig_types[17] +#define SWIGTYPE_p_unsigned_long_long swig_types[18] +#define SWIGTYPE_p_unsigned_short swig_types[19] +#define SWIGTYPE_p_vlan_map swig_types[20] +static swig_type_info *swig_types[22]; +static swig_module_info swig_module = {swig_types, 21, 0, 0, 0, 0}; +#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name) +#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name) + +/* -------- TYPES TABLE (END) -------- */ + +#if (PY_VERSION_HEX <= 0x02000000) +# if !defined(SWIG_PYTHON_CLASSIC) +# error "This python version requires swig to be run with the '-classic' option" +# endif +#endif +#if (PY_VERSION_HEX <= 0x02020000) +# error "This python version requires swig to be run with the '-nomodern' option" +#endif +#if (PY_VERSION_HEX <= 0x02020000) +# error "This python version requires swig to be run with the '-nomodernargs' option" +#endif +#ifndef METH_O +# error "This python version requires swig to be run with the '-nofastunpack' option" +#endif +#ifdef SWIG_TypeQuery +# undef SWIG_TypeQuery +#endif +#define SWIG_TypeQuery SWIG_Python_TypeQuery + +/*----------------------------------------------- + @(target):= _capi.so + ------------------------------------------------*/ +#if PY_VERSION_HEX >= 0x03000000 +# define SWIG_init PyInit__capi + +#else +# define SWIG_init init_capi + +#endif +#define SWIG_name "_capi" + +#define SWIGVERSION 0x010340 +#define SWIG_VERSION SWIGVERSION + + +#define SWIG_as_voidptr(a) (void *)((const void *)(a)) +#define SWIG_as_voidptrptr(a) ((void)SWIG_as_voidptr(*a),(void**)(a)) + + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include + + +#include // Use the C99 official header + + + struct nl_object *link2obj(struct rtnl_link *link) + { + return OBJ_CAST(link); + } + + struct rtnl_link *obj2link(struct nl_object *obj) + { + return (struct rtnl_link *) obj; + } + + struct rtnl_link *get_from_kernel(struct nl_sock *sk, int ifindex, const char *name) + { + struct rtnl_link *link; + if (rtnl_link_get_kernel(sk, ifindex, name, &link) < 0) + return NULL; + return link; + } + + uint32_t inet_get_conf(struct rtnl_link *link, const unsigned int id) + { + uint32_t result; + + if (rtnl_link_inet_get_conf(link, id, &result) < 0) + return 0; + + return result; + } + + +#include +#if !defined(SWIG_NO_LLONG_MAX) +# if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__) +# define LLONG_MAX __LONG_LONG_MAX__ +# define LLONG_MIN (-LLONG_MAX - 1LL) +# define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL) +# endif +#endif + + +SWIGINTERN int +SWIG_AsVal_double (PyObject *obj, double *val) +{ + int res = SWIG_TypeError; + if (PyFloat_Check(obj)) { + if (val) *val = PyFloat_AsDouble(obj); + return SWIG_OK; + } else if (PyInt_Check(obj)) { + if (val) *val = PyInt_AsLong(obj); + return SWIG_OK; + } else if (PyLong_Check(obj)) { + double v = PyLong_AsDouble(obj); + if (!PyErr_Occurred()) { + if (val) *val = v; + return SWIG_OK; + } else { + PyErr_Clear(); + } + } +#ifdef SWIG_PYTHON_CAST_MODE + { + int dispatch = 0; + double d = PyFloat_AsDouble(obj); + if (!PyErr_Occurred()) { + if (val) *val = d; + return SWIG_AddCast(SWIG_OK); + } else { + PyErr_Clear(); + } + if (!dispatch) { + long v = PyLong_AsLong(obj); + if (!PyErr_Occurred()) { + if (val) *val = v; + return SWIG_AddCast(SWIG_AddCast(SWIG_OK)); + } else { + PyErr_Clear(); + } + } + } +#endif + return res; +} + + +#include + + +#include + + +SWIGINTERNINLINE int +SWIG_CanCastAsInteger(double *d, double min, double max) { + double x = *d; + if ((min <= x && x <= max)) { + double fx = floor(x); + double cx = ceil(x); + double rd = ((x - fx) < 0.5) ? fx : cx; /* simple rint */ + if ((errno == EDOM) || (errno == ERANGE)) { + errno = 0; + } else { + double summ, reps, diff; + if (rd < x) { + diff = x - rd; + } else if (rd > x) { + diff = rd - x; + } else { + return 1; + } + summ = rd + x; + reps = diff/summ; + if (reps < 8*DBL_EPSILON) { + *d = rd; + return 1; + } + } + } + return 0; +} + + +SWIGINTERN int +SWIG_AsVal_long (PyObject *obj, long* val) +{ + if (PyInt_Check(obj)) { + if (val) *val = PyInt_AsLong(obj); + return SWIG_OK; + } else if (PyLong_Check(obj)) { + long v = PyLong_AsLong(obj); + if (!PyErr_Occurred()) { + if (val) *val = v; + return SWIG_OK; + } else { + PyErr_Clear(); + } + } +#ifdef SWIG_PYTHON_CAST_MODE + { + int dispatch = 0; + long v = PyInt_AsLong(obj); + if (!PyErr_Occurred()) { + if (val) *val = v; + return SWIG_AddCast(SWIG_OK); + } else { + PyErr_Clear(); + } + if (!dispatch) { + double d; + int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d)); + if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) { + if (val) *val = (long)(d); + return res; + } + } + } +#endif + return SWIG_TypeError; +} + + +SWIGINTERN int +SWIG_AsVal_int (PyObject * obj, int *val) +{ + long v; + int res = SWIG_AsVal_long (obj, &v); + if (SWIG_IsOK(res)) { + if ((v < INT_MIN || v > INT_MAX)) { + return SWIG_OverflowError; + } else { + if (val) *val = (int)(v); + } + } + return res; +} + + +SWIGINTERN swig_type_info* +SWIG_pchar_descriptor(void) +{ + static int init = 0; + static swig_type_info* info = 0; + if (!init) { + info = SWIG_TypeQuery("_p_char"); + init = 1; + } + return info; +} + + +SWIGINTERN int +SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc) +{ +#if PY_VERSION_HEX>=0x03000000 + if (PyUnicode_Check(obj)) +#else + if (PyString_Check(obj)) +#endif + { + char *cstr; Py_ssize_t len; +#if PY_VERSION_HEX>=0x03000000 + if (!alloc && cptr) { + /* We can't allow converting without allocation, since the internal + representation of string in Python 3 is UCS-2/UCS-4 but we require + a UTF-8 representation. + TODO(bhy) More detailed explanation */ + return SWIG_RuntimeError; + } + obj = PyUnicode_AsUTF8String(obj); + PyBytes_AsStringAndSize(obj, &cstr, &len); + if(alloc) *alloc = SWIG_NEWOBJ; +#else + PyString_AsStringAndSize(obj, &cstr, &len); +#endif + if (cptr) { + if (alloc) { + /* + In python the user should not be able to modify the inner + string representation. To warranty that, if you define + SWIG_PYTHON_SAFE_CSTRINGS, a new/copy of the python string + buffer is always returned. + + The default behavior is just to return the pointer value, + so, be careful. + */ +#if defined(SWIG_PYTHON_SAFE_CSTRINGS) + if (*alloc != SWIG_OLDOBJ) +#else + if (*alloc == SWIG_NEWOBJ) +#endif + { + *cptr = (char *)memcpy((char *)malloc((len + 1)*sizeof(char)), cstr, sizeof(char)*(len + 1)); + *alloc = SWIG_NEWOBJ; + } + else { + *cptr = cstr; + *alloc = SWIG_OLDOBJ; + } + } else { + #if PY_VERSION_HEX>=0x03000000 + assert(0); /* Should never reach here in Python 3 */ + #endif + *cptr = SWIG_Python_str_AsChar(obj); + } + } + if (psize) *psize = len + 1; +#if PY_VERSION_HEX>=0x03000000 + Py_XDECREF(obj); +#endif + return SWIG_OK; + } else { + swig_type_info* pchar_descriptor = SWIG_pchar_descriptor(); + if (pchar_descriptor) { + void* vptr = 0; + if (SWIG_ConvertPtr(obj, &vptr, pchar_descriptor, 0) == SWIG_OK) { + if (cptr) *cptr = (char *) vptr; + if (psize) *psize = vptr ? (strlen((char *)vptr) + 1) : 0; + if (alloc) *alloc = SWIG_OLDOBJ; + return SWIG_OK; + } + } + } + return SWIG_TypeError; +} + + + + + +SWIGINTERN int +SWIG_AsVal_unsigned_SS_long (PyObject *obj, unsigned long *val) +{ + if (PyInt_Check(obj)) { + long v = PyInt_AsLong(obj); + if (v >= 0) { + if (val) *val = v; + return SWIG_OK; + } else { + return SWIG_OverflowError; + } + } else if (PyLong_Check(obj)) { + unsigned long v = PyLong_AsUnsignedLong(obj); + if (!PyErr_Occurred()) { + if (val) *val = v; + return SWIG_OK; + } else { + PyErr_Clear(); + } + } +#ifdef SWIG_PYTHON_CAST_MODE + { + int dispatch = 0; + unsigned long v = PyLong_AsUnsignedLong(obj); + if (!PyErr_Occurred()) { + if (val) *val = v; + return SWIG_AddCast(SWIG_OK); + } else { + PyErr_Clear(); + } + if (!dispatch) { + double d; + int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d)); + if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ULONG_MAX)) { + if (val) *val = (unsigned long)(d); + return res; + } + } + } +#endif + return SWIG_TypeError; +} + + +SWIGINTERN int +SWIG_AsVal_unsigned_SS_int (PyObject * obj, unsigned int *val) +{ + unsigned long v; + int res = SWIG_AsVal_unsigned_SS_long (obj, &v); + if (SWIG_IsOK(res)) { + if ((v > UINT_MAX)) { + return SWIG_OverflowError; + } else { + if (val) *val = (unsigned int)(v); + } + } + return res; +} + + + #define SWIG_From_long PyInt_FromLong + + +SWIGINTERNINLINE PyObject* +SWIG_From_unsigned_SS_long (unsigned long value) +{ + return (value > LONG_MAX) ? + PyLong_FromUnsignedLong(value) : PyInt_FromLong((long)(value)); +} + + +SWIGINTERNINLINE PyObject * +SWIG_From_unsigned_SS_int (unsigned int value) +{ + return SWIG_From_unsigned_SS_long (value); +} + + +SWIGINTERNINLINE int +SWIG_AsVal_size_t (PyObject * obj, size_t *val) +{ + unsigned long v; + int res = SWIG_AsVal_unsigned_SS_long (obj, val ? &v : 0); + if (SWIG_IsOK(res) && val) *val = (size_t)(v); + return res; +} + + +SWIGINTERNINLINE PyObject * +SWIG_FromCharPtrAndSize(const char* carray, size_t size) +{ + if (carray) { + if (size > INT_MAX) { + swig_type_info* pchar_descriptor = SWIG_pchar_descriptor(); + return pchar_descriptor ? + SWIG_NewPointerObj((char *)(carray), pchar_descriptor, 0) : SWIG_Py_Void(); + } else { +#if PY_VERSION_HEX >= 0x03000000 + return PyUnicode_FromStringAndSize(carray, (int)(size)); +#else + return PyString_FromStringAndSize(carray, (int)(size)); +#endif + } + } else { + return SWIG_Py_Void(); + } +} + + +SWIGINTERNINLINE PyObject * +SWIG_FromCharPtr(const char *cptr) +{ + return SWIG_FromCharPtrAndSize(cptr, (cptr ? strlen(cptr) : 0)); +} + + +SWIGINTERNINLINE PyObject * +SWIG_From_int (int value) +{ + return SWIG_From_long (value); +} + + +SWIGINTERN int +SWIG_AsVal_unsigned_SS_char (PyObject * obj, unsigned char *val) +{ + unsigned long v; + int res = SWIG_AsVal_unsigned_SS_long (obj, &v); + if (SWIG_IsOK(res)) { + if ((v > UCHAR_MAX)) { + return SWIG_OverflowError; + } else { + if (val) *val = (unsigned char)(v); + } + } + return res; +} + + +SWIGINTERNINLINE PyObject * +SWIG_From_unsigned_SS_char (unsigned char value) +{ + return SWIG_From_unsigned_SS_long (value); +} + + +SWIGINTERNINLINE PyObject* +SWIG_From_long_SS_long (long long value) +{ + return ((value < LONG_MIN) || (value > LONG_MAX)) ? + PyLong_FromLongLong(value) : PyInt_FromLong((long)(value)); +} + + +SWIGINTERNINLINE PyObject* +SWIG_From_unsigned_SS_long_SS_long (unsigned long long value) +{ + return (value > LONG_MAX) ? + PyLong_FromUnsignedLongLong(value) : PyInt_FromLong((long)(value)); +} + + +SWIGINTERN int +SWIG_AsVal_unsigned_SS_long_SS_long (PyObject *obj, unsigned long long *val) +{ + int res = SWIG_TypeError; + if (PyLong_Check(obj)) { + unsigned long long v = PyLong_AsUnsignedLongLong(obj); + if (!PyErr_Occurred()) { + if (val) *val = v; + return SWIG_OK; + } else { + PyErr_Clear(); + } + } else { + unsigned long v; + res = SWIG_AsVal_unsigned_SS_long (obj,&v); + if (SWIG_IsOK(res)) { + if (val) *val = v; + return res; + } + } +#ifdef SWIG_PYTHON_CAST_MODE + { + const double mant_max = 1LL << DBL_MANT_DIG; + double d; + res = SWIG_AsVal_double (obj,&d); + if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, mant_max)) { + if (val) *val = (unsigned long long)(d); + return SWIG_AddCast(res); + } + res = SWIG_TypeError; + } +#endif + return res; +} + + + uint32_t tc_str2handle(const char *name) + { + uint32_t result; + + if (rtnl_tc_str2handle(name, &result) < 0) + return 0; + + return result; + } + + + struct nl_object *qdisc2obj(struct rtnl_qdisc *qdisc) + { + return OBJ_CAST(qdisc); + } + + struct rtnl_qdisc *obj2qdisc(struct nl_object *obj) + { + return (struct rtnl_qdisc *) obj; + } + + struct nl_object *class2obj(struct rtnl_class *cl) + { + return OBJ_CAST(cl); + } + + struct rtnl_class *obj2class(struct nl_object *obj) + { + return (struct rtnl_class *) obj; + } + + struct nl_object *cls2obj(struct rtnl_cls *cls) + { + return OBJ_CAST(cls); + } + + struct rtnl_cls *obj2cls(struct nl_object *obj) + { + return (struct rtnl_cls *) obj; + } + + struct rtnl_tc *obj2tc(struct nl_object *obj) + { + return TC_CAST(obj); + } + + +SWIGINTERN int +SWIG_AsVal_unsigned_SS_short (PyObject * obj, unsigned short *val) +{ + unsigned long v; + int res = SWIG_AsVal_unsigned_SS_long (obj, &v); + if (SWIG_IsOK(res)) { + if ((v > USHRT_MAX)) { + return SWIG_OverflowError; + } else { + if (val) *val = (unsigned short)(v); + } + } + return res; +} + + +SWIGINTERNINLINE PyObject * +SWIG_From_unsigned_SS_short (unsigned short value) +{ + return SWIG_From_unsigned_SS_long (value); +} + + + struct nl_object *addr2obj(struct rtnl_addr *addr) + { + return OBJ_CAST(addr); + } + + struct rtnl_addr *obj2addr(struct nl_object *obj) + { + return (struct rtnl_addr *) obj; + } + +#ifdef __cplusplus +extern "C" { +#endif +SWIGINTERN PyObject *_wrap_link2obj(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_object *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "link2obj" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + result = (struct nl_object *)link2obj(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_obj2link(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_object *arg1 = (struct nl_object *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct rtnl_link *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "obj2link" "', argument " "1"" of type '" "struct nl_object *""'"); + } + arg1 = (struct nl_object *)(argp1); + result = (struct rtnl_link *)obj2link(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_link, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_get_from_kernel(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_sock *arg1 = (struct nl_sock *) 0 ; + int arg2 ; + char *arg3 = (char *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + int res3 ; + char *buf3 = 0 ; + int alloc3 = 0 ; + PyObject *swig_obj[3] ; + struct rtnl_link *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"get_from_kernel",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "get_from_kernel" "', argument " "1"" of type '" "struct nl_sock *""'"); + } + arg1 = (struct nl_sock *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "get_from_kernel" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + res3 = SWIG_AsCharPtrAndSize(swig_obj[2], &buf3, NULL, &alloc3); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "get_from_kernel" "', argument " "3"" of type '" "char const *""'"); + } + arg3 = (char *)(buf3); + result = (struct rtnl_link *)get_from_kernel(arg1,arg2,(char const *)arg3); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (alloc3 == SWIG_NEWOBJ) free((char*)buf3); + return resultobj; +fail: + if (alloc3 == SWIG_NEWOBJ) free((char*)buf3); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_inet_get_conf(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + unsigned int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + uint32_t result; + + if (!SWIG_Python_UnpackTuple(args,"inet_get_conf",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "inet_get_conf" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "inet_get_conf" "', argument " "2"" of type '" "unsigned int""'"); + } + arg2 = (unsigned int)(val2); + result = (uint32_t)inet_get_conf(arg1,arg2); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_scope2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + int arg1 ; + char *arg2 = (char *) 0 ; + size_t arg3 ; + int val1 ; + int ecode1 = 0 ; + int res2 ; + size_t size2 ; + char *buff2 = 0 ; + PyObject *swig_obj[2] ; + char *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_scope2str",2,2,swig_obj)) SWIG_fail; + ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rtnl_scope2str" "', argument " "1"" of type '" "int""'"); + } + arg1 = (int)(val1); + res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_scope2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); + } + buff2= (char *)malloc((size2+1)*sizeof(char)); + arg3 = (size_t)(size2); + arg2 = (char *)(buff2); + result = (char *)rtnl_scope2str(arg1,arg2,arg3); + resultobj = SWIG_FromCharPtr((const char *)result); + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); + if (buff2) free((char*)buff2); + return resultobj; +fail: + if (buff2) free((char*)buff2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_str2scope(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + char *arg1 = (char *) 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_str2scope" "', argument " "1"" of type '" "char const *""'"); + } + arg1 = (char *)(buf1); + result = (int)rtnl_str2scope((char const *)arg1); + resultobj = SWIG_From_int((int)(result)); + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_alloc(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_alloc",0,0,0)) SWIG_fail; + result = (struct rtnl_link *)rtnl_link_alloc(); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_link, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache *arg1 = (struct nl_cache *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + struct rtnl_link *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_get",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get" "', argument " "1"" of type '" "struct nl_cache *""'"); + } + arg1 = (struct nl_cache *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_get" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + result = (struct rtnl_link *)rtnl_link_get(arg1,arg2); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_link, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_get_by_name(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache *arg1 = (struct nl_cache *) 0 ; + char *arg2 = (char *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + PyObject *swig_obj[2] ; + struct rtnl_link *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_get_by_name",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_by_name" "', argument " "1"" of type '" "struct nl_cache *""'"); + } + arg1 = (struct nl_cache *)(argp1); + res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_get_by_name" "', argument " "2"" of type '" "char const *""'"); + } + arg2 = (char *)(buf2); + result = (struct rtnl_link *)rtnl_link_get_by_name(arg1,(char const *)arg2); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return resultobj; +fail: + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_build_add_request(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + int arg2 ; + struct nl_msg **arg3 = (struct nl_msg **) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + void *argp3 = 0 ; + int res3 = 0 ; + PyObject *swig_obj[3] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_build_add_request",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_build_add_request" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_build_add_request" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + res3 = SWIG_ConvertPtr(swig_obj[2], &argp3,SWIGTYPE_p_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "rtnl_link_build_add_request" "', argument " "3"" of type '" "struct nl_msg **""'"); + } + arg3 = (struct nl_msg **)(argp3); + result = (int)rtnl_link_build_add_request(arg1,arg2,arg3); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_add(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_sock *arg1 = (struct nl_sock *) 0 ; + struct rtnl_link *arg2 = (struct rtnl_link *) 0 ; + int arg3 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + int val3 ; + int ecode3 = 0 ; + PyObject *swig_obj[3] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_add",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_add" "', argument " "1"" of type '" "struct nl_sock *""'"); + } + arg1 = (struct nl_sock *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_add" "', argument " "2"" of type '" "struct rtnl_link *""'"); + } + arg2 = (struct rtnl_link *)(argp2); + ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_link_add" "', argument " "3"" of type '" "int""'"); + } + arg3 = (int)(val3); + result = (int)rtnl_link_add(arg1,arg2,arg3); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_build_change_request(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + struct rtnl_link *arg2 = (struct rtnl_link *) 0 ; + int arg3 ; + struct nl_msg **arg4 = (struct nl_msg **) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + int val3 ; + int ecode3 = 0 ; + void *argp4 = 0 ; + int res4 = 0 ; + PyObject *swig_obj[4] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_build_change_request",4,4,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_build_change_request" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_build_change_request" "', argument " "2"" of type '" "struct rtnl_link *""'"); + } + arg2 = (struct rtnl_link *)(argp2); + ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_link_build_change_request" "', argument " "3"" of type '" "int""'"); + } + arg3 = (int)(val3); + res4 = SWIG_ConvertPtr(swig_obj[3], &argp4,SWIGTYPE_p_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res4)) { + SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "rtnl_link_build_change_request" "', argument " "4"" of type '" "struct nl_msg **""'"); + } + arg4 = (struct nl_msg **)(argp4); + result = (int)rtnl_link_build_change_request(arg1,arg2,arg3,arg4); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_change(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_sock *arg1 = (struct nl_sock *) 0 ; + struct rtnl_link *arg2 = (struct rtnl_link *) 0 ; + struct rtnl_link *arg3 = (struct rtnl_link *) 0 ; + int arg4 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + void *argp3 = 0 ; + int res3 = 0 ; + int val4 ; + int ecode4 = 0 ; + PyObject *swig_obj[4] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_change",4,4,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_change" "', argument " "1"" of type '" "struct nl_sock *""'"); + } + arg1 = (struct nl_sock *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_change" "', argument " "2"" of type '" "struct rtnl_link *""'"); + } + arg2 = (struct rtnl_link *)(argp2); + res3 = SWIG_ConvertPtr(swig_obj[2], &argp3,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "rtnl_link_change" "', argument " "3"" of type '" "struct rtnl_link *""'"); + } + arg3 = (struct rtnl_link *)(argp3); + ecode4 = SWIG_AsVal_int(swig_obj[3], &val4); + if (!SWIG_IsOK(ecode4)) { + SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "rtnl_link_change" "', argument " "4"" of type '" "int""'"); + } + arg4 = (int)(val4); + result = (int)rtnl_link_change(arg1,arg2,arg3,arg4); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_build_delete_request(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + struct nl_msg **arg2 = (struct nl_msg **) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_build_delete_request",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_build_delete_request" "', argument " "1"" of type '" "struct rtnl_link const *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_build_delete_request" "', argument " "2"" of type '" "struct nl_msg **""'"); + } + arg2 = (struct nl_msg **)(argp2); + result = (int)rtnl_link_build_delete_request((struct rtnl_link const *)arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_delete(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_sock *arg1 = (struct nl_sock *) 0 ; + struct rtnl_link *arg2 = (struct rtnl_link *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_delete",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_delete" "', argument " "1"" of type '" "struct nl_sock *""'"); + } + arg1 = (struct nl_sock *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_delete" "', argument " "2"" of type '" "struct rtnl_link const *""'"); + } + arg2 = (struct rtnl_link *)(argp2); + result = (int)rtnl_link_delete(arg1,(struct rtnl_link const *)arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_build_get_request(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + int arg1 ; + char *arg2 = (char *) 0 ; + struct nl_msg **arg3 = (struct nl_msg **) 0 ; + int val1 ; + int ecode1 = 0 ; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + void *argp3 = 0 ; + int res3 = 0 ; + PyObject *swig_obj[3] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_build_get_request",3,3,swig_obj)) SWIG_fail; + ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rtnl_link_build_get_request" "', argument " "1"" of type '" "int""'"); + } + arg1 = (int)(val1); + res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_build_get_request" "', argument " "2"" of type '" "char const *""'"); + } + arg2 = (char *)(buf2); + res3 = SWIG_ConvertPtr(swig_obj[2], &argp3,SWIGTYPE_p_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "rtnl_link_build_get_request" "', argument " "3"" of type '" "struct nl_msg **""'"); + } + arg3 = (struct nl_msg **)(argp3); + result = (int)rtnl_link_build_get_request(arg1,(char const *)arg2,arg3); + resultobj = SWIG_From_int((int)(result)); + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return resultobj; +fail: + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_stat2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + int arg1 ; + char *arg2 = (char *) 0 ; + size_t arg3 ; + int val1 ; + int ecode1 = 0 ; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + size_t val3 ; + int ecode3 = 0 ; + PyObject *swig_obj[3] ; + char *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_stat2str",3,3,swig_obj)) SWIG_fail; + ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rtnl_link_stat2str" "', argument " "1"" of type '" "int""'"); + } + arg1 = (int)(val1); + res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_stat2str" "', argument " "2"" of type '" "char *""'"); + } + arg2 = (char *)(buf2); + ecode3 = SWIG_AsVal_size_t(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_link_stat2str" "', argument " "3"" of type '" "size_t""'"); + } + arg3 = (size_t)(val3); + result = (char *)rtnl_link_stat2str(arg1,arg2,arg3); + resultobj = SWIG_FromCharPtr((const char *)result); + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return resultobj; +fail: + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_str2stat(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + char *arg1 = (char *) 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_str2stat" "', argument " "1"" of type '" "char const *""'"); + } + arg1 = (char *)(buf1); + result = (int)rtnl_link_str2stat((char const *)arg1); + resultobj = SWIG_From_int((int)(result)); + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_flags2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + int arg1 ; + char *arg2 = (char *) 0 ; + size_t arg3 ; + int val1 ; + int ecode1 = 0 ; + int res2 ; + size_t size2 ; + char *buff2 = 0 ; + PyObject *swig_obj[2] ; + char *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_flags2str",2,2,swig_obj)) SWIG_fail; + ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rtnl_link_flags2str" "', argument " "1"" of type '" "int""'"); + } + arg1 = (int)(val1); + res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_flags2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); + } + buff2= (char *)malloc((size2+1)*sizeof(char)); + arg3 = (size_t)(size2); + arg2 = (char *)(buff2); + result = (char *)rtnl_link_flags2str(arg1,arg2,arg3); + resultobj = SWIG_FromCharPtr((const char *)result); + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); + if (buff2) free((char*)buff2); + return resultobj; +fail: + if (buff2) free((char*)buff2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_str2flags(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + char *arg1 = (char *) 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_str2flags" "', argument " "1"" of type '" "char const *""'"); + } + arg1 = (char *)(buf1); + result = (int)rtnl_link_str2flags((char const *)arg1); + resultobj = SWIG_From_int((int)(result)); + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_operstate2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + uint8_t arg1 ; + char *arg2 = (char *) 0 ; + size_t arg3 ; + unsigned char val1 ; + int ecode1 = 0 ; + int res2 ; + size_t size2 ; + char *buff2 = 0 ; + PyObject *swig_obj[2] ; + char *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_operstate2str",2,2,swig_obj)) SWIG_fail; + ecode1 = SWIG_AsVal_unsigned_SS_char(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rtnl_link_operstate2str" "', argument " "1"" of type '" "uint8_t""'"); + } + arg1 = (uint8_t)(val1); + res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_operstate2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); + } + buff2= (char *)malloc((size2+1)*sizeof(char)); + arg3 = (size_t)(size2); + arg2 = (char *)(buff2); + result = (char *)rtnl_link_operstate2str(arg1,arg2,arg3); + resultobj = SWIG_FromCharPtr((const char *)result); + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); + if (buff2) free((char*)buff2); + return resultobj; +fail: + if (buff2) free((char*)buff2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_str2operstate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + char *arg1 = (char *) 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_str2operstate" "', argument " "1"" of type '" "char const *""'"); + } + arg1 = (char *)(buf1); + result = (int)rtnl_link_str2operstate((char const *)arg1); + resultobj = SWIG_From_int((int)(result)); + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_mode2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + uint8_t arg1 ; + char *arg2 = (char *) 0 ; + size_t arg3 ; + unsigned char val1 ; + int ecode1 = 0 ; + int res2 ; + size_t size2 ; + char *buff2 = 0 ; + PyObject *swig_obj[2] ; + char *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_mode2str",2,2,swig_obj)) SWIG_fail; + ecode1 = SWIG_AsVal_unsigned_SS_char(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rtnl_link_mode2str" "', argument " "1"" of type '" "uint8_t""'"); + } + arg1 = (uint8_t)(val1); + res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_mode2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); + } + buff2= (char *)malloc((size2+1)*sizeof(char)); + arg3 = (size_t)(size2); + arg2 = (char *)(buff2); + result = (char *)rtnl_link_mode2str(arg1,arg2,arg3); + resultobj = SWIG_FromCharPtr((const char *)result); + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); + if (buff2) free((char*)buff2); + return resultobj; +fail: + if (buff2) free((char*)buff2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_str2mode(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + char *arg1 = (char *) 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_str2mode" "', argument " "1"" of type '" "char const *""'"); + } + arg1 = (char *)(buf1); + result = (int)rtnl_link_str2mode((char const *)arg1); + resultobj = SWIG_From_int((int)(result)); + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_set_qdisc(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + char *arg2 = (char *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_qdisc",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_qdisc" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_set_qdisc" "', argument " "2"" of type '" "char const *""'"); + } + arg2 = (char *)(buf2); + rtnl_link_set_qdisc(arg1,(char const *)arg2); + resultobj = SWIG_Py_Void(); + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return resultobj; +fail: + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_get_qdisc(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + char *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_qdisc" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + result = (char *)rtnl_link_get_qdisc(arg1); + resultobj = SWIG_FromCharPtr((const char *)result); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_set_name(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + char *arg2 = (char *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_name",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_name" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_set_name" "', argument " "2"" of type '" "char const *""'"); + } + arg2 = (char *)(buf2); + rtnl_link_set_name(arg1,(char const *)arg2); + resultobj = SWIG_Py_Void(); + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return resultobj; +fail: + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_get_name(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + char *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_name" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + result = (char *)rtnl_link_get_name(arg1); + resultobj = SWIG_FromCharPtr((const char *)result); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_set_flags(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + unsigned int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_flags",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_flags" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_set_flags" "', argument " "2"" of type '" "unsigned int""'"); + } + arg2 = (unsigned int)(val2); + rtnl_link_set_flags(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_unset_flags(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + unsigned int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_unset_flags",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_unset_flags" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_unset_flags" "', argument " "2"" of type '" "unsigned int""'"); + } + arg2 = (unsigned int)(val2); + rtnl_link_unset_flags(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_get_flags(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + unsigned int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_flags" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + result = (unsigned int)rtnl_link_get_flags(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_set_mtu(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + unsigned int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_mtu",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_mtu" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_set_mtu" "', argument " "2"" of type '" "unsigned int""'"); + } + arg2 = (unsigned int)(val2); + rtnl_link_set_mtu(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_get_mtu(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + unsigned int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_mtu" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + result = (unsigned int)rtnl_link_get_mtu(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_set_txqlen(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + unsigned int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_txqlen",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_txqlen" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_set_txqlen" "', argument " "2"" of type '" "unsigned int""'"); + } + arg2 = (unsigned int)(val2); + rtnl_link_set_txqlen(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_get_txqlen(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + unsigned int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_txqlen" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + result = (unsigned int)rtnl_link_get_txqlen(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_set_weight(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + unsigned int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_weight",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_weight" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_set_weight" "', argument " "2"" of type '" "unsigned int""'"); + } + arg2 = (unsigned int)(val2); + rtnl_link_set_weight(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_get_weight(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + unsigned int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_weight" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + result = (unsigned int)rtnl_link_get_weight(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_set_ifindex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_ifindex",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_ifindex" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_set_ifindex" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + rtnl_link_set_ifindex(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_get_ifindex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_ifindex" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + result = (int)rtnl_link_get_ifindex(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_set_family(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_family",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_family" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_set_family" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + rtnl_link_set_family(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_get_family(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_family" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + result = (int)rtnl_link_get_family(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_set_arptype(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + unsigned int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_arptype",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_arptype" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_set_arptype" "', argument " "2"" of type '" "unsigned int""'"); + } + arg2 = (unsigned int)(val2); + rtnl_link_set_arptype(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_get_arptype(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + unsigned int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_arptype" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + result = (unsigned int)rtnl_link_get_arptype(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_set_addr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + struct nl_addr *arg2 = (struct nl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_addr",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_addr" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_set_addr" "', argument " "2"" of type '" "struct nl_addr *""'"); + } + arg2 = (struct nl_addr *)(argp2); + rtnl_link_set_addr(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_get_addr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_addr *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_addr" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + result = (struct nl_addr *)rtnl_link_get_addr(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_addr, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_set_broadcast(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + struct nl_addr *arg2 = (struct nl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_broadcast",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_broadcast" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_set_broadcast" "', argument " "2"" of type '" "struct nl_addr *""'"); + } + arg2 = (struct nl_addr *)(argp2); + rtnl_link_set_broadcast(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_get_broadcast(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_addr *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_broadcast" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + result = (struct nl_addr *)rtnl_link_get_broadcast(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_addr, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_set_link(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_link",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_link" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_set_link" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + rtnl_link_set_link(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_get_link(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_link" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + result = (int)rtnl_link_get_link(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_set_master(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_master",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_master" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_set_master" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + rtnl_link_set_master(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_get_master(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_master" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + result = (int)rtnl_link_get_master(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_set_operstate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + uint8_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned char val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_operstate",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_operstate" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_char(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_set_operstate" "', argument " "2"" of type '" "uint8_t""'"); + } + arg2 = (uint8_t)(val2); + rtnl_link_set_operstate(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_get_operstate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint8_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_operstate" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + result = (uint8_t)rtnl_link_get_operstate(arg1); + resultobj = SWIG_From_unsigned_SS_char((unsigned char)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_set_linkmode(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + uint8_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned char val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_linkmode",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_linkmode" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_char(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_set_linkmode" "', argument " "2"" of type '" "uint8_t""'"); + } + arg2 = (uint8_t)(val2); + rtnl_link_set_linkmode(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_get_linkmode(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint8_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_linkmode" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + result = (uint8_t)rtnl_link_get_linkmode(arg1); + resultobj = SWIG_From_unsigned_SS_char((unsigned char)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_get_ifalias(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + char *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_ifalias" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + result = (char *)rtnl_link_get_ifalias(arg1); + resultobj = SWIG_FromCharPtr((const char *)result); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_set_ifalias(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + char *arg2 = (char *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_ifalias",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_ifalias" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_set_ifalias" "', argument " "2"" of type '" "char const *""'"); + } + arg2 = (char *)(buf2); + rtnl_link_set_ifalias(arg1,(char const *)arg2); + resultobj = SWIG_Py_Void(); + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return resultobj; +fail: + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_get_num_vf(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + uint32_t *arg2 = (uint32_t *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_get_num_vf",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_num_vf" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_unsigned_int, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_get_num_vf" "', argument " "2"" of type '" "uint32_t *""'"); + } + arg2 = (uint32_t *)(argp2); + result = (int)rtnl_link_get_num_vf(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_get_stat(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + uint64_t result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_get_stat",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_stat" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_get_stat" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + result = (uint64_t)rtnl_link_get_stat(arg1,arg2); + resultobj = SWIG_From_unsigned_SS_long_SS_long((unsigned long long)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_set_stat(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + unsigned int arg2 ; + uint64_t arg3 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + unsigned long long val3 ; + int ecode3 = 0 ; + PyObject *swig_obj[3] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_stat",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_stat" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_set_stat" "', argument " "2"" of type '" "unsigned int""'"); + } + arg2 = (unsigned int)(val2); + ecode3 = SWIG_AsVal_unsigned_SS_long_SS_long(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_link_set_stat" "', argument " "3"" of type '" "uint64_t""'"); + } + arg3 = (uint64_t)(val3); + result = (int)rtnl_link_set_stat(arg1,arg2,arg3); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_set_info_type(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + char *arg2 = (char *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_info_type",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_info_type" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_set_info_type" "', argument " "2"" of type '" "char const *""'"); + } + arg2 = (char *)(buf2); + result = (int)rtnl_link_set_info_type(arg1,(char const *)arg2); + resultobj = SWIG_From_int((int)(result)); + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return resultobj; +fail: + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_get_info_type(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + char *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_info_type" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + result = (char *)rtnl_link_get_info_type(arg1); + resultobj = SWIG_FromCharPtr((const char *)result); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_vlan_map_vm_from_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct vlan_map *arg1 = (struct vlan_map *) 0 ; + uint32_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"vlan_map_vm_from_set",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_vlan_map, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "vlan_map_vm_from_set" "', argument " "1"" of type '" "struct vlan_map *""'"); + } + arg1 = (struct vlan_map *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "vlan_map_vm_from_set" "', argument " "2"" of type '" "uint32_t""'"); + } + arg2 = (uint32_t)(val2); + if (arg1) (arg1)->vm_from = arg2; + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_vlan_map_vm_from_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct vlan_map *arg1 = (struct vlan_map *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint32_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_vlan_map, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "vlan_map_vm_from_get" "', argument " "1"" of type '" "struct vlan_map *""'"); + } + arg1 = (struct vlan_map *)(argp1); + result = (uint32_t) ((arg1)->vm_from); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_vlan_map_vm_to_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct vlan_map *arg1 = (struct vlan_map *) 0 ; + uint32_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"vlan_map_vm_to_set",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_vlan_map, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "vlan_map_vm_to_set" "', argument " "1"" of type '" "struct vlan_map *""'"); + } + arg1 = (struct vlan_map *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "vlan_map_vm_to_set" "', argument " "2"" of type '" "uint32_t""'"); + } + arg2 = (uint32_t)(val2); + if (arg1) (arg1)->vm_to = arg2; + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_vlan_map_vm_to_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct vlan_map *arg1 = (struct vlan_map *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint32_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_vlan_map, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "vlan_map_vm_to_get" "', argument " "1"" of type '" "struct vlan_map *""'"); + } + arg1 = (struct vlan_map *)(argp1); + result = (uint32_t) ((arg1)->vm_to); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_delete_vlan_map(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct vlan_map *arg1 = (struct vlan_map *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_vlan_map, SWIG_POINTER_DISOWN | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_vlan_map" "', argument " "1"" of type '" "struct vlan_map *""'"); + } + arg1 = (struct vlan_map *)(argp1); + free((char *) arg1); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *vlan_map_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *obj; + if (!SWIG_Python_UnpackTuple(args,(char*)"swigregister", 1, 1,&obj)) return NULL; + SWIG_TypeNewClientData(SWIGTYPE_p_vlan_map, SWIG_NewClientData(obj)); + return SWIG_Py_Void(); +} + +SWIGINTERN PyObject *_wrap_rtnl_link_vlan_flags2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + int arg1 ; + char *arg2 = (char *) 0 ; + size_t arg3 ; + int val1 ; + int ecode1 = 0 ; + int res2 ; + size_t size2 ; + char *buff2 = 0 ; + PyObject *swig_obj[2] ; + char *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_vlan_flags2str",2,2,swig_obj)) SWIG_fail; + ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rtnl_link_vlan_flags2str" "', argument " "1"" of type '" "int""'"); + } + arg1 = (int)(val1); + res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_vlan_flags2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); + } + buff2= (char *)malloc((size2+1)*sizeof(char)); + arg3 = (size_t)(size2); + arg2 = (char *)(buff2); + result = (char *)rtnl_link_vlan_flags2str(arg1,arg2,arg3); + resultobj = SWIG_FromCharPtr((const char *)result); + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); + if (buff2) free((char*)buff2); + return resultobj; +fail: + if (buff2) free((char*)buff2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_vlan_str2flags(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + char *arg1 = (char *) 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_vlan_str2flags" "', argument " "1"" of type '" "char const *""'"); + } + arg1 = (char *)(buf1); + result = (int)rtnl_link_vlan_str2flags((char const *)arg1); + resultobj = SWIG_From_int((int)(result)); + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_vlan_set_id(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_vlan_set_id",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_vlan_set_id" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_vlan_set_id" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + result = (int)rtnl_link_vlan_set_id(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_vlan_get_id(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_vlan_get_id" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + result = (int)rtnl_link_vlan_get_id(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_vlan_set_flags(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + unsigned int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_vlan_set_flags",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_vlan_set_flags" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_vlan_set_flags" "', argument " "2"" of type '" "unsigned int""'"); + } + arg2 = (unsigned int)(val2); + result = (int)rtnl_link_vlan_set_flags(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_vlan_unset_flags(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + unsigned int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_vlan_unset_flags",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_vlan_unset_flags" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_vlan_unset_flags" "', argument " "2"" of type '" "unsigned int""'"); + } + arg2 = (unsigned int)(val2); + result = (int)rtnl_link_vlan_unset_flags(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_vlan_get_flags(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + unsigned int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_vlan_get_flags" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + result = (unsigned int)rtnl_link_vlan_get_flags(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_vlan_set_ingress_map(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + int arg2 ; + uint32_t arg3 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + unsigned int val3 ; + int ecode3 = 0 ; + PyObject *swig_obj[3] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_vlan_set_ingress_map",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_vlan_set_ingress_map" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_vlan_set_ingress_map" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + ecode3 = SWIG_AsVal_unsigned_SS_int(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_link_vlan_set_ingress_map" "', argument " "3"" of type '" "uint32_t""'"); + } + arg3 = (uint32_t)(val3); + result = (int)rtnl_link_vlan_set_ingress_map(arg1,arg2,arg3); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_vlan_get_ingress_map(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint32_t *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_vlan_get_ingress_map" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + result = (uint32_t *)rtnl_link_vlan_get_ingress_map(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_unsigned_int, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_vlan_set_egress_map(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + uint32_t arg2 ; + int arg3 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + int val3 ; + int ecode3 = 0 ; + PyObject *swig_obj[3] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_vlan_set_egress_map",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_vlan_set_egress_map" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_vlan_set_egress_map" "', argument " "2"" of type '" "uint32_t""'"); + } + arg2 = (uint32_t)(val2); + ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_link_vlan_set_egress_map" "', argument " "3"" of type '" "int""'"); + } + arg3 = (int)(val3); + result = (int)rtnl_link_vlan_set_egress_map(arg1,arg2,arg3); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_vlan_get_egress_map(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + int *arg2 = (int *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + struct vlan_map *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_vlan_get_egress_map",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_vlan_get_egress_map" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_int, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_vlan_get_egress_map" "', argument " "2"" of type '" "int *""'"); + } + arg2 = (int *)(argp2); + result = (struct vlan_map *)rtnl_link_vlan_get_egress_map(arg1,arg2); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_vlan_map, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_inet_devconf2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + int arg1 ; + char *arg2 = (char *) 0 ; + size_t arg3 ; + int val1 ; + int ecode1 = 0 ; + int res2 ; + size_t size2 ; + char *buff2 = 0 ; + PyObject *swig_obj[2] ; + char *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_inet_devconf2str",2,2,swig_obj)) SWIG_fail; + ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rtnl_link_inet_devconf2str" "', argument " "1"" of type '" "int""'"); + } + arg1 = (int)(val1); + res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_inet_devconf2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); + } + buff2= (char *)malloc((size2+1)*sizeof(char)); + arg3 = (size_t)(size2); + arg2 = (char *)(buff2); + result = (char *)rtnl_link_inet_devconf2str(arg1,arg2,arg3); + resultobj = SWIG_FromCharPtr((const char *)result); + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); + if (buff2) free((char*)buff2); + return resultobj; +fail: + if (buff2) free((char*)buff2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_inet_str2devconf(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + char *arg1 = (char *) 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + PyObject *swig_obj[1] ; + unsigned int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_inet_str2devconf" "', argument " "1"" of type '" "char const *""'"); + } + arg1 = (char *)(buf1); + result = (unsigned int)rtnl_link_inet_str2devconf((char const *)arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_link_inet_set_conf(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; + unsigned int arg2 ; + uint32_t arg3 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + unsigned int val3 ; + int ecode3 = 0 ; + PyObject *swig_obj[3] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_link_inet_set_conf",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_inet_set_conf" "', argument " "1"" of type '" "struct rtnl_link *""'"); + } + arg1 = (struct rtnl_link *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_inet_set_conf" "', argument " "2"" of type '" "unsigned int""'"); + } + arg2 = (unsigned int)(val2); + ecode3 = SWIG_AsVal_unsigned_SS_int(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_link_inet_set_conf" "', argument " "3"" of type '" "uint32_t""'"); + } + arg3 = (uint32_t)(val3); + result = (int)rtnl_link_inet_set_conf(arg1,arg2,arg3); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_tc_str2handle(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + char *arg1 = (char *) 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + PyObject *swig_obj[1] ; + uint32_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "tc_str2handle" "', argument " "1"" of type '" "char const *""'"); + } + arg1 = (char *)(buf1); + result = (uint32_t)tc_str2handle((char const *)arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_tc_set_ifindex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_set_ifindex",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_set_ifindex" "', argument " "1"" of type '" "struct rtnl_tc *""'"); + } + arg1 = (struct rtnl_tc *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_tc_set_ifindex" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + rtnl_tc_set_ifindex(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_tc_get_ifindex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_get_ifindex" "', argument " "1"" of type '" "struct rtnl_tc *""'"); + } + arg1 = (struct rtnl_tc *)(argp1); + result = (int)rtnl_tc_get_ifindex(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_tc_set_link(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; + struct rtnl_link *arg2 = (struct rtnl_link *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_set_link",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_set_link" "', argument " "1"" of type '" "struct rtnl_tc *""'"); + } + arg1 = (struct rtnl_tc *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_tc_set_link" "', argument " "2"" of type '" "struct rtnl_link *""'"); + } + arg2 = (struct rtnl_link *)(argp2); + rtnl_tc_set_link(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_tc_get_link(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct rtnl_link *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_get_link" "', argument " "1"" of type '" "struct rtnl_tc *""'"); + } + arg1 = (struct rtnl_tc *)(argp1); + result = (struct rtnl_link *)rtnl_tc_get_link(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_link, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_tc_set_mtu(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; + uint32_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_set_mtu",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_set_mtu" "', argument " "1"" of type '" "struct rtnl_tc *""'"); + } + arg1 = (struct rtnl_tc *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_tc_set_mtu" "', argument " "2"" of type '" "uint32_t""'"); + } + arg2 = (uint32_t)(val2); + rtnl_tc_set_mtu(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_tc_get_mtu(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint32_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_get_mtu" "', argument " "1"" of type '" "struct rtnl_tc *""'"); + } + arg1 = (struct rtnl_tc *)(argp1); + result = (uint32_t)rtnl_tc_get_mtu(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_tc_set_mpu(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; + uint32_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_set_mpu",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_set_mpu" "', argument " "1"" of type '" "struct rtnl_tc *""'"); + } + arg1 = (struct rtnl_tc *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_tc_set_mpu" "', argument " "2"" of type '" "uint32_t""'"); + } + arg2 = (uint32_t)(val2); + rtnl_tc_set_mpu(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_tc_get_mpu(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint32_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_get_mpu" "', argument " "1"" of type '" "struct rtnl_tc *""'"); + } + arg1 = (struct rtnl_tc *)(argp1); + result = (uint32_t)rtnl_tc_get_mpu(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_tc_set_overhead(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; + uint32_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_set_overhead",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_set_overhead" "', argument " "1"" of type '" "struct rtnl_tc *""'"); + } + arg1 = (struct rtnl_tc *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_tc_set_overhead" "', argument " "2"" of type '" "uint32_t""'"); + } + arg2 = (uint32_t)(val2); + rtnl_tc_set_overhead(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_tc_get_overhead(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint32_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_get_overhead" "', argument " "1"" of type '" "struct rtnl_tc *""'"); + } + arg1 = (struct rtnl_tc *)(argp1); + result = (uint32_t)rtnl_tc_get_overhead(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_tc_set_linktype(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; + uint32_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_set_linktype",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_set_linktype" "', argument " "1"" of type '" "struct rtnl_tc *""'"); + } + arg1 = (struct rtnl_tc *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_tc_set_linktype" "', argument " "2"" of type '" "uint32_t""'"); + } + arg2 = (uint32_t)(val2); + rtnl_tc_set_linktype(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_tc_get_linktype(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint32_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_get_linktype" "', argument " "1"" of type '" "struct rtnl_tc *""'"); + } + arg1 = (struct rtnl_tc *)(argp1); + result = (uint32_t)rtnl_tc_get_linktype(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_tc_set_handle(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; + uint32_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_set_handle",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_set_handle" "', argument " "1"" of type '" "struct rtnl_tc *""'"); + } + arg1 = (struct rtnl_tc *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_tc_set_handle" "', argument " "2"" of type '" "uint32_t""'"); + } + arg2 = (uint32_t)(val2); + rtnl_tc_set_handle(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_tc_get_handle(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint32_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_get_handle" "', argument " "1"" of type '" "struct rtnl_tc *""'"); + } + arg1 = (struct rtnl_tc *)(argp1); + result = (uint32_t)rtnl_tc_get_handle(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_tc_set_parent(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; + uint32_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_set_parent",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_set_parent" "', argument " "1"" of type '" "struct rtnl_tc *""'"); + } + arg1 = (struct rtnl_tc *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_tc_set_parent" "', argument " "2"" of type '" "uint32_t""'"); + } + arg2 = (uint32_t)(val2); + rtnl_tc_set_parent(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_tc_get_parent(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint32_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_get_parent" "', argument " "1"" of type '" "struct rtnl_tc *""'"); + } + arg1 = (struct rtnl_tc *)(argp1); + result = (uint32_t)rtnl_tc_get_parent(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_tc_set_kind(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; + char *arg2 = (char *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_set_kind",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_set_kind" "', argument " "1"" of type '" "struct rtnl_tc *""'"); + } + arg1 = (struct rtnl_tc *)(argp1); + res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_tc_set_kind" "', argument " "2"" of type '" "char const *""'"); + } + arg2 = (char *)(buf2); + result = (int)rtnl_tc_set_kind(arg1,(char const *)arg2); + resultobj = SWIG_From_int((int)(result)); + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return resultobj; +fail: + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_tc_get_kind(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + char *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_get_kind" "', argument " "1"" of type '" "struct rtnl_tc *""'"); + } + arg1 = (struct rtnl_tc *)(argp1); + result = (char *)rtnl_tc_get_kind(arg1); + resultobj = SWIG_FromCharPtr((const char *)result); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_tc_get_stat(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; + enum rtnl_tc_stat arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + uint64_t result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_get_stat",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_get_stat" "', argument " "1"" of type '" "struct rtnl_tc *""'"); + } + arg1 = (struct rtnl_tc *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_tc_get_stat" "', argument " "2"" of type '" "enum rtnl_tc_stat""'"); + } + arg2 = (enum rtnl_tc_stat)(val2); + result = (uint64_t)rtnl_tc_get_stat(arg1,arg2); + resultobj = SWIG_From_unsigned_SS_long_SS_long((unsigned long long)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_tc_calc_txtime(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + int arg1 ; + int arg2 ; + int val1 ; + int ecode1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_calc_txtime",2,2,swig_obj)) SWIG_fail; + ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rtnl_tc_calc_txtime" "', argument " "1"" of type '" "int""'"); + } + arg1 = (int)(val1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_tc_calc_txtime" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + result = (int)rtnl_tc_calc_txtime(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_tc_calc_bufsize(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + int arg1 ; + int arg2 ; + int val1 ; + int ecode1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_calc_bufsize",2,2,swig_obj)) SWIG_fail; + ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rtnl_tc_calc_bufsize" "', argument " "1"" of type '" "int""'"); + } + arg1 = (int)(val1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_tc_calc_bufsize" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + result = (int)rtnl_tc_calc_bufsize(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_tc_calc_cell_log(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + int arg1 ; + int val1 ; + int ecode1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rtnl_tc_calc_cell_log" "', argument " "1"" of type '" "int""'"); + } + arg1 = (int)(val1); + result = (int)rtnl_tc_calc_cell_log(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_tc_read_classid_file(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_read_classid_file",0,0,0)) SWIG_fail; + result = (int)rtnl_tc_read_classid_file(); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_tc_handle2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + uint32_t arg1 ; + char *arg2 = (char *) 0 ; + size_t arg3 ; + unsigned int val1 ; + int ecode1 = 0 ; + int res2 ; + size_t size2 ; + char *buff2 = 0 ; + PyObject *swig_obj[2] ; + char *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_handle2str",2,2,swig_obj)) SWIG_fail; + ecode1 = SWIG_AsVal_unsigned_SS_int(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rtnl_tc_handle2str" "', argument " "1"" of type '" "uint32_t""'"); + } + arg1 = (uint32_t)(val1); + res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_tc_handle2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); + } + buff2= (char *)malloc((size2+1)*sizeof(char)); + arg3 = (size_t)(size2); + arg2 = (char *)(buff2); + result = (char *)rtnl_tc_handle2str(arg1,arg2,arg3); + resultobj = SWIG_FromCharPtr((const char *)result); + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); + if (buff2) free((char*)buff2); + return resultobj; +fail: + if (buff2) free((char*)buff2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_classid_generate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + char *arg1 = (char *) 0 ; + uint32_t *arg2 = (uint32_t *) 0 ; + uint32_t arg3 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + unsigned int val3 ; + int ecode3 = 0 ; + PyObject *swig_obj[3] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_classid_generate",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_classid_generate" "', argument " "1"" of type '" "char const *""'"); + } + arg1 = (char *)(buf1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_unsigned_int, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_classid_generate" "', argument " "2"" of type '" "uint32_t *""'"); + } + arg2 = (uint32_t *)(argp2); + ecode3 = SWIG_AsVal_unsigned_SS_int(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_classid_generate" "', argument " "3"" of type '" "uint32_t""'"); + } + arg3 = (uint32_t)(val3); + result = (int)rtnl_classid_generate((char const *)arg1,arg2,arg3); + resultobj = SWIG_From_int((int)(result)); + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_qdisc2obj(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_qdisc *arg1 = (struct rtnl_qdisc *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_object *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "qdisc2obj" "', argument " "1"" of type '" "struct rtnl_qdisc *""'"); + } + arg1 = (struct rtnl_qdisc *)(argp1); + result = (struct nl_object *)qdisc2obj(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_obj2qdisc(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_object *arg1 = (struct nl_object *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct rtnl_qdisc *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "obj2qdisc" "', argument " "1"" of type '" "struct nl_object *""'"); + } + arg1 = (struct nl_object *)(argp1); + result = (struct rtnl_qdisc *)obj2qdisc(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_class2obj(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_object *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "class2obj" "', argument " "1"" of type '" "struct rtnl_class *""'"); + } + arg1 = (struct rtnl_class *)(argp1); + result = (struct nl_object *)class2obj(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_obj2class(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_object *arg1 = (struct nl_object *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct rtnl_class *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "obj2class" "', argument " "1"" of type '" "struct nl_object *""'"); + } + arg1 = (struct nl_object *)(argp1); + result = (struct rtnl_class *)obj2class(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_class, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_cls2obj(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_cls *arg1 = (struct rtnl_cls *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_object *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_cls, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "cls2obj" "', argument " "1"" of type '" "struct rtnl_cls *""'"); + } + arg1 = (struct rtnl_cls *)(argp1); + result = (struct nl_object *)cls2obj(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_obj2cls(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_object *arg1 = (struct nl_object *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct rtnl_cls *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "obj2cls" "', argument " "1"" of type '" "struct nl_object *""'"); + } + arg1 = (struct nl_object *)(argp1); + result = (struct rtnl_cls *)obj2cls(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_cls, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_obj2tc(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_object *arg1 = (struct nl_object *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct rtnl_tc *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "obj2tc" "', argument " "1"" of type '" "struct nl_object *""'"); + } + arg1 = (struct nl_object *)(argp1); + result = (struct rtnl_tc *)obj2tc(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_tc, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_qdisc_alloc(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_qdisc *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_qdisc_alloc",0,0,0)) SWIG_fail; + result = (struct rtnl_qdisc *)rtnl_qdisc_alloc(); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_qdisc_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache *arg1 = (struct nl_cache *) 0 ; + int arg2 ; + uint32_t arg3 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + unsigned int val3 ; + int ecode3 = 0 ; + PyObject *swig_obj[3] ; + struct rtnl_qdisc *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_qdisc_get",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_qdisc_get" "', argument " "1"" of type '" "struct nl_cache *""'"); + } + arg1 = (struct nl_cache *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_qdisc_get" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + ecode3 = SWIG_AsVal_unsigned_SS_int(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_qdisc_get" "', argument " "3"" of type '" "uint32_t""'"); + } + arg3 = (uint32_t)(val3); + result = (struct rtnl_qdisc *)rtnl_qdisc_get(arg1,arg2,arg3); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_qdisc_get_by_parent(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache *arg1 = (struct nl_cache *) 0 ; + int arg2 ; + uint32_t arg3 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + unsigned int val3 ; + int ecode3 = 0 ; + PyObject *swig_obj[3] ; + struct rtnl_qdisc *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_qdisc_get_by_parent",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_qdisc_get_by_parent" "', argument " "1"" of type '" "struct nl_cache *""'"); + } + arg1 = (struct nl_cache *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_qdisc_get_by_parent" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + ecode3 = SWIG_AsVal_unsigned_SS_int(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_qdisc_get_by_parent" "', argument " "3"" of type '" "uint32_t""'"); + } + arg3 = (uint32_t)(val3); + result = (struct rtnl_qdisc *)rtnl_qdisc_get_by_parent(arg1,arg2,arg3); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_qdisc_build_add_request(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_qdisc *arg1 = (struct rtnl_qdisc *) 0 ; + int arg2 ; + struct nl_msg **arg3 = (struct nl_msg **) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + void *argp3 = 0 ; + int res3 = 0 ; + PyObject *swig_obj[3] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_qdisc_build_add_request",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_qdisc_build_add_request" "', argument " "1"" of type '" "struct rtnl_qdisc *""'"); + } + arg1 = (struct rtnl_qdisc *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_qdisc_build_add_request" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + res3 = SWIG_ConvertPtr(swig_obj[2], &argp3,SWIGTYPE_p_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "rtnl_qdisc_build_add_request" "', argument " "3"" of type '" "struct nl_msg **""'"); + } + arg3 = (struct nl_msg **)(argp3); + result = (int)rtnl_qdisc_build_add_request(arg1,arg2,arg3); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_qdisc_add(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_sock *arg1 = (struct nl_sock *) 0 ; + struct rtnl_qdisc *arg2 = (struct rtnl_qdisc *) 0 ; + int arg3 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + int val3 ; + int ecode3 = 0 ; + PyObject *swig_obj[3] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_qdisc_add",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_qdisc_add" "', argument " "1"" of type '" "struct nl_sock *""'"); + } + arg1 = (struct nl_sock *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_qdisc_add" "', argument " "2"" of type '" "struct rtnl_qdisc *""'"); + } + arg2 = (struct rtnl_qdisc *)(argp2); + ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_qdisc_add" "', argument " "3"" of type '" "int""'"); + } + arg3 = (int)(val3); + result = (int)rtnl_qdisc_add(arg1,arg2,arg3); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_qdisc_build_update_request(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_qdisc *arg1 = (struct rtnl_qdisc *) 0 ; + struct rtnl_qdisc *arg2 = (struct rtnl_qdisc *) 0 ; + int arg3 ; + struct nl_msg **arg4 = (struct nl_msg **) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + int val3 ; + int ecode3 = 0 ; + void *argp4 = 0 ; + int res4 = 0 ; + PyObject *swig_obj[4] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_qdisc_build_update_request",4,4,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_qdisc_build_update_request" "', argument " "1"" of type '" "struct rtnl_qdisc *""'"); + } + arg1 = (struct rtnl_qdisc *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_qdisc_build_update_request" "', argument " "2"" of type '" "struct rtnl_qdisc *""'"); + } + arg2 = (struct rtnl_qdisc *)(argp2); + ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_qdisc_build_update_request" "', argument " "3"" of type '" "int""'"); + } + arg3 = (int)(val3); + res4 = SWIG_ConvertPtr(swig_obj[3], &argp4,SWIGTYPE_p_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res4)) { + SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "rtnl_qdisc_build_update_request" "', argument " "4"" of type '" "struct nl_msg **""'"); + } + arg4 = (struct nl_msg **)(argp4); + result = (int)rtnl_qdisc_build_update_request(arg1,arg2,arg3,arg4); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_qdisc_update(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_sock *arg1 = (struct nl_sock *) 0 ; + struct rtnl_qdisc *arg2 = (struct rtnl_qdisc *) 0 ; + struct rtnl_qdisc *arg3 = (struct rtnl_qdisc *) 0 ; + int arg4 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + void *argp3 = 0 ; + int res3 = 0 ; + int val4 ; + int ecode4 = 0 ; + PyObject *swig_obj[4] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_qdisc_update",4,4,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_qdisc_update" "', argument " "1"" of type '" "struct nl_sock *""'"); + } + arg1 = (struct nl_sock *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_qdisc_update" "', argument " "2"" of type '" "struct rtnl_qdisc *""'"); + } + arg2 = (struct rtnl_qdisc *)(argp2); + res3 = SWIG_ConvertPtr(swig_obj[2], &argp3,SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "rtnl_qdisc_update" "', argument " "3"" of type '" "struct rtnl_qdisc *""'"); + } + arg3 = (struct rtnl_qdisc *)(argp3); + ecode4 = SWIG_AsVal_int(swig_obj[3], &val4); + if (!SWIG_IsOK(ecode4)) { + SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "rtnl_qdisc_update" "', argument " "4"" of type '" "int""'"); + } + arg4 = (int)(val4); + result = (int)rtnl_qdisc_update(arg1,arg2,arg3,arg4); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_qdisc_build_delete_request(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_qdisc *arg1 = (struct rtnl_qdisc *) 0 ; + struct nl_msg **arg2 = (struct nl_msg **) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_qdisc_build_delete_request",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_qdisc_build_delete_request" "', argument " "1"" of type '" "struct rtnl_qdisc *""'"); + } + arg1 = (struct rtnl_qdisc *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_qdisc_build_delete_request" "', argument " "2"" of type '" "struct nl_msg **""'"); + } + arg2 = (struct nl_msg **)(argp2); + result = (int)rtnl_qdisc_build_delete_request(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_qdisc_delete(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_sock *arg1 = (struct nl_sock *) 0 ; + struct rtnl_qdisc *arg2 = (struct rtnl_qdisc *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_qdisc_delete",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_qdisc_delete" "', argument " "1"" of type '" "struct nl_sock *""'"); + } + arg1 = (struct nl_sock *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_qdisc_delete" "', argument " "2"" of type '" "struct rtnl_qdisc *""'"); + } + arg2 = (struct rtnl_qdisc *)(argp2); + result = (int)rtnl_qdisc_delete(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_cls_alloc(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_cls *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_cls_alloc",0,0,0)) SWIG_fail; + result = (struct rtnl_cls *)rtnl_cls_alloc(); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_cls, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_cls_put(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_cls *arg1 = (struct rtnl_cls *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_cls, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_cls_put" "', argument " "1"" of type '" "struct rtnl_cls *""'"); + } + arg1 = (struct rtnl_cls *)(argp1); + rtnl_cls_put(arg1); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_cls_add(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_sock *arg1 = (struct nl_sock *) 0 ; + struct rtnl_cls *arg2 = (struct rtnl_cls *) 0 ; + int arg3 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + int val3 ; + int ecode3 = 0 ; + PyObject *swig_obj[3] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_cls_add",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_cls_add" "', argument " "1"" of type '" "struct nl_sock *""'"); + } + arg1 = (struct nl_sock *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_cls, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_cls_add" "', argument " "2"" of type '" "struct rtnl_cls *""'"); + } + arg2 = (struct rtnl_cls *)(argp2); + ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_cls_add" "', argument " "3"" of type '" "int""'"); + } + arg3 = (int)(val3); + result = (int)rtnl_cls_add(arg1,arg2,arg3); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_cls_delete(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_sock *arg1 = (struct nl_sock *) 0 ; + struct rtnl_cls *arg2 = (struct rtnl_cls *) 0 ; + int arg3 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + int val3 ; + int ecode3 = 0 ; + PyObject *swig_obj[3] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_cls_delete",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_cls_delete" "', argument " "1"" of type '" "struct nl_sock *""'"); + } + arg1 = (struct nl_sock *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_cls, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_cls_delete" "', argument " "2"" of type '" "struct rtnl_cls *""'"); + } + arg2 = (struct rtnl_cls *)(argp2); + ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_cls_delete" "', argument " "3"" of type '" "int""'"); + } + arg3 = (int)(val3); + result = (int)rtnl_cls_delete(arg1,arg2,arg3); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_cls_set_prio(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_cls *arg1 = (struct rtnl_cls *) 0 ; + uint16_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned short val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_cls_set_prio",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_cls, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_cls_set_prio" "', argument " "1"" of type '" "struct rtnl_cls *""'"); + } + arg1 = (struct rtnl_cls *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_short(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_cls_set_prio" "', argument " "2"" of type '" "uint16_t""'"); + } + arg2 = (uint16_t)(val2); + rtnl_cls_set_prio(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_cls_get_prio(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_cls *arg1 = (struct rtnl_cls *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint16_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_cls, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_cls_get_prio" "', argument " "1"" of type '" "struct rtnl_cls *""'"); + } + arg1 = (struct rtnl_cls *)(argp1); + result = (uint16_t)rtnl_cls_get_prio(arg1); + resultobj = SWIG_From_unsigned_SS_short((unsigned short)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_cls_set_protocol(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_cls *arg1 = (struct rtnl_cls *) 0 ; + uint16_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned short val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_cls_set_protocol",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_cls, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_cls_set_protocol" "', argument " "1"" of type '" "struct rtnl_cls *""'"); + } + arg1 = (struct rtnl_cls *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_short(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_cls_set_protocol" "', argument " "2"" of type '" "uint16_t""'"); + } + arg2 = (uint16_t)(val2); + rtnl_cls_set_protocol(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_cls_get_protocol(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_cls *arg1 = (struct rtnl_cls *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint16_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_cls, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_cls_get_protocol" "', argument " "1"" of type '" "struct rtnl_cls *""'"); + } + arg1 = (struct rtnl_cls *)(argp1); + result = (uint16_t)rtnl_cls_get_protocol(arg1); + resultobj = SWIG_From_unsigned_SS_short((unsigned short)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_htb_get_rate2quantum(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_qdisc *arg1 = (struct rtnl_qdisc *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint32_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_get_rate2quantum" "', argument " "1"" of type '" "struct rtnl_qdisc *""'"); + } + arg1 = (struct rtnl_qdisc *)(argp1); + result = (uint32_t)rtnl_htb_get_rate2quantum(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_htb_set_rate2quantum(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_qdisc *arg1 = (struct rtnl_qdisc *) 0 ; + uint32_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_htb_set_rate2quantum",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_set_rate2quantum" "', argument " "1"" of type '" "struct rtnl_qdisc *""'"); + } + arg1 = (struct rtnl_qdisc *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_htb_set_rate2quantum" "', argument " "2"" of type '" "uint32_t""'"); + } + arg2 = (uint32_t)(val2); + result = (int)rtnl_htb_set_rate2quantum(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_htb_get_defcls(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_qdisc *arg1 = (struct rtnl_qdisc *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint32_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_get_defcls" "', argument " "1"" of type '" "struct rtnl_qdisc *""'"); + } + arg1 = (struct rtnl_qdisc *)(argp1); + result = (uint32_t)rtnl_htb_get_defcls(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_htb_set_defcls(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_qdisc *arg1 = (struct rtnl_qdisc *) 0 ; + uint32_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_htb_set_defcls",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_set_defcls" "', argument " "1"" of type '" "struct rtnl_qdisc *""'"); + } + arg1 = (struct rtnl_qdisc *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_htb_set_defcls" "', argument " "2"" of type '" "uint32_t""'"); + } + arg2 = (uint32_t)(val2); + result = (int)rtnl_htb_set_defcls(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_htb_get_prio(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint32_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_get_prio" "', argument " "1"" of type '" "struct rtnl_class *""'"); + } + arg1 = (struct rtnl_class *)(argp1); + result = (uint32_t)rtnl_htb_get_prio(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_htb_set_prio(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; + uint32_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_htb_set_prio",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_set_prio" "', argument " "1"" of type '" "struct rtnl_class *""'"); + } + arg1 = (struct rtnl_class *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_htb_set_prio" "', argument " "2"" of type '" "uint32_t""'"); + } + arg2 = (uint32_t)(val2); + result = (int)rtnl_htb_set_prio(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_htb_get_rate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint32_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_get_rate" "', argument " "1"" of type '" "struct rtnl_class *""'"); + } + arg1 = (struct rtnl_class *)(argp1); + result = (uint32_t)rtnl_htb_get_rate(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_htb_set_rate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; + uint32_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_htb_set_rate",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_set_rate" "', argument " "1"" of type '" "struct rtnl_class *""'"); + } + arg1 = (struct rtnl_class *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_htb_set_rate" "', argument " "2"" of type '" "uint32_t""'"); + } + arg2 = (uint32_t)(val2); + result = (int)rtnl_htb_set_rate(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_htb_get_ceil(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint32_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_get_ceil" "', argument " "1"" of type '" "struct rtnl_class *""'"); + } + arg1 = (struct rtnl_class *)(argp1); + result = (uint32_t)rtnl_htb_get_ceil(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_htb_set_ceil(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; + uint32_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_htb_set_ceil",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_set_ceil" "', argument " "1"" of type '" "struct rtnl_class *""'"); + } + arg1 = (struct rtnl_class *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_htb_set_ceil" "', argument " "2"" of type '" "uint32_t""'"); + } + arg2 = (uint32_t)(val2); + result = (int)rtnl_htb_set_ceil(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_htb_get_rbuffer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint32_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_get_rbuffer" "', argument " "1"" of type '" "struct rtnl_class *""'"); + } + arg1 = (struct rtnl_class *)(argp1); + result = (uint32_t)rtnl_htb_get_rbuffer(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_htb_set_rbuffer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; + uint32_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_htb_set_rbuffer",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_set_rbuffer" "', argument " "1"" of type '" "struct rtnl_class *""'"); + } + arg1 = (struct rtnl_class *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_htb_set_rbuffer" "', argument " "2"" of type '" "uint32_t""'"); + } + arg2 = (uint32_t)(val2); + result = (int)rtnl_htb_set_rbuffer(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_htb_get_cbuffer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint32_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_get_cbuffer" "', argument " "1"" of type '" "struct rtnl_class *""'"); + } + arg1 = (struct rtnl_class *)(argp1); + result = (uint32_t)rtnl_htb_get_cbuffer(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_htb_set_cbuffer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; + uint32_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_htb_set_cbuffer",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_set_cbuffer" "', argument " "1"" of type '" "struct rtnl_class *""'"); + } + arg1 = (struct rtnl_class *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_htb_set_cbuffer" "', argument " "2"" of type '" "uint32_t""'"); + } + arg2 = (uint32_t)(val2); + result = (int)rtnl_htb_set_cbuffer(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_htb_get_quantum(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint32_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_get_quantum" "', argument " "1"" of type '" "struct rtnl_class *""'"); + } + arg1 = (struct rtnl_class *)(argp1); + result = (uint32_t)rtnl_htb_get_quantum(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_htb_set_quantum(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; + uint32_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_htb_set_quantum",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_set_quantum" "', argument " "1"" of type '" "struct rtnl_class *""'"); + } + arg1 = (struct rtnl_class *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_htb_set_quantum" "', argument " "2"" of type '" "uint32_t""'"); + } + arg2 = (uint32_t)(val2); + result = (int)rtnl_htb_set_quantum(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_htb_get_level(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_get_level" "', argument " "1"" of type '" "struct rtnl_class *""'"); + } + arg1 = (struct rtnl_class *)(argp1); + result = (int)rtnl_htb_get_level(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_addr2obj(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_object *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "addr2obj" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + result = (struct nl_object *)addr2obj(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_obj2addr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_object *arg1 = (struct nl_object *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct rtnl_addr *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "obj2addr" "', argument " "1"" of type '" "struct nl_object *""'"); + } + arg1 = (struct nl_object *)(argp1); + result = (struct rtnl_addr *)obj2addr(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_addr, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_alloc(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_alloc",0,0,0)) SWIG_fail; + result = (struct rtnl_addr *)rtnl_addr_alloc(); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_addr, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_cache *arg1 = (struct nl_cache *) 0 ; + int arg2 ; + struct nl_addr *arg3 = (struct nl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + void *argp3 = 0 ; + int res3 = 0 ; + PyObject *swig_obj[3] ; + struct rtnl_addr *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_get",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get" "', argument " "1"" of type '" "struct nl_cache *""'"); + } + arg1 = (struct nl_cache *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_addr_get" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + res3 = SWIG_ConvertPtr(swig_obj[2], &argp3,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "rtnl_addr_get" "', argument " "3"" of type '" "struct nl_addr *""'"); + } + arg3 = (struct nl_addr *)(argp3); + result = (struct rtnl_addr *)rtnl_addr_get(arg1,arg2,arg3); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_addr, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_build_add_request(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + int arg2 ; + struct nl_msg **arg3 = (struct nl_msg **) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + void *argp3 = 0 ; + int res3 = 0 ; + PyObject *swig_obj[3] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_build_add_request",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_build_add_request" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_addr_build_add_request" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + res3 = SWIG_ConvertPtr(swig_obj[2], &argp3,SWIGTYPE_p_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "rtnl_addr_build_add_request" "', argument " "3"" of type '" "struct nl_msg **""'"); + } + arg3 = (struct nl_msg **)(argp3); + result = (int)rtnl_addr_build_add_request(arg1,arg2,arg3); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_add(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_sock *arg1 = (struct nl_sock *) 0 ; + struct rtnl_addr *arg2 = (struct rtnl_addr *) 0 ; + int arg3 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + int val3 ; + int ecode3 = 0 ; + PyObject *swig_obj[3] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_add",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_add" "', argument " "1"" of type '" "struct nl_sock *""'"); + } + arg1 = (struct nl_sock *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_addr_add" "', argument " "2"" of type '" "struct rtnl_addr *""'"); + } + arg2 = (struct rtnl_addr *)(argp2); + ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_addr_add" "', argument " "3"" of type '" "int""'"); + } + arg3 = (int)(val3); + result = (int)rtnl_addr_add(arg1,arg2,arg3); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_build_delete_request(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + int arg2 ; + struct nl_msg **arg3 = (struct nl_msg **) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + void *argp3 = 0 ; + int res3 = 0 ; + PyObject *swig_obj[3] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_build_delete_request",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_build_delete_request" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_addr_build_delete_request" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + res3 = SWIG_ConvertPtr(swig_obj[2], &argp3,SWIGTYPE_p_p_nl_msg, 0 | 0 ); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "rtnl_addr_build_delete_request" "', argument " "3"" of type '" "struct nl_msg **""'"); + } + arg3 = (struct nl_msg **)(argp3); + result = (int)rtnl_addr_build_delete_request(arg1,arg2,arg3); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_delete(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct nl_sock *arg1 = (struct nl_sock *) 0 ; + struct rtnl_addr *arg2 = (struct rtnl_addr *) 0 ; + int arg3 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + int val3 ; + int ecode3 = 0 ; + PyObject *swig_obj[3] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_delete",3,3,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_delete" "', argument " "1"" of type '" "struct nl_sock *""'"); + } + arg1 = (struct nl_sock *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_addr_delete" "', argument " "2"" of type '" "struct rtnl_addr *""'"); + } + arg2 = (struct rtnl_addr *)(argp2); + ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_addr_delete" "', argument " "3"" of type '" "int""'"); + } + arg3 = (int)(val3); + result = (int)rtnl_addr_delete(arg1,arg2,arg3); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_flags2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + int arg1 ; + char *arg2 = (char *) 0 ; + size_t arg3 ; + int val1 ; + int ecode1 = 0 ; + int res2 ; + size_t size2 ; + char *buff2 = 0 ; + PyObject *swig_obj[2] ; + char *result = 0 ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_flags2str",2,2,swig_obj)) SWIG_fail; + ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rtnl_addr_flags2str" "', argument " "1"" of type '" "int""'"); + } + arg1 = (int)(val1); + res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_addr_flags2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); + } + buff2= (char *)malloc((size2+1)*sizeof(char)); + arg3 = (size_t)(size2); + arg2 = (char *)(buff2); + result = (char *)rtnl_addr_flags2str(arg1,arg2,arg3); + resultobj = SWIG_FromCharPtr((const char *)result); + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); + if (buff2) free((char*)buff2); + return resultobj; +fail: + if (buff2) free((char*)buff2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_str2flags(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + char *arg1 = (char *) 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_str2flags" "', argument " "1"" of type '" "char const *""'"); + } + arg1 = (char *)(buf1); + result = (int)rtnl_addr_str2flags((char const *)arg1); + resultobj = SWIG_From_int((int)(result)); + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_set_label(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + char *arg2 = (char *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_label",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_label" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_addr_set_label" "', argument " "2"" of type '" "char const *""'"); + } + arg2 = (char *)(buf2); + result = (int)rtnl_addr_set_label(arg1,(char const *)arg2); + resultobj = SWIG_From_int((int)(result)); + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return resultobj; +fail: + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_get_label(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + char *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_label" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + result = (char *)rtnl_addr_get_label(arg1); + resultobj = SWIG_FromCharPtr((const char *)result); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_set_ifindex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_ifindex",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_ifindex" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_addr_set_ifindex" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + rtnl_addr_set_ifindex(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_get_ifindex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_ifindex" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + result = (int)rtnl_addr_get_ifindex(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_set_link(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + struct rtnl_link *arg2 = (struct rtnl_link *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_link",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_link" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_link, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_addr_set_link" "', argument " "2"" of type '" "struct rtnl_link *""'"); + } + arg2 = (struct rtnl_link *)(argp2); + rtnl_addr_set_link(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_get_link(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct rtnl_link *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_link" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + result = (struct rtnl_link *)rtnl_addr_get_link(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_link, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_set_family(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_family",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_family" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_addr_set_family" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + rtnl_addr_set_family(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_get_family(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_family" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + result = (int)rtnl_addr_get_family(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_set_prefixlen(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_prefixlen",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_prefixlen" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_addr_set_prefixlen" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + rtnl_addr_set_prefixlen(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_get_prefixlen(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_prefixlen" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + result = (int)rtnl_addr_get_prefixlen(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_set_scope(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_scope",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_scope" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_addr_set_scope" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + rtnl_addr_set_scope(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_get_scope(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_scope" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + result = (int)rtnl_addr_get_scope(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_set_flags(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + unsigned int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_flags",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_flags" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_addr_set_flags" "', argument " "2"" of type '" "unsigned int""'"); + } + arg2 = (unsigned int)(val2); + rtnl_addr_set_flags(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_unset_flags(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + unsigned int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_unset_flags",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_unset_flags" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_addr_unset_flags" "', argument " "2"" of type '" "unsigned int""'"); + } + arg2 = (unsigned int)(val2); + rtnl_addr_unset_flags(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_get_flags(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + unsigned int result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_flags" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + result = (unsigned int)rtnl_addr_get_flags(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_set_local(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + struct nl_addr *arg2 = (struct nl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_local",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_local" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_addr_set_local" "', argument " "2"" of type '" "struct nl_addr *""'"); + } + arg2 = (struct nl_addr *)(argp2); + result = (int)rtnl_addr_set_local(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_get_local(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_addr *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_local" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + result = (struct nl_addr *)rtnl_addr_get_local(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_addr, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_set_peer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + struct nl_addr *arg2 = (struct nl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_peer",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_peer" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_addr_set_peer" "', argument " "2"" of type '" "struct nl_addr *""'"); + } + arg2 = (struct nl_addr *)(argp2); + result = (int)rtnl_addr_set_peer(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_get_peer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_addr *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_peer" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + result = (struct nl_addr *)rtnl_addr_get_peer(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_addr, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_set_broadcast(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + struct nl_addr *arg2 = (struct nl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_broadcast",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_broadcast" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_addr_set_broadcast" "', argument " "2"" of type '" "struct nl_addr *""'"); + } + arg2 = (struct nl_addr *)(argp2); + result = (int)rtnl_addr_set_broadcast(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_get_broadcast(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_addr *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_broadcast" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + result = (struct nl_addr *)rtnl_addr_get_broadcast(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_addr, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_set_multicast(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + struct nl_addr *arg2 = (struct nl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_multicast",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_multicast" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_addr_set_multicast" "', argument " "2"" of type '" "struct nl_addr *""'"); + } + arg2 = (struct nl_addr *)(argp2); + result = (int)rtnl_addr_set_multicast(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_get_multicast(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_addr *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_multicast" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + result = (struct nl_addr *)rtnl_addr_get_multicast(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_addr, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_set_anycast(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + struct nl_addr *arg2 = (struct nl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_anycast",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_anycast" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_addr, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_addr_set_anycast" "', argument " "2"" of type '" "struct nl_addr *""'"); + } + arg2 = (struct nl_addr *)(argp2); + result = (int)rtnl_addr_set_anycast(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_get_anycast(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + struct nl_addr *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_anycast" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + result = (struct nl_addr *)rtnl_addr_get_anycast(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_addr, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_get_valid_lifetime(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint32_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_valid_lifetime" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + result = (uint32_t)rtnl_addr_get_valid_lifetime(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_set_valid_lifetime(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + uint32_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_valid_lifetime",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_valid_lifetime" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_addr_set_valid_lifetime" "', argument " "2"" of type '" "uint32_t""'"); + } + arg2 = (uint32_t)(val2); + rtnl_addr_set_valid_lifetime(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_get_preferred_lifetime(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint32_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_preferred_lifetime" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + result = (uint32_t)rtnl_addr_get_preferred_lifetime(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_set_preferred_lifetime(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + uint32_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + unsigned int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + + if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_preferred_lifetime",2,2,swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_preferred_lifetime" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_addr_set_preferred_lifetime" "', argument " "2"" of type '" "uint32_t""'"); + } + arg2 = (uint32_t)(val2); + rtnl_addr_set_preferred_lifetime(arg1,arg2); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_get_create_time(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint32_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_create_time" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + result = (uint32_t)rtnl_addr_get_create_time(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_rtnl_addr_get_last_update_time(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + uint32_t result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_last_update_time" "', argument " "1"" of type '" "struct rtnl_addr *""'"); + } + arg1 = (struct rtnl_addr *)(argp1); + result = (uint32_t)rtnl_addr_get_last_update_time(arg1); + resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); + return resultobj; +fail: + return NULL; +} + + +static PyMethodDef SwigMethods[] = { + { (char *)"SWIG_PyInstanceMethod_New", (PyCFunction)SWIG_PyInstanceMethod_New, METH_O, NULL}, + { (char *)"link2obj", (PyCFunction)_wrap_link2obj, METH_O, NULL}, + { (char *)"obj2link", (PyCFunction)_wrap_obj2link, METH_O, NULL}, + { (char *)"get_from_kernel", _wrap_get_from_kernel, METH_VARARGS, NULL}, + { (char *)"inet_get_conf", _wrap_inet_get_conf, METH_VARARGS, NULL}, + { (char *)"rtnl_scope2str", _wrap_rtnl_scope2str, METH_VARARGS, NULL}, + { (char *)"rtnl_str2scope", (PyCFunction)_wrap_rtnl_str2scope, METH_O, NULL}, + { (char *)"rtnl_link_alloc", (PyCFunction)_wrap_rtnl_link_alloc, METH_NOARGS, NULL}, + { (char *)"rtnl_link_get", _wrap_rtnl_link_get, METH_VARARGS, NULL}, + { (char *)"rtnl_link_get_by_name", _wrap_rtnl_link_get_by_name, METH_VARARGS, NULL}, + { (char *)"rtnl_link_build_add_request", _wrap_rtnl_link_build_add_request, METH_VARARGS, NULL}, + { (char *)"rtnl_link_add", _wrap_rtnl_link_add, METH_VARARGS, NULL}, + { (char *)"rtnl_link_build_change_request", _wrap_rtnl_link_build_change_request, METH_VARARGS, NULL}, + { (char *)"rtnl_link_change", _wrap_rtnl_link_change, METH_VARARGS, NULL}, + { (char *)"rtnl_link_build_delete_request", _wrap_rtnl_link_build_delete_request, METH_VARARGS, NULL}, + { (char *)"rtnl_link_delete", _wrap_rtnl_link_delete, METH_VARARGS, NULL}, + { (char *)"rtnl_link_build_get_request", _wrap_rtnl_link_build_get_request, METH_VARARGS, NULL}, + { (char *)"rtnl_link_stat2str", _wrap_rtnl_link_stat2str, METH_VARARGS, NULL}, + { (char *)"rtnl_link_str2stat", (PyCFunction)_wrap_rtnl_link_str2stat, METH_O, NULL}, + { (char *)"rtnl_link_flags2str", _wrap_rtnl_link_flags2str, METH_VARARGS, NULL}, + { (char *)"rtnl_link_str2flags", (PyCFunction)_wrap_rtnl_link_str2flags, METH_O, NULL}, + { (char *)"rtnl_link_operstate2str", _wrap_rtnl_link_operstate2str, METH_VARARGS, NULL}, + { (char *)"rtnl_link_str2operstate", (PyCFunction)_wrap_rtnl_link_str2operstate, METH_O, NULL}, + { (char *)"rtnl_link_mode2str", _wrap_rtnl_link_mode2str, METH_VARARGS, NULL}, + { (char *)"rtnl_link_str2mode", (PyCFunction)_wrap_rtnl_link_str2mode, METH_O, NULL}, + { (char *)"rtnl_link_set_qdisc", _wrap_rtnl_link_set_qdisc, METH_VARARGS, NULL}, + { (char *)"rtnl_link_get_qdisc", (PyCFunction)_wrap_rtnl_link_get_qdisc, METH_O, NULL}, + { (char *)"rtnl_link_set_name", _wrap_rtnl_link_set_name, METH_VARARGS, NULL}, + { (char *)"rtnl_link_get_name", (PyCFunction)_wrap_rtnl_link_get_name, METH_O, NULL}, + { (char *)"rtnl_link_set_flags", _wrap_rtnl_link_set_flags, METH_VARARGS, NULL}, + { (char *)"rtnl_link_unset_flags", _wrap_rtnl_link_unset_flags, METH_VARARGS, NULL}, + { (char *)"rtnl_link_get_flags", (PyCFunction)_wrap_rtnl_link_get_flags, METH_O, NULL}, + { (char *)"rtnl_link_set_mtu", _wrap_rtnl_link_set_mtu, METH_VARARGS, NULL}, + { (char *)"rtnl_link_get_mtu", (PyCFunction)_wrap_rtnl_link_get_mtu, METH_O, NULL}, + { (char *)"rtnl_link_set_txqlen", _wrap_rtnl_link_set_txqlen, METH_VARARGS, NULL}, + { (char *)"rtnl_link_get_txqlen", (PyCFunction)_wrap_rtnl_link_get_txqlen, METH_O, NULL}, + { (char *)"rtnl_link_set_weight", _wrap_rtnl_link_set_weight, METH_VARARGS, NULL}, + { (char *)"rtnl_link_get_weight", (PyCFunction)_wrap_rtnl_link_get_weight, METH_O, NULL}, + { (char *)"rtnl_link_set_ifindex", _wrap_rtnl_link_set_ifindex, METH_VARARGS, NULL}, + { (char *)"rtnl_link_get_ifindex", (PyCFunction)_wrap_rtnl_link_get_ifindex, METH_O, NULL}, + { (char *)"rtnl_link_set_family", _wrap_rtnl_link_set_family, METH_VARARGS, NULL}, + { (char *)"rtnl_link_get_family", (PyCFunction)_wrap_rtnl_link_get_family, METH_O, NULL}, + { (char *)"rtnl_link_set_arptype", _wrap_rtnl_link_set_arptype, METH_VARARGS, NULL}, + { (char *)"rtnl_link_get_arptype", (PyCFunction)_wrap_rtnl_link_get_arptype, METH_O, NULL}, + { (char *)"rtnl_link_set_addr", _wrap_rtnl_link_set_addr, METH_VARARGS, NULL}, + { (char *)"rtnl_link_get_addr", (PyCFunction)_wrap_rtnl_link_get_addr, METH_O, NULL}, + { (char *)"rtnl_link_set_broadcast", _wrap_rtnl_link_set_broadcast, METH_VARARGS, NULL}, + { (char *)"rtnl_link_get_broadcast", (PyCFunction)_wrap_rtnl_link_get_broadcast, METH_O, NULL}, + { (char *)"rtnl_link_set_link", _wrap_rtnl_link_set_link, METH_VARARGS, NULL}, + { (char *)"rtnl_link_get_link", (PyCFunction)_wrap_rtnl_link_get_link, METH_O, NULL}, + { (char *)"rtnl_link_set_master", _wrap_rtnl_link_set_master, METH_VARARGS, NULL}, + { (char *)"rtnl_link_get_master", (PyCFunction)_wrap_rtnl_link_get_master, METH_O, NULL}, + { (char *)"rtnl_link_set_operstate", _wrap_rtnl_link_set_operstate, METH_VARARGS, NULL}, + { (char *)"rtnl_link_get_operstate", (PyCFunction)_wrap_rtnl_link_get_operstate, METH_O, NULL}, + { (char *)"rtnl_link_set_linkmode", _wrap_rtnl_link_set_linkmode, METH_VARARGS, NULL}, + { (char *)"rtnl_link_get_linkmode", (PyCFunction)_wrap_rtnl_link_get_linkmode, METH_O, NULL}, + { (char *)"rtnl_link_get_ifalias", (PyCFunction)_wrap_rtnl_link_get_ifalias, METH_O, NULL}, + { (char *)"rtnl_link_set_ifalias", _wrap_rtnl_link_set_ifalias, METH_VARARGS, NULL}, + { (char *)"rtnl_link_get_num_vf", _wrap_rtnl_link_get_num_vf, METH_VARARGS, NULL}, + { (char *)"rtnl_link_get_stat", _wrap_rtnl_link_get_stat, METH_VARARGS, NULL}, + { (char *)"rtnl_link_set_stat", _wrap_rtnl_link_set_stat, METH_VARARGS, NULL}, + { (char *)"rtnl_link_set_info_type", _wrap_rtnl_link_set_info_type, METH_VARARGS, NULL}, + { (char *)"rtnl_link_get_info_type", (PyCFunction)_wrap_rtnl_link_get_info_type, METH_O, NULL}, + { (char *)"vlan_map_vm_from_set", _wrap_vlan_map_vm_from_set, METH_VARARGS, NULL}, + { (char *)"vlan_map_vm_from_get", (PyCFunction)_wrap_vlan_map_vm_from_get, METH_O, NULL}, + { (char *)"vlan_map_vm_to_set", _wrap_vlan_map_vm_to_set, METH_VARARGS, NULL}, + { (char *)"vlan_map_vm_to_get", (PyCFunction)_wrap_vlan_map_vm_to_get, METH_O, NULL}, + { (char *)"delete_vlan_map", (PyCFunction)_wrap_delete_vlan_map, METH_O, NULL}, + { (char *)"vlan_map_swigregister", vlan_map_swigregister, METH_VARARGS, NULL}, + { (char *)"rtnl_link_vlan_flags2str", _wrap_rtnl_link_vlan_flags2str, METH_VARARGS, NULL}, + { (char *)"rtnl_link_vlan_str2flags", (PyCFunction)_wrap_rtnl_link_vlan_str2flags, METH_O, NULL}, + { (char *)"rtnl_link_vlan_set_id", _wrap_rtnl_link_vlan_set_id, METH_VARARGS, NULL}, + { (char *)"rtnl_link_vlan_get_id", (PyCFunction)_wrap_rtnl_link_vlan_get_id, METH_O, NULL}, + { (char *)"rtnl_link_vlan_set_flags", _wrap_rtnl_link_vlan_set_flags, METH_VARARGS, NULL}, + { (char *)"rtnl_link_vlan_unset_flags", _wrap_rtnl_link_vlan_unset_flags, METH_VARARGS, NULL}, + { (char *)"rtnl_link_vlan_get_flags", (PyCFunction)_wrap_rtnl_link_vlan_get_flags, METH_O, NULL}, + { (char *)"rtnl_link_vlan_set_ingress_map", _wrap_rtnl_link_vlan_set_ingress_map, METH_VARARGS, NULL}, + { (char *)"rtnl_link_vlan_get_ingress_map", (PyCFunction)_wrap_rtnl_link_vlan_get_ingress_map, METH_O, NULL}, + { (char *)"rtnl_link_vlan_set_egress_map", _wrap_rtnl_link_vlan_set_egress_map, METH_VARARGS, NULL}, + { (char *)"rtnl_link_vlan_get_egress_map", _wrap_rtnl_link_vlan_get_egress_map, METH_VARARGS, NULL}, + { (char *)"rtnl_link_inet_devconf2str", _wrap_rtnl_link_inet_devconf2str, METH_VARARGS, NULL}, + { (char *)"rtnl_link_inet_str2devconf", (PyCFunction)_wrap_rtnl_link_inet_str2devconf, METH_O, NULL}, + { (char *)"rtnl_link_inet_set_conf", _wrap_rtnl_link_inet_set_conf, METH_VARARGS, NULL}, + { (char *)"tc_str2handle", (PyCFunction)_wrap_tc_str2handle, METH_O, NULL}, + { (char *)"rtnl_tc_set_ifindex", _wrap_rtnl_tc_set_ifindex, METH_VARARGS, NULL}, + { (char *)"rtnl_tc_get_ifindex", (PyCFunction)_wrap_rtnl_tc_get_ifindex, METH_O, NULL}, + { (char *)"rtnl_tc_set_link", _wrap_rtnl_tc_set_link, METH_VARARGS, NULL}, + { (char *)"rtnl_tc_get_link", (PyCFunction)_wrap_rtnl_tc_get_link, METH_O, NULL}, + { (char *)"rtnl_tc_set_mtu", _wrap_rtnl_tc_set_mtu, METH_VARARGS, NULL}, + { (char *)"rtnl_tc_get_mtu", (PyCFunction)_wrap_rtnl_tc_get_mtu, METH_O, NULL}, + { (char *)"rtnl_tc_set_mpu", _wrap_rtnl_tc_set_mpu, METH_VARARGS, NULL}, + { (char *)"rtnl_tc_get_mpu", (PyCFunction)_wrap_rtnl_tc_get_mpu, METH_O, NULL}, + { (char *)"rtnl_tc_set_overhead", _wrap_rtnl_tc_set_overhead, METH_VARARGS, NULL}, + { (char *)"rtnl_tc_get_overhead", (PyCFunction)_wrap_rtnl_tc_get_overhead, METH_O, NULL}, + { (char *)"rtnl_tc_set_linktype", _wrap_rtnl_tc_set_linktype, METH_VARARGS, NULL}, + { (char *)"rtnl_tc_get_linktype", (PyCFunction)_wrap_rtnl_tc_get_linktype, METH_O, NULL}, + { (char *)"rtnl_tc_set_handle", _wrap_rtnl_tc_set_handle, METH_VARARGS, NULL}, + { (char *)"rtnl_tc_get_handle", (PyCFunction)_wrap_rtnl_tc_get_handle, METH_O, NULL}, + { (char *)"rtnl_tc_set_parent", _wrap_rtnl_tc_set_parent, METH_VARARGS, NULL}, + { (char *)"rtnl_tc_get_parent", (PyCFunction)_wrap_rtnl_tc_get_parent, METH_O, NULL}, + { (char *)"rtnl_tc_set_kind", _wrap_rtnl_tc_set_kind, METH_VARARGS, NULL}, + { (char *)"rtnl_tc_get_kind", (PyCFunction)_wrap_rtnl_tc_get_kind, METH_O, NULL}, + { (char *)"rtnl_tc_get_stat", _wrap_rtnl_tc_get_stat, METH_VARARGS, NULL}, + { (char *)"rtnl_tc_calc_txtime", _wrap_rtnl_tc_calc_txtime, METH_VARARGS, NULL}, + { (char *)"rtnl_tc_calc_bufsize", _wrap_rtnl_tc_calc_bufsize, METH_VARARGS, NULL}, + { (char *)"rtnl_tc_calc_cell_log", (PyCFunction)_wrap_rtnl_tc_calc_cell_log, METH_O, NULL}, + { (char *)"rtnl_tc_read_classid_file", (PyCFunction)_wrap_rtnl_tc_read_classid_file, METH_NOARGS, NULL}, + { (char *)"rtnl_tc_handle2str", _wrap_rtnl_tc_handle2str, METH_VARARGS, NULL}, + { (char *)"rtnl_classid_generate", _wrap_rtnl_classid_generate, METH_VARARGS, NULL}, + { (char *)"qdisc2obj", (PyCFunction)_wrap_qdisc2obj, METH_O, NULL}, + { (char *)"obj2qdisc", (PyCFunction)_wrap_obj2qdisc, METH_O, NULL}, + { (char *)"class2obj", (PyCFunction)_wrap_class2obj, METH_O, NULL}, + { (char *)"obj2class", (PyCFunction)_wrap_obj2class, METH_O, NULL}, + { (char *)"cls2obj", (PyCFunction)_wrap_cls2obj, METH_O, NULL}, + { (char *)"obj2cls", (PyCFunction)_wrap_obj2cls, METH_O, NULL}, + { (char *)"obj2tc", (PyCFunction)_wrap_obj2tc, METH_O, NULL}, + { (char *)"rtnl_qdisc_alloc", (PyCFunction)_wrap_rtnl_qdisc_alloc, METH_NOARGS, NULL}, + { (char *)"rtnl_qdisc_get", _wrap_rtnl_qdisc_get, METH_VARARGS, NULL}, + { (char *)"rtnl_qdisc_get_by_parent", _wrap_rtnl_qdisc_get_by_parent, METH_VARARGS, NULL}, + { (char *)"rtnl_qdisc_build_add_request", _wrap_rtnl_qdisc_build_add_request, METH_VARARGS, NULL}, + { (char *)"rtnl_qdisc_add", _wrap_rtnl_qdisc_add, METH_VARARGS, NULL}, + { (char *)"rtnl_qdisc_build_update_request", _wrap_rtnl_qdisc_build_update_request, METH_VARARGS, NULL}, + { (char *)"rtnl_qdisc_update", _wrap_rtnl_qdisc_update, METH_VARARGS, NULL}, + { (char *)"rtnl_qdisc_build_delete_request", _wrap_rtnl_qdisc_build_delete_request, METH_VARARGS, NULL}, + { (char *)"rtnl_qdisc_delete", _wrap_rtnl_qdisc_delete, METH_VARARGS, NULL}, + { (char *)"rtnl_cls_alloc", (PyCFunction)_wrap_rtnl_cls_alloc, METH_NOARGS, NULL}, + { (char *)"rtnl_cls_put", (PyCFunction)_wrap_rtnl_cls_put, METH_O, NULL}, + { (char *)"rtnl_cls_add", _wrap_rtnl_cls_add, METH_VARARGS, NULL}, + { (char *)"rtnl_cls_delete", _wrap_rtnl_cls_delete, METH_VARARGS, NULL}, + { (char *)"rtnl_cls_set_prio", _wrap_rtnl_cls_set_prio, METH_VARARGS, NULL}, + { (char *)"rtnl_cls_get_prio", (PyCFunction)_wrap_rtnl_cls_get_prio, METH_O, NULL}, + { (char *)"rtnl_cls_set_protocol", _wrap_rtnl_cls_set_protocol, METH_VARARGS, NULL}, + { (char *)"rtnl_cls_get_protocol", (PyCFunction)_wrap_rtnl_cls_get_protocol, METH_O, NULL}, + { (char *)"rtnl_htb_get_rate2quantum", (PyCFunction)_wrap_rtnl_htb_get_rate2quantum, METH_O, NULL}, + { (char *)"rtnl_htb_set_rate2quantum", _wrap_rtnl_htb_set_rate2quantum, METH_VARARGS, NULL}, + { (char *)"rtnl_htb_get_defcls", (PyCFunction)_wrap_rtnl_htb_get_defcls, METH_O, NULL}, + { (char *)"rtnl_htb_set_defcls", _wrap_rtnl_htb_set_defcls, METH_VARARGS, NULL}, + { (char *)"rtnl_htb_get_prio", (PyCFunction)_wrap_rtnl_htb_get_prio, METH_O, NULL}, + { (char *)"rtnl_htb_set_prio", _wrap_rtnl_htb_set_prio, METH_VARARGS, NULL}, + { (char *)"rtnl_htb_get_rate", (PyCFunction)_wrap_rtnl_htb_get_rate, METH_O, NULL}, + { (char *)"rtnl_htb_set_rate", _wrap_rtnl_htb_set_rate, METH_VARARGS, NULL}, + { (char *)"rtnl_htb_get_ceil", (PyCFunction)_wrap_rtnl_htb_get_ceil, METH_O, NULL}, + { (char *)"rtnl_htb_set_ceil", _wrap_rtnl_htb_set_ceil, METH_VARARGS, NULL}, + { (char *)"rtnl_htb_get_rbuffer", (PyCFunction)_wrap_rtnl_htb_get_rbuffer, METH_O, NULL}, + { (char *)"rtnl_htb_set_rbuffer", _wrap_rtnl_htb_set_rbuffer, METH_VARARGS, NULL}, + { (char *)"rtnl_htb_get_cbuffer", (PyCFunction)_wrap_rtnl_htb_get_cbuffer, METH_O, NULL}, + { (char *)"rtnl_htb_set_cbuffer", _wrap_rtnl_htb_set_cbuffer, METH_VARARGS, NULL}, + { (char *)"rtnl_htb_get_quantum", (PyCFunction)_wrap_rtnl_htb_get_quantum, METH_O, NULL}, + { (char *)"rtnl_htb_set_quantum", _wrap_rtnl_htb_set_quantum, METH_VARARGS, NULL}, + { (char *)"rtnl_htb_get_level", (PyCFunction)_wrap_rtnl_htb_get_level, METH_O, NULL}, + { (char *)"addr2obj", (PyCFunction)_wrap_addr2obj, METH_O, NULL}, + { (char *)"obj2addr", (PyCFunction)_wrap_obj2addr, METH_O, NULL}, + { (char *)"rtnl_addr_alloc", (PyCFunction)_wrap_rtnl_addr_alloc, METH_NOARGS, NULL}, + { (char *)"rtnl_addr_get", _wrap_rtnl_addr_get, METH_VARARGS, NULL}, + { (char *)"rtnl_addr_build_add_request", _wrap_rtnl_addr_build_add_request, METH_VARARGS, NULL}, + { (char *)"rtnl_addr_add", _wrap_rtnl_addr_add, METH_VARARGS, NULL}, + { (char *)"rtnl_addr_build_delete_request", _wrap_rtnl_addr_build_delete_request, METH_VARARGS, NULL}, + { (char *)"rtnl_addr_delete", _wrap_rtnl_addr_delete, METH_VARARGS, NULL}, + { (char *)"rtnl_addr_flags2str", _wrap_rtnl_addr_flags2str, METH_VARARGS, NULL}, + { (char *)"rtnl_addr_str2flags", (PyCFunction)_wrap_rtnl_addr_str2flags, METH_O, NULL}, + { (char *)"rtnl_addr_set_label", _wrap_rtnl_addr_set_label, METH_VARARGS, NULL}, + { (char *)"rtnl_addr_get_label", (PyCFunction)_wrap_rtnl_addr_get_label, METH_O, NULL}, + { (char *)"rtnl_addr_set_ifindex", _wrap_rtnl_addr_set_ifindex, METH_VARARGS, NULL}, + { (char *)"rtnl_addr_get_ifindex", (PyCFunction)_wrap_rtnl_addr_get_ifindex, METH_O, NULL}, + { (char *)"rtnl_addr_set_link", _wrap_rtnl_addr_set_link, METH_VARARGS, NULL}, + { (char *)"rtnl_addr_get_link", (PyCFunction)_wrap_rtnl_addr_get_link, METH_O, NULL}, + { (char *)"rtnl_addr_set_family", _wrap_rtnl_addr_set_family, METH_VARARGS, NULL}, + { (char *)"rtnl_addr_get_family", (PyCFunction)_wrap_rtnl_addr_get_family, METH_O, NULL}, + { (char *)"rtnl_addr_set_prefixlen", _wrap_rtnl_addr_set_prefixlen, METH_VARARGS, NULL}, + { (char *)"rtnl_addr_get_prefixlen", (PyCFunction)_wrap_rtnl_addr_get_prefixlen, METH_O, NULL}, + { (char *)"rtnl_addr_set_scope", _wrap_rtnl_addr_set_scope, METH_VARARGS, NULL}, + { (char *)"rtnl_addr_get_scope", (PyCFunction)_wrap_rtnl_addr_get_scope, METH_O, NULL}, + { (char *)"rtnl_addr_set_flags", _wrap_rtnl_addr_set_flags, METH_VARARGS, NULL}, + { (char *)"rtnl_addr_unset_flags", _wrap_rtnl_addr_unset_flags, METH_VARARGS, NULL}, + { (char *)"rtnl_addr_get_flags", (PyCFunction)_wrap_rtnl_addr_get_flags, METH_O, NULL}, + { (char *)"rtnl_addr_set_local", _wrap_rtnl_addr_set_local, METH_VARARGS, NULL}, + { (char *)"rtnl_addr_get_local", (PyCFunction)_wrap_rtnl_addr_get_local, METH_O, NULL}, + { (char *)"rtnl_addr_set_peer", _wrap_rtnl_addr_set_peer, METH_VARARGS, NULL}, + { (char *)"rtnl_addr_get_peer", (PyCFunction)_wrap_rtnl_addr_get_peer, METH_O, NULL}, + { (char *)"rtnl_addr_set_broadcast", _wrap_rtnl_addr_set_broadcast, METH_VARARGS, NULL}, + { (char *)"rtnl_addr_get_broadcast", (PyCFunction)_wrap_rtnl_addr_get_broadcast, METH_O, NULL}, + { (char *)"rtnl_addr_set_multicast", _wrap_rtnl_addr_set_multicast, METH_VARARGS, NULL}, + { (char *)"rtnl_addr_get_multicast", (PyCFunction)_wrap_rtnl_addr_get_multicast, METH_O, NULL}, + { (char *)"rtnl_addr_set_anycast", _wrap_rtnl_addr_set_anycast, METH_VARARGS, NULL}, + { (char *)"rtnl_addr_get_anycast", (PyCFunction)_wrap_rtnl_addr_get_anycast, METH_O, NULL}, + { (char *)"rtnl_addr_get_valid_lifetime", (PyCFunction)_wrap_rtnl_addr_get_valid_lifetime, METH_O, NULL}, + { (char *)"rtnl_addr_set_valid_lifetime", _wrap_rtnl_addr_set_valid_lifetime, METH_VARARGS, NULL}, + { (char *)"rtnl_addr_get_preferred_lifetime", (PyCFunction)_wrap_rtnl_addr_get_preferred_lifetime, METH_O, NULL}, + { (char *)"rtnl_addr_set_preferred_lifetime", _wrap_rtnl_addr_set_preferred_lifetime, METH_VARARGS, NULL}, + { (char *)"rtnl_addr_get_create_time", (PyCFunction)_wrap_rtnl_addr_get_create_time, METH_O, NULL}, + { (char *)"rtnl_addr_get_last_update_time", (PyCFunction)_wrap_rtnl_addr_get_last_update_time, METH_O, NULL}, + { NULL, NULL, 0, NULL } +}; + + +/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */ + +static swig_type_info _swigt__p_char = {"_p_char", "char *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_int = {"_p_int", "intptr_t *|int *|int_least32_t *|int_fast32_t *|int32_t *|int_fast16_t *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_long_long = {"_p_long_long", "int_least64_t *|int_fast64_t *|int64_t *|long long *|intmax_t *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_nl_addr = {"_p_nl_addr", "struct nl_addr *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_nl_cache = {"_p_nl_cache", "struct nl_cache *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_nl_object = {"_p_nl_object", "struct nl_object *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_nl_sock = {"_p_nl_sock", "struct nl_sock *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_p_nl_msg = {"_p_p_nl_msg", "struct nl_msg **", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_rtnl_addr = {"_p_rtnl_addr", "struct rtnl_addr *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_rtnl_class = {"_p_rtnl_class", "struct rtnl_class *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_rtnl_cls = {"_p_rtnl_cls", "struct rtnl_cls *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_rtnl_link = {"_p_rtnl_link", "struct rtnl_link *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_rtnl_qdisc = {"_p_rtnl_qdisc", "struct rtnl_qdisc *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_rtnl_tc = {"_p_rtnl_tc", "struct rtnl_tc *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_short = {"_p_short", "short *|int_least16_t *|int16_t *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_signed_char = {"_p_signed_char", "signed char *|int_least8_t *|int_fast8_t *|int8_t *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_unsigned_char = {"_p_unsigned_char", "unsigned char *|uint_least8_t *|uint_fast8_t *|uint8_t *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_unsigned_int = {"_p_unsigned_int", "uintptr_t *|uint_least32_t *|uint_fast32_t *|uint32_t *|unsigned int *|uint_fast16_t *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_unsigned_long_long = {"_p_unsigned_long_long", "uint_least64_t *|uint_fast64_t *|uint64_t *|unsigned long long *|uintmax_t *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_unsigned_short = {"_p_unsigned_short", "unsigned short *|uint_least16_t *|uint16_t *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_vlan_map = {"_p_vlan_map", "struct vlan_map *|vlan_map *", 0, 0, (void*)0, 0}; + +static swig_type_info *swig_type_initial[] = { + &_swigt__p_char, + &_swigt__p_int, + &_swigt__p_long_long, + &_swigt__p_nl_addr, + &_swigt__p_nl_cache, + &_swigt__p_nl_object, + &_swigt__p_nl_sock, + &_swigt__p_p_nl_msg, + &_swigt__p_rtnl_addr, + &_swigt__p_rtnl_class, + &_swigt__p_rtnl_cls, + &_swigt__p_rtnl_link, + &_swigt__p_rtnl_qdisc, + &_swigt__p_rtnl_tc, + &_swigt__p_short, + &_swigt__p_signed_char, + &_swigt__p_unsigned_char, + &_swigt__p_unsigned_int, + &_swigt__p_unsigned_long_long, + &_swigt__p_unsigned_short, + &_swigt__p_vlan_map, +}; + +static swig_cast_info _swigc__p_char[] = { {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_int[] = { {&_swigt__p_int, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_long_long[] = { {&_swigt__p_long_long, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_nl_addr[] = { {&_swigt__p_nl_addr, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_nl_cache[] = { {&_swigt__p_nl_cache, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_nl_object[] = { {&_swigt__p_nl_object, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_nl_sock[] = { {&_swigt__p_nl_sock, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_p_nl_msg[] = { {&_swigt__p_p_nl_msg, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_rtnl_addr[] = { {&_swigt__p_rtnl_addr, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_rtnl_class[] = { {&_swigt__p_rtnl_class, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_rtnl_cls[] = { {&_swigt__p_rtnl_cls, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_rtnl_link[] = { {&_swigt__p_rtnl_link, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_rtnl_qdisc[] = { {&_swigt__p_rtnl_qdisc, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_rtnl_tc[] = { {&_swigt__p_rtnl_tc, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_short[] = { {&_swigt__p_short, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_signed_char[] = { {&_swigt__p_signed_char, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_unsigned_char[] = { {&_swigt__p_unsigned_char, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_unsigned_int[] = { {&_swigt__p_unsigned_int, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_unsigned_long_long[] = { {&_swigt__p_unsigned_long_long, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_unsigned_short[] = { {&_swigt__p_unsigned_short, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_vlan_map[] = { {&_swigt__p_vlan_map, 0, 0, 0},{0, 0, 0, 0}}; + +static swig_cast_info *swig_cast_initial[] = { + _swigc__p_char, + _swigc__p_int, + _swigc__p_long_long, + _swigc__p_nl_addr, + _swigc__p_nl_cache, + _swigc__p_nl_object, + _swigc__p_nl_sock, + _swigc__p_p_nl_msg, + _swigc__p_rtnl_addr, + _swigc__p_rtnl_class, + _swigc__p_rtnl_cls, + _swigc__p_rtnl_link, + _swigc__p_rtnl_qdisc, + _swigc__p_rtnl_tc, + _swigc__p_short, + _swigc__p_signed_char, + _swigc__p_unsigned_char, + _swigc__p_unsigned_int, + _swigc__p_unsigned_long_long, + _swigc__p_unsigned_short, + _swigc__p_vlan_map, +}; + + +/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */ + +static swig_const_info swig_const_table[] = { +{0, 0, 0, 0.0, 0, 0}}; + +#ifdef __cplusplus +} +#endif +/* ----------------------------------------------------------------------------- + * Type initialization: + * This problem is tough by the requirement that no dynamic + * memory is used. Also, since swig_type_info structures store pointers to + * swig_cast_info structures and swig_cast_info structures store pointers back + * to swig_type_info structures, we need some lookup code at initialization. + * The idea is that swig generates all the structures that are needed. + * The runtime then collects these partially filled structures. + * The SWIG_InitializeModule function takes these initial arrays out of + * swig_module, and does all the lookup, filling in the swig_module.types + * array with the correct data and linking the correct swig_cast_info + * structures together. + * + * The generated swig_type_info structures are assigned staticly to an initial + * array. We just loop through that array, and handle each type individually. + * First we lookup if this type has been already loaded, and if so, use the + * loaded structure instead of the generated one. Then we have to fill in the + * cast linked list. The cast data is initially stored in something like a + * two-dimensional array. Each row corresponds to a type (there are the same + * number of rows as there are in the swig_type_initial array). Each entry in + * a column is one of the swig_cast_info structures for that type. + * The cast_initial array is actually an array of arrays, because each row has + * a variable number of columns. So to actually build the cast linked list, + * we find the array of casts associated with the type, and loop through it + * adding the casts to the list. The one last trick we need to do is making + * sure the type pointer in the swig_cast_info struct is correct. + * + * First off, we lookup the cast->type name to see if it is already loaded. + * There are three cases to handle: + * 1) If the cast->type has already been loaded AND the type we are adding + * casting info to has not been loaded (it is in this module), THEN we + * replace the cast->type pointer with the type pointer that has already + * been loaded. + * 2) If BOTH types (the one we are adding casting info to, and the + * cast->type) are loaded, THEN the cast info has already been loaded by + * the previous module so we just ignore it. + * 3) Finally, if cast->type has not already been loaded, then we add that + * swig_cast_info to the linked list (because the cast->type) pointer will + * be correct. + * ----------------------------------------------------------------------------- */ + +#ifdef __cplusplus +extern "C" { +#if 0 +} /* c-mode */ +#endif +#endif + +#if 0 +#define SWIGRUNTIME_DEBUG +#endif + + +SWIGRUNTIME void +SWIG_InitializeModule(void *clientdata) { + size_t i; + swig_module_info *module_head, *iter; + int found, init; + + clientdata = clientdata; + + /* check to see if the circular list has been setup, if not, set it up */ + if (swig_module.next==0) { + /* Initialize the swig_module */ + swig_module.type_initial = swig_type_initial; + swig_module.cast_initial = swig_cast_initial; + swig_module.next = &swig_module; + init = 1; + } else { + init = 0; + } + + /* Try and load any already created modules */ + module_head = SWIG_GetModule(clientdata); + if (!module_head) { + /* This is the first module loaded for this interpreter */ + /* so set the swig module into the interpreter */ + SWIG_SetModule(clientdata, &swig_module); + module_head = &swig_module; + } else { + /* the interpreter has loaded a SWIG module, but has it loaded this one? */ + found=0; + iter=module_head; + do { + if (iter==&swig_module) { + found=1; + break; + } + iter=iter->next; + } while (iter!= module_head); + + /* if the is found in the list, then all is done and we may leave */ + if (found) return; + /* otherwise we must add out module into the list */ + swig_module.next = module_head->next; + module_head->next = &swig_module; + } + + /* When multiple interpeters are used, a module could have already been initialized in + a different interpreter, but not yet have a pointer in this interpreter. + In this case, we do not want to continue adding types... everything should be + set up already */ + if (init == 0) return; + + /* Now work on filling in swig_module.types */ +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: size %d\n", swig_module.size); +#endif + for (i = 0; i < swig_module.size; ++i) { + swig_type_info *type = 0; + swig_type_info *ret; + swig_cast_info *cast; + +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name); +#endif + + /* if there is another module already loaded */ + if (swig_module.next != &swig_module) { + type = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, swig_module.type_initial[i]->name); + } + if (type) { + /* Overwrite clientdata field */ +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: found type %s\n", type->name); +#endif + if (swig_module.type_initial[i]->clientdata) { + type->clientdata = swig_module.type_initial[i]->clientdata; +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: found and overwrite type %s \n", type->name); +#endif + } + } else { + type = swig_module.type_initial[i]; + } + + /* Insert casting types */ + cast = swig_module.cast_initial[i]; + while (cast->type) { + /* Don't need to add information already in the list */ + ret = 0; +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: look cast %s\n", cast->type->name); +#endif + if (swig_module.next != &swig_module) { + ret = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, cast->type->name); +#ifdef SWIGRUNTIME_DEBUG + if (ret) printf("SWIG_InitializeModule: found cast %s\n", ret->name); +#endif + } + if (ret) { + if (type == swig_module.type_initial[i]) { +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: skip old type %s\n", ret->name); +#endif + cast->type = ret; + ret = 0; + } else { + /* Check for casting already in the list */ + swig_cast_info *ocast = SWIG_TypeCheck(ret->name, type); +#ifdef SWIGRUNTIME_DEBUG + if (ocast) printf("SWIG_InitializeModule: skip old cast %s\n", ret->name); +#endif + if (!ocast) ret = 0; + } + } + + if (!ret) { +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: adding cast %s\n", cast->type->name); +#endif + if (type->cast) { + type->cast->prev = cast; + cast->next = type->cast; + } + type->cast = cast; + } + cast++; + } + /* Set entry in modules->types array equal to the type */ + swig_module.types[i] = type; + } + swig_module.types[i] = 0; + +#ifdef SWIGRUNTIME_DEBUG + printf("**** SWIG_InitializeModule: Cast List ******\n"); + for (i = 0; i < swig_module.size; ++i) { + int j = 0; + swig_cast_info *cast = swig_module.cast_initial[i]; + printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name); + while (cast->type) { + printf("SWIG_InitializeModule: cast type %s\n", cast->type->name); + cast++; + ++j; + } + printf("---- Total casts: %d\n",j); + } + printf("**** SWIG_InitializeModule: Cast List ******\n"); +#endif +} + +/* This function will propagate the clientdata field of type to +* any new swig_type_info structures that have been added into the list +* of equivalent types. It is like calling +* SWIG_TypeClientData(type, clientdata) a second time. +*/ +SWIGRUNTIME void +SWIG_PropagateClientData(void) { + size_t i; + swig_cast_info *equiv; + static int init_run = 0; + + if (init_run) return; + init_run = 1; + + for (i = 0; i < swig_module.size; i++) { + if (swig_module.types[i]->clientdata) { + equiv = swig_module.types[i]->cast; + while (equiv) { + if (!equiv->converter) { + if (equiv->type && !equiv->type->clientdata) + SWIG_TypeClientData(equiv->type, swig_module.types[i]->clientdata); + } + equiv = equiv->next; + } + } + } +} + +#ifdef __cplusplus +#if 0 +{ + /* c-mode */ +#endif +} +#endif + + + +#ifdef __cplusplus +extern "C" { +#endif + + /* Python-specific SWIG API */ +#define SWIG_newvarlink() SWIG_Python_newvarlink() +#define SWIG_addvarlink(p, name, get_attr, set_attr) SWIG_Python_addvarlink(p, name, get_attr, set_attr) +#define SWIG_InstallConstants(d, constants) SWIG_Python_InstallConstants(d, constants) + + /* ----------------------------------------------------------------------------- + * global variable support code. + * ----------------------------------------------------------------------------- */ + + typedef struct swig_globalvar { + char *name; /* Name of global variable */ + PyObject *(*get_attr)(void); /* Return the current value */ + int (*set_attr)(PyObject *); /* Set the value */ + struct swig_globalvar *next; + } swig_globalvar; + + typedef struct swig_varlinkobject { + PyObject_HEAD + swig_globalvar *vars; + } swig_varlinkobject; + + SWIGINTERN PyObject * + swig_varlink_repr(swig_varlinkobject *SWIGUNUSEDPARM(v)) { +#if PY_VERSION_HEX >= 0x03000000 + return PyUnicode_InternFromString(""); +#else + return PyString_FromString(""); +#endif + } + + SWIGINTERN PyObject * + swig_varlink_str(swig_varlinkobject *v) { +#if PY_VERSION_HEX >= 0x03000000 + PyObject *str = PyUnicode_InternFromString("("); + PyObject *tail; + PyObject *joined; + swig_globalvar *var; + for (var = v->vars; var; var=var->next) { + tail = PyUnicode_FromString(var->name); + joined = PyUnicode_Concat(str, tail); + Py_DecRef(str); + Py_DecRef(tail); + str = joined; + if (var->next) { + tail = PyUnicode_InternFromString(", "); + joined = PyUnicode_Concat(str, tail); + Py_DecRef(str); + Py_DecRef(tail); + str = joined; + } + } + tail = PyUnicode_InternFromString(")"); + joined = PyUnicode_Concat(str, tail); + Py_DecRef(str); + Py_DecRef(tail); + str = joined; +#else + PyObject *str = PyString_FromString("("); + swig_globalvar *var; + for (var = v->vars; var; var=var->next) { + PyString_ConcatAndDel(&str,PyString_FromString(var->name)); + if (var->next) PyString_ConcatAndDel(&str,PyString_FromString(", ")); + } + PyString_ConcatAndDel(&str,PyString_FromString(")")); +#endif + return str; + } + + SWIGINTERN int + swig_varlink_print(swig_varlinkobject *v, FILE *fp, int SWIGUNUSEDPARM(flags)) { + char *tmp; + PyObject *str = swig_varlink_str(v); + fprintf(fp,"Swig global variables "); + fprintf(fp,"%s\n", tmp = SWIG_Python_str_AsChar(str)); + SWIG_Python_str_DelForPy3(tmp); + Py_DECREF(str); + return 0; + } + + SWIGINTERN void + swig_varlink_dealloc(swig_varlinkobject *v) { + swig_globalvar *var = v->vars; + while (var) { + swig_globalvar *n = var->next; + free(var->name); + free(var); + var = n; + } + } + + SWIGINTERN PyObject * + swig_varlink_getattr(swig_varlinkobject *v, char *n) { + PyObject *res = NULL; + swig_globalvar *var = v->vars; + while (var) { + if (strcmp(var->name,n) == 0) { + res = (*var->get_attr)(); + break; + } + var = var->next; + } + if (res == NULL && !PyErr_Occurred()) { + PyErr_SetString(PyExc_NameError,"Unknown C global variable"); + } + return res; + } + + SWIGINTERN int + swig_varlink_setattr(swig_varlinkobject *v, char *n, PyObject *p) { + int res = 1; + swig_globalvar *var = v->vars; + while (var) { + if (strcmp(var->name,n) == 0) { + res = (*var->set_attr)(p); + break; + } + var = var->next; + } + if (res == 1 && !PyErr_Occurred()) { + PyErr_SetString(PyExc_NameError,"Unknown C global variable"); + } + return res; + } + + SWIGINTERN PyTypeObject* + swig_varlink_type(void) { + static char varlink__doc__[] = "Swig var link object"; + static PyTypeObject varlink_type; + static int type_init = 0; + if (!type_init) { + const PyTypeObject tmp + = { + /* PyObject header changed in Python 3 */ +#if PY_VERSION_HEX >= 0x03000000 + PyVarObject_HEAD_INIT(&PyType_Type, 0) +#else + PyObject_HEAD_INIT(NULL) + 0, /* Number of items in variable part (ob_size) */ +#endif + (char *)"swigvarlink", /* Type name (tp_name) */ + sizeof(swig_varlinkobject), /* Basic size (tp_basicsize) */ + 0, /* Itemsize (tp_itemsize) */ + (destructor) swig_varlink_dealloc, /* Deallocator (tp_dealloc) */ + (printfunc) swig_varlink_print, /* Print (tp_print) */ + (getattrfunc) swig_varlink_getattr, /* get attr (tp_getattr) */ + (setattrfunc) swig_varlink_setattr, /* Set attr (tp_setattr) */ + 0, /* tp_compare */ + (reprfunc) swig_varlink_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + (reprfunc) swig_varlink_str, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + 0, /* tp_flags */ + varlink__doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ +#if PY_VERSION_HEX >= 0x02020000 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* tp_iter -> tp_weaklist */ +#endif +#if PY_VERSION_HEX >= 0x02030000 + 0, /* tp_del */ +#endif +#ifdef COUNT_ALLOCS + 0,0,0,0 /* tp_alloc -> tp_next */ +#endif + }; + varlink_type = tmp; + /* for Python 3 we already assigned ob_type in PyVarObject_HEAD_INIT() */ +#if PY_VERSION_HEX < 0x03000000 + varlink_type.ob_type = &PyType_Type; +#endif + type_init = 1; + } + return &varlink_type; + } + + /* Create a variable linking object for use later */ + SWIGINTERN PyObject * + SWIG_Python_newvarlink(void) { + swig_varlinkobject *result = PyObject_NEW(swig_varlinkobject, swig_varlink_type()); + if (result) { + result->vars = 0; + } + return ((PyObject*) result); + } + + SWIGINTERN void + SWIG_Python_addvarlink(PyObject *p, char *name, PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p)) { + swig_varlinkobject *v = (swig_varlinkobject *) p; + swig_globalvar *gv = (swig_globalvar *) malloc(sizeof(swig_globalvar)); + if (gv) { + size_t size = strlen(name)+1; + gv->name = (char *)malloc(size); + if (gv->name) { + strncpy(gv->name,name,size); + gv->get_attr = get_attr; + gv->set_attr = set_attr; + gv->next = v->vars; + } + } + v->vars = gv; + } + + SWIGINTERN PyObject * + SWIG_globals(void) { + static PyObject *_SWIG_globals = 0; + if (!_SWIG_globals) _SWIG_globals = SWIG_newvarlink(); + return _SWIG_globals; + } + + /* ----------------------------------------------------------------------------- + * constants/methods manipulation + * ----------------------------------------------------------------------------- */ + + /* Install Constants */ + SWIGINTERN void + SWIG_Python_InstallConstants(PyObject *d, swig_const_info constants[]) { + PyObject *obj = 0; + size_t i; + for (i = 0; constants[i].type; ++i) { + switch(constants[i].type) { + case SWIG_PY_POINTER: + obj = SWIG_NewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0); + break; + case SWIG_PY_BINARY: + obj = SWIG_NewPackedObj(constants[i].pvalue, constants[i].lvalue, *(constants[i].ptype)); + break; + default: + obj = 0; + break; + } + if (obj) { + PyDict_SetItemString(d, constants[i].name, obj); + Py_DECREF(obj); + } + } + } + + /* -----------------------------------------------------------------------------*/ + /* Fix SwigMethods to carry the callback ptrs when needed */ + /* -----------------------------------------------------------------------------*/ + + SWIGINTERN void + SWIG_Python_FixMethods(PyMethodDef *methods, + swig_const_info *const_table, + swig_type_info **types, + swig_type_info **types_initial) { + size_t i; + for (i = 0; methods[i].ml_name; ++i) { + const char *c = methods[i].ml_doc; + if (c && (c = strstr(c, "swig_ptr: "))) { + int j; + swig_const_info *ci = 0; + const char *name = c + 10; + for (j = 0; const_table[j].type; ++j) { + if (strncmp(const_table[j].name, name, + strlen(const_table[j].name)) == 0) { + ci = &(const_table[j]); + break; + } + } + if (ci) { + size_t shift = (ci->ptype) - types; + swig_type_info *ty = types_initial[shift]; + size_t ldoc = (c - methods[i].ml_doc); + size_t lptr = strlen(ty->name)+2*sizeof(void*)+2; + char *ndoc = (char*)malloc(ldoc + lptr + 10); + if (ndoc) { + char *buff = ndoc; + void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue : 0; + if (ptr) { + strncpy(buff, methods[i].ml_doc, ldoc); + buff += ldoc; + strncpy(buff, "swig_ptr: ", 10); + buff += 10; + SWIG_PackVoidPtr(buff, ptr, ty->name, lptr); + methods[i].ml_doc = ndoc; + } + } + } + } + } + } + +#ifdef __cplusplus +} +#endif + +/* -----------------------------------------------------------------------------* + * Partial Init method + * -----------------------------------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" +#endif + +SWIGEXPORT +#if PY_VERSION_HEX >= 0x03000000 +PyObject* +#else +void +#endif +SWIG_init(void) { + PyObject *m, *d; +#if PY_VERSION_HEX >= 0x03000000 + static struct PyModuleDef SWIG_module = { + PyModuleDef_HEAD_INIT, + (char *) SWIG_name, + NULL, + -1, + SwigMethods, + NULL, + NULL, + NULL, + NULL + }; +#endif + + /* Fix SwigMethods to carry the callback ptrs when needed */ + SWIG_Python_FixMethods(SwigMethods, swig_const_table, swig_types, swig_type_initial); + +#if PY_VERSION_HEX >= 0x03000000 + m = PyModule_Create(&SWIG_module); +#else + m = Py_InitModule((char *) SWIG_name, SwigMethods); +#endif + d = PyModule_GetDict(m); + + SWIG_InitializeModule(0); + SWIG_InstallConstants(d,swig_const_table); + + + SWIG_Python_SetConstant(d, "VLAN_PRIO_MAX",SWIG_From_int((int)(7))); +#if PY_VERSION_HEX >= 0x03000000 + return m; +#else + return; +#endif +} + diff --git a/python/netlink/route/link.py b/python/netlink/route/link.py index b8e19fa..c4eb20c 100644 --- a/python/netlink/route/link.py +++ b/python/netlink/route/link.py @@ -117,15 +117,16 @@ class LinkCache(netlink.Cache): if not cache: cache = self._alloc_cache_name("route/link") + self._info_module = None self._protocol = netlink.NETLINK_ROUTE - self._c_cache = cache + self._nl_cache = cache self._set_arg1(family) def __getitem__(self, key): if type(key) is int: - link = capi.rtnl_link_get(self._c_cache, key) + link = capi.rtnl_link_get(self._nl_cache, key) elif type(key) is str: - link = capi.rtnl_link_get_by_name(self._c_cache, key) + link = capi.rtnl_link_get_by_name(self._nl_cache, key) if link is None: raise KeyError() @@ -147,10 +148,8 @@ class Link(netlink.Object): netlink.Object.__init__(self, "route/link", "link", obj) self._rtnl_link = self._obj2type(self._nl_object) - self._type = None - if self.type: - self._type_lookup(self.type) + self._module_lookup('netlink.route.links.' + self.type) self.inet = inet.InetLink(self) self.af = {'inet' : self.inet } @@ -171,15 +170,6 @@ class Link(netlink.Object): return Link(obj) - def _type_lookup(self, name): - rname = 'netlink.route.links.' + name - tmp = __import__(rname) - mod = sys.modules[rname] - - # this will create a type instance and assign it to - # link., e.g. link.vlan.id - self._type = mod.assign_type(self) - ##################################################################### # ifindex @netlink.nlattr('link.ifindex', type=int, immutable=True, fmt=util.num) @@ -403,7 +393,7 @@ class Link(netlink.Object): if capi.rtnl_link_set_info_type(self._rtnl_link, value) < 0: raise NameError("unknown info type") - self._type_lookup(value) + self._module_lookup('netlink.route.links.' + value) ##################################################################### # get_stat() @@ -469,14 +459,7 @@ class Link(netlink.Object): @property def _brief(self): - buf = '' - if self.type: - if self._type and hasattr(self._type, 'brief'): - buf += self._type.brief() - else: - buf += util.yellow(self.type) - - return buf + self._foreach_af('brief') + return self._module_brief() + self._foreach_af('brief') @property def _flags(self): @@ -587,10 +570,8 @@ def get(name, socket=None): return Link.from_capi(link) -link_cache = LinkCache() +_link_cache = LinkCache() def resolve(name): - socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) - link_cache.refill() - - return link_cache[name] + _link_cache.refill() + return _link_cache[name] diff --git a/python/netlink/route/links/dummy.py b/python/netlink/route/links/dummy.py index 495be94..8210413 100644 --- a/python/netlink/route/links/dummy.py +++ b/python/netlink/route/links/dummy.py @@ -7,7 +7,7 @@ """ __version__ = "1.0" -__all__ = ['assign_type'] +__all__ = ['init'] import netlink.core as netlink import netlink.route.capi as capi @@ -15,7 +15,10 @@ import netlink.route.capi as capi class DummyLink(object): def __init__(self, link): self._rtnl_link = link + + def brief(self): + return 'dummy' -def assign_type(link): +def init(link): link.dummy = DummyLink(link._rtnl_link) - return link.dummy + return link.dummy diff --git a/python/netlink/route/links/vlan.py b/python/netlink/route/links/vlan.py index 1d4e03d..7f28247 100644 --- a/python/netlink/route/links/vlan.py +++ b/python/netlink/route/links/vlan.py @@ -57,6 +57,6 @@ class VLANLink(object): def brief(self): return 'vlan-id ' + self.id -def assign_type(link): +def init(link): link.vlan = VLANLink(link._link) - return link.vlan + return link.vlan diff --git a/python/netlink/route/qdisc.py b/python/netlink/route/qdisc.py deleted file mode 100644 index c8a4c6f..0000000 --- a/python/netlink/route/qdisc.py +++ /dev/null @@ -1,185 +0,0 @@ -# -# Copyright (c) 2011 Thomas Graf -# - -__all__ = [ - 'QdiscCache', - 'Qdisc'] - -import netlink.core as netlink -import netlink.capi as core_capi -import netlink.route.capi as capi -import netlink.util as util -import netlink.route.tc as tc - -########################################################################### -# Link Cache -class QdiscCache(netlink.Cache): - """Cache of qdiscs""" - - def __init__(self, cache=None): - if not cache: - cache = self._alloc_cache_name("route/qdisc") - - self._protocol = netlink.NETLINK_ROUTE - self._c_cache = cache - -# def __getitem__(self, key): -# if type(key) is int: -# link = capi.rtnl_link_get(self._this, key) -# elif type(key) is str: -# link = capi.rtnl_link_get_by_name(self._this, key) -# -# if qdisc is None: -# raise KeyError() -# else: -# return Qdisc._from_capi(capi.qdisc2obj(qdisc)) - - def _new_object(self, obj): - return Qdisc(obj) - - def _new_cache(self, cache): - return QdiscCache(cache=cache) - -########################################################################### -# Qdisc Object -class Qdisc(tc.Tc): - """Network link""" - - def __init__(self, obj=None): - self._name = "qdisc" - self._abbr = "qdisc" - - netlink.Object.__init__(self, "route/qdisc", "qdisc", obj) - self._tc = capi.obj2tc(self._nl_object) - self._rtnl_qdisc = self._obj2type(self._nl_object) - - netlink.attr('qdisc.handle', fmt=util.handle) - netlink.attr('qdisc.parent', fmt=util.handle) - netlink.attr('qdisc.kind', fmt=util.bold) - - def _obj2type(self, obj): - return capi.obj2qdisc(obj) - - def __cmp__(self, other): - return self.handle - other.handle - - def _new_instance(self, obj): - if not obj: - raise ValueError() - - return Qdisc(obj) - -# ##################################################################### -# # add() -# def add(self, socket, flags=None): -# if not flags: -# flags = netlink.NLM_F_CREATE -# -# ret = capi.rtnl_link_add(socket._sock, self._link, flags) -# if ret < 0: -# raise netlink.KernelError(ret) -# -# ##################################################################### -# # change() -# def change(self, socket, flags=0): -# """Commit changes made to the link object""" -# if not self._orig: -# raise NetlinkError("Original link not available") -# ret = capi.rtnl_link_change(socket._sock, self._orig, self._link, flags) -# if ret < 0: -# raise netlink.KernelError(ret) -# -# ##################################################################### -# # delete() -# def delete(self, socket): -# """Attempt to delete this link in the kernel""" -# ret = capi.rtnl_link_delete(socket._sock, self._link) -# if ret < 0: -# raise netlink.KernelError(ret) - - @property - def _dev(self): - buf = util.kw('dev') + ' ' - - if self.link: - return buf + util.string(self.link.name) - else: - return buf + util.num(self.ifindex) - - @property - def _parent(self): - return util.kw('parent') + ' ' + str(self.parent) - - ################################################################### - # - # format(details=False, stats=False) - # - def format(self, details=False, stats=False): - """Return qdisc as formatted text""" - fmt = util.MyFormatter(self) - - buf = fmt.format('qdisc {kind} {handle} {_dev} {_parent}') - - if details: - fmt = util.MyFormatter(self) - buf += fmt.format('\n'\ - '\t{mtu} {mpu} {overhead}\n') - -# if stats: -# l = [['Packets', RX_PACKETS, TX_PACKETS], -# ['Bytes', RX_BYTES, TX_BYTES], -# ['Errors', RX_ERRORS, TX_ERRORS], -# ['Dropped', RX_DROPPED, TX_DROPPED], -# ['Compressed', RX_COMPRESSED, TX_COMPRESSED], -# ['FIFO Errors', RX_FIFO_ERR, TX_FIFO_ERR], -# ['Length Errors', RX_LEN_ERR, None], -# ['Over Errors', RX_OVER_ERR, None], -# ['CRC Errors', RX_CRC_ERR, None], -# ['Frame Errors', RX_FRAME_ERR, None], -# ['Missed Errors', RX_MISSED_ERR, None], -# ['Abort Errors', None, TX_ABORT_ERR], -# ['Carrier Errors', None, TX_CARRIER_ERR], -# ['Heartbeat Errors', None, TX_HBEAT_ERR], -# ['Window Errors', None, TX_WIN_ERR], -# ['Collisions', None, COLLISIONS], -# ['Multicast', None, MULTICAST], -# ['', None, None], -# ['Ipv6:', None, None], -# ['Packets', IP6_INPKTS, IP6_OUTPKTS], -# ['Bytes', IP6_INOCTETS, IP6_OUTOCTETS], -# ['Discards', IP6_INDISCARDS, IP6_OUTDISCARDS], -# ['Multicast Packets', IP6_INMCASTPKTS, IP6_OUTMCASTPKTS], -# ['Multicast Bytes', IP6_INMCASTOCTETS, IP6_OUTMCASTOCTETS], -# ['Broadcast Packets', IP6_INBCASTPKTS, IP6_OUTBCASTPKTS], -# ['Broadcast Bytes', IP6_INBCASTOCTETS, IP6_OUTBCASTOCTETS], -# ['Delivers', IP6_INDELIVERS, None], -# ['Forwarded', None, IP6_OUTFORWDATAGRAMS], -# ['No Routes', IP6_INNOROUTES, IP6_OUTNOROUTES], -# ['Header Errors', IP6_INHDRERRORS, None], -# ['Too Big Errors', IP6_INTOOBIGERRORS, None], -# ['Address Errors', IP6_INADDRERRORS, None], -# ['Unknown Protocol', IP6_INUNKNOWNPROTOS, None], -# ['Truncated Packets', IP6_INTRUNCATEDPKTS, None], -# ['Reasm Timeouts', IP6_REASMTIMEOUT, None], -# ['Reasm Requests', IP6_REASMREQDS, None], -# ['Reasm Failures', IP6_REASMFAILS, None], -# ['Reasm OK', IP6_REASMOKS, None], -# ['Frag Created', None, IP6_FRAGCREATES], -# ['Frag Failures', None, IP6_FRAGFAILS], -# ['Frag OK', None, IP6_FRAGOKS], -# ['', None, None], -# ['ICMPv6:', None, None], -# ['Messages', ICMP6_INMSGS, ICMP6_OUTMSGS], -# ['Errors', ICMP6_INERRORS, ICMP6_OUTERRORS]] -# -# buf += '\n\t%s%s%s%s\n' % (33 * ' ', util.title('RX'), -# 15 * ' ', util.title('TX')) -# -# for row in l: -# row[0] = util.kw(row[0]) -# row[1] = self.get_stat(row[1]) if row[1] else '' -# row[2] = self.get_stat(row[2]) if row[2] else '' -# buf += '\t{0:27} {1:>16} {2:>16}\n'.format(*row) - - return buf diff --git a/python/netlink/route/qdisc/__init__.py b/python/netlink/route/qdisc/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python/netlink/route/qdisc/htb.py b/python/netlink/route/qdisc/htb.py new file mode 100644 index 0000000..13e10f2 --- /dev/null +++ b/python/netlink/route/qdisc/htb.py @@ -0,0 +1,161 @@ +# +# Copyright (c) 2011 Thomas Graf +# + +"""HTB qdisc + +""" + +import netlink.core as netlink +import netlink.util as util +import netlink.route.capi as capi +import netlink.route.tc as tc + +class HTBQdisc(object): + def __init__(self, qdisc): + self._qdisc = qdisc + + ################################################################### + # default class + @netlink.nlattr('qdisc.htb.default_class', type=int) + @property + def default_class(self): + return tc.Handle(capi.rtnl_htb_get_defcls(self._qdisc._rtnl_qdisc)) + + @default_class.setter + def default_class(self, value): + capi.rtnl_htb_set_defcls(self._qdisc._rtnl_qdisc, int(value)) + + ##################################################################### + # r2q + @netlink.nlattr('qdisc.htb.r2q', type=int) + @property + def r2q(self): + return capi.rtnl_htb_get_rate2quantum(self._qdisc._rtnl_qdisc) + + @r2q.setter + def r2q(self, value): + capi.rtnl_htb_get_rate2quantum(self._qdisc._rtnl_qdisc, + int(value)) + + def brief(self): + fmt = util.MyFormatter(self) + + ret = ' {s|default-class!k} {a|default_class}' + + if self.r2q: + ret += ' {s|r2q!k} {a|r2q}' + + return fmt.format(ret) + +class HTBClass(object): + def __init__(self, cl): + self._class = cl + + ##################################################################### + # rate + @netlink.nlattr('class.htb.rate', type=str) + @property + def rate(self): + rate = capi.rtnl_htb_get_rate(self._class._rtnl_class) + return util.Rate(rate) + + @rate.setter + def rate(self, value): + capi.rtnl_htb_set_rate(self._class._rtnl_class, int(value)) + + ##################################################################### + # ceil + @netlink.nlattr('class.htb.ceil', type=str) + @property + def ceil(self): + ceil = capi.rtnl_htb_get_ceil(self._class._rtnl_class) + return util.Rate(ceil) + + @ceil.setter + def ceil(self, value): + capi.rtnl_htb_set_ceil(self._class._rtnl_class, int(value)) + + ##################################################################### + # burst + @netlink.nlattr('class.htb.burst', type=str) + @property + def burst(self): + burst = capi.rtnl_htb_get_rbuffer(self._class._rtnl_class) + return util.Size(burst) + + @burst.setter + def burst(self, value): + capi.rtnl_htb_set_rbuffer(self._class._rtnl_class, int(value)) + + ##################################################################### + # ceil burst + @netlink.nlattr('class.htb.ceil_burst', type=str) + @property + def ceil_burst(self): + burst = capi.rtnl_htb_get_cbuffer(self._class._rtnl_class) + return util.Size(burst) + + @ceil_burst.setter + def ceil_burst(self, value): + capi.rtnl_htb_set_cbuffer(self._class._rtnl_class, int(value)) + + ##################################################################### + # priority + @netlink.nlattr('class.htb.prio', type=int) + @property + def prio(self): + return capi.rtnl_htb_get_prio(self._class._rtnl_class) + + @prio.setter + def prio(self, value): + capi.rtnl_htb_set_prio(self._class._rtnl_class, int(value)) + + ##################################################################### + # quantum + @netlink.nlattr('class.htb.quantum', type=int) + @property + def quantum(self): + return capi.rtnl_htb_get_quantum(self._class._rtnl_class) + + @quantum.setter + def quantum(self, value): + capi.rtnl_htb_set_quantum(self._class._rtnl_class, int(value)) + + ##################################################################### + # level + @netlink.nlattr('class.htb.level', type=int) + @property + def level(self): + level = capi.rtnl_htb_get_level(self._class._rtnl_class) + + @level.setter + def level(self, value): + capi.rtnl_htb_set_level(self._class._rtnl_class, int(value)) + + def brief(self): + fmt = util.MyFormatter(self) + + ret = ' {t|prio} {t|rate}' + + if self.rate != self.ceil: + ret += ' {s|borrow-up-to!k} {a|ceil}' + + ret += ' {t|burst}' + + return fmt.format(ret) + + def details(self): + fmt = util.MyFormatter(self) + + return fmt.nl('\t{t|level} {t|quantum}') + +def init_qdisc(qdisc): + qdisc.htb = HTBQdisc(qdisc) + return qdisc.htb + +def init_class(cl): + cl.htb = HTBClass(cl) + return cl.htb + +#extern void rtnl_htb_set_quantum(struct rtnl_class *, uint32_t quantum); diff --git a/python/netlink/route/tc.py b/python/netlink/route/tc.py index ebe25e1..bae9bca 100644 --- a/python/netlink/route/tc.py +++ b/python/netlink/route/tc.py @@ -1,5 +1,3 @@ - - # # Copyright (c) 2011 Thomas Graf # @@ -8,7 +6,9 @@ __all__ = [ 'TcCache', 'Tc', 'QdiscCache', - 'Qdisc'] + 'Qdisc', + 'TcClassCache', + 'TcClass'] import socket import sys @@ -17,7 +17,7 @@ import netlink.capi as core_capi import netlink.route.capi as capi import netlink.util as util -from netlink.route.link import Link +import netlink.route.link as Link TC_PACKETS = 0 TC_BYTES = 1 @@ -32,7 +32,31 @@ TC_OVERLIMITS = 9 TC_H_ROOT = 0xFFFFFFFF TC_H_INGRESS = 0xFFFFFFF1 +STAT_PACKETS = 0 +STAT_BYTES = 1 +STAT_RATE_BPS = 2 +STAT_RATE_PPS = 3 +STAT_QLEN = 4 +STAT_BACKLOG = 5 +STAT_DROPS = 6 +STAT_REQUEUES = 7 +STAT_OVERLIMITS = 8 +STAT_MAX = STAT_OVERLIMITS + + +########################################################################### +# Handle class Handle(object): + """ Traffic control handle + + Representation of a traffic control handle which uniquely identifies + each traffic control object in its link namespace. + + handle = tc.Handle('10:20') + handle = tc.handle('root') + print int(handle) + print str(handle) + """ def __init__(self, val=None): if type(val) is str: val = capi.tc_str2handle(val) @@ -41,6 +65,17 @@ class Handle(object): self._val = int(val) + def __cmp__(self, other): + if other is None: + other = 0 + + if isinstance(other, Handle): + return int(self) - int(other) + elif isinstance(other, int): + return int(self) - other + else: + raise TypeError() + def __int__(self): return self._val @@ -62,9 +97,18 @@ class TcCache(netlink.Cache): # Tc Object class Tc(netlink.Object): def __cmp__(self, other): - return self.ifindex - other.ifindex + diff = self.ifindex - other.ifindex + if diff == 0: + diff = int(self.handle) - int(other.handle) + return diff - def isroot(self): + def _tc_module_lookup(self): + self._module_lookup(self._module_path + self.kind, + 'init_' + self._name) + + @property + def root(self): + """True if tc object is a root object""" return self.parent.isroot() ##################################################################### @@ -72,120 +116,140 @@ class Tc(netlink.Object): @property def ifindex(self): """interface index""" - return capi.rtnl_tc_get_ifindex(self._tc) + return capi.rtnl_tc_get_ifindex(self._rtnl_tc) @ifindex.setter def ifindex(self, value): - capi.rtnl_tc_set_ifindex(self._tc, int(value)) + capi.rtnl_tc_set_ifindex(self._rtnl_tc, int(value)) ##################################################################### # link @property def link(self): - link = capi.rtnl_tc_get_link(self._tc) + link = capi.rtnl_tc_get_link(self._rtnl_tc) if not link: return None - else: - return Link._from_capi(link) + + return Link.Link.from_capi(link) @link.setter def link(self, value): - capi.rtnl_tc_set_link(self._tc, value._link) + capi.rtnl_tc_set_link(self._rtnl_tc, value._link) ##################################################################### # mtu @property def mtu(self): - return capi.rtnl_tc_get_mtu(self._tc) + return capi.rtnl_tc_get_mtu(self._rtnl_tc) @mtu.setter def mtu(self, value): - capi.rtnl_tc_set_mtu(self._tc, int(value)) + capi.rtnl_tc_set_mtu(self._rtnl_tc, int(value)) ##################################################################### # mpu @property def mpu(self): - return capi.rtnl_tc_get_mpu(self._tc) + return capi.rtnl_tc_get_mpu(self._rtnl_tc) @mpu.setter def mpu(self, value): - capi.rtnl_tc_set_mpu(self._tc, int(value)) + capi.rtnl_tc_set_mpu(self._rtnl_tc, int(value)) ##################################################################### # overhead @property def overhead(self): - return capi.rtnl_tc_get_overhead(self._tc) + return capi.rtnl_tc_get_overhead(self._rtnl_tc) @overhead.setter def overhead(self, value): - capi.rtnl_tc_set_overhead(self._tc, int(value)) + capi.rtnl_tc_set_overhead(self._rtnl_tc, int(value)) ##################################################################### # linktype @property def linktype(self): - return capi.rtnl_tc_get_linktype(self._tc) + return capi.rtnl_tc_get_linktype(self._rtnl_tc) @linktype.setter def linktype(self, value): - capi.rtnl_tc_set_linktype(self._tc, int(value)) + capi.rtnl_tc_set_linktype(self._rtnl_tc, int(value)) ##################################################################### # handle @property def handle(self): - return Handle(capi.rtnl_tc_get_handle(self._tc)) + return Handle(capi.rtnl_tc_get_handle(self._rtnl_tc)) @handle.setter def handle(self, value): - capi.rtnl_tc_set_handle(self._tc, int(value)) + capi.rtnl_tc_set_handle(self._rtnl_tc, int(value)) ##################################################################### # parent @property def parent(self): - return Handle(capi.rtnl_tc_get_parent(self._tc)) + return Handle(capi.rtnl_tc_get_parent(self._rtnl_tc)) @parent.setter def parent(self, value): - capi.rtnl_tc_set_parent(self._tc, int(value)) + capi.rtnl_tc_set_parent(self._rtnl_tc, int(value)) ##################################################################### # kind @property def kind(self): - return capi.rtnl_tc_get_kind(self._tc) + return capi.rtnl_tc_get_kind(self._rtnl_tc) @kind.setter def kind(self, value): - capi.rtnl_tc_set_kind(self._tc, value) + capi.rtnl_tc_set_kind(self._rtnl_tc, value) + self._tc_module_lookup() def get_stat(self, id): - return capi.rtnl_tc_get_stat(self._tc, id) + return capi.rtnl_tc_get_stat(self._rtnl_tc, id) -class TcTree(object): - def __init__(self, link, sock): - self._qdisc_cache = QdiscCache().refill(sock) + @property + def _dev(self): + buf = util.kw('dev') + ' ' - def __getitem__(self, key): - pass -# if type(key) is int: -# link = capi.rtnl_link_get(self._this, key) -# elif type(key) is str: -# link = capi.rtnl_link_get_by_name(self._this, key) -# -# if qdisc is None: -# raise KeyError() -# else: -# return Qdisc._from_capi(capi.qdisc2obj(qdisc)) + if self.link: + return buf + util.string(self.link.name) + else: + return buf + util.num(self.ifindex) - + def brief(self, title, nodev=False, noparent=False): + ret = title + ' {a|kind} {a|handle}' + if not nodev: + ret += ' {a|_dev}' + if not noparent: + ret += ' {t|parent}' + + return ret + self._module_brief() + + def details(self): + return '{t|mtu} {t|mpu} {t|overhead} {t|linktype}' + + @property + def packets(self): + return self.get_stat(STAT_PACKETS) + + @property + def bytes(self): + return self.get_stat(STAT_BYTES) + + @property + def qlen(self): + return self.get_stat(STAT_QLEN) + + def stats(self, fmt): + return fmt.nl('{t|packets} {t|bytes} {t|qlen}') + ########################################################################### -# Link Cache +# Queueing discipline cache class QdiscCache(netlink.Cache): """Cache of qdiscs""" @@ -193,7 +257,8 @@ class QdiscCache(netlink.Cache): if not cache: cache = self._alloc_cache_name("route/qdisc") - self._c_cache = cache + self._protocol = netlink.NETLINK_ROUTE + self._nl_cache = cache # def __getitem__(self, key): # if type(key) is int: @@ -215,33 +280,48 @@ class QdiscCache(netlink.Cache): ########################################################################### # Qdisc Object class Qdisc(Tc): - """Network link""" + """Queueing discipline""" def __init__(self, obj=None): - self._name = "qdisc" - self._abbr = "qdisc" + netlink.Object.__init__(self, "route/qdisc", "qdisc", obj) + self._module_path = 'netlink.route.qdisc.' + self._rtnl_qdisc = self._obj2type(self._nl_object) + self._rtnl_tc = capi.obj2tc(self._nl_object) - if not obj: - self._qdisc = capi.rtnl_qdisc_alloc() - else: - self._qdisc = capi.obj2qdisc(obj) + netlink.add_attr('qdisc.handle', fmt=util.handle) + netlink.add_attr('qdisc.parent', fmt=util.handle) + netlink.add_attr('qdisc.kind', fmt=util.bold) - self._obj = capi.qdisc2obj(self._qdisc) - self._orig = capi.obj2qdisc(core_capi.nl_object_clone(self._obj)) + if self.kind: + self._tc_module_lookup() - Tc.__init__(self) + @classmethod + def from_capi(cls, obj): + return cls(capi.qdisc2obj(obj)) - netlink.attr('qdisc.handle', fmt=util.handle) - netlink.attr('qdisc.parent', fmt=util.handle) - netlink.attr('qdisc.kind', fmt=util.bold) - - def __cmp__(self, other): - return self.handle - other.handle + def _obj2type(self, obj): + return capi.obj2qdisc(obj) def _new_instance(self, obj): - if not obj: raise ValueError() + if not obj: + raise ValueError() + return Qdisc(obj) + @property + def childs(self): + ret = [] + + if int(self.handle): + ret += get_cls(self.ifindex, parent=self.handle) + + if self.root: + ret += get_class(self.ifindex, parent=TC_H_ROOT) + + ret += get_class(self.ifindex, parent=self.handle) + + return ret + # ##################################################################### # # add() # def add(self, socket, flags=None): @@ -270,33 +350,22 @@ class Qdisc(Tc): # if ret < 0: # raise netlink.KernelError(ret) - @property - def _dev(self): - buf = util.kw('dev') + ' ' - - if self.link: - return buf + util.string(self.link.name) - else: - return buf + util.num(self.ifindex) - - @property - def _parent(self): - return util.kw('parent') + ' ' + str(self.parent) - ################################################################### # # format(details=False, stats=False) # - def format(self, details=False, stats=False): + def format(self, details=False, stats=False, nodev=False, + noparent=False, indent=''): """Return qdisc as formatted text""" - fmt = util.BriefFormatter(self) - - buf = fmt.format('qdisc {kind} {handle} {_dev} {_parent}') + fmt = util.MyFormatter(self, indent) + buf = fmt.format(self.brief('qdisc', nodev, noparent)) + if details: - fmt = util.DetailFormatter(self) - buf += fmt.format('\n'\ - '\t{mtu} {mpu} {overhead}\n') + buf += fmt.nl('\t' + self.details()) + + if stats: + buf += self.stats(fmt) # if stats: # l = [['Packets', RX_PACKETS, TX_PACKETS], @@ -355,3 +424,229 @@ class Qdisc(Tc): # buf += '\t{0:27} {1:>16} {2:>16}\n'.format(*row) return buf + +########################################################################### +# Traffic class cache +class TcClassCache(netlink.Cache): + """Cache of traffic classes""" + + def __init__(self, ifindex, cache=None): + if not cache: + cache = self._alloc_cache_name("route/class") + + self._protocol = netlink.NETLINK_ROUTE + self._nl_cache = cache + self._set_arg1(ifindex) + + def _new_object(self, obj): + return TcClass(obj) + + def _new_cache(self, cache): + return TcClassCache(self.arg1, cache=cache) + +########################################################################### +# Traffic Class Object +class TcClass(Tc): + """Traffic Class""" + + def __init__(self, obj=None): + netlink.Object.__init__(self, "route/class", "class", obj) + self._module_path = 'netlink.route.qdisc.' + self._rtnl_class = self._obj2type(self._nl_object) + self._rtnl_tc = capi.obj2tc(self._nl_object) + + netlink.add_attr('class.handle', fmt=util.handle) + netlink.add_attr('class.parent', fmt=util.handle) + netlink.add_attr('class.kind', fmt=util.bold) + + if self.kind: + self._tc_module_lookup() + + @classmethod + def from_capi(cls, obj): + return cls(capi.class2obj(obj)) + + def _obj2type(self, obj): + return capi.obj2class(obj) + + def _new_instance(self, obj): + if not obj: + raise ValueError() + + return TcClass(obj) + + @property + def childs(self): + ret = [] + + # classes can have classifiers, child classes and leaf + # qdiscs + ret += get_cls(self.ifindex, parent=self.handle) + ret += get_class(self.ifindex, parent=self.handle) + ret += get_qdisc(self.ifindex, parent=self.handle) + + return ret + + ################################################################### + # + # format(details=False, stats=False) + # + def format(self, details=False, stats=False, nodev=False, + noparent=False, indent=''): + """Return class as formatted text""" + fmt = util.MyFormatter(self, indent) + + buf = fmt.format(self.brief('class', nodev, noparent)) + + if details: + buf += fmt.nl('\t' + self.details()) + + return buf + +########################################################################### +# Classifier Cache +class ClassifierCache(netlink.Cache): + """Cache of traffic classifiers objects""" + + def __init__(self, ifindex, parent, cache=None): + if not cache: + cache = self._alloc_cache_name("route/cls") + + self._protocol = netlink.NETLINK_ROUTE + self._nl_cache = cache + self._set_arg1(ifindex) + self._set_arg2(int(parent)) + + def _new_object(self, obj): + return Classifier(obj) + + def _new_cache(self, cache): + return ClassifierCache(self.arg1, self.arg2, cache=cache) + +########################################################################### +# Classifier Object +class Classifier(Tc): + """Classifier""" + + def __init__(self, obj=None): + netlink.Object.__init__(self, "route/cls", "cls", obj) + self._module_path = 'netlink.route.cls.' + self._rtnl_cls = self._obj2type(self._nl_object) + self._rtnl_tc = capi.obj2tc(self._nl_object) + + netlink.add_attr('cls.handle', fmt=util.handle) + netlink.add_attr('cls.parent', fmt=util.handle) + netlink.add_attr('cls.kind', fmt=util.bold) + + @classmethod + def from_capi(cls, obj): + return cls(capi.cls2obj(obj)) + + def _obj2type(self, obj): + return capi.obj2cls(obj) + + def _new_instance(self, obj): + if not obj: + raise ValueError() + + return Classifier(obj) + + ##################################################################### + # priority + @property + def priority(self): + return capi.rtnl_cls_get_prio(self._rtnl_cls) + + @priority.setter + def priority(self, value): + capi.rtnl_cls_set_prio(self._rtnl_cls, int(value)) + + ##################################################################### + # protocol + @property + def protocol(self): + return capi.rtnl_cls_get_protocol(self._rtnl_cls) + + @protocol.setter + def protocol(self, value): + capi.rtnl_cls_set_protocol(self._rtnl_cls, int(value)) + + @property + def childs(self): + return [] + + ################################################################### + # + # format(details=False, stats=False) + # + def format(self, details=False, stats=False, nodev=False, + noparent=False, indent=''): + """Return class as formatted text""" + fmt = util.MyFormatter(self, indent) + + buf = fmt.format(self.brief('classifier', nodev, noparent)) + buf += fmt.format(' {t|priority} {t|protocol}') + + if details: + buf += fmt.nl('\t' + self.details()) + + return buf + +_qdisc_cache = QdiscCache() + +def get_qdisc(ifindex, handle=None, parent=None): + l = [] + + _qdisc_cache.refill() + + for qdisc in _qdisc_cache: + if qdisc.ifindex == ifindex and \ + (handle == None or qdisc.handle == handle) and \ + (parent == None or qdisc.parent == parent): + l.append(qdisc) + + return l + +_class_cache = {} + +def get_class(ifindex, parent, handle=None): + l = [] + + try: + cache = _class_cache[ifindex] + except KeyError: + cache = TcClassCache(ifindex) + _class_cache[ifindex] = cache + + cache.refill() + + for cl in cache: + if (parent == None or cl.parent == parent) and \ + (handle == None or cl.handle == handle): + l.append(cl) + + return l + +_cls_cache = {} + +def get_cls(ifindex, parent, handle=None): + l = [] + + try: + chain = _cls_cache[ifindex] + except KeyError: + _cls_cache[ifindex] = {} + + try: + cache = _cls_cache[ifindex][parent] + except KeyError: + cache = ClassifierCache(ifindex, parent) + _cls_cache[ifindex][parent] = cache + + cache.refill() + + for cls in cache: + if handle == None or cls.handle == handle: + l.append(cls) + + return l diff --git a/python/netlink/util.py b/python/netlink/util.py index d3d0167..01db224 100644 --- a/python/netlink/util.py +++ b/python/netlink/util.py @@ -9,6 +9,7 @@ """ import netlink.core as netlink +import netlink.capi as capi from string import Formatter __version__ = "1.0" @@ -92,6 +93,8 @@ class MyFormatter(Formatter): title = d['title'] except KeyError: pass + except AttributeError: + pass return title, str(value) @@ -144,3 +147,33 @@ class MyFormatter(Formatter): def nl(self, format_string=''): return '\n' + self._indent + self.format(format_string) + +NL_BYTE_RATE = 0 +NL_BIT_RATE = 1 + +class Rate(object): + def __init__(self, rate, mode=NL_BYTE_RATE): + self._rate = rate + self._mode = mode + + def __str__(self): + return capi.nl_rate2str(self._rate, self._mode, 32)[1] + + def __int__(self): + return self._rate + + def __cmp__(self, other): + return int(self) - int(other) + +class Size(object): + def __init__(self, size): + self._size = size + + def __str__(self): + return capi.nl_size2str(self._size, 32)[0] + + def __int__(self): + return self._size + + def __cmp__(self, other): + return int(self) - int(other) diff --git a/python/setup.py b/python/setup.py index 9ea7c15..f201a84 100644 --- a/python/setup.py +++ b/python/setup.py @@ -25,5 +25,6 @@ setup(name = 'netlink', author = 'Thomas Graf', author_email = 'tgraf@suug.ch', ext_modules = [netlink_capi, route_capi], - packages = ['netlink', 'netlink.route', 'netlink.route.links'], + packages = ['netlink', 'netlink.route', 'netlink.route.links', + 'netlink.route.qdisc'], ) From c881908ac7a485512b74bcd583c5890f2ad2af19 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 15 Jun 2011 16:23:35 +0200 Subject: [PATCH 049/432] neigh: include ndm flags while building message Reported by jeff courington --- lib/route/neigh.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/route/neigh.c b/lib/route/neigh.c index 0cd0366..7985d34 100644 --- a/lib/route/neigh.c +++ b/lib/route/neigh.c @@ -465,6 +465,9 @@ static int build_neigh_msg(struct rtnl_neigh *tmpl, int cmd, int flags, nhdr.ndm_family = nl_addr_get_family(tmpl->n_dst); + if (tmpl->ce_mask & NEIGH_ATTR_FLAGS) + nhdr.ndm_flags = tmpl->n_flags; + if (tmpl->ce_mask & NEIGH_ATTR_STATE) nhdr.ndm_state = tmpl->n_state; From ca0fc75580512ccb5931fe1e05092c6c52a4e99c Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 15 Jun 2011 17:37:28 +0200 Subject: [PATCH 050/432] socket: Set SOCK_CLOEXEC if available MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported by Марк Коренберг --- lib/nl.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/nl.c b/lib/nl.c index f5f94e3..fc70374 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -101,14 +101,20 @@ * Creates a netlink socket using the specified protocol, binds the socket * and issues a connection attempt. * + * @note SOCK_CLOEXEC is set on the socket if available. + * * @return 0 on success or a negative error code. */ int nl_connect(struct nl_sock *sk, int protocol) { - int err; + int err, flags = 0; socklen_t addrlen; - sk->s_fd = socket(AF_NETLINK, SOCK_RAW, protocol); +#ifdef SOCK_CLOEXEC + flags |= SOCK_CLOEXEC; +#endif + + sk->s_fd = socket(AF_NETLINK, SOCK_RAW | flags, protocol); if (sk->s_fd < 0) { err = -nl_syserr2nlerr(errno); goto errout; From 4806c5c058ba95b0c88af7731d26dad427d2fcb8 Mon Sep 17 00:00:00 2001 From: Christian Ruppert Date: Tue, 21 Jun 2011 00:05:08 +0200 Subject: [PATCH 051/432] Don't redefine offsetof when already defined by e.g. stddef.h --- include/netlink-local.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/netlink-local.h b/include/netlink-local.h index 63dd661..01c611a 100644 --- a/include/netlink-local.h +++ b/include/netlink-local.h @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -126,7 +127,11 @@ static inline int nl_cb_call(struct nl_cb *cb, int type, struct nl_msg *msg) } #define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0])) + +/* This is also defined in stddef.h */ +#ifndef offsetof #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif #define __init __attribute__ ((constructor)) #define __exit __attribute__ ((destructor)) From 21d52eabba00089e3319575616a429fb75309cb7 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 14 Jul 2011 10:51:49 +0200 Subject: [PATCH 052/432] Support for NLM_F_INTR Check if a dump was interrupted and needs to be redone --- include/linux/netlink.h | 1 + include/netlink/errno.h | 3 ++- include/netlink/handlers.h | 2 ++ lib/cache.c | 14 ++++++++++++-- lib/error.c | 1 + lib/nl.c | 18 +++++++++++++++++- 6 files changed, 35 insertions(+), 4 deletions(-) diff --git a/include/linux/netlink.h b/include/linux/netlink.h index 0abcdaf..3925254 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -49,6 +49,7 @@ struct nlmsghdr { #define NLM_F_MULTI 2 /* Multipart message, terminated by NLMSG_DONE */ #define NLM_F_ACK 4 /* Reply with ack, with zero or error code */ #define NLM_F_ECHO 8 /* Echo this request */ +#define NLM_F_DUMP_INTR 16 /* Dump was inconsistent due to sequence change */ /* Modifiers to GET request */ #define NLM_F_ROOT 0x100 /* specify tree root */ diff --git a/include/netlink/errno.h b/include/netlink/errno.h index 267a745..f8b5130 100644 --- a/include/netlink/errno.h +++ b/include/netlink/errno.h @@ -49,8 +49,9 @@ extern "C" { #define NLE_PARSE_ERR 30 #define NLE_NODEV 31 #define NLE_IMMUTABLE 32 +#define NLE_DUMP_INTR 33 -#define NLE_MAX NLE_IMMUTABLE +#define NLE_MAX NLE_DUMP_INTR extern const char * nl_geterror(int); extern void nl_perror(int, const char *); diff --git a/include/netlink/handlers.h b/include/netlink/handlers.h index f373f58..dfa2809 100644 --- a/include/netlink/handlers.h +++ b/include/netlink/handlers.h @@ -108,6 +108,8 @@ enum nl_cb_type { NL_CB_SEQ_CHECK, /** Sending of an acknowledge message has been requested */ NL_CB_SEND_ACK, + /** Flag NLM_F_DUMP_INTR is set in message */ + NL_CB_DUMP_INTR, __NL_CB_TYPE_MAX, }; diff --git a/lib/cache.c b/lib/cache.c index 7afa42e..3b453a9 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -677,6 +677,7 @@ int nl_cache_resync(struct nl_sock *sk, struct nl_cache *cache, NL_DBG(1, "Resyncing cache %p <%s>...\n", cache, nl_cache_name(cache)); +restart: /* Mark all objects so we can see if some of them are obsolete */ nl_cache_mark_all(cache); @@ -685,7 +686,9 @@ int nl_cache_resync(struct nl_sock *sk, struct nl_cache *cache, goto errout; err = __cache_pickup(sk, cache, &p); - if (err < 0) + if (err == -NLE_DUMP_INTR) + goto restart; + else if (err < 0) goto errout; nl_list_for_each_entry_safe(obj, next, &cache->c_items, ce_list) { @@ -770,6 +773,7 @@ int nl_cache_refill(struct nl_sock *sk, struct nl_cache *cache) { int err; +restart: err = nl_cache_request_full_dump(sk, cache); if (err < 0) return err; @@ -778,7 +782,13 @@ int nl_cache_refill(struct nl_sock *sk, struct nl_cache *cache) cache, nl_cache_name(cache)); nl_cache_clear(cache); - return nl_cache_pickup(sk, cache); + err = nl_cache_pickup(sk, cache); + if (err == -NLE_DUMP_INTR) { + fprintf(stderr, "dump interrupted, restarting!\n"); + goto restart; + } + + return err; } /** @} */ diff --git a/lib/error.c b/lib/error.c index 8934020..e8ee474 100644 --- a/lib/error.c +++ b/lib/error.c @@ -46,6 +46,7 @@ static const char *errmsg[NLE_MAX+1] = { [NLE_PARSE_ERR] = "Unable to parse object", [NLE_NODEV] = "No such device", [NLE_IMMUTABLE] = "Immutable attribute", +[NLE_DUMP_INTR] = "Dump inconsistency detected, interrupted", }; /** diff --git a/lib/nl.c b/lib/nl.c index fc70374..cc450c7 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -559,7 +559,7 @@ do { \ static int recvmsgs(struct nl_sock *sk, struct nl_cb *cb) { - int n, err = 0, multipart = 0; + int n, err = 0, multipart = 0, interrupted = 0; unsigned char *buf = NULL; struct nlmsghdr *hdr; struct sockaddr_nl nla = {0}; @@ -631,6 +631,19 @@ continue_reading: if (hdr->nlmsg_flags & NLM_F_MULTI) multipart = 1; + + if (hdr->nlmsg_flags & NLM_F_DUMP_INTR) { + if (cb->cb_set[NL_CB_DUMP_INTR]) + NL_CB_CALL(cb, NL_CB_DUMP_INTR, msg); + else { + /* + * We have to continue reading to clear + * all messages until a NLMSG_DONE is + * received and report the inconsistency. + */ + interrupted = 1; + } + } /* Other side wishes to see an ack for this message */ if (hdr->nlmsg_flags & NLM_F_ACK) { @@ -738,6 +751,9 @@ out: free(buf); free(creds); + if (interrupted) + err = -NLE_DUMP_INTR; + return err; } From 63548f5664e0e149f5e51219ad6f582f985e3c42 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 14 Jul 2011 12:48:00 +0200 Subject: [PATCH 053/432] documentation updates --- doc/Doxyfile.in | 2 +- doc/Makefile.am | 24 +- doc/core.txt | 2 + doc/index.txt | 16 + doc/route.txt | 720 +++++++++++++++++++++++++++ doc/src/examples/NLA_PUT.c | 15 - doc/src/examples/msg_constr_attr.c | 51 -- doc/src/examples/msg_parse_attr.c | 50 -- doc/src/examples/my_parse.c | 11 - doc/src/examples/nl_cb_set.c | 14 - doc/src/examples/nl_send_simple.c | 11 - doc/src/examples/nla_flag.c | 7 - doc/src/examples/nla_for_each_attr.c | 11 - doc/src/examples/nla_nest_start.c | 16 - doc/src/examples/nla_ok.c | 10 - doc/src/examples/nla_parse_nested.c | 12 - doc/src/examples/nla_put.c | 14 - doc/src/examples/nlmsg_for_each.c | 7 - doc/src/examples/nlmsg_parse.c | 29 -- doc/src/examples/nlmsg_put.c | 31 -- doc/src/examples/sk_group_example.c | 43 -- doc/src/genl.c | 10 - doc/src/nf.c | 10 - doc/src/route.c | 10 - doc/src/toc.c | 7 +- lib/msg.c | 6 - lib/route/cls.c | 2 + lib/route/tc.c | 1 - 28 files changed, 758 insertions(+), 384 deletions(-) create mode 100644 doc/index.txt create mode 100644 doc/route.txt delete mode 100644 doc/src/examples/NLA_PUT.c delete mode 100644 doc/src/examples/msg_constr_attr.c delete mode 100644 doc/src/examples/msg_parse_attr.c delete mode 100644 doc/src/examples/my_parse.c delete mode 100644 doc/src/examples/nl_cb_set.c delete mode 100644 doc/src/examples/nl_send_simple.c delete mode 100644 doc/src/examples/nla_flag.c delete mode 100644 doc/src/examples/nla_for_each_attr.c delete mode 100644 doc/src/examples/nla_nest_start.c delete mode 100644 doc/src/examples/nla_ok.c delete mode 100644 doc/src/examples/nla_parse_nested.c delete mode 100644 doc/src/examples/nla_put.c delete mode 100644 doc/src/examples/nlmsg_for_each.c delete mode 100644 doc/src/examples/nlmsg_parse.c delete mode 100644 doc/src/examples/nlmsg_put.c delete mode 100644 doc/src/examples/sk_group_example.c delete mode 100644 doc/src/genl.c delete mode 100644 doc/src/nf.c delete mode 100644 doc/src/route.c diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 9bfb711..ed78bfe 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -642,7 +642,7 @@ EXCLUDE_SYMBOLS = # directories that contain example code fragments that are included (see # the \include command). -EXAMPLE_PATH = src/examples +EXAMPLE_PATH = src # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp diff --git a/doc/Makefile.am b/doc/Makefile.am index 0dd044b..dc52163 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,17 +1,25 @@ # -*- Makefile -*- -.PHONY: gendoc +.PHONY: gendoc api_refs asciidoc -ASCIIDOCOPTS=-n -a pygments -a toc -a language=c -a icons \ +ASCIIDOCOPTS=-a pygments -a language=c -a icons \ -a imagesdir="images/" \ -a stylesdir="${abs_srcdir}/stylesheets/" -gendoc: +%.html: %.txt + asciidoc $(ASCIIDOCOPTS) $< + ./doxygen-link.py libnl.dict $@ > doxygen-link.tmp + mv doxygen-link.tmp $@ + +asciidoc: core.html route.html index.html link.html + +api_ref: doxygen Doxyfile; ./gen-tags.sh | ./tags2dict.sh > libnl.dict - asciidoc $(ASCIIDOCOPTS) core.txt - ./doxygen-link.py libnl.dict core.html > core.tmp.html - mv core.tmp.html core.html -distclean-local: - rm -f api/* libnl.tags *.html; +gendoc: + $(MAKE) api_ref + $(MAKE) asciidoc + +clean-local: + rm -f api/* libnl.dict *.html; diff --git a/doc/core.txt b/doc/core.txt index 7ae3081..22b0e1c 100644 --- a/doc/core.txt +++ b/doc/core.txt @@ -8,6 +8,8 @@ Netlink Core Library ==================== Thomas Graf 3.0, March 30 2011: +:toc: +:numbered: == Introduction diff --git a/doc/index.txt b/doc/index.txt new file mode 100644 index 0000000..c59be0e --- /dev/null +++ b/doc/index.txt @@ -0,0 +1,16 @@ +libnl +===== +Thomas Graf +3.0, April 12 2011: + +== Table of Contents +=== Libraries + - link:core.html[Core Library] + - link:route.html[Routing Family] + +=== Tools + - link:link.html[Link Utility] + +=== Python Packages + - netlink.core + - netlink.route.link diff --git a/doc/route.txt b/doc/route.txt new file mode 100644 index 0000000..4c184e9 --- /dev/null +++ b/doc/route.txt @@ -0,0 +1,720 @@ +//// + vim.syntax: asciidoc + + Copyright (c) 2011 Thomas Graf +//// + +Netlink Routing Library +======================= +Thomas Graf +3.0, March 23 2011: +:toc: +:icons: +:numbered: + + +== Introduction + +== Introduction to the Library + +== Addresses + +== Links / Interfaces + +== Neighbouring + +== Routing + +== Traffic Control + +The traffic control architecture allows the queueing and +prioritization of packets before they are enqueued to the network +driver. To a limited degree it is also possible to take control of +network traffic as it enters the network stack. + +The architecture consists of three different types of modules: + +- *Queueing disciplines (qdisc)* provide a mechanism to enqueue packets + in different forms. They may be used to implement fair queueing, + prioritization of differentiated services, enforce bandwidth + limitations, or even to simulate network behaviour such as packet + loss and packet delay. Qdiscs can be classful in which case they + allow traffic classes described in the next paragraph to be attached + to them. + +- *Traffic classes (class)* are supported by several qdiscs to build + a tree structure for different types of traffic. Each class may be + assigned its own set of attributes such as bandwidth limits or + queueing priorities. Some qdiscs even allow borrowing of bandwidth + between classes. + +- *Classifiers (cls)* are used to decide which qdisc/class the packet + should be enqueued to. Different types of classifiers exists, + ranging from classification based on protocol header values to + classification based on packet priority or firewall marks. + Additionally most classifiers support *extended matches (ematch)* + which allow extending classifiers by a set of matcher modules, and + *actions* which allow classifiers to take actions such as mangling, + mirroring, or even rerouting of packets. + +.Default Qdisc + +The default qdisc used on all network devices is `pfifo_fast`. +Network devices which do not require a transmit queue such as the +loopback device do not have a default qdisc attached. The `pfifo_fast` +qdisc provides three bands to prioritize interactive traffic over bulk +traffic. Classification is based on the packet priority (diffserv). + +image:qdisc_default.png["Default Qdisc"] + +.Multiqueue Default Qdisc + +If the network device provides multiple transmit queues the `mq` +qdisc is used by default. It will automatically create a separate +class for each transmit queue available and will also replace +the single per device tx lock with a per queue lock. + +image:qdisc_mq.png["Multiqueue default Qdisc"] + +.Example of a customized classful qdisc setup + +The following figure illustrates a possible combination of different +queueing and classification modules to implement quality of service +needs. + +image:tc_overview.png["Classful Qdisc diagram"] + +=== Traffic Control Object + +Each type traffic control module (qdisc, class, classifier) is +represented by its own structure. All of them are based on the traffic +control object represented by `struct rtnl_tc` which itself is based +on the generic object `struct nl_object` to make it cacheable. The +traffic control object contains all attributes, implementation details +and statistics that are shared by all of the traffic control object +types. + +image:tc_obj.png["struct rtnl_tc hierarchy"] + +It is not possible to allocate a `struct rtnl_tc` object, instead the +actual tc object types must be allocated directly using +`rtnl_qdisc_alloc()`, `rtnl_class_alloc()`, `rtnl_cls_alloc()` and +then casted to `struct rtnl_tc` using the `TC_CAST()` macro. + +.Usage Example: Allocation, Casting, Freeing +[source,c] +----- +#include +#include + +struct rtnl_qdisc *qdisc; + +/* Allocation of a qdisc object */ +qdisc = rtnl_qdisc_alloc(); + +/* Cast the qdisc to a tc object using TC_CAST() to use rtnl_tc_ functions. */ +rtnl_tc_set_mpu(TC_CAST(qdisc), 64); + +/* Free the qdisc object */ +rtnl_qdisc_put(qdisc); +----- + +[[tc_attr]] +==== Attributes + +[cols="a,a", options="header", frame="topbot"] +|==================================================================== +| Attribute | C Interface +| +Handle:: +The handle uniquely identifies a tc object and is used to refer +to other tc objects when constructing tc trees. +| +[source,c] +----- +void rtnl_tc_set_handle(struct rtnl_tc *tc, uint32_t handle); +uint32_t rtnl_tc_get_handle(struct rtnl_tc *tc); +----- +| +IfIndex:: +The interface index specifies the network device the traffic object +is attached to. The function `rtnl_tc_set_link()` should be preferred +when setting the interface index. It stores the reference to the link +object in the tc object and allows retrieving the `mtu` and `linktype` +automatically. +| +[source,c] +----- +void rtnl_tc_set_ifindex(struct rtnl_tc *tc, int ifindex); +void rtnl_tc_set_link(struct rtnl_tc *tc, struct rtnl_link *link); +int rtnl_tc_get_ifindex(struct rtnl_tc *tc); +----- +| +LinkType:: +The link type specifies the kind of link that is used by the network +device (e.g. ethernet, ATM, ...). It is derived automatically when +the network device is specified with `rtnl_tc_set_link()`. +The default fallback is `ARPHRD_ETHER` (ethernet). +| +[source,c] +----- +void rtnl_tc_set_linktype(struct rtnl_tc *tc, uint32_t type); +uint32_t rtnl_tc_get_linktype(struct rtnl_tc *tc); +----- +| +Kind:: +The kind character string specifies the type of qdisc, class, +classifier. Setting the kind results in the module specific +structure being allocated. Therefore it is imperative to call +`rtnl_tc_set_kind()` before using any type specific API functions +such as `rtnl_htb_set_rate()`. +| +[source,c] +----- +int rtnl_tc_set_kind(struct rtnl_tc *tc, const char *kind); +char *rtnl_tc_get_kind(struct rtnl_tc *tc); +----- +| +MPU:: +The Minimum Packet Unit specifies the minimum packet size which will +be transmitted +ever be seen by this traffic control object. This value is used for +rate calculations. Not all object implementations will make use of +this value. The default value is 0. +| +[source,c] +----- +void rtnl_tc_set_mpu(struct rtnl_tc *tc, uint32_t mpu); +uint32_t rtnl_tc_get_mpu(struct rtnl_tc *tc); +----- +| +MTU:: +The Maximum Transmission Unit specifies the maximum packet size which +will be transmitted. The value is derived from the link specified +with `rtnl_tc_set_link()` if not overwritten with `rtnl_tc_set_mtu()`. +If no link and MTU is specified, the value defaults to 1500 +(ethernet). +| +[source,c] +----- +void rtnl_tc_set_mtu(struct rtnl_tc *tc, uint32_t mtu); +uint32_t rtnl_tc_get_mtu(struct rtnl_tc *tc); +----- +| +Overhead:: +The overhead specifies the additional overhead per packet caused by +the network layer. This value can be used to correct packet size +calculations if the packet size on the wire does not match the packet +size seen by the kernel. The default value is 0. +| +[source,c] +----- +void rtnl_tc_set_overhead(struct rtnl_tc *tc, uint32_t overhead); +uint32_t rtnl_tc_get_overhead(struct rtnl_tc *tc); +----- +| +Parent:: +Specifies the parent traffic control object. The parent is identifier +by its handle. Special values are: +- `TC_H_ROOT`: attach tc object directly to network device (root + qdisc, root classifier) +- `TC_H_INGRESS`: same as `TC_H_ROOT` but on the ingress side of the + network stack. +| +[source,c] +----- +void rtnl_tc_set_parent(struct rtnl_tc *tc, uint32_t parent); +uint32_t rtnl_tc_get_parent(struct rtnl_tc *tc); +----- +| +Statistics:: +Generic statistics, see <> for +additional information. +| +[source,c] +----- +uint64_t rtnl_tc_get_stat(struct rtnl_tc *tc, enum rtnl_tc_stat id); +----- +|==================================================================== + +[[tc_stats]] +==== Accessing Statistics + +The traffic control object holds a set of generic statistics. Not all +traffic control modules will make use of all of these statistics. Some +modules may provide additional statistics via their own APIs. + +.Statistic identifiers `(enum rtnl_tc_stat)` +[cols="m,,", options="header", frame="topbot"] +|==================================================================== +| ID | Type | Description +| RTNL_TC_PACKETS | Counter | Total # of packets transmitted +| RTNL_TC_BYTES | Counter | Total # of bytes transmitted +| RTNL_TC_RATE_BPS | Rate | Current bytes/s rate +| RTNL_TC_RATE_PPS | Rate | Current packets/s rate +| RTNL_TC_QLEN | Rate | Current length of the queue +| RTNL_TC_BACKLOG | Rate | # of packets currently backloged +| RTNL_TC_DROPS | Counter | # of packets dropped +| RTNL_TC_REQUEUES | Counter | # of packets requeued +| RTNL_TC_OVERLIMITS | Counter | # of packets that exceeded the limit +|==================================================================== + +NOTE: `RTNL_TC_RATE_BPS` and `RTNL_TC_RATE_PPS` only return meaningful + values if a rate estimator has been configured. + +.Usage Example: Retrieving tc statistics +[source,c] +------- +#include + +uint64_t drops, qlen; + +drops = rtnl_tc_get_stat(TC_CAST(qdisc), RTNL_TC_DROPS); +qlen = rtnl_tc_get_stat(TC_CAST(qdisc), RTNL_TC_QLEN); +------- + +==== Rate Table Calculations + +[[tc_qdisc]] +=== Queueing Discipline (qdisc) + +.Classless Qdisc + +The queueing discipline (qdisc) is used to implement fair queueing, +priorization or rate control. It provides a _enqueue()_ and +_dequeue()_ operation. Whenever a network packet leaves the networking +stack over a network device, be it a physical or virtual device, it +will be enqueued to a qdisc unless the device is queueless. The +_enqueue()_ operation is followed by an immediate call to _dequeue()_ +for the same qdisc to eventually retrieve a packet which can be +scheduled for transmission by the driver. Additionally, the networking +stack runs a watchdog which polls the qdisc regularly to dequeue and +send packets even if no new packets are being enqueued. + +This additional watchdog is required due to the fact that qdiscs may +hold on to packets and not return any packets upon _dequeue()_ in +order to enforce bandwidth restrictions. + +image:classless_qdisc_nbands.png[alt="Multiband Qdisc", float="right"] + +The figure illustrates a trivial example of a classless qdisc +consisting of three bands (queues). Use of multiple bands is a common +technique in qdiscs to implement fair queueing between flows or +prioritize differentiated services. + +Classless qdiscs can be regarded as a blackbox, their inner workings +can only be steered using the configuration parameters provided by the +qdisc. There is no way of taking influence on the structure of its +internal queues itself. + +.Classful Qdisc + +Classful qdiscs allow for the queueing structure and classification +process to be created by the user. + +image:classful_qdisc.png["Classful Qdisc"] + +The figure above shows a classful qdisc with a classifier attached to +it which will make the decision whether to enqueue a packet to traffic +class +1:1+ or +1:2+. Unlike with classless qdiscs, classful qdiscs +allow the classification process and the structure of the queues to be +defined by the user. This allows for complex traffic class rules to +be applied. + +.List of Qdisc Implementations +[options="header", frame="topbot", cols="2,1^,8"] +|====================================================================== +| Qdisc | Classful | Description +| ATM | Yes | FIXME +| Blackhole | No | This qdisc will drop all packets passed to it. +| CBQ | Yes | +The CBQ (Class Based Queueing) is a classful qdisc which allows +creating traffic classes and enforce bandwidth limitations for each +class. +| DRR | Yes | +The DRR (Deficit Round Robin) scheduler is a classful qdisc +impelemting fair queueing. Each class is assigned a quantum specyfing +the maximum number of bytes that can be served per round. Unused +quantum at the end of the round is carried over to the next round. +| DSMARK | Yes | FIXME +| FIFO | No | FIXME +| GRED | No | FIXME +| HFSC | Yes | FIXME +| HTB | Yes | FIXME +| mq | Yes | FIXME +| multiq | Yes | FIXME +| netem | No | FIXME +| Prio | Yes | FIXME +| RED | Yes | FIXME +| SFQ | Yes | FIXME +| TBF | Yes | FIXME +| teql | No | FIXME +|====================================================================== + + +.QDisc API Overview +[cols="a,a", options="header", frame="topbot"] +|==================================================================== +| Attribute | C Interface +| +Allocation / Freeing:: +| +[source,c] +----- +struct rtnl_qdisc *rtnl_qdisc_alloc(void); +void rtnl_qdisc_put(struct rtnl_qdisc *qdisc); +----- +| +Addition:: +| +[source,c] +----- +int rtnl_qdisc_build_add_request(struct rtnl_qdisc *qdisc, int flags, + struct nl_msg **result); +int rtnl_qdisc_add(struct nl_sock *sock, struct rtnl_qdisc *qdisc, + int flags); +----- +| +Modification:: +| +[source,c] +----- +int rtnl_qdisc_build_change_request(struct rtnl_qdisc *old, + struct rtnl_qdisc *new, + struct nl_msg **result); +int rtnl_qdisc_change(struct nl_sock *sock, struct rtnl_qdisc *old, + struct rtnl_qdisc *new); +----- +| +Deletion:: +| +[source,c] +----- +int rtnl_qdisc_build_delete_request(struct rtnl_qdisc *qdisc, + struct nl_msg **result); +int rtnl_qdisc_delete(struct nl_sock *sock, struct rtnl_qdisc *qdisc); +----- +| +Cache:: +| +[source,c] +----- +int rtnl_qdisc_alloc_cache(struct nl_sock *sock, + struct nl_cache **cache); +struct rtnl_qdisc *rtnl_qdisc_get(struct nl_cache *cache, int, uint32_t); + +struct rtnl_qdisc *rtnl_qdisc_get_by_parent(struct nl_cache *, int, uint32_t); +----- +|==================================================================== + +[[qdisc_get]] +==== Retrieving Qdisc Configuration + +The function rtnl_qdisc_alloc_cache() is used to retrieve the current +qdisc configuration in the kernel. It will construct a +RTM_GETQDISC+ +netlink message, requesting the complete list of qdiscs configured in +the kernel. + +[source,c] +------- +#include + +struct nl_cache *all_qdiscs; + +if (rtnl_link_alloc_cache(sock, &all_qdiscs) < 0) + /* error while retrieving qdisc cfg */ +------- + +The cache can be accessed using the following functions: + +- Search qdisc with matching ifindex and handle: ++ +[source,c] +-------- +struct rtnl_qdisc *rtnl_qdisc_get(struct nl_cache *cache, int ifindex, uint32_t handle); +-------- +- Search qdisc with matching ifindex and parent: ++ +[source,c] +-------- +struct rtnl_qdisc *rtnl_qdisc_get_by_parent(struct nl_cache *cache, int ifindex , uint32_t parent); +-------- +- Or any of the generic cache functions (e.g. nl_cache_search(), nl_cache_dump(), etc.) + +.Example: Search and print qdisc +[source,c] +------- +struct rtnl_qdisc *qdisc; +int ifindex; + +ifindex = rtnl_link_get_ifindex(eth0_obj); + +/* search for qdisc on eth0 with handle 1:0 */ +if (!(qdisc = rtnl_qdisc_get(all_qdiscs, ifindex, TC_HANDLE(1, 0)))) + /* no such qdisc found */ + +nl_object_dump(OBJ_CAST(qdisc), NULL); + +rtnl_qdisc_put(qdisc); +------- + +[[qdisc_add]] +==== Adding a Qdisc + +In order to add a new qdisc to the kernel, a qdisc object needs to be +allocated. It will hold all attributes of the new qdisc. + +[source,c] +----- +#include + +struct rtnl_qdisc *qdisc; + +if (!(qdisc = rtnl_qdisc_alloc())) + /* OOM error */ +----- + +The next step is to specify all generic qdisc attributes using the tc +object interface described in the section <>. + +The following attributes must be specified: +- IfIndex +- Parent +- Kind + +[source,c] +----- +/* Attach qdisc to device eth0 */ +rtnl_tc_set_link(TC_CAST(qdisc), eth0_obj); + +/* Make this the root qdisc */ +rtnl_tc_set_parent(TC_CAST(qdisc), TC_H_ROOT); + +/* Set qdisc identifier to 1:0, if left unspecified, a handle will be generated by the kernel. */ +rtnl_tc_set_handle(TC_CAST(qdisc), TC_HANDLE(1, 0)); + +/* Make this a HTB qdisc */ +rtnl_tc_set_kind(TC_CAST(qdisc), "htb"); +----- + +After specyfing the qdisc kind (rtnl_tc_set_kind()) the qdisc type +specific interface can be used to set attributes which are specific +to the respective qdisc implementations: + +[source,c] +------ +/* HTB feature: Make unclassified packets go to traffic class 1:5 */ +rtnl_htb_set_defcls(qdisc, TC_HANDLE(1, 5)); +------ + +Finally, the qdisc is ready to be added and can be passed on to the +function rntl_qdisc_add() which takes care of constructing a netlink +message requesting the addition of the new qdisc, sends the message to +the kernel and waits for the response by the kernel. The function +returns 0 if the qdisc has been added or updated successfully or a +negative error code if an error occured. + +CAUTION: The kernel operation for updating and adding a qdisc is the + same. Therefore when calling rtnl_qdisc_add() any existing + qdisc with matching handle will be updated unless the flag + NLM_F_EXCL is specified. + +The following flags may be specified: +[horizontal] +NLM_F_CREATE:: Create qdisc if it does not exist, otherwise + -NLE_OBJ_NOTFOUND is returned. +NLM_F_REPLACE:: If another qdisc is already attached to the same + parent and their handles mismatch, replace the qdisc + instead of returning -EEXIST. +NLM_F_EXCL:: Return -NLE_EXISTS if a qdisc with matching handles + exists already. + +WARNING: The function rtnl_qdisc_add() requires administrator + privileges. + +[source,c] +------ +/* Submit request to kernel and wait for response */ +err = rtnl_qdisc_add(sock, qdisc, NLM_F_CREATE); + +/* Return the qdisc object to free memory resources */ +rtnl_qdisc_put(qdisc); + +if (err < 0) { + fprintf(stderr, "Unable to add qdisc: %s\n", nl_geterror(err)); + return err; +} +------ + +==== Deleting a qdisc + +[source,c] +------ +#include + +struct rtnl_qdisc *qdisc; + +qdisc = rtnl_qdisc_alloc(); + +rtnl_tc_set_link(TC_CAST(qdisc), eth0_obj); +rtnl_tc_set_parent(TC_CAST(qdisc), TC_H_ROOT); + +rtnl_qdisc_delete(sock, qdisc) + +rtnl_qdisc_put(qdisc); +------ + +WARNING: The function rtnl_qdisc_delete() requires administrator + privileges. + + +[[qdisc_htb]] +==== HTB - Hierarchical Token Bucket + +.HTB Qdisc Attributes + +[cols="a,a", options="header", frame="topbot"] +|==================================================================== +| Attribute | C Interface +| +Default Class:: +The default class is the fallback class to which all traffic which +remained unclassified is directed to. If no default class or an +invalid default class is specified, packets are transmitted directly +to the next layer (direct transmissions). +| +[source,c] +----- +uint32_t rtnl_htb_get_defcls(struct rtnl_qdisc *qdisc); +int rtnl_htb_set_defcls(struct rtnl_qdisc *qdisc, uint32_t defcls); +----- +| +Rate to Quantum (r2q):: +TODO +| +[source,c] +----- +uint32_t rtnl_htb_get_rate2quantum(struct rtnl_qdisc *qdisc); +int rtnl_htb_set_rate2quantum(struct rtnl_qdisc *qdisc, uint32_t rate2quantum); +----- +|==================================================================== + + +.HTB Class Attributes + +[cols="a,a", options="header", frame="topbot"] +|==================================================================== +| Attribute | C Interface +| +Priority:: +| +[source,c] +----- +uint32_t rtnl_htb_get_prio(struct rtnl_class *class); +int rtnl_htb_set_prio(struct rtnl_class *class, uint32_t prio); +----- +| +Rate:: +The rate (bytes/s) specifies the maximum bandwidth an invidivual class +can use without borrowing. The rate of a class should always be greater +or erqual than the rate of its children. +| +[source,c] +----- +uint32_t rtnl_htb_get_rate(struct rtnl_class *class); +int rtnl_htb_set_rate(struct rtnl_class *class, uint32_t ceil); +----- +| +Ceil Rate:: +The ceil rate specifies the maximum bandwidth an invidivual class +can use. This includes bandwidth that is being borrowed from other +classes. Ceil defaults to the class rate implying that by default +the class will not borrow. The ceil rate of a class should always +be greater or erqual than the ceil rate of its children. +| +[source,c] +----- +uint32_t rtnl_htb_get_ceil(struct rtnl_class *class); +int rtnl_htb_set_ceil(struct rtnl_class *class, uint32_t ceil); +----- +| +Burst:: +TODO +| +[source,c] +----- +uint32_t rtnl_htb_get_rbuffer(struct rtnl_class *class); +int rtnl_htb_set_rbuffer(struct rtnl_class *class, uint32_t burst); +----- +| +Ceil Burst:: +TODO +| +[source,c] +----- +uint32_t rtnl_htb_get_bbuffer(struct rtnl_class *class); +int rtnl_htb_set_bbuffer(struct rtnl_class *class, uint32_t burst); +----- +| +Quantum:: +TODO +| +[source,c] +----- +int rtnl_htb_set_quantum(struct rtnl_class *class, uint32_t quantum); +----- +|==================================================================== + +extern int rtnl_htb_set_cbuffer(struct rtnl_class *, uint32_t); + + + + +[[tc_class]] +=== Class + +[options="header", cols="s,a,a,a,a"] +|======================================================================= +| | UNSPEC | TC_H_ROOT | 0:pY | pX:pY +| UNSPEC 3+^| +[horizontal] +qdisc =:: root-qdisc +class =:: root-qdisc:0 +| +[horizontal] +qdisc =:: pX:0 +class =:: pX:0 +| 0:hY 3+^| +[horizontal] +qdisc =:: root-qdisc +class =:: root-qdisc:hY +| +[horizontal] +qdisc =:: pX:0 +class =:: pX:hY +| hX:hY 3+^| +[horizontal] +qdisc =:: hX: +class =:: hX:hY +| +if pX != hX + return -EINVAL +[horizontal] +qdisc =:: hX: +class =:: hX:hY +|======================================================================= + +[[tc_cls]] +=== Classifier (cls) + +[[tc_classid_mngt]] +=== ClassID Management + +[[tc_pktloc]] +=== Packet Location Aliasing (pktloc) + +[[tc_api]] +=== Traffic Control Module API + + diff --git a/doc/src/examples/NLA_PUT.c b/doc/src/examples/NLA_PUT.c deleted file mode 100644 index c3afb47..0000000 --- a/doc/src/examples/NLA_PUT.c +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include - -void construct_attrs(struct nl_msg *msg) -{ - NLA_PUT_STRING(msg, MY_ATTR_FOO1, "some text"); - NLA_PUT_U32(msg, MY_ATTR_FOO1, 0x1010); - NLA_PUT_FLAG(msg, MY_ATTR_FOO3, 1); - - return 0; - -nla_put_failure: - /* NLA_PUT* macros jump here in case of an error */ - return -EMSGSIZE; -} diff --git a/doc/src/examples/msg_constr_attr.c b/doc/src/examples/msg_constr_attr.c deleted file mode 100644 index bfa00fe..0000000 --- a/doc/src/examples/msg_constr_attr.c +++ /dev/null @@ -1,51 +0,0 @@ -struct nl_msg *build_msg(int ifindex, struct nl_addr *lladdr, int mtu) -{ - struct nl_msg *msg; - struct nlattr *info, *vlan; - struct ifinfomsg ifi = { - .ifi_family = AF_INET, - .ifi_index = ifindex, - }; - - /* Allocate a default sized netlink message */ - if (!(msg = nlmsg_alloc_simple(RTM_SETLINK, 0))) - return NULL; - - /* Append the protocol specific header (struct ifinfomsg)*/ - if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0) - goto nla_put_failure - - /* Append a 32 bit integer attribute to carry the MTU */ - NLA_PUT_U32(msg, IFLA_MTU, mtu); - - /* Append a unspecific attribute to carry the link layer address */ - NLA_PUT_ADDR(msg, IFLA_ADDRESS, lladdr); - - /* Append a container for nested attributes to carry link information */ - if (!(info = nla_nest_start(msg, IFLA_LINKINFO))) - goto nla_put_failure; - - /* Put a string attribute into the container */ - NLA_PUT_STRING(msg, IFLA_INFO_KIND, "vlan"); - - /* - * Append another container inside the open container to carry - * vlan specific attributes - */ - if (!(vlan = nla_nest_start(msg, IFLA_INFO_DATA))) - goto nla_put_failure; - - /* add vlan specific info attributes here... */ - - /* Finish nesting the vlan attributes and close the second container. */ - nla_nest_end(msg, vlan); - - /* Finish nesting the link info attribute and close the first container. */ - nla_nest_end(msg, info); - - return msg; - -nla_put_failure: - nlmsg_free(msg); - return NULL; -} diff --git a/doc/src/examples/msg_parse_attr.c b/doc/src/examples/msg_parse_attr.c deleted file mode 100644 index 6e275e9..0000000 --- a/doc/src/examples/msg_parse_attr.c +++ /dev/null @@ -1,50 +0,0 @@ -int parse_message(struct nlmsghdr *hdr) -{ - /* - * The policy defines two attributes: a 32 bit integer and a container - * for nested attributes. - */ - struct nla_policy attr_policy[] = { - [ATTR_FOO] = { .type = NLA_U32 }, - [ATTR_BAR] = { .type = NLA_NESTED }, - }; - struct nlattr *attrs[ATTR_MAX+1]; - int err; - - /* - * The nlmsg_parse() function will make sure that the message contains - * enough payload to hold the header (struct my_hdr), validates any - * attributes attached to the messages and stores a pointer to each - * attribute in the attrs[] array accessable by attribute type. - */ - if ((err = nlmsg_parse(hdr, sizeof(struct my_hdr), attrs, ATTR_MAX, - attr_policy)) < 0) - goto errout; - - if (attrs[ATTR_FOO]) { - /* - * It is safe to directly access the attribute payload without - * any further checks since nlmsg_parse() enforced the policy. - */ - uint32_t foo = nla_get_u32(attrs[ATTR_FOO]); - } - - if (attrs[ATTR_BAR]) { - struct *nested[NESTED_MAX+1]; - - /* - * Attributes nested in a container can be parsed the same way - * as top level attributes. - */ - err = nla_parse_nested(nested, NESTED_MAX, attrs[ATTR_BAR], - nested_policy); - if (err < 0) - goto errout; - - // Process nested attributes here. - } - - err = 0; -errout: - return err; -} diff --git a/doc/src/examples/my_parse.c b/doc/src/examples/my_parse.c deleted file mode 100644 index c1ff637..0000000 --- a/doc/src/examples/my_parse.c +++ /dev/null @@ -1,11 +0,0 @@ -#include - -void my_parse(void *stream, int length) -{ - struct nlmsghdr *hdr = stream; - - while (nlmsg_ok(hdr, length)) { - // Parse message here - hdr = nlmsg_next(hdr, &length); - } -} diff --git a/doc/src/examples/nl_cb_set.c b/doc/src/examples/nl_cb_set.c deleted file mode 100644 index 4fbaefc..0000000 --- a/doc/src/examples/nl_cb_set.c +++ /dev/null @@ -1,14 +0,0 @@ -#include - -/* Allocate a callback set and initialize it to the verbose default set */ -struct nl_cb *cb = nl_cb_alloc(NL_CB_VERBOSE); - -/* Modify the set to call my_func() for all valid messages */ -nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, my_func, NULL); - -/* - * Set the error message handler to the verbose default implementation - * and direct it to print all errors to the given file descriptor. - */ -FILE *file = fopen(...); -nl_cb_err(cb, NL_CB_VERBOSE, NULL, file); diff --git a/doc/src/examples/nl_send_simple.c b/doc/src/examples/nl_send_simple.c deleted file mode 100644 index afbed7a..0000000 --- a/doc/src/examples/nl_send_simple.c +++ /dev/null @@ -1,11 +0,0 @@ -#include - -struct nl_sock *sk; -struct rtgenmsg rt_hdr = { - .rtgen_family = AF_UNSPEC, -}; - -sk = nl_socket_alloc(); -nl_connect(sk, NETLINK_ROUTE); - -nl_send_simple(sock, RTM_GETLINK, NLM_F_DUMP, &rt_hdr, sizeof(rt_hdr)); diff --git a/doc/src/examples/nla_flag.c b/doc/src/examples/nla_flag.c deleted file mode 100644 index dc3d0f9..0000000 --- a/doc/src/examples/nla_flag.c +++ /dev/null @@ -1,7 +0,0 @@ -/* nla_put_flag() appends a zero sized attribute to the message. */ -nla_put_flag(msg, ATTR_FLAG); - - -/* There is no need for a receival function, the presence is the value. */ -if (attrs[ATTR_FLAG]) - /* flag is present */ diff --git a/doc/src/examples/nla_for_each_attr.c b/doc/src/examples/nla_for_each_attr.c deleted file mode 100644 index 9d81835..0000000 --- a/doc/src/examples/nla_for_each_attr.c +++ /dev/null @@ -1,11 +0,0 @@ -#include - -struct nalttr *nla; -int rem; - -nla_for_each_attr(nla, attrstream, streamlen, rem) { - /* validate & parse attribute */ -} - -if (rem > 0) - /* unparsed attribute data */ diff --git a/doc/src/examples/nla_nest_start.c b/doc/src/examples/nla_nest_start.c deleted file mode 100644 index 51cd616..0000000 --- a/doc/src/examples/nla_nest_start.c +++ /dev/null @@ -1,16 +0,0 @@ -int put_opts(struct nl_msg *msg) -{ - struct nlattr *opts; - - if (!(opts = nla_nest_start(msg, ATTR_OPTS))) - goto nla_put_failure; - - NLA_PUT_U32(msg, NESTED_FOO, 123); - NLA_PUT_STRING(msg, NESTED_BAR, "some text"); - - nla_nest_end(msg, opts); - return 0; - -nla_put_failure: - return -EMSGSIZE; -} diff --git a/doc/src/examples/nla_ok.c b/doc/src/examples/nla_ok.c deleted file mode 100644 index 4485a96..0000000 --- a/doc/src/examples/nla_ok.c +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include - -struct nlattr *hdr = nlmsg_attrdata(msg, 0); -int remaining = nlmsg_attrlen(msg, 0); - -while (nla_ok(hdr, remaining)) { - /* parse attribute here */ - hdr = nla_next(hdr, &remaining); -}; diff --git a/doc/src/examples/nla_parse_nested.c b/doc/src/examples/nla_parse_nested.c deleted file mode 100644 index 563bfc8..0000000 --- a/doc/src/examples/nla_parse_nested.c +++ /dev/null @@ -1,12 +0,0 @@ -if (attrs[ATTR_OPTS]) { - struct nlattr *nested[NESTED_MAX+1]; - struct nla_policy nested_policy[] = { - [NESTED_FOO] = { .type = NLA_U32 }, - }; - - if (nla_parse_nested(nested, NESTED_MAX, attrs[ATTR_OPTS], nested_policy) < 0) - /* error */ - - if (nested[NESTED_FOO]) - uint32_t val = nla_get_u32(nested[NESTED_FOO]); -} diff --git a/doc/src/examples/nla_put.c b/doc/src/examples/nla_put.c deleted file mode 100644 index 0683fa5..0000000 --- a/doc/src/examples/nla_put.c +++ /dev/null @@ -1,14 +0,0 @@ -struct my_attr_struct { - uint32_t a; - uint32_t b; -}; - -int my_put(struct nl_msg *msg) -{ - struct my_attr_struct obj = { - .a = 10, - .b = 20, - }; - - return nla_put(msg, ATTR_MY_STRUCT, sizeof(obj), &obj); -} diff --git a/doc/src/examples/nlmsg_for_each.c b/doc/src/examples/nlmsg_for_each.c deleted file mode 100644 index ae2ee66..0000000 --- a/doc/src/examples/nlmsg_for_each.c +++ /dev/null @@ -1,7 +0,0 @@ -#include - -struct nlmsghdr *hdr; - -nlmsg_for_each(hdr, stream, length) { - /* do something with message */ -} diff --git a/doc/src/examples/nlmsg_parse.c b/doc/src/examples/nlmsg_parse.c deleted file mode 100644 index ac6acb3..0000000 --- a/doc/src/examples/nlmsg_parse.c +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include - -enum { - MY_ATTR_FOO = 1, - MY_ATTR_BAR, - __MY_ATTR_MAX, -}; - -#define MY_ATTR_MAX (__MY_ATTR_MAX - 1) - -static struct nla_policy my_policy[MY_ATTR_MAX+1] = { - [MY_ATTR_FOO] = { .type = NLA_U32 }, - [MY_ATTR_BAR] = { .type = NLA_STRING, - .maxlen = 16 }, -}; - -void parse_msg(struct nlmsghdr *nlh) -{ - struct nlattr *attrs[MY_ATTR_MAX+1]; - - if (nlmsg_parse(nlh, 0, attrs, MY_ATTR_MAX, my_policy) < 0) - /* error */ - - if (attrs[MY_ATTR_FOO]) { - /* MY_ATTR_FOO is present in message */ - printf("value: %u\n", nla_get_u32(attrs[MY_ATTR_FOO])); - } -} diff --git a/doc/src/examples/nlmsg_put.c b/doc/src/examples/nlmsg_put.c deleted file mode 100644 index 5e609c6..0000000 --- a/doc/src/examples/nlmsg_put.c +++ /dev/null @@ -1,31 +0,0 @@ -#include - -struct nlmsghdr *hdr; -struct nl_msg *msg; -struct myhdr { - uint32_t foo1, foo2; -} hdr = { 10, 20 }; - -/* Allocate a message with the default maximum message size */ -msg = nlmsg_alloc(); - -/* - * Add header with message type MY_MSGTYPE, the flag NLM_F_CREATE, - * let library fill port and sequence number, and reserve room for - * struct myhdr - */ -hdr = nlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, MY_MSGTYPE, sizeof(hdr), NLM_F_CREATE); - -/* Copy own header into newly reserved payload section */ -memcpy(nlmsg_data(hdr), &hdr, sizeof(hdr)); - -/* - * The message will now look like this: - * +-------------------+- - -+----------------+- - -+ - * | struct nlmsghdr | Pad | struct myhdr | Pad | - * +-------------------+-----+----------------+- - -+ - * nlh -^ / \ - * +--------+---------+ - * | foo1 | foo2 | - * +--------+---------+ - */ diff --git a/doc/src/examples/sk_group_example.c b/doc/src/examples/sk_group_example.c deleted file mode 100644 index f948e18..0000000 --- a/doc/src/examples/sk_group_example.c +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include -#include - -/* - * This function will be called for each valid netlink message received - * in nl_recvmsgs_default() - */ -static int my_func(struct nl_msg *msg, void *arg) -{ - return 0; -} - -struct nl_sock *sk; - -/* Allocate a new socket */ -sk = nl_socket_alloc(); - -/* - * Notifications do not use sequence numbers, disable sequence number - * checking. - */ -nl_socket_disable_seq_check(sk); - -/* - * Define a callback function, which will be called for each notification - * received - */ -nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, my_func, NULL); - -/* Connect to routing netlink protocol */ -nl_connect(sk, NETLINK_ROUTE); - -/* Subscribe to link notifications group */ -nl_socket_add_memberships(sk, RTNLGRP_LINK); - -/* - * Start receiving messages. The function nl_recvmsgs_default() will block - * until one or more netlink messages (notification) are received which - * will be passed on to my_func(). - */ -while (1) - nl_recvmsgs_default(sock); diff --git a/doc/src/genl.c b/doc/src/genl.c deleted file mode 100644 index 8585c62..0000000 --- a/doc/src/genl.c +++ /dev/null @@ -1,10 +0,0 @@ -/** - * \cond skip - * vim:syntax=doxygen - * \endcond - -\page genl_doc Generic Netlink Library (-lnl-genl) - -\section genl_intro Introduction - -*/ diff --git a/doc/src/nf.c b/doc/src/nf.c deleted file mode 100644 index 006500d..0000000 --- a/doc/src/nf.c +++ /dev/null @@ -1,10 +0,0 @@ -/** - * \cond skip - * vim:syntax=doxygen - * \endcond - -\page nf_doc Netfilter Netlink Library (-lnl-nf) - -\section nf_intro Introduction - -*/ diff --git a/doc/src/route.c b/doc/src/route.c deleted file mode 100644 index 2c042db..0000000 --- a/doc/src/route.c +++ /dev/null @@ -1,10 +0,0 @@ -/** - * \cond skip - * vim:syntax=doxygen - * \endcond - -\page route_doc Routing Netlink Library (-lnl-route) - -\section route_intro Introduction - -*/ diff --git a/doc/src/toc.c b/doc/src/toc.c index c33727c..ba7e07a 100644 --- a/doc/src/toc.c +++ b/doc/src/toc.c @@ -13,7 +13,7 @@ provide APIs on different levels of abstraction. The core library libnl.so provides a fundamental set of functions to deal with sockets, construct messages, and send/receive those messages. Additional high level interfaces for several individual netlink protocols are provided in separate -libraries (e.g. \ref route_doc "nl-route.so", \ref genl_doc "nl-genl.so", ...). +libraries (e.g. "nl-route.so", "nl-genl.so", ...). The library is designed to ensure that all components are optional, i.e. even though the core library provides a caching system which allows to @@ -28,11 +28,6 @@ version is used with a considerably older kernel. \section main_toc Table of Contents -- \subpage core_doc "1. Netlink Core Library (-lnl)" -- \subpage route_doc "2. Routing Netlink Library (-lnl-route)" -- \subpage genl_doc "3. Generic Netlink Library (-lnl-genl)" -- \subpage nf_doc "4. Netfilter Netlink Library (-lnl-nf)" - \section main_trees GIT Trees \subsection tree_dev Development Tree diff --git a/lib/msg.c b/lib/msg.c index 62f0911..ee2922c 100644 --- a/lib/msg.c +++ b/lib/msg.c @@ -181,8 +181,6 @@ static void __init init_msg_size(void) * Calculates size of netlink message based on payload length. * @arg payload Length of payload * - * See \ref core_msg_fmt_align for more information on alignment. - * * @return size of netlink message without padding. */ int nlmsg_size(int payload) @@ -201,8 +199,6 @@ int nlmsg_msg_size(int payload) * * This function is idential to nlmsg_size() + nlmsg_padlen(). * - * See \ref core_msg_fmt_align for more information on alignment. - * * @return Size of netlink message including padding. */ int nlmsg_total_size(int payload) @@ -218,8 +214,6 @@ int nlmsg_total_size(int payload) * the end of the message to ensure that the next netlink message header begins * properly aligned to NLMSG_ALIGNTO. * - * See \ref core_msg_fmt_align for more information on alignment. - * * @return Number of bytes of padding needed. */ int nlmsg_padlen(int payload) diff --git a/lib/route/cls.c b/lib/route/cls.c index aa79b09..fb2e9be 100644 --- a/lib/route/cls.c +++ b/lib/route/cls.c @@ -237,6 +237,7 @@ int rtnl_cls_change(struct nl_sock *sk, struct rtnl_cls *cls, int flags) /** * Build netlink message requesting the deletion of a classifier * @arg cls Classifier to delete + * @arg flags Additional netlink message flags * @arg result Pointer to store resulting netlink message * * The behaviour of this function is identical to rtnl_cls_delete() with @@ -264,6 +265,7 @@ int rtnl_cls_build_delete_request(struct rtnl_cls *cls, int flags, * Delete classifier * @arg sk Netlink socket * @arg cls Classifier to delete + * @arg flags Additional netlink message flags * * Builds a \c RTM_DELTFILTER netlink message requesting the deletion * of a classifier and sends the message to the kernel. diff --git a/lib/route/tc.c b/lib/route/tc.c index 7bd4728..6826a05 100644 --- a/lib/route/tc.c +++ b/lib/route/tc.c @@ -307,7 +307,6 @@ void rtnl_tc_set_link(struct rtnl_tc *tc, struct rtnl_link *link) /** * Get link of traffic control object * @arg tc traffic control object - * @arg link link object * * Returns the link of a traffic control object. The link is only * returned if it has been set before via rtnl_tc_set_link() or From 7d484555f6db215ebd506c2e0e808aea9f93997d Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Mon, 18 Jul 2011 08:50:42 +0200 Subject: [PATCH 054/432] Documentation updates - update to asciidoc 8.6.5 - added doc/README - switched to toc2 - started adding link documentation --- doc/Makefile.am | 6 +- doc/README | 6 + doc/core.txt | 11 +- doc/images/classless_qdisc_nbands.png | Bin 0 -> 17727 bytes doc/route.txt | 230 +++++-- doc/stylesheets/asciidoc-manpage.css | 18 + doc/stylesheets/{xhtml11.css => asciidoc.css} | 289 ++++++--- doc/stylesheets/docbook-xsl.css | 322 ++++++++++ doc/stylesheets/flask-manpage.css | 1 + doc/stylesheets/flask.css | 584 ++++++++++++++++++ doc/stylesheets/pygments.css | 106 ++-- doc/stylesheets/slidy.css | 445 +++++++++++++ doc/stylesheets/toc2.css | 34 + doc/stylesheets/volnitsky-manpage.css | 1 + doc/stylesheets/volnitsky.css | 435 +++++++++++++ doc/stylesheets/xhtml11-quirks.css | 43 ++ 16 files changed, 2316 insertions(+), 215 deletions(-) create mode 100644 doc/README create mode 100644 doc/images/classless_qdisc_nbands.png create mode 100644 doc/stylesheets/asciidoc-manpage.css rename doc/stylesheets/{xhtml11.css => asciidoc.css} (63%) create mode 100644 doc/stylesheets/docbook-xsl.css create mode 100644 doc/stylesheets/flask-manpage.css create mode 100644 doc/stylesheets/flask.css create mode 100644 doc/stylesheets/slidy.css create mode 100644 doc/stylesheets/toc2.css create mode 100644 doc/stylesheets/volnitsky-manpage.css create mode 100644 doc/stylesheets/volnitsky.css create mode 100644 doc/stylesheets/xhtml11-quirks.css diff --git a/doc/Makefile.am b/doc/Makefile.am index dc52163..165660b 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -3,7 +3,9 @@ .PHONY: gendoc api_refs asciidoc ASCIIDOCOPTS=-a pygments -a language=c -a icons \ - -a imagesdir="images/" \ + -a toc2 \ + -a imagesdir="./images/" \ + -a iconsdir="./images/icons" \ -a stylesdir="${abs_srcdir}/stylesheets/" %.html: %.txt @@ -11,7 +13,7 @@ ASCIIDOCOPTS=-a pygments -a language=c -a icons \ ./doxygen-link.py libnl.dict $@ > doxygen-link.tmp mv doxygen-link.tmp $@ -asciidoc: core.html route.html index.html link.html +asciidoc: core.html route.html index.html api_ref: doxygen Doxyfile; diff --git a/doc/README b/doc/README new file mode 100644 index 0000000..f4d1211 --- /dev/null +++ b/doc/README @@ -0,0 +1,6 @@ +Requirements to build documentation + +mscgen +asciidoc 8.6.5 +mscgen-filter-1.2 +doxygen diff --git a/doc/core.txt b/doc/core.txt index 22b0e1c..42f1035 100644 --- a/doc/core.txt +++ b/doc/core.txt @@ -4,11 +4,10 @@ Copyright (c) 2011 Thomas Graf //// -Netlink Core Library -==================== +Netlink Library (libnl) +======================= Thomas Graf -3.0, March 30 2011: -:toc: +3.0, July 17 2011: :numbered: == Introduction @@ -26,7 +25,7 @@ modified using a netlink based protocol. Several sub libraries exist which provide APIs to several netlink protocols: -- Adresses, Links, Neighbours, Routing & Traffic Control +- link:route.html[libnl-route] Adresses, Links, Neighbours, Routing & Traffic Control - Netfilter - Generic Netlink @@ -295,7 +294,7 @@ Error messages can be sent in response to a request. Error messages must use the standard message type +NLMSG_ERROR+. The payload consists of a error code and the original netlink mesage header of the request. -.Netlink Error Message Header (+struct nlmsggerr) +.Netlink Error Message Header (+struct nlmsggerr+) [cols="^,^", width="50%"] |============================================================== 2+| Length diff --git a/doc/images/classless_qdisc_nbands.png b/doc/images/classless_qdisc_nbands.png new file mode 100644 index 0000000000000000000000000000000000000000..14cb0260f17086036543c3a0f4df507fa520be6c GIT binary patch literal 17727 zcmb4qWl&vBuq_%ONRZ$b+}+*XU4py2ySux)yC2*&5G1&JfN;=2aCrNxd+XKv`+iVx z_Swwz^vv|EUaKcsSy2l4Gu~$i2nb{uX>nBu2*@(v?_+o<;IAWH@@U`#f|In4D+C0} zAK>Q=No#yqK}4;58l5q8Hw=8rmput@Ai!3U`9F7snd(FcRw7v!+ukfr|U>79V{m;4UdB2;pD{a_vqAU z(D!_I_V)s`d%4kW`>RYQm&@_}W`Z~!92*xm^W&L_GvL)ZPgjnlD5EjD%V}S<{Che$ z)VWh%RdqPbhyorb@~`&T&?C2FmfI)G$ca45pEghjuZ0h>v2+3xd?>Zh{WbwcloSHt zuKB!y%qADQt7nVmaiOihRHg*WeRUbB0v6Cb$;doevptmfD<>ePf+%Gw4I zq#BRDT-nMQC;4xD#XlojuY@9h0cj8PFC0yAIlGRr;e?l=3D`M{kd9>Nu+X=|7IAOP6p;f;Fc4F{l*XE;ih! zGZA+)Q}9X}fyVMLel!-~snHA3jOHhy2xPrfK37`7Tw_E`K3~tfDf} ziD^)xe?%m6nA~c^GD~!g_ICHXhsSN;SBmK@v+`#Rg}VG!w=>2ID4VMm?uqZ5O#M}w zHF4HS{<>cg1%~DpTiunDYE#upgMv18c81lt)YLu{l$8AL;9+dJXo{)R{bkqT?a_ZV z;RumPMQ8jFEVmOkg8b-o&lZ#U_PZnycHx zN|ol>a^TsomNwdLZeRRE;8So;ewRx!yubz8Boob7FO*2x_=~R#J#KYENc)kD0r*0 zIvoE<|9diL`K2L&kguf28rbSy>aW1|wqY<$WJ1&DTUhwg<1SVimJfQ6_WN-1^t4;Q z-Nx2nq_-8MBxH~ImAzM= zFQK+V%Qhp-bHZUwd1dJDER(f!41E~F@p$xQx{T~I!PE#8>SXWbJe=;md|%vXUr1J)Th*#|CFh|- zB;;u+Dd~j!a%pMNvh-t_cHWv@H7k;`yeaEm@E!qCjgAb{#fEJ$(|UoB=NW5!^cG9M znQ~lo7d#W1FW#sAjAbC@ZG4i+9PQnNp=;FFhH1)WcC{lA3J3ixaWb1PuZZI2xw}=1 z&GZjGal0n?c`XT2xqV9`=ZqC#xv+c3I=QH_wzGzdugmT z&@t+#pm1Atn1GGmr1tj-@+|}f<90Z#P@^Jtb_!`Cpj{wKF@6szauY0{O0af|dh02B zX2J2fXJ`{AHencA;x&&LWoy>!dV6~p$Cjv7Dq7AJm~U_3#NFPn8cKW6+SVf?TrA9-V zkB^p9?##1yVisGGtcWLHYnbc$|Zqv zIH$?A(O73iH-jU`ChJBZ?oL42m$7@dof7Q!QD|O>FcI);c5FoDOpcPccb0iLQo(Nm zO^`0^V`0O&jS@_d@9wW@gwt2q=q#vf8$6fObU4QC0bVN>i+nWK5HEM2hJ$-DLN`Wd zKcxl9k*@2PX9O`Ll-3TSQ2sk#RpQ9TQnaw3>_0rPZNS2Xb`)sfMp8HNa{TX z&2w~%uVN|Z)$ ziSv(={VcS9BApL^Tva{QX6_;sVm{_1L=)JRU@XRd?3R>Ft5s?u#mB|whG(bPxM&#D zyy!1oYz}eQ)?QjOJluybvv8>g^UHQ;+(TudD55g6_dPRHhmA|Gt(D*|T75T#Cn`Y8!9P$`KF2 z0_~B3kOW@~&xcl&PSI=vu8@!d-T!s%01>Z>3kso$;f4wb41m|w_;GwH+DyQL=PStJ zeWh73-G{S;^SG?*fhYvRm3vIkpX~a)Ti0e4e+}A7h7cNRkRafCPwDN2 ztwP+AZhUrXrvNz-mVKbMj*XVXX>uv1IdwAEP0RKZm^tF3B+c-fJ5z5$3Ksj0*N?3( zje!2eX7viR5oWpePq{-^@@hsHN1|)daM?{{;8C(~g5}9?|KTWLhA|uyG|JTz2@3^- zr|!nayqMC685tS1*{XmQgN)Dl`u=jY4o1A*?6CK}Igp?yPb(};RN=2wDjd&)s{2+f zt)8#+r+Gw}Og`iBVK*@H^9riFiwhpJ5d_vpr_(;vrx;_aFW-}BI61LQm6w0n-=B&^LStfLyl6?#{@R+HScc$8am#B^mm=z$S9hjFMLBzWtGuF*e0{ihNvro6 z&XQHr7+mVZS~i_v!$3#kCXq@X-{`B6pXGV5L=SKWM-YCzJCye4F;M+Nzts~U6!2$f z3{scTEkrb?F!rMg!f+{)IaBrA_A#pLQDsO$N%)5l94JrF)#O*mE_aqab#ixS&mY@JJ zmI9-lwfFCW+&FU$<|%{nw%jh>MO_Sx!>E-|c4YRINQswWl#z$$iRI8Z8I=!(!0BwcR?2vPEFOPO;IDitabWKcY!wf8_q3@a z|8DJpEQZ<{;kcL-CX~iQHe7@#qH+bQjYw8zuWCCYl%#%HrK?okW z(aB`85%#)WTBQo^I&{A67s2URnkhs3wPFmfA89nt7O_)Pb_w{$ zH4I%gU9C{a-P+RgyE9P(v9Yo?(Gd0DgSUG?fgkU4LLYwTEA={xkI&G8FJ_RU84CZ!Dn)y)h8U#V3v7OHCV_Qi)h*SD!yi)%3U@pZ;ywHugRLseRO& zeq3!dw1nxv9US@_gj1jlmLs#Qp$Ie7W{xkMW{-~RZQ#w$*0WsMRc&eIQIpojb84#p^#P{a z-+x44;AF|SyHzknrZJ)bBdL@*>h5D>EgzHJEmz1G+>;G38)nF+m&)X#@7k@=tQ*H? zhUGu%w)%jZnB;vN9CRHRJ0hl-=wX7J?WWe(?T(EY28;TR4=*pT&Tz}LBjJ7FO%bsj zwX`~tV>7~DGk~26s^6Dj#Wnr}b_=9q#{Im(_RFjZw`tL#3UiwRJgS9dYzg7v_fzPG zmzsj4hzjbCsg}x!+yMz@@**yn^lTmj(uGd|lFZrkn-QIZWr$MBcohoWO7U5|p?$L5 z*oA}NOMRIfel_f>N7kA#RxZ<-fx&lYzHKxT8H{hj4wg_!G>GOvTWM%4L-$vnSCmJ; z6={gQKW_I&Y_oRV*x6?7j~k9o52= z%V2$Xh5KT1KiNEyAW{@zf{}R_5~ASj>_{^nJM0{~&g{yTHaJf|b%7+IEdHDy`iZ2# zxO#H!?yif4WgdcwzP)ubGYJATjZqitLP1vQn9qCNH8VWCoXI5BX6s4HgL{iwfR1_3 zN6D&vBH~~f;WKhuM!#XKVnOr|d;#vbPjCEsczHCMB}9kiWq)$@g_8e^AY2FwiCv#y zq-xS8Bn+>7JVaN1HCp9sP*8oR{-H|gr}M=^nb~4&s4SV-E8*_IswPa(BBD5Y1|Hzi zYBb6>8`N(gHR#XHWs*T#iZ)>~19&iXgBJxpf2xJvAE90QYVy8RRQQdyNW(}s;^^q;ZvihCTpg-{mkt|k2>rvF6T5xBTq}>t3MgD}&*zQB zsJ0>Byypr8fW4O}2i6H<)2ts-rTd2Sw({MPC1-XeAt=B>OIv%bR*Q-LG3)|o1LQd1 zxGPwf3=7}V+PbbPrQhv#b9c7|uoZE*Y=eQv=~{T~R?Ln&z3%5L}<`0(f6;(?v}B&T^wkrR^S1sn-!`!r8YWIAW)MMwst-=`tOEw7zGOuTY2T%U38a zcUoX!%}Zc2uB@RmVp7om&f#b&mwWhGDCGC-=FL$pkcHk35@%cP-0q0dF6O1emhw0| zjr%h1k)UWkZIQ0eo2hT|7iG)cBi-;)+xy>Dz2|YJgSoW`;+KhA^`ywS*q+kN!dT^? z1%Tn8`IziuCTlJ#>r68z8K9Vx6+{{_NamSd8k#CtA7{iwH?Le1n_5dd4rH6X_fqNS zry#VD5{}>OYbxVq-@LfE;QgTL+{Q4k#nSTY<}vb^nF{*zqVTW%9uJiCz3Y~<(Hk54 zB?KzYfR0a3|F|>`Nhk(U&P$w2@B95?5#@%)faqtrvPZo><;mobS%39YLS+_d{TTWz zMPJ{<<=WQH0CqW9S=#s5uUDoXR7zOz=AFz@RaJ1@o14Ck2Ko!a^t80jw2rdr8CY^G zVe7xQ6ydww+UP6S_=I%?0vlEPjR)IHP3=8B?V02!-3Ei2b6f_6RpGh$A`dEMKKW5h zyAxZN$WV3VQ<@{9CkSOyaH8N0yulUM1SoXPFj%B27%BXseNl>Jm)-%dZU65B# zf!jnW`X0ADPv=P}DmV=Ow7iI?ACrP=(MegLV7q?gHk%&7ps;keRp@kHFX!bQ`adsq z2MExyun-%PH5p1oqGX+41Stq%(Q`jdQN_Bryf2kO`?i*jRkuY)DnE`!=N(R5A@E2R zPhG@8mA0gm496HC9s8Cv+|+;Z{T3mF0X|SU8~O4nwE2r6A>T9W*ejp*!{xi7|2<|_ zUTF>+zEyGe2SVoPztlWVQXmM4GpB3huV*hgYZLa(*1s$#ywPu$QHc|pX+Ln@zWQ)yNGNe#TK^>l{ts_s<`rI38ja_-5C zGU0SL&0vTweN2c2dm2>KE026$cV2&8Q`42Gj_2p+ipokZ+Z8YXnI+ZbYG$H<@bIuV z1a0>g$I!;Y`37EZZNfiXW$}jlJH!kJ#pclT;9+A!JDc^OtgIZw!?&jN^k=y?35JS? z$NTYmUn+rMh{B*HDQQ>Y(DUq9`5KN+6|#xn0q*bOd~W9w+tmi6U&a^krzaj+4kN!M zjfm|z>7djm_gsaGO(zmgyGNHkKN3L03O)=YG8y%MVJr-IwwC8XL`F7Oqu7helKb=? zkI$9GT#;=&TcV8rxHg8*W|lqp`t-N8h4xbh3uS)&SIGRWhN7y;F&V}wKa^1*SJVmC zIfeRJu{KC368Ny~X@^Hzk;KBni4mtXxBvZzDJ>p`Q7ch;8;}y%U2L=i!JWKAaDrTq z(t7Xd0#xYtcHio}75(czZK4g5IL=`6YAs8XY<%8IE(e=m7sRQ%pS-GB#*?efJID(2*p zsKRimVd*=3eVP(_O-jkPH^L?JyfWZ+s|uEtPvvJ|pre*H)y#saKPxz8t#R&2&gb2y znmL=lKOdg{qad`|Ko~I0I*eA!1yx;5x~&+MV$g;MQd8JfYO?A3qkn$z`u4D$g6`PP zX_}O%+h0RggUN>YcQm?Jqn4=V=kq86R=Hj{R6|1otIk-E@4x4V$HQ%<{BHN7$?cN@ z+Ya;T^6P8f+1Z4LtCO&>rCvXt>N0Yf`T(&k-mZKSTy5QrQYohFG4kjLZxn*Znu-G? z0_sAa!@Zye*t#2C=d=g*H0K|cC+r=qwy%HZ08A~?+-wd?IeK4Nnq>s(NzM}UxR_~c zYiEb832~lym;|%3=ZlZv~@4<`T`Ax$K)pT-AaynJf(X|j%O8}oJ=U#USgicq;TVi9rS$@3l zvSfDOs>J)Fz*2x}^)`PQ9%Es0+%{+O7QnY`Jj->=&%q;Hdav_Wmd1 zUf1uP|8JSpvF*Fa+|QYrp`jr!f<%qF59aeD8OlYLZxF3$O~N(*dg=c$0nAq(O^46JGD)RwpRcWe=5I>+0zCnZk`&IQk_ag zij(7bE&3{r)kQXa$`K-W!?B5h&3=JJPO~e6Fp!}8AEa&2mpn=iTfvz*sir(^jMgH3 zKBkkFJ}y{e1ul$asKb5&v%Z9|8)O|y-y-`vemNi3-b0-D^=c^h2{$PP>X}m z{rSU>WHKuh#;Yydh=#Kbj@zxStfi%o4m)cAgN7t+W)EE?9b>qkA57f7x4zbUWDkRI zFs?AZ?S0?9yZp%w?rq{n{hX~SmAa{;pRNHHI(1Pa#-OW@J9$yp@S`Sl=*VNa7^}Vk zspG)I)x@N(%0Z8SV676-ws~EES(!=Ae)!^bqphoGF3GkJmE8DS(Um%8t`pxalAKu3 z*6c5vQA#igs5RQAqfInrQ%5&`Ell9ZgHz>ahNiR&pIj|kZd2seEM?95ug|~%ZOvhV z@h@p}U7X{)E(yc-1+%HqXcU^E-_6)gpRb|M8HHSEA{Z?)sJtgXH#b+FQf%GgXO4se zRYL*;b9#US2p~w;TP>M%+fJWO3N2r%yu7{R3HdyLlK_KKzSH?IqO|mos?hKDvgbM!Ml!3pqe9F^zBmP6!lH6e$PN!8w|DAf*l>jeHY61%j zyWi`u-Tm?YFaQAsLx2*@z{iLG4*4K@4ZXX&OKjPTx@Y`Zl;#N#4SxU3g?mp`63oud z?y_BF9PQoP+q=GY+JY)1etEe1xE}fPR8AtENaWt_UR$gw=5{wS@Ug-fs$ow{m<8pabZ9jiRNfm!xhC>+e<>y8)^?K! zV~NC64#%x|a9n`&frqS!T-!oC9*3wdnjqB-%V9wOfc`3S>Z})B=RdFJg6j-ge+x_1 z31j!P*`Geo6H=Ao9@kyOh5Bss99JsIxgY}2K?%APRpgdbIEQTyg~6Q7{LaaEb(`j! zjUjIq5=G6A=n*t!j~+QVB0ZiIRp(8K9r2Oaz>}A&;Dk3qcLg9FYGu>h$)YI#-tGjNktI3yz2xz2-ksn!K!k5Y*E#nS)vx&)c=X_XM9Dmi~EJO^*b% zCU@zQmv>4)D)H4UuUr&lugd#QQS`|zDDw3JpV={At_H3$(~he8@CoxPGMGZv1FCu% zq$4R|>}D?#h(Dw-uq2NPH~k9>T6M46ctDFG;b@NSmyPdYQE073HNgC8_vs39i`^Ry zZ4M3D-v4=dW%POUwhXYgZjO9?+f=%^o%53`Q#d^x}?P1V!${jFW5;;Q48b2tkM$git-LrGWWkvzS5i> zLqDWHYI;stGUA)?0AT6VTK*hRGTr8=+sn%qeVG1BpL!x6ZkhL#(3jKG6Yw-XKHiyd z)EKCg96AHu7_hM;NyLa=-X2EZ-)xBm^?Loh(=yI@78VkjiKs|TL=ASDf9TRRtPvE( z*pjInc}POFwB!_3V7{1Y^_w2mMq}VdgnPSRF&6TVSN>r>SgMw1ZkM0a>AGcXji6HJ z00?}QWBf@H5F4uS{nVAg4D-Pj1QK36U%|%T%LoL)kHnewCr*IArH50WV>K-(D>SZi=}S%i%a~0=$^8 z7YWRH#uzVetKB48(5bW{^X^3D_Y^vF)~UCyeC|d(LZRob{DYEtJp+InHw^7#a*@-acFj))SbPSC_lR1yS5Cy znNj%Y7Cyro056o<<(kbl69D{|%byY(xjlPr<5Fj@F(W|*WWH0MN9IPGc#9MO++bWk zo1Gv0p1)fDB{HIoIP6&mcKu&JYD8ZACxk&0;b#O%%>Ag_rYqw%KXe`3kpY z!5T(MkX(*FTRmDySy`}DFV`cdn)Nng;}y)$2V;GJXasdGnBF*4ny2FC#;g7B-=!#I z9kObjHbj_AE05q08svUT5F3tYD{U6r3B;V?d1o_HbJ!m_$2>pD)7jP>;XrtgTLwE*$ym^9KL;cSI z`U<3w%h~+q={0E7kiSzsryGvNQmq>Jv}|LVz#!1AP;_mAvPZcj;*)X*QRWYg7h`}$S(a>3(Qzz zTI0R;b10YDs9Qu6d<`rgJ%Ms_%p&9;`0>g834V& z?pN6qz_3RkWAA&cc_8r#kysgj@WIf+8(~vFV(Gg4%;lP(;A|4JbsUSq1g2@6V)!VJ z$91pA%ZV&Kg%kc7+BXu=P4f+7C{bNnTKZShwwBxPU#>pN&Kh8Eu^DnQ^WS1AM{2f= zBNg^VZr59L58{&P?f7G_`Tc!<%?TB*q=j4c2RKZWpydS}uYw#6!Bn4~>p@4;R|5^) z!q@g^S+Aqf7}@->-c~3ra=jGHA^GWT!BfP$ktl?st*X@YIVFQNuGb7g$)#C8DBLT(t&=-?yuIcy_C!`ZoG{glo{(>qVgT zq>yk!*rs7E&u@E^$;4|Zk6T4EK>LZAOr7v#| zI`m$>zgaIo^_BCxi(<2nRK6ARM`YwhI?YX1Ick@mTpRds@#-9x7spmB-Mpy_iCc0V z!qmkcdQ~#am57A&XJd_dZMV(-nOkevX8w4ssM~_7KU1@=p5EV*%+f1Yv&#uL+s_{=mA+VQ-2DlKD-H;-?&=bZ8QP>b^ka1(!hvU# z^!Q_z2BvhoN&r8Hh3m^p4`SPxNi8U%U$KbO)JW0ryyUF+H~6)SX&Ofq?h>)XZ}6_J zt{qM~;1-}QUatf}ZnUb=wp7T)c;qCJ^oPN(g>4r99q#V_$-IDoaZO(5;ab~)0D_)e zZrPmKnk5qq1bB)YcokU$fPhGaP*>H#1P%-h67dHLVL%pvQkF5-fKS@g2uIz{{Er4f z5T;1iAlVzGywswQd_aH{4MJ^lfH}pr-M*Jv!GH=2N`O~x0-TCY1_KXyE*TV(@4iZ` zqXdr%#Y-wYq$pJ+9f$f2rVbzSv&V{lpqT)PF#Ks01S}t6Fe%Ibv_-w9;@Av3J)nd*o{_XWVwA$)%G5LQZRD40Pqn6d9*dlI}0k*V(cVF&G35CGDC`) zg?5{i$>EqE00S>2x(x{b^4Vm^67V>P!6w;tWmP7jkfzngKGbW@)KTAH;Di6f zLBRI>(d$v?1T5GC>_1dS6#*<>#s#cg?((R%1B@92`kyHNR`N`ytghQFM6$1}`m26s z=JmkDP-}IizyG7!a6m^R*VVDd|E2bPRp@-DFB$aEyI6ThEbt7JIQ~i0x~C-p`q3y< z$3uqyHq(bj=+8!H>vlLU$LH?S0~vxvGxbZQB*SB$PwGbZ)uFP-U)4e{ zN0buX67vLXPK#mI7*v6FYTU(m$XSa*_e7Oe)1mKIv$cUDnN;S2C zKJUMh78Rh@zePpgw1%7{jHelUnwo({!CLwucM5_=7I;L5u=$#22+|JAUuA{TxZbKu%>+o~F+Z_#zLPgPR z#P#oVVK^m)$>;9c#Un!ALS(3{ikfjInmya@Xn$lbA|hb5hs*SU(0i)O)e%UTXC~nC zR+aJ|x%mE*8iQjlG~{IEEDQL%Zl2vo^|(atjy^{xeFfZ~GA#Fl0V)_`Y<8jg=_#kq zyJ)R9B|2YPrmHZMtJPc%>ny1(B6hk~A;-_}EJf8tNNW|e*`be#-vbn~`1-yuJ35Xo zjuG-MX@+&w;^M9n3*cd3jgu1oDmm^1!X5>Mn>8y8^;$NP&5ubtcrR`q1>2q1)>^Gq zgFfCqZ&!Qi&e5`o6|5|LDglG*?1FhXW}olAJc=e#;uFa+&BPz-AydlBqW* zxmK5!o*Nttx12*+@4Bk=xQ4CkU>L%(M> zI+`alNfR_^`$9;Q+0?n`L5NjwDSU!v(c^z#SC>*Pnitk+Q6=@smgh2Hm zErq$BHV(|j^V0qY1|NB}(+{ks!r+&t&C?6nX7r*#0vD z^*as_;Wtyb!d20(Kz`;9iB*5mDVnh6jwI{jZb%{U#laEORz%}|I1 z<8aBT6!WfcZnA;8#4rR5K!ENFczce+$Nv|}gqZ#1>1jU&<-cL0!jL0*(9qBTnBIQ7 z`yQYTpKP}QD}h?hSZo2!02n^h9*>LX#si2qfXx3-6RN5@1>X9JIniu7!T%NC`EtFr z5-7=nr?cX1J_5)*38$lE6nQ770#@@F#xDFU0>`=@&#QN!2FtrlYz2^pxeW&b`sgmm zV85MygQ5Qfi4dw^DCqxdaS`zKpN2IZMeU=wIHa~Er}Nw6>8rj6B3(;xgFGdWc-&IbzF zNeQ#yvEU7WzK);(2hq~gi-YNCXu7=rQkD=6z?zK5;R2M{Bg$Zw*9A~r=5x`$+BqY~ z)CU8}-Z@y!>It1nEEGV{h4j^KIz$d9(F)O`&*#2V!-5KnG0)Uei+nh4axxJNCXgU! zcT54uPRu^s-|fLJ*rd#X?|!efpLr~bDcX#Hxv+}mu>J+}vk<5*3hM|93j>5T1b-W9 z8(rOvFG8@=}xx7x7aMxl8@3cJfF?$ZS;D(y12N29JV*wtVhC{8CZ5a z7Lr#>BoKQQ50-I~QJDIzR78b+FHxD9d3@d7ot%uuoBpmfn~K=&_UliwGsP3ly}pt; z_S1ZLm8>?KjNL~?%}~g3o~8dl4_mO089}Ef!KeTH-xTil`=j}LS?~IsGbn}%e+c|L z|LP)qSfAl)phfVC&f>6CrP8YdCul-}LOIy4+5iUanmz40uVlgze*4|AnmFoe?wOoeZ5P58jgE3MN zV|AJt0f7y@0sYnCxQcSnmuO;E-Nx3?(7A&#+dEkkMq`A~eCOD^<4i*zZ*P(vT&;R5 zdoPT@lYGx>eXpSq*i#$uR@dJo60ww&6mhyGmi@#lP5v*hA=~Gm8w6`Lwx;6BgejSs z5>(~39#e~-HYJTf`TVx9Zin*uaQM}v*@-x{PU~+$Ep*&2Y04gQ*(tFG@m9QJYin4z(Q8?tQgMv-IG!;nBPnvXOK6(ZjMn*7szF6FxRMRrvIwxbE3bE6G)3A?m0g?*gIU({H=ErFKth&Ff;RY zJv(0pdE=!B!TWvgWo)b*AWD6oJAvKM)9VOJA`+}zq6A4W~RR{L>NFV7CQ z>MVs-{WMMVI<8C|kole{$IU6mELRc!ezy7Zc6BT@1#-ppKUCi+HPex<&1n}EU!*@58LN(I6O_x# zUC4gcXMIkzG6Z=eUj?<$#>Tz&adS<~D$e*a4kO1}O~RAJSx#i{IpK*UEuLx|x#crE zzG~}^a=+r}H<~NF;%syGnm~ALiUh|+yGBwS-=q;LN3CJMXt~t(`vlt2tcnEMn=}n-N+y zA<)9cO>qxanDD*rI)lzFrXZcQji>4FPA8OXCE_ie^ zpVMB;BoKa^+vIG~sty}E;Y#{3 zk|NXT1Wf@nxJI|?rZ5V_1=Vi7nkD(62H7a-K~>cGW^<|90&UrFoh(A&tgaKCB=`w` zy4JE-7j(JC4xF-f-Ou&4*SsCzx>{wk`lpB|lI(f}ND-E)f-xT1Lrxh_+M^|Bik#-k}vtk7YF*5Mk^;!p?_v*s6yTcq{s}hW5Wh|p9$wb22}L!Ht?OM%?gZ!1OlIjUANoW z>|r9v)!kjt=^G_?=gRf|n`YzAr=H()#4ig{yO>|U3O?xV_IMJHj_L(xRaR~m2vEJg zLRrr0eaimzYYP_9z|{%0xwm04g#usaEH;+7_vMlv4$ksz$VtD&tna;gCN(4^-`lBD zPvTpV+_YktE*oWZoL*8UcKO=x-w-oaq`O{J?M>G;Cg-L-cXx?Y@o0msT6fwz$25Gb)O&+9oM&e zQoMgBiYHWLHX?d-jg~wma@@MyI34+s0N1v3wW|VT(2KKZ-}WOHh=|O;)70!xB90X4LHm%6i=|T=GG^>RiD3y>mJ?*>J*CUjg;d`eVgQpg3pP9{=sUJF??1n!~2o!$E0UkNGC&c%k&PJi}&3 z^2L|+vfKes;QD*g#V5D}iZm_~M3-15LfLT_r?nF#e7W&LdDnZl(SH_RrV@M&7WP`; z*m2gH?ZHx6g7Ez>xnd@z?JRQ%&d60!5gImoP(wpI4h{ydDe(G$NtKAQ4a zo04`MvBa%PiyiT|t5ckS2@&q~YaPu$-bikqr*cz=<0+u=eGVpAk6*-0@bwg!N!pgJ z54NjPndtBC>K{*W(QXV340@yH5Ch-bCq@pX0jR@%EbXW9pR-Iv2}B3K!LWyOYLq)T zFml-b01YiYWU*I^DbMTqtF3qP!}8&KLeTavpbFzBaY4JQKNo)7$;x)ulr|~b9ge#? zI84X42sbO+-&fGAX^>X2$Ij5crqkQc{j zqBHyh`32}Yz$&@15-c=pI_mC8ES!kFr{K%r}bjR-Q8UdhlHOq7bNAgxr(mtGeBCKe%ZU& z1OYd`U}0eVfWjiCzPpqFUFjSkF(8*5TpDTsfNrj1zxT};cCAzy0D^Uas|LWOq4(dp zjwKb$cV~cPUdUmK1;*vCg%Z4)C4lh! z{&<)Oko(j$hx6IMnCKw^l(r3&S_wVwg+jxj++FP!Vqy|}`H~25{QoYu@d=Pp`~bAg zT$M5bD_#|WjIWr@3M+yP(rh#!#Ka7DmgeW#!2%fU8B%@Vz7Od(kiCS*kG9*ca$3zp z__WbYOjiU?8UF%=c(jcj?-N1`BEHPD$%!;uyeXPAa^24`R;STltMEz|DLJ=vx?GL{ zO?--s@EVA=ss;u`w(a{a>n-L2K6it$3^~#SKLP2UO#SKQCGh#Ia!&AtKG6-8+yB|k z*qB7A-(j2gF7sy=OK9abusnf#dw}{NcJTx4?3mcmEA>cz#ywYrQa79z42?%g-3Ai{VA zE*wlG5XPt8qti17oua)?mW^Oh<&*dxi7u{~SCT?crs#aD_J?S|<+=A~X ze@`4MDhy(ylv`Xn4)$i2medv5N(v8@O>U=oVnX#rG2q`(5P7Mot$@v;ha)a4TP|VP zPRGT}V_^ldUi@Te1o$Pq&eX)@dORM27q|*qEYl(O;eWnT+S^;q@O?uuxmHa^==oGD z8ypce*<-ivzy(sT&C;zkY%(pjKR;Vk0Xd!k#Z7cQ1&xi@zfSLfk`N)ci8iZ+;nN%m zx=~;D4&DL3C)RH4g}Mlby=iQ-~k4u6$zXEIG75-|fMgVIB@x;DyFv!LAo zMmo8-XKL9L+04Jck?VC_bI=!Anc87{9*>URoSipk^LU(JJVct&GzVB=pn4JUQ}klm zPMb`34OSaLIsPGI`$e2>(P|Ra^ccbAa)B9B4VzZej68JbswM|Fxm---KU19Nl1?tEoB>>^#WdWb- zy*r@q$uu$kbRM#gKW!GrH+|{9}sG6X)$`wHioG4UWTcr(Ps95rtqdc6hBp z|NP~NVZ9YDF^TK>-@UV^B~iQ6>AYRG-Plklv#E3}7RT0Bk&aZVw7e9II0)?1KY!w8 zBDX|eBdNVA1jNhx_qTq9oI9H>90O-2vcq*C4#UARY=at$s;opGF1@Innm`l!gbeI@ z@}|=b9U!i_k;D^7*ZoneQ^KfNHJ`}vxWY=Ryc9$X<4-UqCP~)ix>3NpXO_|jmo{Plep3L5P!35IAUABP1+r~>Ze%OlHk`n6NTYds`1 zHz7+|$w+SI*z|Jxf>1tRWOs?s35Cb>IYy|4CQEKsM%E*C~)OIS)H)8)f971O7 zXb=||_!bOJ-vk6)X#9$e@*k+aDwloym4vEwoHZdn#;h z8R2;a^gmZK4R5ggh~T3x&0Lkksf`=^!CdoEnke|==g+Y}_*omHl;S2xG!|mUYeJMF z#?=Wx*{n$Dr{HKEh=;3P!%k%+X?-!VMHdbSIz~xT4eO;BAC2nM{^f5*n56>lQhx(1 zDk5WJFK@9JtN~6l*D2wb??Oyxh=ZNtw#v`66WT0(0CY*!`-BR?ALh#^LF!bNp82Mzi|FcRtkvFF% zF4%vqf#F%~g2l^|JvvM!yv?$l6M(Zr5fgkZ+G1vJF?<)e!I-UU$>9(VpVwEl-PMvW zPZIb9tbqIiZ%Im5KYJJZP-N-y+gmb$yNKs65_$9Z@UjI9BOg9{b7uMCg-{-Hf_|Rc#R+bHw`N4Aa zGR#7iZW5l|^+gL>ITimeS(^-9*o&-dMSm_;YntNm){zN5^}0ahi=Ny{1xlofS%m2gT*&R(?WgDL0bz //// -Netlink Routing Library -======================= +Routing Family Netlink Library (libnl-route) +============================================ Thomas Graf -3.0, March 23 2011: -:toc: -:icons: -:numbered: - +3.1, July 17 2011: == Introduction -== Introduction to the Library +This library provides APIs to the kernel interfaces of the routing family. == Addresses -== Links / Interfaces +== Links (Network Devices) + +The link configuration interface is part of the +NETLINK_ROUTE+ protocol +family and implements the following netlink message types: + +- View and modify the configuration of physical and virtual network devices. +- Create and delete virtual network devices (e.g. dummy devices, VLAN devices, + tun devices, bridging devices, ...) +- View and modify per link network configuration settings (e.g. + +net.ipv6.conf.eth0.accept_ra+, +net.ipv4.conf.eth1.forwarding+, ...) + +.Naming Convention (network device, link, interface) + +In networking several terms are commonly used to refer to network devices. +While they have distinct meanings they have been used interchangeably in +the past. Within the Linux kernel, the term _network device_ or _netdev_ is +commonly used In user space the term _network interface_ is very common. +The routing netlink protocol uses the term _link_ and so does the _iproute2_ +utility and most routing daemons. + +=== Protocol Definition + +This section describes the protocol semantics of the netlink link configuration +interface. The following netlink message types are defined: + +[options="header", cols="1,2,2"] +|============================================================================== +| Message Type | User -> Kernel | Kernel -> User +| +RTM_NEWLINK+ | Create new virtual network device | Notification: Link changed or added +| +RTM_DELLINK+ | Delete virtual network device | Notification: Link deleted or disappeared +| +RTM_GETLINK+ | Retrieve link configuration and statistics | +| +RTM_SETLINK+ | Modify link configuration | +|============================================================================== + +See the link:core.html#core_msg_types[Message Types] section of the Netlink +Library documentation for more information on common semantics of these message +types. + +.Link Message Header + +All netlink link messages share the following common header which is appended +after the netlink message header (+struct nlmsghdr+). It is defined in the +header ++ + +[source,c] +----- +struct ifinfomsg { + unsigned char ifi_family; + unsigned char __ifi_pad; + unsigned short ifi_type; /* ARPHRD_* */ + int ifi_index; /* Link index */ + unsigned ifi_flags; /* IFF_* flags */ + unsigned ifi_change; /* IFF_* change mask */ +}; +----- + +The meaning of each field may differ depending on the message type. + +.Attributes + +All link message types may carry netlink attributes. They are defined in the +header file and share the prefix +IFLA_+. + + +=== Link Object + +Name:: +The name of a network device is the human readable representation of a +network device and secondary identification parameter besides the interface +index. ++ +[source,c] +----- +void rtnl_link_set_name(struct rtnl_link *link, const char *name); +char *rtnl_link_get_name(struct rtnl_link *link); +----- + +Interface Index:: +The interface index is an integer uniquely identifying a network device. +If present, it will be used to identify an existing network device. ++ +[source,c] +----- +void rtnl_link_set_ifindex(struct rtnl_link *link, int ifindex); +int rtnl_link_get_ifindex(struct rtnl_link *link); +----- + + +Address:: +The link layer address (MAC address). ++ +[source,c] +----- +void rtnl_link_set_addr(struct rtnl_link *link, struct nl_addr *addr); +struct nl_addr *rtnl_link_get_addr(struct rtnl_link *link); +----- + +Broadcast Address:: +Foo ++ +[source,c] +----- +void rtnl_link_set_broadcast(struct rtnl_link *link, struct nl_addr *addr); +struct nl_addr *rtnl_link_get_broadcast(struct rtnl_link *link); +----- + +MTU:: +The maximum transmission unit specifies the maximum packet size a network +device can transmit or receive. This value may be lower than the capability +of the physical network device. ++ +[source,c] +----- +void rtnl_link_set_mtu(struct rtnl_link *link, unsigned int mtu); +unsigned int rtnl_link_get_mtu(struct rtnl_link *link); +----- + +Weight:: +Foo ++ +[source,c] +----- +void rtnl_link_set_weight(struct rtnl_link *link, unsigned int weight); +unsigned int rtnl_link_get_weight(struct rtnl_link *link); +----- + +=== Link Cache + == Neighbouring @@ -122,97 +245,93 @@ rtnl_qdisc_put(qdisc); [[tc_attr]] ==== Attributes -[cols="a,a", options="header", frame="topbot"] -|==================================================================== -| Attribute | C Interface -| Handle:: The handle uniquely identifies a tc object and is used to refer to other tc objects when constructing tc trees. -| ++ [source,c] ----- void rtnl_tc_set_handle(struct rtnl_tc *tc, uint32_t handle); uint32_t rtnl_tc_get_handle(struct rtnl_tc *tc); ----- -| -IfIndex:: + +Interface Index:: The interface index specifies the network device the traffic object is attached to. The function `rtnl_tc_set_link()` should be preferred when setting the interface index. It stores the reference to the link object in the tc object and allows retrieving the `mtu` and `linktype` automatically. -| ++ [source,c] ----- void rtnl_tc_set_ifindex(struct rtnl_tc *tc, int ifindex); void rtnl_tc_set_link(struct rtnl_tc *tc, struct rtnl_link *link); int rtnl_tc_get_ifindex(struct rtnl_tc *tc); ----- -| -LinkType:: + +Link Type:: The link type specifies the kind of link that is used by the network device (e.g. ethernet, ATM, ...). It is derived automatically when the network device is specified with `rtnl_tc_set_link()`. The default fallback is `ARPHRD_ETHER` (ethernet). -| ++ [source,c] ----- void rtnl_tc_set_linktype(struct rtnl_tc *tc, uint32_t type); uint32_t rtnl_tc_get_linktype(struct rtnl_tc *tc); ----- -| + Kind:: The kind character string specifies the type of qdisc, class, classifier. Setting the kind results in the module specific structure being allocated. Therefore it is imperative to call `rtnl_tc_set_kind()` before using any type specific API functions such as `rtnl_htb_set_rate()`. -| ++ [source,c] ----- int rtnl_tc_set_kind(struct rtnl_tc *tc, const char *kind); char *rtnl_tc_get_kind(struct rtnl_tc *tc); ----- -| + MPU:: The Minimum Packet Unit specifies the minimum packet size which will be transmitted ever be seen by this traffic control object. This value is used for rate calculations. Not all object implementations will make use of this value. The default value is 0. -| ++ [source,c] ----- void rtnl_tc_set_mpu(struct rtnl_tc *tc, uint32_t mpu); uint32_t rtnl_tc_get_mpu(struct rtnl_tc *tc); ----- -| + MTU:: The Maximum Transmission Unit specifies the maximum packet size which will be transmitted. The value is derived from the link specified with `rtnl_tc_set_link()` if not overwritten with `rtnl_tc_set_mtu()`. If no link and MTU is specified, the value defaults to 1500 (ethernet). -| ++ [source,c] ----- void rtnl_tc_set_mtu(struct rtnl_tc *tc, uint32_t mtu); uint32_t rtnl_tc_get_mtu(struct rtnl_tc *tc); ----- -| + Overhead:: The overhead specifies the additional overhead per packet caused by the network layer. This value can be used to correct packet size calculations if the packet size on the wire does not match the packet size seen by the kernel. The default value is 0. -| ++ [source,c] ----- void rtnl_tc_set_overhead(struct rtnl_tc *tc, uint32_t overhead); uint32_t rtnl_tc_get_overhead(struct rtnl_tc *tc); ----- -| + Parent:: Specifies the parent traffic control object. The parent is identifier by its handle. Special values are: @@ -220,22 +339,21 @@ by its handle. Special values are: qdisc, root classifier) - `TC_H_INGRESS`: same as `TC_H_ROOT` but on the ingress side of the network stack. -| ++ [source,c] ----- void rtnl_tc_set_parent(struct rtnl_tc *tc, uint32_t parent); uint32_t rtnl_tc_get_parent(struct rtnl_tc *tc); ----- -| + Statistics:: Generic statistics, see <> for additional information. -| ++ [source,c] ----- uint64_t rtnl_tc_get_stat(struct rtnl_tc *tc, enum rtnl_tc_stat id); ----- -|==================================================================== [[tc_stats]] ==== Accessing Statistics @@ -574,97 +692,87 @@ WARNING: The function rtnl_qdisc_delete() requires administrator .HTB Qdisc Attributes -[cols="a,a", options="header", frame="topbot"] -|==================================================================== -| Attribute | C Interface -| Default Class:: The default class is the fallback class to which all traffic which remained unclassified is directed to. If no default class or an invalid default class is specified, packets are transmitted directly to the next layer (direct transmissions). -| ++ [source,c] ----- uint32_t rtnl_htb_get_defcls(struct rtnl_qdisc *qdisc); int rtnl_htb_set_defcls(struct rtnl_qdisc *qdisc, uint32_t defcls); ----- -| + Rate to Quantum (r2q):: TODO -| ++ [source,c] ----- uint32_t rtnl_htb_get_rate2quantum(struct rtnl_qdisc *qdisc); int rtnl_htb_set_rate2quantum(struct rtnl_qdisc *qdisc, uint32_t rate2quantum); ----- -|==================================================================== .HTB Class Attributes -[cols="a,a", options="header", frame="topbot"] -|==================================================================== -| Attribute | C Interface -| Priority:: -| ++ [source,c] ----- uint32_t rtnl_htb_get_prio(struct rtnl_class *class); int rtnl_htb_set_prio(struct rtnl_class *class, uint32_t prio); ----- -| + Rate:: The rate (bytes/s) specifies the maximum bandwidth an invidivual class can use without borrowing. The rate of a class should always be greater or erqual than the rate of its children. -| ++ [source,c] ----- uint32_t rtnl_htb_get_rate(struct rtnl_class *class); int rtnl_htb_set_rate(struct rtnl_class *class, uint32_t ceil); ----- -| + Ceil Rate:: The ceil rate specifies the maximum bandwidth an invidivual class can use. This includes bandwidth that is being borrowed from other classes. Ceil defaults to the class rate implying that by default the class will not borrow. The ceil rate of a class should always be greater or erqual than the ceil rate of its children. -| ++ [source,c] ----- uint32_t rtnl_htb_get_ceil(struct rtnl_class *class); int rtnl_htb_set_ceil(struct rtnl_class *class, uint32_t ceil); ----- -| + Burst:: TODO -| ++ [source,c] ----- uint32_t rtnl_htb_get_rbuffer(struct rtnl_class *class); int rtnl_htb_set_rbuffer(struct rtnl_class *class, uint32_t burst); ----- -| + Ceil Burst:: TODO -| ++ [source,c] ----- uint32_t rtnl_htb_get_bbuffer(struct rtnl_class *class); int rtnl_htb_set_bbuffer(struct rtnl_class *class, uint32_t burst); ----- -| + Quantum:: TODO -| ++ [source,c] ----- int rtnl_htb_set_quantum(struct rtnl_class *class, uint32_t quantum); ----- -|==================================================================== extern int rtnl_htb_set_cbuffer(struct rtnl_class *, uint32_t); @@ -708,13 +816,19 @@ class =:: hX:hY [[tc_cls]] === Classifier (cls) +TODO + [[tc_classid_mngt]] === ClassID Management +TODO + [[tc_pktloc]] === Packet Location Aliasing (pktloc) +TODO + [[tc_api]] === Traffic Control Module API - +TODO diff --git a/doc/stylesheets/asciidoc-manpage.css b/doc/stylesheets/asciidoc-manpage.css new file mode 100644 index 0000000..45eba23 --- /dev/null +++ b/doc/stylesheets/asciidoc-manpage.css @@ -0,0 +1,18 @@ +/* Overrides for manpage documents */ +h1 { + padding-top: 0.5em; + padding-bottom: 0.5em; + border-top: 2px solid silver; + border-bottom: 2px solid silver; +} +h2 { + border-style: none; +} +div.sectionbody { + margin-left: 3em; +} + +@media print { + div#toc { display: none; } +} + diff --git a/doc/stylesheets/xhtml11.css b/doc/stylesheets/asciidoc.css similarity index 63% rename from doc/stylesheets/xhtml11.css rename to doc/stylesheets/asciidoc.css index 39e7b16..19796dd 100644 --- a/doc/stylesheets/xhtml11.css +++ b/doc/stylesheets/asciidoc.css @@ -1,63 +1,55 @@ -/* Sans-serif font. */ +/* Shared CSS for AsciiDoc xhtml11 and html5 backends */ + +/* Default font. */ +body { + font-family: Georgia,serif; +} + +/* Title font. */ h1, h2, h3, h4, h5, h6, div.title, caption.title, thead, p.table.header, -div#toctitle, -span#author, span#revnumber, span#revdate, span#revremark, -div#footer { - font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif; -} - -/* Serif font. */ -div.sectionbody { - font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif; -} - -/* Monospace font. */ -tt { - font-size: inherit; +#toctitle, +#author, #revnumber, #revdate, #revremark, +#footer { + /* OLD: font-family: Arial,Helvetica,sans-serif; */ + font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif; } body { - margin: 1em 5% 1em 5%; + margin: 1em 5% 1em 5%; } a { - color: #990000; - text-decoration: underline; + /* color: blue; */ + color: #990000; + text-decoration: underline; } a:visited { - color: #990000; + /* color: fuchsia; */ } -.dg { color: #990000; } - em { - font-style: italic; - /* color: navy; */ + font-style: italic; + /* color: navy; */ } strong { - font-weight: bold; - color: black; - /* color: #083194; */ -} - -tt { - font-size: inherit; - color: navy; + font-weight: bold; + color: black; + /* color: #083194; */ } h1, h2, h3, h4, h5, h6 { - color: #990000; - margin-top: 1.2em; - margin-bottom: 0.5em; - line-height: 1.3; + /* color: #527bbd; */ + color: #990000; + margin-top: 1.2em; + margin-bottom: 0.5em; + line-height: 1.3; } -h1 { - border-bottom: 2px solid silver; - color: #990000; +h1, h2, h3 { + border-bottom: 2px solid silver; } h2 { padding-top: 0.5em; @@ -68,6 +60,9 @@ h3 { h3 + * { clear: left; } +h5 { + font-size: 1.0em; +} div.sectionbody { margin-left: 0; @@ -93,59 +88,60 @@ pre { margin: 0; } -span#author { - color: #990000; - font-weight: bold; - font-size: 1.1em; +#author { + /* color: #527bbd; */ + font-weight: bold; + font-size: 1.1em; } -span#email { +#email { } -span#revnumber, span#revdate, span#revremark { +#revnumber, #revdate, #revremark { } -div#footer { +#footer { font-size: small; border-top: 2px solid silver; padding-top: 0.5em; margin-top: 4.0em; } -div#footer-text { +#footer-text { float: left; padding-bottom: 0.5em; } -div#footer-badges { +#footer-badges { float: right; padding-bottom: 0.5em; } -div#preamble { +#preamble { margin-top: 1.5em; margin-bottom: 1.5em; } -div.tableblock, div.imageblock, div.exampleblock, div.verseblock, +div.imageblock, div.exampleblock, div.verseblock, div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock, div.admonitionblock { - margin-top: 1.0em; - margin-bottom: 1.5em; + margin-top: 1.0em; + margin-bottom: 1.5em; } div.admonitionblock { - margin-top: 2.0em; - margin-bottom: 2.0em; - margin-right: 10%; - color: #606060; + margin-top: 2.0em; + margin-bottom: 2.0em; + margin-right: 10%; + /* color: #606060; */ } div.content { /* Block element content. */ - padding: 0; + padding: 0; } /* Block element titles. */ div.title, caption.title { - color: #990000; - font-weight: bold; - text-align: left; - margin-top: 1.0em; - margin-bottom: 0.5em; + /* OLD: color: #527bbd; */ + color: #990000; + font-weight: bold; + text-align: left; + margin-top: 1.0em; + margin-bottom: 0.5em; } div.title + * { margin-top: 0; @@ -170,7 +166,7 @@ div.sidebarblock > div.content { div.listingblock > div.content { border: 1px solid #dddddd; - border-left: 5px solid #f0f0f0; + /* border-left: 5px solid #f0f0f0; */ background: #f8f8f8; padding: 0.5em; } @@ -206,7 +202,8 @@ div.admonitionblock .icon { font-size: 1.1em; font-weight: bold; text-decoration: underline; - color: #527bbd; + /* OLD: color: #527bbd; */ + color: #990000; padding-right: 0.5em; } div.admonitionblock td.content { @@ -228,10 +225,10 @@ dl { margin-bottom: 0.8em; } dt { - margin-top: 0.5em; - margin-bottom: 0; - font-style: normal; - color: #990000; + margin-top: 0.5em; + margin-bottom: 0; + font-style: normal; + color: navy; } dd > *:first-child { margin-top: 0.1em; @@ -263,35 +260,12 @@ div.compact div, div.compact div { margin-bottom: 0.1em; } -div.tableblock > table { - border: 3px solid #990000; -} -thead, p.table.header { - font-weight: bold; - color: #990000; -} tfoot { font-weight: bold; } td > div.verse { white-space: pre; } -p.table { - margin-top: 0; -} -/* Because the table frame attribute is overriden by CSS in most browsers. */ -div.tableblock > table[frame="void"] { - border-style: none; -} -div.tableblock > table[frame="hsides"] { - border-left-style: none; - border-right-style: none; -} -div.tableblock > table[frame="vsides"] { - border-top-style: none; - border-bottom-style: none; -} - div.hdlist { margin-top: 0.8em; @@ -304,10 +278,10 @@ dt.hdlist1.strong, td.hdlist1.strong { font-weight: bold; } td.hdlist1 { - vertical-align: top; - font-style: normal; - padding-right: 0.8em; - color: #990000; + vertical-align: top; + font-style: normal; + padding-right: 0.8em; + color: navy; } td.hdlist2 { vertical-align: top; @@ -358,15 +332,16 @@ div.colist td img { } @media print { - div#footer-badges { display: none; } + #footer-badges { display: none; } } -div#toc { +#toc { margin-bottom: 2.5em; } -div#toctitle { - color: black; +#toctitle { + /* color: #527bbd; */ + color: #990000; font-size: 1.1em; font-weight: bold; margin-top: 1.0em; @@ -426,3 +401,121 @@ span.yellow-background { background: yellow; } span.big { font-size: 2em; } span.small { font-size: 0.6em; } + +span.underline { text-decoration: underline; } +span.overline { text-decoration: overline; } +span.line-through { text-decoration: line-through; } + + +/* + * xhtml11 specific + * + * */ + +tt { + font-family: monospace; + font-size: inherit; + /* color: navy; */ + color: black; +} + +div.tableblock { + margin-top: 1.0em; + margin-bottom: 1.5em; +} +div.tableblock > table { + /* border: 3px solid #527bbd; */ + border: 2px solid #990000; +} +thead, p.table.header { + font-weight: bold; + /* color: #527bbd; */ + color: #990000; +} +p.table { + margin-top: 0; +} +/* Because the table frame attribute is overriden by CSS in most browsers. */ +div.tableblock > table[frame="void"] { + border-style: none; +} +div.tableblock > table[frame="hsides"] { + border-left-style: none; + border-right-style: none; +} +div.tableblock > table[frame="vsides"] { + border-top-style: none; + border-bottom-style: none; +} + + +/* + * html5 specific + * + * */ + +.monospaced { + font-family: monospace; + font-size: inherit; + color: navy; +} + +table.tableblock { + margin-top: 1.0em; + margin-bottom: 1.5em; +} +thead, p.tableblock.header { + font-weight: bold; + /* color: #527bbd; */ + color: #990000; +} +p.tableblock { + margin-top: 0; +} +table.tableblock { + border-width: 3px; + border-spacing: 0px; + border-style: solid; + /* border-color: #527bbd; */ + border-color: #990000; + border-collapse: collapse; +} +th.tableblock, td.tableblock { + border-width: 1px; + padding: 4px; + border-style: solid; + /* border-color: #527bbd; */ + border-color: #990000; +} + +table.tableblock.frame-topbot { + border-left-style: hidden; + border-right-style: hidden; +} +table.tableblock.frame-sides { + border-top-style: hidden; + border-bottom-style: hidden; +} +table.tableblock.frame-none { + border-style: hidden; +} + +th.tableblock.halign-left, td.tableblock.halign-left { + text-align: left; +} +th.tableblock.halign-center, td.tableblock.halign-center { + text-align: center; +} +th.tableblock.halign-right, td.tableblock.halign-right { + text-align: right; +} + +th.tableblock.valign-top, td.tableblock.valign-top { + vertical-align: top; +} +th.tableblock.valign-middle, td.tableblock.valign-middle { + vertical-align: middle; +} +th.tableblock.valign-bottom, td.tableblock.valign-bottom { + vertical-align: bottom; +} diff --git a/doc/stylesheets/docbook-xsl.css b/doc/stylesheets/docbook-xsl.css new file mode 100644 index 0000000..6df2944 --- /dev/null +++ b/doc/stylesheets/docbook-xsl.css @@ -0,0 +1,322 @@ +/* + CSS stylesheet for XHTML produced by DocBook XSL stylesheets. + Tested with XSL stylesheets 1.61.2, 1.67.2 +*/ + +span.strong { + font-weight: bold; +} + +body blockquote { + margin-top: .75em; + line-height: 1.5; + margin-bottom: .75em; +} + +html body { + margin: 1em 5% 1em 5%; + line-height: 1.2; +} + +body div { + margin: 0; +} + +h1, h2, h3, h4, h5, h6 +{ + color: #527bbd; + font-family: tahoma, verdana, sans-serif; +} + +div.toc p:first-child, +div.list-of-figures p:first-child, +div.list-of-tables p:first-child, +div.list-of-examples p:first-child, +div.example p.title, +div.sidebar p.title +{ + font-weight: bold; + color: #527bbd; + font-family: tahoma, verdana, sans-serif; + margin-bottom: 0.2em; +} + +body h1 { + margin: .0em 0 0 -4%; + line-height: 1.3; + border-bottom: 2px solid silver; +} + +body h2 { + margin: 0.5em 0 0 -4%; + line-height: 1.3; + border-bottom: 2px solid silver; +} + +body h3 { + margin: .8em 0 0 -3%; + line-height: 1.3; +} + +body h4 { + margin: .8em 0 0 -3%; + line-height: 1.3; +} + +body h5 { + margin: .8em 0 0 -2%; + line-height: 1.3; +} + +body h6 { + margin: .8em 0 0 -1%; + line-height: 1.3; +} + +body hr { + border: none; /* Broken on IE6 */ +} +div.footnotes hr { + border: 1px solid silver; +} + +div.navheader th, div.navheader td, div.navfooter td { + font-family: sans-serif; + font-size: 0.9em; + font-weight: bold; + color: #527bbd; +} +div.navheader img, div.navfooter img { + border-style: none; +} +div.navheader a, div.navfooter a { + font-weight: normal; +} +div.navfooter hr { + border: 1px solid silver; +} + +body td { + line-height: 1.2 +} + +body th { + line-height: 1.2; +} + +ol { + line-height: 1.2; +} + +ul, body dir, body menu { + line-height: 1.2; +} + +html { + margin: 0; + padding: 0; +} + +body h1, body h2, body h3, body h4, body h5, body h6 { + margin-left: 0 +} + +body pre { + margin: 0.5em 10% 0.5em 1em; + line-height: 1.0; + color: navy; +} + +tt.literal, code.literal { + color: navy; +} + +.programlisting, .screen { + border: 1px solid silver; + background: #f4f4f4; + margin: 0.5em 10% 0.5em 0; + padding: 0.5em 1em; +} + +div.sidebar { + background: #ffffee; + margin: 1.0em 10% 0.5em 0; + padding: 0.5em 1em; + border: 1px solid silver; +} +div.sidebar * { padding: 0; } +div.sidebar div { margin: 0; } +div.sidebar p.title { + margin-top: 0.5em; + margin-bottom: 0.2em; +} + +div.bibliomixed { + margin: 0.5em 5% 0.5em 1em; +} + +div.glossary dt { + font-weight: bold; +} +div.glossary dd p { + margin-top: 0.2em; +} + +dl { + margin: .8em 0; + line-height: 1.2; +} + +dt { + margin-top: 0.5em; +} + +dt span.term { + font-style: normal; + color: navy; +} + +div.variablelist dd p { + margin-top: 0; +} + +div.itemizedlist li, div.orderedlist li { + margin-left: -0.8em; + margin-top: 0.5em; +} + +ul, ol { + list-style-position: outside; +} + +div.sidebar ul, div.sidebar ol { + margin-left: 2.8em; +} + +div.itemizedlist p.title, +div.orderedlist p.title, +div.variablelist p.title +{ + margin-bottom: -0.8em; +} + +div.revhistory table { + border-collapse: collapse; + border: none; +} +div.revhistory th { + border: none; + color: #527bbd; + font-family: tahoma, verdana, sans-serif; +} +div.revhistory td { + border: 1px solid silver; +} + +/* Keep TOC and index lines close together. */ +div.toc dl, div.toc dt, +div.list-of-figures dl, div.list-of-figures dt, +div.list-of-tables dl, div.list-of-tables dt, +div.indexdiv dl, div.indexdiv dt +{ + line-height: normal; + margin-top: 0; + margin-bottom: 0; +} + +/* + Table styling does not work because of overriding attributes in + generated HTML. +*/ +div.table table, +div.informaltable table +{ + margin-left: 0; + margin-right: 5%; + margin-bottom: 0.8em; +} +div.informaltable table +{ + margin-top: 0.4em +} +div.table thead, +div.table tfoot, +div.table tbody, +div.informaltable thead, +div.informaltable tfoot, +div.informaltable tbody +{ + /* No effect in IE6. */ + border-top: 3px solid #527bbd; + border-bottom: 3px solid #527bbd; +} +div.table thead, div.table tfoot, +div.informaltable thead, div.informaltable tfoot +{ + font-weight: bold; +} + +div.mediaobject img { + margin-bottom: 0.8em; +} +div.figure p.title, +div.table p.title +{ + margin-top: 1em; + margin-bottom: 0.4em; +} + +div.calloutlist p +{ + margin-top: 0em; + margin-bottom: 0.4em; +} + +a img { + border-style: none; +} + +@media print { + div.navheader, div.navfooter { display: none; } +} + +span.aqua { color: aqua; } +span.black { color: black; } +span.blue { color: blue; } +span.fuchsia { color: fuchsia; } +span.gray { color: gray; } +span.green { color: green; } +span.lime { color: lime; } +span.maroon { color: maroon; } +span.navy { color: navy; } +span.olive { color: olive; } +span.purple { color: purple; } +span.red { color: red; } +span.silver { color: silver; } +span.teal { color: teal; } +span.white { color: white; } +span.yellow { color: yellow; } + +span.aqua-background { background: aqua; } +span.black-background { background: black; } +span.blue-background { background: blue; } +span.fuchsia-background { background: fuchsia; } +span.gray-background { background: gray; } +span.green-background { background: green; } +span.lime-background { background: lime; } +span.maroon-background { background: maroon; } +span.navy-background { background: navy; } +span.olive-background { background: olive; } +span.purple-background { background: purple; } +span.red-background { background: red; } +span.silver-background { background: silver; } +span.teal-background { background: teal; } +span.white-background { background: white; } +span.yellow-background { background: yellow; } + +span.big { font-size: 2em; } +span.small { font-size: 0.6em; } + +span.underline { text-decoration: underline; } +span.overline { text-decoration: overline; } +span.line-through { text-decoration: line-through; } diff --git a/doc/stylesheets/flask-manpage.css b/doc/stylesheets/flask-manpage.css new file mode 100644 index 0000000..75a2dda --- /dev/null +++ b/doc/stylesheets/flask-manpage.css @@ -0,0 +1 @@ +/* Empty placeholder file */ diff --git a/doc/stylesheets/flask.css b/doc/stylesheets/flask.css new file mode 100644 index 0000000..8d33bc4 --- /dev/null +++ b/doc/stylesheets/flask.css @@ -0,0 +1,584 @@ +/* + * AsciiDoc 'flask' theme for xhtml11 and html5 backends. A shameless knock-off + * of the Flask website styling (http://flask.pocoo.org/docs/). + * + * The implementation is straight-forward, consisting of the asciidoc.css file + * followed by theme specific overrides. + * + * */ + + +/* Shared CSS for AsciiDoc xhtml11 and html5 backends */ + +/* Default font. */ +body { + font-family: Georgia,serif; +} + +/* Title font. */ +h1, h2, h3, h4, h5, h6, +div.title, caption.title, +thead, p.table.header, +#toctitle, +#author, #revnumber, #revdate, #revremark, +#footer { + font-family: Arial,Helvetica,sans-serif; +} + +body { + margin: 1em 5% 1em 5%; +} + +a { + color: blue; + text-decoration: underline; +} +a:visited { + color: fuchsia; +} + +em { + font-style: italic; + color: navy; +} + +strong { + font-weight: bold; + color: #083194; +} + +h1, h2, h3, h4, h5, h6 { + color: #527bbd; + margin-top: 1.2em; + margin-bottom: 0.5em; + line-height: 1.3; +} + +h1, h2, h3 { + border-bottom: 2px solid silver; +} +h2 { + padding-top: 0.5em; +} +h3 { + float: left; +} +h3 + * { + clear: left; +} +h5 { + font-size: 1.0em; +} + +div.sectionbody { + margin-left: 0; +} + +hr { + border: 1px solid silver; +} + +p { + margin-top: 0.5em; + margin-bottom: 0.5em; +} + +ul, ol, li > p { + margin-top: 0; +} +ul > li { color: #aaa; } +ul > li > * { color: black; } + +pre { + padding: 0; + margin: 0; +} + +#author { + color: #527bbd; + font-weight: bold; + font-size: 1.1em; +} +#email { +} +#revnumber, #revdate, #revremark { +} + +#footer { + font-size: small; + border-top: 2px solid silver; + padding-top: 0.5em; + margin-top: 4.0em; +} +#footer-text { + float: left; + padding-bottom: 0.5em; +} +#footer-badges { + float: right; + padding-bottom: 0.5em; +} + +#preamble { + margin-top: 1.5em; + margin-bottom: 1.5em; +} +div.imageblock, div.exampleblock, div.verseblock, +div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock, +div.admonitionblock { + margin-top: 1.0em; + margin-bottom: 1.5em; +} +div.admonitionblock { + margin-top: 2.0em; + margin-bottom: 2.0em; + margin-right: 10%; + color: #606060; +} + +div.content { /* Block element content. */ + padding: 0; +} + +/* Block element titles. */ +div.title, caption.title { + color: #527bbd; + font-weight: bold; + text-align: left; + margin-top: 1.0em; + margin-bottom: 0.5em; +} +div.title + * { + margin-top: 0; +} + +td div.title:first-child { + margin-top: 0.0em; +} +div.content div.title:first-child { + margin-top: 0.0em; +} +div.content + div.title { + margin-top: 0.0em; +} + +div.sidebarblock > div.content { + background: #ffffee; + border: 1px solid #dddddd; + border-left: 4px solid #f0f0f0; + padding: 0.5em; +} + +div.listingblock > div.content { + border: 1px solid #dddddd; + border-left: 5px solid #f0f0f0; + background: #f8f8f8; + padding: 0.5em; +} + +div.quoteblock, div.verseblock { + padding-left: 1.0em; + margin-left: 1.0em; + margin-right: 10%; + border-left: 5px solid #f0f0f0; + color: #777777; +} + +div.quoteblock > div.attribution { + padding-top: 0.5em; + text-align: right; +} + +div.verseblock > pre.content { + font-family: inherit; + font-size: inherit; +} +div.verseblock > div.attribution { + padding-top: 0.75em; + text-align: left; +} +/* DEPRECATED: Pre version 8.2.7 verse style literal block. */ +div.verseblock + div.attribution { + text-align: left; +} + +div.admonitionblock .icon { + vertical-align: top; + font-size: 1.1em; + font-weight: bold; + text-decoration: underline; + color: #527bbd; + padding-right: 0.5em; +} +div.admonitionblock td.content { + padding-left: 0.5em; + border-left: 3px solid #dddddd; +} + +div.exampleblock > div.content { + border-left: 3px solid #dddddd; + padding-left: 0.5em; +} + +div.imageblock div.content { padding-left: 0; } +span.image img { border-style: none; } +a.image:visited { color: white; } + +dl { + margin-top: 0.8em; + margin-bottom: 0.8em; +} +dt { + margin-top: 0.5em; + margin-bottom: 0; + font-style: normal; + color: navy; +} +dd > *:first-child { + margin-top: 0.1em; +} + +ul, ol { + list-style-position: outside; +} +ol.arabic { + list-style-type: decimal; +} +ol.loweralpha { + list-style-type: lower-alpha; +} +ol.upperalpha { + list-style-type: upper-alpha; +} +ol.lowerroman { + list-style-type: lower-roman; +} +ol.upperroman { + list-style-type: upper-roman; +} + +div.compact ul, div.compact ol, +div.compact p, div.compact p, +div.compact div, div.compact div { + margin-top: 0.1em; + margin-bottom: 0.1em; +} + +tfoot { + font-weight: bold; +} +td > div.verse { + white-space: pre; +} + +div.hdlist { + margin-top: 0.8em; + margin-bottom: 0.8em; +} +div.hdlist tr { + padding-bottom: 15px; +} +dt.hdlist1.strong, td.hdlist1.strong { + font-weight: bold; +} +td.hdlist1 { + vertical-align: top; + font-style: normal; + padding-right: 0.8em; + color: navy; +} +td.hdlist2 { + vertical-align: top; +} +div.hdlist.compact tr { + margin: 0; + padding-bottom: 0; +} + +.comment { + background: yellow; +} + +.footnote, .footnoteref { + font-size: 0.8em; +} + +span.footnote, span.footnoteref { + vertical-align: super; +} + +#footnotes { + margin: 20px 0 20px 0; + padding: 7px 0 0 0; +} + +#footnotes div.footnote { + margin: 0 0 5px 0; +} + +#footnotes hr { + border: none; + border-top: 1px solid silver; + height: 1px; + text-align: left; + margin-left: 0; + width: 20%; + min-width: 100px; +} + +div.colist td { + padding-right: 0.5em; + padding-bottom: 0.3em; + vertical-align: top; +} +div.colist td img { + margin-top: 0.3em; +} + +@media print { + #footer-badges { display: none; } +} + +#toc { + margin-bottom: 2.5em; +} + +#toctitle { + color: #527bbd; + font-size: 1.1em; + font-weight: bold; + margin-top: 1.0em; + margin-bottom: 0.1em; +} + +div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 { + margin-top: 0; + margin-bottom: 0; +} +div.toclevel2 { + margin-left: 2em; + font-size: 0.9em; +} +div.toclevel3 { + margin-left: 4em; + font-size: 0.9em; +} +div.toclevel4 { + margin-left: 6em; + font-size: 0.9em; +} + +span.aqua { color: aqua; } +span.black { color: black; } +span.blue { color: blue; } +span.fuchsia { color: fuchsia; } +span.gray { color: gray; } +span.green { color: green; } +span.lime { color: lime; } +span.maroon { color: maroon; } +span.navy { color: navy; } +span.olive { color: olive; } +span.purple { color: purple; } +span.red { color: red; } +span.silver { color: silver; } +span.teal { color: teal; } +span.white { color: white; } +span.yellow { color: yellow; } + +span.aqua-background { background: aqua; } +span.black-background { background: black; } +span.blue-background { background: blue; } +span.fuchsia-background { background: fuchsia; } +span.gray-background { background: gray; } +span.green-background { background: green; } +span.lime-background { background: lime; } +span.maroon-background { background: maroon; } +span.navy-background { background: navy; } +span.olive-background { background: olive; } +span.purple-background { background: purple; } +span.red-background { background: red; } +span.silver-background { background: silver; } +span.teal-background { background: teal; } +span.white-background { background: white; } +span.yellow-background { background: yellow; } + +span.big { font-size: 2em; } +span.small { font-size: 0.6em; } + +span.underline { text-decoration: underline; } +span.overline { text-decoration: overline; } +span.line-through { text-decoration: line-through; } + + +/* + * xhtml11 specific + * + * */ + +tt { + font-family: monospace; + font-size: inherit; + color: navy; +} + +div.tableblock { + margin-top: 1.0em; + margin-bottom: 1.5em; +} +div.tableblock > table { + border: 3px solid #527bbd; +} +thead, p.table.header { + font-weight: bold; + color: #527bbd; +} +p.table { + margin-top: 0; +} +/* Because the table frame attribute is overriden by CSS in most browsers. */ +div.tableblock > table[frame="void"] { + border-style: none; +} +div.tableblock > table[frame="hsides"] { + border-left-style: none; + border-right-style: none; +} +div.tableblock > table[frame="vsides"] { + border-top-style: none; + border-bottom-style: none; +} + + +/* + * html5 specific + * + * */ + +.monospaced { + font-family: monospace; + font-size: inherit; + color: navy; +} + +table.tableblock { + margin-top: 1.0em; + margin-bottom: 1.5em; +} +thead, p.tableblock.header { + font-weight: bold; + color: #527bbd; +} +p.tableblock { + margin-top: 0; +} +table.tableblock { + border-width: 3px; + border-spacing: 0px; + border-style: solid; + border-color: #527bbd; + border-collapse: collapse; +} +th.tableblock, td.tableblock { + border-width: 1px; + padding: 4px; + border-style: solid; + border-color: #527bbd; +} + +table.tableblock.frame-topbot { + border-left-style: hidden; + border-right-style: hidden; +} +table.tableblock.frame-sides { + border-top-style: hidden; + border-bottom-style: hidden; +} +table.tableblock.frame-none { + border-style: hidden; +} + +th.tableblock.halign-left, td.tableblock.halign-left { + text-align: left; +} +th.tableblock.halign-center, td.tableblock.halign-center { + text-align: center; +} +th.tableblock.halign-right, td.tableblock.halign-right { + text-align: right; +} + +th.tableblock.valign-top, td.tableblock.valign-top { + vertical-align: top; +} +th.tableblock.valign-middle, td.tableblock.valign-middle { + vertical-align: middle; +} +th.tableblock.valign-bottom, td.tableblock.valign-bottom { + vertical-align: bottom; +} + + +/* + * Theme specific overrides of the preceding (asciidoc.css) CSS. + * + */ +body { + font-family: Garamond, Georgia, serif; + font-size: 17px; + color: #3E4349; + line-height: 1.3em; +} +h1, h2, h3, h4, h5, h6, +div.title, caption.title, +thead, p.table.header, +#toctitle, +#author, #revnumber, #revdate, #revremark, +#footer { + font-family: Garmond, Georgia, serif; + font-weight: normal; + border-bottom-width: 0; + color: #3E4349; +} +div.title, caption.title { color: #596673; font-weight: bold; } +h1 { font-size: 240%; } +h2 { font-size: 180%; } +h3 { font-size: 150%; } +h4 { font-size: 130%; } +h5 { font-size: 100%; } +h6 { font-size: 100%; } +#header h1 { margin-top: 0; } +#toc { + color: #444444; + line-height: 1.5; + padding-top: 1.5em; +} +#toctitle { + font-size: 20px; +} +#toc a { + border-bottom: 1px dotted #999999; + color: #444444 !important; + text-decoration: none !important; +} +#toc a:hover { + border-bottom: 1px solid #6D4100; + color: #6D4100 !important; + text-decoration: none !important; +} +div.toclevel1 { margin-top: 0.2em; font-size: 16px; } +div.toclevel2 { margin-top: 0.15em; font-size: 14px; } +em, dt, td.hdlist1 { color: black; } +strong { color: #3E4349; } +a { color: #004B6B; text-decoration: none; border-bottom: 1px dotted #004B6B; } +a:visited { color: #615FA0; border-bottom: 1px dotted #615FA0; } +a:hover { color: #6D4100; border-bottom: 1px solid #6D4100; } +div.tableblock > table, table.tableblock { border: 3px solid #E8E8E8; } +th.tableblock, td.tableblock { border: 1px solid #E8E8E8; } +ul > li > * { color: #3E4349; } +pre, tt, .monospaced { font-family: Consolas,Menlo,'Deja Vu Sans Mono','Bitstream Vera Sans Mono',monospace; } +tt, .monospaced { font-size: 0.9em; color: black; +} +div.exampleblock > div.content, div.sidebarblock > div.content, div.listingblock > div.content { border-width: 0 0 0 3px; border-color: #E8E8E8; } +div.verseblock { border-left-width: 0; margin-left: 3em; } +div.quoteblock { border-left-width: 3px; margin-left: 0; margin-right: 0;} +div.admonitionblock td.content { border-left: 3px solid #E8E8E8; } diff --git a/doc/stylesheets/pygments.css b/doc/stylesheets/pygments.css index cd6fdbd..9ca3659 100644 --- a/doc/stylesheets/pygments.css +++ b/doc/stylesheets/pygments.css @@ -1,62 +1,66 @@ +/* + pygmentize filter +*/ .highlight .hll { background-color: #ffffcc } -.highlight .c { color: #808080 } /* Comment */ -.highlight .err { color: #F00000; background-color: #F0A0A0 } /* Error */ -.highlight .k { color: #008000; font-weight: bold } /* Keyword */ -.highlight .o { color: #303030 } /* Operator */ -.highlight .cm { color: #808080 } /* Comment.Multiline */ -.highlight .cp { color: #507090 } /* Comment.Preproc */ -.highlight .c1 { color: #808080 } /* Comment.Single */ -.highlight .cs { color: #cc0000; font-weight: bold } /* Comment.Special */ +.highlight { background: #f4f4f4; } +.highlight .c { color: #008800; font-style: italic } /* Comment */ +.highlight .err { border: 1px solid #FF0000 } /* Error */ +.highlight .k { color: #AA22FF; font-weight: bold } /* Keyword */ +.highlight .o { color: #666666 } /* Operator */ +.highlight .cm { color: #008800; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #008800 } /* Comment.Preproc */ +.highlight .c1 { color: #008800; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #008800; font-weight: bold } /* Comment.Special */ .highlight .gd { color: #A00000 } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #FF0000 } /* Generic.Error */ .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ .highlight .gi { color: #00A000 } /* Generic.Inserted */ .highlight .go { color: #808080 } /* Generic.Output */ -.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ +.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ .highlight .gt { color: #0040D0 } /* Generic.Traceback */ -.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ -.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ -.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ -.highlight .kp { color: #003080; font-weight: bold } /* Keyword.Pseudo */ -.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ -.highlight .kt { color: #303090; font-weight: bold } /* Keyword.Type */ -.highlight .m { color: #6000E0; font-weight: bold } /* Literal.Number */ -.highlight .s { background-color: #fff0f0 } /* Literal.String */ -.highlight .na { color: #0000C0 } /* Name.Attribute */ -.highlight .nb { color: #007020 } /* Name.Builtin */ -.highlight .nc { color: #B00060; font-weight: bold } /* Name.Class */ -.highlight .no { color: #003060; font-weight: bold } /* Name.Constant */ -.highlight .nd { color: #505050; font-weight: bold } /* Name.Decorator */ -.highlight .ni { color: #800000; font-weight: bold } /* Name.Entity */ -.highlight .ne { color: #F00000; font-weight: bold } /* Name.Exception */ -.highlight .nf { color: #0060B0; font-weight: bold } /* Name.Function */ -.highlight .nl { color: #907000; font-weight: bold } /* Name.Label */ -.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ -.highlight .nt { color: #007000 } /* Name.Tag */ -.highlight .nv { color: #906030 } /* Name.Variable */ -.highlight .ow { color: #000000; font-weight: bold } /* Operator.Word */ +.highlight .kc { color: #AA22FF; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #AA22FF; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #AA22FF; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #AA22FF } /* Keyword.Pseudo */ +.highlight .kr { color: #AA22FF; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #00BB00; font-weight: bold } /* Keyword.Type */ +.highlight .m { color: #666666 } /* Literal.Number */ +.highlight .s { color: #BB4444 } /* Literal.String */ +.highlight .na { color: #BB4444 } /* Name.Attribute */ +.highlight .nb { color: #AA22FF } /* Name.Builtin */ +.highlight .nc { color: #0000FF } /* Name.Class */ +.highlight .no { color: #880000 } /* Name.Constant */ +.highlight .nd { color: #AA22FF } /* Name.Decorator */ +.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ +.highlight .nf { color: #00A000 } /* Name.Function */ +.highlight .nl { color: #A0A000 } /* Name.Label */ +.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #B8860B } /* Name.Variable */ +.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ -.highlight .mf { color: #6000E0; font-weight: bold } /* Literal.Number.Float */ -.highlight .mh { color: #005080; font-weight: bold } /* Literal.Number.Hex */ -.highlight .mi { color: #0000D0; font-weight: bold } /* Literal.Number.Integer */ -.highlight .mo { color: #4000E0; font-weight: bold } /* Literal.Number.Oct */ -.highlight .sb { background-color: #fff0f0 } /* Literal.String.Backtick */ -.highlight .sc { color: #0040D0 } /* Literal.String.Char */ -.highlight .sd { color: #D04020 } /* Literal.String.Doc */ -.highlight .s2 { background-color: #fff0f0 } /* Literal.String.Double */ -.highlight .se { color: #606060; font-weight: bold; background-color: #fff0f0 } /* Literal.String.Escape */ -.highlight .sh { background-color: #fff0f0 } /* Literal.String.Heredoc */ -.highlight .si { background-color: #e0e0e0 } /* Literal.String.Interpol */ -.highlight .sx { color: #D02000; background-color: #fff0f0 } /* Literal.String.Other */ -.highlight .sr { color: #000000; background-color: #fff0ff } /* Literal.String.Regex */ -.highlight .s1 { background-color: #fff0f0 } /* Literal.String.Single */ -.highlight .ss { color: #A06000 } /* Literal.String.Symbol */ -.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ -.highlight .vc { color: #306090 } /* Name.Variable.Class */ -.highlight .vg { color: #d07000; font-weight: bold } /* Name.Variable.Global */ -.highlight .vi { color: #3030B0 } /* Name.Variable.Instance */ -.highlight .il { color: #0000D0; font-weight: bold } /* Literal.Number.Integer.Long */ -.highlight .dg { color: #990000; font-weight: bold } +.highlight .mf { color: #666666 } /* Literal.Number.Float */ +.highlight .mh { color: #666666 } /* Literal.Number.Hex */ +.highlight .mi { color: #666666 } /* Literal.Number.Integer */ +.highlight .mo { color: #666666 } /* Literal.Number.Oct */ +.highlight .sb { color: #BB4444 } /* Literal.String.Backtick */ +.highlight .sc { color: #BB4444 } /* Literal.String.Char */ +.highlight .sd { color: #BB4444; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #BB4444 } /* Literal.String.Double */ +.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #BB4444 } /* Literal.String.Heredoc */ +.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ +.highlight .sx { color: #008000 } /* Literal.String.Other */ +.highlight .sr { color: #BB6688 } /* Literal.String.Regex */ +.highlight .s1 { color: #BB4444 } /* Literal.String.Single */ +.highlight .ss { color: #B8860B } /* Literal.String.Symbol */ +.highlight .bp { color: #AA22FF } /* Name.Builtin.Pseudo */ +.highlight .vc { color: #B8860B } /* Name.Variable.Class */ +.highlight .vg { color: #B8860B } /* Name.Variable.Global */ +.highlight .vi { color: #B8860B } /* Name.Variable.Instance */ +.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */ + diff --git a/doc/stylesheets/slidy.css b/doc/stylesheets/slidy.css new file mode 100644 index 0000000..bbb790e --- /dev/null +++ b/doc/stylesheets/slidy.css @@ -0,0 +1,445 @@ +/* slidy.css + + Copyright (c) 2005-2010 W3C (MIT, ERCIM, Keio), All Rights Reserved. + W3C liability, trademark, document use and software licensing + rules apply, see: + + http://www.w3.org/Consortium/Legal/copyright-documents + http://www.w3.org/Consortium/Legal/copyright-software +*/ + +/* + SJR: 2010-09-29: Modified for AsciiDoc slidy backend. + Mostly just commented out stuff that is handled by AsciiDoc's CSS files. +*/ + +body +{ + margin: 0 0 0 0; + padding: 0 0 0 0; + width: 100%; + height: 100%; + color: black; + background-color: white; +/* + font-family: "Gill Sans MT", "Gill Sans", GillSans, sans-serif; +*/ + font-size: 14pt; +} + +div.toolbar { + position: fixed; z-index: 200; + top: auto; bottom: 0; left: 0; right: 0; + height: 1.2em; text-align: right; + padding-left: 1em; + padding-right: 1em; + font-size: 60%; + color: red; + background-color: rgb(240,240,240); + border-top: solid 1px rgb(180,180,180); +} + +div.toolbar span.copyright { + color: black; + margin-left: 0.5em; +} + +div.initial_prompt { + position: absolute; + z-index: 1000; + bottom: 1.2em; + width: 90%; + background-color: rgb(200,200,200); + opacity: 0.35; + background-color: rgb(200,200,200, 0.35); + cursor: pointer; +} + +div.initial_prompt p.help { + text-align: center; +} + +div.initial_prompt p.close { + text-align: right; + font-style: italic; +} + +div.slidy_toc { + position: absolute; + z-index: 300; + width: 60%; + max-width: 30em; + height: 30em; + overflow: auto; + top: auto; + right: auto; + left: 4em; + bottom: 4em; + padding: 1em; + background: rgb(240,240,240); + border-style: solid; + border-width: 2px; + font-size: 60%; +} + +div.slidy_toc .toc_heading { + text-align: center; + width: 100%; + margin: 0; + margin-bottom: 1em; + border-bottom-style: solid; + border-bottom-color: rgb(180,180,180); + border-bottom-width: 1px; +} + +div.slide { + z-index: 20; + margin: 0 0 0 0; + padding-top: 0; + padding-bottom: 0; + padding-left: 20px; + padding-right: 20px; + border-width: 0; + clear: both; + top: 0; + bottom: 0; + left: 0; + right: 0; + line-height: 120%; + background-color: transparent; +} + +div.background { + display: none; +} + +div.handout { + margin-left: 20px; + margin-right: 20px; +} + +div.slide.titlepage { + text-align: center; +} + +div.slide.titlepage.h1 { + padding-top: 10%; +} + +div.slide h1 { + padding-left: 0; + padding-right: 20pt; + padding-top: 4pt; + padding-bottom: 4pt; + margin-top: 0; + margin-left: 0; + margin-right: 60pt; + margin-bottom: 0.5em; + display: block; + font-size: 160%; + line-height: 1.2em; + background: transparent; +} + +div.toc { + position: absolute; + top: auto; + bottom: 4em; + left: 4em; + right: auto; + width: 60%; + max-width: 30em; + height: 30em; + border: solid thin black; + padding: 1em; + background: rgb(240,240,240); + color: black; + z-index: 300; + overflow: auto; + display: block; + visibility: visible; +} + +div.toc-heading { + width: 100%; + border-bottom: solid 1px rgb(180,180,180); + margin-bottom: 1em; + text-align: center; +} + +/* +pre { + font-size: 80%; + font-weight: bold; + line-height: 120%; + padding-top: 0.2em; + padding-bottom: 0.2em; + padding-left: 1em; + padding-right: 1em; + border-style: solid; + border-left-width: 1em; + border-top-width: thin; + border-right-width: thin; + border-bottom-width: thin; + border-color: #95ABD0; + color: #00428C; + background-color: #E4E5E7; +} +*/ + +/* +li pre { margin-left: 0; } + +blockquote { font-style: italic } + +img { background-color: transparent } + +p.copyright { font-size: smaller } +*/ + +.center { text-align: center } +.footnote { font-size: smaller; margin-left: 2em; } + +/* +a img { border-width: 0; border-style: none } +*/ + +a:visited { color: navy } +a:link { color: navy } +a:hover { color: red; text-decoration: underline } +a:active { color: red; text-decoration: underline } + +a {text-decoration: none} +.navbar a:link {color: white} +.navbar a:visited {color: yellow} +.navbar a:active {color: red} +.navbar a:hover {color: red} + +/* +ul { list-style-type: square; } +ul ul { list-style-type: disc; } +ul ul ul { list-style-type: circle; } +ul ul ul ul { list-style-type: disc; } +li { margin-left: 0.5em; margin-top: 0.5em; } +li li { font-size: 85%; font-style: italic } +li li li { font-size: 85%; font-style: normal } +*/ + +div dt +{ + margin-left: 0; + margin-top: 1em; + margin-bottom: 0.5em; + font-weight: bold; +} +div dd +{ + margin-left: 2em; + margin-bottom: 0.5em; +} + + +/* +p,pre,ul,ol,blockquote,h2,h3,h4,h5,h6,dl,table { + margin-left: 1em; + margin-right: 1em; +} +*/ + +p.subhead { font-weight: bold; margin-top: 2em; } + +.smaller { font-size: smaller } +.bigger { font-size: 130% } + +/* +td,th { padding: 0.2em } +*/ + +ul { + margin: 0.5em 1.5em 0.5em 1.5em; + padding: 0; +} + +ol { + margin: 0.5em 1.5em 0.5em 1.5em; + padding: 0; +} + +ul { list-style-type: square; } +ul ul { list-style-type: disc; } +ul ul ul { list-style-type: circle; } +ul ul ul ul { list-style-type: disc; } + +/* +ul li { + list-style: square; + margin: 0.1em 0em 0.6em 0; + padding: 0 0 0 0; + line-height: 140%; +} + +ol li { + margin: 0.1em 0em 0.6em 1.5em; + padding: 0 0 0 0px; + line-height: 140%; + list-style-type: decimal; +} + +li ul li { + font-size: 85%; + font-style: italic; + list-style-type: disc; + background: transparent; + padding: 0 0 0 0; +} +li li ul li { + font-size: 85%; + font-style: normal; + list-style-type: circle; + background: transparent; + padding: 0 0 0 0; +} +li li li ul li { + list-style-type: disc; + background: transparent; + padding: 0 0 0 0; +} + +li ol li { + list-style-type: decimal; +} + + +li li ol li { + list-style-type: decimal; +} +*/ + +/* + setting class="outline" on ol or ul makes it behave as an + ouline list where blocklevel content in li elements is + hidden by default and can be expanded or collapsed with + mouse click. Set class="expand" on li to override default +*/ + +ol.outline li:hover { cursor: pointer } +ol.outline li.nofold:hover { cursor: default } + +ul.outline li:hover { cursor: pointer } +ul.outline li.nofold:hover { cursor: default } + +ol.outline { list-style:decimal; } +ol.outline ol { list-style-type:lower-alpha } + +ol.outline li.nofold { + padding: 0 0 0 20px; + background: transparent url(../graphics/nofold-dim.gif) no-repeat 0px 0.5em; +} +ol.outline li.unfolded { + padding: 0 0 0 20px; + background: transparent url(../graphics/fold-dim.gif) no-repeat 0px 0.5em; +} +ol.outline li.folded { + padding: 0 0 0 20px; + background: transparent url(../graphics/unfold-dim.gif) no-repeat 0px 0.5em; +} +ol.outline li.unfolded:hover { + padding: 0 0 0 20px; + background: transparent url(../graphics/fold.gif) no-repeat 0px 0.5em; +} +ol.outline li.folded:hover { + padding: 0 0 0 20px; + background: transparent url(../graphics/unfold.gif) no-repeat 0px 0.5em; +} + +ul.outline li.nofold { + padding: 0 0 0 20px; + background: transparent url(../graphics/nofold-dim.gif) no-repeat 0px 0.5em; +} +ul.outline li.unfolded { + padding: 0 0 0 20px; + background: transparent url(../graphics/fold-dim.gif) no-repeat 0px 0.5em; +} +ul.outline li.folded { + padding: 0 0 0 20px; + background: transparent url(../graphics/unfold-dim.gif) no-repeat 0px 0.5em; +} +ul.outline li.unfolded:hover { + padding: 0 0 0 20px; + background: transparent url(../graphics/fold.gif) no-repeat 0px 0.5em; +} +ul.outline li.folded:hover { + padding: 0 0 0 20px; + background: transparent url(../graphics/unfold.gif) no-repeat 0px 0.5em; +} + +/* for slides with class "title" in table of contents */ +a.titleslide { font-weight: bold; font-style: italic } + +/* + hide images for work around for save as bug + where browsers fail to save images used by CSS +*/ +img.hidden { display: none; visibility: hidden } +div.initial_prompt { display: none; visibility: hidden } + + div.slide { + visibility: visible; + position: inherit; + } + div.handout { + border-top-style: solid; + border-top-width: thin; + border-top-color: black; + } + +@media screen { + .hidden { display: none; visibility: visible } + + div.slide.hidden { display: block; visibility: visible } + div.handout.hidden { display: block; visibility: visible } + div.background { display: none; visibility: hidden } + body.single_slide div.initial_prompt { display: block; visibility: visible } + body.single_slide div.background { display: block; visibility: visible } + body.single_slide div.background.hidden { display: none; visibility: hidden } + body.single_slide .invisible { visibility: hidden } + body.single_slide .hidden { display: none; visibility: hidden } + body.single_slide div.slide { position: absolute } + body.single_slide div.handout { display: none; visibility: hidden } +} + +@media print { + .hidden { display: block; visibility: visible } + +/* + div.slide pre { font-size: 60%; padding-left: 0.5em; } +*/ + div.toolbar { display: none; visibility: hidden; } + div.slidy_toc { display: none; visibility: hidden; } + div.background { display: none; visibility: hidden; } + div.slide { page-break-before: always } + /* :first-child isn't reliable for print media */ + div.slide.first-slide { page-break-before: avoid } +} + + +/* SJR: AsciiDoc slidy backend tweaks */ + +ol, ul { + margin: 0.8em 1.5em 0.8em 1.8em; +} +li > ul, li > ol { + margin-top: 0.5em; +} + +.outline > li.folded, +.outline > li.unfolded { + color: #527bbd; +} +ul > li{ color: #aaa; } +ul > li > *, ol > li > * { color: black; } + +li { + margin-top: 0.5em; + margin-bottom: 0.5em; +} diff --git a/doc/stylesheets/toc2.css b/doc/stylesheets/toc2.css new file mode 100644 index 0000000..a1e368b --- /dev/null +++ b/doc/stylesheets/toc2.css @@ -0,0 +1,34 @@ +@media screen { + body { + max-width: 50em; /* approximately 80 characters wide */ + margin-left: 16em; + } + + #toc { + position: fixed; + top: 0; + left: 0; + bottom: 0; + width: 13em; + padding: 0.5em; + padding-bottom: 1.5em; + margin: 0; + overflow: auto; + border-right: 3px solid #f8f8f8; + } + + #toc .toclevel1 { + margin-top: 0.5em; + } + + #toc .toclevel2 { + margin-top: 0.25em; + display: list-item; + /* OLD color: #aaaaaa; */ + color: #990000; + } + + #toctitle { + margin-top: 0.5em; + } +} diff --git a/doc/stylesheets/volnitsky-manpage.css b/doc/stylesheets/volnitsky-manpage.css new file mode 100644 index 0000000..75a2dda --- /dev/null +++ b/doc/stylesheets/volnitsky-manpage.css @@ -0,0 +1 @@ +/* Empty placeholder file */ diff --git a/doc/stylesheets/volnitsky.css b/doc/stylesheets/volnitsky.css new file mode 100644 index 0000000..b6c4a15 --- /dev/null +++ b/doc/stylesheets/volnitsky.css @@ -0,0 +1,435 @@ +/* + * AsciiDoc 'volnitsky' theme for xhtml11 and html5 backends. + * Based on css from http://volnitsky.com, which was in turn based on default + * theme from AsciiDoc + * + * FIXME: The stlying is still a bit rough in places. + * + */ + +/* Default font. */ +body { + font-family: Georgia,"Times New Roman",Times,serif; +} + +/* Title font. */ +h1, h2, h3, h4, h5, h6, +div.title, caption.title, +thead, p.table.header, +#toctitle, +#author, #revnumber, #revdate, #revremark, +#footer { + font-family: Candara,Arial,sans-serif; +} + + +#toc a { + border-bottom: 1px dotted #999999; + color: #3A3A4D !important; + text-decoration: none !important; +} +#toc a:hover { + border-bottom: 1px solid #6D4100; + color: #6D4100 !important; + text-decoration: none !important; +} +a { color: #666688; text-decoration: none; border-bottom: 1px dotted #666688; } +a:visited { color: #615FA0; border-bottom: 1px dotted #615FA0; } +a:hover { color: #6D4100; border-bottom: 1px solid #6D4100; } + +em { + font-style: italic; + color: #444466; +} + +strong { + font-weight: bold; + color: #444466; +} + +h1, h2, h3, h4, h5, h6 { + color: #666688; + margin-bottom: 0.5em; + line-height: 1.3; + letter-spacing:+0.15em; +} + +h1, h2, h3 { border-bottom: 2px solid #ccd; } +h2 { padding-top: 0.5em; } +h3 { float: left; } +h3 + * { clear: left; } + +div.sectionbody { + margin-left: 0; +} + +hr { + border: 1px solid #444466; +} + +p { + margin-top: 0.5em; + margin-bottom: 0.5em; +} + +ul, ol, li > p { + margin-top: 0; +} + +pre { + padding: 0; + margin: 0; +} + +#author { + color: #444466; + font-weight: bold; + font-size: 1.1em; +} + +#footer { + font-size: small; + border-top: 2px solid silver; + padding-top: 0.5em; + margin-top: 4.0em; +} + +#footer-text { + float: left; + padding-bottom: 0.5em; +} + +#footer-badges { + float: right; + padding-bottom: 0.5em; +} + +#preamble { + margin-top: 1.5em; + margin-bottom: 1.5em; +} + +div.tableblock, div.imageblock, div.exampleblock, div.verseblock, +div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock, +div.admonitionblock { + margin-top: 1.5em; + margin-bottom: 1.5em; +} + +div.admonitionblock { + margin-top: 2.5em; + margin-bottom: 2.5em; +} + +div.content { /* Block element content. */ + padding: 0; +} + +/* Block element titles. */ +div.title, caption.title { + color: #444466; + font-weight: bold; + text-align: left; + margin-top: 1.0em; + margin-bottom: 0.5em; +} +div.title + * { + margin-top: 0; +} + +td div.title:first-child { + margin-top: 0.0em; +} +div.content div.title:first-child { + margin-top: 0.0em; +} +div.content + div.title { + margin-top: 0.0em; +} + +div.sidebarblock > div.content { + background: #ffffee; + border: 1px solid silver; + padding: 0.5em; +} + +div.listingblock > div.content { + border: 1px solid silver; + background: #f4f4f4; + padding: 0.5em; +} + +div.quoteblock { + padding-left: 2.0em; + margin-right: 10%; +} +div.quoteblock > div.attribution { + padding-top: 0.5em; + text-align: right; +} + +div.verseblock { + padding-left: 2.0em; + margin-right: 10%; +} +div.verseblock > pre.content { + font-family: inherit; +} +div.verseblock > div.attribution { + padding-top: 0.75em; + text-align: left; +} +/* DEPRECATED: Pre version 8.2.7 verse style literal block. */ +div.verseblock + div.attribution { + text-align: left; +} + +div.admonitionblock .icon { + vertical-align: top; + font-size: 1.1em; + font-weight: bold; + text-decoration: underline; + color: #444466; + padding-right: 0.5em; +} +div.admonitionblock td.content { + padding-left: 0.5em; + border-left: 2px solid silver; +} + +div.exampleblock > div.content { + border-left: 2px solid silver; + padding: 0.5em; +} + +div.imageblock div.content { padding-left: 0; } +span.image img { border-style: none; } +a.image:visited { color: white; } + +dl { + margin-top: 0.8em; + margin-bottom: 0.8em; +} +dt { + margin-top: 0.5em; + margin-bottom: 0; + font-style: normal; + color: #444466; +} +dd > *:first-child { + margin-top: 0.1em; +} + +ul, ol { + list-style-position: outside; +} +ol.arabic { + list-style-type: decimal; +} +ol.loweralpha { + list-style-type: lower-alpha; +} +ol.upperalpha { + list-style-type: upper-alpha; +} +ol.lowerroman { + list-style-type: lower-roman; +} +ol.upperroman { + list-style-type: upper-roman; +} + +div.compact ul, div.compact ol, +div.compact p, div.compact p, +div.compact div, div.compact div { + margin-top: 0.1em; + margin-bottom: 0.1em; +} + +div.tableblock > table { + border: 3px solid #444466; +} +thead { + font-weight: bold; + color: #444466; +} +tfoot { + font-weight: bold; +} +td > div.verse { + white-space: pre; +} +p.table { + margin-top: 0; +} +/* Because the table frame attribute is overriden by CSS in most browsers. */ +div.tableblock > table[frame="void"] { + border-style: none; +} +div.tableblock > table[frame="hsides"] { + border-left-style: none; + border-right-style: none; +} +div.tableblock > table[frame="vsides"] { + border-top-style: none; + border-bottom-style: none; +} + + +div.hdlist { + margin-top: 0.8em; + margin-bottom: 0.8em; +} +div.hdlist tr { + padding-bottom: 15px; +} +dt.hdlist1.strong, td.hdlist1.strong { + font-weight: bold; +} +td.hdlist1 { + vertical-align: top; + font-style: normal; + padding-right: 0.8em; + color: #444466; +} +td.hdlist2 { + vertical-align: top; +} +div.hdlist.compact tr { + margin: 0; + padding-bottom: 0; +} + +.comment { + background: yellow; +} + +@media print { + #footer-badges { display: none; } +} + +#toctitle { + color: #666688; + font-size: 1.2em; + font-weight: bold; + margin-top: 1.0em; + margin-bottom: 0.1em; +} + +div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 { margin-top: 0; margin-bottom: 0; } +div.toclevel1 { margin-top: 0.3em; margin-left: 0; font-size: 1.0em; } +div.toclevel2 { margin-top: 0.25em; margin-left: 2em; font-size: 0.9em; } +div.toclevel3 { margin-left: 4em; font-size: 0.8em; } +div.toclevel4 { margin-left: 6em; font-size: 0.8em; } + +body { + margin: 1em 5%; + max-width: 55em; + padding-left: 0; + +} + +.monospaced, tt, div.listingblock > div.content { + font-family: Consolas, "Andale Mono", "Courier New", monospace; + color: #004400; + background: #f4f4f4; + max-width: 80em; + line-height: 1.2em; +} + +.paragraph p { + line-height: 1.5em; + margin-top: 1em; +} + +.paragraph p, li, dd, .content { max-width: 45em; } +.admonitionblock { max-width: 35em; } + +div.sectionbody div.ulist > ul > li { + list-style-type: square; + color: #aaa; +} + div.sectionbody div.ulist > ul > li > * { + color: black; + /*font-size: 50%;*/ + } + + +div.sectionbody div.ulist > ul > li div.ulist > ul > li { + color: #ccd ; +} + div.sectionbody div.ulist > ul > li div.ulist > ul > li > * { + color: black ; + } + +em { + font-style: normal ! important; + font-weight: bold ! important; + color: #662222 ! important; + letter-spacing:+0.08em ! important; +} + + +/* + * html5 specific + * + * */ + +table.tableblock { + margin-top: 1.0em; + margin-bottom: 1.5em; +} +thead, p.tableblock.header { + font-weight: bold; + color: #666688; +} +p.tableblock { + margin-top: 0; +} +table.tableblock { + border-width: 3px; + border-spacing: 0px; + border-style: solid; + border-color: #444466; + border-collapse: collapse; +} +th.tableblock, td.tableblock { + border-width: 1px; + padding: 4px; + border-style: solid; + border-color: #444466; +} + +table.tableblock.frame-topbot { + border-left-style: hidden; + border-right-style: hidden; +} +table.tableblock.frame-sides { + border-top-style: hidden; + border-bottom-style: hidden; +} +table.tableblock.frame-none { + border-style: hidden; +} + +th.tableblock.halign-left, td.tableblock.halign-left { + text-align: left; +} +th.tableblock.halign-center, td.tableblock.halign-center { + text-align: center; +} +th.tableblock.halign-right, td.tableblock.halign-right { + text-align: right; +} + +th.tableblock.valign-top, td.tableblock.valign-top { + vertical-align: top; +} +th.tableblock.valign-middle, td.tableblock.valign-middle { + vertical-align: middle; +} +th.tableblock.valign-bottom, td.tableblock.valign-bottom { + vertical-align: bottom; +} + + diff --git a/doc/stylesheets/xhtml11-quirks.css b/doc/stylesheets/xhtml11-quirks.css new file mode 100644 index 0000000..b3b46d2 --- /dev/null +++ b/doc/stylesheets/xhtml11-quirks.css @@ -0,0 +1,43 @@ +/* Workarounds for IE6's broken and incomplete CSS2. */ + +div.sidebar-content { + background: #ffffee; + border: 1px solid silver; + padding: 0.5em; +} +div.sidebar-title, div.image-title { + color: #527bbd; + font-family: sans-serif; + font-weight: bold; + margin-top: 0.0em; + margin-bottom: 0.5em; +} + +div.listingblock div.content { + border: 1px solid silver; + background: #f4f4f4; + padding: 0.5em; +} + +div.quoteblock-attribution { + padding-top: 0.5em; + text-align: right; +} + +pre.verseblock-content { + font-family: inherit; +} +div.verseblock-attribution { + padding-top: 0.75em; + text-align: left; +} + +div.exampleblock-content { + border-left: 3px solid #dddddd; + padding-left: 0.5em; +} + +div.imageblock.latex div.image-title { margin-top: 0.5em; } + +/* IE6 sets dynamically generated links as visited. */ +div#toc a:visited { color: blue; } From dea6de42f69a5137544723f7a96bc097adbbdd29 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 21 Jul 2011 12:27:52 +0200 Subject: [PATCH 055/432] Include IFLA_LINK in link messages --- lib/route/link.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/route/link.c b/lib/route/link.c index 0295666..8406edc 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -1073,6 +1073,9 @@ static int build_link_msg(int cmd, struct ifinfomsg *hdr, if (link->ce_mask & LINK_ATTR_IFALIAS) NLA_PUT_STRING(msg, IFLA_IFALIAS, link->l_ifalias); + if (link->ce_mask & LINK_ATTR_LINK) + NLA_PUT_U32(msg, IFLA_LINK, link->l_link); + if ((link->ce_mask & LINK_ATTR_LINKINFO) && link->l_info_ops) { struct nlattr *info; From 50074732af4fbfc0ca5ae4bb07e971bc9e222126 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 21 Jul 2011 16:24:31 +0200 Subject: [PATCH 056/432] more documentation updates - improved stylesheets for both doxygen and asciidoc - use of xml doxygen layout - python script to resolve <> asciidoc references to <> based on the target caption - graphics for netlink and netlink error headers - more link documentation --- doc/Doxyfile.in | 2 +- doc/DoxygenLayout.xml | 185 +++++++++++++++ doc/Makefile.am | 8 +- doc/core.txt | 309 ++++++++++++------------- doc/images/attribute_hdr.png | Bin 0 -> 14996 bytes doc/images/ifinfomsg.png | Bin 0 -> 44814 bytes doc/images/library_overview.png | Bin 0 -> 23870 bytes doc/images/nlmsgerr.png | Bin 0 -> 43810 bytes doc/images/nlmsghdr.png | Bin 0 -> 19553 bytes doc/index.txt | 28 ++- doc/libnl.css | 271 +++++++++++++++++++--- doc/resolve-asciidoc-refs.py | 25 ++ doc/route.txt | 399 +++++++++++++++++++++++++++++--- doc/stylesheets/asciidoc.css | 6 +- 14 files changed, 998 insertions(+), 235 deletions(-) create mode 100644 doc/DoxygenLayout.xml create mode 100644 doc/images/attribute_hdr.png create mode 100644 doc/images/ifinfomsg.png create mode 100644 doc/images/library_overview.png create mode 100644 doc/images/nlmsgerr.png create mode 100644 doc/images/nlmsghdr.png create mode 100755 doc/resolve-asciidoc-refs.py diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index ed78bfe..5deba44 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -519,7 +519,7 @@ FILE_VERSION_FILTER = # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. -LAYOUT_FILE = +LAYOUT_FILE = DoxygenLayout.xml #--------------------------------------------------------------------------- # configuration options related to warning and progress messages diff --git a/doc/DoxygenLayout.xml b/doc/DoxygenLayout.xml new file mode 100644 index 0000000..29049d1 --- /dev/null +++ b/doc/DoxygenLayout.xml @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/Makefile.am b/doc/Makefile.am index 165660b..149daba 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -4,14 +4,16 @@ ASCIIDOCOPTS=-a pygments -a language=c -a icons \ -a toc2 \ + -a numbered \ -a imagesdir="./images/" \ -a iconsdir="./images/icons" \ -a stylesdir="${abs_srcdir}/stylesheets/" %.html: %.txt - asciidoc $(ASCIIDOCOPTS) $< - ./doxygen-link.py libnl.dict $@ > doxygen-link.tmp - mv doxygen-link.tmp $@ + ./resolve-asciidoc-refs.py $< > asciidoc.tmp + asciidoc $(ASCIIDOCOPTS) -o $@ asciidoc.tmp + ./doxygen-link.py libnl.dict $@ > asciidoc.tmp + mv asciidoc.tmp $@ asciidoc: core.html route.html index.html diff --git a/doc/core.txt b/doc/core.txt index 42f1035..0ab32ec 100644 --- a/doc/core.txt +++ b/doc/core.txt @@ -20,25 +20,42 @@ provides a abstract data type framework which eases the implementation of object based netlink protocols where objects are added, removed, or modified using a netlink based protocol. -.Sub Libraries +.Library Hierarchy -Several sub libraries exist which provide APIs to several netlink -protocols: +The suite is split into multiple libraries: -- link:route.html[libnl-route] Adresses, Links, Neighbours, Routing & Traffic Control -- Netfilter -- Generic Netlink +image:library_overview.png["Library Hierarchy"] -+FIXME+: Add links +link:core.html[Netlink Library] (libnl):: +Socket handling, sending and receiving, message construction and parsing, ... + +link:route.html[Routing Family Library] (libnl-route):: +Adresses, links, neighbours, routing, traffic control, neighbour tables, ... + +Netfilter Library (libnl-nf):: +Connection tracking, logging, queueing + +Generic Netlink Library (libnl-genl):: +Controller API, family and command registration === How To Read This Documentation -The documentation consists of this manual and the API reference pages. -Both contain references to each other and as many examples as -possible. +The libraries provide a broad set of APIs of which most applications only +require a small subset of it. Depending on the type of application, some +users may only be interested in the low level netlink messaging API while +others wish to make heavy use of the high level API. + +In any case it is recommended to get familiar with the netlink protocol +first. + +- <> + +The low level APIs are described in: + +- <> +- <> -+FIXME+ === Linking to this Library @@ -48,9 +65,10 @@ The main header is ``. Additional headers need to be included in your sources depending on the subsystems your program makes use of. +.Version Checking [source,c] ----- -#include +#include #if LIBNL_VER_NUM >= LIBNL_VER(3,0) /* include code if compiled with libnl version >= 3.0 */ @@ -64,8 +82,9 @@ $ gcc myprogram.c -o myprogram -lnl === Debugging -The library contains debugging statements which are printed to -+stderr+ if the environment variable +NLDBG+ is set to > 0. +The library has been compiled with debugging statements enabled it will +print debug information to +stderr+ if the environment variable +NLDBG+ +is set to > 0. ----- $ NLDBG=2 ./myprogram @@ -130,7 +149,7 @@ $ NLCB=debug ./myprogram ----- -[[core_prot_fund]] +[[core_netlink_fundamentals]] == Netlink Protocol Fundamentals The netlink protocol is a socket based IPC mechanism used for @@ -147,19 +166,36 @@ each peer. A netlink protocol is typically based on messages and consists of the netlink message header (+struct nlmsghdr+) plus the payload attached -to it. The payload can consist of arbitary data but usually contains +to it. The payload can consist of arbitrary data but usually contains a fixed size protocol specific header followed by a stream of attributes. -.Netlink message header (+struct nlmsghdr+) -[cols="^s,^s", width="40%", align="center"] -|============================================================== -2+| Length -| Type | Flags -2+| Sequence Number -2+| Port (Address) -|============================================================== +.Netlink message header (struct nlmsghdr) +image:nlmsghdr.png[align="center", alt="Netlink Message Header"] + +Total Length (32bit):: +Total length of the message in bytes including the netlink message header. + +Message Type (16bit):: +The message type specifies the type of payload the message is carrying. +Several standard message types are defined by the netlink protocol. +Additional message types may be defined by each protocol family. See +<> for additional information. + +Message Flags (16bit):: +The message flags may be used to modify the behaviour of a message type. +See section <> for a list of standard message flags. + +Sequence Number (32bit):: +The sequence number is optional and may be used to allow referring to +a previous message, e.g. an error message can refer to the original +request causing the error. + +Port Number (32bit):: +The port number specifies the peer to which the message should be delivered +to. If not specified, the message will be delivered to the first matching +kernel side socket of the same protocol family. [[core_msg_types]] === Message Types @@ -193,10 +229,9 @@ The type of message is primarly identified by its 16 bit message type set in the message header. The following standard message types are defined: - +NLMSG_NOOP+ - No operation, message must be discarded -- +NLMSG_ERROR+ - Error message or ACK, see <>, respectively <> -- +NLMSG_DONE+ - End of multipart sequence, see <> +- +NLMSG_ERROR+ - Error message or ACK, see <> + respectively <> +- +NLMSG_DONE+ - End of multipart sequence, see <> - +NLMSG_OVERRUN+ - Overrun notification (Error) Every netlink protocol is free to define own message types. Note that @@ -231,8 +266,8 @@ msc { -------- The configuration may be changed by sending a +MSG_SETCFG+ which will -be responded to with either a ACK (see <>) -or a error message (see <>). +be responded to with either a ACK (see <>) +or a error message (see <>). ["mscgen"] -------- @@ -294,16 +329,7 @@ Error messages can be sent in response to a request. Error messages must use the standard message type +NLMSG_ERROR+. The payload consists of a error code and the original netlink mesage header of the request. -.Netlink Error Message Header (+struct nlmsggerr+) -[cols="^,^", width="50%"] -|============================================================== -2+| Length -|.nlmsg_type = NLMSG_ERROR | .nlmsg_flags = 0 -2+| Sequence number of the orig request -2+| Port number of the orig request -2+| Error Code (e.g. EINVAL) -2+| Netlink Message Header of orig. request -|============================================================== +image:nlmsgerr.png["Netlink Errror Message header"] Error messages should set the sequence number to the sequence number of the request which caused the error. @@ -337,6 +363,7 @@ msc { ACK messages also use the message type +NLMSG_ERROR+ and payload format but the error code is set to 0. +[[core_msg_flags]] ==== Message Flags The following standard flags are defined @@ -349,19 +376,16 @@ The following standard flags are defined #define NLM_F_ECHO 8 -------- -- `NLM_F_REQUEST` - Message is a request, see <>. -- `NLM_F_MULTI` - Multipart message, see <> -- `NLM_F_ACK` - ACK message requested, see <>. +- `NLM_F_REQUEST` - Message is a request, see <>. +- `NLM_F_MULTI` - Multipart message, see <> +- `NLM_F_ACK` - ACK message requested, see <>. - `NLM_F_ECHO` - Request to echo the request. The flag +NLM_F_ECHO+ is similar to the `NLM_F_ACK` flag. It can be used in combination with `NLM_F_REQUEST` and causes a notification which is sent as a result of a request to also be sent to the sender regardless of whether the sender has subscribed to the corresponding -multicast group or not. See <> +multicast group or not. See <> Additional universal message flags are defined which only apply for +GET+ requests: @@ -383,8 +407,7 @@ Additional universal message flags are defined which only apply for Use of these flags is completely optional and many netlink protocols only make use of the `NLM_F_DUMP` flag which typically requests the receiver to send a list of all objects in the context of the message type as a -sequence of multipart messages (see <>). +sequence of multipart messages (see <>). Another set of flags exist related to `NEW` or `SET` requests. These flags are mutually exclusive to the `GET` flags: @@ -411,20 +434,19 @@ Netlink allows the use of sequence numbers to help relate replies to requests. It should be noted that unlike in protocols such as TCP there is no strict enforcment of the sequence number. The sole purpose of sequence numbers is to assist a sender in relating replies to the -corresponding requests. See <> for more -information. +corresponding requests. See <> for more information. Sequence numbers are managed on a per socket basis, see -<> for more information on -how to use sequence numbers. +<> for more information on how to use sequence numbers. [[core_multicast]] === Multicast Groups TODO -See <> +See <> +[[core_sockets]] == Netlink Sockets In order to use the netlink protocol, a netlink socket is required. @@ -434,10 +456,10 @@ same netlink protocol, e.g. one socket to send requests and receive replies and another socket subscribed to a multicast group to receive notifications. -=== Socket Allocation & Freeing +=== Allocation & Freeing The netlink socket and all its related attributes are represented by -=struct nl_sock=. ++struct nl_sock+. [source,c] -------- @@ -470,8 +492,7 @@ unsigned int nl_socket_use_seq(struct nl_sock *sk); Most applications will not want to deal with sequence number handling themselves though. When using nl_send_auto() the sequence number is filled out automatically and matched again on the receiving side. See -<> for more -information. +<> for more information. This behaviour can and must be disabled if the netlink protocol implemented does not use a request/reply model, e.g. when a socket is @@ -567,7 +588,7 @@ while (1) [[core_sk_cb]] === Modifiying Socket Callback Configuration -See <> for more information on +See <> for more information on callback hooks and overwriting capabilities. Each socket is assigned a callback configuration which controls the @@ -696,9 +717,9 @@ int nl_socket_set_passcred(struct nl_sock *sk, int state); .Enable/Disable Auto-ACK Mode -The following functions allow to enable/disable Auto-ACK mode on a -socket. See <> for more information on -what implications that has. Auto-ACK mode is enabled by default. +The following functions allow to enable/disable Auto-ACK mode on a socket. +See <> for more information on what implications that has. +Auto-ACK mode is enabled by default. [source,c] -------- @@ -742,7 +763,7 @@ NOTE: Processing of NETLINK_PKTINFO has not been implemented yet. == Sending and Receiving of Messages / Data [[core_send]] -=== Sending Netlink Messages +=== Sending Messages The standard method of sending a netlink message over a netlink socket is to use the function nl_send_auto(). It will automatically complete @@ -800,7 +821,7 @@ it will try to fall back to the peer address specified in the socket unaddressed and it is left to the kernel to find the correct peer. nl_send_iovec() also adds credentials if present and enabled -(see <>). +(see <>). The message is then passed on to nl_sendmsg(). @@ -838,8 +859,8 @@ may inspect or modify the message and return an error code. If this error code is NL_OK the message is sent using sendmsg() resulting in the number of bytes written being returned. Otherwise the message sending process is aborted and the error code specified by the -callback function is returned. See <> for more information on how to set callbacks. +callback function is returned. See <> for more information +on how to set callbacks. .Sending Raw Data with nl_sendto() @@ -889,7 +910,7 @@ nl_send_simple(sock, RTM_GETLINK, NLM_F_DUMP, &rt_hdr, sizeof(rt_hdr)); -------- [[core_recv]] -=== Receiving Netlink Messages +=== Receiving Messages The easiest method to receive netlink messages is to call nl_recvmsgs_default(). It will receive messages based on the semantics defined in the socket. The @@ -917,12 +938,11 @@ nl_recvmsgs() implements the actual receiving loop, it blocks until a netlink message has been received unless the socket has been put into non-blocking mode. -For the unlikely scenario that certain required receive -characteristics can not be achieved by fine tuning the internal -recvmsgs function using the callback configuration (see <>) the application may provide a -complete own implementation of it and overwrite all calls to -nl_recvmsgs() with the function nl_cb_overwrite_recvmsgs(). +For the unlikely scenario that certain required receive characteristics +can not be achieved by fine tuning the internal recvmsgs function using +the callback configuration (see <>) the application may provide +a complete own implementation of it and overwrite all calls to nl_recvmsgs() +with the function nl_cb_overwrite_recvmsgs(). [source,c] -------- @@ -972,21 +992,21 @@ will be done repeately until the parser returns NL_STOP, an error was returned or all data has been parsed. In case the last message parsed successfully was a multipart message -(see <>) and the parser did not +(see <>) and the parser did not quit due to either an error or NL_STOP nl_recv() respectively the applications own implementation will be called again and the parser starts all over. -See <> for information on -how to extract valid netlink messages from the parser and on how to -control the behaviour of it. +See <> for information on how to extract valid +netlink messages from the parser and on how to control the behaviour +of it. [[core_parse_character]] .Parsing Characteristics The internal parser is invoked for each netlink message received from a netlink socket. It is typically fed by nl_recv() (see -<>). +<>). The parser will first ensure that the length of the data stream provided is sufficient to contain a netlink message header and that @@ -1010,8 +1030,7 @@ always returns NL_OK. Another callback hook NL_CB_SEND_ACK exists which is called if the message has the NLM_F_ACK flag set. Although I am not aware of any userspace netlink socket doing this, the application may want to send -an ACK message back to the sender (see <>). +an ACK message back to the sender (see <>). [source,c] -------- @@ -1041,12 +1060,12 @@ Messages>>). TODO -== Netlink Message Parsing & Construction +== Message Parsing & Construction === Message Format -See <> for an introduction to -the netlink protocol and its message format. +See <> for an introduction to the netlink +protocol and its message format. .Alignment @@ -1097,8 +1116,7 @@ the parsing manually. This method is described below. Alternatively the library also offers an interface to implement a parser as part of a cache operations set which is especially useful when your protocol deals with objects of any sort such as network links, routes, etc. -This high level interface is described in <> +This high level interface is described in <>. .Splitting a byte stream into separate messages @@ -1234,8 +1252,7 @@ struct nlattr *nlmsg_attrdata(const struct nlmsghdr *hdr, int hdrlen); int nlmsg_attrlen(const struct nlmsghdr *hdr, int hdrlen); -------- -See <> for more information on how to use netlink -attributes. +See <> for more information on how to use netlink attributes. .Parsing a Message the Easy Way @@ -1244,8 +1261,7 @@ step. If +hdrlen > 0+ it will first call nlmsg_valid_hdr() to check if the protocol header fits into the message. If there is more payload to parse, it will assume it to be attributes and parse the payload accordingly. The function behaves exactly like nla_parse() when -parsing attributes, see <>. +parsing attributes, see <>. [source,c] -------- @@ -1263,13 +1279,13 @@ int nlmsg_validate(struct nlmsghdr *hdr, int hdrlen, intmaxtype, struct nla_policy *policy); -------- -See <> for an -example and more information on attribute parsing. +See <> for an example and more information on +attribute parsing. === Construction of a Message -See <> for information on the netlink -message format and alignment requirements. +See <> for information on the netlink message format +and alignment requirements. Message construction is based on struct nl_msg which uses an internal buffer to store the actual netlink message. struct nl_msg +does not+ @@ -1374,14 +1390,13 @@ To use this feature, the message must be sent using the function nl_send_auto(). Like +port+, the argument +seqnr+ can be set to +NL_AUTO_PORT+ indicating that the local port assigned to the socket should be used as source port. This is generally a good idea unless -you are replying to a request. See <> for more information on how to fill the header. +you are replying to a request. See <> +for more information on how to fill the header. NOTE: The argument +payload+ can be used by the application to reserve room for additional data after the header. A value of > 0 is - equivalent to calling +nlmsg_reserve(msg, payload, - NLMSG_ALIGNTO)+. See <> for more information on reserving room for + equivalent to calling +nlmsg_reserve(msg, payload, NLMSG_ALIGNTO)+. + See <> for more information on reserving room for data. .Example @@ -1477,10 +1492,10 @@ NOTE: `nlmsg_append()` will *not* align the start of the data. Any .Adding attribtues to a message Construction of attributes and addition of attribtues to the message is -covereted in section <>. +covereted in section <>. [[core_attr]] -== Netlink Attributes +== Attributes Any form of payload should be encoded as netlink attributes whenever possible. Use of attributes allows to extend any netlink protocol in @@ -1510,9 +1525,8 @@ the message format will never ever change in the future. === Attribute Format Netlink attributes allow for any number of data chunks of arbitary -length to be attached to a netlink message. See <> for more information on where attributes are -stored in the message. +length to be attached to a netlink message. See <> +for more information on where attributes are stored in the message. The format of the attributes data returned by nlmsg_attrdata() is as follows: @@ -1532,17 +1546,7 @@ Every attribute must start at an offset which is a multiple of to be padded at the end, the function nla_padlen() returns the number of padding bytes that will or need to be added. --------- -0 1 2 3 -0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -+-------------------------------------------------------------+ -| Length | Type | -+------------------------------+------------------------------+ -| Attribute Payload | -. . -. . -+-------------------------------------------------------------+ --------- +image:attribute_hdr.png["Netlink Attribute Header"] Every attribute is encoded with a type and length field, both 16 bits, stored in the attribute header (struct nlattr) preceding the attribute @@ -1556,16 +1560,14 @@ the next attribute. .Splitting an Attributes Stream into Attributes Although most applications will use one of the functions from the -nlmsg_parse() family (See <>) an interface exists to split the attributes stream -manually. +nlmsg_parse() family (See <>) an interface exists +to split the attributes stream manually. -As described in <> the attributes -section contains a infinite sequence or stream of attributes. The -pointer returned by nlmsg_attrdata() (See <>) points to the first attribute header. Any subsequent -attribute is accessed with the function nla_next() based on the -previous header. +As described in <> the attributes section contains a +infinite sequence or stream of attributes. The pointer returned by +nlmsg_attrdata() (See <>) points to the first attribute +header. Any subsequent attribute is accessed with the function nla_next() +based on the previous header. [source,c] -------- @@ -1654,7 +1656,7 @@ void *nla_data(const struct nlattr *hdr); [NOTE] Never rely on the size of a payload being what you expect it to be. _Always_ verify the payload size and make sure that it matches your -expectations. See <>. +expectations. See <> [[core_attr_validation]] .Attribute Validation @@ -1702,8 +1704,7 @@ introduced attributes to continue functioning. -------- #include -int nla_validate(struct nlattr *head, int len, int maxtype, - struct nla_policy *policy); +int nla_validate(struct nlattr *head, int len, int maxtype, struct nla_policy *policy); -------- The function nla_validate() returns 0 if all attributes are valid, @@ -1712,26 +1713,24 @@ otherwise a validation failure specific error code is returned. Most applications will rarely use nla_validate() directly but use nla_parse() instead which takes care of validation in the same way but also parses the the attributes in the same step. See -<> for an -example and more information. +<> for an example and more information. The validation process in detail: --# If attribute type is 0 or exceeds +maxtype+ attribute is - considered valid, 0 is returned. --# If payload length is < +minlen+, +-NLE_ERANGE+ is returned. --# If +maxlen+ is defined and payload exceeds it, +-NLE_ERANGE+ - is returned. --# Datatype specific requirements rules, see - <> --# If all is ok, 0 is returned. -[[core_attr_nla_parse]] +. If attribute type is 0 or exceeds +maxtype+ attribute is + considered valid, 0 is returned. +. If payload length is < +minlen+, +-NLE_ERANGE+ is returned. +. If +maxlen+ is defined and payload exceeds it, +-NLE_ERANGE+ + is returned. +. Datatype specific requirements rules, see <> +. If all is ok, 0 is returned. + +[[core_attr_parse_easy]] .Parsing Attributes the Easy Way Most applications will not want to deal with splitting attribute -streams themselves as described in <>. A much easier method is to use -nla_parse(). +streams themselves as described in <> +A much easier method is to use nla_parse(). [source,c] -------- @@ -1742,15 +1741,13 @@ int nla_parse(struct nlattr **attrs, int maxtype, struct nlattr *head, -------- The function nla_parse() will iterate over a stream of attributes, -validate each attribute as described in <>. If the validation of all attributes succeeds, -a pointer to each attribute is stored in the +attrs+ array at -`attrs[nla_type(attr)]`. +validate each attribute as described in <> +If the validation of all attributes succeeds, a pointer to each attribute +is stored in the +attrs+ array at `attrs[nla_type(attr)]`. As an alernative to nla_parse() the function nlmsg_parse() can be used to parse the message and its attributes in one step. See -<> for -information on how to use these functions. +<> for information on how to use these functions. .Example: @@ -1815,8 +1812,7 @@ struct nlattr *nlmsg_find_attr(struct nlmsghdr *hdr, int hdrlen, int attrtype); -------- NOTE: `nla_find()` and `nlmsg_find_attr()` will *not* search in nested - attributes recursively, see <>. + attributes recursively, see <>. ==== Iterating over a Stream of Attributes @@ -1901,8 +1897,8 @@ int my_put(struct nl_msg *msg) } -------- -See <> for datatype specific -attribute construction functions. +See <> for datatype specific attribute construction +functions. .Exception Based Attribute Construction @@ -1931,8 +1927,8 @@ nla_put_failure: } -------- -See <> for more information on the -datatype specific exception based variants. +See <> for more information on the datatype specific +exception based variants. [[core_attr_types]] === Attribute Data Types @@ -2114,11 +2110,10 @@ if (attrs[ATTR_FLAG]) [[core_attr_nested]] ==== Nested Attributes -As described in <>, attributes can be -nested allowing for complex tree structures of attributes. It is -commonly used to delegate the responsibility of a subsection of the -message to a subsystem. Nested attributes are also commonly used for -transmitting list of objects. +As described in <>, attributes can be nested allowing for +complex tree structures of attributes. It is commonly used to delegate +the responsibility of a subsection of the message to a subsystem. +Nested attributes are also commonly used for transmitting list of objects. When nesting attributes, the nested attributes are included as payload of a container attribute. diff --git a/doc/images/attribute_hdr.png b/doc/images/attribute_hdr.png new file mode 100644 index 0000000000000000000000000000000000000000..0e6cfdadb032818d58350eac14fd14eb90b88c69 GIT binary patch literal 14996 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 literal 0 HcmV?d00001 diff --git a/doc/images/library_overview.png b/doc/images/library_overview.png new file mode 100644 index 0000000000000000000000000000000000000000..dd9d5fe9a6ae0b5d45a0d3816a5dbdbd83480cf4 GIT binary patch literal 23870 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 E08+_^&;S4c literal 0 HcmV?d00001 diff --git a/doc/images/nlmsgerr.png b/doc/images/nlmsgerr.png new file mode 100644 index 0000000000000000000000000000000000000000..58e53d55defe6daf927c38ea6e3adc71604177d4 GIT binary patch literal 43810 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�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 literal 0 HcmV?d00001 diff --git a/doc/index.txt b/doc/index.txt index c59be0e..c207b44 100644 --- a/doc/index.txt +++ b/doc/index.txt @@ -1,16 +1,22 @@ -libnl -===== -Thomas Graf -3.0, April 12 2011: +Documentation Overview - libnl Suite +==================================== -== Table of Contents -=== Libraries - - link:core.html[Core Library] - - link:route.html[Routing Family] +== Libraries -=== Tools - - link:link.html[Link Utility] +image:library_overview.png["Library Hierarchy"] -=== Python Packages +link:core.html[Netlink Library] (libnl):: +Socket handling, sending and receiving, message construction and parsing, ... + +link:route.html[Routing Family Library] (libnl-route):: +Adresses, links, neighbours, routing, traffic control, neighbour tables, ... + +Netfilter Library (libnl-nf):: +Connection tracking, logging, queueing + +Generic Netlink Library (libnl-genl):: +Controller API, family and command registration + +== Python Packages - netlink.core - netlink.route.link diff --git a/doc/libnl.css b/doc/libnl.css index b92bafc..ddc6ac3 100644 --- a/doc/libnl.css +++ b/doc/libnl.css @@ -2,21 +2,31 @@ body, table, div, p, dl { font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif; - font-size: 12px; + font-size: 13px; } /* @group Heading Levels */ +h1, h2, h3 { + color: #990000; +} + h1 { - font-size: 180%; + font-size: 150%; +} + +.title { + font-size: 150%; + font-weight: bold; + margin: 10px 2px; } h2 { - font-size: 140%; + font-size: 120%; } h3 { - font-size: 120%; + font-size: 100%; } dt { @@ -82,13 +92,15 @@ div.navtab { /* @group Link Styling */ a { - color: #3D578C; + /* color: #3D578C; */ + color: #990000; font-weight: normal; text-decoration: none; } .contents a:visited { - color: #4665A2; + /* color: #4665A2; */ + color: #990000; } a:hover { @@ -118,7 +130,8 @@ a.elRef { } a.code { - color: #4665A2; + /* color: #4665A2; */ + color: #990000; } a.codeRef { @@ -158,6 +171,7 @@ div.ah { border-radius: 0.5em; -webkit-border-radius: .5em; -moz-border-radius: .5em; + box-shadow: 2px 2px 3px #999; -webkit-box-shadow: 2px 2px 3px #999; -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); @@ -167,7 +181,6 @@ div.ah { div.groupHeader { margin-left: 16px; margin-top: 12px; - margin-bottom: 6px; font-weight: bold; } @@ -185,16 +198,7 @@ body { div.contents { margin-top: 10px; margin-left: 10px; - margin-right: 10px; -} - -div.contents p { - margin-left: 30px; -} - -div.contents .fragment { - margin-left: 30px; - margin-right: 20px; + margin-right: 5px; } td.indexkey { @@ -370,8 +374,13 @@ table.memberdecls { white-space: nowrap; } +.memItemRight { + width: 100%; +} + .memTemplParams { - color: #4665A2; + /* color: #4665A2; */ + color: #990000; white-space: nowrap; } @@ -382,10 +391,11 @@ table.memberdecls { /* Styles for detailed member documentation */ .memtemplate { - font-size: 100%; - color: #4665A2; + font-size: 80%; + /* color: #4665A2; */ + color: #990000; font-weight: normal; - margin-left: 3px; + margin-left: 9px; } .memnav { @@ -397,10 +407,14 @@ table.memberdecls { padding: 2px; } +.mempage { + width: 100%; +} + .memitem { padding: 0; - border: 1px solid #C4CFE5; - margin-bottom: 30px; + margin-bottom: 10px; + margin-right: 5px; } .memname { @@ -410,17 +424,53 @@ table.memberdecls { } .memproto { - background-color: #F9FAFC; - border-bottom: 1px solid #A3B4D7; + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; padding: 6px 0px 6px 0px; - color: #000000; + color: #253555; font-weight: bold; + /* text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); */ + /* opera specific markup */ + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + border-top-right-radius: 8px; + border-top-left-radius: 8px; + /* firefox specific markup */ + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + -moz-border-radius-topright: 8px; + -moz-border-radius-topleft: 8px; + /* webkit specific markup */ + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -webkit-border-top-right-radius: 8px; + -webkit-border-top-left-radius: 8px; + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; } .memdoc { + border-bottom: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; padding: 2px 5px; - margin-left: 30px; + background-color: #FBFCFD; + border-top-width: 0; + /* opera specific markup */ + border-bottom-left-radius: 8px; + border-bottom-right-radius: 8px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + /* firefox specific markup */ + -moz-border-radius-bottomleft: 8px; + -moz-border-radius-bottomright: 8px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + background-image: -moz-linear-gradient(center top, #FFFFFF 0%, #FFFFFF 60%, #F7F8FB 95%, #EEF1F7); + /* webkit specific markup */ + -webkit-border-bottom-left-radius: 8px; + -webkit-border-bottom-right-radius: 8px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + background-image: -webkit-gradient(linear,center top,center bottom,from(#FFFFFF), color-stop(0.6,#FFFFFF), color-stop(0.60,#FFFFFF), color-stop(0.95,#F7F8FB), to(#EEF1F7)); } .paramkey { @@ -432,13 +482,36 @@ table.memberdecls { } .paramname { - color: #602020; + /* color: #602020; */ + color: black; white-space: nowrap; } .paramname em { font-style: normal; } +.params, .retval, .exception, .tparams { + border-spacing: 6px 2px; +} + +.params .paramname, .retval .paramname { + font-weight: bold; + vertical-align: top; +} + +.params .paramtype { + font-style: italic; + vertical-align: top; +} + +.params .paramdir { + font-family: "courier new",courier,monospace; + vertical-align: top; +} + + + + /* @end */ /* @group Directory (tree) */ @@ -589,14 +662,14 @@ table.doxtable th { list-style-type:none; float:left; padding-left:10px; - padding-right: 15px; + padding-right:15px; background-image:url('bc_s.png'); background-repeat:no-repeat; background-position:right; color:#364D7C; } -.navpath a +.navpath li.navelem a { height:32px; display:block; @@ -604,11 +677,25 @@ table.doxtable th { outline: none; } -.navpath a:hover +.navpath li.navelem a:hover { color:#6884BD; } +.navpath li.footer +{ + list-style-type:none; + float:right; + padding-left:10px; + padding-right:15px; + background-image:none; + background-repeat:no-repeat; + background-position:right; + color:#364D7C; + font-size: 8pt; +} + + div.summary { float: right; @@ -623,6 +710,19 @@ div.summary a white-space: nowrap; } +div.ingroups +{ + font-size: 8pt; + padding-left: 5px; + width: 50%; + text-align: left; +} + +div.ingroups a +{ + white-space: nowrap; +} + div.header { background-image:url('nav_h.png'); @@ -637,3 +737,110 @@ div.headertitle padding: 5px 5px 5px 10px; } +dl +{ + padding: 0 0 0 10px; +} + +dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug +{ + border-left:4px solid; + padding: 0 0 0 6px; +} + +dl.note +{ + border-color: #D0C000; +} + +dl.warning, dl.attention +{ + border-color: #FF0000; +} + +dl.pre, dl.post, dl.invariant +{ + border-color: #00D000; +} + +dl.deprecated +{ + border-color: #505050; +} + +dl.todo +{ + border-color: #00C0E0; +} + +dl.test +{ + border-color: #3030E0; +} + +dl.bug +{ + border-color: #C08050; +} + +#projectlogo +{ + text-align: center; + vertical-align: bottom; + border-collapse: separate; +} + +#projectlogo img +{ + border: 0px none; +} + +#projectname +{ + font: 300% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 2px 0px; +} + +#projectbrief +{ + font: 120% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#projectnumber +{ + font: 50% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#titlearea +{ + padding: 0px; + margin: 0px; + width: 100%; + border-bottom: 1px solid #5373B4; +} + +.image +{ + text-align: center; +} + +.dotgraph +{ + text-align: center; +} + +.mscgraph +{ + text-align: center; +} + +.caption +{ + font-weight: bold; +} + diff --git a/doc/resolve-asciidoc-refs.py b/doc/resolve-asciidoc-refs.py new file mode 100755 index 0000000..5418747 --- /dev/null +++ b/doc/resolve-asciidoc-refs.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python + +import fileinput +import re +import sys + +refs = {} +complete_file = "" + +for line in open(sys.argv[1], 'r'): + complete_file += line + +for m in re.findall('\[\[(.+)\]\]\n=+ ([^\n]+)', complete_file): + ref, title = m + refs["<<" + ref + ">>"] = "<<" + ref + ", " + title + ">>" + +def translate(match): + try: + return refs[match.group(0)] + except KeyError: + return "" + +rc = re.compile('|'.join(map(re.escape, sorted(refs, reverse=True)))) +for line in open(sys.argv[1], 'r'): + print rc.sub(translate, line), diff --git a/doc/route.txt b/doc/route.txt index 1f68116..b9b50b6 100644 --- a/doc/route.txt +++ b/doc/route.txt @@ -35,50 +35,316 @@ commonly used In user space the term _network interface_ is very common. The routing netlink protocol uses the term _link_ and so does the _iproute2_ utility and most routing daemons. -=== Protocol Definition +=== Netlink Protocol -This section describes the protocol semantics of the netlink link configuration -interface. The following netlink message types are defined: +This section describes the protocol semantics of the netlink based link +configuration interface. The following messages are defined: [options="header", cols="1,2,2"] |============================================================================== | Message Type | User -> Kernel | Kernel -> User -| +RTM_NEWLINK+ | Create new virtual network device | Notification: Link changed or added -| +RTM_DELLINK+ | Delete virtual network device | Notification: Link deleted or disappeared +| +RTM_NEWLINK+ | Create or update virtual network device +| Reply to +RTM_GETLINK+ request or notification of link added or updated +| +RTM_DELLINK+ | Delete virtual network device +| Notification of link deleted or disappeared | +RTM_GETLINK+ | Retrieve link configuration and statistics | | +RTM_SETLINK+ | Modify link configuration | |============================================================================== -See the link:core.html#core_msg_types[Message Types] section of the Netlink -Library documentation for more information on common semantics of these message -types. +See link:core.html#core_msg_types[Netlink Library - Message Types] for more +information on common semantics of these message types. -.Link Message Header +==== Link Message Format -All netlink link messages share the following common header which is appended -after the netlink message header (+struct nlmsghdr+). It is defined in the -header ++ +All netlink link messages share a common header (+struct ifinfomsg+) which +is appended after the netlink header (+struct nlmsghdr+). -[source,c] ------ -struct ifinfomsg { - unsigned char ifi_family; - unsigned char __ifi_pad; - unsigned short ifi_type; /* ARPHRD_* */ - int ifi_index; /* Link index */ - unsigned ifi_flags; /* IFF_* flags */ - unsigned ifi_change; /* IFF_* change mask */ -}; ------ +image:ifinfomsg.png["Link Message Header"] -The meaning of each field may differ depending on the message type. +The meaning of each field may differ depending on the message type. A ++struct ifinfomsg+ is defined in ++ to represent the +header. -.Attributes +Address Family (8bit):: +The address family is usually set to +AF_UNSPEC+ but may be specified in ++RTM_GETLINK+ requests to limit the returned links to a specific address +family. +Link Layer Type (16bit):: +Currently only used in kernel->user messages to report the link layer type +of a link. The value corresponds to the +ARPHRD_*+ defines found in +++. Translation from/to strings can be done using the +functions nl_llproto2str()/nl_str2llproto(). + +Link Index (32bit):: +Carries the interface index and is used to identify existing links. + +Flags (32bit):: +In kernel->user messages the value of this field represents the current +state of the link flags. In user->kernel messages this field is used to +change flags or set the initial flag state of new links. Note that in order +to change a flag, the flag must also be set in the _Flags Change Mask_ field. + +Flags Change Mask (32bit):: +The primary use of this field is to specify a mask of flags that should be +changed based on the value of the _Flags_ field. A special meaning is given +to this field when present in link notifications, see TODO. + +Attributes (variable):: All link message types may carry netlink attributes. They are defined in the header file and share the prefix +IFLA_+. +==== Link Message Types +.RTM_GETLINK (user->kernel) + +Lookup link by 1. interface index or 2. link name (+IFLA_IFNAME+) and return +a single +RTM_NEWLINK+ message containing the link configuration and statistics +or a netlink error message if no such link was found. + +*Parameters:* + +* *Address family* +** If the address family is set to +PF_BRIDGE+, only bridging devices will be + returned. +** If the address family is set to +PF_INET6+, only ipv6 enabled devices will + be returned. + +*Flags:* + +* +NLM_F_DUMP+ If set, all links will be returned in form of a multipart + message. + +*Returns:* + +* +EINVAL+ if neither interface nor link name are set +* +ENODEV+ if no link was found +* +ENOBUFS+ if allocation failed + +.RTM_NEWLINK (user->kernel) + +Creates a new or updates an existing link. Only virtual links may be created +but all links may be updated. + +*Flags:* + +- +NLM_F_CREATE+ Create link if it does not exist +- +NLM_F_EXCL+ Return +EEXIST+ if link already exists + +*Returns:* + +- +EINVAL+ malformed message or invalid configuration parameters +- +EAFNOSUPPORT+ if a address family specific configuration (+IFLA_AF_SPEC+) + is not supported. +- +EOPNOTSUPP+ if the link does not support modification of parameters +- +EEXIST+ if +NLM_F_EXCL+ was set and the link exists alraedy +- +ENODEV+ if the link does not exist and +NLM_F_CREATE+ is not set + +.RTM_NEWLINK (kernel->user) + +This message type is used in reply to a +RTM_GETLINK+ request and carries +the configuration and statistics of a link. If multiple links need to +be sent, the messages will be sent in form of a multipart message. + +The message type is also used for notifications sent by the kernel to the +multicast group +RTNLGRP_LINK+ to inform about various link events. It is +therefore recommended to always use a separate link socket for link +notifications in order to separate between the two message types. + +TODO: document how to detect different notifications + +.RTM_DELLINK (user->kernel) + +Lookup link by 1. interface index or 2. link name (+IFLA_IFNAME+) and delete +the virtual link. + +*Returns:* + +* +EINVAL+ if neither interface nor link name are set +* +ENODEV+ if no link was found +* +ENOTSUPP+ if the operation is not supported (not a virtual link) + +.RTM_DELLINK (kernel->user) + +Notification sent by the kernel to the multicast group +RTNLGRP_LINK+ when + +a. a network device was unregistered (change == ~0) +b. a bridging device was deleted (address family will be +PF_BRIDGE+) + +[source,c] +----- +#define IFF_UP 0x1 /* interface is up */ +#define IFF_BROADCAST 0x2 /* broadcast address valid */ +#define IFF_DEBUG 0x4 /* turn on debugging */ +#define IFF_LOOPBACK 0x8 /* is a loopback net */ +#define IFF_POINTOPOINT 0x10 /* interface is has p-p link */ +#define IFF_NOTRAILERS 0x20 /* avoid use of trailers */ +#define IFF_RUNNING 0x40 /* interface RFC2863 OPER_UP */ +#define IFF_NOARP 0x80 /* no ARP protocol */ +#define IFF_PROMISC 0x100 /* receive all packets */ +#define IFF_ALLMULTI 0x200 /* receive all multicast packets*/ + +#define IFF_MASTER 0x400 /* master of a load balancer */ +#define IFF_SLAVE 0x800 /* slave of a load balancer */ + +#define IFF_MULTICAST 0x1000 /* Supports multicast */ + +#define IFF_PORTSEL 0x2000 /* can set media type */ +#define IFF_AUTOMEDIA 0x4000 /* auto media select active */ +#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses*/ + +#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */ +#define IFF_DORMANT 0x20000 /* driver signals dormant */ + +#define IFF_ECHO 0x40000 /* echo sent packets */ +----- + +=== Get / List + +[[link_list]] +==== Get list of links + +To retrieve the list of links in the kernel, allocate a new link cache +using +rtnl_link_alloc_cache()+ to hold the links. It will automatically +construct and send a +RTM_GETLINK+ message requesting a dump of all links +from the kernel and feed the returned +RTM_NEWLINK+ to the internal link +message parser which adds the returned links to the cache. + +[source,c] +----- +#include + +int rtnl_link_alloc_cache(struct nl_sock *sk, int family, struct nl_cache **result) +----- + +The cache will contain link objects (+struct rtnl_link+, see <>) +and can be accessed using the standard cache functions. By setting the ++family+ parameter to an address familly other than +AF_UNSPEC+, the resulting +cache will only contain links supporting the specified address family. + +The following direct search functions are provided to search by interface +index and by link name: + +[source,c] +----- +#include + +struct rtnl_link *rtnl_link_get(struct nl_cache *cache, int ifindex); +struct rtnl_link *rtnl_link_get_by_name(struct nl_cache *cache, const char *name); +----- + +.Example: Link Cache + +[source,c] +----- +struct nl_cache *cache; +struct rtnl_link *link; + +if (rtnl_link_alloc_cache(sock, AF_UNSPEC, &cache)) < 0) + /* error */ + +if (!(link = rtnl_link_get_by_name(cache, "eth1"))) + /* link does not exist */ + +/* do something with link */ + +rtnl_link_put(link); +nl_cache_put(cache); +----- + +==== Lookup Single Link (Direct Lookup) + +If only a single link is of interest, the link can be looked up directly +without the use of a link cache using the function +rtnl_link_get_kernel()+. + +[source,c] +----- +#include + +int rtnl_link_get_kernel(struct nl_sock *sk, int ifindex, const char *name, struct rtnl_link **result); +----- + +It will construct and send a +RTM_GETLINK+ request using the parameters +provided and wait for a +RTM_NEWLINK+ or netlink error message sent in +return. If the link exists, the link is returned as link object +(see <>). + +.Example: Direct link lookup +[source,c] +----- +struct rtnl_link *link; + +if (rtnl_link_get_kernel(sock, 0, "eth1", &link) < 0) + /* error */ + +/* do something with link */ + +rtnl_link_put(link); +----- + +NOTE: While using this function can save a substantial amount of bandwidth + on the netlink socket, the result will not be cached, subsequent calls + to rtnl_link_get_kernel() will always trigger sending a +RTM_GETLINK+ + request. + +==== Translating interface index to link name + +Applications which require to translate interface index to a link name or +vice verase may use the following functions to do so. Both functions require +a filled link cache to work with. + +[source,c] +----- +char *rtnl_link_i2name (struct nl_cache *cache, int ifindex, char *dst, size_t len); +int rtnl_link_name2i (struct nl_cache *cache, const char *name); +----- + +=== Add / Modify + +Several types of virtual link can be added on the fly using the function ++rtnl_link_add()+. + +[source,c] +----- +#include + +int rtnl_link_add(struct nl_sock *sk, struct rtnl_link *link, int flags); +----- + +=== Delete + +The deletion of virtual links such as VLAN devices or dummy devices is done +using the function +rtnl_link_delete()+. The link passed on to the function +can be a link from a link cache or it can be construct with the minimal +attributes needed to identify the link. + +[source,c] +----- +#include + +int rtnl_link_delete(struct nl_sock *sk, const struct rtnl_link *link); +----- + +The function will construct and send a +RTM_DELLINK+ request message and +returns any errors returned by the kernel. + +.Example: Delete link by name +[source,c] +----- +struct rtnl_link *link; + +if (!(link = rtnl_link_alloc())) + /* error */ + +rtnl_link_set_name(link, "my_vlan"); + +if (rtnl_link_delete(sock, link) < 0) + /* error */ + +rtnl_link_put(link); +----- + +[[link_object]] === Link Object Name:: @@ -86,6 +352,8 @@ The name of a network device is the human readable representation of a network device and secondary identification parameter besides the interface index. + +Kernels >= 2.6.11 support identification by link name. ++ [source,c] ----- void rtnl_link_set_name(struct rtnl_link *link, const char *name); @@ -141,8 +409,81 @@ void rtnl_link_set_weight(struct rtnl_link *link, unsigned int weight); unsigned int rtnl_link_get_weight(struct rtnl_link *link); ----- -=== Link Cache +=== Modules +[[link_bonding]] +==== Bonding + +.Example: Add bonding link +[source,c] +----- +#include + +struct rtnl_link *link; + +link = rtnl_link_alloc(); +rtnl_link_set_name(link, "my_bond"); +rtnl_link_set_type(link, "bond"); + +/* requires admin privileges */ +if (rtnl_link_add(sk, link, NLM_F_CREATE) < 0) + /* error */ + +rtnl_link_put(link); +----- + +==== VLAN + +[source,c] +----- +extern char * rtnl_link_vlan_flags2str(int, char *, size_t); +extern int rtnl_link_vlan_str2flags(const char *); + +extern int rtnl_link_vlan_set_id(struct rtnl_link *, int); +extern int rtnl_link_vlan_get_id(struct rtnl_link *); + +extern int rtnl_link_vlan_set_flags(struct rtnl_link *, + unsigned int); +extern int rtnl_link_vlan_unset_flags(struct rtnl_link *, + unsigned int); +extern unsigned int rtnl_link_vlan_get_flags(struct rtnl_link *); + +extern int rtnl_link_vlan_set_ingress_map(struct rtnl_link *, + int, uint32_t); +extern uint32_t * rtnl_link_vlan_get_ingress_map(struct rtnl_link *); + +extern int rtnl_link_vlan_set_egress_map(struct rtnl_link *, + uint32_t, int); +extern struct vlan_map *rtnl_link_vlan_get_egress_map(struct rtnl_link *, + int *); +----- + +.Example: Add a VLAN device +[source,c] +----- +struct rtnl_link *link; +int master_index; + +/* lookup interface index of eth0 */ +if (!(master_index = rtnl_link_name2i(link_cache, "eth0"))) + /* error */ + +/* allocate new link object to configure the vlan device */ +link = rtnl_link_alloc(); + +/* set eth0 to be our master device */ +rtnl_link_set_link(link, master_index); + +if ((err = rtnl_link_set_type(link, "vlan")) < 0) + /* error */ + +rtnl_link_vlan_set_id(link, 10); + +if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) + /* error */ + +rtnl_link_put(link); +----- == Neighbouring @@ -347,8 +688,7 @@ uint32_t rtnl_tc_get_parent(struct rtnl_tc *tc); ----- Statistics:: -Generic statistics, see <> for -additional information. +Generic statistics, see <> for additional information. + [source,c] ----- @@ -593,8 +933,7 @@ if (!(qdisc = rtnl_qdisc_alloc())) ----- The next step is to specify all generic qdisc attributes using the tc -object interface described in the section <>. +object interface described in the section <>. The following attributes must be specified: - IfIndex diff --git a/doc/stylesheets/asciidoc.css b/doc/stylesheets/asciidoc.css index 19796dd..8ded7c9 100644 --- a/doc/stylesheets/asciidoc.css +++ b/doc/stylesheets/asciidoc.css @@ -23,12 +23,16 @@ body { a { /* color: blue; */ color: #990000; - text-decoration: underline; + text-decoration: none; } a:visited { /* color: fuchsia; */ } +a:hover { + text-decoration: underline; +} + em { font-style: italic; /* color: navy; */ From 4d2383620b195af055c42f9b8ced3c3668a2c505 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 21 Jul 2011 16:38:04 +0200 Subject: [PATCH 057/432] bonding link module --- lib/Makefile.am | 1 + lib/route/link/bonding.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 lib/route/link/bonding.c diff --git a/lib/Makefile.am b/lib/Makefile.am index b7f2e31..ddda933 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -58,6 +58,7 @@ libnl_route_la_SOURCES = \ \ route/link/api.c route/link/vlan.c route/link/dummy.c \ route/link/bridge.c route/link/inet6.c route/link/inet.c \ + route/link/bonding.c \ \ route/qdisc/blackhole.c route/qdisc/cbq.c route/qdisc/dsmark.c \ route/qdisc/fifo.c route/qdisc/htb.c route/qdisc/netem.c \ diff --git a/lib/route/link/bonding.c b/lib/route/link/bonding.c new file mode 100644 index 0000000..c53bf52 --- /dev/null +++ b/lib/route/link/bonding.c @@ -0,0 +1,39 @@ +/* + * lib/route/link/bonding.c Bonding Link Module + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2011 Thomas Graf + */ + +/** + * @ingroup link + * @defgroup bonding Bonding + * + * Link Documentation + * + * @{ + */ + +#include +#include +#include + +static struct rtnl_link_info_ops bonding_info_ops = { + .io_name = "bond", +}; + +static void __init bonding_init(void) +{ + rtnl_link_register_info(&bonding_info_ops); +} + +static void __exit bonding_exit(void) +{ + rtnl_link_unregister_info(&bonding_info_ops); +} + +/** @} */ From c79ab52d4767538369087d8769a8eeb8d7537ab0 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 21 Jul 2011 16:39:29 +0200 Subject: [PATCH 058/432] ignore various generated files --- doc/api/.gitignore | 1 + doc/images/.gitignore | 2 ++ 2 files changed, 3 insertions(+) diff --git a/doc/api/.gitignore b/doc/api/.gitignore index 18a5fd8..821cf65 100644 --- a/doc/api/.gitignore +++ b/doc/api/.gitignore @@ -4,3 +4,4 @@ *.map *.md5 formula.repository +jquery.js diff --git a/doc/images/.gitignore b/doc/images/.gitignore index 8a23fba..efcc7e2 100644 --- a/doc/images/.gitignore +++ b/doc/images/.gitignore @@ -1 +1,3 @@ core__* +asciidoc__*.png +*.odg From 49d29e9c2d06a3402cc197c8f916e891354324d1 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 21 Jul 2011 16:41:45 +0200 Subject: [PATCH 059/432] ignore python build directory --- python/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 python/.gitignore diff --git a/python/.gitignore b/python/.gitignore new file mode 100644 index 0000000..378eac2 --- /dev/null +++ b/python/.gitignore @@ -0,0 +1 @@ +build From 16d38a49d167983cc21067f17c84b4f07121a00d Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 21 Jul 2011 16:45:01 +0200 Subject: [PATCH 060/432] Use 'link type' instead of 'link info type' The term 'link type' is much more easier to understand than 'link info type' rtnl_link_set/get_info_type() left around for backwards compatibility --- include/netlink/route/link.h | 7 +++++-- lib/route/link.c | 33 +++++++++++++++++++++------------ 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/include/netlink/route/link.h b/include/netlink/route/link.h index 0dddaf7..d7d9cd3 100644 --- a/include/netlink/route/link.h +++ b/include/netlink/route/link.h @@ -187,8 +187,11 @@ extern uint64_t rtnl_link_get_stat(struct rtnl_link *, int); extern int rtnl_link_set_stat(struct rtnl_link *, const unsigned int, const uint64_t); -extern int rtnl_link_set_info_type(struct rtnl_link *, const char *); -extern char * rtnl_link_get_info_type(struct rtnl_link *); +extern int rtnl_link_set_type(struct rtnl_link *, const char *); +extern char * rtnl_link_get_type(struct rtnl_link *); + +extern int rtnl_link_set_info_type(struct rtnl_link *, const char *) __attribute__((deprecated)); +extern char * rtnl_link_get_info_type(struct rtnl_link *) __attribute__((deprecated)); #ifdef __cplusplus } diff --git a/lib/route/link.c b/lib/route/link.c index 8406edc..6268886 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -1977,17 +1977,17 @@ int rtnl_link_set_stat(struct rtnl_link *link, const unsigned int id, } /** - * Specify the info type of a link - * @arg link link object - * @arg type info type + * Set link type + * @arg link Link object + * @arg type Type of link * - * Looks up the info type and prepares the link to store info type - * specific attributes. If an info type has been assigned already - * it will be released with all changes lost. + * Looks up the link type modules and prepares the link to store type + * specific attributes. If a type has been assigned already it will + * be released with all link type specific attributes lost. * * @return 0 on success or a negative errror code. */ -int rtnl_link_set_info_type(struct rtnl_link *link, const char *type) +int rtnl_link_set_type(struct rtnl_link *link, const char *type) { struct rtnl_link_info_ops *io; int err; @@ -2008,13 +2008,12 @@ int rtnl_link_set_info_type(struct rtnl_link *link, const char *type) } /** - * Return info type of a link - * @arg link link object + * Get type of link + * @arg link Link object * - * @note The returned pointer is only valid as long as the link exists - * @return Info type name or NULL if unknown. + * @return Name of link type or NULL if unknown. */ -char *rtnl_link_get_info_type(struct rtnl_link *link) +char *rtnl_link_get_type(struct rtnl_link *link) { if (link->l_info_ops) return link->l_info_ops->io_name; @@ -2022,6 +2021,16 @@ char *rtnl_link_get_info_type(struct rtnl_link *link) return NULL; } +int rtnl_link_set_info_type(struct rtnl_link *link, const char *type) +{ + return rtnl_link_set_type(link, type); +} + +char *rtnl_link_get_info_type(struct rtnl_link *link) +{ + return rtnl_link_get_type(link); +} + /** @} */ static struct nl_object_ops link_obj_ops = { From 8219cc79f827459192022c026f9d82d23ff1ab3b Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 21 Jul 2011 17:47:00 +0200 Subject: [PATCH 061/432] VLAN: rtnl_link_is_vlan() function and API documentation --- doc/route.txt | 1 + include/netlink/route/link/vlan.h | 6 +- lib/route/link/vlan.c | 131 +++++++++++++++++++++++------- 3 files changed, 106 insertions(+), 32 deletions(-) diff --git a/doc/route.txt b/doc/route.txt index b9b50b6..d48c26e 100644 --- a/doc/route.txt +++ b/doc/route.txt @@ -432,6 +432,7 @@ if (rtnl_link_add(sk, link, NLM_F_CREATE) < 0) rtnl_link_put(link); ----- +[[link_vlan]] ==== VLAN [source,c] diff --git a/include/netlink/route/link/vlan.h b/include/netlink/route/link/vlan.h index a3ad76d..42768b6 100644 --- a/include/netlink/route/link/vlan.h +++ b/include/netlink/route/link/vlan.h @@ -27,17 +27,19 @@ struct vlan_map #define VLAN_PRIO_MAX 7 +extern int rtnl_link_is_vlan(struct rtnl_link *); + extern char * rtnl_link_vlan_flags2str(int, char *, size_t); extern int rtnl_link_vlan_str2flags(const char *); -extern int rtnl_link_vlan_set_id(struct rtnl_link *, int); +extern int rtnl_link_vlan_set_id(struct rtnl_link *, uint16_t); extern int rtnl_link_vlan_get_id(struct rtnl_link *); extern int rtnl_link_vlan_set_flags(struct rtnl_link *, unsigned int); extern int rtnl_link_vlan_unset_flags(struct rtnl_link *, unsigned int); -extern unsigned int rtnl_link_vlan_get_flags(struct rtnl_link *); +extern int rtnl_link_vlan_get_flags(struct rtnl_link *); extern int rtnl_link_vlan_set_ingress_map(struct rtnl_link *, int, uint32_t); diff --git a/lib/route/link/vlan.c b/lib/route/link/vlan.c index cbfdf34..cd831ce 100644 --- a/lib/route/link/vlan.c +++ b/lib/route/link/vlan.c @@ -12,7 +12,9 @@ /** * @ingroup link * @defgroup vlan VLAN - * @brief + * Virtual LAN link module + * + * See VLAN API documentation for more information * * @{ */ @@ -45,22 +47,9 @@ struct vlan_info struct vlan_map * vi_egress_qos; uint32_t vi_mask; }; + /** @endcond */ -static const struct trans_tbl vlan_flags[] = { - __ADD(VLAN_FLAG_REORDER_HDR, reorder_hdr) -}; - -char *rtnl_link_vlan_flags2str(int flags, char *buf, size_t len) -{ - return __flags2str(flags, buf, len, vlan_flags, ARRAY_SIZE(vlan_flags)); -} - -int rtnl_link_vlan_str2flags(const char *name) -{ - return __str2flags(name, vlan_flags, ARRAY_SIZE(vlan_flags)); -} - static struct nla_policy vlan_policy[IFLA_VLAN_MAX+1] = { [IFLA_VLAN_ID] = { .type = NLA_U16 }, [IFLA_VLAN_FLAGS] = { .minlen = sizeof(struct ifla_vlan_flags) }, @@ -241,7 +230,7 @@ static int vlan_clone(struct rtnl_link *dst, struct rtnl_link *src) int err; dst->l_info = NULL; - if ((err = rtnl_link_set_info_type(dst, "vlan")) < 0) + if ((err = rtnl_link_set_type(dst, "vlan")) < 0) return err; vdst = dst->l_info; @@ -334,12 +323,42 @@ static struct rtnl_link_info_ops vlan_info_ops = { .io_free = vlan_free, }; -int rtnl_link_vlan_set_id(struct rtnl_link *link, int id) +/** @cond SKIP */ +#define IS_VLAN_LINK_ASSERT(link) \ + if ((link)->l_info_ops != &vlan_info_ops) { \ + APPBUG("Link is not a vlan link. set type \"vlan\" first."); \ + return -NLE_OPNOTSUPP; \ + } +/** @endcond */ + +/** + * @name VLAN Object + * @{ + */ + +/** + * Check if link is a VLAN link + * @arg link Link object + * + * @return True if link is a VLAN link, otherwise false is returned. + */ +int rtnl_link_is_vlan(struct rtnl_link *link) +{ + return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "vlan"); +} + +/** + * Set VLAN ID + * @arg link Link object + * @arg id VLAN identifier + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vlan_set_id(struct rtnl_link *link, uint16_t id) { struct vlan_info *vi = link->l_info; - if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops) - return -NLE_OPNOTSUPP; + IS_VLAN_LINK_ASSERT(link); vi->vi_vlan_id = id; vi->vi_mask |= VLAN_HAS_ID; @@ -347,12 +366,17 @@ int rtnl_link_vlan_set_id(struct rtnl_link *link, int id) return 0; } +/** + * Get VLAN Id + * @arg link Link object + * + * @return VLAN id, 0 if not set or a negative error code. + */ int rtnl_link_vlan_get_id(struct rtnl_link *link) { struct vlan_info *vi = link->l_info; - if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops) - return -NLE_OPNOTSUPP; + IS_VLAN_LINK_ASSERT(link); if (vi->vi_mask & VLAN_HAS_ID) return vi->vi_vlan_id; @@ -360,12 +384,18 @@ int rtnl_link_vlan_get_id(struct rtnl_link *link) return 0; } +/** + * Set VLAN flags + * @arg link Link object + * @arg flags VLAN flags + * + * @return 0 on success or a negative error code. + */ int rtnl_link_vlan_set_flags(struct rtnl_link *link, unsigned int flags) { struct vlan_info *vi = link->l_info; - if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops) - return -NLE_OPNOTSUPP; + IS_VLAN_LINK_ASSERT(link); vi->vi_flags_mask |= flags; vi->vi_flags |= flags; @@ -374,12 +404,18 @@ int rtnl_link_vlan_set_flags(struct rtnl_link *link, unsigned int flags) return 0; } +/** + * Unset VLAN flags + * @arg link Link object + * @arg flags VLAN flags + * + * @return 0 on success or a negative error code. + */ int rtnl_link_vlan_unset_flags(struct rtnl_link *link, unsigned int flags) { struct vlan_info *vi = link->l_info; - if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops) - return -NLE_OPNOTSUPP; + IS_VLAN_LINK_ASSERT(link); vi->vi_flags_mask |= flags; vi->vi_flags &= ~flags; @@ -388,23 +424,34 @@ int rtnl_link_vlan_unset_flags(struct rtnl_link *link, unsigned int flags) return 0; } -unsigned int rtnl_link_vlan_get_flags(struct rtnl_link *link) +/** + * Get VLAN flags + * @arg link Link object + * + * @return VLAN flags, 0 if none set, or a negative error code. + */ +int rtnl_link_vlan_get_flags(struct rtnl_link *link) { struct vlan_info *vi = link->l_info; - if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops) - return -NLE_OPNOTSUPP; + IS_VLAN_LINK_ASSERT(link); return vi->vi_flags; } +/** @} */ + +/** + * @name Quality of Service + * @{ + */ + int rtnl_link_vlan_set_ingress_map(struct rtnl_link *link, int from, uint32_t to) { struct vlan_info *vi = link->l_info; - if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops) - return -NLE_OPNOTSUPP; + IS_VLAN_LINK_ASSERT(link); if (from < 0 || from > VLAN_PRIO_MAX) return -NLE_INVAL; @@ -478,6 +525,30 @@ struct vlan_map *rtnl_link_vlan_get_egress_map(struct rtnl_link *link, } } +/** @} */ + +static const struct trans_tbl vlan_flags[] = { + __ADD(VLAN_FLAG_REORDER_HDR, reorder_hdr) +}; + +/** + * @name Flag Translation + * @{ + */ + +char *rtnl_link_vlan_flags2str(int flags, char *buf, size_t len) +{ + return __flags2str(flags, buf, len, vlan_flags, ARRAY_SIZE(vlan_flags)); +} + +int rtnl_link_vlan_str2flags(const char *name) +{ + return __str2flags(name, vlan_flags, ARRAY_SIZE(vlan_flags)); +} + +/** @} */ + + static void __init vlan_init(void) { rtnl_link_register_info(&vlan_info_ops); From bf1b5d28c01a5c21f2432fdb56ad69bbf19cd288 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 21 Jul 2011 17:49:21 +0200 Subject: [PATCH 062/432] removed autogenerated swig interface files from git tree --- python/netlink/capi.py | 773 --- python/netlink/capi_wrap.c | 9640 ------------------------------ python/netlink/route/capi.py | 830 --- python/netlink/route/capi_wrap.c | 9514 ----------------------------- 4 files changed, 20757 deletions(-) delete mode 100644 python/netlink/capi.py delete mode 100644 python/netlink/capi_wrap.c delete mode 100644 python/netlink/route/capi.py delete mode 100644 python/netlink/route/capi_wrap.c diff --git a/python/netlink/capi.py b/python/netlink/capi.py deleted file mode 100644 index 28e4e61..0000000 --- a/python/netlink/capi.py +++ /dev/null @@ -1,773 +0,0 @@ -# This file was automatically generated by SWIG (http://www.swig.org). -# Version 1.3.40 -# -# Do not make changes to this file unless you know what you are doing--modify -# the SWIG interface file instead. - -from sys import version_info -if version_info >= (3,0,0): - new_instancemethod = lambda func, inst, cls: _capi.SWIG_PyInstanceMethod_New(func) -else: - from new import instancemethod as new_instancemethod -if version_info >= (2,6,0): - def swig_import_helper(): - from os.path import dirname - import imp - fp = None - try: - fp, pathname, description = imp.find_module('_capi', [dirname(__file__)]) - except ImportError: - import _capi - return _capi - if fp is not None: - try: - _mod = imp.load_module('_capi', fp, pathname, description) - finally: - fp.close() - return _mod - _capi = swig_import_helper() - del swig_import_helper -else: - import _capi -del version_info -try: - _swig_property = property -except NameError: - pass # Python < 2.2 doesn't have 'property'. -def _swig_setattr_nondynamic(self,class_type,name,value,static=1): - if (name == "thisown"): return self.this.own(value) - if (name == "this"): - if type(value).__name__ == 'SwigPyObject': - self.__dict__[name] = value - return - method = class_type.__swig_setmethods__.get(name,None) - if method: return method(self,value) - if (not static) or hasattr(self,name): - self.__dict__[name] = value - else: - raise AttributeError("You cannot add attributes to %s" % self) - -def _swig_setattr(self,class_type,name,value): - return _swig_setattr_nondynamic(self,class_type,name,value,0) - -def _swig_getattr(self,class_type,name): - if (name == "thisown"): return self.this.own() - method = class_type.__swig_getmethods__.get(name,None) - if method: return method(self) - raise AttributeError(name) - -def _swig_repr(self): - try: strthis = "proxy of " + self.this.__repr__() - except: strthis = "" - return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,) - -try: - _object = object - _newclass = 1 -except AttributeError: - class _object : pass - _newclass = 0 - - -def _swig_setattr_nondynamic_method(set): - def set_attr(self,name,value): - if (name == "thisown"): return self.this.own(value) - if hasattr(self,name) or (name == "this"): - set(self,name,value) - else: - raise AttributeError("You cannot add attributes to %s" % self) - return set_attr - - - -def alloc_dump_params(): - return _capi.alloc_dump_params() -alloc_dump_params = _capi.alloc_dump_params - -def free_dump_params(*args): - return _capi.free_dump_params(*args) -free_dump_params = _capi.free_dump_params -NL_DUMP_LINE = _capi.NL_DUMP_LINE -NL_DUMP_DETAILS = _capi.NL_DUMP_DETAILS -NL_DUMP_STATS = _capi.NL_DUMP_STATS -__NL_DUMP_MAX = _capi.__NL_DUMP_MAX -class nl_dump_params(object): - thisown = _swig_property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag') - def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined") - __repr__ = _swig_repr - dp_type = _swig_property(_capi.nl_dump_params_dp_type_get, _capi.nl_dump_params_dp_type_set) - dp_prefix = _swig_property(_capi.nl_dump_params_dp_prefix_get, _capi.nl_dump_params_dp_prefix_set) - dp_print_index = _swig_property(_capi.nl_dump_params_dp_print_index_get, _capi.nl_dump_params_dp_print_index_set) - dp_dump_msgtype = _swig_property(_capi.nl_dump_params_dp_dump_msgtype_get, _capi.nl_dump_params_dp_dump_msgtype_set) - dp_cb = _swig_property(_capi.nl_dump_params_dp_cb_get, _capi.nl_dump_params_dp_cb_set) - dp_nl_cb = _swig_property(_capi.nl_dump_params_dp_nl_cb_get, _capi.nl_dump_params_dp_nl_cb_set) - dp_data = _swig_property(_capi.nl_dump_params_dp_data_get, _capi.nl_dump_params_dp_data_set) - dp_fd = _swig_property(_capi.nl_dump_params_dp_fd_get, _capi.nl_dump_params_dp_fd_set) - dp_buf = _swig_property(_capi.nl_dump_params_dp_buf_get, _capi.nl_dump_params_dp_buf_set) - dp_buflen = _swig_property(_capi.nl_dump_params_dp_buflen_get, _capi.nl_dump_params_dp_buflen_set) - dp_pre_dump = _swig_property(_capi.nl_dump_params_dp_pre_dump_get, _capi.nl_dump_params_dp_pre_dump_set) - dp_ivar = _swig_property(_capi.nl_dump_params_dp_ivar_get, _capi.nl_dump_params_dp_ivar_set) - dp_line = _swig_property(_capi.nl_dump_params_dp_line_get, _capi.nl_dump_params_dp_line_set) - __swig_destroy__ = _capi.delete_nl_dump_params -nl_dump_params_swigregister = _capi.nl_dump_params_swigregister -nl_dump_params_swigregister(nl_dump_params) - - -def nl_geterror(*args): - return _capi.nl_geterror(*args) -nl_geterror = _capi.nl_geterror - -def nl_cancel_down_bytes(*args): - return _capi.nl_cancel_down_bytes(*args) -nl_cancel_down_bytes = _capi.nl_cancel_down_bytes - -def nl_cancel_down_bits(*args): - return _capi.nl_cancel_down_bits(*args) -nl_cancel_down_bits = _capi.nl_cancel_down_bits - -def nl_rate2str(*args): - return _capi.nl_rate2str(*args) -nl_rate2str = _capi.nl_rate2str - -def nl_cancel_down_us(*args): - return _capi.nl_cancel_down_us(*args) -nl_cancel_down_us = _capi.nl_cancel_down_us - -def nl_size2int(*args): - return _capi.nl_size2int(*args) -nl_size2int = _capi.nl_size2int - -def nl_size2str(*args): - return _capi.nl_size2str(*args) -nl_size2str = _capi.nl_size2str - -def nl_prob2int(*args): - return _capi.nl_prob2int(*args) -nl_prob2int = _capi.nl_prob2int - -def nl_get_user_hz(): - return _capi.nl_get_user_hz() -nl_get_user_hz = _capi.nl_get_user_hz - -def nl_us2ticks(*args): - return _capi.nl_us2ticks(*args) -nl_us2ticks = _capi.nl_us2ticks - -def nl_ticks2us(*args): - return _capi.nl_ticks2us(*args) -nl_ticks2us = _capi.nl_ticks2us - -def nl_str2msec(*args): - return _capi.nl_str2msec(*args) -nl_str2msec = _capi.nl_str2msec - -def nl_msec2str(*args): - return _capi.nl_msec2str(*args) -nl_msec2str = _capi.nl_msec2str - -def nl_llproto2str(*args): - return _capi.nl_llproto2str(*args) -nl_llproto2str = _capi.nl_llproto2str - -def nl_str2llproto(*args): - return _capi.nl_str2llproto(*args) -nl_str2llproto = _capi.nl_str2llproto - -def nl_ether_proto2str(*args): - return _capi.nl_ether_proto2str(*args) -nl_ether_proto2str = _capi.nl_ether_proto2str - -def nl_str2ether_proto(*args): - return _capi.nl_str2ether_proto(*args) -nl_str2ether_proto = _capi.nl_str2ether_proto - -def nl_ip_proto2str(*args): - return _capi.nl_ip_proto2str(*args) -nl_ip_proto2str = _capi.nl_ip_proto2str - -def nl_str2ip_proto(*args): - return _capi.nl_str2ip_proto(*args) -nl_str2ip_proto = _capi.nl_str2ip_proto - -def nl_new_line(*args): - return _capi.nl_new_line(*args) -nl_new_line = _capi.nl_new_line - -def nl_dump(*args): - return _capi.nl_dump(*args) -nl_dump = _capi.nl_dump - -def nl_dump_line(*args): - return _capi.nl_dump_line(*args) -nl_dump_line = _capi.nl_dump_line - -def nl_connect(*args): - return _capi.nl_connect(*args) -nl_connect = _capi.nl_connect - -def nl_close(*args): - return _capi.nl_close(*args) -nl_close = _capi.nl_close - -def nl_pickup(*args): - return _capi.nl_pickup(*args) -nl_pickup = _capi.nl_pickup - -def nl_socket_alloc(): - return _capi.nl_socket_alloc() -nl_socket_alloc = _capi.nl_socket_alloc - -def nl_socket_alloc_cb(*args): - return _capi.nl_socket_alloc_cb(*args) -nl_socket_alloc_cb = _capi.nl_socket_alloc_cb - -def nl_socket_free(*args): - return _capi.nl_socket_free(*args) -nl_socket_free = _capi.nl_socket_free - -def nl_socket_get_local_port(*args): - return _capi.nl_socket_get_local_port(*args) -nl_socket_get_local_port = _capi.nl_socket_get_local_port - -def nl_socket_set_local_port(*args): - return _capi.nl_socket_set_local_port(*args) -nl_socket_set_local_port = _capi.nl_socket_set_local_port - -def nl_socket_get_peer_port(*args): - return _capi.nl_socket_get_peer_port(*args) -nl_socket_get_peer_port = _capi.nl_socket_get_peer_port - -def nl_socket_set_peer_port(*args): - return _capi.nl_socket_set_peer_port(*args) -nl_socket_set_peer_port = _capi.nl_socket_set_peer_port - -def nl_socket_get_peer_groups(*args): - return _capi.nl_socket_get_peer_groups(*args) -nl_socket_get_peer_groups = _capi.nl_socket_get_peer_groups - -def nl_socket_set_peer_groups(*args): - return _capi.nl_socket_set_peer_groups(*args) -nl_socket_set_peer_groups = _capi.nl_socket_set_peer_groups - -def nl_socket_set_buffer_size(*args): - return _capi.nl_socket_set_buffer_size(*args) -nl_socket_set_buffer_size = _capi.nl_socket_set_buffer_size - -def nlmsg_size(*args): - return _capi.nlmsg_size(*args) -nlmsg_size = _capi.nlmsg_size - -def nlmsg_total_size(*args): - return _capi.nlmsg_total_size(*args) -nlmsg_total_size = _capi.nlmsg_total_size - -def nlmsg_padlen(*args): - return _capi.nlmsg_padlen(*args) -nlmsg_padlen = _capi.nlmsg_padlen - -def nlmsg_data(*args): - return _capi.nlmsg_data(*args) -nlmsg_data = _capi.nlmsg_data - -def nlmsg_datalen(*args): - return _capi.nlmsg_datalen(*args) -nlmsg_datalen = _capi.nlmsg_datalen - -def nlmsg_tail(*args): - return _capi.nlmsg_tail(*args) -nlmsg_tail = _capi.nlmsg_tail - -def nlmsg_attrdata(*args): - return _capi.nlmsg_attrdata(*args) -nlmsg_attrdata = _capi.nlmsg_attrdata - -def nlmsg_attrlen(*args): - return _capi.nlmsg_attrlen(*args) -nlmsg_attrlen = _capi.nlmsg_attrlen - -def nlmsg_valid_hdr(*args): - return _capi.nlmsg_valid_hdr(*args) -nlmsg_valid_hdr = _capi.nlmsg_valid_hdr - -def nlmsg_ok(*args): - return _capi.nlmsg_ok(*args) -nlmsg_ok = _capi.nlmsg_ok - -def nlmsg_next(*args): - return _capi.nlmsg_next(*args) -nlmsg_next = _capi.nlmsg_next - -def nlmsg_parse(*args): - return _capi.nlmsg_parse(*args) -nlmsg_parse = _capi.nlmsg_parse - -def nlmsg_find_attr(*args): - return _capi.nlmsg_find_attr(*args) -nlmsg_find_attr = _capi.nlmsg_find_attr - -def nlmsg_validate(*args): - return _capi.nlmsg_validate(*args) -nlmsg_validate = _capi.nlmsg_validate - -def nlmsg_alloc(): - return _capi.nlmsg_alloc() -nlmsg_alloc = _capi.nlmsg_alloc - -def nlmsg_alloc_size(*args): - return _capi.nlmsg_alloc_size(*args) -nlmsg_alloc_size = _capi.nlmsg_alloc_size - -def nlmsg_alloc_simple(*args): - return _capi.nlmsg_alloc_simple(*args) -nlmsg_alloc_simple = _capi.nlmsg_alloc_simple - -def nlmsg_set_default_size(*args): - return _capi.nlmsg_set_default_size(*args) -nlmsg_set_default_size = _capi.nlmsg_set_default_size - -def nlmsg_inherit(*args): - return _capi.nlmsg_inherit(*args) -nlmsg_inherit = _capi.nlmsg_inherit - -def nlmsg_convert(*args): - return _capi.nlmsg_convert(*args) -nlmsg_convert = _capi.nlmsg_convert - -def nlmsg_reserve(*args): - return _capi.nlmsg_reserve(*args) -nlmsg_reserve = _capi.nlmsg_reserve - -def nlmsg_append(*args): - return _capi.nlmsg_append(*args) -nlmsg_append = _capi.nlmsg_append - -def nlmsg_expand(*args): - return _capi.nlmsg_expand(*args) -nlmsg_expand = _capi.nlmsg_expand - -def nlmsg_put(*args): - return _capi.nlmsg_put(*args) -nlmsg_put = _capi.nlmsg_put - -def nlmsg_hdr(*args): - return _capi.nlmsg_hdr(*args) -nlmsg_hdr = _capi.nlmsg_hdr - -def nlmsg_get(*args): - return _capi.nlmsg_get(*args) -nlmsg_get = _capi.nlmsg_get - -def nlmsg_free(*args): - return _capi.nlmsg_free(*args) -nlmsg_free = _capi.nlmsg_free - -def nlmsg_set_proto(*args): - return _capi.nlmsg_set_proto(*args) -nlmsg_set_proto = _capi.nlmsg_set_proto - -def nlmsg_get_proto(*args): - return _capi.nlmsg_get_proto(*args) -nlmsg_get_proto = _capi.nlmsg_get_proto - -def nlmsg_get_max_size(*args): - return _capi.nlmsg_get_max_size(*args) -nlmsg_get_max_size = _capi.nlmsg_get_max_size - -def nlmsg_set_src(*args): - return _capi.nlmsg_set_src(*args) -nlmsg_set_src = _capi.nlmsg_set_src - -def nlmsg_get_src(*args): - return _capi.nlmsg_get_src(*args) -nlmsg_get_src = _capi.nlmsg_get_src - -def nlmsg_set_dst(*args): - return _capi.nlmsg_set_dst(*args) -nlmsg_set_dst = _capi.nlmsg_set_dst - -def nlmsg_get_dst(*args): - return _capi.nlmsg_get_dst(*args) -nlmsg_get_dst = _capi.nlmsg_get_dst - -def nlmsg_set_creds(*args): - return _capi.nlmsg_set_creds(*args) -nlmsg_set_creds = _capi.nlmsg_set_creds - -def nlmsg_get_creds(*args): - return _capi.nlmsg_get_creds(*args) -nlmsg_get_creds = _capi.nlmsg_get_creds - -def nl_nlmsgtype2str(*args): - return _capi.nl_nlmsgtype2str(*args) -nl_nlmsgtype2str = _capi.nl_nlmsgtype2str - -def nl_str2nlmsgtype(*args): - return _capi.nl_str2nlmsgtype(*args) -nl_str2nlmsgtype = _capi.nl_str2nlmsgtype - -def nl_nlmsg_flags2str(*args): - return _capi.nl_nlmsg_flags2str(*args) -nl_nlmsg_flags2str = _capi.nl_nlmsg_flags2str - -def nl_msg_parse(*args): - return _capi.nl_msg_parse(*args) -nl_msg_parse = _capi.nl_msg_parse - -def nl_msg_dump(*args): - return _capi.nl_msg_dump(*args) -nl_msg_dump = _capi.nl_msg_dump - -def cast_obj(*args): - return _capi.cast_obj(*args) -cast_obj = _capi.cast_obj - -def object_alloc_name(*args): - return _capi.object_alloc_name(*args) -object_alloc_name = _capi.object_alloc_name - -def nl_object_alloc(*args): - return _capi.nl_object_alloc(*args) -nl_object_alloc = _capi.nl_object_alloc - -def nl_object_free(*args): - return _capi.nl_object_free(*args) -nl_object_free = _capi.nl_object_free - -def nl_object_clone(*args): - return _capi.nl_object_clone(*args) -nl_object_clone = _capi.nl_object_clone - -def nl_object_get(*args): - return _capi.nl_object_get(*args) -nl_object_get = _capi.nl_object_get - -def nl_object_put(*args): - return _capi.nl_object_put(*args) -nl_object_put = _capi.nl_object_put - -def nl_object_shared(*args): - return _capi.nl_object_shared(*args) -nl_object_shared = _capi.nl_object_shared - -def nl_object_dump_buf(*args): - return _capi.nl_object_dump_buf(*args) -nl_object_dump_buf = _capi.nl_object_dump_buf - -def nl_object_dump(*args): - return _capi.nl_object_dump(*args) -nl_object_dump = _capi.nl_object_dump - -def nl_object_identical(*args): - return _capi.nl_object_identical(*args) -nl_object_identical = _capi.nl_object_identical - -def nl_object_diff(*args): - return _capi.nl_object_diff(*args) -nl_object_diff = _capi.nl_object_diff - -def nl_object_match_filter(*args): - return _capi.nl_object_match_filter(*args) -nl_object_match_filter = _capi.nl_object_match_filter - -def nl_object_attrs2str(*args): - return _capi.nl_object_attrs2str(*args) -nl_object_attrs2str = _capi.nl_object_attrs2str - -def nl_object_attr_list(*args): - return _capi.nl_object_attr_list(*args) -nl_object_attr_list = _capi.nl_object_attr_list - -def nl_object_mark(*args): - return _capi.nl_object_mark(*args) -nl_object_mark = _capi.nl_object_mark - -def nl_object_unmark(*args): - return _capi.nl_object_unmark(*args) -nl_object_unmark = _capi.nl_object_unmark - -def nl_object_is_marked(*args): - return _capi.nl_object_is_marked(*args) -nl_object_is_marked = _capi.nl_object_is_marked - -def nl_object_get_refcnt(*args): - return _capi.nl_object_get_refcnt(*args) -nl_object_get_refcnt = _capi.nl_object_get_refcnt - -def alloc_cache_name(*args): - return _capi.alloc_cache_name(*args) -alloc_cache_name = _capi.alloc_cache_name - -def alloc_cache_mngr(*args): - return _capi.alloc_cache_mngr(*args) -alloc_cache_mngr = _capi.alloc_cache_mngr - -def cache_mngr_add(*args): - return _capi.cache_mngr_add(*args) -cache_mngr_add = _capi.cache_mngr_add - -def nl_cache_nitems(*args): - return _capi.nl_cache_nitems(*args) -nl_cache_nitems = _capi.nl_cache_nitems - -def nl_cache_nitems_filter(*args): - return _capi.nl_cache_nitems_filter(*args) -nl_cache_nitems_filter = _capi.nl_cache_nitems_filter - -def nl_cache_get_ops(*args): - return _capi.nl_cache_get_ops(*args) -nl_cache_get_ops = _capi.nl_cache_get_ops - -def nl_cache_get_first(*args): - return _capi.nl_cache_get_first(*args) -nl_cache_get_first = _capi.nl_cache_get_first - -def nl_cache_get_last(*args): - return _capi.nl_cache_get_last(*args) -nl_cache_get_last = _capi.nl_cache_get_last - -def nl_cache_get_next(*args): - return _capi.nl_cache_get_next(*args) -nl_cache_get_next = _capi.nl_cache_get_next - -def nl_cache_get_prev(*args): - return _capi.nl_cache_get_prev(*args) -nl_cache_get_prev = _capi.nl_cache_get_prev - -def nl_cache_alloc(*args): - return _capi.nl_cache_alloc(*args) -nl_cache_alloc = _capi.nl_cache_alloc - -def nl_cache_subset(*args): - return _capi.nl_cache_subset(*args) -nl_cache_subset = _capi.nl_cache_subset - -def nl_cache_clear(*args): - return _capi.nl_cache_clear(*args) -nl_cache_clear = _capi.nl_cache_clear - -def nl_cache_free(*args): - return _capi.nl_cache_free(*args) -nl_cache_free = _capi.nl_cache_free - -def nl_cache_add(*args): - return _capi.nl_cache_add(*args) -nl_cache_add = _capi.nl_cache_add - -def nl_cache_parse_and_add(*args): - return _capi.nl_cache_parse_and_add(*args) -nl_cache_parse_and_add = _capi.nl_cache_parse_and_add - -def nl_cache_remove(*args): - return _capi.nl_cache_remove(*args) -nl_cache_remove = _capi.nl_cache_remove - -def nl_cache_refill(*args): - return _capi.nl_cache_refill(*args) -nl_cache_refill = _capi.nl_cache_refill - -def nl_cache_pickup(*args): - return _capi.nl_cache_pickup(*args) -nl_cache_pickup = _capi.nl_cache_pickup - -def nl_cache_resync(*args): - return _capi.nl_cache_resync(*args) -nl_cache_resync = _capi.nl_cache_resync - -def nl_cache_include(*args): - return _capi.nl_cache_include(*args) -nl_cache_include = _capi.nl_cache_include - -def nl_cache_set_arg1(*args): - return _capi.nl_cache_set_arg1(*args) -nl_cache_set_arg1 = _capi.nl_cache_set_arg1 - -def nl_cache_set_arg2(*args): - return _capi.nl_cache_set_arg2(*args) -nl_cache_set_arg2 = _capi.nl_cache_set_arg2 - -def nl_cache_is_empty(*args): - return _capi.nl_cache_is_empty(*args) -nl_cache_is_empty = _capi.nl_cache_is_empty - -def nl_cache_search(*args): - return _capi.nl_cache_search(*args) -nl_cache_search = _capi.nl_cache_search - -def nl_cache_mark_all(*args): - return _capi.nl_cache_mark_all(*args) -nl_cache_mark_all = _capi.nl_cache_mark_all - -def nl_cache_dump(*args): - return _capi.nl_cache_dump(*args) -nl_cache_dump = _capi.nl_cache_dump - -def nl_cache_dump_filter(*args): - return _capi.nl_cache_dump_filter(*args) -nl_cache_dump_filter = _capi.nl_cache_dump_filter - -def nl_cache_foreach(*args): - return _capi.nl_cache_foreach(*args) -nl_cache_foreach = _capi.nl_cache_foreach - -def nl_cache_foreach_filter(*args): - return _capi.nl_cache_foreach_filter(*args) -nl_cache_foreach_filter = _capi.nl_cache_foreach_filter - -def nl_cache_ops_lookup(*args): - return _capi.nl_cache_ops_lookup(*args) -nl_cache_ops_lookup = _capi.nl_cache_ops_lookup - -def nl_cache_ops_associate(*args): - return _capi.nl_cache_ops_associate(*args) -nl_cache_ops_associate = _capi.nl_cache_ops_associate - -def nl_msgtype_lookup(*args): - return _capi.nl_msgtype_lookup(*args) -nl_msgtype_lookup = _capi.nl_msgtype_lookup - -def nl_cache_ops_foreach(*args): - return _capi.nl_cache_ops_foreach(*args) -nl_cache_ops_foreach = _capi.nl_cache_ops_foreach - -def nl_cache_mngt_register(*args): - return _capi.nl_cache_mngt_register(*args) -nl_cache_mngt_register = _capi.nl_cache_mngt_register - -def nl_cache_mngt_unregister(*args): - return _capi.nl_cache_mngt_unregister(*args) -nl_cache_mngt_unregister = _capi.nl_cache_mngt_unregister - -def nl_cache_mngt_provide(*args): - return _capi.nl_cache_mngt_provide(*args) -nl_cache_mngt_provide = _capi.nl_cache_mngt_provide - -def nl_cache_mngt_unprovide(*args): - return _capi.nl_cache_mngt_unprovide(*args) -nl_cache_mngt_unprovide = _capi.nl_cache_mngt_unprovide - -def nl_cache_mngt_require(*args): - return _capi.nl_cache_mngt_require(*args) -nl_cache_mngt_require = _capi.nl_cache_mngt_require -NL_AUTO_PROVIDE = _capi.NL_AUTO_PROVIDE - -def nl_cache_mngr_get_fd(*args): - return _capi.nl_cache_mngr_get_fd(*args) -nl_cache_mngr_get_fd = _capi.nl_cache_mngr_get_fd - -def nl_cache_mngr_poll(*args): - return _capi.nl_cache_mngr_poll(*args) -nl_cache_mngr_poll = _capi.nl_cache_mngr_poll - -def nl_cache_mngr_data_ready(*args): - return _capi.nl_cache_mngr_data_ready(*args) -nl_cache_mngr_data_ready = _capi.nl_cache_mngr_data_ready - -def nl_cache_mngr_free(*args): - return _capi.nl_cache_mngr_free(*args) -nl_cache_mngr_free = _capi.nl_cache_mngr_free - -def addr_parse(*args): - return _capi.addr_parse(*args) -addr_parse = _capi.addr_parse - -def nl_addr_alloc(*args): - return _capi.nl_addr_alloc(*args) -nl_addr_alloc = _capi.nl_addr_alloc - -def nl_addr_alloc_attr(*args): - return _capi.nl_addr_alloc_attr(*args) -nl_addr_alloc_attr = _capi.nl_addr_alloc_attr - -def nl_addr_build(*args): - return _capi.nl_addr_build(*args) -nl_addr_build = _capi.nl_addr_build - -def nl_addr_clone(*args): - return _capi.nl_addr_clone(*args) -nl_addr_clone = _capi.nl_addr_clone - -def nl_addr_get(*args): - return _capi.nl_addr_get(*args) -nl_addr_get = _capi.nl_addr_get - -def nl_addr_put(*args): - return _capi.nl_addr_put(*args) -nl_addr_put = _capi.nl_addr_put - -def nl_addr_shared(*args): - return _capi.nl_addr_shared(*args) -nl_addr_shared = _capi.nl_addr_shared - -def nl_addr_cmp(*args): - return _capi.nl_addr_cmp(*args) -nl_addr_cmp = _capi.nl_addr_cmp - -def nl_addr_cmp_prefix(*args): - return _capi.nl_addr_cmp_prefix(*args) -nl_addr_cmp_prefix = _capi.nl_addr_cmp_prefix - -def nl_addr_iszero(*args): - return _capi.nl_addr_iszero(*args) -nl_addr_iszero = _capi.nl_addr_iszero - -def nl_addr_valid(*args): - return _capi.nl_addr_valid(*args) -nl_addr_valid = _capi.nl_addr_valid - -def nl_addr_guess_family(*args): - return _capi.nl_addr_guess_family(*args) -nl_addr_guess_family = _capi.nl_addr_guess_family - -def nl_addr_fill_sockaddr(*args): - return _capi.nl_addr_fill_sockaddr(*args) -nl_addr_fill_sockaddr = _capi.nl_addr_fill_sockaddr - -def nl_addr_info(*args): - return _capi.nl_addr_info(*args) -nl_addr_info = _capi.nl_addr_info - -def nl_addr_resolve(*args): - return _capi.nl_addr_resolve(*args) -nl_addr_resolve = _capi.nl_addr_resolve - -def nl_addr_set_family(*args): - return _capi.nl_addr_set_family(*args) -nl_addr_set_family = _capi.nl_addr_set_family - -def nl_addr_get_family(*args): - return _capi.nl_addr_get_family(*args) -nl_addr_get_family = _capi.nl_addr_get_family - -def nl_addr_set_binary_addr(*args): - return _capi.nl_addr_set_binary_addr(*args) -nl_addr_set_binary_addr = _capi.nl_addr_set_binary_addr - -def nl_addr_get_binary_addr(*args): - return _capi.nl_addr_get_binary_addr(*args) -nl_addr_get_binary_addr = _capi.nl_addr_get_binary_addr - -def nl_addr_get_len(*args): - return _capi.nl_addr_get_len(*args) -nl_addr_get_len = _capi.nl_addr_get_len - -def nl_addr_set_prefixlen(*args): - return _capi.nl_addr_set_prefixlen(*args) -nl_addr_set_prefixlen = _capi.nl_addr_set_prefixlen - -def nl_addr_get_prefixlen(*args): - return _capi.nl_addr_get_prefixlen(*args) -nl_addr_get_prefixlen = _capi.nl_addr_get_prefixlen - -def nl_af2str(*args): - return _capi.nl_af2str(*args) -nl_af2str = _capi.nl_af2str - -def nl_str2af(*args): - return _capi.nl_str2af(*args) -nl_str2af = _capi.nl_str2af - -def nl_addr2str(*args): - return _capi.nl_addr2str(*args) -nl_addr2str = _capi.nl_addr2str - - diff --git a/python/netlink/capi_wrap.c b/python/netlink/capi_wrap.c deleted file mode 100644 index 5027a75..0000000 --- a/python/netlink/capi_wrap.c +++ /dev/null @@ -1,9640 +0,0 @@ -/* ---------------------------------------------------------------------------- - * This file was automatically generated by SWIG (http://www.swig.org). - * Version 1.3.40 - * - * This file is not intended to be easily readable and contains a number of - * coding conventions designed to improve portability and efficiency. Do not make - * changes to this file unless you know what you are doing--modify the SWIG - * interface file instead. - * ----------------------------------------------------------------------------- */ - -#define SWIGPYTHON -#define SWIG_PYTHON_NO_BUILD_NONE - -/* ----------------------------------------------------------------------------- - * This section contains generic SWIG labels for method/variable - * declarations/attributes, and other compiler dependent labels. - * ----------------------------------------------------------------------------- */ - -/* template workaround for compilers that cannot correctly implement the C++ standard */ -#ifndef SWIGTEMPLATEDISAMBIGUATOR -# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560) -# define SWIGTEMPLATEDISAMBIGUATOR template -# elif defined(__HP_aCC) -/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */ -/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */ -# define SWIGTEMPLATEDISAMBIGUATOR template -# else -# define SWIGTEMPLATEDISAMBIGUATOR -# endif -#endif - -/* inline attribute */ -#ifndef SWIGINLINE -# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__)) -# define SWIGINLINE inline -# else -# define SWIGINLINE -# endif -#endif - -/* attribute recognised by some compilers to avoid 'unused' warnings */ -#ifndef SWIGUNUSED -# if defined(__GNUC__) -# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) -# define SWIGUNUSED __attribute__ ((__unused__)) -# else -# define SWIGUNUSED -# endif -# elif defined(__ICC) -# define SWIGUNUSED __attribute__ ((__unused__)) -# else -# define SWIGUNUSED -# endif -#endif - -#ifndef SWIG_MSC_UNSUPPRESS_4505 -# if defined(_MSC_VER) -# pragma warning(disable : 4505) /* unreferenced local function has been removed */ -# endif -#endif - -#ifndef SWIGUNUSEDPARM -# ifdef __cplusplus -# define SWIGUNUSEDPARM(p) -# else -# define SWIGUNUSEDPARM(p) p SWIGUNUSED -# endif -#endif - -/* internal SWIG method */ -#ifndef SWIGINTERN -# define SWIGINTERN static SWIGUNUSED -#endif - -/* internal inline SWIG method */ -#ifndef SWIGINTERNINLINE -# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE -#endif - -/* exporting methods */ -#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) -# ifndef GCC_HASCLASSVISIBILITY -# define GCC_HASCLASSVISIBILITY -# endif -#endif - -#ifndef SWIGEXPORT -# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# if defined(STATIC_LINKED) -# define SWIGEXPORT -# else -# define SWIGEXPORT __declspec(dllexport) -# endif -# else -# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY) -# define SWIGEXPORT __attribute__ ((visibility("default"))) -# else -# define SWIGEXPORT -# endif -# endif -#endif - -/* calling conventions for Windows */ -#ifndef SWIGSTDCALL -# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# define SWIGSTDCALL __stdcall -# else -# define SWIGSTDCALL -# endif -#endif - -/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ -#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) -# define _CRT_SECURE_NO_DEPRECATE -#endif - -/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */ -#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE) -# define _SCL_SECURE_NO_DEPRECATE -#endif - - - -/* Python.h has to appear first */ -#include - -/* ----------------------------------------------------------------------------- - * swigrun.swg - * - * This file contains generic C API SWIG runtime support for pointer - * type checking. - * ----------------------------------------------------------------------------- */ - -/* This should only be incremented when either the layout of swig_type_info changes, - or for whatever reason, the runtime changes incompatibly */ -#define SWIG_RUNTIME_VERSION "4" - -/* define SWIG_TYPE_TABLE_NAME as "SWIG_TYPE_TABLE" */ -#ifdef SWIG_TYPE_TABLE -# define SWIG_QUOTE_STRING(x) #x -# define SWIG_EXPAND_AND_QUOTE_STRING(x) SWIG_QUOTE_STRING(x) -# define SWIG_TYPE_TABLE_NAME SWIG_EXPAND_AND_QUOTE_STRING(SWIG_TYPE_TABLE) -#else -# define SWIG_TYPE_TABLE_NAME -#endif - -/* - You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for - creating a static or dynamic library from the SWIG runtime code. - In 99.9% of the cases, SWIG just needs to declare them as 'static'. - - But only do this if strictly necessary, ie, if you have problems - with your compiler or suchlike. -*/ - -#ifndef SWIGRUNTIME -# define SWIGRUNTIME SWIGINTERN -#endif - -#ifndef SWIGRUNTIMEINLINE -# define SWIGRUNTIMEINLINE SWIGRUNTIME SWIGINLINE -#endif - -/* Generic buffer size */ -#ifndef SWIG_BUFFER_SIZE -# define SWIG_BUFFER_SIZE 1024 -#endif - -/* Flags for pointer conversions */ -#define SWIG_POINTER_DISOWN 0x1 -#define SWIG_CAST_NEW_MEMORY 0x2 - -/* Flags for new pointer objects */ -#define SWIG_POINTER_OWN 0x1 - - -/* - Flags/methods for returning states. - - The SWIG conversion methods, as ConvertPtr, return and integer - that tells if the conversion was successful or not. And if not, - an error code can be returned (see swigerrors.swg for the codes). - - Use the following macros/flags to set or process the returning - states. - - In old versions of SWIG, code such as the following was usually written: - - if (SWIG_ConvertPtr(obj,vptr,ty.flags) != -1) { - // success code - } else { - //fail code - } - - Now you can be more explicit: - - int res = SWIG_ConvertPtr(obj,vptr,ty.flags); - if (SWIG_IsOK(res)) { - // success code - } else { - // fail code - } - - which is the same really, but now you can also do - - Type *ptr; - int res = SWIG_ConvertPtr(obj,(void **)(&ptr),ty.flags); - if (SWIG_IsOK(res)) { - // success code - if (SWIG_IsNewObj(res) { - ... - delete *ptr; - } else { - ... - } - } else { - // fail code - } - - I.e., now SWIG_ConvertPtr can return new objects and you can - identify the case and take care of the deallocation. Of course that - also requires SWIG_ConvertPtr to return new result values, such as - - int SWIG_ConvertPtr(obj, ptr,...) { - if () { - if () { - *ptr = ; - return SWIG_NEWOBJ; - } else { - *ptr = ; - return SWIG_OLDOBJ; - } - } else { - return SWIG_BADOBJ; - } - } - - Of course, returning the plain '0(success)/-1(fail)' still works, but you can be - more explicit by returning SWIG_BADOBJ, SWIG_ERROR or any of the - SWIG errors code. - - Finally, if the SWIG_CASTRANK_MODE is enabled, the result code - allows to return the 'cast rank', for example, if you have this - - int food(double) - int fooi(int); - - and you call - - food(1) // cast rank '1' (1 -> 1.0) - fooi(1) // cast rank '0' - - just use the SWIG_AddCast()/SWIG_CheckState() -*/ - -#define SWIG_OK (0) -#define SWIG_ERROR (-1) -#define SWIG_IsOK(r) (r >= 0) -#define SWIG_ArgError(r) ((r != SWIG_ERROR) ? r : SWIG_TypeError) - -/* The CastRankLimit says how many bits are used for the cast rank */ -#define SWIG_CASTRANKLIMIT (1 << 8) -/* The NewMask denotes the object was created (using new/malloc) */ -#define SWIG_NEWOBJMASK (SWIG_CASTRANKLIMIT << 1) -/* The TmpMask is for in/out typemaps that use temporal objects */ -#define SWIG_TMPOBJMASK (SWIG_NEWOBJMASK << 1) -/* Simple returning values */ -#define SWIG_BADOBJ (SWIG_ERROR) -#define SWIG_OLDOBJ (SWIG_OK) -#define SWIG_NEWOBJ (SWIG_OK | SWIG_NEWOBJMASK) -#define SWIG_TMPOBJ (SWIG_OK | SWIG_TMPOBJMASK) -/* Check, add and del mask methods */ -#define SWIG_AddNewMask(r) (SWIG_IsOK(r) ? (r | SWIG_NEWOBJMASK) : r) -#define SWIG_DelNewMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_NEWOBJMASK) : r) -#define SWIG_IsNewObj(r) (SWIG_IsOK(r) && (r & SWIG_NEWOBJMASK)) -#define SWIG_AddTmpMask(r) (SWIG_IsOK(r) ? (r | SWIG_TMPOBJMASK) : r) -#define SWIG_DelTmpMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_TMPOBJMASK) : r) -#define SWIG_IsTmpObj(r) (SWIG_IsOK(r) && (r & SWIG_TMPOBJMASK)) - -/* Cast-Rank Mode */ -#if defined(SWIG_CASTRANK_MODE) -# ifndef SWIG_TypeRank -# define SWIG_TypeRank unsigned long -# endif -# ifndef SWIG_MAXCASTRANK /* Default cast allowed */ -# define SWIG_MAXCASTRANK (2) -# endif -# define SWIG_CASTRANKMASK ((SWIG_CASTRANKLIMIT) -1) -# define SWIG_CastRank(r) (r & SWIG_CASTRANKMASK) -SWIGINTERNINLINE int SWIG_AddCast(int r) { - return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r; -} -SWIGINTERNINLINE int SWIG_CheckState(int r) { - return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0; -} -#else /* no cast-rank mode */ -# define SWIG_AddCast -# define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0) -#endif - - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void *(*swig_converter_func)(void *, int *); -typedef struct swig_type_info *(*swig_dycast_func)(void **); - -/* Structure to store information on one type */ -typedef struct swig_type_info { - const char *name; /* mangled name of this type */ - const char *str; /* human readable name of this type */ - swig_dycast_func dcast; /* dynamic cast function down a hierarchy */ - struct swig_cast_info *cast; /* linked list of types that can cast into this type */ - void *clientdata; /* language specific type data */ - int owndata; /* flag if the structure owns the clientdata */ -} swig_type_info; - -/* Structure to store a type and conversion function used for casting */ -typedef struct swig_cast_info { - swig_type_info *type; /* pointer to type that is equivalent to this type */ - swig_converter_func converter; /* function to cast the void pointers */ - struct swig_cast_info *next; /* pointer to next cast in linked list */ - struct swig_cast_info *prev; /* pointer to the previous cast */ -} swig_cast_info; - -/* Structure used to store module information - * Each module generates one structure like this, and the runtime collects - * all of these structures and stores them in a circularly linked list.*/ -typedef struct swig_module_info { - swig_type_info **types; /* Array of pointers to swig_type_info structures that are in this module */ - size_t size; /* Number of types in this module */ - struct swig_module_info *next; /* Pointer to next element in circularly linked list */ - swig_type_info **type_initial; /* Array of initially generated type structures */ - swig_cast_info **cast_initial; /* Array of initially generated casting structures */ - void *clientdata; /* Language specific module data */ -} swig_module_info; - -/* - Compare two type names skipping the space characters, therefore - "char*" == "char *" and "Class" == "Class", etc. - - Return 0 when the two name types are equivalent, as in - strncmp, but skipping ' '. -*/ -SWIGRUNTIME int -SWIG_TypeNameComp(const char *f1, const char *l1, - const char *f2, const char *l2) { - for (;(f1 != l1) && (f2 != l2); ++f1, ++f2) { - while ((*f1 == ' ') && (f1 != l1)) ++f1; - while ((*f2 == ' ') && (f2 != l2)) ++f2; - if (*f1 != *f2) return (*f1 > *f2) ? 1 : -1; - } - return (int)((l1 - f1) - (l2 - f2)); -} - -/* - Check type equivalence in a name list like ||... - Return 0 if not equal, 1 if equal -*/ -SWIGRUNTIME int -SWIG_TypeEquiv(const char *nb, const char *tb) { - int equiv = 0; - const char* te = tb + strlen(tb); - const char* ne = nb; - while (!equiv && *ne) { - for (nb = ne; *ne; ++ne) { - if (*ne == '|') break; - } - equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0; - if (*ne) ++ne; - } - return equiv; -} - -/* - Check type equivalence in a name list like ||... - Return 0 if equal, -1 if nb < tb, 1 if nb > tb -*/ -SWIGRUNTIME int -SWIG_TypeCompare(const char *nb, const char *tb) { - int equiv = 0; - const char* te = tb + strlen(tb); - const char* ne = nb; - while (!equiv && *ne) { - for (nb = ne; *ne; ++ne) { - if (*ne == '|') break; - } - equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0; - if (*ne) ++ne; - } - return equiv; -} - - -/* - Check the typename -*/ -SWIGRUNTIME swig_cast_info * -SWIG_TypeCheck(const char *c, swig_type_info *ty) { - if (ty) { - swig_cast_info *iter = ty->cast; - while (iter) { - if (strcmp(iter->type->name, c) == 0) { - if (iter == ty->cast) - return iter; - /* Move iter to the top of the linked list */ - iter->prev->next = iter->next; - if (iter->next) - iter->next->prev = iter->prev; - iter->next = ty->cast; - iter->prev = 0; - if (ty->cast) ty->cast->prev = iter; - ty->cast = iter; - return iter; - } - iter = iter->next; - } - } - return 0; -} - -/* - Identical to SWIG_TypeCheck, except strcmp is replaced with a pointer comparison -*/ -SWIGRUNTIME swig_cast_info * -SWIG_TypeCheckStruct(swig_type_info *from, swig_type_info *ty) { - if (ty) { - swig_cast_info *iter = ty->cast; - while (iter) { - if (iter->type == from) { - if (iter == ty->cast) - return iter; - /* Move iter to the top of the linked list */ - iter->prev->next = iter->next; - if (iter->next) - iter->next->prev = iter->prev; - iter->next = ty->cast; - iter->prev = 0; - if (ty->cast) ty->cast->prev = iter; - ty->cast = iter; - return iter; - } - iter = iter->next; - } - } - return 0; -} - -/* - Cast a pointer up an inheritance hierarchy -*/ -SWIGRUNTIMEINLINE void * -SWIG_TypeCast(swig_cast_info *ty, void *ptr, int *newmemory) { - return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr, newmemory); -} - -/* - Dynamic pointer casting. Down an inheritance hierarchy -*/ -SWIGRUNTIME swig_type_info * -SWIG_TypeDynamicCast(swig_type_info *ty, void **ptr) { - swig_type_info *lastty = ty; - if (!ty || !ty->dcast) return ty; - while (ty && (ty->dcast)) { - ty = (*ty->dcast)(ptr); - if (ty) lastty = ty; - } - return lastty; -} - -/* - Return the name associated with this type -*/ -SWIGRUNTIMEINLINE const char * -SWIG_TypeName(const swig_type_info *ty) { - return ty->name; -} - -/* - Return the pretty name associated with this type, - that is an unmangled type name in a form presentable to the user. -*/ -SWIGRUNTIME const char * -SWIG_TypePrettyName(const swig_type_info *type) { - /* The "str" field contains the equivalent pretty names of the - type, separated by vertical-bar characters. We choose - to print the last name, as it is often (?) the most - specific. */ - if (!type) return NULL; - if (type->str != NULL) { - const char *last_name = type->str; - const char *s; - for (s = type->str; *s; s++) - if (*s == '|') last_name = s+1; - return last_name; - } - else - return type->name; -} - -/* - Set the clientdata field for a type -*/ -SWIGRUNTIME void -SWIG_TypeClientData(swig_type_info *ti, void *clientdata) { - swig_cast_info *cast = ti->cast; - /* if (ti->clientdata == clientdata) return; */ - ti->clientdata = clientdata; - - while (cast) { - if (!cast->converter) { - swig_type_info *tc = cast->type; - if (!tc->clientdata) { - SWIG_TypeClientData(tc, clientdata); - } - } - cast = cast->next; - } -} -SWIGRUNTIME void -SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) { - SWIG_TypeClientData(ti, clientdata); - ti->owndata = 1; -} - -/* - Search for a swig_type_info structure only by mangled name - Search is a O(log #types) - - We start searching at module start, and finish searching when start == end. - Note: if start == end at the beginning of the function, we go all the way around - the circular list. -*/ -SWIGRUNTIME swig_type_info * -SWIG_MangledTypeQueryModule(swig_module_info *start, - swig_module_info *end, - const char *name) { - swig_module_info *iter = start; - do { - if (iter->size) { - register size_t l = 0; - register size_t r = iter->size - 1; - do { - /* since l+r >= 0, we can (>> 1) instead (/ 2) */ - register size_t i = (l + r) >> 1; - const char *iname = iter->types[i]->name; - if (iname) { - register int compare = strcmp(name, iname); - if (compare == 0) { - return iter->types[i]; - } else if (compare < 0) { - if (i) { - r = i - 1; - } else { - break; - } - } else if (compare > 0) { - l = i + 1; - } - } else { - break; /* should never happen */ - } - } while (l <= r); - } - iter = iter->next; - } while (iter != end); - return 0; -} - -/* - Search for a swig_type_info structure for either a mangled name or a human readable name. - It first searches the mangled names of the types, which is a O(log #types) - If a type is not found it then searches the human readable names, which is O(#types). - - We start searching at module start, and finish searching when start == end. - Note: if start == end at the beginning of the function, we go all the way around - the circular list. -*/ -SWIGRUNTIME swig_type_info * -SWIG_TypeQueryModule(swig_module_info *start, - swig_module_info *end, - const char *name) { - /* STEP 1: Search the name field using binary search */ - swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name); - if (ret) { - return ret; - } else { - /* STEP 2: If the type hasn't been found, do a complete search - of the str field (the human readable name) */ - swig_module_info *iter = start; - do { - register size_t i = 0; - for (; i < iter->size; ++i) { - if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name))) - return iter->types[i]; - } - iter = iter->next; - } while (iter != end); - } - - /* neither found a match */ - return 0; -} - -/* - Pack binary data into a string -*/ -SWIGRUNTIME char * -SWIG_PackData(char *c, void *ptr, size_t sz) { - static const char hex[17] = "0123456789abcdef"; - register const unsigned char *u = (unsigned char *) ptr; - register const unsigned char *eu = u + sz; - for (; u != eu; ++u) { - register unsigned char uu = *u; - *(c++) = hex[(uu & 0xf0) >> 4]; - *(c++) = hex[uu & 0xf]; - } - return c; -} - -/* - Unpack binary data from a string -*/ -SWIGRUNTIME const char * -SWIG_UnpackData(const char *c, void *ptr, size_t sz) { - register unsigned char *u = (unsigned char *) ptr; - register const unsigned char *eu = u + sz; - for (; u != eu; ++u) { - register char d = *(c++); - register unsigned char uu; - if ((d >= '0') && (d <= '9')) - uu = ((d - '0') << 4); - else if ((d >= 'a') && (d <= 'f')) - uu = ((d - ('a'-10)) << 4); - else - return (char *) 0; - d = *(c++); - if ((d >= '0') && (d <= '9')) - uu |= (d - '0'); - else if ((d >= 'a') && (d <= 'f')) - uu |= (d - ('a'-10)); - else - return (char *) 0; - *u = uu; - } - return c; -} - -/* - Pack 'void *' into a string buffer. -*/ -SWIGRUNTIME char * -SWIG_PackVoidPtr(char *buff, void *ptr, const char *name, size_t bsz) { - char *r = buff; - if ((2*sizeof(void *) + 2) > bsz) return 0; - *(r++) = '_'; - r = SWIG_PackData(r,&ptr,sizeof(void *)); - if (strlen(name) + 1 > (bsz - (r - buff))) return 0; - strcpy(r,name); - return buff; -} - -SWIGRUNTIME const char * -SWIG_UnpackVoidPtr(const char *c, void **ptr, const char *name) { - if (*c != '_') { - if (strcmp(c,"NULL") == 0) { - *ptr = (void *) 0; - return name; - } else { - return 0; - } - } - return SWIG_UnpackData(++c,ptr,sizeof(void *)); -} - -SWIGRUNTIME char * -SWIG_PackDataName(char *buff, void *ptr, size_t sz, const char *name, size_t bsz) { - char *r = buff; - size_t lname = (name ? strlen(name) : 0); - if ((2*sz + 2 + lname) > bsz) return 0; - *(r++) = '_'; - r = SWIG_PackData(r,ptr,sz); - if (lname) { - strncpy(r,name,lname+1); - } else { - *r = 0; - } - return buff; -} - -SWIGRUNTIME const char * -SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) { - if (*c != '_') { - if (strcmp(c,"NULL") == 0) { - memset(ptr,0,sz); - return name; - } else { - return 0; - } - } - return SWIG_UnpackData(++c,ptr,sz); -} - -#ifdef __cplusplus -} -#endif - -/* Errors in SWIG */ -#define SWIG_UnknownError -1 -#define SWIG_IOError -2 -#define SWIG_RuntimeError -3 -#define SWIG_IndexError -4 -#define SWIG_TypeError -5 -#define SWIG_DivisionByZero -6 -#define SWIG_OverflowError -7 -#define SWIG_SyntaxError -8 -#define SWIG_ValueError -9 -#define SWIG_SystemError -10 -#define SWIG_AttributeError -11 -#define SWIG_MemoryError -12 -#define SWIG_NullReferenceError -13 - - - -/* Compatibility macros for Python 3 */ -#if PY_VERSION_HEX >= 0x03000000 - -#define PyClass_Check(obj) PyObject_IsInstance(obj, (PyObject *)&PyType_Type) -#define PyInt_Check(x) PyLong_Check(x) -#define PyInt_AsLong(x) PyLong_AsLong(x) -#define PyInt_FromLong(x) PyLong_FromLong(x) -#define PyString_Format(fmt, args) PyUnicode_Format(fmt, args) - -#endif - -#ifndef Py_TYPE -# define Py_TYPE(op) ((op)->ob_type) -#endif - -/* SWIG APIs for compatibility of both Python 2 & 3 */ - -#if PY_VERSION_HEX >= 0x03000000 -# define SWIG_Python_str_FromFormat PyUnicode_FromFormat -#else -# define SWIG_Python_str_FromFormat PyString_FromFormat -#endif - - -/* Warning: This function will allocate a new string in Python 3, - * so please call SWIG_Python_str_DelForPy3(x) to free the space. - */ -SWIGINTERN char* -SWIG_Python_str_AsChar(PyObject *str) -{ -#if PY_VERSION_HEX >= 0x03000000 - char *cstr; - char *newstr; - Py_ssize_t len; - str = PyUnicode_AsUTF8String(str); - PyBytes_AsStringAndSize(str, &cstr, &len); - newstr = (char *) malloc(len+1); - memcpy(newstr, cstr, len+1); - Py_XDECREF(str); - return newstr; -#else - return PyString_AsString(str); -#endif -} - -#if PY_VERSION_HEX >= 0x03000000 -# define SWIG_Python_str_DelForPy3(x) free( (void*) (x) ) -#else -# define SWIG_Python_str_DelForPy3(x) -#endif - - -SWIGINTERN PyObject* -SWIG_Python_str_FromChar(const char *c) -{ -#if PY_VERSION_HEX >= 0x03000000 - return PyUnicode_FromString(c); -#else - return PyString_FromString(c); -#endif -} - -/* Add PyOS_snprintf for old Pythons */ -#if PY_VERSION_HEX < 0x02020000 -# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WATCOM) -# define PyOS_snprintf _snprintf -# else -# define PyOS_snprintf snprintf -# endif -#endif - -/* A crude PyString_FromFormat implementation for old Pythons */ -#if PY_VERSION_HEX < 0x02020000 - -#ifndef SWIG_PYBUFFER_SIZE -# define SWIG_PYBUFFER_SIZE 1024 -#endif - -static PyObject * -PyString_FromFormat(const char *fmt, ...) { - va_list ap; - char buf[SWIG_PYBUFFER_SIZE * 2]; - int res; - va_start(ap, fmt); - res = vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - return (res < 0 || res >= (int)sizeof(buf)) ? 0 : PyString_FromString(buf); -} -#endif - -/* Add PyObject_Del for old Pythons */ -#if PY_VERSION_HEX < 0x01060000 -# define PyObject_Del(op) PyMem_DEL((op)) -#endif -#ifndef PyObject_DEL -# define PyObject_DEL PyObject_Del -#endif - -/* A crude PyExc_StopIteration exception for old Pythons */ -#if PY_VERSION_HEX < 0x02020000 -# ifndef PyExc_StopIteration -# define PyExc_StopIteration PyExc_RuntimeError -# endif -# ifndef PyObject_GenericGetAttr -# define PyObject_GenericGetAttr 0 -# endif -#endif - -/* Py_NotImplemented is defined in 2.1 and up. */ -#if PY_VERSION_HEX < 0x02010000 -# ifndef Py_NotImplemented -# define Py_NotImplemented PyExc_RuntimeError -# endif -#endif - -/* A crude PyString_AsStringAndSize implementation for old Pythons */ -#if PY_VERSION_HEX < 0x02010000 -# ifndef PyString_AsStringAndSize -# define PyString_AsStringAndSize(obj, s, len) {*s = PyString_AsString(obj); *len = *s ? strlen(*s) : 0;} -# endif -#endif - -/* PySequence_Size for old Pythons */ -#if PY_VERSION_HEX < 0x02000000 -# ifndef PySequence_Size -# define PySequence_Size PySequence_Length -# endif -#endif - -/* PyBool_FromLong for old Pythons */ -#if PY_VERSION_HEX < 0x02030000 -static -PyObject *PyBool_FromLong(long ok) -{ - PyObject *result = ok ? Py_True : Py_False; - Py_INCREF(result); - return result; -} -#endif - -/* Py_ssize_t for old Pythons */ -/* This code is as recommended by: */ -/* http://www.python.org/dev/peps/pep-0353/#conversion-guidelines */ -#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) -typedef int Py_ssize_t; -# define PY_SSIZE_T_MAX INT_MAX -# define PY_SSIZE_T_MIN INT_MIN -#endif - -/* ----------------------------------------------------------------------------- - * error manipulation - * ----------------------------------------------------------------------------- */ - -SWIGRUNTIME PyObject* -SWIG_Python_ErrorType(int code) { - PyObject* type = 0; - switch(code) { - case SWIG_MemoryError: - type = PyExc_MemoryError; - break; - case SWIG_IOError: - type = PyExc_IOError; - break; - case SWIG_RuntimeError: - type = PyExc_RuntimeError; - break; - case SWIG_IndexError: - type = PyExc_IndexError; - break; - case SWIG_TypeError: - type = PyExc_TypeError; - break; - case SWIG_DivisionByZero: - type = PyExc_ZeroDivisionError; - break; - case SWIG_OverflowError: - type = PyExc_OverflowError; - break; - case SWIG_SyntaxError: - type = PyExc_SyntaxError; - break; - case SWIG_ValueError: - type = PyExc_ValueError; - break; - case SWIG_SystemError: - type = PyExc_SystemError; - break; - case SWIG_AttributeError: - type = PyExc_AttributeError; - break; - default: - type = PyExc_RuntimeError; - } - return type; -} - - -SWIGRUNTIME void -SWIG_Python_AddErrorMsg(const char* mesg) -{ - PyObject *type = 0; - PyObject *value = 0; - PyObject *traceback = 0; - - if (PyErr_Occurred()) PyErr_Fetch(&type, &value, &traceback); - if (value) { - char *tmp; - PyObject *old_str = PyObject_Str(value); - PyErr_Clear(); - Py_XINCREF(type); - - PyErr_Format(type, "%s %s", tmp = SWIG_Python_str_AsChar(old_str), mesg); - SWIG_Python_str_DelForPy3(tmp); - Py_DECREF(old_str); - Py_DECREF(value); - } else { - PyErr_SetString(PyExc_RuntimeError, mesg); - } -} - -#if defined(SWIG_PYTHON_NO_THREADS) -# if defined(SWIG_PYTHON_THREADS) -# undef SWIG_PYTHON_THREADS -# endif -#endif -#if defined(SWIG_PYTHON_THREADS) /* Threading support is enabled */ -# if !defined(SWIG_PYTHON_USE_GIL) && !defined(SWIG_PYTHON_NO_USE_GIL) -# if (PY_VERSION_HEX >= 0x02030000) /* For 2.3 or later, use the PyGILState calls */ -# define SWIG_PYTHON_USE_GIL -# endif -# endif -# if defined(SWIG_PYTHON_USE_GIL) /* Use PyGILState threads calls */ -# ifndef SWIG_PYTHON_INITIALIZE_THREADS -# define SWIG_PYTHON_INITIALIZE_THREADS PyEval_InitThreads() -# endif -# ifdef __cplusplus /* C++ code */ - class SWIG_Python_Thread_Block { - bool status; - PyGILState_STATE state; - public: - void end() { if (status) { PyGILState_Release(state); status = false;} } - SWIG_Python_Thread_Block() : status(true), state(PyGILState_Ensure()) {} - ~SWIG_Python_Thread_Block() { end(); } - }; - class SWIG_Python_Thread_Allow { - bool status; - PyThreadState *save; - public: - void end() { if (status) { PyEval_RestoreThread(save); status = false; }} - SWIG_Python_Thread_Allow() : status(true), save(PyEval_SaveThread()) {} - ~SWIG_Python_Thread_Allow() { end(); } - }; -# define SWIG_PYTHON_THREAD_BEGIN_BLOCK SWIG_Python_Thread_Block _swig_thread_block -# define SWIG_PYTHON_THREAD_END_BLOCK _swig_thread_block.end() -# define SWIG_PYTHON_THREAD_BEGIN_ALLOW SWIG_Python_Thread_Allow _swig_thread_allow -# define SWIG_PYTHON_THREAD_END_ALLOW _swig_thread_allow.end() -# else /* C code */ -# define SWIG_PYTHON_THREAD_BEGIN_BLOCK PyGILState_STATE _swig_thread_block = PyGILState_Ensure() -# define SWIG_PYTHON_THREAD_END_BLOCK PyGILState_Release(_swig_thread_block) -# define SWIG_PYTHON_THREAD_BEGIN_ALLOW PyThreadState *_swig_thread_allow = PyEval_SaveThread() -# define SWIG_PYTHON_THREAD_END_ALLOW PyEval_RestoreThread(_swig_thread_allow) -# endif -# else /* Old thread way, not implemented, user must provide it */ -# if !defined(SWIG_PYTHON_INITIALIZE_THREADS) -# define SWIG_PYTHON_INITIALIZE_THREADS -# endif -# if !defined(SWIG_PYTHON_THREAD_BEGIN_BLOCK) -# define SWIG_PYTHON_THREAD_BEGIN_BLOCK -# endif -# if !defined(SWIG_PYTHON_THREAD_END_BLOCK) -# define SWIG_PYTHON_THREAD_END_BLOCK -# endif -# if !defined(SWIG_PYTHON_THREAD_BEGIN_ALLOW) -# define SWIG_PYTHON_THREAD_BEGIN_ALLOW -# endif -# if !defined(SWIG_PYTHON_THREAD_END_ALLOW) -# define SWIG_PYTHON_THREAD_END_ALLOW -# endif -# endif -#else /* No thread support */ -# define SWIG_PYTHON_INITIALIZE_THREADS -# define SWIG_PYTHON_THREAD_BEGIN_BLOCK -# define SWIG_PYTHON_THREAD_END_BLOCK -# define SWIG_PYTHON_THREAD_BEGIN_ALLOW -# define SWIG_PYTHON_THREAD_END_ALLOW -#endif - -/* ----------------------------------------------------------------------------- - * Python API portion that goes into the runtime - * ----------------------------------------------------------------------------- */ - -#ifdef __cplusplus -extern "C" { -#if 0 -} /* cc-mode */ -#endif -#endif - -/* ----------------------------------------------------------------------------- - * Constant declarations - * ----------------------------------------------------------------------------- */ - -/* Constant Types */ -#define SWIG_PY_POINTER 4 -#define SWIG_PY_BINARY 5 - -/* Constant information structure */ -typedef struct swig_const_info { - int type; - char *name; - long lvalue; - double dvalue; - void *pvalue; - swig_type_info **ptype; -} swig_const_info; - - -/* ----------------------------------------------------------------------------- - * Wrapper of PyInstanceMethod_New() used in Python 3 - * It is exported to the generated module, used for -fastproxy - * ----------------------------------------------------------------------------- */ -SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func) -{ -#if PY_VERSION_HEX >= 0x03000000 - return PyInstanceMethod_New(func); -#else - return NULL; -#endif -} - -#ifdef __cplusplus -#if 0 -{ /* cc-mode */ -#endif -} -#endif - - -/* ----------------------------------------------------------------------------- - * See the LICENSE file for information on copyright, usage and redistribution - * of SWIG, and the README file for authors - http://www.swig.org/release.html. - * - * pyrun.swg - * - * This file contains the runtime support for Python modules - * and includes code for managing global variables and pointer - * type checking. - * - * ----------------------------------------------------------------------------- */ - -/* Common SWIG API */ - -/* for raw pointers */ -#define SWIG_Python_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, 0) -#define SWIG_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtr(obj, pptr, type, flags) -#define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, own) -#define SWIG_NewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(ptr, type, flags) -#define SWIG_CheckImplicit(ty) SWIG_Python_CheckImplicit(ty) -#define SWIG_AcquirePtr(ptr, src) SWIG_Python_AcquirePtr(ptr, src) -#define swig_owntype int - -/* for raw packed data */ -#define SWIG_ConvertPacked(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty) -#define SWIG_NewPackedObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type) - -/* for class or struct pointers */ -#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_ConvertPtr(obj, pptr, type, flags) -#define SWIG_NewInstanceObj(ptr, type, flags) SWIG_NewPointerObj(ptr, type, flags) - -/* for C or C++ function pointers */ -#define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_Python_ConvertFunctionPtr(obj, pptr, type) -#define SWIG_NewFunctionPtrObj(ptr, type) SWIG_Python_NewPointerObj(ptr, type, 0) - -/* for C++ member pointers, ie, member methods */ -#define SWIG_ConvertMember(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty) -#define SWIG_NewMemberObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type) - - -/* Runtime API */ - -#define SWIG_GetModule(clientdata) SWIG_Python_GetModule() -#define SWIG_SetModule(clientdata, pointer) SWIG_Python_SetModule(pointer) -#define SWIG_NewClientData(obj) SwigPyClientData_New(obj) - -#define SWIG_SetErrorObj SWIG_Python_SetErrorObj -#define SWIG_SetErrorMsg SWIG_Python_SetErrorMsg -#define SWIG_ErrorType(code) SWIG_Python_ErrorType(code) -#define SWIG_Error(code, msg) SWIG_Python_SetErrorMsg(SWIG_ErrorType(code), msg) -#define SWIG_fail goto fail - - -/* Runtime API implementation */ - -/* Error manipulation */ - -SWIGINTERN void -SWIG_Python_SetErrorObj(PyObject *errtype, PyObject *obj) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - PyErr_SetObject(errtype, obj); - Py_DECREF(obj); - SWIG_PYTHON_THREAD_END_BLOCK; -} - -SWIGINTERN void -SWIG_Python_SetErrorMsg(PyObject *errtype, const char *msg) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - PyErr_SetString(errtype, (char *) msg); - SWIG_PYTHON_THREAD_END_BLOCK; -} - -#define SWIG_Python_Raise(obj, type, desc) SWIG_Python_SetErrorObj(SWIG_Python_ExceptionType(desc), obj) - -/* Set a constant value */ - -SWIGINTERN void -SWIG_Python_SetConstant(PyObject *d, const char *name, PyObject *obj) { - PyDict_SetItemString(d, (char*) name, obj); - Py_DECREF(obj); -} - -/* Append a value to the result obj */ - -SWIGINTERN PyObject* -SWIG_Python_AppendOutput(PyObject* result, PyObject* obj) { -#if !defined(SWIG_PYTHON_OUTPUT_TUPLE) - if (!result) { - result = obj; - } else if (result == Py_None) { - Py_DECREF(result); - result = obj; - } else { - if (!PyList_Check(result)) { - PyObject *o2 = result; - result = PyList_New(1); - PyList_SetItem(result, 0, o2); - } - PyList_Append(result,obj); - Py_DECREF(obj); - } - return result; -#else - PyObject* o2; - PyObject* o3; - if (!result) { - result = obj; - } else if (result == Py_None) { - Py_DECREF(result); - result = obj; - } else { - if (!PyTuple_Check(result)) { - o2 = result; - result = PyTuple_New(1); - PyTuple_SET_ITEM(result, 0, o2); - } - o3 = PyTuple_New(1); - PyTuple_SET_ITEM(o3, 0, obj); - o2 = result; - result = PySequence_Concat(o2, o3); - Py_DECREF(o2); - Py_DECREF(o3); - } - return result; -#endif -} - -/* Unpack the argument tuple */ - -SWIGINTERN int -SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, PyObject **objs) -{ - if (!args) { - if (!min && !max) { - return 1; - } else { - PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got none", - name, (min == max ? "" : "at least "), (int)min); - return 0; - } - } - if (!PyTuple_Check(args)) { - PyErr_SetString(PyExc_SystemError, "UnpackTuple() argument list is not a tuple"); - return 0; - } else { - register Py_ssize_t l = PyTuple_GET_SIZE(args); - if (l < min) { - PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", - name, (min == max ? "" : "at least "), (int)min, (int)l); - return 0; - } else if (l > max) { - PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", - name, (min == max ? "" : "at most "), (int)max, (int)l); - return 0; - } else { - register int i; - for (i = 0; i < l; ++i) { - objs[i] = PyTuple_GET_ITEM(args, i); - } - for (; l < max; ++l) { - objs[l] = 0; - } - return i + 1; - } - } -} - -/* A functor is a function object with one single object argument */ -#if PY_VERSION_HEX >= 0x02020000 -#define SWIG_Python_CallFunctor(functor, obj) PyObject_CallFunctionObjArgs(functor, obj, NULL); -#else -#define SWIG_Python_CallFunctor(functor, obj) PyObject_CallFunction(functor, "O", obj); -#endif - -/* - Helper for static pointer initialization for both C and C++ code, for example - static PyObject *SWIG_STATIC_POINTER(MyVar) = NewSomething(...); -*/ -#ifdef __cplusplus -#define SWIG_STATIC_POINTER(var) var -#else -#define SWIG_STATIC_POINTER(var) var = 0; if (!var) var -#endif - -/* ----------------------------------------------------------------------------- - * Pointer declarations - * ----------------------------------------------------------------------------- */ - -/* Flags for new pointer objects */ -#define SWIG_POINTER_NOSHADOW (SWIG_POINTER_OWN << 1) -#define SWIG_POINTER_NEW (SWIG_POINTER_NOSHADOW | SWIG_POINTER_OWN) - -#define SWIG_POINTER_IMPLICIT_CONV (SWIG_POINTER_DISOWN << 1) - -#ifdef __cplusplus -extern "C" { -#if 0 -} /* cc-mode */ -#endif -#endif - -/* How to access Py_None */ -#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# ifndef SWIG_PYTHON_NO_BUILD_NONE -# ifndef SWIG_PYTHON_BUILD_NONE -# define SWIG_PYTHON_BUILD_NONE -# endif -# endif -#endif - -#ifdef SWIG_PYTHON_BUILD_NONE -# ifdef Py_None -# undef Py_None -# define Py_None SWIG_Py_None() -# endif -SWIGRUNTIMEINLINE PyObject * -_SWIG_Py_None(void) -{ - PyObject *none = Py_BuildValue((char*)""); - Py_DECREF(none); - return none; -} -SWIGRUNTIME PyObject * -SWIG_Py_None(void) -{ - static PyObject *SWIG_STATIC_POINTER(none) = _SWIG_Py_None(); - return none; -} -#endif - -/* The python void return value */ - -SWIGRUNTIMEINLINE PyObject * -SWIG_Py_Void(void) -{ - PyObject *none = Py_None; - Py_INCREF(none); - return none; -} - -/* SwigPyClientData */ - -typedef struct { - PyObject *klass; - PyObject *newraw; - PyObject *newargs; - PyObject *destroy; - int delargs; - int implicitconv; -} SwigPyClientData; - -SWIGRUNTIMEINLINE int -SWIG_Python_CheckImplicit(swig_type_info *ty) -{ - SwigPyClientData *data = (SwigPyClientData *)ty->clientdata; - return data ? data->implicitconv : 0; -} - -SWIGRUNTIMEINLINE PyObject * -SWIG_Python_ExceptionType(swig_type_info *desc) { - SwigPyClientData *data = desc ? (SwigPyClientData *) desc->clientdata : 0; - PyObject *klass = data ? data->klass : 0; - return (klass ? klass : PyExc_RuntimeError); -} - - -SWIGRUNTIME SwigPyClientData * -SwigPyClientData_New(PyObject* obj) -{ - if (!obj) { - return 0; - } else { - SwigPyClientData *data = (SwigPyClientData *)malloc(sizeof(SwigPyClientData)); - /* the klass element */ - data->klass = obj; - Py_INCREF(data->klass); - /* the newraw method and newargs arguments used to create a new raw instance */ - if (PyClass_Check(obj)) { - data->newraw = 0; - data->newargs = obj; - Py_INCREF(obj); - } else { -#if (PY_VERSION_HEX < 0x02020000) - data->newraw = 0; -#else - data->newraw = PyObject_GetAttrString(data->klass, (char *)"__new__"); -#endif - if (data->newraw) { - Py_INCREF(data->newraw); - data->newargs = PyTuple_New(1); - PyTuple_SetItem(data->newargs, 0, obj); - } else { - data->newargs = obj; - } - Py_INCREF(data->newargs); - } - /* the destroy method, aka as the C++ delete method */ - data->destroy = PyObject_GetAttrString(data->klass, (char *)"__swig_destroy__"); - if (PyErr_Occurred()) { - PyErr_Clear(); - data->destroy = 0; - } - if (data->destroy) { - int flags; - Py_INCREF(data->destroy); - flags = PyCFunction_GET_FLAGS(data->destroy); -#ifdef METH_O - data->delargs = !(flags & (METH_O)); -#else - data->delargs = 0; -#endif - } else { - data->delargs = 0; - } - data->implicitconv = 0; - return data; - } -} - -SWIGRUNTIME void -SwigPyClientData_Del(SwigPyClientData* data) -{ - Py_XDECREF(data->newraw); - Py_XDECREF(data->newargs); - Py_XDECREF(data->destroy); -} - -/* =============== SwigPyObject =====================*/ - -typedef struct { - PyObject_HEAD - void *ptr; - swig_type_info *ty; - int own; - PyObject *next; -} SwigPyObject; - -SWIGRUNTIME PyObject * -SwigPyObject_long(SwigPyObject *v) -{ - return PyLong_FromVoidPtr(v->ptr); -} - -SWIGRUNTIME PyObject * -SwigPyObject_format(const char* fmt, SwigPyObject *v) -{ - PyObject *res = NULL; - PyObject *args = PyTuple_New(1); - if (args) { - if (PyTuple_SetItem(args, 0, SwigPyObject_long(v)) == 0) { - PyObject *ofmt = SWIG_Python_str_FromChar(fmt); - if (ofmt) { -#if PY_VERSION_HEX >= 0x03000000 - res = PyUnicode_Format(ofmt,args); -#else - res = PyString_Format(ofmt,args); -#endif - Py_DECREF(ofmt); - } - Py_DECREF(args); - } - } - return res; -} - -SWIGRUNTIME PyObject * -SwigPyObject_oct(SwigPyObject *v) -{ - return SwigPyObject_format("%o",v); -} - -SWIGRUNTIME PyObject * -SwigPyObject_hex(SwigPyObject *v) -{ - return SwigPyObject_format("%x",v); -} - -SWIGRUNTIME PyObject * -#ifdef METH_NOARGS -SwigPyObject_repr(SwigPyObject *v) -#else -SwigPyObject_repr(SwigPyObject *v, PyObject *args) -#endif -{ - const char *name = SWIG_TypePrettyName(v->ty); - PyObject *repr = SWIG_Python_str_FromFormat("", name, v); - if (v->next) { -#ifdef METH_NOARGS - PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next); -#else - PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next, args); -#endif -#if PY_VERSION_HEX >= 0x03000000 - PyObject *joined = PyUnicode_Concat(repr, nrep); - Py_DecRef(repr); - Py_DecRef(nrep); - repr = joined; -#else - PyString_ConcatAndDel(&repr,nrep); -#endif - } - return repr; -} - -SWIGRUNTIME int -SwigPyObject_print(SwigPyObject *v, FILE *fp, int SWIGUNUSEDPARM(flags)) -{ - char *str; -#ifdef METH_NOARGS - PyObject *repr = SwigPyObject_repr(v); -#else - PyObject *repr = SwigPyObject_repr(v, NULL); -#endif - if (repr) { - str = SWIG_Python_str_AsChar(repr); - fputs(str, fp); - SWIG_Python_str_DelForPy3(str); - Py_DECREF(repr); - return 0; - } else { - return 1; - } -} - -SWIGRUNTIME PyObject * -SwigPyObject_str(SwigPyObject *v) -{ - char result[SWIG_BUFFER_SIZE]; - return SWIG_PackVoidPtr(result, v->ptr, v->ty->name, sizeof(result)) ? - SWIG_Python_str_FromChar(result) : 0; -} - -SWIGRUNTIME int -SwigPyObject_compare(SwigPyObject *v, SwigPyObject *w) -{ - void *i = v->ptr; - void *j = w->ptr; - return (i < j) ? -1 : ((i > j) ? 1 : 0); -} - -/* Added for Python 3.x, would it also be useful for Python 2.x? */ -SWIGRUNTIME PyObject* -SwigPyObject_richcompare(SwigPyObject *v, SwigPyObject *w, int op) -{ - PyObject* res; - if( op != Py_EQ && op != Py_NE ) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - if( (SwigPyObject_compare(v, w)==0) == (op == Py_EQ) ) - res = Py_True; - else - res = Py_False; - Py_INCREF(res); - return res; -} - - -SWIGRUNTIME PyTypeObject* _PySwigObject_type(void); - -SWIGRUNTIME PyTypeObject* -SwigPyObject_type(void) { - static PyTypeObject *SWIG_STATIC_POINTER(type) = _PySwigObject_type(); - return type; -} - -SWIGRUNTIMEINLINE int -SwigPyObject_Check(PyObject *op) { - return (Py_TYPE(op) == SwigPyObject_type()) - || (strcmp(Py_TYPE(op)->tp_name,"SwigPyObject") == 0); -} - -SWIGRUNTIME PyObject * -SwigPyObject_New(void *ptr, swig_type_info *ty, int own); - -SWIGRUNTIME void -SwigPyObject_dealloc(PyObject *v) -{ - SwigPyObject *sobj = (SwigPyObject *) v; - PyObject *next = sobj->next; - if (sobj->own == SWIG_POINTER_OWN) { - swig_type_info *ty = sobj->ty; - SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0; - PyObject *destroy = data ? data->destroy : 0; - if (destroy) { - /* destroy is always a VARARGS method */ - PyObject *res; - if (data->delargs) { - /* we need to create a temporary object to carry the destroy operation */ - PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0); - res = SWIG_Python_CallFunctor(destroy, tmp); - Py_DECREF(tmp); - } else { - PyCFunction meth = PyCFunction_GET_FUNCTION(destroy); - PyObject *mself = PyCFunction_GET_SELF(destroy); - res = ((*meth)(mself, v)); - } - Py_XDECREF(res); - } -#if !defined(SWIG_PYTHON_SILENT_MEMLEAK) - else { - const char *name = SWIG_TypePrettyName(ty); - printf("swig/python detected a memory leak of type '%s', no destructor found.\n", (name ? name : "unknown")); - } -#endif - } - Py_XDECREF(next); - PyObject_DEL(v); -} - -SWIGRUNTIME PyObject* -SwigPyObject_append(PyObject* v, PyObject* next) -{ - SwigPyObject *sobj = (SwigPyObject *) v; -#ifndef METH_O - PyObject *tmp = 0; - if (!PyArg_ParseTuple(next,(char *)"O:append", &tmp)) return NULL; - next = tmp; -#endif - if (!SwigPyObject_Check(next)) { - return NULL; - } - sobj->next = next; - Py_INCREF(next); - return SWIG_Py_Void(); -} - -SWIGRUNTIME PyObject* -#ifdef METH_NOARGS -SwigPyObject_next(PyObject* v) -#else -SwigPyObject_next(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) -#endif -{ - SwigPyObject *sobj = (SwigPyObject *) v; - if (sobj->next) { - Py_INCREF(sobj->next); - return sobj->next; - } else { - return SWIG_Py_Void(); - } -} - -SWIGINTERN PyObject* -#ifdef METH_NOARGS -SwigPyObject_disown(PyObject *v) -#else -SwigPyObject_disown(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) -#endif -{ - SwigPyObject *sobj = (SwigPyObject *)v; - sobj->own = 0; - return SWIG_Py_Void(); -} - -SWIGINTERN PyObject* -#ifdef METH_NOARGS -SwigPyObject_acquire(PyObject *v) -#else -SwigPyObject_acquire(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) -#endif -{ - SwigPyObject *sobj = (SwigPyObject *)v; - sobj->own = SWIG_POINTER_OWN; - return SWIG_Py_Void(); -} - -SWIGINTERN PyObject* -SwigPyObject_own(PyObject *v, PyObject *args) -{ - PyObject *val = 0; -#if (PY_VERSION_HEX < 0x02020000) - if (!PyArg_ParseTuple(args,(char *)"|O:own",&val)) -#else - if (!PyArg_UnpackTuple(args, (char *)"own", 0, 1, &val)) -#endif - { - return NULL; - } - else - { - SwigPyObject *sobj = (SwigPyObject *)v; - PyObject *obj = PyBool_FromLong(sobj->own); - if (val) { -#ifdef METH_NOARGS - if (PyObject_IsTrue(val)) { - SwigPyObject_acquire(v); - } else { - SwigPyObject_disown(v); - } -#else - if (PyObject_IsTrue(val)) { - SwigPyObject_acquire(v,args); - } else { - SwigPyObject_disown(v,args); - } -#endif - } - return obj; - } -} - -#ifdef METH_O -static PyMethodDef -swigobject_methods[] = { - {(char *)"disown", (PyCFunction)SwigPyObject_disown, METH_NOARGS, (char *)"releases ownership of the pointer"}, - {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_NOARGS, (char *)"aquires ownership of the pointer"}, - {(char *)"own", (PyCFunction)SwigPyObject_own, METH_VARARGS, (char *)"returns/sets ownership of the pointer"}, - {(char *)"append", (PyCFunction)SwigPyObject_append, METH_O, (char *)"appends another 'this' object"}, - {(char *)"next", (PyCFunction)SwigPyObject_next, METH_NOARGS, (char *)"returns the next 'this' object"}, - {(char *)"__repr__",(PyCFunction)SwigPyObject_repr, METH_NOARGS, (char *)"returns object representation"}, - {0, 0, 0, 0} -}; -#else -static PyMethodDef -swigobject_methods[] = { - {(char *)"disown", (PyCFunction)SwigPyObject_disown, METH_VARARGS, (char *)"releases ownership of the pointer"}, - {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_VARARGS, (char *)"aquires ownership of the pointer"}, - {(char *)"own", (PyCFunction)SwigPyObject_own, METH_VARARGS, (char *)"returns/sets ownership of the pointer"}, - {(char *)"append", (PyCFunction)SwigPyObject_append, METH_VARARGS, (char *)"appends another 'this' object"}, - {(char *)"next", (PyCFunction)SwigPyObject_next, METH_VARARGS, (char *)"returns the next 'this' object"}, - {(char *)"__repr__",(PyCFunction)SwigPyObject_repr, METH_VARARGS, (char *)"returns object representation"}, - {0, 0, 0, 0} -}; -#endif - -#if PY_VERSION_HEX < 0x02020000 -SWIGINTERN PyObject * -SwigPyObject_getattr(SwigPyObject *sobj,char *name) -{ - return Py_FindMethod(swigobject_methods, (PyObject *)sobj, name); -} -#endif - -SWIGRUNTIME PyTypeObject* -_PySwigObject_type(void) { - static char swigobject_doc[] = "Swig object carries a C/C++ instance pointer"; - - static PyNumberMethods SwigPyObject_as_number = { - (binaryfunc)0, /*nb_add*/ - (binaryfunc)0, /*nb_subtract*/ - (binaryfunc)0, /*nb_multiply*/ - /* nb_divide removed in Python 3 */ -#if PY_VERSION_HEX < 0x03000000 - (binaryfunc)0, /*nb_divide*/ -#endif - (binaryfunc)0, /*nb_remainder*/ - (binaryfunc)0, /*nb_divmod*/ - (ternaryfunc)0,/*nb_power*/ - (unaryfunc)0, /*nb_negative*/ - (unaryfunc)0, /*nb_positive*/ - (unaryfunc)0, /*nb_absolute*/ - (inquiry)0, /*nb_nonzero*/ - 0, /*nb_invert*/ - 0, /*nb_lshift*/ - 0, /*nb_rshift*/ - 0, /*nb_and*/ - 0, /*nb_xor*/ - 0, /*nb_or*/ -#if PY_VERSION_HEX < 0x03000000 - 0, /*nb_coerce*/ -#endif - (unaryfunc)SwigPyObject_long, /*nb_int*/ -#if PY_VERSION_HEX < 0x03000000 - (unaryfunc)SwigPyObject_long, /*nb_long*/ -#else - 0, /*nb_reserved*/ -#endif - (unaryfunc)0, /*nb_float*/ -#if PY_VERSION_HEX < 0x03000000 - (unaryfunc)SwigPyObject_oct, /*nb_oct*/ - (unaryfunc)SwigPyObject_hex, /*nb_hex*/ -#endif -#if PY_VERSION_HEX >= 0x03000000 /* 3.0 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index, nb_inplace_divide removed */ -#elif PY_VERSION_HEX >= 0x02050000 /* 2.5.0 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index */ -#elif PY_VERSION_HEX >= 0x02020000 /* 2.2.0 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_true_divide */ -#elif PY_VERSION_HEX >= 0x02000000 /* 2.0.0 */ - 0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_or */ -#endif - }; - - static PyTypeObject swigpyobject_type; - static int type_init = 0; - if (!type_init) { - const PyTypeObject tmp - = { - /* PyObject header changed in Python 3 */ -#if PY_VERSION_HEX >= 0x03000000 - PyVarObject_HEAD_INIT(&PyType_Type, 0) -#else - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ -#endif - (char *)"SwigPyObject", /* tp_name */ - sizeof(SwigPyObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)SwigPyObject_dealloc, /* tp_dealloc */ - (printfunc)SwigPyObject_print, /* tp_print */ -#if PY_VERSION_HEX < 0x02020000 - (getattrfunc)SwigPyObject_getattr, /* tp_getattr */ -#else - (getattrfunc)0, /* tp_getattr */ -#endif - (setattrfunc)0, /* tp_setattr */ -#if PY_VERSION_HEX >= 0x03000000 - 0, /* tp_reserved in 3.0.1, tp_compare in 3.0.0 but not used */ -#else - (cmpfunc)SwigPyObject_compare, /* tp_compare */ -#endif - (reprfunc)SwigPyObject_repr, /* tp_repr */ - &SwigPyObject_as_number, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)0, /* tp_hash */ - (ternaryfunc)0, /* tp_call */ - (reprfunc)SwigPyObject_str, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - swigobject_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - (richcmpfunc)SwigPyObject_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ -#if PY_VERSION_HEX >= 0x02020000 - 0, /* tp_iter */ - 0, /* tp_iternext */ - swigobject_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ -#endif -#if PY_VERSION_HEX >= 0x02030000 - 0, /* tp_del */ -#endif -#ifdef COUNT_ALLOCS - 0,0,0,0 /* tp_alloc -> tp_next */ -#endif - }; - swigpyobject_type = tmp; - /* for Python 3 we already assigned ob_type in PyVarObject_HEAD_INIT() */ -#if PY_VERSION_HEX < 0x03000000 - swigpyobject_type.ob_type = &PyType_Type; -#endif - type_init = 1; - } - return &swigpyobject_type; -} - -SWIGRUNTIME PyObject * -SwigPyObject_New(void *ptr, swig_type_info *ty, int own) -{ - SwigPyObject *sobj = PyObject_NEW(SwigPyObject, SwigPyObject_type()); - if (sobj) { - sobj->ptr = ptr; - sobj->ty = ty; - sobj->own = own; - sobj->next = 0; - } - return (PyObject *)sobj; -} - -/* ----------------------------------------------------------------------------- - * Implements a simple Swig Packed type, and use it instead of string - * ----------------------------------------------------------------------------- */ - -typedef struct { - PyObject_HEAD - void *pack; - swig_type_info *ty; - size_t size; -} SwigPyPacked; - -SWIGRUNTIME int -SwigPyPacked_print(SwigPyPacked *v, FILE *fp, int SWIGUNUSEDPARM(flags)) -{ - char result[SWIG_BUFFER_SIZE]; - fputs("pack, v->size, 0, sizeof(result))) { - fputs("at ", fp); - fputs(result, fp); - } - fputs(v->ty->name,fp); - fputs(">", fp); - return 0; -} - -SWIGRUNTIME PyObject * -SwigPyPacked_repr(SwigPyPacked *v) -{ - char result[SWIG_BUFFER_SIZE]; - if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))) { - return SWIG_Python_str_FromFormat("", result, v->ty->name); - } else { - return SWIG_Python_str_FromFormat("", v->ty->name); - } -} - -SWIGRUNTIME PyObject * -SwigPyPacked_str(SwigPyPacked *v) -{ - char result[SWIG_BUFFER_SIZE]; - if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))){ - return SWIG_Python_str_FromFormat("%s%s", result, v->ty->name); - } else { - return SWIG_Python_str_FromChar(v->ty->name); - } -} - -SWIGRUNTIME int -SwigPyPacked_compare(SwigPyPacked *v, SwigPyPacked *w) -{ - size_t i = v->size; - size_t j = w->size; - int s = (i < j) ? -1 : ((i > j) ? 1 : 0); - return s ? s : strncmp((char *)v->pack, (char *)w->pack, 2*v->size); -} - -SWIGRUNTIME PyTypeObject* _PySwigPacked_type(void); - -SWIGRUNTIME PyTypeObject* -SwigPyPacked_type(void) { - static PyTypeObject *SWIG_STATIC_POINTER(type) = _PySwigPacked_type(); - return type; -} - -SWIGRUNTIMEINLINE int -SwigPyPacked_Check(PyObject *op) { - return ((op)->ob_type == _PySwigPacked_type()) - || (strcmp((op)->ob_type->tp_name,"SwigPyPacked") == 0); -} - -SWIGRUNTIME void -SwigPyPacked_dealloc(PyObject *v) -{ - if (SwigPyPacked_Check(v)) { - SwigPyPacked *sobj = (SwigPyPacked *) v; - free(sobj->pack); - } - PyObject_DEL(v); -} - -SWIGRUNTIME PyTypeObject* -_PySwigPacked_type(void) { - static char swigpacked_doc[] = "Swig object carries a C/C++ instance pointer"; - static PyTypeObject swigpypacked_type; - static int type_init = 0; - if (!type_init) { - const PyTypeObject tmp - = { - /* PyObject header changed in Python 3 */ -#if PY_VERSION_HEX>=0x03000000 - PyVarObject_HEAD_INIT(&PyType_Type, 0) -#else - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ -#endif - (char *)"SwigPyPacked", /* tp_name */ - sizeof(SwigPyPacked), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)SwigPyPacked_dealloc, /* tp_dealloc */ - (printfunc)SwigPyPacked_print, /* tp_print */ - (getattrfunc)0, /* tp_getattr */ - (setattrfunc)0, /* tp_setattr */ -#if PY_VERSION_HEX>=0x03000000 - 0, /* tp_reserved in 3.0.1 */ -#else - (cmpfunc)SwigPyPacked_compare, /* tp_compare */ -#endif - (reprfunc)SwigPyPacked_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)0, /* tp_hash */ - (ternaryfunc)0, /* tp_call */ - (reprfunc)SwigPyPacked_str, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - swigpacked_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ -#if PY_VERSION_HEX >= 0x02020000 - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ -#endif -#if PY_VERSION_HEX >= 0x02030000 - 0, /* tp_del */ -#endif -#ifdef COUNT_ALLOCS - 0,0,0,0 /* tp_alloc -> tp_next */ -#endif - }; - swigpypacked_type = tmp; - /* for Python 3 the ob_type already assigned in PyVarObject_HEAD_INIT() */ -#if PY_VERSION_HEX < 0x03000000 - swigpypacked_type.ob_type = &PyType_Type; -#endif - type_init = 1; - } - return &swigpypacked_type; -} - -SWIGRUNTIME PyObject * -SwigPyPacked_New(void *ptr, size_t size, swig_type_info *ty) -{ - SwigPyPacked *sobj = PyObject_NEW(SwigPyPacked, SwigPyPacked_type()); - if (sobj) { - void *pack = malloc(size); - if (pack) { - memcpy(pack, ptr, size); - sobj->pack = pack; - sobj->ty = ty; - sobj->size = size; - } else { - PyObject_DEL((PyObject *) sobj); - sobj = 0; - } - } - return (PyObject *) sobj; -} - -SWIGRUNTIME swig_type_info * -SwigPyPacked_UnpackData(PyObject *obj, void *ptr, size_t size) -{ - if (SwigPyPacked_Check(obj)) { - SwigPyPacked *sobj = (SwigPyPacked *)obj; - if (sobj->size != size) return 0; - memcpy(ptr, sobj->pack, size); - return sobj->ty; - } else { - return 0; - } -} - -/* ----------------------------------------------------------------------------- - * pointers/data manipulation - * ----------------------------------------------------------------------------- */ - -SWIGRUNTIMEINLINE PyObject * -_SWIG_This(void) -{ - return SWIG_Python_str_FromChar("this"); -} - -SWIGRUNTIME PyObject * -SWIG_This(void) -{ - static PyObject *SWIG_STATIC_POINTER(swig_this) = _SWIG_This(); - return swig_this; -} - -/* #define SWIG_PYTHON_SLOW_GETSET_THIS */ - -/* TODO: I don't know how to implement the fast getset in Python 3 right now */ -#if PY_VERSION_HEX>=0x03000000 -#define SWIG_PYTHON_SLOW_GETSET_THIS -#endif - -SWIGRUNTIME SwigPyObject * -SWIG_Python_GetSwigThis(PyObject *pyobj) -{ - if (SwigPyObject_Check(pyobj)) { - return (SwigPyObject *) pyobj; - } else { - PyObject *obj = 0; -#if (!defined(SWIG_PYTHON_SLOW_GETSET_THIS) && (PY_VERSION_HEX >= 0x02030000)) - if (PyInstance_Check(pyobj)) { - obj = _PyInstance_Lookup(pyobj, SWIG_This()); - } else { - PyObject **dictptr = _PyObject_GetDictPtr(pyobj); - if (dictptr != NULL) { - PyObject *dict = *dictptr; - obj = dict ? PyDict_GetItem(dict, SWIG_This()) : 0; - } else { -#ifdef PyWeakref_CheckProxy - if (PyWeakref_CheckProxy(pyobj)) { - PyObject *wobj = PyWeakref_GET_OBJECT(pyobj); - return wobj ? SWIG_Python_GetSwigThis(wobj) : 0; - } -#endif - obj = PyObject_GetAttr(pyobj,SWIG_This()); - if (obj) { - Py_DECREF(obj); - } else { - if (PyErr_Occurred()) PyErr_Clear(); - return 0; - } - } - } -#else - obj = PyObject_GetAttr(pyobj,SWIG_This()); - if (obj) { - Py_DECREF(obj); - } else { - if (PyErr_Occurred()) PyErr_Clear(); - return 0; - } -#endif - if (obj && !SwigPyObject_Check(obj)) { - /* a PyObject is called 'this', try to get the 'real this' - SwigPyObject from it */ - return SWIG_Python_GetSwigThis(obj); - } - return (SwigPyObject *)obj; - } -} - -/* Acquire a pointer value */ - -SWIGRUNTIME int -SWIG_Python_AcquirePtr(PyObject *obj, int own) { - if (own == SWIG_POINTER_OWN) { - SwigPyObject *sobj = SWIG_Python_GetSwigThis(obj); - if (sobj) { - int oldown = sobj->own; - sobj->own = own; - return oldown; - } - } - return 0; -} - -/* Convert a pointer value */ - -SWIGRUNTIME int -SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int flags, int *own) { - if (!obj) return SWIG_ERROR; - if (obj == Py_None) { - if (ptr) *ptr = 0; - return SWIG_OK; - } else { - SwigPyObject *sobj = SWIG_Python_GetSwigThis(obj); - if (own) - *own = 0; - while (sobj) { - void *vptr = sobj->ptr; - if (ty) { - swig_type_info *to = sobj->ty; - if (to == ty) { - /* no type cast needed */ - if (ptr) *ptr = vptr; - break; - } else { - swig_cast_info *tc = SWIG_TypeCheck(to->name,ty); - if (!tc) { - sobj = (SwigPyObject *)sobj->next; - } else { - if (ptr) { - int newmemory = 0; - *ptr = SWIG_TypeCast(tc,vptr,&newmemory); - if (newmemory == SWIG_CAST_NEW_MEMORY) { - assert(own); - if (own) - *own = *own | SWIG_CAST_NEW_MEMORY; - } - } - break; - } - } - } else { - if (ptr) *ptr = vptr; - break; - } - } - if (sobj) { - if (own) - *own = *own | sobj->own; - if (flags & SWIG_POINTER_DISOWN) { - sobj->own = 0; - } - return SWIG_OK; - } else { - int res = SWIG_ERROR; - if (flags & SWIG_POINTER_IMPLICIT_CONV) { - SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0; - if (data && !data->implicitconv) { - PyObject *klass = data->klass; - if (klass) { - PyObject *impconv; - data->implicitconv = 1; /* avoid recursion and call 'explicit' constructors*/ - impconv = SWIG_Python_CallFunctor(klass, obj); - data->implicitconv = 0; - if (PyErr_Occurred()) { - PyErr_Clear(); - impconv = 0; - } - if (impconv) { - SwigPyObject *iobj = SWIG_Python_GetSwigThis(impconv); - if (iobj) { - void *vptr; - res = SWIG_Python_ConvertPtrAndOwn((PyObject*)iobj, &vptr, ty, 0, 0); - if (SWIG_IsOK(res)) { - if (ptr) { - *ptr = vptr; - /* transfer the ownership to 'ptr' */ - iobj->own = 0; - res = SWIG_AddCast(res); - res = SWIG_AddNewMask(res); - } else { - res = SWIG_AddCast(res); - } - } - } - Py_DECREF(impconv); - } - } - } - } - return res; - } - } -} - -/* Convert a function ptr value */ - -SWIGRUNTIME int -SWIG_Python_ConvertFunctionPtr(PyObject *obj, void **ptr, swig_type_info *ty) { - if (!PyCFunction_Check(obj)) { - return SWIG_ConvertPtr(obj, ptr, ty, 0); - } else { - void *vptr = 0; - - /* here we get the method pointer for callbacks */ - const char *doc = (((PyCFunctionObject *)obj) -> m_ml -> ml_doc); - const char *desc = doc ? strstr(doc, "swig_ptr: ") : 0; - if (desc) - desc = ty ? SWIG_UnpackVoidPtr(desc + 10, &vptr, ty->name) : 0; - if (!desc) - return SWIG_ERROR; - if (ty) { - swig_cast_info *tc = SWIG_TypeCheck(desc,ty); - if (tc) { - int newmemory = 0; - *ptr = SWIG_TypeCast(tc,vptr,&newmemory); - assert(!newmemory); /* newmemory handling not yet implemented */ - } else { - return SWIG_ERROR; - } - } else { - *ptr = vptr; - } - return SWIG_OK; - } -} - -/* Convert a packed value value */ - -SWIGRUNTIME int -SWIG_Python_ConvertPacked(PyObject *obj, void *ptr, size_t sz, swig_type_info *ty) { - swig_type_info *to = SwigPyPacked_UnpackData(obj, ptr, sz); - if (!to) return SWIG_ERROR; - if (ty) { - if (to != ty) { - /* check type cast? */ - swig_cast_info *tc = SWIG_TypeCheck(to->name,ty); - if (!tc) return SWIG_ERROR; - } - } - return SWIG_OK; -} - -/* ----------------------------------------------------------------------------- - * Create a new pointer object - * ----------------------------------------------------------------------------- */ - -/* - Create a new instance object, without calling __init__, and set the - 'this' attribute. -*/ - -SWIGRUNTIME PyObject* -SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this) -{ -#if (PY_VERSION_HEX >= 0x02020000) - PyObject *inst = 0; - PyObject *newraw = data->newraw; - if (newraw) { - inst = PyObject_Call(newraw, data->newargs, NULL); - if (inst) { -#if !defined(SWIG_PYTHON_SLOW_GETSET_THIS) - PyObject **dictptr = _PyObject_GetDictPtr(inst); - if (dictptr != NULL) { - PyObject *dict = *dictptr; - if (dict == NULL) { - dict = PyDict_New(); - *dictptr = dict; - PyDict_SetItem(dict, SWIG_This(), swig_this); - } - } -#else - PyObject *key = SWIG_This(); - PyObject_SetAttr(inst, key, swig_this); -#endif - } - } else { -#if PY_VERSION_HEX >= 0x03000000 - inst = PyBaseObject_Type.tp_new((PyTypeObject*) data->newargs, Py_None, Py_None); - PyObject_SetAttr(inst, SWIG_This(), swig_this); - Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG; -#else - PyObject *dict = PyDict_New(); - PyDict_SetItem(dict, SWIG_This(), swig_this); - inst = PyInstance_NewRaw(data->newargs, dict); - Py_DECREF(dict); -#endif - } - return inst; -#else -#if (PY_VERSION_HEX >= 0x02010000) - PyObject *inst; - PyObject *dict = PyDict_New(); - PyDict_SetItem(dict, SWIG_This(), swig_this); - inst = PyInstance_NewRaw(data->newargs, dict); - Py_DECREF(dict); - return (PyObject *) inst; -#else - PyInstanceObject *inst = PyObject_NEW(PyInstanceObject, &PyInstance_Type); - if (inst == NULL) { - return NULL; - } - inst->in_class = (PyClassObject *)data->newargs; - Py_INCREF(inst->in_class); - inst->in_dict = PyDict_New(); - if (inst->in_dict == NULL) { - Py_DECREF(inst); - return NULL; - } -#ifdef Py_TPFLAGS_HAVE_WEAKREFS - inst->in_weakreflist = NULL; -#endif -#ifdef Py_TPFLAGS_GC - PyObject_GC_Init(inst); -#endif - PyDict_SetItem(inst->in_dict, SWIG_This(), swig_this); - return (PyObject *) inst; -#endif -#endif -} - -SWIGRUNTIME void -SWIG_Python_SetSwigThis(PyObject *inst, PyObject *swig_this) -{ - PyObject *dict; -#if (PY_VERSION_HEX >= 0x02020000) && !defined(SWIG_PYTHON_SLOW_GETSET_THIS) - PyObject **dictptr = _PyObject_GetDictPtr(inst); - if (dictptr != NULL) { - dict = *dictptr; - if (dict == NULL) { - dict = PyDict_New(); - *dictptr = dict; - } - PyDict_SetItem(dict, SWIG_This(), swig_this); - return; - } -#endif - dict = PyObject_GetAttrString(inst, (char*)"__dict__"); - PyDict_SetItem(dict, SWIG_This(), swig_this); - Py_DECREF(dict); -} - - -SWIGINTERN PyObject * -SWIG_Python_InitShadowInstance(PyObject *args) { - PyObject *obj[2]; - if (!SWIG_Python_UnpackTuple(args,(char*)"swiginit", 2, 2, obj)) { - return NULL; - } else { - SwigPyObject *sthis = SWIG_Python_GetSwigThis(obj[0]); - if (sthis) { - SwigPyObject_append((PyObject*) sthis, obj[1]); - } else { - SWIG_Python_SetSwigThis(obj[0], obj[1]); - } - return SWIG_Py_Void(); - } -} - -/* Create a new pointer object */ - -SWIGRUNTIME PyObject * -SWIG_Python_NewPointerObj(void *ptr, swig_type_info *type, int flags) { - if (!ptr) { - return SWIG_Py_Void(); - } else { - int own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0; - PyObject *robj = SwigPyObject_New(ptr, type, own); - SwigPyClientData *clientdata = type ? (SwigPyClientData *)(type->clientdata) : 0; - if (clientdata && !(flags & SWIG_POINTER_NOSHADOW)) { - PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj); - if (inst) { - Py_DECREF(robj); - robj = inst; - } - } - return robj; - } -} - -/* Create a new packed object */ - -SWIGRUNTIMEINLINE PyObject * -SWIG_Python_NewPackedObj(void *ptr, size_t sz, swig_type_info *type) { - return ptr ? SwigPyPacked_New((void *) ptr, sz, type) : SWIG_Py_Void(); -} - -/* -----------------------------------------------------------------------------* - * Get type list - * -----------------------------------------------------------------------------*/ - -#ifdef SWIG_LINK_RUNTIME -void *SWIG_ReturnGlobalTypeList(void *); -#endif - -SWIGRUNTIME swig_module_info * -SWIG_Python_GetModule(void) { - static void *type_pointer = (void *)0; - /* first check if module already created */ - if (!type_pointer) { -#ifdef SWIG_LINK_RUNTIME - type_pointer = SWIG_ReturnGlobalTypeList((void *)0); -#else - type_pointer = PyCObject_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, - (char*)"type_pointer" SWIG_TYPE_TABLE_NAME); - if (PyErr_Occurred()) { - PyErr_Clear(); - type_pointer = (void *)0; - } -#endif - } - return (swig_module_info *) type_pointer; -} - -#if PY_MAJOR_VERSION < 2 -/* PyModule_AddObject function was introduced in Python 2.0. The following function - is copied out of Python/modsupport.c in python version 2.3.4 */ -SWIGINTERN int -PyModule_AddObject(PyObject *m, char *name, PyObject *o) -{ - PyObject *dict; - if (!PyModule_Check(m)) { - PyErr_SetString(PyExc_TypeError, - "PyModule_AddObject() needs module as first arg"); - return SWIG_ERROR; - } - if (!o) { - PyErr_SetString(PyExc_TypeError, - "PyModule_AddObject() needs non-NULL value"); - return SWIG_ERROR; - } - - dict = PyModule_GetDict(m); - if (dict == NULL) { - /* Internal error -- modules must have a dict! */ - PyErr_Format(PyExc_SystemError, "module '%s' has no __dict__", - PyModule_GetName(m)); - return SWIG_ERROR; - } - if (PyDict_SetItemString(dict, name, o)) - return SWIG_ERROR; - Py_DECREF(o); - return SWIG_OK; -} -#endif - -SWIGRUNTIME void -SWIG_Python_DestroyModule(void *vptr) -{ - swig_module_info *swig_module = (swig_module_info *) vptr; - swig_type_info **types = swig_module->types; - size_t i; - for (i =0; i < swig_module->size; ++i) { - swig_type_info *ty = types[i]; - if (ty->owndata) { - SwigPyClientData *data = (SwigPyClientData *) ty->clientdata; - if (data) SwigPyClientData_Del(data); - } - } - Py_DECREF(SWIG_This()); -} - -SWIGRUNTIME void -SWIG_Python_SetModule(swig_module_info *swig_module) { - static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} };/* Sentinel */ - -#if PY_VERSION_HEX >= 0x03000000 - /* Add a dummy module object into sys.modules */ - PyObject *module = PyImport_AddModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION); -#else - PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, - swig_empty_runtime_method_table); -#endif - PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule); - if (pointer && module) { - PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer); - } else { - Py_XDECREF(pointer); - } -} - -/* The python cached type query */ -SWIGRUNTIME PyObject * -SWIG_Python_TypeCache(void) { - static PyObject *SWIG_STATIC_POINTER(cache) = PyDict_New(); - return cache; -} - -SWIGRUNTIME swig_type_info * -SWIG_Python_TypeQuery(const char *type) -{ - PyObject *cache = SWIG_Python_TypeCache(); - PyObject *key = SWIG_Python_str_FromChar(type); - PyObject *obj = PyDict_GetItem(cache, key); - swig_type_info *descriptor; - if (obj) { - descriptor = (swig_type_info *) PyCObject_AsVoidPtr(obj); - } else { - swig_module_info *swig_module = SWIG_Python_GetModule(); - descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type); - if (descriptor) { - obj = PyCObject_FromVoidPtr(descriptor, NULL); - PyDict_SetItem(cache, key, obj); - Py_DECREF(obj); - } - } - Py_DECREF(key); - return descriptor; -} - -/* - For backward compatibility only -*/ -#define SWIG_POINTER_EXCEPTION 0 -#define SWIG_arg_fail(arg) SWIG_Python_ArgFail(arg) -#define SWIG_MustGetPtr(p, type, argnum, flags) SWIG_Python_MustGetPtr(p, type, argnum, flags) - -SWIGRUNTIME int -SWIG_Python_AddErrMesg(const char* mesg, int infront) -{ - if (PyErr_Occurred()) { - PyObject *type = 0; - PyObject *value = 0; - PyObject *traceback = 0; - PyErr_Fetch(&type, &value, &traceback); - if (value) { - char *tmp; - PyObject *old_str = PyObject_Str(value); - Py_XINCREF(type); - PyErr_Clear(); - if (infront) { - PyErr_Format(type, "%s %s", mesg, tmp = SWIG_Python_str_AsChar(old_str)); - } else { - PyErr_Format(type, "%s %s", tmp = SWIG_Python_str_AsChar(old_str), mesg); - } - SWIG_Python_str_DelForPy3(tmp); - Py_DECREF(old_str); - } - return 1; - } else { - return 0; - } -} - -SWIGRUNTIME int -SWIG_Python_ArgFail(int argnum) -{ - if (PyErr_Occurred()) { - /* add information about failing argument */ - char mesg[256]; - PyOS_snprintf(mesg, sizeof(mesg), "argument number %d:", argnum); - return SWIG_Python_AddErrMesg(mesg, 1); - } else { - return 0; - } -} - -SWIGRUNTIMEINLINE const char * -SwigPyObject_GetDesc(PyObject *self) -{ - SwigPyObject *v = (SwigPyObject *)self; - swig_type_info *ty = v ? v->ty : 0; - return ty ? ty->str : (char*)""; -} - -SWIGRUNTIME void -SWIG_Python_TypeError(const char *type, PyObject *obj) -{ - if (type) { -#if defined(SWIG_COBJECT_TYPES) - if (obj && SwigPyObject_Check(obj)) { - const char *otype = (const char *) SwigPyObject_GetDesc(obj); - if (otype) { - PyErr_Format(PyExc_TypeError, "a '%s' is expected, 'SwigPyObject(%s)' is received", - type, otype); - return; - } - } else -#endif - { - const char *otype = (obj ? obj->ob_type->tp_name : 0); - if (otype) { - PyObject *str = PyObject_Str(obj); - const char *cstr = str ? SWIG_Python_str_AsChar(str) : 0; - if (cstr) { - PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s(%s)' is received", - type, otype, cstr); - SWIG_Python_str_DelForPy3(cstr); - } else { - PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s' is received", - type, otype); - } - Py_XDECREF(str); - return; - } - } - PyErr_Format(PyExc_TypeError, "a '%s' is expected", type); - } else { - PyErr_Format(PyExc_TypeError, "unexpected type is received"); - } -} - - -/* Convert a pointer value, signal an exception on a type mismatch */ -SWIGRUNTIME void * -SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags) { - void *result; - if (SWIG_Python_ConvertPtr(obj, &result, ty, flags) == -1) { - PyErr_Clear(); -#if SWIG_POINTER_EXCEPTION - if (flags) { - SWIG_Python_TypeError(SWIG_TypePrettyName(ty), obj); - SWIG_Python_ArgFail(argnum); - } -#endif - } - return result; -} - - -#ifdef __cplusplus -#if 0 -{ /* cc-mode */ -#endif -} -#endif - - - -#define SWIG_exception_fail(code, msg) do { SWIG_Error(code, msg); SWIG_fail; } while(0) - -#define SWIG_contract_assert(expr, msg) if (!(expr)) { SWIG_Error(SWIG_RuntimeError, msg); SWIG_fail; } else - - - -/* -------- TYPES TABLE (BEGIN) -------- */ - -#define SWIGTYPE_p_FILE swig_types[0] -#define SWIGTYPE_p_char swig_types[1] -#define SWIGTYPE_p_f_p_struct_nl_cache_ops_p_struct_sockaddr_nl_p_struct_nlmsghdr_p_struct_nl_parser_param__int swig_types[2] -#define SWIGTYPE_p_f_p_struct_nl_cache_ops_p_void__void swig_types[3] -#define SWIGTYPE_p_f_p_struct_nl_cache_p_struct_nl_object_int_p_void__void swig_types[4] -#define SWIGTYPE_p_f_p_struct_nl_dump_params_int__void swig_types[5] -#define SWIGTYPE_p_f_p_struct_nl_dump_params_p_char__void swig_types[6] -#define SWIGTYPE_p_f_p_struct_nl_object_p_void__void swig_types[7] -#define SWIGTYPE_p_int swig_types[8] -#define SWIGTYPE_p_long_long swig_types[9] -#define SWIGTYPE_p_nl_addr swig_types[10] -#define SWIGTYPE_p_nl_cache swig_types[11] -#define SWIGTYPE_p_nl_cache_mngr swig_types[12] -#define SWIGTYPE_p_nl_cache_ops swig_types[13] -#define SWIGTYPE_p_nl_cb swig_types[14] -#define SWIGTYPE_p_nl_dump_params swig_types[15] -#define SWIGTYPE_p_nl_msg swig_types[16] -#define SWIGTYPE_p_nl_msgtype swig_types[17] -#define SWIGTYPE_p_nl_object swig_types[18] -#define SWIGTYPE_p_nl_object_ops swig_types[19] -#define SWIGTYPE_p_nl_sock swig_types[20] -#define SWIGTYPE_p_nla_policy swig_types[21] -#define SWIGTYPE_p_nlattr swig_types[22] -#define SWIGTYPE_p_nlmsghdr swig_types[23] -#define SWIGTYPE_p_p_addrinfo swig_types[24] -#define SWIGTYPE_p_p_char swig_types[25] -#define SWIGTYPE_p_p_nl_object swig_types[26] -#define SWIGTYPE_p_p_nlattr swig_types[27] -#define SWIGTYPE_p_short swig_types[28] -#define SWIGTYPE_p_signed_char swig_types[29] -#define SWIGTYPE_p_sockaddr swig_types[30] -#define SWIGTYPE_p_sockaddr_nl swig_types[31] -#define SWIGTYPE_p_socklen_t swig_types[32] -#define SWIGTYPE_p_ucred swig_types[33] -#define SWIGTYPE_p_unsigned_char swig_types[34] -#define SWIGTYPE_p_unsigned_int swig_types[35] -#define SWIGTYPE_p_unsigned_long_long swig_types[36] -#define SWIGTYPE_p_unsigned_short swig_types[37] -#define SWIGTYPE_p_void swig_types[38] -static swig_type_info *swig_types[40]; -static swig_module_info swig_module = {swig_types, 39, 0, 0, 0, 0}; -#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name) -#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name) - -/* -------- TYPES TABLE (END) -------- */ - -#if (PY_VERSION_HEX <= 0x02000000) -# if !defined(SWIG_PYTHON_CLASSIC) -# error "This python version requires swig to be run with the '-classic' option" -# endif -#endif -#if (PY_VERSION_HEX <= 0x02020000) -# error "This python version requires swig to be run with the '-nomodern' option" -#endif -#if (PY_VERSION_HEX <= 0x02020000) -# error "This python version requires swig to be run with the '-nomodernargs' option" -#endif -#ifndef METH_O -# error "This python version requires swig to be run with the '-nofastunpack' option" -#endif -#ifdef SWIG_TypeQuery -# undef SWIG_TypeQuery -#endif -#define SWIG_TypeQuery SWIG_Python_TypeQuery - -/*----------------------------------------------- - @(target):= _capi.so - ------------------------------------------------*/ -#if PY_VERSION_HEX >= 0x03000000 -# define SWIG_init PyInit__capi - -#else -# define SWIG_init init_capi - -#endif -#define SWIG_name "_capi" - -#define SWIGVERSION 0x010340 -#define SWIG_VERSION SWIGVERSION - - -#define SWIG_as_voidptr(a) (void *)((const void *)(a)) -#define SWIG_as_voidptrptr(a) ((void)SWIG_as_voidptr(*a),(void**)(a)) - - -#include -#include -#include -#include -#include -#include - - -#include // Use the C99 official header - - - struct nl_dump_params *alloc_dump_params(void) - { - struct nl_dump_params *dp; - if (!(dp = calloc(1, sizeof(*dp)))) - return NULL; - dp->dp_fd = stdout; - return dp; - } - - void free_dump_params(struct nl_dump_params *dp) - { - free(dp); - } - - - #define SWIG_From_long PyInt_FromLong - - -SWIGINTERNINLINE PyObject * -SWIG_From_int (int value) -{ - return SWIG_From_long (value); -} - - -#include -#if !defined(SWIG_NO_LLONG_MAX) -# if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__) -# define LLONG_MAX __LONG_LONG_MAX__ -# define LLONG_MIN (-LLONG_MAX - 1LL) -# define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL) -# endif -#endif - - -SWIGINTERN int -SWIG_AsVal_double (PyObject *obj, double *val) -{ - int res = SWIG_TypeError; - if (PyFloat_Check(obj)) { - if (val) *val = PyFloat_AsDouble(obj); - return SWIG_OK; - } else if (PyInt_Check(obj)) { - if (val) *val = PyInt_AsLong(obj); - return SWIG_OK; - } else if (PyLong_Check(obj)) { - double v = PyLong_AsDouble(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_OK; - } else { - PyErr_Clear(); - } - } -#ifdef SWIG_PYTHON_CAST_MODE - { - int dispatch = 0; - double d = PyFloat_AsDouble(obj); - if (!PyErr_Occurred()) { - if (val) *val = d; - return SWIG_AddCast(SWIG_OK); - } else { - PyErr_Clear(); - } - if (!dispatch) { - long v = PyLong_AsLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_AddCast(SWIG_AddCast(SWIG_OK)); - } else { - PyErr_Clear(); - } - } - } -#endif - return res; -} - - -#include - - -#include - - -SWIGINTERNINLINE int -SWIG_CanCastAsInteger(double *d, double min, double max) { - double x = *d; - if ((min <= x && x <= max)) { - double fx = floor(x); - double cx = ceil(x); - double rd = ((x - fx) < 0.5) ? fx : cx; /* simple rint */ - if ((errno == EDOM) || (errno == ERANGE)) { - errno = 0; - } else { - double summ, reps, diff; - if (rd < x) { - diff = x - rd; - } else if (rd > x) { - diff = rd - x; - } else { - return 1; - } - summ = rd + x; - reps = diff/summ; - if (reps < 8*DBL_EPSILON) { - *d = rd; - return 1; - } - } - } - return 0; -} - - -SWIGINTERN int -SWIG_AsVal_long (PyObject *obj, long* val) -{ - if (PyInt_Check(obj)) { - if (val) *val = PyInt_AsLong(obj); - return SWIG_OK; - } else if (PyLong_Check(obj)) { - long v = PyLong_AsLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_OK; - } else { - PyErr_Clear(); - } - } -#ifdef SWIG_PYTHON_CAST_MODE - { - int dispatch = 0; - long v = PyInt_AsLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_AddCast(SWIG_OK); - } else { - PyErr_Clear(); - } - if (!dispatch) { - double d; - int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d)); - if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) { - if (val) *val = (long)(d); - return res; - } - } - } -#endif - return SWIG_TypeError; -} - - -SWIGINTERN int -SWIG_AsVal_int (PyObject * obj, int *val) -{ - long v; - int res = SWIG_AsVal_long (obj, &v); - if (SWIG_IsOK(res)) { - if ((v < INT_MIN || v > INT_MAX)) { - return SWIG_OverflowError; - } else { - if (val) *val = (int)(v); - } - } - return res; -} - - -SWIGINTERN swig_type_info* -SWIG_pchar_descriptor(void) -{ - static int init = 0; - static swig_type_info* info = 0; - if (!init) { - info = SWIG_TypeQuery("_p_char"); - init = 1; - } - return info; -} - - -SWIGINTERN int -SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc) -{ -#if PY_VERSION_HEX>=0x03000000 - if (PyUnicode_Check(obj)) -#else - if (PyString_Check(obj)) -#endif - { - char *cstr; Py_ssize_t len; -#if PY_VERSION_HEX>=0x03000000 - if (!alloc && cptr) { - /* We can't allow converting without allocation, since the internal - representation of string in Python 3 is UCS-2/UCS-4 but we require - a UTF-8 representation. - TODO(bhy) More detailed explanation */ - return SWIG_RuntimeError; - } - obj = PyUnicode_AsUTF8String(obj); - PyBytes_AsStringAndSize(obj, &cstr, &len); - if(alloc) *alloc = SWIG_NEWOBJ; -#else - PyString_AsStringAndSize(obj, &cstr, &len); -#endif - if (cptr) { - if (alloc) { - /* - In python the user should not be able to modify the inner - string representation. To warranty that, if you define - SWIG_PYTHON_SAFE_CSTRINGS, a new/copy of the python string - buffer is always returned. - - The default behavior is just to return the pointer value, - so, be careful. - */ -#if defined(SWIG_PYTHON_SAFE_CSTRINGS) - if (*alloc != SWIG_OLDOBJ) -#else - if (*alloc == SWIG_NEWOBJ) -#endif - { - *cptr = (char *)memcpy((char *)malloc((len + 1)*sizeof(char)), cstr, sizeof(char)*(len + 1)); - *alloc = SWIG_NEWOBJ; - } - else { - *cptr = cstr; - *alloc = SWIG_OLDOBJ; - } - } else { - #if PY_VERSION_HEX>=0x03000000 - assert(0); /* Should never reach here in Python 3 */ - #endif - *cptr = SWIG_Python_str_AsChar(obj); - } - } - if (psize) *psize = len + 1; -#if PY_VERSION_HEX>=0x03000000 - Py_XDECREF(obj); -#endif - return SWIG_OK; - } else { - swig_type_info* pchar_descriptor = SWIG_pchar_descriptor(); - if (pchar_descriptor) { - void* vptr = 0; - if (SWIG_ConvertPtr(obj, &vptr, pchar_descriptor, 0) == SWIG_OK) { - if (cptr) *cptr = (char *) vptr; - if (psize) *psize = vptr ? (strlen((char *)vptr) + 1) : 0; - if (alloc) *alloc = SWIG_OLDOBJ; - return SWIG_OK; - } - } - } - return SWIG_TypeError; -} - - - - - -SWIGINTERNINLINE PyObject * -SWIG_FromCharPtrAndSize(const char* carray, size_t size) -{ - if (carray) { - if (size > INT_MAX) { - swig_type_info* pchar_descriptor = SWIG_pchar_descriptor(); - return pchar_descriptor ? - SWIG_NewPointerObj((char *)(carray), pchar_descriptor, 0) : SWIG_Py_Void(); - } else { -#if PY_VERSION_HEX >= 0x03000000 - return PyUnicode_FromStringAndSize(carray, (int)(size)); -#else - return PyString_FromStringAndSize(carray, (int)(size)); -#endif - } - } else { - return SWIG_Py_Void(); - } -} - - -SWIGINTERNINLINE PyObject * -SWIG_FromCharPtr(const char *cptr) -{ - return SWIG_FromCharPtrAndSize(cptr, (cptr ? strlen(cptr) : 0)); -} - - -SWIGINTERN int -SWIG_AsVal_unsigned_SS_long (PyObject *obj, unsigned long *val) -{ - if (PyInt_Check(obj)) { - long v = PyInt_AsLong(obj); - if (v >= 0) { - if (val) *val = v; - return SWIG_OK; - } else { - return SWIG_OverflowError; - } - } else if (PyLong_Check(obj)) { - unsigned long v = PyLong_AsUnsignedLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_OK; - } else { - PyErr_Clear(); - } - } -#ifdef SWIG_PYTHON_CAST_MODE - { - int dispatch = 0; - unsigned long v = PyLong_AsUnsignedLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_AddCast(SWIG_OK); - } else { - PyErr_Clear(); - } - if (!dispatch) { - double d; - int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d)); - if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ULONG_MAX)) { - if (val) *val = (unsigned long)(d); - return res; - } - } - } -#endif - return SWIG_TypeError; -} - - -SWIGINTERNINLINE int -SWIG_AsVal_size_t (PyObject * obj, size_t *val) -{ - unsigned long v; - int res = SWIG_AsVal_unsigned_SS_long (obj, val ? &v : 0); - if (SWIG_IsOK(res) && val) *val = (size_t)(v); - return res; -} - - -SWIGINTERNINLINE PyObject* -SWIG_From_unsigned_SS_long (unsigned long value) -{ - return (value > LONG_MAX) ? - PyLong_FromUnsignedLong(value) : PyInt_FromLong((long)(value)); -} - - -SWIGINTERNINLINE PyObject * -SWIG_From_size_t (size_t value) -{ - return SWIG_From_unsigned_SS_long ((unsigned long)(value)); -} - - -SWIGINTERN int -SWIG_AsVal_unsigned_SS_int (PyObject * obj, unsigned int *val) -{ - unsigned long v; - int res = SWIG_AsVal_unsigned_SS_long (obj, &v); - if (SWIG_IsOK(res)) { - if ((v > UINT_MAX)) { - return SWIG_OverflowError; - } else { - if (val) *val = (unsigned int)(v); - } - } - return res; -} - - -SWIGINTERNINLINE PyObject * -SWIG_From_unsigned_SS_int (unsigned int value) -{ - return SWIG_From_unsigned_SS_long (value); -} - - -SWIGINTERN int -SWIG_AsVal_unsigned_SS_long_SS_long (PyObject *obj, unsigned long long *val) -{ - int res = SWIG_TypeError; - if (PyLong_Check(obj)) { - unsigned long long v = PyLong_AsUnsignedLongLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_OK; - } else { - PyErr_Clear(); - } - } else { - unsigned long v; - res = SWIG_AsVal_unsigned_SS_long (obj,&v); - if (SWIG_IsOK(res)) { - if (val) *val = v; - return res; - } - } -#ifdef SWIG_PYTHON_CAST_MODE - { - const double mant_max = 1LL << DBL_MANT_DIG; - double d; - res = SWIG_AsVal_double (obj,&d); - if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, mant_max)) { - if (val) *val = (unsigned long long)(d); - return SWIG_AddCast(res); - } - res = SWIG_TypeError; - } -#endif - return res; -} - - - #define SWIG_From_double PyFloat_FromDouble - - - struct nl_object *cast_obj(void *obj) - { - return (struct nl_object *) obj; - } - - struct nl_object *object_alloc_name(const char *name) - { - struct nl_object *obj; - - if (nl_object_alloc_name(name, &obj) < 0) - return NULL; - - return obj; - } - - - struct nl_cache *alloc_cache_name(const char *name) - { - struct nl_cache *c; - if (nl_cache_alloc_name(name, &c) < 0) - return NULL; - return c; - } - - struct nl_cache_mngr *alloc_cache_mngr(struct nl_sock *sock, - int protocol, int flags) - { - struct nl_cache_mngr *mngr; - - if (nl_cache_mngr_alloc(sock, protocol, flags, &mngr) < 0) - return NULL; - - return mngr; - } - - struct nl_cache *cache_mngr_add(struct nl_cache_mngr *mngr, - const char *name, change_func_t func, - void *arg) - { - struct nl_cache *cache; - - if (nl_cache_mngr_add(mngr, name, func, arg, &cache) < 0) - return NULL; - - return cache; - } - - - struct nl_addr *addr_parse(const char *addr, int guess) - { - struct nl_addr *result; - - if (nl_addr_parse(addr, guess, &result) < 0) - return NULL; - - return result; - } - -#ifdef __cplusplus -extern "C" { -#endif -SWIGINTERN PyObject *_wrap_alloc_dump_params(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"alloc_dump_params",0,0,0)) SWIG_fail; - result = (struct nl_dump_params *)alloc_dump_params(); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_dump_params, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_free_dump_params(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "free_dump_params" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - free_dump_params(arg1); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_params_dp_type_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - enum nl_dump_type arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_dump_params_dp_type_set",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_type_set" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_dump_params_dp_type_set" "', argument " "2"" of type '" "enum nl_dump_type""'"); - } - arg2 = (enum nl_dump_type)(val2); - if (arg1) (arg1)->dp_type = arg2; - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_params_dp_type_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - enum nl_dump_type result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_type_get" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - result = (enum nl_dump_type) ((arg1)->dp_type); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_params_dp_prefix_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_dump_params_dp_prefix_set",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_prefix_set" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_dump_params_dp_prefix_set" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - if (arg1) (arg1)->dp_prefix = arg2; - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_params_dp_prefix_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_prefix_get" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - result = (int) ((arg1)->dp_prefix); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_params_dp_print_index_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_dump_params_dp_print_index_set",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_print_index_set" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_dump_params_dp_print_index_set" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - if (arg1) (arg1)->dp_print_index = arg2; - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_params_dp_print_index_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_print_index_get" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - result = (int) ((arg1)->dp_print_index); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_params_dp_dump_msgtype_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_dump_params_dp_dump_msgtype_set",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_dump_msgtype_set" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_dump_params_dp_dump_msgtype_set" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - if (arg1) (arg1)->dp_dump_msgtype = arg2; - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_params_dp_dump_msgtype_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_dump_msgtype_get" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - result = (int) ((arg1)->dp_dump_msgtype); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_params_dp_cb_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - void (*arg2)(struct nl_dump_params *,char *) = (void (*)(struct nl_dump_params *,char *)) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_dump_params_dp_cb_set",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_cb_set" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - { - int res = SWIG_ConvertFunctionPtr(swig_obj[1], (void**)(&arg2), SWIGTYPE_p_f_p_struct_nl_dump_params_p_char__void); - if (!SWIG_IsOK(res)) { - SWIG_exception_fail(SWIG_ArgError(res), "in method '" "nl_dump_params_dp_cb_set" "', argument " "2"" of type '" "void (*)(struct nl_dump_params *,char *)""'"); - } - } - if (arg1) (arg1)->dp_cb = arg2; - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_params_dp_cb_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - void (*result)(struct nl_dump_params *,char *) = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_cb_get" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - result = (void (*)(struct nl_dump_params *,char *)) ((arg1)->dp_cb); - resultobj = SWIG_NewFunctionPtrObj((void *)(result), SWIGTYPE_p_f_p_struct_nl_dump_params_p_char__void); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_params_dp_nl_cb_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - void (*arg2)(struct nl_dump_params *,int) = (void (*)(struct nl_dump_params *,int)) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_dump_params_dp_nl_cb_set",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_nl_cb_set" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - { - int res = SWIG_ConvertFunctionPtr(swig_obj[1], (void**)(&arg2), SWIGTYPE_p_f_p_struct_nl_dump_params_int__void); - if (!SWIG_IsOK(res)) { - SWIG_exception_fail(SWIG_ArgError(res), "in method '" "nl_dump_params_dp_nl_cb_set" "', argument " "2"" of type '" "void (*)(struct nl_dump_params *,int)""'"); - } - } - if (arg1) (arg1)->dp_nl_cb = arg2; - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_params_dp_nl_cb_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - void (*result)(struct nl_dump_params *,int) = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_nl_cb_get" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - result = (void (*)(struct nl_dump_params *,int)) ((arg1)->dp_nl_cb); - resultobj = SWIG_NewFunctionPtrObj((void *)(result), SWIGTYPE_p_f_p_struct_nl_dump_params_int__void); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_params_dp_data_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - void *arg2 = (void *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - int res2 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_dump_params_dp_data_set",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_data_set" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1],SWIG_as_voidptrptr(&arg2), 0, SWIG_POINTER_DISOWN); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_dump_params_dp_data_set" "', argument " "2"" of type '" "void *""'"); - } - if (arg1) (arg1)->dp_data = arg2; - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_params_dp_data_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - void *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_data_get" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - result = (void *) ((arg1)->dp_data); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_void, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_params_dp_fd_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - FILE *arg2 = (FILE *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_dump_params_dp_fd_set",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_fd_set" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_FILE, SWIG_POINTER_DISOWN | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_dump_params_dp_fd_set" "', argument " "2"" of type '" "FILE *""'"); - } - arg2 = (FILE *)(argp2); - if (arg1) (arg1)->dp_fd = arg2; - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_params_dp_fd_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - FILE *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_fd_get" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - result = (FILE *) ((arg1)->dp_fd); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_FILE, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_params_dp_buf_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - char *arg2 = (char *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_dump_params_dp_buf_set",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_buf_set" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_dump_params_dp_buf_set" "', argument " "2"" of type '" "char *""'"); - } - arg2 = (char *)(buf2); - if (arg1->dp_buf) free((char*)arg1->dp_buf); - if (arg2) { - size_t size = strlen((const char *)(arg2)) + 1; - arg1->dp_buf = (char *)(char *)memcpy((char *)malloc((size)*sizeof(char)), (const char *)(arg2), sizeof(char)*(size)); - } else { - arg1->dp_buf = 0; - } - resultobj = SWIG_Py_Void(); - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return resultobj; -fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_params_dp_buf_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - char *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_buf_get" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - result = (char *) ((arg1)->dp_buf); - resultobj = SWIG_FromCharPtr((const char *)result); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_params_dp_buflen_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - size_t arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - size_t val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_dump_params_dp_buflen_set",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_buflen_set" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - ecode2 = SWIG_AsVal_size_t(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_dump_params_dp_buflen_set" "', argument " "2"" of type '" "size_t""'"); - } - arg2 = (size_t)(val2); - if (arg1) (arg1)->dp_buflen = arg2; - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_params_dp_buflen_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - size_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_buflen_get" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - result = ((arg1)->dp_buflen); - resultobj = SWIG_From_size_t((size_t)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_params_dp_pre_dump_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_dump_params_dp_pre_dump_set",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_pre_dump_set" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_dump_params_dp_pre_dump_set" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - if (arg1) (arg1)->dp_pre_dump = arg2; - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_params_dp_pre_dump_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_pre_dump_get" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - result = (int) ((arg1)->dp_pre_dump); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_params_dp_ivar_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_dump_params_dp_ivar_set",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_ivar_set" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_dump_params_dp_ivar_set" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - if (arg1) (arg1)->dp_ivar = arg2; - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_params_dp_ivar_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_ivar_get" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - result = (int) ((arg1)->dp_ivar); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_params_dp_line_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - unsigned int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_dump_params_dp_line_set",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_line_set" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_dump_params_dp_line_set" "', argument " "2"" of type '" "unsigned int""'"); - } - arg2 = (unsigned int)(val2); - if (arg1) (arg1)->dp_line = arg2; - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_params_dp_line_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - unsigned int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_params_dp_line_get" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - result = (unsigned int) ((arg1)->dp_line); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_delete_nl_dump_params(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, SWIG_POINTER_DISOWN | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_nl_dump_params" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - free((char *) arg1); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *nl_dump_params_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *obj; - if (!SWIG_Python_UnpackTuple(args,(char*)"swigregister", 1, 1,&obj)) return NULL; - SWIG_TypeNewClientData(SWIGTYPE_p_nl_dump_params, SWIG_NewClientData(obj)); - return SWIG_Py_Void(); -} - -SWIGINTERN PyObject *_wrap_nl_geterror(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - int val1 ; - int ecode1 = 0 ; - PyObject *swig_obj[1] ; - char *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_geterror" "', argument " "1"" of type '" "int""'"); - } - arg1 = (int)(val1); - result = (char *)nl_geterror(arg1); - resultobj = SWIG_FromCharPtr((const char *)result); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cancel_down_bytes(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - unsigned long long arg1 ; - char **arg2 = (char **) 0 ; - unsigned long long val1 ; - int ecode1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - double result; - - if (!SWIG_Python_UnpackTuple(args,"nl_cancel_down_bytes",2,2,swig_obj)) SWIG_fail; - ecode1 = SWIG_AsVal_unsigned_SS_long_SS_long(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_cancel_down_bytes" "', argument " "1"" of type '" "unsigned long long""'"); - } - arg1 = (unsigned long long)(val1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_p_char, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cancel_down_bytes" "', argument " "2"" of type '" "char **""'"); - } - arg2 = (char **)(argp2); - result = (double)nl_cancel_down_bytes(arg1,arg2); - resultobj = SWIG_From_double((double)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cancel_down_bits(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - unsigned long long arg1 ; - char **arg2 = (char **) 0 ; - unsigned long long val1 ; - int ecode1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - double result; - - if (!SWIG_Python_UnpackTuple(args,"nl_cancel_down_bits",2,2,swig_obj)) SWIG_fail; - ecode1 = SWIG_AsVal_unsigned_SS_long_SS_long(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_cancel_down_bits" "', argument " "1"" of type '" "unsigned long long""'"); - } - arg1 = (unsigned long long)(val1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_p_char, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cancel_down_bits" "', argument " "2"" of type '" "char **""'"); - } - arg2 = (char **)(argp2); - result = (double)nl_cancel_down_bits(arg1,arg2); - resultobj = SWIG_From_double((double)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_rate2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - unsigned long long arg1 ; - int arg2 ; - char *arg3 = (char *) 0 ; - size_t arg4 ; - unsigned long long val1 ; - int ecode1 = 0 ; - int val2 ; - int ecode2 = 0 ; - int res3 ; - size_t size3 ; - char *buff3 = 0 ; - PyObject *swig_obj[3] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nl_rate2str",3,3,swig_obj)) SWIG_fail; - ecode1 = SWIG_AsVal_unsigned_SS_long_SS_long(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_rate2str" "', argument " "1"" of type '" "unsigned long long""'"); - } - arg1 = (unsigned long long)(val1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_rate2str" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - res3 = SWIG_AsVal_size_t (swig_obj[2], &size3); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "nl_rate2str" "', argument " "3"" of type '" "(char *buf, size_t len)""'"); - } - buff3= (char *)malloc((size3+1)*sizeof(char)); - arg4 = (size_t)(size3); - arg3 = (char *)(buff3); - result = (int)nl_rate2str(arg1,arg2,arg3,arg4); - resultobj = SWIG_From_int((int)(result)); - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg3)); - if (buff3) free((char*)buff3); - return resultobj; -fail: - if (buff3) free((char*)buff3); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cancel_down_us(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint32_t arg1 ; - char **arg2 = (char **) 0 ; - unsigned int val1 ; - int ecode1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - double result; - - if (!SWIG_Python_UnpackTuple(args,"nl_cancel_down_us",2,2,swig_obj)) SWIG_fail; - ecode1 = SWIG_AsVal_unsigned_SS_int(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_cancel_down_us" "', argument " "1"" of type '" "uint32_t""'"); - } - arg1 = (uint32_t)(val1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_p_char, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cancel_down_us" "', argument " "2"" of type '" "char **""'"); - } - arg2 = (char **)(argp2); - result = (double)nl_cancel_down_us(arg1,arg2); - resultobj = SWIG_From_double((double)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_size2int(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - PyObject *swig_obj[1] ; - long result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_size2int" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = (char *)(buf1); - result = (long)nl_size2int((char const *)arg1); - resultobj = SWIG_From_long((long)(result)); - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_size2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - size_t arg1 ; - char *arg2 = (char *) 0 ; - size_t arg3 ; - size_t val1 ; - int ecode1 = 0 ; - int res2 ; - size_t size2 ; - char *buff2 = 0 ; - PyObject *swig_obj[2] ; - char *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"nl_size2str",2,2,swig_obj)) SWIG_fail; - ecode1 = SWIG_AsVal_size_t(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_size2str" "', argument " "1"" of type '" "size_t""'"); - } - arg1 = (size_t)(val1); - res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_size2str" "', argument " "2"" of type '" "(char *buf, const size_t len)""'"); - } - buff2= (char *)malloc((size2+1)*sizeof(char)); - arg3 = (size_t)(size2); - arg2 = (char *)(buff2); - result = (char *)nl_size2str(arg1,arg2,arg3); - resultobj = SWIG_FromCharPtr((const char *)result); - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); - if (buff2) free((char*)buff2); - return resultobj; -fail: - if (buff2) free((char*)buff2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_prob2int(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - PyObject *swig_obj[1] ; - long result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_prob2int" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = (char *)(buf1); - result = (long)nl_prob2int((char const *)arg1); - resultobj = SWIG_From_long((long)(result)); - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_get_user_hz(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nl_get_user_hz",0,0,0)) SWIG_fail; - result = (int)nl_get_user_hz(); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_us2ticks(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint32_t arg1 ; - unsigned int val1 ; - int ecode1 = 0 ; - PyObject *swig_obj[1] ; - uint32_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - ecode1 = SWIG_AsVal_unsigned_SS_int(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_us2ticks" "', argument " "1"" of type '" "uint32_t""'"); - } - arg1 = (uint32_t)(val1); - result = (uint32_t)nl_us2ticks(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_ticks2us(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint32_t arg1 ; - unsigned int val1 ; - int ecode1 = 0 ; - PyObject *swig_obj[1] ; - uint32_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - ecode1 = SWIG_AsVal_unsigned_SS_int(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_ticks2us" "', argument " "1"" of type '" "uint32_t""'"); - } - arg1 = (uint32_t)(val1); - result = (uint32_t)nl_ticks2us(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_str2msec(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - uint64_t *arg2 = (uint64_t *) 0 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nl_str2msec",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_str2msec" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = (char *)(buf1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_unsigned_long_long, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_str2msec" "', argument " "2"" of type '" "uint64_t *""'"); - } - arg2 = (uint64_t *)(argp2); - result = (int)nl_str2msec((char const *)arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_msec2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint64_t arg1 ; - char *arg2 = (char *) 0 ; - size_t arg3 ; - unsigned long long val1 ; - int ecode1 = 0 ; - int res2 ; - size_t size2 ; - char *buff2 = 0 ; - PyObject *swig_obj[2] ; - char *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"nl_msec2str",2,2,swig_obj)) SWIG_fail; - ecode1 = SWIG_AsVal_unsigned_SS_long_SS_long(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_msec2str" "', argument " "1"" of type '" "uint64_t""'"); - } - arg1 = (uint64_t)(val1); - res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_msec2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); - } - buff2= (char *)malloc((size2+1)*sizeof(char)); - arg3 = (size_t)(size2); - arg2 = (char *)(buff2); - result = (char *)nl_msec2str(arg1,arg2,arg3); - resultobj = SWIG_FromCharPtr((const char *)result); - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); - if (buff2) free((char*)buff2); - return resultobj; -fail: - if (buff2) free((char*)buff2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_llproto2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - char *arg2 = (char *) 0 ; - size_t arg3 ; - int val1 ; - int ecode1 = 0 ; - int res2 ; - size_t size2 ; - char *buff2 = 0 ; - PyObject *swig_obj[2] ; - char *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"nl_llproto2str",2,2,swig_obj)) SWIG_fail; - ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_llproto2str" "', argument " "1"" of type '" "int""'"); - } - arg1 = (int)(val1); - res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_llproto2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); - } - buff2= (char *)malloc((size2+1)*sizeof(char)); - arg3 = (size_t)(size2); - arg2 = (char *)(buff2); - result = (char *)nl_llproto2str(arg1,arg2,arg3); - resultobj = SWIG_FromCharPtr((const char *)result); - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); - if (buff2) free((char*)buff2); - return resultobj; -fail: - if (buff2) free((char*)buff2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_str2llproto(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_str2llproto" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = (char *)(buf1); - result = (int)nl_str2llproto((char const *)arg1); - resultobj = SWIG_From_int((int)(result)); - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_ether_proto2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - char *arg2 = (char *) 0 ; - size_t arg3 ; - int val1 ; - int ecode1 = 0 ; - int res2 ; - size_t size2 ; - char *buff2 = 0 ; - PyObject *swig_obj[2] ; - char *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"nl_ether_proto2str",2,2,swig_obj)) SWIG_fail; - ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_ether_proto2str" "', argument " "1"" of type '" "int""'"); - } - arg1 = (int)(val1); - res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_ether_proto2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); - } - buff2= (char *)malloc((size2+1)*sizeof(char)); - arg3 = (size_t)(size2); - arg2 = (char *)(buff2); - result = (char *)nl_ether_proto2str(arg1,arg2,arg3); - resultobj = SWIG_FromCharPtr((const char *)result); - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); - if (buff2) free((char*)buff2); - return resultobj; -fail: - if (buff2) free((char*)buff2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_str2ether_proto(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_str2ether_proto" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = (char *)(buf1); - result = (int)nl_str2ether_proto((char const *)arg1); - resultobj = SWIG_From_int((int)(result)); - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_ip_proto2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - char *arg2 = (char *) 0 ; - size_t arg3 ; - int val1 ; - int ecode1 = 0 ; - int res2 ; - size_t size2 ; - char *buff2 = 0 ; - PyObject *swig_obj[2] ; - char *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"nl_ip_proto2str",2,2,swig_obj)) SWIG_fail; - ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_ip_proto2str" "', argument " "1"" of type '" "int""'"); - } - arg1 = (int)(val1); - res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_ip_proto2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); - } - buff2= (char *)malloc((size2+1)*sizeof(char)); - arg3 = (size_t)(size2); - arg2 = (char *)(buff2); - result = (char *)nl_ip_proto2str(arg1,arg2,arg3); - resultobj = SWIG_FromCharPtr((const char *)result); - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); - if (buff2) free((char*)buff2); - return resultobj; -fail: - if (buff2) free((char*)buff2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_str2ip_proto(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_str2ip_proto" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = (char *)(buf1); - result = (int)nl_str2ip_proto((char const *)arg1); - resultobj = SWIG_From_int((int)(result)); - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_new_line(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_new_line" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - nl_new_line(arg1); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump__varargs__(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *varargs) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - char *arg2 = (char *) 0 ; - void *arg3 = 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - - if(!PyArg_UnpackTuple(args,(char *)"nl_dump",2,2,&obj0,&obj1)) SWIG_fail; - res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_dump" "', argument " "2"" of type '" "char const *""'"); - } - arg2 = (char *)(buf2); - nl_dump(arg1,(char const *)arg2,arg3); - resultobj = SWIG_Py_Void(); - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return resultobj; -fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump(PyObject *self, PyObject *args) { - PyObject *resultobj; - PyObject *varargs; - PyObject *newargs; - - newargs = PyTuple_GetSlice(args,0,2); - varargs = PyTuple_GetSlice(args,2,PyTuple_Size(args)+1); - resultobj = _wrap_nl_dump__varargs__(self,newargs,varargs); - Py_XDECREF(newargs); - Py_XDECREF(varargs); - return resultobj; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_line__varargs__(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *varargs) { - PyObject *resultobj = 0; - struct nl_dump_params *arg1 = (struct nl_dump_params *) 0 ; - char *arg2 = (char *) 0 ; - void *arg3 = 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - - if(!PyArg_UnpackTuple(args,(char *)"nl_dump_line",2,2,&obj0,&obj1)) SWIG_fail; - res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_dump_line" "', argument " "1"" of type '" "struct nl_dump_params *""'"); - } - arg1 = (struct nl_dump_params *)(argp1); - res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_dump_line" "', argument " "2"" of type '" "char const *""'"); - } - arg2 = (char *)(buf2); - nl_dump_line(arg1,(char const *)arg2,arg3); - resultobj = SWIG_Py_Void(); - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return resultobj; -fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_dump_line(PyObject *self, PyObject *args) { - PyObject *resultobj; - PyObject *varargs; - PyObject *newargs; - - newargs = PyTuple_GetSlice(args,0,2); - varargs = PyTuple_GetSlice(args,2,PyTuple_Size(args)+1); - resultobj = _wrap_nl_dump_line__varargs__(self,newargs,varargs); - Py_XDECREF(newargs); - Py_XDECREF(varargs); - return resultobj; -} - - -SWIGINTERN PyObject *_wrap_nl_connect(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_sock *arg1 = (struct nl_sock *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nl_connect",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_connect" "', argument " "1"" of type '" "struct nl_sock *""'"); - } - arg1 = (struct nl_sock *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_connect" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - result = (int)nl_connect(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_close(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_sock *arg1 = (struct nl_sock *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_close" "', argument " "1"" of type '" "struct nl_sock *""'"); - } - arg1 = (struct nl_sock *)(argp1); - nl_close(arg1); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_pickup(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_sock *arg1 = (struct nl_sock *) 0 ; - int (*arg2)(struct nl_cache_ops *,struct sockaddr_nl *,struct nlmsghdr *,struct nl_parser_param *) = (int (*)(struct nl_cache_ops *,struct sockaddr_nl *,struct nlmsghdr *,struct nl_parser_param *)) 0 ; - struct nl_object **arg3 = (struct nl_object **) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp3 = 0 ; - int res3 = 0 ; - PyObject *swig_obj[3] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nl_pickup",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_pickup" "', argument " "1"" of type '" "struct nl_sock *""'"); - } - arg1 = (struct nl_sock *)(argp1); - { - int res = SWIG_ConvertFunctionPtr(swig_obj[1], (void**)(&arg2), SWIGTYPE_p_f_p_struct_nl_cache_ops_p_struct_sockaddr_nl_p_struct_nlmsghdr_p_struct_nl_parser_param__int); - if (!SWIG_IsOK(res)) { - SWIG_exception_fail(SWIG_ArgError(res), "in method '" "nl_pickup" "', argument " "2"" of type '" "int (*)(struct nl_cache_ops *,struct sockaddr_nl *,struct nlmsghdr *,struct nl_parser_param *)""'"); - } - } - res3 = SWIG_ConvertPtr(swig_obj[2], &argp3,SWIGTYPE_p_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "nl_pickup" "', argument " "3"" of type '" "struct nl_object **""'"); - } - arg3 = (struct nl_object **)(argp3); - result = (int)nl_pickup(arg1,arg2,arg3); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_socket_alloc(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_sock *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"nl_socket_alloc",0,0,0)) SWIG_fail; - result = (struct nl_sock *)nl_socket_alloc(); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_sock, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_socket_alloc_cb(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cb *arg1 = (struct nl_cb *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_sock *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cb, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_socket_alloc_cb" "', argument " "1"" of type '" "struct nl_cb *""'"); - } - arg1 = (struct nl_cb *)(argp1); - result = (struct nl_sock *)nl_socket_alloc_cb(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_sock, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_socket_free(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_sock *arg1 = (struct nl_sock *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_socket_free" "', argument " "1"" of type '" "struct nl_sock *""'"); - } - arg1 = (struct nl_sock *)(argp1); - nl_socket_free(arg1); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_socket_get_local_port(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_sock *arg1 = (struct nl_sock *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint32_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_socket_get_local_port" "', argument " "1"" of type '" "struct nl_sock const *""'"); - } - arg1 = (struct nl_sock *)(argp1); - result = (uint32_t)nl_socket_get_local_port((struct nl_sock const *)arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_socket_set_local_port(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_sock *arg1 = (struct nl_sock *) 0 ; - uint32_t arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_socket_set_local_port",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_socket_set_local_port" "', argument " "1"" of type '" "struct nl_sock *""'"); - } - arg1 = (struct nl_sock *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_socket_set_local_port" "', argument " "2"" of type '" "uint32_t""'"); - } - arg2 = (uint32_t)(val2); - nl_socket_set_local_port(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_socket_get_peer_port(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_sock *arg1 = (struct nl_sock *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint32_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_socket_get_peer_port" "', argument " "1"" of type '" "struct nl_sock const *""'"); - } - arg1 = (struct nl_sock *)(argp1); - result = (uint32_t)nl_socket_get_peer_port((struct nl_sock const *)arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_socket_set_peer_port(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_sock *arg1 = (struct nl_sock *) 0 ; - uint32_t arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_socket_set_peer_port",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_socket_set_peer_port" "', argument " "1"" of type '" "struct nl_sock *""'"); - } - arg1 = (struct nl_sock *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_socket_set_peer_port" "', argument " "2"" of type '" "uint32_t""'"); - } - arg2 = (uint32_t)(val2); - nl_socket_set_peer_port(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_socket_get_peer_groups(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_sock *arg1 = (struct nl_sock *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint32_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_socket_get_peer_groups" "', argument " "1"" of type '" "struct nl_sock const *""'"); - } - arg1 = (struct nl_sock *)(argp1); - result = (uint32_t)nl_socket_get_peer_groups((struct nl_sock const *)arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_socket_set_peer_groups(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_sock *arg1 = (struct nl_sock *) 0 ; - uint32_t arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_socket_set_peer_groups",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_socket_set_peer_groups" "', argument " "1"" of type '" "struct nl_sock *""'"); - } - arg1 = (struct nl_sock *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_socket_set_peer_groups" "', argument " "2"" of type '" "uint32_t""'"); - } - arg2 = (uint32_t)(val2); - nl_socket_set_peer_groups(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_socket_set_buffer_size(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_sock *arg1 = (struct nl_sock *) 0 ; - int arg2 ; - int arg3 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - int val3 ; - int ecode3 = 0 ; - PyObject *swig_obj[3] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nl_socket_set_buffer_size",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_socket_set_buffer_size" "', argument " "1"" of type '" "struct nl_sock *""'"); - } - arg1 = (struct nl_sock *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_socket_set_buffer_size" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "nl_socket_set_buffer_size" "', argument " "3"" of type '" "int""'"); - } - arg3 = (int)(val3); - result = (int)nl_socket_set_buffer_size(arg1,arg2,arg3); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_size(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - int val1 ; - int ecode1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nlmsg_size" "', argument " "1"" of type '" "int""'"); - } - arg1 = (int)(val1); - result = (int)nlmsg_size(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_total_size(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - int val1 ; - int ecode1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nlmsg_total_size" "', argument " "1"" of type '" "int""'"); - } - arg1 = (int)(val1); - result = (int)nlmsg_total_size(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_padlen(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - int val1 ; - int ecode1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nlmsg_padlen" "', argument " "1"" of type '" "int""'"); - } - arg1 = (int)(val1); - result = (int)nlmsg_padlen(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_data(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nlmsghdr *arg1 = (struct nlmsghdr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - void *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlmsghdr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_data" "', argument " "1"" of type '" "struct nlmsghdr const *""'"); - } - arg1 = (struct nlmsghdr *)(argp1); - result = (void *)nlmsg_data((struct nlmsghdr const *)arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_void, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_datalen(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nlmsghdr *arg1 = (struct nlmsghdr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlmsghdr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_datalen" "', argument " "1"" of type '" "struct nlmsghdr const *""'"); - } - arg1 = (struct nlmsghdr *)(argp1); - result = (int)nlmsg_datalen((struct nlmsghdr const *)arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_tail(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nlmsghdr *arg1 = (struct nlmsghdr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - void *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlmsghdr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_tail" "', argument " "1"" of type '" "struct nlmsghdr const *""'"); - } - arg1 = (struct nlmsghdr *)(argp1); - result = (void *)nlmsg_tail((struct nlmsghdr const *)arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_void, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_attrdata(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nlmsghdr *arg1 = (struct nlmsghdr *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - struct nlattr *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"nlmsg_attrdata",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlmsghdr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_attrdata" "', argument " "1"" of type '" "struct nlmsghdr const *""'"); - } - arg1 = (struct nlmsghdr *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nlmsg_attrdata" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - result = (struct nlattr *)nlmsg_attrdata((struct nlmsghdr const *)arg1,arg2); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nlattr, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_attrlen(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nlmsghdr *arg1 = (struct nlmsghdr *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nlmsg_attrlen",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlmsghdr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_attrlen" "', argument " "1"" of type '" "struct nlmsghdr const *""'"); - } - arg1 = (struct nlmsghdr *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nlmsg_attrlen" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - result = (int)nlmsg_attrlen((struct nlmsghdr const *)arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_valid_hdr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nlmsghdr *arg1 = (struct nlmsghdr *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nlmsg_valid_hdr",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlmsghdr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_valid_hdr" "', argument " "1"" of type '" "struct nlmsghdr const *""'"); - } - arg1 = (struct nlmsghdr *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nlmsg_valid_hdr" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - result = (int)nlmsg_valid_hdr((struct nlmsghdr const *)arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_ok(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nlmsghdr *arg1 = (struct nlmsghdr *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nlmsg_ok",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlmsghdr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_ok" "', argument " "1"" of type '" "struct nlmsghdr const *""'"); - } - arg1 = (struct nlmsghdr *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nlmsg_ok" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - result = (int)nlmsg_ok((struct nlmsghdr const *)arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_next(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nlmsghdr *arg1 = (struct nlmsghdr *) 0 ; - int *arg2 = (int *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - struct nlmsghdr *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"nlmsg_next",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlmsghdr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_next" "', argument " "1"" of type '" "struct nlmsghdr *""'"); - } - arg1 = (struct nlmsghdr *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_int, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nlmsg_next" "', argument " "2"" of type '" "int *""'"); - } - arg2 = (int *)(argp2); - result = (struct nlmsghdr *)nlmsg_next(arg1,arg2); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nlmsghdr, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_parse(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nlmsghdr *arg1 = (struct nlmsghdr *) 0 ; - int arg2 ; - struct nlattr **arg3 = (struct nlattr **) 0 ; - int arg4 ; - struct nla_policy *arg5 = (struct nla_policy *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - void *argp3 = 0 ; - int res3 = 0 ; - int val4 ; - int ecode4 = 0 ; - void *argp5 = 0 ; - int res5 = 0 ; - PyObject *swig_obj[5] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nlmsg_parse",5,5,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlmsghdr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_parse" "', argument " "1"" of type '" "struct nlmsghdr *""'"); - } - arg1 = (struct nlmsghdr *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nlmsg_parse" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - res3 = SWIG_ConvertPtr(swig_obj[2], &argp3,SWIGTYPE_p_p_nlattr, 0 | 0 ); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "nlmsg_parse" "', argument " "3"" of type '" "struct nlattr **""'"); - } - arg3 = (struct nlattr **)(argp3); - ecode4 = SWIG_AsVal_int(swig_obj[3], &val4); - if (!SWIG_IsOK(ecode4)) { - SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "nlmsg_parse" "', argument " "4"" of type '" "int""'"); - } - arg4 = (int)(val4); - res5 = SWIG_ConvertPtr(swig_obj[4], &argp5,SWIGTYPE_p_nla_policy, 0 | 0 ); - if (!SWIG_IsOK(res5)) { - SWIG_exception_fail(SWIG_ArgError(res5), "in method '" "nlmsg_parse" "', argument " "5"" of type '" "struct nla_policy *""'"); - } - arg5 = (struct nla_policy *)(argp5); - result = (int)nlmsg_parse(arg1,arg2,arg3,arg4,arg5); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_find_attr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nlmsghdr *arg1 = (struct nlmsghdr *) 0 ; - int arg2 ; - int arg3 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - int val3 ; - int ecode3 = 0 ; - PyObject *swig_obj[3] ; - struct nlattr *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"nlmsg_find_attr",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlmsghdr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_find_attr" "', argument " "1"" of type '" "struct nlmsghdr *""'"); - } - arg1 = (struct nlmsghdr *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nlmsg_find_attr" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "nlmsg_find_attr" "', argument " "3"" of type '" "int""'"); - } - arg3 = (int)(val3); - result = (struct nlattr *)nlmsg_find_attr(arg1,arg2,arg3); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nlattr, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_validate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nlmsghdr *arg1 = (struct nlmsghdr *) 0 ; - int arg2 ; - int arg3 ; - struct nla_policy *arg4 = (struct nla_policy *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - int val3 ; - int ecode3 = 0 ; - void *argp4 = 0 ; - int res4 = 0 ; - PyObject *swig_obj[4] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nlmsg_validate",4,4,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlmsghdr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_validate" "', argument " "1"" of type '" "struct nlmsghdr *""'"); - } - arg1 = (struct nlmsghdr *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nlmsg_validate" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "nlmsg_validate" "', argument " "3"" of type '" "int""'"); - } - arg3 = (int)(val3); - res4 = SWIG_ConvertPtr(swig_obj[3], &argp4,SWIGTYPE_p_nla_policy, 0 | 0 ); - if (!SWIG_IsOK(res4)) { - SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "nlmsg_validate" "', argument " "4"" of type '" "struct nla_policy *""'"); - } - arg4 = (struct nla_policy *)(argp4); - result = (int)nlmsg_validate(arg1,arg2,arg3,arg4); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_alloc(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_msg *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"nlmsg_alloc",0,0,0)) SWIG_fail; - result = (struct nl_msg *)nlmsg_alloc(); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_msg, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_alloc_size(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - size_t arg1 ; - size_t val1 ; - int ecode1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_msg *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - ecode1 = SWIG_AsVal_size_t(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nlmsg_alloc_size" "', argument " "1"" of type '" "size_t""'"); - } - arg1 = (size_t)(val1); - result = (struct nl_msg *)nlmsg_alloc_size(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_msg, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_alloc_simple(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - int arg2 ; - int val1 ; - int ecode1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - struct nl_msg *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"nlmsg_alloc_simple",2,2,swig_obj)) SWIG_fail; - ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nlmsg_alloc_simple" "', argument " "1"" of type '" "int""'"); - } - arg1 = (int)(val1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nlmsg_alloc_simple" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - result = (struct nl_msg *)nlmsg_alloc_simple(arg1,arg2); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_msg, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_set_default_size(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - size_t arg1 ; - size_t val1 ; - int ecode1 = 0 ; - PyObject *swig_obj[1] ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - ecode1 = SWIG_AsVal_size_t(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nlmsg_set_default_size" "', argument " "1"" of type '" "size_t""'"); - } - arg1 = (size_t)(val1); - nlmsg_set_default_size(arg1); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_inherit(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nlmsghdr *arg1 = (struct nlmsghdr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_msg *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlmsghdr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_inherit" "', argument " "1"" of type '" "struct nlmsghdr *""'"); - } - arg1 = (struct nlmsghdr *)(argp1); - result = (struct nl_msg *)nlmsg_inherit(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_msg, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_convert(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nlmsghdr *arg1 = (struct nlmsghdr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_msg *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlmsghdr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_convert" "', argument " "1"" of type '" "struct nlmsghdr *""'"); - } - arg1 = (struct nlmsghdr *)(argp1); - result = (struct nl_msg *)nlmsg_convert(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_msg, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_reserve(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_msg *arg1 = (struct nl_msg *) 0 ; - size_t arg2 ; - int arg3 ; - void *argp1 = 0 ; - int res1 = 0 ; - size_t val2 ; - int ecode2 = 0 ; - int val3 ; - int ecode3 = 0 ; - PyObject *swig_obj[3] ; - void *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"nlmsg_reserve",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_reserve" "', argument " "1"" of type '" "struct nl_msg *""'"); - } - arg1 = (struct nl_msg *)(argp1); - ecode2 = SWIG_AsVal_size_t(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nlmsg_reserve" "', argument " "2"" of type '" "size_t""'"); - } - arg2 = (size_t)(val2); - ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "nlmsg_reserve" "', argument " "3"" of type '" "int""'"); - } - arg3 = (int)(val3); - result = (void *)nlmsg_reserve(arg1,arg2,arg3); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_void, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_append(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_msg *arg1 = (struct nl_msg *) 0 ; - void *arg2 = (void *) 0 ; - size_t arg3 ; - int arg4 ; - void *argp1 = 0 ; - int res1 = 0 ; - int res2 ; - size_t val3 ; - int ecode3 = 0 ; - int val4 ; - int ecode4 = 0 ; - PyObject *swig_obj[4] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nlmsg_append",4,4,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_append" "', argument " "1"" of type '" "struct nl_msg *""'"); - } - arg1 = (struct nl_msg *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1],SWIG_as_voidptrptr(&arg2), 0, 0); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nlmsg_append" "', argument " "2"" of type '" "void *""'"); - } - ecode3 = SWIG_AsVal_size_t(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "nlmsg_append" "', argument " "3"" of type '" "size_t""'"); - } - arg3 = (size_t)(val3); - ecode4 = SWIG_AsVal_int(swig_obj[3], &val4); - if (!SWIG_IsOK(ecode4)) { - SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "nlmsg_append" "', argument " "4"" of type '" "int""'"); - } - arg4 = (int)(val4); - result = (int)nlmsg_append(arg1,arg2,arg3,arg4); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_expand(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_msg *arg1 = (struct nl_msg *) 0 ; - size_t arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - size_t val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nlmsg_expand",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_expand" "', argument " "1"" of type '" "struct nl_msg *""'"); - } - arg1 = (struct nl_msg *)(argp1); - ecode2 = SWIG_AsVal_size_t(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nlmsg_expand" "', argument " "2"" of type '" "size_t""'"); - } - arg2 = (size_t)(val2); - result = (int)nlmsg_expand(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_put(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_msg *arg1 = (struct nl_msg *) 0 ; - uint32_t arg2 ; - uint32_t arg3 ; - int arg4 ; - int arg5 ; - int arg6 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - unsigned int val3 ; - int ecode3 = 0 ; - int val4 ; - int ecode4 = 0 ; - int val5 ; - int ecode5 = 0 ; - int val6 ; - int ecode6 = 0 ; - PyObject *swig_obj[6] ; - struct nlmsghdr *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"nlmsg_put",6,6,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_put" "', argument " "1"" of type '" "struct nl_msg *""'"); - } - arg1 = (struct nl_msg *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nlmsg_put" "', argument " "2"" of type '" "uint32_t""'"); - } - arg2 = (uint32_t)(val2); - ecode3 = SWIG_AsVal_unsigned_SS_int(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "nlmsg_put" "', argument " "3"" of type '" "uint32_t""'"); - } - arg3 = (uint32_t)(val3); - ecode4 = SWIG_AsVal_int(swig_obj[3], &val4); - if (!SWIG_IsOK(ecode4)) { - SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "nlmsg_put" "', argument " "4"" of type '" "int""'"); - } - arg4 = (int)(val4); - ecode5 = SWIG_AsVal_int(swig_obj[4], &val5); - if (!SWIG_IsOK(ecode5)) { - SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "nlmsg_put" "', argument " "5"" of type '" "int""'"); - } - arg5 = (int)(val5); - ecode6 = SWIG_AsVal_int(swig_obj[5], &val6); - if (!SWIG_IsOK(ecode6)) { - SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "nlmsg_put" "', argument " "6"" of type '" "int""'"); - } - arg6 = (int)(val6); - result = (struct nlmsghdr *)nlmsg_put(arg1,arg2,arg3,arg4,arg5,arg6); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nlmsghdr, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_hdr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_msg *arg1 = (struct nl_msg *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct nlmsghdr *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_hdr" "', argument " "1"" of type '" "struct nl_msg *""'"); - } - arg1 = (struct nl_msg *)(argp1); - result = (struct nlmsghdr *)nlmsg_hdr(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nlmsghdr, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_msg *arg1 = (struct nl_msg *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_get" "', argument " "1"" of type '" "struct nl_msg *""'"); - } - arg1 = (struct nl_msg *)(argp1); - nlmsg_get(arg1); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_free(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_msg *arg1 = (struct nl_msg *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_free" "', argument " "1"" of type '" "struct nl_msg *""'"); - } - arg1 = (struct nl_msg *)(argp1); - nlmsg_free(arg1); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_set_proto(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_msg *arg1 = (struct nl_msg *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nlmsg_set_proto",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_set_proto" "', argument " "1"" of type '" "struct nl_msg *""'"); - } - arg1 = (struct nl_msg *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nlmsg_set_proto" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - nlmsg_set_proto(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_get_proto(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_msg *arg1 = (struct nl_msg *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_get_proto" "', argument " "1"" of type '" "struct nl_msg *""'"); - } - arg1 = (struct nl_msg *)(argp1); - result = (int)nlmsg_get_proto(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_get_max_size(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_msg *arg1 = (struct nl_msg *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - size_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_get_max_size" "', argument " "1"" of type '" "struct nl_msg *""'"); - } - arg1 = (struct nl_msg *)(argp1); - result = nlmsg_get_max_size(arg1); - resultobj = SWIG_From_size_t((size_t)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_set_src(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_msg *arg1 = (struct nl_msg *) 0 ; - struct sockaddr_nl *arg2 = (struct sockaddr_nl *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nlmsg_set_src",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_set_src" "', argument " "1"" of type '" "struct nl_msg *""'"); - } - arg1 = (struct nl_msg *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_sockaddr_nl, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nlmsg_set_src" "', argument " "2"" of type '" "struct sockaddr_nl *""'"); - } - arg2 = (struct sockaddr_nl *)(argp2); - nlmsg_set_src(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_get_src(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_msg *arg1 = (struct nl_msg *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct sockaddr_nl *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_get_src" "', argument " "1"" of type '" "struct nl_msg *""'"); - } - arg1 = (struct nl_msg *)(argp1); - result = (struct sockaddr_nl *)nlmsg_get_src(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_sockaddr_nl, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_set_dst(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_msg *arg1 = (struct nl_msg *) 0 ; - struct sockaddr_nl *arg2 = (struct sockaddr_nl *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nlmsg_set_dst",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_set_dst" "', argument " "1"" of type '" "struct nl_msg *""'"); - } - arg1 = (struct nl_msg *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_sockaddr_nl, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nlmsg_set_dst" "', argument " "2"" of type '" "struct sockaddr_nl *""'"); - } - arg2 = (struct sockaddr_nl *)(argp2); - nlmsg_set_dst(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_get_dst(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_msg *arg1 = (struct nl_msg *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct sockaddr_nl *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_get_dst" "', argument " "1"" of type '" "struct nl_msg *""'"); - } - arg1 = (struct nl_msg *)(argp1); - result = (struct sockaddr_nl *)nlmsg_get_dst(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_sockaddr_nl, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_set_creds(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_msg *arg1 = (struct nl_msg *) 0 ; - struct ucred *arg2 = (struct ucred *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nlmsg_set_creds",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_set_creds" "', argument " "1"" of type '" "struct nl_msg *""'"); - } - arg1 = (struct nl_msg *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_ucred, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nlmsg_set_creds" "', argument " "2"" of type '" "struct ucred *""'"); - } - arg2 = (struct ucred *)(argp2); - nlmsg_set_creds(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nlmsg_get_creds(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_msg *arg1 = (struct nl_msg *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct ucred *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nlmsg_get_creds" "', argument " "1"" of type '" "struct nl_msg *""'"); - } - arg1 = (struct nl_msg *)(argp1); - result = (struct ucred *)nlmsg_get_creds(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_ucred, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_nlmsgtype2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - char *arg2 = (char *) 0 ; - size_t arg3 ; - int val1 ; - int ecode1 = 0 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - size_t val3 ; - int ecode3 = 0 ; - PyObject *swig_obj[3] ; - char *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"nl_nlmsgtype2str",3,3,swig_obj)) SWIG_fail; - ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_nlmsgtype2str" "', argument " "1"" of type '" "int""'"); - } - arg1 = (int)(val1); - res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_nlmsgtype2str" "', argument " "2"" of type '" "char *""'"); - } - arg2 = (char *)(buf2); - ecode3 = SWIG_AsVal_size_t(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "nl_nlmsgtype2str" "', argument " "3"" of type '" "size_t""'"); - } - arg3 = (size_t)(val3); - result = (char *)nl_nlmsgtype2str(arg1,arg2,arg3); - resultobj = SWIG_FromCharPtr((const char *)result); - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return resultobj; -fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_str2nlmsgtype(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_str2nlmsgtype" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = (char *)(buf1); - result = (int)nl_str2nlmsgtype((char const *)arg1); - resultobj = SWIG_From_int((int)(result)); - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_nlmsg_flags2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - char *arg2 = (char *) 0 ; - size_t arg3 ; - int val1 ; - int ecode1 = 0 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - size_t val3 ; - int ecode3 = 0 ; - PyObject *swig_obj[3] ; - char *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"nl_nlmsg_flags2str",3,3,swig_obj)) SWIG_fail; - ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_nlmsg_flags2str" "', argument " "1"" of type '" "int""'"); - } - arg1 = (int)(val1); - res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_nlmsg_flags2str" "', argument " "2"" of type '" "char *""'"); - } - arg2 = (char *)(buf2); - ecode3 = SWIG_AsVal_size_t(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "nl_nlmsg_flags2str" "', argument " "3"" of type '" "size_t""'"); - } - arg3 = (size_t)(val3); - result = (char *)nl_nlmsg_flags2str(arg1,arg2,arg3); - resultobj = SWIG_FromCharPtr((const char *)result); - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return resultobj; -fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_msg_parse(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_msg *arg1 = (struct nl_msg *) 0 ; - void (*arg2)(struct nl_object *,void *) = (void (*)(struct nl_object *,void *)) 0 ; - void *arg3 = (void *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - int res3 ; - PyObject *swig_obj[3] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nl_msg_parse",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_msg_parse" "', argument " "1"" of type '" "struct nl_msg *""'"); - } - arg1 = (struct nl_msg *)(argp1); - { - int res = SWIG_ConvertFunctionPtr(swig_obj[1], (void**)(&arg2), SWIGTYPE_p_f_p_struct_nl_object_p_void__void); - if (!SWIG_IsOK(res)) { - SWIG_exception_fail(SWIG_ArgError(res), "in method '" "nl_msg_parse" "', argument " "2"" of type '" "void (*)(struct nl_object *,void *)""'"); - } - } - res3 = SWIG_ConvertPtr(swig_obj[2],SWIG_as_voidptrptr(&arg3), 0, 0); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "nl_msg_parse" "', argument " "3"" of type '" "void *""'"); - } - result = (int)nl_msg_parse(arg1,arg2,arg3); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_msg_dump(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_msg *arg1 = (struct nl_msg *) 0 ; - FILE *arg2 = (FILE *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_msg_dump",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_msg_dump" "', argument " "1"" of type '" "struct nl_msg *""'"); - } - arg1 = (struct nl_msg *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_FILE, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_msg_dump" "', argument " "2"" of type '" "FILE *""'"); - } - arg2 = (FILE *)(argp2); - nl_msg_dump(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_cast_obj(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - void *arg1 = (void *) 0 ; - int res1 ; - PyObject *swig_obj[1] ; - struct nl_object *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "cast_obj" "', argument " "1"" of type '" "void *""'"); - } - result = (struct nl_object *)cast_obj(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_object_alloc_name(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_object *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "object_alloc_name" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = (char *)(buf1); - result = (struct nl_object *)object_alloc_name((char const *)arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_object_alloc(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_object_ops *arg1 = (struct nl_object_ops *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_object *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object_ops, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_alloc" "', argument " "1"" of type '" "struct nl_object_ops *""'"); - } - arg1 = (struct nl_object_ops *)(argp1); - result = (struct nl_object *)nl_object_alloc(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_object_free(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_object *arg1 = (struct nl_object *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_free" "', argument " "1"" of type '" "struct nl_object *""'"); - } - arg1 = (struct nl_object *)(argp1); - nl_object_free(arg1); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_object_clone(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_object *arg1 = (struct nl_object *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_object *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_clone" "', argument " "1"" of type '" "struct nl_object *""'"); - } - arg1 = (struct nl_object *)(argp1); - result = (struct nl_object *)nl_object_clone(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_object_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_object *arg1 = (struct nl_object *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_get" "', argument " "1"" of type '" "struct nl_object *""'"); - } - arg1 = (struct nl_object *)(argp1); - nl_object_get(arg1); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_object_put(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_object *arg1 = (struct nl_object *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_put" "', argument " "1"" of type '" "struct nl_object *""'"); - } - arg1 = (struct nl_object *)(argp1); - nl_object_put(arg1); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_object_shared(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_object *arg1 = (struct nl_object *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_shared" "', argument " "1"" of type '" "struct nl_object *""'"); - } - arg1 = (struct nl_object *)(argp1); - result = (int)nl_object_shared(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_object_dump_buf(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_object *arg1 = (struct nl_object *) 0 ; - char *arg2 = (char *) 0 ; - size_t arg3 ; - void *argp1 = 0 ; - int res1 = 0 ; - int res2 ; - size_t size2 ; - char *buff2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_object_dump_buf",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_dump_buf" "', argument " "1"" of type '" "struct nl_object *""'"); - } - arg1 = (struct nl_object *)(argp1); - res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_object_dump_buf" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); - } - buff2= (char *)malloc((size2+1)*sizeof(char)); - arg3 = (size_t)(size2); - arg2 = (char *)(buff2); - nl_object_dump_buf(arg1,arg2,arg3); - resultobj = SWIG_Py_Void(); - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); - if (buff2) free((char*)buff2); - return resultobj; -fail: - if (buff2) free((char*)buff2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_object_dump(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_object *arg1 = (struct nl_object *) 0 ; - struct nl_dump_params *arg2 = (struct nl_dump_params *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_object_dump",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_dump" "', argument " "1"" of type '" "struct nl_object *""'"); - } - arg1 = (struct nl_object *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_object_dump" "', argument " "2"" of type '" "struct nl_dump_params *""'"); - } - arg2 = (struct nl_dump_params *)(argp2); - nl_object_dump(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_object_identical(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_object *arg1 = (struct nl_object *) 0 ; - struct nl_object *arg2 = (struct nl_object *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nl_object_identical",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_identical" "', argument " "1"" of type '" "struct nl_object *""'"); - } - arg1 = (struct nl_object *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_object_identical" "', argument " "2"" of type '" "struct nl_object *""'"); - } - arg2 = (struct nl_object *)(argp2); - result = (int)nl_object_identical(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_object_diff(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_object *arg1 = (struct nl_object *) 0 ; - struct nl_object *arg2 = (struct nl_object *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - uint32_t result; - - if (!SWIG_Python_UnpackTuple(args,"nl_object_diff",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_diff" "', argument " "1"" of type '" "struct nl_object *""'"); - } - arg1 = (struct nl_object *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_object_diff" "', argument " "2"" of type '" "struct nl_object *""'"); - } - arg2 = (struct nl_object *)(argp2); - result = (uint32_t)nl_object_diff(arg1,arg2); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_object_match_filter(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_object *arg1 = (struct nl_object *) 0 ; - struct nl_object *arg2 = (struct nl_object *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nl_object_match_filter",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_match_filter" "', argument " "1"" of type '" "struct nl_object *""'"); - } - arg1 = (struct nl_object *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_object_match_filter" "', argument " "2"" of type '" "struct nl_object *""'"); - } - arg2 = (struct nl_object *)(argp2); - result = (int)nl_object_match_filter(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_object_attrs2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_object *arg1 = (struct nl_object *) 0 ; - uint32_t arg2 ; - char *arg3 = (char *) 0 ; - size_t arg4 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - int res3 ; - size_t size3 ; - char *buff3 = 0 ; - PyObject *swig_obj[3] ; - char *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"nl_object_attrs2str",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_attrs2str" "', argument " "1"" of type '" "struct nl_object *""'"); - } - arg1 = (struct nl_object *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_object_attrs2str" "', argument " "2"" of type '" "uint32_t""'"); - } - arg2 = (uint32_t)(val2); - res3 = SWIG_AsVal_size_t (swig_obj[2], &size3); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "nl_object_attrs2str" "', argument " "3"" of type '" "(char *buf, size_t len)""'"); - } - buff3= (char *)malloc((size3+1)*sizeof(char)); - arg4 = (size_t)(size3); - arg3 = (char *)(buff3); - result = (char *)nl_object_attrs2str(arg1,arg2,arg3,arg4); - resultobj = SWIG_FromCharPtr((const char *)result); - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg3)); - if (buff3) free((char*)buff3); - return resultobj; -fail: - if (buff3) free((char*)buff3); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_object_attr_list(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_object *arg1 = (struct nl_object *) 0 ; - char *arg2 = (char *) 0 ; - size_t arg3 ; - void *argp1 = 0 ; - int res1 = 0 ; - int res2 ; - size_t size2 ; - char *buff2 = 0 ; - PyObject *swig_obj[2] ; - char *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"nl_object_attr_list",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_attr_list" "', argument " "1"" of type '" "struct nl_object *""'"); - } - arg1 = (struct nl_object *)(argp1); - res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_object_attr_list" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); - } - buff2= (char *)malloc((size2+1)*sizeof(char)); - arg3 = (size_t)(size2); - arg2 = (char *)(buff2); - result = (char *)nl_object_attr_list(arg1,arg2,arg3); - resultobj = SWIG_FromCharPtr((const char *)result); - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); - if (buff2) free((char*)buff2); - return resultobj; -fail: - if (buff2) free((char*)buff2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_object_mark(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_object *arg1 = (struct nl_object *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_mark" "', argument " "1"" of type '" "struct nl_object *""'"); - } - arg1 = (struct nl_object *)(argp1); - nl_object_mark(arg1); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_object_unmark(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_object *arg1 = (struct nl_object *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_unmark" "', argument " "1"" of type '" "struct nl_object *""'"); - } - arg1 = (struct nl_object *)(argp1); - nl_object_unmark(arg1); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_object_is_marked(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_object *arg1 = (struct nl_object *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_is_marked" "', argument " "1"" of type '" "struct nl_object *""'"); - } - arg1 = (struct nl_object *)(argp1); - result = (int)nl_object_is_marked(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_object_get_refcnt(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_object *arg1 = (struct nl_object *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_object_get_refcnt" "', argument " "1"" of type '" "struct nl_object *""'"); - } - arg1 = (struct nl_object *)(argp1); - result = (int)nl_object_get_refcnt(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_alloc_cache_name(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_cache *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "alloc_cache_name" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = (char *)(buf1); - result = (struct nl_cache *)alloc_cache_name((char const *)arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_cache, 0 | 0 ); - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_alloc_cache_mngr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_sock *arg1 = (struct nl_sock *) 0 ; - int arg2 ; - int arg3 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - int val3 ; - int ecode3 = 0 ; - PyObject *swig_obj[3] ; - struct nl_cache_mngr *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"alloc_cache_mngr",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "alloc_cache_mngr" "', argument " "1"" of type '" "struct nl_sock *""'"); - } - arg1 = (struct nl_sock *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "alloc_cache_mngr" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "alloc_cache_mngr" "', argument " "3"" of type '" "int""'"); - } - arg3 = (int)(val3); - result = (struct nl_cache_mngr *)alloc_cache_mngr(arg1,arg2,arg3); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_cache_mngr, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_cache_mngr_add(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache_mngr *arg1 = (struct nl_cache_mngr *) 0 ; - char *arg2 = (char *) 0 ; - change_func_t arg3 = (change_func_t) 0 ; - void *arg4 = (void *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - int res4 ; - PyObject *swig_obj[4] ; - struct nl_cache *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"cache_mngr_add",4,4,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache_mngr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "cache_mngr_add" "', argument " "1"" of type '" "struct nl_cache_mngr *""'"); - } - arg1 = (struct nl_cache_mngr *)(argp1); - res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "cache_mngr_add" "', argument " "2"" of type '" "char const *""'"); - } - arg2 = (char *)(buf2); - { - int res = SWIG_ConvertFunctionPtr(swig_obj[2], (void**)(&arg3), SWIGTYPE_p_f_p_struct_nl_cache_p_struct_nl_object_int_p_void__void); - if (!SWIG_IsOK(res)) { - SWIG_exception_fail(SWIG_ArgError(res), "in method '" "cache_mngr_add" "', argument " "3"" of type '" "change_func_t""'"); - } - } - res4 = SWIG_ConvertPtr(swig_obj[3],SWIG_as_voidptrptr(&arg4), 0, 0); - if (!SWIG_IsOK(res4)) { - SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "cache_mngr_add" "', argument " "4"" of type '" "void *""'"); - } - result = (struct nl_cache *)cache_mngr_add(arg1,(char const *)arg2,arg3,arg4); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_cache, 0 | 0 ); - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return resultobj; -fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_nitems(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache *arg1 = (struct nl_cache *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_nitems" "', argument " "1"" of type '" "struct nl_cache *""'"); - } - arg1 = (struct nl_cache *)(argp1); - result = (int)nl_cache_nitems(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_nitems_filter(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache *arg1 = (struct nl_cache *) 0 ; - struct nl_object *arg2 = (struct nl_object *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nl_cache_nitems_filter",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_nitems_filter" "', argument " "1"" of type '" "struct nl_cache *""'"); - } - arg1 = (struct nl_cache *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cache_nitems_filter" "', argument " "2"" of type '" "struct nl_object *""'"); - } - arg2 = (struct nl_object *)(argp2); - result = (int)nl_cache_nitems_filter(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_get_ops(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache *arg1 = (struct nl_cache *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_cache_ops *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_get_ops" "', argument " "1"" of type '" "struct nl_cache *""'"); - } - arg1 = (struct nl_cache *)(argp1); - result = (struct nl_cache_ops *)nl_cache_get_ops(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_cache_ops, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_get_first(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache *arg1 = (struct nl_cache *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_object *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_get_first" "', argument " "1"" of type '" "struct nl_cache *""'"); - } - arg1 = (struct nl_cache *)(argp1); - result = (struct nl_object *)nl_cache_get_first(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_get_last(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache *arg1 = (struct nl_cache *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_object *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_get_last" "', argument " "1"" of type '" "struct nl_cache *""'"); - } - arg1 = (struct nl_cache *)(argp1); - result = (struct nl_object *)nl_cache_get_last(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_get_next(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_object *arg1 = (struct nl_object *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_object *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_get_next" "', argument " "1"" of type '" "struct nl_object *""'"); - } - arg1 = (struct nl_object *)(argp1); - result = (struct nl_object *)nl_cache_get_next(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_get_prev(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_object *arg1 = (struct nl_object *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_object *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_get_prev" "', argument " "1"" of type '" "struct nl_object *""'"); - } - arg1 = (struct nl_object *)(argp1); - result = (struct nl_object *)nl_cache_get_prev(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_alloc(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache_ops *arg1 = (struct nl_cache_ops *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_cache *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache_ops, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_alloc" "', argument " "1"" of type '" "struct nl_cache_ops *""'"); - } - arg1 = (struct nl_cache_ops *)(argp1); - result = (struct nl_cache *)nl_cache_alloc(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_cache, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_subset(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache *arg1 = (struct nl_cache *) 0 ; - struct nl_object *arg2 = (struct nl_object *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - struct nl_cache *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"nl_cache_subset",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_subset" "', argument " "1"" of type '" "struct nl_cache *""'"); - } - arg1 = (struct nl_cache *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cache_subset" "', argument " "2"" of type '" "struct nl_object *""'"); - } - arg2 = (struct nl_object *)(argp2); - result = (struct nl_cache *)nl_cache_subset(arg1,arg2); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_cache, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_clear(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache *arg1 = (struct nl_cache *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_clear" "', argument " "1"" of type '" "struct nl_cache *""'"); - } - arg1 = (struct nl_cache *)(argp1); - nl_cache_clear(arg1); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_free(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache *arg1 = (struct nl_cache *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_free" "', argument " "1"" of type '" "struct nl_cache *""'"); - } - arg1 = (struct nl_cache *)(argp1); - nl_cache_free(arg1); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_add(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache *arg1 = (struct nl_cache *) 0 ; - struct nl_object *arg2 = (struct nl_object *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nl_cache_add",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_add" "', argument " "1"" of type '" "struct nl_cache *""'"); - } - arg1 = (struct nl_cache *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cache_add" "', argument " "2"" of type '" "struct nl_object *""'"); - } - arg2 = (struct nl_object *)(argp2); - result = (int)nl_cache_add(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_parse_and_add(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache *arg1 = (struct nl_cache *) 0 ; - struct nl_msg *arg2 = (struct nl_msg *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nl_cache_parse_and_add",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_parse_and_add" "', argument " "1"" of type '" "struct nl_cache *""'"); - } - arg1 = (struct nl_cache *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cache_parse_and_add" "', argument " "2"" of type '" "struct nl_msg *""'"); - } - arg2 = (struct nl_msg *)(argp2); - result = (int)nl_cache_parse_and_add(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_remove(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_object *arg1 = (struct nl_object *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_remove" "', argument " "1"" of type '" "struct nl_object *""'"); - } - arg1 = (struct nl_object *)(argp1); - nl_cache_remove(arg1); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_refill(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_sock *arg1 = (struct nl_sock *) 0 ; - struct nl_cache *arg2 = (struct nl_cache *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nl_cache_refill",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_refill" "', argument " "1"" of type '" "struct nl_sock *""'"); - } - arg1 = (struct nl_sock *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cache_refill" "', argument " "2"" of type '" "struct nl_cache *""'"); - } - arg2 = (struct nl_cache *)(argp2); - result = (int)nl_cache_refill(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_pickup(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_sock *arg1 = (struct nl_sock *) 0 ; - struct nl_cache *arg2 = (struct nl_cache *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nl_cache_pickup",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_pickup" "', argument " "1"" of type '" "struct nl_sock *""'"); - } - arg1 = (struct nl_sock *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cache_pickup" "', argument " "2"" of type '" "struct nl_cache *""'"); - } - arg2 = (struct nl_cache *)(argp2); - result = (int)nl_cache_pickup(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_resync(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_sock *arg1 = (struct nl_sock *) 0 ; - struct nl_cache *arg2 = (struct nl_cache *) 0 ; - change_func_t arg3 = (change_func_t) 0 ; - void *arg4 = (void *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - int res4 ; - PyObject *swig_obj[4] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nl_cache_resync",4,4,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_resync" "', argument " "1"" of type '" "struct nl_sock *""'"); - } - arg1 = (struct nl_sock *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cache_resync" "', argument " "2"" of type '" "struct nl_cache *""'"); - } - arg2 = (struct nl_cache *)(argp2); - { - int res = SWIG_ConvertFunctionPtr(swig_obj[2], (void**)(&arg3), SWIGTYPE_p_f_p_struct_nl_cache_p_struct_nl_object_int_p_void__void); - if (!SWIG_IsOK(res)) { - SWIG_exception_fail(SWIG_ArgError(res), "in method '" "nl_cache_resync" "', argument " "3"" of type '" "change_func_t""'"); - } - } - res4 = SWIG_ConvertPtr(swig_obj[3],SWIG_as_voidptrptr(&arg4), 0, 0); - if (!SWIG_IsOK(res4)) { - SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "nl_cache_resync" "', argument " "4"" of type '" "void *""'"); - } - result = (int)nl_cache_resync(arg1,arg2,arg3,arg4); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_include(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache *arg1 = (struct nl_cache *) 0 ; - struct nl_object *arg2 = (struct nl_object *) 0 ; - change_func_t arg3 = (change_func_t) 0 ; - void *arg4 = (void *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - int res4 ; - PyObject *swig_obj[4] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nl_cache_include",4,4,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_include" "', argument " "1"" of type '" "struct nl_cache *""'"); - } - arg1 = (struct nl_cache *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cache_include" "', argument " "2"" of type '" "struct nl_object *""'"); - } - arg2 = (struct nl_object *)(argp2); - { - int res = SWIG_ConvertFunctionPtr(swig_obj[2], (void**)(&arg3), SWIGTYPE_p_f_p_struct_nl_cache_p_struct_nl_object_int_p_void__void); - if (!SWIG_IsOK(res)) { - SWIG_exception_fail(SWIG_ArgError(res), "in method '" "nl_cache_include" "', argument " "3"" of type '" "change_func_t""'"); - } - } - res4 = SWIG_ConvertPtr(swig_obj[3],SWIG_as_voidptrptr(&arg4), 0, 0); - if (!SWIG_IsOK(res4)) { - SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "nl_cache_include" "', argument " "4"" of type '" "void *""'"); - } - result = (int)nl_cache_include(arg1,arg2,arg3,arg4); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_set_arg1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache *arg1 = (struct nl_cache *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_cache_set_arg1",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_set_arg1" "', argument " "1"" of type '" "struct nl_cache *""'"); - } - arg1 = (struct nl_cache *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_cache_set_arg1" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - nl_cache_set_arg1(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_set_arg2(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache *arg1 = (struct nl_cache *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_cache_set_arg2",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_set_arg2" "', argument " "1"" of type '" "struct nl_cache *""'"); - } - arg1 = (struct nl_cache *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_cache_set_arg2" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - nl_cache_set_arg2(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_is_empty(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache *arg1 = (struct nl_cache *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_is_empty" "', argument " "1"" of type '" "struct nl_cache *""'"); - } - arg1 = (struct nl_cache *)(argp1); - result = (int)nl_cache_is_empty(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_search(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache *arg1 = (struct nl_cache *) 0 ; - struct nl_object *arg2 = (struct nl_object *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - struct nl_object *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"nl_cache_search",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_search" "', argument " "1"" of type '" "struct nl_cache *""'"); - } - arg1 = (struct nl_cache *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cache_search" "', argument " "2"" of type '" "struct nl_object *""'"); - } - arg2 = (struct nl_object *)(argp2); - result = (struct nl_object *)nl_cache_search(arg1,arg2); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_mark_all(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache *arg1 = (struct nl_cache *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_mark_all" "', argument " "1"" of type '" "struct nl_cache *""'"); - } - arg1 = (struct nl_cache *)(argp1); - nl_cache_mark_all(arg1); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_dump(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache *arg1 = (struct nl_cache *) 0 ; - struct nl_dump_params *arg2 = (struct nl_dump_params *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_cache_dump",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_dump" "', argument " "1"" of type '" "struct nl_cache *""'"); - } - arg1 = (struct nl_cache *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cache_dump" "', argument " "2"" of type '" "struct nl_dump_params *""'"); - } - arg2 = (struct nl_dump_params *)(argp2); - nl_cache_dump(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_dump_filter(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache *arg1 = (struct nl_cache *) 0 ; - struct nl_dump_params *arg2 = (struct nl_dump_params *) 0 ; - struct nl_object *arg3 = (struct nl_object *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - void *argp3 = 0 ; - int res3 = 0 ; - PyObject *swig_obj[3] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_cache_dump_filter",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_dump_filter" "', argument " "1"" of type '" "struct nl_cache *""'"); - } - arg1 = (struct nl_cache *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_dump_params, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cache_dump_filter" "', argument " "2"" of type '" "struct nl_dump_params *""'"); - } - arg2 = (struct nl_dump_params *)(argp2); - res3 = SWIG_ConvertPtr(swig_obj[2], &argp3,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "nl_cache_dump_filter" "', argument " "3"" of type '" "struct nl_object *""'"); - } - arg3 = (struct nl_object *)(argp3); - nl_cache_dump_filter(arg1,arg2,arg3); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_foreach(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache *arg1 = (struct nl_cache *) 0 ; - void (*arg2)(struct nl_object *,void *) = (void (*)(struct nl_object *,void *)) 0 ; - void *arg3 = (void *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - int res3 ; - PyObject *swig_obj[3] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_cache_foreach",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_foreach" "', argument " "1"" of type '" "struct nl_cache *""'"); - } - arg1 = (struct nl_cache *)(argp1); - { - int res = SWIG_ConvertFunctionPtr(swig_obj[1], (void**)(&arg2), SWIGTYPE_p_f_p_struct_nl_object_p_void__void); - if (!SWIG_IsOK(res)) { - SWIG_exception_fail(SWIG_ArgError(res), "in method '" "nl_cache_foreach" "', argument " "2"" of type '" "void (*)(struct nl_object *,void *)""'"); - } - } - res3 = SWIG_ConvertPtr(swig_obj[2],SWIG_as_voidptrptr(&arg3), 0, 0); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "nl_cache_foreach" "', argument " "3"" of type '" "void *""'"); - } - nl_cache_foreach(arg1,arg2,arg3); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_foreach_filter(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache *arg1 = (struct nl_cache *) 0 ; - struct nl_object *arg2 = (struct nl_object *) 0 ; - void (*arg3)(struct nl_object *,void *) = (void (*)(struct nl_object *,void *)) 0 ; - void *arg4 = (void *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - int res4 ; - PyObject *swig_obj[4] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_cache_foreach_filter",4,4,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_foreach_filter" "', argument " "1"" of type '" "struct nl_cache *""'"); - } - arg1 = (struct nl_cache *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cache_foreach_filter" "', argument " "2"" of type '" "struct nl_object *""'"); - } - arg2 = (struct nl_object *)(argp2); - { - int res = SWIG_ConvertFunctionPtr(swig_obj[2], (void**)(&arg3), SWIGTYPE_p_f_p_struct_nl_object_p_void__void); - if (!SWIG_IsOK(res)) { - SWIG_exception_fail(SWIG_ArgError(res), "in method '" "nl_cache_foreach_filter" "', argument " "3"" of type '" "void (*)(struct nl_object *,void *)""'"); - } - } - res4 = SWIG_ConvertPtr(swig_obj[3],SWIG_as_voidptrptr(&arg4), 0, 0); - if (!SWIG_IsOK(res4)) { - SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "nl_cache_foreach_filter" "', argument " "4"" of type '" "void *""'"); - } - nl_cache_foreach_filter(arg1,arg2,arg3,arg4); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_ops_lookup(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_cache_ops *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_ops_lookup" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = (char *)(buf1); - result = (struct nl_cache_ops *)nl_cache_ops_lookup((char const *)arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_cache_ops, 0 | 0 ); - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_ops_associate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - int arg2 ; - int val1 ; - int ecode1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - struct nl_cache_ops *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"nl_cache_ops_associate",2,2,swig_obj)) SWIG_fail; - ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_cache_ops_associate" "', argument " "1"" of type '" "int""'"); - } - arg1 = (int)(val1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_cache_ops_associate" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - result = (struct nl_cache_ops *)nl_cache_ops_associate(arg1,arg2); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_cache_ops, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_msgtype_lookup(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache_ops *arg1 = (struct nl_cache_ops *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - struct nl_msgtype *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"nl_msgtype_lookup",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache_ops, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_msgtype_lookup" "', argument " "1"" of type '" "struct nl_cache_ops *""'"); - } - arg1 = (struct nl_cache_ops *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_msgtype_lookup" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - result = (struct nl_msgtype *)nl_msgtype_lookup(arg1,arg2); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_msgtype, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_ops_foreach(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - void (*arg1)(struct nl_cache_ops *,void *) = (void (*)(struct nl_cache_ops *,void *)) 0 ; - void *arg2 = (void *) 0 ; - int res2 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_cache_ops_foreach",2,2,swig_obj)) SWIG_fail; - { - int res = SWIG_ConvertFunctionPtr(swig_obj[0], (void**)(&arg1), SWIGTYPE_p_f_p_struct_nl_cache_ops_p_void__void); - if (!SWIG_IsOK(res)) { - SWIG_exception_fail(SWIG_ArgError(res), "in method '" "nl_cache_ops_foreach" "', argument " "1"" of type '" "void (*)(struct nl_cache_ops *,void *)""'"); - } - } - res2 = SWIG_ConvertPtr(swig_obj[1],SWIG_as_voidptrptr(&arg2), 0, 0); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_cache_ops_foreach" "', argument " "2"" of type '" "void *""'"); - } - nl_cache_ops_foreach(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_mngt_register(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache_ops *arg1 = (struct nl_cache_ops *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache_ops, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_mngt_register" "', argument " "1"" of type '" "struct nl_cache_ops *""'"); - } - arg1 = (struct nl_cache_ops *)(argp1); - result = (int)nl_cache_mngt_register(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_mngt_unregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache_ops *arg1 = (struct nl_cache_ops *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache_ops, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_mngt_unregister" "', argument " "1"" of type '" "struct nl_cache_ops *""'"); - } - arg1 = (struct nl_cache_ops *)(argp1); - result = (int)nl_cache_mngt_unregister(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_mngt_provide(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache *arg1 = (struct nl_cache *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_mngt_provide" "', argument " "1"" of type '" "struct nl_cache *""'"); - } - arg1 = (struct nl_cache *)(argp1); - nl_cache_mngt_provide(arg1); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_mngt_unprovide(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache *arg1 = (struct nl_cache *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_mngt_unprovide" "', argument " "1"" of type '" "struct nl_cache *""'"); - } - arg1 = (struct nl_cache *)(argp1); - nl_cache_mngt_unprovide(arg1); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_mngt_require(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_cache *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_mngt_require" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = (char *)(buf1); - result = (struct nl_cache *)nl_cache_mngt_require((char const *)arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_cache, 0 | 0 ); - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_mngr_get_fd(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache_mngr *arg1 = (struct nl_cache_mngr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache_mngr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_mngr_get_fd" "', argument " "1"" of type '" "struct nl_cache_mngr *""'"); - } - arg1 = (struct nl_cache_mngr *)(argp1); - result = (int)nl_cache_mngr_get_fd(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_mngr_poll(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache_mngr *arg1 = (struct nl_cache_mngr *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nl_cache_mngr_poll",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache_mngr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_mngr_poll" "', argument " "1"" of type '" "struct nl_cache_mngr *""'"); - } - arg1 = (struct nl_cache_mngr *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_cache_mngr_poll" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - result = (int)nl_cache_mngr_poll(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_mngr_data_ready(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache_mngr *arg1 = (struct nl_cache_mngr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache_mngr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_mngr_data_ready" "', argument " "1"" of type '" "struct nl_cache_mngr *""'"); - } - arg1 = (struct nl_cache_mngr *)(argp1); - result = (int)nl_cache_mngr_data_ready(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_cache_mngr_free(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache_mngr *arg1 = (struct nl_cache_mngr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache_mngr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_cache_mngr_free" "', argument " "1"" of type '" "struct nl_cache_mngr *""'"); - } - arg1 = (struct nl_cache_mngr *)(argp1); - nl_cache_mngr_free(arg1); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_addr_parse(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - int arg2 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - struct nl_addr *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"addr_parse",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "addr_parse" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = (char *)(buf1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "addr_parse" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - result = (struct nl_addr *)addr_parse((char const *)arg1,arg2); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_addr, 0 | 0 ); - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_addr_alloc(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - size_t arg1 ; - size_t val1 ; - int ecode1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_addr *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - ecode1 = SWIG_AsVal_size_t(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_addr_alloc" "', argument " "1"" of type '" "size_t""'"); - } - arg1 = (size_t)(val1); - result = (struct nl_addr *)nl_addr_alloc(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_addr, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_addr_alloc_attr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nlattr *arg1 = (struct nlattr *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - struct nl_addr *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"nl_addr_alloc_attr",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nlattr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_alloc_attr" "', argument " "1"" of type '" "struct nlattr *""'"); - } - arg1 = (struct nlattr *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_addr_alloc_attr" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - result = (struct nl_addr *)nl_addr_alloc_attr(arg1,arg2); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_addr, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_addr_build(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - void *arg2 = (void *) 0 ; - size_t arg3 ; - int val1 ; - int ecode1 = 0 ; - int res2 ; - size_t val3 ; - int ecode3 = 0 ; - PyObject *swig_obj[3] ; - struct nl_addr *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"nl_addr_build",3,3,swig_obj)) SWIG_fail; - ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_addr_build" "', argument " "1"" of type '" "int""'"); - } - arg1 = (int)(val1); - res2 = SWIG_ConvertPtr(swig_obj[1],SWIG_as_voidptrptr(&arg2), 0, 0); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_addr_build" "', argument " "2"" of type '" "void *""'"); - } - ecode3 = SWIG_AsVal_size_t(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "nl_addr_build" "', argument " "3"" of type '" "size_t""'"); - } - arg3 = (size_t)(val3); - result = (struct nl_addr *)nl_addr_build(arg1,arg2,arg3); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_addr, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_addr_clone(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_addr *arg1 = (struct nl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_addr *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_clone" "', argument " "1"" of type '" "struct nl_addr *""'"); - } - arg1 = (struct nl_addr *)(argp1); - result = (struct nl_addr *)nl_addr_clone(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_addr, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_addr_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_addr *arg1 = (struct nl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_addr *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_get" "', argument " "1"" of type '" "struct nl_addr *""'"); - } - arg1 = (struct nl_addr *)(argp1); - result = (struct nl_addr *)nl_addr_get(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_addr, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_addr_put(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_addr *arg1 = (struct nl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_put" "', argument " "1"" of type '" "struct nl_addr *""'"); - } - arg1 = (struct nl_addr *)(argp1); - nl_addr_put(arg1); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_addr_shared(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_addr *arg1 = (struct nl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_shared" "', argument " "1"" of type '" "struct nl_addr *""'"); - } - arg1 = (struct nl_addr *)(argp1); - result = (int)nl_addr_shared(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_addr_cmp(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_addr *arg1 = (struct nl_addr *) 0 ; - struct nl_addr *arg2 = (struct nl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nl_addr_cmp",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_cmp" "', argument " "1"" of type '" "struct nl_addr *""'"); - } - arg1 = (struct nl_addr *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_addr_cmp" "', argument " "2"" of type '" "struct nl_addr *""'"); - } - arg2 = (struct nl_addr *)(argp2); - result = (int)nl_addr_cmp(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_addr_cmp_prefix(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_addr *arg1 = (struct nl_addr *) 0 ; - struct nl_addr *arg2 = (struct nl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nl_addr_cmp_prefix",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_cmp_prefix" "', argument " "1"" of type '" "struct nl_addr *""'"); - } - arg1 = (struct nl_addr *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_addr_cmp_prefix" "', argument " "2"" of type '" "struct nl_addr *""'"); - } - arg2 = (struct nl_addr *)(argp2); - result = (int)nl_addr_cmp_prefix(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_addr_iszero(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_addr *arg1 = (struct nl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_iszero" "', argument " "1"" of type '" "struct nl_addr *""'"); - } - arg1 = (struct nl_addr *)(argp1); - result = (int)nl_addr_iszero(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_addr_valid(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - int arg2 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nl_addr_valid",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_valid" "', argument " "1"" of type '" "char *""'"); - } - arg1 = (char *)(buf1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_addr_valid" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - result = (int)nl_addr_valid(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_addr_guess_family(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_addr *arg1 = (struct nl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_guess_family" "', argument " "1"" of type '" "struct nl_addr *""'"); - } - arg1 = (struct nl_addr *)(argp1); - result = (int)nl_addr_guess_family(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_addr_fill_sockaddr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_addr *arg1 = (struct nl_addr *) 0 ; - struct sockaddr *arg2 = (struct sockaddr *) 0 ; - socklen_t *arg3 = (socklen_t *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - void *argp3 = 0 ; - int res3 = 0 ; - PyObject *swig_obj[3] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nl_addr_fill_sockaddr",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_fill_sockaddr" "', argument " "1"" of type '" "struct nl_addr *""'"); - } - arg1 = (struct nl_addr *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_sockaddr, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_addr_fill_sockaddr" "', argument " "2"" of type '" "struct sockaddr *""'"); - } - arg2 = (struct sockaddr *)(argp2); - res3 = SWIG_ConvertPtr(swig_obj[2], &argp3,SWIGTYPE_p_socklen_t, 0 | 0 ); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "nl_addr_fill_sockaddr" "', argument " "3"" of type '" "socklen_t *""'"); - } - arg3 = (socklen_t *)(argp3); - result = (int)nl_addr_fill_sockaddr(arg1,arg2,arg3); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_addr_info(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_addr *arg1 = (struct nl_addr *) 0 ; - struct addrinfo **arg2 = (struct addrinfo **) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nl_addr_info",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_info" "', argument " "1"" of type '" "struct nl_addr *""'"); - } - arg1 = (struct nl_addr *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_p_addrinfo, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_addr_info" "', argument " "2"" of type '" "struct addrinfo **""'"); - } - arg2 = (struct addrinfo **)(argp2); - result = (int)nl_addr_info(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_addr_resolve(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_addr *arg1 = (struct nl_addr *) 0 ; - char *arg2 = (char *) 0 ; - size_t arg3 ; - void *argp1 = 0 ; - int res1 = 0 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - size_t val3 ; - int ecode3 = 0 ; - PyObject *swig_obj[3] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nl_addr_resolve",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_resolve" "', argument " "1"" of type '" "struct nl_addr *""'"); - } - arg1 = (struct nl_addr *)(argp1); - res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_addr_resolve" "', argument " "2"" of type '" "char *""'"); - } - arg2 = (char *)(buf2); - ecode3 = SWIG_AsVal_size_t(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "nl_addr_resolve" "', argument " "3"" of type '" "size_t""'"); - } - arg3 = (size_t)(val3); - result = (int)nl_addr_resolve(arg1,arg2,arg3); - resultobj = SWIG_From_int((int)(result)); - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return resultobj; -fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_addr_set_family(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_addr *arg1 = (struct nl_addr *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_addr_set_family",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_set_family" "', argument " "1"" of type '" "struct nl_addr *""'"); - } - arg1 = (struct nl_addr *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_addr_set_family" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - nl_addr_set_family(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_addr_get_family(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_addr *arg1 = (struct nl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_get_family" "', argument " "1"" of type '" "struct nl_addr *""'"); - } - arg1 = (struct nl_addr *)(argp1); - result = (int)nl_addr_get_family(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_addr_set_binary_addr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_addr *arg1 = (struct nl_addr *) 0 ; - void *arg2 = (void *) 0 ; - size_t arg3 ; - void *argp1 = 0 ; - int res1 = 0 ; - int res2 ; - size_t val3 ; - int ecode3 = 0 ; - PyObject *swig_obj[3] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"nl_addr_set_binary_addr",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_set_binary_addr" "', argument " "1"" of type '" "struct nl_addr *""'"); - } - arg1 = (struct nl_addr *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1],SWIG_as_voidptrptr(&arg2), 0, 0); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_addr_set_binary_addr" "', argument " "2"" of type '" "void *""'"); - } - ecode3 = SWIG_AsVal_size_t(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "nl_addr_set_binary_addr" "', argument " "3"" of type '" "size_t""'"); - } - arg3 = (size_t)(val3); - result = (int)nl_addr_set_binary_addr(arg1,arg2,arg3); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_addr_get_binary_addr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_addr *arg1 = (struct nl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - void *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_get_binary_addr" "', argument " "1"" of type '" "struct nl_addr *""'"); - } - arg1 = (struct nl_addr *)(argp1); - result = (void *)nl_addr_get_binary_addr(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_void, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_addr_get_len(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_addr *arg1 = (struct nl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - unsigned int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_get_len" "', argument " "1"" of type '" "struct nl_addr *""'"); - } - arg1 = (struct nl_addr *)(argp1); - result = (unsigned int)nl_addr_get_len(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_addr_set_prefixlen(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_addr *arg1 = (struct nl_addr *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"nl_addr_set_prefixlen",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_set_prefixlen" "', argument " "1"" of type '" "struct nl_addr *""'"); - } - arg1 = (struct nl_addr *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nl_addr_set_prefixlen" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - nl_addr_set_prefixlen(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_addr_get_prefixlen(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_addr *arg1 = (struct nl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - unsigned int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr_get_prefixlen" "', argument " "1"" of type '" "struct nl_addr *""'"); - } - arg1 = (struct nl_addr *)(argp1); - result = (unsigned int)nl_addr_get_prefixlen(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_af2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - char *arg2 = (char *) 0 ; - size_t arg3 ; - int val1 ; - int ecode1 = 0 ; - int res2 ; - size_t size2 ; - char *buff2 = 0 ; - PyObject *swig_obj[2] ; - char *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"nl_af2str",2,2,swig_obj)) SWIG_fail; - ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "nl_af2str" "', argument " "1"" of type '" "int""'"); - } - arg1 = (int)(val1); - res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_af2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); - } - buff2= (char *)malloc((size2+1)*sizeof(char)); - arg3 = (size_t)(size2); - arg2 = (char *)(buff2); - result = (char *)nl_af2str(arg1,arg2,arg3); - resultobj = SWIG_FromCharPtr((const char *)result); - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); - if (buff2) free((char*)buff2); - return resultobj; -fail: - if (buff2) free((char*)buff2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_str2af(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_str2af" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = (char *)(buf1); - result = (int)nl_str2af((char const *)arg1); - resultobj = SWIG_From_int((int)(result)); - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_nl_addr2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_addr *arg1 = (struct nl_addr *) 0 ; - char *arg2 = (char *) 0 ; - size_t arg3 ; - void *argp1 = 0 ; - int res1 = 0 ; - int res2 ; - size_t size2 ; - char *buff2 = 0 ; - PyObject *swig_obj[2] ; - char *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"nl_addr2str",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nl_addr2str" "', argument " "1"" of type '" "struct nl_addr *""'"); - } - arg1 = (struct nl_addr *)(argp1); - res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nl_addr2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); - } - buff2= (char *)malloc((size2+1)*sizeof(char)); - arg3 = (size_t)(size2); - arg2 = (char *)(buff2); - result = (char *)nl_addr2str(arg1,arg2,arg3); - resultobj = SWIG_FromCharPtr((const char *)result); - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); - if (buff2) free((char*)buff2); - return resultobj; -fail: - if (buff2) free((char*)buff2); - return NULL; -} - - -static PyMethodDef SwigMethods[] = { - { (char *)"SWIG_PyInstanceMethod_New", (PyCFunction)SWIG_PyInstanceMethod_New, METH_O, NULL}, - { (char *)"alloc_dump_params", (PyCFunction)_wrap_alloc_dump_params, METH_NOARGS, NULL}, - { (char *)"free_dump_params", (PyCFunction)_wrap_free_dump_params, METH_O, NULL}, - { (char *)"nl_dump_params_dp_type_set", _wrap_nl_dump_params_dp_type_set, METH_VARARGS, NULL}, - { (char *)"nl_dump_params_dp_type_get", (PyCFunction)_wrap_nl_dump_params_dp_type_get, METH_O, NULL}, - { (char *)"nl_dump_params_dp_prefix_set", _wrap_nl_dump_params_dp_prefix_set, METH_VARARGS, NULL}, - { (char *)"nl_dump_params_dp_prefix_get", (PyCFunction)_wrap_nl_dump_params_dp_prefix_get, METH_O, NULL}, - { (char *)"nl_dump_params_dp_print_index_set", _wrap_nl_dump_params_dp_print_index_set, METH_VARARGS, NULL}, - { (char *)"nl_dump_params_dp_print_index_get", (PyCFunction)_wrap_nl_dump_params_dp_print_index_get, METH_O, NULL}, - { (char *)"nl_dump_params_dp_dump_msgtype_set", _wrap_nl_dump_params_dp_dump_msgtype_set, METH_VARARGS, NULL}, - { (char *)"nl_dump_params_dp_dump_msgtype_get", (PyCFunction)_wrap_nl_dump_params_dp_dump_msgtype_get, METH_O, NULL}, - { (char *)"nl_dump_params_dp_cb_set", _wrap_nl_dump_params_dp_cb_set, METH_VARARGS, NULL}, - { (char *)"nl_dump_params_dp_cb_get", (PyCFunction)_wrap_nl_dump_params_dp_cb_get, METH_O, NULL}, - { (char *)"nl_dump_params_dp_nl_cb_set", _wrap_nl_dump_params_dp_nl_cb_set, METH_VARARGS, NULL}, - { (char *)"nl_dump_params_dp_nl_cb_get", (PyCFunction)_wrap_nl_dump_params_dp_nl_cb_get, METH_O, NULL}, - { (char *)"nl_dump_params_dp_data_set", _wrap_nl_dump_params_dp_data_set, METH_VARARGS, NULL}, - { (char *)"nl_dump_params_dp_data_get", (PyCFunction)_wrap_nl_dump_params_dp_data_get, METH_O, NULL}, - { (char *)"nl_dump_params_dp_fd_set", _wrap_nl_dump_params_dp_fd_set, METH_VARARGS, NULL}, - { (char *)"nl_dump_params_dp_fd_get", (PyCFunction)_wrap_nl_dump_params_dp_fd_get, METH_O, NULL}, - { (char *)"nl_dump_params_dp_buf_set", _wrap_nl_dump_params_dp_buf_set, METH_VARARGS, NULL}, - { (char *)"nl_dump_params_dp_buf_get", (PyCFunction)_wrap_nl_dump_params_dp_buf_get, METH_O, NULL}, - { (char *)"nl_dump_params_dp_buflen_set", _wrap_nl_dump_params_dp_buflen_set, METH_VARARGS, NULL}, - { (char *)"nl_dump_params_dp_buflen_get", (PyCFunction)_wrap_nl_dump_params_dp_buflen_get, METH_O, NULL}, - { (char *)"nl_dump_params_dp_pre_dump_set", _wrap_nl_dump_params_dp_pre_dump_set, METH_VARARGS, NULL}, - { (char *)"nl_dump_params_dp_pre_dump_get", (PyCFunction)_wrap_nl_dump_params_dp_pre_dump_get, METH_O, NULL}, - { (char *)"nl_dump_params_dp_ivar_set", _wrap_nl_dump_params_dp_ivar_set, METH_VARARGS, NULL}, - { (char *)"nl_dump_params_dp_ivar_get", (PyCFunction)_wrap_nl_dump_params_dp_ivar_get, METH_O, NULL}, - { (char *)"nl_dump_params_dp_line_set", _wrap_nl_dump_params_dp_line_set, METH_VARARGS, NULL}, - { (char *)"nl_dump_params_dp_line_get", (PyCFunction)_wrap_nl_dump_params_dp_line_get, METH_O, NULL}, - { (char *)"delete_nl_dump_params", (PyCFunction)_wrap_delete_nl_dump_params, METH_O, NULL}, - { (char *)"nl_dump_params_swigregister", nl_dump_params_swigregister, METH_VARARGS, NULL}, - { (char *)"nl_geterror", (PyCFunction)_wrap_nl_geterror, METH_O, NULL}, - { (char *)"nl_cancel_down_bytes", _wrap_nl_cancel_down_bytes, METH_VARARGS, NULL}, - { (char *)"nl_cancel_down_bits", _wrap_nl_cancel_down_bits, METH_VARARGS, NULL}, - { (char *)"nl_rate2str", _wrap_nl_rate2str, METH_VARARGS, NULL}, - { (char *)"nl_cancel_down_us", _wrap_nl_cancel_down_us, METH_VARARGS, NULL}, - { (char *)"nl_size2int", (PyCFunction)_wrap_nl_size2int, METH_O, NULL}, - { (char *)"nl_size2str", _wrap_nl_size2str, METH_VARARGS, NULL}, - { (char *)"nl_prob2int", (PyCFunction)_wrap_nl_prob2int, METH_O, NULL}, - { (char *)"nl_get_user_hz", (PyCFunction)_wrap_nl_get_user_hz, METH_NOARGS, NULL}, - { (char *)"nl_us2ticks", (PyCFunction)_wrap_nl_us2ticks, METH_O, NULL}, - { (char *)"nl_ticks2us", (PyCFunction)_wrap_nl_ticks2us, METH_O, NULL}, - { (char *)"nl_str2msec", _wrap_nl_str2msec, METH_VARARGS, NULL}, - { (char *)"nl_msec2str", _wrap_nl_msec2str, METH_VARARGS, NULL}, - { (char *)"nl_llproto2str", _wrap_nl_llproto2str, METH_VARARGS, NULL}, - { (char *)"nl_str2llproto", (PyCFunction)_wrap_nl_str2llproto, METH_O, NULL}, - { (char *)"nl_ether_proto2str", _wrap_nl_ether_proto2str, METH_VARARGS, NULL}, - { (char *)"nl_str2ether_proto", (PyCFunction)_wrap_nl_str2ether_proto, METH_O, NULL}, - { (char *)"nl_ip_proto2str", _wrap_nl_ip_proto2str, METH_VARARGS, NULL}, - { (char *)"nl_str2ip_proto", (PyCFunction)_wrap_nl_str2ip_proto, METH_O, NULL}, - { (char *)"nl_new_line", (PyCFunction)_wrap_nl_new_line, METH_O, NULL}, - { (char *)"nl_dump", _wrap_nl_dump, METH_VARARGS, NULL}, - { (char *)"nl_dump_line", _wrap_nl_dump_line, METH_VARARGS, NULL}, - { (char *)"nl_connect", _wrap_nl_connect, METH_VARARGS, NULL}, - { (char *)"nl_close", (PyCFunction)_wrap_nl_close, METH_O, NULL}, - { (char *)"nl_pickup", _wrap_nl_pickup, METH_VARARGS, NULL}, - { (char *)"nl_socket_alloc", (PyCFunction)_wrap_nl_socket_alloc, METH_NOARGS, NULL}, - { (char *)"nl_socket_alloc_cb", (PyCFunction)_wrap_nl_socket_alloc_cb, METH_O, NULL}, - { (char *)"nl_socket_free", (PyCFunction)_wrap_nl_socket_free, METH_O, NULL}, - { (char *)"nl_socket_get_local_port", (PyCFunction)_wrap_nl_socket_get_local_port, METH_O, NULL}, - { (char *)"nl_socket_set_local_port", _wrap_nl_socket_set_local_port, METH_VARARGS, NULL}, - { (char *)"nl_socket_get_peer_port", (PyCFunction)_wrap_nl_socket_get_peer_port, METH_O, NULL}, - { (char *)"nl_socket_set_peer_port", _wrap_nl_socket_set_peer_port, METH_VARARGS, NULL}, - { (char *)"nl_socket_get_peer_groups", (PyCFunction)_wrap_nl_socket_get_peer_groups, METH_O, NULL}, - { (char *)"nl_socket_set_peer_groups", _wrap_nl_socket_set_peer_groups, METH_VARARGS, NULL}, - { (char *)"nl_socket_set_buffer_size", _wrap_nl_socket_set_buffer_size, METH_VARARGS, NULL}, - { (char *)"nlmsg_size", (PyCFunction)_wrap_nlmsg_size, METH_O, NULL}, - { (char *)"nlmsg_total_size", (PyCFunction)_wrap_nlmsg_total_size, METH_O, NULL}, - { (char *)"nlmsg_padlen", (PyCFunction)_wrap_nlmsg_padlen, METH_O, NULL}, - { (char *)"nlmsg_data", (PyCFunction)_wrap_nlmsg_data, METH_O, NULL}, - { (char *)"nlmsg_datalen", (PyCFunction)_wrap_nlmsg_datalen, METH_O, NULL}, - { (char *)"nlmsg_tail", (PyCFunction)_wrap_nlmsg_tail, METH_O, NULL}, - { (char *)"nlmsg_attrdata", _wrap_nlmsg_attrdata, METH_VARARGS, NULL}, - { (char *)"nlmsg_attrlen", _wrap_nlmsg_attrlen, METH_VARARGS, NULL}, - { (char *)"nlmsg_valid_hdr", _wrap_nlmsg_valid_hdr, METH_VARARGS, NULL}, - { (char *)"nlmsg_ok", _wrap_nlmsg_ok, METH_VARARGS, NULL}, - { (char *)"nlmsg_next", _wrap_nlmsg_next, METH_VARARGS, NULL}, - { (char *)"nlmsg_parse", _wrap_nlmsg_parse, METH_VARARGS, NULL}, - { (char *)"nlmsg_find_attr", _wrap_nlmsg_find_attr, METH_VARARGS, NULL}, - { (char *)"nlmsg_validate", _wrap_nlmsg_validate, METH_VARARGS, NULL}, - { (char *)"nlmsg_alloc", (PyCFunction)_wrap_nlmsg_alloc, METH_NOARGS, NULL}, - { (char *)"nlmsg_alloc_size", (PyCFunction)_wrap_nlmsg_alloc_size, METH_O, NULL}, - { (char *)"nlmsg_alloc_simple", _wrap_nlmsg_alloc_simple, METH_VARARGS, NULL}, - { (char *)"nlmsg_set_default_size", (PyCFunction)_wrap_nlmsg_set_default_size, METH_O, NULL}, - { (char *)"nlmsg_inherit", (PyCFunction)_wrap_nlmsg_inherit, METH_O, NULL}, - { (char *)"nlmsg_convert", (PyCFunction)_wrap_nlmsg_convert, METH_O, NULL}, - { (char *)"nlmsg_reserve", _wrap_nlmsg_reserve, METH_VARARGS, NULL}, - { (char *)"nlmsg_append", _wrap_nlmsg_append, METH_VARARGS, NULL}, - { (char *)"nlmsg_expand", _wrap_nlmsg_expand, METH_VARARGS, NULL}, - { (char *)"nlmsg_put", _wrap_nlmsg_put, METH_VARARGS, NULL}, - { (char *)"nlmsg_hdr", (PyCFunction)_wrap_nlmsg_hdr, METH_O, NULL}, - { (char *)"nlmsg_get", (PyCFunction)_wrap_nlmsg_get, METH_O, NULL}, - { (char *)"nlmsg_free", (PyCFunction)_wrap_nlmsg_free, METH_O, NULL}, - { (char *)"nlmsg_set_proto", _wrap_nlmsg_set_proto, METH_VARARGS, NULL}, - { (char *)"nlmsg_get_proto", (PyCFunction)_wrap_nlmsg_get_proto, METH_O, NULL}, - { (char *)"nlmsg_get_max_size", (PyCFunction)_wrap_nlmsg_get_max_size, METH_O, NULL}, - { (char *)"nlmsg_set_src", _wrap_nlmsg_set_src, METH_VARARGS, NULL}, - { (char *)"nlmsg_get_src", (PyCFunction)_wrap_nlmsg_get_src, METH_O, NULL}, - { (char *)"nlmsg_set_dst", _wrap_nlmsg_set_dst, METH_VARARGS, NULL}, - { (char *)"nlmsg_get_dst", (PyCFunction)_wrap_nlmsg_get_dst, METH_O, NULL}, - { (char *)"nlmsg_set_creds", _wrap_nlmsg_set_creds, METH_VARARGS, NULL}, - { (char *)"nlmsg_get_creds", (PyCFunction)_wrap_nlmsg_get_creds, METH_O, NULL}, - { (char *)"nl_nlmsgtype2str", _wrap_nl_nlmsgtype2str, METH_VARARGS, NULL}, - { (char *)"nl_str2nlmsgtype", (PyCFunction)_wrap_nl_str2nlmsgtype, METH_O, NULL}, - { (char *)"nl_nlmsg_flags2str", _wrap_nl_nlmsg_flags2str, METH_VARARGS, NULL}, - { (char *)"nl_msg_parse", _wrap_nl_msg_parse, METH_VARARGS, NULL}, - { (char *)"nl_msg_dump", _wrap_nl_msg_dump, METH_VARARGS, NULL}, - { (char *)"cast_obj", (PyCFunction)_wrap_cast_obj, METH_O, NULL}, - { (char *)"object_alloc_name", (PyCFunction)_wrap_object_alloc_name, METH_O, NULL}, - { (char *)"nl_object_alloc", (PyCFunction)_wrap_nl_object_alloc, METH_O, NULL}, - { (char *)"nl_object_free", (PyCFunction)_wrap_nl_object_free, METH_O, NULL}, - { (char *)"nl_object_clone", (PyCFunction)_wrap_nl_object_clone, METH_O, NULL}, - { (char *)"nl_object_get", (PyCFunction)_wrap_nl_object_get, METH_O, NULL}, - { (char *)"nl_object_put", (PyCFunction)_wrap_nl_object_put, METH_O, NULL}, - { (char *)"nl_object_shared", (PyCFunction)_wrap_nl_object_shared, METH_O, NULL}, - { (char *)"nl_object_dump_buf", _wrap_nl_object_dump_buf, METH_VARARGS, NULL}, - { (char *)"nl_object_dump", _wrap_nl_object_dump, METH_VARARGS, NULL}, - { (char *)"nl_object_identical", _wrap_nl_object_identical, METH_VARARGS, NULL}, - { (char *)"nl_object_diff", _wrap_nl_object_diff, METH_VARARGS, NULL}, - { (char *)"nl_object_match_filter", _wrap_nl_object_match_filter, METH_VARARGS, NULL}, - { (char *)"nl_object_attrs2str", _wrap_nl_object_attrs2str, METH_VARARGS, NULL}, - { (char *)"nl_object_attr_list", _wrap_nl_object_attr_list, METH_VARARGS, NULL}, - { (char *)"nl_object_mark", (PyCFunction)_wrap_nl_object_mark, METH_O, NULL}, - { (char *)"nl_object_unmark", (PyCFunction)_wrap_nl_object_unmark, METH_O, NULL}, - { (char *)"nl_object_is_marked", (PyCFunction)_wrap_nl_object_is_marked, METH_O, NULL}, - { (char *)"nl_object_get_refcnt", (PyCFunction)_wrap_nl_object_get_refcnt, METH_O, NULL}, - { (char *)"alloc_cache_name", (PyCFunction)_wrap_alloc_cache_name, METH_O, NULL}, - { (char *)"alloc_cache_mngr", _wrap_alloc_cache_mngr, METH_VARARGS, NULL}, - { (char *)"cache_mngr_add", _wrap_cache_mngr_add, METH_VARARGS, NULL}, - { (char *)"nl_cache_nitems", (PyCFunction)_wrap_nl_cache_nitems, METH_O, NULL}, - { (char *)"nl_cache_nitems_filter", _wrap_nl_cache_nitems_filter, METH_VARARGS, NULL}, - { (char *)"nl_cache_get_ops", (PyCFunction)_wrap_nl_cache_get_ops, METH_O, NULL}, - { (char *)"nl_cache_get_first", (PyCFunction)_wrap_nl_cache_get_first, METH_O, NULL}, - { (char *)"nl_cache_get_last", (PyCFunction)_wrap_nl_cache_get_last, METH_O, NULL}, - { (char *)"nl_cache_get_next", (PyCFunction)_wrap_nl_cache_get_next, METH_O, NULL}, - { (char *)"nl_cache_get_prev", (PyCFunction)_wrap_nl_cache_get_prev, METH_O, NULL}, - { (char *)"nl_cache_alloc", (PyCFunction)_wrap_nl_cache_alloc, METH_O, NULL}, - { (char *)"nl_cache_subset", _wrap_nl_cache_subset, METH_VARARGS, NULL}, - { (char *)"nl_cache_clear", (PyCFunction)_wrap_nl_cache_clear, METH_O, NULL}, - { (char *)"nl_cache_free", (PyCFunction)_wrap_nl_cache_free, METH_O, NULL}, - { (char *)"nl_cache_add", _wrap_nl_cache_add, METH_VARARGS, NULL}, - { (char *)"nl_cache_parse_and_add", _wrap_nl_cache_parse_and_add, METH_VARARGS, NULL}, - { (char *)"nl_cache_remove", (PyCFunction)_wrap_nl_cache_remove, METH_O, NULL}, - { (char *)"nl_cache_refill", _wrap_nl_cache_refill, METH_VARARGS, NULL}, - { (char *)"nl_cache_pickup", _wrap_nl_cache_pickup, METH_VARARGS, NULL}, - { (char *)"nl_cache_resync", _wrap_nl_cache_resync, METH_VARARGS, NULL}, - { (char *)"nl_cache_include", _wrap_nl_cache_include, METH_VARARGS, NULL}, - { (char *)"nl_cache_set_arg1", _wrap_nl_cache_set_arg1, METH_VARARGS, NULL}, - { (char *)"nl_cache_set_arg2", _wrap_nl_cache_set_arg2, METH_VARARGS, NULL}, - { (char *)"nl_cache_is_empty", (PyCFunction)_wrap_nl_cache_is_empty, METH_O, NULL}, - { (char *)"nl_cache_search", _wrap_nl_cache_search, METH_VARARGS, NULL}, - { (char *)"nl_cache_mark_all", (PyCFunction)_wrap_nl_cache_mark_all, METH_O, NULL}, - { (char *)"nl_cache_dump", _wrap_nl_cache_dump, METH_VARARGS, NULL}, - { (char *)"nl_cache_dump_filter", _wrap_nl_cache_dump_filter, METH_VARARGS, NULL}, - { (char *)"nl_cache_foreach", _wrap_nl_cache_foreach, METH_VARARGS, NULL}, - { (char *)"nl_cache_foreach_filter", _wrap_nl_cache_foreach_filter, METH_VARARGS, NULL}, - { (char *)"nl_cache_ops_lookup", (PyCFunction)_wrap_nl_cache_ops_lookup, METH_O, NULL}, - { (char *)"nl_cache_ops_associate", _wrap_nl_cache_ops_associate, METH_VARARGS, NULL}, - { (char *)"nl_msgtype_lookup", _wrap_nl_msgtype_lookup, METH_VARARGS, NULL}, - { (char *)"nl_cache_ops_foreach", _wrap_nl_cache_ops_foreach, METH_VARARGS, NULL}, - { (char *)"nl_cache_mngt_register", (PyCFunction)_wrap_nl_cache_mngt_register, METH_O, NULL}, - { (char *)"nl_cache_mngt_unregister", (PyCFunction)_wrap_nl_cache_mngt_unregister, METH_O, NULL}, - { (char *)"nl_cache_mngt_provide", (PyCFunction)_wrap_nl_cache_mngt_provide, METH_O, NULL}, - { (char *)"nl_cache_mngt_unprovide", (PyCFunction)_wrap_nl_cache_mngt_unprovide, METH_O, NULL}, - { (char *)"nl_cache_mngt_require", (PyCFunction)_wrap_nl_cache_mngt_require, METH_O, NULL}, - { (char *)"nl_cache_mngr_get_fd", (PyCFunction)_wrap_nl_cache_mngr_get_fd, METH_O, NULL}, - { (char *)"nl_cache_mngr_poll", _wrap_nl_cache_mngr_poll, METH_VARARGS, NULL}, - { (char *)"nl_cache_mngr_data_ready", (PyCFunction)_wrap_nl_cache_mngr_data_ready, METH_O, NULL}, - { (char *)"nl_cache_mngr_free", (PyCFunction)_wrap_nl_cache_mngr_free, METH_O, NULL}, - { (char *)"addr_parse", _wrap_addr_parse, METH_VARARGS, NULL}, - { (char *)"nl_addr_alloc", (PyCFunction)_wrap_nl_addr_alloc, METH_O, NULL}, - { (char *)"nl_addr_alloc_attr", _wrap_nl_addr_alloc_attr, METH_VARARGS, NULL}, - { (char *)"nl_addr_build", _wrap_nl_addr_build, METH_VARARGS, NULL}, - { (char *)"nl_addr_clone", (PyCFunction)_wrap_nl_addr_clone, METH_O, NULL}, - { (char *)"nl_addr_get", (PyCFunction)_wrap_nl_addr_get, METH_O, NULL}, - { (char *)"nl_addr_put", (PyCFunction)_wrap_nl_addr_put, METH_O, NULL}, - { (char *)"nl_addr_shared", (PyCFunction)_wrap_nl_addr_shared, METH_O, NULL}, - { (char *)"nl_addr_cmp", _wrap_nl_addr_cmp, METH_VARARGS, NULL}, - { (char *)"nl_addr_cmp_prefix", _wrap_nl_addr_cmp_prefix, METH_VARARGS, NULL}, - { (char *)"nl_addr_iszero", (PyCFunction)_wrap_nl_addr_iszero, METH_O, NULL}, - { (char *)"nl_addr_valid", _wrap_nl_addr_valid, METH_VARARGS, NULL}, - { (char *)"nl_addr_guess_family", (PyCFunction)_wrap_nl_addr_guess_family, METH_O, NULL}, - { (char *)"nl_addr_fill_sockaddr", _wrap_nl_addr_fill_sockaddr, METH_VARARGS, NULL}, - { (char *)"nl_addr_info", _wrap_nl_addr_info, METH_VARARGS, NULL}, - { (char *)"nl_addr_resolve", _wrap_nl_addr_resolve, METH_VARARGS, NULL}, - { (char *)"nl_addr_set_family", _wrap_nl_addr_set_family, METH_VARARGS, NULL}, - { (char *)"nl_addr_get_family", (PyCFunction)_wrap_nl_addr_get_family, METH_O, NULL}, - { (char *)"nl_addr_set_binary_addr", _wrap_nl_addr_set_binary_addr, METH_VARARGS, NULL}, - { (char *)"nl_addr_get_binary_addr", (PyCFunction)_wrap_nl_addr_get_binary_addr, METH_O, NULL}, - { (char *)"nl_addr_get_len", (PyCFunction)_wrap_nl_addr_get_len, METH_O, NULL}, - { (char *)"nl_addr_set_prefixlen", _wrap_nl_addr_set_prefixlen, METH_VARARGS, NULL}, - { (char *)"nl_addr_get_prefixlen", (PyCFunction)_wrap_nl_addr_get_prefixlen, METH_O, NULL}, - { (char *)"nl_af2str", _wrap_nl_af2str, METH_VARARGS, NULL}, - { (char *)"nl_str2af", (PyCFunction)_wrap_nl_str2af, METH_O, NULL}, - { (char *)"nl_addr2str", _wrap_nl_addr2str, METH_VARARGS, NULL}, - { NULL, NULL, 0, NULL } -}; - - -/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */ - -static swig_type_info _swigt__p_FILE = {"_p_FILE", "FILE *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_char = {"_p_char", "char *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_f_p_struct_nl_cache_ops_p_struct_sockaddr_nl_p_struct_nlmsghdr_p_struct_nl_parser_param__int = {"_p_f_p_struct_nl_cache_ops_p_struct_sockaddr_nl_p_struct_nlmsghdr_p_struct_nl_parser_param__int", "int (*)(struct nl_cache_ops *,struct sockaddr_nl *,struct nlmsghdr *,struct nl_parser_param *)", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_f_p_struct_nl_cache_ops_p_void__void = {"_p_f_p_struct_nl_cache_ops_p_void__void", "void (*)(struct nl_cache_ops *,void *)", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_f_p_struct_nl_cache_p_struct_nl_object_int_p_void__void = {"_p_f_p_struct_nl_cache_p_struct_nl_object_int_p_void__void", "void (*)(struct nl_cache *,struct nl_object *,int,void *)|change_func_t", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_f_p_struct_nl_dump_params_int__void = {"_p_f_p_struct_nl_dump_params_int__void", "void (*)(struct nl_dump_params *,int)", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_f_p_struct_nl_dump_params_p_char__void = {"_p_f_p_struct_nl_dump_params_p_char__void", "void (*)(struct nl_dump_params *,char *)", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_f_p_struct_nl_object_p_void__void = {"_p_f_p_struct_nl_object_p_void__void", "void (*)(struct nl_object *,void *)", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_int = {"_p_int", "intptr_t *|int *|int_least32_t *|int_fast32_t *|int32_t *|int_fast16_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_long_long = {"_p_long_long", "int_least64_t *|int_fast64_t *|int64_t *|long long *|intmax_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_nl_addr = {"_p_nl_addr", "struct nl_addr *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_nl_cache = {"_p_nl_cache", "struct nl_cache *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_nl_cache_mngr = {"_p_nl_cache_mngr", "struct nl_cache_mngr *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_nl_cache_ops = {"_p_nl_cache_ops", "struct nl_cache_ops *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_nl_cb = {"_p_nl_cb", "struct nl_cb *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_nl_dump_params = {"_p_nl_dump_params", "struct nl_dump_params *|nl_dump_params *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_nl_msg = {"_p_nl_msg", "struct nl_msg *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_nl_msgtype = {"_p_nl_msgtype", "struct nl_msgtype *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_nl_object = {"_p_nl_object", "struct nl_object *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_nl_object_ops = {"_p_nl_object_ops", "struct nl_object_ops *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_nl_sock = {"_p_nl_sock", "struct nl_sock *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_nla_policy = {"_p_nla_policy", "struct nla_policy *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_nlattr = {"_p_nlattr", "struct nlattr *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_nlmsghdr = {"_p_nlmsghdr", "struct nlmsghdr *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_p_addrinfo = {"_p_p_addrinfo", "struct addrinfo **", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_p_char = {"_p_p_char", "char **", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_p_nl_object = {"_p_p_nl_object", "struct nl_object **", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_p_nlattr = {"_p_p_nlattr", "struct nlattr **", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_short = {"_p_short", "short *|int_least16_t *|int16_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_signed_char = {"_p_signed_char", "signed char *|int_least8_t *|int_fast8_t *|int8_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_sockaddr = {"_p_sockaddr", "struct sockaddr *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_sockaddr_nl = {"_p_sockaddr_nl", "struct sockaddr_nl *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_socklen_t = {"_p_socklen_t", "socklen_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_ucred = {"_p_ucred", "struct ucred *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_unsigned_char = {"_p_unsigned_char", "unsigned char *|uint_least8_t *|uint_fast8_t *|uint8_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_unsigned_int = {"_p_unsigned_int", "uintptr_t *|uint_least32_t *|uint_fast32_t *|uint32_t *|unsigned int *|uint_fast16_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_unsigned_long_long = {"_p_unsigned_long_long", "uint_least64_t *|uint_fast64_t *|uint64_t *|unsigned long long *|uintmax_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_unsigned_short = {"_p_unsigned_short", "unsigned short *|uint_least16_t *|uint16_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_void = {"_p_void", "void *", 0, 0, (void*)0, 0}; - -static swig_type_info *swig_type_initial[] = { - &_swigt__p_FILE, - &_swigt__p_char, - &_swigt__p_f_p_struct_nl_cache_ops_p_struct_sockaddr_nl_p_struct_nlmsghdr_p_struct_nl_parser_param__int, - &_swigt__p_f_p_struct_nl_cache_ops_p_void__void, - &_swigt__p_f_p_struct_nl_cache_p_struct_nl_object_int_p_void__void, - &_swigt__p_f_p_struct_nl_dump_params_int__void, - &_swigt__p_f_p_struct_nl_dump_params_p_char__void, - &_swigt__p_f_p_struct_nl_object_p_void__void, - &_swigt__p_int, - &_swigt__p_long_long, - &_swigt__p_nl_addr, - &_swigt__p_nl_cache, - &_swigt__p_nl_cache_mngr, - &_swigt__p_nl_cache_ops, - &_swigt__p_nl_cb, - &_swigt__p_nl_dump_params, - &_swigt__p_nl_msg, - &_swigt__p_nl_msgtype, - &_swigt__p_nl_object, - &_swigt__p_nl_object_ops, - &_swigt__p_nl_sock, - &_swigt__p_nla_policy, - &_swigt__p_nlattr, - &_swigt__p_nlmsghdr, - &_swigt__p_p_addrinfo, - &_swigt__p_p_char, - &_swigt__p_p_nl_object, - &_swigt__p_p_nlattr, - &_swigt__p_short, - &_swigt__p_signed_char, - &_swigt__p_sockaddr, - &_swigt__p_sockaddr_nl, - &_swigt__p_socklen_t, - &_swigt__p_ucred, - &_swigt__p_unsigned_char, - &_swigt__p_unsigned_int, - &_swigt__p_unsigned_long_long, - &_swigt__p_unsigned_short, - &_swigt__p_void, -}; - -static swig_cast_info _swigc__p_FILE[] = { {&_swigt__p_FILE, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_char[] = { {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_f_p_struct_nl_cache_ops_p_struct_sockaddr_nl_p_struct_nlmsghdr_p_struct_nl_parser_param__int[] = { {&_swigt__p_f_p_struct_nl_cache_ops_p_struct_sockaddr_nl_p_struct_nlmsghdr_p_struct_nl_parser_param__int, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_f_p_struct_nl_cache_ops_p_void__void[] = { {&_swigt__p_f_p_struct_nl_cache_ops_p_void__void, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_f_p_struct_nl_cache_p_struct_nl_object_int_p_void__void[] = { {&_swigt__p_f_p_struct_nl_cache_p_struct_nl_object_int_p_void__void, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_f_p_struct_nl_dump_params_int__void[] = { {&_swigt__p_f_p_struct_nl_dump_params_int__void, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_f_p_struct_nl_dump_params_p_char__void[] = { {&_swigt__p_f_p_struct_nl_dump_params_p_char__void, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_f_p_struct_nl_object_p_void__void[] = { {&_swigt__p_f_p_struct_nl_object_p_void__void, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_int[] = { {&_swigt__p_int, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_long_long[] = { {&_swigt__p_long_long, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_nl_addr[] = { {&_swigt__p_nl_addr, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_nl_cache[] = { {&_swigt__p_nl_cache, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_nl_cache_mngr[] = { {&_swigt__p_nl_cache_mngr, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_nl_cache_ops[] = { {&_swigt__p_nl_cache_ops, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_nl_cb[] = { {&_swigt__p_nl_cb, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_nl_dump_params[] = { {&_swigt__p_nl_dump_params, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_nl_msg[] = { {&_swigt__p_nl_msg, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_nl_msgtype[] = { {&_swigt__p_nl_msgtype, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_nl_object[] = { {&_swigt__p_nl_object, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_nl_object_ops[] = { {&_swigt__p_nl_object_ops, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_nl_sock[] = { {&_swigt__p_nl_sock, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_nla_policy[] = { {&_swigt__p_nla_policy, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_nlattr[] = { {&_swigt__p_nlattr, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_nlmsghdr[] = { {&_swigt__p_nlmsghdr, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_p_addrinfo[] = { {&_swigt__p_p_addrinfo, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_p_char[] = { {&_swigt__p_p_char, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_p_nl_object[] = { {&_swigt__p_p_nl_object, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_p_nlattr[] = { {&_swigt__p_p_nlattr, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_short[] = { {&_swigt__p_short, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_signed_char[] = { {&_swigt__p_signed_char, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_sockaddr[] = { {&_swigt__p_sockaddr, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_sockaddr_nl[] = { {&_swigt__p_sockaddr_nl, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_socklen_t[] = { {&_swigt__p_socklen_t, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_ucred[] = { {&_swigt__p_ucred, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_unsigned_char[] = { {&_swigt__p_unsigned_char, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_unsigned_int[] = { {&_swigt__p_unsigned_int, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_unsigned_long_long[] = { {&_swigt__p_unsigned_long_long, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_unsigned_short[] = { {&_swigt__p_unsigned_short, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_void[] = { {&_swigt__p_void, 0, 0, 0},{0, 0, 0, 0}}; - -static swig_cast_info *swig_cast_initial[] = { - _swigc__p_FILE, - _swigc__p_char, - _swigc__p_f_p_struct_nl_cache_ops_p_struct_sockaddr_nl_p_struct_nlmsghdr_p_struct_nl_parser_param__int, - _swigc__p_f_p_struct_nl_cache_ops_p_void__void, - _swigc__p_f_p_struct_nl_cache_p_struct_nl_object_int_p_void__void, - _swigc__p_f_p_struct_nl_dump_params_int__void, - _swigc__p_f_p_struct_nl_dump_params_p_char__void, - _swigc__p_f_p_struct_nl_object_p_void__void, - _swigc__p_int, - _swigc__p_long_long, - _swigc__p_nl_addr, - _swigc__p_nl_cache, - _swigc__p_nl_cache_mngr, - _swigc__p_nl_cache_ops, - _swigc__p_nl_cb, - _swigc__p_nl_dump_params, - _swigc__p_nl_msg, - _swigc__p_nl_msgtype, - _swigc__p_nl_object, - _swigc__p_nl_object_ops, - _swigc__p_nl_sock, - _swigc__p_nla_policy, - _swigc__p_nlattr, - _swigc__p_nlmsghdr, - _swigc__p_p_addrinfo, - _swigc__p_p_char, - _swigc__p_p_nl_object, - _swigc__p_p_nlattr, - _swigc__p_short, - _swigc__p_signed_char, - _swigc__p_sockaddr, - _swigc__p_sockaddr_nl, - _swigc__p_socklen_t, - _swigc__p_ucred, - _swigc__p_unsigned_char, - _swigc__p_unsigned_int, - _swigc__p_unsigned_long_long, - _swigc__p_unsigned_short, - _swigc__p_void, -}; - - -/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */ - -static swig_const_info swig_const_table[] = { -{0, 0, 0, 0.0, 0, 0}}; - -#ifdef __cplusplus -} -#endif -/* ----------------------------------------------------------------------------- - * Type initialization: - * This problem is tough by the requirement that no dynamic - * memory is used. Also, since swig_type_info structures store pointers to - * swig_cast_info structures and swig_cast_info structures store pointers back - * to swig_type_info structures, we need some lookup code at initialization. - * The idea is that swig generates all the structures that are needed. - * The runtime then collects these partially filled structures. - * The SWIG_InitializeModule function takes these initial arrays out of - * swig_module, and does all the lookup, filling in the swig_module.types - * array with the correct data and linking the correct swig_cast_info - * structures together. - * - * The generated swig_type_info structures are assigned staticly to an initial - * array. We just loop through that array, and handle each type individually. - * First we lookup if this type has been already loaded, and if so, use the - * loaded structure instead of the generated one. Then we have to fill in the - * cast linked list. The cast data is initially stored in something like a - * two-dimensional array. Each row corresponds to a type (there are the same - * number of rows as there are in the swig_type_initial array). Each entry in - * a column is one of the swig_cast_info structures for that type. - * The cast_initial array is actually an array of arrays, because each row has - * a variable number of columns. So to actually build the cast linked list, - * we find the array of casts associated with the type, and loop through it - * adding the casts to the list. The one last trick we need to do is making - * sure the type pointer in the swig_cast_info struct is correct. - * - * First off, we lookup the cast->type name to see if it is already loaded. - * There are three cases to handle: - * 1) If the cast->type has already been loaded AND the type we are adding - * casting info to has not been loaded (it is in this module), THEN we - * replace the cast->type pointer with the type pointer that has already - * been loaded. - * 2) If BOTH types (the one we are adding casting info to, and the - * cast->type) are loaded, THEN the cast info has already been loaded by - * the previous module so we just ignore it. - * 3) Finally, if cast->type has not already been loaded, then we add that - * swig_cast_info to the linked list (because the cast->type) pointer will - * be correct. - * ----------------------------------------------------------------------------- */ - -#ifdef __cplusplus -extern "C" { -#if 0 -} /* c-mode */ -#endif -#endif - -#if 0 -#define SWIGRUNTIME_DEBUG -#endif - - -SWIGRUNTIME void -SWIG_InitializeModule(void *clientdata) { - size_t i; - swig_module_info *module_head, *iter; - int found, init; - - clientdata = clientdata; - - /* check to see if the circular list has been setup, if not, set it up */ - if (swig_module.next==0) { - /* Initialize the swig_module */ - swig_module.type_initial = swig_type_initial; - swig_module.cast_initial = swig_cast_initial; - swig_module.next = &swig_module; - init = 1; - } else { - init = 0; - } - - /* Try and load any already created modules */ - module_head = SWIG_GetModule(clientdata); - if (!module_head) { - /* This is the first module loaded for this interpreter */ - /* so set the swig module into the interpreter */ - SWIG_SetModule(clientdata, &swig_module); - module_head = &swig_module; - } else { - /* the interpreter has loaded a SWIG module, but has it loaded this one? */ - found=0; - iter=module_head; - do { - if (iter==&swig_module) { - found=1; - break; - } - iter=iter->next; - } while (iter!= module_head); - - /* if the is found in the list, then all is done and we may leave */ - if (found) return; - /* otherwise we must add out module into the list */ - swig_module.next = module_head->next; - module_head->next = &swig_module; - } - - /* When multiple interpeters are used, a module could have already been initialized in - a different interpreter, but not yet have a pointer in this interpreter. - In this case, we do not want to continue adding types... everything should be - set up already */ - if (init == 0) return; - - /* Now work on filling in swig_module.types */ -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: size %d\n", swig_module.size); -#endif - for (i = 0; i < swig_module.size; ++i) { - swig_type_info *type = 0; - swig_type_info *ret; - swig_cast_info *cast; - -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name); -#endif - - /* if there is another module already loaded */ - if (swig_module.next != &swig_module) { - type = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, swig_module.type_initial[i]->name); - } - if (type) { - /* Overwrite clientdata field */ -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: found type %s\n", type->name); -#endif - if (swig_module.type_initial[i]->clientdata) { - type->clientdata = swig_module.type_initial[i]->clientdata; -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: found and overwrite type %s \n", type->name); -#endif - } - } else { - type = swig_module.type_initial[i]; - } - - /* Insert casting types */ - cast = swig_module.cast_initial[i]; - while (cast->type) { - /* Don't need to add information already in the list */ - ret = 0; -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: look cast %s\n", cast->type->name); -#endif - if (swig_module.next != &swig_module) { - ret = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, cast->type->name); -#ifdef SWIGRUNTIME_DEBUG - if (ret) printf("SWIG_InitializeModule: found cast %s\n", ret->name); -#endif - } - if (ret) { - if (type == swig_module.type_initial[i]) { -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: skip old type %s\n", ret->name); -#endif - cast->type = ret; - ret = 0; - } else { - /* Check for casting already in the list */ - swig_cast_info *ocast = SWIG_TypeCheck(ret->name, type); -#ifdef SWIGRUNTIME_DEBUG - if (ocast) printf("SWIG_InitializeModule: skip old cast %s\n", ret->name); -#endif - if (!ocast) ret = 0; - } - } - - if (!ret) { -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: adding cast %s\n", cast->type->name); -#endif - if (type->cast) { - type->cast->prev = cast; - cast->next = type->cast; - } - type->cast = cast; - } - cast++; - } - /* Set entry in modules->types array equal to the type */ - swig_module.types[i] = type; - } - swig_module.types[i] = 0; - -#ifdef SWIGRUNTIME_DEBUG - printf("**** SWIG_InitializeModule: Cast List ******\n"); - for (i = 0; i < swig_module.size; ++i) { - int j = 0; - swig_cast_info *cast = swig_module.cast_initial[i]; - printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name); - while (cast->type) { - printf("SWIG_InitializeModule: cast type %s\n", cast->type->name); - cast++; - ++j; - } - printf("---- Total casts: %d\n",j); - } - printf("**** SWIG_InitializeModule: Cast List ******\n"); -#endif -} - -/* This function will propagate the clientdata field of type to -* any new swig_type_info structures that have been added into the list -* of equivalent types. It is like calling -* SWIG_TypeClientData(type, clientdata) a second time. -*/ -SWIGRUNTIME void -SWIG_PropagateClientData(void) { - size_t i; - swig_cast_info *equiv; - static int init_run = 0; - - if (init_run) return; - init_run = 1; - - for (i = 0; i < swig_module.size; i++) { - if (swig_module.types[i]->clientdata) { - equiv = swig_module.types[i]->cast; - while (equiv) { - if (!equiv->converter) { - if (equiv->type && !equiv->type->clientdata) - SWIG_TypeClientData(equiv->type, swig_module.types[i]->clientdata); - } - equiv = equiv->next; - } - } - } -} - -#ifdef __cplusplus -#if 0 -{ - /* c-mode */ -#endif -} -#endif - - - -#ifdef __cplusplus -extern "C" { -#endif - - /* Python-specific SWIG API */ -#define SWIG_newvarlink() SWIG_Python_newvarlink() -#define SWIG_addvarlink(p, name, get_attr, set_attr) SWIG_Python_addvarlink(p, name, get_attr, set_attr) -#define SWIG_InstallConstants(d, constants) SWIG_Python_InstallConstants(d, constants) - - /* ----------------------------------------------------------------------------- - * global variable support code. - * ----------------------------------------------------------------------------- */ - - typedef struct swig_globalvar { - char *name; /* Name of global variable */ - PyObject *(*get_attr)(void); /* Return the current value */ - int (*set_attr)(PyObject *); /* Set the value */ - struct swig_globalvar *next; - } swig_globalvar; - - typedef struct swig_varlinkobject { - PyObject_HEAD - swig_globalvar *vars; - } swig_varlinkobject; - - SWIGINTERN PyObject * - swig_varlink_repr(swig_varlinkobject *SWIGUNUSEDPARM(v)) { -#if PY_VERSION_HEX >= 0x03000000 - return PyUnicode_InternFromString(""); -#else - return PyString_FromString(""); -#endif - } - - SWIGINTERN PyObject * - swig_varlink_str(swig_varlinkobject *v) { -#if PY_VERSION_HEX >= 0x03000000 - PyObject *str = PyUnicode_InternFromString("("); - PyObject *tail; - PyObject *joined; - swig_globalvar *var; - for (var = v->vars; var; var=var->next) { - tail = PyUnicode_FromString(var->name); - joined = PyUnicode_Concat(str, tail); - Py_DecRef(str); - Py_DecRef(tail); - str = joined; - if (var->next) { - tail = PyUnicode_InternFromString(", "); - joined = PyUnicode_Concat(str, tail); - Py_DecRef(str); - Py_DecRef(tail); - str = joined; - } - } - tail = PyUnicode_InternFromString(")"); - joined = PyUnicode_Concat(str, tail); - Py_DecRef(str); - Py_DecRef(tail); - str = joined; -#else - PyObject *str = PyString_FromString("("); - swig_globalvar *var; - for (var = v->vars; var; var=var->next) { - PyString_ConcatAndDel(&str,PyString_FromString(var->name)); - if (var->next) PyString_ConcatAndDel(&str,PyString_FromString(", ")); - } - PyString_ConcatAndDel(&str,PyString_FromString(")")); -#endif - return str; - } - - SWIGINTERN int - swig_varlink_print(swig_varlinkobject *v, FILE *fp, int SWIGUNUSEDPARM(flags)) { - char *tmp; - PyObject *str = swig_varlink_str(v); - fprintf(fp,"Swig global variables "); - fprintf(fp,"%s\n", tmp = SWIG_Python_str_AsChar(str)); - SWIG_Python_str_DelForPy3(tmp); - Py_DECREF(str); - return 0; - } - - SWIGINTERN void - swig_varlink_dealloc(swig_varlinkobject *v) { - swig_globalvar *var = v->vars; - while (var) { - swig_globalvar *n = var->next; - free(var->name); - free(var); - var = n; - } - } - - SWIGINTERN PyObject * - swig_varlink_getattr(swig_varlinkobject *v, char *n) { - PyObject *res = NULL; - swig_globalvar *var = v->vars; - while (var) { - if (strcmp(var->name,n) == 0) { - res = (*var->get_attr)(); - break; - } - var = var->next; - } - if (res == NULL && !PyErr_Occurred()) { - PyErr_SetString(PyExc_NameError,"Unknown C global variable"); - } - return res; - } - - SWIGINTERN int - swig_varlink_setattr(swig_varlinkobject *v, char *n, PyObject *p) { - int res = 1; - swig_globalvar *var = v->vars; - while (var) { - if (strcmp(var->name,n) == 0) { - res = (*var->set_attr)(p); - break; - } - var = var->next; - } - if (res == 1 && !PyErr_Occurred()) { - PyErr_SetString(PyExc_NameError,"Unknown C global variable"); - } - return res; - } - - SWIGINTERN PyTypeObject* - swig_varlink_type(void) { - static char varlink__doc__[] = "Swig var link object"; - static PyTypeObject varlink_type; - static int type_init = 0; - if (!type_init) { - const PyTypeObject tmp - = { - /* PyObject header changed in Python 3 */ -#if PY_VERSION_HEX >= 0x03000000 - PyVarObject_HEAD_INIT(&PyType_Type, 0) -#else - PyObject_HEAD_INIT(NULL) - 0, /* Number of items in variable part (ob_size) */ -#endif - (char *)"swigvarlink", /* Type name (tp_name) */ - sizeof(swig_varlinkobject), /* Basic size (tp_basicsize) */ - 0, /* Itemsize (tp_itemsize) */ - (destructor) swig_varlink_dealloc, /* Deallocator (tp_dealloc) */ - (printfunc) swig_varlink_print, /* Print (tp_print) */ - (getattrfunc) swig_varlink_getattr, /* get attr (tp_getattr) */ - (setattrfunc) swig_varlink_setattr, /* Set attr (tp_setattr) */ - 0, /* tp_compare */ - (reprfunc) swig_varlink_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - (reprfunc) swig_varlink_str, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - 0, /* tp_flags */ - varlink__doc__, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ -#if PY_VERSION_HEX >= 0x02020000 - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* tp_iter -> tp_weaklist */ -#endif -#if PY_VERSION_HEX >= 0x02030000 - 0, /* tp_del */ -#endif -#ifdef COUNT_ALLOCS - 0,0,0,0 /* tp_alloc -> tp_next */ -#endif - }; - varlink_type = tmp; - /* for Python 3 we already assigned ob_type in PyVarObject_HEAD_INIT() */ -#if PY_VERSION_HEX < 0x03000000 - varlink_type.ob_type = &PyType_Type; -#endif - type_init = 1; - } - return &varlink_type; - } - - /* Create a variable linking object for use later */ - SWIGINTERN PyObject * - SWIG_Python_newvarlink(void) { - swig_varlinkobject *result = PyObject_NEW(swig_varlinkobject, swig_varlink_type()); - if (result) { - result->vars = 0; - } - return ((PyObject*) result); - } - - SWIGINTERN void - SWIG_Python_addvarlink(PyObject *p, char *name, PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p)) { - swig_varlinkobject *v = (swig_varlinkobject *) p; - swig_globalvar *gv = (swig_globalvar *) malloc(sizeof(swig_globalvar)); - if (gv) { - size_t size = strlen(name)+1; - gv->name = (char *)malloc(size); - if (gv->name) { - strncpy(gv->name,name,size); - gv->get_attr = get_attr; - gv->set_attr = set_attr; - gv->next = v->vars; - } - } - v->vars = gv; - } - - SWIGINTERN PyObject * - SWIG_globals(void) { - static PyObject *_SWIG_globals = 0; - if (!_SWIG_globals) _SWIG_globals = SWIG_newvarlink(); - return _SWIG_globals; - } - - /* ----------------------------------------------------------------------------- - * constants/methods manipulation - * ----------------------------------------------------------------------------- */ - - /* Install Constants */ - SWIGINTERN void - SWIG_Python_InstallConstants(PyObject *d, swig_const_info constants[]) { - PyObject *obj = 0; - size_t i; - for (i = 0; constants[i].type; ++i) { - switch(constants[i].type) { - case SWIG_PY_POINTER: - obj = SWIG_NewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0); - break; - case SWIG_PY_BINARY: - obj = SWIG_NewPackedObj(constants[i].pvalue, constants[i].lvalue, *(constants[i].ptype)); - break; - default: - obj = 0; - break; - } - if (obj) { - PyDict_SetItemString(d, constants[i].name, obj); - Py_DECREF(obj); - } - } - } - - /* -----------------------------------------------------------------------------*/ - /* Fix SwigMethods to carry the callback ptrs when needed */ - /* -----------------------------------------------------------------------------*/ - - SWIGINTERN void - SWIG_Python_FixMethods(PyMethodDef *methods, - swig_const_info *const_table, - swig_type_info **types, - swig_type_info **types_initial) { - size_t i; - for (i = 0; methods[i].ml_name; ++i) { - const char *c = methods[i].ml_doc; - if (c && (c = strstr(c, "swig_ptr: "))) { - int j; - swig_const_info *ci = 0; - const char *name = c + 10; - for (j = 0; const_table[j].type; ++j) { - if (strncmp(const_table[j].name, name, - strlen(const_table[j].name)) == 0) { - ci = &(const_table[j]); - break; - } - } - if (ci) { - size_t shift = (ci->ptype) - types; - swig_type_info *ty = types_initial[shift]; - size_t ldoc = (c - methods[i].ml_doc); - size_t lptr = strlen(ty->name)+2*sizeof(void*)+2; - char *ndoc = (char*)malloc(ldoc + lptr + 10); - if (ndoc) { - char *buff = ndoc; - void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue : 0; - if (ptr) { - strncpy(buff, methods[i].ml_doc, ldoc); - buff += ldoc; - strncpy(buff, "swig_ptr: ", 10); - buff += 10; - SWIG_PackVoidPtr(buff, ptr, ty->name, lptr); - methods[i].ml_doc = ndoc; - } - } - } - } - } - } - -#ifdef __cplusplus -} -#endif - -/* -----------------------------------------------------------------------------* - * Partial Init method - * -----------------------------------------------------------------------------*/ - -#ifdef __cplusplus -extern "C" -#endif - -SWIGEXPORT -#if PY_VERSION_HEX >= 0x03000000 -PyObject* -#else -void -#endif -SWIG_init(void) { - PyObject *m, *d; -#if PY_VERSION_HEX >= 0x03000000 - static struct PyModuleDef SWIG_module = { - PyModuleDef_HEAD_INIT, - (char *) SWIG_name, - NULL, - -1, - SwigMethods, - NULL, - NULL, - NULL, - NULL - }; -#endif - - /* Fix SwigMethods to carry the callback ptrs when needed */ - SWIG_Python_FixMethods(SwigMethods, swig_const_table, swig_types, swig_type_initial); - -#if PY_VERSION_HEX >= 0x03000000 - m = PyModule_Create(&SWIG_module); -#else - m = Py_InitModule((char *) SWIG_name, SwigMethods); -#endif - d = PyModule_GetDict(m); - - SWIG_InitializeModule(0); - SWIG_InstallConstants(d,swig_const_table); - - - SWIG_Python_SetConstant(d, "NL_DUMP_LINE",SWIG_From_int((int)(NL_DUMP_LINE))); - SWIG_Python_SetConstant(d, "NL_DUMP_DETAILS",SWIG_From_int((int)(NL_DUMP_DETAILS))); - SWIG_Python_SetConstant(d, "NL_DUMP_STATS",SWIG_From_int((int)(NL_DUMP_STATS))); - SWIG_Python_SetConstant(d, "__NL_DUMP_MAX",SWIG_From_int((int)(__NL_DUMP_MAX))); - SWIG_Python_SetConstant(d, "NL_AUTO_PROVIDE",SWIG_From_int((int)(1))); -#if PY_VERSION_HEX >= 0x03000000 - return m; -#else - return; -#endif -} - diff --git a/python/netlink/route/capi.py b/python/netlink/route/capi.py deleted file mode 100644 index 66356a5..0000000 --- a/python/netlink/route/capi.py +++ /dev/null @@ -1,830 +0,0 @@ -# This file was automatically generated by SWIG (http://www.swig.org). -# Version 1.3.40 -# -# Do not make changes to this file unless you know what you are doing--modify -# the SWIG interface file instead. - -from sys import version_info -if version_info >= (3,0,0): - new_instancemethod = lambda func, inst, cls: _capi.SWIG_PyInstanceMethod_New(func) -else: - from new import instancemethod as new_instancemethod -if version_info >= (2,6,0): - def swig_import_helper(): - from os.path import dirname - import imp - fp = None - try: - fp, pathname, description = imp.find_module('_capi', [dirname(__file__)]) - except ImportError: - import _capi - return _capi - if fp is not None: - try: - _mod = imp.load_module('_capi', fp, pathname, description) - finally: - fp.close() - return _mod - _capi = swig_import_helper() - del swig_import_helper -else: - import _capi -del version_info -try: - _swig_property = property -except NameError: - pass # Python < 2.2 doesn't have 'property'. -def _swig_setattr_nondynamic(self,class_type,name,value,static=1): - if (name == "thisown"): return self.this.own(value) - if (name == "this"): - if type(value).__name__ == 'SwigPyObject': - self.__dict__[name] = value - return - method = class_type.__swig_setmethods__.get(name,None) - if method: return method(self,value) - if (not static) or hasattr(self,name): - self.__dict__[name] = value - else: - raise AttributeError("You cannot add attributes to %s" % self) - -def _swig_setattr(self,class_type,name,value): - return _swig_setattr_nondynamic(self,class_type,name,value,0) - -def _swig_getattr(self,class_type,name): - if (name == "thisown"): return self.this.own() - method = class_type.__swig_getmethods__.get(name,None) - if method: return method(self) - raise AttributeError(name) - -def _swig_repr(self): - try: strthis = "proxy of " + self.this.__repr__() - except: strthis = "" - return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,) - -try: - _object = object - _newclass = 1 -except AttributeError: - class _object : pass - _newclass = 0 - - -def _swig_setattr_nondynamic_method(set): - def set_attr(self,name,value): - if (name == "thisown"): return self.this.own(value) - if hasattr(self,name) or (name == "this"): - set(self,name,value) - else: - raise AttributeError("You cannot add attributes to %s" % self) - return set_attr - - - -def link2obj(*args): - return _capi.link2obj(*args) -link2obj = _capi.link2obj - -def obj2link(*args): - return _capi.obj2link(*args) -obj2link = _capi.obj2link - -def get_from_kernel(*args): - return _capi.get_from_kernel(*args) -get_from_kernel = _capi.get_from_kernel - -def inet_get_conf(*args): - return _capi.inet_get_conf(*args) -inet_get_conf = _capi.inet_get_conf - -def rtnl_scope2str(*args): - return _capi.rtnl_scope2str(*args) -rtnl_scope2str = _capi.rtnl_scope2str - -def rtnl_str2scope(*args): - return _capi.rtnl_str2scope(*args) -rtnl_str2scope = _capi.rtnl_str2scope - -def rtnl_link_alloc(): - return _capi.rtnl_link_alloc() -rtnl_link_alloc = _capi.rtnl_link_alloc - -def rtnl_link_get(*args): - return _capi.rtnl_link_get(*args) -rtnl_link_get = _capi.rtnl_link_get - -def rtnl_link_get_by_name(*args): - return _capi.rtnl_link_get_by_name(*args) -rtnl_link_get_by_name = _capi.rtnl_link_get_by_name - -def rtnl_link_build_add_request(*args): - return _capi.rtnl_link_build_add_request(*args) -rtnl_link_build_add_request = _capi.rtnl_link_build_add_request - -def rtnl_link_add(*args): - return _capi.rtnl_link_add(*args) -rtnl_link_add = _capi.rtnl_link_add - -def rtnl_link_build_change_request(*args): - return _capi.rtnl_link_build_change_request(*args) -rtnl_link_build_change_request = _capi.rtnl_link_build_change_request - -def rtnl_link_change(*args): - return _capi.rtnl_link_change(*args) -rtnl_link_change = _capi.rtnl_link_change - -def rtnl_link_build_delete_request(*args): - return _capi.rtnl_link_build_delete_request(*args) -rtnl_link_build_delete_request = _capi.rtnl_link_build_delete_request - -def rtnl_link_delete(*args): - return _capi.rtnl_link_delete(*args) -rtnl_link_delete = _capi.rtnl_link_delete - -def rtnl_link_build_get_request(*args): - return _capi.rtnl_link_build_get_request(*args) -rtnl_link_build_get_request = _capi.rtnl_link_build_get_request - -def rtnl_link_stat2str(*args): - return _capi.rtnl_link_stat2str(*args) -rtnl_link_stat2str = _capi.rtnl_link_stat2str - -def rtnl_link_str2stat(*args): - return _capi.rtnl_link_str2stat(*args) -rtnl_link_str2stat = _capi.rtnl_link_str2stat - -def rtnl_link_flags2str(*args): - return _capi.rtnl_link_flags2str(*args) -rtnl_link_flags2str = _capi.rtnl_link_flags2str - -def rtnl_link_str2flags(*args): - return _capi.rtnl_link_str2flags(*args) -rtnl_link_str2flags = _capi.rtnl_link_str2flags - -def rtnl_link_operstate2str(*args): - return _capi.rtnl_link_operstate2str(*args) -rtnl_link_operstate2str = _capi.rtnl_link_operstate2str - -def rtnl_link_str2operstate(*args): - return _capi.rtnl_link_str2operstate(*args) -rtnl_link_str2operstate = _capi.rtnl_link_str2operstate - -def rtnl_link_mode2str(*args): - return _capi.rtnl_link_mode2str(*args) -rtnl_link_mode2str = _capi.rtnl_link_mode2str - -def rtnl_link_str2mode(*args): - return _capi.rtnl_link_str2mode(*args) -rtnl_link_str2mode = _capi.rtnl_link_str2mode - -def rtnl_link_set_qdisc(*args): - return _capi.rtnl_link_set_qdisc(*args) -rtnl_link_set_qdisc = _capi.rtnl_link_set_qdisc - -def rtnl_link_get_qdisc(*args): - return _capi.rtnl_link_get_qdisc(*args) -rtnl_link_get_qdisc = _capi.rtnl_link_get_qdisc - -def rtnl_link_set_name(*args): - return _capi.rtnl_link_set_name(*args) -rtnl_link_set_name = _capi.rtnl_link_set_name - -def rtnl_link_get_name(*args): - return _capi.rtnl_link_get_name(*args) -rtnl_link_get_name = _capi.rtnl_link_get_name - -def rtnl_link_set_flags(*args): - return _capi.rtnl_link_set_flags(*args) -rtnl_link_set_flags = _capi.rtnl_link_set_flags - -def rtnl_link_unset_flags(*args): - return _capi.rtnl_link_unset_flags(*args) -rtnl_link_unset_flags = _capi.rtnl_link_unset_flags - -def rtnl_link_get_flags(*args): - return _capi.rtnl_link_get_flags(*args) -rtnl_link_get_flags = _capi.rtnl_link_get_flags - -def rtnl_link_set_mtu(*args): - return _capi.rtnl_link_set_mtu(*args) -rtnl_link_set_mtu = _capi.rtnl_link_set_mtu - -def rtnl_link_get_mtu(*args): - return _capi.rtnl_link_get_mtu(*args) -rtnl_link_get_mtu = _capi.rtnl_link_get_mtu - -def rtnl_link_set_txqlen(*args): - return _capi.rtnl_link_set_txqlen(*args) -rtnl_link_set_txqlen = _capi.rtnl_link_set_txqlen - -def rtnl_link_get_txqlen(*args): - return _capi.rtnl_link_get_txqlen(*args) -rtnl_link_get_txqlen = _capi.rtnl_link_get_txqlen - -def rtnl_link_set_weight(*args): - return _capi.rtnl_link_set_weight(*args) -rtnl_link_set_weight = _capi.rtnl_link_set_weight - -def rtnl_link_get_weight(*args): - return _capi.rtnl_link_get_weight(*args) -rtnl_link_get_weight = _capi.rtnl_link_get_weight - -def rtnl_link_set_ifindex(*args): - return _capi.rtnl_link_set_ifindex(*args) -rtnl_link_set_ifindex = _capi.rtnl_link_set_ifindex - -def rtnl_link_get_ifindex(*args): - return _capi.rtnl_link_get_ifindex(*args) -rtnl_link_get_ifindex = _capi.rtnl_link_get_ifindex - -def rtnl_link_set_family(*args): - return _capi.rtnl_link_set_family(*args) -rtnl_link_set_family = _capi.rtnl_link_set_family - -def rtnl_link_get_family(*args): - return _capi.rtnl_link_get_family(*args) -rtnl_link_get_family = _capi.rtnl_link_get_family - -def rtnl_link_set_arptype(*args): - return _capi.rtnl_link_set_arptype(*args) -rtnl_link_set_arptype = _capi.rtnl_link_set_arptype - -def rtnl_link_get_arptype(*args): - return _capi.rtnl_link_get_arptype(*args) -rtnl_link_get_arptype = _capi.rtnl_link_get_arptype - -def rtnl_link_set_addr(*args): - return _capi.rtnl_link_set_addr(*args) -rtnl_link_set_addr = _capi.rtnl_link_set_addr - -def rtnl_link_get_addr(*args): - return _capi.rtnl_link_get_addr(*args) -rtnl_link_get_addr = _capi.rtnl_link_get_addr - -def rtnl_link_set_broadcast(*args): - return _capi.rtnl_link_set_broadcast(*args) -rtnl_link_set_broadcast = _capi.rtnl_link_set_broadcast - -def rtnl_link_get_broadcast(*args): - return _capi.rtnl_link_get_broadcast(*args) -rtnl_link_get_broadcast = _capi.rtnl_link_get_broadcast - -def rtnl_link_set_link(*args): - return _capi.rtnl_link_set_link(*args) -rtnl_link_set_link = _capi.rtnl_link_set_link - -def rtnl_link_get_link(*args): - return _capi.rtnl_link_get_link(*args) -rtnl_link_get_link = _capi.rtnl_link_get_link - -def rtnl_link_set_master(*args): - return _capi.rtnl_link_set_master(*args) -rtnl_link_set_master = _capi.rtnl_link_set_master - -def rtnl_link_get_master(*args): - return _capi.rtnl_link_get_master(*args) -rtnl_link_get_master = _capi.rtnl_link_get_master - -def rtnl_link_set_operstate(*args): - return _capi.rtnl_link_set_operstate(*args) -rtnl_link_set_operstate = _capi.rtnl_link_set_operstate - -def rtnl_link_get_operstate(*args): - return _capi.rtnl_link_get_operstate(*args) -rtnl_link_get_operstate = _capi.rtnl_link_get_operstate - -def rtnl_link_set_linkmode(*args): - return _capi.rtnl_link_set_linkmode(*args) -rtnl_link_set_linkmode = _capi.rtnl_link_set_linkmode - -def rtnl_link_get_linkmode(*args): - return _capi.rtnl_link_get_linkmode(*args) -rtnl_link_get_linkmode = _capi.rtnl_link_get_linkmode - -def rtnl_link_get_ifalias(*args): - return _capi.rtnl_link_get_ifalias(*args) -rtnl_link_get_ifalias = _capi.rtnl_link_get_ifalias - -def rtnl_link_set_ifalias(*args): - return _capi.rtnl_link_set_ifalias(*args) -rtnl_link_set_ifalias = _capi.rtnl_link_set_ifalias - -def rtnl_link_get_num_vf(*args): - return _capi.rtnl_link_get_num_vf(*args) -rtnl_link_get_num_vf = _capi.rtnl_link_get_num_vf - -def rtnl_link_get_stat(*args): - return _capi.rtnl_link_get_stat(*args) -rtnl_link_get_stat = _capi.rtnl_link_get_stat - -def rtnl_link_set_stat(*args): - return _capi.rtnl_link_set_stat(*args) -rtnl_link_set_stat = _capi.rtnl_link_set_stat - -def rtnl_link_set_info_type(*args): - return _capi.rtnl_link_set_info_type(*args) -rtnl_link_set_info_type = _capi.rtnl_link_set_info_type - -def rtnl_link_get_info_type(*args): - return _capi.rtnl_link_get_info_type(*args) -rtnl_link_get_info_type = _capi.rtnl_link_get_info_type -class vlan_map(object): - thisown = _swig_property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag') - def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined") - __repr__ = _swig_repr - vm_from = _swig_property(_capi.vlan_map_vm_from_get, _capi.vlan_map_vm_from_set) - vm_to = _swig_property(_capi.vlan_map_vm_to_get, _capi.vlan_map_vm_to_set) - __swig_destroy__ = _capi.delete_vlan_map -vlan_map_swigregister = _capi.vlan_map_swigregister -vlan_map_swigregister(vlan_map) - -VLAN_PRIO_MAX = _capi.VLAN_PRIO_MAX - -def rtnl_link_vlan_flags2str(*args): - return _capi.rtnl_link_vlan_flags2str(*args) -rtnl_link_vlan_flags2str = _capi.rtnl_link_vlan_flags2str - -def rtnl_link_vlan_str2flags(*args): - return _capi.rtnl_link_vlan_str2flags(*args) -rtnl_link_vlan_str2flags = _capi.rtnl_link_vlan_str2flags - -def rtnl_link_vlan_set_id(*args): - return _capi.rtnl_link_vlan_set_id(*args) -rtnl_link_vlan_set_id = _capi.rtnl_link_vlan_set_id - -def rtnl_link_vlan_get_id(*args): - return _capi.rtnl_link_vlan_get_id(*args) -rtnl_link_vlan_get_id = _capi.rtnl_link_vlan_get_id - -def rtnl_link_vlan_set_flags(*args): - return _capi.rtnl_link_vlan_set_flags(*args) -rtnl_link_vlan_set_flags = _capi.rtnl_link_vlan_set_flags - -def rtnl_link_vlan_unset_flags(*args): - return _capi.rtnl_link_vlan_unset_flags(*args) -rtnl_link_vlan_unset_flags = _capi.rtnl_link_vlan_unset_flags - -def rtnl_link_vlan_get_flags(*args): - return _capi.rtnl_link_vlan_get_flags(*args) -rtnl_link_vlan_get_flags = _capi.rtnl_link_vlan_get_flags - -def rtnl_link_vlan_set_ingress_map(*args): - return _capi.rtnl_link_vlan_set_ingress_map(*args) -rtnl_link_vlan_set_ingress_map = _capi.rtnl_link_vlan_set_ingress_map - -def rtnl_link_vlan_get_ingress_map(*args): - return _capi.rtnl_link_vlan_get_ingress_map(*args) -rtnl_link_vlan_get_ingress_map = _capi.rtnl_link_vlan_get_ingress_map - -def rtnl_link_vlan_set_egress_map(*args): - return _capi.rtnl_link_vlan_set_egress_map(*args) -rtnl_link_vlan_set_egress_map = _capi.rtnl_link_vlan_set_egress_map - -def rtnl_link_vlan_get_egress_map(*args): - return _capi.rtnl_link_vlan_get_egress_map(*args) -rtnl_link_vlan_get_egress_map = _capi.rtnl_link_vlan_get_egress_map - -def rtnl_link_inet_devconf2str(*args): - return _capi.rtnl_link_inet_devconf2str(*args) -rtnl_link_inet_devconf2str = _capi.rtnl_link_inet_devconf2str - -def rtnl_link_inet_str2devconf(*args): - return _capi.rtnl_link_inet_str2devconf(*args) -rtnl_link_inet_str2devconf = _capi.rtnl_link_inet_str2devconf - -def rtnl_link_inet_set_conf(*args): - return _capi.rtnl_link_inet_set_conf(*args) -rtnl_link_inet_set_conf = _capi.rtnl_link_inet_set_conf - -def tc_str2handle(*args): - return _capi.tc_str2handle(*args) -tc_str2handle = _capi.tc_str2handle - -def rtnl_tc_set_ifindex(*args): - return _capi.rtnl_tc_set_ifindex(*args) -rtnl_tc_set_ifindex = _capi.rtnl_tc_set_ifindex - -def rtnl_tc_get_ifindex(*args): - return _capi.rtnl_tc_get_ifindex(*args) -rtnl_tc_get_ifindex = _capi.rtnl_tc_get_ifindex - -def rtnl_tc_set_link(*args): - return _capi.rtnl_tc_set_link(*args) -rtnl_tc_set_link = _capi.rtnl_tc_set_link - -def rtnl_tc_get_link(*args): - return _capi.rtnl_tc_get_link(*args) -rtnl_tc_get_link = _capi.rtnl_tc_get_link - -def rtnl_tc_set_mtu(*args): - return _capi.rtnl_tc_set_mtu(*args) -rtnl_tc_set_mtu = _capi.rtnl_tc_set_mtu - -def rtnl_tc_get_mtu(*args): - return _capi.rtnl_tc_get_mtu(*args) -rtnl_tc_get_mtu = _capi.rtnl_tc_get_mtu - -def rtnl_tc_set_mpu(*args): - return _capi.rtnl_tc_set_mpu(*args) -rtnl_tc_set_mpu = _capi.rtnl_tc_set_mpu - -def rtnl_tc_get_mpu(*args): - return _capi.rtnl_tc_get_mpu(*args) -rtnl_tc_get_mpu = _capi.rtnl_tc_get_mpu - -def rtnl_tc_set_overhead(*args): - return _capi.rtnl_tc_set_overhead(*args) -rtnl_tc_set_overhead = _capi.rtnl_tc_set_overhead - -def rtnl_tc_get_overhead(*args): - return _capi.rtnl_tc_get_overhead(*args) -rtnl_tc_get_overhead = _capi.rtnl_tc_get_overhead - -def rtnl_tc_set_linktype(*args): - return _capi.rtnl_tc_set_linktype(*args) -rtnl_tc_set_linktype = _capi.rtnl_tc_set_linktype - -def rtnl_tc_get_linktype(*args): - return _capi.rtnl_tc_get_linktype(*args) -rtnl_tc_get_linktype = _capi.rtnl_tc_get_linktype - -def rtnl_tc_set_handle(*args): - return _capi.rtnl_tc_set_handle(*args) -rtnl_tc_set_handle = _capi.rtnl_tc_set_handle - -def rtnl_tc_get_handle(*args): - return _capi.rtnl_tc_get_handle(*args) -rtnl_tc_get_handle = _capi.rtnl_tc_get_handle - -def rtnl_tc_set_parent(*args): - return _capi.rtnl_tc_set_parent(*args) -rtnl_tc_set_parent = _capi.rtnl_tc_set_parent - -def rtnl_tc_get_parent(*args): - return _capi.rtnl_tc_get_parent(*args) -rtnl_tc_get_parent = _capi.rtnl_tc_get_parent - -def rtnl_tc_set_kind(*args): - return _capi.rtnl_tc_set_kind(*args) -rtnl_tc_set_kind = _capi.rtnl_tc_set_kind - -def rtnl_tc_get_kind(*args): - return _capi.rtnl_tc_get_kind(*args) -rtnl_tc_get_kind = _capi.rtnl_tc_get_kind - -def rtnl_tc_get_stat(*args): - return _capi.rtnl_tc_get_stat(*args) -rtnl_tc_get_stat = _capi.rtnl_tc_get_stat - -def rtnl_tc_calc_txtime(*args): - return _capi.rtnl_tc_calc_txtime(*args) -rtnl_tc_calc_txtime = _capi.rtnl_tc_calc_txtime - -def rtnl_tc_calc_bufsize(*args): - return _capi.rtnl_tc_calc_bufsize(*args) -rtnl_tc_calc_bufsize = _capi.rtnl_tc_calc_bufsize - -def rtnl_tc_calc_cell_log(*args): - return _capi.rtnl_tc_calc_cell_log(*args) -rtnl_tc_calc_cell_log = _capi.rtnl_tc_calc_cell_log - -def rtnl_tc_read_classid_file(): - return _capi.rtnl_tc_read_classid_file() -rtnl_tc_read_classid_file = _capi.rtnl_tc_read_classid_file - -def rtnl_tc_handle2str(*args): - return _capi.rtnl_tc_handle2str(*args) -rtnl_tc_handle2str = _capi.rtnl_tc_handle2str - -def rtnl_classid_generate(*args): - return _capi.rtnl_classid_generate(*args) -rtnl_classid_generate = _capi.rtnl_classid_generate - -def qdisc2obj(*args): - return _capi.qdisc2obj(*args) -qdisc2obj = _capi.qdisc2obj - -def obj2qdisc(*args): - return _capi.obj2qdisc(*args) -obj2qdisc = _capi.obj2qdisc - -def class2obj(*args): - return _capi.class2obj(*args) -class2obj = _capi.class2obj - -def obj2class(*args): - return _capi.obj2class(*args) -obj2class = _capi.obj2class - -def cls2obj(*args): - return _capi.cls2obj(*args) -cls2obj = _capi.cls2obj - -def obj2cls(*args): - return _capi.obj2cls(*args) -obj2cls = _capi.obj2cls - -def obj2tc(*args): - return _capi.obj2tc(*args) -obj2tc = _capi.obj2tc - -def rtnl_qdisc_alloc(): - return _capi.rtnl_qdisc_alloc() -rtnl_qdisc_alloc = _capi.rtnl_qdisc_alloc - -def rtnl_qdisc_get(*args): - return _capi.rtnl_qdisc_get(*args) -rtnl_qdisc_get = _capi.rtnl_qdisc_get - -def rtnl_qdisc_get_by_parent(*args): - return _capi.rtnl_qdisc_get_by_parent(*args) -rtnl_qdisc_get_by_parent = _capi.rtnl_qdisc_get_by_parent - -def rtnl_qdisc_build_add_request(*args): - return _capi.rtnl_qdisc_build_add_request(*args) -rtnl_qdisc_build_add_request = _capi.rtnl_qdisc_build_add_request - -def rtnl_qdisc_add(*args): - return _capi.rtnl_qdisc_add(*args) -rtnl_qdisc_add = _capi.rtnl_qdisc_add - -def rtnl_qdisc_build_update_request(*args): - return _capi.rtnl_qdisc_build_update_request(*args) -rtnl_qdisc_build_update_request = _capi.rtnl_qdisc_build_update_request - -def rtnl_qdisc_update(*args): - return _capi.rtnl_qdisc_update(*args) -rtnl_qdisc_update = _capi.rtnl_qdisc_update - -def rtnl_qdisc_build_delete_request(*args): - return _capi.rtnl_qdisc_build_delete_request(*args) -rtnl_qdisc_build_delete_request = _capi.rtnl_qdisc_build_delete_request - -def rtnl_qdisc_delete(*args): - return _capi.rtnl_qdisc_delete(*args) -rtnl_qdisc_delete = _capi.rtnl_qdisc_delete - -def rtnl_cls_alloc(): - return _capi.rtnl_cls_alloc() -rtnl_cls_alloc = _capi.rtnl_cls_alloc - -def rtnl_cls_put(*args): - return _capi.rtnl_cls_put(*args) -rtnl_cls_put = _capi.rtnl_cls_put - -def rtnl_cls_add(*args): - return _capi.rtnl_cls_add(*args) -rtnl_cls_add = _capi.rtnl_cls_add - -def rtnl_cls_delete(*args): - return _capi.rtnl_cls_delete(*args) -rtnl_cls_delete = _capi.rtnl_cls_delete - -def rtnl_cls_set_prio(*args): - return _capi.rtnl_cls_set_prio(*args) -rtnl_cls_set_prio = _capi.rtnl_cls_set_prio - -def rtnl_cls_get_prio(*args): - return _capi.rtnl_cls_get_prio(*args) -rtnl_cls_get_prio = _capi.rtnl_cls_get_prio - -def rtnl_cls_set_protocol(*args): - return _capi.rtnl_cls_set_protocol(*args) -rtnl_cls_set_protocol = _capi.rtnl_cls_set_protocol - -def rtnl_cls_get_protocol(*args): - return _capi.rtnl_cls_get_protocol(*args) -rtnl_cls_get_protocol = _capi.rtnl_cls_get_protocol - -def rtnl_htb_get_rate2quantum(*args): - return _capi.rtnl_htb_get_rate2quantum(*args) -rtnl_htb_get_rate2quantum = _capi.rtnl_htb_get_rate2quantum - -def rtnl_htb_set_rate2quantum(*args): - return _capi.rtnl_htb_set_rate2quantum(*args) -rtnl_htb_set_rate2quantum = _capi.rtnl_htb_set_rate2quantum - -def rtnl_htb_get_defcls(*args): - return _capi.rtnl_htb_get_defcls(*args) -rtnl_htb_get_defcls = _capi.rtnl_htb_get_defcls - -def rtnl_htb_set_defcls(*args): - return _capi.rtnl_htb_set_defcls(*args) -rtnl_htb_set_defcls = _capi.rtnl_htb_set_defcls - -def rtnl_htb_get_prio(*args): - return _capi.rtnl_htb_get_prio(*args) -rtnl_htb_get_prio = _capi.rtnl_htb_get_prio - -def rtnl_htb_set_prio(*args): - return _capi.rtnl_htb_set_prio(*args) -rtnl_htb_set_prio = _capi.rtnl_htb_set_prio - -def rtnl_htb_get_rate(*args): - return _capi.rtnl_htb_get_rate(*args) -rtnl_htb_get_rate = _capi.rtnl_htb_get_rate - -def rtnl_htb_set_rate(*args): - return _capi.rtnl_htb_set_rate(*args) -rtnl_htb_set_rate = _capi.rtnl_htb_set_rate - -def rtnl_htb_get_ceil(*args): - return _capi.rtnl_htb_get_ceil(*args) -rtnl_htb_get_ceil = _capi.rtnl_htb_get_ceil - -def rtnl_htb_set_ceil(*args): - return _capi.rtnl_htb_set_ceil(*args) -rtnl_htb_set_ceil = _capi.rtnl_htb_set_ceil - -def rtnl_htb_get_rbuffer(*args): - return _capi.rtnl_htb_get_rbuffer(*args) -rtnl_htb_get_rbuffer = _capi.rtnl_htb_get_rbuffer - -def rtnl_htb_set_rbuffer(*args): - return _capi.rtnl_htb_set_rbuffer(*args) -rtnl_htb_set_rbuffer = _capi.rtnl_htb_set_rbuffer - -def rtnl_htb_get_cbuffer(*args): - return _capi.rtnl_htb_get_cbuffer(*args) -rtnl_htb_get_cbuffer = _capi.rtnl_htb_get_cbuffer - -def rtnl_htb_set_cbuffer(*args): - return _capi.rtnl_htb_set_cbuffer(*args) -rtnl_htb_set_cbuffer = _capi.rtnl_htb_set_cbuffer - -def rtnl_htb_get_quantum(*args): - return _capi.rtnl_htb_get_quantum(*args) -rtnl_htb_get_quantum = _capi.rtnl_htb_get_quantum - -def rtnl_htb_set_quantum(*args): - return _capi.rtnl_htb_set_quantum(*args) -rtnl_htb_set_quantum = _capi.rtnl_htb_set_quantum - -def rtnl_htb_get_level(*args): - return _capi.rtnl_htb_get_level(*args) -rtnl_htb_get_level = _capi.rtnl_htb_get_level - -def addr2obj(*args): - return _capi.addr2obj(*args) -addr2obj = _capi.addr2obj - -def obj2addr(*args): - return _capi.obj2addr(*args) -obj2addr = _capi.obj2addr - -def rtnl_addr_alloc(): - return _capi.rtnl_addr_alloc() -rtnl_addr_alloc = _capi.rtnl_addr_alloc - -def rtnl_addr_get(*args): - return _capi.rtnl_addr_get(*args) -rtnl_addr_get = _capi.rtnl_addr_get - -def rtnl_addr_build_add_request(*args): - return _capi.rtnl_addr_build_add_request(*args) -rtnl_addr_build_add_request = _capi.rtnl_addr_build_add_request - -def rtnl_addr_add(*args): - return _capi.rtnl_addr_add(*args) -rtnl_addr_add = _capi.rtnl_addr_add - -def rtnl_addr_build_delete_request(*args): - return _capi.rtnl_addr_build_delete_request(*args) -rtnl_addr_build_delete_request = _capi.rtnl_addr_build_delete_request - -def rtnl_addr_delete(*args): - return _capi.rtnl_addr_delete(*args) -rtnl_addr_delete = _capi.rtnl_addr_delete - -def rtnl_addr_flags2str(*args): - return _capi.rtnl_addr_flags2str(*args) -rtnl_addr_flags2str = _capi.rtnl_addr_flags2str - -def rtnl_addr_str2flags(*args): - return _capi.rtnl_addr_str2flags(*args) -rtnl_addr_str2flags = _capi.rtnl_addr_str2flags - -def rtnl_addr_set_label(*args): - return _capi.rtnl_addr_set_label(*args) -rtnl_addr_set_label = _capi.rtnl_addr_set_label - -def rtnl_addr_get_label(*args): - return _capi.rtnl_addr_get_label(*args) -rtnl_addr_get_label = _capi.rtnl_addr_get_label - -def rtnl_addr_set_ifindex(*args): - return _capi.rtnl_addr_set_ifindex(*args) -rtnl_addr_set_ifindex = _capi.rtnl_addr_set_ifindex - -def rtnl_addr_get_ifindex(*args): - return _capi.rtnl_addr_get_ifindex(*args) -rtnl_addr_get_ifindex = _capi.rtnl_addr_get_ifindex - -def rtnl_addr_set_link(*args): - return _capi.rtnl_addr_set_link(*args) -rtnl_addr_set_link = _capi.rtnl_addr_set_link - -def rtnl_addr_get_link(*args): - return _capi.rtnl_addr_get_link(*args) -rtnl_addr_get_link = _capi.rtnl_addr_get_link - -def rtnl_addr_set_family(*args): - return _capi.rtnl_addr_set_family(*args) -rtnl_addr_set_family = _capi.rtnl_addr_set_family - -def rtnl_addr_get_family(*args): - return _capi.rtnl_addr_get_family(*args) -rtnl_addr_get_family = _capi.rtnl_addr_get_family - -def rtnl_addr_set_prefixlen(*args): - return _capi.rtnl_addr_set_prefixlen(*args) -rtnl_addr_set_prefixlen = _capi.rtnl_addr_set_prefixlen - -def rtnl_addr_get_prefixlen(*args): - return _capi.rtnl_addr_get_prefixlen(*args) -rtnl_addr_get_prefixlen = _capi.rtnl_addr_get_prefixlen - -def rtnl_addr_set_scope(*args): - return _capi.rtnl_addr_set_scope(*args) -rtnl_addr_set_scope = _capi.rtnl_addr_set_scope - -def rtnl_addr_get_scope(*args): - return _capi.rtnl_addr_get_scope(*args) -rtnl_addr_get_scope = _capi.rtnl_addr_get_scope - -def rtnl_addr_set_flags(*args): - return _capi.rtnl_addr_set_flags(*args) -rtnl_addr_set_flags = _capi.rtnl_addr_set_flags - -def rtnl_addr_unset_flags(*args): - return _capi.rtnl_addr_unset_flags(*args) -rtnl_addr_unset_flags = _capi.rtnl_addr_unset_flags - -def rtnl_addr_get_flags(*args): - return _capi.rtnl_addr_get_flags(*args) -rtnl_addr_get_flags = _capi.rtnl_addr_get_flags - -def rtnl_addr_set_local(*args): - return _capi.rtnl_addr_set_local(*args) -rtnl_addr_set_local = _capi.rtnl_addr_set_local - -def rtnl_addr_get_local(*args): - return _capi.rtnl_addr_get_local(*args) -rtnl_addr_get_local = _capi.rtnl_addr_get_local - -def rtnl_addr_set_peer(*args): - return _capi.rtnl_addr_set_peer(*args) -rtnl_addr_set_peer = _capi.rtnl_addr_set_peer - -def rtnl_addr_get_peer(*args): - return _capi.rtnl_addr_get_peer(*args) -rtnl_addr_get_peer = _capi.rtnl_addr_get_peer - -def rtnl_addr_set_broadcast(*args): - return _capi.rtnl_addr_set_broadcast(*args) -rtnl_addr_set_broadcast = _capi.rtnl_addr_set_broadcast - -def rtnl_addr_get_broadcast(*args): - return _capi.rtnl_addr_get_broadcast(*args) -rtnl_addr_get_broadcast = _capi.rtnl_addr_get_broadcast - -def rtnl_addr_set_multicast(*args): - return _capi.rtnl_addr_set_multicast(*args) -rtnl_addr_set_multicast = _capi.rtnl_addr_set_multicast - -def rtnl_addr_get_multicast(*args): - return _capi.rtnl_addr_get_multicast(*args) -rtnl_addr_get_multicast = _capi.rtnl_addr_get_multicast - -def rtnl_addr_set_anycast(*args): - return _capi.rtnl_addr_set_anycast(*args) -rtnl_addr_set_anycast = _capi.rtnl_addr_set_anycast - -def rtnl_addr_get_anycast(*args): - return _capi.rtnl_addr_get_anycast(*args) -rtnl_addr_get_anycast = _capi.rtnl_addr_get_anycast - -def rtnl_addr_get_valid_lifetime(*args): - return _capi.rtnl_addr_get_valid_lifetime(*args) -rtnl_addr_get_valid_lifetime = _capi.rtnl_addr_get_valid_lifetime - -def rtnl_addr_set_valid_lifetime(*args): - return _capi.rtnl_addr_set_valid_lifetime(*args) -rtnl_addr_set_valid_lifetime = _capi.rtnl_addr_set_valid_lifetime - -def rtnl_addr_get_preferred_lifetime(*args): - return _capi.rtnl_addr_get_preferred_lifetime(*args) -rtnl_addr_get_preferred_lifetime = _capi.rtnl_addr_get_preferred_lifetime - -def rtnl_addr_set_preferred_lifetime(*args): - return _capi.rtnl_addr_set_preferred_lifetime(*args) -rtnl_addr_set_preferred_lifetime = _capi.rtnl_addr_set_preferred_lifetime - -def rtnl_addr_get_create_time(*args): - return _capi.rtnl_addr_get_create_time(*args) -rtnl_addr_get_create_time = _capi.rtnl_addr_get_create_time - -def rtnl_addr_get_last_update_time(*args): - return _capi.rtnl_addr_get_last_update_time(*args) -rtnl_addr_get_last_update_time = _capi.rtnl_addr_get_last_update_time - - diff --git a/python/netlink/route/capi_wrap.c b/python/netlink/route/capi_wrap.c deleted file mode 100644 index f560e01..0000000 --- a/python/netlink/route/capi_wrap.c +++ /dev/null @@ -1,9514 +0,0 @@ -/* ---------------------------------------------------------------------------- - * This file was automatically generated by SWIG (http://www.swig.org). - * Version 1.3.40 - * - * This file is not intended to be easily readable and contains a number of - * coding conventions designed to improve portability and efficiency. Do not make - * changes to this file unless you know what you are doing--modify the SWIG - * interface file instead. - * ----------------------------------------------------------------------------- */ - -#define SWIGPYTHON -#define SWIG_PYTHON_NO_BUILD_NONE - -/* ----------------------------------------------------------------------------- - * This section contains generic SWIG labels for method/variable - * declarations/attributes, and other compiler dependent labels. - * ----------------------------------------------------------------------------- */ - -/* template workaround for compilers that cannot correctly implement the C++ standard */ -#ifndef SWIGTEMPLATEDISAMBIGUATOR -# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560) -# define SWIGTEMPLATEDISAMBIGUATOR template -# elif defined(__HP_aCC) -/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */ -/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */ -# define SWIGTEMPLATEDISAMBIGUATOR template -# else -# define SWIGTEMPLATEDISAMBIGUATOR -# endif -#endif - -/* inline attribute */ -#ifndef SWIGINLINE -# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__)) -# define SWIGINLINE inline -# else -# define SWIGINLINE -# endif -#endif - -/* attribute recognised by some compilers to avoid 'unused' warnings */ -#ifndef SWIGUNUSED -# if defined(__GNUC__) -# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) -# define SWIGUNUSED __attribute__ ((__unused__)) -# else -# define SWIGUNUSED -# endif -# elif defined(__ICC) -# define SWIGUNUSED __attribute__ ((__unused__)) -# else -# define SWIGUNUSED -# endif -#endif - -#ifndef SWIG_MSC_UNSUPPRESS_4505 -# if defined(_MSC_VER) -# pragma warning(disable : 4505) /* unreferenced local function has been removed */ -# endif -#endif - -#ifndef SWIGUNUSEDPARM -# ifdef __cplusplus -# define SWIGUNUSEDPARM(p) -# else -# define SWIGUNUSEDPARM(p) p SWIGUNUSED -# endif -#endif - -/* internal SWIG method */ -#ifndef SWIGINTERN -# define SWIGINTERN static SWIGUNUSED -#endif - -/* internal inline SWIG method */ -#ifndef SWIGINTERNINLINE -# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE -#endif - -/* exporting methods */ -#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) -# ifndef GCC_HASCLASSVISIBILITY -# define GCC_HASCLASSVISIBILITY -# endif -#endif - -#ifndef SWIGEXPORT -# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# if defined(STATIC_LINKED) -# define SWIGEXPORT -# else -# define SWIGEXPORT __declspec(dllexport) -# endif -# else -# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY) -# define SWIGEXPORT __attribute__ ((visibility("default"))) -# else -# define SWIGEXPORT -# endif -# endif -#endif - -/* calling conventions for Windows */ -#ifndef SWIGSTDCALL -# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# define SWIGSTDCALL __stdcall -# else -# define SWIGSTDCALL -# endif -#endif - -/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ -#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) -# define _CRT_SECURE_NO_DEPRECATE -#endif - -/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */ -#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE) -# define _SCL_SECURE_NO_DEPRECATE -#endif - - - -/* Python.h has to appear first */ -#include - -/* ----------------------------------------------------------------------------- - * swigrun.swg - * - * This file contains generic C API SWIG runtime support for pointer - * type checking. - * ----------------------------------------------------------------------------- */ - -/* This should only be incremented when either the layout of swig_type_info changes, - or for whatever reason, the runtime changes incompatibly */ -#define SWIG_RUNTIME_VERSION "4" - -/* define SWIG_TYPE_TABLE_NAME as "SWIG_TYPE_TABLE" */ -#ifdef SWIG_TYPE_TABLE -# define SWIG_QUOTE_STRING(x) #x -# define SWIG_EXPAND_AND_QUOTE_STRING(x) SWIG_QUOTE_STRING(x) -# define SWIG_TYPE_TABLE_NAME SWIG_EXPAND_AND_QUOTE_STRING(SWIG_TYPE_TABLE) -#else -# define SWIG_TYPE_TABLE_NAME -#endif - -/* - You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for - creating a static or dynamic library from the SWIG runtime code. - In 99.9% of the cases, SWIG just needs to declare them as 'static'. - - But only do this if strictly necessary, ie, if you have problems - with your compiler or suchlike. -*/ - -#ifndef SWIGRUNTIME -# define SWIGRUNTIME SWIGINTERN -#endif - -#ifndef SWIGRUNTIMEINLINE -# define SWIGRUNTIMEINLINE SWIGRUNTIME SWIGINLINE -#endif - -/* Generic buffer size */ -#ifndef SWIG_BUFFER_SIZE -# define SWIG_BUFFER_SIZE 1024 -#endif - -/* Flags for pointer conversions */ -#define SWIG_POINTER_DISOWN 0x1 -#define SWIG_CAST_NEW_MEMORY 0x2 - -/* Flags for new pointer objects */ -#define SWIG_POINTER_OWN 0x1 - - -/* - Flags/methods for returning states. - - The SWIG conversion methods, as ConvertPtr, return and integer - that tells if the conversion was successful or not. And if not, - an error code can be returned (see swigerrors.swg for the codes). - - Use the following macros/flags to set or process the returning - states. - - In old versions of SWIG, code such as the following was usually written: - - if (SWIG_ConvertPtr(obj,vptr,ty.flags) != -1) { - // success code - } else { - //fail code - } - - Now you can be more explicit: - - int res = SWIG_ConvertPtr(obj,vptr,ty.flags); - if (SWIG_IsOK(res)) { - // success code - } else { - // fail code - } - - which is the same really, but now you can also do - - Type *ptr; - int res = SWIG_ConvertPtr(obj,(void **)(&ptr),ty.flags); - if (SWIG_IsOK(res)) { - // success code - if (SWIG_IsNewObj(res) { - ... - delete *ptr; - } else { - ... - } - } else { - // fail code - } - - I.e., now SWIG_ConvertPtr can return new objects and you can - identify the case and take care of the deallocation. Of course that - also requires SWIG_ConvertPtr to return new result values, such as - - int SWIG_ConvertPtr(obj, ptr,...) { - if () { - if () { - *ptr = ; - return SWIG_NEWOBJ; - } else { - *ptr = ; - return SWIG_OLDOBJ; - } - } else { - return SWIG_BADOBJ; - } - } - - Of course, returning the plain '0(success)/-1(fail)' still works, but you can be - more explicit by returning SWIG_BADOBJ, SWIG_ERROR or any of the - SWIG errors code. - - Finally, if the SWIG_CASTRANK_MODE is enabled, the result code - allows to return the 'cast rank', for example, if you have this - - int food(double) - int fooi(int); - - and you call - - food(1) // cast rank '1' (1 -> 1.0) - fooi(1) // cast rank '0' - - just use the SWIG_AddCast()/SWIG_CheckState() -*/ - -#define SWIG_OK (0) -#define SWIG_ERROR (-1) -#define SWIG_IsOK(r) (r >= 0) -#define SWIG_ArgError(r) ((r != SWIG_ERROR) ? r : SWIG_TypeError) - -/* The CastRankLimit says how many bits are used for the cast rank */ -#define SWIG_CASTRANKLIMIT (1 << 8) -/* The NewMask denotes the object was created (using new/malloc) */ -#define SWIG_NEWOBJMASK (SWIG_CASTRANKLIMIT << 1) -/* The TmpMask is for in/out typemaps that use temporal objects */ -#define SWIG_TMPOBJMASK (SWIG_NEWOBJMASK << 1) -/* Simple returning values */ -#define SWIG_BADOBJ (SWIG_ERROR) -#define SWIG_OLDOBJ (SWIG_OK) -#define SWIG_NEWOBJ (SWIG_OK | SWIG_NEWOBJMASK) -#define SWIG_TMPOBJ (SWIG_OK | SWIG_TMPOBJMASK) -/* Check, add and del mask methods */ -#define SWIG_AddNewMask(r) (SWIG_IsOK(r) ? (r | SWIG_NEWOBJMASK) : r) -#define SWIG_DelNewMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_NEWOBJMASK) : r) -#define SWIG_IsNewObj(r) (SWIG_IsOK(r) && (r & SWIG_NEWOBJMASK)) -#define SWIG_AddTmpMask(r) (SWIG_IsOK(r) ? (r | SWIG_TMPOBJMASK) : r) -#define SWIG_DelTmpMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_TMPOBJMASK) : r) -#define SWIG_IsTmpObj(r) (SWIG_IsOK(r) && (r & SWIG_TMPOBJMASK)) - -/* Cast-Rank Mode */ -#if defined(SWIG_CASTRANK_MODE) -# ifndef SWIG_TypeRank -# define SWIG_TypeRank unsigned long -# endif -# ifndef SWIG_MAXCASTRANK /* Default cast allowed */ -# define SWIG_MAXCASTRANK (2) -# endif -# define SWIG_CASTRANKMASK ((SWIG_CASTRANKLIMIT) -1) -# define SWIG_CastRank(r) (r & SWIG_CASTRANKMASK) -SWIGINTERNINLINE int SWIG_AddCast(int r) { - return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r; -} -SWIGINTERNINLINE int SWIG_CheckState(int r) { - return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0; -} -#else /* no cast-rank mode */ -# define SWIG_AddCast -# define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0) -#endif - - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void *(*swig_converter_func)(void *, int *); -typedef struct swig_type_info *(*swig_dycast_func)(void **); - -/* Structure to store information on one type */ -typedef struct swig_type_info { - const char *name; /* mangled name of this type */ - const char *str; /* human readable name of this type */ - swig_dycast_func dcast; /* dynamic cast function down a hierarchy */ - struct swig_cast_info *cast; /* linked list of types that can cast into this type */ - void *clientdata; /* language specific type data */ - int owndata; /* flag if the structure owns the clientdata */ -} swig_type_info; - -/* Structure to store a type and conversion function used for casting */ -typedef struct swig_cast_info { - swig_type_info *type; /* pointer to type that is equivalent to this type */ - swig_converter_func converter; /* function to cast the void pointers */ - struct swig_cast_info *next; /* pointer to next cast in linked list */ - struct swig_cast_info *prev; /* pointer to the previous cast */ -} swig_cast_info; - -/* Structure used to store module information - * Each module generates one structure like this, and the runtime collects - * all of these structures and stores them in a circularly linked list.*/ -typedef struct swig_module_info { - swig_type_info **types; /* Array of pointers to swig_type_info structures that are in this module */ - size_t size; /* Number of types in this module */ - struct swig_module_info *next; /* Pointer to next element in circularly linked list */ - swig_type_info **type_initial; /* Array of initially generated type structures */ - swig_cast_info **cast_initial; /* Array of initially generated casting structures */ - void *clientdata; /* Language specific module data */ -} swig_module_info; - -/* - Compare two type names skipping the space characters, therefore - "char*" == "char *" and "Class" == "Class", etc. - - Return 0 when the two name types are equivalent, as in - strncmp, but skipping ' '. -*/ -SWIGRUNTIME int -SWIG_TypeNameComp(const char *f1, const char *l1, - const char *f2, const char *l2) { - for (;(f1 != l1) && (f2 != l2); ++f1, ++f2) { - while ((*f1 == ' ') && (f1 != l1)) ++f1; - while ((*f2 == ' ') && (f2 != l2)) ++f2; - if (*f1 != *f2) return (*f1 > *f2) ? 1 : -1; - } - return (int)((l1 - f1) - (l2 - f2)); -} - -/* - Check type equivalence in a name list like ||... - Return 0 if not equal, 1 if equal -*/ -SWIGRUNTIME int -SWIG_TypeEquiv(const char *nb, const char *tb) { - int equiv = 0; - const char* te = tb + strlen(tb); - const char* ne = nb; - while (!equiv && *ne) { - for (nb = ne; *ne; ++ne) { - if (*ne == '|') break; - } - equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0; - if (*ne) ++ne; - } - return equiv; -} - -/* - Check type equivalence in a name list like ||... - Return 0 if equal, -1 if nb < tb, 1 if nb > tb -*/ -SWIGRUNTIME int -SWIG_TypeCompare(const char *nb, const char *tb) { - int equiv = 0; - const char* te = tb + strlen(tb); - const char* ne = nb; - while (!equiv && *ne) { - for (nb = ne; *ne; ++ne) { - if (*ne == '|') break; - } - equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0; - if (*ne) ++ne; - } - return equiv; -} - - -/* - Check the typename -*/ -SWIGRUNTIME swig_cast_info * -SWIG_TypeCheck(const char *c, swig_type_info *ty) { - if (ty) { - swig_cast_info *iter = ty->cast; - while (iter) { - if (strcmp(iter->type->name, c) == 0) { - if (iter == ty->cast) - return iter; - /* Move iter to the top of the linked list */ - iter->prev->next = iter->next; - if (iter->next) - iter->next->prev = iter->prev; - iter->next = ty->cast; - iter->prev = 0; - if (ty->cast) ty->cast->prev = iter; - ty->cast = iter; - return iter; - } - iter = iter->next; - } - } - return 0; -} - -/* - Identical to SWIG_TypeCheck, except strcmp is replaced with a pointer comparison -*/ -SWIGRUNTIME swig_cast_info * -SWIG_TypeCheckStruct(swig_type_info *from, swig_type_info *ty) { - if (ty) { - swig_cast_info *iter = ty->cast; - while (iter) { - if (iter->type == from) { - if (iter == ty->cast) - return iter; - /* Move iter to the top of the linked list */ - iter->prev->next = iter->next; - if (iter->next) - iter->next->prev = iter->prev; - iter->next = ty->cast; - iter->prev = 0; - if (ty->cast) ty->cast->prev = iter; - ty->cast = iter; - return iter; - } - iter = iter->next; - } - } - return 0; -} - -/* - Cast a pointer up an inheritance hierarchy -*/ -SWIGRUNTIMEINLINE void * -SWIG_TypeCast(swig_cast_info *ty, void *ptr, int *newmemory) { - return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr, newmemory); -} - -/* - Dynamic pointer casting. Down an inheritance hierarchy -*/ -SWIGRUNTIME swig_type_info * -SWIG_TypeDynamicCast(swig_type_info *ty, void **ptr) { - swig_type_info *lastty = ty; - if (!ty || !ty->dcast) return ty; - while (ty && (ty->dcast)) { - ty = (*ty->dcast)(ptr); - if (ty) lastty = ty; - } - return lastty; -} - -/* - Return the name associated with this type -*/ -SWIGRUNTIMEINLINE const char * -SWIG_TypeName(const swig_type_info *ty) { - return ty->name; -} - -/* - Return the pretty name associated with this type, - that is an unmangled type name in a form presentable to the user. -*/ -SWIGRUNTIME const char * -SWIG_TypePrettyName(const swig_type_info *type) { - /* The "str" field contains the equivalent pretty names of the - type, separated by vertical-bar characters. We choose - to print the last name, as it is often (?) the most - specific. */ - if (!type) return NULL; - if (type->str != NULL) { - const char *last_name = type->str; - const char *s; - for (s = type->str; *s; s++) - if (*s == '|') last_name = s+1; - return last_name; - } - else - return type->name; -} - -/* - Set the clientdata field for a type -*/ -SWIGRUNTIME void -SWIG_TypeClientData(swig_type_info *ti, void *clientdata) { - swig_cast_info *cast = ti->cast; - /* if (ti->clientdata == clientdata) return; */ - ti->clientdata = clientdata; - - while (cast) { - if (!cast->converter) { - swig_type_info *tc = cast->type; - if (!tc->clientdata) { - SWIG_TypeClientData(tc, clientdata); - } - } - cast = cast->next; - } -} -SWIGRUNTIME void -SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) { - SWIG_TypeClientData(ti, clientdata); - ti->owndata = 1; -} - -/* - Search for a swig_type_info structure only by mangled name - Search is a O(log #types) - - We start searching at module start, and finish searching when start == end. - Note: if start == end at the beginning of the function, we go all the way around - the circular list. -*/ -SWIGRUNTIME swig_type_info * -SWIG_MangledTypeQueryModule(swig_module_info *start, - swig_module_info *end, - const char *name) { - swig_module_info *iter = start; - do { - if (iter->size) { - register size_t l = 0; - register size_t r = iter->size - 1; - do { - /* since l+r >= 0, we can (>> 1) instead (/ 2) */ - register size_t i = (l + r) >> 1; - const char *iname = iter->types[i]->name; - if (iname) { - register int compare = strcmp(name, iname); - if (compare == 0) { - return iter->types[i]; - } else if (compare < 0) { - if (i) { - r = i - 1; - } else { - break; - } - } else if (compare > 0) { - l = i + 1; - } - } else { - break; /* should never happen */ - } - } while (l <= r); - } - iter = iter->next; - } while (iter != end); - return 0; -} - -/* - Search for a swig_type_info structure for either a mangled name or a human readable name. - It first searches the mangled names of the types, which is a O(log #types) - If a type is not found it then searches the human readable names, which is O(#types). - - We start searching at module start, and finish searching when start == end. - Note: if start == end at the beginning of the function, we go all the way around - the circular list. -*/ -SWIGRUNTIME swig_type_info * -SWIG_TypeQueryModule(swig_module_info *start, - swig_module_info *end, - const char *name) { - /* STEP 1: Search the name field using binary search */ - swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name); - if (ret) { - return ret; - } else { - /* STEP 2: If the type hasn't been found, do a complete search - of the str field (the human readable name) */ - swig_module_info *iter = start; - do { - register size_t i = 0; - for (; i < iter->size; ++i) { - if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name))) - return iter->types[i]; - } - iter = iter->next; - } while (iter != end); - } - - /* neither found a match */ - return 0; -} - -/* - Pack binary data into a string -*/ -SWIGRUNTIME char * -SWIG_PackData(char *c, void *ptr, size_t sz) { - static const char hex[17] = "0123456789abcdef"; - register const unsigned char *u = (unsigned char *) ptr; - register const unsigned char *eu = u + sz; - for (; u != eu; ++u) { - register unsigned char uu = *u; - *(c++) = hex[(uu & 0xf0) >> 4]; - *(c++) = hex[uu & 0xf]; - } - return c; -} - -/* - Unpack binary data from a string -*/ -SWIGRUNTIME const char * -SWIG_UnpackData(const char *c, void *ptr, size_t sz) { - register unsigned char *u = (unsigned char *) ptr; - register const unsigned char *eu = u + sz; - for (; u != eu; ++u) { - register char d = *(c++); - register unsigned char uu; - if ((d >= '0') && (d <= '9')) - uu = ((d - '0') << 4); - else if ((d >= 'a') && (d <= 'f')) - uu = ((d - ('a'-10)) << 4); - else - return (char *) 0; - d = *(c++); - if ((d >= '0') && (d <= '9')) - uu |= (d - '0'); - else if ((d >= 'a') && (d <= 'f')) - uu |= (d - ('a'-10)); - else - return (char *) 0; - *u = uu; - } - return c; -} - -/* - Pack 'void *' into a string buffer. -*/ -SWIGRUNTIME char * -SWIG_PackVoidPtr(char *buff, void *ptr, const char *name, size_t bsz) { - char *r = buff; - if ((2*sizeof(void *) + 2) > bsz) return 0; - *(r++) = '_'; - r = SWIG_PackData(r,&ptr,sizeof(void *)); - if (strlen(name) + 1 > (bsz - (r - buff))) return 0; - strcpy(r,name); - return buff; -} - -SWIGRUNTIME const char * -SWIG_UnpackVoidPtr(const char *c, void **ptr, const char *name) { - if (*c != '_') { - if (strcmp(c,"NULL") == 0) { - *ptr = (void *) 0; - return name; - } else { - return 0; - } - } - return SWIG_UnpackData(++c,ptr,sizeof(void *)); -} - -SWIGRUNTIME char * -SWIG_PackDataName(char *buff, void *ptr, size_t sz, const char *name, size_t bsz) { - char *r = buff; - size_t lname = (name ? strlen(name) : 0); - if ((2*sz + 2 + lname) > bsz) return 0; - *(r++) = '_'; - r = SWIG_PackData(r,ptr,sz); - if (lname) { - strncpy(r,name,lname+1); - } else { - *r = 0; - } - return buff; -} - -SWIGRUNTIME const char * -SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) { - if (*c != '_') { - if (strcmp(c,"NULL") == 0) { - memset(ptr,0,sz); - return name; - } else { - return 0; - } - } - return SWIG_UnpackData(++c,ptr,sz); -} - -#ifdef __cplusplus -} -#endif - -/* Errors in SWIG */ -#define SWIG_UnknownError -1 -#define SWIG_IOError -2 -#define SWIG_RuntimeError -3 -#define SWIG_IndexError -4 -#define SWIG_TypeError -5 -#define SWIG_DivisionByZero -6 -#define SWIG_OverflowError -7 -#define SWIG_SyntaxError -8 -#define SWIG_ValueError -9 -#define SWIG_SystemError -10 -#define SWIG_AttributeError -11 -#define SWIG_MemoryError -12 -#define SWIG_NullReferenceError -13 - - - -/* Compatibility macros for Python 3 */ -#if PY_VERSION_HEX >= 0x03000000 - -#define PyClass_Check(obj) PyObject_IsInstance(obj, (PyObject *)&PyType_Type) -#define PyInt_Check(x) PyLong_Check(x) -#define PyInt_AsLong(x) PyLong_AsLong(x) -#define PyInt_FromLong(x) PyLong_FromLong(x) -#define PyString_Format(fmt, args) PyUnicode_Format(fmt, args) - -#endif - -#ifndef Py_TYPE -# define Py_TYPE(op) ((op)->ob_type) -#endif - -/* SWIG APIs for compatibility of both Python 2 & 3 */ - -#if PY_VERSION_HEX >= 0x03000000 -# define SWIG_Python_str_FromFormat PyUnicode_FromFormat -#else -# define SWIG_Python_str_FromFormat PyString_FromFormat -#endif - - -/* Warning: This function will allocate a new string in Python 3, - * so please call SWIG_Python_str_DelForPy3(x) to free the space. - */ -SWIGINTERN char* -SWIG_Python_str_AsChar(PyObject *str) -{ -#if PY_VERSION_HEX >= 0x03000000 - char *cstr; - char *newstr; - Py_ssize_t len; - str = PyUnicode_AsUTF8String(str); - PyBytes_AsStringAndSize(str, &cstr, &len); - newstr = (char *) malloc(len+1); - memcpy(newstr, cstr, len+1); - Py_XDECREF(str); - return newstr; -#else - return PyString_AsString(str); -#endif -} - -#if PY_VERSION_HEX >= 0x03000000 -# define SWIG_Python_str_DelForPy3(x) free( (void*) (x) ) -#else -# define SWIG_Python_str_DelForPy3(x) -#endif - - -SWIGINTERN PyObject* -SWIG_Python_str_FromChar(const char *c) -{ -#if PY_VERSION_HEX >= 0x03000000 - return PyUnicode_FromString(c); -#else - return PyString_FromString(c); -#endif -} - -/* Add PyOS_snprintf for old Pythons */ -#if PY_VERSION_HEX < 0x02020000 -# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WATCOM) -# define PyOS_snprintf _snprintf -# else -# define PyOS_snprintf snprintf -# endif -#endif - -/* A crude PyString_FromFormat implementation for old Pythons */ -#if PY_VERSION_HEX < 0x02020000 - -#ifndef SWIG_PYBUFFER_SIZE -# define SWIG_PYBUFFER_SIZE 1024 -#endif - -static PyObject * -PyString_FromFormat(const char *fmt, ...) { - va_list ap; - char buf[SWIG_PYBUFFER_SIZE * 2]; - int res; - va_start(ap, fmt); - res = vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - return (res < 0 || res >= (int)sizeof(buf)) ? 0 : PyString_FromString(buf); -} -#endif - -/* Add PyObject_Del for old Pythons */ -#if PY_VERSION_HEX < 0x01060000 -# define PyObject_Del(op) PyMem_DEL((op)) -#endif -#ifndef PyObject_DEL -# define PyObject_DEL PyObject_Del -#endif - -/* A crude PyExc_StopIteration exception for old Pythons */ -#if PY_VERSION_HEX < 0x02020000 -# ifndef PyExc_StopIteration -# define PyExc_StopIteration PyExc_RuntimeError -# endif -# ifndef PyObject_GenericGetAttr -# define PyObject_GenericGetAttr 0 -# endif -#endif - -/* Py_NotImplemented is defined in 2.1 and up. */ -#if PY_VERSION_HEX < 0x02010000 -# ifndef Py_NotImplemented -# define Py_NotImplemented PyExc_RuntimeError -# endif -#endif - -/* A crude PyString_AsStringAndSize implementation for old Pythons */ -#if PY_VERSION_HEX < 0x02010000 -# ifndef PyString_AsStringAndSize -# define PyString_AsStringAndSize(obj, s, len) {*s = PyString_AsString(obj); *len = *s ? strlen(*s) : 0;} -# endif -#endif - -/* PySequence_Size for old Pythons */ -#if PY_VERSION_HEX < 0x02000000 -# ifndef PySequence_Size -# define PySequence_Size PySequence_Length -# endif -#endif - -/* PyBool_FromLong for old Pythons */ -#if PY_VERSION_HEX < 0x02030000 -static -PyObject *PyBool_FromLong(long ok) -{ - PyObject *result = ok ? Py_True : Py_False; - Py_INCREF(result); - return result; -} -#endif - -/* Py_ssize_t for old Pythons */ -/* This code is as recommended by: */ -/* http://www.python.org/dev/peps/pep-0353/#conversion-guidelines */ -#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) -typedef int Py_ssize_t; -# define PY_SSIZE_T_MAX INT_MAX -# define PY_SSIZE_T_MIN INT_MIN -#endif - -/* ----------------------------------------------------------------------------- - * error manipulation - * ----------------------------------------------------------------------------- */ - -SWIGRUNTIME PyObject* -SWIG_Python_ErrorType(int code) { - PyObject* type = 0; - switch(code) { - case SWIG_MemoryError: - type = PyExc_MemoryError; - break; - case SWIG_IOError: - type = PyExc_IOError; - break; - case SWIG_RuntimeError: - type = PyExc_RuntimeError; - break; - case SWIG_IndexError: - type = PyExc_IndexError; - break; - case SWIG_TypeError: - type = PyExc_TypeError; - break; - case SWIG_DivisionByZero: - type = PyExc_ZeroDivisionError; - break; - case SWIG_OverflowError: - type = PyExc_OverflowError; - break; - case SWIG_SyntaxError: - type = PyExc_SyntaxError; - break; - case SWIG_ValueError: - type = PyExc_ValueError; - break; - case SWIG_SystemError: - type = PyExc_SystemError; - break; - case SWIG_AttributeError: - type = PyExc_AttributeError; - break; - default: - type = PyExc_RuntimeError; - } - return type; -} - - -SWIGRUNTIME void -SWIG_Python_AddErrorMsg(const char* mesg) -{ - PyObject *type = 0; - PyObject *value = 0; - PyObject *traceback = 0; - - if (PyErr_Occurred()) PyErr_Fetch(&type, &value, &traceback); - if (value) { - char *tmp; - PyObject *old_str = PyObject_Str(value); - PyErr_Clear(); - Py_XINCREF(type); - - PyErr_Format(type, "%s %s", tmp = SWIG_Python_str_AsChar(old_str), mesg); - SWIG_Python_str_DelForPy3(tmp); - Py_DECREF(old_str); - Py_DECREF(value); - } else { - PyErr_SetString(PyExc_RuntimeError, mesg); - } -} - -#if defined(SWIG_PYTHON_NO_THREADS) -# if defined(SWIG_PYTHON_THREADS) -# undef SWIG_PYTHON_THREADS -# endif -#endif -#if defined(SWIG_PYTHON_THREADS) /* Threading support is enabled */ -# if !defined(SWIG_PYTHON_USE_GIL) && !defined(SWIG_PYTHON_NO_USE_GIL) -# if (PY_VERSION_HEX >= 0x02030000) /* For 2.3 or later, use the PyGILState calls */ -# define SWIG_PYTHON_USE_GIL -# endif -# endif -# if defined(SWIG_PYTHON_USE_GIL) /* Use PyGILState threads calls */ -# ifndef SWIG_PYTHON_INITIALIZE_THREADS -# define SWIG_PYTHON_INITIALIZE_THREADS PyEval_InitThreads() -# endif -# ifdef __cplusplus /* C++ code */ - class SWIG_Python_Thread_Block { - bool status; - PyGILState_STATE state; - public: - void end() { if (status) { PyGILState_Release(state); status = false;} } - SWIG_Python_Thread_Block() : status(true), state(PyGILState_Ensure()) {} - ~SWIG_Python_Thread_Block() { end(); } - }; - class SWIG_Python_Thread_Allow { - bool status; - PyThreadState *save; - public: - void end() { if (status) { PyEval_RestoreThread(save); status = false; }} - SWIG_Python_Thread_Allow() : status(true), save(PyEval_SaveThread()) {} - ~SWIG_Python_Thread_Allow() { end(); } - }; -# define SWIG_PYTHON_THREAD_BEGIN_BLOCK SWIG_Python_Thread_Block _swig_thread_block -# define SWIG_PYTHON_THREAD_END_BLOCK _swig_thread_block.end() -# define SWIG_PYTHON_THREAD_BEGIN_ALLOW SWIG_Python_Thread_Allow _swig_thread_allow -# define SWIG_PYTHON_THREAD_END_ALLOW _swig_thread_allow.end() -# else /* C code */ -# define SWIG_PYTHON_THREAD_BEGIN_BLOCK PyGILState_STATE _swig_thread_block = PyGILState_Ensure() -# define SWIG_PYTHON_THREAD_END_BLOCK PyGILState_Release(_swig_thread_block) -# define SWIG_PYTHON_THREAD_BEGIN_ALLOW PyThreadState *_swig_thread_allow = PyEval_SaveThread() -# define SWIG_PYTHON_THREAD_END_ALLOW PyEval_RestoreThread(_swig_thread_allow) -# endif -# else /* Old thread way, not implemented, user must provide it */ -# if !defined(SWIG_PYTHON_INITIALIZE_THREADS) -# define SWIG_PYTHON_INITIALIZE_THREADS -# endif -# if !defined(SWIG_PYTHON_THREAD_BEGIN_BLOCK) -# define SWIG_PYTHON_THREAD_BEGIN_BLOCK -# endif -# if !defined(SWIG_PYTHON_THREAD_END_BLOCK) -# define SWIG_PYTHON_THREAD_END_BLOCK -# endif -# if !defined(SWIG_PYTHON_THREAD_BEGIN_ALLOW) -# define SWIG_PYTHON_THREAD_BEGIN_ALLOW -# endif -# if !defined(SWIG_PYTHON_THREAD_END_ALLOW) -# define SWIG_PYTHON_THREAD_END_ALLOW -# endif -# endif -#else /* No thread support */ -# define SWIG_PYTHON_INITIALIZE_THREADS -# define SWIG_PYTHON_THREAD_BEGIN_BLOCK -# define SWIG_PYTHON_THREAD_END_BLOCK -# define SWIG_PYTHON_THREAD_BEGIN_ALLOW -# define SWIG_PYTHON_THREAD_END_ALLOW -#endif - -/* ----------------------------------------------------------------------------- - * Python API portion that goes into the runtime - * ----------------------------------------------------------------------------- */ - -#ifdef __cplusplus -extern "C" { -#if 0 -} /* cc-mode */ -#endif -#endif - -/* ----------------------------------------------------------------------------- - * Constant declarations - * ----------------------------------------------------------------------------- */ - -/* Constant Types */ -#define SWIG_PY_POINTER 4 -#define SWIG_PY_BINARY 5 - -/* Constant information structure */ -typedef struct swig_const_info { - int type; - char *name; - long lvalue; - double dvalue; - void *pvalue; - swig_type_info **ptype; -} swig_const_info; - - -/* ----------------------------------------------------------------------------- - * Wrapper of PyInstanceMethod_New() used in Python 3 - * It is exported to the generated module, used for -fastproxy - * ----------------------------------------------------------------------------- */ -SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func) -{ -#if PY_VERSION_HEX >= 0x03000000 - return PyInstanceMethod_New(func); -#else - return NULL; -#endif -} - -#ifdef __cplusplus -#if 0 -{ /* cc-mode */ -#endif -} -#endif - - -/* ----------------------------------------------------------------------------- - * See the LICENSE file for information on copyright, usage and redistribution - * of SWIG, and the README file for authors - http://www.swig.org/release.html. - * - * pyrun.swg - * - * This file contains the runtime support for Python modules - * and includes code for managing global variables and pointer - * type checking. - * - * ----------------------------------------------------------------------------- */ - -/* Common SWIG API */ - -/* for raw pointers */ -#define SWIG_Python_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, 0) -#define SWIG_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtr(obj, pptr, type, flags) -#define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, own) -#define SWIG_NewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(ptr, type, flags) -#define SWIG_CheckImplicit(ty) SWIG_Python_CheckImplicit(ty) -#define SWIG_AcquirePtr(ptr, src) SWIG_Python_AcquirePtr(ptr, src) -#define swig_owntype int - -/* for raw packed data */ -#define SWIG_ConvertPacked(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty) -#define SWIG_NewPackedObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type) - -/* for class or struct pointers */ -#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_ConvertPtr(obj, pptr, type, flags) -#define SWIG_NewInstanceObj(ptr, type, flags) SWIG_NewPointerObj(ptr, type, flags) - -/* for C or C++ function pointers */ -#define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_Python_ConvertFunctionPtr(obj, pptr, type) -#define SWIG_NewFunctionPtrObj(ptr, type) SWIG_Python_NewPointerObj(ptr, type, 0) - -/* for C++ member pointers, ie, member methods */ -#define SWIG_ConvertMember(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty) -#define SWIG_NewMemberObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type) - - -/* Runtime API */ - -#define SWIG_GetModule(clientdata) SWIG_Python_GetModule() -#define SWIG_SetModule(clientdata, pointer) SWIG_Python_SetModule(pointer) -#define SWIG_NewClientData(obj) SwigPyClientData_New(obj) - -#define SWIG_SetErrorObj SWIG_Python_SetErrorObj -#define SWIG_SetErrorMsg SWIG_Python_SetErrorMsg -#define SWIG_ErrorType(code) SWIG_Python_ErrorType(code) -#define SWIG_Error(code, msg) SWIG_Python_SetErrorMsg(SWIG_ErrorType(code), msg) -#define SWIG_fail goto fail - - -/* Runtime API implementation */ - -/* Error manipulation */ - -SWIGINTERN void -SWIG_Python_SetErrorObj(PyObject *errtype, PyObject *obj) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - PyErr_SetObject(errtype, obj); - Py_DECREF(obj); - SWIG_PYTHON_THREAD_END_BLOCK; -} - -SWIGINTERN void -SWIG_Python_SetErrorMsg(PyObject *errtype, const char *msg) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - PyErr_SetString(errtype, (char *) msg); - SWIG_PYTHON_THREAD_END_BLOCK; -} - -#define SWIG_Python_Raise(obj, type, desc) SWIG_Python_SetErrorObj(SWIG_Python_ExceptionType(desc), obj) - -/* Set a constant value */ - -SWIGINTERN void -SWIG_Python_SetConstant(PyObject *d, const char *name, PyObject *obj) { - PyDict_SetItemString(d, (char*) name, obj); - Py_DECREF(obj); -} - -/* Append a value to the result obj */ - -SWIGINTERN PyObject* -SWIG_Python_AppendOutput(PyObject* result, PyObject* obj) { -#if !defined(SWIG_PYTHON_OUTPUT_TUPLE) - if (!result) { - result = obj; - } else if (result == Py_None) { - Py_DECREF(result); - result = obj; - } else { - if (!PyList_Check(result)) { - PyObject *o2 = result; - result = PyList_New(1); - PyList_SetItem(result, 0, o2); - } - PyList_Append(result,obj); - Py_DECREF(obj); - } - return result; -#else - PyObject* o2; - PyObject* o3; - if (!result) { - result = obj; - } else if (result == Py_None) { - Py_DECREF(result); - result = obj; - } else { - if (!PyTuple_Check(result)) { - o2 = result; - result = PyTuple_New(1); - PyTuple_SET_ITEM(result, 0, o2); - } - o3 = PyTuple_New(1); - PyTuple_SET_ITEM(o3, 0, obj); - o2 = result; - result = PySequence_Concat(o2, o3); - Py_DECREF(o2); - Py_DECREF(o3); - } - return result; -#endif -} - -/* Unpack the argument tuple */ - -SWIGINTERN int -SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, PyObject **objs) -{ - if (!args) { - if (!min && !max) { - return 1; - } else { - PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got none", - name, (min == max ? "" : "at least "), (int)min); - return 0; - } - } - if (!PyTuple_Check(args)) { - PyErr_SetString(PyExc_SystemError, "UnpackTuple() argument list is not a tuple"); - return 0; - } else { - register Py_ssize_t l = PyTuple_GET_SIZE(args); - if (l < min) { - PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", - name, (min == max ? "" : "at least "), (int)min, (int)l); - return 0; - } else if (l > max) { - PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", - name, (min == max ? "" : "at most "), (int)max, (int)l); - return 0; - } else { - register int i; - for (i = 0; i < l; ++i) { - objs[i] = PyTuple_GET_ITEM(args, i); - } - for (; l < max; ++l) { - objs[l] = 0; - } - return i + 1; - } - } -} - -/* A functor is a function object with one single object argument */ -#if PY_VERSION_HEX >= 0x02020000 -#define SWIG_Python_CallFunctor(functor, obj) PyObject_CallFunctionObjArgs(functor, obj, NULL); -#else -#define SWIG_Python_CallFunctor(functor, obj) PyObject_CallFunction(functor, "O", obj); -#endif - -/* - Helper for static pointer initialization for both C and C++ code, for example - static PyObject *SWIG_STATIC_POINTER(MyVar) = NewSomething(...); -*/ -#ifdef __cplusplus -#define SWIG_STATIC_POINTER(var) var -#else -#define SWIG_STATIC_POINTER(var) var = 0; if (!var) var -#endif - -/* ----------------------------------------------------------------------------- - * Pointer declarations - * ----------------------------------------------------------------------------- */ - -/* Flags for new pointer objects */ -#define SWIG_POINTER_NOSHADOW (SWIG_POINTER_OWN << 1) -#define SWIG_POINTER_NEW (SWIG_POINTER_NOSHADOW | SWIG_POINTER_OWN) - -#define SWIG_POINTER_IMPLICIT_CONV (SWIG_POINTER_DISOWN << 1) - -#ifdef __cplusplus -extern "C" { -#if 0 -} /* cc-mode */ -#endif -#endif - -/* How to access Py_None */ -#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# ifndef SWIG_PYTHON_NO_BUILD_NONE -# ifndef SWIG_PYTHON_BUILD_NONE -# define SWIG_PYTHON_BUILD_NONE -# endif -# endif -#endif - -#ifdef SWIG_PYTHON_BUILD_NONE -# ifdef Py_None -# undef Py_None -# define Py_None SWIG_Py_None() -# endif -SWIGRUNTIMEINLINE PyObject * -_SWIG_Py_None(void) -{ - PyObject *none = Py_BuildValue((char*)""); - Py_DECREF(none); - return none; -} -SWIGRUNTIME PyObject * -SWIG_Py_None(void) -{ - static PyObject *SWIG_STATIC_POINTER(none) = _SWIG_Py_None(); - return none; -} -#endif - -/* The python void return value */ - -SWIGRUNTIMEINLINE PyObject * -SWIG_Py_Void(void) -{ - PyObject *none = Py_None; - Py_INCREF(none); - return none; -} - -/* SwigPyClientData */ - -typedef struct { - PyObject *klass; - PyObject *newraw; - PyObject *newargs; - PyObject *destroy; - int delargs; - int implicitconv; -} SwigPyClientData; - -SWIGRUNTIMEINLINE int -SWIG_Python_CheckImplicit(swig_type_info *ty) -{ - SwigPyClientData *data = (SwigPyClientData *)ty->clientdata; - return data ? data->implicitconv : 0; -} - -SWIGRUNTIMEINLINE PyObject * -SWIG_Python_ExceptionType(swig_type_info *desc) { - SwigPyClientData *data = desc ? (SwigPyClientData *) desc->clientdata : 0; - PyObject *klass = data ? data->klass : 0; - return (klass ? klass : PyExc_RuntimeError); -} - - -SWIGRUNTIME SwigPyClientData * -SwigPyClientData_New(PyObject* obj) -{ - if (!obj) { - return 0; - } else { - SwigPyClientData *data = (SwigPyClientData *)malloc(sizeof(SwigPyClientData)); - /* the klass element */ - data->klass = obj; - Py_INCREF(data->klass); - /* the newraw method and newargs arguments used to create a new raw instance */ - if (PyClass_Check(obj)) { - data->newraw = 0; - data->newargs = obj; - Py_INCREF(obj); - } else { -#if (PY_VERSION_HEX < 0x02020000) - data->newraw = 0; -#else - data->newraw = PyObject_GetAttrString(data->klass, (char *)"__new__"); -#endif - if (data->newraw) { - Py_INCREF(data->newraw); - data->newargs = PyTuple_New(1); - PyTuple_SetItem(data->newargs, 0, obj); - } else { - data->newargs = obj; - } - Py_INCREF(data->newargs); - } - /* the destroy method, aka as the C++ delete method */ - data->destroy = PyObject_GetAttrString(data->klass, (char *)"__swig_destroy__"); - if (PyErr_Occurred()) { - PyErr_Clear(); - data->destroy = 0; - } - if (data->destroy) { - int flags; - Py_INCREF(data->destroy); - flags = PyCFunction_GET_FLAGS(data->destroy); -#ifdef METH_O - data->delargs = !(flags & (METH_O)); -#else - data->delargs = 0; -#endif - } else { - data->delargs = 0; - } - data->implicitconv = 0; - return data; - } -} - -SWIGRUNTIME void -SwigPyClientData_Del(SwigPyClientData* data) -{ - Py_XDECREF(data->newraw); - Py_XDECREF(data->newargs); - Py_XDECREF(data->destroy); -} - -/* =============== SwigPyObject =====================*/ - -typedef struct { - PyObject_HEAD - void *ptr; - swig_type_info *ty; - int own; - PyObject *next; -} SwigPyObject; - -SWIGRUNTIME PyObject * -SwigPyObject_long(SwigPyObject *v) -{ - return PyLong_FromVoidPtr(v->ptr); -} - -SWIGRUNTIME PyObject * -SwigPyObject_format(const char* fmt, SwigPyObject *v) -{ - PyObject *res = NULL; - PyObject *args = PyTuple_New(1); - if (args) { - if (PyTuple_SetItem(args, 0, SwigPyObject_long(v)) == 0) { - PyObject *ofmt = SWIG_Python_str_FromChar(fmt); - if (ofmt) { -#if PY_VERSION_HEX >= 0x03000000 - res = PyUnicode_Format(ofmt,args); -#else - res = PyString_Format(ofmt,args); -#endif - Py_DECREF(ofmt); - } - Py_DECREF(args); - } - } - return res; -} - -SWIGRUNTIME PyObject * -SwigPyObject_oct(SwigPyObject *v) -{ - return SwigPyObject_format("%o",v); -} - -SWIGRUNTIME PyObject * -SwigPyObject_hex(SwigPyObject *v) -{ - return SwigPyObject_format("%x",v); -} - -SWIGRUNTIME PyObject * -#ifdef METH_NOARGS -SwigPyObject_repr(SwigPyObject *v) -#else -SwigPyObject_repr(SwigPyObject *v, PyObject *args) -#endif -{ - const char *name = SWIG_TypePrettyName(v->ty); - PyObject *repr = SWIG_Python_str_FromFormat("", name, v); - if (v->next) { -#ifdef METH_NOARGS - PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next); -#else - PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next, args); -#endif -#if PY_VERSION_HEX >= 0x03000000 - PyObject *joined = PyUnicode_Concat(repr, nrep); - Py_DecRef(repr); - Py_DecRef(nrep); - repr = joined; -#else - PyString_ConcatAndDel(&repr,nrep); -#endif - } - return repr; -} - -SWIGRUNTIME int -SwigPyObject_print(SwigPyObject *v, FILE *fp, int SWIGUNUSEDPARM(flags)) -{ - char *str; -#ifdef METH_NOARGS - PyObject *repr = SwigPyObject_repr(v); -#else - PyObject *repr = SwigPyObject_repr(v, NULL); -#endif - if (repr) { - str = SWIG_Python_str_AsChar(repr); - fputs(str, fp); - SWIG_Python_str_DelForPy3(str); - Py_DECREF(repr); - return 0; - } else { - return 1; - } -} - -SWIGRUNTIME PyObject * -SwigPyObject_str(SwigPyObject *v) -{ - char result[SWIG_BUFFER_SIZE]; - return SWIG_PackVoidPtr(result, v->ptr, v->ty->name, sizeof(result)) ? - SWIG_Python_str_FromChar(result) : 0; -} - -SWIGRUNTIME int -SwigPyObject_compare(SwigPyObject *v, SwigPyObject *w) -{ - void *i = v->ptr; - void *j = w->ptr; - return (i < j) ? -1 : ((i > j) ? 1 : 0); -} - -/* Added for Python 3.x, would it also be useful for Python 2.x? */ -SWIGRUNTIME PyObject* -SwigPyObject_richcompare(SwigPyObject *v, SwigPyObject *w, int op) -{ - PyObject* res; - if( op != Py_EQ && op != Py_NE ) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - if( (SwigPyObject_compare(v, w)==0) == (op == Py_EQ) ) - res = Py_True; - else - res = Py_False; - Py_INCREF(res); - return res; -} - - -SWIGRUNTIME PyTypeObject* _PySwigObject_type(void); - -SWIGRUNTIME PyTypeObject* -SwigPyObject_type(void) { - static PyTypeObject *SWIG_STATIC_POINTER(type) = _PySwigObject_type(); - return type; -} - -SWIGRUNTIMEINLINE int -SwigPyObject_Check(PyObject *op) { - return (Py_TYPE(op) == SwigPyObject_type()) - || (strcmp(Py_TYPE(op)->tp_name,"SwigPyObject") == 0); -} - -SWIGRUNTIME PyObject * -SwigPyObject_New(void *ptr, swig_type_info *ty, int own); - -SWIGRUNTIME void -SwigPyObject_dealloc(PyObject *v) -{ - SwigPyObject *sobj = (SwigPyObject *) v; - PyObject *next = sobj->next; - if (sobj->own == SWIG_POINTER_OWN) { - swig_type_info *ty = sobj->ty; - SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0; - PyObject *destroy = data ? data->destroy : 0; - if (destroy) { - /* destroy is always a VARARGS method */ - PyObject *res; - if (data->delargs) { - /* we need to create a temporary object to carry the destroy operation */ - PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0); - res = SWIG_Python_CallFunctor(destroy, tmp); - Py_DECREF(tmp); - } else { - PyCFunction meth = PyCFunction_GET_FUNCTION(destroy); - PyObject *mself = PyCFunction_GET_SELF(destroy); - res = ((*meth)(mself, v)); - } - Py_XDECREF(res); - } -#if !defined(SWIG_PYTHON_SILENT_MEMLEAK) - else { - const char *name = SWIG_TypePrettyName(ty); - printf("swig/python detected a memory leak of type '%s', no destructor found.\n", (name ? name : "unknown")); - } -#endif - } - Py_XDECREF(next); - PyObject_DEL(v); -} - -SWIGRUNTIME PyObject* -SwigPyObject_append(PyObject* v, PyObject* next) -{ - SwigPyObject *sobj = (SwigPyObject *) v; -#ifndef METH_O - PyObject *tmp = 0; - if (!PyArg_ParseTuple(next,(char *)"O:append", &tmp)) return NULL; - next = tmp; -#endif - if (!SwigPyObject_Check(next)) { - return NULL; - } - sobj->next = next; - Py_INCREF(next); - return SWIG_Py_Void(); -} - -SWIGRUNTIME PyObject* -#ifdef METH_NOARGS -SwigPyObject_next(PyObject* v) -#else -SwigPyObject_next(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) -#endif -{ - SwigPyObject *sobj = (SwigPyObject *) v; - if (sobj->next) { - Py_INCREF(sobj->next); - return sobj->next; - } else { - return SWIG_Py_Void(); - } -} - -SWIGINTERN PyObject* -#ifdef METH_NOARGS -SwigPyObject_disown(PyObject *v) -#else -SwigPyObject_disown(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) -#endif -{ - SwigPyObject *sobj = (SwigPyObject *)v; - sobj->own = 0; - return SWIG_Py_Void(); -} - -SWIGINTERN PyObject* -#ifdef METH_NOARGS -SwigPyObject_acquire(PyObject *v) -#else -SwigPyObject_acquire(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) -#endif -{ - SwigPyObject *sobj = (SwigPyObject *)v; - sobj->own = SWIG_POINTER_OWN; - return SWIG_Py_Void(); -} - -SWIGINTERN PyObject* -SwigPyObject_own(PyObject *v, PyObject *args) -{ - PyObject *val = 0; -#if (PY_VERSION_HEX < 0x02020000) - if (!PyArg_ParseTuple(args,(char *)"|O:own",&val)) -#else - if (!PyArg_UnpackTuple(args, (char *)"own", 0, 1, &val)) -#endif - { - return NULL; - } - else - { - SwigPyObject *sobj = (SwigPyObject *)v; - PyObject *obj = PyBool_FromLong(sobj->own); - if (val) { -#ifdef METH_NOARGS - if (PyObject_IsTrue(val)) { - SwigPyObject_acquire(v); - } else { - SwigPyObject_disown(v); - } -#else - if (PyObject_IsTrue(val)) { - SwigPyObject_acquire(v,args); - } else { - SwigPyObject_disown(v,args); - } -#endif - } - return obj; - } -} - -#ifdef METH_O -static PyMethodDef -swigobject_methods[] = { - {(char *)"disown", (PyCFunction)SwigPyObject_disown, METH_NOARGS, (char *)"releases ownership of the pointer"}, - {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_NOARGS, (char *)"aquires ownership of the pointer"}, - {(char *)"own", (PyCFunction)SwigPyObject_own, METH_VARARGS, (char *)"returns/sets ownership of the pointer"}, - {(char *)"append", (PyCFunction)SwigPyObject_append, METH_O, (char *)"appends another 'this' object"}, - {(char *)"next", (PyCFunction)SwigPyObject_next, METH_NOARGS, (char *)"returns the next 'this' object"}, - {(char *)"__repr__",(PyCFunction)SwigPyObject_repr, METH_NOARGS, (char *)"returns object representation"}, - {0, 0, 0, 0} -}; -#else -static PyMethodDef -swigobject_methods[] = { - {(char *)"disown", (PyCFunction)SwigPyObject_disown, METH_VARARGS, (char *)"releases ownership of the pointer"}, - {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_VARARGS, (char *)"aquires ownership of the pointer"}, - {(char *)"own", (PyCFunction)SwigPyObject_own, METH_VARARGS, (char *)"returns/sets ownership of the pointer"}, - {(char *)"append", (PyCFunction)SwigPyObject_append, METH_VARARGS, (char *)"appends another 'this' object"}, - {(char *)"next", (PyCFunction)SwigPyObject_next, METH_VARARGS, (char *)"returns the next 'this' object"}, - {(char *)"__repr__",(PyCFunction)SwigPyObject_repr, METH_VARARGS, (char *)"returns object representation"}, - {0, 0, 0, 0} -}; -#endif - -#if PY_VERSION_HEX < 0x02020000 -SWIGINTERN PyObject * -SwigPyObject_getattr(SwigPyObject *sobj,char *name) -{ - return Py_FindMethod(swigobject_methods, (PyObject *)sobj, name); -} -#endif - -SWIGRUNTIME PyTypeObject* -_PySwigObject_type(void) { - static char swigobject_doc[] = "Swig object carries a C/C++ instance pointer"; - - static PyNumberMethods SwigPyObject_as_number = { - (binaryfunc)0, /*nb_add*/ - (binaryfunc)0, /*nb_subtract*/ - (binaryfunc)0, /*nb_multiply*/ - /* nb_divide removed in Python 3 */ -#if PY_VERSION_HEX < 0x03000000 - (binaryfunc)0, /*nb_divide*/ -#endif - (binaryfunc)0, /*nb_remainder*/ - (binaryfunc)0, /*nb_divmod*/ - (ternaryfunc)0,/*nb_power*/ - (unaryfunc)0, /*nb_negative*/ - (unaryfunc)0, /*nb_positive*/ - (unaryfunc)0, /*nb_absolute*/ - (inquiry)0, /*nb_nonzero*/ - 0, /*nb_invert*/ - 0, /*nb_lshift*/ - 0, /*nb_rshift*/ - 0, /*nb_and*/ - 0, /*nb_xor*/ - 0, /*nb_or*/ -#if PY_VERSION_HEX < 0x03000000 - 0, /*nb_coerce*/ -#endif - (unaryfunc)SwigPyObject_long, /*nb_int*/ -#if PY_VERSION_HEX < 0x03000000 - (unaryfunc)SwigPyObject_long, /*nb_long*/ -#else - 0, /*nb_reserved*/ -#endif - (unaryfunc)0, /*nb_float*/ -#if PY_VERSION_HEX < 0x03000000 - (unaryfunc)SwigPyObject_oct, /*nb_oct*/ - (unaryfunc)SwigPyObject_hex, /*nb_hex*/ -#endif -#if PY_VERSION_HEX >= 0x03000000 /* 3.0 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index, nb_inplace_divide removed */ -#elif PY_VERSION_HEX >= 0x02050000 /* 2.5.0 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index */ -#elif PY_VERSION_HEX >= 0x02020000 /* 2.2.0 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_true_divide */ -#elif PY_VERSION_HEX >= 0x02000000 /* 2.0.0 */ - 0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_or */ -#endif - }; - - static PyTypeObject swigpyobject_type; - static int type_init = 0; - if (!type_init) { - const PyTypeObject tmp - = { - /* PyObject header changed in Python 3 */ -#if PY_VERSION_HEX >= 0x03000000 - PyVarObject_HEAD_INIT(&PyType_Type, 0) -#else - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ -#endif - (char *)"SwigPyObject", /* tp_name */ - sizeof(SwigPyObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)SwigPyObject_dealloc, /* tp_dealloc */ - (printfunc)SwigPyObject_print, /* tp_print */ -#if PY_VERSION_HEX < 0x02020000 - (getattrfunc)SwigPyObject_getattr, /* tp_getattr */ -#else - (getattrfunc)0, /* tp_getattr */ -#endif - (setattrfunc)0, /* tp_setattr */ -#if PY_VERSION_HEX >= 0x03000000 - 0, /* tp_reserved in 3.0.1, tp_compare in 3.0.0 but not used */ -#else - (cmpfunc)SwigPyObject_compare, /* tp_compare */ -#endif - (reprfunc)SwigPyObject_repr, /* tp_repr */ - &SwigPyObject_as_number, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)0, /* tp_hash */ - (ternaryfunc)0, /* tp_call */ - (reprfunc)SwigPyObject_str, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - swigobject_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - (richcmpfunc)SwigPyObject_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ -#if PY_VERSION_HEX >= 0x02020000 - 0, /* tp_iter */ - 0, /* tp_iternext */ - swigobject_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ -#endif -#if PY_VERSION_HEX >= 0x02030000 - 0, /* tp_del */ -#endif -#ifdef COUNT_ALLOCS - 0,0,0,0 /* tp_alloc -> tp_next */ -#endif - }; - swigpyobject_type = tmp; - /* for Python 3 we already assigned ob_type in PyVarObject_HEAD_INIT() */ -#if PY_VERSION_HEX < 0x03000000 - swigpyobject_type.ob_type = &PyType_Type; -#endif - type_init = 1; - } - return &swigpyobject_type; -} - -SWIGRUNTIME PyObject * -SwigPyObject_New(void *ptr, swig_type_info *ty, int own) -{ - SwigPyObject *sobj = PyObject_NEW(SwigPyObject, SwigPyObject_type()); - if (sobj) { - sobj->ptr = ptr; - sobj->ty = ty; - sobj->own = own; - sobj->next = 0; - } - return (PyObject *)sobj; -} - -/* ----------------------------------------------------------------------------- - * Implements a simple Swig Packed type, and use it instead of string - * ----------------------------------------------------------------------------- */ - -typedef struct { - PyObject_HEAD - void *pack; - swig_type_info *ty; - size_t size; -} SwigPyPacked; - -SWIGRUNTIME int -SwigPyPacked_print(SwigPyPacked *v, FILE *fp, int SWIGUNUSEDPARM(flags)) -{ - char result[SWIG_BUFFER_SIZE]; - fputs("pack, v->size, 0, sizeof(result))) { - fputs("at ", fp); - fputs(result, fp); - } - fputs(v->ty->name,fp); - fputs(">", fp); - return 0; -} - -SWIGRUNTIME PyObject * -SwigPyPacked_repr(SwigPyPacked *v) -{ - char result[SWIG_BUFFER_SIZE]; - if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))) { - return SWIG_Python_str_FromFormat("", result, v->ty->name); - } else { - return SWIG_Python_str_FromFormat("", v->ty->name); - } -} - -SWIGRUNTIME PyObject * -SwigPyPacked_str(SwigPyPacked *v) -{ - char result[SWIG_BUFFER_SIZE]; - if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))){ - return SWIG_Python_str_FromFormat("%s%s", result, v->ty->name); - } else { - return SWIG_Python_str_FromChar(v->ty->name); - } -} - -SWIGRUNTIME int -SwigPyPacked_compare(SwigPyPacked *v, SwigPyPacked *w) -{ - size_t i = v->size; - size_t j = w->size; - int s = (i < j) ? -1 : ((i > j) ? 1 : 0); - return s ? s : strncmp((char *)v->pack, (char *)w->pack, 2*v->size); -} - -SWIGRUNTIME PyTypeObject* _PySwigPacked_type(void); - -SWIGRUNTIME PyTypeObject* -SwigPyPacked_type(void) { - static PyTypeObject *SWIG_STATIC_POINTER(type) = _PySwigPacked_type(); - return type; -} - -SWIGRUNTIMEINLINE int -SwigPyPacked_Check(PyObject *op) { - return ((op)->ob_type == _PySwigPacked_type()) - || (strcmp((op)->ob_type->tp_name,"SwigPyPacked") == 0); -} - -SWIGRUNTIME void -SwigPyPacked_dealloc(PyObject *v) -{ - if (SwigPyPacked_Check(v)) { - SwigPyPacked *sobj = (SwigPyPacked *) v; - free(sobj->pack); - } - PyObject_DEL(v); -} - -SWIGRUNTIME PyTypeObject* -_PySwigPacked_type(void) { - static char swigpacked_doc[] = "Swig object carries a C/C++ instance pointer"; - static PyTypeObject swigpypacked_type; - static int type_init = 0; - if (!type_init) { - const PyTypeObject tmp - = { - /* PyObject header changed in Python 3 */ -#if PY_VERSION_HEX>=0x03000000 - PyVarObject_HEAD_INIT(&PyType_Type, 0) -#else - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ -#endif - (char *)"SwigPyPacked", /* tp_name */ - sizeof(SwigPyPacked), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)SwigPyPacked_dealloc, /* tp_dealloc */ - (printfunc)SwigPyPacked_print, /* tp_print */ - (getattrfunc)0, /* tp_getattr */ - (setattrfunc)0, /* tp_setattr */ -#if PY_VERSION_HEX>=0x03000000 - 0, /* tp_reserved in 3.0.1 */ -#else - (cmpfunc)SwigPyPacked_compare, /* tp_compare */ -#endif - (reprfunc)SwigPyPacked_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)0, /* tp_hash */ - (ternaryfunc)0, /* tp_call */ - (reprfunc)SwigPyPacked_str, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - swigpacked_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ -#if PY_VERSION_HEX >= 0x02020000 - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ -#endif -#if PY_VERSION_HEX >= 0x02030000 - 0, /* tp_del */ -#endif -#ifdef COUNT_ALLOCS - 0,0,0,0 /* tp_alloc -> tp_next */ -#endif - }; - swigpypacked_type = tmp; - /* for Python 3 the ob_type already assigned in PyVarObject_HEAD_INIT() */ -#if PY_VERSION_HEX < 0x03000000 - swigpypacked_type.ob_type = &PyType_Type; -#endif - type_init = 1; - } - return &swigpypacked_type; -} - -SWIGRUNTIME PyObject * -SwigPyPacked_New(void *ptr, size_t size, swig_type_info *ty) -{ - SwigPyPacked *sobj = PyObject_NEW(SwigPyPacked, SwigPyPacked_type()); - if (sobj) { - void *pack = malloc(size); - if (pack) { - memcpy(pack, ptr, size); - sobj->pack = pack; - sobj->ty = ty; - sobj->size = size; - } else { - PyObject_DEL((PyObject *) sobj); - sobj = 0; - } - } - return (PyObject *) sobj; -} - -SWIGRUNTIME swig_type_info * -SwigPyPacked_UnpackData(PyObject *obj, void *ptr, size_t size) -{ - if (SwigPyPacked_Check(obj)) { - SwigPyPacked *sobj = (SwigPyPacked *)obj; - if (sobj->size != size) return 0; - memcpy(ptr, sobj->pack, size); - return sobj->ty; - } else { - return 0; - } -} - -/* ----------------------------------------------------------------------------- - * pointers/data manipulation - * ----------------------------------------------------------------------------- */ - -SWIGRUNTIMEINLINE PyObject * -_SWIG_This(void) -{ - return SWIG_Python_str_FromChar("this"); -} - -SWIGRUNTIME PyObject * -SWIG_This(void) -{ - static PyObject *SWIG_STATIC_POINTER(swig_this) = _SWIG_This(); - return swig_this; -} - -/* #define SWIG_PYTHON_SLOW_GETSET_THIS */ - -/* TODO: I don't know how to implement the fast getset in Python 3 right now */ -#if PY_VERSION_HEX>=0x03000000 -#define SWIG_PYTHON_SLOW_GETSET_THIS -#endif - -SWIGRUNTIME SwigPyObject * -SWIG_Python_GetSwigThis(PyObject *pyobj) -{ - if (SwigPyObject_Check(pyobj)) { - return (SwigPyObject *) pyobj; - } else { - PyObject *obj = 0; -#if (!defined(SWIG_PYTHON_SLOW_GETSET_THIS) && (PY_VERSION_HEX >= 0x02030000)) - if (PyInstance_Check(pyobj)) { - obj = _PyInstance_Lookup(pyobj, SWIG_This()); - } else { - PyObject **dictptr = _PyObject_GetDictPtr(pyobj); - if (dictptr != NULL) { - PyObject *dict = *dictptr; - obj = dict ? PyDict_GetItem(dict, SWIG_This()) : 0; - } else { -#ifdef PyWeakref_CheckProxy - if (PyWeakref_CheckProxy(pyobj)) { - PyObject *wobj = PyWeakref_GET_OBJECT(pyobj); - return wobj ? SWIG_Python_GetSwigThis(wobj) : 0; - } -#endif - obj = PyObject_GetAttr(pyobj,SWIG_This()); - if (obj) { - Py_DECREF(obj); - } else { - if (PyErr_Occurred()) PyErr_Clear(); - return 0; - } - } - } -#else - obj = PyObject_GetAttr(pyobj,SWIG_This()); - if (obj) { - Py_DECREF(obj); - } else { - if (PyErr_Occurred()) PyErr_Clear(); - return 0; - } -#endif - if (obj && !SwigPyObject_Check(obj)) { - /* a PyObject is called 'this', try to get the 'real this' - SwigPyObject from it */ - return SWIG_Python_GetSwigThis(obj); - } - return (SwigPyObject *)obj; - } -} - -/* Acquire a pointer value */ - -SWIGRUNTIME int -SWIG_Python_AcquirePtr(PyObject *obj, int own) { - if (own == SWIG_POINTER_OWN) { - SwigPyObject *sobj = SWIG_Python_GetSwigThis(obj); - if (sobj) { - int oldown = sobj->own; - sobj->own = own; - return oldown; - } - } - return 0; -} - -/* Convert a pointer value */ - -SWIGRUNTIME int -SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int flags, int *own) { - if (!obj) return SWIG_ERROR; - if (obj == Py_None) { - if (ptr) *ptr = 0; - return SWIG_OK; - } else { - SwigPyObject *sobj = SWIG_Python_GetSwigThis(obj); - if (own) - *own = 0; - while (sobj) { - void *vptr = sobj->ptr; - if (ty) { - swig_type_info *to = sobj->ty; - if (to == ty) { - /* no type cast needed */ - if (ptr) *ptr = vptr; - break; - } else { - swig_cast_info *tc = SWIG_TypeCheck(to->name,ty); - if (!tc) { - sobj = (SwigPyObject *)sobj->next; - } else { - if (ptr) { - int newmemory = 0; - *ptr = SWIG_TypeCast(tc,vptr,&newmemory); - if (newmemory == SWIG_CAST_NEW_MEMORY) { - assert(own); - if (own) - *own = *own | SWIG_CAST_NEW_MEMORY; - } - } - break; - } - } - } else { - if (ptr) *ptr = vptr; - break; - } - } - if (sobj) { - if (own) - *own = *own | sobj->own; - if (flags & SWIG_POINTER_DISOWN) { - sobj->own = 0; - } - return SWIG_OK; - } else { - int res = SWIG_ERROR; - if (flags & SWIG_POINTER_IMPLICIT_CONV) { - SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0; - if (data && !data->implicitconv) { - PyObject *klass = data->klass; - if (klass) { - PyObject *impconv; - data->implicitconv = 1; /* avoid recursion and call 'explicit' constructors*/ - impconv = SWIG_Python_CallFunctor(klass, obj); - data->implicitconv = 0; - if (PyErr_Occurred()) { - PyErr_Clear(); - impconv = 0; - } - if (impconv) { - SwigPyObject *iobj = SWIG_Python_GetSwigThis(impconv); - if (iobj) { - void *vptr; - res = SWIG_Python_ConvertPtrAndOwn((PyObject*)iobj, &vptr, ty, 0, 0); - if (SWIG_IsOK(res)) { - if (ptr) { - *ptr = vptr; - /* transfer the ownership to 'ptr' */ - iobj->own = 0; - res = SWIG_AddCast(res); - res = SWIG_AddNewMask(res); - } else { - res = SWIG_AddCast(res); - } - } - } - Py_DECREF(impconv); - } - } - } - } - return res; - } - } -} - -/* Convert a function ptr value */ - -SWIGRUNTIME int -SWIG_Python_ConvertFunctionPtr(PyObject *obj, void **ptr, swig_type_info *ty) { - if (!PyCFunction_Check(obj)) { - return SWIG_ConvertPtr(obj, ptr, ty, 0); - } else { - void *vptr = 0; - - /* here we get the method pointer for callbacks */ - const char *doc = (((PyCFunctionObject *)obj) -> m_ml -> ml_doc); - const char *desc = doc ? strstr(doc, "swig_ptr: ") : 0; - if (desc) - desc = ty ? SWIG_UnpackVoidPtr(desc + 10, &vptr, ty->name) : 0; - if (!desc) - return SWIG_ERROR; - if (ty) { - swig_cast_info *tc = SWIG_TypeCheck(desc,ty); - if (tc) { - int newmemory = 0; - *ptr = SWIG_TypeCast(tc,vptr,&newmemory); - assert(!newmemory); /* newmemory handling not yet implemented */ - } else { - return SWIG_ERROR; - } - } else { - *ptr = vptr; - } - return SWIG_OK; - } -} - -/* Convert a packed value value */ - -SWIGRUNTIME int -SWIG_Python_ConvertPacked(PyObject *obj, void *ptr, size_t sz, swig_type_info *ty) { - swig_type_info *to = SwigPyPacked_UnpackData(obj, ptr, sz); - if (!to) return SWIG_ERROR; - if (ty) { - if (to != ty) { - /* check type cast? */ - swig_cast_info *tc = SWIG_TypeCheck(to->name,ty); - if (!tc) return SWIG_ERROR; - } - } - return SWIG_OK; -} - -/* ----------------------------------------------------------------------------- - * Create a new pointer object - * ----------------------------------------------------------------------------- */ - -/* - Create a new instance object, without calling __init__, and set the - 'this' attribute. -*/ - -SWIGRUNTIME PyObject* -SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this) -{ -#if (PY_VERSION_HEX >= 0x02020000) - PyObject *inst = 0; - PyObject *newraw = data->newraw; - if (newraw) { - inst = PyObject_Call(newraw, data->newargs, NULL); - if (inst) { -#if !defined(SWIG_PYTHON_SLOW_GETSET_THIS) - PyObject **dictptr = _PyObject_GetDictPtr(inst); - if (dictptr != NULL) { - PyObject *dict = *dictptr; - if (dict == NULL) { - dict = PyDict_New(); - *dictptr = dict; - PyDict_SetItem(dict, SWIG_This(), swig_this); - } - } -#else - PyObject *key = SWIG_This(); - PyObject_SetAttr(inst, key, swig_this); -#endif - } - } else { -#if PY_VERSION_HEX >= 0x03000000 - inst = PyBaseObject_Type.tp_new((PyTypeObject*) data->newargs, Py_None, Py_None); - PyObject_SetAttr(inst, SWIG_This(), swig_this); - Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG; -#else - PyObject *dict = PyDict_New(); - PyDict_SetItem(dict, SWIG_This(), swig_this); - inst = PyInstance_NewRaw(data->newargs, dict); - Py_DECREF(dict); -#endif - } - return inst; -#else -#if (PY_VERSION_HEX >= 0x02010000) - PyObject *inst; - PyObject *dict = PyDict_New(); - PyDict_SetItem(dict, SWIG_This(), swig_this); - inst = PyInstance_NewRaw(data->newargs, dict); - Py_DECREF(dict); - return (PyObject *) inst; -#else - PyInstanceObject *inst = PyObject_NEW(PyInstanceObject, &PyInstance_Type); - if (inst == NULL) { - return NULL; - } - inst->in_class = (PyClassObject *)data->newargs; - Py_INCREF(inst->in_class); - inst->in_dict = PyDict_New(); - if (inst->in_dict == NULL) { - Py_DECREF(inst); - return NULL; - } -#ifdef Py_TPFLAGS_HAVE_WEAKREFS - inst->in_weakreflist = NULL; -#endif -#ifdef Py_TPFLAGS_GC - PyObject_GC_Init(inst); -#endif - PyDict_SetItem(inst->in_dict, SWIG_This(), swig_this); - return (PyObject *) inst; -#endif -#endif -} - -SWIGRUNTIME void -SWIG_Python_SetSwigThis(PyObject *inst, PyObject *swig_this) -{ - PyObject *dict; -#if (PY_VERSION_HEX >= 0x02020000) && !defined(SWIG_PYTHON_SLOW_GETSET_THIS) - PyObject **dictptr = _PyObject_GetDictPtr(inst); - if (dictptr != NULL) { - dict = *dictptr; - if (dict == NULL) { - dict = PyDict_New(); - *dictptr = dict; - } - PyDict_SetItem(dict, SWIG_This(), swig_this); - return; - } -#endif - dict = PyObject_GetAttrString(inst, (char*)"__dict__"); - PyDict_SetItem(dict, SWIG_This(), swig_this); - Py_DECREF(dict); -} - - -SWIGINTERN PyObject * -SWIG_Python_InitShadowInstance(PyObject *args) { - PyObject *obj[2]; - if (!SWIG_Python_UnpackTuple(args,(char*)"swiginit", 2, 2, obj)) { - return NULL; - } else { - SwigPyObject *sthis = SWIG_Python_GetSwigThis(obj[0]); - if (sthis) { - SwigPyObject_append((PyObject*) sthis, obj[1]); - } else { - SWIG_Python_SetSwigThis(obj[0], obj[1]); - } - return SWIG_Py_Void(); - } -} - -/* Create a new pointer object */ - -SWIGRUNTIME PyObject * -SWIG_Python_NewPointerObj(void *ptr, swig_type_info *type, int flags) { - if (!ptr) { - return SWIG_Py_Void(); - } else { - int own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0; - PyObject *robj = SwigPyObject_New(ptr, type, own); - SwigPyClientData *clientdata = type ? (SwigPyClientData *)(type->clientdata) : 0; - if (clientdata && !(flags & SWIG_POINTER_NOSHADOW)) { - PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj); - if (inst) { - Py_DECREF(robj); - robj = inst; - } - } - return robj; - } -} - -/* Create a new packed object */ - -SWIGRUNTIMEINLINE PyObject * -SWIG_Python_NewPackedObj(void *ptr, size_t sz, swig_type_info *type) { - return ptr ? SwigPyPacked_New((void *) ptr, sz, type) : SWIG_Py_Void(); -} - -/* -----------------------------------------------------------------------------* - * Get type list - * -----------------------------------------------------------------------------*/ - -#ifdef SWIG_LINK_RUNTIME -void *SWIG_ReturnGlobalTypeList(void *); -#endif - -SWIGRUNTIME swig_module_info * -SWIG_Python_GetModule(void) { - static void *type_pointer = (void *)0; - /* first check if module already created */ - if (!type_pointer) { -#ifdef SWIG_LINK_RUNTIME - type_pointer = SWIG_ReturnGlobalTypeList((void *)0); -#else - type_pointer = PyCObject_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, - (char*)"type_pointer" SWIG_TYPE_TABLE_NAME); - if (PyErr_Occurred()) { - PyErr_Clear(); - type_pointer = (void *)0; - } -#endif - } - return (swig_module_info *) type_pointer; -} - -#if PY_MAJOR_VERSION < 2 -/* PyModule_AddObject function was introduced in Python 2.0. The following function - is copied out of Python/modsupport.c in python version 2.3.4 */ -SWIGINTERN int -PyModule_AddObject(PyObject *m, char *name, PyObject *o) -{ - PyObject *dict; - if (!PyModule_Check(m)) { - PyErr_SetString(PyExc_TypeError, - "PyModule_AddObject() needs module as first arg"); - return SWIG_ERROR; - } - if (!o) { - PyErr_SetString(PyExc_TypeError, - "PyModule_AddObject() needs non-NULL value"); - return SWIG_ERROR; - } - - dict = PyModule_GetDict(m); - if (dict == NULL) { - /* Internal error -- modules must have a dict! */ - PyErr_Format(PyExc_SystemError, "module '%s' has no __dict__", - PyModule_GetName(m)); - return SWIG_ERROR; - } - if (PyDict_SetItemString(dict, name, o)) - return SWIG_ERROR; - Py_DECREF(o); - return SWIG_OK; -} -#endif - -SWIGRUNTIME void -SWIG_Python_DestroyModule(void *vptr) -{ - swig_module_info *swig_module = (swig_module_info *) vptr; - swig_type_info **types = swig_module->types; - size_t i; - for (i =0; i < swig_module->size; ++i) { - swig_type_info *ty = types[i]; - if (ty->owndata) { - SwigPyClientData *data = (SwigPyClientData *) ty->clientdata; - if (data) SwigPyClientData_Del(data); - } - } - Py_DECREF(SWIG_This()); -} - -SWIGRUNTIME void -SWIG_Python_SetModule(swig_module_info *swig_module) { - static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} };/* Sentinel */ - -#if PY_VERSION_HEX >= 0x03000000 - /* Add a dummy module object into sys.modules */ - PyObject *module = PyImport_AddModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION); -#else - PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, - swig_empty_runtime_method_table); -#endif - PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule); - if (pointer && module) { - PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer); - } else { - Py_XDECREF(pointer); - } -} - -/* The python cached type query */ -SWIGRUNTIME PyObject * -SWIG_Python_TypeCache(void) { - static PyObject *SWIG_STATIC_POINTER(cache) = PyDict_New(); - return cache; -} - -SWIGRUNTIME swig_type_info * -SWIG_Python_TypeQuery(const char *type) -{ - PyObject *cache = SWIG_Python_TypeCache(); - PyObject *key = SWIG_Python_str_FromChar(type); - PyObject *obj = PyDict_GetItem(cache, key); - swig_type_info *descriptor; - if (obj) { - descriptor = (swig_type_info *) PyCObject_AsVoidPtr(obj); - } else { - swig_module_info *swig_module = SWIG_Python_GetModule(); - descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type); - if (descriptor) { - obj = PyCObject_FromVoidPtr(descriptor, NULL); - PyDict_SetItem(cache, key, obj); - Py_DECREF(obj); - } - } - Py_DECREF(key); - return descriptor; -} - -/* - For backward compatibility only -*/ -#define SWIG_POINTER_EXCEPTION 0 -#define SWIG_arg_fail(arg) SWIG_Python_ArgFail(arg) -#define SWIG_MustGetPtr(p, type, argnum, flags) SWIG_Python_MustGetPtr(p, type, argnum, flags) - -SWIGRUNTIME int -SWIG_Python_AddErrMesg(const char* mesg, int infront) -{ - if (PyErr_Occurred()) { - PyObject *type = 0; - PyObject *value = 0; - PyObject *traceback = 0; - PyErr_Fetch(&type, &value, &traceback); - if (value) { - char *tmp; - PyObject *old_str = PyObject_Str(value); - Py_XINCREF(type); - PyErr_Clear(); - if (infront) { - PyErr_Format(type, "%s %s", mesg, tmp = SWIG_Python_str_AsChar(old_str)); - } else { - PyErr_Format(type, "%s %s", tmp = SWIG_Python_str_AsChar(old_str), mesg); - } - SWIG_Python_str_DelForPy3(tmp); - Py_DECREF(old_str); - } - return 1; - } else { - return 0; - } -} - -SWIGRUNTIME int -SWIG_Python_ArgFail(int argnum) -{ - if (PyErr_Occurred()) { - /* add information about failing argument */ - char mesg[256]; - PyOS_snprintf(mesg, sizeof(mesg), "argument number %d:", argnum); - return SWIG_Python_AddErrMesg(mesg, 1); - } else { - return 0; - } -} - -SWIGRUNTIMEINLINE const char * -SwigPyObject_GetDesc(PyObject *self) -{ - SwigPyObject *v = (SwigPyObject *)self; - swig_type_info *ty = v ? v->ty : 0; - return ty ? ty->str : (char*)""; -} - -SWIGRUNTIME void -SWIG_Python_TypeError(const char *type, PyObject *obj) -{ - if (type) { -#if defined(SWIG_COBJECT_TYPES) - if (obj && SwigPyObject_Check(obj)) { - const char *otype = (const char *) SwigPyObject_GetDesc(obj); - if (otype) { - PyErr_Format(PyExc_TypeError, "a '%s' is expected, 'SwigPyObject(%s)' is received", - type, otype); - return; - } - } else -#endif - { - const char *otype = (obj ? obj->ob_type->tp_name : 0); - if (otype) { - PyObject *str = PyObject_Str(obj); - const char *cstr = str ? SWIG_Python_str_AsChar(str) : 0; - if (cstr) { - PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s(%s)' is received", - type, otype, cstr); - SWIG_Python_str_DelForPy3(cstr); - } else { - PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s' is received", - type, otype); - } - Py_XDECREF(str); - return; - } - } - PyErr_Format(PyExc_TypeError, "a '%s' is expected", type); - } else { - PyErr_Format(PyExc_TypeError, "unexpected type is received"); - } -} - - -/* Convert a pointer value, signal an exception on a type mismatch */ -SWIGRUNTIME void * -SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags) { - void *result; - if (SWIG_Python_ConvertPtr(obj, &result, ty, flags) == -1) { - PyErr_Clear(); -#if SWIG_POINTER_EXCEPTION - if (flags) { - SWIG_Python_TypeError(SWIG_TypePrettyName(ty), obj); - SWIG_Python_ArgFail(argnum); - } -#endif - } - return result; -} - - -#ifdef __cplusplus -#if 0 -{ /* cc-mode */ -#endif -} -#endif - - - -#define SWIG_exception_fail(code, msg) do { SWIG_Error(code, msg); SWIG_fail; } while(0) - -#define SWIG_contract_assert(expr, msg) if (!(expr)) { SWIG_Error(SWIG_RuntimeError, msg); SWIG_fail; } else - - - -/* -------- TYPES TABLE (BEGIN) -------- */ - -#define SWIGTYPE_p_char swig_types[0] -#define SWIGTYPE_p_int swig_types[1] -#define SWIGTYPE_p_long_long swig_types[2] -#define SWIGTYPE_p_nl_addr swig_types[3] -#define SWIGTYPE_p_nl_cache swig_types[4] -#define SWIGTYPE_p_nl_object swig_types[5] -#define SWIGTYPE_p_nl_sock swig_types[6] -#define SWIGTYPE_p_p_nl_msg swig_types[7] -#define SWIGTYPE_p_rtnl_addr swig_types[8] -#define SWIGTYPE_p_rtnl_class swig_types[9] -#define SWIGTYPE_p_rtnl_cls swig_types[10] -#define SWIGTYPE_p_rtnl_link swig_types[11] -#define SWIGTYPE_p_rtnl_qdisc swig_types[12] -#define SWIGTYPE_p_rtnl_tc swig_types[13] -#define SWIGTYPE_p_short swig_types[14] -#define SWIGTYPE_p_signed_char swig_types[15] -#define SWIGTYPE_p_unsigned_char swig_types[16] -#define SWIGTYPE_p_unsigned_int swig_types[17] -#define SWIGTYPE_p_unsigned_long_long swig_types[18] -#define SWIGTYPE_p_unsigned_short swig_types[19] -#define SWIGTYPE_p_vlan_map swig_types[20] -static swig_type_info *swig_types[22]; -static swig_module_info swig_module = {swig_types, 21, 0, 0, 0, 0}; -#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name) -#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name) - -/* -------- TYPES TABLE (END) -------- */ - -#if (PY_VERSION_HEX <= 0x02000000) -# if !defined(SWIG_PYTHON_CLASSIC) -# error "This python version requires swig to be run with the '-classic' option" -# endif -#endif -#if (PY_VERSION_HEX <= 0x02020000) -# error "This python version requires swig to be run with the '-nomodern' option" -#endif -#if (PY_VERSION_HEX <= 0x02020000) -# error "This python version requires swig to be run with the '-nomodernargs' option" -#endif -#ifndef METH_O -# error "This python version requires swig to be run with the '-nofastunpack' option" -#endif -#ifdef SWIG_TypeQuery -# undef SWIG_TypeQuery -#endif -#define SWIG_TypeQuery SWIG_Python_TypeQuery - -/*----------------------------------------------- - @(target):= _capi.so - ------------------------------------------------*/ -#if PY_VERSION_HEX >= 0x03000000 -# define SWIG_init PyInit__capi - -#else -# define SWIG_init init_capi - -#endif -#define SWIG_name "_capi" - -#define SWIGVERSION 0x010340 -#define SWIG_VERSION SWIGVERSION - - -#define SWIG_as_voidptr(a) (void *)((const void *)(a)) -#define SWIG_as_voidptrptr(a) ((void)SWIG_as_voidptr(*a),(void**)(a)) - - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include - - -#include // Use the C99 official header - - - struct nl_object *link2obj(struct rtnl_link *link) - { - return OBJ_CAST(link); - } - - struct rtnl_link *obj2link(struct nl_object *obj) - { - return (struct rtnl_link *) obj; - } - - struct rtnl_link *get_from_kernel(struct nl_sock *sk, int ifindex, const char *name) - { - struct rtnl_link *link; - if (rtnl_link_get_kernel(sk, ifindex, name, &link) < 0) - return NULL; - return link; - } - - uint32_t inet_get_conf(struct rtnl_link *link, const unsigned int id) - { - uint32_t result; - - if (rtnl_link_inet_get_conf(link, id, &result) < 0) - return 0; - - return result; - } - - -#include -#if !defined(SWIG_NO_LLONG_MAX) -# if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__) -# define LLONG_MAX __LONG_LONG_MAX__ -# define LLONG_MIN (-LLONG_MAX - 1LL) -# define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL) -# endif -#endif - - -SWIGINTERN int -SWIG_AsVal_double (PyObject *obj, double *val) -{ - int res = SWIG_TypeError; - if (PyFloat_Check(obj)) { - if (val) *val = PyFloat_AsDouble(obj); - return SWIG_OK; - } else if (PyInt_Check(obj)) { - if (val) *val = PyInt_AsLong(obj); - return SWIG_OK; - } else if (PyLong_Check(obj)) { - double v = PyLong_AsDouble(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_OK; - } else { - PyErr_Clear(); - } - } -#ifdef SWIG_PYTHON_CAST_MODE - { - int dispatch = 0; - double d = PyFloat_AsDouble(obj); - if (!PyErr_Occurred()) { - if (val) *val = d; - return SWIG_AddCast(SWIG_OK); - } else { - PyErr_Clear(); - } - if (!dispatch) { - long v = PyLong_AsLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_AddCast(SWIG_AddCast(SWIG_OK)); - } else { - PyErr_Clear(); - } - } - } -#endif - return res; -} - - -#include - - -#include - - -SWIGINTERNINLINE int -SWIG_CanCastAsInteger(double *d, double min, double max) { - double x = *d; - if ((min <= x && x <= max)) { - double fx = floor(x); - double cx = ceil(x); - double rd = ((x - fx) < 0.5) ? fx : cx; /* simple rint */ - if ((errno == EDOM) || (errno == ERANGE)) { - errno = 0; - } else { - double summ, reps, diff; - if (rd < x) { - diff = x - rd; - } else if (rd > x) { - diff = rd - x; - } else { - return 1; - } - summ = rd + x; - reps = diff/summ; - if (reps < 8*DBL_EPSILON) { - *d = rd; - return 1; - } - } - } - return 0; -} - - -SWIGINTERN int -SWIG_AsVal_long (PyObject *obj, long* val) -{ - if (PyInt_Check(obj)) { - if (val) *val = PyInt_AsLong(obj); - return SWIG_OK; - } else if (PyLong_Check(obj)) { - long v = PyLong_AsLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_OK; - } else { - PyErr_Clear(); - } - } -#ifdef SWIG_PYTHON_CAST_MODE - { - int dispatch = 0; - long v = PyInt_AsLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_AddCast(SWIG_OK); - } else { - PyErr_Clear(); - } - if (!dispatch) { - double d; - int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d)); - if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) { - if (val) *val = (long)(d); - return res; - } - } - } -#endif - return SWIG_TypeError; -} - - -SWIGINTERN int -SWIG_AsVal_int (PyObject * obj, int *val) -{ - long v; - int res = SWIG_AsVal_long (obj, &v); - if (SWIG_IsOK(res)) { - if ((v < INT_MIN || v > INT_MAX)) { - return SWIG_OverflowError; - } else { - if (val) *val = (int)(v); - } - } - return res; -} - - -SWIGINTERN swig_type_info* -SWIG_pchar_descriptor(void) -{ - static int init = 0; - static swig_type_info* info = 0; - if (!init) { - info = SWIG_TypeQuery("_p_char"); - init = 1; - } - return info; -} - - -SWIGINTERN int -SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc) -{ -#if PY_VERSION_HEX>=0x03000000 - if (PyUnicode_Check(obj)) -#else - if (PyString_Check(obj)) -#endif - { - char *cstr; Py_ssize_t len; -#if PY_VERSION_HEX>=0x03000000 - if (!alloc && cptr) { - /* We can't allow converting without allocation, since the internal - representation of string in Python 3 is UCS-2/UCS-4 but we require - a UTF-8 representation. - TODO(bhy) More detailed explanation */ - return SWIG_RuntimeError; - } - obj = PyUnicode_AsUTF8String(obj); - PyBytes_AsStringAndSize(obj, &cstr, &len); - if(alloc) *alloc = SWIG_NEWOBJ; -#else - PyString_AsStringAndSize(obj, &cstr, &len); -#endif - if (cptr) { - if (alloc) { - /* - In python the user should not be able to modify the inner - string representation. To warranty that, if you define - SWIG_PYTHON_SAFE_CSTRINGS, a new/copy of the python string - buffer is always returned. - - The default behavior is just to return the pointer value, - so, be careful. - */ -#if defined(SWIG_PYTHON_SAFE_CSTRINGS) - if (*alloc != SWIG_OLDOBJ) -#else - if (*alloc == SWIG_NEWOBJ) -#endif - { - *cptr = (char *)memcpy((char *)malloc((len + 1)*sizeof(char)), cstr, sizeof(char)*(len + 1)); - *alloc = SWIG_NEWOBJ; - } - else { - *cptr = cstr; - *alloc = SWIG_OLDOBJ; - } - } else { - #if PY_VERSION_HEX>=0x03000000 - assert(0); /* Should never reach here in Python 3 */ - #endif - *cptr = SWIG_Python_str_AsChar(obj); - } - } - if (psize) *psize = len + 1; -#if PY_VERSION_HEX>=0x03000000 - Py_XDECREF(obj); -#endif - return SWIG_OK; - } else { - swig_type_info* pchar_descriptor = SWIG_pchar_descriptor(); - if (pchar_descriptor) { - void* vptr = 0; - if (SWIG_ConvertPtr(obj, &vptr, pchar_descriptor, 0) == SWIG_OK) { - if (cptr) *cptr = (char *) vptr; - if (psize) *psize = vptr ? (strlen((char *)vptr) + 1) : 0; - if (alloc) *alloc = SWIG_OLDOBJ; - return SWIG_OK; - } - } - } - return SWIG_TypeError; -} - - - - - -SWIGINTERN int -SWIG_AsVal_unsigned_SS_long (PyObject *obj, unsigned long *val) -{ - if (PyInt_Check(obj)) { - long v = PyInt_AsLong(obj); - if (v >= 0) { - if (val) *val = v; - return SWIG_OK; - } else { - return SWIG_OverflowError; - } - } else if (PyLong_Check(obj)) { - unsigned long v = PyLong_AsUnsignedLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_OK; - } else { - PyErr_Clear(); - } - } -#ifdef SWIG_PYTHON_CAST_MODE - { - int dispatch = 0; - unsigned long v = PyLong_AsUnsignedLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_AddCast(SWIG_OK); - } else { - PyErr_Clear(); - } - if (!dispatch) { - double d; - int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d)); - if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ULONG_MAX)) { - if (val) *val = (unsigned long)(d); - return res; - } - } - } -#endif - return SWIG_TypeError; -} - - -SWIGINTERN int -SWIG_AsVal_unsigned_SS_int (PyObject * obj, unsigned int *val) -{ - unsigned long v; - int res = SWIG_AsVal_unsigned_SS_long (obj, &v); - if (SWIG_IsOK(res)) { - if ((v > UINT_MAX)) { - return SWIG_OverflowError; - } else { - if (val) *val = (unsigned int)(v); - } - } - return res; -} - - - #define SWIG_From_long PyInt_FromLong - - -SWIGINTERNINLINE PyObject* -SWIG_From_unsigned_SS_long (unsigned long value) -{ - return (value > LONG_MAX) ? - PyLong_FromUnsignedLong(value) : PyInt_FromLong((long)(value)); -} - - -SWIGINTERNINLINE PyObject * -SWIG_From_unsigned_SS_int (unsigned int value) -{ - return SWIG_From_unsigned_SS_long (value); -} - - -SWIGINTERNINLINE int -SWIG_AsVal_size_t (PyObject * obj, size_t *val) -{ - unsigned long v; - int res = SWIG_AsVal_unsigned_SS_long (obj, val ? &v : 0); - if (SWIG_IsOK(res) && val) *val = (size_t)(v); - return res; -} - - -SWIGINTERNINLINE PyObject * -SWIG_FromCharPtrAndSize(const char* carray, size_t size) -{ - if (carray) { - if (size > INT_MAX) { - swig_type_info* pchar_descriptor = SWIG_pchar_descriptor(); - return pchar_descriptor ? - SWIG_NewPointerObj((char *)(carray), pchar_descriptor, 0) : SWIG_Py_Void(); - } else { -#if PY_VERSION_HEX >= 0x03000000 - return PyUnicode_FromStringAndSize(carray, (int)(size)); -#else - return PyString_FromStringAndSize(carray, (int)(size)); -#endif - } - } else { - return SWIG_Py_Void(); - } -} - - -SWIGINTERNINLINE PyObject * -SWIG_FromCharPtr(const char *cptr) -{ - return SWIG_FromCharPtrAndSize(cptr, (cptr ? strlen(cptr) : 0)); -} - - -SWIGINTERNINLINE PyObject * -SWIG_From_int (int value) -{ - return SWIG_From_long (value); -} - - -SWIGINTERN int -SWIG_AsVal_unsigned_SS_char (PyObject * obj, unsigned char *val) -{ - unsigned long v; - int res = SWIG_AsVal_unsigned_SS_long (obj, &v); - if (SWIG_IsOK(res)) { - if ((v > UCHAR_MAX)) { - return SWIG_OverflowError; - } else { - if (val) *val = (unsigned char)(v); - } - } - return res; -} - - -SWIGINTERNINLINE PyObject * -SWIG_From_unsigned_SS_char (unsigned char value) -{ - return SWIG_From_unsigned_SS_long (value); -} - - -SWIGINTERNINLINE PyObject* -SWIG_From_long_SS_long (long long value) -{ - return ((value < LONG_MIN) || (value > LONG_MAX)) ? - PyLong_FromLongLong(value) : PyInt_FromLong((long)(value)); -} - - -SWIGINTERNINLINE PyObject* -SWIG_From_unsigned_SS_long_SS_long (unsigned long long value) -{ - return (value > LONG_MAX) ? - PyLong_FromUnsignedLongLong(value) : PyInt_FromLong((long)(value)); -} - - -SWIGINTERN int -SWIG_AsVal_unsigned_SS_long_SS_long (PyObject *obj, unsigned long long *val) -{ - int res = SWIG_TypeError; - if (PyLong_Check(obj)) { - unsigned long long v = PyLong_AsUnsignedLongLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_OK; - } else { - PyErr_Clear(); - } - } else { - unsigned long v; - res = SWIG_AsVal_unsigned_SS_long (obj,&v); - if (SWIG_IsOK(res)) { - if (val) *val = v; - return res; - } - } -#ifdef SWIG_PYTHON_CAST_MODE - { - const double mant_max = 1LL << DBL_MANT_DIG; - double d; - res = SWIG_AsVal_double (obj,&d); - if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, mant_max)) { - if (val) *val = (unsigned long long)(d); - return SWIG_AddCast(res); - } - res = SWIG_TypeError; - } -#endif - return res; -} - - - uint32_t tc_str2handle(const char *name) - { - uint32_t result; - - if (rtnl_tc_str2handle(name, &result) < 0) - return 0; - - return result; - } - - - struct nl_object *qdisc2obj(struct rtnl_qdisc *qdisc) - { - return OBJ_CAST(qdisc); - } - - struct rtnl_qdisc *obj2qdisc(struct nl_object *obj) - { - return (struct rtnl_qdisc *) obj; - } - - struct nl_object *class2obj(struct rtnl_class *cl) - { - return OBJ_CAST(cl); - } - - struct rtnl_class *obj2class(struct nl_object *obj) - { - return (struct rtnl_class *) obj; - } - - struct nl_object *cls2obj(struct rtnl_cls *cls) - { - return OBJ_CAST(cls); - } - - struct rtnl_cls *obj2cls(struct nl_object *obj) - { - return (struct rtnl_cls *) obj; - } - - struct rtnl_tc *obj2tc(struct nl_object *obj) - { - return TC_CAST(obj); - } - - -SWIGINTERN int -SWIG_AsVal_unsigned_SS_short (PyObject * obj, unsigned short *val) -{ - unsigned long v; - int res = SWIG_AsVal_unsigned_SS_long (obj, &v); - if (SWIG_IsOK(res)) { - if ((v > USHRT_MAX)) { - return SWIG_OverflowError; - } else { - if (val) *val = (unsigned short)(v); - } - } - return res; -} - - -SWIGINTERNINLINE PyObject * -SWIG_From_unsigned_SS_short (unsigned short value) -{ - return SWIG_From_unsigned_SS_long (value); -} - - - struct nl_object *addr2obj(struct rtnl_addr *addr) - { - return OBJ_CAST(addr); - } - - struct rtnl_addr *obj2addr(struct nl_object *obj) - { - return (struct rtnl_addr *) obj; - } - -#ifdef __cplusplus -extern "C" { -#endif -SWIGINTERN PyObject *_wrap_link2obj(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_object *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "link2obj" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - result = (struct nl_object *)link2obj(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_obj2link(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_object *arg1 = (struct nl_object *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct rtnl_link *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "obj2link" "', argument " "1"" of type '" "struct nl_object *""'"); - } - arg1 = (struct nl_object *)(argp1); - result = (struct rtnl_link *)obj2link(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_link, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_get_from_kernel(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_sock *arg1 = (struct nl_sock *) 0 ; - int arg2 ; - char *arg3 = (char *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - int res3 ; - char *buf3 = 0 ; - int alloc3 = 0 ; - PyObject *swig_obj[3] ; - struct rtnl_link *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"get_from_kernel",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "get_from_kernel" "', argument " "1"" of type '" "struct nl_sock *""'"); - } - arg1 = (struct nl_sock *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "get_from_kernel" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - res3 = SWIG_AsCharPtrAndSize(swig_obj[2], &buf3, NULL, &alloc3); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "get_from_kernel" "', argument " "3"" of type '" "char const *""'"); - } - arg3 = (char *)(buf3); - result = (struct rtnl_link *)get_from_kernel(arg1,arg2,(char const *)arg3); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (alloc3 == SWIG_NEWOBJ) free((char*)buf3); - return resultobj; -fail: - if (alloc3 == SWIG_NEWOBJ) free((char*)buf3); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_inet_get_conf(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - unsigned int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - uint32_t result; - - if (!SWIG_Python_UnpackTuple(args,"inet_get_conf",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "inet_get_conf" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "inet_get_conf" "', argument " "2"" of type '" "unsigned int""'"); - } - arg2 = (unsigned int)(val2); - result = (uint32_t)inet_get_conf(arg1,arg2); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_scope2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - char *arg2 = (char *) 0 ; - size_t arg3 ; - int val1 ; - int ecode1 = 0 ; - int res2 ; - size_t size2 ; - char *buff2 = 0 ; - PyObject *swig_obj[2] ; - char *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_scope2str",2,2,swig_obj)) SWIG_fail; - ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rtnl_scope2str" "', argument " "1"" of type '" "int""'"); - } - arg1 = (int)(val1); - res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_scope2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); - } - buff2= (char *)malloc((size2+1)*sizeof(char)); - arg3 = (size_t)(size2); - arg2 = (char *)(buff2); - result = (char *)rtnl_scope2str(arg1,arg2,arg3); - resultobj = SWIG_FromCharPtr((const char *)result); - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); - if (buff2) free((char*)buff2); - return resultobj; -fail: - if (buff2) free((char*)buff2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_str2scope(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_str2scope" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = (char *)(buf1); - result = (int)rtnl_str2scope((char const *)arg1); - resultobj = SWIG_From_int((int)(result)); - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_alloc(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_alloc",0,0,0)) SWIG_fail; - result = (struct rtnl_link *)rtnl_link_alloc(); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_link, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache *arg1 = (struct nl_cache *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - struct rtnl_link *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_get",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get" "', argument " "1"" of type '" "struct nl_cache *""'"); - } - arg1 = (struct nl_cache *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_get" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - result = (struct rtnl_link *)rtnl_link_get(arg1,arg2); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_link, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_get_by_name(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache *arg1 = (struct nl_cache *) 0 ; - char *arg2 = (char *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - PyObject *swig_obj[2] ; - struct rtnl_link *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_get_by_name",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_by_name" "', argument " "1"" of type '" "struct nl_cache *""'"); - } - arg1 = (struct nl_cache *)(argp1); - res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_get_by_name" "', argument " "2"" of type '" "char const *""'"); - } - arg2 = (char *)(buf2); - result = (struct rtnl_link *)rtnl_link_get_by_name(arg1,(char const *)arg2); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return resultobj; -fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_build_add_request(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - int arg2 ; - struct nl_msg **arg3 = (struct nl_msg **) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - void *argp3 = 0 ; - int res3 = 0 ; - PyObject *swig_obj[3] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_build_add_request",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_build_add_request" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_build_add_request" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - res3 = SWIG_ConvertPtr(swig_obj[2], &argp3,SWIGTYPE_p_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "rtnl_link_build_add_request" "', argument " "3"" of type '" "struct nl_msg **""'"); - } - arg3 = (struct nl_msg **)(argp3); - result = (int)rtnl_link_build_add_request(arg1,arg2,arg3); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_add(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_sock *arg1 = (struct nl_sock *) 0 ; - struct rtnl_link *arg2 = (struct rtnl_link *) 0 ; - int arg3 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - int val3 ; - int ecode3 = 0 ; - PyObject *swig_obj[3] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_add",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_add" "', argument " "1"" of type '" "struct nl_sock *""'"); - } - arg1 = (struct nl_sock *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_add" "', argument " "2"" of type '" "struct rtnl_link *""'"); - } - arg2 = (struct rtnl_link *)(argp2); - ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_link_add" "', argument " "3"" of type '" "int""'"); - } - arg3 = (int)(val3); - result = (int)rtnl_link_add(arg1,arg2,arg3); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_build_change_request(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - struct rtnl_link *arg2 = (struct rtnl_link *) 0 ; - int arg3 ; - struct nl_msg **arg4 = (struct nl_msg **) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - int val3 ; - int ecode3 = 0 ; - void *argp4 = 0 ; - int res4 = 0 ; - PyObject *swig_obj[4] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_build_change_request",4,4,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_build_change_request" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_build_change_request" "', argument " "2"" of type '" "struct rtnl_link *""'"); - } - arg2 = (struct rtnl_link *)(argp2); - ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_link_build_change_request" "', argument " "3"" of type '" "int""'"); - } - arg3 = (int)(val3); - res4 = SWIG_ConvertPtr(swig_obj[3], &argp4,SWIGTYPE_p_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res4)) { - SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "rtnl_link_build_change_request" "', argument " "4"" of type '" "struct nl_msg **""'"); - } - arg4 = (struct nl_msg **)(argp4); - result = (int)rtnl_link_build_change_request(arg1,arg2,arg3,arg4); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_change(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_sock *arg1 = (struct nl_sock *) 0 ; - struct rtnl_link *arg2 = (struct rtnl_link *) 0 ; - struct rtnl_link *arg3 = (struct rtnl_link *) 0 ; - int arg4 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - void *argp3 = 0 ; - int res3 = 0 ; - int val4 ; - int ecode4 = 0 ; - PyObject *swig_obj[4] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_change",4,4,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_change" "', argument " "1"" of type '" "struct nl_sock *""'"); - } - arg1 = (struct nl_sock *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_change" "', argument " "2"" of type '" "struct rtnl_link *""'"); - } - arg2 = (struct rtnl_link *)(argp2); - res3 = SWIG_ConvertPtr(swig_obj[2], &argp3,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "rtnl_link_change" "', argument " "3"" of type '" "struct rtnl_link *""'"); - } - arg3 = (struct rtnl_link *)(argp3); - ecode4 = SWIG_AsVal_int(swig_obj[3], &val4); - if (!SWIG_IsOK(ecode4)) { - SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "rtnl_link_change" "', argument " "4"" of type '" "int""'"); - } - arg4 = (int)(val4); - result = (int)rtnl_link_change(arg1,arg2,arg3,arg4); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_build_delete_request(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - struct nl_msg **arg2 = (struct nl_msg **) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_build_delete_request",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_build_delete_request" "', argument " "1"" of type '" "struct rtnl_link const *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_build_delete_request" "', argument " "2"" of type '" "struct nl_msg **""'"); - } - arg2 = (struct nl_msg **)(argp2); - result = (int)rtnl_link_build_delete_request((struct rtnl_link const *)arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_delete(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_sock *arg1 = (struct nl_sock *) 0 ; - struct rtnl_link *arg2 = (struct rtnl_link *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_delete",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_delete" "', argument " "1"" of type '" "struct nl_sock *""'"); - } - arg1 = (struct nl_sock *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_delete" "', argument " "2"" of type '" "struct rtnl_link const *""'"); - } - arg2 = (struct rtnl_link *)(argp2); - result = (int)rtnl_link_delete(arg1,(struct rtnl_link const *)arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_build_get_request(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - char *arg2 = (char *) 0 ; - struct nl_msg **arg3 = (struct nl_msg **) 0 ; - int val1 ; - int ecode1 = 0 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - void *argp3 = 0 ; - int res3 = 0 ; - PyObject *swig_obj[3] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_build_get_request",3,3,swig_obj)) SWIG_fail; - ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rtnl_link_build_get_request" "', argument " "1"" of type '" "int""'"); - } - arg1 = (int)(val1); - res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_build_get_request" "', argument " "2"" of type '" "char const *""'"); - } - arg2 = (char *)(buf2); - res3 = SWIG_ConvertPtr(swig_obj[2], &argp3,SWIGTYPE_p_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "rtnl_link_build_get_request" "', argument " "3"" of type '" "struct nl_msg **""'"); - } - arg3 = (struct nl_msg **)(argp3); - result = (int)rtnl_link_build_get_request(arg1,(char const *)arg2,arg3); - resultobj = SWIG_From_int((int)(result)); - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return resultobj; -fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_stat2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - char *arg2 = (char *) 0 ; - size_t arg3 ; - int val1 ; - int ecode1 = 0 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - size_t val3 ; - int ecode3 = 0 ; - PyObject *swig_obj[3] ; - char *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_stat2str",3,3,swig_obj)) SWIG_fail; - ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rtnl_link_stat2str" "', argument " "1"" of type '" "int""'"); - } - arg1 = (int)(val1); - res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_stat2str" "', argument " "2"" of type '" "char *""'"); - } - arg2 = (char *)(buf2); - ecode3 = SWIG_AsVal_size_t(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_link_stat2str" "', argument " "3"" of type '" "size_t""'"); - } - arg3 = (size_t)(val3); - result = (char *)rtnl_link_stat2str(arg1,arg2,arg3); - resultobj = SWIG_FromCharPtr((const char *)result); - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return resultobj; -fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_str2stat(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_str2stat" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = (char *)(buf1); - result = (int)rtnl_link_str2stat((char const *)arg1); - resultobj = SWIG_From_int((int)(result)); - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_flags2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - char *arg2 = (char *) 0 ; - size_t arg3 ; - int val1 ; - int ecode1 = 0 ; - int res2 ; - size_t size2 ; - char *buff2 = 0 ; - PyObject *swig_obj[2] ; - char *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_flags2str",2,2,swig_obj)) SWIG_fail; - ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rtnl_link_flags2str" "', argument " "1"" of type '" "int""'"); - } - arg1 = (int)(val1); - res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_flags2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); - } - buff2= (char *)malloc((size2+1)*sizeof(char)); - arg3 = (size_t)(size2); - arg2 = (char *)(buff2); - result = (char *)rtnl_link_flags2str(arg1,arg2,arg3); - resultobj = SWIG_FromCharPtr((const char *)result); - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); - if (buff2) free((char*)buff2); - return resultobj; -fail: - if (buff2) free((char*)buff2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_str2flags(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_str2flags" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = (char *)(buf1); - result = (int)rtnl_link_str2flags((char const *)arg1); - resultobj = SWIG_From_int((int)(result)); - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_operstate2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint8_t arg1 ; - char *arg2 = (char *) 0 ; - size_t arg3 ; - unsigned char val1 ; - int ecode1 = 0 ; - int res2 ; - size_t size2 ; - char *buff2 = 0 ; - PyObject *swig_obj[2] ; - char *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_operstate2str",2,2,swig_obj)) SWIG_fail; - ecode1 = SWIG_AsVal_unsigned_SS_char(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rtnl_link_operstate2str" "', argument " "1"" of type '" "uint8_t""'"); - } - arg1 = (uint8_t)(val1); - res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_operstate2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); - } - buff2= (char *)malloc((size2+1)*sizeof(char)); - arg3 = (size_t)(size2); - arg2 = (char *)(buff2); - result = (char *)rtnl_link_operstate2str(arg1,arg2,arg3); - resultobj = SWIG_FromCharPtr((const char *)result); - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); - if (buff2) free((char*)buff2); - return resultobj; -fail: - if (buff2) free((char*)buff2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_str2operstate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_str2operstate" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = (char *)(buf1); - result = (int)rtnl_link_str2operstate((char const *)arg1); - resultobj = SWIG_From_int((int)(result)); - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_mode2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint8_t arg1 ; - char *arg2 = (char *) 0 ; - size_t arg3 ; - unsigned char val1 ; - int ecode1 = 0 ; - int res2 ; - size_t size2 ; - char *buff2 = 0 ; - PyObject *swig_obj[2] ; - char *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_mode2str",2,2,swig_obj)) SWIG_fail; - ecode1 = SWIG_AsVal_unsigned_SS_char(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rtnl_link_mode2str" "', argument " "1"" of type '" "uint8_t""'"); - } - arg1 = (uint8_t)(val1); - res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_mode2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); - } - buff2= (char *)malloc((size2+1)*sizeof(char)); - arg3 = (size_t)(size2); - arg2 = (char *)(buff2); - result = (char *)rtnl_link_mode2str(arg1,arg2,arg3); - resultobj = SWIG_FromCharPtr((const char *)result); - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); - if (buff2) free((char*)buff2); - return resultobj; -fail: - if (buff2) free((char*)buff2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_str2mode(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_str2mode" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = (char *)(buf1); - result = (int)rtnl_link_str2mode((char const *)arg1); - resultobj = SWIG_From_int((int)(result)); - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_set_qdisc(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - char *arg2 = (char *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_qdisc",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_qdisc" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_set_qdisc" "', argument " "2"" of type '" "char const *""'"); - } - arg2 = (char *)(buf2); - rtnl_link_set_qdisc(arg1,(char const *)arg2); - resultobj = SWIG_Py_Void(); - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return resultobj; -fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_get_qdisc(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - char *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_qdisc" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - result = (char *)rtnl_link_get_qdisc(arg1); - resultobj = SWIG_FromCharPtr((const char *)result); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_set_name(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - char *arg2 = (char *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_name",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_name" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_set_name" "', argument " "2"" of type '" "char const *""'"); - } - arg2 = (char *)(buf2); - rtnl_link_set_name(arg1,(char const *)arg2); - resultobj = SWIG_Py_Void(); - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return resultobj; -fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_get_name(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - char *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_name" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - result = (char *)rtnl_link_get_name(arg1); - resultobj = SWIG_FromCharPtr((const char *)result); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_set_flags(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - unsigned int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_flags",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_flags" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_set_flags" "', argument " "2"" of type '" "unsigned int""'"); - } - arg2 = (unsigned int)(val2); - rtnl_link_set_flags(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_unset_flags(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - unsigned int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_unset_flags",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_unset_flags" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_unset_flags" "', argument " "2"" of type '" "unsigned int""'"); - } - arg2 = (unsigned int)(val2); - rtnl_link_unset_flags(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_get_flags(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - unsigned int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_flags" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - result = (unsigned int)rtnl_link_get_flags(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_set_mtu(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - unsigned int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_mtu",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_mtu" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_set_mtu" "', argument " "2"" of type '" "unsigned int""'"); - } - arg2 = (unsigned int)(val2); - rtnl_link_set_mtu(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_get_mtu(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - unsigned int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_mtu" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - result = (unsigned int)rtnl_link_get_mtu(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_set_txqlen(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - unsigned int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_txqlen",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_txqlen" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_set_txqlen" "', argument " "2"" of type '" "unsigned int""'"); - } - arg2 = (unsigned int)(val2); - rtnl_link_set_txqlen(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_get_txqlen(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - unsigned int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_txqlen" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - result = (unsigned int)rtnl_link_get_txqlen(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_set_weight(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - unsigned int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_weight",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_weight" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_set_weight" "', argument " "2"" of type '" "unsigned int""'"); - } - arg2 = (unsigned int)(val2); - rtnl_link_set_weight(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_get_weight(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - unsigned int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_weight" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - result = (unsigned int)rtnl_link_get_weight(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_set_ifindex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_ifindex",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_ifindex" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_set_ifindex" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - rtnl_link_set_ifindex(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_get_ifindex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_ifindex" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - result = (int)rtnl_link_get_ifindex(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_set_family(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_family",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_family" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_set_family" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - rtnl_link_set_family(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_get_family(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_family" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - result = (int)rtnl_link_get_family(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_set_arptype(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - unsigned int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_arptype",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_arptype" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_set_arptype" "', argument " "2"" of type '" "unsigned int""'"); - } - arg2 = (unsigned int)(val2); - rtnl_link_set_arptype(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_get_arptype(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - unsigned int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_arptype" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - result = (unsigned int)rtnl_link_get_arptype(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_set_addr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - struct nl_addr *arg2 = (struct nl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_addr",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_addr" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_set_addr" "', argument " "2"" of type '" "struct nl_addr *""'"); - } - arg2 = (struct nl_addr *)(argp2); - rtnl_link_set_addr(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_get_addr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_addr *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_addr" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - result = (struct nl_addr *)rtnl_link_get_addr(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_addr, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_set_broadcast(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - struct nl_addr *arg2 = (struct nl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_broadcast",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_broadcast" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_set_broadcast" "', argument " "2"" of type '" "struct nl_addr *""'"); - } - arg2 = (struct nl_addr *)(argp2); - rtnl_link_set_broadcast(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_get_broadcast(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_addr *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_broadcast" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - result = (struct nl_addr *)rtnl_link_get_broadcast(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_addr, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_set_link(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_link",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_link" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_set_link" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - rtnl_link_set_link(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_get_link(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_link" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - result = (int)rtnl_link_get_link(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_set_master(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_master",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_master" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_set_master" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - rtnl_link_set_master(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_get_master(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_master" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - result = (int)rtnl_link_get_master(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_set_operstate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - uint8_t arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned char val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_operstate",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_operstate" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_char(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_set_operstate" "', argument " "2"" of type '" "uint8_t""'"); - } - arg2 = (uint8_t)(val2); - rtnl_link_set_operstate(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_get_operstate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint8_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_operstate" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - result = (uint8_t)rtnl_link_get_operstate(arg1); - resultobj = SWIG_From_unsigned_SS_char((unsigned char)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_set_linkmode(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - uint8_t arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned char val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_linkmode",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_linkmode" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_char(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_set_linkmode" "', argument " "2"" of type '" "uint8_t""'"); - } - arg2 = (uint8_t)(val2); - rtnl_link_set_linkmode(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_get_linkmode(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint8_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_linkmode" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - result = (uint8_t)rtnl_link_get_linkmode(arg1); - resultobj = SWIG_From_unsigned_SS_char((unsigned char)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_get_ifalias(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - char *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_ifalias" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - result = (char *)rtnl_link_get_ifalias(arg1); - resultobj = SWIG_FromCharPtr((const char *)result); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_set_ifalias(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - char *arg2 = (char *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_ifalias",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_ifalias" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_set_ifalias" "', argument " "2"" of type '" "char const *""'"); - } - arg2 = (char *)(buf2); - rtnl_link_set_ifalias(arg1,(char const *)arg2); - resultobj = SWIG_Py_Void(); - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return resultobj; -fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_get_num_vf(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - uint32_t *arg2 = (uint32_t *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_get_num_vf",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_num_vf" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_unsigned_int, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_get_num_vf" "', argument " "2"" of type '" "uint32_t *""'"); - } - arg2 = (uint32_t *)(argp2); - result = (int)rtnl_link_get_num_vf(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_get_stat(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - uint64_t result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_get_stat",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_stat" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_get_stat" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - result = (uint64_t)rtnl_link_get_stat(arg1,arg2); - resultobj = SWIG_From_unsigned_SS_long_SS_long((unsigned long long)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_set_stat(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - unsigned int arg2 ; - uint64_t arg3 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - unsigned long long val3 ; - int ecode3 = 0 ; - PyObject *swig_obj[3] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_stat",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_stat" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_set_stat" "', argument " "2"" of type '" "unsigned int""'"); - } - arg2 = (unsigned int)(val2); - ecode3 = SWIG_AsVal_unsigned_SS_long_SS_long(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_link_set_stat" "', argument " "3"" of type '" "uint64_t""'"); - } - arg3 = (uint64_t)(val3); - result = (int)rtnl_link_set_stat(arg1,arg2,arg3); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_set_info_type(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - char *arg2 = (char *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_set_info_type",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_set_info_type" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_set_info_type" "', argument " "2"" of type '" "char const *""'"); - } - arg2 = (char *)(buf2); - result = (int)rtnl_link_set_info_type(arg1,(char const *)arg2); - resultobj = SWIG_From_int((int)(result)); - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return resultobj; -fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_get_info_type(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - char *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_get_info_type" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - result = (char *)rtnl_link_get_info_type(arg1); - resultobj = SWIG_FromCharPtr((const char *)result); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_vlan_map_vm_from_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct vlan_map *arg1 = (struct vlan_map *) 0 ; - uint32_t arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"vlan_map_vm_from_set",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_vlan_map, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "vlan_map_vm_from_set" "', argument " "1"" of type '" "struct vlan_map *""'"); - } - arg1 = (struct vlan_map *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "vlan_map_vm_from_set" "', argument " "2"" of type '" "uint32_t""'"); - } - arg2 = (uint32_t)(val2); - if (arg1) (arg1)->vm_from = arg2; - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_vlan_map_vm_from_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct vlan_map *arg1 = (struct vlan_map *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint32_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_vlan_map, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "vlan_map_vm_from_get" "', argument " "1"" of type '" "struct vlan_map *""'"); - } - arg1 = (struct vlan_map *)(argp1); - result = (uint32_t) ((arg1)->vm_from); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_vlan_map_vm_to_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct vlan_map *arg1 = (struct vlan_map *) 0 ; - uint32_t arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"vlan_map_vm_to_set",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_vlan_map, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "vlan_map_vm_to_set" "', argument " "1"" of type '" "struct vlan_map *""'"); - } - arg1 = (struct vlan_map *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "vlan_map_vm_to_set" "', argument " "2"" of type '" "uint32_t""'"); - } - arg2 = (uint32_t)(val2); - if (arg1) (arg1)->vm_to = arg2; - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_vlan_map_vm_to_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct vlan_map *arg1 = (struct vlan_map *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint32_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_vlan_map, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "vlan_map_vm_to_get" "', argument " "1"" of type '" "struct vlan_map *""'"); - } - arg1 = (struct vlan_map *)(argp1); - result = (uint32_t) ((arg1)->vm_to); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_delete_vlan_map(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct vlan_map *arg1 = (struct vlan_map *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_vlan_map, SWIG_POINTER_DISOWN | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_vlan_map" "', argument " "1"" of type '" "struct vlan_map *""'"); - } - arg1 = (struct vlan_map *)(argp1); - free((char *) arg1); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *vlan_map_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *obj; - if (!SWIG_Python_UnpackTuple(args,(char*)"swigregister", 1, 1,&obj)) return NULL; - SWIG_TypeNewClientData(SWIGTYPE_p_vlan_map, SWIG_NewClientData(obj)); - return SWIG_Py_Void(); -} - -SWIGINTERN PyObject *_wrap_rtnl_link_vlan_flags2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - char *arg2 = (char *) 0 ; - size_t arg3 ; - int val1 ; - int ecode1 = 0 ; - int res2 ; - size_t size2 ; - char *buff2 = 0 ; - PyObject *swig_obj[2] ; - char *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_vlan_flags2str",2,2,swig_obj)) SWIG_fail; - ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rtnl_link_vlan_flags2str" "', argument " "1"" of type '" "int""'"); - } - arg1 = (int)(val1); - res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_vlan_flags2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); - } - buff2= (char *)malloc((size2+1)*sizeof(char)); - arg3 = (size_t)(size2); - arg2 = (char *)(buff2); - result = (char *)rtnl_link_vlan_flags2str(arg1,arg2,arg3); - resultobj = SWIG_FromCharPtr((const char *)result); - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); - if (buff2) free((char*)buff2); - return resultobj; -fail: - if (buff2) free((char*)buff2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_vlan_str2flags(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_vlan_str2flags" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = (char *)(buf1); - result = (int)rtnl_link_vlan_str2flags((char const *)arg1); - resultobj = SWIG_From_int((int)(result)); - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_vlan_set_id(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_vlan_set_id",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_vlan_set_id" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_vlan_set_id" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - result = (int)rtnl_link_vlan_set_id(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_vlan_get_id(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_vlan_get_id" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - result = (int)rtnl_link_vlan_get_id(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_vlan_set_flags(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - unsigned int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_vlan_set_flags",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_vlan_set_flags" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_vlan_set_flags" "', argument " "2"" of type '" "unsigned int""'"); - } - arg2 = (unsigned int)(val2); - result = (int)rtnl_link_vlan_set_flags(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_vlan_unset_flags(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - unsigned int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_vlan_unset_flags",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_vlan_unset_flags" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_vlan_unset_flags" "', argument " "2"" of type '" "unsigned int""'"); - } - arg2 = (unsigned int)(val2); - result = (int)rtnl_link_vlan_unset_flags(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_vlan_get_flags(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - unsigned int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_vlan_get_flags" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - result = (unsigned int)rtnl_link_vlan_get_flags(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_vlan_set_ingress_map(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - int arg2 ; - uint32_t arg3 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - unsigned int val3 ; - int ecode3 = 0 ; - PyObject *swig_obj[3] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_vlan_set_ingress_map",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_vlan_set_ingress_map" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_vlan_set_ingress_map" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - ecode3 = SWIG_AsVal_unsigned_SS_int(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_link_vlan_set_ingress_map" "', argument " "3"" of type '" "uint32_t""'"); - } - arg3 = (uint32_t)(val3); - result = (int)rtnl_link_vlan_set_ingress_map(arg1,arg2,arg3); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_vlan_get_ingress_map(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint32_t *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_vlan_get_ingress_map" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - result = (uint32_t *)rtnl_link_vlan_get_ingress_map(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_unsigned_int, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_vlan_set_egress_map(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - uint32_t arg2 ; - int arg3 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - int val3 ; - int ecode3 = 0 ; - PyObject *swig_obj[3] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_vlan_set_egress_map",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_vlan_set_egress_map" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_vlan_set_egress_map" "', argument " "2"" of type '" "uint32_t""'"); - } - arg2 = (uint32_t)(val2); - ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_link_vlan_set_egress_map" "', argument " "3"" of type '" "int""'"); - } - arg3 = (int)(val3); - result = (int)rtnl_link_vlan_set_egress_map(arg1,arg2,arg3); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_vlan_get_egress_map(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - int *arg2 = (int *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - struct vlan_map *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_vlan_get_egress_map",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_vlan_get_egress_map" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_int, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_vlan_get_egress_map" "', argument " "2"" of type '" "int *""'"); - } - arg2 = (int *)(argp2); - result = (struct vlan_map *)rtnl_link_vlan_get_egress_map(arg1,arg2); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_vlan_map, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_inet_devconf2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - char *arg2 = (char *) 0 ; - size_t arg3 ; - int val1 ; - int ecode1 = 0 ; - int res2 ; - size_t size2 ; - char *buff2 = 0 ; - PyObject *swig_obj[2] ; - char *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_inet_devconf2str",2,2,swig_obj)) SWIG_fail; - ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rtnl_link_inet_devconf2str" "', argument " "1"" of type '" "int""'"); - } - arg1 = (int)(val1); - res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_link_inet_devconf2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); - } - buff2= (char *)malloc((size2+1)*sizeof(char)); - arg3 = (size_t)(size2); - arg2 = (char *)(buff2); - result = (char *)rtnl_link_inet_devconf2str(arg1,arg2,arg3); - resultobj = SWIG_FromCharPtr((const char *)result); - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); - if (buff2) free((char*)buff2); - return resultobj; -fail: - if (buff2) free((char*)buff2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_inet_str2devconf(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - PyObject *swig_obj[1] ; - unsigned int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_inet_str2devconf" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = (char *)(buf1); - result = (unsigned int)rtnl_link_inet_str2devconf((char const *)arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_link_inet_set_conf(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_link *arg1 = (struct rtnl_link *) 0 ; - unsigned int arg2 ; - uint32_t arg3 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - unsigned int val3 ; - int ecode3 = 0 ; - PyObject *swig_obj[3] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_link_inet_set_conf",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_link_inet_set_conf" "', argument " "1"" of type '" "struct rtnl_link *""'"); - } - arg1 = (struct rtnl_link *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_link_inet_set_conf" "', argument " "2"" of type '" "unsigned int""'"); - } - arg2 = (unsigned int)(val2); - ecode3 = SWIG_AsVal_unsigned_SS_int(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_link_inet_set_conf" "', argument " "3"" of type '" "uint32_t""'"); - } - arg3 = (uint32_t)(val3); - result = (int)rtnl_link_inet_set_conf(arg1,arg2,arg3); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_tc_str2handle(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - PyObject *swig_obj[1] ; - uint32_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "tc_str2handle" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = (char *)(buf1); - result = (uint32_t)tc_str2handle((char const *)arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_tc_set_ifindex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_set_ifindex",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_set_ifindex" "', argument " "1"" of type '" "struct rtnl_tc *""'"); - } - arg1 = (struct rtnl_tc *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_tc_set_ifindex" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - rtnl_tc_set_ifindex(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_tc_get_ifindex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_get_ifindex" "', argument " "1"" of type '" "struct rtnl_tc *""'"); - } - arg1 = (struct rtnl_tc *)(argp1); - result = (int)rtnl_tc_get_ifindex(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_tc_set_link(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; - struct rtnl_link *arg2 = (struct rtnl_link *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_set_link",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_set_link" "', argument " "1"" of type '" "struct rtnl_tc *""'"); - } - arg1 = (struct rtnl_tc *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_tc_set_link" "', argument " "2"" of type '" "struct rtnl_link *""'"); - } - arg2 = (struct rtnl_link *)(argp2); - rtnl_tc_set_link(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_tc_get_link(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct rtnl_link *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_get_link" "', argument " "1"" of type '" "struct rtnl_tc *""'"); - } - arg1 = (struct rtnl_tc *)(argp1); - result = (struct rtnl_link *)rtnl_tc_get_link(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_link, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_tc_set_mtu(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; - uint32_t arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_set_mtu",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_set_mtu" "', argument " "1"" of type '" "struct rtnl_tc *""'"); - } - arg1 = (struct rtnl_tc *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_tc_set_mtu" "', argument " "2"" of type '" "uint32_t""'"); - } - arg2 = (uint32_t)(val2); - rtnl_tc_set_mtu(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_tc_get_mtu(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint32_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_get_mtu" "', argument " "1"" of type '" "struct rtnl_tc *""'"); - } - arg1 = (struct rtnl_tc *)(argp1); - result = (uint32_t)rtnl_tc_get_mtu(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_tc_set_mpu(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; - uint32_t arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_set_mpu",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_set_mpu" "', argument " "1"" of type '" "struct rtnl_tc *""'"); - } - arg1 = (struct rtnl_tc *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_tc_set_mpu" "', argument " "2"" of type '" "uint32_t""'"); - } - arg2 = (uint32_t)(val2); - rtnl_tc_set_mpu(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_tc_get_mpu(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint32_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_get_mpu" "', argument " "1"" of type '" "struct rtnl_tc *""'"); - } - arg1 = (struct rtnl_tc *)(argp1); - result = (uint32_t)rtnl_tc_get_mpu(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_tc_set_overhead(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; - uint32_t arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_set_overhead",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_set_overhead" "', argument " "1"" of type '" "struct rtnl_tc *""'"); - } - arg1 = (struct rtnl_tc *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_tc_set_overhead" "', argument " "2"" of type '" "uint32_t""'"); - } - arg2 = (uint32_t)(val2); - rtnl_tc_set_overhead(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_tc_get_overhead(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint32_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_get_overhead" "', argument " "1"" of type '" "struct rtnl_tc *""'"); - } - arg1 = (struct rtnl_tc *)(argp1); - result = (uint32_t)rtnl_tc_get_overhead(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_tc_set_linktype(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; - uint32_t arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_set_linktype",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_set_linktype" "', argument " "1"" of type '" "struct rtnl_tc *""'"); - } - arg1 = (struct rtnl_tc *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_tc_set_linktype" "', argument " "2"" of type '" "uint32_t""'"); - } - arg2 = (uint32_t)(val2); - rtnl_tc_set_linktype(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_tc_get_linktype(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint32_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_get_linktype" "', argument " "1"" of type '" "struct rtnl_tc *""'"); - } - arg1 = (struct rtnl_tc *)(argp1); - result = (uint32_t)rtnl_tc_get_linktype(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_tc_set_handle(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; - uint32_t arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_set_handle",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_set_handle" "', argument " "1"" of type '" "struct rtnl_tc *""'"); - } - arg1 = (struct rtnl_tc *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_tc_set_handle" "', argument " "2"" of type '" "uint32_t""'"); - } - arg2 = (uint32_t)(val2); - rtnl_tc_set_handle(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_tc_get_handle(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint32_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_get_handle" "', argument " "1"" of type '" "struct rtnl_tc *""'"); - } - arg1 = (struct rtnl_tc *)(argp1); - result = (uint32_t)rtnl_tc_get_handle(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_tc_set_parent(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; - uint32_t arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_set_parent",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_set_parent" "', argument " "1"" of type '" "struct rtnl_tc *""'"); - } - arg1 = (struct rtnl_tc *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_tc_set_parent" "', argument " "2"" of type '" "uint32_t""'"); - } - arg2 = (uint32_t)(val2); - rtnl_tc_set_parent(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_tc_get_parent(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint32_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_get_parent" "', argument " "1"" of type '" "struct rtnl_tc *""'"); - } - arg1 = (struct rtnl_tc *)(argp1); - result = (uint32_t)rtnl_tc_get_parent(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_tc_set_kind(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; - char *arg2 = (char *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_set_kind",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_set_kind" "', argument " "1"" of type '" "struct rtnl_tc *""'"); - } - arg1 = (struct rtnl_tc *)(argp1); - res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_tc_set_kind" "', argument " "2"" of type '" "char const *""'"); - } - arg2 = (char *)(buf2); - result = (int)rtnl_tc_set_kind(arg1,(char const *)arg2); - resultobj = SWIG_From_int((int)(result)); - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return resultobj; -fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_tc_get_kind(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - char *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_get_kind" "', argument " "1"" of type '" "struct rtnl_tc *""'"); - } - arg1 = (struct rtnl_tc *)(argp1); - result = (char *)rtnl_tc_get_kind(arg1); - resultobj = SWIG_FromCharPtr((const char *)result); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_tc_get_stat(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_tc *arg1 = (struct rtnl_tc *) 0 ; - enum rtnl_tc_stat arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - uint64_t result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_get_stat",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_tc, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_tc_get_stat" "', argument " "1"" of type '" "struct rtnl_tc *""'"); - } - arg1 = (struct rtnl_tc *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_tc_get_stat" "', argument " "2"" of type '" "enum rtnl_tc_stat""'"); - } - arg2 = (enum rtnl_tc_stat)(val2); - result = (uint64_t)rtnl_tc_get_stat(arg1,arg2); - resultobj = SWIG_From_unsigned_SS_long_SS_long((unsigned long long)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_tc_calc_txtime(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - int arg2 ; - int val1 ; - int ecode1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_calc_txtime",2,2,swig_obj)) SWIG_fail; - ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rtnl_tc_calc_txtime" "', argument " "1"" of type '" "int""'"); - } - arg1 = (int)(val1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_tc_calc_txtime" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - result = (int)rtnl_tc_calc_txtime(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_tc_calc_bufsize(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - int arg2 ; - int val1 ; - int ecode1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_calc_bufsize",2,2,swig_obj)) SWIG_fail; - ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rtnl_tc_calc_bufsize" "', argument " "1"" of type '" "int""'"); - } - arg1 = (int)(val1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_tc_calc_bufsize" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - result = (int)rtnl_tc_calc_bufsize(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_tc_calc_cell_log(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - int val1 ; - int ecode1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rtnl_tc_calc_cell_log" "', argument " "1"" of type '" "int""'"); - } - arg1 = (int)(val1); - result = (int)rtnl_tc_calc_cell_log(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_tc_read_classid_file(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_read_classid_file",0,0,0)) SWIG_fail; - result = (int)rtnl_tc_read_classid_file(); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_tc_handle2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint32_t arg1 ; - char *arg2 = (char *) 0 ; - size_t arg3 ; - unsigned int val1 ; - int ecode1 = 0 ; - int res2 ; - size_t size2 ; - char *buff2 = 0 ; - PyObject *swig_obj[2] ; - char *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_tc_handle2str",2,2,swig_obj)) SWIG_fail; - ecode1 = SWIG_AsVal_unsigned_SS_int(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rtnl_tc_handle2str" "', argument " "1"" of type '" "uint32_t""'"); - } - arg1 = (uint32_t)(val1); - res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_tc_handle2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); - } - buff2= (char *)malloc((size2+1)*sizeof(char)); - arg3 = (size_t)(size2); - arg2 = (char *)(buff2); - result = (char *)rtnl_tc_handle2str(arg1,arg2,arg3); - resultobj = SWIG_FromCharPtr((const char *)result); - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); - if (buff2) free((char*)buff2); - return resultobj; -fail: - if (buff2) free((char*)buff2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_classid_generate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - uint32_t *arg2 = (uint32_t *) 0 ; - uint32_t arg3 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - unsigned int val3 ; - int ecode3 = 0 ; - PyObject *swig_obj[3] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_classid_generate",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_classid_generate" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = (char *)(buf1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_unsigned_int, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_classid_generate" "', argument " "2"" of type '" "uint32_t *""'"); - } - arg2 = (uint32_t *)(argp2); - ecode3 = SWIG_AsVal_unsigned_SS_int(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_classid_generate" "', argument " "3"" of type '" "uint32_t""'"); - } - arg3 = (uint32_t)(val3); - result = (int)rtnl_classid_generate((char const *)arg1,arg2,arg3); - resultobj = SWIG_From_int((int)(result)); - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_qdisc2obj(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_qdisc *arg1 = (struct rtnl_qdisc *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_object *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "qdisc2obj" "', argument " "1"" of type '" "struct rtnl_qdisc *""'"); - } - arg1 = (struct rtnl_qdisc *)(argp1); - result = (struct nl_object *)qdisc2obj(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_obj2qdisc(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_object *arg1 = (struct nl_object *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct rtnl_qdisc *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "obj2qdisc" "', argument " "1"" of type '" "struct nl_object *""'"); - } - arg1 = (struct nl_object *)(argp1); - result = (struct rtnl_qdisc *)obj2qdisc(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_class2obj(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_object *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "class2obj" "', argument " "1"" of type '" "struct rtnl_class *""'"); - } - arg1 = (struct rtnl_class *)(argp1); - result = (struct nl_object *)class2obj(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_obj2class(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_object *arg1 = (struct nl_object *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct rtnl_class *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "obj2class" "', argument " "1"" of type '" "struct nl_object *""'"); - } - arg1 = (struct nl_object *)(argp1); - result = (struct rtnl_class *)obj2class(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_class, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_cls2obj(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_cls *arg1 = (struct rtnl_cls *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_object *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_cls, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "cls2obj" "', argument " "1"" of type '" "struct rtnl_cls *""'"); - } - arg1 = (struct rtnl_cls *)(argp1); - result = (struct nl_object *)cls2obj(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_obj2cls(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_object *arg1 = (struct nl_object *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct rtnl_cls *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "obj2cls" "', argument " "1"" of type '" "struct nl_object *""'"); - } - arg1 = (struct nl_object *)(argp1); - result = (struct rtnl_cls *)obj2cls(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_cls, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_obj2tc(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_object *arg1 = (struct nl_object *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct rtnl_tc *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "obj2tc" "', argument " "1"" of type '" "struct nl_object *""'"); - } - arg1 = (struct nl_object *)(argp1); - result = (struct rtnl_tc *)obj2tc(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_tc, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_qdisc_alloc(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_qdisc *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_qdisc_alloc",0,0,0)) SWIG_fail; - result = (struct rtnl_qdisc *)rtnl_qdisc_alloc(); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_qdisc_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache *arg1 = (struct nl_cache *) 0 ; - int arg2 ; - uint32_t arg3 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - unsigned int val3 ; - int ecode3 = 0 ; - PyObject *swig_obj[3] ; - struct rtnl_qdisc *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_qdisc_get",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_qdisc_get" "', argument " "1"" of type '" "struct nl_cache *""'"); - } - arg1 = (struct nl_cache *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_qdisc_get" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - ecode3 = SWIG_AsVal_unsigned_SS_int(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_qdisc_get" "', argument " "3"" of type '" "uint32_t""'"); - } - arg3 = (uint32_t)(val3); - result = (struct rtnl_qdisc *)rtnl_qdisc_get(arg1,arg2,arg3); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_qdisc_get_by_parent(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache *arg1 = (struct nl_cache *) 0 ; - int arg2 ; - uint32_t arg3 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - unsigned int val3 ; - int ecode3 = 0 ; - PyObject *swig_obj[3] ; - struct rtnl_qdisc *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_qdisc_get_by_parent",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_qdisc_get_by_parent" "', argument " "1"" of type '" "struct nl_cache *""'"); - } - arg1 = (struct nl_cache *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_qdisc_get_by_parent" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - ecode3 = SWIG_AsVal_unsigned_SS_int(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_qdisc_get_by_parent" "', argument " "3"" of type '" "uint32_t""'"); - } - arg3 = (uint32_t)(val3); - result = (struct rtnl_qdisc *)rtnl_qdisc_get_by_parent(arg1,arg2,arg3); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_qdisc_build_add_request(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_qdisc *arg1 = (struct rtnl_qdisc *) 0 ; - int arg2 ; - struct nl_msg **arg3 = (struct nl_msg **) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - void *argp3 = 0 ; - int res3 = 0 ; - PyObject *swig_obj[3] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_qdisc_build_add_request",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_qdisc_build_add_request" "', argument " "1"" of type '" "struct rtnl_qdisc *""'"); - } - arg1 = (struct rtnl_qdisc *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_qdisc_build_add_request" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - res3 = SWIG_ConvertPtr(swig_obj[2], &argp3,SWIGTYPE_p_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "rtnl_qdisc_build_add_request" "', argument " "3"" of type '" "struct nl_msg **""'"); - } - arg3 = (struct nl_msg **)(argp3); - result = (int)rtnl_qdisc_build_add_request(arg1,arg2,arg3); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_qdisc_add(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_sock *arg1 = (struct nl_sock *) 0 ; - struct rtnl_qdisc *arg2 = (struct rtnl_qdisc *) 0 ; - int arg3 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - int val3 ; - int ecode3 = 0 ; - PyObject *swig_obj[3] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_qdisc_add",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_qdisc_add" "', argument " "1"" of type '" "struct nl_sock *""'"); - } - arg1 = (struct nl_sock *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_qdisc_add" "', argument " "2"" of type '" "struct rtnl_qdisc *""'"); - } - arg2 = (struct rtnl_qdisc *)(argp2); - ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_qdisc_add" "', argument " "3"" of type '" "int""'"); - } - arg3 = (int)(val3); - result = (int)rtnl_qdisc_add(arg1,arg2,arg3); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_qdisc_build_update_request(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_qdisc *arg1 = (struct rtnl_qdisc *) 0 ; - struct rtnl_qdisc *arg2 = (struct rtnl_qdisc *) 0 ; - int arg3 ; - struct nl_msg **arg4 = (struct nl_msg **) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - int val3 ; - int ecode3 = 0 ; - void *argp4 = 0 ; - int res4 = 0 ; - PyObject *swig_obj[4] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_qdisc_build_update_request",4,4,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_qdisc_build_update_request" "', argument " "1"" of type '" "struct rtnl_qdisc *""'"); - } - arg1 = (struct rtnl_qdisc *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_qdisc_build_update_request" "', argument " "2"" of type '" "struct rtnl_qdisc *""'"); - } - arg2 = (struct rtnl_qdisc *)(argp2); - ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_qdisc_build_update_request" "', argument " "3"" of type '" "int""'"); - } - arg3 = (int)(val3); - res4 = SWIG_ConvertPtr(swig_obj[3], &argp4,SWIGTYPE_p_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res4)) { - SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "rtnl_qdisc_build_update_request" "', argument " "4"" of type '" "struct nl_msg **""'"); - } - arg4 = (struct nl_msg **)(argp4); - result = (int)rtnl_qdisc_build_update_request(arg1,arg2,arg3,arg4); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_qdisc_update(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_sock *arg1 = (struct nl_sock *) 0 ; - struct rtnl_qdisc *arg2 = (struct rtnl_qdisc *) 0 ; - struct rtnl_qdisc *arg3 = (struct rtnl_qdisc *) 0 ; - int arg4 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - void *argp3 = 0 ; - int res3 = 0 ; - int val4 ; - int ecode4 = 0 ; - PyObject *swig_obj[4] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_qdisc_update",4,4,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_qdisc_update" "', argument " "1"" of type '" "struct nl_sock *""'"); - } - arg1 = (struct nl_sock *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_qdisc_update" "', argument " "2"" of type '" "struct rtnl_qdisc *""'"); - } - arg2 = (struct rtnl_qdisc *)(argp2); - res3 = SWIG_ConvertPtr(swig_obj[2], &argp3,SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "rtnl_qdisc_update" "', argument " "3"" of type '" "struct rtnl_qdisc *""'"); - } - arg3 = (struct rtnl_qdisc *)(argp3); - ecode4 = SWIG_AsVal_int(swig_obj[3], &val4); - if (!SWIG_IsOK(ecode4)) { - SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "rtnl_qdisc_update" "', argument " "4"" of type '" "int""'"); - } - arg4 = (int)(val4); - result = (int)rtnl_qdisc_update(arg1,arg2,arg3,arg4); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_qdisc_build_delete_request(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_qdisc *arg1 = (struct rtnl_qdisc *) 0 ; - struct nl_msg **arg2 = (struct nl_msg **) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_qdisc_build_delete_request",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_qdisc_build_delete_request" "', argument " "1"" of type '" "struct rtnl_qdisc *""'"); - } - arg1 = (struct rtnl_qdisc *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_qdisc_build_delete_request" "', argument " "2"" of type '" "struct nl_msg **""'"); - } - arg2 = (struct nl_msg **)(argp2); - result = (int)rtnl_qdisc_build_delete_request(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_qdisc_delete(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_sock *arg1 = (struct nl_sock *) 0 ; - struct rtnl_qdisc *arg2 = (struct rtnl_qdisc *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_qdisc_delete",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_qdisc_delete" "', argument " "1"" of type '" "struct nl_sock *""'"); - } - arg1 = (struct nl_sock *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_qdisc_delete" "', argument " "2"" of type '" "struct rtnl_qdisc *""'"); - } - arg2 = (struct rtnl_qdisc *)(argp2); - result = (int)rtnl_qdisc_delete(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_cls_alloc(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_cls *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_cls_alloc",0,0,0)) SWIG_fail; - result = (struct rtnl_cls *)rtnl_cls_alloc(); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_cls, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_cls_put(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_cls *arg1 = (struct rtnl_cls *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_cls, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_cls_put" "', argument " "1"" of type '" "struct rtnl_cls *""'"); - } - arg1 = (struct rtnl_cls *)(argp1); - rtnl_cls_put(arg1); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_cls_add(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_sock *arg1 = (struct nl_sock *) 0 ; - struct rtnl_cls *arg2 = (struct rtnl_cls *) 0 ; - int arg3 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - int val3 ; - int ecode3 = 0 ; - PyObject *swig_obj[3] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_cls_add",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_cls_add" "', argument " "1"" of type '" "struct nl_sock *""'"); - } - arg1 = (struct nl_sock *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_cls, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_cls_add" "', argument " "2"" of type '" "struct rtnl_cls *""'"); - } - arg2 = (struct rtnl_cls *)(argp2); - ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_cls_add" "', argument " "3"" of type '" "int""'"); - } - arg3 = (int)(val3); - result = (int)rtnl_cls_add(arg1,arg2,arg3); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_cls_delete(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_sock *arg1 = (struct nl_sock *) 0 ; - struct rtnl_cls *arg2 = (struct rtnl_cls *) 0 ; - int arg3 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - int val3 ; - int ecode3 = 0 ; - PyObject *swig_obj[3] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_cls_delete",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_cls_delete" "', argument " "1"" of type '" "struct nl_sock *""'"); - } - arg1 = (struct nl_sock *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_cls, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_cls_delete" "', argument " "2"" of type '" "struct rtnl_cls *""'"); - } - arg2 = (struct rtnl_cls *)(argp2); - ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_cls_delete" "', argument " "3"" of type '" "int""'"); - } - arg3 = (int)(val3); - result = (int)rtnl_cls_delete(arg1,arg2,arg3); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_cls_set_prio(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_cls *arg1 = (struct rtnl_cls *) 0 ; - uint16_t arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned short val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_cls_set_prio",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_cls, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_cls_set_prio" "', argument " "1"" of type '" "struct rtnl_cls *""'"); - } - arg1 = (struct rtnl_cls *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_short(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_cls_set_prio" "', argument " "2"" of type '" "uint16_t""'"); - } - arg2 = (uint16_t)(val2); - rtnl_cls_set_prio(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_cls_get_prio(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_cls *arg1 = (struct rtnl_cls *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint16_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_cls, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_cls_get_prio" "', argument " "1"" of type '" "struct rtnl_cls *""'"); - } - arg1 = (struct rtnl_cls *)(argp1); - result = (uint16_t)rtnl_cls_get_prio(arg1); - resultobj = SWIG_From_unsigned_SS_short((unsigned short)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_cls_set_protocol(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_cls *arg1 = (struct rtnl_cls *) 0 ; - uint16_t arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned short val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_cls_set_protocol",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_cls, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_cls_set_protocol" "', argument " "1"" of type '" "struct rtnl_cls *""'"); - } - arg1 = (struct rtnl_cls *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_short(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_cls_set_protocol" "', argument " "2"" of type '" "uint16_t""'"); - } - arg2 = (uint16_t)(val2); - rtnl_cls_set_protocol(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_cls_get_protocol(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_cls *arg1 = (struct rtnl_cls *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint16_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_cls, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_cls_get_protocol" "', argument " "1"" of type '" "struct rtnl_cls *""'"); - } - arg1 = (struct rtnl_cls *)(argp1); - result = (uint16_t)rtnl_cls_get_protocol(arg1); - resultobj = SWIG_From_unsigned_SS_short((unsigned short)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_htb_get_rate2quantum(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_qdisc *arg1 = (struct rtnl_qdisc *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint32_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_get_rate2quantum" "', argument " "1"" of type '" "struct rtnl_qdisc *""'"); - } - arg1 = (struct rtnl_qdisc *)(argp1); - result = (uint32_t)rtnl_htb_get_rate2quantum(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_htb_set_rate2quantum(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_qdisc *arg1 = (struct rtnl_qdisc *) 0 ; - uint32_t arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_htb_set_rate2quantum",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_set_rate2quantum" "', argument " "1"" of type '" "struct rtnl_qdisc *""'"); - } - arg1 = (struct rtnl_qdisc *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_htb_set_rate2quantum" "', argument " "2"" of type '" "uint32_t""'"); - } - arg2 = (uint32_t)(val2); - result = (int)rtnl_htb_set_rate2quantum(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_htb_get_defcls(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_qdisc *arg1 = (struct rtnl_qdisc *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint32_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_get_defcls" "', argument " "1"" of type '" "struct rtnl_qdisc *""'"); - } - arg1 = (struct rtnl_qdisc *)(argp1); - result = (uint32_t)rtnl_htb_get_defcls(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_htb_set_defcls(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_qdisc *arg1 = (struct rtnl_qdisc *) 0 ; - uint32_t arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_htb_set_defcls",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_qdisc, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_set_defcls" "', argument " "1"" of type '" "struct rtnl_qdisc *""'"); - } - arg1 = (struct rtnl_qdisc *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_htb_set_defcls" "', argument " "2"" of type '" "uint32_t""'"); - } - arg2 = (uint32_t)(val2); - result = (int)rtnl_htb_set_defcls(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_htb_get_prio(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint32_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_get_prio" "', argument " "1"" of type '" "struct rtnl_class *""'"); - } - arg1 = (struct rtnl_class *)(argp1); - result = (uint32_t)rtnl_htb_get_prio(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_htb_set_prio(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; - uint32_t arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_htb_set_prio",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_set_prio" "', argument " "1"" of type '" "struct rtnl_class *""'"); - } - arg1 = (struct rtnl_class *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_htb_set_prio" "', argument " "2"" of type '" "uint32_t""'"); - } - arg2 = (uint32_t)(val2); - result = (int)rtnl_htb_set_prio(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_htb_get_rate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint32_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_get_rate" "', argument " "1"" of type '" "struct rtnl_class *""'"); - } - arg1 = (struct rtnl_class *)(argp1); - result = (uint32_t)rtnl_htb_get_rate(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_htb_set_rate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; - uint32_t arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_htb_set_rate",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_set_rate" "', argument " "1"" of type '" "struct rtnl_class *""'"); - } - arg1 = (struct rtnl_class *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_htb_set_rate" "', argument " "2"" of type '" "uint32_t""'"); - } - arg2 = (uint32_t)(val2); - result = (int)rtnl_htb_set_rate(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_htb_get_ceil(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint32_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_get_ceil" "', argument " "1"" of type '" "struct rtnl_class *""'"); - } - arg1 = (struct rtnl_class *)(argp1); - result = (uint32_t)rtnl_htb_get_ceil(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_htb_set_ceil(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; - uint32_t arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_htb_set_ceil",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_set_ceil" "', argument " "1"" of type '" "struct rtnl_class *""'"); - } - arg1 = (struct rtnl_class *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_htb_set_ceil" "', argument " "2"" of type '" "uint32_t""'"); - } - arg2 = (uint32_t)(val2); - result = (int)rtnl_htb_set_ceil(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_htb_get_rbuffer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint32_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_get_rbuffer" "', argument " "1"" of type '" "struct rtnl_class *""'"); - } - arg1 = (struct rtnl_class *)(argp1); - result = (uint32_t)rtnl_htb_get_rbuffer(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_htb_set_rbuffer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; - uint32_t arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_htb_set_rbuffer",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_set_rbuffer" "', argument " "1"" of type '" "struct rtnl_class *""'"); - } - arg1 = (struct rtnl_class *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_htb_set_rbuffer" "', argument " "2"" of type '" "uint32_t""'"); - } - arg2 = (uint32_t)(val2); - result = (int)rtnl_htb_set_rbuffer(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_htb_get_cbuffer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint32_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_get_cbuffer" "', argument " "1"" of type '" "struct rtnl_class *""'"); - } - arg1 = (struct rtnl_class *)(argp1); - result = (uint32_t)rtnl_htb_get_cbuffer(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_htb_set_cbuffer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; - uint32_t arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_htb_set_cbuffer",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_set_cbuffer" "', argument " "1"" of type '" "struct rtnl_class *""'"); - } - arg1 = (struct rtnl_class *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_htb_set_cbuffer" "', argument " "2"" of type '" "uint32_t""'"); - } - arg2 = (uint32_t)(val2); - result = (int)rtnl_htb_set_cbuffer(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_htb_get_quantum(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint32_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_get_quantum" "', argument " "1"" of type '" "struct rtnl_class *""'"); - } - arg1 = (struct rtnl_class *)(argp1); - result = (uint32_t)rtnl_htb_get_quantum(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_htb_set_quantum(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; - uint32_t arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_htb_set_quantum",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_set_quantum" "', argument " "1"" of type '" "struct rtnl_class *""'"); - } - arg1 = (struct rtnl_class *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_htb_set_quantum" "', argument " "2"" of type '" "uint32_t""'"); - } - arg2 = (uint32_t)(val2); - result = (int)rtnl_htb_set_quantum(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_htb_get_level(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_class *arg1 = (struct rtnl_class *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_class, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_htb_get_level" "', argument " "1"" of type '" "struct rtnl_class *""'"); - } - arg1 = (struct rtnl_class *)(argp1); - result = (int)rtnl_htb_get_level(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_addr2obj(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_object *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "addr2obj" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - result = (struct nl_object *)addr2obj(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_object, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_obj2addr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_object *arg1 = (struct nl_object *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct rtnl_addr *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_object, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "obj2addr" "', argument " "1"" of type '" "struct nl_object *""'"); - } - arg1 = (struct nl_object *)(argp1); - result = (struct rtnl_addr *)obj2addr(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_addr, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_alloc(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_alloc",0,0,0)) SWIG_fail; - result = (struct rtnl_addr *)rtnl_addr_alloc(); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_addr, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_cache *arg1 = (struct nl_cache *) 0 ; - int arg2 ; - struct nl_addr *arg3 = (struct nl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - void *argp3 = 0 ; - int res3 = 0 ; - PyObject *swig_obj[3] ; - struct rtnl_addr *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_get",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_cache, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get" "', argument " "1"" of type '" "struct nl_cache *""'"); - } - arg1 = (struct nl_cache *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_addr_get" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - res3 = SWIG_ConvertPtr(swig_obj[2], &argp3,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "rtnl_addr_get" "', argument " "3"" of type '" "struct nl_addr *""'"); - } - arg3 = (struct nl_addr *)(argp3); - result = (struct rtnl_addr *)rtnl_addr_get(arg1,arg2,arg3); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_addr, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_build_add_request(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - int arg2 ; - struct nl_msg **arg3 = (struct nl_msg **) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - void *argp3 = 0 ; - int res3 = 0 ; - PyObject *swig_obj[3] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_build_add_request",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_build_add_request" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_addr_build_add_request" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - res3 = SWIG_ConvertPtr(swig_obj[2], &argp3,SWIGTYPE_p_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "rtnl_addr_build_add_request" "', argument " "3"" of type '" "struct nl_msg **""'"); - } - arg3 = (struct nl_msg **)(argp3); - result = (int)rtnl_addr_build_add_request(arg1,arg2,arg3); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_add(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_sock *arg1 = (struct nl_sock *) 0 ; - struct rtnl_addr *arg2 = (struct rtnl_addr *) 0 ; - int arg3 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - int val3 ; - int ecode3 = 0 ; - PyObject *swig_obj[3] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_add",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_add" "', argument " "1"" of type '" "struct nl_sock *""'"); - } - arg1 = (struct nl_sock *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_addr_add" "', argument " "2"" of type '" "struct rtnl_addr *""'"); - } - arg2 = (struct rtnl_addr *)(argp2); - ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_addr_add" "', argument " "3"" of type '" "int""'"); - } - arg3 = (int)(val3); - result = (int)rtnl_addr_add(arg1,arg2,arg3); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_build_delete_request(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - int arg2 ; - struct nl_msg **arg3 = (struct nl_msg **) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - void *argp3 = 0 ; - int res3 = 0 ; - PyObject *swig_obj[3] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_build_delete_request",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_build_delete_request" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_addr_build_delete_request" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - res3 = SWIG_ConvertPtr(swig_obj[2], &argp3,SWIGTYPE_p_p_nl_msg, 0 | 0 ); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "rtnl_addr_build_delete_request" "', argument " "3"" of type '" "struct nl_msg **""'"); - } - arg3 = (struct nl_msg **)(argp3); - result = (int)rtnl_addr_build_delete_request(arg1,arg2,arg3); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_delete(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct nl_sock *arg1 = (struct nl_sock *) 0 ; - struct rtnl_addr *arg2 = (struct rtnl_addr *) 0 ; - int arg3 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - int val3 ; - int ecode3 = 0 ; - PyObject *swig_obj[3] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_delete",3,3,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_nl_sock, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_delete" "', argument " "1"" of type '" "struct nl_sock *""'"); - } - arg1 = (struct nl_sock *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_addr_delete" "', argument " "2"" of type '" "struct rtnl_addr *""'"); - } - arg2 = (struct rtnl_addr *)(argp2); - ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "rtnl_addr_delete" "', argument " "3"" of type '" "int""'"); - } - arg3 = (int)(val3); - result = (int)rtnl_addr_delete(arg1,arg2,arg3); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_flags2str(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - char *arg2 = (char *) 0 ; - size_t arg3 ; - int val1 ; - int ecode1 = 0 ; - int res2 ; - size_t size2 ; - char *buff2 = 0 ; - PyObject *swig_obj[2] ; - char *result = 0 ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_flags2str",2,2,swig_obj)) SWIG_fail; - ecode1 = SWIG_AsVal_int(swig_obj[0], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rtnl_addr_flags2str" "', argument " "1"" of type '" "int""'"); - } - arg1 = (int)(val1); - res2 = SWIG_AsVal_size_t (swig_obj[1], &size2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_addr_flags2str" "', argument " "2"" of type '" "(char *buf, size_t len)""'"); - } - buff2= (char *)malloc((size2+1)*sizeof(char)); - arg3 = (size_t)(size2); - arg2 = (char *)(buff2); - result = (char *)rtnl_addr_flags2str(arg1,arg2,arg3); - resultobj = SWIG_FromCharPtr((const char *)result); - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2)); - if (buff2) free((char*)buff2); - return resultobj; -fail: - if (buff2) free((char*)buff2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_str2flags(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_str2flags" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = (char *)(buf1); - result = (int)rtnl_addr_str2flags((char const *)arg1); - resultobj = SWIG_From_int((int)(result)); - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_set_label(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - char *arg2 = (char *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_label",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_label" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_addr_set_label" "', argument " "2"" of type '" "char const *""'"); - } - arg2 = (char *)(buf2); - result = (int)rtnl_addr_set_label(arg1,(char const *)arg2); - resultobj = SWIG_From_int((int)(result)); - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return resultobj; -fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_get_label(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - char *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_label" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - result = (char *)rtnl_addr_get_label(arg1); - resultobj = SWIG_FromCharPtr((const char *)result); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_set_ifindex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_ifindex",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_ifindex" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_addr_set_ifindex" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - rtnl_addr_set_ifindex(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_get_ifindex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_ifindex" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - result = (int)rtnl_addr_get_ifindex(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_set_link(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - struct rtnl_link *arg2 = (struct rtnl_link *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_link",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_link" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_rtnl_link, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_addr_set_link" "', argument " "2"" of type '" "struct rtnl_link *""'"); - } - arg2 = (struct rtnl_link *)(argp2); - rtnl_addr_set_link(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_get_link(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct rtnl_link *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_link" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - result = (struct rtnl_link *)rtnl_addr_get_link(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_rtnl_link, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_set_family(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_family",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_family" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_addr_set_family" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - rtnl_addr_set_family(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_get_family(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_family" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - result = (int)rtnl_addr_get_family(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_set_prefixlen(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_prefixlen",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_prefixlen" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_addr_set_prefixlen" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - rtnl_addr_set_prefixlen(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_get_prefixlen(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_prefixlen" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - result = (int)rtnl_addr_get_prefixlen(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_set_scope(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_scope",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_scope" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_addr_set_scope" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - rtnl_addr_set_scope(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_get_scope(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_scope" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - result = (int)rtnl_addr_get_scope(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_set_flags(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - unsigned int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_flags",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_flags" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_addr_set_flags" "', argument " "2"" of type '" "unsigned int""'"); - } - arg2 = (unsigned int)(val2); - rtnl_addr_set_flags(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_unset_flags(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - unsigned int arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_unset_flags",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_unset_flags" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_addr_unset_flags" "', argument " "2"" of type '" "unsigned int""'"); - } - arg2 = (unsigned int)(val2); - rtnl_addr_unset_flags(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_get_flags(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - unsigned int result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_flags" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - result = (unsigned int)rtnl_addr_get_flags(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_set_local(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - struct nl_addr *arg2 = (struct nl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_local",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_local" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_addr_set_local" "', argument " "2"" of type '" "struct nl_addr *""'"); - } - arg2 = (struct nl_addr *)(argp2); - result = (int)rtnl_addr_set_local(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_get_local(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_addr *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_local" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - result = (struct nl_addr *)rtnl_addr_get_local(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_addr, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_set_peer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - struct nl_addr *arg2 = (struct nl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_peer",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_peer" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_addr_set_peer" "', argument " "2"" of type '" "struct nl_addr *""'"); - } - arg2 = (struct nl_addr *)(argp2); - result = (int)rtnl_addr_set_peer(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_get_peer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_addr *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_peer" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - result = (struct nl_addr *)rtnl_addr_get_peer(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_addr, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_set_broadcast(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - struct nl_addr *arg2 = (struct nl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_broadcast",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_broadcast" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_addr_set_broadcast" "', argument " "2"" of type '" "struct nl_addr *""'"); - } - arg2 = (struct nl_addr *)(argp2); - result = (int)rtnl_addr_set_broadcast(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_get_broadcast(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_addr *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_broadcast" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - result = (struct nl_addr *)rtnl_addr_get_broadcast(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_addr, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_set_multicast(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - struct nl_addr *arg2 = (struct nl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_multicast",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_multicast" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_addr_set_multicast" "', argument " "2"" of type '" "struct nl_addr *""'"); - } - arg2 = (struct nl_addr *)(argp2); - result = (int)rtnl_addr_set_multicast(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_get_multicast(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_addr *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_multicast" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - result = (struct nl_addr *)rtnl_addr_get_multicast(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_addr, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_set_anycast(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - struct nl_addr *arg2 = (struct nl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - PyObject *swig_obj[2] ; - int result; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_anycast",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_anycast" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_nl_addr, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "rtnl_addr_set_anycast" "', argument " "2"" of type '" "struct nl_addr *""'"); - } - arg2 = (struct nl_addr *)(argp2); - result = (int)rtnl_addr_set_anycast(arg1,arg2); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_get_anycast(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - struct nl_addr *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_anycast" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - result = (struct nl_addr *)rtnl_addr_get_anycast(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_nl_addr, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_get_valid_lifetime(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint32_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_valid_lifetime" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - result = (uint32_t)rtnl_addr_get_valid_lifetime(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_set_valid_lifetime(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - uint32_t arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_valid_lifetime",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_valid_lifetime" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_addr_set_valid_lifetime" "', argument " "2"" of type '" "uint32_t""'"); - } - arg2 = (uint32_t)(val2); - rtnl_addr_set_valid_lifetime(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_get_preferred_lifetime(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint32_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_preferred_lifetime" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - result = (uint32_t)rtnl_addr_get_preferred_lifetime(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_set_preferred_lifetime(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - uint32_t arg2 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned int val2 ; - int ecode2 = 0 ; - PyObject *swig_obj[2] ; - - if (!SWIG_Python_UnpackTuple(args,"rtnl_addr_set_preferred_lifetime",2,2,swig_obj)) SWIG_fail; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_set_preferred_lifetime" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_int(swig_obj[1], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "rtnl_addr_set_preferred_lifetime" "', argument " "2"" of type '" "uint32_t""'"); - } - arg2 = (uint32_t)(val2); - rtnl_addr_set_preferred_lifetime(arg1,arg2); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_get_create_time(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint32_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_create_time" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - result = (uint32_t)rtnl_addr_get_create_time(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_rtnl_addr_get_last_update_time(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct rtnl_addr *arg1 = (struct rtnl_addr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - uint32_t result; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_rtnl_addr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "rtnl_addr_get_last_update_time" "', argument " "1"" of type '" "struct rtnl_addr *""'"); - } - arg1 = (struct rtnl_addr *)(argp1); - result = (uint32_t)rtnl_addr_get_last_update_time(arg1); - resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result)); - return resultobj; -fail: - return NULL; -} - - -static PyMethodDef SwigMethods[] = { - { (char *)"SWIG_PyInstanceMethod_New", (PyCFunction)SWIG_PyInstanceMethod_New, METH_O, NULL}, - { (char *)"link2obj", (PyCFunction)_wrap_link2obj, METH_O, NULL}, - { (char *)"obj2link", (PyCFunction)_wrap_obj2link, METH_O, NULL}, - { (char *)"get_from_kernel", _wrap_get_from_kernel, METH_VARARGS, NULL}, - { (char *)"inet_get_conf", _wrap_inet_get_conf, METH_VARARGS, NULL}, - { (char *)"rtnl_scope2str", _wrap_rtnl_scope2str, METH_VARARGS, NULL}, - { (char *)"rtnl_str2scope", (PyCFunction)_wrap_rtnl_str2scope, METH_O, NULL}, - { (char *)"rtnl_link_alloc", (PyCFunction)_wrap_rtnl_link_alloc, METH_NOARGS, NULL}, - { (char *)"rtnl_link_get", _wrap_rtnl_link_get, METH_VARARGS, NULL}, - { (char *)"rtnl_link_get_by_name", _wrap_rtnl_link_get_by_name, METH_VARARGS, NULL}, - { (char *)"rtnl_link_build_add_request", _wrap_rtnl_link_build_add_request, METH_VARARGS, NULL}, - { (char *)"rtnl_link_add", _wrap_rtnl_link_add, METH_VARARGS, NULL}, - { (char *)"rtnl_link_build_change_request", _wrap_rtnl_link_build_change_request, METH_VARARGS, NULL}, - { (char *)"rtnl_link_change", _wrap_rtnl_link_change, METH_VARARGS, NULL}, - { (char *)"rtnl_link_build_delete_request", _wrap_rtnl_link_build_delete_request, METH_VARARGS, NULL}, - { (char *)"rtnl_link_delete", _wrap_rtnl_link_delete, METH_VARARGS, NULL}, - { (char *)"rtnl_link_build_get_request", _wrap_rtnl_link_build_get_request, METH_VARARGS, NULL}, - { (char *)"rtnl_link_stat2str", _wrap_rtnl_link_stat2str, METH_VARARGS, NULL}, - { (char *)"rtnl_link_str2stat", (PyCFunction)_wrap_rtnl_link_str2stat, METH_O, NULL}, - { (char *)"rtnl_link_flags2str", _wrap_rtnl_link_flags2str, METH_VARARGS, NULL}, - { (char *)"rtnl_link_str2flags", (PyCFunction)_wrap_rtnl_link_str2flags, METH_O, NULL}, - { (char *)"rtnl_link_operstate2str", _wrap_rtnl_link_operstate2str, METH_VARARGS, NULL}, - { (char *)"rtnl_link_str2operstate", (PyCFunction)_wrap_rtnl_link_str2operstate, METH_O, NULL}, - { (char *)"rtnl_link_mode2str", _wrap_rtnl_link_mode2str, METH_VARARGS, NULL}, - { (char *)"rtnl_link_str2mode", (PyCFunction)_wrap_rtnl_link_str2mode, METH_O, NULL}, - { (char *)"rtnl_link_set_qdisc", _wrap_rtnl_link_set_qdisc, METH_VARARGS, NULL}, - { (char *)"rtnl_link_get_qdisc", (PyCFunction)_wrap_rtnl_link_get_qdisc, METH_O, NULL}, - { (char *)"rtnl_link_set_name", _wrap_rtnl_link_set_name, METH_VARARGS, NULL}, - { (char *)"rtnl_link_get_name", (PyCFunction)_wrap_rtnl_link_get_name, METH_O, NULL}, - { (char *)"rtnl_link_set_flags", _wrap_rtnl_link_set_flags, METH_VARARGS, NULL}, - { (char *)"rtnl_link_unset_flags", _wrap_rtnl_link_unset_flags, METH_VARARGS, NULL}, - { (char *)"rtnl_link_get_flags", (PyCFunction)_wrap_rtnl_link_get_flags, METH_O, NULL}, - { (char *)"rtnl_link_set_mtu", _wrap_rtnl_link_set_mtu, METH_VARARGS, NULL}, - { (char *)"rtnl_link_get_mtu", (PyCFunction)_wrap_rtnl_link_get_mtu, METH_O, NULL}, - { (char *)"rtnl_link_set_txqlen", _wrap_rtnl_link_set_txqlen, METH_VARARGS, NULL}, - { (char *)"rtnl_link_get_txqlen", (PyCFunction)_wrap_rtnl_link_get_txqlen, METH_O, NULL}, - { (char *)"rtnl_link_set_weight", _wrap_rtnl_link_set_weight, METH_VARARGS, NULL}, - { (char *)"rtnl_link_get_weight", (PyCFunction)_wrap_rtnl_link_get_weight, METH_O, NULL}, - { (char *)"rtnl_link_set_ifindex", _wrap_rtnl_link_set_ifindex, METH_VARARGS, NULL}, - { (char *)"rtnl_link_get_ifindex", (PyCFunction)_wrap_rtnl_link_get_ifindex, METH_O, NULL}, - { (char *)"rtnl_link_set_family", _wrap_rtnl_link_set_family, METH_VARARGS, NULL}, - { (char *)"rtnl_link_get_family", (PyCFunction)_wrap_rtnl_link_get_family, METH_O, NULL}, - { (char *)"rtnl_link_set_arptype", _wrap_rtnl_link_set_arptype, METH_VARARGS, NULL}, - { (char *)"rtnl_link_get_arptype", (PyCFunction)_wrap_rtnl_link_get_arptype, METH_O, NULL}, - { (char *)"rtnl_link_set_addr", _wrap_rtnl_link_set_addr, METH_VARARGS, NULL}, - { (char *)"rtnl_link_get_addr", (PyCFunction)_wrap_rtnl_link_get_addr, METH_O, NULL}, - { (char *)"rtnl_link_set_broadcast", _wrap_rtnl_link_set_broadcast, METH_VARARGS, NULL}, - { (char *)"rtnl_link_get_broadcast", (PyCFunction)_wrap_rtnl_link_get_broadcast, METH_O, NULL}, - { (char *)"rtnl_link_set_link", _wrap_rtnl_link_set_link, METH_VARARGS, NULL}, - { (char *)"rtnl_link_get_link", (PyCFunction)_wrap_rtnl_link_get_link, METH_O, NULL}, - { (char *)"rtnl_link_set_master", _wrap_rtnl_link_set_master, METH_VARARGS, NULL}, - { (char *)"rtnl_link_get_master", (PyCFunction)_wrap_rtnl_link_get_master, METH_O, NULL}, - { (char *)"rtnl_link_set_operstate", _wrap_rtnl_link_set_operstate, METH_VARARGS, NULL}, - { (char *)"rtnl_link_get_operstate", (PyCFunction)_wrap_rtnl_link_get_operstate, METH_O, NULL}, - { (char *)"rtnl_link_set_linkmode", _wrap_rtnl_link_set_linkmode, METH_VARARGS, NULL}, - { (char *)"rtnl_link_get_linkmode", (PyCFunction)_wrap_rtnl_link_get_linkmode, METH_O, NULL}, - { (char *)"rtnl_link_get_ifalias", (PyCFunction)_wrap_rtnl_link_get_ifalias, METH_O, NULL}, - { (char *)"rtnl_link_set_ifalias", _wrap_rtnl_link_set_ifalias, METH_VARARGS, NULL}, - { (char *)"rtnl_link_get_num_vf", _wrap_rtnl_link_get_num_vf, METH_VARARGS, NULL}, - { (char *)"rtnl_link_get_stat", _wrap_rtnl_link_get_stat, METH_VARARGS, NULL}, - { (char *)"rtnl_link_set_stat", _wrap_rtnl_link_set_stat, METH_VARARGS, NULL}, - { (char *)"rtnl_link_set_info_type", _wrap_rtnl_link_set_info_type, METH_VARARGS, NULL}, - { (char *)"rtnl_link_get_info_type", (PyCFunction)_wrap_rtnl_link_get_info_type, METH_O, NULL}, - { (char *)"vlan_map_vm_from_set", _wrap_vlan_map_vm_from_set, METH_VARARGS, NULL}, - { (char *)"vlan_map_vm_from_get", (PyCFunction)_wrap_vlan_map_vm_from_get, METH_O, NULL}, - { (char *)"vlan_map_vm_to_set", _wrap_vlan_map_vm_to_set, METH_VARARGS, NULL}, - { (char *)"vlan_map_vm_to_get", (PyCFunction)_wrap_vlan_map_vm_to_get, METH_O, NULL}, - { (char *)"delete_vlan_map", (PyCFunction)_wrap_delete_vlan_map, METH_O, NULL}, - { (char *)"vlan_map_swigregister", vlan_map_swigregister, METH_VARARGS, NULL}, - { (char *)"rtnl_link_vlan_flags2str", _wrap_rtnl_link_vlan_flags2str, METH_VARARGS, NULL}, - { (char *)"rtnl_link_vlan_str2flags", (PyCFunction)_wrap_rtnl_link_vlan_str2flags, METH_O, NULL}, - { (char *)"rtnl_link_vlan_set_id", _wrap_rtnl_link_vlan_set_id, METH_VARARGS, NULL}, - { (char *)"rtnl_link_vlan_get_id", (PyCFunction)_wrap_rtnl_link_vlan_get_id, METH_O, NULL}, - { (char *)"rtnl_link_vlan_set_flags", _wrap_rtnl_link_vlan_set_flags, METH_VARARGS, NULL}, - { (char *)"rtnl_link_vlan_unset_flags", _wrap_rtnl_link_vlan_unset_flags, METH_VARARGS, NULL}, - { (char *)"rtnl_link_vlan_get_flags", (PyCFunction)_wrap_rtnl_link_vlan_get_flags, METH_O, NULL}, - { (char *)"rtnl_link_vlan_set_ingress_map", _wrap_rtnl_link_vlan_set_ingress_map, METH_VARARGS, NULL}, - { (char *)"rtnl_link_vlan_get_ingress_map", (PyCFunction)_wrap_rtnl_link_vlan_get_ingress_map, METH_O, NULL}, - { (char *)"rtnl_link_vlan_set_egress_map", _wrap_rtnl_link_vlan_set_egress_map, METH_VARARGS, NULL}, - { (char *)"rtnl_link_vlan_get_egress_map", _wrap_rtnl_link_vlan_get_egress_map, METH_VARARGS, NULL}, - { (char *)"rtnl_link_inet_devconf2str", _wrap_rtnl_link_inet_devconf2str, METH_VARARGS, NULL}, - { (char *)"rtnl_link_inet_str2devconf", (PyCFunction)_wrap_rtnl_link_inet_str2devconf, METH_O, NULL}, - { (char *)"rtnl_link_inet_set_conf", _wrap_rtnl_link_inet_set_conf, METH_VARARGS, NULL}, - { (char *)"tc_str2handle", (PyCFunction)_wrap_tc_str2handle, METH_O, NULL}, - { (char *)"rtnl_tc_set_ifindex", _wrap_rtnl_tc_set_ifindex, METH_VARARGS, NULL}, - { (char *)"rtnl_tc_get_ifindex", (PyCFunction)_wrap_rtnl_tc_get_ifindex, METH_O, NULL}, - { (char *)"rtnl_tc_set_link", _wrap_rtnl_tc_set_link, METH_VARARGS, NULL}, - { (char *)"rtnl_tc_get_link", (PyCFunction)_wrap_rtnl_tc_get_link, METH_O, NULL}, - { (char *)"rtnl_tc_set_mtu", _wrap_rtnl_tc_set_mtu, METH_VARARGS, NULL}, - { (char *)"rtnl_tc_get_mtu", (PyCFunction)_wrap_rtnl_tc_get_mtu, METH_O, NULL}, - { (char *)"rtnl_tc_set_mpu", _wrap_rtnl_tc_set_mpu, METH_VARARGS, NULL}, - { (char *)"rtnl_tc_get_mpu", (PyCFunction)_wrap_rtnl_tc_get_mpu, METH_O, NULL}, - { (char *)"rtnl_tc_set_overhead", _wrap_rtnl_tc_set_overhead, METH_VARARGS, NULL}, - { (char *)"rtnl_tc_get_overhead", (PyCFunction)_wrap_rtnl_tc_get_overhead, METH_O, NULL}, - { (char *)"rtnl_tc_set_linktype", _wrap_rtnl_tc_set_linktype, METH_VARARGS, NULL}, - { (char *)"rtnl_tc_get_linktype", (PyCFunction)_wrap_rtnl_tc_get_linktype, METH_O, NULL}, - { (char *)"rtnl_tc_set_handle", _wrap_rtnl_tc_set_handle, METH_VARARGS, NULL}, - { (char *)"rtnl_tc_get_handle", (PyCFunction)_wrap_rtnl_tc_get_handle, METH_O, NULL}, - { (char *)"rtnl_tc_set_parent", _wrap_rtnl_tc_set_parent, METH_VARARGS, NULL}, - { (char *)"rtnl_tc_get_parent", (PyCFunction)_wrap_rtnl_tc_get_parent, METH_O, NULL}, - { (char *)"rtnl_tc_set_kind", _wrap_rtnl_tc_set_kind, METH_VARARGS, NULL}, - { (char *)"rtnl_tc_get_kind", (PyCFunction)_wrap_rtnl_tc_get_kind, METH_O, NULL}, - { (char *)"rtnl_tc_get_stat", _wrap_rtnl_tc_get_stat, METH_VARARGS, NULL}, - { (char *)"rtnl_tc_calc_txtime", _wrap_rtnl_tc_calc_txtime, METH_VARARGS, NULL}, - { (char *)"rtnl_tc_calc_bufsize", _wrap_rtnl_tc_calc_bufsize, METH_VARARGS, NULL}, - { (char *)"rtnl_tc_calc_cell_log", (PyCFunction)_wrap_rtnl_tc_calc_cell_log, METH_O, NULL}, - { (char *)"rtnl_tc_read_classid_file", (PyCFunction)_wrap_rtnl_tc_read_classid_file, METH_NOARGS, NULL}, - { (char *)"rtnl_tc_handle2str", _wrap_rtnl_tc_handle2str, METH_VARARGS, NULL}, - { (char *)"rtnl_classid_generate", _wrap_rtnl_classid_generate, METH_VARARGS, NULL}, - { (char *)"qdisc2obj", (PyCFunction)_wrap_qdisc2obj, METH_O, NULL}, - { (char *)"obj2qdisc", (PyCFunction)_wrap_obj2qdisc, METH_O, NULL}, - { (char *)"class2obj", (PyCFunction)_wrap_class2obj, METH_O, NULL}, - { (char *)"obj2class", (PyCFunction)_wrap_obj2class, METH_O, NULL}, - { (char *)"cls2obj", (PyCFunction)_wrap_cls2obj, METH_O, NULL}, - { (char *)"obj2cls", (PyCFunction)_wrap_obj2cls, METH_O, NULL}, - { (char *)"obj2tc", (PyCFunction)_wrap_obj2tc, METH_O, NULL}, - { (char *)"rtnl_qdisc_alloc", (PyCFunction)_wrap_rtnl_qdisc_alloc, METH_NOARGS, NULL}, - { (char *)"rtnl_qdisc_get", _wrap_rtnl_qdisc_get, METH_VARARGS, NULL}, - { (char *)"rtnl_qdisc_get_by_parent", _wrap_rtnl_qdisc_get_by_parent, METH_VARARGS, NULL}, - { (char *)"rtnl_qdisc_build_add_request", _wrap_rtnl_qdisc_build_add_request, METH_VARARGS, NULL}, - { (char *)"rtnl_qdisc_add", _wrap_rtnl_qdisc_add, METH_VARARGS, NULL}, - { (char *)"rtnl_qdisc_build_update_request", _wrap_rtnl_qdisc_build_update_request, METH_VARARGS, NULL}, - { (char *)"rtnl_qdisc_update", _wrap_rtnl_qdisc_update, METH_VARARGS, NULL}, - { (char *)"rtnl_qdisc_build_delete_request", _wrap_rtnl_qdisc_build_delete_request, METH_VARARGS, NULL}, - { (char *)"rtnl_qdisc_delete", _wrap_rtnl_qdisc_delete, METH_VARARGS, NULL}, - { (char *)"rtnl_cls_alloc", (PyCFunction)_wrap_rtnl_cls_alloc, METH_NOARGS, NULL}, - { (char *)"rtnl_cls_put", (PyCFunction)_wrap_rtnl_cls_put, METH_O, NULL}, - { (char *)"rtnl_cls_add", _wrap_rtnl_cls_add, METH_VARARGS, NULL}, - { (char *)"rtnl_cls_delete", _wrap_rtnl_cls_delete, METH_VARARGS, NULL}, - { (char *)"rtnl_cls_set_prio", _wrap_rtnl_cls_set_prio, METH_VARARGS, NULL}, - { (char *)"rtnl_cls_get_prio", (PyCFunction)_wrap_rtnl_cls_get_prio, METH_O, NULL}, - { (char *)"rtnl_cls_set_protocol", _wrap_rtnl_cls_set_protocol, METH_VARARGS, NULL}, - { (char *)"rtnl_cls_get_protocol", (PyCFunction)_wrap_rtnl_cls_get_protocol, METH_O, NULL}, - { (char *)"rtnl_htb_get_rate2quantum", (PyCFunction)_wrap_rtnl_htb_get_rate2quantum, METH_O, NULL}, - { (char *)"rtnl_htb_set_rate2quantum", _wrap_rtnl_htb_set_rate2quantum, METH_VARARGS, NULL}, - { (char *)"rtnl_htb_get_defcls", (PyCFunction)_wrap_rtnl_htb_get_defcls, METH_O, NULL}, - { (char *)"rtnl_htb_set_defcls", _wrap_rtnl_htb_set_defcls, METH_VARARGS, NULL}, - { (char *)"rtnl_htb_get_prio", (PyCFunction)_wrap_rtnl_htb_get_prio, METH_O, NULL}, - { (char *)"rtnl_htb_set_prio", _wrap_rtnl_htb_set_prio, METH_VARARGS, NULL}, - { (char *)"rtnl_htb_get_rate", (PyCFunction)_wrap_rtnl_htb_get_rate, METH_O, NULL}, - { (char *)"rtnl_htb_set_rate", _wrap_rtnl_htb_set_rate, METH_VARARGS, NULL}, - { (char *)"rtnl_htb_get_ceil", (PyCFunction)_wrap_rtnl_htb_get_ceil, METH_O, NULL}, - { (char *)"rtnl_htb_set_ceil", _wrap_rtnl_htb_set_ceil, METH_VARARGS, NULL}, - { (char *)"rtnl_htb_get_rbuffer", (PyCFunction)_wrap_rtnl_htb_get_rbuffer, METH_O, NULL}, - { (char *)"rtnl_htb_set_rbuffer", _wrap_rtnl_htb_set_rbuffer, METH_VARARGS, NULL}, - { (char *)"rtnl_htb_get_cbuffer", (PyCFunction)_wrap_rtnl_htb_get_cbuffer, METH_O, NULL}, - { (char *)"rtnl_htb_set_cbuffer", _wrap_rtnl_htb_set_cbuffer, METH_VARARGS, NULL}, - { (char *)"rtnl_htb_get_quantum", (PyCFunction)_wrap_rtnl_htb_get_quantum, METH_O, NULL}, - { (char *)"rtnl_htb_set_quantum", _wrap_rtnl_htb_set_quantum, METH_VARARGS, NULL}, - { (char *)"rtnl_htb_get_level", (PyCFunction)_wrap_rtnl_htb_get_level, METH_O, NULL}, - { (char *)"addr2obj", (PyCFunction)_wrap_addr2obj, METH_O, NULL}, - { (char *)"obj2addr", (PyCFunction)_wrap_obj2addr, METH_O, NULL}, - { (char *)"rtnl_addr_alloc", (PyCFunction)_wrap_rtnl_addr_alloc, METH_NOARGS, NULL}, - { (char *)"rtnl_addr_get", _wrap_rtnl_addr_get, METH_VARARGS, NULL}, - { (char *)"rtnl_addr_build_add_request", _wrap_rtnl_addr_build_add_request, METH_VARARGS, NULL}, - { (char *)"rtnl_addr_add", _wrap_rtnl_addr_add, METH_VARARGS, NULL}, - { (char *)"rtnl_addr_build_delete_request", _wrap_rtnl_addr_build_delete_request, METH_VARARGS, NULL}, - { (char *)"rtnl_addr_delete", _wrap_rtnl_addr_delete, METH_VARARGS, NULL}, - { (char *)"rtnl_addr_flags2str", _wrap_rtnl_addr_flags2str, METH_VARARGS, NULL}, - { (char *)"rtnl_addr_str2flags", (PyCFunction)_wrap_rtnl_addr_str2flags, METH_O, NULL}, - { (char *)"rtnl_addr_set_label", _wrap_rtnl_addr_set_label, METH_VARARGS, NULL}, - { (char *)"rtnl_addr_get_label", (PyCFunction)_wrap_rtnl_addr_get_label, METH_O, NULL}, - { (char *)"rtnl_addr_set_ifindex", _wrap_rtnl_addr_set_ifindex, METH_VARARGS, NULL}, - { (char *)"rtnl_addr_get_ifindex", (PyCFunction)_wrap_rtnl_addr_get_ifindex, METH_O, NULL}, - { (char *)"rtnl_addr_set_link", _wrap_rtnl_addr_set_link, METH_VARARGS, NULL}, - { (char *)"rtnl_addr_get_link", (PyCFunction)_wrap_rtnl_addr_get_link, METH_O, NULL}, - { (char *)"rtnl_addr_set_family", _wrap_rtnl_addr_set_family, METH_VARARGS, NULL}, - { (char *)"rtnl_addr_get_family", (PyCFunction)_wrap_rtnl_addr_get_family, METH_O, NULL}, - { (char *)"rtnl_addr_set_prefixlen", _wrap_rtnl_addr_set_prefixlen, METH_VARARGS, NULL}, - { (char *)"rtnl_addr_get_prefixlen", (PyCFunction)_wrap_rtnl_addr_get_prefixlen, METH_O, NULL}, - { (char *)"rtnl_addr_set_scope", _wrap_rtnl_addr_set_scope, METH_VARARGS, NULL}, - { (char *)"rtnl_addr_get_scope", (PyCFunction)_wrap_rtnl_addr_get_scope, METH_O, NULL}, - { (char *)"rtnl_addr_set_flags", _wrap_rtnl_addr_set_flags, METH_VARARGS, NULL}, - { (char *)"rtnl_addr_unset_flags", _wrap_rtnl_addr_unset_flags, METH_VARARGS, NULL}, - { (char *)"rtnl_addr_get_flags", (PyCFunction)_wrap_rtnl_addr_get_flags, METH_O, NULL}, - { (char *)"rtnl_addr_set_local", _wrap_rtnl_addr_set_local, METH_VARARGS, NULL}, - { (char *)"rtnl_addr_get_local", (PyCFunction)_wrap_rtnl_addr_get_local, METH_O, NULL}, - { (char *)"rtnl_addr_set_peer", _wrap_rtnl_addr_set_peer, METH_VARARGS, NULL}, - { (char *)"rtnl_addr_get_peer", (PyCFunction)_wrap_rtnl_addr_get_peer, METH_O, NULL}, - { (char *)"rtnl_addr_set_broadcast", _wrap_rtnl_addr_set_broadcast, METH_VARARGS, NULL}, - { (char *)"rtnl_addr_get_broadcast", (PyCFunction)_wrap_rtnl_addr_get_broadcast, METH_O, NULL}, - { (char *)"rtnl_addr_set_multicast", _wrap_rtnl_addr_set_multicast, METH_VARARGS, NULL}, - { (char *)"rtnl_addr_get_multicast", (PyCFunction)_wrap_rtnl_addr_get_multicast, METH_O, NULL}, - { (char *)"rtnl_addr_set_anycast", _wrap_rtnl_addr_set_anycast, METH_VARARGS, NULL}, - { (char *)"rtnl_addr_get_anycast", (PyCFunction)_wrap_rtnl_addr_get_anycast, METH_O, NULL}, - { (char *)"rtnl_addr_get_valid_lifetime", (PyCFunction)_wrap_rtnl_addr_get_valid_lifetime, METH_O, NULL}, - { (char *)"rtnl_addr_set_valid_lifetime", _wrap_rtnl_addr_set_valid_lifetime, METH_VARARGS, NULL}, - { (char *)"rtnl_addr_get_preferred_lifetime", (PyCFunction)_wrap_rtnl_addr_get_preferred_lifetime, METH_O, NULL}, - { (char *)"rtnl_addr_set_preferred_lifetime", _wrap_rtnl_addr_set_preferred_lifetime, METH_VARARGS, NULL}, - { (char *)"rtnl_addr_get_create_time", (PyCFunction)_wrap_rtnl_addr_get_create_time, METH_O, NULL}, - { (char *)"rtnl_addr_get_last_update_time", (PyCFunction)_wrap_rtnl_addr_get_last_update_time, METH_O, NULL}, - { NULL, NULL, 0, NULL } -}; - - -/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */ - -static swig_type_info _swigt__p_char = {"_p_char", "char *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_int = {"_p_int", "intptr_t *|int *|int_least32_t *|int_fast32_t *|int32_t *|int_fast16_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_long_long = {"_p_long_long", "int_least64_t *|int_fast64_t *|int64_t *|long long *|intmax_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_nl_addr = {"_p_nl_addr", "struct nl_addr *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_nl_cache = {"_p_nl_cache", "struct nl_cache *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_nl_object = {"_p_nl_object", "struct nl_object *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_nl_sock = {"_p_nl_sock", "struct nl_sock *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_p_nl_msg = {"_p_p_nl_msg", "struct nl_msg **", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_rtnl_addr = {"_p_rtnl_addr", "struct rtnl_addr *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_rtnl_class = {"_p_rtnl_class", "struct rtnl_class *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_rtnl_cls = {"_p_rtnl_cls", "struct rtnl_cls *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_rtnl_link = {"_p_rtnl_link", "struct rtnl_link *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_rtnl_qdisc = {"_p_rtnl_qdisc", "struct rtnl_qdisc *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_rtnl_tc = {"_p_rtnl_tc", "struct rtnl_tc *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_short = {"_p_short", "short *|int_least16_t *|int16_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_signed_char = {"_p_signed_char", "signed char *|int_least8_t *|int_fast8_t *|int8_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_unsigned_char = {"_p_unsigned_char", "unsigned char *|uint_least8_t *|uint_fast8_t *|uint8_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_unsigned_int = {"_p_unsigned_int", "uintptr_t *|uint_least32_t *|uint_fast32_t *|uint32_t *|unsigned int *|uint_fast16_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_unsigned_long_long = {"_p_unsigned_long_long", "uint_least64_t *|uint_fast64_t *|uint64_t *|unsigned long long *|uintmax_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_unsigned_short = {"_p_unsigned_short", "unsigned short *|uint_least16_t *|uint16_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_vlan_map = {"_p_vlan_map", "struct vlan_map *|vlan_map *", 0, 0, (void*)0, 0}; - -static swig_type_info *swig_type_initial[] = { - &_swigt__p_char, - &_swigt__p_int, - &_swigt__p_long_long, - &_swigt__p_nl_addr, - &_swigt__p_nl_cache, - &_swigt__p_nl_object, - &_swigt__p_nl_sock, - &_swigt__p_p_nl_msg, - &_swigt__p_rtnl_addr, - &_swigt__p_rtnl_class, - &_swigt__p_rtnl_cls, - &_swigt__p_rtnl_link, - &_swigt__p_rtnl_qdisc, - &_swigt__p_rtnl_tc, - &_swigt__p_short, - &_swigt__p_signed_char, - &_swigt__p_unsigned_char, - &_swigt__p_unsigned_int, - &_swigt__p_unsigned_long_long, - &_swigt__p_unsigned_short, - &_swigt__p_vlan_map, -}; - -static swig_cast_info _swigc__p_char[] = { {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_int[] = { {&_swigt__p_int, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_long_long[] = { {&_swigt__p_long_long, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_nl_addr[] = { {&_swigt__p_nl_addr, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_nl_cache[] = { {&_swigt__p_nl_cache, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_nl_object[] = { {&_swigt__p_nl_object, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_nl_sock[] = { {&_swigt__p_nl_sock, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_p_nl_msg[] = { {&_swigt__p_p_nl_msg, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_rtnl_addr[] = { {&_swigt__p_rtnl_addr, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_rtnl_class[] = { {&_swigt__p_rtnl_class, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_rtnl_cls[] = { {&_swigt__p_rtnl_cls, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_rtnl_link[] = { {&_swigt__p_rtnl_link, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_rtnl_qdisc[] = { {&_swigt__p_rtnl_qdisc, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_rtnl_tc[] = { {&_swigt__p_rtnl_tc, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_short[] = { {&_swigt__p_short, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_signed_char[] = { {&_swigt__p_signed_char, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_unsigned_char[] = { {&_swigt__p_unsigned_char, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_unsigned_int[] = { {&_swigt__p_unsigned_int, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_unsigned_long_long[] = { {&_swigt__p_unsigned_long_long, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_unsigned_short[] = { {&_swigt__p_unsigned_short, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_vlan_map[] = { {&_swigt__p_vlan_map, 0, 0, 0},{0, 0, 0, 0}}; - -static swig_cast_info *swig_cast_initial[] = { - _swigc__p_char, - _swigc__p_int, - _swigc__p_long_long, - _swigc__p_nl_addr, - _swigc__p_nl_cache, - _swigc__p_nl_object, - _swigc__p_nl_sock, - _swigc__p_p_nl_msg, - _swigc__p_rtnl_addr, - _swigc__p_rtnl_class, - _swigc__p_rtnl_cls, - _swigc__p_rtnl_link, - _swigc__p_rtnl_qdisc, - _swigc__p_rtnl_tc, - _swigc__p_short, - _swigc__p_signed_char, - _swigc__p_unsigned_char, - _swigc__p_unsigned_int, - _swigc__p_unsigned_long_long, - _swigc__p_unsigned_short, - _swigc__p_vlan_map, -}; - - -/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */ - -static swig_const_info swig_const_table[] = { -{0, 0, 0, 0.0, 0, 0}}; - -#ifdef __cplusplus -} -#endif -/* ----------------------------------------------------------------------------- - * Type initialization: - * This problem is tough by the requirement that no dynamic - * memory is used. Also, since swig_type_info structures store pointers to - * swig_cast_info structures and swig_cast_info structures store pointers back - * to swig_type_info structures, we need some lookup code at initialization. - * The idea is that swig generates all the structures that are needed. - * The runtime then collects these partially filled structures. - * The SWIG_InitializeModule function takes these initial arrays out of - * swig_module, and does all the lookup, filling in the swig_module.types - * array with the correct data and linking the correct swig_cast_info - * structures together. - * - * The generated swig_type_info structures are assigned staticly to an initial - * array. We just loop through that array, and handle each type individually. - * First we lookup if this type has been already loaded, and if so, use the - * loaded structure instead of the generated one. Then we have to fill in the - * cast linked list. The cast data is initially stored in something like a - * two-dimensional array. Each row corresponds to a type (there are the same - * number of rows as there are in the swig_type_initial array). Each entry in - * a column is one of the swig_cast_info structures for that type. - * The cast_initial array is actually an array of arrays, because each row has - * a variable number of columns. So to actually build the cast linked list, - * we find the array of casts associated with the type, and loop through it - * adding the casts to the list. The one last trick we need to do is making - * sure the type pointer in the swig_cast_info struct is correct. - * - * First off, we lookup the cast->type name to see if it is already loaded. - * There are three cases to handle: - * 1) If the cast->type has already been loaded AND the type we are adding - * casting info to has not been loaded (it is in this module), THEN we - * replace the cast->type pointer with the type pointer that has already - * been loaded. - * 2) If BOTH types (the one we are adding casting info to, and the - * cast->type) are loaded, THEN the cast info has already been loaded by - * the previous module so we just ignore it. - * 3) Finally, if cast->type has not already been loaded, then we add that - * swig_cast_info to the linked list (because the cast->type) pointer will - * be correct. - * ----------------------------------------------------------------------------- */ - -#ifdef __cplusplus -extern "C" { -#if 0 -} /* c-mode */ -#endif -#endif - -#if 0 -#define SWIGRUNTIME_DEBUG -#endif - - -SWIGRUNTIME void -SWIG_InitializeModule(void *clientdata) { - size_t i; - swig_module_info *module_head, *iter; - int found, init; - - clientdata = clientdata; - - /* check to see if the circular list has been setup, if not, set it up */ - if (swig_module.next==0) { - /* Initialize the swig_module */ - swig_module.type_initial = swig_type_initial; - swig_module.cast_initial = swig_cast_initial; - swig_module.next = &swig_module; - init = 1; - } else { - init = 0; - } - - /* Try and load any already created modules */ - module_head = SWIG_GetModule(clientdata); - if (!module_head) { - /* This is the first module loaded for this interpreter */ - /* so set the swig module into the interpreter */ - SWIG_SetModule(clientdata, &swig_module); - module_head = &swig_module; - } else { - /* the interpreter has loaded a SWIG module, but has it loaded this one? */ - found=0; - iter=module_head; - do { - if (iter==&swig_module) { - found=1; - break; - } - iter=iter->next; - } while (iter!= module_head); - - /* if the is found in the list, then all is done and we may leave */ - if (found) return; - /* otherwise we must add out module into the list */ - swig_module.next = module_head->next; - module_head->next = &swig_module; - } - - /* When multiple interpeters are used, a module could have already been initialized in - a different interpreter, but not yet have a pointer in this interpreter. - In this case, we do not want to continue adding types... everything should be - set up already */ - if (init == 0) return; - - /* Now work on filling in swig_module.types */ -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: size %d\n", swig_module.size); -#endif - for (i = 0; i < swig_module.size; ++i) { - swig_type_info *type = 0; - swig_type_info *ret; - swig_cast_info *cast; - -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name); -#endif - - /* if there is another module already loaded */ - if (swig_module.next != &swig_module) { - type = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, swig_module.type_initial[i]->name); - } - if (type) { - /* Overwrite clientdata field */ -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: found type %s\n", type->name); -#endif - if (swig_module.type_initial[i]->clientdata) { - type->clientdata = swig_module.type_initial[i]->clientdata; -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: found and overwrite type %s \n", type->name); -#endif - } - } else { - type = swig_module.type_initial[i]; - } - - /* Insert casting types */ - cast = swig_module.cast_initial[i]; - while (cast->type) { - /* Don't need to add information already in the list */ - ret = 0; -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: look cast %s\n", cast->type->name); -#endif - if (swig_module.next != &swig_module) { - ret = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, cast->type->name); -#ifdef SWIGRUNTIME_DEBUG - if (ret) printf("SWIG_InitializeModule: found cast %s\n", ret->name); -#endif - } - if (ret) { - if (type == swig_module.type_initial[i]) { -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: skip old type %s\n", ret->name); -#endif - cast->type = ret; - ret = 0; - } else { - /* Check for casting already in the list */ - swig_cast_info *ocast = SWIG_TypeCheck(ret->name, type); -#ifdef SWIGRUNTIME_DEBUG - if (ocast) printf("SWIG_InitializeModule: skip old cast %s\n", ret->name); -#endif - if (!ocast) ret = 0; - } - } - - if (!ret) { -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: adding cast %s\n", cast->type->name); -#endif - if (type->cast) { - type->cast->prev = cast; - cast->next = type->cast; - } - type->cast = cast; - } - cast++; - } - /* Set entry in modules->types array equal to the type */ - swig_module.types[i] = type; - } - swig_module.types[i] = 0; - -#ifdef SWIGRUNTIME_DEBUG - printf("**** SWIG_InitializeModule: Cast List ******\n"); - for (i = 0; i < swig_module.size; ++i) { - int j = 0; - swig_cast_info *cast = swig_module.cast_initial[i]; - printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name); - while (cast->type) { - printf("SWIG_InitializeModule: cast type %s\n", cast->type->name); - cast++; - ++j; - } - printf("---- Total casts: %d\n",j); - } - printf("**** SWIG_InitializeModule: Cast List ******\n"); -#endif -} - -/* This function will propagate the clientdata field of type to -* any new swig_type_info structures that have been added into the list -* of equivalent types. It is like calling -* SWIG_TypeClientData(type, clientdata) a second time. -*/ -SWIGRUNTIME void -SWIG_PropagateClientData(void) { - size_t i; - swig_cast_info *equiv; - static int init_run = 0; - - if (init_run) return; - init_run = 1; - - for (i = 0; i < swig_module.size; i++) { - if (swig_module.types[i]->clientdata) { - equiv = swig_module.types[i]->cast; - while (equiv) { - if (!equiv->converter) { - if (equiv->type && !equiv->type->clientdata) - SWIG_TypeClientData(equiv->type, swig_module.types[i]->clientdata); - } - equiv = equiv->next; - } - } - } -} - -#ifdef __cplusplus -#if 0 -{ - /* c-mode */ -#endif -} -#endif - - - -#ifdef __cplusplus -extern "C" { -#endif - - /* Python-specific SWIG API */ -#define SWIG_newvarlink() SWIG_Python_newvarlink() -#define SWIG_addvarlink(p, name, get_attr, set_attr) SWIG_Python_addvarlink(p, name, get_attr, set_attr) -#define SWIG_InstallConstants(d, constants) SWIG_Python_InstallConstants(d, constants) - - /* ----------------------------------------------------------------------------- - * global variable support code. - * ----------------------------------------------------------------------------- */ - - typedef struct swig_globalvar { - char *name; /* Name of global variable */ - PyObject *(*get_attr)(void); /* Return the current value */ - int (*set_attr)(PyObject *); /* Set the value */ - struct swig_globalvar *next; - } swig_globalvar; - - typedef struct swig_varlinkobject { - PyObject_HEAD - swig_globalvar *vars; - } swig_varlinkobject; - - SWIGINTERN PyObject * - swig_varlink_repr(swig_varlinkobject *SWIGUNUSEDPARM(v)) { -#if PY_VERSION_HEX >= 0x03000000 - return PyUnicode_InternFromString(""); -#else - return PyString_FromString(""); -#endif - } - - SWIGINTERN PyObject * - swig_varlink_str(swig_varlinkobject *v) { -#if PY_VERSION_HEX >= 0x03000000 - PyObject *str = PyUnicode_InternFromString("("); - PyObject *tail; - PyObject *joined; - swig_globalvar *var; - for (var = v->vars; var; var=var->next) { - tail = PyUnicode_FromString(var->name); - joined = PyUnicode_Concat(str, tail); - Py_DecRef(str); - Py_DecRef(tail); - str = joined; - if (var->next) { - tail = PyUnicode_InternFromString(", "); - joined = PyUnicode_Concat(str, tail); - Py_DecRef(str); - Py_DecRef(tail); - str = joined; - } - } - tail = PyUnicode_InternFromString(")"); - joined = PyUnicode_Concat(str, tail); - Py_DecRef(str); - Py_DecRef(tail); - str = joined; -#else - PyObject *str = PyString_FromString("("); - swig_globalvar *var; - for (var = v->vars; var; var=var->next) { - PyString_ConcatAndDel(&str,PyString_FromString(var->name)); - if (var->next) PyString_ConcatAndDel(&str,PyString_FromString(", ")); - } - PyString_ConcatAndDel(&str,PyString_FromString(")")); -#endif - return str; - } - - SWIGINTERN int - swig_varlink_print(swig_varlinkobject *v, FILE *fp, int SWIGUNUSEDPARM(flags)) { - char *tmp; - PyObject *str = swig_varlink_str(v); - fprintf(fp,"Swig global variables "); - fprintf(fp,"%s\n", tmp = SWIG_Python_str_AsChar(str)); - SWIG_Python_str_DelForPy3(tmp); - Py_DECREF(str); - return 0; - } - - SWIGINTERN void - swig_varlink_dealloc(swig_varlinkobject *v) { - swig_globalvar *var = v->vars; - while (var) { - swig_globalvar *n = var->next; - free(var->name); - free(var); - var = n; - } - } - - SWIGINTERN PyObject * - swig_varlink_getattr(swig_varlinkobject *v, char *n) { - PyObject *res = NULL; - swig_globalvar *var = v->vars; - while (var) { - if (strcmp(var->name,n) == 0) { - res = (*var->get_attr)(); - break; - } - var = var->next; - } - if (res == NULL && !PyErr_Occurred()) { - PyErr_SetString(PyExc_NameError,"Unknown C global variable"); - } - return res; - } - - SWIGINTERN int - swig_varlink_setattr(swig_varlinkobject *v, char *n, PyObject *p) { - int res = 1; - swig_globalvar *var = v->vars; - while (var) { - if (strcmp(var->name,n) == 0) { - res = (*var->set_attr)(p); - break; - } - var = var->next; - } - if (res == 1 && !PyErr_Occurred()) { - PyErr_SetString(PyExc_NameError,"Unknown C global variable"); - } - return res; - } - - SWIGINTERN PyTypeObject* - swig_varlink_type(void) { - static char varlink__doc__[] = "Swig var link object"; - static PyTypeObject varlink_type; - static int type_init = 0; - if (!type_init) { - const PyTypeObject tmp - = { - /* PyObject header changed in Python 3 */ -#if PY_VERSION_HEX >= 0x03000000 - PyVarObject_HEAD_INIT(&PyType_Type, 0) -#else - PyObject_HEAD_INIT(NULL) - 0, /* Number of items in variable part (ob_size) */ -#endif - (char *)"swigvarlink", /* Type name (tp_name) */ - sizeof(swig_varlinkobject), /* Basic size (tp_basicsize) */ - 0, /* Itemsize (tp_itemsize) */ - (destructor) swig_varlink_dealloc, /* Deallocator (tp_dealloc) */ - (printfunc) swig_varlink_print, /* Print (tp_print) */ - (getattrfunc) swig_varlink_getattr, /* get attr (tp_getattr) */ - (setattrfunc) swig_varlink_setattr, /* Set attr (tp_setattr) */ - 0, /* tp_compare */ - (reprfunc) swig_varlink_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - (reprfunc) swig_varlink_str, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - 0, /* tp_flags */ - varlink__doc__, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ -#if PY_VERSION_HEX >= 0x02020000 - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* tp_iter -> tp_weaklist */ -#endif -#if PY_VERSION_HEX >= 0x02030000 - 0, /* tp_del */ -#endif -#ifdef COUNT_ALLOCS - 0,0,0,0 /* tp_alloc -> tp_next */ -#endif - }; - varlink_type = tmp; - /* for Python 3 we already assigned ob_type in PyVarObject_HEAD_INIT() */ -#if PY_VERSION_HEX < 0x03000000 - varlink_type.ob_type = &PyType_Type; -#endif - type_init = 1; - } - return &varlink_type; - } - - /* Create a variable linking object for use later */ - SWIGINTERN PyObject * - SWIG_Python_newvarlink(void) { - swig_varlinkobject *result = PyObject_NEW(swig_varlinkobject, swig_varlink_type()); - if (result) { - result->vars = 0; - } - return ((PyObject*) result); - } - - SWIGINTERN void - SWIG_Python_addvarlink(PyObject *p, char *name, PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p)) { - swig_varlinkobject *v = (swig_varlinkobject *) p; - swig_globalvar *gv = (swig_globalvar *) malloc(sizeof(swig_globalvar)); - if (gv) { - size_t size = strlen(name)+1; - gv->name = (char *)malloc(size); - if (gv->name) { - strncpy(gv->name,name,size); - gv->get_attr = get_attr; - gv->set_attr = set_attr; - gv->next = v->vars; - } - } - v->vars = gv; - } - - SWIGINTERN PyObject * - SWIG_globals(void) { - static PyObject *_SWIG_globals = 0; - if (!_SWIG_globals) _SWIG_globals = SWIG_newvarlink(); - return _SWIG_globals; - } - - /* ----------------------------------------------------------------------------- - * constants/methods manipulation - * ----------------------------------------------------------------------------- */ - - /* Install Constants */ - SWIGINTERN void - SWIG_Python_InstallConstants(PyObject *d, swig_const_info constants[]) { - PyObject *obj = 0; - size_t i; - for (i = 0; constants[i].type; ++i) { - switch(constants[i].type) { - case SWIG_PY_POINTER: - obj = SWIG_NewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0); - break; - case SWIG_PY_BINARY: - obj = SWIG_NewPackedObj(constants[i].pvalue, constants[i].lvalue, *(constants[i].ptype)); - break; - default: - obj = 0; - break; - } - if (obj) { - PyDict_SetItemString(d, constants[i].name, obj); - Py_DECREF(obj); - } - } - } - - /* -----------------------------------------------------------------------------*/ - /* Fix SwigMethods to carry the callback ptrs when needed */ - /* -----------------------------------------------------------------------------*/ - - SWIGINTERN void - SWIG_Python_FixMethods(PyMethodDef *methods, - swig_const_info *const_table, - swig_type_info **types, - swig_type_info **types_initial) { - size_t i; - for (i = 0; methods[i].ml_name; ++i) { - const char *c = methods[i].ml_doc; - if (c && (c = strstr(c, "swig_ptr: "))) { - int j; - swig_const_info *ci = 0; - const char *name = c + 10; - for (j = 0; const_table[j].type; ++j) { - if (strncmp(const_table[j].name, name, - strlen(const_table[j].name)) == 0) { - ci = &(const_table[j]); - break; - } - } - if (ci) { - size_t shift = (ci->ptype) - types; - swig_type_info *ty = types_initial[shift]; - size_t ldoc = (c - methods[i].ml_doc); - size_t lptr = strlen(ty->name)+2*sizeof(void*)+2; - char *ndoc = (char*)malloc(ldoc + lptr + 10); - if (ndoc) { - char *buff = ndoc; - void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue : 0; - if (ptr) { - strncpy(buff, methods[i].ml_doc, ldoc); - buff += ldoc; - strncpy(buff, "swig_ptr: ", 10); - buff += 10; - SWIG_PackVoidPtr(buff, ptr, ty->name, lptr); - methods[i].ml_doc = ndoc; - } - } - } - } - } - } - -#ifdef __cplusplus -} -#endif - -/* -----------------------------------------------------------------------------* - * Partial Init method - * -----------------------------------------------------------------------------*/ - -#ifdef __cplusplus -extern "C" -#endif - -SWIGEXPORT -#if PY_VERSION_HEX >= 0x03000000 -PyObject* -#else -void -#endif -SWIG_init(void) { - PyObject *m, *d; -#if PY_VERSION_HEX >= 0x03000000 - static struct PyModuleDef SWIG_module = { - PyModuleDef_HEAD_INIT, - (char *) SWIG_name, - NULL, - -1, - SwigMethods, - NULL, - NULL, - NULL, - NULL - }; -#endif - - /* Fix SwigMethods to carry the callback ptrs when needed */ - SWIG_Python_FixMethods(SwigMethods, swig_const_table, swig_types, swig_type_initial); - -#if PY_VERSION_HEX >= 0x03000000 - m = PyModule_Create(&SWIG_module); -#else - m = Py_InitModule((char *) SWIG_name, SwigMethods); -#endif - d = PyModule_GetDict(m); - - SWIG_InitializeModule(0); - SWIG_InstallConstants(d,swig_const_table); - - - SWIG_Python_SetConstant(d, "VLAN_PRIO_MAX",SWIG_From_int((int)(7))); -#if PY_VERSION_HEX >= 0x03000000 - return m; -#else - return; -#endif -} - From 20e979765249206f48ec5a9427f38123e7b8af29 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 21 Jul 2011 17:52:43 +0200 Subject: [PATCH 063/432] use rtnl_link_set/get_type() --- python/.gitignore | 2 ++ python/netlink/route/capi.i | 4 ++-- python/netlink/route/link.py | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/python/.gitignore b/python/.gitignore index 378eac2..9f3c73b 100644 --- a/python/.gitignore +++ b/python/.gitignore @@ -1 +1,3 @@ build +capi_wrap.c +capi.py diff --git a/python/netlink/route/capi.i b/python/netlink/route/capi.i index 204f93a..ae3592d 100644 --- a/python/netlink/route/capi.i +++ b/python/netlink/route/capi.i @@ -142,8 +142,8 @@ extern int rtnl_link_get_num_vf(struct rtnl_link *, uint32_t *); extern uint64_t rtnl_link_get_stat(struct rtnl_link *, int); extern int rtnl_link_set_stat(struct rtnl_link *, const unsigned int, const uint64_t); -extern int rtnl_link_set_info_type(struct rtnl_link *, const char *); -extern char *rtnl_link_get_info_type(struct rtnl_link *); +extern int rtnl_link_set_type(struct rtnl_link *, const char *); +extern char *rtnl_link_get_type(struct rtnl_link *); /* */ diff --git a/python/netlink/route/link.py b/python/netlink/route/link.py index c4eb20c..e613f2e 100644 --- a/python/netlink/route/link.py +++ b/python/netlink/route/link.py @@ -386,11 +386,11 @@ class Link(netlink.Object): @property def type(self): """Link type""" - return capi.rtnl_link_get_info_type(self._rtnl_link) + return capi.rtnl_link_get_type(self._rtnl_link) @type.setter def type(self, value): - if capi.rtnl_link_set_info_type(self._rtnl_link, value) < 0: + if capi.rtnl_link_set_type(self._rtnl_link, value) < 0: raise NameError("unknown info type") self._module_lookup('netlink.route.links.' + value) From f3ee2167158b01e9a7d1fc2a4a57d5d49391ea37 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Mon, 25 Jul 2011 10:32:26 +0200 Subject: [PATCH 064/432] include from to export IFF_* flags --- include/netlink/route/link.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/netlink/route/link.h b/include/netlink/route/link.h index d7d9cd3..2e5274a 100644 --- a/include/netlink/route/link.h +++ b/include/netlink/route/link.h @@ -15,6 +15,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { From 915a23fd16315eed2b13dda38c96ca824935e844 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 27 Jul 2011 17:01:34 +0200 Subject: [PATCH 065/432] Hack doxygen CSS to avoid stupid margins in modules listing --- doc/libnl.css | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/libnl.css b/doc/libnl.css index ddc6ac3..65fabaa 100644 --- a/doc/libnl.css +++ b/doc/libnl.css @@ -361,6 +361,15 @@ table.memberdecls { padding: 1px 0 0 8px; } +.mdescRight > p { + padding: 0px; + margin: 0px; +} + +.mdescRight > br { + font-size: 0pt; +} + .mdescLeft, .mdescRight { padding: 0px 8px 4px 8px; color: #555; From 70c93717607a15d37b60d7caefb58e78d28c5e59 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 28 Jul 2011 16:23:57 +0200 Subject: [PATCH 066/432] Updated link documentation - API documentation - developer guide - enabled doxygen navbar - fixed css --- doc/Doxyfile.in | 16 +- doc/DoxygenLayout.xml | 10 +- doc/libnl.css | 41 +- doc/route.txt | 289 +++++-- doc/src/hidden.c | 35 + doc/stylesheets/asciidoc.css | 3 +- include/netlink/route/link.h | 142 ++-- lib/fib_lookup/lookup.c | 2 - lib/route/link.c | 1433 ++++++++++++++++++---------------- lib/route/link/bonding.c | 4 +- lib/route/link/dummy.c | 4 +- lib/route/link/vlan.c | 5 +- 12 files changed, 1163 insertions(+), 821 deletions(-) create mode 100644 doc/src/hidden.c diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 5deba44..33d5a8c 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -181,6 +181,12 @@ TAB_SIZE = 8 ALIASES = arg=\param +ALIASES += ref_asciidoc{3}="\3" +ALIASES += ref_core{2}="\ref_asciidoc{core,\1,\2 (Netlink Library)}" +ALIASES += ref_route{2}="\ref_asciidoc{route,\1,\2 (Routing Family Library)}" +ALIASES += core_doc{2}="\par Related Documentation:\n\ref_core{\1,\2}" +ALIASES += route_doc{2}="\par Related Documentation:\n\ref_route{\1,\2}" + # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list @@ -487,13 +493,13 @@ SHOW_USED_FILES = NO # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. -SHOW_DIRECTORIES = YES +SHOW_DIRECTORIES = NO # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. -SHOW_FILES = YES +SHOW_FILES = NO # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. @@ -1012,7 +1018,7 @@ GENERATE_ECLIPSEHELP = NO # the directory name containing the HTML and XML files should also have # this name. -ECLIPSE_DOC_ID = org.doxygen.Project +ECLIPSE_DOC_ID = org.infradead.libnl # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and @@ -1033,7 +1039,7 @@ ENUM_VALUES_PER_LINE = 1 # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. -GENERATE_TREEVIEW = NO +GENERATE_TREEVIEW = YES # By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list. @@ -1044,7 +1050,7 @@ USE_INLINE_TREES = YES # used to set the initial width (in pixels) of the frame in which the tree # is shown. -TREEVIEW_WIDTH = 250 +TREEVIEW_WIDTH = 205 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open # links to external symbols imported via tag files in a separate window. diff --git a/doc/DoxygenLayout.xml b/doc/DoxygenLayout.xml index 29049d1..8d3e3ff 100644 --- a/doc/DoxygenLayout.xml +++ b/doc/DoxygenLayout.xml @@ -14,11 +14,11 @@ - + - + @@ -64,13 +64,13 @@ - + @@ -132,14 +132,13 @@ - + - @@ -151,6 +150,7 @@ + diff --git a/doc/libnl.css b/doc/libnl.css index 65fabaa..6b04f0d 100644 --- a/doc/libnl.css +++ b/doc/libnl.css @@ -376,7 +376,7 @@ table.memberdecls { } .memItemLeft, .memItemRight, .memTemplParams { - border-top: 1px solid #C4CFE5; + border-top: 1px solid #a7a7a7; } .memItemLeft, .memTemplItemLeft { @@ -428,18 +428,17 @@ table.memberdecls { .memname { white-space: nowrap; - font-weight: bold; + font-family: monospace, fixed; + font-weight: bold; + font-size: 110%; margin-left: 6px; } .memproto { - border-top: 1px solid #A8B8D9; - border-left: 1px solid #A8B8D9; - border-right: 1px solid #A8B8D9; - border-bottom: 1px solid #A8B8D9; + border: 1px solid #990000; padding: 6px 0px 6px 0px; - color: #253555; - font-weight: bold; + /* color: #253555; */ + color: #990000; /* text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); */ /* opera specific markup */ box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); @@ -453,17 +452,16 @@ table.memberdecls { -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); -webkit-border-top-right-radius: 8px; -webkit-border-top-left-radius: 8px; - background-image:url('nav_f.png'); - background-repeat:repeat-x; - background-color: #E2E8F2; - + /* background-image:url('nav_f.png'); + background-repeat:repeat-x; */ + background-color: #f1f1f1; } .memdoc { - border-bottom: 1px solid #A8B8D9; - border-left: 1px solid #A8B8D9; - border-right: 1px solid #A8B8D9; - padding: 2px 5px; + border-bottom: 1px solid #990000; + border-left: 1px solid #990000; + border-right: 1px solid #990000; + padding: 10px 15px; background-color: #FBFCFD; border-top-width: 0; /* opera specific markup */ @@ -487,13 +485,15 @@ table.memberdecls { } .paramtype { + color: #c87424; white-space: nowrap; + font-family: monospace, fixed; } .paramname { - /* color: #602020; */ - color: black; + color: #990000; white-space: nowrap; + font-family: monospace, fixed; } .paramname em { font-style: normal; @@ -751,6 +751,11 @@ dl padding: 0 0 0 10px; } +.memdoc > dl +{ + padding: 0px; +} + dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug { border-left:4px solid; diff --git a/doc/route.txt b/doc/route.txt index d48c26e..757b4bd 100644 --- a/doc/route.txt +++ b/doc/route.txt @@ -15,6 +15,7 @@ This library provides APIs to the kernel interfaces of the routing family. == Addresses +[[route_link]] == Links (Network Devices) The link configuration interface is part of the +NETLINK_ROUTE+ protocol @@ -171,34 +172,6 @@ Notification sent by the kernel to the multicast group +RTNLGRP_LINK+ when a. a network device was unregistered (change == ~0) b. a bridging device was deleted (address family will be +PF_BRIDGE+) -[source,c] ------ -#define IFF_UP 0x1 /* interface is up */ -#define IFF_BROADCAST 0x2 /* broadcast address valid */ -#define IFF_DEBUG 0x4 /* turn on debugging */ -#define IFF_LOOPBACK 0x8 /* is a loopback net */ -#define IFF_POINTOPOINT 0x10 /* interface is has p-p link */ -#define IFF_NOTRAILERS 0x20 /* avoid use of trailers */ -#define IFF_RUNNING 0x40 /* interface RFC2863 OPER_UP */ -#define IFF_NOARP 0x80 /* no ARP protocol */ -#define IFF_PROMISC 0x100 /* receive all packets */ -#define IFF_ALLMULTI 0x200 /* receive all multicast packets*/ - -#define IFF_MASTER 0x400 /* master of a load balancer */ -#define IFF_SLAVE 0x800 /* slave of a load balancer */ - -#define IFF_MULTICAST 0x1000 /* Supports multicast */ - -#define IFF_PORTSEL 0x2000 /* can set media type */ -#define IFF_AUTOMEDIA 0x4000 /* auto media select active */ -#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses*/ - -#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */ -#define IFF_DORMANT 0x20000 /* driver signals dormant */ - -#define IFF_ECHO 0x40000 /* echo sent packets */ ------ - === Get / List [[link_list]] @@ -252,6 +225,7 @@ rtnl_link_put(link); nl_cache_put(cache); ----- +[[link_direct_lookup]] ==== Lookup Single Link (Direct Lookup) If only a single link is of interest, the link can be looked up directly @@ -287,6 +261,7 @@ NOTE: While using this function can save a substantial amount of bandwidth to rtnl_link_get_kernel() will always trigger sending a +RTM_GETLINK+ request. +[[link_translate_ifindex]] ==== Translating interface index to link name Applications which require to translate interface index to a link name or @@ -347,68 +322,267 @@ rtnl_link_put(link); [[link_object]] === Link Object -Name:: -The name of a network device is the human readable representation of a -network device and secondary identification parameter besides the interface -index. -+ -Kernels >= 2.6.11 support identification by link name. -+ +A link is represented by the structure +struct rtnl_link+. Instances may be +created with the function +rtnl_link_alloc()+ or via a link cache (see +<>) and are freed again using the function +rtnl_link_put()+. + [source,c] ----- -void rtnl_link_set_name(struct rtnl_link *link, const char *name); +#include + +struct rtnl_link *rtnl_link_alloc(void); +void rtnl_link_put(struct rtnl_link *link); +----- + +[[link_attr_name]] +==== Name +The name serves as unique, human readable description of the link. By +default, links are named based on their type and then enumerated, e.g. +eth0, eth1, ethn but they may be renamed at any time. + +Kernels >= 2.6.11 support identification by link name. + +[source,c] +----- +#include + +void rtnl_link_set_name(struct rtnl_link *link, const char *name); char *rtnl_link_get_name(struct rtnl_link *link); ----- -Interface Index:: -The interface index is an integer uniquely identifying a network device. -If present, it will be used to identify an existing network device. -+ +*Accepted link name format:* +[^ /]*+ (maximum length: 15 characters) + +[[link_attr_ifindex]] +==== Interface Index (Identifier) +The interface index is an integer uniquely identifying a link. If present +in any link message, it will be used to identify an existing link. + [source,c] ----- +#include + void rtnl_link_set_ifindex(struct rtnl_link *link, int ifindex); -int rtnl_link_get_ifindex(struct rtnl_link *link); +int rtnl_link_get_ifindex(struct rtnl_link *link); ----- +[[link_attr_address]] +==== Link Layer Address +The link layer address (e.g. MAC address). -Address:: -The link layer address (MAC address). -+ [source,c] ----- -void rtnl_link_set_addr(struct rtnl_link *link, struct nl_addr *addr); +#include + +void rtnl_link_set_addr(struct rtnl_link *link, struct nl_addr *addr); struct nl_addr *rtnl_link_get_addr(struct rtnl_link *link); ----- -Broadcast Address:: -Foo -+ +[[link_attr_broadcast]] +==== Broadcast Address +The link layer broadcast address + [source,c] ----- -void rtnl_link_set_broadcast(struct rtnl_link *link, struct nl_addr *addr); +#include + +void rtnl_link_set_broadcast(struct rtnl_link *link, struct nl_addr *addr); struct nl_addr *rtnl_link_get_broadcast(struct rtnl_link *link); ----- -MTU:: +[[link_attr_mtu]] +==== MTU (Maximum Transmission Unit) The maximum transmission unit specifies the maximum packet size a network device can transmit or receive. This value may be lower than the capability of the physical network device. -+ + [source,c] ----- -void rtnl_link_set_mtu(struct rtnl_link *link, unsigned int mtu); +#include + +void rtnl_link_set_mtu(struct rtnl_link *link, unsigned int mtu); unsigned int rtnl_link_get_mtu(struct rtnl_link *link); ----- -Weight:: -Foo -+ +[[link_attr_flags]] +==== Flags +The flags of a link enable or disable various link features or inform about +the state of the link. + [source,c] ----- -void rtnl_link_set_weight(struct rtnl_link *link, unsigned int weight); -unsigned int rtnl_link_get_weight(struct rtnl_link *link); +#include + +void rtnl_link_set_flags(struct rtnl_link *link, unsigned int flags); +void rtnl_link_unset_flags(struct rtnl_link *link, unsigned int flags); +unsigned int rtnl_link_get_flags(struct rtnl_link *link); ----- +[options="compact"] +[horizontal] +IFF_UP:: Link is up (administratively) +IFF_RUNNING:: Link is up and carrier is OK (RFC2863 OPER_UP) +IFF_LOWER_UP:: Link layer is operational +IFF_DORMANT:: Driver signals dormant +IFF_BROADCAST:: Link supports broadcasting +IFF_MULTICAST:: Link supports multicasting +IFF_ALLMULTI:: Link supports multicast routing +IFF_DEBUG:: Tell driver to do debugging (currently unused) +IFF_LOOPBACK:: Link loopback network +IFF_POINTOPOINT:: Point-to-point link +IFF_NOARP:: ARP is not supported +IFF_PROMISC:: Status of promiscious mode +IFF_MASTER:: Master of a load balancer (bonding) +IFF_SLAVE:: Slave to a master link +IFF_PORTSEL:: Driver supports setting media type (only used by ARM ethernet) +IFF_AUTOMEDIA:: Link selects port automatically (only used by ARM ethernet) +IFF_ECHO:: Echo sent packets (testing feature, CAN only) +IFF_DYNAMIC:: Unused (BSD compatibility) +IFF_NOTRAILERS:: Unused (BSD compatibility) + +To translate a link flag to a link flag name or vice versa: + +[source,c] +----- +#include + +char *rtnl_link_flags2str(int flags, char *buf, size_t size); +int rtnl_link_str2flags(const char *flag_name); +----- + +[[link_attr_txqlen]] +==== Transmission Queue Length + +The transmission queue holds packets before packets are delivered to +the driver for transmission. It is usually specified in number of +packets but the unit may be specific to the link type. + +[source,c] +----- +#include + +void rtnl_link_set_txqlen(struct rtnl_link *link, unsigned int txqlen); +unsigned int rtnl_link_get_txqlen(struct rtnl_link *link); +----- + +[[link_attr_operstate]] +==== Operational Status +The operational status has been introduced to provide extended information +on the link status. Traditionally the link state has been described using +the link flags +IFF_UP, IFF_RUNNING, IFF_LOWER_UP+, and +IFF_DORMANT+ which +was no longer sufficient for some link types. + +[source,c] +----- +#include + +void rtnl_link_set_operstate(struct rtnl_link *link, uint8_t state); +uint8_t rtnl_link_get_operstate(struct rtnl_link *link); +----- + +[options="compact"] +[horizontal] +IF_OPER_UNKNOWN:: Unknown state +IF_OPER_NOTPRESENT:: Link not present +IF_OPER_DOWN:: Link down +IF_OPER_LOWERLAYERDOWN:: L1 down +IF_OPER_TESTING:: Testing +IF_OPER_DORMANT:: Dormant +IF_OPER_UP:: Link up + +Translation of operational status code to string and vice versa: + +[source,c] +----- +#include + +char *rtnl_link_operstate2str(uint8_t state, char *buf, size_t size); +int rtnl_link_str2operstate(const char *name); +----- + +[[link_attr_mode]] +==== Mode +Currently known link modes are: + +[options="compact"] +[horizontal] +IF_LINK_MODE_DEFAULT:: Default link mode +IF_LINK_MODE_DORMANT:: Limit upward transition to dormant + +[source,c] +----- +#include + +void rtnl_link_set_linkmode(struct rtnl_link *link, uint8_t mode); +uint8_t rtnl_link_get_linkmode(struct rtnl_link *link); +----- + +Translation of link mode to string and vice versa: + +[source,c] +----- +char *rtnl_link_mode2str(uint8_t mode, char *buf, size_t len); +uint8_t rtnl_link_str2mode(const char *name); +----- + +[[link_attr_alias]] +==== IfAlias +Alternative name for the link, primarly used for SNMP IfAlias. + +[source,c] +----- +#include + +const char *rtnl_link_get_ifalias(struct rtnl_link *link); +void rtnl_link_set_ifalias(struct rtnl_link *link, const char *alias); +----- + +*Length limit:* 256 + +[[link_attr_arptype]] +==== Hardware Type + +[source,c] +----- +#include +#include + +void rtnl_link_set_arptype(struct rtnl_link *link, unsigned int arptype); +unsigned int rtnl_link_get_arptype(struct rtnl_link *link); +---- + +Translation of hardware type to character string and vice versa: + +[source,c] +----- +#include + +char *nl_llproto2str(int arptype, char *buf, size_t len); +int nl_str2llproto(const char *name); +----- + +[[link_attr_qdisc]] +==== Qdisc +The name of the queueing discipline used by the link is of informational +nature only. It is a read-only attribute provided by the kernel and cannot +be modified. The set function is provided solely for the purpose of creating +link objects to be used for comparison. + +For more information on how to modify the qdisc of a link, see section +<>. + +[[link_attr_weight]] +==== Weight +This attribute is unused and obsoleted in all recent kernels. + +[source,c] +----- +#include + +extern void rtnl_link_set_qdisc(struct rtnl_link *link, const char *name); +extern char *rtnl_link_get_qdisc(struct rtnl_link *link); +----- + +[[link_modules]] === Modules [[link_bonding]] @@ -490,6 +664,7 @@ rtnl_link_put(link); == Routing +[[route_tc]] == Traffic Control The traffic control architecture allows the queueing and diff --git a/doc/src/hidden.c b/doc/src/hidden.c new file mode 100644 index 0000000..be4a042 --- /dev/null +++ b/doc/src/hidden.c @@ -0,0 +1,35 @@ +/** + * \cond skip + * vim:syntax=doxygen + * \endcond + +\page auto_ack_warning Disabling Auto-ACK + +\attention Disabling Auto-ACK (nl_socket_disable_auto_ack()) will cause this + function to return immediately after sending the netlink message. + The function will not wait for an eventual error message. It is + the responsibility of the caller to handle any error messages or + ACKs returned. + +\page pointer_lifetime_warning Pointer Lifetime + +\attention The reference counter of the returned object is not incremented. + Therefore, the returned pointer is only valid during the lifetime + of the parent object. Increment the reference counter if the object + is supposed to stay around after the parent object was freed. + +\page private_struct Private Structure + +\note The definition of this structure is private to allow modification + without breaking API. Use the designated accessor functions to + access individual object attributes. + +\page read_only_attribute Read-Only Attribute + +\note The attribute this accessor is modifying is a read-only attribute + which can not be modified in the kernel. Any changes to the + attribute only have an effect on the local copy of the object. The + accessor function is provided solely for the purpose of creating + objects for comparison and filtering. + +*/ diff --git a/doc/stylesheets/asciidoc.css b/doc/stylesheets/asciidoc.css index 8ded7c9..2852168 100644 --- a/doc/stylesheets/asciidoc.css +++ b/doc/stylesheets/asciidoc.css @@ -285,7 +285,8 @@ td.hdlist1 { vertical-align: top; font-style: normal; padding-right: 0.8em; - color: navy; + /* color: navy; */ + color: #990000; } td.hdlist2 { vertical-align: top; diff --git a/include/netlink/route/link.h b/include/netlink/route/link.h index 2e5274a..79c2d56 100644 --- a/include/netlink/route/link.h +++ b/include/netlink/route/link.h @@ -21,77 +21,86 @@ extern "C" { #endif +/** + * @struct rtnl_link link.h "netlink/route/link.h" + * @brief Link object + * @implements nl_object + * @ingroup link + * + * @copydoc private_struct + */ struct rtnl_link; -enum rtnl_link_st { - RTNL_LINK_RX_PACKETS, - RTNL_LINK_TX_PACKETS, - RTNL_LINK_RX_BYTES, - RTNL_LINK_TX_BYTES, - RTNL_LINK_RX_ERRORS, - RTNL_LINK_TX_ERRORS, - RTNL_LINK_RX_DROPPED, - RTNL_LINK_TX_DROPPED, - RTNL_LINK_RX_COMPRESSED, - RTNL_LINK_TX_COMPRESSED, - RTNL_LINK_RX_FIFO_ERR, - RTNL_LINK_TX_FIFO_ERR, - RTNL_LINK_RX_LEN_ERR, - RTNL_LINK_RX_OVER_ERR, - RTNL_LINK_RX_CRC_ERR, - RTNL_LINK_RX_FRAME_ERR, - RTNL_LINK_RX_MISSED_ERR, - RTNL_LINK_TX_ABORT_ERR, - RTNL_LINK_TX_CARRIER_ERR, - RTNL_LINK_TX_HBEAT_ERR, - RTNL_LINK_TX_WIN_ERR, - RTNL_LINK_COLLISIONS, - RTNL_LINK_MULTICAST, - RTNL_LINK_IP6_INPKTS, /* InReceives */ - RTNL_LINK_IP6_INHDRERRORS, /* InHdrErrors */ - RTNL_LINK_IP6_INTOOBIGERRORS, /* InTooBigErrors */ - RTNL_LINK_IP6_INNOROUTES, /* InNoRoutes */ - RTNL_LINK_IP6_INADDRERRORS, /* InAddrErrors */ - RTNL_LINK_IP6_INUNKNOWNPROTOS, /* InUnknownProtos */ - RTNL_LINK_IP6_INTRUNCATEDPKTS, /* InTruncatedPkts */ - RTNL_LINK_IP6_INDISCARDS, /* InDiscards */ - RTNL_LINK_IP6_INDELIVERS, /* InDelivers */ - RTNL_LINK_IP6_OUTFORWDATAGRAMS, /* OutForwDatagrams */ - RTNL_LINK_IP6_OUTPKTS, /* OutRequests */ - RTNL_LINK_IP6_OUTDISCARDS, /* OutDiscards */ - RTNL_LINK_IP6_OUTNOROUTES, /* OutNoRoutes */ - RTNL_LINK_IP6_REASMTIMEOUT, /* ReasmTimeout */ - RTNL_LINK_IP6_REASMREQDS, /* ReasmReqds */ - RTNL_LINK_IP6_REASMOKS, /* ReasmOKs */ - RTNL_LINK_IP6_REASMFAILS, /* ReasmFails */ - RTNL_LINK_IP6_FRAGOKS, /* FragOKs */ - RTNL_LINK_IP6_FRAGFAILS, /* FragFails */ - RTNL_LINK_IP6_FRAGCREATES, /* FragCreates */ - RTNL_LINK_IP6_INMCASTPKTS, /* InMcastPkts */ - RTNL_LINK_IP6_OUTMCASTPKTS, /* OutMcastPkts */ - RTNL_LINK_IP6_INBCASTPKTS, /* InBcastPkts */ - RTNL_LINK_IP6_OUTBCASTPKTS, /* OutBcastPkts */ - RTNL_LINK_IP6_INOCTETS, /* InOctets */ - RTNL_LINK_IP6_OUTOCTETS, /* OutOctets */ - RTNL_LINK_IP6_INMCASTOCTETS, /* InMcastOctets */ - RTNL_LINK_IP6_OUTMCASTOCTETS, /* OutMcastOctets */ - RTNL_LINK_IP6_INBCASTOCTETS, /* InBcastOctets */ - RTNL_LINK_IP6_OUTBCASTOCTETS, /* OutBcastOctets */ - RTNL_LINK_ICMP6_INMSGS, /* InMsgs */ - RTNL_LINK_ICMP6_INERRORS, /* InErrors */ - RTNL_LINK_ICMP6_OUTMSGS, /* OutMsgs */ - RTNL_LINK_ICMP6_OUTERRORS, /* OutErrors */ +/** + * @ingroup link + */ +typedef enum { + RTNL_LINK_RX_PACKETS, /*!< Packets received */ + RTNL_LINK_TX_PACKETS, /*!< Packets sent */ + RTNL_LINK_RX_BYTES, /*!< Bytes received */ + RTNL_LINK_TX_BYTES, /*!< Bytes sent */ + RTNL_LINK_RX_ERRORS, /*!< Receive errors */ + RTNL_LINK_TX_ERRORS, /*!< Send errors */ + RTNL_LINK_RX_DROPPED, /*!< Received packets dropped */ + RTNL_LINK_TX_DROPPED, /*!< Packets dropped during transmit */ + RTNL_LINK_RX_COMPRESSED, /*!< Compressed packets received */ + RTNL_LINK_TX_COMPRESSED, /*!< Compressed packets sent */ + RTNL_LINK_RX_FIFO_ERR, /*!< Receive FIFO errors */ + RTNL_LINK_TX_FIFO_ERR, /*!< Send FIFO errors */ + RTNL_LINK_RX_LEN_ERR, /*!< Length errors */ + RTNL_LINK_RX_OVER_ERR, /*!< Over errors */ + RTNL_LINK_RX_CRC_ERR, /*!< CRC errors */ + RTNL_LINK_RX_FRAME_ERR, /*!< Frame errors */ + RTNL_LINK_RX_MISSED_ERR, /*!< Missed errors */ + RTNL_LINK_TX_ABORT_ERR, /*!< Aborted errors */ + RTNL_LINK_TX_CARRIER_ERR, /*!< Carrier errors */ + RTNL_LINK_TX_HBEAT_ERR, /*!< Heartbeat errors */ + RTNL_LINK_TX_WIN_ERR, /*!< Window errors */ + RTNL_LINK_COLLISIONS, /*!< Send collisions */ + RTNL_LINK_MULTICAST, /*!< Multicast */ + RTNL_LINK_IP6_INPKTS, /*!< IPv6 SNMP InReceives */ + RTNL_LINK_IP6_INHDRERRORS, /*!< IPv6 SNMP InHdrErrors */ + RTNL_LINK_IP6_INTOOBIGERRORS, /*!< IPv6 SNMP InTooBigErrors */ + RTNL_LINK_IP6_INNOROUTES, /*!< IPv6 SNMP InNoRoutes */ + RTNL_LINK_IP6_INADDRERRORS, /*!< IPv6 SNMP InAddrErrors */ + RTNL_LINK_IP6_INUNKNOWNPROTOS, /*!< IPv6 SNMP InUnknownProtos */ + RTNL_LINK_IP6_INTRUNCATEDPKTS, /*!< IPv6 SNMP InTruncatedPkts */ + RTNL_LINK_IP6_INDISCARDS, /*!< IPv6 SNMP InDiscards */ + RTNL_LINK_IP6_INDELIVERS, /*!< IPv6 SNMP InDelivers */ + RTNL_LINK_IP6_OUTFORWDATAGRAMS, /*!< IPv6 SNMP OutForwDatagrams */ + RTNL_LINK_IP6_OUTPKTS, /*!< IPv6 SNMP OutRequests */ + RTNL_LINK_IP6_OUTDISCARDS, /*!< IPv6 SNMP OutDiscards */ + RTNL_LINK_IP6_OUTNOROUTES, /*!< IPv6 SNMP OutNoRoutes */ + RTNL_LINK_IP6_REASMTIMEOUT, /*!< IPv6 SNMP ReasmTimeout */ + RTNL_LINK_IP6_REASMREQDS, /*!< IPv6 SNMP ReasmReqds */ + RTNL_LINK_IP6_REASMOKS, /*!< IPv6 SNMP ReasmOKs */ + RTNL_LINK_IP6_REASMFAILS, /*!< IPv6 SNMP ReasmFails */ + RTNL_LINK_IP6_FRAGOKS, /*!< IPv6 SNMP FragOKs */ + RTNL_LINK_IP6_FRAGFAILS, /*!< IPv6 SNMP FragFails */ + RTNL_LINK_IP6_FRAGCREATES, /*!< IPv6 SNMP FragCreates */ + RTNL_LINK_IP6_INMCASTPKTS, /*!< IPv6 SNMP InMcastPkts */ + RTNL_LINK_IP6_OUTMCASTPKTS, /*!< IPv6 SNMP OutMcastPkts */ + RTNL_LINK_IP6_INBCASTPKTS, /*!< IPv6 SNMP InBcastPkts */ + RTNL_LINK_IP6_OUTBCASTPKTS, /*!< IPv6 SNMP OutBcastPkts */ + RTNL_LINK_IP6_INOCTETS, /*!< IPv6 SNMP InOctets */ + RTNL_LINK_IP6_OUTOCTETS, /*!< IPv6 SNMP OutOctets */ + RTNL_LINK_IP6_INMCASTOCTETS, /*!< IPv6 SNMP InMcastOctets */ + RTNL_LINK_IP6_OUTMCASTOCTETS, /*!< IPv6 SNMP OutMcastOctets */ + RTNL_LINK_IP6_INBCASTOCTETS, /*!< IPv6 SNMP InBcastOctets */ + RTNL_LINK_IP6_OUTBCASTOCTETS, /*!< IPv6 SNMP OutBcastOctets */ + RTNL_LINK_ICMP6_INMSGS, /*!< ICMPv6 SNMP InMsgs */ + RTNL_LINK_ICMP6_INERRORS, /*!< ICMPv6 SNMP InErrors */ + RTNL_LINK_ICMP6_OUTMSGS, /*!< ICMPv6 SNMP OutMsgs */ + RTNL_LINK_ICMP6_OUTERRORS, /*!< ICMPv6 SNMP OutErrors */ __RTNL_LINK_STATS_MAX, -}; +} rtnl_link_stat_id_t; #define RTNL_LINK_STATS_MAX (__RTNL_LINK_STATS_MAX - 1) -/* link object allocation/freeage */ extern struct rtnl_link *rtnl_link_alloc(void); extern void rtnl_link_put(struct rtnl_link *); extern void rtnl_link_free(struct rtnl_link *); -/* link cache management */ extern int rtnl_link_alloc_cache(struct nl_sock *, int, struct nl_cache **); extern struct rtnl_link *rtnl_link_get(struct nl_cache *, int); extern struct rtnl_link *rtnl_link_get_by_name(struct nl_cache *, const char *); @@ -149,9 +158,6 @@ extern unsigned int rtnl_link_get_mtu(struct rtnl_link *); extern void rtnl_link_set_txqlen(struct rtnl_link *, unsigned int); extern unsigned int rtnl_link_get_txqlen(struct rtnl_link *); -extern void rtnl_link_set_weight(struct rtnl_link *, unsigned int); -extern unsigned int rtnl_link_get_weight(struct rtnl_link *); - extern void rtnl_link_set_ifindex(struct rtnl_link *, int); extern int rtnl_link_get_ifindex(struct rtnl_link *); @@ -184,15 +190,19 @@ extern void rtnl_link_set_ifalias(struct rtnl_link *, const char *); extern int rtnl_link_get_num_vf(struct rtnl_link *, uint32_t *); -extern uint64_t rtnl_link_get_stat(struct rtnl_link *, int); -extern int rtnl_link_set_stat(struct rtnl_link *, const unsigned int, +extern uint64_t rtnl_link_get_stat(struct rtnl_link *, rtnl_link_stat_id_t); +extern int rtnl_link_set_stat(struct rtnl_link *, rtnl_link_stat_id_t, const uint64_t); extern int rtnl_link_set_type(struct rtnl_link *, const char *); extern char * rtnl_link_get_type(struct rtnl_link *); +/* deprecated */ extern int rtnl_link_set_info_type(struct rtnl_link *, const char *) __attribute__((deprecated)); extern char * rtnl_link_get_info_type(struct rtnl_link *) __attribute__((deprecated)); +extern void rtnl_link_set_weight(struct rtnl_link *, unsigned int) __attribute__((deprecated)); +extern unsigned int rtnl_link_get_weight(struct rtnl_link *) __attribute__((deprecated)); + #ifdef __cplusplus } diff --git a/lib/fib_lookup/lookup.c b/lib/fib_lookup/lookup.c index 61984c7..6018251 100644 --- a/lib/fib_lookup/lookup.c +++ b/lib/fib_lookup/lookup.c @@ -203,8 +203,6 @@ struct nl_cache *flnl_result_alloc_cache(void) * \c rtnl_link_set_* functions. * * @return 0 on success or a negative error code. - * @note Not all attributes can be changed, see - * \ref link_changeable "Changeable Attributes" for more details. */ int flnl_lookup_build_request(struct flnl_request *req, int flags, struct nl_msg **result) diff --git a/lib/route/link.c b/lib/route/link.c index 6268886..4932722 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -6,144 +6,15 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2010 Thomas Graf + * Copyright (c) 2003-2011 Thomas Graf */ /** * @ingroup rtnl * @defgroup link Links (Interfaces) - * @brief * - * @par Link Identification - * A link can be identified by either its interface index or by its - * name. The kernel favours the interface index but falls back to the - * interface name if the interface index is lesser-than 0 for kernels - * >= 2.6.11. Therefore you can request changes without mapping a - * interface name to the corresponding index first. - * - * @par Changeable Attributes - * @anchor link_changeable - * - Link layer address - * - Link layer broadcast address - * - device mapping (ifmap) (>= 2.6.9) - * - MTU (>= 2.6.9) - * - Transmission queue length (>= 2.6.9) - * - Weight (>= 2.6.9) - * - Link name (only via access through interface index) (>= 2.6.9) - * - Flags (>= 2.6.9) - * - IFF_DEBUG - * - IFF_NOTRAILERS - * - IFF_NOARP - * - IFF_DYNAMIC - * - IFF_MULTICAST - * - IFF_PORTSEL - * - IFF_AUTOMEDIA - * - IFF_UP - * - IFF_PROMISC - * - IFF_ALLMULTI - * - * @par Link Flags (linux/if.h) - * @anchor link_flags - * @code - * IFF_UP Status of link (up|down) - * IFF_BROADCAST Indicates this link allows broadcasting - * IFF_MULTICAST Indicates this link allows multicasting - * IFF_ALLMULTI Indicates this link is doing multicast routing - * IFF_DEBUG Tell the driver to do debugging (currently unused) - * IFF_LOOPBACK This is the loopback link - * IFF_POINTOPOINT Point-to-point link - * IFF_NOARP Link is unable to perform ARP - * IFF_PROMISC Status of promiscious mode flag - * IFF_MASTER Used by teql - * IFF_SLAVE Used by teql - * IFF_PORTSEL Indicates this link allows port selection - * IFF_AUTOMEDIA Indicates this link selects port automatically - * IFF_DYNAMIC Indicates the address of this link is dynamic - * IFF_RUNNING Link is running and carrier is ok. - * IFF_NOTRAILERS Unused, BSD compat. - * @endcode - * - * @par Notes on IFF_PROMISC and IFF_ALLMULTI flags - * Although you can query the status of IFF_PROMISC and IFF_ALLMULTI - * they do not represent the actual state in the kernel but rather - * whether the flag has been enabled/disabled by userspace. The link - * may be in promiscious mode even if IFF_PROMISC is not set in a link - * dump request response because promiscity might be needed by the driver - * for a period of time. - * - * @note The unit of the transmission queue length depends on the - * link type, a common unit is \a packets. - * - * @par 1) Retrieving information about available links - * @code - * // The first step is to retrieve a list of all available interfaces within - * // the kernel and put them into a cache. - * struct nl_cache *cache = rtnl_link_alloc_cache(sk); - * - * // In a second step, a specific link may be looked up by either interface - * // index or interface name. - * struct rtnl_link *link = rtnl_link_get_by_name(cache, "lo"); - * - * // rtnl_link_get_by_name() is the short version for translating the - * // interface name to an interface index first like this: - * int ifindex = rtnl_link_name2i(cache, "lo"); - * struct rtnl_link *link = rtnl_link_get(cache, ifindex); - * - * // After successful usage, the object must be given back to the cache - * rtnl_link_put(link); - * @endcode - * - * @par 2) Changing link attributes - * @code - * // In order to change any attributes of an existing link, we must allocate - * // a new link to hold the change requests: - * struct rtnl_link *request = rtnl_link_alloc(); - * - * // Now we can go on and specify the attributes we want to change: - * rtnl_link_set_weight(request, 300); - * rtnl_link_set_mtu(request, 1360); - * - * // We can also shut an interface down administratively - * rtnl_link_unset_flags(request, rtnl_link_str2flags("up")); - * - * // Actually, we should know which link to change, so let's look it up - * struct rtnl_link *old = rtnl_link_get(cache, "eth0"); - * - * // Two ways exist to commit this change request, the first one is to - * // build the required netlink message and send it out in one single - * // step: - * rtnl_link_change(sk, old, request, 0); - * - * // An alternative way is to build the netlink message and send it - * // out yourself using nl_send_auto_complete() - * struct nl_msg *msg = rtnl_link_build_change_request(old, request); - * nl_send_auto_complete(sk, nlmsg_hdr(msg)); - * nlmsg_free(msg); - * - * // Don't forget to give back the link object ;-> - * rtnl_link_put(old); - * @endcode - * - * @par 3) Link Type Specific Attributes - * @code - * // Some link types offer additional parameters and statistics specific - * // to their type. F.e. a VLAN link can be configured like this: - * // - * // Allocate a new link and set the info type to "vlan". This is required - * // to prepare the link to hold vlan specific attributes. - * struct rtnl_link *request = rtnl_link_alloc(); - * rtnl_link_set_info_type(request, "vlan"); - * - * // Now vlan specific attributes can be set: - * rtnl_link_vlan_set_id(request, 10); - * rtnl_link_vlan_set_ingress_map(request, 2, 8); - * - * // Of course the attributes can also be read, check the info type - * // to make sure you are using the right access functions: - * char *type = rtnl_link_get_info_type(link); - * if (!strcmp(type, "vlan")) - * int id = rtnl_link_vlan_get_id(link); - * @endcode + * @details + * @route_doc{route_link, Link Documentation} * @{ */ @@ -918,24 +789,7 @@ static char *link_attrs2str(int attrs, char *buf, size_t len) } /** - * @name Allocation/Freeing - * @{ - */ - -struct rtnl_link *rtnl_link_alloc(void) -{ - return (struct rtnl_link *) nl_object_alloc(&link_obj_ops); -} - -void rtnl_link_put(struct rtnl_link *link) -{ - nl_object_put((struct nl_object *) link); -} - -/** @} */ - -/** - * @name Cache Management + * @name Get / List * @{ */ @@ -946,9 +800,21 @@ void rtnl_link_put(struct rtnl_link *link) * @arg family Link address family or AF_UNSPEC * @arg result Pointer to store resulting cache. * - * Allocates a new link cache, initializes it properly and updates it - * to include all links currently configured in the kernel. + * Allocates and initializes a new link cache. A netlink message is sent to + * the kernel requesting a full dump of all configured links. The returned + * messages are parsed and filled into the cache. If the operation succeeds + * the resulting cache will a link object for each link configured in the + * kernel. * + * If \c family is set to an address family other than \c AF_UNSPEC the + * contents of the cache can be limited to a specific address family. + * Currently the following address families are supported: + * - AF_BRIDGE + * - AF_INET6 + * + * @route_doc{link_list, Get List of Links} + * @see rtnl_link_get() + * @see rtnl_link_get_by_name() * @return 0 on success or a negative error code. */ int rtnl_link_alloc_cache(struct nl_sock *sk, int family, struct nl_cache **result) @@ -972,14 +838,19 @@ int rtnl_link_alloc_cache(struct nl_sock *sk, int family, struct nl_cache **resu } /** - * Look up link by interface index in the provided cache - * @arg cache link cache - * @arg ifindex link interface index + * Lookup link in cache by interface index + * @arg cache Link cache + * @arg ifindex Interface index * - * The caller owns a reference on the returned object and - * must give the object back via rtnl_link_put(). + * Searches through the provided cache looking for a link with matching + * interface index. * - * @return pointer to link inside the cache or NULL if no match was found. + * @attention The reference counter of the returned link object will be + * incremented. Use rtnl_link_put() to release the reference. + * + * @route_doc{link_list, Get List of Links} + * @see rtnl_link_get_by_name() + * @return Link object or NULL if no match was found. */ struct rtnl_link *rtnl_link_get(struct nl_cache *cache, int ifindex) { @@ -999,14 +870,19 @@ struct rtnl_link *rtnl_link_get(struct nl_cache *cache, int ifindex) } /** - * Look up link by link name in the provided cache - * @arg cache link cache - * @arg name link name + * Lookup link in cache by link name + * @arg cache Link cache + * @arg name Name of link * - * The caller owns a reference on the returned object and - * must give the object back via rtnl_link_put(). + * Searches through the provided cache looking for a link with matching + * link name * - * @return pointer to link inside the cache or NULL if no match was found. + * @attention The reference counter of the returned link object will be + * incremented. Use rtnl_link_put() to release the reference. + * + * @route_doc{link_list, Get List of Links} + * @see rtnl_link_get() + * @return Link object or NULL if no match was found. */ struct rtnl_link *rtnl_link_get_by_name(struct nl_cache *cache, const char *name) @@ -1026,12 +902,145 @@ struct rtnl_link *rtnl_link_get_by_name(struct nl_cache *cache, return NULL; } -/** @} */ +/** + * Construct RTM_GETLINK netlink message + * @arg ifindex Interface index + * @arg name Name of link + * @arg result Pointer to store resulting netlink message + * + * The behaviour of this function is identical to rtnl_link_get_kernel() + * with the exception that it will not send the message but return it in + * the provided return pointer instead. + * + * @see rtnl_link_get_kernel() + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_build_get_request(int ifindex, const char *name, + struct nl_msg **result) +{ + struct ifinfomsg ifi; + struct nl_msg *msg; + + if (ifindex <= 0 && !name) { + APPBUG("ifindex or name must be specified"); + return -NLE_MISSING_ATTR; + } + + memset(&ifi, 0, sizeof(ifi)); + + if (!(msg = nlmsg_alloc_simple(RTM_GETLINK, 0))) + return -NLE_NOMEM; + + if (ifindex > 0) + ifi.ifi_index = ifindex; + + if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0) + goto nla_put_failure; + + if (name) + NLA_PUT_STRING(msg, IFLA_IFNAME, name); + + *result = msg; + return 0; + +nla_put_failure: + nlmsg_free(msg); + return -NLE_MSGSIZE; +} /** - * @name Link Modifications - * @{ + * Get a link object directly from kernel + * @arg sk Netlink socket + * @arg ifindex Interface index + * @arg name Name of link + * @arg result Pointer to store resulting link object + * + * This function builds a \c RTM_GETLINK netlink message to request + * a specific link directly from the kernel. The returned answer is + * parsed into a struct rtnl_link object and returned via the result + * pointer or -NLE_OBJ_NOTFOUND is returned if no matching link was + * found. + * + * @route_doc{link_direct_lookup, Lookup Single Link (Direct Lookup)} + * @return 0 on success or a negative error code. */ +int rtnl_link_get_kernel(struct nl_sock *sk, int ifindex, const char *name, + struct rtnl_link **result) +{ + struct nl_msg *msg = NULL; + struct nl_object *obj; + int err; + + if ((err = rtnl_link_build_get_request(ifindex, name, &msg)) < 0) + return err; + + err = nl_send_auto(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + if ((err = nl_pickup(sk, link_msg_parser, &obj)) < 0) + return err; + + /* We have used link_msg_parser(), object is definitely a link */ + *result = (struct rtnl_link *) obj; + + return 0; +} + +/** + * Translate interface index to corresponding link name + * @arg cache Link cache + * @arg ifindex Interface index + * @arg dst String to store name + * @arg len Length of destination string + * + * Translates the specified interface index to the corresponding + * link name and stores the name in the destination string. + * + * @route_doc{link_translate_ifindex, Translating interface index to link name} + * @see rtnl_link_name2i() + * @return Name of link or NULL if no match was found. + */ +char * rtnl_link_i2name(struct nl_cache *cache, int ifindex, char *dst, + size_t len) +{ + struct rtnl_link *link = rtnl_link_get(cache, ifindex); + + if (link) { + strncpy(dst, link->l_name, len - 1); + rtnl_link_put(link); + return dst; + } + + return NULL; +} + +/** + * Translate link name to corresponding interface index + * @arg cache Link cache + * @arg name Name of link + * + * @route_doc{link_translate_ifindex, Translating interface index to link name} + * @see rtnl_link_i2name() + * @return Interface index or 0 if no match was found. + */ +int rtnl_link_name2i(struct nl_cache *cache, const char *name) +{ + int ifindex = 0; + struct rtnl_link *link; + + link = rtnl_link_get_by_name(cache, name); + if (link) { + ifindex = link->l_index; + rtnl_link_put(link); + } + + return ifindex; +} + +/** @} */ static int build_link_msg(int cmd, struct ifinfomsg *hdr, struct rtnl_link *link, int flags, struct nl_msg **result) @@ -1108,7 +1117,12 @@ nla_put_failure: } /** - * Build a netlink message requesting the addition of a new virtual link + * @name Add / Modify + * @{ + */ + +/** + * Build a netlink message requesting the addition of new virtual link * @arg link new link to add * @arg flags additional netlink message flags * @arg result pointer to store resulting netlink message @@ -1148,10 +1162,7 @@ int rtnl_link_build_add_request(struct rtnl_link *link, int flags, * error message to be received and will therefore block until the * operation has been completed. * - * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause - * this function to return immediately after sending. In this case, - * it is the responsibility of the caller to handle any error - * messages returned. + * @copydoc auto_ack_warning * * @return 0 on success or a negative error code. */ @@ -1164,16 +1175,11 @@ int rtnl_link_add(struct nl_sock *sk, struct rtnl_link *link, int flags) if (err < 0) return err; - err = nl_send_auto_complete(sk, msg); - nlmsg_free(msg); - if (err < 0) - return err; - - return wait_for_ack(sk); + return nl_send_sync(sk, msg); } /** - * Build a netlink message requesting the modification of a link + * Build a netlink message requesting the modification of link * @arg orig original link to change * @arg changes link containing the changes to be made * @arg flags additional netlink message flags @@ -1252,10 +1258,7 @@ errout: * error message to be received and will therefore block until the * operation has been completed. * - * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause - * this function to return immediately after sending. In this case, - * it is the responsibility of the caller to handle any error - * messages returned. + * @copydoc auto_ack_warning * * @note The link name can only be changed if the link has been put * in opertional down state. (~IF_UP) @@ -1288,6 +1291,13 @@ errout: return err; } +/** @} */ + +/** + * @name Delete + * @{ + */ + /** * Build a netlink message requesting the deletion of a link * @arg link Link to delete @@ -1347,10 +1357,7 @@ nla_put_failure: * error message to be received and will therefore block until the * operation has been completed. * - * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause - * this function to return immediately after sending. In this case, - * it is the responsibility of the caller to handle any error - * messages returned. + * @copydoc auto_ack_warning * * @note Only virtual links such as dummy interface or vlan interfaces * can be deleted. It is not possible to delete physical interfaces @@ -1369,156 +1376,584 @@ int rtnl_link_delete(struct nl_sock *sk, const struct rtnl_link *link) return nl_send_sync(sk, msg); } - -/** - * Build a netlink message requesting a link - * @arg ifindex Interface index - * @arg name Name of link - * @arg result Pointer to store resulting netlink message - * - * The behaviour of this function is identical to rtnl_link_get_kernel() - * with the exception that it will not send the message but return it in - * the provided return pointer instead. - * - * @see rtnl_link_get_kernel() - * - * @return 0 on success or a negative error code. - */ -int rtnl_link_build_get_request(int ifindex, const char *name, - struct nl_msg **result) -{ - struct ifinfomsg ifi; - struct nl_msg *msg; - - if (ifindex <= 0 && !name) { - APPBUG("ifindex or name must be specified"); - return -NLE_MISSING_ATTR; - } - - memset(&ifi, 0, sizeof(ifi)); - - if (!(msg = nlmsg_alloc_simple(RTM_GETLINK, 0))) - return -NLE_NOMEM; - - if (ifindex > 0) - ifi.ifi_index = ifindex; - - if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0) - goto nla_put_failure; - - if (name) - NLA_PUT_STRING(msg, IFLA_IFNAME, name); - - *result = msg; - return 0; - -nla_put_failure: - nlmsg_free(msg); - return -NLE_MSGSIZE; -} - -/** - * Get a link object directly from the kernel - * @arg sk Netlink socket - * @arg ifindex Interface index - * @arg name name of link - * @arg result result pointer to return link object - * - * This function builds a \c RTM_GETLINK netlink message to request - * a specific link directly from the kernel. The returned answer is - * parsed into a struct rtnl_link object and returned via the result - * pointer or -NLE_OBJ_NOTFOUND is returned if no matching link was - * found. - * - * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause - * this function to return immediately after sending. In this case, - * it is the responsibility of the caller to handle any error - * messages returned. - * - * @return 0 on success or a negative error code. - */ -int rtnl_link_get_kernel(struct nl_sock *sk, int ifindex, const char *name, - struct rtnl_link **result) -{ - struct nl_msg *msg = NULL; - struct nl_object *obj; - int err; - - if ((err = rtnl_link_build_get_request(ifindex, name, &msg)) < 0) - return err; - - err = nl_send_auto(sk, msg); - nlmsg_free(msg); - if (err < 0) - return err; - - if ((err = nl_pickup(sk, link_msg_parser, &obj)) < 0) - return err; - - /* We have used link_msg_parser(), object is definitely a link */ - *result = (struct rtnl_link *) obj; - - return 0; -} - /** @} */ /** - * @name Name <-> Index Translations + * @name Link Object * @{ */ /** - * Translate an interface index to the corresponding link name - * @arg cache link cache - * @arg ifindex link interface index - * @arg dst destination buffer - * @arg len length of destination buffer + * Allocate link object * - * Translates the specified interface index to the corresponding - * link name and stores the name in the destination buffer. - * - * @return link name or NULL if no match was found. + * @see rtnl_link_put() + * @return New link object or NULL if allocation failed */ -char * rtnl_link_i2name(struct nl_cache *cache, int ifindex, char *dst, - size_t len) +struct rtnl_link *rtnl_link_alloc(void) { - struct rtnl_link *link = rtnl_link_get(cache, ifindex); - - if (link) { - strncpy(dst, link->l_name, len - 1); - rtnl_link_put(link); - return dst; - } - - return NULL; + return (struct rtnl_link *) nl_object_alloc(&link_obj_ops); } /** - * Translate a link name to the corresponding interface index - * @arg cache link cache - * @arg name link name + * Return a link object reference * - * @return interface index or 0 if no match was found. + * @copydetails nl_object_put() */ -int rtnl_link_name2i(struct nl_cache *cache, const char *name) +void rtnl_link_put(struct rtnl_link *link) { - int ifindex = 0; - struct rtnl_link *link; - - link = rtnl_link_get_by_name(cache, name); - if (link) { - ifindex = link->l_index; - rtnl_link_put(link); - } + nl_object_put((struct nl_object *) link); +} - return ifindex; +/** + * Set name of link object + * @arg link Link object + * @arg name New name + * + * @note To change the name of a link in the kernel, set the interface + * index to the link you wish to change, modify the link name using + * this function and pass the link object to rtnl_link_change() or + * rtnl_link_add(). + * + * @route_doc{link_attr_name, Link Name} + * @see rtnl_link_get_name() + * @see rtnl_link_set_ifindex() + */ +void rtnl_link_set_name(struct rtnl_link *link, const char *name) +{ + strncpy(link->l_name, name, sizeof(link->l_name) - 1); + link->ce_mask |= LINK_ATTR_IFNAME; +} + +/** + * Return name of link object + * @arg link Link object + * + * @route_doc{link_attr_name, Link Name} + * @see rtnl_link_set_name() + * @return Link name or NULL if name is not specified + */ +char *rtnl_link_get_name(struct rtnl_link *link) +{ + return link->ce_mask & LINK_ATTR_IFNAME ? link->l_name : NULL; +} + +static inline void __assign_addr(struct rtnl_link *link, struct nl_addr **pos, + struct nl_addr *new, int flag) +{ + if (*pos) + nl_addr_put(*pos); + + nl_addr_get(new); + *pos = new; + + link->ce_mask |= flag; +} + +/** + * Set link layer address of link object + * @arg link Link object + * @arg addr New link layer address + * + * The function increments the reference counter of the address object + * and overwrites any existing link layer address previously assigned. + * + * @route_doc{link_attr_address, Link layer address} + * @see rtnl_link_get_addr() + */ +void rtnl_link_set_addr(struct rtnl_link *link, struct nl_addr *addr) +{ + __assign_addr(link, &link->l_addr, addr, LINK_ATTR_ADDR); +} + +/** + * Return link layer address of link object + * @arg link Link object + * + * @copydoc pointer_lifetime_warning + * @route_doc{link_attr_address, Link Layer Address} + * @see rtnl_link_set_addr() + * @return Link layer address or NULL if not set. + */ +struct nl_addr *rtnl_link_get_addr(struct rtnl_link *link) +{ + return link->ce_mask & LINK_ATTR_ADDR ? link->l_addr : NULL; +} + +/** + * Set link layer broadcast address of link object + * @arg link Link object + * @arg addr New broadcast address + * + * The function increments the reference counter of the address object + * and overwrites any existing link layer broadcast address previously + * assigned. + * + * @route_doc{link_attr_broadcast, Link Layer Broadcast Address} + * @see rtnl_link_get_broadcast() + */ +void rtnl_link_set_broadcast(struct rtnl_link *link, struct nl_addr *addr) +{ + __assign_addr(link, &link->l_bcast, addr, LINK_ATTR_BRD); +} + +/** + * Return link layer broadcast address of link object + * @arg link Link object + * + * @copydoc pointer_lifetime_warning + * @route_doc{link_attr_address, Link Layer Address} + * @see rtnl_link_set_broadcast() + * @return Link layer address or NULL if not set. + */ +struct nl_addr *rtnl_link_get_broadcast(struct rtnl_link *link) +{ + return link->ce_mask & LINK_ATTR_BRD ? link->l_bcast : NULL; +} + +/** + * Set flags of link object + * @arg link Link object + * @arg flags Flags + * + * @see rtnl_link_get_flags() + * @see rtnl_link_unset_flags() + */ +void rtnl_link_set_flags(struct rtnl_link *link, unsigned int flags) +{ + link->l_flag_mask |= flags; + link->l_flags |= flags; + link->ce_mask |= LINK_ATTR_FLAGS; +} + +/** + * Unset flags of link object + * @arg link Link object + * @arg flags Flags + * + * @see rtnl_link_set_flags() + * @see rtnl_link_get_flags() + */ +void rtnl_link_unset_flags(struct rtnl_link *link, unsigned int flags) +{ + link->l_flag_mask |= flags; + link->l_flags &= ~flags; + link->ce_mask |= LINK_ATTR_FLAGS; +} + +/** + * Return flags of link object + * @arg link Link object + * + * @route_doc{link_attr_flags, Link Flags} + * @see rtnl_link_set_flags() + * @see rtnl_link_unset_flags() + * @return Link flags or 0 if none have been set. + */ +unsigned int rtnl_link_get_flags(struct rtnl_link *link) +{ + return link->l_flags; +} + +/** + * Set address family of link object + * + * @see rtnl_link_get_family() + */ +void rtnl_link_set_family(struct rtnl_link *link, int family) +{ + link->l_family = family; + link->ce_mask |= LINK_ATTR_FAMILY; +} + +/** + * Return address family of link object + * @arg link Link object + * + * @see rtnl_link_set_family() + * @return Address family or \c AF_UNSPEC if not specified. + */ +int rtnl_link_get_family(struct rtnl_link *link) +{ + return link->ce_mask & LINK_ATTR_FAMILY ? link->l_family : AF_UNSPEC; +} + +/** + * Set hardware type of link object + * @arg link Link object + * @arg arptype New hardware type \c (ARPHRD_*) + * + * @route_doc{link_attr_arptype, Hardware Type} + * @copydoc read_only_attribute + * @see rtnl_link_get_arptype() + */ +void rtnl_link_set_arptype(struct rtnl_link *link, unsigned int arptype) +{ + link->l_arptype = arptype; + link->ce_mask |= LINK_ATTR_ARPTYPE; +} + +/** + * Get hardware type of link object + * @arg link Link object + * + * @route_doc{link_attr_arptype, Hardware Type} + * @see rtnl_link_set_arptype() + * @return Hardware type \c (ARPHRD_ETHER *) or \c ARPHRD_VOID + */ +unsigned int rtnl_link_get_arptype(struct rtnl_link *link) +{ + if (link->ce_mask & LINK_ATTR_ARPTYPE) + return link->l_arptype; + else + return ARPHRD_VOID; +} + +/** + * Set interface index of link object + * @arg link Link object + * @arg ifindex Interface index + * + * @route_doc{link_attr_ifindex, Interface Index} + * @see rtnl_link_get_ifindex() + */ +void rtnl_link_set_ifindex(struct rtnl_link *link, int ifindex) +{ + link->l_index = ifindex; + link->ce_mask |= LINK_ATTR_IFINDEX; +} + + +/** + * Return interface index of link object + * @arg link Link object + * + * @route_doc{link_attr_ifindex, Interface Index} + * @see rtnl_link_set_ifindex() + * @return Interface index or 0 if not set. + */ +int rtnl_link_get_ifindex(struct rtnl_link *link) +{ + return link->l_index; +} + +/** + * Set Maximum Transmission Unit of link object + * @arg link Link object + * @arg mtu New MTU value in number of bytes + * + * @route_doc{link_attr_mtu, Maximum Transmission Unit} + * @see rtnl_link_get_mtu() + */ +void rtnl_link_set_mtu(struct rtnl_link *link, unsigned int mtu) +{ + link->l_mtu = mtu; + link->ce_mask |= LINK_ATTR_MTU; +} + +/** + * Return maximum transmission unit of link object + * @arg link Link object + * + * @route_doc{link_attr_mtu, Maximum Transmission Unit} + * @see rtnl_link_set_mtu() + * @return MTU in bytes or 0 if not set + */ +unsigned int rtnl_link_get_mtu(struct rtnl_link *link) +{ + return link->l_mtu; +} + +/** + * Set transmission queue length + * @arg link Link object + * @arg txqlen New queue length + * + * The unit is dependant on the link type. The most common units is number + * of packets. + * + * @route_doc{link_attr_txqlen, Transmission Queue Length} + */ +void rtnl_link_set_txqlen(struct rtnl_link *link, unsigned int txqlen) +{ + link->l_txqlen = txqlen; + link->ce_mask |= LINK_ATTR_TXQLEN; +} + +/** + * Return transmission queue length + * @arg link Link object + * + * The unit is dependant on the link type. The most common units is number + * of packets. + * + * @route_doc{link_attr_txqlen, Transmission Queue Length} + * @return queue length or 0 if not specified. + */ +unsigned int rtnl_link_get_txqlen(struct rtnl_link *link) +{ + return link->ce_mask & LINK_ATTR_TXQLEN ? link->l_txqlen : 0; +} + +void rtnl_link_set_link(struct rtnl_link *link, int ifindex) +{ + link->l_link = ifindex; + link->ce_mask |= LINK_ATTR_LINK; +} + +int rtnl_link_get_link(struct rtnl_link *link) +{ + return link->l_link; +} + +/** + * Set master link of link object + * @arg link Link object + * @arg ifindex Interface index of master link + * + * @see rtnl_link_get_master() + */ +void rtnl_link_set_master(struct rtnl_link *link, int ifindex) +{ + link->l_master = ifindex; + link->ce_mask |= LINK_ATTR_MASTER; +} + +/** + * Return master link of link object + * @arg link Link object + * + * @see rtnl_link_set_master() + * @return Interface index of master link or 0 if not specified + */ +int rtnl_link_get_master(struct rtnl_link *link) +{ + return link->l_master; +} + +/** + * Set operational status of link object + * @arg link Link object + * @arg status New opertional status + * + * @route_doc{link_attr_operstate, Operational Status}} + * @see rtnl_link_get_operstate() + */ +void rtnl_link_set_operstate(struct rtnl_link *link, uint8_t status) +{ + link->l_operstate = status; + link->ce_mask |= LINK_ATTR_OPERSTATE; +} + +/** + * Return operational status of link object + * @arg link Link object + * + * @route_doc{link_attr_operstate, Operational Status} + * @see rtnl_link_set_operstate() + * @return Opertional state or \c IF_OPER_UNKNOWN + */ +uint8_t rtnl_link_get_operstate(struct rtnl_link *link) +{ + return link->l_operstate; +} + +/** + * Set link mode of link object + * @arg link Link object + * @arg mode New link mode + * + * @route_doc{link_attr_mode, Mode} + * @see rtnl_link_get_linkmode() + */ +void rtnl_link_set_linkmode(struct rtnl_link *link, uint8_t mode) +{ + link->l_linkmode = mode; + link->ce_mask |= LINK_ATTR_LINKMODE; +} + +/** + * Return link mode of link object + * @arg link Link object + * + * @route_doc{link_attr_mode, Mode} + * @see rtnl_link_get_linkmode() + * @return Link mode or \c IF_LINK_MODE_DEFAULT + */ +uint8_t rtnl_link_get_linkmode(struct rtnl_link *link) +{ + return link->l_linkmode; +} + +/** + * Return alias name of link object (SNMP IfAlias) + * @arg link Link object + * + * @route_doc{link_attr_alias, Alias} + * @see rtnl_link_set_ifalias() + * @return Alias name or NULL if not set. + */ +const char *rtnl_link_get_ifalias(struct rtnl_link *link) +{ + return link->l_ifalias; +} + +/** + * Set alias name of link object (SNMP IfAlias) + * @arg link Link object + * @arg alias Alias name or NULL to unset + * + * Sets the alias name of the link to the specified name. The alias + * name can be unset by specyfing NULL as the alias. The name will + * be strdup()ed, so no need to provide a persistent character string. + * + * @route_doc{link_attr_alias, Alias} + * @see rtnl_link_get_ifalias() + */ +void rtnl_link_set_ifalias(struct rtnl_link *link, const char *alias) +{ + free(link->l_ifalias); + link->ce_mask &= ~LINK_ATTR_IFALIAS; + + if (alias) { + link->l_ifalias = strdup(alias); + link->ce_mask |= LINK_ATTR_IFALIAS; + } +} + +/** + * Set queueing discipline name of link object + * @arg link Link object + * @arg name Name of queueing discipline + * + * @copydoc read_only_attribute + * + * For more information on how to modify the qdisc of a link, see section + * @ref_route{route_tc, Traffic Control}. + * + * @route_doc{link_attr_qdisc, Queueing Discipline Name} + * @see rtnl_link_get_qdisc() + */ +void rtnl_link_set_qdisc(struct rtnl_link *link, const char *name) +{ + strncpy(link->l_qdisc, name, sizeof(link->l_qdisc) - 1); + link->ce_mask |= LINK_ATTR_QDISC; +} + +/** + * Return name of queueing discipline of link object + * @arg link Link object + * + * @route_doc{link_attr_qdisc, Queueing Discipline Name} + * @see rtnl_link_set_qdisc() + * @return Name of qdisc or NULL if not specified. + */ +char *rtnl_link_get_qdisc(struct rtnl_link *link) +{ + return link->ce_mask & LINK_ATTR_QDISC ? link->l_qdisc : NULL; +} + + +/** + * Return number of PCI virtual functions of link object + * @arg link Link object + * @arg num_vf Pointer to store number of VFs + * + * @return 0 on success or -NLE_OPNOTSUPP if not available + */ +int rtnl_link_get_num_vf(struct rtnl_link *link, uint32_t *num_vf) +{ + if (link->ce_mask & LINK_ATTR_NUM_VF) { + *num_vf = link->l_num_vf; + return 0; + } else + return -NLE_OPNOTSUPP; +} + +/** + * Return value of link statistics counter + * @arg link Link object + * @arg id Identifier of statistical counter + * + * @return Value of counter or 0 if not specified. + */ +uint64_t rtnl_link_get_stat(struct rtnl_link *link, rtnl_link_stat_id_t id) +{ + if (id > RTNL_LINK_STATS_MAX) + return 0; + + return link->l_stats[id]; +} + +/** + * Set value of link statistics counter + * @arg link Link object + * @arg id Identifier of statistical counter + * @arg value New value + * + * \note Changing the value of a statistical counter will not change the + * value in the kernel. + * + * @return 0 on success or a negative error code + */ +int rtnl_link_set_stat(struct rtnl_link *link, rtnl_link_stat_id_t id, + const uint64_t value) +{ + if (id > RTNL_LINK_STATS_MAX) + return -NLE_INVAL; + + link->l_stats[id] = value; + + return 0; +} + +/** + * Set type of link object + * @arg link Link object + * @arg type Name of link type + * + * Looks up the link type module and prepares the link to store type + * specific attributes. If a type has been assigned already it will + * be released with all link type specific attributes lost. + * + * @route_doc{link_modules, Link Modules} + * @return 0 on success or a negative errror code. + */ +int rtnl_link_set_type(struct rtnl_link *link, const char *type) +{ + struct rtnl_link_info_ops *io; + int err; + + if ((io = rtnl_link_info_ops_lookup(type)) == NULL) + return -NLE_OPNOTSUPP; + + if (link->l_info_ops) + release_link_info(link); + + if (io->io_alloc && (err = io->io_alloc(link)) < 0) + return err; + + link->ce_mask |= LINK_ATTR_LINKINFO; + link->l_info_ops = io; + + return 0; +} + +/** + * Return type of link + * @arg link Link object + * + * @route_doc{link_modules, Link Modules} + * @return Name of link type or NULL if not specified. + */ +char *rtnl_link_get_type(struct rtnl_link *link) +{ + return link->l_info_ops ? link->l_info_ops->io_name : NULL; } /** @} */ /** - * @name Link Flags Translations + * @name Utilities * @{ */ @@ -1544,7 +1979,7 @@ static const struct trans_tbl link_flags[] = { __ADD(IFF_ECHO, echo) }; -char * rtnl_link_flags2str(int flags, char *buf, size_t len) +char *rtnl_link_flags2str(int flags, char *buf, size_t len) { return __flags2str(flags, buf, len, link_flags, ARRAY_SIZE(link_flags)); @@ -1555,13 +1990,6 @@ int rtnl_link_str2flags(const char *name) return __str2flags(name, link_flags, ARRAY_SIZE(link_flags)); } -/** @} */ - -/** - * @name Link Statistics Translations - * @{ - */ - static const struct trans_tbl link_stats[] = { __ADD(RTNL_LINK_RX_PACKETS, rx_packets) __ADD(RTNL_LINK_TX_PACKETS, tx_packets) @@ -1632,13 +2060,6 @@ int rtnl_link_str2stat(const char *name) return __str2type(name, link_stats, ARRAY_SIZE(link_stats)); } -/** @} */ - -/** - * @name Link Operstate Translations - * @{ - */ - static const struct trans_tbl link_operstates[] = { __ADD(IF_OPER_UNKNOWN, unknown) __ADD(IF_OPER_NOTPRESENT, notpresent) @@ -1661,13 +2082,6 @@ int rtnl_link_str2operstate(const char *name) ARRAY_SIZE(link_operstates)); } -/** @} */ - -/** - * @name Link Mode Translations - * @{ - */ - static const struct trans_tbl link_modes[] = { __ADD(IF_LINK_MODE_DEFAULT, default) __ADD(IF_LINK_MODE_DORMANT, dormant) @@ -1686,349 +2100,40 @@ int rtnl_link_str2mode(const char *name) /** @} */ /** - * @name Attributes - * @{ + * @name Deprecated Functions */ -void rtnl_link_set_qdisc(struct rtnl_link *link, const char *qdisc) +/** + * @deprecated Use of this function is deprecated, use rtnl_link_set_type() + */ +int rtnl_link_set_info_type(struct rtnl_link *link, const char *type) { - strncpy(link->l_qdisc, qdisc, sizeof(link->l_qdisc) - 1); - link->ce_mask |= LINK_ATTR_QDISC; + return rtnl_link_set_type(link, type); } -char *rtnl_link_get_qdisc(struct rtnl_link *link) +/** + * @deprecated Use of this function is deprecated, use rtnl_link_get_type() + */ +char *rtnl_link_get_info_type(struct rtnl_link *link) { - if (link->ce_mask & LINK_ATTR_QDISC) - return link->l_qdisc; - else - return NULL; -} - -void rtnl_link_set_name(struct rtnl_link *link, const char *name) -{ - strncpy(link->l_name, name, sizeof(link->l_name) - 1); - link->ce_mask |= LINK_ATTR_IFNAME; -} - -char *rtnl_link_get_name(struct rtnl_link *link) -{ - if (link->ce_mask & LINK_ATTR_IFNAME) - return link->l_name; - else - return NULL; -} - -static inline void __assign_addr(struct rtnl_link *link, struct nl_addr **pos, - struct nl_addr *new, int flag) -{ - if (*pos) - nl_addr_put(*pos); - - nl_addr_get(new); - *pos = new; - - link->ce_mask |= flag; -} - -void rtnl_link_set_addr(struct rtnl_link *link, struct nl_addr *addr) -{ - __assign_addr(link, &link->l_addr, addr, LINK_ATTR_ADDR); -} - -struct nl_addr *rtnl_link_get_addr(struct rtnl_link *link) -{ - if (link->ce_mask & LINK_ATTR_ADDR) - return link->l_addr; - else - return NULL; -} - -void rtnl_link_set_broadcast(struct rtnl_link *link, struct nl_addr *brd) -{ - __assign_addr(link, &link->l_bcast, brd, LINK_ATTR_BRD); -} - -struct nl_addr *rtnl_link_get_broadcast(struct rtnl_link *link) -{ - if (link->ce_mask & LINK_ATTR_BRD) - return link->l_bcast; - else - return NULL; -} - -void rtnl_link_set_flags(struct rtnl_link *link, unsigned int flags) -{ - link->l_flag_mask |= flags; - link->l_flags |= flags; - link->ce_mask |= LINK_ATTR_FLAGS; -} - -void rtnl_link_unset_flags(struct rtnl_link *link, unsigned int flags) -{ - link->l_flag_mask |= flags; - link->l_flags &= ~flags; - link->ce_mask |= LINK_ATTR_FLAGS; -} - -unsigned int rtnl_link_get_flags(struct rtnl_link *link) -{ - return link->l_flags; -} - -void rtnl_link_set_family(struct rtnl_link *link, int family) -{ - link->l_family = family; - link->ce_mask |= LINK_ATTR_FAMILY; -} - -int rtnl_link_get_family(struct rtnl_link *link) -{ - if (link->ce_mask & LINK_ATTR_FAMILY) - return link->l_family; - else - return AF_UNSPEC; -} - -void rtnl_link_set_arptype(struct rtnl_link *link, unsigned int arptype) -{ - link->l_arptype = arptype; -} - -unsigned int rtnl_link_get_arptype(struct rtnl_link *link) -{ - return link->l_arptype; -} - -void rtnl_link_set_ifindex(struct rtnl_link *link, int ifindex) -{ - link->l_index = ifindex; - link->ce_mask |= LINK_ATTR_IFINDEX; -} - -int rtnl_link_get_ifindex(struct rtnl_link *link) -{ - return link->l_index; -} - -void rtnl_link_set_mtu(struct rtnl_link *link, unsigned int mtu) -{ - link->l_mtu = mtu; - link->ce_mask |= LINK_ATTR_MTU; -} - -unsigned int rtnl_link_get_mtu(struct rtnl_link *link) -{ - if (link->ce_mask & LINK_ATTR_MTU) - return link->l_mtu; - else - return 0; -} - -void rtnl_link_set_txqlen(struct rtnl_link *link, unsigned int txqlen) -{ - link->l_txqlen = txqlen; - link->ce_mask |= LINK_ATTR_TXQLEN; -} - -unsigned int rtnl_link_get_txqlen(struct rtnl_link *link) -{ - if (link->ce_mask & LINK_ATTR_TXQLEN) - return link->l_txqlen; - else - return UINT_MAX; + return rtnl_link_get_type(link); } +/** + * @deprecated The weight attribute is unused and obsoleted in all recent kernels + */ void rtnl_link_set_weight(struct rtnl_link *link, unsigned int weight) { link->l_weight = weight; link->ce_mask |= LINK_ATTR_WEIGHT; } +/** + * @deprecated The weight attribute is unused and obsoleted in all recent kernels + */ unsigned int rtnl_link_get_weight(struct rtnl_link *link) { - if (link->ce_mask & LINK_ATTR_WEIGHT) - return link->l_weight; - else - return UINT_MAX; -} - -void rtnl_link_set_link(struct rtnl_link *link, int ifindex) -{ - link->l_link = ifindex; - link->ce_mask |= LINK_ATTR_LINK; -} - -int rtnl_link_get_link(struct rtnl_link *link) -{ - return link->l_link; -} - -void rtnl_link_set_master(struct rtnl_link *link, int ifindex) -{ - link->l_master = ifindex; - link->ce_mask |= LINK_ATTR_MASTER; -} - -int rtnl_link_get_master(struct rtnl_link *link) -{ - return link->l_master; -} - -void rtnl_link_set_operstate(struct rtnl_link *link, uint8_t operstate) -{ - link->l_operstate = operstate; - link->ce_mask |= LINK_ATTR_OPERSTATE; -} - -uint8_t rtnl_link_get_operstate(struct rtnl_link *link) -{ - if (link->ce_mask & LINK_ATTR_OPERSTATE) - return link->l_operstate; - else - return IF_OPER_UNKNOWN; -} - -void rtnl_link_set_linkmode(struct rtnl_link *link, uint8_t linkmode) -{ - link->l_linkmode = linkmode; - link->ce_mask |= LINK_ATTR_LINKMODE; -} - -uint8_t rtnl_link_get_linkmode(struct rtnl_link *link) -{ - if (link->ce_mask & LINK_ATTR_LINKMODE) - return link->l_linkmode; - else - return IF_LINK_MODE_DEFAULT; -} - -/** - * Return alias name of link (SNMP IfAlias) - * @arg link Link object - * - * @return Alias name or NULL if not set. - */ -const char *rtnl_link_get_ifalias(struct rtnl_link *link) -{ - return link->l_ifalias; -} - -/** - * Set alias name of link (SNMP IfAlias) - * @arg link Link object - * @arg alias Alias name or NULL to unset - * - * Sets the alias name of the link to the specified name. The alias - * name can be unset by specyfing NULL as the alias. The name will - * be strdup()ed, so no need to provide a persistent character string. - */ -void rtnl_link_set_ifalias(struct rtnl_link *link, const char *alias) -{ - free(link->l_ifalias); - link->ce_mask &= ~LINK_ATTR_IFALIAS; - - if (alias) { - link->l_ifalias = strdup(alias); - link->ce_mask |= LINK_ATTR_IFALIAS; - } -} - -/** - * Retrieve number of PCI VFs of link - * @arg link Link object - * @arg num_vf Pointer to store number of VFs - * - * @return 0 if value is available or -NLE_OPNOTSUPP if not. - */ -int rtnl_link_get_num_vf(struct rtnl_link *link, uint32_t *num_vf) -{ - if (link->ce_mask & LINK_ATTR_NUM_VF) { - *num_vf = link->l_num_vf; - return 0; - } else - return -NLE_OPNOTSUPP; -} - -uint64_t rtnl_link_get_stat(struct rtnl_link *link, int id) -{ - if (id < 0 || id > RTNL_LINK_STATS_MAX) - return 0; - - return link->l_stats[id]; -} - -/** - * Set value of a link statistics counter - * @arg link Link object - * @arg id Counter ID - * @arg value New value - * - * @return 0 on success or a negative error code - */ -int rtnl_link_set_stat(struct rtnl_link *link, const unsigned int id, - const uint64_t value) -{ - if (id > RTNL_LINK_STATS_MAX) - return -NLE_INVAL; - - link->l_stats[id] = value; - - return 0; -} - -/** - * Set link type - * @arg link Link object - * @arg type Type of link - * - * Looks up the link type modules and prepares the link to store type - * specific attributes. If a type has been assigned already it will - * be released with all link type specific attributes lost. - * - * @return 0 on success or a negative errror code. - */ -int rtnl_link_set_type(struct rtnl_link *link, const char *type) -{ - struct rtnl_link_info_ops *io; - int err; - - if ((io = rtnl_link_info_ops_lookup(type)) == NULL) - return -NLE_OPNOTSUPP; - - if (link->l_info_ops) - release_link_info(link); - - if (io->io_alloc && (err = io->io_alloc(link)) < 0) - return err; - - link->ce_mask |= LINK_ATTR_LINKINFO; - link->l_info_ops = io; - - return 0; -} - -/** - * Get type of link - * @arg link Link object - * - * @return Name of link type or NULL if unknown. - */ -char *rtnl_link_get_type(struct rtnl_link *link) -{ - if (link->l_info_ops) - return link->l_info_ops->io_name; - else - return NULL; -} - -int rtnl_link_set_info_type(struct rtnl_link *link, const char *type) -{ - return rtnl_link_set_type(link, type); -} - -char *rtnl_link_get_info_type(struct rtnl_link *link) -{ - return rtnl_link_get_type(link); + return link->l_weight; } /** @} */ diff --git a/lib/route/link/bonding.c b/lib/route/link/bonding.c index c53bf52..176be27 100644 --- a/lib/route/link/bonding.c +++ b/lib/route/link/bonding.c @@ -13,8 +13,10 @@ * @ingroup link * @defgroup bonding Bonding * - * Link Documentation + * @details + * \b Link Type Name: "bond" * + * @route_doc{link_bonding, Bonding Documentation} * @{ */ diff --git a/lib/route/link/dummy.c b/lib/route/link/dummy.c index b837f48..c7dabc1 100644 --- a/lib/route/link/dummy.c +++ b/lib/route/link/dummy.c @@ -12,7 +12,9 @@ /** * @ingroup link * @defgroup dummy Dummy - * @brief + * + * @details + * \b Link Type Name: "dummy" * * @{ */ diff --git a/lib/route/link/vlan.c b/lib/route/link/vlan.c index cd831ce..a30ff77 100644 --- a/lib/route/link/vlan.c +++ b/lib/route/link/vlan.c @@ -14,7 +14,10 @@ * @defgroup vlan VLAN * Virtual LAN link module * - * See VLAN API documentation for more information + * @details + * \b Link Type Name: "vlan" + * + * @route_doc{link_vlan, VLAN Documentation} * * @{ */ From f1c8d5b0a3a1baa87a773feb34866ca51e0989bb Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 11 Aug 2011 14:30:24 +0200 Subject: [PATCH 067/432] 3.1 release --- .gitignore | 6 ++-- Makefile.am | 5 +++- configure.in | 7 +++-- doc/core.txt | 17 ++++++----- doc/route.txt | 2 +- lib/Makefile.am | 2 +- libnl-3.0.pc.in => libnl-3.1.pc.in | 0 libnl-genl-3.1.pc.in | 11 +++++++ libnl-nf-3.1.pc.in | 11 +++++++ libnl-route-3.1.pc.in | 11 +++++++ src/lib/link.c | 2 -- tests/Makefile | 14 ++++----- tests/test-create-bond.c | 33 ++++++++++++++++++++ tests/test-create-vlan.c | 48 ++++++++++++++++++++++++++++++ tests/test-delete-link.c | 28 +++++++++++++++++ 15 files changed, 170 insertions(+), 27 deletions(-) rename libnl-3.0.pc.in => libnl-3.1.pc.in (100%) create mode 100644 libnl-genl-3.1.pc.in create mode 100644 libnl-nf-3.1.pc.in create mode 100644 libnl-route-3.1.pc.in create mode 100644 tests/test-create-bond.c create mode 100644 tests/test-create-vlan.c create mode 100644 tests/test-delete-link.c diff --git a/.gitignore b/.gitignore index 17a67a0..85ddb3c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,14 @@ .deps .libs .dirstamp -*.in *.la *.lo *.o *.swp Makefile +Makefile.in +defs.h.in +defs.h.in~ /lib/stamp-h1 /libnl-1.pc @@ -24,5 +26,5 @@ cscope.* /ltmain.sh /install-sh /missing - /*.pc + diff --git a/Makefile.am b/Makefile.am index 07017c8..68d236c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,7 +10,10 @@ endif SUBDIRS = include lib doc man $(OPT_DIRS) -pkgconfig_DATA = libnl-3.0.pc +pkgconfig_DATA = libnl-3.1.pc \ + libnl-route-3.1.pc \ + libnl-genl-3.1.pc \ + libnl-nf-3.1.pc sysconfdir = @sysconfdir@/libnl sysconf_DATA = etc/pktloc etc/classid diff --git a/configure.in b/configure.in index 00ad3ee..47567af 100644 --- a/configure.in +++ b/configure.in @@ -9,7 +9,7 @@ # Copyright (c) 2003-2011 Thomas Graf # -AC_INIT(libnl, 3.0, tgraf@suug.ch) +AC_INIT(libnl, 3.1, tgraf@suug.ch) AC_CONFIG_HEADERS([lib/defs.h]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([-Wall foreign subdir-objects]) @@ -17,7 +17,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES(yes)], []) MAJ_VERSION=3 AC_SUBST([MAJ_VERSION]) -MIN_VERSION=0 +MIN_VERSION=1 AC_SUBST([MIN_VERSION]) AC_PROG_CC @@ -49,5 +49,6 @@ AC_CHECK_LIB([m], [pow], [], AC_MSG_ERROR([libm is required])) AC_CONFIG_FILES([Makefile doc/Doxyfile doc/Makefile lib/Makefile include/Makefile src/Makefile src/lib/Makefile man/Makefile - libnl-3.0.pc include/netlink/version.h]) + libnl-3.1.pc libnl-route-3.1.pc libnl-genl-3.1.pc libnl-nf-3.1.pc + include/netlink/version.h]) AC_OUTPUT diff --git a/doc/core.txt b/doc/core.txt index 0ab32ec..796e9fc 100644 --- a/doc/core.txt +++ b/doc/core.txt @@ -7,7 +7,7 @@ Netlink Library (libnl) ======================= Thomas Graf -3.0, July 17 2011: +3.1, Aug 11 2011: :numbered: == Introduction @@ -70,8 +70,8 @@ makes use of. ----- #include -#if LIBNL_VER_NUM >= LIBNL_VER(3,0) - /* include code if compiled with libnl version >= 3.0 */ +#if LIBNL_VER_NUM >= LIBNL_VER(3,1) + /* include code if compiled with libnl version >= 3.1 */ #endif ----- @@ -2549,11 +2549,12 @@ dealing with network addresses is a common task. Currently the following address families are supported: - - `AF_INET` - - `AF_INET6` - - `AF_LLC` - - `AF_DECnet` - - `AF_UNSPEC` +[options="compact"] + * `AF_INET` + * `AF_INET6` + * `AF_LLC` + * `AF_DECnet` + * `AF_UNSPEC` [[core_addr_alloc]] .Address Allocation diff --git a/doc/route.txt b/doc/route.txt index 757b4bd..33f58d0 100644 --- a/doc/route.txt +++ b/doc/route.txt @@ -7,7 +7,7 @@ Routing Family Netlink Library (libnl-route) ============================================ Thomas Graf -3.1, July 17 2011: +3.1, Aug 11 2011: == Introduction diff --git a/lib/Makefile.am b/lib/Makefile.am index ddda933..cb5403f 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,7 +1,7 @@ # -*- Makefile -*- AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -I${builddir}/route -I${builddir}/route/cls -D_GNU_SOURCE -DSYSCONFDIR=\"$(sysconfdir)/libnl\" -AM_LDFLAGS = -version-info 3:0:0 +AM_LDFLAGS = -version-info 3:1:0 lib_LTLIBRARIES = \ libnl.la libnl-genl.la libnl-route.la libnl-nf.la diff --git a/libnl-3.0.pc.in b/libnl-3.1.pc.in similarity index 100% rename from libnl-3.0.pc.in rename to libnl-3.1.pc.in diff --git a/libnl-genl-3.1.pc.in b/libnl-genl-3.1.pc.in new file mode 100644 index 0000000..5b5f841 --- /dev/null +++ b/libnl-genl-3.1.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libnl-genl +Description: Generic Netlink Library +Version: @PACKAGE_VERSION@ +Requires: libnl +Libs: -L${libdir} -lnl-genl +Cflags: -I${includedir} diff --git a/libnl-nf-3.1.pc.in b/libnl-nf-3.1.pc.in new file mode 100644 index 0000000..ffff22b --- /dev/null +++ b/libnl-nf-3.1.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libnl-nf +Description: Netfilter Netlink Library +Version: @PACKAGE_VERSION@ +Requires: libnl +Libs: -L${libdir} -lnl-nf +Cflags: -I${includedir} diff --git a/libnl-route-3.1.pc.in b/libnl-route-3.1.pc.in new file mode 100644 index 0000000..95be862 --- /dev/null +++ b/libnl-route-3.1.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libnl-route +Description: Netlink Routing Family Library +Version: @PACKAGE_VERSION@ +Requires: libnl +Libs: -L${libdir} -lnl-route +Cflags: -I${includedir} diff --git a/src/lib/link.c b/src/lib/link.c index db90558..5bce824 100644 --- a/src/lib/link.c +++ b/src/lib/link.c @@ -86,8 +86,6 @@ void nl_cli_link_parse_txqlen(struct rtnl_link *link, char *arg) void nl_cli_link_parse_weight(struct rtnl_link *link, char *arg) { - uint32_t weight = nl_cli_parse_u32(arg); - rtnl_link_set_weight(link, weight); } void nl_cli_link_parse_ifalias(struct rtnl_link *link, char *arg) diff --git a/tests/Makefile b/tests/Makefile index 8494eea..d072ddb 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -13,25 +13,21 @@ ifeq ($(shell [ ! -r ../Makefile.opts ] && echo 1),) include ../Makefile.opts endif -LDFLAGS += -L../lib -lnl ../src/utils.o +LDFLAGS += -L../lib -lnl -lnl-genl -lnl-route CIN := $(wildcard test-*.c) -TOOLS := $(CIN:%.c=%) +TESTS := $(CIN:%.c=%) -all: $(TOOLS) - -$(TOOLS): ../src/utils.o +all: $(TESTS) test-%: test-%.c @echo " LD $@"; \ - $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) -lnl-genl -lnl-route + $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) clean: @echo " CLEAN src"; \ - rm -f $(TOOLS) + rm -f $(TESTS) distclean: clean install: @true - -include ../Makefile.rules diff --git a/tests/test-create-bond.c b/tests/test-create-bond.c new file mode 100644 index 0000000..99166aa --- /dev/null +++ b/tests/test-create-bond.c @@ -0,0 +1,33 @@ +#include +#include + +int main(int argc, char *argv[]) +{ + struct rtnl_link *link; + struct nl_sock *sk; + int err; + + sk = nl_socket_alloc(); + if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { + nl_perror(err, "Unable to connect socket"); + return err; + } + + link = rtnl_link_alloc(); + rtnl_link_set_name(link, "my_bond"); + + if ((err = rtnl_link_set_info_type(link, "bond")) < 0) { + nl_perror(err, "Unable to set link info type"); + return err; + } + + if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) { + nl_perror(err, "Unable to add link"); + return err; + } + + rtnl_link_put(link); + nl_close(sk); + + return 0; +} diff --git a/tests/test-create-vlan.c b/tests/test-create-vlan.c new file mode 100644 index 0000000..00a4d91 --- /dev/null +++ b/tests/test-create-vlan.c @@ -0,0 +1,48 @@ +#include +#include +#include + +int main(int argc, char *argv[]) +{ + struct rtnl_link *link; + struct nl_cache *link_cache; + struct nl_sock *sk; + int err, master_index; + + sk = nl_socket_alloc(); + if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { + nl_perror(err, "Unable to connect socket"); + return err; + } + + if ((err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache)) < 0) { + nl_perror(err, "Unable to allocate cache"); + return err; + } + + if (!(master_index = rtnl_link_name2i(link_cache, "eth0"))) { + fprintf(stderr, "Unable to lookup eth0"); + return -1; + } + + link = rtnl_link_alloc(); + + rtnl_link_set_link(link, master_index); + + if ((err = rtnl_link_set_type(link, "vlan")) < 0) { + nl_perror(err, "Unable to set link info type"); + return err; + } + + rtnl_link_vlan_set_id(link, 10); + + if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) { + nl_perror(err, "Unable to add link"); + return err; + } + + rtnl_link_put(link); + nl_close(sk); + + return 0; +} diff --git a/tests/test-delete-link.c b/tests/test-delete-link.c new file mode 100644 index 0000000..9cf1034 --- /dev/null +++ b/tests/test-delete-link.c @@ -0,0 +1,28 @@ +#include +#include + +int main(int argc, char *argv[]) +{ + struct rtnl_link *link; + struct nl_sock *sk; + int err; + + sk = nl_socket_alloc(); + if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { + nl_perror(err, "Unable to connect socket"); + return err; + } + + link = rtnl_link_alloc(); + rtnl_link_set_name(link, "my_bond"); + + if ((err = rtnl_link_delete(sk, link)) < 0) { + nl_perror(err, "Unable to delete link"); + return err; + } + + rtnl_link_put(link); + nl_close(sk); + + return 0; +} From f9993836ed0cb0359e486daa50f72c889f81a36a Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Thu, 4 Aug 2011 11:58:56 -0400 Subject: [PATCH 068/432] Remove write-only variables in lib/cache.c --- lib/cache.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/lib/cache.c b/lib/cache.c index 3b453a9..90c0c0f 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -67,15 +67,12 @@ int nl_cache_nitems(struct nl_cache *cache) */ int nl_cache_nitems_filter(struct nl_cache *cache, struct nl_object *filter) { - struct nl_object_ops *ops; struct nl_object *obj; int nitems = 0; if (cache->c_ops == NULL) BUG(); - ops = cache->c_ops->co_obj_ops; - nl_list_for_each_entry(obj, &cache->c_items, ce_list) { if (filter && !nl_object_match_filter(obj, filter)) continue; @@ -271,7 +268,6 @@ struct nl_cache *nl_cache_subset(struct nl_cache *orig, struct nl_object *filter) { struct nl_cache *cache; - struct nl_object_ops *ops; struct nl_object *obj; if (!filter) @@ -281,8 +277,6 @@ struct nl_cache *nl_cache_subset(struct nl_cache *orig, if (!cache) return NULL; - ops = orig->c_ops->co_obj_ops; - nl_list_for_each_entry(obj, &orig->c_items, ce_list) { if (!nl_object_match_filter(obj, filter)) continue; @@ -941,13 +935,10 @@ void nl_cache_foreach_filter(struct nl_cache *cache, struct nl_object *filter, void (*cb)(struct nl_object *, void *), void *arg) { struct nl_object *obj, *tmp; - struct nl_object_ops *ops; if (cache->c_ops == NULL) BUG(); - ops = cache->c_ops->co_obj_ops; - nl_list_for_each_entry_safe(obj, tmp, &cache->c_items, ce_list) { if (filter) { int diff = nl_object_match_filter(obj, filter); From 7701c8572fa4bf23f0cbd652ee3e347f6924ac94 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Thu, 4 Aug 2011 11:59:03 -0400 Subject: [PATCH 069/432] Make some functions and global variables static --- lib/cache.c | 7 ++++--- lib/msg.c | 4 ++-- lib/route/pktloc.c | 2 +- lib/route/qdisc/netem.c | 3 ++- src/lib/tc.c | 2 +- src/nl-addr-list.c | 2 +- src/nl-class-delete.c | 2 +- src/nl-class-list.c | 4 ++-- src/nl-cls-delete.c | 2 +- src/nl-cls-list.c | 4 ++-- src/nl-neigh-delete.c | 2 +- src/nl-qdisc-delete.c | 2 +- 12 files changed, 19 insertions(+), 17 deletions(-) diff --git a/lib/cache.c b/lib/cache.c index 90c0c0f..a1c8eae 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -506,7 +506,8 @@ void nl_cache_set_arg2(struct nl_cache *cache, int arg) * * @return 0 on success or a negative error code. */ -int nl_cache_request_full_dump(struct nl_sock *sk, struct nl_cache *cache) +static int nl_cache_request_full_dump(struct nl_sock *sk, + struct nl_cache *cache) { NL_DBG(2, "Requesting dump from kernel for cache %p <%s>...\n", cache, nl_cache_name(cache)); @@ -537,8 +538,8 @@ static int update_msg_parser(struct nl_msg *msg, void *arg) * @arg cache Cache * @arg param Parser parameters */ -int __cache_pickup(struct nl_sock *sk, struct nl_cache *cache, - struct nl_parser_param *param) +static int __cache_pickup(struct nl_sock *sk, struct nl_cache *cache, + struct nl_parser_param *param) { int err; struct nl_cb *cb; diff --git a/lib/msg.c b/lib/msg.c index ee2922c..235ee82 100644 --- a/lib/msg.c +++ b/lib/msg.c @@ -188,7 +188,7 @@ int nlmsg_size(int payload) return NLMSG_HDRLEN + payload; } -int nlmsg_msg_size(int payload) +static int nlmsg_msg_size(int payload) { return nlmsg_size(payload); } @@ -255,7 +255,7 @@ int nlmsg_datalen(const struct nlmsghdr *nlh) return nlh->nlmsg_len - NLMSG_HDRLEN; } -int nlmsg_len(const struct nlmsghdr *nlh) +static int nlmsg_len(const struct nlmsghdr *nlh) { return nlmsg_datalen(nlh); } diff --git a/lib/route/pktloc.c b/lib/route/pktloc.c index b677ab5..c658e67 100644 --- a/lib/route/pktloc.c +++ b/lib/route/pktloc.c @@ -45,7 +45,7 @@ static struct nl_list_head pktloc_name_ht[PKTLOC_NAME_HT_SIZ]; /* djb2 */ -unsigned int pktloc_hash(const char *str) +static unsigned int pktloc_hash(const char *str) { unsigned long hash = 5381; int c; diff --git a/lib/route/qdisc/netem.c b/lib/route/qdisc/netem.c index c86af56..997a31f 100644 --- a/lib/route/qdisc/netem.c +++ b/lib/route/qdisc/netem.c @@ -145,7 +145,8 @@ static void netem_dump_line(struct rtnl_tc *tc, void *data, nl_dump(p, "limit %d", netem->qnm_limit); } -int netem_msg_fill_raw(struct rtnl_tc *tc, void *data, struct nl_msg *msg) +static int netem_msg_fill_raw(struct rtnl_tc *tc, void *data, + struct nl_msg *msg) { int err = 0; struct tc_netem_qopt opts; diff --git a/src/lib/tc.c b/src/lib/tc.c index 4cdd081..26124f1 100644 --- a/src/lib/tc.c +++ b/src/lib/tc.c @@ -94,7 +94,7 @@ void nl_cli_tc_parse_linktype(struct rtnl_tc *tc, char *arg) static NL_LIST_HEAD(tc_modules); -struct nl_cli_tc_module *__nl_cli_tc_lookup(struct rtnl_tc_ops *ops) +static struct nl_cli_tc_module *__nl_cli_tc_lookup(struct rtnl_tc_ops *ops) { struct nl_cli_tc_module *tm; diff --git a/src/nl-addr-list.c b/src/nl-addr-list.c index 9b045a5..5044d5c 100644 --- a/src/nl-addr-list.c +++ b/src/nl-addr-list.c @@ -41,7 +41,7 @@ static void print_usage(void) static char *prefix; -void print_prefix(struct nl_dump_params *p, int line) +static void print_prefix(struct nl_dump_params *p, int line) { if (prefix) nl_dump(p, "%s", prefix); diff --git a/src/nl-class-delete.c b/src/nl-class-delete.c index 3df5a9a..37657a4 100644 --- a/src/nl-class-delete.c +++ b/src/nl-class-delete.c @@ -14,7 +14,7 @@ #include static int quiet = 0, default_yes = 0, deleted = 0, interactive = 0; -struct nl_sock *sock; +static struct nl_sock *sock; static void print_usage(void) { diff --git a/src/nl-class-list.c b/src/nl-class-list.c index 44ca49b..c2423fb 100644 --- a/src/nl-class-list.c +++ b/src/nl-class-list.c @@ -14,9 +14,9 @@ #include #include -struct nl_sock *sock; +static struct nl_sock *sock; -struct nl_dump_params params = { +static struct nl_dump_params params = { .dp_type = NL_DUMP_LINE, }; diff --git a/src/nl-cls-delete.c b/src/nl-cls-delete.c index 7d998fd..2b3db1f 100644 --- a/src/nl-cls-delete.c +++ b/src/nl-cls-delete.c @@ -14,7 +14,7 @@ #include static int quiet = 0, default_yes = 0, deleted = 0, interactive = 0; -struct nl_sock *sock; +static struct nl_sock *sock; static void print_usage(void) { diff --git a/src/nl-cls-list.c b/src/nl-cls-list.c index fcb5dcb..5072585 100644 --- a/src/nl-cls-list.c +++ b/src/nl-cls-list.c @@ -14,9 +14,9 @@ #include #include -struct nl_sock *sock; +static struct nl_sock *sock; -struct nl_dump_params params = { +static struct nl_dump_params params = { .dp_type = NL_DUMP_LINE, }; diff --git a/src/nl-neigh-delete.c b/src/nl-neigh-delete.c index 887bd84..c418608 100644 --- a/src/nl-neigh-delete.c +++ b/src/nl-neigh-delete.c @@ -14,7 +14,7 @@ #include static int quiet = 0, default_yes = 0, deleted = 0, interactive = 0; -struct nl_sock *sock; +static struct nl_sock *sock; static void print_usage(void) { diff --git a/src/nl-qdisc-delete.c b/src/nl-qdisc-delete.c index 9c7ec14..2f945bb 100644 --- a/src/nl-qdisc-delete.c +++ b/src/nl-qdisc-delete.c @@ -15,7 +15,7 @@ #include static int quiet = 0, default_yes = 0, deleted = 0, interactive = 0; -struct nl_sock *sock; +static struct nl_sock *sock; static void print_usage(void) { From bbe5e9425366c19ae152dc2c1a09b8fc348807f2 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Thu, 4 Aug 2011 11:59:10 -0400 Subject: [PATCH 070/432] Put "break" inside the "if" block in route_compare() --- lib/route/route_obj.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/route/route_obj.c b/lib/route/route_obj.c index d3b09ab..3d208b4 100644 --- a/lib/route/route_obj.c +++ b/lib/route/route_obj.c @@ -346,9 +346,10 @@ static int route_compare(struct nl_object *_a, struct nl_object *_b, found = 0; nl_list_for_each_entry(nh_b, &b->rt_nexthops, rtnh_list) { - if (!rtnl_route_nh_compare(nh_a, nh_b, ~0, 0)) + if (!rtnl_route_nh_compare(nh_a, nh_b, ~0, 0)) { found = 1; break; + } } if (!found) goto nh_mismatch; @@ -360,9 +361,10 @@ static int route_compare(struct nl_object *_a, struct nl_object *_b, found = 0; nl_list_for_each_entry(nh_a, &a->rt_nexthops, rtnh_list) { - if (!rtnl_route_nh_compare(nh_a, nh_b, ~0, 0)) + if (!rtnl_route_nh_compare(nh_a, nh_b, ~0, 0)) { found = 1; break; + } } if (!found) goto nh_mismatch; From d886de5e9d2455d5c111dd90e845b3ddb0c4c8b3 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 11 Aug 2011 14:57:59 +0200 Subject: [PATCH 071/432] Allow building documentation out of the tree Patch originally provided by Gaudenz Steinlin --- doc/Doxyfile.in | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 33d5a8c..0e1108a 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -587,10 +587,10 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = ../lib \ - ../src/lib \ - ../include/netlink \ - src +INPUT = @top_srcdir@/lib \ + @top_srcdir@/src/lib \ + @top_srcdir@/include/netlink \ + @top_srcdir@/src # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is @@ -648,7 +648,7 @@ EXCLUDE_SYMBOLS = # directories that contain example code fragments that are included (see # the \include command). -EXAMPLE_PATH = src +EXAMPLE_PATH = @top_srcdir@/src # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp @@ -822,7 +822,7 @@ HTML_TIMESTAMP = NO # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! -HTML_STYLESHEET = libnl.css +HTML_STYLESHEET = @srcdir@/libnl.css # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. # Doxygen will adjust the colors in the stylesheet and background images From b5d081d1c9c9757e5e1d2e0babcace8b2a95fbe8 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 11 Aug 2011 15:06:29 +0200 Subject: [PATCH 072/432] Avoid freeing memory if vasprintf() failed Founds this bugfix in Fedora's SOURCES for libnl. Not sure who the original author is but the bug should be fixed upstream as well. --- lib/utils.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/utils.c b/lib/utils.c index 8eb068a..37ad4cc 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -815,13 +815,14 @@ static void dump_one(struct nl_dump_params *parms, const char *fmt, vfprintf(parms->dp_fd, fmt, args); else if (parms->dp_buf || parms->dp_cb) { char *buf = NULL; - vasprintf(&buf, fmt, args); - if (parms->dp_cb) - parms->dp_cb(parms, buf); - else - strncat(parms->dp_buf, buf, - parms->dp_buflen - strlen(parms->dp_buf) - 1); - free(buf); + if (vasprintf(&buf, fmt, args) >= 0) { + if (parms->dp_cb) + parms->dp_cb(parms, buf); + else + strncat(parms->dp_buf, buf, + parms->dp_buflen - strlen(parms->dp_buf) - 1); + free(buf); + } } } From 569bec5b5cd2028467ee21980739a3d720a13f87 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 11 Aug 2011 15:17:56 +0200 Subject: [PATCH 073/432] make port map thread safe This patch has been in Fedora and RHEL for a while. It adds a mutex to protect the port map from concurrent thread accesses. Original patch from Stefan Berger . Modified to use configure.in to check for libpthread --- configure.in | 1 + lib/socket.c | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 47567af..f217231 100644 --- a/configure.in +++ b/configure.in @@ -46,6 +46,7 @@ AC_ARG_ENABLE([cli], AM_CONDITIONAL([ENABLE_CLI], [test "$enable_cli" = "yes"]) AC_CHECK_LIB([m], [pow], [], AC_MSG_ERROR([libm is required])) +AC_CHECK_LIB([pthread], [pthread_mutex_lock], [], AC_MSG_ERROR([libpthread is required])) AC_CONFIG_FILES([Makefile doc/Doxyfile doc/Makefile lib/Makefile include/Makefile src/Makefile src/lib/Makefile man/Makefile diff --git a/lib/socket.c b/lib/socket.c index ebdf4e8..461cd41 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -15,6 +15,8 @@ * @{ */ +#include + #include #include #include @@ -43,12 +45,15 @@ static void __init init_default_cb(void) } static uint32_t used_ports_map[32]; +static pthread_mutex_t port_map_mutex = PTHREAD_MUTEX_INITIALIZER; static uint32_t generate_local_port(void) { int i, n; uint32_t pid = getpid() & 0x3FFFFF; + pthread_mutex_lock(&port_map_mutex); + for (i = 0; i < 32; i++) { if (used_ports_map[i] == 0xFFFFFFFF) continue; @@ -62,11 +67,15 @@ static uint32_t generate_local_port(void) /* PID_MAX_LIMIT is currently at 2^22, leaving 10 bit * to, i.e. 1024 unique ports per application. */ - return pid + (n << 22); + pthread_mutex_unlock(&port_map_mutex); + + return pid + (n << 22); } } + pthread_mutex_unlock(&port_map_mutex); + /* Out of sockets in our own PID namespace, what to do? FIXME */ return UINT_MAX; } @@ -79,7 +88,10 @@ static void release_local_port(uint32_t port) return; nr = port >> 22; - used_ports_map[nr / 32] &= ~(1 << nr % 32); + + pthread_mutex_lock(&port_map_mutex); + used_ports_map[nr / 32] &= ~(1 << (nr % 32)); + pthread_mutex_unlock(&port_map_mutex); } /** From 7a46ef074a65ba2ad7675ef794bde4f6854330ca Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 11 Aug 2011 15:43:34 +0200 Subject: [PATCH 074/432] Include all files necessary to build documentation in distribution --- doc/Makefile.am | 76 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/doc/Makefile.am b/doc/Makefile.am index 149daba..2b226ad 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -9,6 +9,82 @@ ASCIIDOCOPTS=-a pygments -a language=c -a icons \ -a iconsdir="./images/icons" \ -a stylesdir="${abs_srcdir}/stylesheets/" +EXTRA_DIST = \ + Doxyfile \ + DoxygenLayout.xml \ + core.txt \ + route.txt \ + index.txt \ + libnl.css \ + README \ + doxygen-link.py \ + gen-tags.sh \ + resolve-asciidoc-refs.py \ + tags2dict.sh \ + stylesheets/asciidoc.css \ + stylesheets/asciidoc-manpage.css \ + stylesheets/docbook-xsl.css \ + stylesheets/flask.css \ + stylesheets/flask-manpage.css \ + stylesheets/pygments.css \ + stylesheets/slidy.css \ + stylesheets/toc2.css \ + stylesheets/volnitsky.css \ + stylesheets/volnitsky-manpage.css \ + stylesheets/xhtml11-quirks.css \ + images/asciidoc__1.png \ + images/asciidoc__2.png \ + images/asciidoc__3.png \ + images/asciidoc__4.png \ + images/asciidoc__5.png \ + images/asciidoc__6.png \ + images/asciidoc__7.png \ + images/attribute_hdr.png \ + images/classful_qdisc.png \ + images/classless_qdisc_nbands.png \ + images/classless_qdisc.png \ + images/core__1.png \ + images/core__2.png \ + images/core__3.png \ + images/core__4.png \ + images/core__5.png \ + images/core__6.png \ + images/core__7.png \ + images/ifinfomsg.png \ + images/library_overview.png \ + images/nlmsgerr.png \ + images/nlmsghdr.png \ + images/qdisc_default.png \ + images/qdisc_mq.png \ + images/tc_obj.png \ + images/tc_overview.png \ + images/icons/caution.png \ + images/icons/example.png \ + images/icons/home.png \ + images/icons/important.png \ + images/icons/next.png \ + images/icons/note.png \ + images/icons/prev.png \ + images/icons/README \ + images/icons/tip.png \ + images/icons/up.png \ + images/icons/warning.png \ + images/icons/callouts/1.png \ + images/icons/callouts/2.png \ + images/icons/callouts/3.png \ + images/icons/callouts/4.png \ + images/icons/callouts/5.png \ + images/icons/callouts/6.png \ + images/icons/callouts/7.png \ + images/icons/callouts/8.png \ + images/icons/callouts/9.png \ + images/icons/callouts/10.png \ + images/icons/callouts/11.png \ + images/icons/callouts/12.png \ + images/icons/callouts/13.png \ + images/icons/callouts/14.png \ + images/icons/callouts/15.png + %.html: %.txt ./resolve-asciidoc-refs.py $< > asciidoc.tmp asciidoc $(ASCIIDOCOPTS) -o $@ asciidoc.tmp From d8d96bb2365f28ee3f519d610aced5d0c1e71c3d Mon Sep 17 00:00:00 2001 From: Bryan Phillippe Date: Thu, 11 Aug 2011 11:43:46 -0700 Subject: [PATCH 075/432] link: fix unaligned access to 64bit link stats --- lib/route/link.c | 58 ++++++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/lib/route/link.c b/lib/route/link.c index 4932722..3e070e5 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -341,34 +341,44 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, } if (tb[IFLA_STATS64]) { - struct rtnl_link_stats64 *st = nla_data(tb[IFLA_STATS64]); + /* + * This structure contains 64bit parameters, and per the + * documentation in lib/attr.c, must not be accessed + * directly (because of alignment to 4 instead of 8). + * Therefore, copy the data to the stack and access it from + * there, where it will be aligned to 8. + */ + struct rtnl_link_stats64 st; + + nla_memcpy(&st, tb[IFLA_STATS64], + sizeof(struct rtnl_link_stats64)); - link->l_stats[RTNL_LINK_RX_PACKETS] = st->rx_packets; - link->l_stats[RTNL_LINK_TX_PACKETS] = st->tx_packets; - link->l_stats[RTNL_LINK_RX_BYTES] = st->rx_bytes; - link->l_stats[RTNL_LINK_TX_BYTES] = st->tx_bytes; - link->l_stats[RTNL_LINK_RX_ERRORS] = st->rx_errors; - link->l_stats[RTNL_LINK_TX_ERRORS] = st->tx_errors; - link->l_stats[RTNL_LINK_RX_DROPPED] = st->rx_dropped; - link->l_stats[RTNL_LINK_TX_DROPPED] = st->tx_dropped; - link->l_stats[RTNL_LINK_MULTICAST] = st->multicast; - link->l_stats[RTNL_LINK_COLLISIONS] = st->collisions; + link->l_stats[RTNL_LINK_RX_PACKETS] = st.rx_packets; + link->l_stats[RTNL_LINK_TX_PACKETS] = st.tx_packets; + link->l_stats[RTNL_LINK_RX_BYTES] = st.rx_bytes; + link->l_stats[RTNL_LINK_TX_BYTES] = st.tx_bytes; + link->l_stats[RTNL_LINK_RX_ERRORS] = st.rx_errors; + link->l_stats[RTNL_LINK_TX_ERRORS] = st.tx_errors; + link->l_stats[RTNL_LINK_RX_DROPPED] = st.rx_dropped; + link->l_stats[RTNL_LINK_TX_DROPPED] = st.tx_dropped; + link->l_stats[RTNL_LINK_MULTICAST] = st.multicast; + link->l_stats[RTNL_LINK_COLLISIONS] = st.collisions; - link->l_stats[RTNL_LINK_RX_LEN_ERR] = st->rx_length_errors; - link->l_stats[RTNL_LINK_RX_OVER_ERR] = st->rx_over_errors; - link->l_stats[RTNL_LINK_RX_CRC_ERR] = st->rx_crc_errors; - link->l_stats[RTNL_LINK_RX_FRAME_ERR] = st->rx_frame_errors; - link->l_stats[RTNL_LINK_RX_FIFO_ERR] = st->rx_fifo_errors; - link->l_stats[RTNL_LINK_RX_MISSED_ERR] = st->rx_missed_errors; + link->l_stats[RTNL_LINK_RX_LEN_ERR] = st.rx_length_errors; + link->l_stats[RTNL_LINK_RX_OVER_ERR] = st.rx_over_errors; + link->l_stats[RTNL_LINK_RX_CRC_ERR] = st.rx_crc_errors; + link->l_stats[RTNL_LINK_RX_FRAME_ERR] = st.rx_frame_errors; + link->l_stats[RTNL_LINK_RX_FIFO_ERR] = st.rx_fifo_errors; + link->l_stats[RTNL_LINK_RX_MISSED_ERR] = st.rx_missed_errors; - link->l_stats[RTNL_LINK_TX_ABORT_ERR] = st->tx_aborted_errors; - link->l_stats[RTNL_LINK_TX_CARRIER_ERR] = st->tx_carrier_errors; - link->l_stats[RTNL_LINK_TX_FIFO_ERR] = st->tx_fifo_errors; - link->l_stats[RTNL_LINK_TX_HBEAT_ERR] = st->tx_heartbeat_errors; - link->l_stats[RTNL_LINK_TX_WIN_ERR] = st->tx_window_errors; + link->l_stats[RTNL_LINK_TX_ABORT_ERR] = st.tx_aborted_errors; + link->l_stats[RTNL_LINK_TX_CARRIER_ERR] = st.tx_carrier_errors; + link->l_stats[RTNL_LINK_TX_FIFO_ERR] = st.tx_fifo_errors; + link->l_stats[RTNL_LINK_TX_HBEAT_ERR] = st.tx_heartbeat_errors; + link->l_stats[RTNL_LINK_TX_WIN_ERR] = st.tx_window_errors; - link->l_stats[RTNL_LINK_RX_COMPRESSED] = st->rx_compressed; - link->l_stats[RTNL_LINK_TX_COMPRESSED] = st->tx_compressed; + link->l_stats[RTNL_LINK_RX_COMPRESSED] = st.rx_compressed; + link->l_stats[RTNL_LINK_TX_COMPRESSED] = st.tx_compressed; link->ce_mask |= LINK_ATTR_STATS; } From 23333e5e354cc89cf036e16551957710480d511e Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 12 Aug 2011 10:45:47 +0200 Subject: [PATCH 076/432] python: Include python/ in distribution and provide a README on how to build & install --- Makefile.am | 2 +- configure.in | 2 ++ python/.gitignore | 1 + python/Makefile.am | 3 +++ python/README | 12 ++++++++++++ python/netlink/Makefile.am | 10 ++++++++++ python/netlink/route/Makefile.am | 14 ++++++++++++++ python/{setup.py => setup.py.in} | 2 +- 8 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 python/Makefile.am create mode 100644 python/README create mode 100644 python/netlink/Makefile.am create mode 100644 python/netlink/route/Makefile.am rename python/{setup.py => setup.py.in} (95%) diff --git a/Makefile.am b/Makefile.am index 68d236c..644fdb1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,7 +8,7 @@ if ENABLE_CLI OPT_DIRS += src endif -SUBDIRS = include lib doc man $(OPT_DIRS) +SUBDIRS = include lib doc man python $(OPT_DIRS) pkgconfig_DATA = libnl-3.1.pc \ libnl-route-3.1.pc \ diff --git a/configure.in b/configure.in index f217231..7611e92 100644 --- a/configure.in +++ b/configure.in @@ -51,5 +51,7 @@ AC_CHECK_LIB([pthread], [pthread_mutex_lock], [], AC_MSG_ERROR([libpthread is re AC_CONFIG_FILES([Makefile doc/Doxyfile doc/Makefile lib/Makefile include/Makefile src/Makefile src/lib/Makefile man/Makefile libnl-3.1.pc libnl-route-3.1.pc libnl-genl-3.1.pc libnl-nf-3.1.pc + python/Makefile python/setup.py python/netlink/Makefile + python/netlink/route/Makefile include/netlink/version.h]) AC_OUTPUT diff --git a/python/.gitignore b/python/.gitignore index 9f3c73b..a83b942 100644 --- a/python/.gitignore +++ b/python/.gitignore @@ -1,3 +1,4 @@ build capi_wrap.c capi.py +setup.py diff --git a/python/Makefile.am b/python/Makefile.am new file mode 100644 index 0000000..bd5ac11 --- /dev/null +++ b/python/Makefile.am @@ -0,0 +1,3 @@ +# -*- Makefile -*- + +SUBDIRS = netlink diff --git a/python/README b/python/README new file mode 100644 index 0000000..4ccc337 --- /dev/null +++ b/python/README @@ -0,0 +1,12 @@ + +*************************************************************************** + +NOTE: The python wrapper is experimental and may or may not work. + +*************************************************************************** + +For the brave: + + (requires an installed libnl) + - $ python ./setup.py build + - $ sudo python ./setup.py install diff --git a/python/netlink/Makefile.am b/python/netlink/Makefile.am new file mode 100644 index 0000000..0f1045b --- /dev/null +++ b/python/netlink/Makefile.am @@ -0,0 +1,10 @@ +# -*- Makefile -*- + +SUBDIRS = route + +EXTRA_DIST = \ + capi.i \ + fixes.h \ + __init__.py \ + core.py \ + util.py diff --git a/python/netlink/route/Makefile.am b/python/netlink/route/Makefile.am new file mode 100644 index 0000000..ef714f4 --- /dev/null +++ b/python/netlink/route/Makefile.am @@ -0,0 +1,14 @@ +# -*- Makefile -*- + +EXTRA_DIST = \ + capi.i \ + __init__.py \ + address.py \ + link.py \ + tc.py \ + links/__init__.py \ + links/dummy.py \ + links/inet.py \ + links/vlan.py \ + qdisc/__init__.py \ + qdisc/htb.py diff --git a/python/setup.py b/python/setup.py.in similarity index 95% rename from python/setup.py rename to python/setup.py.in index f201a84..e1a3aca 100644 --- a/python/setup.py +++ b/python/setup.py.in @@ -3,7 +3,7 @@ from distutils.core import setup, Extension opts = ['-O', '-nodefaultctor'] -include = ['../include'] +include = ['@top_builddir@/include'] netlink_capi = Extension('netlink/_capi', sources = ['netlink/capi.i'], From cc9ae9b34b393c13d7c682d5284f11d3f2f73517 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 12 Aug 2011 11:06:50 +0200 Subject: [PATCH 077/432] doc: need to include @srcdir@/src not @top_srcdir@/src --- doc/Doxyfile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 0e1108a..c183abd 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -590,7 +590,7 @@ WARN_LOGFILE = INPUT = @top_srcdir@/lib \ @top_srcdir@/src/lib \ @top_srcdir@/include/netlink \ - @top_srcdir@/src + @srcdir@/src # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is From 4be7adbb71b3f4f31aecb46c9dbfaa4b1fa45009 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 12 Aug 2011 13:47:23 +0200 Subject: [PATCH 078/432] htb: fix misplaced memset() overwriting already set htb prio option Reported by Richard Cesar --- lib/route/qdisc/htb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/route/qdisc/htb.c b/lib/route/qdisc/htb.c index 4417b8e..f1d0e75 100644 --- a/lib/route/qdisc/htb.c +++ b/lib/route/qdisc/htb.c @@ -217,12 +217,12 @@ static int htb_class_msg_fill(struct rtnl_tc *tc, void *data, if (!htb || !(htb->ch_mask & SCH_HTB_HAS_RATE)) BUG(); + memset(&opts, 0, sizeof(opts)); + /* if not set, zero (0) is used as priority */ if (htb->ch_mask & SCH_HTB_HAS_PRIO) opts.prio = htb->ch_prio; - memset(&opts, 0, sizeof(opts)); - mtu = rtnl_tc_get_mtu(tc); rtnl_tc_build_rate_table(tc, &htb->ch_rate, rtable); From b367024167f15513a564b5834d31ec186ca79665 Mon Sep 17 00:00:00 2001 From: Andrew Rybchenko Date: Tue, 30 Aug 2011 09:27:37 +0400 Subject: [PATCH 079/432] Local port leak on nl_socket_alloc/nl_socket_set_local_port(, 0) I've found a bug in the following scenario (fragment of code): while (1) { struct nl_sock *sk = nl_socket_alloc(); if (sk == NULL) { fprintf(stderr, "Failed to allocate nl socket\n"); break; } nl_socket_set_local_port(sk, 0); nl_socket_free(sk); } The problem is that nl_socket_set_local_port(, 0) does not release local port if it is allocated before. --- lib/socket.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/socket.c b/lib/socket.c index 461cd41..60120fb 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -268,7 +268,14 @@ void nl_socket_set_local_port(struct nl_sock *sk, uint32_t port) { if (port == 0) { port = generate_local_port(); - sk->s_flags &= ~NL_OWN_PORT; + /* + * Release local port after generation of a new one to be + * able to change local port using nl_socket_set_local_port(, 0) + */ + if (!(sk->s_flags & NL_OWN_PORT)) + release_local_port(sk->s_local.nl_pid); + else + sk->s_flags &= ~NL_OWN_PORT; } else { if (!(sk->s_flags & NL_OWN_PORT)) release_local_port(sk->s_local.nl_pid); From eabb7539dd6cae2387888b6e9e7bcaedee488e3f Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 25 Aug 2011 15:14:07 +0200 Subject: [PATCH 080/432] nl-link-name2ifindex: fix usage text Signed-off-by: Jiri Pirko --- src/nl-link-name2ifindex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nl-link-name2ifindex.c b/src/nl-link-name2ifindex.c index b04af04..b8ae4bc 100644 --- a/src/nl-link-name2ifindex.c +++ b/src/nl-link-name2ifindex.c @@ -14,7 +14,7 @@ static void print_usage(void) { - printf("Usage: nl-link-ifindex2name \n"); + printf("Usage: nl-link-name2ifindex \n"); exit(0); } From 6faeffe64acd7d94f152afbb99ab811949308b11 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Tue, 30 Aug 2011 18:31:47 +0200 Subject: [PATCH 081/432] socket: introduce nl_socket_modify_err_cb This function does the same as nl_socket_modify_cb except for error callback Signed-off-by: Jiri Pirko --- include/netlink/socket.h | 2 ++ lib/socket.c | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/include/netlink/socket.h b/include/netlink/socket.h index f0062b5..d0f5a6a 100644 --- a/include/netlink/socket.h +++ b/include/netlink/socket.h @@ -45,6 +45,8 @@ extern void nl_socket_set_cb(struct nl_sock *, extern int nl_socket_modify_cb(struct nl_sock *, enum nl_cb_type, enum nl_cb_kind, nl_recvmsg_msg_cb_t, void *); +extern int nl_socket_modify_err_cb(struct nl_sock *, enum nl_cb_kind, + nl_recvmsg_err_cb_t, void *); extern int nl_socket_set_buffer_size(struct nl_sock *, int, int); extern int nl_socket_set_passcred(struct nl_sock *, int); diff --git a/lib/socket.c b/lib/socket.c index 60120fb..565248f 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -511,6 +511,21 @@ int nl_socket_modify_cb(struct nl_sock *sk, enum nl_cb_type type, return nl_cb_set(sk->s_cb, type, kind, func, arg); } +/** + * Modify the error callback handler associated with the socket + * @arg sk Netlink socket. + * @arg kind kind of callback + * @arg func callback function + * @arg arg argument to be passed to callback function + * + * @see nl_cb_err + */ +int nl_socket_modify_err_cb(struct nl_sock *sk, enum nl_cb_kind kind, + nl_recvmsg_err_cb_t func, void *arg) +{ + return nl_cb_err(sk->s_cb, kind, func, arg); +} + /** @} */ /** From 17781e44dd6242fc8cecd07b757e7bb0afc87113 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Tue, 30 Aug 2011 18:33:25 +0200 Subject: [PATCH 082/432] socket: fix two typos Signed-off-by: Jiri Pirko --- lib/socket.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/socket.c b/lib/socket.c index 565248f..01b9872 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -495,12 +495,12 @@ void nl_socket_set_cb(struct nl_sock *sk, struct nl_cb *cb) } /** - * Modify the callback handler associated to the socket + * Modify the callback handler associated with the socket * @arg sk Netlink socket. * @arg type which type callback to set * @arg kind kind of callback * @arg func callback function - * @arg arg argument to be passwd to callback function + * @arg arg argument to be passed to callback function * * @see nl_cb_set */ From 7adaad784f02dc3cab0ad97a284edb0eaf2f0663 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 31 Aug 2011 11:14:43 +0200 Subject: [PATCH 083/432] genl: genl_ctrl_grp_by_name: fix retval in case group id not found Now the return value in case group id is not find is 0. Change it to return -NLE_OBJ_NOTFOUND which makes more sense. This should not break anything because genl_ctrl_grp_by_name is static and called only from genl_ctrl_resolve_grp. genl_ctrl_resolve_grp already might return -NLE_OBJ_NOTFOUND. Signed-off-by: Jiri Pirko --- lib/genl/ctrl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/genl/ctrl.c b/lib/genl/ctrl.c index 3871795..107a4fa 100644 --- a/lib/genl/ctrl.c +++ b/lib/genl/ctrl.c @@ -293,7 +293,7 @@ static int genl_ctrl_grp_by_name(const struct genl_family *family, } } - return 0; + return -NLE_OBJ_NOTFOUND; } int genl_ctrl_resolve_grp(struct nl_sock *sk, const char *family_name, From f1d9e9d52d7751a09a744f3ad83613c6b025c230 Mon Sep 17 00:00:00 2001 From: Bryan Phillippe Date: Wed, 31 Aug 2011 11:11:59 -0700 Subject: [PATCH 084/432] 64bit unaligned access This patch fixes an unaligned access for IPv6. On systems with strict alignment requirements, the unaligned access will either result in garbage data or a crash. --- lib/route/link/inet6.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/lib/route/link/inet6.c b/lib/route/link/inet6.c index 399dd4b..5f75342 100644 --- a/lib/route/link/inet6.c +++ b/lib/route/link/inet6.c @@ -71,23 +71,33 @@ static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr, if (tb[IFLA_INET6_CONF]) nla_memcpy(&i6->i6_conf, tb[IFLA_INET6_CONF], sizeof(i6->i6_conf)); - + + /* + * Due to 32bit data alignment, these addresses must be copied to an + * aligned location prior to access. + */ if (tb[IFLA_INET6_STATS]) { - uint64_t *cnt = nla_data(tb[IFLA_INET6_STATS]); + unsigned char *cnt = nla_data(tb[IFLA_INET6_STATS]); + uint64_t stat; int i; - for (i = 1; i < __IPSTATS_MIB_MAX; i++) + for (i = 1; i < __IPSTATS_MIB_MAX; i++) { + memcpy(&stat, &cnt[i * sizeof(stat)], sizeof(stat)); rtnl_link_set_stat(link, RTNL_LINK_IP6_INPKTS + i - 1, - cnt[i]); + stat); + } } if (tb[IFLA_INET6_ICMP6STATS]) { - uint64_t *cnt = nla_data(tb[IFLA_INET6_ICMP6STATS]); + unsigned char *cnt = nla_data(tb[IFLA_INET6_ICMP6STATS]); + uint64_t stat; int i; - for (i = 1; i < __ICMP6_MIB_MAX; i++) + for (i = 1; i < __ICMP6_MIB_MAX; i++) { + memcpy(&stat, &cnt[i * sizeof(stat)], sizeof(stat)); rtnl_link_set_stat(link, RTNL_LINK_ICMP6_INMSGS + i - 1, - cnt[i]); + stat); + } } return 0; From b4b853e5e7a8d3bde7128215d19d76b26ce68a3f Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 8 Sep 2011 14:59:16 +0200 Subject: [PATCH 085/432] Do not require python and swig to be present Allows building without python and swig. Readd this using --enable-python at some point. --- configure.in | 5 ----- 1 file changed, 5 deletions(-) diff --git a/configure.in b/configure.in index 7611e92..3406530 100644 --- a/configure.in +++ b/configure.in @@ -27,11 +27,6 @@ AM_PROG_LIBTOOL AM_PROG_LEX AC_PROG_YACC -AM_PATH_PYTHON(2.6) -AX_PKG_SWIG -AX_PYTHON_DEVEL -AX_SWIG_PYTHON - AC_C_CONST AC_C_INLINE From db6de563fe83feb73e26d765db4128ac30f0167f Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 8 Sep 2011 15:03:25 +0200 Subject: [PATCH 086/432] fix license of lib/route/pktloc.c As Jan Engelhardt pointed out, pktloc.c is currently licenses under the GPL rather than the LGPL. This is a result of its previous existance in src/ which is GPL licensed. I missed to change its license when moving it to lib/. Since I am the only contributor to the code, I am changing the license hereby. --- lib/route/pktloc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/route/pktloc.c b/lib/route/pktloc.c index c658e67..e7dffe5 100644 --- a/lib/route/pktloc.c +++ b/lib/route/pktloc.c @@ -2,10 +2,11 @@ * lib/route/pktloc.c Packet Location Aliasing * * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2 of the License. + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. * - * Copyright (c) 2008-2010 Thomas Graf + * Copyright (c) 2008-2011 Thomas Graf */ /** From 7ac948c643b86104e5b6b795a0f44b8d2ede1bd1 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 8 Sep 2011 15:07:02 +0200 Subject: [PATCH 087/432] Remove GPL-3.0 license file. There is no code licensed GPL-3.0 so we might as well remove this file. --- src/COPYING | 676 ---------------------------------------------------- 1 file changed, 676 deletions(-) delete mode 100644 src/COPYING diff --git a/src/COPYING b/src/COPYING deleted file mode 100644 index 4432540..0000000 --- a/src/COPYING +++ /dev/null @@ -1,676 +0,0 @@ - - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. - From 80569bb24235749e1bd7a611ece363db03f1617f Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 8 Sep 2011 15:33:55 +0200 Subject: [PATCH 088/432] remove dist lines for non existing files --- doc/Makefile.am | 7 ------- 1 file changed, 7 deletions(-) diff --git a/doc/Makefile.am b/doc/Makefile.am index 2b226ad..9b964b5 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -43,13 +43,6 @@ EXTRA_DIST = \ images/classful_qdisc.png \ images/classless_qdisc_nbands.png \ images/classless_qdisc.png \ - images/core__1.png \ - images/core__2.png \ - images/core__3.png \ - images/core__4.png \ - images/core__5.png \ - images/core__6.png \ - images/core__7.png \ images/ifinfomsg.png \ images/library_overview.png \ images/nlmsgerr.png \ From 2a37ab5f34fcbe97aee8cabeb3b85f96751999af Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 8 Sep 2011 15:00:07 +0200 Subject: [PATCH 089/432] prepare for 3.2 release Fall back to using libnl-*.3.pc files. It may be common to have multiple generations of libnl installed but unlikely within the same major release. --- Makefile.am | 8 ++++---- configure.in | 6 +++--- libnl-3.1.pc.in => libnl-3.pc.in | 0 libnl-genl-3.1.pc.in => libnl-genl-3.pc.in | 2 +- libnl-nf-3.1.pc.in => libnl-nf-3.pc.in | 2 +- libnl-route-3.1.pc.in => libnl-route-3.pc.in | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) rename libnl-3.1.pc.in => libnl-3.pc.in (100%) rename libnl-genl-3.1.pc.in => libnl-genl-3.pc.in (92%) rename libnl-nf-3.1.pc.in => libnl-nf-3.pc.in (92%) rename libnl-route-3.1.pc.in => libnl-route-3.pc.in (92%) diff --git a/Makefile.am b/Makefile.am index 644fdb1..e152685 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,10 +10,10 @@ endif SUBDIRS = include lib doc man python $(OPT_DIRS) -pkgconfig_DATA = libnl-3.1.pc \ - libnl-route-3.1.pc \ - libnl-genl-3.1.pc \ - libnl-nf-3.1.pc +pkgconfig_DATA = libnl-3.pc \ + libnl-route-3.pc \ + libnl-genl-3.pc \ + libnl-nf-3.pc sysconfdir = @sysconfdir@/libnl sysconf_DATA = etc/pktloc etc/classid diff --git a/configure.in b/configure.in index 3406530..4eb5420 100644 --- a/configure.in +++ b/configure.in @@ -9,7 +9,7 @@ # Copyright (c) 2003-2011 Thomas Graf # -AC_INIT(libnl, 3.1, tgraf@suug.ch) +AC_INIT(libnl, 3.2, tgraf@suug.ch) AC_CONFIG_HEADERS([lib/defs.h]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([-Wall foreign subdir-objects]) @@ -17,7 +17,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES(yes)], []) MAJ_VERSION=3 AC_SUBST([MAJ_VERSION]) -MIN_VERSION=1 +MIN_VERSION=2 AC_SUBST([MIN_VERSION]) AC_PROG_CC @@ -45,7 +45,7 @@ AC_CHECK_LIB([pthread], [pthread_mutex_lock], [], AC_MSG_ERROR([libpthread is re AC_CONFIG_FILES([Makefile doc/Doxyfile doc/Makefile lib/Makefile include/Makefile src/Makefile src/lib/Makefile man/Makefile - libnl-3.1.pc libnl-route-3.1.pc libnl-genl-3.1.pc libnl-nf-3.1.pc + libnl-3.pc libnl-route-3.pc libnl-genl-3.pc libnl-nf-3.pc python/Makefile python/setup.py python/netlink/Makefile python/netlink/route/Makefile include/netlink/version.h]) diff --git a/libnl-3.1.pc.in b/libnl-3.pc.in similarity index 100% rename from libnl-3.1.pc.in rename to libnl-3.pc.in diff --git a/libnl-genl-3.1.pc.in b/libnl-genl-3.pc.in similarity index 92% rename from libnl-genl-3.1.pc.in rename to libnl-genl-3.pc.in index 5b5f841..2167559 100644 --- a/libnl-genl-3.1.pc.in +++ b/libnl-genl-3.pc.in @@ -6,6 +6,6 @@ includedir=@includedir@ Name: libnl-genl Description: Generic Netlink Library Version: @PACKAGE_VERSION@ -Requires: libnl +Requires: libnl-3 Libs: -L${libdir} -lnl-genl Cflags: -I${includedir} diff --git a/libnl-nf-3.1.pc.in b/libnl-nf-3.pc.in similarity index 92% rename from libnl-nf-3.1.pc.in rename to libnl-nf-3.pc.in index ffff22b..0ec9100 100644 --- a/libnl-nf-3.1.pc.in +++ b/libnl-nf-3.pc.in @@ -6,6 +6,6 @@ includedir=@includedir@ Name: libnl-nf Description: Netfilter Netlink Library Version: @PACKAGE_VERSION@ -Requires: libnl +Requires: libnl-3 Libs: -L${libdir} -lnl-nf Cflags: -I${includedir} diff --git a/libnl-route-3.1.pc.in b/libnl-route-3.pc.in similarity index 92% rename from libnl-route-3.1.pc.in rename to libnl-route-3.pc.in index 95be862..217f6c2 100644 --- a/libnl-route-3.1.pc.in +++ b/libnl-route-3.pc.in @@ -6,6 +6,6 @@ includedir=@includedir@ Name: libnl-route Description: Netlink Routing Family Library Version: @PACKAGE_VERSION@ -Requires: libnl +Requires: libnl-3 Libs: -L${libdir} -lnl-route Cflags: -I${includedir} From 5a59cf85d1aeb8b35b128ea63df1e5bfc80e51fd Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 13 Sep 2011 11:07:23 +0200 Subject: [PATCH 090/432] asciidoc xhtml stylesheet --- doc/stylesheets/xhtml11.css | 333 ++++++++++++++++++++++++++++++++++++ 1 file changed, 333 insertions(+) create mode 100644 doc/stylesheets/xhtml11.css diff --git a/doc/stylesheets/xhtml11.css b/doc/stylesheets/xhtml11.css new file mode 100644 index 0000000..1e6bf5a --- /dev/null +++ b/doc/stylesheets/xhtml11.css @@ -0,0 +1,333 @@ +/* Debug borders */ +p, li, dt, dd, div, pre, h1, h2, h3, h4, h5, h6 { +/* + border: 1px solid red; +*/ +} + +body { + margin: 1em 5% 1em 5%; +} + +a { + color: blue; + text-decoration: underline; +} +a:visited { + color: fuchsia; +} + +em { + font-style: italic; + color: navy; +} + +strong { + font-weight: bold; + color: #083194; +} + +tt { + color: navy; +} + +h1, h2, h3, h4, h5, h6 { + color: #527bbd; + font-family: sans-serif; + margin-top: 1.2em; + margin-bottom: 0.5em; + line-height: 1.3; +} + +h1, h2, h3 { + border-bottom: 2px solid silver; +} +h2 { + padding-top: 0.5em; +} +h3 { + float: left; +} +h3 + * { + clear: left; +} + +div.sectionbody { + font-family: serif; + margin-left: 0; +} + +hr { + border: 1px solid silver; +} + +p { + margin-top: 0.5em; + margin-bottom: 0.5em; +} + +ul, ol, li > p { + margin-top: 0; +} + +pre { + padding: 0; + margin: 0; +} + +span#author { + color: #527bbd; + font-family: sans-serif; + font-weight: bold; + font-size: 1.1em; +} +span#email { +} +span#revnumber, span#revdate, span#revremark { + font-family: sans-serif; +} + +div#footer { + font-family: sans-serif; + font-size: small; + border-top: 2px solid silver; + padding-top: 0.5em; + margin-top: 4.0em; +} +div#footer-text { + float: left; + padding-bottom: 0.5em; +} +div#footer-badges { + float: right; + padding-bottom: 0.5em; +} + +div#preamble { + margin-top: 1.5em; + margin-bottom: 1.5em; +} +div.tableblock, div.imageblock, div.exampleblock, div.verseblock, +div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock, +div.admonitionblock { + margin-top: 1.5em; + margin-bottom: 1.5em; +} +div.admonitionblock { + margin-top: 2.5em; + margin-bottom: 2.5em; +} + +div.content { /* Block element content. */ + padding: 0; +} + +/* Block element titles. */ +div.title, caption.title { + color: #527bbd; + font-family: sans-serif; + font-weight: bold; + text-align: left; + margin-top: 1.0em; + margin-bottom: 0.5em; +} +div.title + * { + margin-top: 0; +} + +td div.title:first-child { + margin-top: 0.0em; +} +div.content div.title:first-child { + margin-top: 0.0em; +} +div.content + div.title { + margin-top: 0.0em; +} + +div.sidebarblock > div.content { + background: #ffffee; + border: 1px solid silver; + padding: 0.5em; +} + +div.listingblock > div.content { + border: 1px solid silver; + background: #f4f4f4; + padding: 0.5em; +} + +div.quoteblock { + padding-left: 2.0em; + margin-right: 10%; +} +div.quoteblock > div.attribution { + padding-top: 0.5em; + text-align: right; +} + +div.verseblock { + padding-left: 2.0em; + margin-right: 10%; +} +div.verseblock > div.content { + white-space: pre; +} +div.verseblock > div.attribution { + padding-top: 0.75em; + text-align: left; +} +/* DEPRECATED: Pre version 8.2.7 verse style literal block. */ +div.verseblock + div.attribution { + text-align: left; +} + +div.admonitionblock .icon { + vertical-align: top; + font-size: 1.1em; + font-weight: bold; + text-decoration: underline; + color: #527bbd; + padding-right: 0.5em; +} +div.admonitionblock td.content { + padding-left: 0.5em; + border-left: 2px solid silver; +} + +div.exampleblock > div.content { + border-left: 2px solid silver; + padding: 0.5em; +} + +div.imageblock div.content { padding-left: 0; } +span.image img { border-style: none; } +a.image:visited { color: white; } + +dl { + margin-top: 0.8em; + margin-bottom: 0.8em; +} +dt { + margin-top: 0.5em; + margin-bottom: 0; + font-style: normal; + color: navy; +} +dd > *:first-child { + margin-top: 0.1em; +} + +ul, ol { + list-style-position: outside; +} +ol.arabic { + list-style-type: decimal; +} +ol.loweralpha { + list-style-type: lower-alpha; +} +ol.upperalpha { + list-style-type: upper-alpha; +} +ol.lowerroman { + list-style-type: lower-roman; +} +ol.upperroman { + list-style-type: upper-roman; +} + +div.compact ul, div.compact ol, +div.compact p, div.compact p, +div.compact div, div.compact div { + margin-top: 0.1em; + margin-bottom: 0.1em; +} + +div.tableblock > table { + border: 3px solid #527bbd; +} +thead { + font-family: sans-serif; + font-weight: bold; +} +tfoot { + font-weight: bold; +} +td > div.verse { + white-space: pre; +} +p.table { + margin-top: 0; +} +/* Because the table frame attribute is overriden by CSS in most browsers. */ +div.tableblock > table[frame="void"] { + border-style: none; +} +div.tableblock > table[frame="hsides"] { + border-left-style: none; + border-right-style: none; +} +div.tableblock > table[frame="vsides"] { + border-top-style: none; + border-bottom-style: none; +} + + +div.hdlist { + margin-top: 0.8em; + margin-bottom: 0.8em; +} +div.hdlist tr { + padding-bottom: 15px; +} +dt.hdlist1.strong, td.hdlist1.strong { + font-weight: bold; +} +td.hdlist1 { + vertical-align: top; + font-style: normal; + padding-right: 0.8em; + color: navy; +} +td.hdlist2 { + vertical-align: top; +} +div.hdlist.compact tr { + margin: 0; + padding-bottom: 0; +} + +.comment { + background: yellow; +} + +@media print { + div#footer-badges { display: none; } +} + +div#toctitle { + color: #527bbd; + font-family: sans-serif; + font-size: 1.1em; + font-weight: bold; + margin-top: 1.0em; + margin-bottom: 0.1em; +} + +div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 { + margin-top: 0; + margin-bottom: 0; +} +div.toclevel2 { + margin-left: 2em; + font-size: 0.9em; +} +div.toclevel3 { + margin-left: 4em; + font-size: 0.9em; +} +div.toclevel4 { + margin-left: 6em; + font-size: 0.9em; +} From 7b0d063fc17a01ffb6f8b26a2edcb28e847d975e Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 13 Sep 2011 11:47:39 +0200 Subject: [PATCH 091/432] lib: Use @MAJ_VERSION and @MAJ_MINOR@ for -version-info --- lib/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Makefile.am b/lib/Makefile.am index cb5403f..90c98e9 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,7 +1,7 @@ # -*- Makefile -*- AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -I${builddir}/route -I${builddir}/route/cls -D_GNU_SOURCE -DSYSCONFDIR=\"$(sysconfdir)/libnl\" -AM_LDFLAGS = -version-info 3:1:0 +AM_LDFLAGS = -version-info @MAJ_VERSION@:@MIN_VERSION@:0 lib_LTLIBRARIES = \ libnl.la libnl-genl.la libnl-route.la libnl-nf.la From 226b387557b402843d4fc17b1e62c69138549459 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 13 Sep 2011 11:48:18 +0200 Subject: [PATCH 092/432] Install headers in ${includedir}/libnl3 This allows for multiple major versions to be installed in parallel. Pkg-config files are adapted to provide appropriate cflags to find new header locations. --- include/Makefile.am | 4 +++- libnl-3.pc.in | 2 +- libnl-genl-3.pc.in | 2 +- libnl-nf-3.pc.in | 2 +- libnl-route-3.pc.in | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/include/Makefile.am b/include/Makefile.am index e9fa8ad..fa8e9b3 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,6 +1,8 @@ # -*- Makefile -*- -nobase_include_HEADERS = \ +libnlincludedir = $(includedir)/libnl@MAJ_VERSION@ + +nobase_libnlinclude_HEADERS = \ netlink/cli/addr.h \ netlink/cli/class.h \ netlink/cli/cls.h \ diff --git a/libnl-3.pc.in b/libnl-3.pc.in index e44f0fb..05a06fc 100644 --- a/libnl-3.pc.in +++ b/libnl-3.pc.in @@ -7,4 +7,4 @@ Name: libnl Description: Convenience library for netlink sockets Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lnl -Cflags: -I${includedir} +Cflags: -I${includedir}/libnl@MAJ_VERSION@ diff --git a/libnl-genl-3.pc.in b/libnl-genl-3.pc.in index 2167559..e9cbe62 100644 --- a/libnl-genl-3.pc.in +++ b/libnl-genl-3.pc.in @@ -8,4 +8,4 @@ Description: Generic Netlink Library Version: @PACKAGE_VERSION@ Requires: libnl-3 Libs: -L${libdir} -lnl-genl -Cflags: -I${includedir} +Cflags: -I${includedir}/libnl@MAJ_VERSION@ diff --git a/libnl-nf-3.pc.in b/libnl-nf-3.pc.in index 0ec9100..b45eb51 100644 --- a/libnl-nf-3.pc.in +++ b/libnl-nf-3.pc.in @@ -8,4 +8,4 @@ Description: Netfilter Netlink Library Version: @PACKAGE_VERSION@ Requires: libnl-3 Libs: -L${libdir} -lnl-nf -Cflags: -I${includedir} +Cflags: -I${includedir}/libnl@MAJ_VERSION@ diff --git a/libnl-route-3.pc.in b/libnl-route-3.pc.in index 217f6c2..4988616 100644 --- a/libnl-route-3.pc.in +++ b/libnl-route-3.pc.in @@ -8,4 +8,4 @@ Description: Netlink Routing Family Library Version: @PACKAGE_VERSION@ Requires: libnl-3 Libs: -L${libdir} -lnl-route -Cflags: -I${includedir} +Cflags: -I${includedir}/libnl@MAJ_VERSION@ From 6e5332b82303ee9503a5800ed721c45da254e9eb Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 13 Sep 2011 11:49:41 +0200 Subject: [PATCH 093/432] Inform users about changed include location at end of configure script --- configure.in | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/configure.in b/configure.in index 4eb5420..2ee35c3 100644 --- a/configure.in +++ b/configure.in @@ -50,3 +50,18 @@ AC_CONFIG_FILES([Makefile doc/Doxyfile doc/Makefile lib/Makefile python/netlink/route/Makefile include/netlink/version.h]) AC_OUTPUT + +echo ------------------------------------------------------------------------------- +echo NOTE +echo +echo Headers will be installed in ${includedir}/libnl${MAJ_VERSION} starting with +echo version 3.2. If you are using pkg-config things should continue to work as +echo expected, otherwise you will have to extend the CLFAGS of your project with +echo +echo -I${includedir}/libnl${MAJ_VERSION} +echo +echo Also, pkg-config files for sub libraries have been added, so you can +echo verify their presence +echo +echo ------------------------------------------------------------------------------- + From a73cb2f26932d90a2d47a28e9c524e7f33dcffbd Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Wed, 24 Aug 2011 12:09:46 +0200 Subject: [PATCH 094/432] build: always install files into /etc/libnl I observed that with the RedHat build target in the Open Build Service, files were put into /etc rather than /etc/libnl. Self-referential variables are a bad idea, and so just avoid this. --- Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index e152685..6706e4b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -15,8 +15,8 @@ pkgconfig_DATA = libnl-3.pc \ libnl-genl-3.pc \ libnl-nf-3.pc -sysconfdir = @sysconfdir@/libnl -sysconf_DATA = etc/pktloc etc/classid +pkgsysconfdir = ${sysconfdir}/libnl +pkgsysconf_DATA = etc/pktloc etc/classid EXTRA_DIST = \ $(sysconf_DATA) From 4c210adcb572d8950fdc6b5135406e06e55f8b56 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 13 Sep 2011 22:58:08 +0200 Subject: [PATCH 095/432] Switch to libtool versioning system It has been a request that multiple libnl versions should be installabe in parallel. In order to achieve this, the basename of the library was changed to libnl-3 which reflects the 3rd generation of libnl APIs. It also means that release based library versioning is left behind and libtool versioning is used instead. Projects using pkgconfig will automatically link against the new library basename and will not notice a difference. The SO versioning is based on the glib model: current := 100 * minor + micro - revision revision := revision age := age (number of backwards compatible versions) --- Makefile.am | 8 +- configure.in | 89 ++++++++++++++------ doc/core.txt | 23 ++++- include/netlink/version.h.in | 4 + lib/Makefile.am | 31 ++++--- libnl-3.pc.in => libnl-3.0.pc.in | 2 +- libnl-genl-3.pc.in => libnl-genl-3.0.pc.in | 4 +- libnl-nf-3.pc.in => libnl-nf-3.0.pc.in | 4 +- libnl-route-3.pc.in => libnl-route-3.0.pc.in | 4 +- src/lib/Makefile.am | 17 ++-- 10 files changed, 131 insertions(+), 55 deletions(-) rename libnl-3.pc.in => libnl-3.0.pc.in (85%) rename libnl-genl-3.pc.in => libnl-genl-3.0.pc.in (76%) rename libnl-nf-3.pc.in => libnl-nf-3.0.pc.in (75%) rename libnl-route-3.pc.in => libnl-route-3.0.pc.in (77%) diff --git a/Makefile.am b/Makefile.am index 6706e4b..a936c49 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,10 +10,10 @@ endif SUBDIRS = include lib doc man python $(OPT_DIRS) -pkgconfig_DATA = libnl-3.pc \ - libnl-route-3.pc \ - libnl-genl-3.pc \ - libnl-nf-3.pc +pkgconfig_DATA = libnl-3.0.pc \ + libnl-route-3.0.pc \ + libnl-genl-3.0.pc \ + libnl-nf-3.0.pc pkgsysconfdir = ${sysconfdir}/libnl pkgsysconf_DATA = etc/pktloc etc/classid diff --git a/configure.in b/configure.in index 2ee35c3..b1b4f11 100644 --- a/configure.in +++ b/configure.in @@ -9,16 +9,43 @@ # Copyright (c) 2003-2011 Thomas Graf # -AC_INIT(libnl, 3.2, tgraf@suug.ch) + +# copied from glib +m4_define([libnl_major_version], [3]) +m4_define([libnl_minor_version], [2]) +m4_define([libnl_micro_version], [0]) # bump for every release unless minor was bumped +m4_define([libnl_lt_revision], [0]) # bump or reset to 0 if interfaces were added +m4_define([libnl_lt_age], [0]) # bump whenever a release is backwards compatible + # bump with +100 if a minor release is compatible + # reset to 0 if interfaces were removed + +m4_define([libnl_version], + [libnl_major_version.libnl_minor_version.libnl_micro_version]) + +m4_define([libnl_lt_current], + [m4_eval(100 * libnl_minor_version + libnl_micro_version - libnl_lt_revision)]) + +AC_INIT(libnl, [libnl_version], [http://www.infradead.org/~tgr/libnl/]) AC_CONFIG_HEADERS([lib/defs.h]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([-Wall foreign subdir-objects]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES(yes)], []) -MAJ_VERSION=3 -AC_SUBST([MAJ_VERSION]) -MIN_VERSION=2 -AC_SUBST([MIN_VERSION]) +MAJ_VERSION=libnl_major_version +AC_SUBST(MAJ_VERSION) +MIN_VERSION=libnl_minor_version +AC_SUBST(MIN_VERSION) +MIC_VERSION=libnl_micro_version +AC_SUBST(MIC_VERSION) +LIBNL_VERSION=libnl_version +AC_SUBST(LIBNL_VERSION) + +LT_CURRENT=libnl_lt_current +AC_SUBST(LT_CURRENT) +LT_REVISION=libnl_lt_revision +AC_SUBST(LT_REVISION) +LT_AGE=libnl_lt_age +AC_SUBST(LT_AGE) AC_PROG_CC AM_PROG_CC_C_O @@ -43,25 +70,39 @@ AM_CONDITIONAL([ENABLE_CLI], [test "$enable_cli" = "yes"]) AC_CHECK_LIB([m], [pow], [], AC_MSG_ERROR([libm is required])) AC_CHECK_LIB([pthread], [pthread_mutex_lock], [], AC_MSG_ERROR([libpthread is required])) -AC_CONFIG_FILES([Makefile doc/Doxyfile doc/Makefile lib/Makefile - include/Makefile src/Makefile src/lib/Makefile man/Makefile - libnl-3.pc libnl-route-3.pc libnl-genl-3.pc libnl-nf-3.pc - python/Makefile python/setup.py python/netlink/Makefile - python/netlink/route/Makefile - include/netlink/version.h]) +AC_CONFIG_FILES([ +Makefile +libnl-3.0.pc +libnl-route-3.0.pc +libnl-genl-3.0.pc +libnl-nf-3.0.pc +doc/Doxyfile +doc/Makefile +lib/Makefile +include/Makefile +src/Makefile +src/lib/Makefile +man/Makefile +python/Makefile +python/setup.py +python/netlink/Makefile +python/netlink/route/Makefile +include/netlink/version.h +]) + AC_OUTPUT -echo ------------------------------------------------------------------------------- -echo NOTE -echo -echo Headers will be installed in ${includedir}/libnl${MAJ_VERSION} starting with -echo version 3.2. If you are using pkg-config things should continue to work as -echo expected, otherwise you will have to extend the CLFAGS of your project with -echo -echo -I${includedir}/libnl${MAJ_VERSION} -echo -echo Also, pkg-config files for sub libraries have been added, so you can -echo verify their presence -echo -echo ------------------------------------------------------------------------------- +echo "-------------------------------------------------------------------------------" +echo " NOTE" +echo "" +echo " Headers will be installed in ${includedir}/libnl${MAJ_VERSION} starting with" +echo " version 3.2. If you are using pkg-config things should continue to work as" +echo " expected, otherwise you will have to extend the CLFAGS of your project with" +echo "" +echo " -I${includedir}/libnl${MAJ_VERSION}" +echo "" +echo " Also, pkg-config files for sub libraries have been added, so you can" +echo " verify their presence" +echo "" +echo "-------------------------------------------------------------------------------" diff --git a/doc/core.txt b/doc/core.txt index 796e9fc..c10cbc0 100644 --- a/doc/core.txt +++ b/doc/core.txt @@ -7,7 +7,7 @@ Netlink Library (libnl) ======================= Thomas Graf -3.1, Aug 11 2011: +3.2, Sep 13 2011: :numbered: == Introduction @@ -59,6 +59,25 @@ The low level APIs are described in: === Linking to this Library +.Checking the presence using autoconf + +Projects using autoconf may use +PKG_CHECK_MODULES()+ to check if +a specific version of libnl is available on the system. The example +below also shows how to retrieve the +CFLAGS+ and linking dependencies +required to link against the library. + +[source] +---- +PKG_CHECK_MODULES(LIBNL3, libnl-3.0 >= 3.1, [have_libnl3=yes], [have_libnl3=no]) +if (test "${have_libnl3}" = "yes"); then + CFLAGS += "$LIBNL3_CFLAGS" + LIBS += "$LIBNL3_LIBS" +fi +---- + +NOTE: The pkgconfig file is named +libnl-3.0.pc+ for historic reasons, it also + covers library versions >= 3.1. + .Main Header The main header is ``. Additional headers need to @@ -77,7 +96,7 @@ makes use of. .Linking to libnl ----- -$ gcc myprogram.c -o myprogram -lnl +$ gcc myprogram.c -o myprogram $(pkgconfig --cflags --libs libnl-3.0) ----- === Debugging diff --git a/include/netlink/version.h.in b/include/netlink/version.h.in index 9deb365..4d32dad 100644 --- a/include/netlink/version.h.in +++ b/include/netlink/version.h.in @@ -20,4 +20,8 @@ #define LIBNL_VER(maj,min) ((maj) << 8 | (min)) #define LIBNL_VER_NUM LIBNL_VER(LIBNL_VER_MAJ, LIBNL_VER_MIN) +#define LIBNL_CURRENT @LT_CURRENT@ +#define LIBNL_REVISION @LT_REVISION@ +#define LIBNL_AGE @LT_AGE@ + #endif diff --git a/lib/Makefile.am b/lib/Makefile.am index 90c98e9..da2dbf6 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,21 +1,30 @@ # -*- Makefile -*- -AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -I${builddir}/route -I${builddir}/route/cls -D_GNU_SOURCE -DSYSCONFDIR=\"$(sysconfdir)/libnl\" -AM_LDFLAGS = -version-info @MAJ_VERSION@:@MIN_VERSION@:0 +AM_CPPFLAGS = \ + -Wall \ + -I${top_srcdir}/include \ + -I${top_builddir}/include \ + -I${builddir}/route \ + -I${builddir}/route/cls \ + -D_GNU_SOURCE \ + -DSYSCONFDIR=\"$(sysconfdir)/libnl\" + +AM_LDFLAGS = \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) lib_LTLIBRARIES = \ - libnl.la libnl-genl.la libnl-route.la libnl-nf.la + libnl-3.la libnl-genl-3.la libnl-route-3.la libnl-nf-3.la -libnl_la_SOURCES = \ +libnl_3_la_SOURCES = \ addr.c attr.c cache.c cache_mngr.c cache_mngt.c data.c \ error.c handlers.c msg.c nl.c object.c socket.c utils.c -libnl_genl_la_LIBADD = libnl.la -libnl_genl_la_SOURCES = \ +libnl_genl_3_la_LIBADD = libnl-3.la +libnl_genl_3_la_SOURCES = \ genl/ctrl.c genl/family.c genl/genl.c genl/mngt.c -libnl_nf_la_LIBADD = libnl-route.la -libnl_nf_la_SOURCES = \ +libnl_nf_3_la_LIBADD = libnl-route-3.la +libnl_nf_3_la_SOURCES = \ netfilter/ct.c netfilter/ct_obj.c netfilter/log.c \ netfilter/log_msg.c netfilter/log_msg_obj.c netfilter/log_obj.c \ netfilter/netfilter.c netfilter/nfnl.c netfilter/queue.c \ @@ -41,8 +50,8 @@ route/cls/ematch_grammar.c: route/cls/ematch_grammar.l route/cls/ematch_syntax.c: route/cls/ematch_syntax.y $(AM_V_GEN) $(YACC) -d $(YFLAGS) -o $@ $^ -libnl_route_la_LIBADD = libnl.la -libnl_route_la_SOURCES = \ +libnl_route_3_la_LIBADD = libnl-3.la +libnl_route_3_la_SOURCES = \ route/addr.c route/class.c route/cls.c route/link.c \ route/neigh.c route/neightbl.c route/nexthop.c route/qdisc.c \ route/route.c route/route_obj.c route/route_utils.c route/rtnl.c \ @@ -69,7 +78,7 @@ libnl_route_la_SOURCES = \ \ route/pktloc.c -nodist_libnl_route_la_SOURCES = \ +nodist_libnl_route_3_la_SOURCES = \ route/pktloc_syntax.c route/pktloc_syntax.h \ route/pktloc_grammar.c route/pktloc_grammar.h \ route/cls/ematch_syntax.c route/cls/ematch_syntax.h \ diff --git a/libnl-3.pc.in b/libnl-3.0.pc.in similarity index 85% rename from libnl-3.pc.in rename to libnl-3.0.pc.in index 05a06fc..b87e3dc 100644 --- a/libnl-3.pc.in +++ b/libnl-3.0.pc.in @@ -6,5 +6,5 @@ includedir=@includedir@ Name: libnl Description: Convenience library for netlink sockets Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lnl +Libs: -L${libdir} -lnl-@MAJ_VERSION@ Cflags: -I${includedir}/libnl@MAJ_VERSION@ diff --git a/libnl-genl-3.pc.in b/libnl-genl-3.0.pc.in similarity index 76% rename from libnl-genl-3.pc.in rename to libnl-genl-3.0.pc.in index e9cbe62..d6b69b8 100644 --- a/libnl-genl-3.pc.in +++ b/libnl-genl-3.0.pc.in @@ -6,6 +6,6 @@ includedir=@includedir@ Name: libnl-genl Description: Generic Netlink Library Version: @PACKAGE_VERSION@ -Requires: libnl-3 -Libs: -L${libdir} -lnl-genl +Requires: libnl-3.0 +Libs: -L${libdir} -lnl-genl-@MAJ_VERSION@ Cflags: -I${includedir}/libnl@MAJ_VERSION@ diff --git a/libnl-nf-3.pc.in b/libnl-nf-3.0.pc.in similarity index 75% rename from libnl-nf-3.pc.in rename to libnl-nf-3.0.pc.in index b45eb51..d82e1a6 100644 --- a/libnl-nf-3.pc.in +++ b/libnl-nf-3.0.pc.in @@ -6,6 +6,6 @@ includedir=@includedir@ Name: libnl-nf Description: Netfilter Netlink Library Version: @PACKAGE_VERSION@ -Requires: libnl-3 -Libs: -L${libdir} -lnl-nf +Requires: libnl-route-3.0 +Libs: -L${libdir} -lnl-nf-@MAJ_VERSION@ Cflags: -I${includedir}/libnl@MAJ_VERSION@ diff --git a/libnl-route-3.pc.in b/libnl-route-3.0.pc.in similarity index 77% rename from libnl-route-3.pc.in rename to libnl-route-3.0.pc.in index 4988616..372a4f4 100644 --- a/libnl-route-3.pc.in +++ b/libnl-route-3.0.pc.in @@ -6,6 +6,6 @@ includedir=@includedir@ Name: libnl-route Description: Netlink Routing Family Library Version: @PACKAGE_VERSION@ -Requires: libnl-3 -Libs: -L${libdir} -lnl-route +Requires: libnl-3.0 +Libs: -L${libdir} -lnl-route-@MAJ_VERSION@ Cflags: -I${includedir}/libnl@MAJ_VERSION@ diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 3236dbe..a88163a 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -1,7 +1,10 @@ # -*- Makefile -*- AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -D_GNU_SOURCE -DPKGLIBDIR=\"$(pkglibdir)\" -DSYSCONFDIR=\"$(sysconfdir)\" -rdynamic -AM_LDFLAGS = -L${top_builddir}/lib -ldl -version-info 3:0:0 +AM_LDFLAGS = \ + -L${top_builddir}/lib \ + -ldl \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) #nobase_pkglib_LTLIBRARIES = cls/basic.la cls/ematch/cmp.la #cls_basic_la_LDFLAGS = -module -version-info 2:0:0 @@ -26,14 +29,14 @@ AM_LDFLAGS = -L${top_builddir}/lib -ldl -version-info 3:0:0 # cls/pktloc_syntax.c cls/pktloc_syntax.h lib_LTLIBRARIES = \ - libnl-cli.la + libnl-cli-3.la -libnl_cli_la_LIBADD = ${top_builddir}/lib/libnl.la \ - ${top_builddir}/lib/libnl-route.la \ - ${top_builddir}/lib/libnl-nf.la \ - ${top_builddir}/lib/libnl-genl.la +libnl_cli_3_la_LIBADD = ${top_builddir}/lib/libnl-3.la \ + ${top_builddir}/lib/libnl-route-3.la \ + ${top_builddir}/lib/libnl-nf-3.la \ + ${top_builddir}/lib/libnl-genl-3.la -libnl_cli_la_SOURCES = \ +libnl_cli_3_la_SOURCES = \ utils.c addr.c ct.c link.c neigh.c rule.c route.c \ tc.c qdisc.c class.c cls.c # cls/ematch_syntax.c cls/ematch_grammar.c cls/ematch.c From b50195c691dc30fd3240a3601596133f178d2d79 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 13 Sep 2011 23:13:51 +0200 Subject: [PATCH 096/432] addr: Add missing header to Fixes a gcc warning --- include/netlink/route/addr.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/netlink/route/addr.h b/include/netlink/route/addr.h index df447f7..56c12e7 100644 --- a/include/netlink/route/addr.h +++ b/include/netlink/route/addr.h @@ -17,6 +17,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { From 6d93b831dd6a8e4720ffcd3e3566ba516c0f44d4 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 13 Sep 2011 23:16:09 +0200 Subject: [PATCH 097/432] route: Remove dead link_cache variable --- lib/route/route_obj.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/route/route_obj.c b/lib/route/route_obj.c index 3d208b4..834cb91 100644 --- a/lib/route/route_obj.c +++ b/lib/route/route_obj.c @@ -125,12 +125,9 @@ static int route_clone(struct nl_object *_dst, struct nl_object *_src) static void route_dump_line(struct nl_object *a, struct nl_dump_params *p) { struct rtnl_route *r = (struct rtnl_route *) a; - struct nl_cache *link_cache; int cache = 0, flags; char buf[64]; - link_cache = nl_cache_mngt_require("route/link"); - if (r->rt_flags & RTM_F_CLONED) cache = 1; From 109ea68ac0c12f9a21197380d0925d4aa79d6a15 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 13 Sep 2011 23:21:52 +0200 Subject: [PATCH 098/432] tools: Use LDADD and link against .la files instead of LDFLAGS and -llib --- src/Makefile.am | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index e196b58..3b5c140 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -3,7 +3,13 @@ SUBDIRS = lib AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -D_GNU_SOURCE -DSYSCONFDIR=\"$(sysconfdir)/libnl\" -AM_LDFLAGS = -L${top_builddir}/lib -L${top_builddir}/src/lib -lnl-cli -lnl -lnl-nf -lnl-genl -lnl-route + +LDADD = \ + ${top_builddir}/src/lib/libnl-cli-3.la \ + ${top_builddir}/lib/libnl-3.la \ + ${top_builddir}/lib/libnl-nf-3.la \ + ${top_builddir}/lib/libnl-genl-3.la \ + ${top_builddir}/lib/libnl-route-3.la sbin_PROGRAMS = \ nl-qdisc-add nl-qdisc-list nl-qdisc-delete \ From 67bd56f21463bc93c81b4a7a0bf3d51d56120b58 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 13 Sep 2011 23:33:06 +0200 Subject: [PATCH 099/432] Fix a73cb2f26 fallout to allow building in separate directory Commit a73cb2f26932d90a2d47a28e9c524e7f33dcffbd missed to change the EXTRA_DATA section --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index a936c49..70d1b76 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,7 +19,7 @@ pkgsysconfdir = ${sysconfdir}/libnl pkgsysconf_DATA = etc/pktloc etc/classid EXTRA_DIST = \ - $(sysconf_DATA) + $(pkgsysconf_DATA) .PHONY: cscope cscope: From 5151cbc2f6e5ca81cfc66eeb1d4a5c6c4e886108 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 14 Sep 2011 11:43:10 +0200 Subject: [PATCH 100/432] link: Eat ACK followed by RTM_NEWLINK when requesting single link When requesting a single link with RTM_GETLINK (no dump) the RTM_NEWLINK carrying the answer will be followed by an ACK we have to wait for. --- lib/route/link.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/route/link.c b/lib/route/link.c index 3e070e5..00beb08 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -996,6 +996,10 @@ int rtnl_link_get_kernel(struct nl_sock *sk, int ifindex, const char *name, /* We have used link_msg_parser(), object is definitely a link */ *result = (struct rtnl_link *) obj; + /* If an object has been returned, we also need to wait for the ACK */ + if (err == 0 && obj) + nl_wait_for_ack(sk); + return 0; } From 96f17ce146b35fda3f745a418352d731c522265e Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 16 Sep 2011 12:57:52 +0200 Subject: [PATCH 101/432] bonding: API to create/enslave/release Although it has been possible to create bonding devices, enslave and release using the regular link API. The added API simplifies usage and hides some of the compatibility logic. F.e. enslave() and release() will both verify that the master assignment has in fact been changed and return -NLE_OPNOTSUPP if it did not. Also the API will make sure to use RTM_NEWLINK or RTM_SETLINK depending on what is availble. Examples are provided in src/ as nl-link-enslave.c and nl-link-release.c --- include/netlink/route/link/bonding.h | 37 ++++++ lib/route/link/bonding.c | 176 +++++++++++++++++++++++++++ src/Makefile.am | 4 +- src/nl-link-enslave.c | 50 ++++++++ src/nl-link-release.c | 45 +++++++ 5 files changed, 311 insertions(+), 1 deletion(-) create mode 100644 include/netlink/route/link/bonding.h create mode 100644 src/nl-link-enslave.c create mode 100644 src/nl-link-release.c diff --git a/include/netlink/route/link/bonding.h b/include/netlink/route/link/bonding.h new file mode 100644 index 0000000..cca777a --- /dev/null +++ b/include/netlink/route/link/bonding.h @@ -0,0 +1,37 @@ +/* + * netlink/route/link/bonding.h Bonding Interface + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2011 Thomas Graf + */ + +#ifndef NETLINK_LINK_VLAN_H_ +#define NETLINK_LINK_VLAN_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int rtnl_link_bond_add(struct nl_sock *, const char *, + struct rtnl_link *); + +extern int rtnl_link_bond_enslave_ifindex(struct nl_sock *, int, int); +extern int rtnl_link_bond_enslave(struct nl_sock *, struct rtnl_link *, + struct rtnl_link *); + +extern int rtnl_link_bond_release_ifindex(struct nl_sock *, int); +extern int rtnl_link_bond_release(struct nl_sock *, struct rtnl_link *); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/lib/route/link/bonding.c b/lib/route/link/bonding.c index 176be27..5788f69 100644 --- a/lib/route/link/bonding.c +++ b/lib/route/link/bonding.c @@ -24,6 +24,182 @@ #include #include +/** + * Create a new kernel bonding device + * @arg sock netlink socket + * @arg name name of bonding device or NULL + * @arg opts bonding options (currently unused) + * + * Creates a new bonding device in the kernel. If no name is + * provided, the kernel will automatically pick a name of the + * form "type%d" (e.g. bond0, vlan1, etc.) + * + * The \a opts argument is currently unused. In the future, it + * may be used to carry additional bonding options to be set + * when creating the bonding device. + * + * @note When letting the kernel assign a name, it will become + * difficult to retrieve the interface afterwards because + * you have to guess the name the kernel has chosen. It is + * therefore not recommended to not provide a device name. + * + * @see rtnl_link_bond_enslave() + * @see rtnl_link_bond_release() + * + * @return 0 on success or a negative error code + */ +int rtnl_link_bond_add(struct nl_sock *sock, const char *name, + struct rtnl_link *opts) +{ + struct rtnl_link *link; + int err; + + if (!(link = rtnl_link_alloc())) + return -NLE_NOMEM; + + if (!name) { + if (opts) + name = rtnl_link_get_name(opts); + + if (!name) + return -NLE_MISSING_ATTR; + } + + if ((err = rtnl_link_set_type(link, "bond")) < 0) + goto errout; + + + rtnl_link_set_name(link, name); + + err = rtnl_link_add(sock, link, NLM_F_CREATE); +errout: + rtnl_link_put(link); + + return err; +} + +/** + * Add a link to a bond (enslave) + * @arg sock netlink socket + * @arg master ifindex of bonding master + * @arg slave ifindex of slave link to add to bond + * + * This function is identical to rtnl_link_bond_enslave() except that + * it takes interface indices instead of rtnl_link objcets. + * + * @see rtnl_link_bond_enslave() + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_bond_enslave_ifindex(struct nl_sock *sock, int master, + int slave) +{ + struct rtnl_link *link; + int err; + + if (!(link = rtnl_link_alloc())) + return -NLE_NOMEM; + + if ((err = rtnl_link_set_type(link, "bond")) < 0) + goto errout; + + rtnl_link_set_ifindex(link, slave); + rtnl_link_set_master(link, master); + + if ((err = rtnl_link_change(sock, link, link, 0)) < 0) + goto errout; + + rtnl_link_put(link); + + /* + * Due to the kernel not signaling whether this opertion is + * supported or not, we will retrieve the attribute to see if the + * request was successful. If the master assigned remains unchanged + * we will return NLE_OPNOTSUPP to allow performing backwards + * compatibility of some sort. + */ + if ((err = rtnl_link_get_kernel(sock, slave, NULL, &link)) < 0) + return err; + + if (rtnl_link_get_master(link) != master) + err = -NLE_OPNOTSUPP; + +errout: + rtnl_link_put(link); + + return err; +} + +/** + * Add a link to a bond (enslave) + * @arg sock netlink socket + * @arg master bonding master + * @arg slave slave link to add to bond + * + * Constructs a RTM_NEWLINK or RTM_SETLINK message adding the slave to + * the master and sends the request via the specified netlink socket. + * + * @note The feature of enslaving/releasing via netlink has only been added + * recently to the kernel (Feb 2011). Also, the kernel does not signal + * if the operation is not supported. Therefore this function will + * verify if the master assignment has changed and will return + * -NLE_OPNOTSUPP if it did not. + * + * @see rtnl_link_bond_enslave_ifindex() + * @see rtnl_link_bond_release() + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_bond_enslave(struct nl_sock *sock, struct rtnl_link *master, + struct rtnl_link *slave) +{ + return rtnl_link_bond_enslave_ifindex(sock, + rtnl_link_get_ifindex(master), + rtnl_link_get_ifindex(slave)); +} + +/** + * Release a link from a bond + * @arg sock netlink socket + * @arg slave slave link to be released + * + * This function is identical to rtnl_link_bond_release() except that + * it takes an interface index instead of a rtnl_link object. + * + * @see rtnl_link_bond_release() + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_bond_release_ifindex(struct nl_sock *sock, int slave) +{ + return rtnl_link_bond_enslave_ifindex(sock, 0, slave); +} + +/** + * Release a link from a bond + * @arg sock netlink socket + * @arg slave slave link to be released + * + * Constructs a RTM_NEWLINK or RTM_SETLINK message releasing the slave from + * its master and sends the request via the specified netlink socket. + * + * @note The feature of enslaving/releasing via netlink has only been added + * recently to the kernel (Feb 2011). Also, the kernel does not signal + * if the operation is not supported. Therefore this function will + * verify if the master assignment has changed and will return + * -NLE_OPNOTSUPP if it did not. + * + * @see rtnl_link_bond_release_ifindex() + * @see rtnl_link_bond_enslave() + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_bond_release(struct nl_sock *sock, struct rtnl_link *slave) +{ + return rtnl_link_bond_release_ifindex(sock, + rtnl_link_get_ifindex(slave)); +} + static struct rtnl_link_info_ops bonding_info_ops = { .io_name = "bond", }; diff --git a/src/Makefile.am b/src/Makefile.am index 3b5c140..b59f96a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -33,7 +33,9 @@ noinst_PROGRAMS = \ nl-route-add nl-route-delete nl-route-get nl-route-list \ nl-fib-lookup \ nl-list-caches nl-list-sockets \ - nl-util-addr + nl-util-addr \ + nl-link-enslave \ + nl-link-release genl_ctrl_list_SOURCES = genl-ctrl-list.c diff --git a/src/nl-link-enslave.c b/src/nl-link-enslave.c new file mode 100644 index 0000000..2b5d47d --- /dev/null +++ b/src/nl-link-enslave.c @@ -0,0 +1,50 @@ +/* + * src/nl-link-enslave.c Enslave a link + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2011 Thomas Graf + */ + +#include +#include +#include + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct nl_cache *link_cache; + struct rtnl_link *master, *slave; + int err; + + if (argc < 3) { + fprintf(stderr, "Usage: nl-link-enslave master slave\n"); + return 1; + } + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(sock); + + if (!(master = rtnl_link_get_by_name(link_cache, argv[1]))) { + fprintf(stderr, "Unknown link: %s\n", argv[1]); + return 1; + } + + if (!(slave = rtnl_link_get_by_name(link_cache, argv[2]))) { + fprintf(stderr, "Unknown link: %s\n", argv[2]); + return 1; + } + + if ((err = rtnl_link_bond_enslave(sock, master, slave)) < 0) { + fprintf(stderr, "Unable to enslave %s to %s: %s\n", + argv[2], argv[1], nl_geterror(err)); + return 1; + } + + return 0; +} + diff --git a/src/nl-link-release.c b/src/nl-link-release.c new file mode 100644 index 0000000..4c9f15a --- /dev/null +++ b/src/nl-link-release.c @@ -0,0 +1,45 @@ +/* + * src/nl-link-release.c release a link + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2011 Thomas Graf + */ + +#include +#include +#include + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct nl_cache *link_cache; + struct rtnl_link *slave; + int err; + + if (argc < 2) { + fprintf(stderr, "Usage: nl-link-release slave\n"); + return 1; + } + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(sock); + + if (!(slave = rtnl_link_get_by_name(link_cache, argv[1]))) { + fprintf(stderr, "Unknown link: %s\n", argv[1]); + return 1; + } + + if ((err = rtnl_link_bond_release(sock, slave)) < 0) { + fprintf(stderr, "Unable to release slave %s: %s\n", + argv[1], nl_geterror(err)); + return 1; + } + + return 0; +} + From 15b13ddbde155d8fc348d882636675d79136469d Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 16 Sep 2011 13:07:03 +0200 Subject: [PATCH 102/432] bonding: Install --- include/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/include/Makefile.am b/include/Makefile.am index fa8e9b3..515c237 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -52,6 +52,7 @@ nobase_libnlinclude_HEADERS = \ netlink/route/cls/police.h \ netlink/route/cls/u32.h \ netlink/route/link/api.h \ + netlink/route/link/bonding.h \ netlink/route/link/info-api.h \ netlink/route/link/inet.h \ netlink/route/link/vlan.h \ From 076909aa82cf063ca02e4b93e0c41b2b7452d4c3 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 16 Sep 2011 13:17:04 +0200 Subject: [PATCH 103/432] Bonding: Fix header guard of (Would be a good idea to change the header guard name when c&p an existing header file to create a new one.) --- include/netlink/route/link/bonding.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/netlink/route/link/bonding.h b/include/netlink/route/link/bonding.h index cca777a..78ee6bd 100644 --- a/include/netlink/route/link/bonding.h +++ b/include/netlink/route/link/bonding.h @@ -9,8 +9,8 @@ * Copyright (c) 2011 Thomas Graf */ -#ifndef NETLINK_LINK_VLAN_H_ -#define NETLINK_LINK_VLAN_H_ +#ifndef NETLINK_LINK_BONDING_H_ +#define NETLINK_LINK_BONDING_H_ #include #include From 0d9958e9ef4152f106867f0e1490d495795cc800 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Mon, 19 Sep 2011 11:24:52 +0200 Subject: [PATCH 104/432] Ingnore src/nl-link-enslave and nl-link-release --- src/.gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/.gitignore b/src/.gitignore index 6385293..cad6f75 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -37,3 +37,5 @@ nl-util-addr nf-queue nl-classid-lookup nl-pktloc-lookup +nl-link-enslave +nl-link-release From 1c9b175a47530f7ce38d934856a08df284c9cb8f Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Mon, 19 Sep 2011 11:28:20 +0200 Subject: [PATCH 105/432] Provide micro version in --- include/netlink/version.h.in | 1 + 1 file changed, 1 insertion(+) diff --git a/include/netlink/version.h.in b/include/netlink/version.h.in index 4d32dad..ac56799 100644 --- a/include/netlink/version.h.in +++ b/include/netlink/version.h.in @@ -17,6 +17,7 @@ #define LIBNL_VER_MAJ @MAJ_VERSION@ #define LIBNL_VER_MIN @MIN_VERSION@ +#define LIBNL_VER_MIC @MIC_VERSION@ #define LIBNL_VER(maj,min) ((maj) << 8 | (min)) #define LIBNL_VER_NUM LIBNL_VER(LIBNL_VER_MAJ, LIBNL_VER_MIN) From d3bb7c9cf16587c71fc01311fe6d8ae5a0280246 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Mon, 19 Sep 2011 11:47:49 +0200 Subject: [PATCH 106/432] 3.2.1 release Added more details on the changes to where and how libnl is being instaslled since 3.2.0 --- configure.in | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/configure.in b/configure.in index b1b4f11..a9e3a7a 100644 --- a/configure.in +++ b/configure.in @@ -13,9 +13,9 @@ # copied from glib m4_define([libnl_major_version], [3]) m4_define([libnl_minor_version], [2]) -m4_define([libnl_micro_version], [0]) # bump for every release unless minor was bumped +m4_define([libnl_micro_version], [1]) # bump for every release unless minor was bumped m4_define([libnl_lt_revision], [0]) # bump or reset to 0 if interfaces were added -m4_define([libnl_lt_age], [0]) # bump whenever a release is backwards compatible +m4_define([libnl_lt_age], [1]) # bump whenever a release is backwards compatible # bump with +100 if a minor release is compatible # reset to 0 if interfaces were removed @@ -95,14 +95,26 @@ AC_OUTPUT echo "-------------------------------------------------------------------------------" echo " NOTE" echo "" -echo " Headers will be installed in ${includedir}/libnl${MAJ_VERSION} starting with" -echo " version 3.2. If you are using pkg-config things should continue to work as" -echo " expected, otherwise you will have to extend the CLFAGS of your project with" +echo " There have been some changes starting with 3.2 regarding where and how libnl" +echo " is being installed on the system in order to allow multiple libnl versions" +echo " to be installed in parallel:" echo "" -echo " -I${includedir}/libnl${MAJ_VERSION}" +echo " - Headers will be installed in ${includedir}/libnl${MAJ_VERSION}, therefore" +echo " you will need to add \"-I/usr/include/libnl${MAJ_VERSION}\" to CFLAGS" echo "" -echo " Also, pkg-config files for sub libraries have been added, so you can" -echo " verify their presence" +echo " - The library basename was renamed to libnl-${MAJ_VERSION}, i.e. the SO names become" +echo " libnl-${MAJ_VERSION}.so., libnl-route-${MAJ_VERSION}.so, etc." +echo "" +echo " - libtool versioning was assumed, to ease detection of compatible library" +echo " versions. libnl-${MAJ_VERSION}.so.CURRENT.REVISION.AGE where." +echo " CURRENT := 100 * \$MINOR_VERSION + \$MICRO_VERSION" +echo " REVISION := nth revision if API was unchanged" +echo " AGE := nth revision that is backwards compatible." +echo "" +echo " If you are using pkg-config for detecting and linking against the library " +echo " things will continue magically as if nothing every happened. If you are " +echo " linking manually you need to adapt your Makefiles or switch to using " +echo " pkg-config files." echo "" echo "-------------------------------------------------------------------------------" From f90dc636cbe69ce157b395d0ae8c06b82ac965e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20=C5=BDupka?= Date: Tue, 4 Oct 2011 16:06:22 +0200 Subject: [PATCH 107/432] Add libnl-cli-3.0 to pkg-config tool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jiří Župka --- Makefile.am | 6 +++++- configure.in | 1 + libnl-cli-3.0.pc.in | 11 +++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 libnl-cli-3.0.pc.in diff --git a/Makefile.am b/Makefile.am index 70d1b76..4b8f020 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,9 +3,11 @@ ACLOCAL_AMFLAGS = -I m4 OPT_DIRS = +PKGCONFIGS = if ENABLE_CLI OPT_DIRS += src +PKGCONFIGS += libnl-cli-3.0.pc endif SUBDIRS = include lib doc man python $(OPT_DIRS) @@ -13,7 +15,9 @@ SUBDIRS = include lib doc man python $(OPT_DIRS) pkgconfig_DATA = libnl-3.0.pc \ libnl-route-3.0.pc \ libnl-genl-3.0.pc \ - libnl-nf-3.0.pc + libnl-nf-3.0.pc \ + $(PKGCONFIGS) + pkgsysconfdir = ${sysconfdir}/libnl pkgsysconf_DATA = etc/pktloc etc/classid diff --git a/configure.in b/configure.in index a9e3a7a..31b5bff 100644 --- a/configure.in +++ b/configure.in @@ -76,6 +76,7 @@ libnl-3.0.pc libnl-route-3.0.pc libnl-genl-3.0.pc libnl-nf-3.0.pc +libnl-cli-3.0.pc doc/Doxyfile doc/Makefile lib/Makefile diff --git a/libnl-cli-3.0.pc.in b/libnl-cli-3.0.pc.in new file mode 100644 index 0000000..d3638ba --- /dev/null +++ b/libnl-cli-3.0.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libnl-cli +Description: Command Line Interface library for netlink sockets +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lnl-cli-@MAJ_VERSION@ +Cflags: -I${includedir} +Requires: libnl-3.0 libnl-genl-3.0 libnl-nf-3.0 libnl-route-3.0 From d17379d1950df679d5560608b2e54aaaa10ab54e Mon Sep 17 00:00:00 2001 From: Michael Altizer Date: Sun, 9 Oct 2011 17:02:34 -0400 Subject: [PATCH 108/432] Fix rtnl_link object memory leak when freeing rtnl_addr objects. Signed-off-by: Michael Altizer --- lib/route/addr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/route/addr.c b/lib/route/addr.c index 4ca6335..deb88ba 100644 --- a/lib/route/addr.c +++ b/lib/route/addr.c @@ -151,6 +151,7 @@ static void addr_free_data(struct nl_object *obj) nl_addr_put(addr->a_bcast); nl_addr_put(addr->a_multicast); nl_addr_put(addr->a_anycast); + rtnl_link_put(addr->a_link); } static int addr_clone(struct nl_object *_dst, struct nl_object *_src) From 6c70cf7d72db62b65de6d5ee810f0c606313fbce Mon Sep 17 00:00:00 2001 From: Michael Altizer Date: Sun, 9 Oct 2011 17:02:35 -0400 Subject: [PATCH 109/432] Don't install CLI header files when --disable-cli has been configured. Signed-off-by: Michael Altizer --- include/Makefile.am | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/include/Makefile.am b/include/Makefile.am index 515c237..db6862d 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -3,17 +3,6 @@ libnlincludedir = $(includedir)/libnl@MAJ_VERSION@ nobase_libnlinclude_HEADERS = \ - netlink/cli/addr.h \ - netlink/cli/class.h \ - netlink/cli/cls.h \ - netlink/cli/ct.h \ - netlink/cli/link.h \ - netlink/cli/neigh.h \ - netlink/cli/qdisc.h \ - netlink/cli/route.h \ - netlink/cli/rule.h \ - netlink/cli/tc.h \ - netlink/cli/utils.h \ netlink/fib_lookup/lookup.h \ netlink/fib_lookup/request.h \ netlink/genl/ctrl.h \ @@ -84,6 +73,21 @@ nobase_libnlinclude_HEADERS = \ netlink/utils.h \ netlink/version.h +if ENABLE_CLI +nobase_libnlinclude_HEADERS += \ + netlink/cli/addr.h \ + netlink/cli/class.h \ + netlink/cli/cls.h \ + netlink/cli/ct.h \ + netlink/cli/link.h \ + netlink/cli/neigh.h \ + netlink/cli/qdisc.h \ + netlink/cli/route.h \ + netlink/cli/rule.h \ + netlink/cli/tc.h \ + netlink/cli/utils.h +endif + noinst_HEADERS = \ linux/fib_rules.h \ linux/genetlink.h \ From 790966d69aea9aea304caed22486834ba55eb5c7 Mon Sep 17 00:00:00 2001 From: Michael Altizer Date: Sun, 9 Oct 2011 17:02:36 -0400 Subject: [PATCH 110/432] Only use the MULTIPATH attribute when adding routes with more than one next hop. Only use the MULTIPATH attribute when adding routes with more than one next hop. This solves issues with two scenarios: 1. Adding an IPv4 route to a kernel configured without CONFIG_IP_ROUTE_MULTIPATH=y. 2. Adding an IPv6 route in general, since the MULTIPATH attribute is not supported there. Signed-off-by: Michael Altizer --- lib/route/route_obj.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/route/route_obj.c b/lib/route/route_obj.c index 834cb91..d322633 100644 --- a/lib/route/route_obj.c +++ b/lib/route/route_obj.c @@ -1078,7 +1078,17 @@ int rtnl_route_build_msg(struct nl_msg *msg, struct rtnl_route *route) nla_nest_end(msg, metrics); } - if (rtnl_route_get_nnexthops(route) > 0) { + if (rtnl_route_get_nnexthops(route) == 1) { + struct rtnl_nexthop *nh; + + nh = rtnl_route_nexthop_n(route, 0); + if (nh->rtnh_gateway) + NLA_PUT_ADDR(msg, RTA_GATEWAY, nh->rtnh_gateway); + if (nh->rtnh_ifindex) + NLA_PUT_U32(msg, RTA_OIF, nh->rtnh_ifindex); + if (nh->rtnh_realms) + NLA_PUT_U32(msg, RTA_FLOW, nh->rtnh_realms); + } else if (rtnl_route_get_nnexthops(route) > 1) { struct nlattr *multipath; struct rtnl_nexthop *nh; From 30d3f8c199d38d830ff340e521b862d8fe4395b6 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Mon, 10 Oct 2011 12:02:33 +0200 Subject: [PATCH 111/432] utils: Initialize list head after freeing translation list Problem found and fix proposed by Andrew Kraslavsky --- lib/utils.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/utils.c b/lib/utils.c index 37ad4cc..0ec7626 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -885,6 +885,8 @@ void __trans_list_clear(struct nl_list_head *head) free(tl->a); free(tl); } + + nl_init_list_head(head); } char *__type2str(int type, char *buf, size_t len, From 2bcd8ecd27a4c3bad006b43926703c0b60158f42 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 21 Oct 2011 11:31:15 +0200 Subject: [PATCH 112/432] cache: event_filter() cache operation to filter notifications Certain notifications need to be filtered out and should not be applied to a cache when a cache is handled by a cache manager. --- include/netlink/cache-api.h | 7 +++++++ lib/cache_mngr.c | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/include/netlink/cache-api.h b/include/netlink/cache-api.h index efae2ed..1b3d099 100644 --- a/include/netlink/cache-api.h +++ b/include/netlink/cache-api.h @@ -201,6 +201,13 @@ struct nl_cache_ops int (*co_msg_parser)(struct nl_cache_ops *, struct sockaddr_nl *, struct nlmsghdr *, struct nl_parser_param *); + /** + * Called whenever a notification has been parsed into an object and + * is considered for inclusion into a cache. Must return NL_SKIP if + * the object should not be included in the cache. + */ + int (*co_event_filter)(struct nl_cache *, struct nl_object *obj); + /** Object operations */ struct nl_object_ops * co_obj_ops; diff --git a/lib/cache_mngr.c b/lib/cache_mngr.c index cfa676b..cf5a951 100644 --- a/lib/cache_mngr.c +++ b/lib/cache_mngr.c @@ -89,12 +89,18 @@ static int include_cb(struct nl_object *obj, struct nl_parser_param *p) { struct nl_cache_assoc *ca = p->pp_arg; + struct nl_cache_ops *ops = ca->ca_cache->c_ops; NL_DBG(2, "Including object %p into cache %p\n", obj, ca->ca_cache); #ifdef NL_DEBUG if (nl_debug >= 4) nl_object_dump(obj, &nl_debug_dp); #endif + + if (ops->co_event_filter) + if (ops->co_event_filter(ca->ca_cache, obj) != NL_OK) + return 0; + return nl_cache_include(ca->ca_cache, obj, ca->ca_change, ca->ca_change_data); } From 7f20c57e378cf76b68b7bf83613032a75bf832fd Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 21 Oct 2011 11:31:58 +0200 Subject: [PATCH 113/432] link: Ignore bridging notifications in link cache manager RTM_DELLINK and RTM_NEWLINK bridging notifications should not delete/add entries to a link cache. --- lib/route/link.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/route/link.c b/lib/route/link.c index 00beb08..b252f39 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -528,6 +528,19 @@ errout: return err; } +static int link_event_filter(struct nl_cache *cache, struct nl_object *obj) +{ + struct rtnl_link *link = (struct rtnl_link *) obj; + + /* + * Ignore bridging messages when keeping the cache manager up to date. + */ + if (link->l_family == AF_BRIDGE) + return NL_SKIP; + + return NL_OK; +} + static int link_request_update(struct nl_cache *cache, struct nl_sock *sk) { int family = cache->c_iarg1; @@ -2186,6 +2199,7 @@ static struct nl_cache_ops rtnl_link_ops = { .co_groups = link_groups, .co_request_update = link_request_update, .co_msg_parser = link_msg_parser, + .co_event_filter = link_event_filter, .co_obj_ops = &link_obj_ops, }; From 9c7593cc9b8e891f4fdf26e12a13c71400b93254 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 26 Oct 2011 10:54:10 +0200 Subject: [PATCH 114/432] python: Link against nl-3 and nl-route-3 --- python/setup.py.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/setup.py.in b/python/setup.py.in index e1a3aca..7ba90d7 100644 --- a/python/setup.py.in +++ b/python/setup.py.in @@ -9,14 +9,14 @@ netlink_capi = Extension('netlink/_capi', sources = ['netlink/capi.i'], include_dirs = include, swig_opts = opts, - libraries = ['nl'], + libraries = ['nl-3'], ) route_capi = Extension('netlink/route/_capi', sources = ['netlink/route/capi.i'], include_dirs = include, swig_opts = opts, - libraries = ['nl', 'nl-route'], + libraries = ['nl-3', 'nl-route-3'], ) setup(name = 'netlink', From 8104b52f755dd4c8a95f63568ca4c4d80cd33670 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 28 Oct 2011 12:30:31 +0200 Subject: [PATCH 115/432] Fix typo in debug message --- lib/nl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nl.c b/lib/nl.c index cc450c7..bcf89da 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -580,7 +580,7 @@ continue_reading: hdr = (struct nlmsghdr *) buf; while (nlmsg_ok(hdr, n)) { - NL_DBG(3, "recgmsgs(%p): Processing valid message...\n", sk); + NL_DBG(3, "recvmsgs(%p): Processing valid message...\n", sk); nlmsg_free(msg); msg = nlmsg_convert(hdr); From 659b6d6f654f9e3b8b1c9b0ccf06e23097f8fd7f Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sun, 30 Oct 2011 17:07:13 +0100 Subject: [PATCH 116/432] bump to 3.2.2 --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 31b5bff..b61eba8 100644 --- a/configure.in +++ b/configure.in @@ -13,9 +13,9 @@ # copied from glib m4_define([libnl_major_version], [3]) m4_define([libnl_minor_version], [2]) -m4_define([libnl_micro_version], [1]) # bump for every release unless minor was bumped +m4_define([libnl_micro_version], [2]) # bump for every release unless minor was bumped m4_define([libnl_lt_revision], [0]) # bump or reset to 0 if interfaces were added -m4_define([libnl_lt_age], [1]) # bump whenever a release is backwards compatible +m4_define([libnl_lt_age], [2]) # bump whenever a release is backwards compatible # bump with +100 if a minor release is compatible # reset to 0 if interfaces were removed From 03f3a58733bf3e414e00dbc9e1c765410079fee2 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Mon, 7 Nov 2011 12:32:35 +0100 Subject: [PATCH 117/432] link: generic link enslaving API Adds rtnl_link_enslave() / rtnl_link_release() providing a genreic link enslaving/release API for use with all link types which use the IFLA_MASTER property. --- include/netlink/route/link.h | 6 ++ lib/route/link.c | 123 +++++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+) diff --git a/include/netlink/route/link.h b/include/netlink/route/link.h index 79c2d56..42ef7c8 100644 --- a/include/netlink/route/link.h +++ b/include/netlink/route/link.h @@ -197,6 +197,12 @@ extern int rtnl_link_set_stat(struct rtnl_link *, rtnl_link_stat_id_t, extern int rtnl_link_set_type(struct rtnl_link *, const char *); extern char * rtnl_link_get_type(struct rtnl_link *); +extern int rtnl_link_enslave_ifindex(struct nl_sock *, int, int); +extern int rtnl_link_enslave(struct nl_sock *, struct rtnl_link *, + struct rtnl_link *); +extern int rtnl_link_release_ifindex(struct nl_sock *, int); +extern int rtnl_link_release(struct nl_sock *, struct rtnl_link *); + /* deprecated */ extern int rtnl_link_set_info_type(struct rtnl_link *, const char *) __attribute__((deprecated)); extern char * rtnl_link_get_info_type(struct rtnl_link *) __attribute__((deprecated)); diff --git a/lib/route/link.c b/lib/route/link.c index b252f39..6d9b8e9 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -1979,6 +1979,129 @@ char *rtnl_link_get_type(struct rtnl_link *link) /** @} */ +/** + * @name Master/Slave + * @{ + */ + +/** + * Enslave slave link to master link + * @arg sock netlink socket + * @arg master ifindex of master link + * @arg slave ifindex of slave link + * + * This function is identical to rtnl_link_enslave() except that + * it takes interface indices instead of rtnl_link objects. + * + * @see rtnl_link_enslave() + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_enslave_ifindex(struct nl_sock *sock, int master, int slave) +{ + struct rtnl_link *link; + int err; + + if (!(link = rtnl_link_alloc())) + return -NLE_NOMEM; + + rtnl_link_set_ifindex(link, slave); + rtnl_link_set_master(link, master); + + if ((err = rtnl_link_change(sock, link, link, 0)) < 0) + goto errout; + + rtnl_link_put(link); + + /* + * Due to the kernel not signaling whether this opertion is + * supported or not, we will retrieve the attribute to see if the + * request was successful. If the master assigned remains unchanged + * we will return NLE_OPNOTSUPP to allow performing backwards + * compatibility of some sort. + */ + if ((err = rtnl_link_get_kernel(sock, slave, NULL, &link)) < 0) + return err; + + if (rtnl_link_get_master(link) != master) + err = -NLE_OPNOTSUPP; + +errout: + rtnl_link_put(link); + + return err; +} + +/** + * Enslave slave link to master link + * @arg sock netlink socket + * @arg master master link + * @arg slave slave link + * + * Constructs a RTM_NEWLINK or RTM_SETLINK message adding the slave to + * the master and sends the request via the specified netlink socket. + * + * @note The feature of enslaving/releasing via netlink has only been added + * recently to the kernel (Feb 2011). Also, the kernel does not signal + * if the operation is not supported. Therefore this function will + * verify if the master assignment has changed and will return + * -NLE_OPNOTSUPP if it did not. + * + * @see rtnl_link_enslave_ifindex() + * @see rtnl_link_release() + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_enslave(struct nl_sock *sock, struct rtnl_link *master, + struct rtnl_link *slave) +{ + return rtnl_link_enslave_ifindex(sock, rtnl_link_get_ifindex(master), + rtnl_link_get_ifindex(slave)); +} + +/** + * Release slave link from its master + * @arg sock netlink socket + * @arg slave slave link + * + * This function is identical to rtnl_link_release() except that + * it takes an interface index instead of a rtnl_link object. + * + * @see rtnl_link_release() + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_release_ifindex(struct nl_sock *sock, int slave) +{ + return rtnl_link_enslave_ifindex(sock, 0, slave); +} + +/** + * Release slave link from its master + * @arg sock netlink socket + * @arg slave slave link + * + * Constructs a RTM_NEWLINK or RTM_SETLINK message releasing the slave from + * its master and sends the request via the specified netlink socket. + * + * @note The feature of enslaving/releasing via netlink has only been added + * recently to the kernel (Feb 2011). Also, the kernel does not signal + * if the operation is not supported. Therefore this function will + * verify if the master assignment has changed and will return + * -NLE_OPNOTSUPP if it did not. + * + * @see rtnl_link_release_ifindex() + * @see rtnl_link_enslave() + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_release(struct nl_sock *sock, struct rtnl_link *slave) +{ + return rtnl_link_release_ifindex(sock, rtnl_link_get_ifindex(slave)); +} + +/** @} */ + /** * @name Utilities * @{ From bd7000948d85beb8eab2f163a9f1ea9e6dc6a009 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 7 Nov 2011 14:35:13 +0100 Subject: [PATCH 118/432] add missing IFLA_MASTER fillup this makes all set_master functions work. Signed-off-by: Jiri Pirko --- lib/route/link.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/route/link.c b/lib/route/link.c index 6d9b8e9..e486b3f 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -1112,6 +1112,9 @@ static int build_link_msg(int cmd, struct ifinfomsg *hdr, if (link->ce_mask & LINK_ATTR_LINK) NLA_PUT_U32(msg, IFLA_LINK, link->l_link); + if (link->ce_mask & LINK_ATTR_MASTER) + NLA_PUT_U32(msg, IFLA_MASTER, link->l_master); + if ((link->ce_mask & LINK_ATTR_LINKINFO) && link->l_info_ops) { struct nlattr *info; From 32f30b739ab8cf542ac9b13f6c418ffa98c56c31 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 10 Nov 2011 15:04:43 +0100 Subject: [PATCH 119/432] release 3.2.3 --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index b61eba8..e91b51f 100644 --- a/configure.in +++ b/configure.in @@ -13,9 +13,9 @@ # copied from glib m4_define([libnl_major_version], [3]) m4_define([libnl_minor_version], [2]) -m4_define([libnl_micro_version], [2]) # bump for every release unless minor was bumped +m4_define([libnl_micro_version], [3]) # bump for every release unless minor was bumped m4_define([libnl_lt_revision], [0]) # bump or reset to 0 if interfaces were added -m4_define([libnl_lt_age], [2]) # bump whenever a release is backwards compatible +m4_define([libnl_lt_age], [3]) # bump whenever a release is backwards compatible # bump with +100 if a minor release is compatible # reset to 0 if interfaces were removed From 88940b71f81525b1080fcdd5a029537e9a85ca38 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 11 Nov 2011 01:33:51 +0100 Subject: [PATCH 120/432] build: simplify optional dirs/files in Makefile.am processing --- Makefile.am | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/Makefile.am b/Makefile.am index 4b8f020..e21060f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,21 +2,17 @@ ACLOCAL_AMFLAGS = -I m4 -OPT_DIRS = -PKGCONFIGS = - -if ENABLE_CLI -OPT_DIRS += src -PKGCONFIGS += libnl-cli-3.0.pc -endif - -SUBDIRS = include lib doc man python $(OPT_DIRS) +SUBDIRS = include lib doc man python pkgconfig_DATA = libnl-3.0.pc \ libnl-route-3.0.pc \ libnl-genl-3.0.pc \ - libnl-nf-3.0.pc \ - $(PKGCONFIGS) + libnl-nf-3.0.pc + +if ENABLE_CLI +SUBDIRS += src +pkgconfig_DATA += libnl-cli-3.0.pc +endif pkgsysconfdir = ${sysconfdir}/libnl From ef75c4edf0930b4d745da695c5fe0075c7b3afdd Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 11 Nov 2011 14:56:16 +0100 Subject: [PATCH 121/432] link: allow to add/get linkinfo of unknown type store type kind in rtnl_link independently. That would allow to use this value even if type_ops are not present. This allows for example to create devices of type unknown to libnl. Signed-off-by: Jiri Pirko --- include/netlink-types.h | 1 + lib/route/link.c | 76 +++++++++++++++++++++++++++++------------ 2 files changed, 55 insertions(+), 22 deletions(-) diff --git a/include/netlink-types.h b/include/netlink-types.h index 750c897..82481b7 100644 --- a/include/netlink-types.h +++ b/include/netlink-types.h @@ -167,6 +167,7 @@ struct rtnl_link uint8_t l_operstate; uint8_t l_linkmode; /* 2 byte hole */ + char * l_info_kind; struct rtnl_link_info_ops * l_info_ops; void * l_af_data[AF_MAX]; void * l_info; diff --git a/lib/route/link.c b/lib/route/link.c index e486b3f..ad5fcbe 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -195,6 +195,7 @@ static void link_free_data(struct nl_object *c) nl_addr_put(link->l_bcast); free(link->l_ifalias); + free(link->l_info_kind); do_foreach_af(link, af_free, NULL); } @@ -218,6 +219,10 @@ static int link_clone(struct nl_object *_dst, struct nl_object *_src) if (!(dst->l_ifalias = strdup(src->l_ifalias))) return -NLE_NOMEM; + if (src->l_info_kind) + if (!(dst->l_info_kind = strdup(src->l_info_kind))) + return -NLE_NOMEM; + if (src->l_info_ops && src->l_info_ops->io_clone) { err = src->l_info_ops->io_clone(dst, src); if (err < 0) @@ -478,18 +483,27 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, struct rtnl_link_info_ops *ops; char *kind; - kind = nla_get_string(li[IFLA_INFO_KIND]); + kind = nla_strdup(tb[IFLA_INFO_KIND]); + if (kind == NULL) { + err = -NLE_NOMEM; + goto errout; + } + link->l_info_kind = kind; + link->ce_mask |= LINK_ATTR_LINKINFO; + ops = rtnl_link_info_ops_lookup(kind); link->l_info_ops = ops; - - if (ops && ops->io_parse && - (li[IFLA_INFO_DATA] || li[IFLA_INFO_XSTATS])) { - err = ops->io_parse(link, li[IFLA_INFO_DATA], - li[IFLA_INFO_XSTATS]); - if (err < 0) - goto errout; - } else { - /* XXX: Warn about unparsed info? */ + + if (ops) { + if (ops->io_parse && + (li[IFLA_INFO_DATA] || li[IFLA_INFO_XSTATS])) { + err = ops->io_parse(link, li[IFLA_INFO_DATA], + li[IFLA_INFO_XSTATS]); + if (err < 0) + goto errout; + } else { + /* XXX: Warn about unparsed info? */ + } } } } @@ -1115,17 +1129,19 @@ static int build_link_msg(int cmd, struct ifinfomsg *hdr, if (link->ce_mask & LINK_ATTR_MASTER) NLA_PUT_U32(msg, IFLA_MASTER, link->l_master); - if ((link->ce_mask & LINK_ATTR_LINKINFO) && link->l_info_ops) { + if (link->ce_mask & LINK_ATTR_LINKINFO) { struct nlattr *info; if (!(info = nla_nest_start(msg, IFLA_LINKINFO))) goto nla_put_failure; - NLA_PUT_STRING(msg, IFLA_INFO_KIND, link->l_info_ops->io_name); + NLA_PUT_STRING(msg, IFLA_INFO_KIND, link->l_info_kind); - if (link->l_info_ops->io_put_attrs && - link->l_info_ops->io_put_attrs(msg, link) < 0) - goto nla_put_failure; + if (link->l_info_ops) { + if (link->l_info_ops->io_put_attrs && + link->l_info_ops->io_put_attrs(msg, link) < 0) + goto nla_put_failure; + } nla_nest_end(msg, info); } @@ -1952,20 +1968,36 @@ int rtnl_link_set_type(struct rtnl_link *link, const char *type) { struct rtnl_link_info_ops *io; int err; + char *kind; - if ((io = rtnl_link_info_ops_lookup(type)) == NULL) - return -NLE_OPNOTSUPP; - + free(link->l_info_kind); + link->ce_mask &= ~LINK_ATTR_LINKINFO; if (link->l_info_ops) release_link_info(link); - if (io->io_alloc && (err = io->io_alloc(link)) < 0) - return err; + if (!type) + return 0; + kind = strdup(type); + if (!kind) + return -NLE_NOMEM; + + io = rtnl_link_info_ops_lookup(type); + if (io) { + if (io->io_alloc && (err = io->io_alloc(link)) < 0) + goto errout; + + link->l_info_ops = io; + } + + link->l_info_kind = kind; link->ce_mask |= LINK_ATTR_LINKINFO; - link->l_info_ops = io; return 0; + +errout: + free(kind); + return err; } /** @@ -1977,7 +2009,7 @@ int rtnl_link_set_type(struct rtnl_link *link, const char *type) */ char *rtnl_link_get_type(struct rtnl_link *link) { - return link->l_info_ops ? link->l_info_ops->io_name : NULL; + return link->l_info_kind; } /** @} */ From 847e269c568740bab1e0c5c39829d30f5b557dda Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 11 Nov 2011 16:01:52 +0100 Subject: [PATCH 122/432] rtnl_link_bond_add: allow to allocate bond name in case NULL is given Signed-off-by: Jiri Pirko --- lib/route/link/bonding.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/route/link/bonding.c b/lib/route/link/bonding.c index 5788f69..5e78084 100644 --- a/lib/route/link/bonding.c +++ b/lib/route/link/bonding.c @@ -60,15 +60,12 @@ int rtnl_link_bond_add(struct nl_sock *sock, const char *name, if (!name) { if (opts) name = rtnl_link_get_name(opts); - - if (!name) - return -NLE_MISSING_ATTR; } if ((err = rtnl_link_set_type(link, "bond")) < 0) goto errout; - + if (name) rtnl_link_set_name(link, name); err = rtnl_link_add(sock, link, NLM_F_CREATE); From 4a7791eca1268e24225c33ed1c00c140a14cd955 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 25 Nov 2011 16:08:25 +0100 Subject: [PATCH 123/432] dsmark: Add missing declarations for rtnl_class_dsmark_(get|set)_bitmask() The existing declarations refered to non-existing functions so removing them is safe. Signed-off-by: Thomas Graf --- include/netlink/route/qdisc/dsmark.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/netlink/route/qdisc/dsmark.h b/include/netlink/route/qdisc/dsmark.h index de65496..d7a6d22 100644 --- a/include/netlink/route/qdisc/dsmark.h +++ b/include/netlink/route/qdisc/dsmark.h @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2006 Thomas Graf + * Copyright (c) 2003-2011 Thomas Graf */ #ifndef NETLINK_DSMARK_H_ @@ -18,8 +18,8 @@ extern "C" { #endif -extern int rtnl_class_dsmark_set_bmask(struct rtnl_class *, uint8_t); -extern int rtnl_class_dsmark_get_bmask(struct rtnl_class *); +extern int rtnl_class_dsmark_set_bitmask(struct rtnl_class *, uint8_t); +extern int rtnl_class_dsmark_get_bitmask(struct rtnl_class *); extern int rtnl_class_dsmark_set_value(struct rtnl_class *, uint8_t); extern int rtnl_class_dsmark_get_value(struct rtnl_class *); From 9819717444e8f58bcf707aac724488c4d5f4e1d7 Mon Sep 17 00:00:00 2001 From: Alexander Sack Date: Fri, 21 Oct 2011 00:31:39 +0200 Subject: [PATCH 124/432] avoid dangling co_major_cache reference to NL_AUTO_PROVIDE caches --- lib/cache_mngr.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/cache_mngr.c b/lib/cache_mngr.c index cf5a951..0be55bc 100644 --- a/lib/cache_mngr.c +++ b/lib/cache_mngr.c @@ -378,9 +378,12 @@ void nl_cache_mngr_free(struct nl_cache_mngr *mngr) if (mngr->cm_handle) nl_close(mngr->cm_handle); - for (i = 0; i < mngr->cm_nassocs; i++) - if (mngr->cm_assocs[i].ca_cache) + for (i = 0; i < mngr->cm_nassocs; i++) { + if (mngr->cm_assocs[i].ca_cache) { + nl_cache_mngt_unprovide(mngr->cm_assocs[i].ca_cache); nl_cache_free(mngr->cm_assocs[i].ca_cache); + } + } free(mngr->cm_assocs); free(mngr); From d7222e5ddeb046dad9b02c0ed7b0771c6aead76b Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 11 Jan 2012 12:51:03 +0100 Subject: [PATCH 125/432] 3.2.4 release --- configure.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.in b/configure.in index e91b51f..a35e543 100644 --- a/configure.in +++ b/configure.in @@ -6,16 +6,16 @@ # License as published by the Free Software Foundation version 2.1 # of the License. # -# Copyright (c) 2003-2011 Thomas Graf +# Copyright (c) 2003-2012 Thomas Graf # # copied from glib m4_define([libnl_major_version], [3]) m4_define([libnl_minor_version], [2]) -m4_define([libnl_micro_version], [3]) # bump for every release unless minor was bumped +m4_define([libnl_micro_version], [4]) # bump for every release unless minor was bumped m4_define([libnl_lt_revision], [0]) # bump or reset to 0 if interfaces were added -m4_define([libnl_lt_age], [3]) # bump whenever a release is backwards compatible +m4_define([libnl_lt_age], [4]) # bump whenever a release is backwards compatible # bump with +100 if a minor release is compatible # reset to 0 if interfaces were removed From 794ac78c5618ee81a45e4f58694ee27b3403ebd7 Mon Sep 17 00:00:00 2001 From: Brett Ciphery Date: Wed, 11 Jan 2012 11:40:11 -0500 Subject: [PATCH 126/432] nl_addr_cmp(): handle prefix length during address comparison Signed-off-by: Brett Ciphery --- lib/addr.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/addr.c b/lib/addr.c index c8c4ca4..30c708d 100644 --- a/lib/addr.c +++ b/lib/addr.c @@ -497,7 +497,10 @@ int nl_addr_cmp(struct nl_addr *a, struct nl_addr *b) d = a->a_len - b->a_len; if (a->a_len && d == 0) - return memcmp(a->a_addr, b->a_addr, a->a_len); + d = memcmp(a->a_addr, b->a_addr, a->a_len); + + if (d == 0) + return (a->a_prefixlen - b->a_prefixlen); } return d; From 4035e5b5e88529e6c7a12c41dcd8637ed69498d9 Mon Sep 17 00:00:00 2001 From: Torsten Hilbrich Date: Thu, 12 Jan 2012 12:28:18 +0100 Subject: [PATCH 127/432] link: fix regression in link message parser In a simple test program that queries the source IP for a given destination address I get a crash in the call to rtnl_link_alloc_cache. Here is the stack trace (created with version 3.2.4): Program received signal SIGSEGV, Segmentation fault. 0xb7eb7553 in strlen () from /lib/libc.so.6 (gdb) bt #0 0xb7eb7553 in strlen () from /lib/libc.so.6 #1 0xb7eb7285 in strdup () from /lib/libc.so.6 #2 0xb7fcc305 in nla_strdup (nla=0x0) at attr.c:1033 #3 0xb7f9c173 in link_msg_parser (ops=0xb7fc2940, who=0x804b330, n=0x804c3e8, pp=0xbffffbf8) at route/link.c:486 #4 0xb7fcd485 in nl_cache_parse (ops=0xb7fc2940, who=0x804b330, nlh=0x804c3e8, params=0xbffffbf8) at cache.c:724 #5 0xb7fcd547 in update_msg_parser (msg=0x804b328, arg=0xbffffbb8) at cache.c:531 #6 0xb7fd1f25 in nl_cb_call (cb=, msg=, type=) at ../include/netlink-local.h:126 #7 recvmsgs (cb=, sk=) at nl.c:729 #8 nl_recvmsgs (sk=0x804b2d0, cb=0x804b368) at nl.c:780 #9 0xb7fcd5fd in __cache_pickup (sk=0x804b2d0, cache=, param=0xbffffbf8) at cache.c:560 #10 0xb7fcd83f in nl_cache_pickup (sk=0x804b2d0, cache=0x804b308) at cache.c:593 #11 0xb7fcd8c8 in nl_cache_refill (sk=0x804b2d0, cache=0x804b308) at cache.c:780 #12 0xb7f9d1fc in rtnl_link_alloc_cache (sk=0x804b2d0, family=4, result=0xbffffcd4) at route/link.c:868 #13 0x08048fd0 in libnl_init (data=) at helper_route.c:60 #14 iproute_get_source (destination=0xbffffeff "127.0.0.1", source=0xbffffd0f "\b\004c\370\267\364_\370\267\260\224\004\b8\375\377\277e\024\347\267\320\016\377\267\273\224\004\b\364_\370\267\260\224\004\b", source_size=17) at helper_route.c:105 #15 0x08048e6a in main (argc=2, argv=0xbffffde4) at ip_route_get.c:25 The attached patch (against 3.2.4) solves the problem, fixing something that looks like a typo. The bug is still present in current Git master. --- lib/route/link.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/route/link.c b/lib/route/link.c index ad5fcbe..4da40a0 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -483,7 +483,7 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, struct rtnl_link_info_ops *ops; char *kind; - kind = nla_strdup(tb[IFLA_INFO_KIND]); + kind = nla_strdup(li[IFLA_INFO_KIND]); if (kind == NULL) { err = -NLE_NOMEM; goto errout; From 9015d115f87fc9884faa5e0ff91ba8d2897700cb Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 12 Jan 2012 13:17:32 +0100 Subject: [PATCH 128/432] 3.2.5 release --- configure.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.in b/configure.in index a35e543..37cb8ae 100644 --- a/configure.in +++ b/configure.in @@ -13,9 +13,9 @@ # copied from glib m4_define([libnl_major_version], [3]) m4_define([libnl_minor_version], [2]) -m4_define([libnl_micro_version], [4]) # bump for every release unless minor was bumped -m4_define([libnl_lt_revision], [0]) # bump or reset to 0 if interfaces were added -m4_define([libnl_lt_age], [4]) # bump whenever a release is backwards compatible +m4_define([libnl_micro_version], [5]) # bump for every release unless minor was bumped +m4_define([libnl_lt_revision], [1]) # bump or reset to 0 if interfaces were added +m4_define([libnl_lt_age], [5]) # bump whenever a release is backwards compatible # bump with +100 if a minor release is compatible # reset to 0 if interfaces were removed From d111b1df47002531b6d5a89f5e61c316f6587f12 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 17 Jan 2012 12:34:26 +0100 Subject: [PATCH 129/432] cli: Use -avoid-version to link cli modules Signed-off-by: Thomas Graf --- lib/Makefile.am | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/Makefile.am b/lib/Makefile.am index da2dbf6..c2668ef 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -105,10 +105,10 @@ nobase_pkglib_LTLIBRARIES = \ cli/cls/basic.la \ cli/cls/cgroup.la -cli_qdisc_htb_la_LDFLAGS = -module -version-info 0:0:0 -cli_qdisc_blackhole_la_LDFLAGS = -module -version-info 0:0:0 -cli_qdisc_pfifo_la_LDFLAGS = -module -version-info 0:0:0 -cli_qdisc_bfifo_la_LDFLAGS = -module -version-info 0:0:0 -cli_cls_basic_la_LDFLAGS = -module -version-info 0:0:0 -cli_cls_cgroup_la_LDFLAGS = -module -version-info 0:0:0 +cli_qdisc_htb_la_LDFLAGS = -module -avoid-version +cli_qdisc_blackhole_la_LDFLAGS = -module -avoid-version +cli_qdisc_pfifo_la_LDFLAGS = -module -avoid-version +cli_qdisc_bfifo_la_LDFLAGS = -module -avoid-version +cli_cls_basic_la_LDFLAGS = -module -avoid-version +cli_cls_cgroup_la_LDFLAGS = -module -avoid-version endif From c857625be074a7b9ef6adbcdde986a0b23aae901 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 17 Jan 2012 12:38:37 +0100 Subject: [PATCH 130/432] Update COPYING to fix FSF address Apparently we have been shiping an outdated version of the LGPL containing an obsolete address of the FSF. Signed-off-by: Thomas Graf --- COPYING | 85 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 63 insertions(+), 22 deletions(-) diff --git a/COPYING b/COPYING index 371ec20..4362b49 100644 --- a/COPYING +++ b/COPYING @@ -1,9 +1,8 @@ - GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -23,8 +22,7 @@ specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations -below. +strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that @@ -89,9 +87,9 @@ libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it -becomes a de-facto standard. To achieve this, non-free programs must -be allowed to use the library. A more frequent case is that a free +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. @@ -138,8 +136,8 @@ included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control -compilation and installation of the library. +interface definition files, plus the scripts used to control compilation +and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of @@ -305,10 +303,10 @@ of these things: the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. - c) Accompany the work with a written offer, valid for at least - three years, to give the same user the materials specified in - Subsection 6a, above, for a charge no more than the cost of - performing this distribution. + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above @@ -386,10 +384,9 @@ all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply, and the section as a whole is intended to apply in other -circumstances. +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any @@ -407,11 +404,11 @@ be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License -may add an explicit geographical distribution limitation excluding those -countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. @@ -459,3 +456,47 @@ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! From 83ab0ae85fd0c458a9c86d76966c405b72a6e064 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 17 Jan 2012 12:45:06 +0100 Subject: [PATCH 131/432] man: Remove bogus .LO macro in manpages Signed-off-by: Thomas Graf --- man/nl-classid-lookup.8 | 1 - man/nl-pktloc-lookup.8 | 1 - man/nl-qdisc-add.8 | 1 - 3 files changed, 3 deletions(-) diff --git a/man/nl-classid-lookup.8 b/man/nl-classid-lookup.8 index d48e9eb..3cf13de 100644 --- a/man/nl-classid-lookup.8 +++ b/man/nl-classid-lookup.8 @@ -1,5 +1,4 @@ .TH nl\-classid\-lookup 8 "19 October 2010" "libnl" -.LO 1 .SH NAME nl\-classid\-lookup - Lookup classid definitions .SH SYNOPSIS diff --git a/man/nl-pktloc-lookup.8 b/man/nl-pktloc-lookup.8 index a583dcc..7a1daa4 100644 --- a/man/nl-pktloc-lookup.8 +++ b/man/nl-pktloc-lookup.8 @@ -1,5 +1,4 @@ .TH nl\-pktloc-lookup 8 "27 October 2010" "libnl" -.LO 1 .SH NAME nl\-pktloc\-lookup - Lookup packet location definitions .SH SYNOPSIS diff --git a/man/nl-qdisc-add.8 b/man/nl-qdisc-add.8 index 7031c39..bc3fb17 100644 --- a/man/nl-qdisc-add.8 +++ b/man/nl-qdisc-add.8 @@ -1,5 +1,4 @@ .TH nl\-qdisc 8 "21 October 2010" "libnl" -.LO 1 .SH NAME nl\-qdisc\-{add|list|delete} - Manage queueing disciplines .SH SYNOPSIS From 4cc1daab3f79fa2e5c9850e53ca28e1fbfbc3afb Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 17 Jan 2012 12:51:15 +0100 Subject: [PATCH 132/432] 3.2.6 release --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 37cb8ae..16158b9 100644 --- a/configure.in +++ b/configure.in @@ -13,9 +13,9 @@ # copied from glib m4_define([libnl_major_version], [3]) m4_define([libnl_minor_version], [2]) -m4_define([libnl_micro_version], [5]) # bump for every release unless minor was bumped +m4_define([libnl_micro_version], [6]) # bump for every release unless minor was bumped m4_define([libnl_lt_revision], [1]) # bump or reset to 0 if interfaces were added -m4_define([libnl_lt_age], [5]) # bump whenever a release is backwards compatible +m4_define([libnl_lt_age], [6]) # bump whenever a release is backwards compatible # bump with +100 if a minor release is compatible # reset to 0 if interfaces were removed From 9cbcbca77d53c04dd1592e521c6c5d124acf681c Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 25 Jan 2012 17:03:37 +0100 Subject: [PATCH 133/432] 3.2.7 release fixes a bug in SO versioning. libtool age was increased incorrectly which resulted in an incorrect SO version string in the releases 3.2.5 and 3.2.6. --- configure.in | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/configure.in b/configure.in index 16158b9..b6060c7 100644 --- a/configure.in +++ b/configure.in @@ -13,15 +13,16 @@ # copied from glib m4_define([libnl_major_version], [3]) m4_define([libnl_minor_version], [2]) -m4_define([libnl_micro_version], [6]) # bump for every release unless minor was bumped -m4_define([libnl_lt_revision], [1]) # bump or reset to 0 if interfaces were added -m4_define([libnl_lt_age], [6]) # bump whenever a release is backwards compatible +m4_define([libnl_micro_version], [7]) # bump for every release unless minor was bumped +m4_define([libnl_lt_revision], [2]) # bump or reset to 0 if interfaces were added +m4_define([libnl_backwards_age], [7]) # bump whenever a release is backwards compatible # bump with +100 if a minor release is compatible # reset to 0 if interfaces were removed m4_define([libnl_version], [libnl_major_version.libnl_minor_version.libnl_micro_version]) +m4_define([libnl_lt_age], [m4_eval(libnl_backwards_age - libnl_lt_revision)]) m4_define([libnl_lt_current], [m4_eval(100 * libnl_minor_version + libnl_micro_version - libnl_lt_revision)]) From a39bb563ab8450d5463540384f4b8abca0d3755e Mon Sep 17 00:00:00 2001 From: Brett Ciphery Date: Sun, 29 Jan 2012 12:19:00 -0500 Subject: [PATCH 134/432] add new function to provide neighbour event parsing the neighbour parsing function was previously not accessible, so custom callback functions had to handle the decoding itself. rtnl_neigh_parse is introduced and implemented in much the same way as rtnl_route_parse. Signed-off-by: Brett Ciphery Signed-off-by: Thomas Graf --- include/netlink/route/neighbour.h | 2 ++ lib/route/neigh.c | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/include/netlink/route/neighbour.h b/include/netlink/route/neighbour.h index 698539a..1d1179b 100644 --- a/include/netlink/route/neighbour.h +++ b/include/netlink/route/neighbour.h @@ -29,6 +29,8 @@ extern int rtnl_neigh_alloc_cache(struct nl_sock *, struct nl_cache **); extern struct rtnl_neigh *rtnl_neigh_get(struct nl_cache *, int, struct nl_addr *); +extern int rtnl_neigh_parse(struct nlmsghdr *, struct rtnl_neigh **); + extern char * rtnl_neigh_state2str(int, char *, size_t); extern int rtnl_neigh_str2state(const char *); diff --git a/lib/route/neigh.c b/lib/route/neigh.c index 7985d34..bb61571 100644 --- a/lib/route/neigh.c +++ b/lib/route/neigh.c @@ -252,6 +252,21 @@ static struct nla_policy neigh_policy[NDA_MAX+1] = { static int neigh_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, struct nlmsghdr *n, struct nl_parser_param *pp) +{ + struct rtnl_neigh *neigh; + int err; + + if ((err = rtnl_neigh_parse(n, &neigh)) < 0) + return err; + + err = pp->pp_cb((struct nl_object *) neigh, pp); + + rtnl_neigh_put(neigh); + return err; +} + + +int rtnl_neigh_parse(struct nlmsghdr *n, struct rtnl_neigh **result) { struct rtnl_neigh *neigh; struct nlattr *tb[NDA_MAX + 1]; @@ -317,7 +332,9 @@ static int neigh_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, neigh->ce_mask |= NEIGH_ATTR_PROBES; } - err = pp->pp_cb((struct nl_object *) neigh, pp); + *result = neigh; + return 0; + errout: rtnl_neigh_put(neigh); return err; From a17970b974bb3896f253817f98a9fa6176fcd422 Mon Sep 17 00:00:00 2001 From: Shriram Rajagopalan Date: Sun, 12 Feb 2012 14:53:10 -0800 Subject: [PATCH 135/432] Support plug qdisc - queue traffic until explicit release The plug qdisc supports two operations - plug and unplug. When the qdisc receives a plug ("buffer") command via netlink request, packets arriving henceforth are buffered until a corresponding unplug command is received. Depending on the type of unplug ("release_one" or "release_indefinite"), the queue can be unplugged indefinitely or selectively. The plug qdisc allows a user to implement network output buffering (aka output commit), used commonly in checkpoint based fault tolerance systems. It also supports a general purpose queue plug/unplug functionality. The associated kernel module is available in David Miller's net-next tree, commit: c3059be16c9ef29c05f0876a9df5fea21f29724f This patch introduces userspace tools and API, to control the qdisc via netlink messages. Signed-off-by: Shriram Rajagopalan Signed-off-by: Thomas Graf --- include/Makefile.am | 1 + include/linux/pkt_sched.h | 21 ++++ include/netlink-types.h | 6 + include/netlink/route/qdisc/plug.h | 30 +++++ lib/Makefile.am | 4 +- lib/cli/qdisc/plug.c | 113 ++++++++++++++++++ lib/route/qdisc/plug.c | 177 +++++++++++++++++++++++++++++ 7 files changed, 351 insertions(+), 1 deletion(-) create mode 100644 include/netlink/route/qdisc/plug.h create mode 100644 lib/cli/qdisc/plug.c create mode 100644 lib/route/qdisc/plug.c diff --git a/include/Makefile.am b/include/Makefile.am index db6862d..2ba0ece 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -54,6 +54,7 @@ nobase_libnlinclude_HEADERS = \ netlink/route/qdisc/red.h \ netlink/route/qdisc/sfq.h \ netlink/route/qdisc/tbf.h \ + netlink/route/qdisc/plug.h \ netlink/route/addr.h \ netlink/route/class.h \ netlink/route/classifier.h \ diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h index c533670..7ccc1fd 100644 --- a/include/linux/pkt_sched.h +++ b/include/linux/pkt_sched.h @@ -127,6 +127,27 @@ struct tc_multiq_qopt { __u16 max_bands; /* Maximum number of queues */ }; +/* PLUG section */ + +#define TCQ_PLUG_BUFFER 0 +#define TCQ_PLUG_RELEASE_ONE 1 +#define TCQ_PLUG_RELEASE_INDEFINITE 2 +#define TCQ_PLUG_LIMIT 3 + +struct tc_plug_qopt { + /* TCQ_PLUG_BUFFER: Inset a plug into the queue and + * buffer any incoming packets + * TCQ_PLUG_RELEASE_ONE: Dequeue packets from queue head + * to beginning of the next plug. + * TCQ_PLUG_RELEASE_INDEFINITE: Dequeue all packets from queue. + * Stop buffering packets until the next TCQ_PLUG_BUFFER + * command is received (just act as a pass-thru queue). + * TCQ_PLUG_LIMIT: Increase/decrease queue size + */ + int action; + __u32 limit; +}; + /* TBF section */ struct tc_tbf_qopt { diff --git a/include/netlink-types.h b/include/netlink-types.h index 82481b7..5ced836 100644 --- a/include/netlink-types.h +++ b/include/netlink-types.h @@ -669,6 +669,12 @@ struct rtnl_red uint32_t qr_mask; }; +struct rtnl_plug +{ + int action; + uint32_t limit; +}; + struct flnl_request { NLHDR_COMMON diff --git a/include/netlink/route/qdisc/plug.h b/include/netlink/route/qdisc/plug.h new file mode 100644 index 0000000..ffb1a04 --- /dev/null +++ b/include/netlink/route/qdisc/plug.h @@ -0,0 +1,30 @@ +/* + * netlink/route/qdisc/plug.c PLUG Qdisc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2012 Shriram Rajagopalan + */ + +#ifndef NETLINK_PLUG_H_ +#define NETLINK_PLUG_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int rtnl_qdisc_plug_set_limit(struct rtnl_qdisc *, int); +extern int rtnl_qdisc_plug_buffer(struct rtnl_qdisc *); +extern int rtnl_qdisc_plug_release_one(struct rtnl_qdisc *); +extern int rtnl_qdisc_plug_release_indefinite(struct rtnl_qdisc *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/Makefile.am b/lib/Makefile.am index c2668ef..aee8d0f 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -72,7 +72,7 @@ libnl_route_3_la_SOURCES = \ route/qdisc/blackhole.c route/qdisc/cbq.c route/qdisc/dsmark.c \ route/qdisc/fifo.c route/qdisc/htb.c route/qdisc/netem.c \ route/qdisc/prio.c route/qdisc/red.c route/qdisc/sfq.c \ - route/qdisc/tbf.c \ + route/qdisc/tbf.c route/qdisc/plug.c \ \ fib_lookup/lookup.c fib_lookup/request.c \ \ @@ -101,6 +101,7 @@ nobase_pkglib_LTLIBRARIES = \ cli/qdisc/htb.la \ cli/qdisc/blackhole.la \ cli/qdisc/pfifo.la \ + cli/qdisc/plug.la \ cli/qdisc/bfifo.la \ cli/cls/basic.la \ cli/cls/cgroup.la @@ -108,6 +109,7 @@ nobase_pkglib_LTLIBRARIES = \ cli_qdisc_htb_la_LDFLAGS = -module -avoid-version cli_qdisc_blackhole_la_LDFLAGS = -module -avoid-version cli_qdisc_pfifo_la_LDFLAGS = -module -avoid-version +cli_qdisc_plug_la_LDFLAGS = -module -avoid-version cli_qdisc_bfifo_la_LDFLAGS = -module -avoid-version cli_cls_basic_la_LDFLAGS = -module -avoid-version cli_cls_cgroup_la_LDFLAGS = -module -avoid-version diff --git a/lib/cli/qdisc/plug.c b/lib/cli/qdisc/plug.c new file mode 100644 index 0000000..2b8d5d6 --- /dev/null +++ b/lib/cli/qdisc/plug.c @@ -0,0 +1,113 @@ + +/* + * src/lib/cli/qdisc/plug.c plug module for CLI lib + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2012 Shriram Rajagopalan + */ + +#include +#include +#include + +static void print_usage(void) +{ + printf( +"Usage: nl-qdisc-add [...] plug [OPTIONS]...\n" +"\n" +"OPTIONS\n" +" --help Show this help text.\n" +" --limit Maximum queue length in bytes.\n" +" --buffer create a new buffer(plug) and queue incoming traffic into it.\n" +" --release-one release traffic from previous buffer.\n" +" --release-indefinite stop buffering and release all (buffered and new) packets.\n" +"\n" +"EXAMPLE" +" # Attach plug qdisc with 32KB queue size to ifb0\n" +" nl-qdisc-add --dev=ifb0 --parent=root plug --limit=32768\n" +" # Plug network traffic arriving at ifb0\n" +" nl-qdisc-add --dev=ifb0 --parent=root --update plug --buffer\n" +" # Unplug traffic arriving at ifb0 indefinitely\n" +" nl-qdisc-add --dev=ifb0 --parent=root --update plug --release-indefinite\n\n" +" # If operating in output buffering mode:\n" +" # at time t=t0, create a new output buffer b0 to hold network output\n" +" nl-qdisc-add --dev=ifb0 --parent=root --update plug --buffer\n\n" +" # at time t=t1, take a checkpoint c0, create a new output buffer b1\n" +" nl-qdisc-add --dev=ifb0 --parent=root --update plug --buffer\n" +" # at time t=t1+r, after c0 is committed, release b0\n" +" nl-qdisc-add --dev=ifb0 --parent=root --update plug --release-one\n\n" +" # at time t=t2, take a checkpoint c1, create a new output buffer b2\n" +" nl-qdisc-add --dev=ifb0 --parent=root --update plug --buffer\n" +" # at time t=t2+r, after c1 is committed, release b1\n" +" nl-qdisc-add --dev=ifb0 --parent=root --update plug --release-one\n"); +} + +static void plug_parse_argv(struct rtnl_tc *tc, int argc, char **argv) +{ + struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) tc; + + for (;;) { + int c, optidx = 0; + enum { + ARG_LIMIT = 257, + ARG_BUFFER = 258, + ARG_RELEASE_ONE = 259, + ARG_RELEASE_INDEFINITE = 260, + }; + static struct option long_opts[] = { + { "help", 0, 0, 'h' }, + { "limit", 1, 0, ARG_LIMIT }, + { "buffer", 0, 0, ARG_BUFFER }, + { "release-one", 0, 0, ARG_RELEASE_ONE }, + { "release-indefinite", 0, 0, ARG_RELEASE_INDEFINITE }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "h", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case 'h': + print_usage(); + return; + + case ARG_LIMIT: + rtnl_qdisc_plug_set_limit(qdisc, nl_cli_parse_u32(optarg)); + break; + + case ARG_BUFFER: + rtnl_qdisc_plug_buffer(qdisc); + break; + + case ARG_RELEASE_ONE: + rtnl_qdisc_plug_release_one(qdisc); + break; + + case ARG_RELEASE_INDEFINITE: + rtnl_qdisc_plug_release_indefinite(qdisc); + break; + } + } +} + +static struct nl_cli_tc_module plug_module = +{ + .tm_name = "plug", + .tm_type = RTNL_TC_TYPE_QDISC, + .tm_parse_argv = plug_parse_argv, +}; + +static void __init plug_init(void) +{ + nl_cli_tc_register(&plug_module); +} + +static void __exit plug_exit(void) +{ + nl_cli_tc_unregister(&plug_module); +} diff --git a/lib/route/qdisc/plug.c b/lib/route/qdisc/plug.c new file mode 100644 index 0000000..a99b9be --- /dev/null +++ b/lib/route/qdisc/plug.c @@ -0,0 +1,177 @@ +/* + * lib/route/qdisc/plug.c PLUG Qdisc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2012 Shriram Rajagopalan + */ + +/** + * @ingroup qdisc + * @defgroup qdisc_plug Plug/Unplug Traffic (PLUG) + * @brief + * + * Queue traffic until an explicit release command. + * + * There are two ways to use this qdisc: + * 1. A simple "instantaneous" plug/unplug operation, by issuing an alternating + * sequence of TCQ_PLUG_BUFFER & TCQ_PLUG_RELEASE_INDEFINITE commands. + * + * 2. For network output buffering (a.k.a output commit) functionality. + * Output commit property is commonly used by applications using checkpoint + * based fault-tolerance to ensure that the checkpoint from which a system + * is being restored is consistent w.r.t outside world. + * + * Consider for e.g. Remus - a Virtual Machine checkpointing system, + * wherein a VM is checkpointed, say every 50ms. The checkpoint is replicated + * asynchronously to the backup host, while the VM continues executing the + * next epoch speculatively. + * + * The following is a typical sequence of output buffer operations: + * 1.At epoch i, start_buffer(i) + * 2. At end of epoch i (i.e. after 50ms): + * 2.1 Stop VM and take checkpoint(i). + * 2.2 start_buffer(i+1) and Resume VM + * 3. While speculatively executing epoch(i+1), asynchronously replicate + * checkpoint(i) to backup host. + * 4. When checkpoint_ack(i) is received from backup, release_buffer(i) + * Thus, this Qdisc would receive the following sequence of commands: + * TCQ_PLUG_BUFFER (epoch i) + * .. TCQ_PLUG_BUFFER (epoch i+1) + * ....TCQ_PLUG_RELEASE_ONE (epoch i) + * ......TCQ_PLUG_BUFFER (epoch i+2) + * ........ + * + * + * State of the queue, when used for network output buffering: + * + * plug(i+1) plug(i) head + * ------------------+--------------------+----------------> + * | | + * | | + * pkts_current_epoch| pkts_last_epoch |pkts_to_release + * ----------------->|<--------+--------->|+---------------> + * v v + * + * + * @{ + */ + +#include +#include +#include +#include +#include +#include + +static int plug_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) +{ + struct rtnl_plug *plug = data; + struct tc_plug_qopt opts; + + if (!plug) + return -NLE_INVAL; + + opts.action = plug->action; + opts.limit = plug->limit; + + return nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD); +} + +/** + * @name Attribute Modification + * @{ + */ + +/** + * Insert a plug into the qdisc and buffer any incoming + * network traffic. + * @arg qdisc PLUG qdisc to be modified. + */ +int rtnl_qdisc_plug_buffer(struct rtnl_qdisc *qdisc) +{ + struct rtnl_plug *plug; + + if (!(plug = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + plug->action = TCQ_PLUG_BUFFER; + return 0; +} + +/** + * Unplug the qdisc, releasing packets from queue head + * to the last complete buffer, while new traffic + * continues to be buffered. + * @arg qdisc PLUG qdisc to be modified. + */ +int rtnl_qdisc_plug_release_one(struct rtnl_qdisc *qdisc) +{ + struct rtnl_plug *plug; + + if (!(plug = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + plug->action = TCQ_PLUG_RELEASE_ONE; + return 0; +} + +/** + * Indefinitely unplug the qdisc, releasing all packets. + * Network traffic will not be buffered until the next + * buffer command is issued. + * @arg qdisc PLUG qdisc to be modified. + */ +int rtnl_qdisc_plug_release_indefinite(struct rtnl_qdisc *qdisc) +{ + struct rtnl_plug *plug; + + if (!(plug = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + plug->action = TCQ_PLUG_RELEASE_INDEFINITE; + return 0; +} + +/** + * Set limit of PLUG qdisc. + * @arg qdisc PLUG qdisc to be modified. + * @arg limit New limit. + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_plug_set_limit(struct rtnl_qdisc *qdisc, int limit) +{ + struct rtnl_plug *plug; + + if (!(plug = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + plug->action = TCQ_PLUG_LIMIT; + plug->limit = limit; + + return 0; +} + +/** @} */ + +static struct rtnl_tc_ops plug_ops = { + .to_kind = "plug", + .to_type = RTNL_TC_TYPE_QDISC, + .to_size = sizeof(struct rtnl_plug), + .to_msg_fill = plug_msg_fill, +}; + +static void __init plug_init(void) +{ + rtnl_tc_register(&plug_ops); +} + +static void __exit plug_exit(void) +{ + rtnl_tc_unregister(&plug_ops); +} + +/** @} */ From 0b40364150452cb8a8467d10143637bfbb99fb89 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 16 Feb 2012 12:57:42 +0100 Subject: [PATCH 136/432] Add new nl_cache_clone() function. The function can be used to make a copy of an existing cache. It is very similar to nl_cache_subset() except that it allows no filtering but copies every object. Signed-off-by: Thierry Reding Signed-off-by: Thomas Graf --- include/netlink/cache.h | 1 + lib/cache.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/include/netlink/cache.h b/include/netlink/cache.h index f8073f0..59886ac 100644 --- a/include/netlink/cache.h +++ b/include/netlink/cache.h @@ -44,6 +44,7 @@ extern int nl_cache_alloc_name(const char *, struct nl_cache **); extern struct nl_cache * nl_cache_subset(struct nl_cache *, struct nl_object *); +extern struct nl_cache * nl_cache_clone(struct nl_cache *); extern void nl_cache_clear(struct nl_cache *); extern void nl_cache_free(struct nl_cache *); diff --git a/lib/cache.c b/lib/cache.c index a1c8eae..814c616 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -287,6 +287,36 @@ struct nl_cache *nl_cache_subset(struct nl_cache *orig, return cache; } +/** + * Allocate new cache and copy the contents of an existing cache + * @arg cache Original cache to base new cache on + * + * Allocates a new cache matching the type of the cache specified by + * \p cache. Iterates over the \p cache cache and copies all objects + * to the new cache. + * + * The copied objects are clones but do not contain a reference to each + * other. Later modifications to objects in the original cache will + * not affect objects in the new cache. + * + * @return A newly allocated cache or NULL. + */ +struct nl_cache *nl_cache_clone(struct nl_cache *cache) +{ + struct nl_cache_ops *ops = nl_cache_get_ops(cache); + struct nl_cache *clone; + struct nl_object *obj; + + clone = nl_cache_alloc(ops); + if (!clone) + return NULL; + + nl_list_for_each_entry(obj, &cache->c_items, ce_list) + nl_cache_add(clone, obj); + + return clone; +} + /** * Remove all objects of a cache. * @arg cache Cache to clear From f7d06614fc233db2ef2a6bce2bcde18dc019be3b Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 23 Feb 2012 00:20:45 +0100 Subject: [PATCH 137/432] doc: Fix typos in autoconf example Reported by nick black --- doc/core.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/core.txt b/doc/core.txt index c10cbc0..1bc5a74 100644 --- a/doc/core.txt +++ b/doc/core.txt @@ -70,8 +70,8 @@ required to link against the library. ---- PKG_CHECK_MODULES(LIBNL3, libnl-3.0 >= 3.1, [have_libnl3=yes], [have_libnl3=no]) if (test "${have_libnl3}" = "yes"); then - CFLAGS += "$LIBNL3_CFLAGS" - LIBS += "$LIBNL3_LIBS" + CFLAGS="$LIBNL3_CFLAGS" + LIBS="$LIBNL3_LIBS" fi ---- From 965fd78042652693cca1c07efcce2f932b405ca7 Mon Sep 17 00:00:00 2001 From: Romary Sonrier Date: Sat, 3 Mar 2012 01:46:46 +0100 Subject: [PATCH 138/432] missing extended Table attribute for lib/route/ I found a small bug in libnl, about extended table id ( above 256 ). Signed-off-by: Romary Sonrier Signed-off-by: Thomas Graf --- lib/route/route_obj.c | 3 +++ lib/route/rule.c | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/lib/route/route_obj.c b/lib/route/route_obj.c index d322633..ac634ae 100644 --- a/lib/route/route_obj.c +++ b/lib/route/route_obj.c @@ -914,6 +914,9 @@ int rtnl_route_parse(struct nlmsghdr *nlh, struct rtnl_route **result) nl_addr_put(src); } + if (tb[RTA_TABLE]) + rtnl_route_set_table(route, nla_get_u32(tb[RTA_TABLE])); + if (tb[RTA_IIF]) rtnl_route_set_iif(route, nla_get_u32(tb[RTA_IIF])); diff --git a/lib/route/rule.c b/lib/route/rule.c index 1a695cd..076ca51 100644 --- a/lib/route/rule.c +++ b/lib/route/rule.c @@ -383,6 +383,10 @@ static int build_rule_msg(struct rtnl_rule *tmpl, int cmd, int flags, if (nlmsg_append(msg, &frh, sizeof(frh), NLMSG_ALIGNTO) < 0) goto nla_put_failure; + /* Additional table attribute replacing the 8bit in the header, was + * required to allow more than 256 tables. */ + NLA_PUT_U32(msg, FRA_TABLE, tmpl->r_table); + if (tmpl->ce_mask & RULE_ATTR_SRC) NLA_PUT_ADDR(msg, FRA_SRC, tmpl->r_src); From 7d47666eb3c414feb8901970d35b96461214c2bf Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Mon, 26 Mar 2012 14:02:25 +0200 Subject: [PATCH 139/432] doc: Fix incorrect nl_socket_add_memberships() example Reported by: Andrew Collins Signed-off-by: Thomas Graf --- doc/core.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/core.txt b/doc/core.txt index 1bc5a74..3dda08e 100644 --- a/doc/core.txt +++ b/doc/core.txt @@ -593,7 +593,7 @@ nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, my_func, NULL); nl_connect(sk, NETLINK_ROUTE); /* Subscribe to link notifications group */ -nl_socket_add_memberships(sk, RTNLGRP_LINK); +nl_socket_add_memberships(sk, RTNLGRP_LINK, 0); /* * Start receiving messages. The function nl_recvmsgs_default() will block From f54ac3d55f9acc3786369509df1bdff737e6d444 Mon Sep 17 00:00:00 2001 From: Nicolas CARRIER Date: Fri, 13 Apr 2012 13:51:44 +0200 Subject: [PATCH 140/432] Memory leak in classid.c I'm using libnl in a program which I give to valgrind in order to track memory errors / leaks. When my program exits, it complains about non-freed memory, allocated in 3 places in classid.c, at lines 280, 284 and 289. It seems related to the module's constructor classid_init which allocates resources, with no destructor to free it. The attached patch tries to fix this issue by registering a destructor which performs the tree liberation at exit. --- lib/route/classid.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/route/classid.c b/lib/route/classid.c index abed244..da531bd 100644 --- a/lib/route/classid.c +++ b/lib/route/classid.c @@ -41,7 +41,7 @@ static int compare_id(const void *pa, const void *pb) if (ma->classid < mb->classid) return -1; - + if (ma->classid > mb->classid) return 1; @@ -217,7 +217,7 @@ not_a_number: } else { /* XXXX:YYYY */ uint32_t l; - + update: l = strtoul(colon+1, &end, 16); @@ -296,7 +296,7 @@ static int classid_map_add(uint32_t classid, const char *name) /** * (Re-)read classid file - * + * * Rereads the contents of the classid file (typically found at the location * /etc/libnl/classid) and refreshes the classid maps. * @@ -409,7 +409,7 @@ int rtnl_classid_generate(const char *name, uint32_t *result, uint32_t parent) fclose(fd); if ((err = classid_map_add(classid, name)) < 0) { - /* + /* * Error adding classid map, re-read classid file is best * option here. It is likely to fail as well but better * than nothing, entry was added to the file already anyway. @@ -438,4 +438,12 @@ static void __init classid_init(void) fprintf(stderr, "Failed to read classid file: %s\n", nl_geterror(err)); } +static void __exit classid_exit(void) +{ + void free_map(void *map) { + free(((struct classid_map *)map)->name); + free(map); + }; + tdestroy(id_root, free_map); +} /** @} */ From 073ef6a66ec5c69fc39f39ab11e64147aab554a8 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 20 Apr 2012 15:18:21 +0200 Subject: [PATCH 141/432] genl-ctrl-list: Introduce -d|--details as a shortcut for --format=details --- src/genl-ctrl-list.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/genl-ctrl-list.c b/src/genl-ctrl-list.c index e25eb2a..70c5991 100644 --- a/src/genl-ctrl-list.c +++ b/src/genl-ctrl-list.c @@ -20,10 +20,10 @@ static struct nl_cache *alloc_genl_family_cache(struct nl_sock *sk) static void print_usage(void) { printf( - "Usage: genl-ctrl-list [OPTION]...\n" + "Usage: genl-ctrl-list [--details]\n" "\n" "Options\n" - " -f, --format=TYPE Output format { brief | details | stats }\n" + " -d, --details Include detailed information in the list\n" " -h, --help Show this help\n" " -v, --version Show versioning information\n" ); @@ -46,18 +46,20 @@ int main(int argc, char *argv[]) for (;;) { int c, optidx = 0; static struct option long_opts[] = { + { "details", 0, 0, 'd' }, { "format", 1, 0, 'f' }, { "help", 0, 0, 'h' }, { "version", 0, 0, 'v' }, { 0, 0, 0, 0 } }; - c = getopt_long(argc, argv, "f:hv", long_opts, &optidx); + c = getopt_long(argc, argv, "df:hv", long_opts, &optidx); if (c == -1) break; switch (c) { case 'f': params.dp_type = nl_cli_parse_dumptype(optarg); break; + case 'd': params.dp_type = NL_DUMP_DETAILS; break; case 'h': print_usage(); break; case 'v': nl_cli_print_version(); break; } From 5399b3d1926254abf9965b7beb440a1fc23a0e7f Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 20 Apr 2012 15:19:41 +0200 Subject: [PATCH 142/432] genl-ctrl-list: Provide manual page --- man/Makefile.am | 3 +- man/genl-ctrl-list.8 | 79 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 man/genl-ctrl-list.8 diff --git a/man/Makefile.am b/man/Makefile.am index afbef3f..af1277b 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -3,4 +3,5 @@ dist_man8_MANS = \ nl-classid-lookup.8 \ nl-pktloc-lookup.8 \ - nl-qdisc-add.8 nl-qdisc-delete.8 nl-qdisc-list.8 + nl-qdisc-add.8 nl-qdisc-delete.8 nl-qdisc-list.8 \ + genl-ctrl-list.8 diff --git a/man/genl-ctrl-list.8 b/man/genl-ctrl-list.8 new file mode 100644 index 0000000..a8aa3f9 --- /dev/null +++ b/man/genl-ctrl-list.8 @@ -0,0 +1,79 @@ +.TH genl\-ctrl-list 8 "20 April 2012" "libnl" +.SH NAME +genl\-ctrl\-list \- List available kernel-side generic netlink families +.SH SYNOPSIS +.B genl\-ctrl\-list [-d] + +.SH DESCRIPTION +.PP +Queries the generic netlink controller in kernel and prints a list of all +registered generic netlink families including the version of the interface +that has been registered. + +.SH OPTIONS +.TP +.BR \-\^h " or " \-\-help +Print help text to console and exit. +.TP +.BR \-\^v " or " \-\-version +Print versioning information to console and exit. +.TP +.BR \-\^d " or " \-\-details +Include additional detailed information for each generic netlink +family that is printed. + +The information includes: +.RS +.IP \(bu +The size of the family specific netlink message header (hdrsize). +.IP \(bu +The maximum netlink attribute identifier allowed by the interface +(maxattr). +.IP \(bu +A list of registered generic netlink operations prefixed with op +including their name (if available), identifier and the flags +indicating the availability of a doit or dump function. +.IP \(bu +A list of registered multicast groups prefixed with grp including +their name (if available) and identifier. +.RE + +.RS +Example: + +0x0010 nlctrl version 2 +.RS 0 + hdrsize 0 maxattr 7 +.RS 0 + op GETFAMILY (0x03) +.RS 0 + grp notify (0x10) +.RE + + +.SH EXAMPLE +.RS 0 +$ genl-ctrl-list +.RS 0 +0x0010 nlctrl version 2 +.RS 0 +0x0011 NLBL_MGMT version 3 +.RS 0 +0x0012 NLBL_CIPSOv4 version 3 +.RS 0 +0x0013 NLBL_UNLBL version 3 +.RS 0 +0x0014 acpi_event version 1 +.RS 0 +0x0015 thermal_event version 1 +.RS 0 +0x0016 VFS_DQUOT version 1 +.RS 0 +0x0017 TASKSTATS version 1 +.RS 0 +0x0018 NET_DM version 2 + +.SH AUTHOR +.PP +Thomas Graf is the original author and current maintainer of libnl and +libnl tools. Many people have contributed to it since. From 4a2962d8974a65bc0eb7cc48614bc2eee1216ea7 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 20 Apr 2012 15:27:52 +0200 Subject: [PATCH 143/432] genl-ctrl-list: fix copyright and summary --- src/genl-ctrl-list.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/genl-ctrl-list.c b/src/genl-ctrl-list.c index 70c5991..0895bcc 100644 --- a/src/genl-ctrl-list.c +++ b/src/genl-ctrl-list.c @@ -1,12 +1,12 @@ /* - * src/genl-ctrl-list.c List Generic Netlink Controller + * src/genl-ctrl-list.c List Generic Netlink Families * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2009 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ #include From 5f4d4d3bec7b9fc9a030f5a27f9cb0cd14ac73fd Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 20 Apr 2012 15:28:48 +0200 Subject: [PATCH 144/432] genl-ctrl-list: Mark for installation --- src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index b59f96a..132a415 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -12,6 +12,7 @@ LDADD = \ ${top_builddir}/lib/libnl-route-3.la sbin_PROGRAMS = \ + genl-ctrl-list \ nl-qdisc-add nl-qdisc-list nl-qdisc-delete \ nl-class-add nl-class-list nl-class-delete \ nl-cls-add nl-cls-list nl-cls-delete \ @@ -20,7 +21,6 @@ sbin_PROGRAMS = \ nl-link-list noinst_PROGRAMS = \ - genl-ctrl-list \ nf-ct-list nf-log nf-queue nf-monitor \ nl-addr-add nl-addr-delete nl-addr-list \ nl-link-set nl-link-stats \ From 653ea3457a2d6d74aa0ba877d7b0e1cd6309fb40 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 21 Apr 2012 09:59:26 +0200 Subject: [PATCH 145/432] cache_mngr: document uncommon error codes --- lib/cache_mngr.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/cache_mngr.c b/lib/cache_mngr.c index 0be55bc..3c0e024 100644 --- a/lib/cache_mngr.c +++ b/lib/cache_mngr.c @@ -213,6 +213,11 @@ errout: * changes. * * @return 0 on success or a negative error code. + * @return -NLE_NOCACHE Unknown cache type + * @return -NLE_PROTO_MISMATCH Protocol mismatch between cache manager and + * cache type + * @return -NLE_OPNOTSUPP Cache type does not support updates + * @return -NLE_EXIST Cache of this type already being managed */ int nl_cache_mngr_add(struct nl_cache_mngr *mngr, const char *name, change_func_t cb, void *data, struct nl_cache **result) From 9af54690041aaa0a4934c336709bdf42a57afe28 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 21 Apr 2012 10:34:43 +0200 Subject: [PATCH 146/432] tests: Convert tests/Makefile to use automake --- Makefile.am | 2 +- configure.in | 1 + tests/Makefile | 33 --------------------------------- tests/Makefile.am | 31 +++++++++++++++++++++++++++++++ 4 files changed, 33 insertions(+), 34 deletions(-) delete mode 100644 tests/Makefile create mode 100644 tests/Makefile.am diff --git a/Makefile.am b/Makefile.am index e21060f..c4617c4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,7 +2,7 @@ ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = include lib doc man python +SUBDIRS = include lib doc man python tests pkgconfig_DATA = libnl-3.0.pc \ libnl-route-3.0.pc \ diff --git a/configure.in b/configure.in index b6060c7..9d99db2 100644 --- a/configure.in +++ b/configure.in @@ -84,6 +84,7 @@ lib/Makefile include/Makefile src/Makefile src/lib/Makefile +tests/Makefile man/Makefile python/Makefile python/setup.py diff --git a/tests/Makefile b/tests/Makefile deleted file mode 100644 index d072ddb..0000000 --- a/tests/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -# -# src/Makefile -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation version 2.1 -# of the License. -# -# Copyright (c) 2003-2006 Thomas Graf -# - -ifeq ($(shell [ ! -r ../Makefile.opts ] && echo 1),) - include ../Makefile.opts -endif - -LDFLAGS += -L../lib -lnl -lnl-genl -lnl-route -CIN := $(wildcard test-*.c) -TESTS := $(CIN:%.c=%) - -all: $(TESTS) - -test-%: test-%.c - @echo " LD $@"; \ - $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) - -clean: - @echo " CLEAN src"; \ - rm -f $(TESTS) - -distclean: clean - -install: - @true diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..4193818 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,31 @@ +# -*- Makefile -*- + +AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -D_GNU_SOURCE -DSYSCONFDIR=\"$(sysconfdir)/libnl\" + +LDADD = \ + ${top_builddir}/src/lib/libnl-cli-3.la \ + ${top_builddir}/lib/libnl-3.la \ + ${top_builddir}/lib/libnl-nf-3.la \ + ${top_builddir}/lib/libnl-genl-3.la \ + ${top_builddir}/lib/libnl-route-3.la + +check_PROGRAMS = \ + test-cache-mngr \ + test-create-bond \ + test-create-vlan \ + test-delete-link \ + test-genl \ + test-nf-cache-mngr \ + test-socket-creation + +# Eventually add these to TESTS once converted to be real +# test programs +# TESTS = $(check_PROGRAMS) + +test_cache_mngr_SOURCES = test-cache-mngr.c +test_create_bond_SOURCES = test-create-bond.c +test_create_vlan_SOURCES = test-create-vlan.c +test_delete_link_SOURCES = test-delete-link.c +test_genl_SOURCES = test-genl.c +test_nf_cache_mngr_SOURCES = test-nf-cache-mngr.c +test_socket_creation_SOURCES = test-socket-creation.c From e78975aea8dc6b091d56f5ac4c0bd6def598f070 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 21 Apr 2012 10:35:20 +0200 Subject: [PATCH 147/432] tests: fix test programs to compile again --- tests/test-cache-mngr.c | 38 +++++++++++++++++++----------------- tests/test-create-bond.c | 2 +- tests/test-genl.c | 16 +++++++-------- tests/test-nf-cache-mngr.c | 23 +++++++++++----------- tests/test-socket-creation.c | 15 +++++++------- 5 files changed, 49 insertions(+), 45 deletions(-) diff --git a/tests/test-cache-mngr.c b/tests/test-cache-mngr.c index 777bce8..2c917da 100644 --- a/tests/test-cache-mngr.c +++ b/tests/test-cache-mngr.c @@ -1,10 +1,12 @@ -#include "../src/utils.h" +#include +#include +#include #include static int quit = 0; static void change_cb(struct nl_cache *cache, struct nl_object *obj, - int action) + int action, void *data) { struct nl_dump_params dp = { .dp_type = NL_DUMP_LINE, @@ -35,32 +37,32 @@ int main(int argc, char *argv[]) signal(SIGINT, sigint); - sock = nlt_alloc_socket(); + sock = nl_cli_alloc_socket(); err = nl_cache_mngr_alloc(sock, NETLINK_ROUTE, NL_AUTO_PROVIDE, &mngr); if (err < 0) - fatal(err, "Unable to allocate cache manager: %s", - nl_geterror(err)); + nl_cli_fatal(err, "Unable to allocate cache manager: %s", + nl_geterror(err)); - if ((err = nl_cache_mngr_add(mngr, "route/link", &change_cb, &lc)) < 0) - fatal(err, "Unable to add cache route/link: %s", - nl_geterror(err)); + if ((err = nl_cache_mngr_add(mngr, "route/link", &change_cb, NULL, &lc)) < 0) + nl_cli_fatal(err, "Unable to add cache route/link: %s", + nl_geterror(err)); - if ((err = nl_cache_mngr_add(mngr, "route/neigh", &change_cb, &nc)) < 0) - fatal(err, "Unable to add cache route/neigh: %s", - nl_geterror(err)); + if ((err = nl_cache_mngr_add(mngr, "route/neigh", &change_cb, NULL, &nc)) < 0) + nl_cli_fatal(err, "Unable to add cache route/neigh: %s", + nl_geterror(err)); - if ((err = nl_cache_mngr_add(mngr, "route/addr", &change_cb, &ac)) < 0) - fatal(err, "Unable to add cache route/addr: %s", - nl_geterror(err)); + if ((err = nl_cache_mngr_add(mngr, "route/addr", &change_cb, NULL, &ac)) < 0) + nl_cli_fatal(err, "Unable to add cache route/addr: %s", + nl_geterror(err)); - if ((err = nl_cache_mngr_add(mngr, "route/route", &change_cb, &rc)) < 0) - fatal(err, "Unable to add cache route/route: %s", - nl_geterror(err)); + if ((err = nl_cache_mngr_add(mngr, "route/route", &change_cb, NULL, &rc)) < 0) + nl_cli_fatal(err, "Unable to add cache route/route: %s", + nl_geterror(err)); while (!quit) { int err = nl_cache_mngr_poll(mngr, 5000); if (err < 0 && err != -NLE_INTR) - fatal(err, "Polling failed: %s", nl_geterror(err)); + nl_cli_fatal(err, "Polling failed: %s", nl_geterror(err)); } diff --git a/tests/test-create-bond.c b/tests/test-create-bond.c index 99166aa..e54b0e6 100644 --- a/tests/test-create-bond.c +++ b/tests/test-create-bond.c @@ -16,7 +16,7 @@ int main(int argc, char *argv[]) link = rtnl_link_alloc(); rtnl_link_set_name(link, "my_bond"); - if ((err = rtnl_link_set_info_type(link, "bond")) < 0) { + if ((err = rtnl_link_set_type(link, "bond")) < 0) { nl_perror(err, "Unable to set link info type"); return err; } diff --git a/tests/test-genl.c b/tests/test-genl.c index 8bf60c5..2706a92 100644 --- a/tests/test-genl.c +++ b/tests/test-genl.c @@ -1,4 +1,4 @@ -#include "../src/utils.h" +#include int main(int argc, char *argv[]) { @@ -7,26 +7,26 @@ int main(int argc, char *argv[]) void *hdr; int err; - sock = nlt_alloc_socket(); - nlt_connect(sock, NETLINK_GENERIC); + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_GENERIC); msg = nlmsg_alloc(); if (msg == NULL) - fatal(NLE_NOMEM, "Unable to allocate netlink message"); + nl_cli_fatal(NLE_NOMEM, "Unable to allocate netlink message"); hdr = genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, GENL_ID_CTRL, 0, 0, CTRL_CMD_GETFAMILY, 1); if (hdr == NULL) - fatal(ENOMEM, "Unable to write genl header"); + nl_cli_fatal(ENOMEM, "Unable to write genl header"); if ((err = nla_put_u32(msg, CTRL_ATTR_FAMILY_ID, GENL_ID_CTRL)) < 0) - fatal(err, "Unable to add attribute: %s", nl_geterror(err)); + nl_cli_fatal(err, "Unable to add attribute: %s", nl_geterror(err)); if ((err = nl_send_auto_complete(sock, msg)) < 0) - fatal(err, "Unable to send message: %s", nl_geterror(err)); + nl_cli_fatal(err, "Unable to send message: %s", nl_geterror(err)); if ((err = nl_recvmsgs_default(sock)) < 0) - fatal(err, "Unable to receive message: %s", nl_geterror(err)); + nl_cli_fatal(err, "Unable to receive message: %s", nl_geterror(err)); nlmsg_free(msg); nl_close(sock); diff --git a/tests/test-nf-cache-mngr.c b/tests/test-nf-cache-mngr.c index 05485bf..b4f3022 100644 --- a/tests/test-nf-cache-mngr.c +++ b/tests/test-nf-cache-mngr.c @@ -1,13 +1,13 @@ -#include "../src/utils.h" +#include static void change_cb(struct nl_cache *cache, struct nl_object *obj, - int action) + int action, void *data) { struct nfnl_ct *ct = (struct nfnl_ct *) obj; static struct nl_addr *hack = NULL; if (!hack) - hack = nl_addr_parse("194.88.212.233", AF_INET); + nl_addr_parse("194.88.212.233", AF_INET, &hack); if (!nl_addr_cmp(hack, nfnl_ct_get_src(ct, 1)) || !nl_addr_cmp(hack, nfnl_ct_get_dst(ct, 1))) { @@ -26,25 +26,26 @@ int main(int argc, char *argv[]) struct nl_cache_mngr *mngr; struct nl_sock *sock; struct nl_cache *ct; + int err; - sock = nlt_socket_alloc(); + sock = nl_cli_alloc_socket(); - mngr = nl_cache_mngr_alloc(sock, NETLINK_NETFILTER, NL_AUTO_PROVIDE); - if (!mngr) { - nl_perror("nl_cache_mngr_alloc"); + err = nl_cache_mngr_alloc(sock, NETLINK_NETFILTER, NL_AUTO_PROVIDE, &mngr); + if (err < 0) { + nl_perror(err, "nl_cache_mngr_alloc"); return -1; } - ct = nl_cache_mngr_add(mngr, "netfilter/ct", &change_cb); - if (ct == NULL) { - nl_perror("nl_cache_mngr_add(netfilter/ct)"); + err = nl_cache_mngr_add(mngr, "netfilter/ct", &change_cb, NULL, &ct); + if (err < 0) { + nl_perror(err, "nl_cache_mngr_add(netfilter/ct)"); return -1; } for (;;) { int err = nl_cache_mngr_poll(mngr, 5000); if (err < 0) { - nl_perror("nl_cache_mngr_poll()"); + nl_perror(err, "nl_cache_mngr_poll()"); return -1; } diff --git a/tests/test-socket-creation.c b/tests/test-socket-creation.c index a170ccd..83f3ad4 100644 --- a/tests/test-socket-creation.c +++ b/tests/test-socket-creation.c @@ -1,23 +1,24 @@ -#include "../src/utils.h" +#include +#include int main(int argc, char *argv[]) { struct nl_sock *h[1025]; int i; - h[0] = nl_handle_alloc(); + h[0] = nl_socket_alloc(); printf("Created handle with port 0x%x\n", nl_socket_get_local_port(h[0])); - nl_handle_destroy(h[0]); - h[0] = nl_handle_alloc(); + nl_socket_free(h[0]); + h[0] = nl_socket_alloc(); printf("Created handle with port 0x%x\n", nl_socket_get_local_port(h[0])); - nl_handle_destroy(h[0]); + nl_socket_free(h[0]); for (i = 0; i < 1025; i++) { - h[i] = nl_handle_alloc(); + h[i] = nl_socket_alloc(); if (h[i] == NULL) - nl_perror("Unable to allocate socket"); + nl_perror(ENOMEM, "Unable to allocate socket"); else printf("Created handle with port 0x%x\n", nl_socket_get_local_port(h[i])); From b32011254d225dc252d491801ddc329be0920ba2 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 21 Apr 2012 10:51:34 +0200 Subject: [PATCH 148/432] cache_mngr: Don't modify callback setup of socket Instead, clone it and modify a temporary copy. Although it is not recommended to use the same socket for requests and to serve a cache manager, this change might prevent some unwanted side effects if done so. --- lib/cache_mngr.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/cache_mngr.c b/lib/cache_mngr.c index 3c0e024..7b75084 100644 --- a/lib/cache_mngr.c +++ b/lib/cache_mngr.c @@ -175,9 +175,6 @@ int nl_cache_mngr_alloc(struct nl_sock *sk, int protocol, int flags, if (!mngr->cm_assocs) goto errout; - nl_socket_modify_cb(mngr->cm_handle, NL_CB_VALID, NL_CB_CUSTOM, - event_input, mngr); - /* Required to receive async event notifications */ nl_socket_disable_seq_check(mngr->cm_handle); @@ -359,8 +356,19 @@ int nl_cache_mngr_poll(struct nl_cache_mngr *mngr, int timeout) int nl_cache_mngr_data_ready(struct nl_cache_mngr *mngr) { int err; + struct nl_cb *cb; - err = nl_recvmsgs_default(mngr->cm_handle); + NL_DBG(2, "Cache manager %p, reading new data from fd %d\n", + mngr, nl_socket_get_fd(mngr->cm_handle)); + + cb = nl_cb_clone(mngr->cm_handle->s_cb); + if (cb == NULL) + return -NLE_NOMEM; + + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, event_input, mngr); + + err = nl_recvmsgs(mngr->cm_handle, cb); + nl_cb_put(cb); if (err < 0) return err; From c55acc438b8703c03f021aeb65a57a7c6b1fc9ed Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 21 Apr 2012 11:38:33 +0200 Subject: [PATCH 149/432] cache_manager: Move documentation to doc/core.txt --- doc/core.txt | 76 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/cache_mngr.c | 66 +---------------------------------------- 2 files changed, 77 insertions(+), 65 deletions(-) diff --git a/doc/core.txt b/doc/core.txt index 3dda08e..19ebf70 100644 --- a/doc/core.txt +++ b/doc/core.txt @@ -2555,6 +2555,82 @@ to further specify what will be part of the cache. All such functions return a newly allocated cache or NULL in case of an error. +=== Cache Manager + +The purpose of a cache manager is to keep track of caches and +automatically receive event notifications to keep the caches +up to date with the kernel state. Each manager has exactly one +netlink socket assigned which limits the scope of each manager +to exactly one netlink family. Therefore all caches committed +to a manager must be part of the same netlink family. Due to the +nature of a manager, it is not possible to have a cache maintain +two instances of the same cache type. The socket is subscribed +to the event notification group of each cache and also put into +non-blocking mode. Functions exist to poll() on the socket to +wait for new events to be received. + + +---- + App libnl Kernel + | | + +-----------------+ [ notification, link change ] + | | Cache Manager | | [ (IFF_UP | IFF_RUNNING) ] + | | | + | | +------------+| | | [ notification, new addr ] + <-------|---| route/link |<-------(async)--+ [ 10.0.1.1/32 dev eth1 ] + | | +------------+| | | + | +------------+| | + <---|---|---| route/addr |<------|-(async)--------------+ + | +------------+| + | | +------------+| | + <-------|---| ... || + | | +------------+| | + +-----------------+ + | | +---- + +.Creating a new cache manager + +[source,c] +---- +struct nl_cache_mngr *mngr; + +// Allocate a new cache manager for RTNETLINK and automatically +// provide the caches added to the manager. +mngr = nl_cache_mngr_alloc(NETLINK_ROUTE, NL_AUTO_PROVIDE); +---- + +.Keep track of a cache + +[source,c] +---- +struct nl_cache *cache; + +// Create a new cache for links/interfaces and ask the manager to +// keep it up to date for us. This will trigger a full dump request +// to initially fill the cache. +cache = nl_cache_mngr_add(mngr, "route/link"); +----- + +.Make the manager receive updates + +[source,c] +---- +// Give the manager the ability to receive updates, will call poll() +// with a timeout of 5 seconds. +if (nl_cache_mngr_poll(mngr, 5000) > 0) { + // Manager received at least one update, dump cache? + nl_cache_dump(cache, ...); +} +---- + +.Release cache manager + +[source,c] +---- +nl_cache_mngr_free(mngr); +---- + == Abstract Data Types A few high level abstract data types which are used by a majority netlink diff --git a/lib/cache_mngr.c b/lib/cache_mngr.c index 7b75084..b6e4a82 100644 --- a/lib/cache_mngr.c +++ b/lib/cache_mngr.c @@ -12,72 +12,8 @@ /** * @ingroup cache_mngt * @defgroup cache_mngr Manager - * @brief Helps keeping caches up to date. + * @brief Automatically keep caches up to date * - * The purpose of a cache manager is to keep track of caches and - * automatically receive event notifications to keep the caches - * up to date with the kernel state. Each manager has exactly one - * netlink socket assigned which limits the scope of each manager - * to exactly one netlink family. Therefore all caches committed - * to a manager must be part of the same netlink family. Due to the - * nature of a manager, it is not possible to have a cache maintain - * two instances of the same cache type. The socket is subscribed - * to the event notification group of each cache and also put into - * non-blocking mode. Functions exist to poll() on the socket to - * wait for new events to be received. - * - * @code - * App libnl Kernel - * | | - * +-----------------+ [ notification, link change ] - * | | Cache Manager | | [ (IFF_UP | IFF_RUNNING) ] - * | | | - * | | +------------+| | | [ notification, new addr ] - * <-------|---| route/link |<-------(async)--+ [ 10.0.1.1/32 dev eth1 ] - * | | +------------+| | | - * | +------------+| | - * <---|---|---| route/addr |<------|-(async)--------------+ - * | +------------+| - * | | +------------+| | - * <-------|---| ... || - * | | +------------+| | - * +-----------------+ - * | | - * @endcode - * - * @par 1) Creating a new cache manager - * @code - * struct nl_cache_mngr *mngr; - * - * // Allocate a new cache manager for RTNETLINK and automatically - * // provide the caches added to the manager. - * mngr = nl_cache_mngr_alloc(NETLINK_ROUTE, NL_AUTO_PROVIDE); - * @endcode - * - * @par 2) Keep track of a cache - * @code - * struct nl_cache *cache; - * - * // Create a new cache for links/interfaces and ask the manager to - * // keep it up to date for us. This will trigger a full dump request - * // to initially fill the cache. - * cache = nl_cache_mngr_add(mngr, "route/link"); - * @endcode - * - * @par 3) Make the manager receive updates - * @code - * // Give the manager the ability to receive updates, will call poll() - * // with a timeout of 5 seconds. - * if (nl_cache_mngr_poll(mngr, 5000) > 0) { - * // Manager received at least one update, dump cache? - * nl_cache_dump(cache, ...); - * } - * @endcode - * - * @par 4) Release cache manager - * @code - * nl_cache_mngr_free(mngr); - * @endcode * @{ */ From e34ed950bd9c8f0deccc3cae1ec473be751253ff Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 21 Apr 2012 12:11:45 +0200 Subject: [PATCH 150/432] cache_mngr: Automatically allocate socket if needed The requirement to have the caller provide the socket does not make much sense. Automatically allocate the socket if none was provided. This may also avoid some future abuse of reusing request sockets for handling notifications. Also rename cm_handle to cm_sock for clarity (no API change) --- include/netlink-types.h | 4 +-- include/netlink/cache.h | 3 +- lib/cache_mngr.c | 75 +++++++++++++++++++++++++++++------------ 3 files changed, 57 insertions(+), 25 deletions(-) diff --git a/include/netlink-types.h b/include/netlink-types.h index 5ced836..24228a7 100644 --- a/include/netlink-types.h +++ b/include/netlink-types.h @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ #ifndef NETLINK_LOCAL_TYPES_H_ @@ -92,7 +92,7 @@ struct nl_cache_mngr int cm_protocol; int cm_flags; int cm_nassocs; - struct nl_sock * cm_handle; + struct nl_sock * cm_sock; struct nl_cache_assoc * cm_assocs; }; diff --git a/include/netlink/cache.h b/include/netlink/cache.h index 59886ac..e42f692 100644 --- a/include/netlink/cache.h +++ b/include/netlink/cache.h @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ #ifndef NETLINK_CACHE_H_ @@ -113,6 +113,7 @@ extern struct nl_cache * __nl_cache_mngt_require(const char *); struct nl_cache_mngr; #define NL_AUTO_PROVIDE 1 +#define NL_ALLOCATED_SOCK 2 /* For internal use only, do not use */ extern int nl_cache_mngr_alloc(struct nl_sock *, int, int, diff --git a/lib/cache_mngr.c b/lib/cache_mngr.c index b6e4a82..f4960d6 100644 --- a/lib/cache_mngr.c +++ b/lib/cache_mngr.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ /** @@ -82,11 +82,30 @@ found: /** * Allocate new cache manager - * @arg sk Netlink socket. - * @arg protocol Netlink Protocol this manager is used for - * @arg flags Flags + * @arg sk Netlink socket or NULL to auto allocate + * @arg protocol Netlink protocol this manager is used for + * @arg flags Flags (\c NL_AUTO_PROVIDE) * @arg result Result pointer * + * Allocates a new cache manager for the specified netlink protocol. + * + * 1. If sk is not specified (\c NULL) a netlink socket matching the + * specified protocol will be automatically allocated. + * + * 2. The socket will be put in non-blocking mode and sequence checking + * will be disabled regardless of whether the socket was provided by + * the caller or automatically allocated. + * + * 3. The socket will be connected. + * + * If the flag \c NL_AUTO_PROVIDE is specified, any cache added to the + * manager will automatically be made available to other users using + * nl_cache_mngt_provide(). + * + * @note If the socket is provided by the caller, it is NOT recommended + * to use the socket for anything else besides receiving netlink + * notifications. + * * @return 0 on success or a negative error code. */ int nl_cache_mngr_alloc(struct nl_sock *sk, int protocol, int flags, @@ -95,14 +114,22 @@ int nl_cache_mngr_alloc(struct nl_sock *sk, int protocol, int flags, struct nl_cache_mngr *mngr; int err = -NLE_NOMEM; - if (sk == NULL) + /* Catch abuse of flags */ + if (flags & NL_ALLOCATED_SOCK) BUG(); mngr = calloc(1, sizeof(*mngr)); if (!mngr) - goto errout; + return -NLE_NOMEM; - mngr->cm_handle = sk; + if (!sk) { + if (!(sk = nl_socket_alloc())) + goto errout; + + flags |= NL_ALLOCATED_SOCK; + } + + mngr->cm_sock = sk; mngr->cm_nassocs = 32; mngr->cm_protocol = protocol; mngr->cm_flags = flags; @@ -112,12 +139,12 @@ int nl_cache_mngr_alloc(struct nl_sock *sk, int protocol, int flags, goto errout; /* Required to receive async event notifications */ - nl_socket_disable_seq_check(mngr->cm_handle); + nl_socket_disable_seq_check(mngr->cm_sock); - if ((err = nl_connect(mngr->cm_handle, protocol) < 0)) + if ((err = nl_connect(mngr->cm_sock, protocol) < 0)) goto errout; - if ((err = nl_socket_set_nonblocking(mngr->cm_handle) < 0)) + if ((err = nl_socket_set_nonblocking(mngr->cm_sock) < 0)) goto errout; NL_DBG(1, "Allocated cache manager %p, protocol %d, %d caches\n", @@ -142,7 +169,7 @@ errout: * Allocates a new cache of the specified type and adds it to the manager. * The operation will trigger a full dump request from the kernel to * initially fill the contents of the cache. The manager will subscribe - * to the notification group of the cache to keep track of any further + * to the notification group of the cache and keep track of any further * changes. * * @return 0 on success or a negative error code. @@ -199,12 +226,12 @@ retry: return -NLE_NOMEM; for (grp = ops->co_groups; grp->ag_group; grp++) { - err = nl_socket_add_membership(mngr->cm_handle, grp->ag_group); + err = nl_socket_add_membership(mngr->cm_sock, grp->ag_group); if (err < 0) goto errout_free_cache; } - err = nl_cache_refill(mngr->cm_handle, cache); + err = nl_cache_refill(mngr->cm_sock, cache); if (err < 0) goto errout_drop_membership; @@ -223,7 +250,7 @@ retry: errout_drop_membership: for (grp = ops->co_groups; grp->ag_group; grp++) - nl_socket_drop_membership(mngr->cm_handle, grp->ag_group); + nl_socket_drop_membership(mngr->cm_sock, grp->ag_group); errout_free_cache: nl_cache_free(cache); @@ -240,7 +267,7 @@ errout_free_cache: */ int nl_cache_mngr_get_fd(struct nl_cache_mngr *mngr) { - return nl_socket_get_fd(mngr->cm_handle); + return nl_socket_get_fd(mngr->cm_sock); } /** @@ -262,7 +289,7 @@ int nl_cache_mngr_poll(struct nl_cache_mngr *mngr, int timeout) { int ret; struct pollfd fds = { - .fd = nl_socket_get_fd(mngr->cm_handle), + .fd = nl_socket_get_fd(mngr->cm_sock), .events = POLLIN, }; @@ -272,6 +299,7 @@ int nl_cache_mngr_poll(struct nl_cache_mngr *mngr, int timeout) if (ret < 0) return -nl_syserr2nlerr(errno); + /* No events, return */ if (ret == 0) return 0; @@ -295,15 +323,15 @@ int nl_cache_mngr_data_ready(struct nl_cache_mngr *mngr) struct nl_cb *cb; NL_DBG(2, "Cache manager %p, reading new data from fd %d\n", - mngr, nl_socket_get_fd(mngr->cm_handle)); + mngr, nl_socket_get_fd(mngr->cm_sock)); - cb = nl_cb_clone(mngr->cm_handle->s_cb); + cb = nl_cb_clone(mngr->cm_sock->s_cb); if (cb == NULL) return -NLE_NOMEM; nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, event_input, mngr); - err = nl_recvmsgs(mngr->cm_handle, cb); + err = nl_recvmsgs(mngr->cm_sock, cb); nl_cb_put(cb); if (err < 0) return err; @@ -315,7 +343,7 @@ int nl_cache_mngr_data_ready(struct nl_cache_mngr *mngr) * Free cache manager and all caches. * @arg mngr Cache manager. * - * Release all resources after usage of a cache manager. + * Release all resources held by a cache manager. */ void nl_cache_mngr_free(struct nl_cache_mngr *mngr) { @@ -324,8 +352,11 @@ void nl_cache_mngr_free(struct nl_cache_mngr *mngr) if (!mngr) return; - if (mngr->cm_handle) - nl_close(mngr->cm_handle); + if (mngr->cm_sock) + nl_close(mngr->cm_sock); + + if (mngr->cm_flags & NL_ALLOCATED_SOCK) + nl_socket_free(mngr->cm_sock); for (i = 0; i < mngr->cm_nassocs; i++) { if (mngr->cm_assocs[i].ca_cache) { From a143037fa37994270a3db7f7eb57f128c9f5b29a Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 21 Apr 2012 12:14:11 +0200 Subject: [PATCH 151/432] test-cache-mngr: Let the cache manager allocate the socket --- tests/test-cache-mngr.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/test-cache-mngr.c b/tests/test-cache-mngr.c index 2c917da..528ae18 100644 --- a/tests/test-cache-mngr.c +++ b/tests/test-cache-mngr.c @@ -32,13 +32,11 @@ int main(int argc, char *argv[]) { struct nl_cache_mngr *mngr; struct nl_cache *lc, *nc, *ac, *rc; - struct nl_sock *sock; int err; signal(SIGINT, sigint); - sock = nl_cli_alloc_socket(); - err = nl_cache_mngr_alloc(sock, NETLINK_ROUTE, NL_AUTO_PROVIDE, &mngr); + err = nl_cache_mngr_alloc(NULL, NETLINK_ROUTE, NL_AUTO_PROVIDE, &mngr); if (err < 0) nl_cli_fatal(err, "Unable to allocate cache manager: %s", nl_geterror(err)); @@ -67,7 +65,6 @@ int main(int argc, char *argv[]) } nl_cache_mngr_free(mngr); - nl_socket_free(sock); return 0; } From adbc5687358ef62c5edb349332b3d031c01fcbb2 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 21 Apr 2012 12:23:38 +0200 Subject: [PATCH 152/432] cache_mngr: Fix memory corruption after resizing The reallocated part of the enlarged association array was left uninitialized which would have resulted in trying to free random pointers. This was a theoretical bug because it wasn't possible to register more than 32 cache types since no netlink family supports that many individual cache types. Nevertheless this patch fixes the bug and also reduces the default size of the allocation table and expandations a bit to reduce the memory footprint slightly. --- lib/cache_mngr.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/cache_mngr.c b/lib/cache_mngr.c index f4960d6..aaf90bf 100644 --- a/lib/cache_mngr.c +++ b/lib/cache_mngr.c @@ -22,6 +22,9 @@ #include #include +#define NASSOC_INIT 16 +#define NASSOC_EXPAND 8 + static int include_cb(struct nl_object *obj, struct nl_parser_param *p) { struct nl_cache_assoc *ca = p->pp_arg; @@ -130,7 +133,7 @@ int nl_cache_mngr_alloc(struct nl_sock *sk, int protocol, int flags, } mngr->cm_sock = sk; - mngr->cm_nassocs = 32; + mngr->cm_nassocs = NASSOC_INIT; mngr->cm_protocol = protocol; mngr->cm_flags = flags; mngr->cm_assocs = calloc(mngr->cm_nassocs, @@ -208,17 +211,19 @@ retry: break; if (i >= mngr->cm_nassocs) { - mngr->cm_nassocs += 16; + mngr->cm_nassocs += NASSOC_EXPAND; mngr->cm_assocs = realloc(mngr->cm_assocs, mngr->cm_nassocs * sizeof(struct nl_cache_assoc)); if (mngr->cm_assocs == NULL) return -NLE_NOMEM; - else { - NL_DBG(1, "Increased capacity of cache manager %p " \ - "to %d\n", mngr, mngr->cm_nassocs); - goto retry; - } + + memset(mngr->cm_assocs + (mngr->cm_nassocs - NASSOC_EXPAND), 0, + NASSOC_EXPAND * sizeof(struct nl_cache_assoc)); + + NL_DBG(1, "Increased capacity of cache manager %p " \ + "to %d\n", mngr, mngr->cm_nassocs); + goto retry; } cache = nl_cache_alloc(ops); From e0482794a8b70ae23361bfbe3701d4c2c96c66a6 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 21 Apr 2012 12:46:01 +0200 Subject: [PATCH 153/432] nl: Make nl_recvmsgs() return the number of netlink messages processed --- lib/nl.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/nl.c b/lib/nl.c index bcf89da..c41a3b9 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -559,7 +559,7 @@ do { \ static int recvmsgs(struct nl_sock *sk, struct nl_cb *cb) { - int n, err = 0, multipart = 0, interrupted = 0; + int n, err = 0, multipart = 0, interrupted = 0, nrecv = 0; unsigned char *buf = NULL; struct nlmsghdr *hdr; struct sockaddr_nl nla = {0}; @@ -594,6 +594,8 @@ continue_reading: if (creds) nlmsg_set_creds(msg, creds); + nrecv++; + /* Raw callback is the first, it gives the most control * to the user and he can do his very own parsing. */ if (cb->cb_set[NL_CB_MSG_IN]) @@ -754,6 +756,9 @@ out: if (interrupted) err = -NLE_DUMP_INTR; + if (!err) + err = nrecv; + return err; } @@ -770,7 +775,7 @@ out: * A non-blocking sockets causes the function to return immediately if * no data is available. * - * @return 0 on success or a negative error code from nl_recv(). + * @return Number of received messages or a negative error code from nl_recv(). */ int nl_recvmsgs(struct nl_sock *sk, struct nl_cb *cb) { From a518a318d496ef5a2c02b4e0ad2eae45b0f77e5d Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 21 Apr 2012 12:47:29 +0200 Subject: [PATCH 154/432] cache_mngr: Let nl_cache_mngr_data_ready() read multiple messages Having nl_recvmsgs() return the number of read messages allows to continue reading until the underlying recvmsg() will return EAGAIN for the non blocking socket. --- lib/cache_mngr.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/cache_mngr.c b/lib/cache_mngr.c index aaf90bf..3eefbb0 100644 --- a/lib/cache_mngr.c +++ b/lib/cache_mngr.c @@ -324,7 +324,7 @@ int nl_cache_mngr_poll(struct nl_cache_mngr *mngr, int timeout) */ int nl_cache_mngr_data_ready(struct nl_cache_mngr *mngr) { - int err; + int err, nread = 0; struct nl_cb *cb; NL_DBG(2, "Cache manager %p, reading new data from fd %d\n", @@ -336,12 +336,17 @@ int nl_cache_mngr_data_ready(struct nl_cache_mngr *mngr) nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, event_input, mngr); - err = nl_recvmsgs(mngr->cm_sock, cb); + while ((err = nl_recvmsgs(mngr->cm_sock, cb)) > 0) { + NL_DBG(2, "Cache manager %p, recvmsgs read %d messages\n", + mngr, err); + nread += err; + } + nl_cb_put(cb); if (err < 0) return err; - return 1; + return nread; } /** From 743756f3b4f634d0c08cb6e883428e63f8b28acc Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 21 Apr 2012 15:22:04 +0200 Subject: [PATCH 155/432] cache_mngr: API doc updates --- lib/cache_mngr.c | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/lib/cache_mngr.c b/lib/cache_mngr.c index 3eefbb0..9388f40 100644 --- a/lib/cache_mngr.c +++ b/lib/cache_mngr.c @@ -22,8 +22,10 @@ #include #include +/** @cond SKIP */ #define NASSOC_INIT 16 #define NASSOC_EXPAND 8 +/** @endcond */ static int include_cb(struct nl_object *obj, struct nl_parser_param *p) { @@ -175,6 +177,13 @@ errout: * to the notification group of the cache and keep track of any further * changes. * + * The user is responsible for calling nl_cache_mngr_poll() or monitor + * the socket and call nl_cache_mngr_data_ready() to allow the library + * to process netlink notification events. + * + * @see nl_cache_mngr_poll() + * @see nl_cache_mngr_data_ready() + * * @return 0 on success or a negative error code. * @return -NLE_NOCACHE Unknown cache type * @return -NLE_PROTO_MISMATCH Protocol mismatch between cache manager and @@ -263,12 +272,13 @@ errout_free_cache: } /** - * Get file descriptor + * Get socket file descriptor * @arg mngr Cache Manager * - * Get the file descriptor of the socket associated to the manager. - * This can be used to change socket options or monitor activity - * using poll()/select(). + * Get the file descriptor of the socket associated with the manager. + * + * @note Do not use the socket for anything besides receiving + * notifications. */ int nl_cache_mngr_get_fd(struct nl_cache_mngr *mngr) { @@ -281,14 +291,18 @@ int nl_cache_mngr_get_fd(struct nl_cache_mngr *mngr) * @arg timeout Upper limit poll() will block, in milliseconds. * * Causes poll() to be called to check for new event notifications - * being available. Automatically receives and handles available - * notifications. + * being available. Calls nl_cache_mngr_data_ready() to process + * available data. * * This functionally is ideally called regularly during an idle * period. * - * @return A positive value if at least one update was handled, 0 - * for none, or a negative error code. + * A timeout can be specified in milliseconds to limit the time the + * function will wait for updates. + * + * @see nl_cache_mngr_data_ready() + * + * @return The number of messages processed or a negative error code. */ int nl_cache_mngr_poll(struct nl_cache_mngr *mngr, int timeout) { @@ -316,11 +330,15 @@ int nl_cache_mngr_poll(struct nl_cache_mngr *mngr, int timeout) * @arg mngr Cache manager * * This function can be called if the socket associated to the manager - * contains updates to be received. This function should not be used - * if nl_cache_mngr_poll() is used. + * contains updates to be received. This function should only be used + * if nl_cache_mngr_poll() is not used. * - * @return A positive value if at least one update was handled, 0 - * for none, or a negative error code. + * The function will process messages until there is no more data to + * be read from the socket. + * + * @see nl_cache_mngr_poll() + * + * @return The number of messages processed or a negative error code. */ int nl_cache_mngr_data_ready(struct nl_cache_mngr *mngr) { From 516536625fb6bd3b3d28cf4bc47b29e9b352cf30 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 21 Apr 2012 15:48:37 +0200 Subject: [PATCH 156/432] cache_mngr: Provide nl_cache_mngr_info() to pring cache manager details Useful for debugging and testing --- include/netlink/cache.h | 2 ++ lib/cache_mngr.c | 42 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/include/netlink/cache.h b/include/netlink/cache.h index e42f692..1e2bb9d 100644 --- a/include/netlink/cache.h +++ b/include/netlink/cache.h @@ -127,6 +127,8 @@ extern int nl_cache_mngr_get_fd(struct nl_cache_mngr *); extern int nl_cache_mngr_poll(struct nl_cache_mngr *, int); extern int nl_cache_mngr_data_ready(struct nl_cache_mngr *); +extern void nl_cache_mngr_info(struct nl_cache_mngr *, + struct nl_dump_params *); extern void nl_cache_mngr_free(struct nl_cache_mngr *); #ifdef __cplusplus diff --git a/lib/cache_mngr.c b/lib/cache_mngr.c index 9388f40..15b545d 100644 --- a/lib/cache_mngr.c +++ b/lib/cache_mngr.c @@ -367,6 +367,48 @@ int nl_cache_mngr_data_ready(struct nl_cache_mngr *mngr) return nread; } +/** + * Print information about cache manager + * @arg mngr Cache manager + * @arg p Dumping parameters + * + * Prints information about the cache manager including all managed caches. + * + * @note This is a debugging function. + */ +void nl_cache_mngr_info(struct nl_cache_mngr *mngr, struct nl_dump_params *p) +{ + char buf[128]; + int i; + + nl_dump_line(p, "cache-manager <%p>\n", mngr); + nl_dump_line(p, " .protocol = %s\n", + nl_nlfamily2str(mngr->cm_protocol, buf, sizeof(buf))); + nl_dump_line(p, " .flags = %#x\n", mngr->cm_flags); + nl_dump_line(p, " .nassocs = %u\n", mngr->cm_nassocs); + nl_dump_line(p, " .sock = <%p>\n", mngr->cm_sock); + + for (i = 0; i < mngr->cm_nassocs; i++) { + struct nl_cache_assoc *assoc = &mngr->cm_assocs[i]; + + if (assoc->ca_cache) { + nl_dump_line(p, " .cache[%d] = <%p> {\n", i, assoc->ca_cache); + nl_dump_line(p, " .name = %s\n", assoc->ca_cache->c_ops->co_name); + nl_dump_line(p, " .change_func = <%p>\n", assoc->ca_change); + nl_dump_line(p, " .change_data = <%p>\n", assoc->ca_change_data); + nl_dump_line(p, " .nitems = %u\n", nl_cache_nitems(assoc->ca_cache)); + nl_dump_line(p, " .objects = {\n"); + + p->dp_prefix += 6; + nl_cache_dump(assoc->ca_cache, p); + p->dp_prefix -= 6; + + nl_dump_line(p, " }\n"); + nl_dump_line(p, " }\n"); + } + } +} + /** * Free cache manager and all caches. * @arg mngr Cache manager. From 2ed371eb597ad8761c4adc59c32252f5327c65d9 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 21 Apr 2012 15:49:09 +0200 Subject: [PATCH 157/432] test-cache-mngr: Allow for management of arbitary caches via argument string Let the user specify a list of cache types to add to the manager as arguments instead of adding a static list. Uses the newly added nl_cache_mngr_info() to constantly print information about the manager. --- tests/test-cache-mngr.c | 40 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/tests/test-cache-mngr.c b/tests/test-cache-mngr.c index 528ae18..da17018 100644 --- a/tests/test-cache-mngr.c +++ b/tests/test-cache-mngr.c @@ -5,14 +5,14 @@ static int quit = 0; +static struct nl_dump_params dp = { + .dp_type = NL_DUMP_LINE, +}; + + static void change_cb(struct nl_cache *cache, struct nl_object *obj, int action, void *data) { - struct nl_dump_params dp = { - .dp_type = NL_DUMP_LINE, - .dp_fd = stdout, - }; - if (action == NL_ACT_NEW) printf("NEW "); else if (action == NL_ACT_DEL) @@ -31,8 +31,10 @@ static void sigint(int arg) int main(int argc, char *argv[]) { struct nl_cache_mngr *mngr; - struct nl_cache *lc, *nc, *ac, *rc; - int err; + struct nl_cache *cache; + int err, i; + + dp.dp_fd = stdout; signal(SIGINT, sigint); @@ -41,27 +43,19 @@ int main(int argc, char *argv[]) nl_cli_fatal(err, "Unable to allocate cache manager: %s", nl_geterror(err)); - if ((err = nl_cache_mngr_add(mngr, "route/link", &change_cb, NULL, &lc)) < 0) - nl_cli_fatal(err, "Unable to add cache route/link: %s", - nl_geterror(err)); - - if ((err = nl_cache_mngr_add(mngr, "route/neigh", &change_cb, NULL, &nc)) < 0) - nl_cli_fatal(err, "Unable to add cache route/neigh: %s", - nl_geterror(err)); - - if ((err = nl_cache_mngr_add(mngr, "route/addr", &change_cb, NULL, &ac)) < 0) - nl_cli_fatal(err, "Unable to add cache route/addr: %s", - nl_geterror(err)); - - if ((err = nl_cache_mngr_add(mngr, "route/route", &change_cb, NULL, &rc)) < 0) - nl_cli_fatal(err, "Unable to add cache route/route: %s", - nl_geterror(err)); + for (i = 1; i < argc; i++) { + err = nl_cache_mngr_add(mngr, argv[i], &change_cb, NULL, &cache); + if (err < 0) + nl_cli_fatal(err, "Unable to add cache %s: %s", + argv[i], nl_geterror(err)); + } while (!quit) { - int err = nl_cache_mngr_poll(mngr, 5000); + int err = nl_cache_mngr_poll(mngr, 1000); if (err < 0 && err != -NLE_INTR) nl_cli_fatal(err, "Polling failed: %s", nl_geterror(err)); + nl_cache_mngr_info(mngr, &dp); } nl_cache_mngr_free(mngr); From 2e93940a86cc78228e8c0b1b7f469d817c6dc178 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 21 Apr 2012 15:51:43 +0200 Subject: [PATCH 158/432] cache_mngr: Make providing the result pointer to nl_cache_mngr_add() optional --- lib/cache_mngr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/cache_mngr.c b/lib/cache_mngr.c index 15b545d..39cf0ac 100644 --- a/lib/cache_mngr.c +++ b/lib/cache_mngr.c @@ -169,7 +169,7 @@ errout: * @arg name Name of cache to keep track of * @arg cb Function to be called upon changes. * @arg data Argument passed on to change callback - * @arg result Pointer to store added cache. + * @arg result Pointer to store added cache (optional) * * Allocates a new cache of the specified type and adds it to the manager. * The operation will trigger a full dump request from the kernel to @@ -259,7 +259,8 @@ retry: NL_DBG(1, "Added cache %p <%s> to cache manager %p\n", cache, nl_cache_name(cache), mngr); - *result = cache; + if (result) + *result = cache; return 0; errout_drop_membership: From 8bbcd2208e366f8d8a708d56974966dd7651ffdf Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sun, 22 Apr 2012 11:12:01 +0200 Subject: [PATCH 159/432] genl: Make genl_unregister() a NOP if NULL pointer is passed --- lib/genl/mngt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/genl/mngt.c b/lib/genl/mngt.c index 0ebe74d..963d497 100644 --- a/lib/genl/mngt.c +++ b/lib/genl/mngt.c @@ -208,6 +208,9 @@ errout: */ void genl_unregister(struct nl_cache_ops *ops) { + if (!ops) + return; + nl_cache_mngt_unregister(ops); nl_list_del(&ops->co_genl->o_list); } From 2e23491c5017e578b34341fe0d0197c7ee1883cc Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sun, 22 Apr 2012 14:36:01 +0200 Subject: [PATCH 160/432] cache: improve documentation of co_event_filter --- include/netlink/cache-api.h | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/include/netlink/cache-api.h b/include/netlink/cache-api.h index 1b3d099..c1c3aaa 100644 --- a/include/netlink/cache-api.h +++ b/include/netlink/cache-api.h @@ -202,9 +202,26 @@ struct nl_cache_ops struct nlmsghdr *, struct nl_parser_param *); /** - * Called whenever a notification has been parsed into an object and - * is considered for inclusion into a cache. Must return NL_SKIP if - * the object should not be included in the cache. + * The function registered under this callback is called after a + * netlink notification associated with this cache type has been + * parsed into an object and is being considered for inclusio into + * the specified cache. + * + * The purpose of this function is to filter out notifications + * which should be ignored when updating caches. + * + * The function must return NL_SKIP to prevent the object from + * being included, or NL_OK to include it. + * + * @code + * int my_filter(struct nl_cache *cache, struct nl_object *obj) + * { + * if (reason_to_not_include_obj(obj)) + * return NL_SKIP; + * + * return NL_OK; + * } + * @endcode */ int (*co_event_filter)(struct nl_cache *, struct nl_object *obj); From bd1e4d03840a4d8289ba87935096c6dcb0c18ea7 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sun, 22 Apr 2012 15:23:52 +0200 Subject: [PATCH 161/432] cache: Add co_include_event allowing caches to provide their own nl_cache_include() implementation --- include/netlink/cache-api.h | 20 +++++++++++++++++++- include/netlink/cache.h | 2 -- lib/cache_mngr.c | 6 +++++- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/include/netlink/cache-api.h b/include/netlink/cache-api.h index c1c3aaa..390cbea 100644 --- a/include/netlink/cache-api.h +++ b/include/netlink/cache-api.h @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2006 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ #ifndef NETLINK_CACHE_API_H_ @@ -18,6 +18,8 @@ extern "C" { #endif +typedef void (*change_func_t)(struct nl_cache *, struct nl_object *, int, void *); + /** * @ingroup cache * @defgroup cache_api Cache Implementation @@ -225,6 +227,22 @@ struct nl_cache_ops */ int (*co_event_filter)(struct nl_cache *, struct nl_object *obj); + /** + * The function registered under this callback is called when an + * object formed from a notification event needs to be included in + * a cache. + * + * For each modified object, the change callback \c change_cb must + * be called with the \c data argument provided. + * + * If no function is registered, the function nl_cache_include() + * will be used for this purpose. + * + * @see nl_cache_include() + */ + int (*co_include_event)(struct nl_cache *cache, struct nl_object *obj, + change_func_t change_cb, void *data); + /** Object operations */ struct nl_object_ops * co_obj_ops; diff --git a/include/netlink/cache.h b/include/netlink/cache.h index 1e2bb9d..fd137e1 100644 --- a/include/netlink/cache.h +++ b/include/netlink/cache.h @@ -24,8 +24,6 @@ extern "C" { struct nl_cache; -typedef void (*change_func_t)(struct nl_cache *, struct nl_object *, int, void *); - /* Access Functions */ extern int nl_cache_nitems(struct nl_cache *); extern int nl_cache_nitems_filter(struct nl_cache *, diff --git a/lib/cache_mngr.c b/lib/cache_mngr.c index 39cf0ac..dae8768 100644 --- a/lib/cache_mngr.c +++ b/lib/cache_mngr.c @@ -42,7 +42,11 @@ static int include_cb(struct nl_object *obj, struct nl_parser_param *p) if (ops->co_event_filter(ca->ca_cache, obj) != NL_OK) return 0; - return nl_cache_include(ca->ca_cache, obj, ca->ca_change, ca->ca_change_data); + if (ops->co_include_event) + return ops->co_include_event(ca->ca_cache, obj, ca->ca_change, + ca->ca_change_data); + else + return nl_cache_include(ca->ca_cache, obj, ca->ca_change, ca->ca_change_data); } static int event_input(struct nl_msg *msg, void *arg) From ff3e9e314cd0dac21806b95d513abadeae0cc96f Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 24 Apr 2012 14:55:23 +0200 Subject: [PATCH 162/432] object: Add functions to access the object type, cache and object ops --- include/netlink/object.h | 7 ++++- lib/object.c | 55 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/include/netlink/object.h b/include/netlink/object.h index 7dc62ac..bbda5f5 100644 --- a/include/netlink/object.h +++ b/include/netlink/object.h @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ #ifndef NETLINK_OBJECT_H_ @@ -57,6 +57,11 @@ extern int nl_object_is_marked(struct nl_object *); /* Access Functions */ extern int nl_object_get_refcnt(struct nl_object *); extern struct nl_cache * nl_object_get_cache(struct nl_object *); +extern const char * nl_object_get_type(const struct nl_object *); +extern int nl_object_get_msgtype(const struct nl_object *); +struct nl_object_ops * nl_object_get_ops(const struct nl_object *); + + static inline void * nl_object_priv(struct nl_object *obj) { return obj; diff --git a/lib/object.c b/lib/object.c index 3bf02ea..554d09b 100644 --- a/lib/object.c +++ b/lib/object.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ /** @@ -380,16 +380,69 @@ char *nl_object_attr_list(struct nl_object *obj, char *buf, size_t len) * @{ */ +/** + * Return number of references held + * @arg obj object + * + * @return The number of references held to this object + */ int nl_object_get_refcnt(struct nl_object *obj) { return obj->ce_refcnt; } +/** + * Return cache the object is associated with + * @arg obj object + * + * @note The returned pointer is not protected with a reference counter, + * it is your responsibility. + * + * @return Pointer to cache or NULL if not associated with a cache. + */ struct nl_cache *nl_object_get_cache(struct nl_object *obj) { return obj->ce_cache; } +/** + * Return the object's type + * @arg obj object + * + * FIXME: link to list of object types + * + * @return Name of the object type + */ +const char *nl_object_get_type(const struct nl_object *obj) +{ + if (!obj->ce_ops) + BUG(); + + return obj->ce_ops->oo_name; +} + +/** + * Return the netlink message type the object was derived from + * @arg obj object + * + * @return Netlink message type or 0. + */ +int nl_object_get_msgtype(const struct nl_object *obj) +{ + return obj->ce_msgtype; +} + +/** + * Return object operations structure + * @arg obj object + * + * @return Pointer to the object operations structure + */ +struct nl_object_ops *nl_object_get_ops(const struct nl_object *obj) +{ + return obj->ce_ops; +} + /** @} */ /** @} */ From ad5d2b7738e053066f91b355dbdfc2e885f764df Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 26 Apr 2012 11:22:49 +0200 Subject: [PATCH 163/432] 3.2.8 release --- configure.in | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/configure.in b/configure.in index 9d99db2..9e578cc 100644 --- a/configure.in +++ b/configure.in @@ -13,19 +13,34 @@ # copied from glib m4_define([libnl_major_version], [3]) m4_define([libnl_minor_version], [2]) -m4_define([libnl_micro_version], [7]) # bump for every release unless minor was bumped -m4_define([libnl_lt_revision], [2]) # bump or reset to 0 if interfaces were added -m4_define([libnl_backwards_age], [7]) # bump whenever a release is backwards compatible - # bump with +100 if a minor release is compatible - # reset to 0 if interfaces were removed +m4_define([libnl_micro_version], [8]) + + +# If either revision or age are omitted, they default to 0. Also note that age +# must be less than or equal to the current interface number. +# +# Here are a set of rules to help you update your library version information: +# +# 1. Start with version information of `0:0:0' for each libtool library. +# 2. Update the version information only immediately before a public release +# of your software. More frequent updates are unnecessary, and only +# guarantee that the current interface number gets larger faster. +# 3. If the library source code has changed at all since the last update, then +# increment revision (`c:r:a' becomes `c:r+1:a'). +# 4. If any interfaces have been added, removed, or changed since the last +# update, increment current, and set revision to 0. +# 5. If any interfaces have been added since the last public release, then +# increment age. +# 6. If any interfaces have been removed since the last public release, then +# set age to 0. + +m4_define([libnl_lt_current], [206]) +m4_define([libnl_lt_revision], [0]) +m4_define([libnl_lt_age], [6]) m4_define([libnl_version], [libnl_major_version.libnl_minor_version.libnl_micro_version]) -m4_define([libnl_lt_age], [m4_eval(libnl_backwards_age - libnl_lt_revision)]) -m4_define([libnl_lt_current], - [m4_eval(100 * libnl_minor_version + libnl_micro_version - libnl_lt_revision)]) - AC_INIT(libnl, [libnl_version], [http://www.infradead.org/~tgr/libnl/]) AC_CONFIG_HEADERS([lib/defs.h]) AC_CONFIG_MACRO_DIR([m4]) From d726ecd2d73bcc27454a62a587030ac2206ebbb2 Mon Sep 17 00:00:00 2001 From: Jeroen Roovers Date: Tue, 1 May 2012 20:32:57 +0200 Subject: [PATCH 164/432] Fix two bugs in 3.2.8/doc/ doc/Doxyfile.in: Refer to @top_srcdir@ instead of @src_dir@ doc/Makefile.in: Set .PHONY to api_ref instead of api_refs http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/dev-libs/libnl/files/ Cheers, jer --- doc/Doxyfile.in | 2 +- doc/Makefile.am | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index c183abd..8bb4fd5 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -590,7 +590,7 @@ WARN_LOGFILE = INPUT = @top_srcdir@/lib \ @top_srcdir@/src/lib \ @top_srcdir@/include/netlink \ - @srcdir@/src + @top_srcdir@/src # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is diff --git a/doc/Makefile.am b/doc/Makefile.am index 9b964b5..6f574dd 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,6 +1,6 @@ # -*- Makefile -*- -.PHONY: gendoc api_refs asciidoc +.PHONY: gendoc api_ref asciidoc ASCIIDOCOPTS=-a pygments -a language=c -a icons \ -a toc2 \ From 6f156a7b58318669cf883f1b43e0f82a961eb9d5 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 8 May 2012 22:48:00 +0200 Subject: [PATCH 165/432] nl: Fix return value of nl_recvmsgs() Apparently the change to have nl_recvmsgs() return the number of parsed messages broke nl_wait_for_ack() among other applications. This patch reverts to the old behaviour and provides a new function nl_recvmsgs_report() which provides the additional information for use by the cache manager and possibly other applications. Reported-by: Scott Bonar Signed-off-by: Thomas Graf --- include/netlink/netlink.h | 1 + lib/cache_mngr.c | 2 +- lib/nl.c | 34 +++++++++++++++++++++++++++++----- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/include/netlink/netlink.h b/include/netlink/netlink.h index 0768708..a501eaa 100644 --- a/include/netlink/netlink.h +++ b/include/netlink/netlink.h @@ -71,6 +71,7 @@ extern int nl_recv(struct nl_sock *, struct ucred **); extern int nl_recvmsgs(struct nl_sock *, struct nl_cb *); +extern int nl_recvmsgs_report(struct nl_sock *, struct nl_cb *); extern int nl_recvmsgs_default(struct nl_sock *); diff --git a/lib/cache_mngr.c b/lib/cache_mngr.c index dae8768..0f0df51 100644 --- a/lib/cache_mngr.c +++ b/lib/cache_mngr.c @@ -359,7 +359,7 @@ int nl_cache_mngr_data_ready(struct nl_cache_mngr *mngr) nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, event_input, mngr); - while ((err = nl_recvmsgs(mngr->cm_sock, cb)) > 0) { + while ((err = nl_recvmsgs_report(mngr->cm_sock, cb)) > 0) { NL_DBG(2, "Cache manager %p, recvmsgs read %d messages\n", mngr, err); nread += err; diff --git a/lib/nl.c b/lib/nl.c index c41a3b9..7e59130 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -762,6 +762,26 @@ out: return err; } +/** + * Receive a set of messages from a netlink socket and report parsed messages + * @arg sk Netlink socket. + * @arg cb set of callbacks to control behaviour. + * + * This function is identical to nl_recvmsgs() to the point that it will + * return the number of parsed messages instead of 0 on success. + * + * @see nl_recvmsgs() + * + * @return Number of received messages or a negative error code from nl_recv(). + */ +int nl_recvmsgs_report(struct nl_sock *sk, struct nl_cb *cb) +{ + if (cb->cb_recvmsgs_ow) + return cb->cb_recvmsgs_ow(sk, cb); + else + return recvmsgs(sk, cb); +} + /** * Receive a set of messages from a netlink socket. * @arg sk Netlink socket. @@ -775,14 +795,18 @@ out: * A non-blocking sockets causes the function to return immediately if * no data is available. * - * @return Number of received messages or a negative error code from nl_recv(). + * @see nl_recvmsgs_report() + * + * @return 0 on success or a negative error code from nl_recv(). */ int nl_recvmsgs(struct nl_sock *sk, struct nl_cb *cb) { - if (cb->cb_recvmsgs_ow) - return cb->cb_recvmsgs_ow(sk, cb); - else - return recvmsgs(sk, cb); + int err; + + if ((err = nl_recvmsgs_report(sk, cb)) > 0) + err = 0; + + return err; } /** From f8b4f9271b86c7294c7f87270e74b8c690798dd9 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 8 May 2012 22:53:26 +0200 Subject: [PATCH 166/432] 3.2.9 release --- configure.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.in b/configure.in index 9e578cc..f676371 100644 --- a/configure.in +++ b/configure.in @@ -13,7 +13,7 @@ # copied from glib m4_define([libnl_major_version], [3]) m4_define([libnl_minor_version], [2]) -m4_define([libnl_micro_version], [8]) +m4_define([libnl_micro_version], [9]) # If either revision or age are omitted, they default to 0. Also note that age @@ -34,9 +34,9 @@ m4_define([libnl_micro_version], [8]) # 6. If any interfaces have been removed since the last public release, then # set age to 0. -m4_define([libnl_lt_current], [206]) +m4_define([libnl_lt_current], [207]) m4_define([libnl_lt_revision], [0]) -m4_define([libnl_lt_age], [6]) +m4_define([libnl_lt_age], [7]) m4_define([libnl_version], [libnl_major_version.libnl_minor_version.libnl_micro_version]) From beb40e2b4ed22ab11867b8c7e68d3be9da64fed8 Mon Sep 17 00:00:00 2001 From: Adrian Ban Date: Tue, 8 May 2012 23:14:13 +0200 Subject: [PATCH 167/432] u32: add support for hashing --- include/netlink/route/cls/u32.h | 4 ++ lib/route/cls/u32.c | 85 +++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/include/netlink/route/cls/u32.h b/include/netlink/route/cls/u32.h index cf35e26..62c5386 100644 --- a/include/netlink/route/cls/u32.h +++ b/include/netlink/route/cls/u32.h @@ -21,6 +21,10 @@ extern "C" { extern void rtnl_u32_set_handle(struct rtnl_cls *, int, int, int); extern int rtnl_u32_set_classid(struct rtnl_cls *, uint32_t); +extern int rtnl_u32_set_divisor(struct rtnl_cls *, uint32_t); +extern int rtnl_u32_set_link(struct rtnl_cls *, uint32_t); +extern int rtnl_u32_set_hashmask(struct rtnl_cls *, uint32_t, uint32_t); +extern int rtnl_u32_set_cls_terminal(struct rtnl_cls *); extern int rtnl_u32_set_flags(struct rtnl_cls *, int); extern int rtnl_u32_add_key(struct rtnl_cls *, uint32_t, uint32_t, diff --git a/lib/route/cls/u32.c b/lib/route/cls/u32.c index 2016460..331e714 100644 --- a/lib/route/cls/u32.c +++ b/lib/route/cls/u32.c @@ -374,6 +374,91 @@ int rtnl_u32_set_classid(struct rtnl_cls *cls, uint32_t classid) return 0; } +int rtnl_u32_set_divisor(struct rtnl_cls *cls, uint32_t divisor) +{ + struct rtnl_u32 *u; + + if (!(u = (struct rtnl_u32 *) rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + u->cu_divisor = divisor; + u->cu_mask |= U32_ATTR_DIVISOR; + return 0; +} + +int rtnl_u32_set_link(struct rtnl_cls *cls, uint32_t link) +{ + struct rtnl_u32 *u; + + if (!(u = (struct rtnl_u32 *) rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + u->cu_link = link; + u->cu_mask |= U32_ATTR_LINK; + return 0; +} + +int rtnl_u32_set_hashtable(struct rtnl_cls *cls, uint32_t ht) +{ + struct rtnl_u32 *u; + + if (!(u = (struct rtnl_u32 *) rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + u->cu_hash = ht; + u->cu_mask |= U32_ATTR_HASH; + return 0; +} + +int rtnl_u32_set_hashmask(struct rtnl_cls *cls, uint32_t hashmask, uint32_t offset) +{ + struct rtnl_u32 *u; + struct tc_u32_sel *sel; + int err; + + hashmask = htonl(hashmask); + + if (!(u = (struct rtnl_u32 *) rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + sel = u32_selector_alloc(u); + if (!sel) + return -NLE_NOMEM; + + err = nl_data_append(u->cu_selector, NULL, sizeof(struct tc_u32_key)); + if(err < 0) + return err; + + sel = u32_selector(u); + + sel->hmask = hashmask; + sel->hoff = offset; + return 0; +} + +int rtnl_u32_set_cls_terminal(struct rtnl_cls *cls) +{ + struct rtnl_u32 *u; + struct tc_u32_sel *sel; + int err; + + if (!(u = (struct rtnl_u32 *) rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + sel = u32_selector_alloc(u); + if (!sel) + return -NLE_NOMEM; + + err = nl_data_append(u->cu_selector, NULL, sizeof(struct tc_u32_key)); + if(err < 0) + return err; + + sel = u32_selector(u); + + sel->flags |= TC_U32_TERMINAL; + return 0; +} + /** @} */ /** From 7b503a12a039aeb129fb75804824f6b365adb54b Mon Sep 17 00:00:00 2001 From: Adrian Ban Date: Tue, 8 May 2012 23:17:53 +0200 Subject: [PATCH 168/432] u32: example/test code for u32 hashing with HTB --- tests/.gitignore | 4 + tests/Makefile.am | 4 +- tests/test-complex-HTB-with-hash-filters.c | 753 +++++++++++++++++++++ 3 files changed, 760 insertions(+), 1 deletion(-) create mode 100644 tests/test-complex-HTB-with-hash-filters.c diff --git a/tests/.gitignore b/tests/.gitignore index 19184ee..b386c45 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -1,4 +1,8 @@ test-cache-mngr +test-complex-HTB-with-hash-filters +test-create-bond +test-create-vlan +test-delete-link test-genl test-nf-cache-mngr test-socket-creation diff --git a/tests/Makefile.am b/tests/Makefile.am index 4193818..1272f98 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -16,7 +16,8 @@ check_PROGRAMS = \ test-delete-link \ test-genl \ test-nf-cache-mngr \ - test-socket-creation + test-socket-creation \ + test-complex-HTB-with-hash-filters # Eventually add these to TESTS once converted to be real # test programs @@ -29,3 +30,4 @@ test_delete_link_SOURCES = test-delete-link.c test_genl_SOURCES = test-genl.c test_nf_cache_mngr_SOURCES = test-nf-cache-mngr.c test_socket_creation_SOURCES = test-socket-creation.c +test_complex_HTB_with_hash_filters_SOURCES = test-complex-HTB-with-hash-filters.c diff --git a/tests/test-complex-HTB-with-hash-filters.c b/tests/test-complex-HTB-with-hash-filters.c new file mode 100644 index 0000000..585a549 --- /dev/null +++ b/tests/test-complex-HTB-with-hash-filters.c @@ -0,0 +1,753 @@ +/* + * test/test-complex-HTB-with-hash-filters.c Add HTB qdisc, HTB classes and creates some hash filters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2011 Adrian Ban + */ + +#include +#include +#include +#include +#include + +#include +//#include "include/rtnl_u32.h" + +#include +#include +//#include "include/rtnl_u32_addon.h" + +#define TC_HANDLE(maj, min) (TC_H_MAJ((maj) << 16) | TC_H_MIN(min)) + +/* some functions are copied from iproute-tc tool */ +int get_u32(__u32 *val, const char *arg, int base) +{ + unsigned long res; + char *ptr; + + if (!arg || !*arg) + return -1; + res = strtoul(arg, &ptr, base); + if (!ptr || ptr == arg || *ptr || res > 0xFFFFFFFFUL) + return -1; + *val = res; + return 0; +} + +int get_u32_handle(__u32 *handle, const char *str) +{ + __u32 htid=0, hash=0, nodeid=0; + char *tmp = strchr(str, ':'); + + if (tmp == NULL) { + if (memcmp("0x", str, 2) == 0) + return get_u32(handle, str, 16); + return -1; + } + htid = strtoul(str, &tmp, 16); + if (tmp == str && *str != ':' && *str != 0) + return -1; + if (htid>=0x1000) + return -1; + if (*tmp) { + str = tmp+1; + hash = strtoul(str, &tmp, 16); + if (tmp == str && *str != ':' && *str != 0) + return -1; + if (hash>=0x100) + return -1; + if (*tmp) { + str = tmp+1; + nodeid = strtoul(str, &tmp, 16); + if (tmp == str && *str != 0) + return -1; + if (nodeid>=0x1000) + return -1; + } + } + *handle = (htid<<20)|(hash<<12)|nodeid; + return 0; +} + +uint32_t get_u32_parse_handle(const char *cHandle) +{ + uint32_t handle=0; + + if(get_u32_handle(&handle, cHandle)) { + printf ("Illegal \"ht\"\n"); + return -1; + } + + if (handle && TC_U32_NODE(handle)) { + printf("\"link\" must be a hash table.\n"); + return -1; + } + return handle; +} + +int get_tc_classid(__u32 *h, const char *str) +{ + __u32 maj, min; + char *p; + + maj = TC_H_ROOT; + if (strcmp(str, "root") == 0) + goto ok; + maj = TC_H_UNSPEC; + if (strcmp(str, "none") == 0) + goto ok; + maj = strtoul(str, &p, 16); + if (p == str) { + maj = 0; + if (*p != ':') + return -1; + } + if (*p == ':') { + if (maj >= (1<<16)) + return -1; + maj <<= 16; + str = p+1; + min = strtoul(str, &p, 16); + if (*p != 0) + return -1; + if (min >= (1<<16)) + return -1; + maj |= min; + } else if (*p != 0) + return -1; + +ok: + *h = maj; + return 0; +} + +/* + * Function that adds a new filter and attach it to a hash table + * + */ +int u32_add_filter_on_ht(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t prio, + uint32_t keyval, uint32_t keymask, int keyoff, int keyoffmask, + uint32_t htid, uint32_t classid +) +{ + struct rtnl_cls *cls; + int err; + + //printf("Key Val : 0x%x\n", keyval); + //printf("Key Mask : 0x%x\n", keymask); + + cls=rtnl_cls_alloc(); + if (!(cls)) { + printf("Can not allocate classifier\n"); + nl_socket_free(sock); + exit(1); + } + + rtnl_tc_set_link(TC_CAST(cls), rtnlLink); + + if (err = rtnl_tc_set_kind(TC_CAST(cls), "u32")) { + printf("Can not set classifier as u32\n"); + return 1; + } + + rtnl_cls_set_prio(cls, prio); + rtnl_cls_set_protocol(cls, ETH_P_IP); + + rtnl_tc_set_parent(TC_CAST(cls), TC_HANDLE(1, 0)); + + rtnl_u32_set_hashtable(cls, htid); + + rtnl_u32_add_key_uint32(cls, keyval, keymask, keyoff, keyoffmask); /* 10.0.0.0/8 */ + + rtnl_u32_set_classid(cls, classid); + + rtnl_u32_set_cls_terminal(cls); + + if (err = rtnl_cls_add(sock, cls, NLM_F_CREATE)) { + printf("Can not add classifier: %s\n", nl_geterror(err)); + return -1; + } + rtnl_cls_put(cls); + return 0; + +} + +/* + * Function that adds a new filter and attach it to a hash table + * and set next hash table link with hash mask + * + */ +int u32_add_filter_on_ht_with_hashmask(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t prio, + uint32_t keyval, uint32_t keymask, int keyoff, int keyoffmask, + uint32_t htid, uint32_t htlink, uint32_t hmask, uint32_t hoffset +) +{ + struct rtnl_cls *cls; + int err; + + //printf("Key Val : 0x%x\n", keyval); + //printf("Key Mask : 0x%x\n", keymask); + + cls=rtnl_cls_alloc(); + if (!(cls)) { + printf("Can not allocate classifier\n"); + nl_socket_free(sock); + exit(1); + } + + rtnl_tc_set_link(TC_CAST(cls), rtnlLink); + + if (err = rtnl_tc_set_kind(TC_CAST(cls), "u32")) { + printf("Can not set classifier as u32\n"); + return 1; + } + + rtnl_cls_set_prio(cls, prio); + rtnl_cls_set_protocol(cls, ETH_P_IP); + + rtnl_tc_set_parent(TC_CAST(cls), TC_HANDLE(1, 0)); + + if (htid) + rtnl_u32_set_hashtable(cls, htid); + + rtnl_u32_add_key_uint32(cls, keyval, keymask, keyoff, keyoffmask); + + rtnl_u32_set_hashmask(cls, hmask, hoffset); + + rtnl_u32_set_link(cls, htlink); + + + if (err = rtnl_cls_add(sock, cls, NLM_F_CREATE)) { + printf("Can not add classifier: %s\n", nl_geterror(err)); + return -1; + } + rtnl_cls_put(cls); + return 0; +} + +/* + * function that creates a new hash table + */ +int u32_add_ht(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t prio, uint32_t htid, uint32_t divisor) +{ + + int err; + struct rtnl_cls *cls; + + cls=rtnl_cls_alloc(); + if (!(cls)) { + printf("Can not allocate classifier\n"); + nl_socket_free(sock); + exit(1); + } + + rtnl_tc_set_link(TC_CAST(cls), rtnlLink); + + if (err = rtnl_tc_set_kind(TC_CAST(cls), "u32")) { + printf("Can not set classifier as u32\n"); + return 1; + } + + rtnl_cls_set_prio(cls, prio); + rtnl_cls_set_protocol(cls, ETH_P_IP); + rtnl_tc_set_parent(TC_CAST(cls), TC_HANDLE(1, 0)); + + rtnl_u32_set_handle(cls, htid, 0x0, 0x0); + //printf("htid: 0x%X\n", htid); + rtnl_u32_set_divisor(cls, divisor); + + if (err = rtnl_cls_add(sock, cls, NLM_F_CREATE)) { + printf("Can not add classifier: %s\n", nl_geterror(err)); + return -1; + } + rtnl_cls_put(cls); + return 0; +} + +/* + * function that adds a new HTB qdisc and set the default class for unclassified traffic + */ +int qdisc_add_HTB(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t defaultClass) +{ + + struct rtnl_qdisc *qdisc; + int err; + + /* Allocation of a qdisc object */ + if (!(qdisc = rtnl_qdisc_alloc())) { + printf("Can not allocate Qdisc\n"); + return -1; + } + + //rtnl_tc_set_ifindex(TC_CAST(qdisc), master_index); + rtnl_tc_set_link(TC_CAST(qdisc), rtnlLink); + rtnl_tc_set_parent(TC_CAST(qdisc), TC_H_ROOT); + + //delete the qdisc + //printf("Delete current qdisc\n"); + rtnl_qdisc_delete(sock, qdisc); + //rtnl_qdisc_put(qdisc); + + //add a HTB qdisc + //printf("Add a new HTB qdisc\n"); + rtnl_tc_set_handle(TC_CAST(qdisc), TC_HANDLE(1,0)); + + if (err = rtnl_tc_set_kind(TC_CAST(qdisc), "htb") ){ + printf("Can not allocate HTB\n"); + return -1; + } + + /* Set default class for unclassified traffic */ + //printf("Set default class for unclassified traffic\n"); + rtnl_htb_set_defcls(qdisc, TC_HANDLE(1, defaultClass)); + rtnl_htb_set_rate2quantum(qdisc, 1); + + /* Submit request to kernel and wait for response */ + if (err = rtnl_qdisc_add(sock, qdisc, NLM_F_CREATE)) { + printf("Can not allocate HTB Qdisc\n"); + return -1; + } + + /* Return the qdisc object to free memory resources */ + rtnl_qdisc_put(qdisc); + +} + +/* + * function that adds a new HTB class and set its parameters + */ +int class_add_HTB(struct nl_sock *sock, struct rtnl_link *rtnlLink, + uint32_t parentMaj, uint32_t parentMin, + uint32_t childMaj, uint32_t childMin, + uint64_t rate, uint64_t ceil, + uint32_t burst, uint32_t cburst, + uint32_t prio +) +{ + int err; + struct rtnl_class *class; + + //create a HTB class + class = (struct rtnl_class *)rtnl_class_alloc(); + //class = rtnl_class_alloc(); + if (!class) { + printf("Can not allocate class object\n"); + return 1; + } + // + rtnl_tc_set_link(TC_CAST(class), rtnlLink); + //add a HTB qdisc + //printf("Add a new HTB class with 0x%X:0x%X on parent 0x%X:0x%X\n", childMaj, childMin, parentMaj, parentMin); + rtnl_tc_set_parent(TC_CAST(class), TC_HANDLE(parentMaj, parentMin)); + rtnl_tc_set_handle(TC_CAST(class), TC_HANDLE(childMaj, childMin)); + + if (err = rtnl_tc_set_kind(TC_CAST(class), "htb") ){ + printf("Can not set HTB to class\n"); + return 1; + } + + //printf("set HTB class prio to %u\n", prio); + rtnl_htb_set_prio(class, prio); + + if (rate) { + //rate=rate/8; + rtnl_htb_set_rate(class, rate); + } + if (ceil) { + //ceil=ceil/8; + rtnl_htb_set_ceil(class, ceil); + } + + if (burst) { + //printf ("Class HTB: set rate burst: %u\n", burst); + rtnl_htb_set_rbuffer(class, burst); + } + if (cburst) { + //printf ("Class HTB: set rate cburst: %u\n", cburst); + rtnl_htb_set_cbuffer(class, cburst); + } + /* Submit request to kernel and wait for response */ + if (err = rtnl_class_add(sock, class, NLM_F_CREATE)) { + printf("Can not allocate HTB Qdisc\n"); + return 1; + } + rtnl_class_put(class); + +} + +/* + * function that adds a HTB root class and set its parameters + */ +int class_add_HTB_root(struct nl_sock *sock, struct rtnl_link *rtnlLink, + uint64_t rate, uint64_t ceil, + uint32_t burst, uint32_t cburst +) +{ + int err; + struct rtnl_class *class; + + //create a HTB class + class = (struct rtnl_class *)rtnl_class_alloc(); + //class = rtnl_class_alloc(); + if (!class) { + printf("Can not allocate class object\n"); + return 1; + } + // + rtnl_tc_set_link(TC_CAST(class), rtnlLink); + rtnl_tc_set_parent(TC_CAST(class), TC_H_ROOT); + //add a HTB class + //printf("Add a new HTB ROOT class\n"); + rtnl_tc_set_handle(TC_CAST(class), 1); + + if (err = rtnl_tc_set_kind(TC_CAST(class), "htb") ){ + printf("Can not set HTB to class\n"); + return 1; + } + + if (rate) { + //rate=rate/8; + rtnl_htb_set_rate(class, rate); + } + if (ceil) { + //ceil=ceil/8; + rtnl_htb_set_ceil(class, ceil); + } + + if (burst) { + rtnl_htb_set_rbuffer(class, burst); + } + if (cburst) { + rtnl_htb_set_cbuffer(class, cburst); + } + + /* Submit request to kernel and wait for response */ + if (err = rtnl_class_add(sock, class, NLM_F_CREATE)) { + printf("Can not allocate HTB Qdisc\n"); + return 1; + } + rtnl_class_put(class); + +} + +/* + * function that adds a new SFQ qdisc as a leaf for a HTB class + */ +int qdisc_add_SFQ_leaf(struct nl_sock *sock, struct rtnl_link *rtnlLink, + uint32_t parentMaj, uint32_t parentMin, + int quantum, int limit, int perturb +) +{ + int err; + struct rtnl_qdisc *qdisc; + + if (!(qdisc = rtnl_qdisc_alloc())) { + printf("Can not allocate qdisc object\n"); + return 1; + } + rtnl_tc_set_link(TC_CAST(qdisc), rtnlLink); + rtnl_tc_set_parent(TC_CAST(qdisc), TC_HANDLE(parentMaj, parentMin)); + + rtnl_tc_set_handle(TC_CAST(qdisc), TC_HANDLE(parentMin,0)); + + if (err = rtnl_tc_set_kind(TC_CAST(qdisc), "sfq") ){ + printf("Can not set SQF class\n"); + return 1; + } + + if(quantum) { + rtnl_sfq_set_quantum(qdisc, quantum); + } else { + rtnl_sfq_set_quantum(qdisc, 16000); // tc default value + } + if(limit) { + rtnl_sfq_set_limit(qdisc, limit); // default is 127 + } + if(perturb) { + rtnl_sfq_set_perturb(qdisc, perturb); // default never perturb the hash + } + + /* Submit request to kernel and wait for response */ + if (err = rtnl_qdisc_add(sock, qdisc, NLM_F_CREATE)) { + printf("Can not allocate SFQ qdisc\n"); + return -1; + } + + /* Return the qdisc object to free memory resources */ + rtnl_qdisc_put(qdisc); +} + + + + +int main() { + + struct nl_sock *sock; + struct rtnl_link *link; + + struct rtnl_qdisc *qdisc; + struct rtnl_class *class; + struct rtnl_cls *cls; + + uint32_t ht, htlink, htid, handle, divisor, hash, nodeid, hashmask, direction, classid; + struct rtnl_u32 *f_u32; + char chashlink[16]=""; + + uint64_t drops, qlen; + + int master_index; + int err; + + uint64_t rate=0, ceil=0; + + struct nl_cache *link_cache; + + if (!(sock = nl_socket_alloc())) { + printf("Unable to allocate netlink socket\n"); + exit(1); + } + + if ((err = nl_connect(sock, NETLINK_ROUTE)) < 0 ) { + printf("Nu s-a putut conecta la NETLINK!\n"); + nl_socket_free(sock); + exit(1); + } + + + if ((err = rtnl_link_alloc_cache(sock, AF_UNSPEC, &link_cache)) < 0) { + printf("Unable to allocate link cache: %s\n", + nl_geterror(err)); + nl_socket_free(sock); + exit(1); + } + + /* lookup interface index of eth0 */ + if (!(link = rtnl_link_get_by_name(link_cache, "eth0"))) { + /* error */ + printf("Interface not found\n"); + nl_socket_free(sock); + exit(1); + } + + err=qdisc_add_HTB(sock, link, 0xffff); + //drops = rtnl_tc_get_stat(TC_CAST(qdisc), RTNL_TC_DROPS); + + //printf("Add ROOT HTB class\n"); + err=class_add_HTB_root(sock, link, 12500000, 12500000, 25000, 25000); + err=class_add_HTB(sock, link, 1, 0, 1, 0xffff, 1250000, 12500000, 25000, 25000, 5); + err=qdisc_add_SFQ_leaf(sock, link, 1, 0xffff, 16000, 0, 10); + err=class_add_HTB(sock, link, 1, 1, 1, 0x5, 2000000, 2000000, 25000, 25000, 5); + err=qdisc_add_SFQ_leaf(sock, link, 1, 0x5, 16000, 0, 10); + err=class_add_HTB(sock, link, 1, 1, 1, 0x6, 1000000, 1000000, 25000, 25000, 5); + err=qdisc_add_SFQ_leaf(sock, link, 1, 0x6, 16000, 0, 10); + //err=class_add_HTB(sock, link, 1, 0, 1, 0x7, 1024000, 100000000, 5); + //err=class_add_HTB(sock, link, 1, 0, 1, 0x8, 2048000, 100000000, 5); + //err=class_add_HTB(sock, link, 1, 0, 1, 0x9, 4096000, 100000000, 5); + //err=class_add_HTB(sock, link, 1, 0, 1, 0xa, 8192000, 100000000, 5); + + //printf("Add main hash table\n"); + + /* create u32 first hash filter table + * + */ + /* formula calcul handle: + * uint32_t handle = (htid << 20) | (hash << 12) | nodeid; + */ + + /* + * Upper limit of number of hash tables: 4096 (0xFFF) + * Number of hashes in a table: 256 values (0xFF) + * + */ + + /* using 256 values for hash table + * each entry in hash table match a byte from IP address specified later by a hash key + */ + + uint32_t i; + for (i = 1; i <= 0xf; i++) + u32_add_ht(sock, link, 1, i, 256); + + /* + * attach a u32 filter to the first hash + * that redirects all traffic and make a hash key + * from the fist byte of the IP address + * + */ + + divisor=0x0; // unused here + handle = 0x0; // unused here + hash = 0x0; // unused here + htid = 0x0; // unused here + nodeid = 0x0; // unused here + uint32_t hashlink; + + direction = 16; + + /* + * which hash table will use + * in our case is hash table no 1 defined previous + * + * There are 2 posibilities to set the the hash table: + * 1. Using function get_u32_handle and sent a string in + * format 10: where 10 is number of the hash table + * 2. Create your own value in format: 0xa00000 + * + */ + strcpy(chashlink, "1:"); + //printf("Hash Link: %s\n", chashlink); + //chashlink=malloc(sizeof(char) * + htlink = 0x0; // is used by get_u32_handle to return the correct value of hash table (link) + + if(get_u32_handle(&htlink, chashlink)) { + printf ("Illegal \"link\""); + nl_socket_free(sock); + exit(1); + } + //printf ("hash link : 0x%X\n", htlink); + //printf ("hash link test : %u\n", (htlink && TC_U32_NODE(htlink))); + + if (htlink && TC_U32_NODE(htlink)) { + printf("\"link\" must be a hash table.\n"); + nl_socket_free(sock); + exit(1); + } + /* the hash mask will hit the hash table (link) no 1: in our case + */ + + /* set the hash key mask */ + //hashmask = 0xFF000000UL; // the mask that is used to match the hash in specific table, in our case for example 1:a with mean the first byte which is 10 in hash table 1 + + /* Here we add a hash filter which match the first byte (see the hashmask value) + * of the source IP (offset 12 in the packet header) + * You can use also offset 16 to match the destination IP + */ + + /* + * Also we need a filter to match our rule + * This mean that we will put a 0.0.0.0/0 filter in our first rule + * that match the offset 12 (source IP) + * Also you can put offset 16 to match the destination IP + */ + + u32_add_filter_on_ht_with_hashmask(sock, link, 1, + 0x0, 0x0, direction, 0, + 0, htlink, 0xff000000, direction); + + /* + * For each first byte that we need to match we will create a new hash table + * For example: you have those clases: 10.0.0.0/24 and 172.16.0.0/23 + * For byte 10 and byte 172 will create a separate hash table that will match the second + * byte from each class. + * + */ + + + // Create a new hash table with prio 1, id 2 and 256 entries +// u32_CreateNewHashTable(sock, link, 1, 2, 256); + // Create a new hash table with prio 1, id 3 and 256 entries +// u32_CreateNewHashTable(sock, link, 1, 3, 256); +// u32_CreateNewHashTable(sock, link, 1, 4, 256); +// u32_CreateNewHashTable(sock, link, 1, 5, 256); + + /* + * Now we will create other filter under (ATENTION) our first hash table (link) 1: + * Previous rule redirects the trafic according the hash mask to hash table (link) no 1: + * Here we will match the hash tables from 1:0 to 1:ff. Under each hash table we will attach + * other rules that matches next byte from IP source/destination IP and we will repeat the + * previous steps. + * + */ + + + // /8 check + + // 10.0.0.0/8 + ht=get_u32_parse_handle("1:a:"); + htid = (ht&0xFFFFF000); + htlink=get_u32_parse_handle("2:"); + + u32_add_filter_on_ht_with_hashmask(sock, link, 1, + 0x0a000000, 0xff000000, direction, 0, + htid, htlink, 0x00ff0000, direction); + + // 172.0.0.0/8 + ht=get_u32_parse_handle("1:ac:"); + htid = (ht&0xFFFFF000); + htlink=get_u32_parse_handle("3:"); + + u32_add_filter_on_ht_with_hashmask(sock, link, 1, + 0xac000000, 0xff000000, direction, 0, + htid, htlink, 0x00ff0000, direction); + + + // /16 check + // 10.0.0.0/16 + ht=get_u32_parse_handle("2:0:"); + htid = (ht&0xFFFFF000); + htlink=get_u32_parse_handle("4:"); + + u32_add_filter_on_ht_with_hashmask(sock, link, 1, + 0x0a000000, 0xffff0000, direction, 0, + htid, htlink, 0x0000ff00, direction); + + // 172.17.0.0/16 + ht=get_u32_parse_handle("3:11:"); + htid = (ht&0xFFFFF000); + htlink=get_u32_parse_handle("5:"); + + u32_add_filter_on_ht_with_hashmask(sock, link, 1, + 0xac110000, 0xffff0000, direction, 0, + htid, htlink, 0x0000ff00, direction); + + // /24 check + // 10.0.9.0/24 + ht=get_u32_parse_handle("4:9:"); + htid = (ht&0xFFFFF000); + htlink=get_u32_parse_handle("6:"); + + u32_add_filter_on_ht_with_hashmask(sock, link, 1, + 0x0a000900, 0xffffff00, direction, 0, + htid, htlink, 0x000000ff, direction); + + // 172.17.2.0/16 + ht=get_u32_parse_handle("5:2:"); + htid = (ht&0xFFFFF000); + htlink=get_u32_parse_handle("7:"); + + u32_add_filter_on_ht_with_hashmask(sock, link, 1, + 0xac110200, 0xffffff00, direction, 0, + htid, htlink, 0x000000ff, direction); + + + // final filters + // 10.0.9.20 + ht=get_u32_parse_handle("6:14:"); + htid = (ht&0xFFFFF000); + + err = get_tc_classid(&classid, "1:5"); + + u32_add_filter_on_ht(sock, link, 1, + 0x0a000914, 0xffffffff, direction, 0, + htid, classid); + + // 172.17.2.120 + ht=get_u32_parse_handle("7:78:"); + htid = (ht&0xFFFFF000); + + err = get_tc_classid(&classid, "1:6"); + + u32_add_filter_on_ht(sock, link, 1, + 0xac110278, 0xffffffff, direction, 0, + htid, classid); + + + + nl_socket_free(sock); + return 0; +} From 183e86913aab58acf7b5b9cd160518e527bb0348 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 9 May 2012 10:06:24 +0200 Subject: [PATCH 169/432] doc: Check documentation generation requirements with autoconf Adds --enable-doc/--disable-doc, if omitted doc will only be build if requirements are met. If explicitely enabled, configure script will fail if requirements are not met. --- configure.in | 62 +++++++++++++++++++++++++++++++ doc/Makefile.am | 25 ++++++++++++- doc/README | 6 ++- m4/ax_python.m4 | 97 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 188 insertions(+), 2 deletions(-) create mode 100644 m4/ax_python.m4 diff --git a/configure.in b/configure.in index f676371..ed059c3 100644 --- a/configure.in +++ b/configure.in @@ -73,6 +73,68 @@ AC_PROG_YACC AC_C_CONST AC_C_INLINE +# +# Generating the documentation +# +AC_ARG_ENABLE([doc], + AS_HELP_STRING([--disable-doc], [Do not generate documentation]), + [generate_doc="$enableval"], [generate_doc=auto]) + +if test "x$generate_doc" != "xno"; then + AC_PROG_SED + AC_PROG_EGREP + + AX_PYTHON + + AC_CHECK_PROG(HAVE_DOXYGEN, [doxygen], yes, no) + if test "x$HAVE_DOXYGEN" = "xno" -a "x$generate_doc" = "xyes"; then + AC_MSG_ERROR([*** doxygen package required to generate documentation]) + fi + + link_doc=yes + AC_CHECK_PROG(HAVE_XMLSTARLET, [xmlstarlet], yes, no) + if test "x$HAVE_XMLSTARLET" = "xno"; then + if test "x$generate_doc" = "xyes"; then + AC_MSG_ERROR([*** xmlstarlet package required to generate documentation]) + else + AC_MSG_WARN([*** xmlstarlet not found, linking to APi reference disabled]) + link_doc=no + fi + fi + + AC_CHECK_PROG(HAVE_ASCIIDOC, [asciidoc], yes, no) + if test "x$HAVE_ASCIIDOC" = "xno"; then + if test "x$generate_doc" = "xyes"; then + AC_MSG_ERROR([*** asciidoc package required to generate documentation]) + else + AC_MSG_WARN([*** asciidoc not found, disabling building of guides]) + fi + fi + + AC_CHECK_PROG(HAVE_MSCGEN, [mscgen], yes, no) + if test "x$HAVE_MSCGEN" = "xno"; then + AC_MSG_WARN([*** mscgen not found, get it at http://www.mcternan.me.uk/mscgen/]) + if test "x$generate_doc" = "xyes"; then + AC_MSG_ERROR([*** mscgen package required to generate documentation]) + else + AC_MSG_WARN([*** Disabling building of guides]) + HAVE_ASCIIDOC=no + HAVE_DOXYGEN=no + fi + fi + + if test "x$HAVE_DOXYGEN" = "xno"; then + AC_MSG_WARN([*** Disabling API linking due to missing doxygen package]) + link_doc=no + fi + + AM_CONDITIONAL([LINK_DOC], [test "x$link_doc" = "xyes"]) + AM_CONDITIONAL([HAVE_DOXYGEN], [test "x$HAVE_DOXYGEN" = "xyes"]) + AM_CONDITIONAL([HAVE_ASCIIDOC], [test "x$HAVE_ASCIIDOC" = "xyes"]) +fi + +AM_CONDITIONAL([GENERATE_DOC], [test "x$generate_doc" != "xno"]) + AC_ARG_WITH([pkgconfigdir], AS_HELP_STRING([--with-pkgconfigdir=PATH], [Path to the pkgconfig directory [[LIBDIR/pkgconfig]]]), [pkgconfigdir="$withval"], [pkgconfigdir='${libdir}/pkgconfig']) diff --git a/doc/Makefile.am b/doc/Makefile.am index 6f574dd..142dc31 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -79,20 +79,43 @@ EXTRA_DIST = \ images/icons/callouts/15.png %.html: %.txt +if LINK_DOC ./resolve-asciidoc-refs.py $< > asciidoc.tmp asciidoc $(ASCIIDOCOPTS) -o $@ asciidoc.tmp ./doxygen-link.py libnl.dict $@ > asciidoc.tmp mv asciidoc.tmp $@ +else + asciidoc $(ASCIIDOCOPTS) -o $@ $< +endif asciidoc: core.html route.html index.html +link_doc: +if LINK_DOC + ./gen-tags.sh | ./tags2dict.sh > libnl.dict +else + @echo "Warning: Linking to API reference is disabled, check configure output" +endif + api_ref: doxygen Doxyfile; - ./gen-tags.sh | ./tags2dict.sh > libnl.dict + $(MAKE) link_doc gendoc: +if GENERATE_DOC +if HAVE_DOXYGEN $(MAKE) api_ref +else + @echo "Warning: Building of API reference (doxygen) is disabled, check autoconf logs" +endif +if HAVE_ASCIIDOC $(MAKE) asciidoc +else + @echo "Warning: Building of asciidoc files is disabled, check autoconf logs" +endif +else + @echo "Warning: Building of documentation disabled by user or autoconf" +endif clean-local: rm -f api/* libnl.dict *.html; diff --git a/doc/README b/doc/README index f4d1211..0c230a2 100644 --- a/doc/README +++ b/doc/README @@ -1,6 +1,10 @@ Requirements to build documentation mscgen -asciidoc 8.6.5 + http://www.mcternan.me.uk/mscgen/ + mscgen-filter-1.2 + http://code.google.com/p/asciidoc-mscgen-filter/ + +asciidoc 8.6.x doxygen diff --git a/m4/ax_python.m4 b/m4/ax_python.m4 new file mode 100644 index 0000000..1bc9d8a --- /dev/null +++ b/m4/ax_python.m4 @@ -0,0 +1,97 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_python.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PYTHON +# +# DESCRIPTION +# +# This macro does a complete Python development environment check. +# +# It recurses through several python versions (from 2.1 to 2.6 in this +# version), looking for an executable. When it finds an executable, it +# looks to find the header files and library. +# +# It sets PYTHON_BIN to the name of the python executable, +# PYTHON_INCLUDE_DIR to the directory holding the header files, and +# PYTHON_LIB to the name of the Python library. +# +# This macro calls AC_SUBST on PYTHON_BIN (via AC_CHECK_PROG), +# PYTHON_INCLUDE_DIR and PYTHON_LIB. +# +# LICENSE +# +# Copyright (c) 2008 Michael Tindal +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 9 + +AC_DEFUN([AX_PYTHON], +[AC_MSG_CHECKING(for python build information) +AC_MSG_RESULT([]) +for python in python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python; do +AC_CHECK_PROGS(PYTHON_BIN, [$python]) +ax_python_bin=$PYTHON_BIN +if test x$ax_python_bin != x; then + AC_CHECK_LIB($ax_python_bin, main, ax_python_lib=$ax_python_bin, ax_python_lib=no) + AC_CHECK_HEADER([$ax_python_bin/Python.h], + [[ax_python_header=`locate $ax_python_bin/Python.h | sed -e s,/Python.h,,`]], + ax_python_header=no) + if test $ax_python_lib != no; then + if test $ax_python_header != no; then + break; + fi + fi +fi +done +if test x$ax_python_bin = x; then + ax_python_bin=no +fi +if test x$ax_python_header = x; then + ax_python_header=no +fi +if test x$ax_python_lib = x; then + ax_python_lib=no +fi + +AC_MSG_RESULT([ results of the Python check:]) +AC_MSG_RESULT([ Binary: $ax_python_bin]) +AC_MSG_RESULT([ Library: $ax_python_lib]) +AC_MSG_RESULT([ Include Dir: $ax_python_header]) + +if test x$ax_python_header != xno; then + PYTHON_INCLUDE_DIR=$ax_python_header + AC_SUBST(PYTHON_INCLUDE_DIR) +fi +if test x$ax_python_lib != xno; then + PYTHON_LIB=$ax_python_lib + AC_SUBST(PYTHON_LIB) +fi +])dnl From 2fbab02ba8c7b0a418c9d89c2c6db89dd4efd0eb Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 9 May 2012 15:02:40 +0200 Subject: [PATCH 170/432] doc: add section about addressing Adds a new section to netlink fundamentals explaining the common addressing use cases and illustrates kernel->user, user->user, and user->kernel communication. --- doc/core.txt | 189 ++++++++++++++++++++++++++++++-------- doc/images/addressing.png | Bin 0 -> 13682 bytes 2 files changed, 150 insertions(+), 39 deletions(-) create mode 100644 doc/images/addressing.png diff --git a/doc/core.txt b/doc/core.txt index 19ebf70..7f26e05 100644 --- a/doc/core.txt +++ b/doc/core.txt @@ -7,7 +7,7 @@ Netlink Library (libnl) ======================= Thomas Graf -3.2, Sep 13 2011: +3.2, May 9 2011: :numbered: == Introduction @@ -59,32 +59,47 @@ The low level APIs are described in: === Linking to this Library -.Checking the presence using autoconf +.Checking the presence of the library using autoconf Projects using autoconf may use +PKG_CHECK_MODULES()+ to check if a specific version of libnl is available on the system. The example below also shows how to retrieve the +CFLAGS+ and linking dependencies required to link against the library. +The following example shows how to check for a specific version of libnl. If +found, it extends the `CFLAGS` and `LIBS` variable appropriately: + [source] ---- PKG_CHECK_MODULES(LIBNL3, libnl-3.0 >= 3.1, [have_libnl3=yes], [have_libnl3=no]) if (test "${have_libnl3}" = "yes"); then - CFLAGS="$LIBNL3_CFLAGS" - LIBS="$LIBNL3_LIBS" + CFLAGS+="$LIBNL3_CFLAGS" + LIBS+="$LIBNL3_LIBS" fi ---- NOTE: The pkgconfig file is named +libnl-3.0.pc+ for historic reasons, it also covers library versions >= 3.1. -.Main Header +.Header Files -The main header is ``. Additional headers need to -be included in your sources depending on the subsystems your program -makes use of. +The main header file is ``. Additional headers may need to +be included in your sources depending on the subsystems and components your +program makes use of. + +[source,c] +----- +#include +#include +#include +----- + +.Version Dependent Code + +If your code wishes to be capable to link against multiple versions of libnl +you may have direct the compiler to only include portions on the code depending +on the version of libnl that it is compiled against. -.Version Checking [source,c] ----- #include @@ -94,7 +109,7 @@ makes use of. #endif ----- -.Linking to libnl +.Linking ----- $ gcc myprogram.c -o myprogram $(pkgconfig --cflags --libs libnl-3.0) ----- @@ -120,13 +135,12 @@ $ NLDBG=2 ./myprogram | 4 | Even less important messages |=============================================================== -.Debugging Netlink Messages +.Debugging the Netlink Protocol -Often it is useful to peek into the stream of netlink messages -exchanged with other sockets. Setting the environment variable -+NLCB=debug+ will cause the debugging message handlers to be used -causing the netlink messages exchanged to be printed to +stderr+ in a -human readable format: +It is often useful to peek into the stream of netlink messages exchanged +with other sockets. Setting the environment variable +NLCB=debug+ will +cause the debugging message handlers to be used which in turn print the +netlink messages exchanged in a human readable format to to +stderr+: ----- $ NLCB=debug ./myprogram @@ -180,6 +194,92 @@ protocol uses its own protocol number (e.g. +NETLINK_ROUTE+, port number, formerly referred to as PID, which uniquely identifies each peer. +[[core_addressing]] +=== Addressing + +The netlink address (port) consists of a 32bit integer. Port 0 (zero) +is reserved for the kernel and refers to the kernel side socket of each +netlink protocol family. Other port numbers usually refer to user space +owned sockets, although this is not enforced. + +NOTE: In the beginning, it was common practice to use the process + identifier (PID) as the local port number. This became unpractical + with the introduction of threaded netlink applications and + applications requiring multiple sockets. Therefore libnl generates + unique port numbers based on the process identifier and adds an + offset to it allowing for multiple sockets to be used. The initial + socket will still equal to the process identifier for backwards + compatibility reasons. + +image:addressing.png["Addressing Example"] + +The above figure illustrates three applications and the kernel side +exposing two kernel side sockets. It shows the common netlink use +cases: + + * User space to kernel + * User space to user space + * Listening to kernel multicast notifications + +.User Space to Kernel + +The most common form of netlink usage is for a user space application +to send requests to the kernel and process the reply which is either +an error message or a success notification. + +["mscgen"] +-------- +msc { + App1,App2,Kernel; + App1=>Kernel [label="request (src=11, dst=0)"]; + Kernel<=App1 [label="reply (src=0, dst=11)"]; + ...; + App2=>Kernel [label="request (src=21, dst=0)"]; + Kernel<=App2 [label="reply (src=0, dst=21)"]; +} +-------- + +.User Space to User Space + +Netlink may also be used as an IPC mechanism to communicate between user +space applications directly. Communication is not limited to two peers, +any number of peers may communicate with each other and multicasting +capabilities allow to reach multiple peers with a single message. + +In order for the sockets to be visible to each other, both sockets must +be created for the same netlink protocol family. + +["mscgen"] +-------- +msc { + App2,App3; + App2=>App3 [label="request (src=22, dst=31)"]; + App2<=App3 [label="reply (src=31, dst=22)"]; + ...; +} +-------- + +.User space listening to kernel notifications + +This form of netlink communication is typically found in user space +daemons that need to act on certain kernel events. Such daemons will +typically maintain a netlink socket subscribed to a multicast group that +is used by the kernel to notify interested user space parties about +specific events. + +["mscgen"] +-------- +msc { + Kernel,App3; + Kernel=>App3 [label="notification (src=0, group=foo)"]; + ...; +} +-------- + +Use of multicasting is preferred over direct addressing due to the +flexibility in exchanging the user space component at any time without +the kernel noticing. + [[core_msg_format]] === Message Format @@ -395,7 +495,7 @@ The following standard flags are defined #define NLM_F_ECHO 8 -------- -- `NLM_F_REQUEST` - Message is a request, see <>. +- `NLM_F_REQUEST` - Message is a request, see <>. - `NLM_F_MULTI` - Multipart message, see <> - `NLM_F_ACK` - ACK message requested, see <>. - `NLM_F_ECHO` - Request to echo the request. @@ -447,13 +547,14 @@ flags are mutually exclusive to the `GET` flags: Behaviour of these flags may differ slightly between different netlink protocols. +[[core_seq_num]] === Sequence Numbers Netlink allows the use of sequence numbers to help relate replies to requests. It should be noted that unlike in protocols such as TCP there is no strict enforcment of the sequence number. The sole purpose of sequence numbers is to assist a sender in relating replies to the -corresponding requests. See <> for more information. +corresponding requests. See <> for more information. Sequence numbers are managed on a per socket basis, see <> for more information on how to use sequence numbers. @@ -469,16 +570,15 @@ See <> == Netlink Sockets In order to use the netlink protocol, a netlink socket is required. -Each socket defines a completely independent context for sending and -receiving of messages. An application may use multiple sockets for the -same netlink protocol, e.g. one socket to send requests and receive -replies and another socket subscribed to a multicast group to receive -notifications. +Each socket defines an independent context for sending and receiving of +messages. An application may make use multiple sockets, e.g. a socket to +send requests and receive the replies and another socket subscribed to a +multicast group to receive notifications. -=== Allocation & Freeing +=== Socket structure (struct nl_sock) -The netlink socket and all its related attributes are represented by -+struct nl_sock+. +The netlink socket and all related attributes including the actual file +descriptor are represented by +struct nl_sock+. [source,c] -------- @@ -488,18 +588,22 @@ struct nl_sock *nl_socket_alloc(void) void nl_socket_free(struct nl_sock *sk) -------- +The application must allocate an instance of +struct nl_sock+ for each +netlink socket it wishes to use. + [[core_sk_seq_num]] === Sequence Numbers The library will automatically take care of sequence number handling -for the application. A sequence number counter is stored in struct -nl_sock which is meant to be used when sending messages which will -produce a reply, error or any other message which needs to be -related to the original message. +for the application. A sequence number counter is stored in the +socket structure which is used and incremented automatically when a +message needs to be sent which is expected to generate a reply such as +an error or any other message type that needs to be related to the +original message. -The counter can be used directly with the function nl_socket_use_seq() -which will return the current value of the counter and increment it by -one afterwards. +Alternatively, the counter can be used directly via the function +nl_socket_use_seq(). It will return the current value of the counter +and increment it by one afterwards. [source,c] -------- @@ -510,8 +614,8 @@ unsigned int nl_socket_use_seq(struct nl_sock *sk); Most applications will not want to deal with sequence number handling themselves though. When using nl_send_auto() the sequence number is -filled out automatically and matched again on the receiving side. See -<> for more information. +filled in automatically and matched again when a reply is received. See +section <> for more information. This behaviour can and must be disabled if the netlink protocol implemented does not use a request/reply model, e.g. when a socket is @@ -524,6 +628,9 @@ used to receive notification messages. void nl_socket_disable_seq_check(struct nl_sock *sk); -------- +For more information on the theory behind netlink sequence numbers, +see section <>. + [[core_sk_multicast]] === Multicast Group Subscriptions @@ -535,7 +642,7 @@ commonly used to implement event notifications. Prior to kernel 2.6.14 the group subscription was performed using a bitmask which limited the number of groups per protocol family to 32. This outdated interface can still be accessed via the function -nl_join_groups even though it is not recommended for new code. +nl_join_groups() even though it is not recommended for new code. [source,c] -------- @@ -663,6 +770,8 @@ uint32_t nl_socket_get_local_port(const struct nl_sock *sk); void nl_socket_set_local_port(struct nl_sock *sk, uint32_t port); -------- +See section <> for more information on port numbers. + CAUTION: Overwriting the local port is possible but you have to ensure that the provided value is unique and no other socket in any other application is using the same value. @@ -685,6 +794,8 @@ uint32_t nl_socket_get_peer_port(const struct nl_sock *sk); void nl_socket_set_peer_port(struct nl_sock *sk, uint32_t port); -------- +See section <> for more information on port numbers. + .File Descriptor Netlink uses the BSD socket interface, therefore a file descriptor is @@ -776,7 +887,7 @@ function can be used to enable/disable receival of packet information. int nl_socket_recv_pktinfo(struct nl_sock *sk, int state); -------- -NOTE: Processing of NETLINK_PKTINFO has not been implemented yet. +CAUTION: Processing of NETLINK_PKTINFO has not been implemented yet. [[core_send_recv]] == Sending and Receiving of Messages / Data @@ -1350,8 +1461,8 @@ size for messages by calling nlmsg_set_default_size(): void nlmsg_set_default_size(size_t); -------- -NOTE: Calling nlmsg_set_default_size() does not change the maximum - message size of already allocated messages. +CAUTION: Calling nlmsg_set_default_size() does not change the maximum + message size of already allocated messages. [source,c] -------- diff --git a/doc/images/addressing.png b/doc/images/addressing.png new file mode 100644 index 0000000000000000000000000000000000000000..9dcaaffd242c3c2fda3cd9ff9f04cd7ec06447ca GIT binary patch literal 13682 zcmaKT1zc9mw=NifASu!zA)<75gMhSjck|NS3J6GvNVjwgFE1TRcXuP*(hYaui~qUj zo^xM+-{#x1XJ*f=S+i!X=UF>gURE3xnE)9M4h~gPLi9Zx+yj3&ICxy72cV?3zsU^z zfp>T>E(}-PN3;QM5DcWmMd5Dm{-xFDM1hhgwi4ZZt(uQ9Kj-@M`M>NuG`Ns+cts|v z^i|S(K7ygisE(Oyt&3>YC{CXm8~JVmpPEIHz#sWgcsRHof`a_~{F)kq4~)O&p>fhu zQc?(h`{7GUN=h9o_ASqzb`K2=H8p+jyREOOsmaer)_-JZXl&eS#QcP;(6~E>jEIW% z&6`bPakWx|$4y9%sXbD$^kQ(o;$E?bU|*!7+4x71_N6h+dEc>#_+)fKWKZJ%p%~RUk-k!;liY+y4x922UMq1}g zwV7|I_c+~ck05PyKkoYVE8T9XjnCucDH4(%bdtKQjYdG=_F$!(7H4ad)?M?U`O8?^3)g3Jxu&+d<|*dmuU~zvtPXmfŻ|rxbY9%d)J({ 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 Date: Wed, 9 May 2012 15:03:46 +0200 Subject: [PATCH 171/432] route: Add FIXME to rtnl_route_nh_set_gateway() to fix return value Reported-by: Justin Mayfield --- lib/route/nexthop.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/route/nexthop.c b/lib/route/nexthop.c index 48cbfcf..189bccd 100644 --- a/lib/route/nexthop.c +++ b/lib/route/nexthop.c @@ -211,6 +211,7 @@ int rtnl_route_nh_get_ifindex(struct rtnl_nexthop *nh) return nh->rtnh_ifindex; } +/* FIXME: Convert to return an int */ void rtnl_route_nh_set_gateway(struct rtnl_nexthop *nh, struct nl_addr *addr) { struct nl_addr *old = nh->rtnh_gateway; From 32057bc15469e6f012841605daa38766497fa196 Mon Sep 17 00:00:00 2001 From: Justin Mayfield Date: Wed, 9 May 2012 21:08:30 -0600 Subject: [PATCH 172/432] __str2flags fix I found a minor bug in __str2flags where empty strings or short strings will match all or many flags respectively. Basically the test needs to ensure the test string is the same length as the table entry before doing a strncasecmp to avoid doing just a prefix test. --- lib/utils.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/utils.c b/lib/utils.c index 0ec7626..83d424f 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -993,7 +993,8 @@ int __str2flags(const char *buf, const struct trans_tbl *tbl, size_t tbl_len) t = strchr(p, ','); len = t ? t - p : strlen(p); for (i = 0; i < tbl_len; i++) - if (!strncasecmp(tbl[i].a, p, len)) + if (len == strlen(tbl[i].a) && + !strncasecmp(tbl[i].a, p, len)) flags |= tbl[i].i; if (!t) From fec10a282355def49133e63b8a4591cc51b46478 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 10 May 2012 12:03:59 +0200 Subject: [PATCH 173/432] doc: documentation restructuring - changes the modules hierarchy to better represent the set of libaries - list the header file that needs to be included - remove examples/doc from api ref that is included in the guide - add references to the guide - fix doxygen api linking for version 1.8.0 - readd doxygen mainpage to config file - fix a couple of doxygen doc bugs --- configure.in | 12 +- doc/Doxyfile.in | 13 +- doc/Makefile.am | 21 +-- doc/README | 4 +- doc/api/.gitignore | 1 + doc/core.txt | 11 ++ doc/gen-tags.sh | 10 +- doc/src/toc.c | 17 +- doc/tags2dict.sh | 8 - include/netlink/attr.h | 14 +- include/netlink/types.h | 8 +- include/netlink/utils.h | 4 +- lib/addr.c | 30 ++-- lib/attr.c | 359 +--------------------------------------- lib/cache.c | 9 + lib/cache_mngr.c | 17 +- lib/cache_mngt.c | 14 +- lib/data.c | 16 +- lib/fib_lookup/lookup.c | 3 +- lib/genl/genl.c | 4 +- lib/handlers.c | 21 +-- lib/msg.c | 152 ++--------------- lib/netfilter/nfnl.c | 4 +- lib/nl.c | 100 ++++------- lib/object.c | 16 +- lib/route/link.c | 3 +- lib/route/rtnl.c | 4 +- lib/socket.c | 16 +- lib/utils.c | 30 +++- 29 files changed, 245 insertions(+), 676 deletions(-) delete mode 100755 doc/tags2dict.sh diff --git a/configure.in b/configure.in index ed059c3..800354d 100644 --- a/configure.in +++ b/configure.in @@ -91,17 +91,6 @@ if test "x$generate_doc" != "xno"; then AC_MSG_ERROR([*** doxygen package required to generate documentation]) fi - link_doc=yes - AC_CHECK_PROG(HAVE_XMLSTARLET, [xmlstarlet], yes, no) - if test "x$HAVE_XMLSTARLET" = "xno"; then - if test "x$generate_doc" = "xyes"; then - AC_MSG_ERROR([*** xmlstarlet package required to generate documentation]) - else - AC_MSG_WARN([*** xmlstarlet not found, linking to APi reference disabled]) - link_doc=no - fi - fi - AC_CHECK_PROG(HAVE_ASCIIDOC, [asciidoc], yes, no) if test "x$HAVE_ASCIIDOC" = "xno"; then if test "x$generate_doc" = "xyes"; then @@ -123,6 +112,7 @@ if test "x$generate_doc" != "xno"; then fi fi + link_doc=yes if test "x$HAVE_DOXYGEN" = "xno"; then AC_MSG_WARN([*** Disabling API linking due to missing doxygen package]) link_doc=no diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 8bb4fd5..d515db2 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -181,11 +181,11 @@ TAB_SIZE = 8 ALIASES = arg=\param -ALIASES += ref_asciidoc{3}="\3" -ALIASES += ref_core{2}="\ref_asciidoc{core,\1,\2 (Netlink Library)}" -ALIASES += ref_route{2}="\ref_asciidoc{route,\1,\2 (Routing Family Library)}" -ALIASES += core_doc{2}="\par Related Documentation:\n\ref_core{\1,\2}" -ALIASES += route_doc{2}="\par Related Documentation:\n\ref_route{\1,\2}" +ALIASES += ref_asciidoc{3}="\3" +ALIASES += ref_core{2}="\ref_asciidoc{core,\1,\2 (Netlink Core Library Development Guide)}" +ALIASES += ref_route{2}="\ref_asciidoc{route,\1,\2 (Netlink Routing Development Guide)}" +ALIASES += core_doc{2}="\ref_core{\1,\2}" +ALIASES += route_doc{2}="\ref_route{\1,\2}" # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. @@ -590,7 +590,8 @@ WARN_LOGFILE = INPUT = @top_srcdir@/lib \ @top_srcdir@/src/lib \ @top_srcdir@/include/netlink \ - @top_srcdir@/src + @top_srcdir@/src \ + @top_srcdir@/doc/src # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is diff --git a/doc/Makefile.am b/doc/Makefile.am index 142dc31..ffa2245 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -20,7 +20,6 @@ EXTRA_DIST = \ doxygen-link.py \ gen-tags.sh \ resolve-asciidoc-refs.py \ - tags2dict.sh \ stylesheets/asciidoc.css \ stylesheets/asciidoc-manpage.css \ stylesheets/docbook-xsl.css \ @@ -78,28 +77,26 @@ EXTRA_DIST = \ images/icons/callouts/14.png \ images/icons/callouts/15.png -%.html: %.txt +link_doc: if LINK_DOC + ./gen-tags.sh > libnl.dict +else + @echo "Warning: Linking to API reference is disabled, check configure output" +endif + + +%.html: %.txt link_doc ./resolve-asciidoc-refs.py $< > asciidoc.tmp asciidoc $(ASCIIDOCOPTS) -o $@ asciidoc.tmp +if LINK_DOC ./doxygen-link.py libnl.dict $@ > asciidoc.tmp mv asciidoc.tmp $@ -else - asciidoc $(ASCIIDOCOPTS) -o $@ $< endif asciidoc: core.html route.html index.html -link_doc: -if LINK_DOC - ./gen-tags.sh | ./tags2dict.sh > libnl.dict -else - @echo "Warning: Linking to API reference is disabled, check configure output" -endif - api_ref: doxygen Doxyfile; - $(MAKE) link_doc gendoc: if GENERATE_DOC diff --git a/doc/README b/doc/README index 0c230a2..0784e13 100644 --- a/doc/README +++ b/doc/README @@ -6,5 +6,5 @@ mscgen mscgen-filter-1.2 http://code.google.com/p/asciidoc-mscgen-filter/ -asciidoc 8.6.x -doxygen +asciidoc > 8.6.x +doxygen > 1.8.0 diff --git a/doc/api/.gitignore b/doc/api/.gitignore index 821cf65..e57ca88 100644 --- a/doc/api/.gitignore +++ b/doc/api/.gitignore @@ -3,5 +3,6 @@ *.css *.map *.md5 +*.js formula.repository jquery.js diff --git a/doc/core.txt b/doc/core.txt index 7f26e05..8a26dba 100644 --- a/doc/core.txt +++ b/doc/core.txt @@ -2811,6 +2811,17 @@ is stored in +*result+. NOTE: Make sure to return the reference to an address using `nl_addr_put()` after usage to allow memory being freed. +.Example: Transform character string to abstract address +[source,c] +----- +struct nl_addr *a = nl_addr_parse("::1", AF_UNSPEC); +printf("Address family: %s\n", nl_af2str(nl_addr_get_family(a))); +nl_addr_put(a); +a = nl_addr_parse("11:22:33:44:55:66", AF_UNSPEC); +printf("Address family: %s\n", nl_af2str(nl_addr_get_family(a))); +nl_addr_put(a); +----- + .Address References Abstract addresses use reference counting to account for all users of diff --git a/doc/gen-tags.sh b/doc/gen-tags.sh index aba6672..862ec09 100755 --- a/doc/gen-tags.sh +++ b/doc/gen-tags.sh @@ -5,16 +5,10 @@ # written by Carsten Haitzler # -echo '' for f in api/group__*.html do bf=$(basename $f) - grep -oE '' $f | - sed 's//file=\"$bf\" \/>/" | - sed "s/ ref=\"/ href=\"$bf#/" | - sed 's/ member="\([^:]*::\)\([^"]*\)"/ member="\2"/' | - sed 's/ member="\([^"]*\)"/ short="\1"/' + grep -oE "href=\"$bf#[a-z0-9]+\">[^<]+" $f | + sed 's/href="\([^"]*\)">\([^<]*\)<\/a>/\2=api\/\1/' done -echo '' diff --git a/doc/src/toc.c b/doc/src/toc.c index ba7e07a..570c1df 100644 --- a/doc/src/toc.c +++ b/doc/src/toc.c @@ -9,11 +9,11 @@ libnl is a set of libraries to deal with the netlink protocol and some of the high level protocols implemented on top of it. The goal is to -provide APIs on different levels of abstraction. The core library libnl.so +provide APIs on different levels of abstraction. The core library libnl provides a fundamental set of functions to deal with sockets, construct messages, and send/receive those messages. Additional high level interfaces for several individual netlink protocols are provided in separate -libraries (e.g. "nl-route.so", "nl-genl.so", ...). +libraries (e.g. "nl-route", "nl-genl", ...). The library is designed to ensure that all components are optional, i.e. even though the core library provides a caching system which allows to @@ -33,16 +33,9 @@ version is used with a considerably older kernel. \subsection tree_dev Development Tree @code -git://git.kernel.org/pub/scm/libs/netlink/libnl.git +git://git.infradead.org/users/tgr/libnl.git @endcode -- Web: http://www.kernel.org/pub/scm/libs/netlink/libnl.git - -\subsection tree_stable Stable Tree - -@code -git://git.kernel.org/pub/scm/libs/netlink/libnl-stable.git -@endcode -- Web: http://www.kernel.org/pub/scm/libs/netlink/libnl-stable.git +- Web: http://git.infradead.org/users/tgr/libnl.git \section main_website Website @@ -50,7 +43,7 @@ git://git.kernel.org/pub/scm/libs/netlink/libnl-stable.git \section main_mailinglist Mailinglist -Please post question and patches to the libnl mailinglist: +Please post questions and patches to the libnl mailinglist: @code libnl@lists.infradead.org diff --git a/doc/tags2dict.sh b/doc/tags2dict.sh deleted file mode 100755 index 76407af..0000000 --- a/doc/tags2dict.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -xmlstarlet sel -t \ - -m "/libnltags/libnltag[@href]" \ - -v "@short" \ - -o "=api/" \ - -v "@href" \ - -n - diff --git a/include/netlink/attr.h b/include/netlink/attr.h index 8479c23..4d32113 100644 --- a/include/netlink/attr.h +++ b/include/netlink/attr.h @@ -28,12 +28,12 @@ struct nl_msg; * @{ */ - /** - * @ingroup attr - * Basic attribute data types - * - * See \ref attr_datatypes for more details. - */ +/** + * @ingroup attr + * Basic attribute data types + * + * See section @core_doc{core_attr_parse,Attribute Parsing} for more details. + */ enum { NLA_UNSPEC, /**< Unspecified type, binary data chunk */ NLA_U8, /**< 8 bit integer */ @@ -55,7 +55,7 @@ enum { * @ingroup attr * Attribute validation policy. * - * See \ref attr_datatypes for more details. + * See section @core_doc{core_attr_parse,Attribute Parsing} for more details. */ struct nla_policy { /** Type of attribute or NLA_UNSPEC */ diff --git a/include/netlink/types.h b/include/netlink/types.h index f6dade3..09cc5bd 100644 --- a/include/netlink/types.h +++ b/include/netlink/types.h @@ -1,12 +1,12 @@ /* - * netlink/netlink-types.h Netlink Types + * netlink/types.h Definition of public types * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2006 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ #ifndef __NETLINK_TYPES_H_ @@ -15,8 +15,8 @@ #include /** - * Dumping types (dp_type) * @ingroup utils + * Enumeration of dumping variations (dp_type) */ enum nl_dump_type { NL_DUMP_LINE, /**< Dump object briefly on one line */ @@ -27,8 +27,8 @@ enum nl_dump_type { #define NL_DUMP_MAX (__NL_DUMP_MAX - 1) /** - * Dumping parameters * @ingroup utils + * Dumping parameters */ struct nl_dump_params { diff --git a/include/netlink/utils.h b/include/netlink/utils.h index a1ef82e..4d7b969 100644 --- a/include/netlink/utils.h +++ b/include/netlink/utils.h @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ #ifndef NETLINK_UTILS_H_ @@ -31,7 +31,7 @@ extern "C" { #define NL_PROB_MIN 0x0 /** - * Upper probability limit + * Upper probability limit nl_dump_type * @ingroup utils */ #define NL_PROB_MAX 0xffffffff diff --git a/lib/addr.c b/lib/addr.c index 30c708d..89d3d4f 100644 --- a/lib/addr.c +++ b/lib/addr.c @@ -1,28 +1,30 @@ /* - * lib/addr.c Abstract Address + * lib/addr.c Network Address * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2010 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ /** - * @ingroup core - * @defgroup addr Abstract Address + * @ingroup core_types + * @defgroup addr Network Address + * + * Abstract data type representing any kind of network address + * + * Related sections in the development guide: + * - @core_doc{_abstract_address, Network Addresses} * - * @par 1) Transform character string to abstract address - * @code - * struct nl_addr *a = nl_addr_parse("::1", AF_UNSPEC); - * printf("Address family: %s\n", nl_af2str(nl_addr_get_family(a))); - * nl_addr_put(a); - * a = nl_addr_parse("11:22:33:44:55:66", AF_UNSPEC); - * printf("Address family: %s\n", nl_af2str(nl_addr_get_family(a))); - * nl_addr_put(a); - * @endcode * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ */ #include @@ -163,7 +165,7 @@ static void addr_destroy(struct nl_addr *addr) } /** - * @name Creating Abstract Addresses + * @name Creating Abstract Network Addresses * @{ */ diff --git a/lib/attr.c b/lib/attr.c index a045351..6ef6cd9 100644 --- a/lib/attr.c +++ b/lib/attr.c @@ -22,356 +22,16 @@ * @defgroup attr Attributes * Netlink Attributes Construction/Parsing Interface * - * \section attr_sec Netlink Attributes - * Netlink attributes allow for data chunks of arbitary length to be - * attached to a netlink message. Each attribute is encoded with a - * type and length field, both 16 bits, stored in the attribute header - * preceding the attribute data. The main advantage of using attributes - * over packing everything into the family header is that the interface - * stays extendable as new attributes can supersede old attributes while - * remaining backwards compatible. Also attributes can be defined optional - * thus avoiding the transmission of unnecessary empty data blocks. - * Special nested attributes allow for more complex data structures to - * be transmitted, e.g. trees, lists, etc. - * - * While not required, netlink attributes typically follow the family - * header of a netlink message and must be properly aligned to NLA_ALIGNTO: - * @code - * +----------------+- - -+---------------+- - -+------------+- - -+ - * | Netlink Header | Pad | Family Header | Pad | Attributes | Pad | - * +----------------+- - -+---------------+- - -+------------+- - -+ - * @endcode - * - * The actual attributes are chained together each separately aligned to - * NLA_ALIGNTO. The position of an attribute is defined based on the - * length field of the preceding attributes: - * @code - * +-------------+- - -+-------------+- - -+------ - * | Attribute 1 | Pad | Attribute 2 | Pad | ... - * +-------------+- - -+-------------+- - -+------ - * nla_next(attr1)------^ - * @endcode - * - * The attribute itself consists of the attribute header followed by - * the actual payload also aligned to NLA_ALIGNTO. The function nla_data() - * returns a pointer to the start of the payload while nla_len() returns - * the length of the payload in bytes. - * - * \b Note: Be aware, NLA_ALIGNTO equals to 4 bytes, therefore it is not - * safe to dereference any 64 bit data types directly. - * - * @code - * <----------- nla_total_size(payload) -----------> - * <-------- nla_attr_size(payload) ---------> - * +------------------+- - -+- - - - - - - - - +- - -+ - * | Attribute Header | Pad | Payload | Pad | - * +------------------+- - -+- - - - - - - - - +- - -+ - * nla_data(nla)-------------^ - * <- nla_len(nla) -> - * @endcode - * - * @subsection attr_datatypes Attribute Data Types - * A number of basic data types are supported to simplify access and - * validation of netlink attributes. This data type information is - * not encoded in the attribute, both the kernel and userspace part - * are required to share this information on their own. - * - * One of the major advantages of these basic types is the automatic - * validation of each attribute based on an attribute policy. The - * validation covers most of the checks required to safely use - * attributes and thus keeps the individual sanity check to a minimum. - * - * Never access attribute payload without ensuring basic validation - * first, attributes may: - * - not be present even though required - * - contain less actual payload than expected - * - fake a attribute length which exceeds the end of the message - * - contain unterminated character strings - * - * Policies are defined as array of the struct nla_policy. The array is - * indexed with the attribute type, therefore the array must be sized - * accordingly. - * @code - * static struct nla_policy my_policy[ATTR_MAX+1] = { - * [ATTR_FOO] = { .type = ..., .minlen = ..., .maxlen = ... }, - * }; - * - * err = nla_validate(attrs, attrlen, ATTR_MAX, &my_policy); - * @endcode - * - * Some basic validations are performed on every attribute, regardless of type. - * - If the attribute type exceeds the maximum attribute type specified or - * the attribute type is lesser-or-equal than zero, the attribute will - * be silently ignored. - * - If the payload length falls below the \a minlen value the attribute - * will be rejected. - * - If \a maxlen is non-zero and the payload length exceeds the \a maxlen - * value the attribute will be rejected. - * - * - * @par Unspecific Attribute (NLA_UNSPEC) - * This is the standard type if no type is specified. It is used for - * binary data of arbitary length. Typically this attribute carries - * a binary structure or a stream of bytes. - * @par - * @code - * // In this example, we will assume a binary structure requires to - * // be transmitted. The definition of the structure will typically - * // go into a header file available to both the kernel and userspace - * // side. - * // - * // Note: Be careful when putting 64 bit data types into a structure. - * // The attribute payload is only aligned to 4 bytes, dereferencing - * // the member may fail. - * struct my_struct { - * int a; - * int b; - * }; - * - * // The validation function will not enforce an exact length match to - * // allow structures to grow as required. Note: While it is allowed - * // to add members to the end of the structure, changing the order or - * // inserting members in the middle of the structure will break your - * // binary interface. - * static struct nla_policy my_policy[ATTR_MAX+1] = { - * [ATTR_MY_STRICT] = { .type = NLA_UNSPEC, - * .minlen = sizeof(struct my_struct) }, - * - * // The binary structure is appened to the message using nla_put() - * struct my_struct foo = { .a = 1, .b = 2 }; - * nla_put(msg, ATTR_MY_STRUCT, sizeof(foo), &foo); - * - * // On the receiving side, a pointer to the structure pointing inside - * // the message payload is returned by nla_get(). - * if (attrs[ATTR_MY_STRUCT]) - * struct my_struct *foo = nla_get(attrs[ATTR_MY_STRUCT]); - * @endcode - * - * @par Integers (NLA_U8, NLA_U16, NLA_U32, NLA_U64) - * Integers come in different sizes from 8 bit to 64 bit. However, since the - * payload length is aligned to 4 bytes, integers smaller than 32 bit are - * only useful to enforce the maximum range of values. - * @par - * \b Note: There is no difference made between signed and unsigned integers. - * The validation only enforces the minimal payload length required to store - * an integer of specified type. - * @par - * @code - * // Even though possible, it does not make sense to specify .minlen or - * // .maxlen for integer types. The data types implies the corresponding - * // minimal payload length. - * static struct nla_policy my_policy[ATTR_MAX+1] = { - * [ATTR_FOO] = { .type = NLA_U32 }, - * - * // Numeric values can be appended directly using the respective - * // nla_put_uxxx() function - * nla_put_u32(msg, ATTR_FOO, 123); - * - * // Same for the receiving side. - * if (attrs[ATTR_FOO]) - * uint32_t foo = nla_get_u32(attrs[ATTR_FOO]); - * @endcode - * - * @par Character string (NLA_STRING) - * This data type represents a NUL terminated character string of variable - * length. For binary data streams the type NLA_UNSPEC is recommended. - * @par - * @code - * // Enforce a NUL terminated character string of at most 4 characters - * // including the NUL termination. - * static struct nla_policy my_policy[ATTR_MAX+1] = { - * [ATTR_BAR] = { .type = NLA_STRING, maxlen = 4 }, - * - * // nla_put_string() creates a string attribute of the necessary length - * // and appends it to the message including the NUL termination. - * nla_put_string(msg, ATTR_BAR, "some text"); - * - * // It is safe to use the returned character string directly if the - * // attribute has been validated as the validation enforces the proper - * // termination of the string. - * if (attrs[ATTR_BAR]) - * char *text = nla_get_string(attrs[ATTR_BAR]); - * @endcode - * - * @par Flag (NLA_FLAG) - * This attribute type may be used to indicate the presence of a flag. The - * attribute is only valid if the payload length is zero. The presence of - * the attribute header indicates the presence of the flag. - * @par - * @code - * // This attribute type is special as .minlen and .maxlen have no effect. - * static struct nla_policy my_policy[ATTR_MAX+1] = { - * [ATTR_FLAG] = { .type = NLA_FLAG }, - * - * // nla_put_flag() appends a zero sized attribute to the message. - * nla_put_flag(msg, ATTR_FLAG); - * - * // There is no need for a receival function, the presence is the value. - * if (attrs[ATTR_FLAG]) - * // flag is present - * @endcode - * - * @par Micro Seconds (NLA_MSECS) - * - * @par Nested Attribute (NLA_NESTED) - * Attributes can be nested and put into a container to create groups, lists - * or to construct trees of attributes. Nested attributes are often used to - * pass attributes to a subsystem where the top layer has no knowledge of the - * configuration possibilities of each subsystem. - * @par - * \b Note: When validating the attributes using nlmsg_validate() or - * nlmsg_parse() it will only affect the top level attributes. Each - * level of nested attributes must be validated seperately using - * nla_parse_nested() or nla_validate(). - * @par - * @code - * // The minimal length policy may be used to enforce the presence of at - * // least one attribute. - * static struct nla_policy my_policy[ATTR_MAX+1] = { - * [ATTR_OPTS] = { .type = NLA_NESTED, minlen = NLA_HDRLEN }, - * - * // Nested attributes are constructed by enclosing the attributes - * // to be nested with calls to nla_nest_start() respetively nla_nest_end(). - * struct nlattr *opts = nla_nest_start(msg, ATTR_OPTS); - * nla_put_u32(msg, ATTR_FOO, 123); - * nla_put_string(msg, ATTR_BAR, "some text"); - * nla_nest_end(msg, opts); - * - * // Various methods exist to parse nested attributes, the easiest being - * // nla_parse_nested() which also allows validation in the same step. - * if (attrs[ATTR_OPTS]) { - * struct nlattr *nested[ATTR_MAX+1]; - * - * nla_parse_nested(nested, ATTR_MAX, attrs[ATTR_OPTS], &policy); - * - * if (nested[ATTR_FOO]) - * uint32_t foo = nla_get_u32(nested[ATTR_FOO]); - * } - * @endcode - * - * @subsection attr_exceptions Exception Based Attribute Construction - * Often a large number of attributes are added to a message in a single - * function. In order to simplify error handling, a second set of - * construction functions exist which jump to a error label when they - * fail instead of returning an error code. This second set consists - * of macros which are named after their error code based counterpart - * except that the name is written all uppercase. - * - * All of the macros jump to the target \c nla_put_failure if they fail. - * @code - * void my_func(struct nl_msg *msg) - * { - * NLA_PUT_U32(msg, ATTR_FOO, 10); - * NLA_PUT_STRING(msg, ATTR_BAR, "bar"); - * - * return 0; - * - * nla_put_failure: - * return -NLE_NOMEM; - * } - * @endcode - * - * @subsection attr_examples Examples - * @par Example 1.1 Constructing a netlink message with attributes. - * @code - * struct nl_msg *build_msg(int ifindex, struct nl_addr *lladdr, int mtu) - * { - * struct nl_msg *msg; - * struct nlattr *info, *vlan; - * struct ifinfomsg ifi = { - * .ifi_family = AF_INET, - * .ifi_index = ifindex, - * }; - * - * // Allocate a new netlink message, type=RTM_SETLINK, flags=NLM_F_ECHO - * if (!(msg = nlmsg_alloc_simple(RTM_SETLINK, NLM_F_ECHO))) - * return NULL; - * - * // Append the family specific header (struct ifinfomsg) - * if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0) - * goto nla_put_failure - * - * // Append a 32 bit integer attribute to carry the MTU - * NLA_PUT_U32(msg, IFLA_MTU, mtu); - * - * // Append a unspecific attribute to carry the link layer address - * NLA_PUT_ADDR(msg, IFLA_ADDRESS, lladdr); - * - * // Append a container for nested attributes to carry link information - * if (!(info = nla_nest_start(msg, IFLA_LINKINFO))) - * goto nla_put_failure; - * - * // Put a string attribute into the container - * NLA_PUT_STRING(msg, IFLA_INFO_KIND, "vlan"); - * - * // Append another container inside the open container to carry - * // vlan specific attributes - * if (!(vlan = nla_nest_start(msg, IFLA_INFO_DATA))) - * goto nla_put_failure; - * - * // add vlan specific info attributes here... - * - * // Finish nesting the vlan attributes and close the second container. - * nla_nest_end(msg, vlan); - * - * // Finish nesting the link info attribute and close the first container. - * nla_nest_end(msg, info); - * - * return msg; - * - * // If any of the construction macros fails, we end up here. - * nla_put_failure: - * nlmsg_free(msg); - * return NULL; - * } - * @endcode - * - * @par Example 2.1 Parsing a netlink message with attributes. - * @code - * int parse_message(struct nl_msg *msg) - * { - * // The policy defines two attributes: a 32 bit integer and a container - * // for nested attributes. - * struct nla_policy attr_policy[ATTR_MAX+1] = { - * [ATTR_FOO] = { .type = NLA_U32 }, - * [ATTR_BAR] = { .type = NLA_NESTED }, - * }; - * struct nlattr *attrs[ATTR_MAX+1]; - * int err; - * - * // The nlmsg_parse() function will make sure that the message contains - * // enough payload to hold the header (struct my_hdr), validates any - * // attributes attached to the messages and stores a pointer to each - * // attribute in the attrs[] array accessable by attribute type. - * if ((err = nlmsg_parse(nlmsg_hdr(msg), sizeof(struct my_hdr), attrs, - * ATTR_MAX, attr_policy)) < 0) - * goto errout; - * - * if (attrs[ATTR_FOO]) { - * // It is safe to directly access the attribute payload without - * // any further checks since nlmsg_parse() enforced the policy. - * uint32_t foo = nla_get_u32(attrs[ATTR_FOO]); - * } - * - * if (attrs[ATTR_BAR]) { - * struct nlattr *nested[NESTED_MAX+1]; - * - * // Attributes nested in a container can be parsed the same way - * // as top level attributes. - * if ((err = nla_parse_nested(nested, NESTED_MAX, attrs[ATTR_BAR], - * nested_policy)) < 0) - * goto errout; - * - * // Process nested attributes here. - * } - * - * err = 0; - * errout: - * return err; - * } - * @endcode + * Related sections in the development guide: + * - @core_doc{core_attr,Netlink Attributes} * * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ */ /** @@ -628,8 +288,7 @@ errout: * than the maximum type specified will be silently ignored in order to * maintain backwards compatibility. * - * See \ref attr_datatypes for more details on what kind of validation - * checks are performed on each attribute data type. + * See section @core_doc{core_attr_parse,Attribute Parsing} for more details. * * @return 0 on success or a negative error code. */ diff --git a/lib/cache.c b/lib/cache.c index 814c616..5cfae67 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -37,7 +37,16 @@ * | | Core Netlink * @endcode * + * Related sections in the development guide: + * - @core_doc{core_cache, Caching System} + * * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ */ #include diff --git a/lib/cache_mngr.c b/lib/cache_mngr.c index 0f0df51..cdf2b7b 100644 --- a/lib/cache_mngr.c +++ b/lib/cache_mngr.c @@ -12,9 +12,24 @@ /** * @ingroup cache_mngt * @defgroup cache_mngr Manager - * @brief Automatically keep caches up to date + * @brief Manager keeping caches up to date automatically. + * + * The cache manager keeps caches up to date automatically by listening to + * netlink notifications and integrating the received information into the + * existing cache. + * + * @note This functionality is still considered experimental. + * + * Related sections in the development guide: + * - @core_doc{_cache_manager,Cache Manager} * * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ */ #include diff --git a/lib/cache_mngt.c b/lib/cache_mngt.c index a9ecf27..6691454 100644 --- a/lib/cache_mngt.c +++ b/lib/cache_mngt.c @@ -6,13 +6,23 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ /** * @ingroup core - * @defgroup cache_mngt Caching + * @defgroup cache_mngt Caching System + * + * Related sections in the development guide: + * - @core_doc{core_cache, Caching System} + * * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ */ #include diff --git a/lib/data.c b/lib/data.c index 03cd9fe..e4196b1 100644 --- a/lib/data.c +++ b/lib/data.c @@ -6,13 +6,25 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ /** - * @ingroup core + * @ingroup core_types * @defgroup data Abstract Data + * + * Abstract data type representing a binary data blob. + * + * Related sections in the development guide: + * - @core_doc{_abstract_data, Abstract Data} + * * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ */ #include diff --git a/lib/fib_lookup/lookup.c b/lib/fib_lookup/lookup.c index 6018251..ec82c16 100644 --- a/lib/fib_lookup/lookup.c +++ b/lib/fib_lookup/lookup.c @@ -6,10 +6,11 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ /** + * @ingroup rtnl * @defgroup fib_lookup FIB Lookup * @brief * @{ diff --git a/lib/genl/genl.c b/lib/genl/genl.c index 055be91..6e6a764 100644 --- a/lib/genl/genl.c +++ b/lib/genl/genl.c @@ -6,11 +6,11 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ /** - * @defgroup genl Generic Netlink + * @defgroup genl Generic Netlink Library (libnl-genl) * * @par Message Format * @code diff --git a/lib/handlers.c b/lib/handlers.c index f13b89e..74276a1 100644 --- a/lib/handlers.c +++ b/lib/handlers.c @@ -13,21 +13,16 @@ * @ingroup core * @defgroup cb Callbacks/Customization * - * @details - * @par 1) Setting up a callback set - * @code - * // Allocate a callback set and initialize it to the verbose default set - * struct nl_cb *cb = nl_cb_alloc(NL_CB_VERBOSE); + * Related sections in the development guide: + * - @core_doc{core_cb, Callback Configuration} * - * // Modify the set to call my_func() for all valid messages - * nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, my_func, NULL); - * - * // Set the error message handler to the verbose default implementation - * // and direct it to print all errors to the given file descriptor. - * FILE *file = fopen(...); - * nl_cb_err(cb, NL_CB_VERBOSE, NULL, file); - * @endcode * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ */ #include diff --git a/lib/msg.c b/lib/msg.c index 235ee82..18174b5 100644 --- a/lib/msg.c +++ b/lib/msg.c @@ -6,156 +6,24 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ /** * @ingroup core - * @defgroup msg Messages + * @defgroup msg Message Construction & Parsing * Netlink Message Construction/Parsing Interface * - * The following information is partly extracted from RFC3549 - * (ftp://ftp.rfc-editor.org/in-notes/rfc3549.txt) + * Related sections in the development guide: + * - @core_doc{_message_parsing_amp_construction,Message Parsing & Construction} * - * @par Message Format - * Netlink messages consist of a byte stream with one or multiple - * Netlink headers and an associated payload. If the payload is too big - * to fit into a single message it, can be split over multiple Netlink - * messages, collectively called a multipart message. For multipart - * messages, the first and all following headers have the \c NLM_F_MULTI - * Netlink header flag set, except for the last header which has the - * Netlink header type \c NLMSG_DONE. - * - * @par - * The Netlink message header (struct nlmsghdr) is shown below. - * @code - * 0 1 2 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Length | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Type | Flags | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Sequence Number | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Process ID (PID) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * @endcode - * - * @par - * The netlink message header and payload must be aligned properly: - * @code - * <------- NLMSG_ALIGN(hlen) ------> <---- NLMSG_ALIGN(len) ---> - * +----------------------------+- - -+- - - - - - - - - - -+- - -+ - * | Header | Pad | Payload | Pad | - * | struct nlmsghdr | | | | - * +----------------------------+- - -+- - - - - - - - - - -+- - -+ - * @endcode - * @par - * Message Format: - * @code - * <--- nlmsg_total_size(payload) ---> - * <-- nlmsg_msg_size(payload) -> - * +----------+- - -+-------------+- - -+-------- - - - * | nlmsghdr | Pad | Payload | Pad | nlmsghdr - * +----------+- - -+-------------+- - -+-------- - - - * nlmsg_data(nlh)---^ ^ - * nlmsg_next(nlh)-----------------------+ - * @endcode - * @par - * The payload may consist of arbitary data but may have strict - * alignment and formatting rules depening on the specific netlink - * families. - * @par - * @code - * <---------------------- nlmsg_len(nlh) ---------------------> - * <------ hdrlen ------> <- nlmsg_attrlen(nlh, hdrlen) -> - * +----------------------+- - -+--------------------------------+ - * | Family Header | Pad | Attributes | - * +----------------------+- - -+--------------------------------+ - * nlmsg_attrdata(nlh, hdrlen)---^ - * @endcode - * @par The ACK Netlink Message - * This message is actually used to denote both an ACK and a NACK. - * Typically, the direction is from FEC to CPC (in response to an ACK - * request message). However, the CPC should be able to send ACKs back - * to FEC when requested. - * @code - * 0 1 2 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Netlink message header | - * | type = NLMSG_ERROR | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Error code | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | OLD Netlink message header | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * @endcode - * - * @par Example - * @code - * // Various methods exist to create/allocate a new netlink - * // message. - * // - * // nlmsg_alloc() will allocate an empty netlink message with - * // a maximum payload size which defaults to the page size of - * // the system. This default size can be modified using the - * // function nlmsg_set_default_size(). - * struct nl_msg *msg = nlmsg_alloc(); - * - * // Very often, the message type and message flags are known - * // at allocation time while the other fields are auto generated: - * struct nl_msg *msg = nlmsg_alloc_simple(MY_TYPE, MY_FLAGS); - * - * // Alternatively an existing netlink message header can be used - * // to inherit the header values: - * struct nlmsghdr hdr = { - * .nlmsg_type = MY_TYPE, - * .nlmsg_flags = MY_FLAGS, - * }; - * struct nl_msg *msg = nlmsg_inherit(&hdr); - * - * // Last but not least, netlink messages received from netlink sockets - * // can be converted into nl_msg objects using nlmsg_convert(). This - * // will create a message with a maximum payload size which equals the - * // length of the existing netlink message, therefore no more data can - * // be appened without calling nlmsg_expand() first. - * struct nl_msg *msg = nlmsg_convert(nlh_from_nl_sock); - * - * // Payload may be added to the message via nlmsg_append(). The fourth - * // parameter specifies the number of alignment bytes the data should - * // be padding with at the end. Common values are 0 to disable it or - * // NLMSG_ALIGNTO to ensure proper netlink message padding. - * nlmsg_append(msg, &mydata, sizeof(mydata), 0); - * - * // Sometimes it may be necessary to reserve room for data but defer - * // the actual copying to a later point, nlmsg_reserve() can be used - * // for this purpose: - * void *data = nlmsg_reserve(msg, sizeof(mydata), NLMSG_ALIGNTO); - * - * // Attributes may be added using the attributes interface. - * - * // After successful use of the message, the memory must be freed - * // using nlmsg_free() - * nlmsg_free(msg); - * @endcode - * - * @par 4) Parsing messages - * @code - * int n; - * unsigned char *buf; - * struct nlmsghdr *hdr; - * - * n = nl_recv(handle, NULL, &buf); - * - * hdr = (struct nlmsghdr *) buf; - * while (nlmsg_ok(hdr, n)) { - * // Process message here... - * hdr = nlmsg_next(hdr, &n); - * } - * @endcode * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ */ #include diff --git a/lib/netfilter/nfnl.c b/lib/netfilter/nfnl.c index ddce4b9..6d27c44 100644 --- a/lib/netfilter/nfnl.c +++ b/lib/netfilter/nfnl.c @@ -6,13 +6,13 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf * Copyright (c) 2007 Philip Craig * Copyright (c) 2007 Secure Computing Corporation */ /** - * @defgroup nfnl Netfilter Netlink + * @defgroup nfnl Netfilter Library (libnl-nf) * * @par Message Format * @code diff --git a/lib/nl.c b/lib/nl.c index 7e59130..64e1382 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -6,78 +6,22 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ /** - * @defgroup core Core + * @defgroup core Core Library (libnl) * - * @details - * @par 1) Connecting the socket - * @code - * // Bind and connect the socket to a protocol, NETLINK_ROUTE in this example. - * nl_connect(sk, NETLINK_ROUTE); - * @endcode + * Socket handling, connection management, sending and receiving of data, + * message construction and parsing, object caching system, ... * - * @par 2) Sending data - * @code - * // The most rudimentary method is to use nl_sendto() simply pushing - * // a piece of data to the other netlink peer. This method is not - * // recommended. - * const char buf[] = { 0x01, 0x02, 0x03, 0x04 }; - * nl_sendto(sk, buf, sizeof(buf)); + * This is the API reference of the core library. It is not meant as a guide + * but as a reference. Please refer to the core library guide for detailed + * documentation on the library architecture and examples: * - * // A more comfortable interface is nl_send() taking a pointer to - * // a netlink message. - * struct nl_msg *msg = my_msg_builder(); - * nl_send(sk, nlmsg_hdr(msg)); + * * @ref_asciidoc{core,_,Netlink Core Library Development Guide} * - * // nl_sendmsg() provides additional control over the sendmsg() message - * // header in order to allow more specific addressing of multiple peers etc. - * struct msghdr hdr = { ... }; - * nl_sendmsg(sk, nlmsg_hdr(msg), &hdr); * - * // You're probably too lazy to fill out the netlink pid, sequence number - * // and message flags all the time. nl_send_auto_complete() automatically - * // extends your message header as needed with an appropriate sequence - * // number, the netlink pid stored in the netlink socket and the message - * // flags NLM_F_REQUEST and NLM_F_ACK (if not disabled in the socket) - * nl_send_auto_complete(sk, nlmsg_hdr(msg)); - * - * // Simple protocols don't require the complex message construction interface - * // and may favour nl_send_simple() to easly send a bunch of payload - * // encapsulated in a netlink message header. - * nl_send_simple(sk, MY_MSG_TYPE, 0, buf, sizeof(buf)); - * @endcode - * - * @par 3) Receiving data - * @code - * // nl_recv() receives a single message allocating a buffer for the message - * // content and gives back the pointer to you. - * struct sockaddr_nl peer; - * unsigned char *msg; - * nl_recv(sk, &peer, &msg); - * - * // nl_recvmsgs() receives a bunch of messages until the callback system - * // orders it to state, usually after receving a compolete multi part - * // message series. - * nl_recvmsgs(sk, my_callback_configuration); - * - * // nl_recvmsgs_default() acts just like nl_recvmsg() but uses the callback - * // configuration stored in the socket. - * nl_recvmsgs_default(sk); - * - * // In case you want to wait for the ACK to be recieved that you requested - * // with your latest message, you can call nl_wait_for_ack() - * nl_wait_for_ack(sk); - * @endcode - * - * @par 4) Closing - * @code - * // Close the socket first to release kernel memory - * nl_close(sk); - * @endcode - * * @{ */ @@ -88,6 +32,30 @@ #include #include +/** + * @defgroup core_types Data Types + * + * Core library data types + * @{ + * @} + * + * @defgroup send_recv Send & Receive Data + * + * Connection management, sending & receiving of data + * + * Related sections in the development guide: + * - @core_doc{core_send_recv, Sending & Receiving} + * - @core_doc{core_sockets, Sockets} + * + * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ + */ + /** * @name Connection Management * @{ @@ -541,6 +509,7 @@ abort: return 0; } +/** @cond SKIP */ #define NL_CB_CALL(cb, type, msg) \ do { \ err = nl_cb_call(cb, type, msg); \ @@ -556,6 +525,7 @@ do { \ goto out; \ } \ } while (0) +/** @endcond */ static int recvmsgs(struct nl_sock *sk, struct nl_cb *cb) { @@ -923,3 +893,5 @@ errout: /** @} */ /** @} */ + +/** @} */ diff --git a/lib/object.c b/lib/object.c index 554d09b..7606535 100644 --- a/lib/object.c +++ b/lib/object.c @@ -10,9 +10,21 @@ */ /** - * @ingroup cache - * @defgroup object Object + * @ingroup core_types + * @defgroup object Object (Cacheable) + * + * Generic object data type, for inheritance purposes to implement cacheable + * data types. + * + * Related sections in the development guide: + * * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ */ #include diff --git a/lib/route/link.c b/lib/route/link.c index 4da40a0..0a17110 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -1442,8 +1442,7 @@ struct rtnl_link *rtnl_link_alloc(void) /** * Return a link object reference - * - * @copydetails nl_object_put() + * @arg link Link object */ void rtnl_link_put(struct rtnl_link *link) { diff --git a/lib/route/rtnl.c b/lib/route/rtnl.c index e5c0798..12a7e97 100644 --- a/lib/route/rtnl.c +++ b/lib/route/rtnl.c @@ -6,11 +6,11 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ /** - * @defgroup rtnl Routing Family + * @defgroup rtnl Routing Library (libnl-route) * @{ */ diff --git a/lib/socket.c b/lib/socket.c index 01b9872..7e3ebf6 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -6,13 +6,25 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ /** - * @ingroup core + * @ingroup core_types * @defgroup socket Socket + * + * Representation of a netlink socket + * + * Related sections in the development guide: + * - @core_doc{core_sockets, Netlink Sockets} + * * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ */ #include diff --git a/lib/utils.c b/lib/utils.c index 83d424f..5a35a53 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -6,13 +6,22 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ /** * @ingroup core * @defgroup utils Utilities + * + * Collection of helper functions + * * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ */ #include @@ -21,10 +30,24 @@ #include /** - * Debug level + * Global variable indicating the desired level of debugging output. + * + * Level | Messages Printed + * ----- | --------------------------------------------------------- + * 0 | Debugging output disabled + * 1 | Warnings, important events and notifications + * 2 | More or less important debugging messages + * 3 | Repetitive events causing a flood of debugging messages + * 4 | Even less important messages + * + * If available, the variable will be initialized to the value of the + * environment variable `NLDBG`. The default value is 0 (disabled). + * + * For more information, see section @core_doc{_debugging, Debugging}. */ int nl_debug = 0; +/** @cond SKIP */ struct nl_dump_params nl_debug_dp = { .dp_type = NL_DUMP_DETAILS, }; @@ -84,9 +107,10 @@ int __nl_read_num_str_file(const char *path, int (*cb)(long, const char *)) return 0; } +/** @endcond */ /** - * @name Unit Pretty-Printing + * @name Pretty Printing of Numbers * @{ */ From 996b502961976d04f058664d5083f121eb61ce4a Mon Sep 17 00:00:00 2001 From: Isaac Date: Sat, 12 May 2012 22:37:48 -0700 Subject: [PATCH 174/432] FTBFS with musl libc: Missing includes Hello, libnl 3.2.9 does not build with musl libc, without patching. I' using a current musl libc (http://www.etalabs.net/musl/) with linux 2.6.32 headers. At first there were a couple problems on the musl side, but those are resolved. However, I found some other issues: First, two files were missing #include : lib/netfilter/log_msg.c lib/netfilter/queue_msg.c These files used __bswap_64 (which should be bswap_64), a macro declared in byteswap.h Second, I got this error after fixing that: In file included from nf-queue.c:16: ./include/linux/netfilter.h:53: error: field in has incomplete type ./include/linux/netfilter.h:54: error: field in6 has incomplete type I found that src/nf-queue.c is missing an #include Attached is a patch which resolves these issues. I've tested with both musl and glibc, and it builds cleanly on both. --- lib/netfilter/ct.c | 2 +- lib/netfilter/log_msg.c | 3 ++- lib/netfilter/queue_msg.c | 3 ++- src/nf-queue.c | 1 + 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/netfilter/ct.c b/lib/netfilter/ct.c index 9d61b6c..59ee1d9 100644 --- a/lib/netfilter/ct.c +++ b/lib/netfilter/ct.c @@ -38,7 +38,7 @@ static uint64_t ntohll(uint64_t x) #elif __BYTE_ORDER == __LITTLE_ENDIAN static uint64_t ntohll(uint64_t x) { - return __bswap_64(x); + return bswap_64(x); } #endif diff --git a/lib/netfilter/log_msg.c b/lib/netfilter/log_msg.c index cad6ddd..65448f9 100644 --- a/lib/netfilter/log_msg.c +++ b/lib/netfilter/log_msg.c @@ -26,6 +26,7 @@ #include #include #include +#include #if __BYTE_ORDER == __BIG_ENDIAN static uint64_t ntohll(uint64_t x) @@ -35,7 +36,7 @@ static uint64_t ntohll(uint64_t x) #elif __BYTE_ORDER == __LITTLE_ENDIAN static uint64_t ntohll(uint64_t x) { - return __bswap_64(x); + return bswap_64(x); } #endif diff --git a/lib/netfilter/queue_msg.c b/lib/netfilter/queue_msg.c index c40f8c2..30c522f 100644 --- a/lib/netfilter/queue_msg.c +++ b/lib/netfilter/queue_msg.c @@ -24,6 +24,7 @@ #include #include #include +#include static struct nl_cache_ops nfnl_queue_msg_ops; @@ -35,7 +36,7 @@ static uint64_t ntohll(uint64_t x) #elif __BYTE_ORDER == __LITTLE_ENDIAN static uint64_t ntohll(uint64_t x) { - return __bswap_64(x); + return bswap_64(x); } #endif diff --git a/src/nf-queue.c b/src/nf-queue.c index bd10adf..922d9c8 100644 --- a/src/nf-queue.c +++ b/src/nf-queue.c @@ -13,6 +13,7 @@ #include #include +#include #include #include #include From 6627ec3836472977f63a571b5fe059524db7ec50 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 16 May 2012 13:42:05 +0200 Subject: [PATCH 175/432] tc: fix included headers Reported-by: Adrian Ban --- include/netlink/route/cls/basic.h | 2 ++ include/netlink/route/cls/cgroup.h | 2 ++ include/netlink/route/cls/fw.h | 1 + include/netlink/route/cls/u32.h | 1 + include/netlink/route/qdisc/dsmark.h | 2 ++ include/netlink/route/qdisc/fifo.h | 1 + include/netlink/route/qdisc/htb.h | 2 ++ include/netlink/route/qdisc/netem.h | 1 + include/netlink/route/qdisc/plug.h | 1 + include/netlink/route/qdisc/prio.h | 1 + include/netlink/route/qdisc/sfq.h | 1 + include/netlink/route/qdisc/tbf.h | 1 + 12 files changed, 16 insertions(+) diff --git a/include/netlink/route/cls/basic.h b/include/netlink/route/cls/basic.h index 8b58c1e..603fa88 100644 --- a/include/netlink/route/cls/basic.h +++ b/include/netlink/route/cls/basic.h @@ -13,6 +13,8 @@ #define NETLINK_BASIC_H_ #include +#include +#include #ifdef __cplusplus extern "C" { diff --git a/include/netlink/route/cls/cgroup.h b/include/netlink/route/cls/cgroup.h index 20346ff..9cd4845 100644 --- a/include/netlink/route/cls/cgroup.h +++ b/include/netlink/route/cls/cgroup.h @@ -14,6 +14,8 @@ #include #include +#include +#include #ifdef __cplusplus extern "C" { diff --git a/include/netlink/route/cls/fw.h b/include/netlink/route/cls/fw.h index 39878de..d1f1b75 100644 --- a/include/netlink/route/cls/fw.h +++ b/include/netlink/route/cls/fw.h @@ -15,6 +15,7 @@ #define NETLINK_FW_H_ #include +#include #ifdef __cplusplus extern "C" { diff --git a/include/netlink/route/cls/u32.h b/include/netlink/route/cls/u32.h index 62c5386..2789b19 100644 --- a/include/netlink/route/cls/u32.h +++ b/include/netlink/route/cls/u32.h @@ -14,6 +14,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { diff --git a/include/netlink/route/qdisc/dsmark.h b/include/netlink/route/qdisc/dsmark.h index d7a6d22..06bd9d3 100644 --- a/include/netlink/route/qdisc/dsmark.h +++ b/include/netlink/route/qdisc/dsmark.h @@ -13,6 +13,8 @@ #define NETLINK_DSMARK_H_ #include +#include +#include #ifdef __cplusplus extern "C" { diff --git a/include/netlink/route/qdisc/fifo.h b/include/netlink/route/qdisc/fifo.h index c18dd79..c033427 100644 --- a/include/netlink/route/qdisc/fifo.h +++ b/include/netlink/route/qdisc/fifo.h @@ -13,6 +13,7 @@ #define NETLINK_FIFO_H_ #include +#include #ifdef __cplusplus extern "C" { diff --git a/include/netlink/route/qdisc/htb.h b/include/netlink/route/qdisc/htb.h index af0287d..c909f84 100644 --- a/include/netlink/route/qdisc/htb.h +++ b/include/netlink/route/qdisc/htb.h @@ -16,6 +16,8 @@ #include #include +#include +#include #ifdef __cplusplus extern "C" { diff --git a/include/netlink/route/qdisc/netem.h b/include/netlink/route/qdisc/netem.h index ce56ee7..4b071bf 100644 --- a/include/netlink/route/qdisc/netem.h +++ b/include/netlink/route/qdisc/netem.h @@ -13,6 +13,7 @@ #define NETLINK_NETEM_H_ #include +#include #ifdef __cplusplus extern "C" { diff --git a/include/netlink/route/qdisc/plug.h b/include/netlink/route/qdisc/plug.h index ffb1a04..40f7e53 100644 --- a/include/netlink/route/qdisc/plug.h +++ b/include/netlink/route/qdisc/plug.h @@ -13,6 +13,7 @@ #define NETLINK_PLUG_H_ #include +#include #ifdef __cplusplus extern "C" { diff --git a/include/netlink/route/qdisc/prio.h b/include/netlink/route/qdisc/prio.h index f6fdc86..636a8f9 100644 --- a/include/netlink/route/qdisc/prio.h +++ b/include/netlink/route/qdisc/prio.h @@ -13,6 +13,7 @@ #define NETLINK_PRIO_H_ #include +#include #ifdef __cplusplus extern "C" { diff --git a/include/netlink/route/qdisc/sfq.h b/include/netlink/route/qdisc/sfq.h index 7cc0b3e..77d2e29 100644 --- a/include/netlink/route/qdisc/sfq.h +++ b/include/netlink/route/qdisc/sfq.h @@ -13,6 +13,7 @@ #define NETLINK_SFQ_H_ #include +#include #ifdef __cplusplus extern "C" { diff --git a/include/netlink/route/qdisc/tbf.h b/include/netlink/route/qdisc/tbf.h index 8a2144a..ce31c54 100644 --- a/include/netlink/route/qdisc/tbf.h +++ b/include/netlink/route/qdisc/tbf.h @@ -14,6 +14,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { From 24d577c93dc0b3382d45ca8b29d3226e182e0669 Mon Sep 17 00:00:00 2001 From: Adrian Ban Date: Wed, 16 May 2012 13:43:52 +0200 Subject: [PATCH 176/432] u32: fix various u32 hashing related warnings I've add an missing u32 hash filter missing from u32.h I've fix all warnings in file test-complex-HTB-with-hash-filters.c --- include/netlink/route/cls/u32.h | 1 + tests/test-complex-HTB-with-hash-filters.c | 78 ++++++++++++---------- 2 files changed, 44 insertions(+), 35 deletions(-) diff --git a/include/netlink/route/cls/u32.h b/include/netlink/route/cls/u32.h index 2789b19..59bed33 100644 --- a/include/netlink/route/cls/u32.h +++ b/include/netlink/route/cls/u32.h @@ -24,6 +24,7 @@ extern void rtnl_u32_set_handle(struct rtnl_cls *, int, int, int); extern int rtnl_u32_set_classid(struct rtnl_cls *, uint32_t); extern int rtnl_u32_set_divisor(struct rtnl_cls *, uint32_t); extern int rtnl_u32_set_link(struct rtnl_cls *, uint32_t); +extern int rtnl_u32_set_hashtable(struct rtnl_cls *, uint32_t); extern int rtnl_u32_set_hashmask(struct rtnl_cls *, uint32_t, uint32_t); extern int rtnl_u32_set_cls_terminal(struct rtnl_cls *); diff --git a/tests/test-complex-HTB-with-hash-filters.c b/tests/test-complex-HTB-with-hash-filters.c index 585a549..48cf5e3 100644 --- a/tests/test-complex-HTB-with-hash-filters.c +++ b/tests/test-complex-HTB-with-hash-filters.c @@ -12,7 +12,11 @@ #include #include #include +#include +#include +#include #include +#include #include #include @@ -150,7 +154,7 @@ int u32_add_filter_on_ht(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint3 rtnl_tc_set_link(TC_CAST(cls), rtnlLink); - if (err = rtnl_tc_set_kind(TC_CAST(cls), "u32")) { + if ((err = rtnl_tc_set_kind(TC_CAST(cls), "u32"))) { printf("Can not set classifier as u32\n"); return 1; } @@ -168,7 +172,7 @@ int u32_add_filter_on_ht(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint3 rtnl_u32_set_cls_terminal(cls); - if (err = rtnl_cls_add(sock, cls, NLM_F_CREATE)) { + if ((err = rtnl_cls_add(sock, cls, NLM_F_CREATE))) { printf("Can not add classifier: %s\n", nl_geterror(err)); return -1; } @@ -202,7 +206,7 @@ int u32_add_filter_on_ht_with_hashmask(struct nl_sock *sock, struct rtnl_link *r rtnl_tc_set_link(TC_CAST(cls), rtnlLink); - if (err = rtnl_tc_set_kind(TC_CAST(cls), "u32")) { + if ((err = rtnl_tc_set_kind(TC_CAST(cls), "u32"))) { printf("Can not set classifier as u32\n"); return 1; } @@ -222,7 +226,7 @@ int u32_add_filter_on_ht_with_hashmask(struct nl_sock *sock, struct rtnl_link *r rtnl_u32_set_link(cls, htlink); - if (err = rtnl_cls_add(sock, cls, NLM_F_CREATE)) { + if ((err = rtnl_cls_add(sock, cls, NLM_F_CREATE))) { printf("Can not add classifier: %s\n", nl_geterror(err)); return -1; } @@ -248,7 +252,7 @@ int u32_add_ht(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t prio, rtnl_tc_set_link(TC_CAST(cls), rtnlLink); - if (err = rtnl_tc_set_kind(TC_CAST(cls), "u32")) { + if ((err = rtnl_tc_set_kind(TC_CAST(cls), "u32"))) { printf("Can not set classifier as u32\n"); return 1; } @@ -261,7 +265,7 @@ int u32_add_ht(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t prio, //printf("htid: 0x%X\n", htid); rtnl_u32_set_divisor(cls, divisor); - if (err = rtnl_cls_add(sock, cls, NLM_F_CREATE)) { + if ((err = rtnl_cls_add(sock, cls, NLM_F_CREATE))) { printf("Can not add classifier: %s\n", nl_geterror(err)); return -1; } @@ -297,7 +301,7 @@ int qdisc_add_HTB(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t def //printf("Add a new HTB qdisc\n"); rtnl_tc_set_handle(TC_CAST(qdisc), TC_HANDLE(1,0)); - if (err = rtnl_tc_set_kind(TC_CAST(qdisc), "htb") ){ + if ((err = rtnl_tc_set_kind(TC_CAST(qdisc), "htb"))) { printf("Can not allocate HTB\n"); return -1; } @@ -308,7 +312,7 @@ int qdisc_add_HTB(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t def rtnl_htb_set_rate2quantum(qdisc, 1); /* Submit request to kernel and wait for response */ - if (err = rtnl_qdisc_add(sock, qdisc, NLM_F_CREATE)) { + if ((err = rtnl_qdisc_add(sock, qdisc, NLM_F_CREATE))) { printf("Can not allocate HTB Qdisc\n"); return -1; } @@ -316,6 +320,7 @@ int qdisc_add_HTB(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t def /* Return the qdisc object to free memory resources */ rtnl_qdisc_put(qdisc); + return 0; } /* @@ -331,11 +336,11 @@ int class_add_HTB(struct nl_sock *sock, struct rtnl_link *rtnlLink, { int err; struct rtnl_class *class; + //struct rtnl_class *class = (struct rtnl_class *) tc; //create a HTB class - class = (struct rtnl_class *)rtnl_class_alloc(); - //class = rtnl_class_alloc(); - if (!class) { + //class = (struct rtnl_class *)rtnl_class_alloc(); + if (!(class = rtnl_class_alloc())) { printf("Can not allocate class object\n"); return 1; } @@ -346,13 +351,13 @@ int class_add_HTB(struct nl_sock *sock, struct rtnl_link *rtnlLink, rtnl_tc_set_parent(TC_CAST(class), TC_HANDLE(parentMaj, parentMin)); rtnl_tc_set_handle(TC_CAST(class), TC_HANDLE(childMaj, childMin)); - if (err = rtnl_tc_set_kind(TC_CAST(class), "htb") ){ + if ((err = rtnl_tc_set_kind(TC_CAST(class), "htb"))) { printf("Can not set HTB to class\n"); return 1; } //printf("set HTB class prio to %u\n", prio); - rtnl_htb_set_prio(class, prio); + rtnl_htb_set_prio((struct rtnl_class *)class, prio); if (rate) { //rate=rate/8; @@ -372,12 +377,12 @@ int class_add_HTB(struct nl_sock *sock, struct rtnl_link *rtnlLink, rtnl_htb_set_cbuffer(class, cburst); } /* Submit request to kernel and wait for response */ - if (err = rtnl_class_add(sock, class, NLM_F_CREATE)) { + if ((err = rtnl_class_add(sock, class, NLM_F_CREATE))) { printf("Can not allocate HTB Qdisc\n"); return 1; } rtnl_class_put(class); - + return 0; } /* @@ -405,7 +410,7 @@ int class_add_HTB_root(struct nl_sock *sock, struct rtnl_link *rtnlLink, //printf("Add a new HTB ROOT class\n"); rtnl_tc_set_handle(TC_CAST(class), 1); - if (err = rtnl_tc_set_kind(TC_CAST(class), "htb") ){ + if ((err = rtnl_tc_set_kind(TC_CAST(class), "htb"))) { printf("Can not set HTB to class\n"); return 1; } @@ -427,12 +432,12 @@ int class_add_HTB_root(struct nl_sock *sock, struct rtnl_link *rtnlLink, } /* Submit request to kernel and wait for response */ - if (err = rtnl_class_add(sock, class, NLM_F_CREATE)) { + if ((err = rtnl_class_add(sock, class, NLM_F_CREATE))) { printf("Can not allocate HTB Qdisc\n"); return 1; } rtnl_class_put(class); - + return 0; } /* @@ -455,7 +460,7 @@ int qdisc_add_SFQ_leaf(struct nl_sock *sock, struct rtnl_link *rtnlLink, rtnl_tc_set_handle(TC_CAST(qdisc), TC_HANDLE(parentMin,0)); - if (err = rtnl_tc_set_kind(TC_CAST(qdisc), "sfq") ){ + if ((err = rtnl_tc_set_kind(TC_CAST(qdisc), "sfq"))) { printf("Can not set SQF class\n"); return 1; } @@ -473,13 +478,14 @@ int qdisc_add_SFQ_leaf(struct nl_sock *sock, struct rtnl_link *rtnlLink, } /* Submit request to kernel and wait for response */ - if (err = rtnl_qdisc_add(sock, qdisc, NLM_F_CREATE)) { + if ((err = rtnl_qdisc_add(sock, qdisc, NLM_F_CREATE))) { printf("Can not allocate SFQ qdisc\n"); return -1; } /* Return the qdisc object to free memory resources */ rtnl_qdisc_put(qdisc); + return 0; } @@ -490,20 +496,21 @@ int main() { struct nl_sock *sock; struct rtnl_link *link; - struct rtnl_qdisc *qdisc; - struct rtnl_class *class; - struct rtnl_cls *cls; + //struct rtnl_qdisc *qdisc; + //struct rtnl_class *class; + //struct rtnl_cls *cls; - uint32_t ht, htlink, htid, handle, divisor, hash, nodeid, hashmask, direction, classid; - struct rtnl_u32 *f_u32; + uint32_t ht, htlink, htid, direction, classid; + //uint32_t hash, hashmask, nodeid, divisor, handle; + //struct rtnl_u32 *f_u32; char chashlink[16]=""; - uint64_t drops, qlen; + //uint64_t drops, qlen; - int master_index; + //int master_index; int err; - uint64_t rate=0, ceil=0; + //uint64_t rate=0, ceil=0; struct nl_cache *link_cache; @@ -527,7 +534,7 @@ int main() { } /* lookup interface index of eth0 */ - if (!(link = rtnl_link_get_by_name(link_cache, "eth0"))) { + if (!(link = rtnl_link_get_by_name(link_cache, "imq0"))) { /* error */ printf("Interface not found\n"); nl_socket_free(sock); @@ -580,13 +587,14 @@ int main() { * */ - divisor=0x0; // unused here - handle = 0x0; // unused here - hash = 0x0; // unused here - htid = 0x0; // unused here - nodeid = 0x0; // unused here - uint32_t hashlink; + //divisor=0x0; // unused here + //handle = 0x0; // unused here + //hash = 0x0; // unused here + //htid = 0x0; // unused here + //nodeid = 0x0; // unused here + // direction = 12 -> source IP + // direction = 16 -> destination IP direction = 16; /* From ca883b61bc88498309afb82be9c8fa071febc741 Mon Sep 17 00:00:00 2001 From: "Bushman, Jeff" Date: Wed, 16 May 2012 11:50:25 -0400 Subject: [PATCH 177/432] Fix for dumping objects to a buffer instead of file descriptor Attached is a patch to fix two problems with dumping objects to a buffer in= stead of a file descriptor. One was a problem in detecting the end of the buffer in the newline code. The other was a problem with clearing the whole buffer before printing each= object. --- lib/cache.c | 3 +++ lib/object.c | 3 +++ lib/utils.c | 8 +++----- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/cache.c b/lib/cache.c index 5cfae67..45a1a27 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -929,6 +929,9 @@ void nl_cache_dump_filter(struct nl_cache *cache, if (!ops->oo_dump[type]) return; + if (params->dp_buf) + memset(params->dp_buf, 0, params->dp_buflen); + nl_list_for_each_entry(obj, &cache->c_items, ce_list) { if (filter && !nl_object_match_filter(obj, filter)) continue; diff --git a/lib/object.c b/lib/object.c index 7606535..df1c963 100644 --- a/lib/object.c +++ b/lib/object.c @@ -259,6 +259,9 @@ int nl_object_is_marked(struct nl_object *obj) */ void nl_object_dump(struct nl_object *obj, struct nl_dump_params *params) { + if (params->dp_buf) + memset(params->dp_buf, 0, params->dp_buflen); + dump_from_ops(obj, params); } diff --git a/lib/utils.c b/lib/utils.c index 5a35a53..36b6292 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -824,7 +824,7 @@ void nl_new_line(struct nl_dump_params *params) else if (params->dp_buf) strncat(params->dp_buf, " ", params->dp_buflen - - sizeof(params->dp_buf) - 1); + strlen(params->dp_buf) - 1); } } @@ -844,7 +844,8 @@ static void dump_one(struct nl_dump_params *parms, const char *fmt, parms->dp_cb(parms, buf); else strncat(parms->dp_buf, buf, - parms->dp_buflen - strlen(parms->dp_buf) - 1); + parms->dp_buflen - + strlen(parms->dp_buf) - 1); free(buf); } } @@ -1053,9 +1054,6 @@ void dump_from_ops(struct nl_object *obj, struct nl_dump_params *params) params->dp_pre_dump = 1; } - if (params->dp_buf) - memset(params->dp_buf, 0, params->dp_buflen); - if (obj->ce_ops->oo_dump[type]) obj->ce_ops->oo_dump[type](obj, params); } From 9bb30a5e801fff2333d9b847be42294aa2e34e06 Mon Sep 17 00:00:00 2001 From: A C Date: Fri, 25 May 2012 13:45:45 -0600 Subject: [PATCH 178/432] add fwmark mask support The fw classifier allows a mask to be set, which is necessary for some complex shaping/firewall scenarios. The attached patch adds support for it to libnl. --- include/netlink-types.h | 1 + lib/route/cls/fw.c | 31 ++++++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/include/netlink-types.h b/include/netlink-types.h index 24228a7..2e80b05 100644 --- a/include/netlink-types.h +++ b/include/netlink-types.h @@ -512,6 +512,7 @@ struct rtnl_fw struct nl_data * cf_act; struct nl_data * cf_police; char cf_indev[IFNAMSIZ]; + uint32_t cf_fwmask; int cf_mask; }; diff --git a/lib/route/cls/fw.c b/lib/route/cls/fw.c index 11c9c67..d24779a 100644 --- a/lib/route/cls/fw.c +++ b/lib/route/cls/fw.c @@ -30,12 +30,14 @@ #define FW_ATTR_ACTION 0x002 #define FW_ATTR_POLICE 0x004 #define FW_ATTR_INDEV 0x008 +#define FW_ATTR_MASK 0x010 /** @endcond */ static struct nla_policy fw_policy[TCA_FW_MAX+1] = { [TCA_FW_CLASSID] = { .type = NLA_U32 }, [TCA_FW_INDEV] = { .type = NLA_STRING, .maxlen = IFNAMSIZ }, + [TCA_FW_MASK] = { .type = NLA_U32 }, }; static int fw_msg_parser(struct rtnl_tc *tc, void *data) @@ -72,6 +74,11 @@ static int fw_msg_parser(struct rtnl_tc *tc, void *data) f->cf_mask |= FW_ATTR_INDEV; } + if (tb[TCA_FW_MASK]) { + f->cf_fwmask = nla_get_u32(tb[TCA_FW_MASK]); + f->cf_mask |= FW_ATTR_MASK; + } + return 0; } @@ -101,12 +108,18 @@ static void fw_dump_line(struct rtnl_tc *tc, void *data, { struct rtnl_fw *f = data; - if (f && f->cf_mask & FW_ATTR_CLASSID) { + if (!f) + return; + + if (f->cf_mask & FW_ATTR_CLASSID) { char buf[32]; nl_dump(p, " target %s", rtnl_tc_handle2str(f->cf_classid, buf, sizeof(buf))); } + + if (f->cf_mask & FW_ATTR_MASK) + nl_dump(p, " mask 0x%x", f->cf_fwmask); } static void fw_dump_details(struct rtnl_tc *tc, void *data, @@ -137,6 +150,9 @@ static int fw_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) if (f->cf_mask & FW_ATTR_INDEV) NLA_PUT_STRING(msg, TCA_FW_INDEV, f->cf_indev); + if (f->cf_mask & FW_ATTR_MASK) + NLA_PUT_U32(msg, TCA_FW_MASK, f->cf_fwmask); + return 0; nla_put_failure: @@ -161,6 +177,19 @@ int rtnl_fw_set_classid(struct rtnl_cls *cls, uint32_t classid) return 0; } +int rtnl_fw_set_mask(struct rtnl_cls *cls, uint32_t mask) +{ + struct rtnl_fw *f; + + if (!(f = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + f->cf_fwmask = mask; + f->cf_mask |= FW_ATTR_MASK; + + return 0; +} + /** @} */ static struct rtnl_tc_ops fw_ops = { From 970f5d0221863b1473740455ca4d8cefcb34ff31 Mon Sep 17 00:00:00 2001 From: Andrew Collins Date: Fri, 25 May 2012 18:08:06 -0600 Subject: [PATCH 179/432] correct HTB rtable/HZ calculations The HTB implementation in libnl uses units of microseconds in a number of places where it seems TC is expecting time in units of ticks, which causes actual rates much higher than requested. Additionally, libnl uses USER_HZ for calculating buffer and cbuffer sizes, which can result in much larger buffers than necessary on systems with high resolution timers. Note that the TBF qdisc uses microseconds incorrectly in two spots as well, I fixed this but did not test. --- include/netlink/utils.h | 1 + lib/route/qdisc/htb.c | 12 ++++++------ lib/route/qdisc/tbf.c | 4 ++-- lib/route/tc.c | 2 +- lib/utils.c | 28 ++++++++++++++++++++-------- 5 files changed, 30 insertions(+), 17 deletions(-) diff --git a/include/netlink/utils.h b/include/netlink/utils.h index 4d7b969..502341a 100644 --- a/include/netlink/utils.h +++ b/include/netlink/utils.h @@ -56,6 +56,7 @@ extern long nl_prob2int(const char *); /* time translations */ extern int nl_get_user_hz(void); +extern int nl_get_psched_hz(void); extern uint32_t nl_us2ticks(uint32_t); extern uint32_t nl_ticks2us(uint32_t); extern int nl_str2msec(const char *, uint64_t *); diff --git a/lib/route/qdisc/htb.c b/lib/route/qdisc/htb.c index f1d0e75..4298580 100644 --- a/lib/route/qdisc/htb.c +++ b/lib/route/qdisc/htb.c @@ -86,9 +86,9 @@ static int htb_class_msg_parser(struct rtnl_tc *tc, void *data) htb->ch_prio = opts.prio; rtnl_copy_ratespec(&htb->ch_rate, &opts.rate); rtnl_copy_ratespec(&htb->ch_ceil, &opts.ceil); - htb->ch_rbuffer = rtnl_tc_calc_bufsize(opts.buffer, + htb->ch_rbuffer = rtnl_tc_calc_bufsize(nl_ticks2us(opts.buffer), opts.rate.rate); - htb->ch_cbuffer = rtnl_tc_calc_bufsize(opts.cbuffer, + htb->ch_cbuffer = rtnl_tc_calc_bufsize(nl_ticks2us(opts.cbuffer), opts.ceil.rate); htb->ch_quantum = opts.quantum; htb->ch_level = opts.level; @@ -242,16 +242,16 @@ static int htb_class_msg_fill(struct rtnl_tc *tc, void *data, if (htb->ch_mask & SCH_HTB_HAS_RBUFFER) buffer = htb->ch_rbuffer; else - buffer = opts.rate.rate / nl_get_user_hz() + mtu; /* XXX */ + buffer = opts.rate.rate / nl_get_psched_hz() + mtu; /* XXX */ - opts.buffer = rtnl_tc_calc_txtime(buffer, opts.rate.rate); + opts.buffer = nl_us2ticks(rtnl_tc_calc_txtime(buffer, opts.rate.rate)); if (htb->ch_mask & SCH_HTB_HAS_CBUFFER) cbuffer = htb->ch_cbuffer; else - cbuffer = opts.ceil.rate / nl_get_user_hz() + mtu; /* XXX */ + cbuffer = opts.ceil.rate / nl_get_psched_hz() + mtu; /* XXX */ - opts.cbuffer = rtnl_tc_calc_txtime(cbuffer, opts.ceil.rate); + opts.cbuffer = nl_us2ticks(rtnl_tc_calc_txtime(cbuffer, opts.ceil.rate)); if (htb->ch_mask & SCH_HTB_HAS_QUANTUM) opts.quantum = htb->ch_quantum; diff --git a/lib/route/qdisc/tbf.c b/lib/route/qdisc/tbf.c index 8a6c400..81bd84c 100644 --- a/lib/route/qdisc/tbf.c +++ b/lib/route/qdisc/tbf.c @@ -290,7 +290,7 @@ void rtnl_qdisc_tbf_set_rate(struct rtnl_qdisc *qdisc, int rate, int bucket, tbf->qt_rate.rs_rate = rate; tbf->qt_rate_bucket = bucket; tbf->qt_rate.rs_cell_log = cell_log; - tbf->qt_rate_txtime = rtnl_tc_calc_txtime(bucket, rate); + tbf->qt_rate_txtime = nl_us2ticks(rtnl_tc_calc_txtime(bucket, rate)); tbf->qt_mask |= TBF_ATTR_RATE; } @@ -372,7 +372,7 @@ int rtnl_qdisc_tbf_set_peakrate(struct rtnl_qdisc *qdisc, int rate, int bucket, tbf->qt_peakrate.rs_rate = rate; tbf->qt_peakrate_bucket = bucket; tbf->qt_peakrate.rs_cell_log = cell_log; - tbf->qt_peakrate_txtime = rtnl_tc_calc_txtime(bucket, rate); + tbf->qt_peakrate_txtime = nl_us2ticks(rtnl_tc_calc_txtime(bucket, rate)); tbf->qt_mask |= TBF_ATTR_PEAKRATE; diff --git a/lib/route/tc.c b/lib/route/tc.c index 6826a05..6c72c15 100644 --- a/lib/route/tc.c +++ b/lib/route/tc.c @@ -710,7 +710,7 @@ int rtnl_tc_build_rate_table(struct rtnl_tc *tc, struct rtnl_ratespec *spec, for (i = 0; i < RTNL_TC_RTABLE_SIZE; i++) { size = adjust_size((i + 1) << cell_log, spec->rs_mpu, linktype); - dst[i] = rtnl_tc_calc_txtime(size, spec->rs_rate); + dst[i] = nl_us2ticks(rtnl_tc_calc_txtime(size, spec->rs_rate)); } spec->rs_cell_align = -1; diff --git a/lib/utils.c b/lib/utils.c index 36b6292..efb2cf4 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -359,12 +359,13 @@ long nl_prob2int(const char *str) * @{ */ -#ifdef USER_HZ -static uint32_t user_hz = USER_HZ; -#else -static uint32_t user_hz = 100; +#ifndef USER_HZ +#define USER_HZ 100 #endif +static uint32_t user_hz = USER_HZ; +static uint32_t psched_hz = USER_HZ; + static double ticks_per_usec = 1.0f; /* Retrieves the configured HZ and ticks/us value in the kernel. @@ -394,6 +395,8 @@ static void __init get_psched_settings(void) if (!got_hz) user_hz = sysconf(_SC_CLK_TCK); + psched_hz = user_hz; + if (getenv("TICKS_PER_USEC")) { double t = strtod(getenv("TICKS_PER_USEC"), NULL); ticks_per_usec = t; @@ -408,14 +411,16 @@ static void __init get_psched_settings(void) strncpy(name, "/proc/net/psched", sizeof(name) - 1); if ((fd = fopen(name, "r"))) { - uint32_t ns_per_usec, ns_per_tick; - /* the file contains 4 hexadecimals, but we just use - the first two of them */ - fscanf(fd, "%08x %08x", &ns_per_usec, &ns_per_tick); + uint32_t ns_per_usec, ns_per_tick, nom, denom; + + fscanf(fd, "%08x %08x %08x %08x", + &ns_per_usec, &ns_per_tick, &nom, &denom); ticks_per_usec = (double) ns_per_usec / (double) ns_per_tick; + if (nom == 1000000) + psched_hz = denom; fclose(fd); } @@ -431,6 +436,13 @@ int nl_get_user_hz(void) return user_hz; } +/** + * Return the value of packet scheduler HZ + */ +int nl_get_psched_hz(void) +{ + return psched_hz; +} /** * Convert micro seconds to ticks From d733f8a0a65a817d16ebaa1a8f5ad1330682b489 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 28 May 2012 14:05:27 +0200 Subject: [PATCH 180/432] use MSG_TRUNC flag to get recv message size at once prevent multiple calls of recvmsg. Signed-off-by: Jiri Pirko --- lib/nl.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/nl.c b/lib/nl.c index 64e1382..b572a1a 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -435,7 +435,7 @@ int nl_recv(struct nl_sock *sk, struct sockaddr_nl *nla, memset(nla, 0, sizeof(*nla)); if (sk->s_flags & NL_MSG_PEEK) - flags |= MSG_PEEK; + flags |= MSG_PEEK | MSG_TRUNC; if (page_size == 0) page_size = getpagesize(); @@ -466,17 +466,18 @@ retry: } } - if (iov.iov_len < n || - msg.msg_flags & MSG_TRUNC) { - /* Provided buffer is not long enough, enlarge it - * and try again. */ - iov.iov_len *= 2; - iov.iov_base = *buf = realloc(*buf, iov.iov_len); - goto retry; - } else if (msg.msg_flags & MSG_CTRUNC) { + if (msg.msg_flags & MSG_CTRUNC) { msg.msg_controllen *= 2; msg.msg_control = realloc(msg.msg_control, msg.msg_controllen); goto retry; + } else if (iov.iov_len < n || msg.msg_flags & MSG_TRUNC) { + /* Provided buffer is not long enough, enlarge it + * to size of n (which should be total length of the message) + * and try again. */ + iov.iov_len = n; + iov.iov_base = *buf = realloc(*buf, iov.iov_len); + flags = 0; + goto retry; } else if (flags != 0) { /* Buffer is big enough, do the actual reading */ flags = 0; From 0b70de5155ba74f152ebece230659e7890cccbd9 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 31 May 2012 13:11:48 +0200 Subject: [PATCH 181/432] genl: updates to API reference documentation --- include/netlink/genl/ctrl.h | 2 +- include/netlink/genl/family.h | 24 ++- include/netlink/genl/genl.h | 4 +- include/netlink/genl/mngt.h | 93 ++++++++++-- lib/genl/ctrl.c | 129 +++++++++++----- lib/genl/family.c | 102 ++++++++++++- lib/genl/genl.c | 279 ++++++++++++++++++++-------------- lib/genl/mngt.c | 118 +++++--------- 8 files changed, 486 insertions(+), 265 deletions(-) diff --git a/include/netlink/genl/ctrl.h b/include/netlink/genl/ctrl.h index 26a0a99..017b8fd 100644 --- a/include/netlink/genl/ctrl.h +++ b/include/netlink/genl/ctrl.h @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ #ifndef NETLINK_GENL_CTRL_H_ diff --git a/include/netlink/genl/family.h b/include/netlink/genl/family.h index 721dc13..5432b59 100644 --- a/include/netlink/genl/family.h +++ b/include/netlink/genl/family.h @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2006 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ #ifndef NETLINK_GENL_FAMILY_H_ @@ -25,25 +25,19 @@ extern struct genl_family * genl_family_alloc(void); extern void genl_family_put(struct genl_family *); extern unsigned int genl_family_get_id(struct genl_family *); -extern void genl_family_set_id(struct genl_family *, - unsigned int); +extern void genl_family_set_id(struct genl_family *, unsigned int); extern char * genl_family_get_name(struct genl_family *); -extern void genl_family_set_name(struct genl_family *, - const char *name); +extern void genl_family_set_name(struct genl_family *, const char *); extern uint8_t genl_family_get_version(struct genl_family *); -extern void genl_family_set_version(struct genl_family *, - uint8_t); +extern void genl_family_set_version(struct genl_family *, uint8_t); extern uint32_t genl_family_get_hdrsize(struct genl_family *); -extern void genl_family_set_hdrsize(struct genl_family *, - uint32_t); +extern void genl_family_set_hdrsize(struct genl_family *, uint32_t); extern uint32_t genl_family_get_maxattr(struct genl_family *); -extern void genl_family_set_maxattr(struct genl_family *, - uint32_t); +extern void genl_family_set_maxattr(struct genl_family *, uint32_t); -extern int genl_family_add_op(struct genl_family *, - int, int); -extern int genl_family_add_grp(struct genl_family *, - uint32_t , const char *); +extern int genl_family_add_op(struct genl_family *, int, int); +extern int genl_family_add_grp(struct genl_family *, uint32_t , + const char *); #ifdef __cplusplus diff --git a/include/netlink/genl/genl.h b/include/netlink/genl/genl.h index 364a471..a2da943 100644 --- a/include/netlink/genl/genl.h +++ b/include/netlink/genl/genl.h @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ #ifndef NETLINK_GENL_H_ @@ -32,6 +32,8 @@ extern int genlmsg_validate(struct nlmsghdr *, int, int, struct nla_policy *); extern int genlmsg_parse(struct nlmsghdr *, int, struct nlattr **, int, struct nla_policy *); +extern struct genlmsghdr * + genlmsg_hdr(struct nlmsghdr *); extern void * genlmsg_data(const struct genlmsghdr *); extern int genlmsg_len(const struct genlmsghdr *); extern struct nlattr * genlmsg_attrdata(const struct genlmsghdr *, int); diff --git a/include/netlink/genl/mngt.h b/include/netlink/genl/mngt.h index 8b0244f..18d3866 100644 --- a/include/netlink/genl/mngt.h +++ b/include/netlink/genl/mngt.h @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2006 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ #ifndef NETLINK_GENL_MNGT_H_ @@ -22,57 +22,124 @@ extern "C" { struct nl_cache_ops; +/** + * @ingroup genl_mngt + * @struct genl_info netlink/genl/mngt.h + * + * Informative structure passed on to message parser callbacks + * + * This structure is passed on to all message parser callbacks and contains + * information about the sender of the message as well as pointers to all + * relevant sections of the parsed message. + * + * @see genl_cmd::c_msg_parser + */ struct genl_info { + /** Socket address of sender */ struct sockaddr_nl * who; + + /** Pointer to Netlink message header */ struct nlmsghdr * nlh; + + /** Pointer to Generic Netlink message header */ struct genlmsghdr * genlhdr; + + /** Pointer to user header */ void * userhdr; + + /** Pointer to array of parsed attributes */ struct nlattr ** attrs; }; /** * @ingroup genl_mngt - * Generic Netlink Command + * @struct genl_cmd netlink/genl/mngt.h + * + * Definition of a Generic Netlink command. + * + * This structure is used to define the list of available commands on the + * receiving side. + * + * @par Example: + * @code + * static struct genl_cmd foo_cmds[] = { + * { + * .c_id = FOO_CMD_NEW, + * .c_name = "NEWFOO" , + * .c_maxattr = FOO_ATTR_MAX, + * .c_attr_policy = foo_policy, + * .c_msg_parser = foo_msg_parser, + * }, + * { + * .c_id = FOO_CMD_DEL, + * .c_name = "DELFOO" , + * }, + * }; + * + * static struct genl_ops my_genl_ops = { + * [...] + * .o_cmds = foo_cmds, + * .o_ncmds = ARRAY_SIZE(foo_cmds), + * }; + * @endcode */ struct genl_cmd { - /** Unique command identifier */ + /** Numeric command identifier (required) */ int c_id; - /** Name/description of command */ + /** Human readable name (required) */ char * c_name; - /** - * Maximum attribute identifier, must be provided if - * a message parser is available. - */ + /** Maximum attribute identifier that the command is prepared to handle. */ int c_maxattr; + /** Called whenever a message for this command is received */ int (*c_msg_parser)(struct nl_cache_ops *, struct genl_cmd *, struct genl_info *, void *); - /** - * Attribute validation policy (optional) - */ + /** Attribute validation policy, enforced before the callback is called */ struct nla_policy * c_attr_policy; }; /** * @ingroup genl_mngt - * Generic Netlink Operations + * @struct genl_ops netlink/genl/mngt.h + * + * Definition of a Generic Netlink family + * + * @see genl_cmd */ struct genl_ops { int o_family; + + /** Numeric identifier, automatically resolved by genl_mngt_resolve() */ int o_id; + + /** Human readable name, used to resolve to numeric identifier */ char * o_name; + + /** + * If registered via genl_register(), will point to the related + * cache operations. + */ struct nl_cache_ops * o_cache_ops; + + /** + * Can point to an array of generic netlink commands definitions. + */ struct genl_cmd * o_cmds; + + /** Size of \c o_cmds array */ int o_ncmds; - /* linked list of all genl cache operations */ + /** + * @private + * Used internally to link together all registered operations. + */ struct nl_list_head o_list; }; diff --git a/lib/genl/ctrl.c b/lib/genl/ctrl.c index 107a4fa..ddb7603 100644 --- a/lib/genl/ctrl.c +++ b/lib/genl/ctrl.c @@ -6,14 +6,18 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ /** - * @ingroup genl_mngt - * @defgroup ctrl Controller - * @brief + * @ingroup genl + * @defgroup genl_ctrl Controller (Resolver) * + * Resolves Generic Netlink family names to numeric identifiers. + * + * The controller is a component in the kernel that resolves Generic Netlink + * family names to their numeric identifiers. This module provides functions + * to query the controller to access the resolving functionality. * @{ */ @@ -29,7 +33,6 @@ #define CTRL_VERSION 0x0001 static struct nl_cache_ops genl_ctrl_ops; -/** @endcond */ static int ctrl_request_update(struct nl_cache *c, struct nl_sock *h) { @@ -173,27 +176,51 @@ errout: return err; } +/** @endcond */ + /** - * @name Cache Management + * @name Controller Cache + * + * The controller cache allows to keep a local copy of the list of all + * kernel side registered Generic Netlink families to quickly resolve + * multiple Generic Netlink family names without requiring to communicate + * with the kernel for each resolving iteration. + * * @{ */ -int genl_ctrl_alloc_cache(struct nl_sock *sock, struct nl_cache **result) +/** + * Allocate a new controller cache + * @arg sk Generic Netlink socket + * @arg result Pointer to store resulting cache + * + * Allocates a new cache mirroring the state of the controller and stores it + * in \c *result. The allocated cache will contain a list of all currently + * registered kernel side Generic Netlink families. The cache is meant to be + * used to resolve family names locally. + * + * @return 0 on success or a negative error code. + */ +int genl_ctrl_alloc_cache(struct nl_sock *sk, struct nl_cache **result) { - return nl_cache_alloc_and_fill(&genl_ctrl_ops, sock, result); + return nl_cache_alloc_and_fill(&genl_ctrl_ops, sk, result); } /** - * Look up generic netlink family by id in the provided cache. - * @arg cache Generic netlink family cache. - * @arg id Family identifier. + * Search controller cache for a numeric address match + * @arg cache Controller cache + * @arg id Numeric family identifier. * - * Searches through the cache looking for a registered family - * matching the specified identifier. The caller will own a - * reference on the returned object which needs to be given - * back after usage using genl_family_put(). + * Searches a previously allocated controller cache and looks for an entry + * that matches the specified numeric family identifier \c id. If a match + * is found successfully, the reference count of the matching object is + * increased by one before the objet is returned. * - * @return Generic netlink family object or NULL if no match was found. + * @see genl_ctrl_alloc_cache() + * @see genl_ctrl_search_by_name() + * @see genl_family_put() + * + * @return Generic Netlink family object or NULL if no match was found. */ struct genl_family *genl_ctrl_search(struct nl_cache *cache, int id) { @@ -213,24 +240,23 @@ struct genl_family *genl_ctrl_search(struct nl_cache *cache, int id) } /** - * @name Resolver - * @{ - */ - -/** - * Look up generic netlink family by family name in the provided cache. - * @arg cache Generic netlink family cache. - * @arg name Family name. + * Search controller cache for a family name match + * @arg cache Controller cache + * @arg name Name of Generic Netlink family * - * Searches through the cache looking for a registered family - * matching the specified name. The caller will own a reference - * on the returned object which needs to be given back after - * usage using genl_family_put(). + * Searches a previously allocated controller cache and looks for an entry + * that matches the specified family \c name. If a match is found successfully, + * the reference count of the matching object is increased by one before the + * objet is returned. * - * @return Generic netlink family object or NULL if no match was found. + * @see genl_ctrl_alloc_cache() + * @see genl_ctrl_search() + * @see genl_family_put() + * + * @return Generic Netlink family object or NULL if no match was found. */ struct genl_family *genl_ctrl_search_by_name(struct nl_cache *cache, - const char *name) + const char *name) { struct genl_family *fam; @@ -250,14 +276,26 @@ struct genl_family *genl_ctrl_search_by_name(struct nl_cache *cache, /** @} */ /** - * Resolve generic netlink family name to its identifier - * @arg sk Netlink socket. - * @arg name Name of generic netlink family + * @name Direct Resolvers * - * Resolves the generic netlink family name to its identifer and returns - * it. + * These functions communicate directly with the kernel and do not require + * a cache to be kept up to date. * - * @return A positive identifier or a negative error code. + * @{ + */ + +/** + * Resolve Generic Netlink family name to numeric identifier + * @arg sk Generic Netlink socket. + * @arg name Name of Generic Netlink family + * + * Resolves the Generic Netlink family name to the corresponding numeric + * family identifier. This function queries the kernel directly, use + * genl_ctrl_search_by_name() if you need to resolve multiple names. + * + * @see genl_ctrl_search_by_name() + * + * @return The numeric family identifier or a negative error code. */ int genl_ctrl_resolve(struct nl_sock *sk, const char *name) { @@ -283,7 +321,7 @@ errout: } static int genl_ctrl_grp_by_name(const struct genl_family *family, - const char *grp_name) + const char *grp_name) { struct genl_family_grp *grp; @@ -296,8 +334,19 @@ static int genl_ctrl_grp_by_name(const struct genl_family *family, return -NLE_OBJ_NOTFOUND; } +/** + * Resolve Generic Netlink family group name + * @arg sk Generic Netlink socket + * @arg family_name Name of Generic Netlink family + * @arg grp_name Name of group to resolve + * + * Looks up the family object and resolves the group name to the numeric + * group identifier. + * + * @return Numeric group identifier or a negative error code. + */ int genl_ctrl_resolve_grp(struct nl_sock *sk, const char *family_name, - const char *grp_name) + const char *grp_name) { struct nl_cache *cache; struct genl_family *family; @@ -322,6 +371,7 @@ errout: /** @} */ +/** @cond SKIP */ static struct genl_cmd genl_cmds[] = { { .c_id = CTRL_CMD_NEWFAMILY, @@ -353,9 +403,7 @@ static struct genl_ops genl_ops = { .o_ncmds = ARRAY_SIZE(genl_cmds), }; -/** @cond SKIP */ extern struct nl_object_ops genl_family_ops; -/** @endcond */ static struct nl_cache_ops genl_ctrl_ops = { .co_name = "genl/family", @@ -376,5 +424,6 @@ static void __exit ctrl_exit(void) { genl_unregister(&genl_ctrl_ops); } +/** @endcond */ /** @} */ diff --git a/lib/genl/family.c b/lib/genl/family.c index ebeebcb..64b98cd 100644 --- a/lib/genl/family.c +++ b/lib/genl/family.c @@ -6,13 +6,14 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2006 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ /** - * @ingroup genl - * @defgroup genl_family Generic Netlink Family - * @brief + * @ingroup genl_ctrl + * @defgroup genl_family Generic Netlink Family Object + * + * Object representing a kernel side registered Generic Netlink family * * @{ */ @@ -32,7 +33,6 @@ #define FAMILY_ATTR_OPS 0x20 struct nl_object_ops genl_family_ops; -/** @endcond */ static void family_constructor(struct nl_object *c) { @@ -166,18 +166,32 @@ static int family_compare(struct nl_object *_a, struct nl_object *_b, return diff; } - +/** @endcond */ /** - * @name Family Object + * @name Object Allocation * @{ */ +/** + * Allocate new Generic Netlink family object + * + * @return Newly allocated Generic Netlink family object or NULL. + */ struct genl_family *genl_family_alloc(void) { return (struct genl_family *) nl_object_alloc(&genl_family_ops); } +/** + * Release reference on Generic Netlink family object + * @arg family Generic Netlink family object + * + * Reduces the reference counter of a Generic Netlink family object by one. + * The object is freed after the last user has returned its reference. + * + * @see nl_object_put() + */ void genl_family_put(struct genl_family *family) { nl_object_put((struct nl_object *) family); @@ -186,10 +200,16 @@ void genl_family_put(struct genl_family *family) /** @} */ /** - * @name Attributes + * @name Numeric Identifier * @{ */ +/** + * Return numeric identifier + * @arg family Generic Netlink family object + * + * @return Numeric identifier or 0 if not available. + */ unsigned int genl_family_get_id(struct genl_family *family) { if (family->ce_mask & FAMILY_ATTR_ID) @@ -198,12 +218,30 @@ unsigned int genl_family_get_id(struct genl_family *family) return GENL_ID_GENERATE; } +/** + * Set the numeric identifier + * @arg family Generic Netlink family object + * @arg id New numeric identifier + */ void genl_family_set_id(struct genl_family *family, unsigned int id) { family->gf_id = id; family->ce_mask |= FAMILY_ATTR_ID; } +/** @} */ + +/** + * @name Human Readable Name + * @{ + */ + +/** + * Return human readable name + * @arg family Generic Netlink family object + * + * @return Name of family or NULL if not available + */ char *genl_family_get_name(struct genl_family *family) { if (family->ce_mask & FAMILY_ATTR_NAME) @@ -212,12 +250,28 @@ char *genl_family_get_name(struct genl_family *family) return NULL; } +/** + * Set human readable name + * @arg family Generic Netlink family object + * @arg name New human readable name + */ void genl_family_set_name(struct genl_family *family, const char *name) { strncpy(family->gf_name, name, GENL_NAMSIZ-1); family->ce_mask |= FAMILY_ATTR_NAME; } +/** + * @name Interface Version + * @{ + */ + +/** + * Return interface version + * @arg family Generic Netlink family object + * + * @return Interface version or 0 if not available. + */ uint8_t genl_family_get_version(struct genl_family *family) { if (family->ce_mask & FAMILY_ATTR_VERSION) @@ -226,12 +280,30 @@ uint8_t genl_family_get_version(struct genl_family *family) return 0; } +/** + * Set interface version + * @arg family Generic Netlink family object + * @arg version New interface version + */ void genl_family_set_version(struct genl_family *family, uint8_t version) { family->gf_version = version; family->ce_mask |= FAMILY_ATTR_VERSION; } +/** @} */ + +/** + * @name Header Size + * @{ + */ + +/** + * Return user header size expected by kernel component + * @arg family Generic Netlink family object + * + * @return Expected header length or 0 if not available. + */ uint32_t genl_family_get_hdrsize(struct genl_family *family) { if (family->ce_mask & FAMILY_ATTR_HDRSIZE) @@ -246,6 +318,13 @@ void genl_family_set_hdrsize(struct genl_family *family, uint32_t hdrsize) family->ce_mask |= FAMILY_ATTR_HDRSIZE; } +/** @} */ + +/** + * @name Maximum Expected Attribute + * @{ + */ + uint32_t genl_family_get_maxattr(struct genl_family *family) { if (family->ce_mask & FAMILY_ATTR_MAXATTR) @@ -260,6 +339,13 @@ void genl_family_set_maxattr(struct genl_family *family, uint32_t maxattr) family->ce_mask |= FAMILY_ATTR_MAXATTR; } +/** @} */ + +/** + * @name Operations + * @{ + */ + int genl_family_add_op(struct genl_family *family, int id, int flags) { struct genl_family_op *op; diff --git a/lib/genl/genl.c b/lib/genl/genl.c index 6e6a764..efe1996 100644 --- a/lib/genl/genl.c +++ b/lib/genl/genl.c @@ -12,80 +12,6 @@ /** * @defgroup genl Generic Netlink Library (libnl-genl) * - * @par Message Format - * @code - * <------- NLMSG_ALIGN(hlen) ------> <---- NLMSG_ALIGN(len) ---> - * +----------------------------+- - -+- - - - - - - - - - -+- - -+ - * | Header | Pad | Payload | Pad | - * | struct nlmsghdr | | | | - * +----------------------------+- - -+- - - - - - - - - - -+- - -+ - * @endcode - * @code - * <-------- GENL_HDRLEN -------> <--- hdrlen --> - * <------- genlmsg_len(ghdr) ------> - * +------------------------+- - -+---------------+- - -+------------+ - * | Generic Netlink Header | Pad | Family Header | Pad | Attributes | - * | struct genlmsghdr | | | | | - * +------------------------+- - -+---------------+- - -+------------+ - * genlmsg_data(ghdr)--------------^ ^ - * genlmsg_attrdata(ghdr, hdrlen)------------------------- - * @endcode - * - * @par Example - * @code - * #include - * #include - * #include - * - * struct nl_sock *sock; - * struct nl_msg *msg; - * int family; - * - * // Allocate a new netlink socket - * sock = nl_socket_alloc(); - * - * // Connect to generic netlink socket on kernel side - * genl_connect(sock); - * - * // Ask kernel to resolve family name to family id - * family = genl_ctrl_resolve(sock, "generic_netlink_family_name"); - * - * // Construct a generic netlink by allocating a new message, fill in - * // the header and append a simple integer attribute. - * msg = nlmsg_alloc(); - * genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_ECHO, - * CMD_FOO_GET, FOO_VERSION); - * nla_put_u32(msg, ATTR_FOO, 123); - * - * // Send message over netlink socket - * nl_send_auto_complete(sock, msg); - * - * // Free message - * nlmsg_free(msg); - * - * // Prepare socket to receive the answer by specifying the callback - * // function to be called for valid messages. - * nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, parse_cb, NULL); - * - * // Wait for the answer and receive it - * nl_recvmsgs_default(sock); - * - * static int parse_cb(struct nl_msg *msg, void *arg) - * { - * struct nlmsghdr *nlh = nlmsg_hdr(msg); - * struct nlattr *attrs[ATTR_MAX+1]; - * - * // Validate message and parse attributes - * genlmsg_parse(nlh, 0, attrs, ATTR_MAX, policy); - * - * if (attrs[ATTR_FOO]) { - * uint32_t value = nla_get_u32(attrs[ATTR_FOO]); - * ... - * } - * - * return 0; - * } - * @endcode * @{ */ @@ -95,10 +21,27 @@ #include /** - * @name Socket Creating + * @name Generic Netlink Socket * @{ */ +/** + * Connect a Generic Netlink socket + * @arg sk Unconnected Netlink socket + * + * This function expects a struct nl_socket object previously allocated via + * nl_socket_alloc(). It calls nl_connect() to create the local socket file + * descriptor and binds the socket to the \c NETLINK_GENERIC Netlink protocol. + * + * Using this function is equivalent to: + * @code + * nl_connect(sk, NETLINK_GENERIC); + * @endcode + * + * @see nl_connect() + * + * @return 0 on success or a negative error code. + */ int genl_connect(struct nl_sock *sk) { return nl_connect(sk, NETLINK_GENERIC); @@ -107,20 +50,34 @@ int genl_connect(struct nl_sock *sk) /** @} */ /** - * @name Sending + * @name Sending Data * @{ */ /** - * Send trivial generic netlink message - * @arg sk Netlink socket. - * @arg family Generic netlink family - * @arg cmd Command - * @arg version Version - * @arg flags Additional netlink message flags. + * Send a Generic Netlink message consisting only of a header + * @arg sk Generic Netlink socket + * @arg family Numeric family identifier + * @arg cmd Numeric command identifier + * @arg version Interface version + * @arg flags Additional Netlink message flags (optional) * - * Fills out a routing netlink request message and sends it out - * using nl_send_simple(). + * This function is a shortcut for sending a Generic Netlink message without + * any message payload. The message will only consist of the Netlink and + * Generic Netlink headers. The header is constructed based on the specified + * parameters and passed on to nl_send_simple() to send it on the specified + * socket. + * + * @par Example: + * @code + * #include + * #include + * + * err = genl_send_simple(sk, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, CTRL_VERSION, + * NLM_F_DUMP); + * @endcode + * + * @see nl_send_simple() * * @return 0 on success or a negative error code. */ @@ -137,12 +94,26 @@ int genl_send_simple(struct nl_sock *sk, int family, int cmd, /** @} */ - /** * @name Message Parsing * @{ */ +/** + * Validate Generic Netlink message headers + * @arg nlh Pointer to Netlink message header + * @arg hdrlen Length of user header + * + * Verifies the integrity of the Netlink and Generic Netlink headers by + * enforcing the following requirements: + * - Valid Netlink message header (nlmsg_valid_hdr()) + * - Presence of a complete Generic Netlink header + * - At least \c hdrlen bytes of payload included after the generic + * netlink header. + * + * @return A positive integer (true) if the headers are valid or + * 0 (false) if not. + */ int genlmsg_valid_hdr(struct nlmsghdr *nlh, int hdrlen) { struct genlmsghdr *ghdr; @@ -157,8 +128,28 @@ int genlmsg_valid_hdr(struct nlmsghdr *nlh, int hdrlen) return 1; } +/** + * Validate Generic Netlink message including attributes + * @arg nlh Pointer to Netlink message header + * @arg hdrlen Length of user header + * @arg maxtype Maximum attribtue id expected + * @arg policy Attribute validation policy + * + * Verifies the validity of the Netlink and Generic Netlink headers using + * genlmsg_valid_hdr() and calls nla_validate() on the message payload to + * verify the integrity of eventual attributes. + * + * @note You may call genlmsg_parse() directly to perform validation and + * parsing in a single step. + * + * @see genlmsg_valid_hdr() + * @see nla_validate() + * @see genlmsg_parse() + * + * @return 0 on success or a negative error code. + */ int genlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype, - struct nla_policy *policy) + struct nla_policy *policy) { struct genlmsghdr *ghdr; @@ -170,6 +161,33 @@ int genlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype, genlmsg_attrlen(ghdr, hdrlen), maxtype, policy); } +/** + * Parse Generic Netlink message including attributes + * @arg nlh Pointer to Netlink message header + * @arg hdrlen Length of user header + * @arg tb Array to store parsed attributes + * @arg maxtype Maximum attribute id expected + * @arg policy Attribute validation policy + * + * Verifies the validity of the Netlink and Generic Netlink headers using + * genlmsg_valid_hdr() and calls nla_parse() on the message payload to + * parse eventual attributes. + * + * @par Example: + * @code + * struct nlattr *attrs[MY_TYPE_MAX+1]; + * + * if ((err = genlsmg_parse(nlmsg_nlh(msg), sizeof(struct my_hdr), attrs, + * MY_TYPE_MAX, attr_policy)) < 0) + * // ERROR + * @endcode + * + * @see genlmsg_valid_hdr() + * @see genlmsg_validate() + * @see nla_parse() + * + * @return 0 on success or a negative error code. + */ int genlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], int maxtype, struct nla_policy *policy) { @@ -184,29 +202,44 @@ int genlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], } /** - * Get head of message payload - * @arg gnlh genetlink messsage header + * Return pointer to message payload + * @arg gnlh Generic Netlink message header + * + * Calculates the pointer to the message payload based on the pointer + * to the generic netlink message header. + * + * @note Depending on whether your own message format uses a header, the + * returned pointer may in fact point to the user header. + * + * @return Pointer to generic netlink message */ void *genlmsg_data(const struct genlmsghdr *gnlh) { return ((unsigned char *) gnlh + GENL_HDRLEN); } + /** - * Get lenght of message payload - * @arg gnlh genetlink message header + * Return length of message payload + * @arg gnlh Generic Netlink message header + * + * @return Length of user payload including an eventual user header in + * number of bytes. */ int genlmsg_len(const struct genlmsghdr *gnlh) { - struct nlmsghdr *nlh = (struct nlmsghdr *)((unsigned char *)gnlh - - NLMSG_HDRLEN); + struct nlmsghdr *nlh; + + nlh = (struct nlmsghdr *)((unsigned char *) gnlh - NLMSG_HDRLEN); return (nlh->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN); } /** - * Get head of attribute data - * @arg gnlh generic netlink message header - * @arg hdrlen length of family specific header + * Return pointer to message attributes + * @arg gnlh Generic Netlink message header + * @arg hdrlen Length of user header + * + * @return Pointer to the start of the message's attributes section. */ struct nlattr *genlmsg_attrdata(const struct genlmsghdr *gnlh, int hdrlen) { @@ -214,9 +247,12 @@ struct nlattr *genlmsg_attrdata(const struct genlmsghdr *gnlh, int hdrlen) } /** - * Get length of attribute data - * @arg gnlh generic netlink message header - * @arg hdrlen length of family specific header + * Return length of message attributes + * @arg gnlh Generic Netlink message header + * @arg hdrlen Length of user header + * + * @return Length of the message section containing attributes in number + * of bytes. */ int genlmsg_attrlen(const struct genlmsghdr *gnlh, int hdrlen) { @@ -226,24 +262,45 @@ int genlmsg_attrlen(const struct genlmsghdr *gnlh, int hdrlen) /** @} */ /** - * @name Message Building + * @name Message Construction * @{ */ /** - * Add generic netlink header to netlink message - * @arg msg netlink message - * @arg pid netlink process id or NL_AUTO_PID - * @arg seq sequence number of message or NL_AUTO_SEQ - * @arg family generic netlink family - * @arg hdrlen length of user specific header - * @arg flags message flags - * @arg cmd generic netlink command - * @arg version protocol version + * Add Generic Netlink headers to Netlink message + * @arg msg Netlink message object + * @arg port Netlink port or NL_AUTO_PORT + * @arg seq Sequence number of message or NL_AUTO_SEQ + * @arg family Numeric family identifier + * @arg hdrlen Length of user header + * @arg flags Additional Netlink message flags (optional) + * @arg cmd Numeric command identifier + * @arg version Interface version * - * Returns pointer to user specific header. + * Calls nlmsg_put() on the specified message object to reserve space for + * the Netlink header, the Generic Netlink header, and a user header of + * specified length. Fills out the header fields with the specified + * parameters. + * + * @par Example: + * @code + * struct nl_msg *msg; + * struct my_hdr *user_hdr; + * + * if (!(msg = nlmsg_alloc())) + * // ERROR + * + * user_hdr = genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, family_id, + * sizeof(struct my_hdr), 0, MY_CMD_FOO, 0); + * if (!user_hdr) + * // ERROR + * @endcode + * + * @see nlmsg_put() + * + * Returns Pointer to user header or NULL if an error occurred. */ -void *genlmsg_put(struct nl_msg *msg, uint32_t pid, uint32_t seq, int family, +void *genlmsg_put(struct nl_msg *msg, uint32_t port, uint32_t seq, int family, int hdrlen, int flags, uint8_t cmd, uint8_t version) { struct nlmsghdr *nlh; @@ -252,7 +309,7 @@ void *genlmsg_put(struct nl_msg *msg, uint32_t pid, uint32_t seq, int family, .version = version, }; - nlh = nlmsg_put(msg, pid, seq, family, GENL_HDRLEN + hdrlen, flags); + nlh = nlmsg_put(msg, port, seq, family, GENL_HDRLEN + hdrlen, flags); if (nlh == NULL) return NULL; diff --git a/lib/genl/mngt.c b/lib/genl/mngt.c index 963d497..fd1aa03 100644 --- a/lib/genl/mngt.c +++ b/lib/genl/mngt.c @@ -6,77 +6,15 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ /** * @ingroup genl - * @defgroup genl_mngt Management + * @defgroup genl_mngt Family and Operations Management * - * @par 1) Registering a generic netlink module - * @code - * #include + * Registering Generic Netlink Families and Commands * - * // First step is to define all the commands being used in - * // particular generic netlink family. The ID and name are - * // mandatory to be filled out. A callback function and - * // most the attribute policy that comes with it must be - * // defined for commands expected to be issued towards - * // userspace. - * static struct genl_cmd foo_cmds[] = { - * { - * .c_id = FOO_CMD_NEW, - * .c_name = "NEWFOO" , - * .c_maxattr = FOO_ATTR_MAX, - * .c_attr_policy = foo_policy, - * .c_msg_parser = foo_msg_parser, - * }, - * { - * .c_id = FOO_CMD_DEL, - * .c_name = "DELFOO" , - * }, - * }; - * - * // The list of commands must then be integrated into a - * // struct genl_ops serving as handle for this particular - * // family. - * static struct genl_ops my_genl_ops = { - * .o_cmds = foo_cmds, - * .o_ncmds = ARRAY_SIZE(foo_cmds), - * }; - * - * // Using the above struct genl_ops an arbitary number of - * // cache handles can be associated to it. - * // - * // The macro GENL_HDRSIZE() must be used to specify the - * // length of the header to automatically take headers on - * // generic layers into account. - * // - * // The macro GENL_FAMILY() is used to represent the generic - * // netlink family id. - * static struct nl_cache_ops genl_foo_ops = { - * .co_name = "genl/foo", - * .co_hdrsize = GENL_HDRSIZE(sizeof(struct my_hdr)), - * .co_msgtypes = GENL_FAMILY(GENL_ID_GENERATE, "foo"), - * .co_genl = &my_genl_ops, - * .co_protocol = NETLINK_GENERIC, - * .co_request_update = foo_request_update, - * .co_obj_ops = &genl_foo_ops, - * }; - * - * // Finally each cache handle for a generic netlink family - * // must be registered using genl_register(). - * static void __init foo_init(void) - * { - * genl_register(&genl_foo_ops); - * } - * - * // ... respectively unregsted again. - * static void __exit foo_exit(void) - * { - * genl_unregister(&genl_foo_ops); - * } - * @endcode * @{ */ @@ -88,6 +26,8 @@ #include #include +/** @cond SKIP */ + static NL_LIST_HEAD(genl_ops_list); static int genl_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, @@ -159,15 +99,18 @@ char *genl_op2name(int family, int op, char *buf, size_t len) return NULL; } +/** @endcond */ /** - * @name Register/Unregister + * @name Registration (Cache Based) * @{ */ /** - * Register generic netlink operations - * @arg ops cache operations + * Register Generic Netlink family backed cache + * @arg ops Cache operations definition + * + * @return 0 on success or a negative error code. */ int genl_register(struct nl_cache_ops *ops) { @@ -203,8 +146,8 @@ errout: } /** - * Unregister generic netlink operations - * @arg ops cache operations + * Unregister cache based Generic Netlink family + * @arg ops Cache operations definition */ void genl_unregister(struct nl_cache_ops *ops) { @@ -217,11 +160,7 @@ void genl_unregister(struct nl_cache_ops *ops) /** @} */ -/** - * @name Resolving ID/Name - * @{ - */ - +/** @cond SKIP */ static int __genl_ops_resolve(struct nl_cache *ctrl, struct genl_ops *ops) { struct genl_family *family; @@ -236,7 +175,22 @@ static int __genl_ops_resolve(struct nl_cache *ctrl, struct genl_ops *ops) return -NLE_OBJ_NOTFOUND; } +/** @endcond */ +/** + * @name Resolving the name of registered families + * @{ + */ + +/** + * Resolve a single Generic Netlink family + * @arg sk Generic Netlink socket + * @arg ops Generic Netlink family definition + * + * Resolves the family name to its numeric identifier. + * + * @return 0 on success or a negative error code. + */ int genl_ops_resolve(struct nl_sock *sk, struct genl_ops *ops) { struct nl_cache *ctrl; @@ -252,6 +206,19 @@ errout: return err; } +/** + * Resolve all registered Generic Netlink families + * @arg sk Generic Netlink socket + * + * Walks through all local Generic Netlink families that have been registered + * using genl_register() and resolves the name of each family to the + * corresponding numeric identifier. + * + * @see genl_register() + * @see genl_ops_resolve() + * + * @return 0 on success or a negative error code. + */ int genl_mngt_resolve(struct nl_sock *sk) { struct nl_cache *ctrl; @@ -272,5 +239,4 @@ errout: /** @} */ - /** @} */ From 71b442b955075d61abe157724541a967811f6bbe Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 31 May 2012 13:13:50 +0200 Subject: [PATCH 182/432] genl: Add genlmsg_hdr() Explicit function to calculate the genl hdr based on nlh --- lib/genl/genl.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/genl/genl.c b/lib/genl/genl.c index efe1996..8f2e496 100644 --- a/lib/genl/genl.c +++ b/lib/genl/genl.c @@ -201,6 +201,17 @@ int genlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], genlmsg_attrlen(ghdr, hdrlen), policy); } +/** + * Return pointer to Generic Netlink header + * @arg nlh Netlink message header + * + * @return Pointer to Generic Netlink message header + */ +struct genlmsghdr *genlmsg_hdr(struct nlmsghdr *nlh) +{ + return nlmsg_data(nlh); +} + /** * Return pointer to message payload * @arg gnlh Generic Netlink message header From 3656b6f908f966f329fb727a805ee46934c360d0 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 31 May 2012 13:37:57 +0200 Subject: [PATCH 183/432] genl: Add genlmsg_user_hdr(), genlmsg_user_data(), and genlmsg_user_datalen() These functions deprecate the function genlmsg_data() which did not allow to specify the length of the user header. Use of the new API will make code much clearer. The old function is still kept around for backwards compatibility but marked deprecated in the API reference. --- include/netlink/genl/genl.h | 4 ++ lib/genl/genl.c | 95 +++++++++++++++++++++++++++++-------- lib/genl/mngt.c | 2 +- 3 files changed, 80 insertions(+), 21 deletions(-) diff --git a/include/netlink/genl/genl.h b/include/netlink/genl/genl.h index a2da943..e455581 100644 --- a/include/netlink/genl/genl.h +++ b/include/netlink/genl/genl.h @@ -35,6 +35,10 @@ extern int genlmsg_parse(struct nlmsghdr *, int, struct nlattr **, extern struct genlmsghdr * genlmsg_hdr(struct nlmsghdr *); extern void * genlmsg_data(const struct genlmsghdr *); +extern void * genlmsg_user_hdr(const struct genlmsghdr *); +extern void * genlmsg_user_data(const struct genlmsghdr *, const int); +extern int genlmsg_user_datalen(const struct genlmsghdr *, + const int); extern int genlmsg_len(const struct genlmsghdr *); extern struct nlattr * genlmsg_attrdata(const struct genlmsghdr *, int); extern int genlmsg_attrlen(const struct genlmsghdr *, int); diff --git a/lib/genl/genl.c b/lib/genl/genl.c index 8f2e496..569ef9e 100644 --- a/lib/genl/genl.c +++ b/lib/genl/genl.c @@ -213,26 +213,10 @@ struct genlmsghdr *genlmsg_hdr(struct nlmsghdr *nlh) } /** - * Return pointer to message payload + * Return length of message payload including user header * @arg gnlh Generic Netlink message header * - * Calculates the pointer to the message payload based on the pointer - * to the generic netlink message header. - * - * @note Depending on whether your own message format uses a header, the - * returned pointer may in fact point to the user header. - * - * @return Pointer to generic netlink message - */ -void *genlmsg_data(const struct genlmsghdr *gnlh) -{ - return ((unsigned char *) gnlh + GENL_HDRLEN); -} - - -/** - * Return length of message payload - * @arg gnlh Generic Netlink message header + * @see genlmsg_data() * * @return Length of user payload including an eventual user header in * number of bytes. @@ -240,21 +224,69 @@ void *genlmsg_data(const struct genlmsghdr *gnlh) int genlmsg_len(const struct genlmsghdr *gnlh) { struct nlmsghdr *nlh; - + nlh = (struct nlmsghdr *)((unsigned char *) gnlh - NLMSG_HDRLEN); return (nlh->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN); } + +/** + * Return pointer to user header + * @arg gnlh Generic Netlink message header + * + * Calculates the pointer to the user header based on the pointer to + * the Generic Netlink message header. + * + * @return Pointer to the user header + */ +void *genlmsg_user_hdr(const struct genlmsghdr *gnlh) +{ + return genlmsg_data(gnlh); +} + +/** + * Return pointer to user data + * @arg gnlh Generic netlink message header + * @arg hdrlen Length of user header + * + * Calculates the pointer to the user data based on the pointer to + * the Generic Netlink message header. + * + * @see genlmsg_user_datalen() + * + * @return Pointer to the user data + */ +void *genlmsg_user_data(const struct genlmsghdr *gnlh, const int hdrlen) +{ + return genlmsg_user_hdr(gnlh) + NLMSG_ALIGN(hdrlen); +} + +/** + * Return length of user data + * @arg gnlh Generic Netlink message header + * @arg hdrlen Length of user header + * + * @see genlmsg_user_data() + * + * @return Length of user data in bytes + */ +int genlmsg_user_datalen(const struct genlmsghdr *gnlh, const int hdrlen) +{ + return genlmsg_len(gnlh) - NLMSG_ALIGN(hdrlen); +} + /** * Return pointer to message attributes * @arg gnlh Generic Netlink message header * @arg hdrlen Length of user header * + * @see genlmsg_attrlen() + * * @return Pointer to the start of the message's attributes section. */ struct nlattr *genlmsg_attrdata(const struct genlmsghdr *gnlh, int hdrlen) { - return genlmsg_data(gnlh) + NLMSG_ALIGN(hdrlen); + return genlmsg_user_data(gnlh, hdrlen); } /** @@ -262,6 +294,8 @@ struct nlattr *genlmsg_attrdata(const struct genlmsghdr *gnlh, int hdrlen) * @arg gnlh Generic Netlink message header * @arg hdrlen Length of user header * + * @see genlmsg_attrdata() + * * @return Length of the message section containing attributes in number * of bytes. */ @@ -333,4 +367,25 @@ void *genlmsg_put(struct nl_msg *msg, uint32_t port, uint32_t seq, int family, /** @} */ +/** + * @name Deprecated + * @{ + */ + +/** + * Return pointer to message payload + * @arg gnlh Generic Netlink message header + * + * @deprecated This function has been deprecated due to inability to specify + * the length of the user header. Use genlmsg_user_hdr() + * respectively genlmsg_user_data(). + * + * @return Pointer to payload section + */ +void *genlmsg_data(const struct genlmsghdr *gnlh) +{ + return ((unsigned char *) gnlh + GENL_HDRLEN); +} + +/** @} */ /** @} */ diff --git a/lib/genl/mngt.c b/lib/genl/mngt.c index fd1aa03..f53aa8a 100644 --- a/lib/genl/mngt.c +++ b/lib/genl/mngt.c @@ -60,7 +60,7 @@ found: .who = who, .nlh = nlh, .genlhdr = ghdr, - .userhdr = genlmsg_data(ghdr), + .userhdr = genlmsg_user_hdr(ghdr), .attrs = tb, }; From faef2fa45f67da810415f4dd4f0ce62d70965ad4 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 1 Jun 2012 11:48:08 +0200 Subject: [PATCH 184/432] genl: Support registration of families without depending on caches Introduces the functions genl_register_family() and genl_unregister_family() to register a Generic Netlink family which does not implement a cachable type. API users can direct received messages into genl_handle_msg() which will validate the messages and call the callback functions defined in the commands definition. See test/test-genl.c for an example on how to use it. --- include/netlink/genl/mngt.h | 33 ++++-- lib/genl/mngt.c | 193 ++++++++++++++++++++++++++++++------ src/nl-list-caches.c | 4 +- tests/test-genl.c | 87 +++++++++++++++- 4 files changed, 271 insertions(+), 46 deletions(-) diff --git a/include/netlink/genl/mngt.h b/include/netlink/genl/mngt.h index 18d3866..01cbdb5 100644 --- a/include/netlink/genl/mngt.h +++ b/include/netlink/genl/mngt.h @@ -110,16 +110,34 @@ struct genl_cmd * * Definition of a Generic Netlink family * + * @par Example: + * @code + * static struct genl_cmd foo_cmds[] = { + * [...] + * }; + * + * static struct genl_ops my_genl_ops = { + * .o_name = "foo", + * .o_hdrsize = sizeof(struct my_hdr), + * .o_cmds = foo_cmds, + * .o_ncmds = ARRAY_SIZE(foo_cmds), + * }; + * + * if ((err = genl_register_family(&my_genl_ops)) < 0) + * // ERROR + * @endcode + * * @see genl_cmd */ struct genl_ops { - int o_family; + /** Length of user header */ + unsigned int o_hdrsize; - /** Numeric identifier, automatically resolved by genl_mngt_resolve() */ + /** Numeric identifier, automatically filled in by genl_ops_resolve() */ int o_id; - /** Human readable name, used to resolve to numeric identifier */ + /** Human readable name, used by genl_ops_resolve() to resolve numeric id */ char * o_name; /** @@ -128,12 +146,10 @@ struct genl_ops */ struct nl_cache_ops * o_cache_ops; - /** - * Can point to an array of generic netlink commands definitions. - */ + /** Optional array defining the available Generic Netlink commands */ struct genl_cmd * o_cmds; - /** Size of \c o_cmds array */ + /** Number of elements in \c o_cmds array */ int o_ncmds; /** @@ -143,6 +159,9 @@ struct genl_ops struct nl_list_head o_list; }; +extern int genl_register_family(struct genl_ops *); +extern int genl_unregister_family(struct genl_ops *); +extern int genl_handle_msg(struct nl_msg *, void *); extern int genl_register(struct nl_cache_ops *); extern void genl_unregister(struct nl_cache_ops *); diff --git a/lib/genl/mngt.c b/lib/genl/mngt.c index f53aa8a..ad25172 100644 --- a/lib/genl/mngt.c +++ b/lib/genl/mngt.c @@ -11,7 +11,7 @@ /** * @ingroup genl - * @defgroup genl_mngt Family and Operations Management + * @defgroup genl_mngt Family and Command Registration * * Registering Generic Netlink Families and Commands * @@ -30,28 +30,34 @@ static NL_LIST_HEAD(genl_ops_list); -static int genl_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, - struct nlmsghdr *nlh, struct nl_parser_param *pp) +static struct genl_cmd *lookup_cmd(struct genl_ops *ops, int cmd_id) { - int i, err; + struct genl_cmd *cmd; + int i; + + for (i = 0; i < ops->o_ncmds; i++) { + cmd = &ops->o_cmds[i]; + if (cmd->c_id == cmd_id) + return cmd; + } + + return NULL; +} + +static int cmd_msg_parser(struct sockaddr_nl *who, struct nlmsghdr *nlh, + struct genl_ops *ops, struct nl_cache_ops *cache_ops, void *arg) +{ + int err; struct genlmsghdr *ghdr; struct genl_cmd *cmd; - ghdr = nlmsg_data(nlh); + ghdr = genlmsg_hdr(nlh); - if (ops->co_genl == NULL) - BUG(); - - for (i = 0; i < ops->co_genl->o_ncmds; i++) { - cmd = &ops->co_genl->o_cmds[i]; - if (cmd->c_id == ghdr->cmd) - goto found; + if (!(cmd = lookup_cmd(ops, ghdr->cmd))) { + err = -NLE_MSGTYPE_NOSUPPORT; + goto errout; } - err = -NLE_MSGTYPE_NOSUPPORT; - goto errout; - -found: if (cmd->c_msg_parser == NULL) err = -NLE_OPNOTSUPP; else { @@ -64,33 +70,64 @@ found: .attrs = tb, }; - err = nlmsg_parse(nlh, ops->co_hdrsize, tb, cmd->c_maxattr, + err = nlmsg_parse(nlh, GENL_HDRSIZE(ops->o_hdrsize), tb, cmd->c_maxattr, cmd->c_attr_policy); if (err < 0) goto errout; - err = cmd->c_msg_parser(ops, cmd, &info, pp); + err = cmd->c_msg_parser(cache_ops, cmd, &info, arg); } errout: return err; } +static int genl_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, + struct nlmsghdr *nlh, struct nl_parser_param *pp) +{ + if (ops->co_genl == NULL) + BUG(); + + return cmd_msg_parser(who, nlh, ops->co_genl, ops, pp); +} + +static struct genl_ops *lookup_family(int family) +{ + struct genl_ops *ops; + + nl_list_for_each_entry(ops, &genl_ops_list, o_list) { + if (ops->o_id == family) + return ops; + } + + return NULL; +} + +static struct genl_ops *lookup_family_by_name(const char *name) +{ + struct genl_ops *ops; + + nl_list_for_each_entry(ops, &genl_ops_list, o_list) { + if (!strcmp(ops->o_name, name)) + return ops; + } + + return NULL; +} + char *genl_op2name(int family, int op, char *buf, size_t len) { struct genl_ops *ops; int i; - nl_list_for_each_entry(ops, &genl_ops_list, o_list) { - if (ops->o_family == family) { - for (i = 0; i < ops->o_ncmds; i++) { - struct genl_cmd *cmd; - cmd = &ops->o_cmds[i]; + if ((ops = lookup_family(family))) { + for (i = 0; i < ops->o_ncmds; i++) { + struct genl_cmd *cmd; + cmd = &ops->o_cmds[i]; - if (cmd->c_id == op) { - strncpy(buf, cmd->c_name, len - 1); - return buf; - } + if (cmd->c_id == op) { + strncpy(buf, cmd->c_name, len - 1); + return buf; } } } @@ -102,7 +139,90 @@ char *genl_op2name(int family, int op, char *buf, size_t len) /** @endcond */ /** - * @name Registration (Cache Based) + * @name Registration + * @{ + */ + +/** + * Register Generic Netlink family and associated commands + * @arg ops Generic Netlink family definition + * + * Registers the specified Generic Netlink family definition together with + * all associated commands. After registration, received Generic Netlink + * messages can be passed to genl_handle_msg() which will validate the + * messages, look for a matching command and call the respective callback + * function automatically. + * + * @note Consider using genl_register() if the family is used to implement a + * cacheable type. + * + * @see genl_unregister_family(); + * @see genl_register(); + * + * @return 0 on success or a negative error code. + */ +int genl_register_family(struct genl_ops *ops) +{ + if (!ops->o_name) + return -NLE_INVAL; + + if (ops->o_cmds && ops->o_ncmds <= 0) + return -NLE_INVAL; + + if (ops->o_id && lookup_family(ops->o_id)) + return -NLE_EXIST; + + if (lookup_family_by_name(ops->o_name)) + return -NLE_EXIST; + + nl_list_add_tail(&ops->o_list, &genl_ops_list); + + return 0; +} + +/** + * Unregister Generic Netlink family + * @arg ops Generic Netlink family definition + * + * Unregisters a family and all associated commands that were previously + * registered using genl_register_family(). + * + * @see genl_register_family() + * + * @return 0 on success or a negative error code. + */ +int genl_unregister_family(struct genl_ops *ops) +{ + nl_list_del(&ops->o_list); + + return 0; +} + +/** + * Run a received message through the demultiplexer + * @arg msg Generic Netlink message + * @arg arg Argument passed on to the message handler callback + * + * @return 0 on success or a negative error code. + */ +int genl_handle_msg(struct nl_msg *msg, void *arg) +{ + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct genl_ops *ops; + + if (!genlmsg_valid_hdr(nlh, 0)) + return -NLE_INVAL; + + if (!(ops = lookup_family(nlh->nlmsg_type))) + return -NLE_MSGTYPE_NOSUPPORT; + + return cmd_msg_parser(nlmsg_get_src(msg), nlh, ops, NULL, arg); +} + +/** @} */ + +/** + * @name Registration of Cache Operations * @{ */ @@ -110,6 +230,12 @@ char *genl_op2name(int family, int op, char *buf, size_t len) * Register Generic Netlink family backed cache * @arg ops Cache operations definition * + * Same as genl_register_family() but additionally registers the specified + * cache operations using nl_cache_mngt_register() and associates it with + * the Generic Netlink family. + * + * @see genl_register_family() + * * @return 0 on success or a negative error code. */ int genl_register(struct nl_cache_ops *ops) @@ -132,13 +258,13 @@ int genl_register(struct nl_cache_ops *ops) } ops->co_genl->o_cache_ops = ops; + ops->co_genl->o_hdrsize = ops->co_hdrsize - GENL_HDRLEN; ops->co_genl->o_name = ops->co_msgtypes[0].mt_name; - ops->co_genl->o_family = ops->co_msgtypes[0].mt_id; + ops->co_genl->o_id = ops->co_msgtypes[0].mt_id; ops->co_msg_parser = genl_msg_parser; - /* FIXME: check for dup */ - - nl_list_add_tail(&ops->co_genl->o_list, &genl_ops_list); + if ((err = genl_register_family(ops->co_genl)) < 0) + goto errout; err = nl_cache_mngt_register(ops); errout: @@ -155,7 +281,8 @@ void genl_unregister(struct nl_cache_ops *ops) return; nl_cache_mngt_unregister(ops); - nl_list_del(&ops->co_genl->o_list); + + genl_unregister_family(ops->co_genl); } /** @} */ diff --git a/src/nl-list-caches.c b/src/nl-list-caches.c index 3c35dd5..14cbab1 100644 --- a/src/nl-list-caches.c +++ b/src/nl-list-caches.c @@ -81,9 +81,9 @@ static void print(struct nl_cache_ops *ops, void *arg) printf(" genl:\n" \ " name: %s\n" \ - " family: %d\n" \ + " user-hdr: %d\n" \ " id: %d\n", - genl_ops->o_name, genl_ops->o_family, genl_ops->o_id); + genl_ops->o_name, genl_ops->o_hdrsize, genl_ops->o_id); if (genl_ops->o_ncmds) { int i; diff --git a/tests/test-genl.c b/tests/test-genl.c index 2706a92..63862b3 100644 --- a/tests/test-genl.c +++ b/tests/test-genl.c @@ -1,4 +1,72 @@ #include +#include + +static struct nla_policy attr_policy[TASKSTATS_TYPE_MAX+1] = { + [TASKSTATS_TYPE_PID] = { .type = NLA_U32 }, + [TASKSTATS_TYPE_TGID] = { .type = NLA_U32 }, + [TASKSTATS_TYPE_STATS] = { .minlen = sizeof(struct taskstats) }, + [TASKSTATS_TYPE_AGGR_PID] = { .type = NLA_NESTED }, + [TASKSTATS_TYPE_AGGR_TGID] = { .type = NLA_NESTED }, +}; + + +static int parse_cmd_new(struct nl_cache_ops *unused, struct genl_cmd *cmd, + struct genl_info *info, void *arg) +{ + struct nlattr *attrs[TASKSTATS_TYPE_MAX+1]; + struct nlattr *nested; + int err; + + if (info->attrs[TASKSTATS_TYPE_AGGR_PID]) + nested = info->attrs[TASKSTATS_TYPE_AGGR_PID]; + else if (info->attrs[TASKSTATS_TYPE_AGGR_TGID]) + nested = info->attrs[TASKSTATS_TYPE_AGGR_TGID]; + else { + fprintf(stderr, "Invalid taskstats message: Unable to find " + "nested attribute/\n"); + return NL_SKIP; + } + + err = nla_parse_nested(attrs, TASKSTATS_TYPE_MAX, nested, attr_policy); + if (err < 0) { + nl_perror(err, "Error while parsing generic netlink message"); + return err; + } + + + if (attrs[TASKSTATS_TYPE_STATS]) { + struct taskstats *stats = nla_data(attrs[TASKSTATS_TYPE_STATS]); + + printf("%s pid %u uid %u gid %u parent %u\n", + stats->ac_comm, stats->ac_pid, stats->ac_uid, + stats->ac_gid, stats->ac_ppid); + } + + return 0; +} + +static int parse_cb(struct nl_msg *msg, void *arg) +{ + return genl_handle_msg(msg, NULL); +} + +static struct genl_cmd cmds[] = { + { + .c_id = TASKSTATS_CMD_NEW, + .c_name = "taskstats_new()", + .c_maxattr = TASKSTATS_TYPE_MAX, + .c_attr_policy = attr_policy, + .c_msg_parser = &parse_cmd_new, + }, +}; + +#define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0])) + +static struct genl_ops ops = { + .o_name = TASKSTATS_GENL_NAME, + .o_cmds = cmds, + .o_ncmds = ARRAY_SIZE(cmds), +}; int main(int argc, char *argv[]) { @@ -10,25 +78,36 @@ int main(int argc, char *argv[]) sock = nl_cli_alloc_socket(); nl_cli_connect(sock, NETLINK_GENERIC); + if ((err = genl_register_family(&ops)) < 0) + nl_cli_fatal(err, "Unable to register Generic Netlink family"); + + if ((err = genl_ops_resolve(sock, &ops)) < 0) + nl_cli_fatal(err, "Unable to resolve family name"); + msg = nlmsg_alloc(); if (msg == NULL) nl_cli_fatal(NLE_NOMEM, "Unable to allocate netlink message"); - hdr = genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, GENL_ID_CTRL, - 0, 0, CTRL_CMD_GETFAMILY, 1); + hdr = genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, ops.o_id, + 0, 0, TASKSTATS_CMD_GET, TASKSTATS_GENL_VERSION); if (hdr == NULL) nl_cli_fatal(ENOMEM, "Unable to write genl header"); - if ((err = nla_put_u32(msg, CTRL_ATTR_FAMILY_ID, GENL_ID_CTRL)) < 0) + if ((err = nla_put_u32(msg, TASKSTATS_CMD_ATTR_PID, 1)) < 0) nl_cli_fatal(err, "Unable to add attribute: %s", nl_geterror(err)); if ((err = nl_send_auto_complete(sock, msg)) < 0) nl_cli_fatal(err, "Unable to send message: %s", nl_geterror(err)); + nlmsg_free(msg); + + if ((err = nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, + parse_cb, NULL)) < 0) + nl_cli_fatal(err, "Unable to modify valid message callback"); + if ((err = nl_recvmsgs_default(sock)) < 0) nl_cli_fatal(err, "Unable to receive message: %s", nl_geterror(err)); - nlmsg_free(msg); nl_close(sock); nl_socket_free(sock); From 8fad2e31942dd1063fd171b0f9596841225c25ff Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 1 Jun 2012 11:51:43 +0200 Subject: [PATCH 185/432] genl: Export genl_ops_resolve() and genl_mngt_resolve() in header These have been public but have not been declared in a header yet. --- include/netlink/genl/mngt.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/netlink/genl/mngt.h b/include/netlink/genl/mngt.h index 01cbdb5..8a51ccd 100644 --- a/include/netlink/genl/mngt.h +++ b/include/netlink/genl/mngt.h @@ -166,6 +166,9 @@ extern int genl_handle_msg(struct nl_msg *, void *); extern int genl_register(struct nl_cache_ops *); extern void genl_unregister(struct nl_cache_ops *); +extern int genl_ops_resolve(struct nl_sock *, struct genl_ops *); +extern int genl_mngt_resolve(struct nl_sock *); + #ifdef __cplusplus } #endif From 43eab4696dc1ce3002238147e2aa099f3a0f7e3a Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 1 Jun 2012 13:10:03 +0200 Subject: [PATCH 186/432] genl: Update genl-ctrl-list(8) --- man/genl-ctrl-list.8 | 61 +++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/man/genl-ctrl-list.8 b/man/genl-ctrl-list.8 index a8aa3f9..6132475 100644 --- a/man/genl-ctrl-list.8 +++ b/man/genl-ctrl-list.8 @@ -1,13 +1,13 @@ .TH genl\-ctrl-list 8 "20 April 2012" "libnl" .SH NAME -genl\-ctrl\-list \- List available kernel-side generic netlink families +genl\-ctrl\-list \- List available kernel-side Generic Netlink families .SH SYNOPSIS .B genl\-ctrl\-list [-d] .SH DESCRIPTION .PP -Queries the generic netlink controller in kernel and prints a list of all -registered generic netlink families including the version of the interface +Queries the Generic Netlink controller in kernel and prints a list of all +registered Generic Netlink families including the version of the interface that has been registered. .SH OPTIONS @@ -19,28 +19,53 @@ Print help text to console and exit. Print versioning information to console and exit. .TP .BR \-\^d " or " \-\-details -Include additional detailed information for each generic netlink +Include additional detailed information for each Generic Netlink family that is printed. The information includes: + .RS -.IP \(bu -The size of the family specific netlink message header (hdrsize). -.IP \(bu -The maximum netlink attribute identifier allowed by the interface -(maxattr). -.IP \(bu -A list of registered generic netlink operations prefixed with op -including their name (if available), identifier and the flags -indicating the availability of a doit or dump function. -.IP \(bu -A list of registered multicast groups prefixed with grp including -their name (if available) and identifier. +.TP +.B hdrsize N +The size of the user specific header. + +.TP +.B maxattr N +The maximum Netlink attribute identifier expected by the interface. + +.TP +.B op NAME (ID) +A list of available operations including their name, numeric identifier +and the flags indicating the capabilities of the opertion. + +Available flags: +.RS +.TP +.I admin-perm +Requires administrative privileges + +.TP +.I has-doit +Command can handle request + +.TP +.I has-dump +Command can handle a dump request + +.TP +.I has-policy +Command enforces attribute validation policy +.RE + +.TP +.B grp NAME (ID) +A list of registered multicast groups including name (if available) +and identifier. .RE .RS -Example: - +.B Example: +.RS 0x0010 nlctrl version 2 .RS 0 hdrsize 0 maxattr 7 From 0c408aad1fc564b53d6382f1076019a7694adff4 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Fri, 1 Jun 2012 12:59:24 -0400 Subject: [PATCH 187/432] genl: modify genl_ctrl_resolve and friends to allow for module auto-loading Generic netlink has the ability to autoload modules in response to a request for a family. Currently libnl uses a GETFAMILY call with the NLM_F_DUMP flag to list all the available families, but doing so neglects the possibility of an autoloaded module. This patch modifies the genl code to probe the kernel for a specific family rather than dumping a list of all the currenlty available ones, making autoload work properly. Signed-off-by: Neil Horman CC: Thomas Graf --- lib/genl/ctrl.c | 190 +++++++++++++++++++++++++++++++++++----------- tests/test-genl.c | 3 + 2 files changed, 148 insertions(+), 45 deletions(-) diff --git a/lib/genl/ctrl.c b/lib/genl/ctrl.c index ddb7603..3902f09 100644 --- a/lib/genl/ctrl.c +++ b/lib/genl/ctrl.c @@ -61,6 +61,47 @@ static struct nla_policy family_grp_policy[CTRL_ATTR_MCAST_GRP_MAX+1] = { [CTRL_ATTR_MCAST_GRP_ID] = { .type = NLA_U32 }, }; +static int parse_mcast_grps(struct genl_family *family, struct nlattr *grp_attr) +{ + struct nlattr *nla; + int remaining, err; + + if (!grp_attr) + BUG(); + + nla_for_each_nested(nla, grp_attr, remaining) { + struct nlattr *tb[CTRL_ATTR_MCAST_GRP_MAX+1]; + int id; + const char * name; + + err = nla_parse_nested(tb, CTRL_ATTR_MCAST_GRP_MAX, nla, + family_grp_policy); + if (err < 0) + goto errout; + + if (tb[CTRL_ATTR_MCAST_GRP_ID] == NULL) { + err = -NLE_MISSING_ATTR; + goto errout; + } + id = nla_get_u32(tb[CTRL_ATTR_MCAST_GRP_ID]); + + if (tb[CTRL_ATTR_MCAST_GRP_NAME] == NULL) { + err = -NLE_MISSING_ATTR; + goto errout; + } + name = nla_get_string(tb[CTRL_ATTR_MCAST_GRP_NAME]); + + err = genl_family_add_grp(family, id, name); + if (err < 0) + goto errout; + } + + err = 0; + +errout: + return err; +} + static int ctrl_msg_parser(struct nl_cache_ops *ops, struct genl_cmd *cmd, struct genl_info *info, void *arg) { @@ -137,37 +178,9 @@ static int ctrl_msg_parser(struct nl_cache_ops *ops, struct genl_cmd *cmd, } if (info->attrs[CTRL_ATTR_MCAST_GROUPS]) { - struct nlattr *nla, *nla_grps; - int remaining; - - nla_grps = info->attrs[CTRL_ATTR_MCAST_GROUPS]; - nla_for_each_nested(nla, nla_grps, remaining) { - struct nlattr *tb[CTRL_ATTR_MCAST_GRP_MAX+1]; - int id; - const char * name; - - err = nla_parse_nested(tb, CTRL_ATTR_MCAST_GRP_MAX, nla, - family_grp_policy); - if (err < 0) - goto errout; - - if (tb[CTRL_ATTR_MCAST_GRP_ID] == NULL) { - err = -NLE_MISSING_ATTR; - goto errout; - } - id = nla_get_u32(tb[CTRL_ATTR_MCAST_GRP_ID]); - - if (tb[CTRL_ATTR_MCAST_GRP_NAME] == NULL) { - err = -NLE_MISSING_ATTR; - goto errout; - } - name = nla_get_string(tb[CTRL_ATTR_MCAST_GRP_NAME]); - - err = genl_family_add_grp(family, id, name); - if (err < 0) - goto errout; - } - + err = parse_mcast_grps(family, info->attrs[CTRL_ATTR_MCAST_GROUPS]); + if (err < 0) + goto errout; } err = pp->pp_cb((struct nl_object *) family, pp); @@ -176,6 +189,104 @@ errout: return err; } +/** + * process responses from from the query sent by genl_ctrl_probe_by_name + * @arg nl_msg Returned message. + * @arg name genl_family structure to fill out. + * + * Process returned messages, filling out the missing informatino in the + * genl_family structure + * + * @return Indicator to keep processing frames or not + * + */ +static int probe_response(struct nl_msg *msg, void *arg) +{ + struct nlattr *tb[CTRL_ATTR_MAX+1]; + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct genl_family *ret = (struct genl_family *)arg; + + if (genlmsg_parse(nlh, 0, tb, CTRL_ATTR_MAX, ctrl_policy)) + return NL_SKIP; + + if (tb[CTRL_ATTR_FAMILY_ID]) + genl_family_set_id(ret, nla_get_u16(tb[CTRL_ATTR_FAMILY_ID])); + + if (tb[CTRL_ATTR_MCAST_GROUPS]) + if (parse_mcast_grps(ret, tb[CTRL_ATTR_MCAST_GROUPS]) < 0) + return NL_SKIP; + + return NL_STOP; +} + +/** + * Look up generic netlink family by family name querying the kernel directly + * @arg sk Socket. + * @arg name Family name. + * + * Directly query's the kernel for a given family name. The caller will own a + * reference on the returned object which needsd to be given back after usage + * using genl_family_put. + * + * Note: This API call differs from genl_ctrl_search_by_name in that it querys + * the kernel directly, alowing for module autoload to take place to resolve the + * family request. Using an nl_cache prevents that operation + * + * @return Generic netlink family object or NULL if no match was found. + */ +static struct genl_family *genl_ctrl_probe_by_name(struct nl_sock *sk, const char *name) +{ + struct nl_msg *msg; + struct genl_family *ret = NULL; + struct nl_cb *cb; + int rc; + + ret = genl_family_alloc(); + if (!ret) + goto out; + + genl_family_set_name(ret, name); + + msg = nlmsg_alloc(); + if (!msg) + goto out_fam_free; + + if (!(cb = nl_cb_clone(nl_socket_get_cb(sk)))) + goto out_msg_free; + + + genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, GENL_ID_CTRL, + 0, 0, CTRL_CMD_GETFAMILY, 1); + + if (nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, name)) + goto out_cb_free; + + rc = nl_send_auto_complete(sk, msg); + if (rc < 0) + goto out_cb_free; + + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, probe_response, (void *)ret); + + nl_recvmsgs(sk, cb); + + if (genl_family_get_id(ret) != 0) { + nlmsg_free(msg); + nl_cb_put(cb); + return ret; + } + +out_cb_free: + nl_cb_put(cb); +out_msg_free: + nlmsg_free(msg); +out_fam_free: + genl_family_put(ret); + ret = NULL; +out: + return ret; +} + + /** @endcond */ /** @@ -299,14 +410,10 @@ struct genl_family *genl_ctrl_search_by_name(struct nl_cache *cache, */ int genl_ctrl_resolve(struct nl_sock *sk, const char *name) { - struct nl_cache *cache; struct genl_family *family; int err; - if ((err = genl_ctrl_alloc_cache(sk, &cache)) < 0) - return err; - - family = genl_ctrl_search_by_name(cache, name); + family = genl_ctrl_probe_by_name(sk, name); if (family == NULL) { err = -NLE_OBJ_NOTFOUND; goto errout; @@ -315,8 +422,6 @@ int genl_ctrl_resolve(struct nl_sock *sk, const char *name) err = genl_family_get_id(family); genl_family_put(family); errout: - nl_cache_free(cache); - return err; } @@ -348,14 +453,11 @@ static int genl_ctrl_grp_by_name(const struct genl_family *family, int genl_ctrl_resolve_grp(struct nl_sock *sk, const char *family_name, const char *grp_name) { - struct nl_cache *cache; + struct genl_family *family; int err; - if ((err = genl_ctrl_alloc_cache(sk, &cache)) < 0) - return err; - - family = genl_ctrl_search_by_name(cache, family_name); + family = genl_ctrl_probe_by_name(sk, family_name); if (family == NULL) { err = -NLE_OBJ_NOTFOUND; goto errout; @@ -364,8 +466,6 @@ int genl_ctrl_resolve_grp(struct nl_sock *sk, const char *family_name, err = genl_ctrl_grp_by_name(family, grp_name); genl_family_put(family); errout: - nl_cache_free(cache); - return err; } diff --git a/tests/test-genl.c b/tests/test-genl.c index 63862b3..74aea10 100644 --- a/tests/test-genl.c +++ b/tests/test-genl.c @@ -84,6 +84,9 @@ int main(int argc, char *argv[]) if ((err = genl_ops_resolve(sock, &ops)) < 0) nl_cli_fatal(err, "Unable to resolve family name"); + if (genl_ctrl_resolve(sock, "nlctrl") != GENL_ID_CTRL) + nl_cli_fatal(NLE_INVAL, "Resolving of \"nlctrl\" failed"); + msg = nlmsg_alloc(); if (msg == NULL) nl_cli_fatal(NLE_NOMEM, "Unable to allocate netlink message"); From 405d16827d9383cc18ca97bbab7f424a120505f7 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 6 Jun 2012 11:43:53 +0200 Subject: [PATCH 188/432] libnl 3.2.10 --- ChangeLog | 2 +- configure.in | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6dc334b..cdd78a8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,5 @@ ChangeLog discontinued, git history can be found here: -http://git.kernel.org/?p=libs/netlink/libnl.git +http://git.infradead.org/users/tgr/libnl.git Summary of Changes from 1.0-pre6 to 1.0-pre7 ================================================ diff --git a/configure.in b/configure.in index 800354d..ef65678 100644 --- a/configure.in +++ b/configure.in @@ -13,7 +13,7 @@ # copied from glib m4_define([libnl_major_version], [3]) m4_define([libnl_minor_version], [2]) -m4_define([libnl_micro_version], [9]) +m4_define([libnl_micro_version], [10]) # If either revision or age are omitted, they default to 0. Also note that age @@ -34,9 +34,9 @@ m4_define([libnl_micro_version], [9]) # 6. If any interfaces have been removed since the last public release, then # set age to 0. -m4_define([libnl_lt_current], [207]) +m4_define([libnl_lt_current], [208]) m4_define([libnl_lt_revision], [0]) -m4_define([libnl_lt_age], [7]) +m4_define([libnl_lt_age], [8]) m4_define([libnl_version], [libnl_major_version.libnl_minor_version.libnl_micro_version]) From 2275bb0aaaf40bcf617fbf4bfd47ea5ae2d00fe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=BD=D0=BE=D1=83=D1=82=D0=B1?= =?UTF-8?q?=D1=83=D0=BA=20=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Thu, 7 Jun 2012 23:48:28 +0600 Subject: [PATCH 189/432] Fix compilation with clang classid_exit unnecessarily used gcc-only closure. conversion to simple static function works OK. --- lib/route/classid.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/route/classid.c b/lib/route/classid.c index da531bd..7b52de8 100644 --- a/lib/route/classid.c +++ b/lib/route/classid.c @@ -438,12 +438,13 @@ static void __init classid_init(void) fprintf(stderr, "Failed to read classid file: %s\n", nl_geterror(err)); } +static void free_map(void *map) { + free(((struct classid_map *)map)->name); + free(map); +}; + static void __exit classid_exit(void) { - void free_map(void *map) { - free(((struct classid_map *)map)->name); - free(map); - }; tdestroy(id_root, free_map); } /** @} */ From d3dcde2585cd26642aa236ed94442c838b8b7471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=BD=D0=BE=D1=83=D1=82=D0=B1?= =?UTF-8?q?=D1=83=D0=BA=20=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Fri, 8 Jun 2012 00:58:14 +0600 Subject: [PATCH 190/432] rtnl_netem_set_delay_distribution: fix possible segfault fix counting of elements in array. Just typo, as I think. --- lib/route/qdisc/netem.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/route/qdisc/netem.c b/lib/route/qdisc/netem.c index 997a31f..5f26096 100644 --- a/lib/route/qdisc/netem.c +++ b/lib/route/qdisc/netem.c @@ -826,7 +826,7 @@ int rtnl_netem_set_delay_distribution(struct rtnl_qdisc *qdisc, const char *dist if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) BUG(); - FILE *f = NULL; + FILE *f; int i, n = 0; size_t len = 2048; char *line; @@ -841,9 +841,10 @@ int rtnl_netem_set_delay_distribution(struct rtnl_qdisc *qdisc, const char *dist /* Check several locations for the dist file */ char *test_path[] = { "", "./", "/usr/lib/tc/", "/usr/local/lib/tc/" }; - for (i = 0; i < sizeof(test_path) && f == NULL; i++) { + for (i = 0; i < sizeof(test_path)/sizeof(test_path[0]); i++) { snprintf(name, NAME_MAX, "%s%s%s", test_path[i], dist_type, dist_suffix); - f = fopen(name, "r"); + if ((f = fopen(name, "r"))) + break; } if ( f == NULL ) From d8a25e4c5cf6a091094ce239c81626410f460266 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 8 Jun 2012 15:21:51 +0200 Subject: [PATCH 191/432] netem: Use ARRAY_SIZE() --- lib/route/qdisc/netem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/route/qdisc/netem.c b/lib/route/qdisc/netem.c index 5f26096..3e5ba52 100644 --- a/lib/route/qdisc/netem.c +++ b/lib/route/qdisc/netem.c @@ -841,7 +841,7 @@ int rtnl_netem_set_delay_distribution(struct rtnl_qdisc *qdisc, const char *dist /* Check several locations for the dist file */ char *test_path[] = { "", "./", "/usr/lib/tc/", "/usr/local/lib/tc/" }; - for (i = 0; i < sizeof(test_path)/sizeof(test_path[0]); i++) { + for (i = 0; i < ARRAY_SIZE(test_path); i++) { snprintf(name, NAME_MAX, "%s%s%s", test_path[i], dist_type, dist_suffix); if ((f = fopen(name, "r"))) break; From bf54d6d03af059b332337dcb90a651eac926adbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=BD=D0=BE=D1=83=D1=82=D0=B1?= =?UTF-8?q?=D1=83=D0=BA=20=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Mon, 4 Jun 2012 22:49:04 +0600 Subject: [PATCH 192/432] Fixed address deletion 1. rtnl_addr_delete require three arguments 2. comment fixed (fixed copy-past from link.py) --- python/netlink/route/address.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/netlink/route/address.py b/python/netlink/route/address.py index d70664c..3654834 100644 --- a/python/netlink/route/address.py +++ b/python/netlink/route/address.py @@ -345,9 +345,9 @@ class Address(netlink.Object): ##################################################################### # delete() - def delete(self, socket): - """Attempt to delete this link in the kernel""" - ret = capi.rtnl_addr_delete(socket._sock, self._addr) + def delete(self, socket, flags=0): + """Attempt to delete this address in the kernel""" + ret = capi.rtnl_addr_delete(socket._sock, self._rtnl_addr, flags) if ret < 0: raise netlink.KernelError(ret) From 9d60ef0d5943b771583e13cdce2798eb38efe975 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA?= Date: Fri, 8 Jun 2012 11:52:50 +0600 Subject: [PATCH 193/432] Removed generated .pyc files from repository --- python/netlink/__init__.pyc | Bin 133 -> 0 bytes python/netlink/capi.pyc | Bin 35688 -> 0 bytes python/netlink/core.pyc | Bin 28503 -> 0 bytes 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 python/netlink/__init__.pyc delete mode 100644 python/netlink/capi.pyc delete mode 100644 python/netlink/core.pyc diff --git a/python/netlink/__init__.pyc b/python/netlink/__init__.pyc deleted file mode 100644 index 54d904888e6d141806eac4bbcfe9d7711e3395f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 133 zcmcckiI?lw*Ezn)3{b!bq#b~`m<33rFfasbfJFQ>fCK{?QLG0P)6dAyP1P?+FVas* zEz{4*Ov=mAFQ_cZ$j{TyOD)OC%*)n~kI&4@EQycT1B!D1wbtdf{uuQxS`^Lf{Ma`1qxo5wx@3m(@aly+g$?;f})_J zqN1Xr;=ZAR;*N?wlb5`h#3Y)S#Ox+7c`=Dej4^xi@_y%6HO!2H5%2wc-ai@aWA(49 zZhiaSbI)CBd*l6ny~i*7()6q(e|_=)@Hz)lx|^-%mWf%cdQt2E-5xw=>891XX?&EOna(a^cj3Z7342IxpqPPT2T~bC zWssP7VOKG`QW-2}Fc*f18N!93Vup&vX8olRdAIAJ4xGhFOYDtl1bL(CpxccZc=l|9AmDRy@%dr{d-%wA%LQK_X;E2dWL za4LIK*;~xsV)vl350!ny>?3whD*IB|SIoX*_o6a_$_Ozd#MV+7NoAy%kz)6zvLBWG z#Ox<_A1eD(*_JqMRn#$2)juv|am5Ed)ikT>O z0+nN^93$o!u}4xlmddeWjum?pmE))!C+0Y@M^ibT%JE{37dw&4Br21{OcHwxl@q9( zAm#+I$5J_w%86o56nh+%$y6qbnJo5rDpROT5i>>XBq}FSIZ4b(Vo#uQGL@6XoGkW4 zDyL96Ma(H;CsUb9WvZB|Vy93!mCC7NP8E9+mD8x4CgwD;CsUb5Wty02Vo#wmoyv4E z)5T7uQctB`Oug7ssm!1{ZEGl!U%oQ_N>})D$ zQ8`P@Sz^ziVyGA~M(mkX&ZcshtDbHtn@b}p53shlh3T(M_SIgiSDV$Kt5 zsHCZ+#iYfaP33$l=ZiUC>^W32R5D^RV$Y@0K&3%UgV^(^WT|AuWW}bbSSnVG6?;CF zkV+^f6q}*aNTpFsqu2&2^Qg=dGf!-mN)wePF->AEl^m6vn4H*<%6uyG#mpDmNTr!d zvzTVF^Qh#hrBSNV)IlkpmKqj z3&gfiDN`wnDT^&osZgnisfaC7iKs+kBC#bZtyEgYw2Hle$^t42#4He7rm~RALNN=) zR;VnZvPjG#u@RLvDs5ug#I{mdOl7f{#bOswxsb|*VlEWBkjfG&OT;V@yNJqCDoe#I z728JTA}SY&xk&6{Di>3^Sj@#@FQl@J$}%y_#4e$736)F4Tq1TUl}o8yD&|tL7g1SG zWx1H;VlSq$g31apE5t6Nav7D Su!5-OKdxm?WUVlSm~1(hqrTp@Njm6cRhidiXk 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 diff --git a/python/netlink/core.pyc b/python/netlink/core.pyc deleted file mode 100644 index db86228abc28968d27aaaa374391b37ddac119b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28503 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 From 1e75bd006b916c39c0a5915a80b555fafd56d07a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=BD=D0=BE=D1=83=D1=82=D0=B1?= =?UTF-8?q?=D1=83=D0=BA=20=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Mon, 4 Jun 2012 22:50:36 +0600 Subject: [PATCH 194/432] Make syntax highlighters happy Fix typo in docstring --- python/netlink/route/link.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/netlink/route/link.py b/python/netlink/route/link.py index e613f2e..3a428c9 100644 --- a/python/netlink/route/link.py +++ b/python/netlink/route/link.py @@ -298,7 +298,7 @@ class Link(netlink.Object): @netlink.nlattr('link.txqlen', type=int, fmt=util.num) @property def txqlen(self): - """"Length of transmit queue""" + """Length of transmit queue""" return capi.rtnl_link_get_txqlen(self._rtnl_link) @txqlen.setter From f55ea7ff9d318be938be3f3ae4f331ba5c7dc150 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=BD=D0=BE=D1=83=D1=82=D0=B1?= =?UTF-8?q?=D1=83=D0=BA=20=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Mon, 4 Jun 2012 22:52:02 +0600 Subject: [PATCH 195/432] Fix typo in still unused function that generate colored message --- python/netlink/util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/netlink/util.py b/python/netlink/util.py index 01db224..191c531 100644 --- a/python/netlink/util.py +++ b/python/netlink/util.py @@ -32,7 +32,7 @@ def yellow(t): def blue(t): return _color(t, 34) -def mangenta(t): +def magenta(t): return _color(t, 35) def cyan(t): From 4be1ae2ae22e100e6bbc4bd127af49296efbd763 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=BD=D0=BE=D1=83=D1=82=D0=B1?= =?UTF-8?q?=D1=83=D0=BA=20=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Mon, 4 Jun 2012 22:54:16 +0600 Subject: [PATCH 196/432] Introduce Python's absolute_imports Helps greatly when porting to Python 3 --- python/netlink/core.py | 5 ++++- python/netlink/route/address.py | 13 ++++++++----- python/netlink/route/link.py | 12 +++++++----- python/netlink/route/links/dummy.py | 5 +++-- python/netlink/route/links/inet.py | 9 +++++---- python/netlink/route/links/vlan.py | 6 ++++-- python/netlink/route/qdisc/htb.py | 10 ++++++---- python/netlink/route/tc.py | 12 ++++++------ python/netlink/util.py | 6 ++++-- 9 files changed, 47 insertions(+), 31 deletions(-) diff --git a/python/netlink/core.py b/python/netlink/core.py index e311d5f..26ea6ca 100644 --- a/python/netlink/core.py +++ b/python/netlink/core.py @@ -25,8 +25,11 @@ The following exceptions are defined: All other classes or functions in this module are considered implementation details. """ +from __future__ import absolute_import -import capi + + +from . import capi import sys import socket import struct diff --git a/python/netlink/route/address.py b/python/netlink/route/address.py index 3654834..29b8072 100644 --- a/python/netlink/route/address.py +++ b/python/netlink/route/address.py @@ -5,17 +5,20 @@ """Module providing access to network addresses """ +from __future__ import absolute_import + + __version__ = "1.0" __all__ = [ 'AddressCache', 'Address'] import datetime -import netlink.core as netlink -import netlink.capi as core_capi -import netlink.route.capi as capi -import netlink.route.link as Link -import netlink.util as util +from .. import core as netlink +from .. import capi as core_capi +from . import capi as capi +from . import link as Link +from .. import util as util ########################################################################### # Address Cache diff --git a/python/netlink/route/link.py b/python/netlink/route/link.py index 3a428c9..fce2cd7 100644 --- a/python/netlink/route/link.py +++ b/python/netlink/route/link.py @@ -34,6 +34,8 @@ The following public functions exist: """ +from __future__ import absolute_import + __version__ = "0.1" __all__ = [ 'LinkCache', @@ -42,11 +44,11 @@ __all__ = [ import socket import sys -import netlink.core as netlink -import netlink.capi as core_capi -import netlink.route.capi as capi -import netlink.route.links.inet as inet -import netlink.util as util +from .. import core as netlink +from .. import capi as core_capi +from . import capi as capi +from .links import inet as inet +from .. import util as util ########################################################################### # Link statistics definitions diff --git a/python/netlink/route/links/dummy.py b/python/netlink/route/links/dummy.py index 8210413..6c96617 100644 --- a/python/netlink/route/links/dummy.py +++ b/python/netlink/route/links/dummy.py @@ -5,13 +5,14 @@ """Dummy """ +from __future__ import absolute_import __version__ = "1.0" __all__ = ['init'] -import netlink.core as netlink -import netlink.route.capi as capi +from ... import core as netlink +from .. import capi as capi class DummyLink(object): def __init__(self, link): self._rtnl_link = link diff --git a/python/netlink/route/links/inet.py b/python/netlink/route/links/inet.py index 63c234f..73bde6b 100644 --- a/python/netlink/route/links/inet.py +++ b/python/netlink/route/links/inet.py @@ -6,12 +6,13 @@ """ +from __future__ import absolute_import + __all__ = [''] -import netlink.core as netlink -import netlink.route.capi as capi -import netlink.util as util - +from ... import core as netlink +from .. import capi as capi +from ... import util as util DEVCONF_FORWARDING = 1 DEVCONF_MC_FORWARDING = 2 DEVCONF_PROXY_ARP = 3 diff --git a/python/netlink/route/links/vlan.py b/python/netlink/route/links/vlan.py index 7f28247..134e721 100644 --- a/python/netlink/route/links/vlan.py +++ b/python/netlink/route/links/vlan.py @@ -6,9 +6,11 @@ """ -import netlink.core as netlink -import netlink.route.capi as capi +from __future__ import absolute_import + +from ... import core as netlink +from .. import capi as capi class VLANLink(object): def __init__(self, link): self._link = link diff --git a/python/netlink/route/qdisc/htb.py b/python/netlink/route/qdisc/htb.py index 13e10f2..23c7f75 100644 --- a/python/netlink/route/qdisc/htb.py +++ b/python/netlink/route/qdisc/htb.py @@ -6,10 +6,12 @@ """ -import netlink.core as netlink -import netlink.util as util -import netlink.route.capi as capi -import netlink.route.tc as tc +from __future__ import absolute_import + +from ... import core as netlink +from ... import util as util +from .. import capi as capi +from .. import tc as tc class HTBQdisc(object): def __init__(self, qdisc): diff --git a/python/netlink/route/tc.py b/python/netlink/route/tc.py index bae9bca..0d20e79 100644 --- a/python/netlink/route/tc.py +++ b/python/netlink/route/tc.py @@ -1,6 +1,7 @@ # # Copyright (c) 2011 Thomas Graf # +from __future__ import absolute_import __all__ = [ 'TcCache', @@ -12,12 +13,11 @@ __all__ = [ import socket import sys -import netlink.core as netlink -import netlink.capi as core_capi -import netlink.route.capi as capi -import netlink.util as util - -import netlink.route.link as Link +from .. import core as netlink +from .. import capi as core_capi +from . import capi as capi +from .. import util as util +from . import link as Link TC_PACKETS = 0 TC_BYTES = 1 diff --git a/python/netlink/util.py b/python/netlink/util.py index 191c531..0a73db4 100644 --- a/python/netlink/util.py +++ b/python/netlink/util.py @@ -8,8 +8,10 @@ """ -import netlink.core as netlink -import netlink.capi as capi +from __future__ import absolute_import + +from . import core as netlink +from . import capi as capi from string import Formatter __version__ = "1.0" From b369d22f9276d4279081b9dff13953adb8f57e07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=BD=D0=BE=D1=83=D1=82=D0=B1?= =?UTF-8?q?=D1=83=D0=BA=20=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Mon, 4 Jun 2012 22:55:49 +0600 Subject: [PATCH 197/432] Fix whitespaces at EOL Make git happy with that --- python/netlink/core.py | 6 +++--- python/netlink/route/address.py | 4 ++-- python/netlink/route/link.py | 6 +++--- python/netlink/route/links/dummy.py | 2 +- python/netlink/route/links/inet.py | 16 ++++++++-------- python/netlink/route/tc.py | 16 ++++++++-------- python/netlink/util.py | 4 ++-- 7 files changed, 27 insertions(+), 27 deletions(-) diff --git a/python/netlink/core.py b/python/netlink/core.py index 26ea6ca..ea78691 100644 --- a/python/netlink/core.py +++ b/python/netlink/core.py @@ -43,13 +43,13 @@ NETLINK_ROUTE = 0 # NETLINK_UNUSED = 1 NETLINK_USERSOCK = 2 NETLINK_FIREWALL = 3 -NETLINK_INET_DIAG = 4 +NETLINK_INET_DIAG = 4 NETLINK_NFLOG = 5 NETLINK_XFRM = 6 NETLINK_SELINUX = 7 NETLINK_ISCSI = 8 NETLINK_AUDIT = 9 -NETLINK_FIB_LOOKUP = 10 +NETLINK_FIB_LOOKUP = 10 NETLINK_CONNECTOR = 11 NETLINK_NETFILTER = 12 NETLINK_IP6_FW = 13 @@ -588,7 +588,7 @@ class CacheManager(object): if self._mngr: capi.nl_cache_mngr_free(self._mngr) - + def add(self, name): capi.cache_mngr_add(self._mngr, name, None, None) diff --git a/python/netlink/route/address.py b/python/netlink/route/address.py index 29b8072..8fab97d 100644 --- a/python/netlink/route/address.py +++ b/python/netlink/route/address.py @@ -374,12 +374,12 @@ class Address(netlink.Object): if not nodev: buf += fmt.format(' {a|ifindex}') - + buf += fmt.format(' {a|scope}') if self.label: buf += fmt.format(' "{a|label}"') - + buf += fmt.format(' <{a|_flags}>') if details: diff --git a/python/netlink/route/link.py b/python/netlink/route/link.py index fce2cd7..74ec2f9 100644 --- a/python/netlink/route/link.py +++ b/python/netlink/route/link.py @@ -66,9 +66,9 @@ RX_FIFO_ERR = 10 TX_FIFO_ERR = 11 RX_LEN_ERR = 12 RX_OVER_ERR = 13 -RX_CRC_ERR = 14 +RX_CRC_ERR = 14 RX_FRAME_ERR = 15 -RX_MISSED_ERR = 16 +RX_MISSED_ERR = 16 TX_ABORT_ERR = 17 TX_CARRIER_ERR = 18 TX_HBEAT_ERR = 19 @@ -495,7 +495,7 @@ class Link(netlink.Object): buf += fmt.nl('\t{t|mtu} {t|txqlen} {t|weight} '\ '{t|qdisc} {t|operstate}') buf += fmt.nl('\t{t|broadcast} {t|alias}') - + buf += self._foreach_af('details', fmt) if stats: diff --git a/python/netlink/route/links/dummy.py b/python/netlink/route/links/dummy.py index 6c96617..caf3ba7 100644 --- a/python/netlink/route/links/dummy.py +++ b/python/netlink/route/links/dummy.py @@ -19,7 +19,7 @@ class DummyLink(object): def brief(self): return 'dummy' - + def init(link): link.dummy = DummyLink(link._rtnl_link) return link.dummy diff --git a/python/netlink/route/links/inet.py b/python/netlink/route/links/inet.py index 73bde6b..76a9e92 100644 --- a/python/netlink/route/links/inet.py +++ b/python/netlink/route/links/inet.py @@ -66,7 +66,7 @@ class InetLink(object): def get_conf(self, id): return capi.inet_get_conf(self._link._rtnl_link, _resolve(id)) - + def set_conf(self, id, value): return capi.rtnl_link_inet_set_conf(self._link._rtnl_link, _resolve(id), int(value)) @@ -75,7 +75,7 @@ class InetLink(object): @property def forwarding(self): return bool(self.get_conf(DEVCONF_FORWARDING)) - + @forwarding.setter def forwarding(self, value): self.set_conf(DEVCONF_FORWARDING, int(value)) @@ -84,7 +84,7 @@ class InetLink(object): @property def mc_forwarding(self): return bool(self.get_conf(DEVCONF_MC_FORWARDING)) - + @mc_forwarding.setter def mc_forwarding(self, value): self.set_conf(DEVCONF_MC_FORWARDING, int(value)) @@ -93,7 +93,7 @@ class InetLink(object): @property def proxy_arp(self): return bool(self.get_conf(DEVCONF_PROXY_ARP)) - + @proxy_arp.setter def proxy_arp(self, value): self.set_conf(DEVCONF_PROXY_ARP, int(value)) @@ -102,7 +102,7 @@ class InetLink(object): @property def accept_redirects(self): return bool(self.get_conf(DEVCONF_ACCEPT_REDIRECTS)) - + @accept_redirects.setter def accept_redirects(self, value): self.set_conf(DEVCONF_ACCEPT_REDIRECTS, int(value)) @@ -111,7 +111,7 @@ class InetLink(object): @property def secure_redirects(self): return bool(self.get_conf(DEVCONF_SECURE_REDIRECTS)) - + @secure_redirects.setter def secure_redirects(self, value): self.set_conf(DEVCONF_SECURE_REDIRECTS, int(value)) @@ -120,7 +120,7 @@ class InetLink(object): @property def send_redirects(self): return bool(self.get_conf(DEVCONF_SEND_REDIRECTS)) - + @send_redirects.setter def send_redirects(self, value): self.set_conf(DEVCONF_SEND_REDIRECTS, int(value)) @@ -129,7 +129,7 @@ class InetLink(object): @property def shared_media(self): return bool(self.get_conf(DEVCONF_SHARED_MEDIA)) - + @shared_media.setter def shared_media(self, value): self.set_conf(DEVCONF_SHARED_MEDIA, int(value)) diff --git a/python/netlink/route/tc.py b/python/netlink/route/tc.py index 0d20e79..1c654e1 100644 --- a/python/netlink/route/tc.py +++ b/python/netlink/route/tc.py @@ -247,7 +247,7 @@ class Tc(netlink.Object): def stats(self, fmt): return fmt.nl('{t|packets} {t|bytes} {t|qlen}') - + ########################################################################### # Queueing discipline cache class QdiscCache(netlink.Cache): @@ -360,13 +360,13 @@ class Qdisc(Tc): fmt = util.MyFormatter(self, indent) buf = fmt.format(self.brief('qdisc', nodev, noparent)) - + if details: buf += fmt.nl('\t' + self.details()) if stats: buf += self.stats(fmt) - + # if stats: # l = [['Packets', RX_PACKETS, TX_PACKETS], # ['Bytes', RX_BYTES, TX_BYTES], @@ -500,7 +500,7 @@ class TcClass(Tc): if details: buf += fmt.nl('\t' + self.details()) - + return buf ########################################################################### @@ -589,7 +589,7 @@ class Classifier(Tc): if details: buf += fmt.nl('\t' + self.details()) - + return buf _qdisc_cache = QdiscCache() @@ -604,7 +604,7 @@ def get_qdisc(ifindex, handle=None, parent=None): (handle == None or qdisc.handle == handle) and \ (parent == None or qdisc.parent == parent): l.append(qdisc) - + return l _class_cache = {} @@ -617,7 +617,7 @@ def get_class(ifindex, parent, handle=None): except KeyError: cache = TcClassCache(ifindex) _class_cache[ifindex] = cache - + cache.refill() for cl in cache: @@ -642,7 +642,7 @@ def get_cls(ifindex, parent, handle=None): except KeyError: cache = ClassifierCache(ifindex, parent) _cls_cache[ifindex][parent] = cache - + cache.refill() for cls in cache: diff --git a/python/netlink/util.py b/python/netlink/util.py index 0a73db4..a8c831f 100644 --- a/python/netlink/util.py +++ b/python/netlink/util.py @@ -1,5 +1,5 @@ # -# Utilities +# Utilities # # Copyright (c) 2011 Thomas Graf # @@ -141,7 +141,7 @@ class MyFormatter(Formatter): return bold(value) elif conversion is None: return value - + raise ValueError("Unknown converion specifier {0!s}".format(conversion)) def nl(self): From 38fefc5c1b005c518d0d511c0921169b92faa86c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=BD=D0=BE=D1=83=D1=82=D0=B1?= =?UTF-8?q?=D1=83=D0=BA=20=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Mon, 4 Jun 2012 23:12:26 +0600 Subject: [PATCH 198/432] Fixed various str-related logick --- python/netlink/core.py | 8 ++++---- python/netlink/route/link.py | 4 ++-- python/netlink/route/links/inet.py | 2 +- python/netlink/route/links/vlan.py | 2 +- python/netlink/util.py | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/python/netlink/core.py b/python/netlink/core.py index ea78691..b6cf7e9 100644 --- a/python/netlink/core.py +++ b/python/netlink/core.py @@ -92,14 +92,14 @@ class NetlinkError(Exception): class KernelError(NetlinkError): def __str__(self): - return "Kernel returned: " + self._msg + return "Kernel returned: {0}".format(self._msg) class ImmutableError(NetlinkError): def __init__(self, msg): self._msg = msg def __str__(self): - return "Immutable attribute: " + self._msg + return "Immutable attribute: {0}".format(self._msg) class Message(object): """Netlink message""" @@ -162,7 +162,7 @@ class Socket(object): capi.nl_socket_free(self._sock) def __str__(self): - return "nlsock<" + str(self.localPort) + ">" + return "nlsock<{0}>".format(self.localPort) @property def local_port(self): @@ -626,7 +626,7 @@ class AddressFamily(object): return self._family def __repr__(self): - return 'AddressFamily(\'' + str(self) + '\')' + return 'AddressFamily({0!r})'.format(str(self)) ########################################################################### diff --git a/python/netlink/route/link.py b/python/netlink/route/link.py index 74ec2f9..8c87971 100644 --- a/python/netlink/route/link.py +++ b/python/netlink/route/link.py @@ -127,7 +127,7 @@ class LinkCache(netlink.Cache): def __getitem__(self, key): if type(key) is int: link = capi.rtnl_link_get(self._nl_cache, key) - elif type(key) is str: + else: link = capi.rtnl_link_get_by_name(self._nl_cache, key) if link is None: @@ -227,7 +227,7 @@ class Link(netlink.Object): @flags.setter def flags(self, value): - if type(value) is list: + if not (type(value) is str): for flag in value: self._set_flag(flag) else: diff --git a/python/netlink/route/links/inet.py b/python/netlink/route/links/inet.py index 76a9e92..b5b1152 100644 --- a/python/netlink/route/links/inet.py +++ b/python/netlink/route/links/inet.py @@ -52,7 +52,7 @@ class InetLink(object): self._link = link def details(self, fmt): - buf = '\n' + fmt.nl('\t%s\n\t' % util.title('Configuration:')) + buf = fmt.nl('\n\t{0}\n\t'.format(util.title('Configuration:'))) for i in range(DEVCONF_FORWARDING,DEVCONF_MAX+1): if i & 1 and i > 1: diff --git a/python/netlink/route/links/vlan.py b/python/netlink/route/links/vlan.py index 134e721..c9fe2a7 100644 --- a/python/netlink/route/links/vlan.py +++ b/python/netlink/route/links/vlan.py @@ -57,7 +57,7 @@ class VLANLink(object): # - egress map def brief(self): - return 'vlan-id ' + self.id + return 'vlan-id {0}'.format(self.id) def init(link): link.vlan = VLANLink(link._link) diff --git a/python/netlink/util.py b/python/netlink/util.py index a8c831f..f6e7dec 100644 --- a/python/netlink/util.py +++ b/python/netlink/util.py @@ -17,7 +17,7 @@ from string import Formatter __version__ = "1.0" def _color(t, c): - return chr(0x1b)+"["+str(c)+"m"+str(t)+chr(0x1b)+"[0m" + return b'{esc}[{color}m{text}{esc}[0m'.format(esc=b'\x1b', color=c, text=t) def black(t): return _color(t, 30) @@ -126,7 +126,7 @@ class MyFormatter(Formatter): if include_title: if not title: title = key # fall back to key as title - value = kw(title) + ' ' + value + value = '{0} {1}'.format(kw(title), value) return value From c1547d90d70016c04c35a3ad2ff42190eb4de18a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=BD=D0=BE=D1=83=D1=82=D0=B1?= =?UTF-8?q?=D1=83=D0=BA=20=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Mon, 4 Jun 2012 23:39:30 +0600 Subject: [PATCH 199/432] Flags properties description and implementation fixed 1. Address, Link and Vlan classes affected with same bug 2. Flags property are not designed as set class. Setting to property will not replace flags, just add flags to set. So, jist document that, and fixed obvious logick. --- python/netlink/route/address.py | 18 +++++++++++++++--- python/netlink/route/link.py | 16 +++++++++++++--- python/netlink/route/links/vlan.py | 17 ++++++++++++++--- 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/python/netlink/route/address.py b/python/netlink/route/address.py index 8fab97d..a8da1ed 100644 --- a/python/netlink/route/address.py +++ b/python/netlink/route/address.py @@ -147,17 +147,29 @@ class Address(netlink.Object): @netlink.nlattr('address.flags', type=str, fmt=util.string) @property def flags(self): - """Flags""" + """Flags + + Setting this property will *Not* reset flags to value you supply in + + Examples: + addr.flags = '+xxx' # add xxx flag + addr.flags = 'xxx' # exactly the same + addr.flags = '-xxx' # remove xxx flag + addr.flags = [ '+xxx', '-yyy' ] # list operation + """ flags = capi.rtnl_addr_get_flags(self._rtnl_addr) return capi.rtnl_addr_flags2str(flags, 256)[0].split(',') def _set_flag(self, flag): - if flag[0] == '-': + if flag.startswith('-'): i = capi.rtnl_addr_str2flags(flag[1:]) capi.rtnl_addr_unset_flags(self._rtnl_addr, i) - else: + elif flag.startswith('+'): i = capi.rtnl_addr_str2flags(flag[1:]) capi.rtnl_addr_set_flags(self._rtnl_addr, i) + else: + i = capi.rtnl_addr_str2flags(flag) + capi.rtnl_addr_set_flags(self._rtnl_addr, i) @flags.setter def flags(self, value): diff --git a/python/netlink/route/link.py b/python/netlink/route/link.py index 8c87971..b7a377a 100644 --- a/python/netlink/route/link.py +++ b/python/netlink/route/link.py @@ -213,17 +213,27 @@ class Link(netlink.Object): @netlink.nlattr('link.flags', type=str, fmt=util.string) @property def flags(self): - """Flags""" + """Flags + Setting this property will *Not* reset flags to value you supply in + Examples: + link.flags = '+xxx' # add xxx flag + link.flags = 'xxx' # exactly the same + link.flags = '-xxx' # remove xxx flag + link.flags = [ '+xxx', '-yyy' ] # list operation + """ flags = capi.rtnl_link_get_flags(self._rtnl_link) return capi.rtnl_link_flags2str(flags, 256)[0].split(',') def _set_flag(self, flag): - if flag[0] == '-': + if flag.startswith('-'): i = capi.rtnl_link_str2flags(flag[1:]) capi.rtnl_link_unset_flags(self._rtnl_link, i) - else: + elif flag.startswith('+'): i = capi.rtnl_link_str2flags(flag[1:]) capi.rtnl_link_set_flags(self._rtnl_link, i) + else: + i = capi.rtnl_link_str2flags(flag) + capi.rtnl_link_set_flags(self._rtnl_link, i) @flags.setter def flags(self, value): diff --git a/python/netlink/route/links/vlan.py b/python/netlink/route/links/vlan.py index c9fe2a7..bb339d0 100644 --- a/python/netlink/route/links/vlan.py +++ b/python/netlink/route/links/vlan.py @@ -32,15 +32,26 @@ class VLANLink(object): @netlink.nlattr('link.vlan.flags', type=str) @property def flags(self): - """vlan flags""" + """ VLAN flags + Setting this property will *Not* reset flags to value you supply in + Examples: + link.flags = '+xxx' # add xxx flag + link.flags = 'xxx' # exactly the same + link.flags = '-xxx' # remove xxx flag + link.flags = [ '+xxx', '-yyy' ] # list operation + """ flags = capi.rtnl_link_vlan_get_flags(self._link) return capi.rtnl_link_vlan_flags2str(flags, 256)[0].split(',') def _set_flag(self, flag): - i = capi.rtnl_link_vlan_str2flags(flag[1:]) - if flag[0] == '-': + if flag.startswith('-'): + i = capi.rtnl_link_vlan_str2flags(flag[1:]) capi.rtnl_link_vlan_unset_flags(self._link, i) + elif flag.startswith('+'): + i = capi.rtnl_link_vlan_str2flags(flag[1:]) + capi.rtnl_link_vlan_set_flags(self._link, i) else: + i = capi.rtnl_link_vlan_str2flags(flag) capi.rtnl_link_vlan_set_flags(self._link, i) @flags.setter From fb890a5b5e769a6ca7e639e004c06c6e3bbc46d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=BD=D0=BE=D1=83=D1=82=D0=B1?= =?UTF-8?q?=D1=83=D0=BA=20=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Mon, 4 Jun 2012 23:20:24 +0600 Subject: [PATCH 200/432] Code cleanups 1. unused "import struct" removed 2. AddressFamily.__len__ is defined, but why in so way? removed. 3. comparison against instancemethod type fixed --- python/netlink/core.py | 4 ---- python/netlink/util.py | 6 ++---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/python/netlink/core.py b/python/netlink/core.py index b6cf7e9..0ffa22f 100644 --- a/python/netlink/core.py +++ b/python/netlink/core.py @@ -32,7 +32,6 @@ from __future__ import absolute_import from . import capi import sys import socket -import struct __all__ = ['Message', 'Socket', 'DumpParams', 'Object', 'Cache', 'KernelError', 'NetlinkError'] @@ -619,9 +618,6 @@ class AddressFamily(object): def __str__(self): return capi.nl_af2str(self._family, 32)[0] - def __len__(self): - return len(str(self)) - def __int__(self): return self._family diff --git a/python/netlink/util.py b/python/netlink/util.py index f6e7dec..73a211d 100644 --- a/python/netlink/util.py +++ b/python/netlink/util.py @@ -13,6 +13,7 @@ from __future__ import absolute_import from . import core as netlink from . import capi as capi from string import Formatter +import types __version__ = "1.0" @@ -82,7 +83,7 @@ class MyFormatter(Formatter): value = getattr(self._obj, key) title = None - if type(value) == 'instancemethod': + if isinstance(value, types.MethodType): value = value() try: @@ -144,9 +145,6 @@ class MyFormatter(Formatter): raise ValueError("Unknown converion specifier {0!s}".format(conversion)) - def nl(self): - return '\n' + self._indent - def nl(self, format_string=''): return '\n' + self._indent + self.format(format_string) From 83f06bfbb85b475f6c6ba9993ed6de9f0f3f9315 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=BD=D0=BE=D1=83=D1=82=D0=B1?= =?UTF-8?q?=D1=83=D0=BA=20=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Tue, 5 Jun 2012 01:08:27 +0600 Subject: [PATCH 201/432] Fix indentation (spaces vs tabs) Now, python files use pseudo-tab equal 4 spaces --- python/netlink/core.py | 992 ++++++++++++++-------------- python/netlink/route/address.py | 634 +++++++++--------- python/netlink/route/link.py | 814 +++++++++++------------ python/netlink/route/links/dummy.py | 12 +- python/netlink/route/links/inet.py | 140 ++-- python/netlink/route/links/vlan.py | 104 +-- python/netlink/route/qdisc/htb.py | 220 +++--- python/netlink/route/tc.py | 716 ++++++++++---------- python/netlink/util.py | 186 +++--- 9 files changed, 1909 insertions(+), 1909 deletions(-) diff --git a/python/netlink/core.py b/python/netlink/core.py index 0ffa22f..219b522 100644 --- a/python/netlink/core.py +++ b/python/netlink/core.py @@ -11,16 +11,16 @@ This module provides an interface to netlink sockets The module contains the following public classes: - Socket -- The netlink socket - Object -- Abstract object (based on struct nl_obect in libnl) used as - base class for all object types which can be put into a Cache + base class for all object types which can be put into a Cache - Cache -- A collection of objects which are derived from the base - class Object. Used for netlink protocols which maintain a list - or tree of objects. + class Object. Used for netlink protocols which maintain a list + or tree of objects. - DumpParams -- The following exceptions are defined: - NetlinkError -- Base exception for all general purpose exceptions raised. - KernelError -- Raised when the kernel returns an error as response to a - request. + request. All other classes or functions in this module are considered implementation details. @@ -34,7 +34,7 @@ import sys import socket __all__ = ['Message', 'Socket', 'DumpParams', 'Object', 'Cache', 'KernelError', - 'NetlinkError'] + 'NetlinkError'] __version__ = "0.1" # netlink protocols @@ -82,168 +82,168 @@ NLM_F_CREATE = 0x400 NLM_F_APPEND = 0x800 class NetlinkError(Exception): - def __init__(self, error): - self._error = error - self._msg = capi.nl_geterror(error) + def __init__(self, error): + self._error = error + self._msg = capi.nl_geterror(error) - def __str__(self): - return self._msg + def __str__(self): + return self._msg class KernelError(NetlinkError): - def __str__(self): - return "Kernel returned: {0}".format(self._msg) + def __str__(self): + return "Kernel returned: {0}".format(self._msg) class ImmutableError(NetlinkError): - def __init__(self, msg): - self._msg = msg + def __init__(self, msg): + self._msg = msg - def __str__(self): - return "Immutable attribute: {0}".format(self._msg) + def __str__(self): + return "Immutable attribute: {0}".format(self._msg) class Message(object): - """Netlink message""" + """Netlink message""" - def __init__(self, size=0): - if size == 0: - self._msg = capi.nlmsg_alloc() - else: - self._msg = capi.nlmsg_alloc_size(size) + def __init__(self, size=0): + if size == 0: + self._msg = capi.nlmsg_alloc() + else: + self._msg = capi.nlmsg_alloc_size(size) - if self._msg is None: - raise Exception("Message allocation returned NULL") + if self._msg is None: + raise Exception("Message allocation returned NULL") - def __del__(self): - capi.nlmsg_free(self._msg) + def __del__(self): + capi.nlmsg_free(self._msg) - def __len__(self): - return capi.nlmsg_len(nlmsg_hdr(self._msg)) + def __len__(self): + return capi.nlmsg_len(nlmsg_hdr(self._msg)) - @property - def protocol(self): - return capi.nlmsg_get_proto(self._msg) + @property + def protocol(self): + return capi.nlmsg_get_proto(self._msg) - @protocol.setter - def protocol(self, value): - capi.nlmsg_set_proto(self._msg, value) + @protocol.setter + def protocol(self, value): + capi.nlmsg_set_proto(self._msg, value) - @property - def maxSize(self): - return capi.nlmsg_get_max_size(self._msg) + @property + def maxSize(self): + return capi.nlmsg_get_max_size(self._msg) - @property - def hdr(self): - return capi.nlmsg_hdr(self._msg) + @property + def hdr(self): + return capi.nlmsg_hdr(self._msg) - @property - def data(self): - return capi.nlmsg_data(self._msg) + @property + def data(self): + return capi.nlmsg_data(self._msg) - @property - def attrs(self): - return capi.nlmsg_attrdata(self._msg) + @property + def attrs(self): + return capi.nlmsg_attrdata(self._msg) - def send(self, socket): - socket.send(self) + def send(self, socket): + socket.send(self) class Socket(object): - """Netlink socket""" + """Netlink socket""" - def __init__(self, cb=None): - if cb is None: - self._sock = capi.nl_socket_alloc() - else: - self._sock = capi.nl_socket_alloc_cb(cb) + def __init__(self, cb=None): + if cb is None: + self._sock = capi.nl_socket_alloc() + else: + self._sock = capi.nl_socket_alloc_cb(cb) - if self._sock is None: - raise Exception("NULL pointer returned while allocating socket") + if self._sock is None: + raise Exception("NULL pointer returned while allocating socket") - def __del__(self): - capi.nl_socket_free(self._sock) + def __del__(self): + capi.nl_socket_free(self._sock) - def __str__(self): - return "nlsock<{0}>".format(self.localPort) + def __str__(self): + return "nlsock<{0}>".format(self.localPort) - @property - def local_port(self): - return capi.nl_socket_get_local_port(self._sock) + @property + def local_port(self): + return capi.nl_socket_get_local_port(self._sock) - @local_port.setter - def local_port(self, value): - capi.nl_socket_set_local_port(self._sock, int(value)) + @local_port.setter + def local_port(self, value): + capi.nl_socket_set_local_port(self._sock, int(value)) - @property - def peer_port(self): - return capi.nl_socket_get_peer_port(self._sock) + @property + def peer_port(self): + return capi.nl_socket_get_peer_port(self._sock) - @peer_port.setter - def peer_port(self, value): - capi.nl_socket_set_peer_port(self._sock, int(value)) + @peer_port.setter + def peer_port(self, value): + capi.nl_socket_set_peer_port(self._sock, int(value)) - @property - def peer_groups(self): - return capi.nl_socket_get_peer_groups(self._sock) + @property + def peer_groups(self): + return capi.nl_socket_get_peer_groups(self._sock) - @peer_groups.setter - def peer_groups(self, value): - capi.nl_socket_set_peer_groups(self._sock, value) + @peer_groups.setter + def peer_groups(self, value): + capi.nl_socket_set_peer_groups(self._sock, value) - def set_bufsize(self, rx, tx): - capi.nl_socket_set_buffer_size(self._sock, rx, tx) + def set_bufsize(self, rx, tx): + capi.nl_socket_set_buffer_size(self._sock, rx, tx) - def connect(self, proto): - capi.nl_connect(self._sock, proto) - return self + def connect(self, proto): + capi.nl_connect(self._sock, proto) + return self - def disconnect(self): - capi.nl_close(self._sock) + def disconnect(self): + capi.nl_close(self._sock) - def sendto(self, buf): - ret = capi.nl_sendto(self._sock, buf, len(buf)) - if ret < 0: - raise Exception("Failed to send") - else: - return ret + def sendto(self, buf): + ret = capi.nl_sendto(self._sock, buf, len(buf)) + if ret < 0: + raise Exception("Failed to send") + else: + return ret _sockets = {} def lookup_socket(protocol): - try: - sock = _sockets[protocol] - except KeyError: - sock = Socket() - sock.connect(protocol) - _sockets[protocol] = sock + try: + sock = _sockets[protocol] + except KeyError: + sock = Socket() + sock.connect(protocol) + _sockets[protocol] = sock - return sock + return sock class DumpParams(object): - """Dumping parameters""" + """Dumping parameters""" - def __init__(self, type=NL_DUMP_LINE): - self._dp = capi.alloc_dump_params() - if not self._dp: - raise Exception("Unable to allocate struct nl_dump_params") + def __init__(self, type=NL_DUMP_LINE): + self._dp = capi.alloc_dump_params() + if not self._dp: + raise Exception("Unable to allocate struct nl_dump_params") - self._dp.dp_type = type + self._dp.dp_type = type - def __del__(self): - capi.free_dump_params(self._dp) + def __del__(self): + capi.free_dump_params(self._dp) - @property - def type(self): - return self._dp.dp_type + @property + def type(self): + return self._dp.dp_type - @type.setter - def type(self, value): - self._dp.dp_type = value + @type.setter + def type(self, value): + self._dp.dp_type = value - @property - def prefix(self): - return self._dp.dp_prefix + @property + def prefix(self): + return self._dp.dp_prefix - @prefix.setter - def prefix(self, value): - self._dp.dp_prefix = value + @prefix.setter + def prefix(self, value): + self._dp.dp_prefix = value # underscore this to make sure it is deleted first upon module deletion _defaultDumpParams = DumpParams(type=NL_DUMP_LINE) @@ -251,493 +251,493 @@ _defaultDumpParams = DumpParams(type=NL_DUMP_LINE) ########################################################################### # Cacheable Object (Base Class) class Object(object): - """Cacheable object (base class)""" + """Cacheable object (base class)""" - def __init__(self, obj_name, name, obj=None): - self._obj_name = obj_name - self._name = name - self._modules = [] + def __init__(self, obj_name, name, obj=None): + self._obj_name = obj_name + self._name = name + self._modules = [] - if not obj: - obj = capi.object_alloc_name(self._obj_name) + if not obj: + obj = capi.object_alloc_name(self._obj_name) - self._nl_object = obj + self._nl_object = obj - # Create a clone which stores the original state to notice - # modifications - clone_obj = capi.nl_object_clone(self._nl_object) - self._orig = self._obj2type(clone_obj) + # Create a clone which stores the original state to notice + # modifications + clone_obj = capi.nl_object_clone(self._nl_object) + self._orig = self._obj2type(clone_obj) - def __del__(self): - if not self._nl_object: - raise ValueError() + def __del__(self): + if not self._nl_object: + raise ValueError() - capi.nl_object_put(self._nl_object) + capi.nl_object_put(self._nl_object) - def __str__(self): - if hasattr(self, 'format'): - return self.format() - else: - return capi.nl_object_dump_buf(self._nl_object, 4096).rstrip() + def __str__(self): + if hasattr(self, 'format'): + return self.format() + else: + return capi.nl_object_dump_buf(self._nl_object, 4096).rstrip() - def _new_instance(self): - raise NotImplementedError() + def _new_instance(self): + raise NotImplementedError() - def clone(self): - """Clone object""" - return self._new_instance(capi.nl_object_clone(self._nl_object)) + def clone(self): + """Clone object""" + return self._new_instance(capi.nl_object_clone(self._nl_object)) - def _module_lookup(self, path, constructor=None): - """Lookup object specific module and load it + def _module_lookup(self, path, constructor=None): + """Lookup object specific module and load it - Object implementations consisting of multiple types may - offload some type specific code to separate modules which - are loadable on demand, e.g. a VLAN link or a specific - queueing discipline implementation. + Object implementations consisting of multiple types may + offload some type specific code to separate modules which + are loadable on demand, e.g. a VLAN link or a specific + queueing discipline implementation. - Loads the module `path` and calls the constructor if - supplied or `module`.init() + Loads the module `path` and calls the constructor if + supplied or `module`.init() - The constructor/init function typically assigns a new - object covering the type specific implementation aspects - to the new object, e.g. link.vlan = VLANLink() - """ - try: - tmp = __import__(path) - except ImportError: - return + The constructor/init function typically assigns a new + object covering the type specific implementation aspects + to the new object, e.g. link.vlan = VLANLink() + """ + try: + tmp = __import__(path) + except ImportError: + return - module = sys.modules[path] + module = sys.modules[path] - if constructor: - ret = getattr(module, constructor)(self) - else: - ret = module.init(self) + if constructor: + ret = getattr(module, constructor)(self) + else: + ret = module.init(self) - if ret: - self._modules.append(ret) + if ret: + self._modules.append(ret) - def _module_brief(self): - ret = '' + def _module_brief(self): + ret = '' - for module in self._modules: - if hasattr(module, 'brief'): - ret += module.brief() + for module in self._modules: + if hasattr(module, 'brief'): + ret += module.brief() - return ret + return ret - def dump(self, params=None): - """Dump object as human readable text""" - if params is None: - params = _defaultDumpParams + def dump(self, params=None): + """Dump object as human readable text""" + if params is None: + params = _defaultDumpParams - capi.nl_object_dump(self._nl_object, params._dp) + capi.nl_object_dump(self._nl_object, params._dp) - ##################################################################### - # mark - @property - def mark(self): - if capi.nl_object_is_marked(self.obj): - return True - else: - return False + ##################################################################### + # mark + @property + def mark(self): + if capi.nl_object_is_marked(self.obj): + return True + else: + return False - @mark.setter - def mark(self, value): - if value: - capi.nl_object_mark(self._nl_object) - else: - capi.nl_object_unmark(self._nl_object) + @mark.setter + def mark(self, value): + if value: + capi.nl_object_mark(self._nl_object) + else: + capi.nl_object_unmark(self._nl_object) - ##################################################################### - # shared - @property - def shared(self): - return capi.nl_object_shared(self._nl_object) != 0 + ##################################################################### + # shared + @property + def shared(self): + return capi.nl_object_shared(self._nl_object) != 0 - ##################################################################### - # attrs - @property - def attrs(self): - attr_list = capi.nl_object_attr_list(self._nl_object, 1024) - return re.split('\W+', attr_list[0]) + ##################################################################### + # attrs + @property + def attrs(self): + attr_list = capi.nl_object_attr_list(self._nl_object, 1024) + return re.split('\W+', attr_list[0]) - ##################################################################### - # refcnt - @property - def refcnt(self): - return capi.nl_object_get_refcnt(self._nl_object) + ##################################################################### + # refcnt + @property + def refcnt(self): + return capi.nl_object_get_refcnt(self._nl_object) - # this method resolves multiple levels of sub types to allow - # accessing properties of subclass/subtypes (e.g. link.vlan.id) - def _resolve(self, attr): - obj = self - l = attr.split('.') - while len(l) > 1: - obj = getattr(obj, l.pop(0)) - return (obj, l.pop(0)) + # this method resolves multiple levels of sub types to allow + # accessing properties of subclass/subtypes (e.g. link.vlan.id) + def _resolve(self, attr): + obj = self + l = attr.split('.') + while len(l) > 1: + obj = getattr(obj, l.pop(0)) + return (obj, l.pop(0)) - def _setattr(self, attr, val): - obj, attr = self._resolve(attr) - return setattr(obj, attr, val) + def _setattr(self, attr, val): + obj, attr = self._resolve(attr) + return setattr(obj, attr, val) - def _hasattr(self, attr): - obj, attr = self._resolve(attr) - return hasattr(obj, attr) + def _hasattr(self, attr): + obj, attr = self._resolve(attr) + return hasattr(obj, attr) - def apply(self, attr, val): - try: - d = attrs[self._name + "." + attr] - except KeyError: - raise KeyError("Unknown " + self._name + - " attribute: " + attr) + def apply(self, attr, val): + try: + d = attrs[self._name + "." + attr] + except KeyError: + raise KeyError("Unknown " + self._name + + " attribute: " + attr) - if 'immutable' in d: - raise ImmutableError(attr) + if 'immutable' in d: + raise ImmutableError(attr) - if not self._hasattr(attr): - raise KeyError("Invalid " + self._name + - " attribute: " + attr) - self._setattr(attr, val) + if not self._hasattr(attr): + raise KeyError("Invalid " + self._name + + " attribute: " + attr) + self._setattr(attr, val) class ObjIterator(object): - def __init__(self, cache, obj): - self._cache = cache - self._nl_object = None + def __init__(self, cache, obj): + self._cache = cache + self._nl_object = None - if not obj: - self._end = 1 - else: - capi.nl_object_get(obj) - self._nl_object = obj - self._first = 1 - self._end = 0 + if not obj: + self._end = 1 + else: + capi.nl_object_get(obj) + self._nl_object = obj + self._first = 1 + self._end = 0 - def __del__(self): - if self._nl_object: - capi.nl_object_put(self._nl_object) + def __del__(self): + if self._nl_object: + capi.nl_object_put(self._nl_object) - def __iter__(self): - return self + def __iter__(self): + return self - def get_next(self): - return capi.nl_cache_get_next(self._nl_object) + def get_next(self): + return capi.nl_cache_get_next(self._nl_object) - def next(self): - if self._end: - raise StopIteration() + def next(self): + if self._end: + raise StopIteration() - if self._first: - ret = self._nl_object - self._first = 0 - else: - ret = self.get_next() - if not ret: - self._end = 1 - raise StopIteration() + if self._first: + ret = self._nl_object + self._first = 0 + else: + ret = self.get_next() + if not ret: + self._end = 1 + raise StopIteration() - # return ref of previous element and acquire ref of current - # element to have object stay around until we fetched the - # next ptr - capi.nl_object_put(self._nl_object) - capi.nl_object_get(ret) - self._nl_object = ret + # return ref of previous element and acquire ref of current + # element to have object stay around until we fetched the + # next ptr + capi.nl_object_put(self._nl_object) + capi.nl_object_get(ret) + self._nl_object = ret - # reference used inside object - capi.nl_object_get(ret) - return self._cache._new_object(ret) + # reference used inside object + capi.nl_object_get(ret) + return self._cache._new_object(ret) class ReverseObjIterator(ObjIterator): - def get_next(self): - return capi.nl_cache_get_prev(self._nl_object) + def get_next(self): + return capi.nl_cache_get_prev(self._nl_object) ########################################################################### # Cache class Cache(object): - """Collection of netlink objects""" - def __init__(self): - raise NotImplementedError() + """Collection of netlink objects""" + def __init__(self): + raise NotImplementedError() - def __del(self): - capi.nl_cache_free(self._nl_cache) + def __del(self): + capi.nl_cache_free(self._nl_cache) - def __len__(self): - return capi.nl_cache_nitems(self._nl_cache) + def __len__(self): + return capi.nl_cache_nitems(self._nl_cache) - def __iter__(self): - obj = capi.nl_cache_get_first(self._nl_cache) - return ObjIterator(self, obj) + def __iter__(self): + obj = capi.nl_cache_get_first(self._nl_cache) + return ObjIterator(self, obj) - def __reversed__(self): - obj = capi.nl_cache_get_last(self._nl_cache) - return ReverseObjIterator(self, obj) + def __reversed__(self): + obj = capi.nl_cache_get_last(self._nl_cache) + return ReverseObjIterator(self, obj) - def __contains__(self, item): - obj = capi.nl_cache_search(self._nl_cache, item._nl_object) - if obj is None: - return False - else: - capi.nl_object_put(obj) - return True + def __contains__(self, item): + obj = capi.nl_cache_search(self._nl_cache, item._nl_object) + if obj is None: + return False + else: + capi.nl_object_put(obj) + return True - # called by sub classes to allocate type specific caches by name - def _alloc_cache_name(self, name): - return capi.alloc_cache_name(name) + # called by sub classes to allocate type specific caches by name + def _alloc_cache_name(self, name): + return capi.alloc_cache_name(name) - # implemented by sub classes, must return new instasnce of cacheable - # object - def _new_object(self, obj): - raise NotImplementedError() + # implemented by sub classes, must return new instasnce of cacheable + # object + def _new_object(self, obj): + raise NotImplementedError() - # implemented by sub classes, must return instance of sub class - def _new_cache(self, cache): - raise NotImplementedError() + # implemented by sub classes, must return instance of sub class + def _new_cache(self, cache): + raise NotImplementedError() - def subset(self, filter): - """Return new cache containing subset of cache + def subset(self, filter): + """Return new cache containing subset of cache - Cretes a new cache containing all objects which match the - specified filter. - """ - if not filter: - raise ValueError() + Cretes a new cache containing all objects which match the + specified filter. + """ + if not filter: + raise ValueError() - c = capi.nl_cache_subset(self._nl_cache, filter._nl_object) - return self._new_cache(cache=c) + c = capi.nl_cache_subset(self._nl_cache, filter._nl_object) + return self._new_cache(cache=c) - def dump(self, params=None, filter=None): - """Dump (print) cache as human readable text""" - if not params: - params = _defaultDumpParams + def dump(self, params=None, filter=None): + """Dump (print) cache as human readable text""" + if not params: + params = _defaultDumpParams - if filter: - filter = filter._nl_object + if filter: + filter = filter._nl_object - capi.nl_cache_dump_filter(self._nl_cache, params._dp, filter) + capi.nl_cache_dump_filter(self._nl_cache, params._dp, filter) - def clear(self): - """Remove all cache entries""" - capi.nl_cache_clear(self._nl_cache) + def clear(self): + """Remove all cache entries""" + capi.nl_cache_clear(self._nl_cache) - # Called by sub classes to set first cache argument - def _set_arg1(self, arg): - self.arg1 = arg - capi.nl_cache_set_arg1(self._nl_cache, arg) + # Called by sub classes to set first cache argument + def _set_arg1(self, arg): + self.arg1 = arg + capi.nl_cache_set_arg1(self._nl_cache, arg) - # Called by sub classes to set second cache argument - def _set_arg2(self, arg): - self.arg2 = arg - capi.nl_cache_set_arg2(self._nl_cache, arg) + # Called by sub classes to set second cache argument + def _set_arg2(self, arg): + self.arg2 = arg + capi.nl_cache_set_arg2(self._nl_cache, arg) - def refill(self, socket=None): - """Clear cache and refill it""" - if socket is None: - socket = lookup_socket(self._protocol) + def refill(self, socket=None): + """Clear cache and refill it""" + if socket is None: + socket = lookup_socket(self._protocol) - capi.nl_cache_refill(socket._sock, self._nl_cache) - return self + capi.nl_cache_refill(socket._sock, self._nl_cache) + return self - def resync(self, socket=None, cb=None): - """Synchronize cache with content in kernel""" - if socket is None: - socket = lookup_socket(self._protocol) + def resync(self, socket=None, cb=None): + """Synchronize cache with content in kernel""" + if socket is None: + socket = lookup_socket(self._protocol) - capi.nl_cache_resync(socket._sock, self._nl_cache, cb) + capi.nl_cache_resync(socket._sock, self._nl_cache, cb) - def provide(self): - """Provide this cache to others + def provide(self): + """Provide this cache to others - Caches which have been "provided" are made available - to other users (of the same application context) which - "require" it. F.e. a link cache is generally provided - to allow others to translate interface indexes to - link names - """ + Caches which have been "provided" are made available + to other users (of the same application context) which + "require" it. F.e. a link cache is generally provided + to allow others to translate interface indexes to + link names + """ - capi.nl_cache_mngt_provide(self._nl_cache) + capi.nl_cache_mngt_provide(self._nl_cache) - def unprovide(self): - """Unprovide this cache + def unprovide(self): + """Unprovide this cache - No longer make the cache available to others. If the cache - has been handed out already, that reference will still - be valid. - """ - capi.nl_cache_mngt_unprovide(self._nl_cache) + No longer make the cache available to others. If the cache + has been handed out already, that reference will still + be valid. + """ + capi.nl_cache_mngt_unprovide(self._nl_cache) ########################################################################### # Cache Manager (Work in Progress) NL_AUTO_PROVIDE = 1 class CacheManager(object): - def __init__(self, protocol, flags=None): + def __init__(self, protocol, flags=None): - self._sock = Socket() - self._sock.connect(protocol) + self._sock = Socket() + self._sock.connect(protocol) - if not flags: - flags = NL_AUTO_PROVIDE + if not flags: + flags = NL_AUTO_PROVIDE - self._mngr = cache_mngr_alloc(self._sock._sock, protocol, flags) + self._mngr = cache_mngr_alloc(self._sock._sock, protocol, flags) - def __del__(self): - if self._sock: - self._sock.disconnect() + def __del__(self): + if self._sock: + self._sock.disconnect() - if self._mngr: - capi.nl_cache_mngr_free(self._mngr) + if self._mngr: + capi.nl_cache_mngr_free(self._mngr) - def add(self, name): - capi.cache_mngr_add(self._mngr, name, None, None) + def add(self, name): + capi.cache_mngr_add(self._mngr, name, None, None) ########################################################################### # Address Family class AddressFamily(object): - """Address family representation + """Address family representation - af = AddressFamily('inet6') - # raises: - # - ValueError if family name is not known - # - TypeError if invalid type is specified for family + af = AddressFamily('inet6') + # raises: + # - ValueError if family name is not known + # - TypeError if invalid type is specified for family - print af # => 'inet6' (string representation) - print int(af) # => 10 (numeric representation) - print repr(af) # => AddressFamily('inet6') - """ - def __init__(self, family=socket.AF_UNSPEC): - if isinstance(family, str): - family = capi.nl_str2af(family) - if family < 0: - raise ValueError('Unknown family name') - elif not isinstance(family, int): - raise TypeError() + print af # => 'inet6' (string representation) + print int(af) # => 10 (numeric representation) + print repr(af) # => AddressFamily('inet6') + """ + def __init__(self, family=socket.AF_UNSPEC): + if isinstance(family, str): + family = capi.nl_str2af(family) + if family < 0: + raise ValueError('Unknown family name') + elif not isinstance(family, int): + raise TypeError() - self._family = family + self._family = family - def __str__(self): - return capi.nl_af2str(self._family, 32)[0] + def __str__(self): + return capi.nl_af2str(self._family, 32)[0] - def __int__(self): - return self._family + def __int__(self): + return self._family - def __repr__(self): - return 'AddressFamily({0!r})'.format(str(self)) + def __repr__(self): + return 'AddressFamily({0!r})'.format(str(self)) ########################################################################### # Abstract Address class AbstractAddress(object): - """Abstract address object + """Abstract address object - addr = AbstractAddress('127.0.0.1/8') - print addr # => '127.0.0.1/8' - print addr.prefixlen # => '8' - print addr.family # => 'inet' - print len(addr) # => '4' (32bit ipv4 address) + addr = AbstractAddress('127.0.0.1/8') + print addr # => '127.0.0.1/8' + print addr.prefixlen # => '8' + print addr.family # => 'inet' + print len(addr) # => '4' (32bit ipv4 address) - a = AbstractAddress('10.0.0.1/24') - b = AbstractAddress('10.0.0.2/24') - print a == b # => False + a = AbstractAddress('10.0.0.1/24') + b = AbstractAddress('10.0.0.2/24') + print a == b # => False - """ - def __init__(self, addr): - self._nl_addr = None + """ + def __init__(self, addr): + self._nl_addr = None - if isinstance(addr, str): - addr = capi.addr_parse(addr, socket.AF_UNSPEC) - if addr is None: - raise ValueError('Invalid address format') - elif addr: - capi.nl_addr_get(addr) + if isinstance(addr, str): + addr = capi.addr_parse(addr, socket.AF_UNSPEC) + if addr is None: + raise ValueError('Invalid address format') + elif addr: + capi.nl_addr_get(addr) - self._nl_addr = addr + self._nl_addr = addr - def __del__(self): - if self._nl_addr: - capi.nl_addr_put(self._nl_addr) + def __del__(self): + if self._nl_addr: + capi.nl_addr_put(self._nl_addr) - def __cmp__(self, other): - if isinstance(other, str): - other = AbstractAddress(other) + def __cmp__(self, other): + if isinstance(other, str): + other = AbstractAddress(other) - diff = self.prefixlen - other.prefixlen - if diff == 0: - diff = capi.nl_addr_cmp(self._nl_addr, other._nl_addr) + diff = self.prefixlen - other.prefixlen + if diff == 0: + diff = capi.nl_addr_cmp(self._nl_addr, other._nl_addr) - return diff + return diff - def contains(self, item): - diff = int(self.family) - int(item.family) - if diff: - return False + def contains(self, item): + diff = int(self.family) - int(item.family) + if diff: + return False - if item.prefixlen < self.prefixlen: - return False + if item.prefixlen < self.prefixlen: + return False - diff = capi.nl_addr_cmp_prefix(self._nl_addr, item._nl_addr) - return diff == 0 + diff = capi.nl_addr_cmp_prefix(self._nl_addr, item._nl_addr) + return diff == 0 - def __nonzero__(self): - if self._nl_addr: - return not capi.nl_addr_iszero(self._nl_addr) - else: - return False + def __nonzero__(self): + if self._nl_addr: + return not capi.nl_addr_iszero(self._nl_addr) + else: + return False - def __len__(self): - if self._nl_addr: - return capi.nl_addr_get_len(self._nl_addr) - else: - return 0 + def __len__(self): + if self._nl_addr: + return capi.nl_addr_get_len(self._nl_addr) + else: + return 0 - def __str__(self): - if self._nl_addr: - return capi.nl_addr2str(self._nl_addr, 64)[0] - else: - return "none" + def __str__(self): + if self._nl_addr: + return capi.nl_addr2str(self._nl_addr, 64)[0] + else: + return "none" - @property - def shared(self): - """True if address is shared (multiple users)""" - if self._nl_addr: - return capi.nl_addr_shared(self._nl_addr) != 0 - else: - return False + @property + def shared(self): + """True if address is shared (multiple users)""" + if self._nl_addr: + return capi.nl_addr_shared(self._nl_addr) != 0 + else: + return False - @property - def prefixlen(self): - """Length of prefix (number of bits)""" - if self._nl_addr: - return capi.nl_addr_get_prefixlen(self._nl_addr) - else: - return 0 + @property + def prefixlen(self): + """Length of prefix (number of bits)""" + if self._nl_addr: + return capi.nl_addr_get_prefixlen(self._nl_addr) + else: + return 0 - @prefixlen.setter - def prefixlen(self, value): - if not self._nl_addr: - raise TypeError() + @prefixlen.setter + def prefixlen(self, value): + if not self._nl_addr: + raise TypeError() - capi.nl_addr_set_prefixlen(self._nl_addr, int(value)) + capi.nl_addr_set_prefixlen(self._nl_addr, int(value)) - @property - def family(self): - """Address family""" - f = 0 - if self._nl_addr: - f = capi.nl_addr_get_family(self._nl_addr) + @property + def family(self): + """Address family""" + f = 0 + if self._nl_addr: + f = capi.nl_addr_get_family(self._nl_addr) - return AddressFamily(f) + return AddressFamily(f) - @family.setter - def family(self, value): - if not self._nl_addr: - raise TypeError() + @family.setter + def family(self, value): + if not self._nl_addr: + raise TypeError() - if not isinstance(value, AddressFamily): - value = AddressFamily(value) + if not isinstance(value, AddressFamily): + value = AddressFamily(value) - capi.nl_addr_set_family(self._nl_addr, int(value)) + capi.nl_addr_set_family(self._nl_addr, int(value)) # global dictionay for all object attributes @@ -752,30 +752,30 @@ class AbstractAddress(object): attrs = {} def add_attr(name, **kwds): - attrs[name] = {} - for k in kwds: - attrs[name][k] = kwds[k] + attrs[name] = {} + for k in kwds: + attrs[name][k] = kwds[k] def nlattr(name, **kwds): - """netlink object attribute decorator + """netlink object attribute decorator - decorator used to mark mutable and immutable properties - of netlink objects. All properties marked as such are - regarded to be accessable. + decorator used to mark mutable and immutable properties + of netlink objects. All properties marked as such are + regarded to be accessable. - @netlink.nlattr('my_type.my_attr', type=int) - @property - def my_attr(self): - return self._my_attr + @netlink.nlattr('my_type.my_attr', type=int) + @property + def my_attr(self): + return self._my_attr - """ + """ - attrs[name] = {} - for k in kwds: - attrs[name][k] = kwds[k] + attrs[name] = {} + for k in kwds: + attrs[name][k] = kwds[k] - def wrap_fn(func): - return func + def wrap_fn(func): + return func - return wrap_fn + return wrap_fn diff --git a/python/netlink/route/address.py b/python/netlink/route/address.py index a8da1ed..b5f2448 100644 --- a/python/netlink/route/address.py +++ b/python/netlink/route/address.py @@ -10,8 +10,8 @@ from __future__ import absolute_import __version__ = "1.0" __all__ = [ - 'AddressCache', - 'Address'] + 'AddressCache', + 'Address'] import datetime from .. import core as netlink @@ -23,391 +23,391 @@ from .. import util as util ########################################################################### # Address Cache class AddressCache(netlink.Cache): - """Cache containing network addresses""" + """Cache containing network addresses""" - def __init__(self, cache=None): - if not cache: - cache = self._alloc_cache_name("route/addr") + def __init__(self, cache=None): + if not cache: + cache = self._alloc_cache_name("route/addr") - self._protocol = netlink.NETLINK_ROUTE - self._nl_cache = cache + self._protocol = netlink.NETLINK_ROUTE + self._nl_cache = cache - def __getitem__(self, key): - # Using ifindex=0 here implies that the local address itself - # is unique, otherwise the first occurence is returned. - return self.lookup(0, key) + def __getitem__(self, key): + # Using ifindex=0 here implies that the local address itself + # is unique, otherwise the first occurence is returned. + return self.lookup(0, key) - def lookup(self, ifindex, local): - if type(local) is str: - local = netlink.AbstractAddress(local) + def lookup(self, ifindex, local): + if type(local) is str: + local = netlink.AbstractAddress(local) - addr = capi.rtnl_addr_get(self._nl_cache, ifindex, - local._nl_addr) - if addr is None: - raise KeyError() + addr = capi.rtnl_addr_get(self._nl_cache, ifindex, + local._nl_addr) + if addr is None: + raise KeyError() - return Address._from_capi(addr) + return Address._from_capi(addr) - def _new_object(self, obj): - return Address(obj) + def _new_object(self, obj): + return Address(obj) - def _new_cache(self, cache): - return AddressCache(cache=cache) + def _new_cache(self, cache): + return AddressCache(cache=cache) ########################################################################### # Address Object class Address(netlink.Object): - """Network address""" + """Network address""" - def __init__(self, obj=None): - netlink.Object.__init__(self, "route/addr", "address", obj) - self._rtnl_addr = self._obj2type(self._nl_object) + def __init__(self, obj=None): + netlink.Object.__init__(self, "route/addr", "address", obj) + self._rtnl_addr = self._obj2type(self._nl_object) - @classmethod - def _from_capi(cls, obj): - return cls(capi.addr2obj(obj)) + @classmethod + def _from_capi(cls, obj): + return cls(capi.addr2obj(obj)) - def _obj2type(self, obj): - return capi.obj2addr(obj) + def _obj2type(self, obj): + return capi.obj2addr(obj) - def __cmp__(self, other): - # sort by: - # 1. network link - # 2. address family - # 3. local address (including prefixlen) - diff = self.ifindex - other.ifindex + def __cmp__(self, other): + # sort by: + # 1. network link + # 2. address family + # 3. local address (including prefixlen) + diff = self.ifindex - other.ifindex - if diff == 0: - diff = self.family - other.family - if diff == 0: - diff = capi.nl_addr_cmp(self.local, other.local) + if diff == 0: + diff = self.family - other.family + if diff == 0: + diff = capi.nl_addr_cmp(self.local, other.local) - return diff + return diff - def _new_instance(self, obj): - return Address(obj) + def _new_instance(self, obj): + return Address(obj) - ##################################################################### - # ifindex - @netlink.nlattr('address.ifindex', type=int, immutable=True, - fmt=util.num) - @property - def ifindex(self): - """interface index""" - return capi.rtnl_addr_get_ifindex(self._rtnl_addr) + ##################################################################### + # ifindex + @netlink.nlattr('address.ifindex', type=int, immutable=True, + fmt=util.num) + @property + def ifindex(self): + """interface index""" + return capi.rtnl_addr_get_ifindex(self._rtnl_addr) - @ifindex.setter - def ifindex(self, value): - link = Link.resolve(value) - if not link: - raise ValueError() + @ifindex.setter + def ifindex(self, value): + link = Link.resolve(value) + if not link: + raise ValueError() - self.link = link + self.link = link - ##################################################################### - # link - @netlink.nlattr('address.link', type=str, fmt=util.string) - @property - def link(self): - link = capi.rtnl_addr_get_link(self._rtnl_addr) - if not link: - return None + ##################################################################### + # link + @netlink.nlattr('address.link', type=str, fmt=util.string) + @property + def link(self): + link = capi.rtnl_addr_get_link(self._rtnl_addr) + if not link: + return None - return Link.Link.from_capi(link) + return Link.Link.from_capi(link) - @link.setter - def link(self, value): - if type(value) is str: - try: - value = Link.resolve(value) - except KeyError: - raise ValueError() + @link.setter + def link(self, value): + if type(value) is str: + try: + value = Link.resolve(value) + except KeyError: + raise ValueError() - capi.rtnl_addr_set_link(self._rtnl_addr, value._rtnl_link) + capi.rtnl_addr_set_link(self._rtnl_addr, value._rtnl_link) - # ifindex is immutable but we assume that if _orig does not - # have an ifindex specified, it was meant to be given here - if capi.rtnl_addr_get_ifindex(self._orig) == 0: - capi.rtnl_addr_set_ifindex(self._orig, value.ifindex) + # ifindex is immutable but we assume that if _orig does not + # have an ifindex specified, it was meant to be given here + if capi.rtnl_addr_get_ifindex(self._orig) == 0: + capi.rtnl_addr_set_ifindex(self._orig, value.ifindex) - ##################################################################### - # label - @netlink.nlattr('address.label', type=str, fmt=util.string) - @property - def label(self): - """address label""" - return capi.rtnl_addr_get_label(self._rtnl_addr) + ##################################################################### + # label + @netlink.nlattr('address.label', type=str, fmt=util.string) + @property + def label(self): + """address label""" + return capi.rtnl_addr_get_label(self._rtnl_addr) - @label.setter - def label(self, value): - capi.rtnl_addr_set_label(self._rtnl_addr, value) + @label.setter + def label(self, value): + capi.rtnl_addr_set_label(self._rtnl_addr, value) - ##################################################################### - # flags - @netlink.nlattr('address.flags', type=str, fmt=util.string) - @property - def flags(self): - """Flags + ##################################################################### + # flags + @netlink.nlattr('address.flags', type=str, fmt=util.string) + @property + def flags(self): + """Flags - Setting this property will *Not* reset flags to value you supply in + Setting this property will *Not* reset flags to value you supply in - Examples: - addr.flags = '+xxx' # add xxx flag - addr.flags = 'xxx' # exactly the same - addr.flags = '-xxx' # remove xxx flag - addr.flags = [ '+xxx', '-yyy' ] # list operation - """ - flags = capi.rtnl_addr_get_flags(self._rtnl_addr) - return capi.rtnl_addr_flags2str(flags, 256)[0].split(',') + Examples: + addr.flags = '+xxx' # add xxx flag + addr.flags = 'xxx' # exactly the same + addr.flags = '-xxx' # remove xxx flag + addr.flags = [ '+xxx', '-yyy' ] # list operation + """ + flags = capi.rtnl_addr_get_flags(self._rtnl_addr) + return capi.rtnl_addr_flags2str(flags, 256)[0].split(',') - def _set_flag(self, flag): - if flag.startswith('-'): - i = capi.rtnl_addr_str2flags(flag[1:]) - capi.rtnl_addr_unset_flags(self._rtnl_addr, i) - elif flag.startswith('+'): - i = capi.rtnl_addr_str2flags(flag[1:]) - capi.rtnl_addr_set_flags(self._rtnl_addr, i) - else: - i = capi.rtnl_addr_str2flags(flag) - capi.rtnl_addr_set_flags(self._rtnl_addr, i) + def _set_flag(self, flag): + if flag.startswith('-'): + i = capi.rtnl_addr_str2flags(flag[1:]) + capi.rtnl_addr_unset_flags(self._rtnl_addr, i) + elif flag.startswith('+'): + i = capi.rtnl_addr_str2flags(flag[1:]) + capi.rtnl_addr_set_flags(self._rtnl_addr, i) + else: + i = capi.rtnl_addr_str2flags(flag) + capi.rtnl_addr_set_flags(self._rtnl_addr, i) - @flags.setter - def flags(self, value): - if type(value) is list: - for flag in value: - self._set_flag(flag) - else: - self._set_flag(value) + @flags.setter + def flags(self, value): + if type(value) is list: + for flag in value: + self._set_flag(flag) + else: + self._set_flag(value) - ##################################################################### - # family - @netlink.nlattr('address.family', type=int, immutable=True, - fmt=util.num) - @property - def family(self): - """Address family""" - fam = capi.rtnl_addr_get_family(self._rtnl_addr) - return netlink.AddressFamily(fam) + ##################################################################### + # family + @netlink.nlattr('address.family', type=int, immutable=True, + fmt=util.num) + @property + def family(self): + """Address family""" + fam = capi.rtnl_addr_get_family(self._rtnl_addr) + return netlink.AddressFamily(fam) - @family.setter - def family(self, value): - if not isinstance(value, AddressFamily): - value = AddressFamily(value) + @family.setter + def family(self, value): + if not isinstance(value, AddressFamily): + value = AddressFamily(value) - capi.rtnl_addr_set_family(self._rtnl_addr, int(value)) + capi.rtnl_addr_set_family(self._rtnl_addr, int(value)) - ##################################################################### - # scope - @netlink.nlattr('address.scope', type=int, fmt=util.num) - @property - def scope(self): - """Address scope""" - scope = capi.rtnl_addr_get_scope(self._rtnl_addr) - return capi.rtnl_scope2str(scope, 32)[0] + ##################################################################### + # scope + @netlink.nlattr('address.scope', type=int, fmt=util.num) + @property + def scope(self): + """Address scope""" + scope = capi.rtnl_addr_get_scope(self._rtnl_addr) + return capi.rtnl_scope2str(scope, 32)[0] - @scope.setter - def scope(self, value): - if type(value) is str: - value = capi.rtnl_str2scope(value) - capi.rtnl_addr_set_scope(self._rtnl_addr, value) + @scope.setter + def scope(self, value): + if type(value) is str: + value = capi.rtnl_str2scope(value) + capi.rtnl_addr_set_scope(self._rtnl_addr, value) - ##################################################################### - # local address - @netlink.nlattr('address.local', type=str, immutable=True, - fmt=util.addr) - @property - def local(self): - """Local address""" - a = capi.rtnl_addr_get_local(self._rtnl_addr) - return netlink.AbstractAddress(a) + ##################################################################### + # local address + @netlink.nlattr('address.local', type=str, immutable=True, + fmt=util.addr) + @property + def local(self): + """Local address""" + a = capi.rtnl_addr_get_local(self._rtnl_addr) + return netlink.AbstractAddress(a) - @local.setter - def local(self, value): - a = netlink.AbstractAddress(value) - capi.rtnl_addr_set_local(self._rtnl_addr, a._nl_addr) + @local.setter + def local(self, value): + a = netlink.AbstractAddress(value) + capi.rtnl_addr_set_local(self._rtnl_addr, a._nl_addr) - # local is immutable but we assume that if _orig does not - # have a local address specified, it was meant to be given here - if capi.rtnl_addr_get_local(self._orig) is None: - capi.rtnl_addr_set_local(self._orig, a._nl_addr) + # local is immutable but we assume that if _orig does not + # have a local address specified, it was meant to be given here + if capi.rtnl_addr_get_local(self._orig) is None: + capi.rtnl_addr_set_local(self._orig, a._nl_addr) - ##################################################################### - # Peer address - @netlink.nlattr('address.peer', type=str, fmt=util.addr) - @property - def peer(self): - """Peer address""" - a = capi.rtnl_addr_get_peer(self._rtnl_addr) - return netlink.AbstractAddress(a) + ##################################################################### + # Peer address + @netlink.nlattr('address.peer', type=str, fmt=util.addr) + @property + def peer(self): + """Peer address""" + a = capi.rtnl_addr_get_peer(self._rtnl_addr) + return netlink.AbstractAddress(a) - @peer.setter - def peer(self, value): - a = netlink.AbstractAddress(value) - capi.rtnl_addr_set_peer(self._rtnl_addr, a._nl_addr) + @peer.setter + def peer(self, value): + a = netlink.AbstractAddress(value) + capi.rtnl_addr_set_peer(self._rtnl_addr, a._nl_addr) - ##################################################################### - # Broadcast address - @netlink.nlattr('address.broadcast', type=str, fmt=util.addr) - @property - def broadcast(self): - """Broadcast address""" - a = capi.rtnl_addr_get_broadcast(self._rtnl_addr) - return netlink.AbstractAddress(a) + ##################################################################### + # Broadcast address + @netlink.nlattr('address.broadcast', type=str, fmt=util.addr) + @property + def broadcast(self): + """Broadcast address""" + a = capi.rtnl_addr_get_broadcast(self._rtnl_addr) + return netlink.AbstractAddress(a) - @broadcast.setter - def broadcast(self, value): - a = netlink.AbstractAddress(value) - capi.rtnl_addr_set_broadcast(self._rtnl_addr, a._nl_addr) + @broadcast.setter + def broadcast(self, value): + a = netlink.AbstractAddress(value) + capi.rtnl_addr_set_broadcast(self._rtnl_addr, a._nl_addr) - ##################################################################### - # Multicast address - @netlink.nlattr('address.multicast', type=str, fmt=util.addr) - @property - def multicast(self): - """multicast address""" - a = capi.rtnl_addr_get_multicast(self._rtnl_addr) - return netlink.AbstractAddress(a) + ##################################################################### + # Multicast address + @netlink.nlattr('address.multicast', type=str, fmt=util.addr) + @property + def multicast(self): + """multicast address""" + a = capi.rtnl_addr_get_multicast(self._rtnl_addr) + return netlink.AbstractAddress(a) - @multicast.setter - def multicast(self, value): - try: - a = netlink.AbstractAddress(value) - except ValueError as err: - raise AttributeError('multicast', err) + @multicast.setter + def multicast(self, value): + try: + a = netlink.AbstractAddress(value) + except ValueError as err: + raise AttributeError('multicast', err) - capi.rtnl_addr_set_multicast(self._rtnl_addr, a._nl_addr) + capi.rtnl_addr_set_multicast(self._rtnl_addr, a._nl_addr) - ##################################################################### - # Anycast address - @netlink.nlattr('address.anycast', type=str, fmt=util.addr) - @property - def anycast(self): - """anycast address""" - a = capi.rtnl_addr_get_anycast(self._rtnl_addr) - return netlink.AbstractAddress(a) + ##################################################################### + # Anycast address + @netlink.nlattr('address.anycast', type=str, fmt=util.addr) + @property + def anycast(self): + """anycast address""" + a = capi.rtnl_addr_get_anycast(self._rtnl_addr) + return netlink.AbstractAddress(a) - @anycast.setter - def anycast(self, value): - a = netlink.AbstractAddress(value) - capi.rtnl_addr_set_anycast(self._rtnl_addr, a._nl_addr) + @anycast.setter + def anycast(self, value): + a = netlink.AbstractAddress(value) + capi.rtnl_addr_set_anycast(self._rtnl_addr, a._nl_addr) - ##################################################################### - # Valid lifetime - @netlink.nlattr('address.valid_lifetime', type=int, immutable=True, - fmt=util.num) - @property - def valid_lifetime(self): - """Valid lifetime""" - msecs = capi.rtnl_addr_get_valid_lifetime(self._rtnl_addr) - if msecs == 0xFFFFFFFF: - return None - else: - return datetime.timedelta(seconds=msecs) + ##################################################################### + # Valid lifetime + @netlink.nlattr('address.valid_lifetime', type=int, immutable=True, + fmt=util.num) + @property + def valid_lifetime(self): + """Valid lifetime""" + msecs = capi.rtnl_addr_get_valid_lifetime(self._rtnl_addr) + if msecs == 0xFFFFFFFF: + return None + else: + return datetime.timedelta(seconds=msecs) - @valid_lifetime.setter - def valid_lifetime(self, value): - capi.rtnl_addr_set_valid_lifetime(self._rtnl_addr, int(value)) + @valid_lifetime.setter + def valid_lifetime(self, value): + capi.rtnl_addr_set_valid_lifetime(self._rtnl_addr, int(value)) - ##################################################################### - # Preferred lifetime - @netlink.nlattr('address.preferred_lifetime', type=int, - immutable=True, fmt=util.num) - @property - def preferred_lifetime(self): - """Preferred lifetime""" - msecs = capi.rtnl_addr_get_preferred_lifetime(self._rtnl_addr) - if msecs == 0xFFFFFFFF: - return None - else: - return datetime.timedelta(seconds=msecs) + ##################################################################### + # Preferred lifetime + @netlink.nlattr('address.preferred_lifetime', type=int, + immutable=True, fmt=util.num) + @property + def preferred_lifetime(self): + """Preferred lifetime""" + msecs = capi.rtnl_addr_get_preferred_lifetime(self._rtnl_addr) + if msecs == 0xFFFFFFFF: + return None + else: + return datetime.timedelta(seconds=msecs) - @preferred_lifetime.setter - def preferred_lifetime(self, value): - capi.rtnl_addr_set_preferred_lifetime(self._rtnl_addr, int(value)) + @preferred_lifetime.setter + def preferred_lifetime(self, value): + capi.rtnl_addr_set_preferred_lifetime(self._rtnl_addr, int(value)) - ##################################################################### - # Creation Time - @netlink.nlattr('address.create_time', type=int, immutable=True, - fmt=util.num) - @property - def create_time(self): - """Creation time""" - hsec = capi.rtnl_addr_get_create_time(self._rtnl_addr) - return datetime.timedelta(milliseconds=10*hsec) + ##################################################################### + # Creation Time + @netlink.nlattr('address.create_time', type=int, immutable=True, + fmt=util.num) + @property + def create_time(self): + """Creation time""" + hsec = capi.rtnl_addr_get_create_time(self._rtnl_addr) + return datetime.timedelta(milliseconds=10*hsec) - ##################################################################### - # Last Update - @netlink.nlattr('address.last_update', type=int, immutable=True, - fmt=util.num) - @property - def last_update(self): - """Last update""" - hsec = capi.rtnl_addr_get_last_update_time(self._rtnl_addr) - return datetime.timedelta(milliseconds=10*hsec) + ##################################################################### + # Last Update + @netlink.nlattr('address.last_update', type=int, immutable=True, + fmt=util.num) + @property + def last_update(self): + """Last update""" + hsec = capi.rtnl_addr_get_last_update_time(self._rtnl_addr) + return datetime.timedelta(milliseconds=10*hsec) - ##################################################################### - # add() - def add(self, socket=None, flags=None): - if not socket: - socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) + ##################################################################### + # add() + def add(self, socket=None, flags=None): + if not socket: + socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) - if not flags: - flags = netlink.NLM_F_CREATE + if not flags: + flags = netlink.NLM_F_CREATE - ret = capi.rtnl_addr_add(socket._sock, self._rtnl_addr, flags) - if ret < 0: - raise netlink.KernelError(ret) + ret = capi.rtnl_addr_add(socket._sock, self._rtnl_addr, flags) + if ret < 0: + raise netlink.KernelError(ret) - ##################################################################### - # delete() - def delete(self, socket, flags=0): - """Attempt to delete this address in the kernel""" - ret = capi.rtnl_addr_delete(socket._sock, self._rtnl_addr, flags) - if ret < 0: - raise netlink.KernelError(ret) + ##################################################################### + # delete() + def delete(self, socket, flags=0): + """Attempt to delete this address in the kernel""" + ret = capi.rtnl_addr_delete(socket._sock, self._rtnl_addr, flags) + if ret < 0: + raise netlink.KernelError(ret) - ################################################################### - # private properties - # - # Used for formatting output. USE AT OWN RISK - @property - def _flags(self): - return ','.join(self.flags) + ################################################################### + # private properties + # + # Used for formatting output. USE AT OWN RISK + @property + def _flags(self): + return ','.join(self.flags) - ################################################################### - # - # format(details=False, stats=False) - # - def format(self, details=False, stats=False, nodev=False, indent=''): - """Return address as formatted text""" - fmt = util.MyFormatter(self, indent) + ################################################################### + # + # format(details=False, stats=False) + # + def format(self, details=False, stats=False, nodev=False, indent=''): + """Return address as formatted text""" + fmt = util.MyFormatter(self, indent) - buf = fmt.format('{a|local!b}') + buf = fmt.format('{a|local!b}') - if not nodev: - buf += fmt.format(' {a|ifindex}') + if not nodev: + buf += fmt.format(' {a|ifindex}') - buf += fmt.format(' {a|scope}') + buf += fmt.format(' {a|scope}') - if self.label: - buf += fmt.format(' "{a|label}"') + if self.label: + buf += fmt.format(' "{a|label}"') - buf += fmt.format(' <{a|_flags}>') + buf += fmt.format(' <{a|_flags}>') - if details: - buf += fmt.nl('\t{t|broadcast} {t|multicast}') \ - + fmt.nl('\t{t|peer} {t|anycast}') + if details: + buf += fmt.nl('\t{t|broadcast} {t|multicast}') \ + + fmt.nl('\t{t|peer} {t|anycast}') - if self.valid_lifetime: - buf += fmt.nl('\t{s|valid-lifetime!k} '\ - '{a|valid_lifetime}') + if self.valid_lifetime: + buf += fmt.nl('\t{s|valid-lifetime!k} '\ + '{a|valid_lifetime}') - if self.preferred_lifetime: - buf += fmt.nl('\t{s|preferred-lifetime!k} '\ - '{a|preferred_lifetime}') + if self.preferred_lifetime: + buf += fmt.nl('\t{s|preferred-lifetime!k} '\ + '{a|preferred_lifetime}') - if stats and (self.create_time or self.last_update): - buf += self.nl('\t{s|created!k} {a|create_time}'\ - ' {s|last-updated!k} {a|last_update}') + if stats and (self.create_time or self.last_update): + buf += self.nl('\t{s|created!k} {a|create_time}'\ + ' {s|last-updated!k} {a|last_update}') - return buf + return buf diff --git a/python/netlink/route/link.py b/python/netlink/route/link.py index b7a377a..465b3b3 100644 --- a/python/netlink/route/link.py +++ b/python/netlink/route/link.py @@ -8,26 +8,26 @@ This module provides an interface to view configured network links, modify them and to add and delete virtual network links. The following is a basic example: - import netlink.core as netlink - import netlink.route.link as link + import netlink.core as netlink + import netlink.route.link as link - sock = netlink.Socket() - sock.connect(netlink.NETLINK_ROUTE) + sock = netlink.Socket() + sock.connect(netlink.NETLINK_ROUTE) - cache = link.LinkCache() # create new empty link cache - cache.refill(sock) # fill cache with all configured links - eth0 = cache['eth0'] # lookup link "eth0" - print eth0 # print basic configuration + cache = link.LinkCache() # create new empty link cache + cache.refill(sock) # fill cache with all configured links + eth0 = cache['eth0'] # lookup link "eth0" + print eth0 # print basic configuration The module contains the following public classes: - Link -- Represents a network link. Instances can be created directly - via the constructor (empty link objects) or via the refill() - method of a LinkCache. + via the constructor (empty link objects) or via the refill() + method of a LinkCache. - LinkCache -- Derived from netlink.Cache, holds any number of - network links (Link instances). Main purpose is to keep - a local list of all network links configured in the - kernel. + network links (Link instances). Main purpose is to keep + a local list of all network links configured in the + kernel. The following public functions exist: - get_from_kernel(socket, name) @@ -38,9 +38,9 @@ from __future__ import absolute_import __version__ = "0.1" __all__ = [ - 'LinkCache', - 'Link', - 'get_from_kernel'] + 'LinkCache', + 'Link', + 'get_from_kernel'] import socket import sys @@ -113,477 +113,477 @@ ICMP6_OUTERRORS = 56 ########################################################################### # Link Cache class LinkCache(netlink.Cache): - """Cache of network links""" + """Cache of network links""" - def __init__(self, family=socket.AF_UNSPEC, cache=None): - if not cache: - cache = self._alloc_cache_name("route/link") + def __init__(self, family=socket.AF_UNSPEC, cache=None): + if not cache: + cache = self._alloc_cache_name("route/link") - self._info_module = None - self._protocol = netlink.NETLINK_ROUTE - self._nl_cache = cache - self._set_arg1(family) + self._info_module = None + self._protocol = netlink.NETLINK_ROUTE + self._nl_cache = cache + self._set_arg1(family) - def __getitem__(self, key): - if type(key) is int: - link = capi.rtnl_link_get(self._nl_cache, key) - else: - link = capi.rtnl_link_get_by_name(self._nl_cache, key) + def __getitem__(self, key): + if type(key) is int: + link = capi.rtnl_link_get(self._nl_cache, key) + else: + link = capi.rtnl_link_get_by_name(self._nl_cache, key) - if link is None: - raise KeyError() - else: - return Link.from_capi(link) + if link is None: + raise KeyError() + else: + return Link.from_capi(link) - def _new_object(self, obj): - return Link(obj) + def _new_object(self, obj): + return Link(obj) - def _new_cache(self, cache): - return LinkCache(family=self.arg1, cache=cache) + def _new_cache(self, cache): + return LinkCache(family=self.arg1, cache=cache) ########################################################################### # Link Object class Link(netlink.Object): - """Network link""" + """Network link""" - def __init__(self, obj=None): - netlink.Object.__init__(self, "route/link", "link", obj) - self._rtnl_link = self._obj2type(self._nl_object) + def __init__(self, obj=None): + netlink.Object.__init__(self, "route/link", "link", obj) + self._rtnl_link = self._obj2type(self._nl_object) - if self.type: - self._module_lookup('netlink.route.links.' + self.type) + if self.type: + self._module_lookup('netlink.route.links.' + self.type) - self.inet = inet.InetLink(self) - self.af = {'inet' : self.inet } + self.inet = inet.InetLink(self) + self.af = {'inet' : self.inet } - @classmethod - def from_capi(cls, obj): - return cls(capi.link2obj(obj)) + @classmethod + def from_capi(cls, obj): + return cls(capi.link2obj(obj)) - def _obj2type(self, obj): - return capi.obj2link(obj) + def _obj2type(self, obj): + return capi.obj2link(obj) - def __cmp__(self, other): - return self.ifindex - other.ifindex + def __cmp__(self, other): + return self.ifindex - other.ifindex - def _new_instance(self, obj): - if not obj: - raise ValueError() + def _new_instance(self, obj): + if not obj: + raise ValueError() - return Link(obj) + return Link(obj) - ##################################################################### - # ifindex - @netlink.nlattr('link.ifindex', type=int, immutable=True, fmt=util.num) - @property - def ifindex(self): - """interface index""" - return capi.rtnl_link_get_ifindex(self._rtnl_link) + ##################################################################### + # ifindex + @netlink.nlattr('link.ifindex', type=int, immutable=True, fmt=util.num) + @property + def ifindex(self): + """interface index""" + return capi.rtnl_link_get_ifindex(self._rtnl_link) - @ifindex.setter - def ifindex(self, value): - capi.rtnl_link_set_ifindex(self._rtnl_link, int(value)) + @ifindex.setter + def ifindex(self, value): + capi.rtnl_link_set_ifindex(self._rtnl_link, int(value)) - # ifindex is immutable but we assume that if _orig does not - # have an ifindex specified, it was meant to be given here - if capi.rtnl_link_get_ifindex(self._orig) == 0: - capi.rtnl_link_set_ifindex(self._orig, int(value)) + # ifindex is immutable but we assume that if _orig does not + # have an ifindex specified, it was meant to be given here + if capi.rtnl_link_get_ifindex(self._orig) == 0: + capi.rtnl_link_set_ifindex(self._orig, int(value)) - ##################################################################### - # name - @netlink.nlattr('link.name', type=str, fmt=util.bold) - @property - def name(self): - """Name of link""" - return capi.rtnl_link_get_name(self._rtnl_link) + ##################################################################### + # name + @netlink.nlattr('link.name', type=str, fmt=util.bold) + @property + def name(self): + """Name of link""" + return capi.rtnl_link_get_name(self._rtnl_link) - @name.setter - def name(self, value): - capi.rtnl_link_set_name(self._rtnl_link, value) + @name.setter + def name(self, value): + capi.rtnl_link_set_name(self._rtnl_link, value) - # name is the secondary identifier, if _orig does not have - # the name specified yet, assume it was meant to be specified - # here. ifindex will always take priority, therefore if ifindex - # is specified as well, this will be ignored automatically. - if capi.rtnl_link_get_name(self._orig) is None: - capi.rtnl_link_set_name(self._orig, value) + # name is the secondary identifier, if _orig does not have + # the name specified yet, assume it was meant to be specified + # here. ifindex will always take priority, therefore if ifindex + # is specified as well, this will be ignored automatically. + if capi.rtnl_link_get_name(self._orig) is None: + capi.rtnl_link_set_name(self._orig, value) - ##################################################################### - # flags - @netlink.nlattr('link.flags', type=str, fmt=util.string) - @property - def flags(self): - """Flags - Setting this property will *Not* reset flags to value you supply in - Examples: - link.flags = '+xxx' # add xxx flag - link.flags = 'xxx' # exactly the same - link.flags = '-xxx' # remove xxx flag - link.flags = [ '+xxx', '-yyy' ] # list operation - """ - flags = capi.rtnl_link_get_flags(self._rtnl_link) - return capi.rtnl_link_flags2str(flags, 256)[0].split(',') + ##################################################################### + # flags + @netlink.nlattr('link.flags', type=str, fmt=util.string) + @property + def flags(self): + """Flags + Setting this property will *Not* reset flags to value you supply in + Examples: + link.flags = '+xxx' # add xxx flag + link.flags = 'xxx' # exactly the same + link.flags = '-xxx' # remove xxx flag + link.flags = [ '+xxx', '-yyy' ] # list operation + """ + flags = capi.rtnl_link_get_flags(self._rtnl_link) + return capi.rtnl_link_flags2str(flags, 256)[0].split(',') - def _set_flag(self, flag): - if flag.startswith('-'): - i = capi.rtnl_link_str2flags(flag[1:]) - capi.rtnl_link_unset_flags(self._rtnl_link, i) - elif flag.startswith('+'): - i = capi.rtnl_link_str2flags(flag[1:]) - capi.rtnl_link_set_flags(self._rtnl_link, i) - else: - i = capi.rtnl_link_str2flags(flag) - capi.rtnl_link_set_flags(self._rtnl_link, i) + def _set_flag(self, flag): + if flag.startswith('-'): + i = capi.rtnl_link_str2flags(flag[1:]) + capi.rtnl_link_unset_flags(self._rtnl_link, i) + elif flag.startswith('+'): + i = capi.rtnl_link_str2flags(flag[1:]) + capi.rtnl_link_set_flags(self._rtnl_link, i) + else: + i = capi.rtnl_link_str2flags(flag) + capi.rtnl_link_set_flags(self._rtnl_link, i) - @flags.setter - def flags(self, value): - if not (type(value) is str): - for flag in value: - self._set_flag(flag) - else: - self._set_flag(value) + @flags.setter + def flags(self, value): + if not (type(value) is str): + for flag in value: + self._set_flag(flag) + else: + self._set_flag(value) - ##################################################################### - # mtu - @netlink.nlattr('link.mtu', type=int, fmt=util.num) - @property - def mtu(self): - """Maximum Transmission Unit""" - return capi.rtnl_link_get_mtu(self._rtnl_link) + ##################################################################### + # mtu + @netlink.nlattr('link.mtu', type=int, fmt=util.num) + @property + def mtu(self): + """Maximum Transmission Unit""" + return capi.rtnl_link_get_mtu(self._rtnl_link) - @mtu.setter - def mtu(self, value): - capi.rtnl_link_set_mtu(self._rtnl_link, int(value)) + @mtu.setter + def mtu(self, value): + capi.rtnl_link_set_mtu(self._rtnl_link, int(value)) - ##################################################################### - # family - @netlink.nlattr('link.family', type=int, immutable=True, fmt=util.num) - @property - def family(self): - """Address family""" - return capi.rtnl_link_get_family(self._rtnl_link) + ##################################################################### + # family + @netlink.nlattr('link.family', type=int, immutable=True, fmt=util.num) + @property + def family(self): + """Address family""" + return capi.rtnl_link_get_family(self._rtnl_link) - @family.setter - def family(self, value): - capi.rtnl_link_set_family(self._rtnl_link, value) + @family.setter + def family(self, value): + capi.rtnl_link_set_family(self._rtnl_link, value) - ##################################################################### - # address - @netlink.nlattr('link.address', type=str, fmt=util.addr) - @property - def address(self): - """Hardware address (MAC address)""" - a = capi.rtnl_link_get_addr(self._rtnl_link) - return netlink.AbstractAddress(a) + ##################################################################### + # address + @netlink.nlattr('link.address', type=str, fmt=util.addr) + @property + def address(self): + """Hardware address (MAC address)""" + a = capi.rtnl_link_get_addr(self._rtnl_link) + return netlink.AbstractAddress(a) - @address.setter - def address(self, value): - capi.rtnl_link_set_addr(self._rtnl_link, value._addr) + @address.setter + def address(self, value): + capi.rtnl_link_set_addr(self._rtnl_link, value._addr) - ##################################################################### - # broadcast - @netlink.nlattr('link.broadcast', type=str, fmt=util.addr) - @property - def broadcast(self): - """Hardware broadcast address""" - a = capi.rtnl_link_get_broadcast(self._rtnl_link) - return netlink.AbstractAddress(a) + ##################################################################### + # broadcast + @netlink.nlattr('link.broadcast', type=str, fmt=util.addr) + @property + def broadcast(self): + """Hardware broadcast address""" + a = capi.rtnl_link_get_broadcast(self._rtnl_link) + return netlink.AbstractAddress(a) - @broadcast.setter - def broadcast(self, value): - capi.rtnl_link_set_broadcast(self._rtnl_link, value._addr) + @broadcast.setter + def broadcast(self, value): + capi.rtnl_link_set_broadcast(self._rtnl_link, value._addr) - ##################################################################### - # qdisc - @netlink.nlattr('link.qdisc', type=str, immutable=True, fmt=util.string) - @property - def qdisc(self): - """Name of qdisc (cannot be changed)""" - return capi.rtnl_link_get_qdisc(self._rtnl_link) + ##################################################################### + # qdisc + @netlink.nlattr('link.qdisc', type=str, immutable=True, fmt=util.string) + @property + def qdisc(self): + """Name of qdisc (cannot be changed)""" + return capi.rtnl_link_get_qdisc(self._rtnl_link) - @qdisc.setter - def qdisc(self, value): - capi.rtnl_link_set_qdisc(self._rtnl_link, value) + @qdisc.setter + def qdisc(self, value): + capi.rtnl_link_set_qdisc(self._rtnl_link, value) - ##################################################################### - # txqlen - @netlink.nlattr('link.txqlen', type=int, fmt=util.num) - @property - def txqlen(self): - """Length of transmit queue""" - return capi.rtnl_link_get_txqlen(self._rtnl_link) + ##################################################################### + # txqlen + @netlink.nlattr('link.txqlen', type=int, fmt=util.num) + @property + def txqlen(self): + """Length of transmit queue""" + return capi.rtnl_link_get_txqlen(self._rtnl_link) - @txqlen.setter - def txqlen(self, value): - capi.rtnl_link_set_txqlen(self._rtnl_link, int(value)) + @txqlen.setter + def txqlen(self, value): + capi.rtnl_link_set_txqlen(self._rtnl_link, int(value)) - ##################################################################### - # weight - @netlink.nlattr('link.weight', type=str, fmt=util.string) - @property - def weight(self): - """Weight""" - v = capi.rtnl_link_get_weight(self._rtnl_link) - if v == 4294967295: - return 'max' - else: - return str(v) + ##################################################################### + # weight + @netlink.nlattr('link.weight', type=str, fmt=util.string) + @property + def weight(self): + """Weight""" + v = capi.rtnl_link_get_weight(self._rtnl_link) + if v == 4294967295: + return 'max' + else: + return str(v) - @weight.setter - def weight(self, value): - if value == 'max': - v = 4294967295 - else: - v = int(value) - capi.rtnl_link_set_weight(self._rtnl_link, v) + @weight.setter + def weight(self, value): + if value == 'max': + v = 4294967295 + else: + v = int(value) + capi.rtnl_link_set_weight(self._rtnl_link, v) - ##################################################################### - # arptype - @netlink.nlattr('link.arptype', type=str, immutable=True, fmt=util.string) - @property - def arptype(self): - """Type of link (cannot be changed)""" - type = capi.rtnl_link_get_arptype(self._rtnl_link) - return core_capi.nl_llproto2str(type, 64)[0] + ##################################################################### + # arptype + @netlink.nlattr('link.arptype', type=str, immutable=True, fmt=util.string) + @property + def arptype(self): + """Type of link (cannot be changed)""" + type = capi.rtnl_link_get_arptype(self._rtnl_link) + return core_capi.nl_llproto2str(type, 64)[0] - @arptype.setter - def arptype(self, value): - i = core_capi.nl_str2llproto(value) - capi.rtnl_link_set_arptype(self._rtnl_link, i) + @arptype.setter + def arptype(self, value): + i = core_capi.nl_str2llproto(value) + capi.rtnl_link_set_arptype(self._rtnl_link, i) - ##################################################################### - # operstate - @netlink.nlattr('link.operstate', type=str, immutable=True, - fmt=util.string, title='state') - @property - def operstate(self): - """Operational status""" - operstate = capi.rtnl_link_get_operstate(self._rtnl_link) - return capi.rtnl_link_operstate2str(operstate, 32)[0] + ##################################################################### + # operstate + @netlink.nlattr('link.operstate', type=str, immutable=True, + fmt=util.string, title='state') + @property + def operstate(self): + """Operational status""" + operstate = capi.rtnl_link_get_operstate(self._rtnl_link) + return capi.rtnl_link_operstate2str(operstate, 32)[0] - @operstate.setter - def operstate(self, value): - i = capi.rtnl_link_str2operstate(flag) - capi.rtnl_link_set_operstate(self._rtnl_link, i) + @operstate.setter + def operstate(self, value): + i = capi.rtnl_link_str2operstate(flag) + capi.rtnl_link_set_operstate(self._rtnl_link, i) - ##################################################################### - # mode - @netlink.nlattr('link.mode', type=str, immutable=True, fmt=util.string) - @property - def mode(self): - """Link mode""" - mode = capi.rtnl_link_get_linkmode(self._rtnl_link) - return capi.rtnl_link_mode2str(mode, 32)[0] + ##################################################################### + # mode + @netlink.nlattr('link.mode', type=str, immutable=True, fmt=util.string) + @property + def mode(self): + """Link mode""" + mode = capi.rtnl_link_get_linkmode(self._rtnl_link) + return capi.rtnl_link_mode2str(mode, 32)[0] - @mode.setter - def mode(self, value): - i = capi.rtnl_link_str2mode(flag) - capi.rtnl_link_set_linkmode(self._rtnl_link, i) + @mode.setter + def mode(self, value): + i = capi.rtnl_link_str2mode(flag) + capi.rtnl_link_set_linkmode(self._rtnl_link, i) - ##################################################################### - # alias - @netlink.nlattr('link.alias', type=str, fmt=util.string) - @property - def alias(self): - """Interface alias (SNMP)""" - return capi.rtnl_link_get_ifalias(self._rtnl_link) + ##################################################################### + # alias + @netlink.nlattr('link.alias', type=str, fmt=util.string) + @property + def alias(self): + """Interface alias (SNMP)""" + return capi.rtnl_link_get_ifalias(self._rtnl_link) - @alias.setter - def alias(self, value): - capi.rtnl_link_set_ifalias(self._rtnl_link, value) + @alias.setter + def alias(self, value): + capi.rtnl_link_set_ifalias(self._rtnl_link, value) - ##################################################################### - # type - @netlink.nlattr('link.type', type=str, fmt=util.string) - @property - def type(self): - """Link type""" - return capi.rtnl_link_get_type(self._rtnl_link) + ##################################################################### + # type + @netlink.nlattr('link.type', type=str, fmt=util.string) + @property + def type(self): + """Link type""" + return capi.rtnl_link_get_type(self._rtnl_link) - @type.setter - def type(self, value): - if capi.rtnl_link_set_type(self._rtnl_link, value) < 0: - raise NameError("unknown info type") + @type.setter + def type(self, value): + if capi.rtnl_link_set_type(self._rtnl_link, value) < 0: + raise NameError("unknown info type") - self._module_lookup('netlink.route.links.' + value) + self._module_lookup('netlink.route.links.' + value) - ##################################################################### - # get_stat() - def get_stat(self, stat): - """Retrieve statistical information""" - if type(stat) is str: - stat = capi.rtnl_link_str2stat(stat) - if stat < 0: - raise NameError("unknown name of statistic") + ##################################################################### + # get_stat() + def get_stat(self, stat): + """Retrieve statistical information""" + if type(stat) is str: + stat = capi.rtnl_link_str2stat(stat) + if stat < 0: + raise NameError("unknown name of statistic") - return capi.rtnl_link_get_stat(self._rtnl_link, stat) + return capi.rtnl_link_get_stat(self._rtnl_link, stat) - ##################################################################### - # add() - def add(self, socket=None, flags=None): - if not socket: - socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) + ##################################################################### + # add() + def add(self, socket=None, flags=None): + if not socket: + socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) - if not flags: - flags = netlink.NLM_F_CREATE + if not flags: + flags = netlink.NLM_F_CREATE - ret = capi.rtnl_link_add(socket._sock, self._rtnl_link, flags) - if ret < 0: - raise netlink.KernelError(ret) + ret = capi.rtnl_link_add(socket._sock, self._rtnl_link, flags) + if ret < 0: + raise netlink.KernelError(ret) - ##################################################################### - # change() - def change(self, socket=None, flags=0): - """Commit changes made to the link object""" - if not socket: - socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) + ##################################################################### + # change() + def change(self, socket=None, flags=0): + """Commit changes made to the link object""" + if not socket: + socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) - if not self._orig: - raise NetlinkError("Original link not available") - ret = capi.rtnl_link_change(socket._sock, self._orig, self._rtnl_link, flags) - if ret < 0: - raise netlink.KernelError(ret) + if not self._orig: + raise NetlinkError("Original link not available") + ret = capi.rtnl_link_change(socket._sock, self._orig, self._rtnl_link, flags) + if ret < 0: + raise netlink.KernelError(ret) - ##################################################################### - # delete() - def delete(self, socket=None): - """Attempt to delete this link in the kernel""" - if not socket: - socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) + ##################################################################### + # delete() + def delete(self, socket=None): + """Attempt to delete this link in the kernel""" + if not socket: + socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) - ret = capi.rtnl_link_delete(socket._sock, self._rtnl_link) - if ret < 0: - raise netlink.KernelError(ret) + ret = capi.rtnl_link_delete(socket._sock, self._rtnl_link) + if ret < 0: + raise netlink.KernelError(ret) - ################################################################### - # private properties - # - # Used for formatting output. USE AT OWN RISK - @property - def _state(self): - if 'up' in self.flags: - buf = util.good('up') - if 'lowerup' not in self.flags: - buf += ' ' + util.bad('no-carrier') - else: - buf = util.bad('down') - return buf + ################################################################### + # private properties + # + # Used for formatting output. USE AT OWN RISK + @property + def _state(self): + if 'up' in self.flags: + buf = util.good('up') + if 'lowerup' not in self.flags: + buf += ' ' + util.bad('no-carrier') + else: + buf = util.bad('down') + return buf - @property - def _brief(self): - return self._module_brief() + self._foreach_af('brief') + @property + def _brief(self): + return self._module_brief() + self._foreach_af('brief') - @property - def _flags(self): - ignore = ['up', 'running', 'lowerup'] - return ','.join([flag for flag in self.flags if flag not in ignore]) + @property + def _flags(self): + ignore = ['up', 'running', 'lowerup'] + return ','.join([flag for flag in self.flags if flag not in ignore]) - def _foreach_af(self, name, args=None): - buf = '' - for af in self.af: - try: - func = getattr(self.af[af], name) - s = str(func(args)) - if len(s) > 0: - buf += ' ' + s - except AttributeError: - pass - return buf + def _foreach_af(self, name, args=None): + buf = '' + for af in self.af: + try: + func = getattr(self.af[af], name) + s = str(func(args)) + if len(s) > 0: + buf += ' ' + s + except AttributeError: + pass + return buf - ################################################################### - # - # format(details=False, stats=False) - # - def format(self, details=False, stats=False, indent=''): - """Return link as formatted text""" - fmt = util.MyFormatter(self, indent) + ################################################################### + # + # format(details=False, stats=False) + # + def format(self, details=False, stats=False, indent=''): + """Return link as formatted text""" + fmt = util.MyFormatter(self, indent) - buf = fmt.format('{a|ifindex} {a|name} {a|arptype} {a|address} '\ - '{a|_state} <{a|_flags}> {a|_brief}') + buf = fmt.format('{a|ifindex} {a|name} {a|arptype} {a|address} '\ + '{a|_state} <{a|_flags}> {a|_brief}') - if details: - buf += fmt.nl('\t{t|mtu} {t|txqlen} {t|weight} '\ - '{t|qdisc} {t|operstate}') - buf += fmt.nl('\t{t|broadcast} {t|alias}') + if details: + buf += fmt.nl('\t{t|mtu} {t|txqlen} {t|weight} '\ + '{t|qdisc} {t|operstate}') + buf += fmt.nl('\t{t|broadcast} {t|alias}') - buf += self._foreach_af('details', fmt) + buf += self._foreach_af('details', fmt) - if stats: - l = [['Packets', RX_PACKETS, TX_PACKETS], - ['Bytes', RX_BYTES, TX_BYTES], - ['Errors', RX_ERRORS, TX_ERRORS], - ['Dropped', RX_DROPPED, TX_DROPPED], - ['Compressed', RX_COMPRESSED, TX_COMPRESSED], - ['FIFO Errors', RX_FIFO_ERR, TX_FIFO_ERR], - ['Length Errors', RX_LEN_ERR, None], - ['Over Errors', RX_OVER_ERR, None], - ['CRC Errors', RX_CRC_ERR, None], - ['Frame Errors', RX_FRAME_ERR, None], - ['Missed Errors', RX_MISSED_ERR, None], - ['Abort Errors', None, TX_ABORT_ERR], - ['Carrier Errors', None, TX_CARRIER_ERR], - ['Heartbeat Errors', None, TX_HBEAT_ERR], - ['Window Errors', None, TX_WIN_ERR], - ['Collisions', None, COLLISIONS], - ['Multicast', None, MULTICAST], - ['', None, None], - ['Ipv6:', None, None], - ['Packets', IP6_INPKTS, IP6_OUTPKTS], - ['Bytes', IP6_INOCTETS, IP6_OUTOCTETS], - ['Discards', IP6_INDISCARDS, IP6_OUTDISCARDS], - ['Multicast Packets', IP6_INMCASTPKTS, IP6_OUTMCASTPKTS], - ['Multicast Bytes', IP6_INMCASTOCTETS, IP6_OUTMCASTOCTETS], - ['Broadcast Packets', IP6_INBCASTPKTS, IP6_OUTBCASTPKTS], - ['Broadcast Bytes', IP6_INBCASTOCTETS, IP6_OUTBCASTOCTETS], - ['Delivers', IP6_INDELIVERS, None], - ['Forwarded', None, IP6_OUTFORWDATAGRAMS], - ['No Routes', IP6_INNOROUTES, IP6_OUTNOROUTES], - ['Header Errors', IP6_INHDRERRORS, None], - ['Too Big Errors', IP6_INTOOBIGERRORS, None], - ['Address Errors', IP6_INADDRERRORS, None], - ['Unknown Protocol', IP6_INUNKNOWNPROTOS, None], - ['Truncated Packets', IP6_INTRUNCATEDPKTS, None], - ['Reasm Timeouts', IP6_REASMTIMEOUT, None], - ['Reasm Requests', IP6_REASMREQDS, None], - ['Reasm Failures', IP6_REASMFAILS, None], - ['Reasm OK', IP6_REASMOKS, None], - ['Frag Created', None, IP6_FRAGCREATES], - ['Frag Failures', None, IP6_FRAGFAILS], - ['Frag OK', None, IP6_FRAGOKS], - ['', None, None], - ['ICMPv6:', None, None], - ['Messages', ICMP6_INMSGS, ICMP6_OUTMSGS], - ['Errors', ICMP6_INERRORS, ICMP6_OUTERRORS]] + if stats: + l = [['Packets', RX_PACKETS, TX_PACKETS], + ['Bytes', RX_BYTES, TX_BYTES], + ['Errors', RX_ERRORS, TX_ERRORS], + ['Dropped', RX_DROPPED, TX_DROPPED], + ['Compressed', RX_COMPRESSED, TX_COMPRESSED], + ['FIFO Errors', RX_FIFO_ERR, TX_FIFO_ERR], + ['Length Errors', RX_LEN_ERR, None], + ['Over Errors', RX_OVER_ERR, None], + ['CRC Errors', RX_CRC_ERR, None], + ['Frame Errors', RX_FRAME_ERR, None], + ['Missed Errors', RX_MISSED_ERR, None], + ['Abort Errors', None, TX_ABORT_ERR], + ['Carrier Errors', None, TX_CARRIER_ERR], + ['Heartbeat Errors', None, TX_HBEAT_ERR], + ['Window Errors', None, TX_WIN_ERR], + ['Collisions', None, COLLISIONS], + ['Multicast', None, MULTICAST], + ['', None, None], + ['Ipv6:', None, None], + ['Packets', IP6_INPKTS, IP6_OUTPKTS], + ['Bytes', IP6_INOCTETS, IP6_OUTOCTETS], + ['Discards', IP6_INDISCARDS, IP6_OUTDISCARDS], + ['Multicast Packets', IP6_INMCASTPKTS, IP6_OUTMCASTPKTS], + ['Multicast Bytes', IP6_INMCASTOCTETS, IP6_OUTMCASTOCTETS], + ['Broadcast Packets', IP6_INBCASTPKTS, IP6_OUTBCASTPKTS], + ['Broadcast Bytes', IP6_INBCASTOCTETS, IP6_OUTBCASTOCTETS], + ['Delivers', IP6_INDELIVERS, None], + ['Forwarded', None, IP6_OUTFORWDATAGRAMS], + ['No Routes', IP6_INNOROUTES, IP6_OUTNOROUTES], + ['Header Errors', IP6_INHDRERRORS, None], + ['Too Big Errors', IP6_INTOOBIGERRORS, None], + ['Address Errors', IP6_INADDRERRORS, None], + ['Unknown Protocol', IP6_INUNKNOWNPROTOS, None], + ['Truncated Packets', IP6_INTRUNCATEDPKTS, None], + ['Reasm Timeouts', IP6_REASMTIMEOUT, None], + ['Reasm Requests', IP6_REASMREQDS, None], + ['Reasm Failures', IP6_REASMFAILS, None], + ['Reasm OK', IP6_REASMOKS, None], + ['Frag Created', None, IP6_FRAGCREATES], + ['Frag Failures', None, IP6_FRAGFAILS], + ['Frag OK', None, IP6_FRAGOKS], + ['', None, None], + ['ICMPv6:', None, None], + ['Messages', ICMP6_INMSGS, ICMP6_OUTMSGS], + ['Errors', ICMP6_INERRORS, ICMP6_OUTERRORS]] - buf += '\n\t%s%s%s%s\n' % (33 * ' ', util.title('RX'), - 15 * ' ', util.title('TX')) + buf += '\n\t%s%s%s%s\n' % (33 * ' ', util.title('RX'), + 15 * ' ', util.title('TX')) - for row in l: - row[0] = util.kw(row[0]) - row[1] = self.get_stat(row[1]) if row[1] else '' - row[2] = self.get_stat(row[2]) if row[2] else '' - buf += '\t{0:27} {1:>16} {2:>16}\n'.format(*row) + for row in l: + row[0] = util.kw(row[0]) + row[1] = self.get_stat(row[1]) if row[1] else '' + row[2] = self.get_stat(row[2]) if row[2] else '' + buf += '\t{0:27} {1:>16} {2:>16}\n'.format(*row) - buf += self._foreach_af('stats') + buf += self._foreach_af('stats') - return buf + return buf def get(name, socket=None): - """Lookup Link object directly from kernel""" - if not name: - raise ValueError() + """Lookup Link object directly from kernel""" + if not name: + raise ValueError() - if not socket: - socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) + if not socket: + socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) - link = capi.get_from_kernel(socket._sock, 0, name) - if not link: - return None + link = capi.get_from_kernel(socket._sock, 0, name) + if not link: + return None - return Link.from_capi(link) + return Link.from_capi(link) _link_cache = LinkCache() def resolve(name): - _link_cache.refill() - return _link_cache[name] + _link_cache.refill() + return _link_cache[name] diff --git a/python/netlink/route/links/dummy.py b/python/netlink/route/links/dummy.py index caf3ba7..13b3077 100644 --- a/python/netlink/route/links/dummy.py +++ b/python/netlink/route/links/dummy.py @@ -14,12 +14,12 @@ __all__ = ['init'] from ... import core as netlink from .. import capi as capi class DummyLink(object): - def __init__(self, link): - self._rtnl_link = link + def __init__(self, link): + self._rtnl_link = link - def brief(self): - return 'dummy' + def brief(self): + return 'dummy' def init(link): - link.dummy = DummyLink(link._rtnl_link) - return link.dummy + link.dummy = DummyLink(link._rtnl_link) + return link.dummy diff --git a/python/netlink/route/links/inet.py b/python/netlink/route/links/inet.py index b5b1152..1a13349 100644 --- a/python/netlink/route/links/inet.py +++ b/python/netlink/route/links/inet.py @@ -41,98 +41,98 @@ DEVCONF_PROXY_ARP_PVLAN = 25 DEVCONF_MAX = DEVCONF_PROXY_ARP_PVLAN def _resolve(id): - if type(id) is str: - id = capi.rtnl_link_inet_str2devconf(id)[0] - if id < 0: - raise NameError("unknown configuration id") - return id + if type(id) is str: + id = capi.rtnl_link_inet_str2devconf(id)[0] + if id < 0: + raise NameError("unknown configuration id") + return id class InetLink(object): - def __init__(self, link): - self._link = link + def __init__(self, link): + self._link = link - def details(self, fmt): - buf = fmt.nl('\n\t{0}\n\t'.format(util.title('Configuration:'))) + def details(self, fmt): + buf = fmt.nl('\n\t{0}\n\t'.format(util.title('Configuration:'))) - for i in range(DEVCONF_FORWARDING,DEVCONF_MAX+1): - if i & 1 and i > 1: - buf += fmt.nl('\t') - txt = util.kw(capi.rtnl_link_inet_devconf2str(i, 32)[0]) - buf += fmt.format('{0:28s} {1:12} ', txt, - self.get_conf(i)) + for i in range(DEVCONF_FORWARDING,DEVCONF_MAX+1): + if i & 1 and i > 1: + buf += fmt.nl('\t') + txt = util.kw(capi.rtnl_link_inet_devconf2str(i, 32)[0]) + buf += fmt.format('{0:28s} {1:12} ', txt, + self.get_conf(i)) - return buf + return buf - def get_conf(self, id): - return capi.inet_get_conf(self._link._rtnl_link, _resolve(id)) + def get_conf(self, id): + return capi.inet_get_conf(self._link._rtnl_link, _resolve(id)) - def set_conf(self, id, value): - return capi.rtnl_link_inet_set_conf(self._link._rtnl_link, - _resolve(id), int(value)) + def set_conf(self, id, value): + return capi.rtnl_link_inet_set_conf(self._link._rtnl_link, + _resolve(id), int(value)) - @netlink.nlattr('link.inet.forwarding', type=bool, fmt=util.bool) - @property - def forwarding(self): - return bool(self.get_conf(DEVCONF_FORWARDING)) + @netlink.nlattr('link.inet.forwarding', type=bool, fmt=util.bool) + @property + def forwarding(self): + return bool(self.get_conf(DEVCONF_FORWARDING)) - @forwarding.setter - def forwarding(self, value): - self.set_conf(DEVCONF_FORWARDING, int(value)) + @forwarding.setter + def forwarding(self, value): + self.set_conf(DEVCONF_FORWARDING, int(value)) - @netlink.nlattr('link.inet.mc_forwarding', type=bool, fmt=util.bool) - @property - def mc_forwarding(self): - return bool(self.get_conf(DEVCONF_MC_FORWARDING)) + @netlink.nlattr('link.inet.mc_forwarding', type=bool, fmt=util.bool) + @property + def mc_forwarding(self): + return bool(self.get_conf(DEVCONF_MC_FORWARDING)) - @mc_forwarding.setter - def mc_forwarding(self, value): - self.set_conf(DEVCONF_MC_FORWARDING, int(value)) + @mc_forwarding.setter + def mc_forwarding(self, value): + self.set_conf(DEVCONF_MC_FORWARDING, int(value)) - @netlink.nlattr('link.inet.proxy_arp', type=bool, fmt=util.bool) - @property - def proxy_arp(self): - return bool(self.get_conf(DEVCONF_PROXY_ARP)) + @netlink.nlattr('link.inet.proxy_arp', type=bool, fmt=util.bool) + @property + def proxy_arp(self): + return bool(self.get_conf(DEVCONF_PROXY_ARP)) - @proxy_arp.setter - def proxy_arp(self, value): - self.set_conf(DEVCONF_PROXY_ARP, int(value)) + @proxy_arp.setter + def proxy_arp(self, value): + self.set_conf(DEVCONF_PROXY_ARP, int(value)) - @netlink.nlattr('link.inet.accept_redirects', type=bool, fmt=util.bool) - @property - def accept_redirects(self): - return bool(self.get_conf(DEVCONF_ACCEPT_REDIRECTS)) + @netlink.nlattr('link.inet.accept_redirects', type=bool, fmt=util.bool) + @property + def accept_redirects(self): + return bool(self.get_conf(DEVCONF_ACCEPT_REDIRECTS)) - @accept_redirects.setter - def accept_redirects(self, value): - self.set_conf(DEVCONF_ACCEPT_REDIRECTS, int(value)) + @accept_redirects.setter + def accept_redirects(self, value): + self.set_conf(DEVCONF_ACCEPT_REDIRECTS, int(value)) - @netlink.nlattr('link.inet.secure_redirects', type=bool, fmt=util.bool) - @property - def secure_redirects(self): - return bool(self.get_conf(DEVCONF_SECURE_REDIRECTS)) + @netlink.nlattr('link.inet.secure_redirects', type=bool, fmt=util.bool) + @property + def secure_redirects(self): + return bool(self.get_conf(DEVCONF_SECURE_REDIRECTS)) - @secure_redirects.setter - def secure_redirects(self, value): - self.set_conf(DEVCONF_SECURE_REDIRECTS, int(value)) + @secure_redirects.setter + def secure_redirects(self, value): + self.set_conf(DEVCONF_SECURE_REDIRECTS, int(value)) - @netlink.nlattr('link.inet.send_redirects', type=bool, fmt=util.bool) - @property - def send_redirects(self): - return bool(self.get_conf(DEVCONF_SEND_REDIRECTS)) + @netlink.nlattr('link.inet.send_redirects', type=bool, fmt=util.bool) + @property + def send_redirects(self): + return bool(self.get_conf(DEVCONF_SEND_REDIRECTS)) - @send_redirects.setter - def send_redirects(self, value): - self.set_conf(DEVCONF_SEND_REDIRECTS, int(value)) + @send_redirects.setter + def send_redirects(self, value): + self.set_conf(DEVCONF_SEND_REDIRECTS, int(value)) - @netlink.nlattr('link.inet.shared_media', type=bool, fmt=util.bool) - @property - def shared_media(self): - return bool(self.get_conf(DEVCONF_SHARED_MEDIA)) + @netlink.nlattr('link.inet.shared_media', type=bool, fmt=util.bool) + @property + def shared_media(self): + return bool(self.get_conf(DEVCONF_SHARED_MEDIA)) - @shared_media.setter - def shared_media(self, value): - self.set_conf(DEVCONF_SHARED_MEDIA, int(value)) + @shared_media.setter + def shared_media(self, value): + self.set_conf(DEVCONF_SHARED_MEDIA, int(value)) # IPV4_DEVCONF_RP_FILTER, # IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE, diff --git a/python/netlink/route/links/vlan.py b/python/netlink/route/links/vlan.py index bb339d0..d13a8c6 100644 --- a/python/netlink/route/links/vlan.py +++ b/python/netlink/route/links/vlan.py @@ -12,64 +12,64 @@ from __future__ import absolute_import from ... import core as netlink from .. import capi as capi class VLANLink(object): - def __init__(self, link): - self._link = link + def __init__(self, link): + self._link = link - ################################################################### - # id - @netlink.nlattr('link.vlan.id', type=int) - @property - def id(self): - """vlan identifier""" - return capi.rtnl_link_vlan_get_id(self._link) + ################################################################### + # id + @netlink.nlattr('link.vlan.id', type=int) + @property + def id(self): + """vlan identifier""" + return capi.rtnl_link_vlan_get_id(self._link) - @id.setter - def id(self, value): - capi.rtnl_link_vlan_set_id(self._link, int(value)) + @id.setter + def id(self, value): + capi.rtnl_link_vlan_set_id(self._link, int(value)) - ################################################################### - # flags - @netlink.nlattr('link.vlan.flags', type=str) - @property - def flags(self): - """ VLAN flags - Setting this property will *Not* reset flags to value you supply in - Examples: - link.flags = '+xxx' # add xxx flag - link.flags = 'xxx' # exactly the same - link.flags = '-xxx' # remove xxx flag - link.flags = [ '+xxx', '-yyy' ] # list operation - """ - flags = capi.rtnl_link_vlan_get_flags(self._link) - return capi.rtnl_link_vlan_flags2str(flags, 256)[0].split(',') + ################################################################### + # flags + @netlink.nlattr('link.vlan.flags', type=str) + @property + def flags(self): + """ VLAN flags + Setting this property will *Not* reset flags to value you supply in + Examples: + link.flags = '+xxx' # add xxx flag + link.flags = 'xxx' # exactly the same + link.flags = '-xxx' # remove xxx flag + link.flags = [ '+xxx', '-yyy' ] # list operation + """ + flags = capi.rtnl_link_vlan_get_flags(self._link) + return capi.rtnl_link_vlan_flags2str(flags, 256)[0].split(',') - def _set_flag(self, flag): - if flag.startswith('-'): - i = capi.rtnl_link_vlan_str2flags(flag[1:]) - capi.rtnl_link_vlan_unset_flags(self._link, i) - elif flag.startswith('+'): - i = capi.rtnl_link_vlan_str2flags(flag[1:]) - capi.rtnl_link_vlan_set_flags(self._link, i) - else: - i = capi.rtnl_link_vlan_str2flags(flag) - capi.rtnl_link_vlan_set_flags(self._link, i) + def _set_flag(self, flag): + if flag.startswith('-'): + i = capi.rtnl_link_vlan_str2flags(flag[1:]) + capi.rtnl_link_vlan_unset_flags(self._link, i) + elif flag.startswith('+'): + i = capi.rtnl_link_vlan_str2flags(flag[1:]) + capi.rtnl_link_vlan_set_flags(self._link, i) + else: + i = capi.rtnl_link_vlan_str2flags(flag) + capi.rtnl_link_vlan_set_flags(self._link, i) - @flags.setter - def flags(self, value): - if type(value) is list: - for flag in value: - self._set_flag(flag) - else: - self._set_flag(value) + @flags.setter + def flags(self, value): + if type(value) is list: + for flag in value: + self._set_flag(flag) + else: + self._set_flag(value) - ################################################################### - # TODO: - # - ingress map - # - egress map + ################################################################### + # TODO: + # - ingress map + # - egress map - def brief(self): - return 'vlan-id {0}'.format(self.id) + def brief(self): + return 'vlan-id {0}'.format(self.id) def init(link): - link.vlan = VLANLink(link._link) - return link.vlan + link.vlan = VLANLink(link._link) + return link.vlan diff --git a/python/netlink/route/qdisc/htb.py b/python/netlink/route/qdisc/htb.py index 23c7f75..799ce48 100644 --- a/python/netlink/route/qdisc/htb.py +++ b/python/netlink/route/qdisc/htb.py @@ -14,150 +14,150 @@ from .. import capi as capi from .. import tc as tc class HTBQdisc(object): - def __init__(self, qdisc): - self._qdisc = qdisc + def __init__(self, qdisc): + self._qdisc = qdisc - ################################################################### - # default class - @netlink.nlattr('qdisc.htb.default_class', type=int) - @property - def default_class(self): - return tc.Handle(capi.rtnl_htb_get_defcls(self._qdisc._rtnl_qdisc)) + ################################################################### + # default class + @netlink.nlattr('qdisc.htb.default_class', type=int) + @property + def default_class(self): + return tc.Handle(capi.rtnl_htb_get_defcls(self._qdisc._rtnl_qdisc)) - @default_class.setter - def default_class(self, value): - capi.rtnl_htb_set_defcls(self._qdisc._rtnl_qdisc, int(value)) + @default_class.setter + def default_class(self, value): + capi.rtnl_htb_set_defcls(self._qdisc._rtnl_qdisc, int(value)) - ##################################################################### - # r2q - @netlink.nlattr('qdisc.htb.r2q', type=int) - @property - def r2q(self): - return capi.rtnl_htb_get_rate2quantum(self._qdisc._rtnl_qdisc) + ##################################################################### + # r2q + @netlink.nlattr('qdisc.htb.r2q', type=int) + @property + def r2q(self): + return capi.rtnl_htb_get_rate2quantum(self._qdisc._rtnl_qdisc) - @r2q.setter - def r2q(self, value): - capi.rtnl_htb_get_rate2quantum(self._qdisc._rtnl_qdisc, - int(value)) + @r2q.setter + def r2q(self, value): + capi.rtnl_htb_get_rate2quantum(self._qdisc._rtnl_qdisc, + int(value)) - def brief(self): - fmt = util.MyFormatter(self) + def brief(self): + fmt = util.MyFormatter(self) - ret = ' {s|default-class!k} {a|default_class}' + ret = ' {s|default-class!k} {a|default_class}' - if self.r2q: - ret += ' {s|r2q!k} {a|r2q}' + if self.r2q: + ret += ' {s|r2q!k} {a|r2q}' - return fmt.format(ret) + return fmt.format(ret) class HTBClass(object): - def __init__(self, cl): - self._class = cl + def __init__(self, cl): + self._class = cl - ##################################################################### - # rate - @netlink.nlattr('class.htb.rate', type=str) - @property - def rate(self): - rate = capi.rtnl_htb_get_rate(self._class._rtnl_class) - return util.Rate(rate) + ##################################################################### + # rate + @netlink.nlattr('class.htb.rate', type=str) + @property + def rate(self): + rate = capi.rtnl_htb_get_rate(self._class._rtnl_class) + return util.Rate(rate) - @rate.setter - def rate(self, value): - capi.rtnl_htb_set_rate(self._class._rtnl_class, int(value)) + @rate.setter + def rate(self, value): + capi.rtnl_htb_set_rate(self._class._rtnl_class, int(value)) - ##################################################################### - # ceil - @netlink.nlattr('class.htb.ceil', type=str) - @property - def ceil(self): - ceil = capi.rtnl_htb_get_ceil(self._class._rtnl_class) - return util.Rate(ceil) + ##################################################################### + # ceil + @netlink.nlattr('class.htb.ceil', type=str) + @property + def ceil(self): + ceil = capi.rtnl_htb_get_ceil(self._class._rtnl_class) + return util.Rate(ceil) - @ceil.setter - def ceil(self, value): - capi.rtnl_htb_set_ceil(self._class._rtnl_class, int(value)) + @ceil.setter + def ceil(self, value): + capi.rtnl_htb_set_ceil(self._class._rtnl_class, int(value)) - ##################################################################### - # burst - @netlink.nlattr('class.htb.burst', type=str) - @property - def burst(self): - burst = capi.rtnl_htb_get_rbuffer(self._class._rtnl_class) - return util.Size(burst) + ##################################################################### + # burst + @netlink.nlattr('class.htb.burst', type=str) + @property + def burst(self): + burst = capi.rtnl_htb_get_rbuffer(self._class._rtnl_class) + return util.Size(burst) - @burst.setter - def burst(self, value): - capi.rtnl_htb_set_rbuffer(self._class._rtnl_class, int(value)) + @burst.setter + def burst(self, value): + capi.rtnl_htb_set_rbuffer(self._class._rtnl_class, int(value)) - ##################################################################### - # ceil burst - @netlink.nlattr('class.htb.ceil_burst', type=str) - @property - def ceil_burst(self): - burst = capi.rtnl_htb_get_cbuffer(self._class._rtnl_class) - return util.Size(burst) + ##################################################################### + # ceil burst + @netlink.nlattr('class.htb.ceil_burst', type=str) + @property + def ceil_burst(self): + burst = capi.rtnl_htb_get_cbuffer(self._class._rtnl_class) + return util.Size(burst) - @ceil_burst.setter - def ceil_burst(self, value): - capi.rtnl_htb_set_cbuffer(self._class._rtnl_class, int(value)) + @ceil_burst.setter + def ceil_burst(self, value): + capi.rtnl_htb_set_cbuffer(self._class._rtnl_class, int(value)) - ##################################################################### - # priority - @netlink.nlattr('class.htb.prio', type=int) - @property - def prio(self): - return capi.rtnl_htb_get_prio(self._class._rtnl_class) + ##################################################################### + # priority + @netlink.nlattr('class.htb.prio', type=int) + @property + def prio(self): + return capi.rtnl_htb_get_prio(self._class._rtnl_class) - @prio.setter - def prio(self, value): - capi.rtnl_htb_set_prio(self._class._rtnl_class, int(value)) + @prio.setter + def prio(self, value): + capi.rtnl_htb_set_prio(self._class._rtnl_class, int(value)) - ##################################################################### - # quantum - @netlink.nlattr('class.htb.quantum', type=int) - @property - def quantum(self): - return capi.rtnl_htb_get_quantum(self._class._rtnl_class) + ##################################################################### + # quantum + @netlink.nlattr('class.htb.quantum', type=int) + @property + def quantum(self): + return capi.rtnl_htb_get_quantum(self._class._rtnl_class) - @quantum.setter - def quantum(self, value): - capi.rtnl_htb_set_quantum(self._class._rtnl_class, int(value)) + @quantum.setter + def quantum(self, value): + capi.rtnl_htb_set_quantum(self._class._rtnl_class, int(value)) - ##################################################################### - # level - @netlink.nlattr('class.htb.level', type=int) - @property - def level(self): - level = capi.rtnl_htb_get_level(self._class._rtnl_class) + ##################################################################### + # level + @netlink.nlattr('class.htb.level', type=int) + @property + def level(self): + level = capi.rtnl_htb_get_level(self._class._rtnl_class) - @level.setter - def level(self, value): - capi.rtnl_htb_set_level(self._class._rtnl_class, int(value)) + @level.setter + def level(self, value): + capi.rtnl_htb_set_level(self._class._rtnl_class, int(value)) - def brief(self): - fmt = util.MyFormatter(self) + def brief(self): + fmt = util.MyFormatter(self) - ret = ' {t|prio} {t|rate}' + ret = ' {t|prio} {t|rate}' - if self.rate != self.ceil: - ret += ' {s|borrow-up-to!k} {a|ceil}' + if self.rate != self.ceil: + ret += ' {s|borrow-up-to!k} {a|ceil}' - ret += ' {t|burst}' + ret += ' {t|burst}' - return fmt.format(ret) + return fmt.format(ret) - def details(self): - fmt = util.MyFormatter(self) + def details(self): + fmt = util.MyFormatter(self) - return fmt.nl('\t{t|level} {t|quantum}') + return fmt.nl('\t{t|level} {t|quantum}') def init_qdisc(qdisc): - qdisc.htb = HTBQdisc(qdisc) - return qdisc.htb + qdisc.htb = HTBQdisc(qdisc) + return qdisc.htb def init_class(cl): - cl.htb = HTBClass(cl) - return cl.htb + cl.htb = HTBClass(cl) + return cl.htb #extern void rtnl_htb_set_quantum(struct rtnl_class *, uint32_t quantum); diff --git a/python/netlink/route/tc.py b/python/netlink/route/tc.py index 1c654e1..92f2950 100644 --- a/python/netlink/route/tc.py +++ b/python/netlink/route/tc.py @@ -4,12 +4,12 @@ from __future__ import absolute_import __all__ = [ - 'TcCache', - 'Tc', - 'QdiscCache', - 'Qdisc', - 'TcClassCache', - 'TcClass'] + 'TcCache', + 'Tc', + 'QdiscCache', + 'Qdisc', + 'TcClassCache', + 'TcClass'] import socket import sys @@ -47,218 +47,218 @@ STAT_MAX = STAT_OVERLIMITS ########################################################################### # Handle class Handle(object): - """ Traffic control handle + """ Traffic control handle - Representation of a traffic control handle which uniquely identifies - each traffic control object in its link namespace. + Representation of a traffic control handle which uniquely identifies + each traffic control object in its link namespace. - handle = tc.Handle('10:20') - handle = tc.handle('root') - print int(handle) - print str(handle) - """ - def __init__(self, val=None): - if type(val) is str: - val = capi.tc_str2handle(val) - elif not val: - val = 0 + handle = tc.Handle('10:20') + handle = tc.handle('root') + print int(handle) + print str(handle) + """ + def __init__(self, val=None): + if type(val) is str: + val = capi.tc_str2handle(val) + elif not val: + val = 0 - self._val = int(val) + self._val = int(val) - def __cmp__(self, other): - if other is None: - other = 0 + def __cmp__(self, other): + if other is None: + other = 0 - if isinstance(other, Handle): - return int(self) - int(other) - elif isinstance(other, int): - return int(self) - other - else: - raise TypeError() + if isinstance(other, Handle): + return int(self) - int(other) + elif isinstance(other, int): + return int(self) - other + else: + raise TypeError() - def __int__(self): - return self._val + def __int__(self): + return self._val - def __str__(self): - return capi.rtnl_tc_handle2str(self._val, 64)[0] + def __str__(self): + return capi.rtnl_tc_handle2str(self._val, 64)[0] - def isroot(self): - return self._val == TC_H_ROOT or self._val == TC_H_INGRESS + def isroot(self): + return self._val == TC_H_ROOT or self._val == TC_H_INGRESS ########################################################################### # TC Cache class TcCache(netlink.Cache): - """Cache of traffic control object""" + """Cache of traffic control object""" - def __getitem__(self, key): - raise NotImplementedError() + def __getitem__(self, key): + raise NotImplementedError() ########################################################################### # Tc Object class Tc(netlink.Object): - def __cmp__(self, other): - diff = self.ifindex - other.ifindex - if diff == 0: - diff = int(self.handle) - int(other.handle) - return diff + def __cmp__(self, other): + diff = self.ifindex - other.ifindex + if diff == 0: + diff = int(self.handle) - int(other.handle) + return diff - def _tc_module_lookup(self): - self._module_lookup(self._module_path + self.kind, - 'init_' + self._name) + def _tc_module_lookup(self): + self._module_lookup(self._module_path + self.kind, + 'init_' + self._name) - @property - def root(self): - """True if tc object is a root object""" - return self.parent.isroot() + @property + def root(self): + """True if tc object is a root object""" + return self.parent.isroot() - ##################################################################### - # ifindex - @property - def ifindex(self): - """interface index""" - return capi.rtnl_tc_get_ifindex(self._rtnl_tc) + ##################################################################### + # ifindex + @property + def ifindex(self): + """interface index""" + return capi.rtnl_tc_get_ifindex(self._rtnl_tc) - @ifindex.setter - def ifindex(self, value): - capi.rtnl_tc_set_ifindex(self._rtnl_tc, int(value)) + @ifindex.setter + def ifindex(self, value): + capi.rtnl_tc_set_ifindex(self._rtnl_tc, int(value)) - ##################################################################### - # link - @property - def link(self): - link = capi.rtnl_tc_get_link(self._rtnl_tc) - if not link: - return None + ##################################################################### + # link + @property + def link(self): + link = capi.rtnl_tc_get_link(self._rtnl_tc) + if not link: + return None - return Link.Link.from_capi(link) + return Link.Link.from_capi(link) - @link.setter - def link(self, value): - capi.rtnl_tc_set_link(self._rtnl_tc, value._link) + @link.setter + def link(self, value): + capi.rtnl_tc_set_link(self._rtnl_tc, value._link) - ##################################################################### - # mtu - @property - def mtu(self): - return capi.rtnl_tc_get_mtu(self._rtnl_tc) + ##################################################################### + # mtu + @property + def mtu(self): + return capi.rtnl_tc_get_mtu(self._rtnl_tc) - @mtu.setter - def mtu(self, value): - capi.rtnl_tc_set_mtu(self._rtnl_tc, int(value)) + @mtu.setter + def mtu(self, value): + capi.rtnl_tc_set_mtu(self._rtnl_tc, int(value)) - ##################################################################### - # mpu - @property - def mpu(self): - return capi.rtnl_tc_get_mpu(self._rtnl_tc) + ##################################################################### + # mpu + @property + def mpu(self): + return capi.rtnl_tc_get_mpu(self._rtnl_tc) - @mpu.setter - def mpu(self, value): - capi.rtnl_tc_set_mpu(self._rtnl_tc, int(value)) + @mpu.setter + def mpu(self, value): + capi.rtnl_tc_set_mpu(self._rtnl_tc, int(value)) - ##################################################################### - # overhead - @property - def overhead(self): - return capi.rtnl_tc_get_overhead(self._rtnl_tc) + ##################################################################### + # overhead + @property + def overhead(self): + return capi.rtnl_tc_get_overhead(self._rtnl_tc) - @overhead.setter - def overhead(self, value): - capi.rtnl_tc_set_overhead(self._rtnl_tc, int(value)) + @overhead.setter + def overhead(self, value): + capi.rtnl_tc_set_overhead(self._rtnl_tc, int(value)) - ##################################################################### - # linktype - @property - def linktype(self): - return capi.rtnl_tc_get_linktype(self._rtnl_tc) + ##################################################################### + # linktype + @property + def linktype(self): + return capi.rtnl_tc_get_linktype(self._rtnl_tc) - @linktype.setter - def linktype(self, value): - capi.rtnl_tc_set_linktype(self._rtnl_tc, int(value)) + @linktype.setter + def linktype(self, value): + capi.rtnl_tc_set_linktype(self._rtnl_tc, int(value)) - ##################################################################### - # handle - @property - def handle(self): - return Handle(capi.rtnl_tc_get_handle(self._rtnl_tc)) + ##################################################################### + # handle + @property + def handle(self): + return Handle(capi.rtnl_tc_get_handle(self._rtnl_tc)) - @handle.setter - def handle(self, value): - capi.rtnl_tc_set_handle(self._rtnl_tc, int(value)) + @handle.setter + def handle(self, value): + capi.rtnl_tc_set_handle(self._rtnl_tc, int(value)) - ##################################################################### - # parent - @property - def parent(self): - return Handle(capi.rtnl_tc_get_parent(self._rtnl_tc)) + ##################################################################### + # parent + @property + def parent(self): + return Handle(capi.rtnl_tc_get_parent(self._rtnl_tc)) - @parent.setter - def parent(self, value): - capi.rtnl_tc_set_parent(self._rtnl_tc, int(value)) + @parent.setter + def parent(self, value): + capi.rtnl_tc_set_parent(self._rtnl_tc, int(value)) - ##################################################################### - # kind - @property - def kind(self): - return capi.rtnl_tc_get_kind(self._rtnl_tc) + ##################################################################### + # kind + @property + def kind(self): + return capi.rtnl_tc_get_kind(self._rtnl_tc) - @kind.setter - def kind(self, value): - capi.rtnl_tc_set_kind(self._rtnl_tc, value) - self._tc_module_lookup() + @kind.setter + def kind(self, value): + capi.rtnl_tc_set_kind(self._rtnl_tc, value) + self._tc_module_lookup() - def get_stat(self, id): - return capi.rtnl_tc_get_stat(self._rtnl_tc, id) + def get_stat(self, id): + return capi.rtnl_tc_get_stat(self._rtnl_tc, id) - @property - def _dev(self): - buf = util.kw('dev') + ' ' + @property + def _dev(self): + buf = util.kw('dev') + ' ' - if self.link: - return buf + util.string(self.link.name) - else: - return buf + util.num(self.ifindex) + if self.link: + return buf + util.string(self.link.name) + else: + return buf + util.num(self.ifindex) - def brief(self, title, nodev=False, noparent=False): - ret = title + ' {a|kind} {a|handle}' + def brief(self, title, nodev=False, noparent=False): + ret = title + ' {a|kind} {a|handle}' - if not nodev: - ret += ' {a|_dev}' + if not nodev: + ret += ' {a|_dev}' - if not noparent: - ret += ' {t|parent}' + if not noparent: + ret += ' {t|parent}' - return ret + self._module_brief() + return ret + self._module_brief() - def details(self): - return '{t|mtu} {t|mpu} {t|overhead} {t|linktype}' + def details(self): + return '{t|mtu} {t|mpu} {t|overhead} {t|linktype}' - @property - def packets(self): - return self.get_stat(STAT_PACKETS) + @property + def packets(self): + return self.get_stat(STAT_PACKETS) - @property - def bytes(self): - return self.get_stat(STAT_BYTES) + @property + def bytes(self): + return self.get_stat(STAT_BYTES) - @property - def qlen(self): - return self.get_stat(STAT_QLEN) + @property + def qlen(self): + return self.get_stat(STAT_QLEN) - def stats(self, fmt): - return fmt.nl('{t|packets} {t|bytes} {t|qlen}') + def stats(self, fmt): + return fmt.nl('{t|packets} {t|bytes} {t|qlen}') ########################################################################### # Queueing discipline cache class QdiscCache(netlink.Cache): - """Cache of qdiscs""" + """Cache of qdiscs""" - def __init__(self, cache=None): - if not cache: - cache = self._alloc_cache_name("route/qdisc") + def __init__(self, cache=None): + if not cache: + cache = self._alloc_cache_name("route/qdisc") - self._protocol = netlink.NETLINK_ROUTE - self._nl_cache = cache + self._protocol = netlink.NETLINK_ROUTE + self._nl_cache = cache # def __getitem__(self, key): # if type(key) is int: @@ -271,56 +271,56 @@ class QdiscCache(netlink.Cache): # else: # return Qdisc._from_capi(capi.qdisc2obj(qdisc)) - def _new_object(self, obj): - return Qdisc(obj) + def _new_object(self, obj): + return Qdisc(obj) - def _new_cache(self, cache): - return QdiscCache(cache=cache) + def _new_cache(self, cache): + return QdiscCache(cache=cache) ########################################################################### # Qdisc Object class Qdisc(Tc): - """Queueing discipline""" + """Queueing discipline""" - def __init__(self, obj=None): - netlink.Object.__init__(self, "route/qdisc", "qdisc", obj) - self._module_path = 'netlink.route.qdisc.' - self._rtnl_qdisc = self._obj2type(self._nl_object) - self._rtnl_tc = capi.obj2tc(self._nl_object) + def __init__(self, obj=None): + netlink.Object.__init__(self, "route/qdisc", "qdisc", obj) + self._module_path = 'netlink.route.qdisc.' + self._rtnl_qdisc = self._obj2type(self._nl_object) + self._rtnl_tc = capi.obj2tc(self._nl_object) - netlink.add_attr('qdisc.handle', fmt=util.handle) - netlink.add_attr('qdisc.parent', fmt=util.handle) - netlink.add_attr('qdisc.kind', fmt=util.bold) + netlink.add_attr('qdisc.handle', fmt=util.handle) + netlink.add_attr('qdisc.parent', fmt=util.handle) + netlink.add_attr('qdisc.kind', fmt=util.bold) - if self.kind: - self._tc_module_lookup() + if self.kind: + self._tc_module_lookup() - @classmethod - def from_capi(cls, obj): - return cls(capi.qdisc2obj(obj)) + @classmethod + def from_capi(cls, obj): + return cls(capi.qdisc2obj(obj)) - def _obj2type(self, obj): - return capi.obj2qdisc(obj) + def _obj2type(self, obj): + return capi.obj2qdisc(obj) - def _new_instance(self, obj): - if not obj: - raise ValueError() + def _new_instance(self, obj): + if not obj: + raise ValueError() - return Qdisc(obj) + return Qdisc(obj) - @property - def childs(self): - ret = [] + @property + def childs(self): + ret = [] - if int(self.handle): - ret += get_cls(self.ifindex, parent=self.handle) + if int(self.handle): + ret += get_cls(self.ifindex, parent=self.handle) - if self.root: - ret += get_class(self.ifindex, parent=TC_H_ROOT) + if self.root: + ret += get_class(self.ifindex, parent=TC_H_ROOT) - ret += get_class(self.ifindex, parent=self.handle) + ret += get_class(self.ifindex, parent=self.handle) - return ret + return ret # ##################################################################### # # add() @@ -350,22 +350,22 @@ class Qdisc(Tc): # if ret < 0: # raise netlink.KernelError(ret) - ################################################################### - # - # format(details=False, stats=False) - # - def format(self, details=False, stats=False, nodev=False, - noparent=False, indent=''): - """Return qdisc as formatted text""" - fmt = util.MyFormatter(self, indent) + ################################################################### + # + # format(details=False, stats=False) + # + def format(self, details=False, stats=False, nodev=False, + noparent=False, indent=''): + """Return qdisc as formatted text""" + fmt = util.MyFormatter(self, indent) - buf = fmt.format(self.brief('qdisc', nodev, noparent)) + buf = fmt.format(self.brief('qdisc', nodev, noparent)) - if details: - buf += fmt.nl('\t' + self.details()) + if details: + buf += fmt.nl('\t' + self.details()) - if stats: - buf += self.stats(fmt) + if stats: + buf += self.stats(fmt) # if stats: # l = [['Packets', RX_PACKETS, TX_PACKETS], @@ -423,230 +423,230 @@ class Qdisc(Tc): # row[2] = self.get_stat(row[2]) if row[2] else '' # buf += '\t{0:27} {1:>16} {2:>16}\n'.format(*row) - return buf + return buf ########################################################################### # Traffic class cache class TcClassCache(netlink.Cache): - """Cache of traffic classes""" + """Cache of traffic classes""" - def __init__(self, ifindex, cache=None): - if not cache: - cache = self._alloc_cache_name("route/class") + def __init__(self, ifindex, cache=None): + if not cache: + cache = self._alloc_cache_name("route/class") - self._protocol = netlink.NETLINK_ROUTE - self._nl_cache = cache - self._set_arg1(ifindex) + self._protocol = netlink.NETLINK_ROUTE + self._nl_cache = cache + self._set_arg1(ifindex) - def _new_object(self, obj): - return TcClass(obj) + def _new_object(self, obj): + return TcClass(obj) - def _new_cache(self, cache): - return TcClassCache(self.arg1, cache=cache) + def _new_cache(self, cache): + return TcClassCache(self.arg1, cache=cache) ########################################################################### # Traffic Class Object class TcClass(Tc): - """Traffic Class""" + """Traffic Class""" - def __init__(self, obj=None): - netlink.Object.__init__(self, "route/class", "class", obj) - self._module_path = 'netlink.route.qdisc.' - self._rtnl_class = self._obj2type(self._nl_object) - self._rtnl_tc = capi.obj2tc(self._nl_object) + def __init__(self, obj=None): + netlink.Object.__init__(self, "route/class", "class", obj) + self._module_path = 'netlink.route.qdisc.' + self._rtnl_class = self._obj2type(self._nl_object) + self._rtnl_tc = capi.obj2tc(self._nl_object) - netlink.add_attr('class.handle', fmt=util.handle) - netlink.add_attr('class.parent', fmt=util.handle) - netlink.add_attr('class.kind', fmt=util.bold) + netlink.add_attr('class.handle', fmt=util.handle) + netlink.add_attr('class.parent', fmt=util.handle) + netlink.add_attr('class.kind', fmt=util.bold) - if self.kind: - self._tc_module_lookup() + if self.kind: + self._tc_module_lookup() - @classmethod - def from_capi(cls, obj): - return cls(capi.class2obj(obj)) + @classmethod + def from_capi(cls, obj): + return cls(capi.class2obj(obj)) - def _obj2type(self, obj): - return capi.obj2class(obj) + def _obj2type(self, obj): + return capi.obj2class(obj) - def _new_instance(self, obj): - if not obj: - raise ValueError() + def _new_instance(self, obj): + if not obj: + raise ValueError() - return TcClass(obj) + return TcClass(obj) - @property - def childs(self): - ret = [] + @property + def childs(self): + ret = [] - # classes can have classifiers, child classes and leaf - # qdiscs - ret += get_cls(self.ifindex, parent=self.handle) - ret += get_class(self.ifindex, parent=self.handle) - ret += get_qdisc(self.ifindex, parent=self.handle) + # classes can have classifiers, child classes and leaf + # qdiscs + ret += get_cls(self.ifindex, parent=self.handle) + ret += get_class(self.ifindex, parent=self.handle) + ret += get_qdisc(self.ifindex, parent=self.handle) - return ret + return ret - ################################################################### - # - # format(details=False, stats=False) - # - def format(self, details=False, stats=False, nodev=False, - noparent=False, indent=''): - """Return class as formatted text""" - fmt = util.MyFormatter(self, indent) + ################################################################### + # + # format(details=False, stats=False) + # + def format(self, details=False, stats=False, nodev=False, + noparent=False, indent=''): + """Return class as formatted text""" + fmt = util.MyFormatter(self, indent) - buf = fmt.format(self.brief('class', nodev, noparent)) + buf = fmt.format(self.brief('class', nodev, noparent)) - if details: - buf += fmt.nl('\t' + self.details()) + if details: + buf += fmt.nl('\t' + self.details()) - return buf + return buf ########################################################################### # Classifier Cache class ClassifierCache(netlink.Cache): - """Cache of traffic classifiers objects""" + """Cache of traffic classifiers objects""" - def __init__(self, ifindex, parent, cache=None): - if not cache: - cache = self._alloc_cache_name("route/cls") + def __init__(self, ifindex, parent, cache=None): + if not cache: + cache = self._alloc_cache_name("route/cls") - self._protocol = netlink.NETLINK_ROUTE - self._nl_cache = cache - self._set_arg1(ifindex) - self._set_arg2(int(parent)) + self._protocol = netlink.NETLINK_ROUTE + self._nl_cache = cache + self._set_arg1(ifindex) + self._set_arg2(int(parent)) - def _new_object(self, obj): - return Classifier(obj) + def _new_object(self, obj): + return Classifier(obj) - def _new_cache(self, cache): - return ClassifierCache(self.arg1, self.arg2, cache=cache) + def _new_cache(self, cache): + return ClassifierCache(self.arg1, self.arg2, cache=cache) ########################################################################### # Classifier Object class Classifier(Tc): - """Classifier""" + """Classifier""" - def __init__(self, obj=None): - netlink.Object.__init__(self, "route/cls", "cls", obj) - self._module_path = 'netlink.route.cls.' - self._rtnl_cls = self._obj2type(self._nl_object) - self._rtnl_tc = capi.obj2tc(self._nl_object) + def __init__(self, obj=None): + netlink.Object.__init__(self, "route/cls", "cls", obj) + self._module_path = 'netlink.route.cls.' + self._rtnl_cls = self._obj2type(self._nl_object) + self._rtnl_tc = capi.obj2tc(self._nl_object) - netlink.add_attr('cls.handle', fmt=util.handle) - netlink.add_attr('cls.parent', fmt=util.handle) - netlink.add_attr('cls.kind', fmt=util.bold) + netlink.add_attr('cls.handle', fmt=util.handle) + netlink.add_attr('cls.parent', fmt=util.handle) + netlink.add_attr('cls.kind', fmt=util.bold) - @classmethod - def from_capi(cls, obj): - return cls(capi.cls2obj(obj)) + @classmethod + def from_capi(cls, obj): + return cls(capi.cls2obj(obj)) - def _obj2type(self, obj): - return capi.obj2cls(obj) + def _obj2type(self, obj): + return capi.obj2cls(obj) - def _new_instance(self, obj): - if not obj: - raise ValueError() + def _new_instance(self, obj): + if not obj: + raise ValueError() - return Classifier(obj) + return Classifier(obj) - ##################################################################### - # priority - @property - def priority(self): - return capi.rtnl_cls_get_prio(self._rtnl_cls) + ##################################################################### + # priority + @property + def priority(self): + return capi.rtnl_cls_get_prio(self._rtnl_cls) - @priority.setter - def priority(self, value): - capi.rtnl_cls_set_prio(self._rtnl_cls, int(value)) + @priority.setter + def priority(self, value): + capi.rtnl_cls_set_prio(self._rtnl_cls, int(value)) - ##################################################################### - # protocol - @property - def protocol(self): - return capi.rtnl_cls_get_protocol(self._rtnl_cls) + ##################################################################### + # protocol + @property + def protocol(self): + return capi.rtnl_cls_get_protocol(self._rtnl_cls) - @protocol.setter - def protocol(self, value): - capi.rtnl_cls_set_protocol(self._rtnl_cls, int(value)) + @protocol.setter + def protocol(self, value): + capi.rtnl_cls_set_protocol(self._rtnl_cls, int(value)) - @property - def childs(self): - return [] + @property + def childs(self): + return [] - ################################################################### - # - # format(details=False, stats=False) - # - def format(self, details=False, stats=False, nodev=False, - noparent=False, indent=''): - """Return class as formatted text""" - fmt = util.MyFormatter(self, indent) + ################################################################### + # + # format(details=False, stats=False) + # + def format(self, details=False, stats=False, nodev=False, + noparent=False, indent=''): + """Return class as formatted text""" + fmt = util.MyFormatter(self, indent) - buf = fmt.format(self.brief('classifier', nodev, noparent)) - buf += fmt.format(' {t|priority} {t|protocol}') + buf = fmt.format(self.brief('classifier', nodev, noparent)) + buf += fmt.format(' {t|priority} {t|protocol}') - if details: - buf += fmt.nl('\t' + self.details()) + if details: + buf += fmt.nl('\t' + self.details()) - return buf + return buf _qdisc_cache = QdiscCache() def get_qdisc(ifindex, handle=None, parent=None): - l = [] + l = [] - _qdisc_cache.refill() + _qdisc_cache.refill() - for qdisc in _qdisc_cache: - if qdisc.ifindex == ifindex and \ - (handle == None or qdisc.handle == handle) and \ - (parent == None or qdisc.parent == parent): - l.append(qdisc) + for qdisc in _qdisc_cache: + if qdisc.ifindex == ifindex and \ + (handle == None or qdisc.handle == handle) and \ + (parent == None or qdisc.parent == parent): + l.append(qdisc) - return l + return l _class_cache = {} def get_class(ifindex, parent, handle=None): - l = [] + l = [] - try: - cache = _class_cache[ifindex] - except KeyError: - cache = TcClassCache(ifindex) - _class_cache[ifindex] = cache + try: + cache = _class_cache[ifindex] + except KeyError: + cache = TcClassCache(ifindex) + _class_cache[ifindex] = cache - cache.refill() + cache.refill() - for cl in cache: - if (parent == None or cl.parent == parent) and \ - (handle == None or cl.handle == handle): - l.append(cl) + for cl in cache: + if (parent == None or cl.parent == parent) and \ + (handle == None or cl.handle == handle): + l.append(cl) - return l + return l _cls_cache = {} def get_cls(ifindex, parent, handle=None): - l = [] + l = [] - try: - chain = _cls_cache[ifindex] - except KeyError: - _cls_cache[ifindex] = {} + try: + chain = _cls_cache[ifindex] + except KeyError: + _cls_cache[ifindex] = {} - try: - cache = _cls_cache[ifindex][parent] - except KeyError: - cache = ClassifierCache(ifindex, parent) - _cls_cache[ifindex][parent] = cache + try: + cache = _cls_cache[ifindex][parent] + except KeyError: + cache = ClassifierCache(ifindex, parent) + _cls_cache[ifindex][parent] = cache - cache.refill() + cache.refill() - for cls in cache: - if handle == None or cls.handle == handle: - l.append(cls) + for cls in cache: + if handle == None or cls.handle == handle: + l.append(cls) - return l + return l diff --git a/python/netlink/util.py b/python/netlink/util.py index 73a211d..5249be9 100644 --- a/python/netlink/util.py +++ b/python/netlink/util.py @@ -18,162 +18,162 @@ import types __version__ = "1.0" def _color(t, c): - return b'{esc}[{color}m{text}{esc}[0m'.format(esc=b'\x1b', color=c, text=t) + return b'{esc}[{color}m{text}{esc}[0m'.format(esc=b'\x1b', color=c, text=t) def black(t): - return _color(t, 30) + return _color(t, 30) def red(t): - return _color(t, 31) + return _color(t, 31) def green(t): - return _color(t, 32) + return _color(t, 32) def yellow(t): - return _color(t, 33) + return _color(t, 33) def blue(t): - return _color(t, 34) + return _color(t, 34) def magenta(t): - return _color(t, 35) + return _color(t, 35) def cyan(t): - return _color(t, 36) + return _color(t, 36) def white(t): - return _color(t, 37) + return _color(t, 37) def bold(t): - return _color(t, 1) + return _color(t, 1) def kw(t): - return yellow(t) + return yellow(t) def num(t): - return str(t) + return str(t) def string(t): - return t + return t def addr(t): - return str(t) + return str(t) def bad(t): - return red(t) + return red(t) def good(t): - return green(t) + return green(t) def title(t): - return t + return t def bool(t): - return str(t) + return str(t) def handle(t): - return str(t) + return str(t) class MyFormatter(Formatter): - def __init__(self, obj, indent=''): - self._obj = obj - self._indent = indent + def __init__(self, obj, indent=''): + self._obj = obj + self._indent = indent - def _nlattr(self, key): - value = getattr(self._obj, key) - title = None + def _nlattr(self, key): + value = getattr(self._obj, key) + title = None - if isinstance(value, types.MethodType): - value = value() + if isinstance(value, types.MethodType): + value = value() - try: - d = netlink.attrs[self._obj._name + '.' + key] + try: + d = netlink.attrs[self._obj._name + '.' + key] - if 'fmt' in d: - value = d['fmt'](value) + if 'fmt' in d: + value = d['fmt'](value) - if 'title' in d: - title = d['title'] - except KeyError: - pass - except AttributeError: - pass + if 'title' in d: + title = d['title'] + except KeyError: + pass + except AttributeError: + pass - return title, str(value) + return title, str(value) - def get_value(self, key, args, kwds): - # Let default get_value() handle ints - if not isinstance(key, str): - return Formatter.get_value(self, key, args, kwds) + def get_value(self, key, args, kwds): + # Let default get_value() handle ints + if not isinstance(key, str): + return Formatter.get_value(self, key, args, kwds) - # HACK, we allow defining strings via fields to allow - # conversions - if key[:2] == 's|': - return key[2:] + # HACK, we allow defining strings via fields to allow + # conversions + if key[:2] == 's|': + return key[2:] - if key[:2] == 't|': - # title mode ("TITLE ATTR") - include_title = True - elif key[:2] == 'a|': - # plain attribute mode ("ATTR") - include_title = False - else: - # No special field, have default get_value() get it - return Formatter.get_value(self, key, args, kwds) + if key[:2] == 't|': + # title mode ("TITLE ATTR") + include_title = True + elif key[:2] == 'a|': + # plain attribute mode ("ATTR") + include_title = False + else: + # No special field, have default get_value() get it + return Formatter.get_value(self, key, args, kwds) - key = key[2:] - (title, value) = self._nlattr(key) + key = key[2:] + (title, value) = self._nlattr(key) - if include_title: - if not title: - title = key # fall back to key as title - value = '{0} {1}'.format(kw(title), value) + if include_title: + if not title: + title = key # fall back to key as title + value = '{0} {1}'.format(kw(title), value) - return value + return value - def convert_field(self, value, conversion): - if conversion == 'r': - return repr(value) - elif conversion == 's': - return str(value) - elif conversion == 'k': - return kw(value) - elif conversion == 'b': - return bold(value) - elif conversion is None: - return value + def convert_field(self, value, conversion): + if conversion == 'r': + return repr(value) + elif conversion == 's': + return str(value) + elif conversion == 'k': + return kw(value) + elif conversion == 'b': + return bold(value) + elif conversion is None: + return value - raise ValueError("Unknown converion specifier {0!s}".format(conversion)) + raise ValueError("Unknown converion specifier {0!s}".format(conversion)) - def nl(self, format_string=''): - return '\n' + self._indent + self.format(format_string) + def nl(self, format_string=''): + return '\n' + self._indent + self.format(format_string) NL_BYTE_RATE = 0 NL_BIT_RATE = 1 class Rate(object): - def __init__(self, rate, mode=NL_BYTE_RATE): - self._rate = rate - self._mode = mode + def __init__(self, rate, mode=NL_BYTE_RATE): + self._rate = rate + self._mode = mode - def __str__(self): - return capi.nl_rate2str(self._rate, self._mode, 32)[1] + def __str__(self): + return capi.nl_rate2str(self._rate, self._mode, 32)[1] - def __int__(self): - return self._rate + def __int__(self): + return self._rate - def __cmp__(self, other): - return int(self) - int(other) + def __cmp__(self, other): + return int(self) - int(other) class Size(object): - def __init__(self, size): - self._size = size + def __init__(self, size): + self._size = size - def __str__(self): - return capi.nl_size2str(self._size, 32)[0] + def __str__(self): + return capi.nl_size2str(self._size, 32)[0] - def __int__(self): - return self._size + def __int__(self): + return self._size - def __cmp__(self, other): - return int(self) - int(other) + def __cmp__(self, other): + return int(self) - int(other) From 8959d95e22858148ca75861431dad51356c8a73b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=BD=D0=BE=D1=83=D1=82=D0=B1?= =?UTF-8?q?=D1=83=D0=BA=20=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Tue, 5 Jun 2012 23:01:39 +0600 Subject: [PATCH 202/432] Using only single quotes now and multi-line lists Nothing algorithmic changed really, just cosmetics --- python/netlink/core.py | 40 +++++++++++++++++------------ python/netlink/route/address.py | 6 ++--- python/netlink/route/link.py | 21 +++++++++------ python/netlink/route/links/dummy.py | 6 +++-- python/netlink/route/links/inet.py | 6 +++-- python/netlink/route/tc.py | 17 ++++++------ python/netlink/util.py | 4 +-- 7 files changed, 59 insertions(+), 41 deletions(-) diff --git a/python/netlink/core.py b/python/netlink/core.py index 219b522..e18230f 100644 --- a/python/netlink/core.py +++ b/python/netlink/core.py @@ -33,9 +33,17 @@ from . import capi import sys import socket -__all__ = ['Message', 'Socket', 'DumpParams', 'Object', 'Cache', 'KernelError', - 'NetlinkError'] -__version__ = "0.1" +__all__ = [ + 'Message', + 'Socket', + 'DumpParams', + 'Object', + 'Cache', + 'KernelError', + 'NetlinkError', +] + +__version__ = '0.1' # netlink protocols NETLINK_ROUTE = 0 @@ -91,14 +99,14 @@ class NetlinkError(Exception): class KernelError(NetlinkError): def __str__(self): - return "Kernel returned: {0}".format(self._msg) + return 'Kernel returned: {0}'.format(self._msg) class ImmutableError(NetlinkError): def __init__(self, msg): self._msg = msg def __str__(self): - return "Immutable attribute: {0}".format(self._msg) + return 'Immutable attribute: {0}'.format(self._msg) class Message(object): """Netlink message""" @@ -110,7 +118,7 @@ class Message(object): self._msg = capi.nlmsg_alloc_size(size) if self._msg is None: - raise Exception("Message allocation returned NULL") + raise Exception('Message allocation returned NULL') def __del__(self): capi.nlmsg_free(self._msg) @@ -155,13 +163,13 @@ class Socket(object): self._sock = capi.nl_socket_alloc_cb(cb) if self._sock is None: - raise Exception("NULL pointer returned while allocating socket") + raise Exception('NULL pointer returned while allocating socket') def __del__(self): capi.nl_socket_free(self._sock) def __str__(self): - return "nlsock<{0}>".format(self.localPort) + return 'nlsock<{0}>'.format(self.localPort) @property def local_port(self): @@ -200,7 +208,7 @@ class Socket(object): def sendto(self, buf): ret = capi.nl_sendto(self._sock, buf, len(buf)) if ret < 0: - raise Exception("Failed to send") + raise Exception('Failed to send') else: return ret @@ -222,7 +230,7 @@ class DumpParams(object): def __init__(self, type=NL_DUMP_LINE): self._dp = capi.alloc_dump_params() if not self._dp: - raise Exception("Unable to allocate struct nl_dump_params") + raise Exception('Unable to allocate struct nl_dump_params') self._dp.dp_type = type @@ -388,17 +396,17 @@ class Object(object): def apply(self, attr, val): try: - d = attrs[self._name + "." + attr] + d = attrs[self._name + '.' + attr] except KeyError: - raise KeyError("Unknown " + self._name + - " attribute: " + attr) + raise KeyError('Unknown ' + self._name + + ' attribute: ' + attr) if 'immutable' in d: raise ImmutableError(attr) if not self._hasattr(attr): - raise KeyError("Invalid " + self._name + - " attribute: " + attr) + raise KeyError('Invalid ' + self._name + + ' attribute: ' + attr) self._setattr(attr, val) class ObjIterator(object): @@ -695,7 +703,7 @@ class AbstractAddress(object): if self._nl_addr: return capi.nl_addr2str(self._nl_addr, 64)[0] else: - return "none" + return 'none' @property def shared(self): diff --git a/python/netlink/route/address.py b/python/netlink/route/address.py index b5f2448..e8e2f87 100644 --- a/python/netlink/route/address.py +++ b/python/netlink/route/address.py @@ -8,7 +8,7 @@ from __future__ import absolute_import -__version__ = "1.0" +__version__ = '1.0' __all__ = [ 'AddressCache', 'Address'] @@ -27,7 +27,7 @@ class AddressCache(netlink.Cache): def __init__(self, cache=None): if not cache: - cache = self._alloc_cache_name("route/addr") + cache = self._alloc_cache_name('route/addr') self._protocol = netlink.NETLINK_ROUTE self._nl_cache = cache @@ -60,7 +60,7 @@ class Address(netlink.Object): """Network address""" def __init__(self, obj=None): - netlink.Object.__init__(self, "route/addr", "address", obj) + netlink.Object.__init__(self, 'route/addr', 'address', obj) self._rtnl_addr = self._obj2type(self._nl_object) @classmethod diff --git a/python/netlink/route/link.py b/python/netlink/route/link.py index 465b3b3..4c213d0 100644 --- a/python/netlink/route/link.py +++ b/python/netlink/route/link.py @@ -36,11 +36,12 @@ The following public functions exist: from __future__ import absolute_import -__version__ = "0.1" +__version__ = '0.1' __all__ = [ 'LinkCache', 'Link', - 'get_from_kernel'] + 'get_from_kernel', +] import socket import sys @@ -117,7 +118,7 @@ class LinkCache(netlink.Cache): def __init__(self, family=socket.AF_UNSPEC, cache=None): if not cache: - cache = self._alloc_cache_name("route/link") + cache = self._alloc_cache_name('route/link') self._info_module = None self._protocol = netlink.NETLINK_ROUTE @@ -147,7 +148,7 @@ class Link(netlink.Object): """Network link""" def __init__(self, obj=None): - netlink.Object.__init__(self, "route/link", "link", obj) + netlink.Object.__init__(self, 'route/link', 'link', obj) self._rtnl_link = self._obj2type(self._nl_object) if self.type: @@ -403,7 +404,7 @@ class Link(netlink.Object): @type.setter def type(self, value): if capi.rtnl_link_set_type(self._rtnl_link, value) < 0: - raise NameError("unknown info type") + raise NameError('unknown info type') self._module_lookup('netlink.route.links.' + value) @@ -414,7 +415,7 @@ class Link(netlink.Object): if type(stat) is str: stat = capi.rtnl_link_str2stat(stat) if stat < 0: - raise NameError("unknown name of statistic") + raise NameError('unknown name of statistic') return capi.rtnl_link_get_stat(self._rtnl_link, stat) @@ -439,7 +440,7 @@ class Link(netlink.Object): socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) if not self._orig: - raise NetlinkError("Original link not available") + raise NetlinkError('Original link not available') ret = capi.rtnl_link_change(socket._sock, self._orig, self._rtnl_link, flags) if ret < 0: raise netlink.KernelError(ret) @@ -475,7 +476,11 @@ class Link(netlink.Object): @property def _flags(self): - ignore = ['up', 'running', 'lowerup'] + ignore = [ + 'up', + 'running', + 'lowerup', + ] return ','.join([flag for flag in self.flags if flag not in ignore]) def _foreach_af(self, name, args=None): diff --git a/python/netlink/route/links/dummy.py b/python/netlink/route/links/dummy.py index 13b3077..c9253cf 100644 --- a/python/netlink/route/links/dummy.py +++ b/python/netlink/route/links/dummy.py @@ -7,8 +7,10 @@ """ from __future__ import absolute_import -__version__ = "1.0" -__all__ = ['init'] +__version__ = '1.0' +__all__ = [ + 'init', +] from ... import core as netlink diff --git a/python/netlink/route/links/inet.py b/python/netlink/route/links/inet.py index 1a13349..8f89b4e 100644 --- a/python/netlink/route/links/inet.py +++ b/python/netlink/route/links/inet.py @@ -8,7 +8,9 @@ from __future__ import absolute_import -__all__ = [''] +__all__ = [ + '', +] from ... import core as netlink from .. import capi as capi @@ -44,7 +46,7 @@ def _resolve(id): if type(id) is str: id = capi.rtnl_link_inet_str2devconf(id)[0] if id < 0: - raise NameError("unknown configuration id") + raise NameError('unknown configuration id') return id class InetLink(object): diff --git a/python/netlink/route/tc.py b/python/netlink/route/tc.py index 92f2950..9a81a67 100644 --- a/python/netlink/route/tc.py +++ b/python/netlink/route/tc.py @@ -9,7 +9,8 @@ __all__ = [ 'QdiscCache', 'Qdisc', 'TcClassCache', - 'TcClass'] + 'TcClass', +] import socket import sys @@ -255,7 +256,7 @@ class QdiscCache(netlink.Cache): def __init__(self, cache=None): if not cache: - cache = self._alloc_cache_name("route/qdisc") + cache = self._alloc_cache_name('route/qdisc') self._protocol = netlink.NETLINK_ROUTE self._nl_cache = cache @@ -283,7 +284,7 @@ class Qdisc(Tc): """Queueing discipline""" def __init__(self, obj=None): - netlink.Object.__init__(self, "route/qdisc", "qdisc", obj) + netlink.Object.__init__(self, 'route/qdisc', 'qdisc', obj) self._module_path = 'netlink.route.qdisc.' self._rtnl_qdisc = self._obj2type(self._nl_object) self._rtnl_tc = capi.obj2tc(self._nl_object) @@ -337,7 +338,7 @@ class Qdisc(Tc): # def change(self, socket, flags=0): # """Commit changes made to the link object""" # if not self._orig: -# raise NetlinkError("Original link not available") +# raise NetlinkError('Original link not available') # ret = capi.rtnl_link_change(socket._sock, self._orig, self._link, flags) # if ret < 0: # raise netlink.KernelError(ret) @@ -432,7 +433,7 @@ class TcClassCache(netlink.Cache): def __init__(self, ifindex, cache=None): if not cache: - cache = self._alloc_cache_name("route/class") + cache = self._alloc_cache_name('route/class') self._protocol = netlink.NETLINK_ROUTE self._nl_cache = cache @@ -450,7 +451,7 @@ class TcClass(Tc): """Traffic Class""" def __init__(self, obj=None): - netlink.Object.__init__(self, "route/class", "class", obj) + netlink.Object.__init__(self, 'route/class', 'class', obj) self._module_path = 'netlink.route.qdisc.' self._rtnl_class = self._obj2type(self._nl_object) self._rtnl_tc = capi.obj2tc(self._nl_object) @@ -510,7 +511,7 @@ class ClassifierCache(netlink.Cache): def __init__(self, ifindex, parent, cache=None): if not cache: - cache = self._alloc_cache_name("route/cls") + cache = self._alloc_cache_name('route/cls') self._protocol = netlink.NETLINK_ROUTE self._nl_cache = cache @@ -529,7 +530,7 @@ class Classifier(Tc): """Classifier""" def __init__(self, obj=None): - netlink.Object.__init__(self, "route/cls", "cls", obj) + netlink.Object.__init__(self, 'route/cls', 'cls', obj) self._module_path = 'netlink.route.cls.' self._rtnl_cls = self._obj2type(self._nl_object) self._rtnl_tc = capi.obj2tc(self._nl_object) diff --git a/python/netlink/util.py b/python/netlink/util.py index 5249be9..995a6d2 100644 --- a/python/netlink/util.py +++ b/python/netlink/util.py @@ -15,7 +15,7 @@ from . import capi as capi from string import Formatter import types -__version__ = "1.0" +__version__ = '1.0' def _color(t, c): return b'{esc}[{color}m{text}{esc}[0m'.format(esc=b'\x1b', color=c, text=t) @@ -143,7 +143,7 @@ class MyFormatter(Formatter): elif conversion is None: return value - raise ValueError("Unknown converion specifier {0!s}".format(conversion)) + raise ValueError('Unknown converion specifier {0!s}'.format(conversion)) def nl(self, format_string=''): return '\n' + self._indent + self.format(format_string) From 454ea4a5b46e84830151796eeab1a57503577776 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=BD=D0=BE=D1=83=D1=82=D0=B1?= =?UTF-8?q?=D1=83=D0=BA=20=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Wed, 6 Jun 2012 01:36:05 +0600 Subject: [PATCH 203/432] pylint's first review and trivial fixes --- python/netlink/core.py | 43 ++++++++++++----------- python/netlink/route/address.py | 17 +++++---- python/netlink/route/link.py | 54 +++++++++++++++-------------- python/netlink/route/links/dummy.py | 5 ++- python/netlink/route/links/inet.py | 16 ++++----- python/netlink/route/qdisc/htb.py | 2 +- python/netlink/route/tc.py | 43 ++++++++++++++--------- python/netlink/util.py | 16 ++++----- 8 files changed, 105 insertions(+), 91 deletions(-) diff --git a/python/netlink/core.py b/python/netlink/core.py index e18230f..3aa69c4 100644 --- a/python/netlink/core.py +++ b/python/netlink/core.py @@ -150,8 +150,8 @@ class Message(object): def attrs(self): return capi.nlmsg_attrdata(self._msg) - def send(self, socket): - socket.send(self) + def send(self, sock): + sock.send(self) class Socket(object): """Netlink socket""" @@ -227,12 +227,12 @@ def lookup_socket(protocol): class DumpParams(object): """Dumping parameters""" - def __init__(self, type=NL_DUMP_LINE): + def __init__(self, type_=NL_DUMP_LINE): self._dp = capi.alloc_dump_params() if not self._dp: raise Exception('Unable to allocate struct nl_dump_params') - self._dp.dp_type = type + self._dp.dp_type = type_ def __del__(self): capi.free_dump_params(self._dp) @@ -254,7 +254,7 @@ class DumpParams(object): self._dp.dp_prefix = value # underscore this to make sure it is deleted first upon module deletion -_defaultDumpParams = DumpParams(type=NL_DUMP_LINE) +_defaultDumpParams = DumpParams(NL_DUMP_LINE) ########################################################################### # Cacheable Object (Base Class) @@ -311,7 +311,7 @@ class Object(object): to the new object, e.g. link.vlan = VLANLink() """ try: - tmp = __import__(path) + __import__(path) except ImportError: return @@ -346,10 +346,7 @@ class Object(object): # mark @property def mark(self): - if capi.nl_object_is_marked(self.obj): - return True - else: - return False + return bool(capi.nl_object_is_marked(self._nl_object)) @mark.setter def mark(self, value): @@ -369,7 +366,7 @@ class Object(object): @property def attrs(self): attr_list = capi.nl_object_attr_list(self._nl_object, 1024) - return re.split('\W+', attr_list[0]) + return attr_list[0].split() ##################################################################### # refcnt @@ -467,6 +464,8 @@ class Cache(object): """Collection of netlink objects""" def __init__(self): raise NotImplementedError() + self.arg1 = None + self.arg2 = None def __del(self): capi.nl_cache_free(self._nl_cache) @@ -491,39 +490,41 @@ class Cache(object): return True # called by sub classes to allocate type specific caches by name - def _alloc_cache_name(self, name): + @staticmethod + def _alloc_cache_name(name): return capi.alloc_cache_name(name) # implemented by sub classes, must return new instasnce of cacheable # object - def _new_object(self, obj): + @staticmethod + def _new_object(obj): raise NotImplementedError() # implemented by sub classes, must return instance of sub class def _new_cache(self, cache): raise NotImplementedError() - def subset(self, filter): + def subset(self, filter_): """Return new cache containing subset of cache Cretes a new cache containing all objects which match the specified filter. """ - if not filter: + if not filter_: raise ValueError() - c = capi.nl_cache_subset(self._nl_cache, filter._nl_object) + c = capi.nl_cache_subset(self._nl_cache, filter_._nl_object) return self._new_cache(cache=c) - def dump(self, params=None, filter=None): + def dump(self, params=None, filter_=None): """Dump (print) cache as human readable text""" if not params: params = _defaultDumpParams - if filter: - filter = filter._nl_object + if filter_: + filter_ = filter_._nl_object - capi.nl_cache_dump_filter(self._nl_cache, params._dp, filter) + capi.nl_cache_dump_filter(self._nl_cache, params._dp, filter_) def clear(self): """Remove all cache entries""" @@ -587,7 +588,7 @@ class CacheManager(object): if not flags: flags = NL_AUTO_PROVIDE - self._mngr = cache_mngr_alloc(self._sock._sock, protocol, flags) + self._mngr = capi.cache_mngr_alloc(self._sock._sock, protocol, flags) def __del__(self): if self._sock: diff --git a/python/netlink/route/address.py b/python/netlink/route/address.py index e8e2f87..1b493fd 100644 --- a/python/netlink/route/address.py +++ b/python/netlink/route/address.py @@ -15,7 +15,6 @@ __all__ = [ import datetime from .. import core as netlink -from .. import capi as core_capi from . import capi as capi from . import link as Link from .. import util as util @@ -48,10 +47,12 @@ class AddressCache(netlink.Cache): return Address._from_capi(addr) - def _new_object(self, obj): + @staticmethod + def _new_object(obj): return Address(obj) - def _new_cache(self, cache): + @staticmethod + def _new_cache(cache): return AddressCache(cache=cache) ########################################################################### @@ -67,7 +68,8 @@ class Address(netlink.Object): def _from_capi(cls, obj): return cls(capi.addr2obj(obj)) - def _obj2type(self, obj): + @staticmethod + def _obj2type(obj): return capi.obj2addr(obj) def __cmp__(self, other): @@ -84,7 +86,8 @@ class Address(netlink.Object): return diff - def _new_instance(self, obj): + @staticmethod + def _new_instance(obj): return Address(obj) ##################################################################### @@ -191,8 +194,8 @@ class Address(netlink.Object): @family.setter def family(self, value): - if not isinstance(value, AddressFamily): - value = AddressFamily(value) + if not isinstance(value, netlink.AddressFamily): + value = netlink.AddressFamily(value) capi.rtnl_addr_set_family(self._rtnl_addr, int(value)) diff --git a/python/netlink/route/link.py b/python/netlink/route/link.py index 4c213d0..66c0ab8 100644 --- a/python/netlink/route/link.py +++ b/python/netlink/route/link.py @@ -44,7 +44,6 @@ __all__ = [ ] import socket -import sys from .. import core as netlink from .. import capi as core_capi from . import capi as capi @@ -136,7 +135,8 @@ class LinkCache(netlink.Cache): else: return Link.from_capi(link) - def _new_object(self, obj): + @staticmethod + def _new_object(obj): return Link(obj) def _new_cache(self, cache): @@ -161,13 +161,15 @@ class Link(netlink.Object): def from_capi(cls, obj): return cls(capi.link2obj(obj)) - def _obj2type(self, obj): + @staticmethod + def _obj2type(obj): return capi.obj2link(obj) def __cmp__(self, other): return self.ifindex - other.ifindex - def _new_instance(self, obj): + @staticmethod + def _new_instance(obj): if not obj: raise ValueError() @@ -344,8 +346,8 @@ class Link(netlink.Object): @property def arptype(self): """Type of link (cannot be changed)""" - type = capi.rtnl_link_get_arptype(self._rtnl_link) - return core_capi.nl_llproto2str(type, 64)[0] + type_ = capi.rtnl_link_get_arptype(self._rtnl_link) + return core_capi.nl_llproto2str(type_, 64)[0] @arptype.setter def arptype(self, value): @@ -364,7 +366,7 @@ class Link(netlink.Object): @operstate.setter def operstate(self, value): - i = capi.rtnl_link_str2operstate(flag) + i = capi.rtnl_link_str2operstate(value) capi.rtnl_link_set_operstate(self._rtnl_link, i) ##################################################################### @@ -378,7 +380,7 @@ class Link(netlink.Object): @mode.setter def mode(self, value): - i = capi.rtnl_link_str2mode(flag) + i = capi.rtnl_link_str2mode(value) capi.rtnl_link_set_linkmode(self._rtnl_link, i) ##################################################################### @@ -421,38 +423,38 @@ class Link(netlink.Object): ##################################################################### # add() - def add(self, socket=None, flags=None): - if not socket: - socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) + def add(self, sock=None, flags=None): + if not sock: + sock = netlink.lookup_socket(netlink.NETLINK_ROUTE) if not flags: flags = netlink.NLM_F_CREATE - ret = capi.rtnl_link_add(socket._sock, self._rtnl_link, flags) + ret = capi.rtnl_link_add(sock._sock, self._rtnl_link, flags) if ret < 0: raise netlink.KernelError(ret) ##################################################################### # change() - def change(self, socket=None, flags=0): + def change(self, sock=None, flags=0): """Commit changes made to the link object""" - if not socket: - socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) + if sock is None: + sock = netlink.lookup_socket(netlink.NETLINK_ROUTE) if not self._orig: - raise NetlinkError('Original link not available') - ret = capi.rtnl_link_change(socket._sock, self._orig, self._rtnl_link, flags) + raise netlink.NetlinkError('Original link not available') + ret = capi.rtnl_link_change(sock._sock, self._orig, self._rtnl_link, flags) if ret < 0: raise netlink.KernelError(ret) ##################################################################### # delete() - def delete(self, socket=None): + def delete(self, sock=None): """Attempt to delete this link in the kernel""" - if not socket: - socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) + if sock is None: + sock = netlink.lookup_socket(netlink.NETLINK_ROUTE) - ret = capi.rtnl_link_delete(socket._sock, self._rtnl_link) + ret = capi.rtnl_link_delete(sock._sock, self._rtnl_link) if ret < 0: raise netlink.KernelError(ret) @@ -567,21 +569,21 @@ class Link(netlink.Object): row[0] = util.kw(row[0]) row[1] = self.get_stat(row[1]) if row[1] else '' row[2] = self.get_stat(row[2]) if row[2] else '' - buf += '\t{0:27} {1:>16} {2:>16}\n'.format(*row) + buf += '\t{0[0]:27} {0[1]:>16} {0[2]:>16}\n'.format(row) buf += self._foreach_af('stats') return buf -def get(name, socket=None): +def get(name, sock=None): """Lookup Link object directly from kernel""" if not name: raise ValueError() - if not socket: - socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) + if not sock: + sock = netlink.lookup_socket(netlink.NETLINK_ROUTE) - link = capi.get_from_kernel(socket._sock, 0, name) + link = capi.get_from_kernel(sock._sock, 0, name) if not link: return None diff --git a/python/netlink/route/links/dummy.py b/python/netlink/route/links/dummy.py index c9253cf..e9491cc 100644 --- a/python/netlink/route/links/dummy.py +++ b/python/netlink/route/links/dummy.py @@ -13,13 +13,12 @@ __all__ = [ ] -from ... import core as netlink -from .. import capi as capi class DummyLink(object): def __init__(self, link): self._rtnl_link = link - def brief(self): + @staticmethod + def brief(): return 'dummy' def init(link): diff --git a/python/netlink/route/links/inet.py b/python/netlink/route/links/inet.py index 8f89b4e..32fe3bc 100644 --- a/python/netlink/route/links/inet.py +++ b/python/netlink/route/links/inet.py @@ -56,7 +56,7 @@ class InetLink(object): def details(self, fmt): buf = fmt.nl('\n\t{0}\n\t'.format(util.title('Configuration:'))) - for i in range(DEVCONF_FORWARDING,DEVCONF_MAX+1): + for i in range(DEVCONF_FORWARDING, DEVCONF_MAX+1): if i & 1 and i > 1: buf += fmt.nl('\t') txt = util.kw(capi.rtnl_link_inet_devconf2str(i, 32)[0]) @@ -73,7 +73,7 @@ class InetLink(object): return capi.rtnl_link_inet_set_conf(self._link._rtnl_link, _resolve(id), int(value)) - @netlink.nlattr('link.inet.forwarding', type=bool, fmt=util.bool) + @netlink.nlattr('link.inet.forwarding', type=bool, fmt=util.boolean) @property def forwarding(self): return bool(self.get_conf(DEVCONF_FORWARDING)) @@ -82,7 +82,7 @@ class InetLink(object): def forwarding(self, value): self.set_conf(DEVCONF_FORWARDING, int(value)) - @netlink.nlattr('link.inet.mc_forwarding', type=bool, fmt=util.bool) + @netlink.nlattr('link.inet.mc_forwarding', type=bool, fmt=util.boolean) @property def mc_forwarding(self): return bool(self.get_conf(DEVCONF_MC_FORWARDING)) @@ -91,7 +91,7 @@ class InetLink(object): def mc_forwarding(self, value): self.set_conf(DEVCONF_MC_FORWARDING, int(value)) - @netlink.nlattr('link.inet.proxy_arp', type=bool, fmt=util.bool) + @netlink.nlattr('link.inet.proxy_arp', type=bool, fmt=util.boolean) @property def proxy_arp(self): return bool(self.get_conf(DEVCONF_PROXY_ARP)) @@ -100,7 +100,7 @@ class InetLink(object): def proxy_arp(self, value): self.set_conf(DEVCONF_PROXY_ARP, int(value)) - @netlink.nlattr('link.inet.accept_redirects', type=bool, fmt=util.bool) + @netlink.nlattr('link.inet.accept_redirects', type=bool, fmt=util.boolean) @property def accept_redirects(self): return bool(self.get_conf(DEVCONF_ACCEPT_REDIRECTS)) @@ -109,7 +109,7 @@ class InetLink(object): def accept_redirects(self, value): self.set_conf(DEVCONF_ACCEPT_REDIRECTS, int(value)) - @netlink.nlattr('link.inet.secure_redirects', type=bool, fmt=util.bool) + @netlink.nlattr('link.inet.secure_redirects', type=bool, fmt=util.boolean) @property def secure_redirects(self): return bool(self.get_conf(DEVCONF_SECURE_REDIRECTS)) @@ -118,7 +118,7 @@ class InetLink(object): def secure_redirects(self, value): self.set_conf(DEVCONF_SECURE_REDIRECTS, int(value)) - @netlink.nlattr('link.inet.send_redirects', type=bool, fmt=util.bool) + @netlink.nlattr('link.inet.send_redirects', type=bool, fmt=util.boolean) @property def send_redirects(self): return bool(self.get_conf(DEVCONF_SEND_REDIRECTS)) @@ -127,7 +127,7 @@ class InetLink(object): def send_redirects(self, value): self.set_conf(DEVCONF_SEND_REDIRECTS, int(value)) - @netlink.nlattr('link.inet.shared_media', type=bool, fmt=util.bool) + @netlink.nlattr('link.inet.shared_media', type=bool, fmt=util.boolean) @property def shared_media(self): return bool(self.get_conf(DEVCONF_SHARED_MEDIA)) diff --git a/python/netlink/route/qdisc/htb.py b/python/netlink/route/qdisc/htb.py index 799ce48..75f2eaa 100644 --- a/python/netlink/route/qdisc/htb.py +++ b/python/netlink/route/qdisc/htb.py @@ -129,7 +129,7 @@ class HTBClass(object): @netlink.nlattr('class.htb.level', type=int) @property def level(self): - level = capi.rtnl_htb_get_level(self._class._rtnl_class) + return capi.rtnl_htb_get_level(self._class._rtnl_class) @level.setter def level(self, value): diff --git a/python/netlink/route/tc.py b/python/netlink/route/tc.py index 9a81a67..3700585 100644 --- a/python/netlink/route/tc.py +++ b/python/netlink/route/tc.py @@ -12,10 +12,7 @@ __all__ = [ 'TcClass', ] -import socket -import sys from .. import core as netlink -from .. import capi as core_capi from . import capi as capi from .. import util as util from . import link as Link @@ -231,7 +228,8 @@ class Tc(netlink.Object): return ret + self._module_brief() - def details(self): + @staticmethod + def details(): return '{t|mtu} {t|mpu} {t|overhead} {t|linktype}' @property @@ -246,7 +244,8 @@ class Tc(netlink.Object): def qlen(self): return self.get_stat(STAT_QLEN) - def stats(self, fmt): + @staticmethod + def stats(fmt): return fmt.nl('{t|packets} {t|bytes} {t|qlen}') ########################################################################### @@ -272,10 +271,12 @@ class QdiscCache(netlink.Cache): # else: # return Qdisc._from_capi(capi.qdisc2obj(qdisc)) - def _new_object(self, obj): + @staticmethod + def _new_object(obj): return Qdisc(obj) - def _new_cache(self, cache): + @staticmethod + def _new_cache(cache): return QdiscCache(cache=cache) ########################################################################### @@ -300,10 +301,12 @@ class Qdisc(Tc): def from_capi(cls, obj): return cls(capi.qdisc2obj(obj)) - def _obj2type(self, obj): + @staticmethod + def _obj2type(obj): return capi.obj2qdisc(obj) - def _new_instance(self, obj): + @staticmethod + def _new_instance(obj): if not obj: raise ValueError() @@ -439,7 +442,8 @@ class TcClassCache(netlink.Cache): self._nl_cache = cache self._set_arg1(ifindex) - def _new_object(self, obj): + @staticmethod + def _new_object(obj): return TcClass(obj) def _new_cache(self, cache): @@ -467,10 +471,12 @@ class TcClass(Tc): def from_capi(cls, obj): return cls(capi.class2obj(obj)) - def _obj2type(self, obj): + @staticmethod + def _obj2type(obj): return capi.obj2class(obj) - def _new_instance(self, obj): + @staticmethod + def _new_instance(obj): if not obj: raise ValueError() @@ -492,7 +498,7 @@ class TcClass(Tc): # # format(details=False, stats=False) # - def format(self, details=False, stats=False, nodev=False, + def format(self, details=False, _stats=False, nodev=False, noparent=False, indent=''): """Return class as formatted text""" fmt = util.MyFormatter(self, indent) @@ -518,7 +524,8 @@ class ClassifierCache(netlink.Cache): self._set_arg1(ifindex) self._set_arg2(int(parent)) - def _new_object(self, obj): + @staticmethod + def _new_object(obj): return Classifier(obj) def _new_cache(self, cache): @@ -543,10 +550,12 @@ class Classifier(Tc): def from_capi(cls, obj): return cls(capi.cls2obj(obj)) - def _obj2type(self, obj): + @staticmethod + def _obj2type(obj): return capi.obj2cls(obj) - def _new_instance(self, obj): + @staticmethod + def _new_instance(obj): if not obj: raise ValueError() @@ -580,7 +589,7 @@ class Classifier(Tc): # # format(details=False, stats=False) # - def format(self, details=False, stats=False, nodev=False, + def format(self, details=False, _stats=False, nodev=False, noparent=False, indent=''): """Return class as formatted text""" fmt = util.MyFormatter(self, indent) diff --git a/python/netlink/util.py b/python/netlink/util.py index 995a6d2..0f2e547 100644 --- a/python/netlink/util.py +++ b/python/netlink/util.py @@ -68,7 +68,7 @@ def good(t): def title(t): return t -def bool(t): +def boolean(t): return str(t) def handle(t): @@ -81,7 +81,7 @@ class MyFormatter(Formatter): def _nlattr(self, key): value = getattr(self._obj, key) - title = None + title_ = None if isinstance(value, types.MethodType): value = value() @@ -93,13 +93,13 @@ class MyFormatter(Formatter): value = d['fmt'](value) if 'title' in d: - title = d['title'] + title_ = d['title'] except KeyError: pass except AttributeError: pass - return title, str(value) + return title_, str(value) def get_value(self, key, args, kwds): # Let default get_value() handle ints @@ -122,12 +122,12 @@ class MyFormatter(Formatter): return Formatter.get_value(self, key, args, kwds) key = key[2:] - (title, value) = self._nlattr(key) + (title_, value) = self._nlattr(key) if include_title: - if not title: - title = key # fall back to key as title - value = '{0} {1}'.format(kw(title), value) + if not title_: + title_ = key # fall back to key as title + value = '{0} {1}'.format(kw(title_), value) return value From 482c602b7416db212a7dae5a2a363ef9714846c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=BD=D0=BE=D1=83=D1=82=D0=B1?= =?UTF-8?q?=D1=83=D0=BA=20=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Tue, 5 Jun 2012 23:02:10 +0600 Subject: [PATCH 204/432] Refine some places No real logick change --- python/netlink/core.py | 3 ++- python/netlink/route/tc.py | 38 +++++++++++++++++++------------------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/python/netlink/core.py b/python/netlink/core.py index 3aa69c4..ecb02c3 100644 --- a/python/netlink/core.py +++ b/python/netlink/core.py @@ -463,7 +463,8 @@ class ReverseObjIterator(ObjIterator): class Cache(object): """Collection of netlink objects""" def __init__(self): - raise NotImplementedError() + if self.__class__ is Cache: + raise NotImplementedError() self.arg1 = None self.arg2 = None diff --git a/python/netlink/route/tc.py b/python/netlink/route/tc.py index 3700585..a79f31e 100644 --- a/python/netlink/route/tc.py +++ b/python/netlink/route/tc.py @@ -610,10 +610,13 @@ def get_qdisc(ifindex, handle=None, parent=None): _qdisc_cache.refill() for qdisc in _qdisc_cache: - if qdisc.ifindex == ifindex and \ - (handle == None or qdisc.handle == handle) and \ - (parent == None or qdisc.parent == parent): - l.append(qdisc) + if qdisc.ifindex != ifindex: + continue + if (handle is not None) and (qdisc.handle != handle): + continue + if (parent is not None) and (qdisc.parent != parent): + continue + l.append(qdisc) return l @@ -631,32 +634,29 @@ def get_class(ifindex, parent, handle=None): cache.refill() for cl in cache: - if (parent == None or cl.parent == parent) and \ - (handle == None or cl.handle == handle): - l.append(cl) + if (parent is not None) and (cl.parent != parent): + continue + if (handle is not None) and (cl.handle != handle): + continue + l.append(cl) return l _cls_cache = {} def get_cls(ifindex, parent, handle=None): - l = [] + + chain = _cls_cache.get(ifindex, dict()) try: - chain = _cls_cache[ifindex] - except KeyError: - _cls_cache[ifindex] = {} - - try: - cache = _cls_cache[ifindex][parent] + cache = chain[parent] except KeyError: cache = ClassifierCache(ifindex, parent) - _cls_cache[ifindex][parent] = cache + chain[parent] = cache cache.refill() - for cls in cache: - if handle == None or cls.handle == handle: - l.append(cls) + if handle is None: + return [ cls for cls in cache ] - return l + return [ cls for cls in cache if cls.handle == handle ] From 08e8b35d9f2ffe77e59a670744d2ace2b80e29d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=BD=D0=BE=D1=83=D1=82=D0=B1?= =?UTF-8?q?=D1=83=D0=BA=20=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Wed, 6 Jun 2012 01:56:58 +0600 Subject: [PATCH 205/432] Remove unnecessary comments --- python/netlink/core.py | 17 --------- python/netlink/route/address.py | 42 ---------------------- python/netlink/route/link.py | 47 ------------------------ python/netlink/route/links/vlan.py | 4 --- python/netlink/route/qdisc/htb.py | 18 ---------- python/netlink/route/tc.py | 58 ------------------------------ 6 files changed, 186 deletions(-) diff --git a/python/netlink/core.py b/python/netlink/core.py index ecb02c3..23286b5 100644 --- a/python/netlink/core.py +++ b/python/netlink/core.py @@ -256,8 +256,6 @@ class DumpParams(object): # underscore this to make sure it is deleted first upon module deletion _defaultDumpParams = DumpParams(NL_DUMP_LINE) -########################################################################### -# Cacheable Object (Base Class) class Object(object): """Cacheable object (base class)""" @@ -342,8 +340,6 @@ class Object(object): capi.nl_object_dump(self._nl_object, params._dp) - ##################################################################### - # mark @property def mark(self): return bool(capi.nl_object_is_marked(self._nl_object)) @@ -355,21 +351,15 @@ class Object(object): else: capi.nl_object_unmark(self._nl_object) - ##################################################################### - # shared @property def shared(self): return capi.nl_object_shared(self._nl_object) != 0 - ##################################################################### - # attrs @property def attrs(self): attr_list = capi.nl_object_attr_list(self._nl_object, 1024) return attr_list[0].split() - ##################################################################### - # refcnt @property def refcnt(self): return capi.nl_object_get_refcnt(self._nl_object) @@ -458,8 +448,6 @@ class ReverseObjIterator(ObjIterator): def get_next(self): return capi.nl_cache_get_prev(self._nl_object) -########################################################################### -# Cache class Cache(object): """Collection of netlink objects""" def __init__(self): @@ -577,7 +565,6 @@ class Cache(object): """ capi.nl_cache_mngt_unprovide(self._nl_cache) -########################################################################### # Cache Manager (Work in Progress) NL_AUTO_PROVIDE = 1 class CacheManager(object): @@ -601,8 +588,6 @@ class CacheManager(object): def add(self, name): capi.cache_mngr_add(self._mngr, name, None, None) -########################################################################### -# Address Family class AddressFamily(object): """Address family representation @@ -635,8 +620,6 @@ class AddressFamily(object): return 'AddressFamily({0!r})'.format(str(self)) -########################################################################### -# Abstract Address class AbstractAddress(object): """Abstract address object diff --git a/python/netlink/route/address.py b/python/netlink/route/address.py index 1b493fd..42c5059 100644 --- a/python/netlink/route/address.py +++ b/python/netlink/route/address.py @@ -19,8 +19,6 @@ from . import capi as capi from . import link as Link from .. import util as util -########################################################################### -# Address Cache class AddressCache(netlink.Cache): """Cache containing network addresses""" @@ -55,8 +53,6 @@ class AddressCache(netlink.Cache): def _new_cache(cache): return AddressCache(cache=cache) -########################################################################### -# Address Object class Address(netlink.Object): """Network address""" @@ -90,8 +86,6 @@ class Address(netlink.Object): def _new_instance(obj): return Address(obj) - ##################################################################### - # ifindex @netlink.nlattr('address.ifindex', type=int, immutable=True, fmt=util.num) @property @@ -107,8 +101,6 @@ class Address(netlink.Object): self.link = link - ##################################################################### - # link @netlink.nlattr('address.link', type=str, fmt=util.string) @property def link(self): @@ -133,8 +125,6 @@ class Address(netlink.Object): if capi.rtnl_addr_get_ifindex(self._orig) == 0: capi.rtnl_addr_set_ifindex(self._orig, value.ifindex) - ##################################################################### - # label @netlink.nlattr('address.label', type=str, fmt=util.string) @property def label(self): @@ -145,8 +135,6 @@ class Address(netlink.Object): def label(self, value): capi.rtnl_addr_set_label(self._rtnl_addr, value) - ##################################################################### - # flags @netlink.nlattr('address.flags', type=str, fmt=util.string) @property def flags(self): @@ -182,8 +170,6 @@ class Address(netlink.Object): else: self._set_flag(value) - ##################################################################### - # family @netlink.nlattr('address.family', type=int, immutable=True, fmt=util.num) @property @@ -199,8 +185,6 @@ class Address(netlink.Object): capi.rtnl_addr_set_family(self._rtnl_addr, int(value)) - ##################################################################### - # scope @netlink.nlattr('address.scope', type=int, fmt=util.num) @property def scope(self): @@ -214,8 +198,6 @@ class Address(netlink.Object): value = capi.rtnl_str2scope(value) capi.rtnl_addr_set_scope(self._rtnl_addr, value) - ##################################################################### - # local address @netlink.nlattr('address.local', type=str, immutable=True, fmt=util.addr) @property @@ -234,8 +216,6 @@ class Address(netlink.Object): if capi.rtnl_addr_get_local(self._orig) is None: capi.rtnl_addr_set_local(self._orig, a._nl_addr) - ##################################################################### - # Peer address @netlink.nlattr('address.peer', type=str, fmt=util.addr) @property def peer(self): @@ -248,8 +228,6 @@ class Address(netlink.Object): a = netlink.AbstractAddress(value) capi.rtnl_addr_set_peer(self._rtnl_addr, a._nl_addr) - ##################################################################### - # Broadcast address @netlink.nlattr('address.broadcast', type=str, fmt=util.addr) @property def broadcast(self): @@ -262,8 +240,6 @@ class Address(netlink.Object): a = netlink.AbstractAddress(value) capi.rtnl_addr_set_broadcast(self._rtnl_addr, a._nl_addr) - ##################################################################### - # Multicast address @netlink.nlattr('address.multicast', type=str, fmt=util.addr) @property def multicast(self): @@ -280,8 +256,6 @@ class Address(netlink.Object): capi.rtnl_addr_set_multicast(self._rtnl_addr, a._nl_addr) - ##################################################################### - # Anycast address @netlink.nlattr('address.anycast', type=str, fmt=util.addr) @property def anycast(self): @@ -294,8 +268,6 @@ class Address(netlink.Object): a = netlink.AbstractAddress(value) capi.rtnl_addr_set_anycast(self._rtnl_addr, a._nl_addr) - ##################################################################### - # Valid lifetime @netlink.nlattr('address.valid_lifetime', type=int, immutable=True, fmt=util.num) @property @@ -311,8 +283,6 @@ class Address(netlink.Object): def valid_lifetime(self, value): capi.rtnl_addr_set_valid_lifetime(self._rtnl_addr, int(value)) - ##################################################################### - # Preferred lifetime @netlink.nlattr('address.preferred_lifetime', type=int, immutable=True, fmt=util.num) @property @@ -328,8 +298,6 @@ class Address(netlink.Object): def preferred_lifetime(self, value): capi.rtnl_addr_set_preferred_lifetime(self._rtnl_addr, int(value)) - ##################################################################### - # Creation Time @netlink.nlattr('address.create_time', type=int, immutable=True, fmt=util.num) @property @@ -338,8 +306,6 @@ class Address(netlink.Object): hsec = capi.rtnl_addr_get_create_time(self._rtnl_addr) return datetime.timedelta(milliseconds=10*hsec) - ##################################################################### - # Last Update @netlink.nlattr('address.last_update', type=int, immutable=True, fmt=util.num) @property @@ -348,8 +314,6 @@ class Address(netlink.Object): hsec = capi.rtnl_addr_get_last_update_time(self._rtnl_addr) return datetime.timedelta(milliseconds=10*hsec) - ##################################################################### - # add() def add(self, socket=None, flags=None): if not socket: socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) @@ -361,8 +325,6 @@ class Address(netlink.Object): if ret < 0: raise netlink.KernelError(ret) - ##################################################################### - # delete() def delete(self, socket, flags=0): """Attempt to delete this address in the kernel""" ret = capi.rtnl_addr_delete(socket._sock, self._rtnl_addr, flags) @@ -377,10 +339,6 @@ class Address(netlink.Object): def _flags(self): return ','.join(self.flags) - ################################################################### - # - # format(details=False, stats=False) - # def format(self, details=False, stats=False, nodev=False, indent=''): """Return address as formatted text""" fmt = util.MyFormatter(self, indent) diff --git a/python/netlink/route/link.py b/python/netlink/route/link.py index 66c0ab8..4cd9f8a 100644 --- a/python/netlink/route/link.py +++ b/python/netlink/route/link.py @@ -50,7 +50,6 @@ from . import capi as capi from .links import inet as inet from .. import util as util -########################################################################### # Link statistics definitions RX_PACKETS = 0 TX_PACKETS = 1 @@ -110,8 +109,6 @@ ICMP6_INERRORS = 54 ICMP6_OUTMSGS = 55 ICMP6_OUTERRORS = 56 -########################################################################### -# Link Cache class LinkCache(netlink.Cache): """Cache of network links""" @@ -142,8 +139,6 @@ class LinkCache(netlink.Cache): def _new_cache(self, cache): return LinkCache(family=self.arg1, cache=cache) -########################################################################### -# Link Object class Link(netlink.Object): """Network link""" @@ -175,8 +170,6 @@ class Link(netlink.Object): return Link(obj) - ##################################################################### - # ifindex @netlink.nlattr('link.ifindex', type=int, immutable=True, fmt=util.num) @property def ifindex(self): @@ -192,8 +185,6 @@ class Link(netlink.Object): if capi.rtnl_link_get_ifindex(self._orig) == 0: capi.rtnl_link_set_ifindex(self._orig, int(value)) - ##################################################################### - # name @netlink.nlattr('link.name', type=str, fmt=util.bold) @property def name(self): @@ -211,8 +202,6 @@ class Link(netlink.Object): if capi.rtnl_link_get_name(self._orig) is None: capi.rtnl_link_set_name(self._orig, value) - ##################################################################### - # flags @netlink.nlattr('link.flags', type=str, fmt=util.string) @property def flags(self): @@ -246,8 +235,6 @@ class Link(netlink.Object): else: self._set_flag(value) - ##################################################################### - # mtu @netlink.nlattr('link.mtu', type=int, fmt=util.num) @property def mtu(self): @@ -258,8 +245,6 @@ class Link(netlink.Object): def mtu(self, value): capi.rtnl_link_set_mtu(self._rtnl_link, int(value)) - ##################################################################### - # family @netlink.nlattr('link.family', type=int, immutable=True, fmt=util.num) @property def family(self): @@ -270,8 +255,6 @@ class Link(netlink.Object): def family(self, value): capi.rtnl_link_set_family(self._rtnl_link, value) - ##################################################################### - # address @netlink.nlattr('link.address', type=str, fmt=util.addr) @property def address(self): @@ -283,8 +266,6 @@ class Link(netlink.Object): def address(self, value): capi.rtnl_link_set_addr(self._rtnl_link, value._addr) - ##################################################################### - # broadcast @netlink.nlattr('link.broadcast', type=str, fmt=util.addr) @property def broadcast(self): @@ -296,8 +277,6 @@ class Link(netlink.Object): def broadcast(self, value): capi.rtnl_link_set_broadcast(self._rtnl_link, value._addr) - ##################################################################### - # qdisc @netlink.nlattr('link.qdisc', type=str, immutable=True, fmt=util.string) @property def qdisc(self): @@ -308,8 +287,6 @@ class Link(netlink.Object): def qdisc(self, value): capi.rtnl_link_set_qdisc(self._rtnl_link, value) - ##################################################################### - # txqlen @netlink.nlattr('link.txqlen', type=int, fmt=util.num) @property def txqlen(self): @@ -320,8 +297,6 @@ class Link(netlink.Object): def txqlen(self, value): capi.rtnl_link_set_txqlen(self._rtnl_link, int(value)) - ##################################################################### - # weight @netlink.nlattr('link.weight', type=str, fmt=util.string) @property def weight(self): @@ -340,8 +315,6 @@ class Link(netlink.Object): v = int(value) capi.rtnl_link_set_weight(self._rtnl_link, v) - ##################################################################### - # arptype @netlink.nlattr('link.arptype', type=str, immutable=True, fmt=util.string) @property def arptype(self): @@ -354,8 +327,6 @@ class Link(netlink.Object): i = core_capi.nl_str2llproto(value) capi.rtnl_link_set_arptype(self._rtnl_link, i) - ##################################################################### - # operstate @netlink.nlattr('link.operstate', type=str, immutable=True, fmt=util.string, title='state') @property @@ -369,8 +340,6 @@ class Link(netlink.Object): i = capi.rtnl_link_str2operstate(value) capi.rtnl_link_set_operstate(self._rtnl_link, i) - ##################################################################### - # mode @netlink.nlattr('link.mode', type=str, immutable=True, fmt=util.string) @property def mode(self): @@ -383,8 +352,6 @@ class Link(netlink.Object): i = capi.rtnl_link_str2mode(value) capi.rtnl_link_set_linkmode(self._rtnl_link, i) - ##################################################################### - # alias @netlink.nlattr('link.alias', type=str, fmt=util.string) @property def alias(self): @@ -395,8 +362,6 @@ class Link(netlink.Object): def alias(self, value): capi.rtnl_link_set_ifalias(self._rtnl_link, value) - ##################################################################### - # type @netlink.nlattr('link.type', type=str, fmt=util.string) @property def type(self): @@ -410,8 +375,6 @@ class Link(netlink.Object): self._module_lookup('netlink.route.links.' + value) - ##################################################################### - # get_stat() def get_stat(self, stat): """Retrieve statistical information""" if type(stat) is str: @@ -421,8 +384,6 @@ class Link(netlink.Object): return capi.rtnl_link_get_stat(self._rtnl_link, stat) - ##################################################################### - # add() def add(self, sock=None, flags=None): if not sock: sock = netlink.lookup_socket(netlink.NETLINK_ROUTE) @@ -434,8 +395,6 @@ class Link(netlink.Object): if ret < 0: raise netlink.KernelError(ret) - ##################################################################### - # change() def change(self, sock=None, flags=0): """Commit changes made to the link object""" if sock is None: @@ -447,8 +406,6 @@ class Link(netlink.Object): if ret < 0: raise netlink.KernelError(ret) - ##################################################################### - # delete() def delete(self, sock=None): """Attempt to delete this link in the kernel""" if sock is None: @@ -497,10 +454,6 @@ class Link(netlink.Object): pass return buf - ################################################################### - # - # format(details=False, stats=False) - # def format(self, details=False, stats=False, indent=''): """Return link as formatted text""" fmt = util.MyFormatter(self, indent) diff --git a/python/netlink/route/links/vlan.py b/python/netlink/route/links/vlan.py index d13a8c6..646ce15 100644 --- a/python/netlink/route/links/vlan.py +++ b/python/netlink/route/links/vlan.py @@ -15,8 +15,6 @@ class VLANLink(object): def __init__(self, link): self._link = link - ################################################################### - # id @netlink.nlattr('link.vlan.id', type=int) @property def id(self): @@ -27,8 +25,6 @@ class VLANLink(object): def id(self, value): capi.rtnl_link_vlan_set_id(self._link, int(value)) - ################################################################### - # flags @netlink.nlattr('link.vlan.flags', type=str) @property def flags(self): diff --git a/python/netlink/route/qdisc/htb.py b/python/netlink/route/qdisc/htb.py index 75f2eaa..2d3ea94 100644 --- a/python/netlink/route/qdisc/htb.py +++ b/python/netlink/route/qdisc/htb.py @@ -17,8 +17,6 @@ class HTBQdisc(object): def __init__(self, qdisc): self._qdisc = qdisc - ################################################################### - # default class @netlink.nlattr('qdisc.htb.default_class', type=int) @property def default_class(self): @@ -28,8 +26,6 @@ class HTBQdisc(object): def default_class(self, value): capi.rtnl_htb_set_defcls(self._qdisc._rtnl_qdisc, int(value)) - ##################################################################### - # r2q @netlink.nlattr('qdisc.htb.r2q', type=int) @property def r2q(self): @@ -54,8 +50,6 @@ class HTBClass(object): def __init__(self, cl): self._class = cl - ##################################################################### - # rate @netlink.nlattr('class.htb.rate', type=str) @property def rate(self): @@ -66,8 +60,6 @@ class HTBClass(object): def rate(self, value): capi.rtnl_htb_set_rate(self._class._rtnl_class, int(value)) - ##################################################################### - # ceil @netlink.nlattr('class.htb.ceil', type=str) @property def ceil(self): @@ -78,8 +70,6 @@ class HTBClass(object): def ceil(self, value): capi.rtnl_htb_set_ceil(self._class._rtnl_class, int(value)) - ##################################################################### - # burst @netlink.nlattr('class.htb.burst', type=str) @property def burst(self): @@ -90,8 +80,6 @@ class HTBClass(object): def burst(self, value): capi.rtnl_htb_set_rbuffer(self._class._rtnl_class, int(value)) - ##################################################################### - # ceil burst @netlink.nlattr('class.htb.ceil_burst', type=str) @property def ceil_burst(self): @@ -102,8 +90,6 @@ class HTBClass(object): def ceil_burst(self, value): capi.rtnl_htb_set_cbuffer(self._class._rtnl_class, int(value)) - ##################################################################### - # priority @netlink.nlattr('class.htb.prio', type=int) @property def prio(self): @@ -113,8 +99,6 @@ class HTBClass(object): def prio(self, value): capi.rtnl_htb_set_prio(self._class._rtnl_class, int(value)) - ##################################################################### - # quantum @netlink.nlattr('class.htb.quantum', type=int) @property def quantum(self): @@ -124,8 +108,6 @@ class HTBClass(object): def quantum(self, value): capi.rtnl_htb_set_quantum(self._class._rtnl_class, int(value)) - ##################################################################### - # level @netlink.nlattr('class.htb.level', type=int) @property def level(self): diff --git a/python/netlink/route/tc.py b/python/netlink/route/tc.py index a79f31e..503f5a4 100644 --- a/python/netlink/route/tc.py +++ b/python/netlink/route/tc.py @@ -42,8 +42,6 @@ STAT_OVERLIMITS = 8 STAT_MAX = STAT_OVERLIMITS -########################################################################### -# Handle class Handle(object): """ Traffic control handle @@ -83,16 +81,12 @@ class Handle(object): def isroot(self): return self._val == TC_H_ROOT or self._val == TC_H_INGRESS -########################################################################### -# TC Cache class TcCache(netlink.Cache): """Cache of traffic control object""" def __getitem__(self, key): raise NotImplementedError() -########################################################################### -# Tc Object class Tc(netlink.Object): def __cmp__(self, other): diff = self.ifindex - other.ifindex @@ -109,8 +103,6 @@ class Tc(netlink.Object): """True if tc object is a root object""" return self.parent.isroot() - ##################################################################### - # ifindex @property def ifindex(self): """interface index""" @@ -120,8 +112,6 @@ class Tc(netlink.Object): def ifindex(self, value): capi.rtnl_tc_set_ifindex(self._rtnl_tc, int(value)) - ##################################################################### - # link @property def link(self): link = capi.rtnl_tc_get_link(self._rtnl_tc) @@ -134,8 +124,6 @@ class Tc(netlink.Object): def link(self, value): capi.rtnl_tc_set_link(self._rtnl_tc, value._link) - ##################################################################### - # mtu @property def mtu(self): return capi.rtnl_tc_get_mtu(self._rtnl_tc) @@ -144,8 +132,6 @@ class Tc(netlink.Object): def mtu(self, value): capi.rtnl_tc_set_mtu(self._rtnl_tc, int(value)) - ##################################################################### - # mpu @property def mpu(self): return capi.rtnl_tc_get_mpu(self._rtnl_tc) @@ -154,8 +140,6 @@ class Tc(netlink.Object): def mpu(self, value): capi.rtnl_tc_set_mpu(self._rtnl_tc, int(value)) - ##################################################################### - # overhead @property def overhead(self): return capi.rtnl_tc_get_overhead(self._rtnl_tc) @@ -164,8 +148,6 @@ class Tc(netlink.Object): def overhead(self, value): capi.rtnl_tc_set_overhead(self._rtnl_tc, int(value)) - ##################################################################### - # linktype @property def linktype(self): return capi.rtnl_tc_get_linktype(self._rtnl_tc) @@ -174,8 +156,6 @@ class Tc(netlink.Object): def linktype(self, value): capi.rtnl_tc_set_linktype(self._rtnl_tc, int(value)) - ##################################################################### - # handle @property def handle(self): return Handle(capi.rtnl_tc_get_handle(self._rtnl_tc)) @@ -184,8 +164,6 @@ class Tc(netlink.Object): def handle(self, value): capi.rtnl_tc_set_handle(self._rtnl_tc, int(value)) - ##################################################################### - # parent @property def parent(self): return Handle(capi.rtnl_tc_get_parent(self._rtnl_tc)) @@ -194,8 +172,6 @@ class Tc(netlink.Object): def parent(self, value): capi.rtnl_tc_set_parent(self._rtnl_tc, int(value)) - ##################################################################### - # kind @property def kind(self): return capi.rtnl_tc_get_kind(self._rtnl_tc) @@ -248,8 +224,6 @@ class Tc(netlink.Object): def stats(fmt): return fmt.nl('{t|packets} {t|bytes} {t|qlen}') -########################################################################### -# Queueing discipline cache class QdiscCache(netlink.Cache): """Cache of qdiscs""" @@ -279,8 +253,6 @@ class QdiscCache(netlink.Cache): def _new_cache(cache): return QdiscCache(cache=cache) -########################################################################### -# Qdisc Object class Qdisc(Tc): """Queueing discipline""" @@ -326,8 +298,6 @@ class Qdisc(Tc): return ret -# ##################################################################### -# # add() # def add(self, socket, flags=None): # if not flags: # flags = netlink.NLM_F_CREATE @@ -336,8 +306,6 @@ class Qdisc(Tc): # if ret < 0: # raise netlink.KernelError(ret) # -# ##################################################################### -# # change() # def change(self, socket, flags=0): # """Commit changes made to the link object""" # if not self._orig: @@ -346,18 +314,12 @@ class Qdisc(Tc): # if ret < 0: # raise netlink.KernelError(ret) # -# ##################################################################### -# # delete() # def delete(self, socket): # """Attempt to delete this link in the kernel""" # ret = capi.rtnl_link_delete(socket._sock, self._link) # if ret < 0: # raise netlink.KernelError(ret) - ################################################################### - # - # format(details=False, stats=False) - # def format(self, details=False, stats=False, nodev=False, noparent=False, indent=''): """Return qdisc as formatted text""" @@ -429,8 +391,6 @@ class Qdisc(Tc): return buf -########################################################################### -# Traffic class cache class TcClassCache(netlink.Cache): """Cache of traffic classes""" @@ -449,8 +409,6 @@ class TcClassCache(netlink.Cache): def _new_cache(self, cache): return TcClassCache(self.arg1, cache=cache) -########################################################################### -# Traffic Class Object class TcClass(Tc): """Traffic Class""" @@ -494,10 +452,6 @@ class TcClass(Tc): return ret - ################################################################### - # - # format(details=False, stats=False) - # def format(self, details=False, _stats=False, nodev=False, noparent=False, indent=''): """Return class as formatted text""" @@ -510,8 +464,6 @@ class TcClass(Tc): return buf -########################################################################### -# Classifier Cache class ClassifierCache(netlink.Cache): """Cache of traffic classifiers objects""" @@ -531,8 +483,6 @@ class ClassifierCache(netlink.Cache): def _new_cache(self, cache): return ClassifierCache(self.arg1, self.arg2, cache=cache) -########################################################################### -# Classifier Object class Classifier(Tc): """Classifier""" @@ -561,8 +511,6 @@ class Classifier(Tc): return Classifier(obj) - ##################################################################### - # priority @property def priority(self): return capi.rtnl_cls_get_prio(self._rtnl_cls) @@ -571,8 +519,6 @@ class Classifier(Tc): def priority(self, value): capi.rtnl_cls_set_prio(self._rtnl_cls, int(value)) - ##################################################################### - # protocol @property def protocol(self): return capi.rtnl_cls_get_protocol(self._rtnl_cls) @@ -585,10 +531,6 @@ class Classifier(Tc): def childs(self): return [] - ################################################################### - # - # format(details=False, stats=False) - # def format(self, details=False, _stats=False, nodev=False, noparent=False, indent=''): """Return class as formatted text""" From 139e3d3203955723606ba395c726a343d3c343ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA?= Date: Thu, 7 Jun 2012 15:15:50 +0600 Subject: [PATCH 206/432] nl_pickup removed from python binding --- python/netlink/capi.i | 5 ----- 1 file changed, 5 deletions(-) diff --git a/python/netlink/capi.i b/python/netlink/capi.i index 8d80520..73c4bf3 100644 --- a/python/netlink/capi.i +++ b/python/netlink/capi.i @@ -159,11 +159,6 @@ extern void free_dump_params(struct nl_dump_params *); extern int nl_connect(struct nl_sock *, int); extern void nl_close(struct nl_sock *); -extern int nl_pickup(struct nl_sock *, int (*parser)(struct nl_cache_ops *, - struct sockaddr_nl *, - struct nlmsghdr *, - struct nl_parser_param *), - struct nl_object **); /* */ extern struct nl_sock *nl_socket_alloc(void); From 87d370912ca8fe4aa68e8fd61cfee201d959ee1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA?= Date: Thu, 7 Jun 2012 13:48:06 +0600 Subject: [PATCH 207/432] netlink.nlattr re-implemented in more pythonic way --- python/netlink/core.py | 38 ++++-------------------------- python/netlink/route/address.py | 37 ++++++++++++----------------- python/netlink/route/link.py | 31 ++++++++++++------------ python/netlink/route/links/inet.py | 16 +++++++------ python/netlink/route/links/vlan.py | 4 ++-- python/netlink/route/qdisc/htb.py | 18 +++++++------- python/netlink/route/tc.py | 15 +++--------- python/netlink/util.py | 25 ++++++++------------ 8 files changed, 67 insertions(+), 117 deletions(-) diff --git a/python/netlink/core.py b/python/netlink/core.py index 23286b5..05420ef 100644 --- a/python/netlink/core.py +++ b/python/netlink/core.py @@ -381,21 +381,6 @@ class Object(object): obj, attr = self._resolve(attr) return hasattr(obj, attr) - def apply(self, attr, val): - try: - d = attrs[self._name + '.' + attr] - except KeyError: - raise KeyError('Unknown ' + self._name + - ' attribute: ' + attr) - - if 'immutable' in d: - raise ImmutableError(attr) - - if not self._hasattr(attr): - raise KeyError('Invalid ' + self._name + - ' attribute: ' + attr) - self._setattr(attr, val) - class ObjIterator(object): def __init__(self, cache, obj): self._cache = cache @@ -733,42 +718,27 @@ class AbstractAddress(object): capi.nl_addr_set_family(self._nl_addr, int(value)) -# global dictionay for all object attributes -# -# attrs[type][keyword] : value -# # keyword: # type = { int | str } # immutable = { True | False } # fmt = func (formatting function) -# -attrs = {} +# title = string -def add_attr(name, **kwds): - attrs[name] = {} - for k in kwds: - attrs[name][k] = kwds[k] - -def nlattr(name, **kwds): +def nlattr(**kwds): """netlink object attribute decorator decorator used to mark mutable and immutable properties of netlink objects. All properties marked as such are regarded to be accessable. - @netlink.nlattr('my_type.my_attr', type=int) @property + @netlink.nlattr(type=int) def my_attr(self): return self._my_attr """ - attrs[name] = {} - for k in kwds: - attrs[name][k] = kwds[k] - def wrap_fn(func): + func.formatinfo = kwds return func - return wrap_fn - diff --git a/python/netlink/route/address.py b/python/netlink/route/address.py index 42c5059..cab2a97 100644 --- a/python/netlink/route/address.py +++ b/python/netlink/route/address.py @@ -86,9 +86,8 @@ class Address(netlink.Object): def _new_instance(obj): return Address(obj) - @netlink.nlattr('address.ifindex', type=int, immutable=True, - fmt=util.num) @property + @netlink.nlattr(type=int, immutable=True, fmt=util.num) def ifindex(self): """interface index""" return capi.rtnl_addr_get_ifindex(self._rtnl_addr) @@ -101,8 +100,8 @@ class Address(netlink.Object): self.link = link - @netlink.nlattr('address.link', type=str, fmt=util.string) @property + @netlink.nlattr(type=str, fmt=util.string) def link(self): link = capi.rtnl_addr_get_link(self._rtnl_addr) if not link: @@ -125,8 +124,8 @@ class Address(netlink.Object): if capi.rtnl_addr_get_ifindex(self._orig) == 0: capi.rtnl_addr_set_ifindex(self._orig, value.ifindex) - @netlink.nlattr('address.label', type=str, fmt=util.string) @property + @netlink.nlattr(type=str, fmt=util.string) def label(self): """address label""" return capi.rtnl_addr_get_label(self._rtnl_addr) @@ -135,8 +134,8 @@ class Address(netlink.Object): def label(self, value): capi.rtnl_addr_set_label(self._rtnl_addr, value) - @netlink.nlattr('address.flags', type=str, fmt=util.string) @property + @netlink.nlattr(type=str, fmt=util.string) def flags(self): """Flags @@ -170,9 +169,8 @@ class Address(netlink.Object): else: self._set_flag(value) - @netlink.nlattr('address.family', type=int, immutable=True, - fmt=util.num) @property + @netlink.nlattr(type=int, immutable=True, fmt=util.num) def family(self): """Address family""" fam = capi.rtnl_addr_get_family(self._rtnl_addr) @@ -185,8 +183,8 @@ class Address(netlink.Object): capi.rtnl_addr_set_family(self._rtnl_addr, int(value)) - @netlink.nlattr('address.scope', type=int, fmt=util.num) @property + @netlink.nlattr(type=int, fmt=util.num) def scope(self): """Address scope""" scope = capi.rtnl_addr_get_scope(self._rtnl_addr) @@ -198,9 +196,8 @@ class Address(netlink.Object): value = capi.rtnl_str2scope(value) capi.rtnl_addr_set_scope(self._rtnl_addr, value) - @netlink.nlattr('address.local', type=str, immutable=True, - fmt=util.addr) @property + @netlink.nlattr(type=str, immutable=True, fmt=util.addr) def local(self): """Local address""" a = capi.rtnl_addr_get_local(self._rtnl_addr) @@ -216,8 +213,8 @@ class Address(netlink.Object): if capi.rtnl_addr_get_local(self._orig) is None: capi.rtnl_addr_set_local(self._orig, a._nl_addr) - @netlink.nlattr('address.peer', type=str, fmt=util.addr) @property + @netlink.nlattr(type=str, fmt=util.addr) def peer(self): """Peer address""" a = capi.rtnl_addr_get_peer(self._rtnl_addr) @@ -228,8 +225,8 @@ class Address(netlink.Object): a = netlink.AbstractAddress(value) capi.rtnl_addr_set_peer(self._rtnl_addr, a._nl_addr) - @netlink.nlattr('address.broadcast', type=str, fmt=util.addr) @property + @netlink.nlattr(type=str, fmt=util.addr) def broadcast(self): """Broadcast address""" a = capi.rtnl_addr_get_broadcast(self._rtnl_addr) @@ -240,8 +237,8 @@ class Address(netlink.Object): a = netlink.AbstractAddress(value) capi.rtnl_addr_set_broadcast(self._rtnl_addr, a._nl_addr) - @netlink.nlattr('address.multicast', type=str, fmt=util.addr) @property + @netlink.nlattr(type=str, fmt=util.addr) def multicast(self): """multicast address""" a = capi.rtnl_addr_get_multicast(self._rtnl_addr) @@ -256,8 +253,8 @@ class Address(netlink.Object): capi.rtnl_addr_set_multicast(self._rtnl_addr, a._nl_addr) - @netlink.nlattr('address.anycast', type=str, fmt=util.addr) @property + @netlink.nlattr(type=str, fmt=util.addr) def anycast(self): """anycast address""" a = capi.rtnl_addr_get_anycast(self._rtnl_addr) @@ -268,9 +265,8 @@ class Address(netlink.Object): a = netlink.AbstractAddress(value) capi.rtnl_addr_set_anycast(self._rtnl_addr, a._nl_addr) - @netlink.nlattr('address.valid_lifetime', type=int, immutable=True, - fmt=util.num) @property + @netlink.nlattr(type=int, immutable=True, fmt=util.num) def valid_lifetime(self): """Valid lifetime""" msecs = capi.rtnl_addr_get_valid_lifetime(self._rtnl_addr) @@ -283,9 +279,8 @@ class Address(netlink.Object): def valid_lifetime(self, value): capi.rtnl_addr_set_valid_lifetime(self._rtnl_addr, int(value)) - @netlink.nlattr('address.preferred_lifetime', type=int, - immutable=True, fmt=util.num) @property + @netlink.nlattr(type=int, immutable=True, fmt=util.num) def preferred_lifetime(self): """Preferred lifetime""" msecs = capi.rtnl_addr_get_preferred_lifetime(self._rtnl_addr) @@ -298,17 +293,15 @@ class Address(netlink.Object): def preferred_lifetime(self, value): capi.rtnl_addr_set_preferred_lifetime(self._rtnl_addr, int(value)) - @netlink.nlattr('address.create_time', type=int, immutable=True, - fmt=util.num) @property + @netlink.nlattr(type=int, immutable=True, fmt=util.num) def create_time(self): """Creation time""" hsec = capi.rtnl_addr_get_create_time(self._rtnl_addr) return datetime.timedelta(milliseconds=10*hsec) - @netlink.nlattr('address.last_update', type=int, immutable=True, - fmt=util.num) @property + @netlink.nlattr(type=int, immutable=True, fmt=util.num) def last_update(self): """Last update""" hsec = capi.rtnl_addr_get_last_update_time(self._rtnl_addr) diff --git a/python/netlink/route/link.py b/python/netlink/route/link.py index 4cd9f8a..a537cd5 100644 --- a/python/netlink/route/link.py +++ b/python/netlink/route/link.py @@ -170,8 +170,8 @@ class Link(netlink.Object): return Link(obj) - @netlink.nlattr('link.ifindex', type=int, immutable=True, fmt=util.num) @property + @netlink.nlattr(type=int, immutable=True, fmt=util.num) def ifindex(self): """interface index""" return capi.rtnl_link_get_ifindex(self._rtnl_link) @@ -185,8 +185,8 @@ class Link(netlink.Object): if capi.rtnl_link_get_ifindex(self._orig) == 0: capi.rtnl_link_set_ifindex(self._orig, int(value)) - @netlink.nlattr('link.name', type=str, fmt=util.bold) @property + @netlink.nlattr(type=str, fmt=util.bold) def name(self): """Name of link""" return capi.rtnl_link_get_name(self._rtnl_link) @@ -202,8 +202,8 @@ class Link(netlink.Object): if capi.rtnl_link_get_name(self._orig) is None: capi.rtnl_link_set_name(self._orig, value) - @netlink.nlattr('link.flags', type=str, fmt=util.string) @property + @netlink.nlattr(type=str, fmt=util.string) def flags(self): """Flags Setting this property will *Not* reset flags to value you supply in @@ -235,8 +235,8 @@ class Link(netlink.Object): else: self._set_flag(value) - @netlink.nlattr('link.mtu', type=int, fmt=util.num) @property + @netlink.nlattr(type=int, fmt=util.num) def mtu(self): """Maximum Transmission Unit""" return capi.rtnl_link_get_mtu(self._rtnl_link) @@ -245,8 +245,8 @@ class Link(netlink.Object): def mtu(self, value): capi.rtnl_link_set_mtu(self._rtnl_link, int(value)) - @netlink.nlattr('link.family', type=int, immutable=True, fmt=util.num) @property + @netlink.nlattr(type=int, immutable=True, fmt=util.num) def family(self): """Address family""" return capi.rtnl_link_get_family(self._rtnl_link) @@ -255,8 +255,8 @@ class Link(netlink.Object): def family(self, value): capi.rtnl_link_set_family(self._rtnl_link, value) - @netlink.nlattr('link.address', type=str, fmt=util.addr) @property + @netlink.nlattr(type=str, fmt=util.addr) def address(self): """Hardware address (MAC address)""" a = capi.rtnl_link_get_addr(self._rtnl_link) @@ -266,8 +266,8 @@ class Link(netlink.Object): def address(self, value): capi.rtnl_link_set_addr(self._rtnl_link, value._addr) - @netlink.nlattr('link.broadcast', type=str, fmt=util.addr) @property + @netlink.nlattr(type=str, fmt=util.addr) def broadcast(self): """Hardware broadcast address""" a = capi.rtnl_link_get_broadcast(self._rtnl_link) @@ -277,8 +277,8 @@ class Link(netlink.Object): def broadcast(self, value): capi.rtnl_link_set_broadcast(self._rtnl_link, value._addr) - @netlink.nlattr('link.qdisc', type=str, immutable=True, fmt=util.string) @property + @netlink.nlattr(type=str, immutable=True, fmt=util.string) def qdisc(self): """Name of qdisc (cannot be changed)""" return capi.rtnl_link_get_qdisc(self._rtnl_link) @@ -287,8 +287,8 @@ class Link(netlink.Object): def qdisc(self, value): capi.rtnl_link_set_qdisc(self._rtnl_link, value) - @netlink.nlattr('link.txqlen', type=int, fmt=util.num) @property + @netlink.nlattr(type=int, fmt=util.num) def txqlen(self): """Length of transmit queue""" return capi.rtnl_link_get_txqlen(self._rtnl_link) @@ -297,8 +297,8 @@ class Link(netlink.Object): def txqlen(self, value): capi.rtnl_link_set_txqlen(self._rtnl_link, int(value)) - @netlink.nlattr('link.weight', type=str, fmt=util.string) @property + @netlink.nlattr(type=str, fmt=util.string) def weight(self): """Weight""" v = capi.rtnl_link_get_weight(self._rtnl_link) @@ -315,8 +315,8 @@ class Link(netlink.Object): v = int(value) capi.rtnl_link_set_weight(self._rtnl_link, v) - @netlink.nlattr('link.arptype', type=str, immutable=True, fmt=util.string) @property + @netlink.nlattr(type=str, immutable=True, fmt=util.string) def arptype(self): """Type of link (cannot be changed)""" type_ = capi.rtnl_link_get_arptype(self._rtnl_link) @@ -327,9 +327,8 @@ class Link(netlink.Object): i = core_capi.nl_str2llproto(value) capi.rtnl_link_set_arptype(self._rtnl_link, i) - @netlink.nlattr('link.operstate', type=str, immutable=True, - fmt=util.string, title='state') @property + @netlink.nlattr(type=str, immutable=True, fmt=util.string, title='state') def operstate(self): """Operational status""" operstate = capi.rtnl_link_get_operstate(self._rtnl_link) @@ -340,8 +339,8 @@ class Link(netlink.Object): i = capi.rtnl_link_str2operstate(value) capi.rtnl_link_set_operstate(self._rtnl_link, i) - @netlink.nlattr('link.mode', type=str, immutable=True, fmt=util.string) @property + @netlink.nlattr(type=str, immutable=True, fmt=util.string) def mode(self): """Link mode""" mode = capi.rtnl_link_get_linkmode(self._rtnl_link) @@ -352,8 +351,8 @@ class Link(netlink.Object): i = capi.rtnl_link_str2mode(value) capi.rtnl_link_set_linkmode(self._rtnl_link, i) - @netlink.nlattr('link.alias', type=str, fmt=util.string) @property + @netlink.nlattr(type=str, fmt=util.string) def alias(self): """Interface alias (SNMP)""" return capi.rtnl_link_get_ifalias(self._rtnl_link) @@ -362,8 +361,8 @@ class Link(netlink.Object): def alias(self, value): capi.rtnl_link_set_ifalias(self._rtnl_link, value) - @netlink.nlattr('link.type', type=str, fmt=util.string) @property + @netlink.nlattr(type=str, fmt=util.string) def type(self): """Link type""" return capi.rtnl_link_get_type(self._rtnl_link) diff --git a/python/netlink/route/links/inet.py b/python/netlink/route/links/inet.py index 32fe3bc..f5f45cb 100644 --- a/python/netlink/route/links/inet.py +++ b/python/netlink/route/links/inet.py @@ -73,8 +73,8 @@ class InetLink(object): return capi.rtnl_link_inet_set_conf(self._link._rtnl_link, _resolve(id), int(value)) - @netlink.nlattr('link.inet.forwarding', type=bool, fmt=util.boolean) @property + @netlink.nlattr(type=bool, fmt=util.boolean) def forwarding(self): return bool(self.get_conf(DEVCONF_FORWARDING)) @@ -82,8 +82,9 @@ class InetLink(object): def forwarding(self, value): self.set_conf(DEVCONF_FORWARDING, int(value)) - @netlink.nlattr('link.inet.mc_forwarding', type=bool, fmt=util.boolean) + @property + @netlink.nlattr(type=bool, fmt=util.boolean) def mc_forwarding(self): return bool(self.get_conf(DEVCONF_MC_FORWARDING)) @@ -91,8 +92,9 @@ class InetLink(object): def mc_forwarding(self, value): self.set_conf(DEVCONF_MC_FORWARDING, int(value)) - @netlink.nlattr('link.inet.proxy_arp', type=bool, fmt=util.boolean) + @property + @netlink.nlattr(type=bool, fmt=util.boolean) def proxy_arp(self): return bool(self.get_conf(DEVCONF_PROXY_ARP)) @@ -100,8 +102,8 @@ class InetLink(object): def proxy_arp(self, value): self.set_conf(DEVCONF_PROXY_ARP, int(value)) - @netlink.nlattr('link.inet.accept_redirects', type=bool, fmt=util.boolean) @property + @netlink.nlattr(type=bool, fmt=util.boolean) def accept_redirects(self): return bool(self.get_conf(DEVCONF_ACCEPT_REDIRECTS)) @@ -109,8 +111,8 @@ class InetLink(object): def accept_redirects(self, value): self.set_conf(DEVCONF_ACCEPT_REDIRECTS, int(value)) - @netlink.nlattr('link.inet.secure_redirects', type=bool, fmt=util.boolean) @property + @netlink.nlattr(type=bool, fmt=util.boolean) def secure_redirects(self): return bool(self.get_conf(DEVCONF_SECURE_REDIRECTS)) @@ -118,8 +120,8 @@ class InetLink(object): def secure_redirects(self, value): self.set_conf(DEVCONF_SECURE_REDIRECTS, int(value)) - @netlink.nlattr('link.inet.send_redirects', type=bool, fmt=util.boolean) @property + @netlink.nlattr(type=bool, fmt=util.boolean) def send_redirects(self): return bool(self.get_conf(DEVCONF_SEND_REDIRECTS)) @@ -127,8 +129,8 @@ class InetLink(object): def send_redirects(self, value): self.set_conf(DEVCONF_SEND_REDIRECTS, int(value)) - @netlink.nlattr('link.inet.shared_media', type=bool, fmt=util.boolean) @property + @netlink.nlattr(type=bool, fmt=util.boolean) def shared_media(self): return bool(self.get_conf(DEVCONF_SHARED_MEDIA)) diff --git a/python/netlink/route/links/vlan.py b/python/netlink/route/links/vlan.py index 646ce15..70045d5 100644 --- a/python/netlink/route/links/vlan.py +++ b/python/netlink/route/links/vlan.py @@ -15,8 +15,8 @@ class VLANLink(object): def __init__(self, link): self._link = link - @netlink.nlattr('link.vlan.id', type=int) @property + @netlink.nlattr(type=int) def id(self): """vlan identifier""" return capi.rtnl_link_vlan_get_id(self._link) @@ -25,8 +25,8 @@ class VLANLink(object): def id(self, value): capi.rtnl_link_vlan_set_id(self._link, int(value)) - @netlink.nlattr('link.vlan.flags', type=str) @property + @netlink.nlattr(type=str) def flags(self): """ VLAN flags Setting this property will *Not* reset flags to value you supply in diff --git a/python/netlink/route/qdisc/htb.py b/python/netlink/route/qdisc/htb.py index 2d3ea94..d051c8d 100644 --- a/python/netlink/route/qdisc/htb.py +++ b/python/netlink/route/qdisc/htb.py @@ -17,8 +17,8 @@ class HTBQdisc(object): def __init__(self, qdisc): self._qdisc = qdisc - @netlink.nlattr('qdisc.htb.default_class', type=int) @property + @netlink.nlattr(type=int) def default_class(self): return tc.Handle(capi.rtnl_htb_get_defcls(self._qdisc._rtnl_qdisc)) @@ -26,8 +26,8 @@ class HTBQdisc(object): def default_class(self, value): capi.rtnl_htb_set_defcls(self._qdisc._rtnl_qdisc, int(value)) - @netlink.nlattr('qdisc.htb.r2q', type=int) @property + @netlink.nlattr('r2q', type=int) def r2q(self): return capi.rtnl_htb_get_rate2quantum(self._qdisc._rtnl_qdisc) @@ -50,8 +50,8 @@ class HTBClass(object): def __init__(self, cl): self._class = cl - @netlink.nlattr('class.htb.rate', type=str) @property + @netlink.nlattr(type=str) def rate(self): rate = capi.rtnl_htb_get_rate(self._class._rtnl_class) return util.Rate(rate) @@ -60,8 +60,8 @@ class HTBClass(object): def rate(self, value): capi.rtnl_htb_set_rate(self._class._rtnl_class, int(value)) - @netlink.nlattr('class.htb.ceil', type=str) @property + @netlink.nlattr(type=str) def ceil(self): ceil = capi.rtnl_htb_get_ceil(self._class._rtnl_class) return util.Rate(ceil) @@ -70,8 +70,8 @@ class HTBClass(object): def ceil(self, value): capi.rtnl_htb_set_ceil(self._class._rtnl_class, int(value)) - @netlink.nlattr('class.htb.burst', type=str) @property + @netlink.nlattr(type=str) def burst(self): burst = capi.rtnl_htb_get_rbuffer(self._class._rtnl_class) return util.Size(burst) @@ -80,8 +80,8 @@ class HTBClass(object): def burst(self, value): capi.rtnl_htb_set_rbuffer(self._class._rtnl_class, int(value)) - @netlink.nlattr('class.htb.ceil_burst', type=str) @property + @netlink.nlattr(type=str) def ceil_burst(self): burst = capi.rtnl_htb_get_cbuffer(self._class._rtnl_class) return util.Size(burst) @@ -90,8 +90,8 @@ class HTBClass(object): def ceil_burst(self, value): capi.rtnl_htb_set_cbuffer(self._class._rtnl_class, int(value)) - @netlink.nlattr('class.htb.prio', type=int) @property + @netlink.nlattr(type=int) def prio(self): return capi.rtnl_htb_get_prio(self._class._rtnl_class) @@ -99,8 +99,8 @@ class HTBClass(object): def prio(self, value): capi.rtnl_htb_set_prio(self._class._rtnl_class, int(value)) - @netlink.nlattr('class.htb.quantum', type=int) @property + @netlink.nlattr(type=int) def quantum(self): return capi.rtnl_htb_get_quantum(self._class._rtnl_class) @@ -108,8 +108,8 @@ class HTBClass(object): def quantum(self, value): capi.rtnl_htb_set_quantum(self._class._rtnl_class, int(value)) - @netlink.nlattr('class.htb.level', type=int) @property + @netlink.nlattr(type=int) def level(self): return capi.rtnl_htb_get_level(self._class._rtnl_class) diff --git a/python/netlink/route/tc.py b/python/netlink/route/tc.py index 503f5a4..0689b71 100644 --- a/python/netlink/route/tc.py +++ b/python/netlink/route/tc.py @@ -157,6 +157,7 @@ class Tc(netlink.Object): capi.rtnl_tc_set_linktype(self._rtnl_tc, int(value)) @property + @netlink.nlattr(fmt=util.handle) def handle(self): return Handle(capi.rtnl_tc_get_handle(self._rtnl_tc)) @@ -165,6 +166,7 @@ class Tc(netlink.Object): capi.rtnl_tc_set_handle(self._rtnl_tc, int(value)) @property + @netlink.nlattr(fmt=util.handle) def parent(self): return Handle(capi.rtnl_tc_get_parent(self._rtnl_tc)) @@ -173,6 +175,7 @@ class Tc(netlink.Object): capi.rtnl_tc_set_parent(self._rtnl_tc, int(value)) @property + @netlink.nlattr(fmt=util.bold) def kind(self): return capi.rtnl_tc_get_kind(self._rtnl_tc) @@ -262,10 +265,6 @@ class Qdisc(Tc): self._rtnl_qdisc = self._obj2type(self._nl_object) self._rtnl_tc = capi.obj2tc(self._nl_object) - netlink.add_attr('qdisc.handle', fmt=util.handle) - netlink.add_attr('qdisc.parent', fmt=util.handle) - netlink.add_attr('qdisc.kind', fmt=util.bold) - if self.kind: self._tc_module_lookup() @@ -418,10 +417,6 @@ class TcClass(Tc): self._rtnl_class = self._obj2type(self._nl_object) self._rtnl_tc = capi.obj2tc(self._nl_object) - netlink.add_attr('class.handle', fmt=util.handle) - netlink.add_attr('class.parent', fmt=util.handle) - netlink.add_attr('class.kind', fmt=util.bold) - if self.kind: self._tc_module_lookup() @@ -492,10 +487,6 @@ class Classifier(Tc): self._rtnl_cls = self._obj2type(self._nl_object) self._rtnl_tc = capi.obj2tc(self._nl_object) - netlink.add_attr('cls.handle', fmt=util.handle) - netlink.add_attr('cls.parent', fmt=util.handle) - netlink.add_attr('cls.kind', fmt=util.bold) - @classmethod def from_capi(cls, obj): return cls(capi.cls2obj(obj)) diff --git a/python/netlink/util.py b/python/netlink/util.py index 0f2e547..2394033 100644 --- a/python/netlink/util.py +++ b/python/netlink/util.py @@ -80,24 +80,19 @@ class MyFormatter(Formatter): self._indent = indent def _nlattr(self, key): + value = getattr(self._obj.__class__, key) + if not isinstance(value, property): + raise ValueError('Invalid formatting string {0}'.format(key)) + + d = getattr(value.fget, 'formatinfo', dict()) + + # value = value.fget() is exactly the same value = getattr(self._obj, key) - title_ = None - if isinstance(value, types.MethodType): - value = value() + if 'fmt' in d: + value = d['fmt'](value) - try: - d = netlink.attrs[self._obj._name + '.' + key] - - if 'fmt' in d: - value = d['fmt'](value) - - if 'title' in d: - title_ = d['title'] - except KeyError: - pass - except AttributeError: - pass + title_ = d.get('title', None) return title_, str(value) From dca358c6a23e9734facc745dd097d4b539c8f438 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=BD=D0=BE=D1=83=D1=82=D0=B1?= =?UTF-8?q?=D1=83=D0=BA=20=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Fri, 8 Jun 2012 02:59:03 +0600 Subject: [PATCH 208/432] rtnl_link_(get|set)_weight is deprecated in libnl. So, remove from python binding. Should not break compatibility. --- python/netlink/route/capi.i | 3 --- python/netlink/route/link.py | 18 ------------------ 2 files changed, 21 deletions(-) diff --git a/python/netlink/route/capi.i b/python/netlink/route/capi.i index ae3592d..8ac114b 100644 --- a/python/netlink/route/capi.i +++ b/python/netlink/route/capi.i @@ -104,9 +104,6 @@ extern unsigned int rtnl_link_get_mtu(struct rtnl_link *); extern void rtnl_link_set_txqlen(struct rtnl_link *, unsigned int); extern unsigned int rtnl_link_get_txqlen(struct rtnl_link *); -extern void rtnl_link_set_weight(struct rtnl_link *, unsigned int); -extern unsigned int rtnl_link_get_weight(struct rtnl_link *); - extern void rtnl_link_set_ifindex(struct rtnl_link *, int); extern int rtnl_link_get_ifindex(struct rtnl_link *); diff --git a/python/netlink/route/link.py b/python/netlink/route/link.py index a537cd5..ab28f37 100644 --- a/python/netlink/route/link.py +++ b/python/netlink/route/link.py @@ -297,24 +297,6 @@ class Link(netlink.Object): def txqlen(self, value): capi.rtnl_link_set_txqlen(self._rtnl_link, int(value)) - @property - @netlink.nlattr(type=str, fmt=util.string) - def weight(self): - """Weight""" - v = capi.rtnl_link_get_weight(self._rtnl_link) - if v == 4294967295: - return 'max' - else: - return str(v) - - @weight.setter - def weight(self, value): - if value == 'max': - v = 4294967295 - else: - v = int(value) - capi.rtnl_link_set_weight(self._rtnl_link, v) - @property @netlink.nlattr(type=str, immutable=True, fmt=util.string) def arptype(self): From ffa461d37c97791f2c4f84682cfd241beb2448c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA?= Date: Fri, 8 Jun 2012 13:19:27 +0600 Subject: [PATCH 209/432] Fixed memory leak in Cache destructor destructor of Cache was missing due to typo --- python/netlink/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/netlink/core.py b/python/netlink/core.py index 05420ef..3298e2c 100644 --- a/python/netlink/core.py +++ b/python/netlink/core.py @@ -441,7 +441,7 @@ class Cache(object): self.arg1 = None self.arg2 = None - def __del(self): + def __del__(self): capi.nl_cache_free(self._nl_cache) def __len__(self): From 3c532654014ae8f7ea91288281e8879aee1ac786 Mon Sep 17 00:00:00 2001 From: Andrew Collins Date: Mon, 11 Jun 2012 10:44:42 -0600 Subject: [PATCH 210/432] Add 'ingress' to the list of recognized TC handles. Currently, rtnl_tc_handle2str understands the ingress handle but rtnl_tc_str2handle does not. This change lets rtnl_tc_str2handle recognize 'ingress' as a valid handle as well. --- lib/route/classid.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/route/classid.c b/lib/route/classid.c index 7b52de8..e1880af 100644 --- a/lib/route/classid.c +++ b/lib/route/classid.c @@ -166,6 +166,11 @@ int rtnl_tc_str2handle(const char *str, uint32_t *res) return 0; } + if (!strcasecmp(str, "ingress")) { + *res = TC_H_INGRESS; + return 0; + } + h = strtoul(str, &colon, 16); /* MAJ is not a number */ From 84037becfd0d50419a03c9a4816375e049b9336b Mon Sep 17 00:00:00 2001 From: Andrew Collins Date: Mon, 11 Jun 2012 10:44:43 -0600 Subject: [PATCH 211/432] Correct missing fwmark mask proto. In my previous patch for adding fwmark mask support, I neglected to add a prototype for it. This change corrects my oversight. --- include/netlink/route/cls/fw.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/netlink/route/cls/fw.h b/include/netlink/route/cls/fw.h index d1f1b75..2e1bade 100644 --- a/include/netlink/route/cls/fw.h +++ b/include/netlink/route/cls/fw.h @@ -22,6 +22,7 @@ extern "C" { #endif extern int rtnl_fw_set_classid(struct rtnl_cls *, uint32_t); +extern int rtnl_fw_set_mask(struct rtnl_cls *, uint32_t); #ifdef __cplusplus } From 69da6af3e4c423a4bdf26854a58188fc47126b13 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 13 Jun 2012 13:04:03 +0200 Subject: [PATCH 212/432] genl: Wait for ACK after successful ctrl reply Signed-off-by: Thomas Graf --- lib/genl/ctrl.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/genl/ctrl.c b/lib/genl/ctrl.c index 3902f09..e11c5c6 100644 --- a/lib/genl/ctrl.c +++ b/lib/genl/ctrl.c @@ -267,7 +267,14 @@ static struct genl_family *genl_ctrl_probe_by_name(struct nl_sock *sk, const cha nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, probe_response, (void *)ret); - nl_recvmsgs(sk, cb); + rc = nl_recvmsgs(sk, cb); + if (rc < 0) + goto out_cb_free; + + /* If search was successful, request may be ACKed after data */ + rc = wait_for_ack(sk); + if (rc < 0) + goto out_cb_free; if (genl_family_get_id(ret) != 0) { nlmsg_free(msg); From 49fe936b8e03ad3398820180310f5161b04c863a Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 13 Jun 2012 13:23:04 +0200 Subject: [PATCH 213/432] genl: cleanup genl_ctrl_resolve() Signed-off-by: Thomas Graf --- lib/genl/ctrl.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/lib/genl/ctrl.c b/lib/genl/ctrl.c index e11c5c6..5950394 100644 --- a/lib/genl/ctrl.c +++ b/lib/genl/ctrl.c @@ -234,10 +234,11 @@ static int probe_response(struct nl_msg *msg, void *arg) * * @return Generic netlink family object or NULL if no match was found. */ -static struct genl_family *genl_ctrl_probe_by_name(struct nl_sock *sk, const char *name) +static struct genl_family *genl_ctrl_probe_by_name(struct nl_sock *sk, + const char *name) { struct nl_msg *msg; - struct genl_family *ret = NULL; + struct genl_family *ret; struct nl_cb *cb; int rc; @@ -254,19 +255,24 @@ static struct genl_family *genl_ctrl_probe_by_name(struct nl_sock *sk, const cha if (!(cb = nl_cb_clone(nl_socket_get_cb(sk)))) goto out_msg_free; + if (genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, GENL_ID_CTRL, + 0, 0, CTRL_CMD_GETFAMILY, 1) < 0) { + BUG(); + goto out_cb_free; + } - genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, GENL_ID_CTRL, - 0, 0, CTRL_CMD_GETFAMILY, 1); + if (nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, name) < 0) + goto out_cb_free; - if (nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, name)) + rc = nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, probe_response, + (void *) ret); + if (rc < 0) goto out_cb_free; rc = nl_send_auto_complete(sk, msg); if (rc < 0) goto out_cb_free; - nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, probe_response, (void *)ret); - rc = nl_recvmsgs(sk, cb); if (rc < 0) goto out_cb_free; From 4f933648622fff2b7fd6ec6c71724da4992c2544 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 13 Jun 2012 13:24:19 +0200 Subject: [PATCH 214/432] link: rtnl_link_get_kernel() should only wait for ACK if AUTO-ACK is on Signed-off-by: Thomas Graf --- lib/route/link.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/route/link.c b/lib/route/link.c index 0a17110..aea43b9 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -1025,7 +1025,7 @@ int rtnl_link_get_kernel(struct nl_sock *sk, int ifindex, const char *name, /* If an object has been returned, we also need to wait for the ACK */ if (err == 0 && obj) - nl_wait_for_ack(sk); + wait_for_ack(sk); return 0; } From 2bdcde7e8e8bb78b165f093f1a708134f417e557 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA?= Date: Fri, 8 Jun 2012 20:15:06 +0600 Subject: [PATCH 215/432] Fix types-related warnings based on clang diagnostics 1. Fix some places where unsigned value compared < 0 2. Fix obsolete %Z specifier to more portable %z 3. Some erroneous types substitution 4. nl_msec2str() - 64-bit msec is now properly used, Only safe changes. I mean int <--> uint32_t and signed/unsigned fixes. Some functinos require size_t argument instead of int, but changes of signatures of that functions is terrible thing. Also, I do not pretend for a full list of fixes. Just to shut up clang -Wall -Wextra One more thing. ifindex. I don't change that because changes will be too big for simple fix. --- lib/addr.c | 6 +++--- lib/attr.c | 3 ++- lib/data.c | 3 --- lib/genl/genl.c | 4 ++-- lib/msg.c | 8 ++++---- lib/nl.c | 2 +- lib/object.c | 4 ++-- lib/route/addr.c | 4 ++-- lib/route/class.c | 4 ++-- lib/route/classid.c | 3 ++- lib/route/cls.c | 4 ++-- lib/route/cls/u32.c | 2 +- lib/route/link/vlan.c | 7 ++++--- lib/route/qdisc.c | 2 +- lib/route/qdisc/netem.c | 3 ++- lib/route/route_obj.c | 2 +- lib/utils.c | 39 +++++++++++++++++++++------------------ src/lib/route.c | 14 +++++++++++--- 18 files changed, 63 insertions(+), 51 deletions(-) diff --git a/lib/addr.c b/lib/addr.c index 89d3d4f..3acd9e4 100644 --- a/lib/addr.c +++ b/lib/addr.c @@ -368,7 +368,7 @@ int nl_addr_parse(const char *addrstr, int hint, struct nl_addr **result) } if (hint == AF_UNSPEC && strchr(str, ':')) { - int i = 0; + size_t i = 0; char *s = str, *p; for (;;) { long l = strtol(s, &p, 16); @@ -542,7 +542,7 @@ int nl_addr_cmp_prefix(struct nl_addr *a, struct nl_addr *b) */ int nl_addr_iszero(struct nl_addr *addr) { - int i; + unsigned int i; for (i = 0; i < addr->a_len; i++) if (addr->a_addr[i]) @@ -823,7 +823,7 @@ unsigned int nl_addr_get_prefixlen(struct nl_addr *addr) */ char *nl_addr2str(struct nl_addr *addr, char *buf, size_t size) { - int i; + unsigned int i; char tmp[16]; if (!addr || !addr->a_len) { diff --git a/lib/attr.c b/lib/attr.c index 6ef6cd9..a095649 100644 --- a/lib/attr.c +++ b/lib/attr.c @@ -188,7 +188,8 @@ static int validate_nla(struct nlattr *nla, int maxtype, struct nla_policy *policy) { struct nla_policy *pt; - int minlen = 0, type = nla_type(nla); + unsigned int minlen = 0; + int type = nla_type(nla); if (type <= 0 || type > maxtype) return 0; diff --git a/lib/data.c b/lib/data.c index e4196b1..f019539 100644 --- a/lib/data.c +++ b/lib/data.c @@ -110,9 +110,6 @@ struct nl_data *nl_data_clone(struct nl_data *src) */ int nl_data_append(struct nl_data *data, void *buf, size_t size) { - if (size < 0) - BUG(); - if (size > 0) { data->d_data = realloc(data->d_data, data->d_size + size); if (!data->d_data) diff --git a/lib/genl/genl.c b/lib/genl/genl.c index 569ef9e..8d3def3 100644 --- a/lib/genl/genl.c +++ b/lib/genl/genl.c @@ -223,9 +223,9 @@ struct genlmsghdr *genlmsg_hdr(struct nlmsghdr *nlh) */ int genlmsg_len(const struct genlmsghdr *gnlh) { - struct nlmsghdr *nlh; + const struct nlmsghdr *nlh; - nlh = (struct nlmsghdr *)((unsigned char *) gnlh - NLMSG_HDRLEN); + nlh = (const struct nlmsghdr *)((const unsigned char *) gnlh - NLMSG_HDRLEN); return (nlh->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN); } diff --git a/lib/msg.c b/lib/msg.c index 18174b5..0adc091 100644 --- a/lib/msg.c +++ b/lib/msg.c @@ -178,7 +178,7 @@ int nlmsg_valid_hdr(const struct nlmsghdr *nlh, int hdrlen) */ int nlmsg_ok(const struct nlmsghdr *nlh, int remaining) { - return (remaining >= (int)sizeof(struct nlmsghdr) && + return (remaining >= sizeof(struct nlmsghdr) && nlh->nlmsg_len >= sizeof(struct nlmsghdr) && nlh->nlmsg_len <= remaining); } @@ -867,7 +867,7 @@ void nl_msg_dump(struct nl_msg *msg, FILE *ofd) "-------------------------- BEGIN NETLINK MESSAGE " "---------------------------\n"); - fprintf(ofd, " [HEADER] %Zu octets\n", sizeof(struct nlmsghdr)); + fprintf(ofd, " [HEADER] %zu octets\n", sizeof(struct nlmsghdr)); print_hdr(ofd, msg); if (hdr->nlmsg_type == NLMSG_ERROR && @@ -875,10 +875,10 @@ void nl_msg_dump(struct nl_msg *msg, FILE *ofd) struct nl_msg *errmsg; struct nlmsgerr *err = nlmsg_data(hdr); - fprintf(ofd, " [ERRORMSG] %Zu octets\n", sizeof(*err)); + fprintf(ofd, " [ERRORMSG] %zu octets\n", sizeof(*err)); fprintf(ofd, " .error = %d \"%s\"\n", err->error, strerror(-err->error)); - fprintf(ofd, " [ORIGINAL MESSAGE] %Zu octets\n", sizeof(*hdr)); + fprintf(ofd, " [ORIGINAL MESSAGE] %zu octets\n", sizeof(*hdr)); errmsg = nlmsg_inherit(&err->msg); print_hdr(ofd, errmsg); diff --git a/lib/nl.c b/lib/nl.c index b572a1a..6b2f027 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -417,7 +417,7 @@ errout: int nl_recv(struct nl_sock *sk, struct sockaddr_nl *nla, unsigned char **buf, struct ucred **creds) { - int n; + ssize_t n; int flags = 0; static int page_size = 0; struct iovec iov; diff --git a/lib/object.c b/lib/object.c index df1c963..055a208 100644 --- a/lib/object.c +++ b/lib/object.c @@ -285,14 +285,14 @@ void nl_object_dump_buf(struct nl_object *obj, char *buf, size_t len) int nl_object_identical(struct nl_object *a, struct nl_object *b) { struct nl_object_ops *ops = obj_ops(a); - int req_attrs; + uint32_t req_attrs; /* Both objects must be of same type */ if (ops != obj_ops(b)) return 0; req_attrs = ops->oo_id_attrs; - if (req_attrs == ~0) + if (req_attrs == 0xFFFFFFFF) req_attrs = a->ce_mask & b->ce_mask; /* Both objects must provide all required attributes to uniquely diff --git a/lib/route/addr.c b/lib/route/addr.c index deb88ba..600857b 100644 --- a/lib/route/addr.c +++ b/lib/route/addr.c @@ -625,7 +625,7 @@ nla_put_failure: int rtnl_addr_build_add_request(struct rtnl_addr *addr, int flags, struct nl_msg **result) { - int required = ADDR_ATTR_IFINDEX | ADDR_ATTR_FAMILY | + uint32_t required = ADDR_ATTR_IFINDEX | ADDR_ATTR_FAMILY | ADDR_ATTR_PREFIXLEN | ADDR_ATTR_LOCAL; if ((addr->ce_mask & required) != required) @@ -698,7 +698,7 @@ int rtnl_addr_add(struct nl_sock *sk, struct rtnl_addr *addr, int flags) int rtnl_addr_build_delete_request(struct rtnl_addr *addr, int flags, struct nl_msg **result) { - int required = ADDR_ATTR_IFINDEX | ADDR_ATTR_FAMILY; + uint32_t required = ADDR_ATTR_IFINDEX | ADDR_ATTR_FAMILY; if ((addr->ce_mask & required) != required) return -NLE_MISSING_ATTR; diff --git a/lib/route/class.c b/lib/route/class.c index 2a9606b..399e8a2 100644 --- a/lib/route/class.c +++ b/lib/route/class.c @@ -100,7 +100,7 @@ void rtnl_class_put(struct rtnl_class *class) static int class_build(struct rtnl_class *class, int type, int flags, struct nl_msg **result) { - int needed = TCA_ATTR_PARENT | TCA_ATTR_HANDLE; + uint32_t needed = TCA_ATTR_PARENT | TCA_ATTR_HANDLE; if ((class->ce_mask & needed) == needed && TC_H_MAJ(class->c_parent) && TC_H_MAJ(class->c_handle) && @@ -196,7 +196,7 @@ int rtnl_class_build_delete_request(struct rtnl_class *class, struct nl_msg **re { struct nl_msg *msg; struct tcmsg tchdr; - int required = TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE; + uint32_t required = TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE; if ((class->ce_mask & required) != required) { APPBUG("ifindex and handle must be specified"); diff --git a/lib/route/classid.c b/lib/route/classid.c index e1880af..a128773 100644 --- a/lib/route/classid.c +++ b/lib/route/classid.c @@ -154,7 +154,8 @@ char *rtnl_tc_handle2str(uint32_t handle, char *buf, size_t len) int rtnl_tc_str2handle(const char *str, uint32_t *res) { char *colon, *end; - uint32_t h, err; + uint32_t h; + int err; if (!strcasecmp(str, "root")) { *res = TC_H_ROOT; diff --git a/lib/route/cls.c b/lib/route/cls.c index fb2e9be..35a010a 100644 --- a/lib/route/cls.c +++ b/lib/route/cls.c @@ -37,7 +37,7 @@ static int cls_build(struct rtnl_cls *cls, int type, int flags, { int err, prio, proto; struct tcmsg *tchdr; - int required = TCA_ATTR_IFINDEX; + uint32_t required = TCA_ATTR_IFINDEX; if ((cls->ce_mask & required) != required) { APPBUG("ifindex must be specified"); @@ -251,7 +251,7 @@ int rtnl_cls_change(struct nl_sock *sk, struct rtnl_cls *cls, int flags) int rtnl_cls_build_delete_request(struct rtnl_cls *cls, int flags, struct nl_msg **result) { - int required = CLS_ATTR_PRIO; + uint32_t required = CLS_ATTR_PRIO; if ((cls->ce_mask & required) != required) { APPBUG("prio must be specified"); diff --git a/lib/route/cls/u32.c b/lib/route/cls/u32.c index 331e714..d3e326d 100644 --- a/lib/route/cls/u32.c +++ b/lib/route/cls/u32.c @@ -116,7 +116,7 @@ static int u32_msg_parser(struct rtnl_tc *tc, void *data) if (tb[TCA_U32_PCNT]) { struct tc_u32_sel *sel; - int pcnt_size; + size_t pcnt_size; if (!tb[TCA_U32_SEL]) { err = -NLE_MISSING_ATTR; diff --git a/lib/route/link/vlan.c b/lib/route/link/vlan.c index a30ff77..a9bf955 100644 --- a/lib/route/link/vlan.c +++ b/lib/route/link/vlan.c @@ -114,7 +114,7 @@ static int vlan_parse(struct rtnl_link *link, struct nlattr *data, return -NLE_INVAL; map = nla_data(nla); - if (map->from < 0 || map->from > VLAN_PRIO_MAX) { + if (map->from > VLAN_PRIO_MAX) { return -NLE_INVAL; } @@ -181,7 +181,8 @@ static void vlan_dump_line(struct rtnl_link *link, struct nl_dump_params *p) static void vlan_dump_details(struct rtnl_link *link, struct nl_dump_params *p) { struct vlan_info *vi = link->l_info; - int i, printed; + int printed; + uint32_t i; char buf[64]; rtnl_link_vlan_flags2str(vi->vi_flags, buf, sizeof(buf)); @@ -291,7 +292,7 @@ static int vlan_put_attrs(struct nl_msg *msg, struct rtnl_link *link) if (vi->vi_mask & VLAN_HAS_EGRESS_QOS) { struct ifla_vlan_qos_mapping map; struct nlattr *qos; - int i; + uint32_t i; if (!(qos = nla_nest_start(msg, IFLA_VLAN_EGRESS_QOS))) goto nla_put_failure; diff --git a/lib/route/qdisc.c b/lib/route/qdisc.c index e5a8aa0..3d618c6 100644 --- a/lib/route/qdisc.c +++ b/lib/route/qdisc.c @@ -275,7 +275,7 @@ int rtnl_qdisc_build_delete_request(struct rtnl_qdisc *qdisc, { struct nl_msg *msg; struct tcmsg tchdr; - int required = TCA_ATTR_IFINDEX | TCA_ATTR_PARENT; + uint32_t required = TCA_ATTR_IFINDEX | TCA_ATTR_PARENT; if ((qdisc->ce_mask & required) != required) { APPBUG("ifindex and parent must be specified"); diff --git a/lib/route/qdisc/netem.c b/lib/route/qdisc/netem.c index 3e5ba52..ddd404d 100644 --- a/lib/route/qdisc/netem.c +++ b/lib/route/qdisc/netem.c @@ -827,7 +827,8 @@ int rtnl_netem_set_delay_distribution(struct rtnl_qdisc *qdisc, const char *dist BUG(); FILE *f; - int i, n = 0; + int n = 0; + size_t i; size_t len = 2048; char *line; char name[NAME_MAX]; diff --git a/lib/route/route_obj.c b/lib/route/route_obj.c index ac634ae..685a926 100644 --- a/lib/route/route_obj.c +++ b/lib/route/route_obj.c @@ -724,7 +724,7 @@ void rtnl_route_foreach_nexthop(struct rtnl_route *r, struct rtnl_nexthop *rtnl_route_nexthop_n(struct rtnl_route *r, int n) { struct rtnl_nexthop *nh; - int i; + uint32_t i; if (r->ce_mask & ROUTE_ATTR_MULTIPATH && r->rt_nr_nh > n) { i = 0; diff --git a/lib/utils.c b/lib/utils.c index efb2cf4..467fd7f 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -305,7 +305,7 @@ static const struct { */ char *nl_size2str(const size_t size, char *buf, const size_t len) { - int i; + size_t i; for (i = 0; i < ARRAY_SIZE(size_units); i++) { if (size >= size_units[i].limit) { @@ -515,10 +515,12 @@ int nl_str2msec(const char *str, uint64_t *result) */ char * nl_msec2str(uint64_t msec, char *buf, size_t len) { - int i, split[5]; - char *units[] = {"d", "h", "m", "s", "msec"}; + uint64_t split[5]; + size_t i; + static const char *units[5] = {"d", "h", "m", "s", "msec"}; + char * const buf_orig = buf; -#define _SPLIT(idx, unit) if ((split[idx] = msec / unit) > 0) msec %= unit +#define _SPLIT(idx, unit) if ((split[idx] = msec / unit)) msec %= unit _SPLIT(0, 86400000); /* days */ _SPLIT(1, 3600000); /* hours */ _SPLIT(2, 60000); /* minutes */ @@ -526,18 +528,17 @@ char * nl_msec2str(uint64_t msec, char *buf, size_t len) #undef _SPLIT split[4] = msec; - memset(buf, 0, len); - - for (i = 0; i < ARRAY_SIZE(split); i++) { - if (split[i] > 0) { - char t[64]; - snprintf(t, sizeof(t), "%s%d%s", - strlen(buf) ? " " : "", split[i], units[i]); - strncat(buf, t, len - strlen(buf) - 1); - } + for (i = 0; i < ARRAY_SIZE(split) && len; i++) { + int l; + if (split[i] == 0) + continue; + l = snprintf(buf, len, "%s%" PRIu64 "%s", + (buf==buf_orig) ? "" : " ", split[i], units[i]); + buf += l; + len -= l; } - return buf; + return buf_orig; } /** @} */ @@ -929,7 +930,7 @@ void __trans_list_clear(struct nl_list_head *head) char *__type2str(int type, char *buf, size_t len, const struct trans_tbl *tbl, size_t tbl_len) { - int i; + size_t i; for (i = 0; i < tbl_len; i++) { if (tbl[i].i == type) { snprintf(buf, len, "%s", tbl[i].a); @@ -960,7 +961,7 @@ char *__list_type2str(int type, char *buf, size_t len, char *__flags2str(int flags, char *buf, size_t len, const struct trans_tbl *tbl, size_t tbl_len) { - int i; + size_t i; int tmp = flags; memset(buf, 0, len); @@ -981,7 +982,7 @@ int __str2type(const char *buf, const struct trans_tbl *tbl, size_t tbl_len) { unsigned long l; char *end; - int i; + size_t i; if (*buf == '\0') return -NLE_INVAL; @@ -1020,7 +1021,9 @@ int __list_str2type(const char *buf, struct nl_list_head *head) int __str2flags(const char *buf, const struct trans_tbl *tbl, size_t tbl_len) { - int i, flags = 0, len; + int flags = 0; + size_t i; + size_t len; /* ptrdiff_t ? */ char *p = (char *) buf, *t; for (;;) { diff --git a/src/lib/route.c b/src/lib/route.c index 05cb2ad..f2d6c60 100644 --- a/src/lib/route.c +++ b/src/lib/route.c @@ -198,12 +198,16 @@ void nl_cli_route_parse_table(struct rtnl_route *route, char *arg) { unsigned long lval; char *endptr; + int table; lval = strtoul(arg, &endptr, 0); if (endptr == arg) { - if ((lval = rtnl_route_str2table(arg)) < 0) + if ((table = rtnl_route_str2table(arg)) < 0) nl_cli_fatal(EINVAL, "Unknown table name \"%s\"", arg); } + else { + table = lval; + } rtnl_route_set_table(route, lval); } @@ -233,16 +237,20 @@ void nl_cli_route_parse_protocol(struct rtnl_route *route, char *arg) { unsigned long lval; char *endptr; + int proto; lval = strtoul(arg, &endptr, 0); if (endptr == arg) { - if ((lval = rtnl_route_str2proto(arg)) < 0) + if ((proto = rtnl_route_str2proto(arg)) < 0) nl_cli_fatal(EINVAL, "Unknown routing protocol name \"%s\"", arg); } + else { + proto = lval; + } - rtnl_route_set_protocol(route, lval); + rtnl_route_set_protocol(route, proto); } void nl_cli_route_parse_type(struct rtnl_route *route, char *arg) From 941ba950a9fa914e324c7e204c145bf7af526bf4 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 13 Jun 2012 13:49:52 +0200 Subject: [PATCH 216/432] libnl 3.2.11 --- configure.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.in b/configure.in index ef65678..ad6fad3 100644 --- a/configure.in +++ b/configure.in @@ -13,7 +13,7 @@ # copied from glib m4_define([libnl_major_version], [3]) m4_define([libnl_minor_version], [2]) -m4_define([libnl_micro_version], [10]) +m4_define([libnl_micro_version], [11]) # If either revision or age are omitted, they default to 0. Also note that age @@ -34,9 +34,9 @@ m4_define([libnl_micro_version], [10]) # 6. If any interfaces have been removed since the last public release, then # set age to 0. -m4_define([libnl_lt_current], [208]) +m4_define([libnl_lt_current], [209]) m4_define([libnl_lt_revision], [0]) -m4_define([libnl_lt_age], [8]) +m4_define([libnl_lt_age], [9]) m4_define([libnl_version], [libnl_major_version.libnl_minor_version.libnl_micro_version]) From 9426d03e3ae4510e3febf73fad520be37de05d7f Mon Sep 17 00:00:00 2001 From: Stephane Fillod Date: Wed, 1 Aug 2012 22:29:47 +0200 Subject: [PATCH 217/432] tbf: fix false missing attr Fix false missing attribute in tbf_msg_fill() when applying a tbf qdisc. --- lib/route/qdisc/tbf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/route/qdisc/tbf.c b/lib/route/qdisc/tbf.c index 81bd84c..a115548 100644 --- a/lib/route/qdisc/tbf.c +++ b/lib/route/qdisc/tbf.c @@ -135,7 +135,7 @@ static int tbf_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) struct rtnl_tbf *tbf = data; int required = TBF_ATTR_RATE | TBF_ATTR_LIMIT; - if (!(tbf->qt_mask & required) != required) + if ((tbf->qt_mask & required) != required) return -NLE_MISSING_ATTR; memset(&opts, 0, sizeof(opts)); From 052a13119353f97e70216808b02bc692bcb18378 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Mon, 27 Aug 2012 23:14:07 +0600 Subject: [PATCH 218/432] nl_cli_route_parse_table fixed typo in code Bug introduced in 2bdcde7e8e8bb78b165f093f1a708134f417e557 --- src/lib/route.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/route.c b/src/lib/route.c index f2d6c60..cd3e897 100644 --- a/src/lib/route.c +++ b/src/lib/route.c @@ -209,7 +209,7 @@ void nl_cli_route_parse_table(struct rtnl_route *route, char *arg) table = lval; } - rtnl_route_set_table(route, lval); + rtnl_route_set_table(route, table); } void nl_cli_route_parse_prio(struct rtnl_route *route, char *arg) From a0f1c0e281ee78ab8ee874bbb6c2140c12101284 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Mon, 27 Aug 2012 23:39:29 +0600 Subject: [PATCH 219/432] ct_dump_stats: detect when stats are not available Since about 2.6.27 kernel, stats are not enabled by default. Stats can be enabled using sysctl named net.netfilter.nf_conntrack_acct So, do not print zeroes in stats if it's not available. When not checked, trash may appear in output --- lib/netfilter/ct_obj.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/lib/netfilter/ct_obj.c b/lib/netfilter/ct_obj.c index c205427..70a814f 100644 --- a/lib/netfilter/ct_obj.c +++ b/lib/netfilter/ct_obj.c @@ -256,18 +256,29 @@ static void ct_dump_stats(struct nl_object *a, struct nl_dump_params *p) struct nfnl_ct *ct = (struct nfnl_ct *) a; double res; char *unit; + uint64_t packets; + const char * const names[] = {"rx", "tx"}; + int i; ct_dump_details(a, p); + if (!nfnl_ct_test_bytes(ct, 0) || + !nfnl_ct_test_packets(ct, 0) || + !nfnl_ct_test_bytes(ct, 1) || + !nfnl_ct_test_packets(ct, 1)) + { + nl_dump_line(p, " Statics are not available.\n"); + nl_dump_line(p, " Please set sysctl net.netfilter.nf_conntrack_acct = 1\n"); + nl_dump_line(p, " (Require kernel 2.6.27)\n"); + return; + } + nl_dump_line(p, " # packets volume\n"); - - res = nl_cancel_down_bytes(nfnl_ct_get_bytes(ct, 1), &unit); - nl_dump_line(p, " rx %10llu %7.2f %s\n", - nfnl_ct_get_packets(ct, 1), res, unit); - - res = nl_cancel_down_bytes(nfnl_ct_get_bytes(ct, 0), &unit); - nl_dump_line(p, " tx %10llu %7.2f %s\n", - nfnl_ct_get_packets(ct, 0), res, unit); + for (i=0; i<=1; i++) { + res = nl_cancel_down_bytes(nfnl_ct_get_bytes(ct, i), &unit); + packets = nfnl_ct_get_packets(ct, i); + nl_dump_line(p, " %s %10llu %7.2f %s\n", names[i], packets, res, unit); + } } static int ct_compare(struct nl_object *_a, struct nl_object *_b, From 25d640da4a132f36ba28791e96b856cdcb899528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA?= Date: Tue, 28 Aug 2012 18:39:14 +0600 Subject: [PATCH 220/432] lib/utils.c: One kilobit now is a 1000bits (instead of 1024) http://en.wikipedia.org/wiki/Kilobit Also, convert "char*" to "const char*" in output value, as returned values can not be modified. --- include/netlink/utils.h | 4 ++-- lib/utils.c | 52 ++++++++++++++++++++++++----------------- 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/include/netlink/utils.h b/include/netlink/utils.h index 502341a..397f9b5 100644 --- a/include/netlink/utils.h +++ b/include/netlink/utils.h @@ -44,8 +44,8 @@ enum { }; /* unit pretty-printing */ -extern double nl_cancel_down_bytes(unsigned long long, char **); -extern double nl_cancel_down_bits(unsigned long long, char **); +extern double nl_cancel_down_bytes(unsigned long long, const char **); +extern double nl_cancel_down_bits(unsigned long long, const char **); extern int nl_rate2str(unsigned long long, int, char *, size_t); extern double nl_cancel_down_us(uint32_t, char **); diff --git a/lib/utils.c b/lib/utils.c index 467fd7f..0f6ff14 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -121,10 +121,11 @@ int __nl_read_num_str_file(const char *path, int (*cb)(long, const char *)) * * Cancels down a byte counter until it reaches a reasonable * unit. The chosen unit is assigned to \a unit. + * This function assume 1024 bytes in one kilobyte * * @return The cancelled down byte counter in the new unit. */ -double nl_cancel_down_bytes(unsigned long long l, char **unit) +double nl_cancel_down_bytes(unsigned long long l, const char **unit) { if (l >= 1099511627776LL) { *unit = "TiB"; @@ -149,30 +150,36 @@ double nl_cancel_down_bytes(unsigned long long l, char **unit) * @arg l bit counter * @arg unit destination unit pointer * - * Cancels downa bit counter until it reaches a reasonable + * Cancels down bit counter until it reaches a reasonable * unit. The chosen unit is assigned to \a unit. + * This function assume 1000 bits in one kilobit * * @return The cancelled down bit counter in the new unit. */ -double nl_cancel_down_bits(unsigned long long l, char **unit) +double nl_cancel_down_bits(unsigned long long l, const char **unit) { - if (l >= 1099511627776ULL) { + if (l >= 1000000000000ULL) { *unit = "Tbit"; - return ((double) l) / 1099511627776ULL; - } else if (l >= 1073741824) { - *unit = "Gbit"; - return ((double) l) / 1073741824; - } else if (l >= 1048576) { - *unit = "Mbit"; - return ((double) l) / 1048576; - } else if (l >= 1024) { - *unit = "Kbit"; - return ((double) l) / 1024; - } else { - *unit = "bit"; - return (double) l; + return ((double) l) / 1000000000000ULL; } - + + if (l >= 1000000000) { + *unit = "Gbit"; + return ((double) l) / 1000000000; + } + + if (l >= 1000000) { + *unit = "Mbit"; + return ((double) l) / 1000000; + } + + if (l >= 1000) { + *unit = "Kbit"; + return ((double) l) / 1000; + } + + *unit = "bit"; + return (double) l; } int nl_rate2str(unsigned long long rate, int type, char *buf, size_t len) @@ -238,6 +245,9 @@ double nl_cancel_down_us(uint32_t l, char **unit) * - b,kb/k,m/mb,gb/g for bytes * - bit,kbit/mbit/gbit * + * This function assume 1000 bits in one kilobit and + * 1024 bytes in one kilobyte + * * @return The number of bytes or -1 if the string is unparseable */ long nl_size2int(const char *str) @@ -253,13 +263,13 @@ long nl_size2int(const char *str) else if (!strcasecmp(p, "gb") || !strcasecmp(p, "g")) l *= 1024*1024*1024; else if (!strcasecmp(p, "gbit")) - l *= 1024*1024*1024/8; + l *= 1000000000L/8; else if (!strcasecmp(p, "mb") || !strcasecmp(p, "m")) l *= 1024*1024; else if (!strcasecmp(p, "mbit")) - l *= 1024*1024/8; + l *= 1000000/8; else if (!strcasecmp(p, "kbit")) - l *= 1024/8; + l *= 1000/8; else if (!strcasecmp(p, "bit")) l /= 8; else if (strcasecmp(p, "b") != 0) From 8222519f85921595b4f36e4dde927fcc677a4afb Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 28 Aug 2012 20:28:28 +0200 Subject: [PATCH 221/432] Fix the always false if (a->rt_nr_nh != a->rt_nr_nh) test Fix the always false if (a->rt_nr_nh != a->rt_nr_nh) test and compare properly the a and b structs --- lib/route/route_obj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/route/route_obj.c b/lib/route/route_obj.c index 685a926..40a157e 100644 --- a/lib/route/route_obj.c +++ b/lib/route/route_obj.c @@ -335,7 +335,7 @@ static int route_compare(struct nl_object *_a, struct nl_object *_b, diff |= ROUTE_DIFF(FLAGS, (a->rt_flags ^ b->rt_flags) & b->rt_flag_mask); } else { - if (a->rt_nr_nh != a->rt_nr_nh) + if (a->rt_nr_nh != b->rt_nr_nh) goto nh_mismatch; /* search for a dup in each nh of a */ From 376a0e29c720add10064b9caa51d8b854b936c48 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 29 Aug 2012 12:05:51 +0200 Subject: [PATCH 222/432] Fix build warning after const char ** convert Commit 25d640da4a caused the following build warning: ../include/netlink/utils.h:47:15: note: expected 'const char **' but argument is of type 'char **' route/link/inet6.c:300:11: warning: passing argument 2 of 'nl_cancel_down_bytes' from incompatible pointer type [enabled by default] Revert the const char ** change. Signed-off-by: Thomas Graf --- include/netlink/utils.h | 4 ++-- lib/utils.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/netlink/utils.h b/include/netlink/utils.h index 397f9b5..502341a 100644 --- a/include/netlink/utils.h +++ b/include/netlink/utils.h @@ -44,8 +44,8 @@ enum { }; /* unit pretty-printing */ -extern double nl_cancel_down_bytes(unsigned long long, const char **); -extern double nl_cancel_down_bits(unsigned long long, const char **); +extern double nl_cancel_down_bytes(unsigned long long, char **); +extern double nl_cancel_down_bits(unsigned long long, char **); extern int nl_rate2str(unsigned long long, int, char *, size_t); extern double nl_cancel_down_us(uint32_t, char **); diff --git a/lib/utils.c b/lib/utils.c index 0f6ff14..74f5639 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -125,7 +125,7 @@ int __nl_read_num_str_file(const char *path, int (*cb)(long, const char *)) * * @return The cancelled down byte counter in the new unit. */ -double nl_cancel_down_bytes(unsigned long long l, const char **unit) +double nl_cancel_down_bytes(unsigned long long l, char **unit) { if (l >= 1099511627776LL) { *unit = "TiB"; @@ -156,7 +156,7 @@ double nl_cancel_down_bytes(unsigned long long l, const char **unit) * * @return The cancelled down bit counter in the new unit. */ -double nl_cancel_down_bits(unsigned long long l, const char **unit) +double nl_cancel_down_bits(unsigned long long l, char **unit) { if (l >= 1000000000000ULL) { *unit = "Tbit"; From 97d2460fabaabffce0d224bdd24c0bdfee57dbf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Touraine?= Date: Wed, 29 Aug 2012 12:14:01 +0200 Subject: [PATCH 223/432] route_clone : fix segmentation fault using nl_cache_subset to filter routes reset the nb nhops to 0 (dst->rt_nr_nh = 0) before setting the dst->nhops from the src->nhops --- lib/route/route_obj.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/route/route_obj.c b/lib/route/route_obj.c index 40a157e..62669a9 100644 --- a/lib/route/route_obj.c +++ b/lib/route/route_obj.c @@ -110,6 +110,9 @@ static int route_clone(struct nl_object *_dst, struct nl_object *_src) if (!(dst->rt_pref_src = nl_addr_clone(src->rt_pref_src))) return -NLE_NOMEM; + /* Will be inc'ed again while adding the nexthops of the source */ + dst->rt_nr_nh = 0; + nl_init_list_head(&dst->rt_nexthops); nl_list_for_each_entry(nh, &src->rt_nexthops, rtnh_list) { new = rtnl_route_nh_clone(nh); From de28daf2269a5c7d55e6f1f50f1c1eff4db27a15 Mon Sep 17 00:00:00 2001 From: Justin Mayfield Date: Fri, 17 Aug 2012 18:16:44 -0600 Subject: [PATCH 224/432] nl_addr_parse handling of 'default', 'any', and 'all' I found a small bug in the nl_addr_parse function when being passed the strings "default", "any", or "all". Currently nl_addr_parse will create a zeroed nl_addr with a length corresponding to the family/hint or AF_INET if omitted. This behavior when used in conjunction with the libnl-route library to add default routes to the system has the side effect of creating a route to the host address 0.0.0.0/32. Attached is a patch that matches the iproute2 behavior more closely where we do set the family but the length of the nl_addr is set to 0. --- lib/addr.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/addr.c b/lib/addr.c index 3acd9e4..6150d75 100644 --- a/lib/addr.c +++ b/lib/addr.c @@ -279,7 +279,9 @@ int nl_addr_parse(const char *addrstr, int hint, struct nl_addr **result) if (!strcasecmp(str, "default") || !strcasecmp(str, "all") || !strcasecmp(str, "any")) { - + + len = 0; + switch (hint) { case AF_INET: case AF_UNSPEC: @@ -287,17 +289,14 @@ int nl_addr_parse(const char *addrstr, int hint, struct nl_addr **result) * no hint given the user wants to have a IPv4 * address given back. */ family = AF_INET; - len = 4; goto prefix; case AF_INET6: family = AF_INET6; - len = 16; goto prefix; case AF_LLC: family = AF_LLC; - len = 6; goto prefix; default: From b62e019afad652748bcda0205f96611640bcd6d5 Mon Sep 17 00:00:00 2001 From: Justin Mayfield Date: Thu, 16 Aug 2012 19:03:48 -0600 Subject: [PATCH 225/432] single nexthop flags bug I ran into a bug today related to how Linux handles a route's nexthop flags when there is just one nexthop. Namely Linux expects the flags to be OR'd into the rtm_flags field when there is only one nexthop and so rtnl_route_build_msg needs to check the number of nexthops and store the nexthops flags into this field prior to calling nlmsg_append(...&rtmsg). Conversely the rtnl_route_parse function needs to pull these lower 0xff bits when a single nexthop is detected. Attached is my patch. I don't like the slight duplication of doing the rtnl_route_get_nnexthops check twice but it seemed to be the least turmoil of any solution I thought of. --- lib/route/route_obj.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/route/route_obj.c b/lib/route/route_obj.c index 62669a9..7ea4fff 100644 --- a/lib/route/route_obj.c +++ b/lib/route/route_obj.c @@ -986,6 +986,7 @@ int rtnl_route_parse(struct nlmsghdr *nlh, struct rtnl_route **result) } if (old_nh) { + rtnl_route_nh_set_flags(old_nh, rtm->rtm_flags & 0xff); if (route->rt_nr_nh == 0) { /* If no nexthops have been provided via RTA_MULTIPATH * we add it as regular nexthop to maintain backwards @@ -1045,10 +1046,15 @@ int rtnl_route_build_msg(struct nl_msg *msg, struct rtnl_route *route) if (route->rt_src) rtmsg.rtm_src_len = nl_addr_get_prefixlen(route->rt_src); - if (rtmsg.rtm_scope == RT_SCOPE_NOWHERE) rtmsg.rtm_scope = rtnl_route_guess_scope(route); + if (rtnl_route_get_nnexthops(route) == 1) { + struct rtnl_nexthop *nh; + nh = rtnl_route_nexthop_n(route, 0); + rtmsg.rtm_flags |= nh->rtnh_flags; + } + if (nlmsg_append(msg, &rtmsg, sizeof(rtmsg), NLMSG_ALIGNTO) < 0) goto nla_put_failure; From d10d9633a5b673641eebe3f33c89a334d1972aa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Wed, 29 Aug 2012 22:38:46 +0600 Subject: [PATCH 226/432] Added lex.yy.c to .gitignore --- lib/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/.gitignore b/lib/.gitignore index 2a450e8..e1abf18 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -1,2 +1,3 @@ libnl.so* libnl-*.so* +lex.yy.c From 582a32433ca03dd2ca78dc485329cb81d391a192 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Wed, 29 Aug 2012 22:55:14 +0600 Subject: [PATCH 227/432] Run-time version information is now available Run-time version information is available as exported four integers: - const int nl_ver_num = LIBNL_VER_NUM; - const int nl_ver_maj = LIBNL_VER_MAJ; - const int nl_ver_min = LIBNL_VER_MIN; - const int nl_ver_mic = LIBNL_VER_MIC; The purpose of this is to get version of compiled library as run time. Use cases: - To know exact version of the library in Python's ctypes module, Say, to find out if nl_cache_mngr_alloc() allow sk=NULL - To make sure that the version of the loaded library corresponds to the version of headers (for the paranoid). Say, to check: if (LIBNL_VER_NUM != nl_ver_num) exit(1); --- include/netlink/version.h.in | 11 ++++++++++- lib/Makefile.am | 3 ++- lib/version.c | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 lib/version.c diff --git a/include/netlink/version.h.in b/include/netlink/version.h.in index ac56799..35bf2aa 100644 --- a/include/netlink/version.h.in +++ b/include/netlink/version.h.in @@ -1,5 +1,5 @@ /* - * netlink/version.h Compile Time Versioning Information + * netlink/version.h Versioning Information * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -12,6 +12,8 @@ #ifndef NETLINK_VERSION_H_ #define NETLINK_VERSION_H_ +/* Compile Time Versioning Information */ + #define LIBNL_STRING "@PACKAGE_STRING@" #define LIBNL_VERSION "@PACKAGE_VERSION@" @@ -25,4 +27,11 @@ #define LIBNL_REVISION @LT_REVISION@ #define LIBNL_AGE @LT_AGE@ +/* Run-time version information */ + +extern const int nl_ver_num; +extern const int nl_ver_maj; +extern const int nl_ver_min; +extern const int nl_ver_mic; + #endif diff --git a/lib/Makefile.am b/lib/Makefile.am index aee8d0f..9e5efd8 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -17,7 +17,8 @@ lib_LTLIBRARIES = \ libnl_3_la_SOURCES = \ addr.c attr.c cache.c cache_mngr.c cache_mngt.c data.c \ - error.c handlers.c msg.c nl.c object.c socket.c utils.c + error.c handlers.c msg.c nl.c object.c socket.c utils.c \ + version.c libnl_genl_3_la_LIBADD = libnl-3.la libnl_genl_3_la_SOURCES = \ diff --git a/lib/version.c b/lib/version.c new file mode 100644 index 0000000..0dcafa0 --- /dev/null +++ b/lib/version.c @@ -0,0 +1,36 @@ +/* + * lib/version.c Run-time version information + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +/** + * @ingroup core + * @defgroup utils Utilities + * + * Run-time version information + * + * @{ + */ + + +/** + * @name Run-time version information + * @{ + */ + +#include + +const int nl_ver_num = LIBNL_VER_NUM; +const int nl_ver_maj = LIBNL_VER_MAJ; +const int nl_ver_min = LIBNL_VER_MIN; +const int nl_ver_mic = LIBNL_VER_MIC; + +/** @} */ + +/** @} */ From ab15d06d13484df246eb0fbd9ab6a6012ed81153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Wed, 29 Aug 2012 23:59:17 +0600 Subject: [PATCH 228/432] "%llu" replaced with "%" PRIu64 On some architectures, uint64_t is defined as: typedef unsigned long long int __u64; on another architectures as: typedef unsigned long int __u64; So, according to man 3 printf, uint64_t should be printed as "%llu" on some architectures, and as "%lu" on another. The same for scanf. To eliminate that challenge, there is inttypes.h, in which appropriate constants are defined for current architecture. 32-bit types (and even 16 and 8 bit types) should be printed using such constants if printed variable defined as uint_XXXt or intXXXt type. But in reality 32-bit and less types does not gain run-time error (except in scanf), because they pushed to stack as 32-bit values at least. So, I decide not to fix that. --- lib/netfilter/ct_obj.c | 2 +- lib/route/cls/u32.c | 2 +- lib/route/link.c | 4 ++-- lib/route/link/inet6.c | 38 +++++++++++++++++++------------------- lib/route/neightbl.c | 21 ++++++++++++++++----- src/nl-list-sockets.c | 2 +- 6 files changed, 40 insertions(+), 29 deletions(-) diff --git a/lib/netfilter/ct_obj.c b/lib/netfilter/ct_obj.c index 70a814f..f57b15e 100644 --- a/lib/netfilter/ct_obj.c +++ b/lib/netfilter/ct_obj.c @@ -277,7 +277,7 @@ static void ct_dump_stats(struct nl_object *a, struct nl_dump_params *p) for (i=0; i<=1; i++) { res = nl_cancel_down_bytes(nfnl_ct_get_bytes(ct, i), &unit); packets = nfnl_ct_get_packets(ct, i); - nl_dump_line(p, " %s %10llu %7.2f %s\n", names[i], packets, res, unit); + nl_dump_line(p, " %s %10" PRIu64 " %7.2f %s\n", names[i], packets, res, unit); } } diff --git a/lib/route/cls/u32.c b/lib/route/cls/u32.c index d3e326d..aa9eb77 100644 --- a/lib/route/cls/u32.c +++ b/lib/route/cls/u32.c @@ -306,7 +306,7 @@ static void u32_dump_stats(struct rtnl_tc *tc, void *data, if (u->cu_mask & U32_ATTR_PCNT) { struct tc_u32_pcnt *pc = u->cu_pcnt->d_data; nl_dump(p, "\n"); - nl_dump_line(p, " hit %8llu count %8llu\n", + nl_dump_line(p, " hit %8" PRIu64 " count %8" PRIu64 "\n", pc->rhit, pc->rcnt); } } diff --git a/lib/route/link.c b/lib/route/link.c index aea43b9..0e8ac07 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -662,7 +662,7 @@ static void link_dump_stats(struct nl_object *obj, struct nl_dump_params *p) res = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_RX_BYTES], &unit); - strcpy(fmt, " RX %X.2f %s %10llu %10llu %10llu %10llu %10llu\n"); + strcpy(fmt, " RX %X.2f %s %10" PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" PRIu64 "\n"); fmt[9] = *unit == 'B' ? '9' : '7'; nl_dump_line(p, fmt, res, unit, @@ -674,7 +674,7 @@ static void link_dump_stats(struct nl_object *obj, struct nl_dump_params *p) res = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_TX_BYTES], &unit); - strcpy(fmt, " TX %X.2f %s %10llu %10llu %10llu %10llu %10llu\n"); + strcpy(fmt, " TX %X.2f %s %10" PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" PRIu64 "\n"); fmt[9] = *unit == 'B' ? '9' : '7'; nl_dump_line(p, fmt, res, unit, diff --git a/lib/route/link/inet6.c b/lib/route/link/inet6.c index 5f75342..9ee8226 100644 --- a/lib/route/link/inet6.c +++ b/lib/route/link/inet6.c @@ -242,78 +242,78 @@ static void inet6_dump_stats(struct rtnl_link *link, nl_dump(p, " IPv6: InPkts InOctets " " InDiscards InDelivers\n"); - nl_dump(p, " %18llu ", link->l_stats[RTNL_LINK_IP6_INPKTS]); + nl_dump(p, " %18" PRIu64 " ", link->l_stats[RTNL_LINK_IP6_INPKTS]); octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_INOCTETS], &octetsUnit); if (octets) nl_dump(p, "%14.2f %3s ", octets, octetsUnit); else - nl_dump(p, "%16llu B ", 0); + nl_dump(p, "%16" PRIu64 " B ", 0); - nl_dump(p, "%18llu %18llu\n", + nl_dump(p, "%18" PRIu64 " %18" PRIu64 "\n", link->l_stats[RTNL_LINK_IP6_INDISCARDS], link->l_stats[RTNL_LINK_IP6_INDELIVERS]); nl_dump(p, " OutPkts OutOctets " " OutDiscards OutForwards\n"); - nl_dump(p, " %18llu ", link->l_stats[RTNL_LINK_IP6_OUTPKTS]); + nl_dump(p, " %18" PRIu64 " ", link->l_stats[RTNL_LINK_IP6_OUTPKTS]); octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_OUTOCTETS], &octetsUnit); if (octets) nl_dump(p, "%14.2f %3s ", octets, octetsUnit); else - nl_dump(p, "%16llu B ", 0); + nl_dump(p, "%16" PRIu64 " B ", 0); - nl_dump(p, "%18llu %18llu\n", + nl_dump(p, "%18" PRIu64 " %18" PRIu64 "\n", link->l_stats[RTNL_LINK_IP6_OUTDISCARDS], link->l_stats[RTNL_LINK_IP6_OUTFORWDATAGRAMS]); nl_dump(p, " InMcastPkts InMcastOctets " " InBcastPkts InBcastOctests\n"); - nl_dump(p, " %18llu ", link->l_stats[RTNL_LINK_IP6_INMCASTPKTS]); + nl_dump(p, " %18" PRIu64 " ", link->l_stats[RTNL_LINK_IP6_INMCASTPKTS]); octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_INMCASTOCTETS], &octetsUnit); if (octets) nl_dump(p, "%14.2f %3s ", octets, octetsUnit); else - nl_dump(p, "%16llu B ", 0); + nl_dump(p, "%16" PRIu64 " B ", 0); - nl_dump(p, "%18llu ", link->l_stats[RTNL_LINK_IP6_INBCASTPKTS]); + nl_dump(p, "%18" PRIu64 " ", link->l_stats[RTNL_LINK_IP6_INBCASTPKTS]); octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_INBCASTOCTETS], &octetsUnit); if (octets) nl_dump(p, "%14.2f %3s\n", octets, octetsUnit); else - nl_dump(p, "%16llu B\n", 0); + nl_dump(p, "%16" PRIu64 " B\n", 0); nl_dump(p, " OutMcastPkts OutMcastOctets " " OutBcastPkts OutBcastOctests\n"); - nl_dump(p, " %18llu ", link->l_stats[RTNL_LINK_IP6_OUTMCASTPKTS]); + nl_dump(p, " %18" PRIu64 " ", link->l_stats[RTNL_LINK_IP6_OUTMCASTPKTS]); octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_OUTMCASTOCTETS], &octetsUnit); if (octets) nl_dump(p, "%14.2f %3s ", octets, octetsUnit); else - nl_dump(p, "%16llu B ", 0); + nl_dump(p, "%16" PRIu64 " B ", 0); - nl_dump(p, "%18llu ", link->l_stats[RTNL_LINK_IP6_OUTBCASTPKTS]); + nl_dump(p, "%18" PRIu64 " ", link->l_stats[RTNL_LINK_IP6_OUTBCASTPKTS]); octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_OUTBCASTOCTETS], &octetsUnit); if (octets) nl_dump(p, "%14.2f %3s\n", octets, octetsUnit); else - nl_dump(p, "%16llu B\n", 0); + nl_dump(p, "%16" PRIu64 " B\n", 0); nl_dump(p, " ReasmOKs ReasmFails " " ReasmReqds ReasmTimeout\n"); - nl_dump(p, " %18llu %18llu %18llu %18llu\n", + nl_dump(p, " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n", link->l_stats[RTNL_LINK_IP6_REASMOKS], link->l_stats[RTNL_LINK_IP6_REASMFAILS], link->l_stats[RTNL_LINK_IP6_REASMREQDS], @@ -321,14 +321,14 @@ static void inet6_dump_stats(struct rtnl_link *link, nl_dump(p, " FragOKs FragFails " " FragCreates\n"); - nl_dump(p, " %18llu %18llu %18llu\n", + nl_dump(p, " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n", link->l_stats[RTNL_LINK_IP6_FRAGOKS], link->l_stats[RTNL_LINK_IP6_FRAGFAILS], link->l_stats[RTNL_LINK_IP6_FRAGCREATES]); nl_dump(p, " InHdrErrors InTooBigErrors " " InNoRoutes InAddrErrors\n"); - nl_dump(p, " %18llu %18llu %18llu %18llu\n", + nl_dump(p, " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n", link->l_stats[RTNL_LINK_IP6_INHDRERRORS], link->l_stats[RTNL_LINK_IP6_INTOOBIGERRORS], link->l_stats[RTNL_LINK_IP6_INNOROUTES], @@ -336,14 +336,14 @@ static void inet6_dump_stats(struct rtnl_link *link, nl_dump(p, " InUnknownProtos InTruncatedPkts " " OutNoRoutes\n"); - nl_dump(p, " %18llu %18llu %18llu\n", + nl_dump(p, " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n", link->l_stats[RTNL_LINK_IP6_INUNKNOWNPROTOS], link->l_stats[RTNL_LINK_IP6_INTRUNCATEDPKTS], link->l_stats[RTNL_LINK_IP6_OUTNOROUTES]); nl_dump(p, " ICMPv6: InMsgs InErrors " " OutMsgs OutErrors\n"); - nl_dump(p, " %18llu %18llu %18llu %18llu\n", + nl_dump(p, " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n", link->l_stats[RTNL_LINK_ICMP6_INMSGS], link->l_stats[RTNL_LINK_ICMP6_INERRORS], link->l_stats[RTNL_LINK_ICMP6_OUTMSGS], diff --git a/lib/route/neightbl.c b/lib/route/neightbl.c index 9599faa..7725482 100644 --- a/lib/route/neightbl.c +++ b/lib/route/neightbl.c @@ -332,21 +332,32 @@ static void neightbl_dump_stats(struct nl_object *arg, struct nl_dump_params *p) if (!(ntbl->ce_mask & NEIGHTBL_ATTR_STATS)) return; - nl_dump_line(p, " lookups %lld hits %lld failed %lld " \ - "allocations %lld destroys %lld\n", + nl_dump_line(p, " " \ + " lookups %" PRIu64 \ + " hits %" PRIu64 \ + " failed %" PRIu64 \ + " allocations %" PRIu64 \ + " destroys %" PRIu64 \ + "\n", ntbl->nt_stats.ndts_lookups, ntbl->nt_stats.ndts_hits, ntbl->nt_stats.ndts_res_failed, ntbl->nt_stats.ndts_allocs, ntbl->nt_stats.ndts_destroys); - nl_dump_line(p, " hash-grows %lld forced-gc-runs %lld " \ - "periodic-gc-runs %lld\n", + nl_dump_line(p, " " \ + " hash-grows %" PRIu64 \ + " forced-gc-runs %" PRIu64 \ + " periodic-gc-runs %" PRIu64 \ + "\n", ntbl->nt_stats.ndts_hash_grows, ntbl->nt_stats.ndts_forced_gc_runs, ntbl->nt_stats.ndts_periodic_gc_runs); - nl_dump_line(p, " rcv-unicast-probes %lld rcv-multicast-probes %lld\n", + nl_dump_line(p, " " \ + " rcv-unicast-probes %" PRIu64 \ + " rcv-multicast-probes %" PRIu64 \ + "\n", ntbl->nt_stats.ndts_rcv_probes_ucast, ntbl->nt_stats.ndts_rcv_probes_mcast); } diff --git a/src/nl-list-sockets.c b/src/nl-list-sockets.c index 868006e..c2fa1cd 100644 --- a/src/nl-list-sockets.c +++ b/src/nl-list-sockets.c @@ -30,7 +30,7 @@ int main(int argc, char *argv[]) while (fgets(buf, sizeof(buf), fd)) { unsigned long sk, cb; int ret, proto, pid, rmem, wmem, refcnt; - uint32_t groups; + unsigned int groups; ret = sscanf(buf, "%lx %d %d %08x %d %d %lx %d\n", &sk, &proto, &pid, &groups, &rmem, &wmem, From 8cd2f5728a106931a1dd5ba96fb5a3d08da36362 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Thu, 30 Aug 2012 00:15:12 +0600 Subject: [PATCH 229/432] Fix typo in textual description in ct_dump_stats() Bug introduced in a0f1c0e281ee78ab8ee874bbb6c2140c12101284 --- lib/netfilter/ct_obj.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/netfilter/ct_obj.c b/lib/netfilter/ct_obj.c index f57b15e..d5cd18a 100644 --- a/lib/netfilter/ct_obj.c +++ b/lib/netfilter/ct_obj.c @@ -267,8 +267,8 @@ static void ct_dump_stats(struct nl_object *a, struct nl_dump_params *p) !nfnl_ct_test_bytes(ct, 1) || !nfnl_ct_test_packets(ct, 1)) { - nl_dump_line(p, " Statics are not available.\n"); - nl_dump_line(p, " Please set sysctl net.netfilter.nf_conntrack_acct = 1\n"); + nl_dump_line(p, " Statistics are not available.\n"); + nl_dump_line(p, " Please set sysctl net.netfilter.nf_conntrack_acct=1\n"); nl_dump_line(p, " (Require kernel 2.6.27)\n"); return; } From a2b23ffe458f7353eacb92cbe3dd29aa21dc195b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Thu, 30 Aug 2012 00:47:09 +0600 Subject: [PATCH 230/432] Fix warning "not checking return value of fscanf" in lib/utils.c: get_psched_settings Also, change internal variables type from uint32_t to unsigned int. Correct scanf format string should contain "SCNx32" instead of just "x", but I decide not to fix that and just changed variable type. --- lib/utils.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/utils.c b/lib/utils.c index 74f5639..b5e32c3 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -28,6 +28,7 @@ #include #include #include +#include /* exit() */ /** * Global variable indicating the desired level of debugging output. @@ -421,10 +422,15 @@ static void __init get_psched_settings(void) strncpy(name, "/proc/net/psched", sizeof(name) - 1); if ((fd = fopen(name, "r"))) { - uint32_t ns_per_usec, ns_per_tick, nom, denom; + unsigned int ns_per_usec, ns_per_tick, nom, denom; - fscanf(fd, "%08x %08x %08x %08x", - &ns_per_usec, &ns_per_tick, &nom, &denom); + if (fscanf(fd, "%08x %08x %08x %08x", + &ns_per_usec, &ns_per_tick, &nom, &denom) != 4) { + fprintf(stderr, "Fatal error: can not read psched settings from \"%s\". " \ + "Try to set TICKS_PER_USEC, PROC_NET_PSCHED or PROC_ROOT " \ + "environment variables\n", name); + exit(1); + } ticks_per_usec = (double) ns_per_usec / (double) ns_per_tick; From 5eee974e034be5bd0614dd907a603b71869646ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Thu, 30 Aug 2012 04:33:40 +0600 Subject: [PATCH 231/432] Prevent potential socket file descriptor leak This may happen when passing connected socket to nl_cache_mngr_alloc(). Now, nl_connect() will return error trying to connect already connected socket. Also, dont call close(-1) if socket() fails. --- lib/nl.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/nl.c b/lib/nl.c index 6b2f027..d3e67aa 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -69,6 +69,8 @@ * Creates a netlink socket using the specified protocol, binds the socket * and issues a connection attempt. * + * This function fail if socket is already connected. + * * @note SOCK_CLOEXEC is set on the socket if available. * * @return 0 on success or a negative error code. @@ -82,6 +84,9 @@ int nl_connect(struct nl_sock *sk, int protocol) flags |= SOCK_CLOEXEC; #endif + if (sk->s_fd != -1) + return -NLE_BAD_SOCK; + sk->s_fd = socket(AF_NETLINK, SOCK_RAW | flags, protocol); if (sk->s_fd < 0) { err = -nl_syserr2nlerr(errno); @@ -123,8 +128,10 @@ int nl_connect(struct nl_sock *sk, int protocol) return 0; errout: - close(sk->s_fd); - sk->s_fd = -1; + if (sk->s_fd != -1) { + close(sk->s_fd); + sk->s_fd = -1; + } return err; } From 717fabc4692790e46059a0d2e65899ca8eda5fe8 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 30 Aug 2012 13:15:45 +0200 Subject: [PATCH 232/432] configure: Check for graphviz and source-highlight before building documentation Signed-off-by: Thomas Graf --- configure.in | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/configure.in b/configure.in index ad6fad3..7bf3423 100644 --- a/configure.in +++ b/configure.in @@ -91,6 +91,16 @@ if test "x$generate_doc" != "xno"; then AC_MSG_ERROR([*** doxygen package required to generate documentation]) fi + AC_CHECK_PROG(HAVE_DOT, [dot], yes, no) + if test "x$HAVE_DOT" = "xno"; then + if test "x$generate_doc" = "xyes"; then + AC_MSG_ERROR([*** graphviz package required to generate documentation]) + else + AC_MSG_WARN([*** graphviz not found, disabling building of API reference]) + HAVE_DOXYGEN=no + fi + fi + AC_CHECK_PROG(HAVE_ASCIIDOC, [asciidoc], yes, no) if test "x$HAVE_ASCIIDOC" = "xno"; then if test "x$generate_doc" = "xyes"; then @@ -100,6 +110,16 @@ if test "x$generate_doc" != "xno"; then fi fi + AC_CHECK_PROG(HAVE_SOURCE_HIGHLIGHT, [source-highlight], yes, no) + if test "x$HAVE_SOURCE_HIGHLIGHT" = "xno"; then + if test "x$generate_doc" = "xyes"; then + AC_MSG_ERROR([*** source-highlight required to generate documentation]) + else + AC_MSG_WARN([*** source-highlight not found, disabling building of guides]) + HAVE_ASCIIDOC=no + fi + fi + AC_CHECK_PROG(HAVE_MSCGEN, [mscgen], yes, no) if test "x$HAVE_MSCGEN" = "xno"; then AC_MSG_WARN([*** mscgen not found, get it at http://www.mcternan.me.uk/mscgen/]) From b377ab1bbd5098cf018ecc595d894330563b6af2 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 30 Aug 2012 13:19:56 +0200 Subject: [PATCH 233/432] route: Document ROUTE_CACHE_CONTENT flag Signed-off-by: Thomas Graf --- include/netlink/route/route.h | 9 +++++++-- lib/route/route.c | 4 ++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include/netlink/route/route.h b/include/netlink/route/route.h index 5729cd7..d3543af 100644 --- a/include/netlink/route/route.h +++ b/include/netlink/route/route.h @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ #ifndef NETLINK_ROUTE_H_ @@ -24,7 +24,12 @@ extern "C" { #endif -/* flags */ +/** + * @ingroup route + * When passed to rtnl_route_alloc_cache() the cache will + * correspond to the contents of the routing cache instead + * of the actual routes. + */ #define ROUTE_CACHE_CONTENT 1 struct rtnl_route; diff --git a/lib/route/route.c b/lib/route/route.c index f684f96..2218a60 100644 --- a/lib/route/route.c +++ b/lib/route/route.c @@ -69,6 +69,10 @@ static int route_request_update(struct nl_cache *c, struct nl_sock *h) * Allocates a new cache, initializes it properly and updates it to * contain all routes currently configured in the kernel. * + * Valid flags: + * * ROUTE_CACHE_CONTENT - Cache will contain contents of routing cache + * instead of actual routes. + * * @note The caller is responsible for destroying and freeing the * cache after using it. * @return 0 on success or a negative error code. From 5eeb3d3ea683152476af4c4068cd3f8312f88766 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 30 Aug 2012 13:22:21 +0200 Subject: [PATCH 234/432] doc: Update Doxyfile config to latest release --- .gitignore | 1 - doc/Doxyfile | 1802 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1802 insertions(+), 1 deletion(-) create mode 100644 doc/Doxyfile diff --git a/.gitignore b/.gitignore index 85ddb3c..ec94f8d 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,6 @@ defs.h.in~ /lib/stamp-h1 /libnl-1.pc -/doc/Doxyfile /lib/defs.h cscope.* diff --git a/doc/Doxyfile b/doc/Doxyfile new file mode 100644 index 0000000..258344e --- /dev/null +++ b/doc/Doxyfile @@ -0,0 +1,1802 @@ +# Doxyfile 1.8.1.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" "). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. + +PROJECT_NAME = libnl + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 3.2.11 + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = ./ + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = YES + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = NO + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = arg=\param \ + "ref_asciidoc{3}=\3" \ + "ref_core{2}=\ref_asciidoc{core,\1,\2 (Netlink Core Library Development Guide)}" \ + "ref_route{2}=\ref_asciidoc{route,\1,\2 (Netlink Routing Development Guide)}" \ + "core_doc{2}=\ref_core{\1,\2}" \ + "route_doc{2}=\ref_route{\1,\2}" + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding +# "class=itcl::class" will allow you to use the command class in the +# itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all +# comments according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you +# can mix doxygen, HTML, and XML commands with Markdown formatting. +# Disable only in case of backward compatibilities issues. + +MARKDOWN_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = NO + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields will be shown inline in the documentation +# of the scope in which they are defined (i.e. file, namespace, or group +# documentation), provided this scope is documented. If set to NO (the default), +# structs, classes, and unions are shown on a separate page (for HTML and Man +# pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +SYMBOL_CACHE_SIZE = 0 + +# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be +# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given +# their name and scope. Since this can be an expensive process and often the +# same symbol appear multiple times in the code, doxygen keeps a cache of +# pre-resolved symbols. If the cache is too small doxygen will become slower. +# If the cache is too large, memory is wasted. The cache size is given by this +# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal scope will be included in the documentation. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = YES + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = NO + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = YES + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = NO + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = NO + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = NO + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = DoxygenLayout.xml + +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this +# feature you need bibtex and perl available in the search path. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = NO + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ../lib \ + ../src/lib \ + ../include/netlink \ + ../src \ + ../doc/src + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = *.c \ + *.h + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = SCCS + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = ../src + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C, C++ and Fortran comments will always remain visible. + +STRIP_CODE_COMMENTS = NO + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = nl_ + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = api + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is advised to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# style sheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = ./libnl.css + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the style sheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. + +HTML_DYNAMIC_SECTIONS = YES + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of +# entries shown in the various tree structured indices initially; the user +# can expand and collapse entries dynamically later on. Doxygen will expand +# the tree to such a level that at most the specified number of entries are +# visible (unless a fully collapsed tree already exceeds this amount). +# So setting the number of entries 1 will produce a full collapsed tree by +# default. 0 is a special value representing an infinite number of entries +# and will result in a full expanded tree by default. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.infradead.libnl + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) +# at top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. Since the tabs have the same information as the +# navigation tree you can set this option to NO if you already set +# GENERATE_TREEVIEW to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. +# Since the tree basically has the same information as the tab index you +# could consider to set DISABLE_INDEX to NO when enabling this option. + +GENERATE_TREEVIEW = YES + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 1 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 205 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you may also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to +# the MathJax Content Delivery Network so you can quickly see the result without +# installing MathJax. +# However, it is strongly recommended to install a local +# copy of MathJax from http://www.mathjax.org before deployment. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = NO + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE = plain + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load style sheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + +SEARCH_INCLUDES = NO + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. For each +# tag file the location of the external documentation should be added. The +# format of a tag file without this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths +# or URLs. Note that each tag file must have a unique name (where the name does +# NOT include the path). If a tag file is not located in the directory in which +# doxygen is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = YES + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = NO + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. + +DOT_FONTNAME = FreeSans.ttf + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = NO + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = NO + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = NO + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = YES + +# If the UML_LOOK tag is enabled, the fields and methods are shown inside +# the class node. If there are many fields or methods and many nodes the +# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS +# threshold limits the number of items for each type to make the size more +# managable. Set this to 0 for no limit. Note that the threshold may be +# exceeded by 50% before the limit is enforced. + +UML_LIMIT_NUM_FIELDS = 10 + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = NO + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = YES + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = YES + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. + +INTERACTIVE_SVG = NO + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES From 929bd0150f33887ba25a9490937659dac89a44b5 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 30 Aug 2012 13:36:23 +0200 Subject: [PATCH 235/432] configure: Check for pygmentize when building docs Signed-off-by: Thomas Graf --- configure.in | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/configure.in b/configure.in index 7bf3423..8ea76cb 100644 --- a/configure.in +++ b/configure.in @@ -132,6 +132,16 @@ if test "x$generate_doc" != "xno"; then fi fi + AC_CHECK_PROG(HAVE_PYGMENTIZE, [pygmentize], yes, no) + if test "x$HAVE_PYGMENTIZE" = "xno"; then + if test "x$generate_doc" = "xyes"; then + AC_MSG_ERROR([*** pygmentize package required to generate documentation]) + else + AC_MSG_WARN([*** Disabling building of guides]) + HAVE_ASCIIDOC=no + fi + fi + link_doc=yes if test "x$HAVE_DOXYGEN" = "xno"; then AC_MSG_WARN([*** Disabling API linking due to missing doxygen package]) From 3bf8712feb2eb7f6d4a1bfdb02c0a7a2f6bcb13b Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 30 Aug 2012 13:46:29 +0200 Subject: [PATCH 236/432] 3.2.12 release --- configure.in | 6 +++--- doc/Doxyfile | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.in b/configure.in index 8ea76cb..5016842 100644 --- a/configure.in +++ b/configure.in @@ -13,7 +13,7 @@ # copied from glib m4_define([libnl_major_version], [3]) m4_define([libnl_minor_version], [2]) -m4_define([libnl_micro_version], [11]) +m4_define([libnl_micro_version], [12]) # If either revision or age are omitted, they default to 0. Also note that age @@ -34,9 +34,9 @@ m4_define([libnl_micro_version], [11]) # 6. If any interfaces have been removed since the last public release, then # set age to 0. -m4_define([libnl_lt_current], [209]) +m4_define([libnl_lt_current], [210]) m4_define([libnl_lt_revision], [0]) -m4_define([libnl_lt_age], [9]) +m4_define([libnl_lt_age], [10]) m4_define([libnl_version], [libnl_major_version.libnl_minor_version.libnl_micro_version]) diff --git a/doc/Doxyfile b/doc/Doxyfile index 258344e..c6586eb 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -32,7 +32,7 @@ PROJECT_NAME = libnl # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = 3.2.11 +PROJECT_NUMBER = 3.2.12 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer From 8f2ce4d791ebdbfcb3699f8890568964c5572a70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA?= Date: Thu, 30 Aug 2012 18:40:11 +0600 Subject: [PATCH 237/432] More clean NL_AUTO_PORT and NL_AUTO_SEQ usage in nl_complete_msg --- lib/nl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/nl.c b/lib/nl.c index d3e67aa..ea3e087 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -274,10 +274,10 @@ void nl_complete_msg(struct nl_sock *sk, struct nl_msg *msg) struct nlmsghdr *nlh; nlh = nlmsg_hdr(msg); - if (nlh->nlmsg_pid == 0) + if (nlh->nlmsg_pid == NL_AUTO_PORT) nlh->nlmsg_pid = sk->s_local.nl_pid; - if (nlh->nlmsg_seq == 0) + if (nlh->nlmsg_seq == NL_AUTO_SEQ) nlh->nlmsg_seq = sk->s_seq_next++; if (msg->nm_protocol == -1) From 00261259f02b41b0689c87525fd5b6039b651c37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA?= Date: Thu, 30 Aug 2012 20:59:38 +0600 Subject: [PATCH 238/432] Address comparison bug fixed Bug introduced in 794ac78c5618ee81a45e4f58694ee27b3403ebd7 --- lib/addr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/addr.c b/lib/addr.c index 6150d75..1f1478a 100644 --- a/lib/addr.c +++ b/lib/addr.c @@ -497,11 +497,12 @@ int nl_addr_cmp(struct nl_addr *a, struct nl_addr *b) if (d == 0) { d = a->a_len - b->a_len; - if (a->a_len && d == 0) + if (a->a_len && d == 0) { d = memcmp(a->a_addr, b->a_addr, a->a_len); if (d == 0) return (a->a_prefixlen - b->a_prefixlen); + } } return d; From a820222877729619b4560afdbddb5f1db293f73f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA?= Date: Thu, 30 Aug 2012 22:25:21 +0600 Subject: [PATCH 239/432] asprintf related fixed in yy parser 1. According to man asprintf: If memory allocation wasn't possible, or some other error occurs, these functions will return -1, and the contents of strp is undefined. 2. Sometimes, errp was not filled at all. In high-level code, free(errp) will called, so segmantation fault may appear in case of error in parser 3. The most cases of using asprintf is to report about allocation fail. So, probability of allocation of asprintf buffer is very high. And that will lead to trash in errp. 4. For simple casses I decide to replace asprintf with strdup --- lib/route/cls/ematch_syntax.y | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/lib/route/cls/ematch_syntax.y b/lib/route/cls/ematch_syntax.y index 61c91d1..39123be 100644 --- a/lib/route/cls/ematch_syntax.y +++ b/lib/route/cls/ematch_syntax.y @@ -53,7 +53,9 @@ extern int ematch_lex(YYSTYPE *, void *); static void yyerror(void *scanner, char **errp, struct nl_list_head *root, const char *msg) { if (msg) - asprintf(errp, "%s", msg); + *errp = strdup(msg); + else + *errp = NULL; } %} @@ -186,7 +188,7 @@ ematch: struct rtnl_ematch *e; if (!(e = rtnl_ematch_alloc())) { - asprintf(errp, "Unable to allocate ematch object"); + *errp = strdup("Unable to allocate ematch object"); YYABORT; } @@ -201,7 +203,7 @@ ematch: struct rtnl_ematch *e; if (!(e = rtnl_ematch_alloc())) { - asprintf(errp, "Unable to allocate ematch object"); + *errp = strdup("Unable to allocate ematch object"); YYABORT; } @@ -219,7 +221,7 @@ ematch: struct rtnl_ematch *e; if (!(e = rtnl_ematch_alloc())) { - asprintf(errp, "Unable to allocate ematch object"); + *errp = strdup("Unable to allocate ematch object"); YYABORT; } @@ -246,7 +248,7 @@ ematch: struct rtnl_ematch *e; if (!(e = rtnl_ematch_alloc())) { - asprintf(errp, "Unable to allocate ematch object"); + *errp = strdup("Unable to allocate ematch object"); YYABORT; } @@ -265,7 +267,7 @@ ematch: struct rtnl_ematch *e; if (!(e = rtnl_ematch_alloc())) { - asprintf(errp, "Unable to allocate ematch object"); + *errp = strdup("Unable to allocate ematch object"); YYABORT; } @@ -417,7 +419,8 @@ pattern: memcpy($$.data, nl_addr_get_binary_addr(addr), $$.len); nl_addr_put(addr); } else { - asprintf(errp, "invalid pattern \"%s\"", $1); + if (asprintf(errp, "invalid pattern \"%s\"", $1) == -1) + *errp = NULL; YYABORT; } } @@ -433,7 +436,8 @@ pktloc: struct rtnl_pktloc *loc; if (rtnl_pktloc_lookup($1, &loc) < 0) { - asprintf(errp, "Packet location \"%s\" not found", $1); + if (asprintf(errp, "Packet location \"%s\" not found", $1) == -1) + *errp = NULL; YYABORT; } @@ -445,12 +449,12 @@ pktloc: struct rtnl_pktloc *loc; if ($5 && (!$1 || $1 > TCF_EM_ALIGN_U32)) { - asprintf(errp, "mask only allowed for alignments u8|u16|u32"); + *errp = strdup("mask only allowed for alignments u8|u16|u32"); YYABORT; } if (!(loc = rtnl_pktloc_alloc())) { - asprintf(errp, "Unable to allocate packet location object"); + *errp = strdup("Unable to allocate packet location object"); YYABORT; } From b1e0a0ca5da3d4d0f061465ff2fd4cf8a2ad62f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA?= Date: Thu, 30 Aug 2012 22:43:09 +0600 Subject: [PATCH 240/432] Remove auto-generated Doxyfile from git Also, add it to gitignore --- doc/.gitignore | 1 + doc/Doxyfile | 1802 ------------------------------------------------ 2 files changed, 1 insertion(+), 1802 deletions(-) delete mode 100644 doc/Doxyfile diff --git a/doc/.gitignore b/doc/.gitignore index deffa1d..b6e9df2 100644 --- a/doc/.gitignore +++ b/doc/.gitignore @@ -1,2 +1,3 @@ *.html libnl.dict +Doxyfile diff --git a/doc/Doxyfile b/doc/Doxyfile deleted file mode 100644 index c6586eb..0000000 --- a/doc/Doxyfile +++ /dev/null @@ -1,1802 +0,0 @@ -# Doxyfile 1.8.1.1 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project. -# -# All text after a hash (#) is considered a comment and will be ignored. -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" "). - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or sequence of words) that should -# identify the project. Note that if you do not use Doxywizard you need -# to put quotes around the project name if it contains spaces. - -PROJECT_NAME = libnl - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = 3.2.12 - -# Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewer -# a quick idea about the purpose of the project. Keep the description short. - -PROJECT_BRIEF = - -# With the PROJECT_LOGO tag one can specify an logo or icon that is -# included in the documentation. The maximum height of the logo should not -# exceed 55 pixels and the maximum width should not exceed 200 pixels. -# Doxygen will copy the logo to the output directory. - -PROJECT_LOGO = - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = ./ - -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. - -CREATE_SUBDIRS = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, -# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English -# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, -# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, -# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. - -INLINE_INHERITED_MEMB = YES - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = YES - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. - -STRIP_FROM_PATH = - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful if your file system -# doesn't support long names like on DOS, Mac, or CD-ROM. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) - -JAVADOC_AUTOBRIEF = YES - -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. - -INHERIT_DOCS = NO - -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 8 - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = arg=\param \ - "ref_asciidoc{3}=\3" \ - "ref_core{2}=\ref_asciidoc{core,\1,\2 (Netlink Core Library Development Guide)}" \ - "ref_route{2}=\ref_asciidoc{route,\1,\2 (Netlink Routing Development Guide)}" \ - "core_doc{2}=\ref_core{\1,\2}" \ - "route_doc{2}=\ref_route{\1,\2}" - -# This tag can be used to specify a number of word-keyword mappings (TCL only). -# A mapping has the form "name=value". For example adding -# "class=itcl::class" will allow you to use the command class in the -# itcl::class meaning. - -TCL_SUBST = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = YES - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Doxygen selects the parser to use depending on the extension of the files it -# parses. With this tag you can assign which parser to use for a given extension. -# Doxygen has a built-in mapping, but you can override or extend it using this -# tag. The format is ext=language, where ext is a file extension, and language -# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, -# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make -# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C -# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions -# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. - -EXTENSION_MAPPING = - -# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all -# comments according to the Markdown format, which allows for more readable -# documentation. See http://daringfireball.net/projects/markdown/ for details. -# The output of markdown processing is further processed by doxygen, so you -# can mix doxygen, HTML, and XML commands with Markdown formatting. -# Disable only in case of backward compatibilities issues. - -MARKDOWN_SUPPORT = YES - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also makes the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. - -BUILTIN_STL_SUPPORT = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate getter -# and setter methods for a property. Setting this option to YES (the default) -# will make doxygen replace the get and set methods by a property in the -# documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. - -IDL_PROPERTY_SUPPORT = NO - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. - -SUBGROUPING = YES - -# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and -# unions are shown inside the group in which they are included (e.g. using -# @ingroup) instead of on a separate page (for HTML and Man pages) or -# section (for LaTeX and RTF). - -INLINE_GROUPED_CLASSES = NO - -# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and -# unions with only public data fields will be shown inline in the documentation -# of the scope in which they are defined (i.e. file, namespace, or group -# documentation), provided this scope is documented. If set to NO (the default), -# structs, classes, and unions are shown on a separate page (for HTML and Man -# pages) or section (for LaTeX and RTF). - -INLINE_SIMPLE_STRUCTS = NO - -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. - -TYPEDEF_HIDES_STRUCT = NO - -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penalty. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will roughly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols. - -SYMBOL_CACHE_SIZE = 0 - -# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be -# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given -# their name and scope. Since this can be an expensive process and often the -# same symbol appear multiple times in the code, doxygen keeps a cache of -# pre-resolved symbols. If the cache is too small doxygen will become slower. -# If the cache is too large, memory is wasted. The cache size is given by this -# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols. - -LOOKUP_CACHE_SIZE = 0 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = NO - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = YES - -# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal scope will be included in the documentation. - -EXTRACT_PACKAGE = NO - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = NO - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. - -EXTRACT_LOCAL_METHODS = YES - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespaces are hidden. - -EXTRACT_ANON_NSPACES = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen -# will list include files with double quotes in the documentation -# rather than with sharp brackets. - -FORCE_LOCAL_INCLUDES = NO - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = NO - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. - -SORT_BRIEF_DOCS = NO - -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen -# will sort the (brief and detailed) documentation of class members so that -# constructors and destructors are listed first. If set to NO (the default) -# the constructors will appear in the respective orders defined by -# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. -# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO -# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. - -SORT_MEMBERS_CTORS_1ST = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. - -SORT_GROUP_NAMES = YES - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. - -SORT_BY_SCOPE_NAME = NO - -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to -# do proper type resolution of all parameters of a function it will reject a -# match between the prototype and the implementation of a member function even -# if there is only one candidate or it is obvious which candidate to choose -# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen -# will still accept a match between prototype and implementation in such cases. - -STRICT_PROTO_MATCHING = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = NO - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = NO - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or macro consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and macros in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = NO - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. - -SHOW_FILES = NO - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. -# This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed -# by doxygen. The layout file controls the global structure of the generated -# output files in an output format independent way. To create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. -# You can optionally specify a file name after the option, if omitted -# DoxygenLayout.xml will be used as the name of the layout file. - -LAYOUT_FILE = DoxygenLayout.xml - -# The CITE_BIB_FILES tag can be used to specify one or more bib files -# containing the references data. This must be a list of .bib files. The -# .bib extension is automatically appended if omitted. Using this command -# requires the bibtex tool to be installed. See also -# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style -# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this -# feature you need bibtex and perl available in the search path. - -CITE_BIB_FILES = - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = YES - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = NO - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. - -WARN_IF_DOC_ERROR = YES - -# The WARN_NO_PARAMDOC option can be enabled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. - -WARN_NO_PARAMDOC = NO - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = ../lib \ - ../src/lib \ - ../include/netlink \ - ../src \ - ../doc/src - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh -# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py -# *.f90 *.f *.for *.vhd *.vhdl - -FILE_PATTERNS = *.c \ - *.h - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should be -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. -# Note that relative paths are relative to the directory from which doxygen is -# run. - -EXCLUDE = SCCS - -# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or -# directories that are symbolic links (a Unix file system feature) are excluded -# from the input. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* - -EXCLUDE_PATTERNS = - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = ../src - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. -# If FILTER_PATTERNS is specified, this tag will be -# ignored. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. -# Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. -# The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty or if -# non of the patterns match the file name, INPUT_FILTER is applied. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). - -FILTER_SOURCE_FILES = NO - -# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file -# pattern. A pattern will override the setting for FILTER_PATTERN (if any) -# and it is also possible to disable source filtering for a specific pattern -# using *.ext= (so without naming a filter). This option only has effect when -# FILTER_SOURCE_FILES is enabled. - -FILTER_SOURCE_PATTERNS = - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. - -SOURCE_BROWSER = YES - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C, C++ and Fortran comments will always remain visible. - -STRIP_CODE_COMMENTS = NO - -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = YES - -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = YES - -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. -# Otherwise they will link to the documentation. - -REFERENCES_LINK_SOURCE = YES - -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = YES - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = nl_ - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = api - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. Note that when using a custom header you are responsible -# for the proper inclusion of any scripts and style sheets that doxygen -# needs, which is dependent on the configuration options used. -# It is advised to generate a default header using "doxygen -w html -# header.html footer.html stylesheet.css YourConfigFile" and then modify -# that header. Note that the header is subject to change so you typically -# have to redo this when upgrading to a newer version of doxygen or when -# changing the value of configuration settings such as GENERATE_TREEVIEW! - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# style sheet in the HTML output directory as well, or it will be erased! - -HTML_STYLESHEET = ./libnl.css - -# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or -# other source files which should be copied to the HTML output directory. Note -# that these files will be copied to the base HTML output directory. Use the -# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these -# files. In the HTML_STYLESHEET file, use the file name only. Also note that -# the files will be copied as-is; there are no commands or markers available. - -HTML_EXTRA_FILES = - -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. -# Doxygen will adjust the colors in the style sheet and background images -# according to this color. Hue is specified as an angle on a colorwheel, -# see http://en.wikipedia.org/wiki/Hue for more information. -# For instance the value 0 represents red, 60 is yellow, 120 is green, -# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. -# The allowed range is 0 to 359. - -HTML_COLORSTYLE_HUE = 220 - -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of -# the colors in the HTML output. For a value of 0 the output will use -# grayscales only. A value of 255 will produce the most vivid colors. - -HTML_COLORSTYLE_SAT = 100 - -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to -# the luminance component of the colors in the HTML output. Values below -# 100 gradually make the output lighter, whereas values above 100 make -# the output darker. The value divided by 100 is the actual gamma applied, -# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, -# and 100 does not change the gamma. - -HTML_COLORSTYLE_GAMMA = 80 - -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting -# this to NO can help when comparing the output of multiple runs. - -HTML_TIMESTAMP = YES - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. - -HTML_DYNAMIC_SECTIONS = YES - -# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of -# entries shown in the various tree structured indices initially; the user -# can expand and collapse entries dynamically later on. Doxygen will expand -# the tree to such a level that at most the specified number of entries are -# visible (unless a fully collapsed tree already exceeds this amount). -# So setting the number of entries 1 will produce a full collapsed tree by -# default. 0 is a special value representing an infinite number of entries -# and will result in a full expanded tree by default. - -HTML_INDEX_NUM_ENTRIES = 100 - -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html -# for more information. - -GENERATE_DOCSET = NO - -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify -# the documentation publisher. This should be a reverse domain-name style -# string, e.g. com.mycompany.MyDocSet.documentation. - -DOCSET_PUBLISHER_ID = org.doxygen.Publisher - -# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. - -DOCSET_PUBLISHER_NAME = Publisher - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be -# written to the html output directory. - -CHM_FILE = - -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. - -HHC_LOCATION = - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. - -CHM_INDEX_ENCODING = - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated -# that can be used as input for Qt's qhelpgenerator to generate a -# Qt Compressed Help (.qch) of the generated HTML documentation. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. -# The path specified is relative to the HTML output folder. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#namespace - -QHP_NAMESPACE = org.doxygen.Project - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#virtual-folders - -QHP_VIRTUAL_FOLDER = doc - -# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to -# add. For more information please see -# http://doc.trolltech.com/qthelpproject.html#custom-filters - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see -# -# Qt Help Project / Custom Filters. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's -# filter section matches. -# -# Qt Help Project / Filter Attributes. - -QHP_SECT_FILTER_ATTRS = - -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated -# .qhp file. - -QHG_LOCATION = - -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files -# will be generated, which together with the HTML files, form an Eclipse help -# plugin. To install this plugin and make it available under the help contents -# menu in Eclipse, the contents of the directory containing the HTML and XML -# files needs to be copied into the plugins directory of eclipse. The name of -# the directory within the plugins directory should be the same as -# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before -# the help appears. - -GENERATE_ECLIPSEHELP = NO - -# A unique identifier for the eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have -# this name. - -ECLIPSE_DOC_ID = org.infradead.libnl - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) -# at top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. Since the tabs have the same information as the -# navigation tree you can set this option to NO if you already set -# GENERATE_TREEVIEW to YES. - -DISABLE_INDEX = NO - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to YES, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). -# Windows users are probably better off using the HTML help feature. -# Since the tree basically has the same information as the tab index you -# could consider to set DISABLE_INDEX to NO when enabling this option. - -GENERATE_TREEVIEW = YES - -# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values -# (range [0,1..20]) that doxygen will group on one line in the generated HTML -# documentation. Note that a value of 0 will completely suppress the enum -# values from appearing in the overview section. - -ENUM_VALUES_PER_LINE = 1 - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 205 - -# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open -# links to external symbols imported via tag files in a separate window. - -EXT_LINKS_IN_WINDOW = NO - -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. - -FORMULA_FONTSIZE = 10 - -# Use the FORMULA_TRANPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are -# not supported properly for IE 6.0, but are supported on all modern browsers. -# Note that when changing this option you need to delete any form_*.png files -# in the HTML output before the changes have effect. - -FORMULA_TRANSPARENT = YES - -# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax -# (see http://www.mathjax.org) which uses client side Javascript for the -# rendering instead of using prerendered bitmaps. Use this if you do not -# have LaTeX installed or if you want to formulas look prettier in the HTML -# output. When enabled you may also need to install MathJax separately and -# configure the path to it using the MATHJAX_RELPATH option. - -USE_MATHJAX = NO - -# When MathJax is enabled you need to specify the location relative to the -# HTML output directory using the MATHJAX_RELPATH option. The destination -# directory should contain the MathJax.js script. For instance, if the mathjax -# directory is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to -# the MathJax Content Delivery Network so you can quickly see the result without -# installing MathJax. -# However, it is strongly recommended to install a local -# copy of MathJax from http://www.mathjax.org before deployment. - -MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest - -# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension -# names that should be enabled during MathJax rendering. - -MATHJAX_EXTENSIONS = - -# When the SEARCHENGINE tag is enabled doxygen will generate a search box -# for the HTML output. The underlying search engine uses javascript -# and DHTML and should work on any modern browser. Note that when using -# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets -# (GENERATE_DOCSET) there is already a search function so this one should -# typically be disabled. For large projects the javascript based search engine -# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. - -SEARCHENGINE = NO - -# When the SERVER_BASED_SEARCH tag is enabled the search engine will be -# implemented using a PHP enabled web server instead of at the web client -# using Javascript. Doxygen will generate the search PHP script and index -# file to put on the web server. The advantage of the server -# based approach is that it scales better to large projects and allows -# full text search. The disadvantages are that it is more difficult to setup -# and does not have live searching capabilities. - -SERVER_BASED_SEARCH = NO - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = NO - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. -# Note that when enabling USE_PDFLATEX this option is only used for -# generating bitmaps for formulas in the HTML output, but not in the -# Makefile that is written to the output directory. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = a4wide - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for -# the generated latex document. The footer should contain everything after -# the last chapter. If it is left blank doxygen will generate a -# standard footer. Notice: only use this tag if you know what you are doing! - -LATEX_FOOTER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = NO - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = NO - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. - -LATEX_HIDE_INDICES = NO - -# If LATEX_SOURCE_CODE is set to YES then doxygen will include -# source code with syntax highlighting in the LaTeX output. -# Note that which sources are shown also depends on other settings -# such as SOURCE_BROWSER. - -LATEX_SOURCE_CODE = NO - -# The LATEX_BIB_STYLE tag can be used to specify the style to use for the -# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See -# http://en.wikipedia.org/wiki/BibTeX for more info. - -LATEX_BIB_STYLE = plain - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load style sheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. - -GENERATE_XML = NO - -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `xml' will be used as the default path. - -XML_OUTPUT = xml - -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_DTD = - -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that -# enabling this will significantly increase the size of the XML output. - -XML_PROGRAMLISTING = YES - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. -# This is useful -# if you want to understand what is going on. -# On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = NO - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_DEFINED tags. - -EXPAND_ONLY_PREDEF = NO - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# pointed to by INCLUDE_PATH will be searched when a #include is found. - -SEARCH_INCLUDES = NO - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. To prevent a macro definition from being -# undefined via #undef or recursively expanded use the := operator -# instead of the = operator. - -PREDEFINED = - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition that -# overrules the definition found in the source code. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all references to function-like macros -# that are alone on a line, have an all uppercase name, and do not end with a -# semicolon, because these will confuse the parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES option can be used to specify one or more tagfiles. For each -# tag file the location of the external documentation should be added. The -# format of a tag file without this location is as follows: -# -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths -# or URLs. Note that each tag file must have a unique name (where the name does -# NOT include the path). If a tag file is not located in the directory in which -# doxygen is run, you must also specify the path to the tagfile here. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = YES - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = YES - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base -# or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option also works with HAVE_DOT disabled, but it is recommended to -# install and use dot, since it yields more powerful graphs. - -CLASS_DIAGRAMS = NO - -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see -# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the -# default search path. - -MSCGEN_PATH = - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = YES - -# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is -# allowed to run in parallel. When set to 0 (the default) doxygen will -# base this on the number of processors available in the system. You can set it -# explicitly to a value larger than 0 to get control over the balance -# between CPU load and processing speed. - -DOT_NUM_THREADS = 0 - -# By default doxygen will use the Helvetica font for all dot files that -# doxygen generates. When you want a differently looking font you can specify -# the font name using DOT_FONTNAME. You need to make sure dot is able to find -# the font, which can be done by putting it in a standard location or by setting -# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the -# directory containing the font. - -DOT_FONTNAME = FreeSans.ttf - -# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. -# The default size is 10pt. - -DOT_FONTSIZE = 10 - -# By default doxygen will tell dot to use the Helvetica font. -# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to -# set the path where dot can find it. - -DOT_FONTPATH = - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = NO - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = NO - -# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for groups, showing the direct groups dependencies - -GROUP_GRAPHS = NO - -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling -# Language. - -UML_LOOK = YES - -# If the UML_LOOK tag is enabled, the fields and methods are shown inside -# the class node. If there are many fields or methods and many nodes the -# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS -# threshold limits the number of items for each type to make the size more -# managable. Set this to 0 for no limit. Note that the threshold may be -# exceeded by 50% before the limit is enforced. - -UML_LIMIT_NUM_FIELDS = 10 - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = NO - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = NO - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = NO - -# If the CALL_GRAPH and HAVE_DOT options are set to YES then -# doxygen will generate a call dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable call graphs -# for selected functions only using the \callgraph command. - -CALL_GRAPH = YES - -# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then -# doxygen will generate a caller dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable caller -# graphs for selected functions only using the \callergraph command. - -CALLER_GRAPH = YES - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will generate a graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES -# then doxygen will show the dependencies a directory has on other directories -# in a graphical way. The dependency relations are determined by the #include -# relations between the files in the directories. - -DIRECTORY_GRAPH = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are svg, png, jpg, or gif. -# If left blank png will be used. If you choose svg you need to set -# HTML_FILE_EXTENSION to xhtml in order to make the SVG files -# visible in IE 9+ (other browsers do not have this requirement). - -DOT_IMAGE_FORMAT = png - -# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to -# enable generation of interactive SVG images that allow zooming and panning. -# Note that this requires a modern browser other than Internet Explorer. -# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you -# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files -# visible. Older versions of IE do not have SVG support. - -INTERACTIVE_SVG = NO - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found in the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# The MSCFILE_DIRS tag can be used to specify one or more directories that -# contain msc files that are included in the documentation (see the -# \mscfile command). - -MSCFILE_DIRS = - -# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of -# nodes that will be shown in the graph. If the number of nodes in a graph -# becomes larger than this value, doxygen will truncate the graph, which is -# visualized by representing a node as a red box. Note that doxygen if the -# number of direct children of the root node in a graph is already larger than -# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note -# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. - -DOT_GRAPH_MAX_NODES = 50 - -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes -# that lay further from the root node will be omitted. Note that setting this -# option to 1 or 2 may greatly reduce the computation time needed for large -# code bases. Also note that the size of a graph can be further restricted by -# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. - -MAX_DOT_GRAPH_DEPTH = 0 - -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not -# seem to support this out of the box. Warning: Depending on the platform used, -# enabling this option may lead to badly anti-aliased labels on the edges of -# a graph (i.e. they become hard to read). - -DOT_TRANSPARENT = NO - -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output -# files in one run (i.e. multiple -o and -T options on the command line). This -# makes dot run faster, but since only newer versions of dot (>1.8.10) -# support this, this feature is disabled by default. - -DOT_MULTI_TARGETS = NO - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES From 49c94c3490fe2691293a8d45b3dab574ee73ca31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA?= Date: Thu, 30 Aug 2012 22:53:19 +0600 Subject: [PATCH 241/432] genl_ctrl_probe_by_name: fix checking of genlmsg_put() return value It's a pointer! not an error code :) nasty bugs --- lib/genl/ctrl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/genl/ctrl.c b/lib/genl/ctrl.c index 5950394..057a1bf 100644 --- a/lib/genl/ctrl.c +++ b/lib/genl/ctrl.c @@ -255,8 +255,8 @@ static struct genl_family *genl_ctrl_probe_by_name(struct nl_sock *sk, if (!(cb = nl_cb_clone(nl_socket_get_cb(sk)))) goto out_msg_free; - if (genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, GENL_ID_CTRL, - 0, 0, CTRL_CMD_GETFAMILY, 1) < 0) { + if (!genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, GENL_ID_CTRL, + 0, 0, CTRL_CMD_GETFAMILY, 1)) { BUG(); goto out_cb_free; } From 49be8cd2b3372882252af0c9aa9be8d9131bd972 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 31 Aug 2012 16:23:07 +0200 Subject: [PATCH 242/432] doc: Update Doxyfile.in to latest syntax --- doc/Doxyfile.in | 370 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 263 insertions(+), 107 deletions(-) diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index d515db2..7c3bd39 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -1,14 +1,14 @@ -# Doxyfile 1.7.1 +# Doxyfile 1.8.1.1 # This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project +# doxygen (www.doxygen.org) for a project. # -# All text after a hash (#) is considered a comment and will be ignored +# All text after a hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") +# Values that contain spaces should be placed between quotes (" "). #--------------------------------------------------------------------------- # Project related configuration options @@ -22,8 +22,9 @@ DOXYFILE_ENCODING = UTF-8 -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. PROJECT_NAME = libnl @@ -33,6 +34,19 @@ PROJECT_NAME = libnl PROJECT_NUMBER = @PACKAGE_VERSION@ +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location @@ -57,7 +71,7 @@ CREATE_SUBDIRS = NO # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, -# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English @@ -126,7 +140,7 @@ STRIP_FROM_PATH = STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems +# (but less readable) file names. This can be useful if your file system # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO @@ -179,13 +193,19 @@ TAB_SIZE = 8 # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. -ALIASES = arg=\param +ALIASES = arg=\param \ + "ref_asciidoc{3}=\3" \ + "ref_core{2}=\ref_asciidoc{core,\1,\2 (Netlink Core Library Development Guide)}" \ + "ref_route{2}=\ref_asciidoc{route,\1,\2 (Netlink Routing Development Guide)}" \ + "core_doc{2}=\ref_core{\1,\2}" \ + "route_doc{2}=\ref_route{\1,\2}" -ALIASES += ref_asciidoc{3}="\3" -ALIASES += ref_core{2}="\ref_asciidoc{core,\1,\2 (Netlink Core Library Development Guide)}" -ALIASES += ref_route{2}="\ref_asciidoc{route,\1,\2 (Netlink Routing Development Guide)}" -ALIASES += core_doc{2}="\ref_core{\1,\2}" -ALIASES += route_doc{2}="\ref_route{\1,\2}" +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding +# "class=itcl::class" will allow you to use the command class in the +# itcl::class meaning. + +TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. @@ -225,11 +245,20 @@ OPTIMIZE_OUTPUT_VHDL = NO EXTENSION_MAPPING = +# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all +# comments according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you +# can mix doxygen, HTML, and XML commands with Markdown formatting. +# Disable only in case of backward compatibilities issues. + +MARKDOWN_SUPPORT = YES + # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also make the inheritance and collaboration +# func(std::string) {}). This also makes the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO @@ -247,7 +276,7 @@ SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) -# will make doxygen to replace the get and set methods by a property in the +# will make doxygen replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. @@ -269,6 +298,22 @@ DISTRIBUTE_GROUP_DOC = NO SUBGROUPING = YES +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields will be shown inline in the documentation +# of the scope in which they are defined (i.e. file, namespace, or group +# documentation), provided this scope is documented. If set to NO (the default), +# structs, classes, and unions are shown on a separate page (for HTML and Man +# pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS = NO + # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct @@ -285,16 +330,27 @@ TYPEDEF_HIDES_STRUCT = NO # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penality. +# causing a significant performance penalty. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will rougly double the +# a logarithmic scale so increasing the size by one will roughly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols +# corresponding to a cache size of 2^16 = 65536 symbols. SYMBOL_CACHE_SIZE = 0 +# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be +# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given +# their name and scope. Since this can be an expensive process and often the +# same symbol appear multiple times in the code, doxygen keeps a cache of +# pre-resolved symbols. If the cache is too small doxygen will become slower. +# If the cache is too large, memory is wasted. The cache size is given by this +# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +LOOKUP_CACHE_SIZE = 0 + #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- @@ -311,6 +367,10 @@ EXTRACT_ALL = NO EXTRACT_PRIVATE = YES +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal scope will be included in the documentation. + +EXTRACT_PACKAGE = NO + # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. @@ -333,7 +393,7 @@ EXTRACT_LOCAL_METHODS = YES # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default -# anonymous namespace are hidden. +# anonymous namespaces are hidden. EXTRACT_ANON_NSPACES = NO @@ -444,6 +504,15 @@ SORT_GROUP_NAMES = YES SORT_BY_SCOPE_NAME = NO +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. @@ -474,10 +543,10 @@ GENERATE_DEPRECATEDLIST= YES ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in +# the initial value of a variable or macro consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the +# The appearance of the initializer of individual variables and macros in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. @@ -489,12 +558,6 @@ MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = NO -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is NO. - -SHOW_DIRECTORIES = NO - # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. @@ -520,13 +583,23 @@ FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated -# output files in an output format independent way. The create the layout file +# output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. LAYOUT_FILE = DoxygenLayout.xml +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this +# feature you need bibtex and perl available in the search path. + +CITE_BIB_FILES = + #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- @@ -555,7 +628,7 @@ WARN_IF_UNDOCUMENTED = NO WARN_IF_DOC_ERROR = YES -# This WARN_NO_PARAMDOC option can be abled to get warnings for +# The WARN_NO_PARAMDOC option can be enabled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of @@ -605,8 +678,9 @@ INPUT_ENCODING = UTF-8 # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx -# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl FILE_PATTERNS = *.c \ *.h @@ -617,14 +691,16 @@ FILE_PATTERNS = *.c \ RECURSIVE = YES -# The EXCLUDE tag can be used to specify files and/or directories that should +# The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to the directory from which doxygen is +# run. EXCLUDE = SCCS -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix filesystem feature) are excluded +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO @@ -669,7 +745,7 @@ EXAMPLE_RECURSIVE = NO # directories that contain image that are included in the documentation (see # the \image command). -IMAGE_PATH = +IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program @@ -688,8 +764,8 @@ INPUT_FILTER = # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER -# is applied to all files. +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = @@ -699,6 +775,14 @@ FILTER_PATTERNS = FILTER_SOURCE_FILES = NO +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- @@ -717,7 +801,7 @@ INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. +# fragments. Normal C, C++ and Fortran comments will always remain visible. STRIP_CODE_COMMENTS = NO @@ -801,7 +885,14 @@ HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a -# standard header. +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is advised to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! HTML_HEADER = @@ -811,22 +902,26 @@ HTML_HEADER = HTML_FOOTER = -# If the HTML_TIMESTAMP tag is set to YES then the generated HTML -# documentation will contain the timesstamp. - -HTML_TIMESTAMP = NO - # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! +# style sheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = @srcdir@/libnl.css +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. -# Doxygen will adjust the colors in the stylesheet and background images +# Doxygen will adjust the colors in the style sheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see http://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, @@ -856,20 +951,23 @@ HTML_COLORSTYLE_GAMMA = 80 HTML_TIMESTAMP = YES -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). +# page has loaded. HTML_DYNAMIC_SECTIONS = YES +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of +# entries shown in the various tree structured indices initially; the user +# can expand and collapse entries dynamically later on. Doxygen will expand +# the tree to such a level that at most the specified number of entries are +# visible (unless a fully collapsed tree already exceeds this amount). +# So setting the number of entries 1 will produce a full collapsed tree by +# default. 0 is a special value representing an infinite number of entries +# and will result in a full expanded tree by default. + +HTML_INDEX_NUM_ENTRIES = 100 + # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). @@ -1021,17 +1119,14 @@ GENERATE_ECLIPSEHELP = NO ECLIPSE_DOC_ID = org.infradead.libnl -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. +# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) +# at top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. Since the tabs have the same information as the +# navigation tree you can set this option to NO if you already set +# GENERATE_TREEVIEW to YES. DISABLE_INDEX = NO -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 1 - # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated @@ -1039,13 +1134,17 @@ ENUM_VALUES_PER_LINE = 1 # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. +# Since the tree basically has the same information as the tab index you +# could consider to set DISABLE_INDEX to NO when enabling this option. GENERATE_TREEVIEW = YES -# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, -# and Class Hierarchy pages using a tree view instead of an ordered list. +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. -USE_INLINE_TREES = YES +ENUM_VALUES_PER_LINE = 1 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree @@ -1074,6 +1173,32 @@ FORMULA_FONTSIZE = 10 FORMULA_TRANSPARENT = YES +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you may also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to +# the MathJax Content Delivery Network so you can quickly see the result without +# installing MathJax. +# However, it is strongly recommended to install a local +# copy of MathJax from http://www.mathjax.org before deployment. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS = + # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using @@ -1089,7 +1214,7 @@ SEARCHENGINE = NO # using Javascript. Doxygen will generate the search PHP script and index # file to put on the web server. The advantage of the server # based approach is that it scales better to large projects and allows -# full text search. The disadvances is that it is more difficult to setup +# full text search. The disadvantages are that it is more difficult to setup # and does not have live searching capabilities. SERVER_BASED_SEARCH = NO @@ -1130,7 +1255,7 @@ MAKEINDEX_CMD_NAME = makeindex COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and +# by the printer. Possible values are: a4, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide @@ -1147,6 +1272,13 @@ EXTRA_PACKAGES = LATEX_HEADER = +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references @@ -1180,6 +1312,12 @@ LATEX_HIDE_INDICES = NO LATEX_SOURCE_CODE = NO +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE = plain + #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- @@ -1211,7 +1349,7 @@ COMPACT_RTF = NO RTF_HYPERLINKS = NO -# Load stylesheet definitions from file. Syntax is similar to doxygen's +# Load style sheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. @@ -1356,7 +1494,7 @@ MACRO_EXPANSION = NO EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. +# pointed to by INCLUDE_PATH will be searched when a #include is found. SEARCH_INCLUDES = NO @@ -1386,15 +1524,15 @@ PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse -# the parser if not removed. +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. SKIP_FUNCTION_MACROS = YES @@ -1402,22 +1540,18 @@ SKIP_FUNCTION_MACROS = YES # Configuration::additions related to external references #--------------------------------------------------------------------------- -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: +# The TAGFILES option can be used to specify one or more tagfiles. For each +# tag file the location of the external documentation should be added. The +# format of a tag file without this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool -# does not have to be run to correct the links. -# Note that each tag file must have a unique name -# (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen -# is run, you must also specify the path to the tagfile here. +# where "loc1" and "loc2" can be relative or absolute paths +# or URLs. Note that each tag file must have a unique name (where the name does +# NOT include the path). If a tag file is not located in the directory in which +# doxygen is run, you must also specify the path to the tagfile here. TAGFILES = @@ -1450,9 +1584,8 @@ PERL_PATH = /usr/bin/perl # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option is superseded by the HAVE_DOT option below. This is only a -# fallback. It is recommended to install and use dot, since it yields more -# powerful graphs. +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = NO @@ -1486,14 +1619,12 @@ HAVE_DOT = YES DOT_NUM_THREADS = 0 -# By default doxygen will write a font called FreeSans.ttf to the output -# directory and reference it in all dot files that doxygen generates. This -# font does not include all possible unicode characters however, so when you need -# these (or just want a differently looking font) you can specify the font name -# using DOT_FONTNAME. You need need to make sure dot is able to find the font, -# which can be done by putting it in a standard location or by setting the -# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory -# containing the font. +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. DOT_FONTNAME = FreeSans.ttf @@ -1502,17 +1633,16 @@ DOT_FONTNAME = FreeSans.ttf DOT_FONTSIZE = 10 -# By default doxygen will tell dot to use the output directory to look for the -# FreeSans.ttf font (which doxygen will put there itself). If you specify a -# different font using DOT_FONTNAME you can set the path where dot -# can find it using this tag. +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. +# CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = NO @@ -1534,6 +1664,15 @@ GROUP_GRAPHS = NO UML_LOOK = YES +# If the UML_LOOK tag is enabled, the fields and methods are shown inside +# the class node. If there are many fields or methods and many nodes the +# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS +# threshold limits the number of items for each type to make the size more +# managable. Set this to 0 for no limit. Note that the threshold may be +# exceeded by 50% before the limit is enforced. + +UML_LIMIT_NUM_FIELDS = 10 + # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. @@ -1570,11 +1709,11 @@ CALL_GRAPH = YES CALLER_GRAPH = YES # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. +# will generate a graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES -# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. @@ -1582,11 +1721,22 @@ GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, jpg, or gif -# If left blank png will be used. +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). DOT_IMAGE_FORMAT = png +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. + +INTERACTIVE_SVG = NO + # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. @@ -1598,6 +1748,12 @@ DOT_PATH = DOTFILE_DIRS = +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is From fddba713a82b2d16da2b67cf609795a2ce89b71c Mon Sep 17 00:00:00 2001 From: Jeroen Roovers Date: Sun, 2 Sep 2012 15:34:53 +0200 Subject: [PATCH 243/432] libnl-3.2.12 - ./configure --disable-doc: error: conditional "LINK_DOC" was never defined. \ Usually this means the macro was only invoked conditionally. configure: error: conditional "LINK_DOC" was never defined. Usually this means the macro was only invoked conditionally. Attached patch provided by Martin Jansa. See also https://bugs.gentoo.org/show_bug.cgi?id=433565 --- configure.in | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.in b/configure.in index 5016842..7fb3da0 100644 --- a/configure.in +++ b/configure.in @@ -147,12 +147,12 @@ if test "x$generate_doc" != "xno"; then AC_MSG_WARN([*** Disabling API linking due to missing doxygen package]) link_doc=no fi - - AM_CONDITIONAL([LINK_DOC], [test "x$link_doc" = "xyes"]) - AM_CONDITIONAL([HAVE_DOXYGEN], [test "x$HAVE_DOXYGEN" = "xyes"]) - AM_CONDITIONAL([HAVE_ASCIIDOC], [test "x$HAVE_ASCIIDOC" = "xyes"]) fi +AM_CONDITIONAL([LINK_DOC], [test "x$link_doc" = "xyes"]) +AM_CONDITIONAL([HAVE_DOXYGEN], [test "x$HAVE_DOXYGEN" = "xyes"]) +AM_CONDITIONAL([HAVE_ASCIIDOC], [test "x$HAVE_ASCIIDOC" = "xyes"]) + AM_CONDITIONAL([GENERATE_DOC], [test "x$generate_doc" != "xno"]) AC_ARG_WITH([pkgconfigdir], AS_HELP_STRING([--with-pkgconfigdir=PATH], From ce72837c90a6adf750bee9e2cb2cb30e65ee3fb1 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Mon, 3 Sep 2012 13:41:11 +0200 Subject: [PATCH 244/432] 3.2.13 release --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 7fb3da0..28d1754 100644 --- a/configure.in +++ b/configure.in @@ -13,7 +13,7 @@ # copied from glib m4_define([libnl_major_version], [3]) m4_define([libnl_minor_version], [2]) -m4_define([libnl_micro_version], [12]) +m4_define([libnl_micro_version], [13]) # If either revision or age are omitted, they default to 0. Also note that age @@ -35,7 +35,7 @@ m4_define([libnl_micro_version], [12]) # set age to 0. m4_define([libnl_lt_current], [210]) -m4_define([libnl_lt_revision], [0]) +m4_define([libnl_lt_revision], [1]) m4_define([libnl_lt_age], [10]) m4_define([libnl_version], From 72c2cb9e299b0510ae76e90b0b4fcc040ab485c7 Mon Sep 17 00:00:00 2001 From: "Antoni S. Puimedon" Date: Thu, 4 Oct 2012 16:36:55 -0400 Subject: [PATCH 245/432] Enabled the use of Links as context managers. With this change you can still set do modifications of Links and then to change to pass the changes to the kernel. But it additionally enables you to interact with this part of libnl-python in a more pythonic way. Instead of: eth0 = links['eth0'] eth0.mtu = 5000 eth0.change() you can do: with links['eth0'] as eth0: eth0.mtu = 5000 --- python/netlink/route/link.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/python/netlink/route/link.py b/python/netlink/route/link.py index ab28f37..36d0e9d 100644 --- a/python/netlink/route/link.py +++ b/python/netlink/route/link.py @@ -152,6 +152,15 @@ class Link(netlink.Object): self.inet = inet.InetLink(self) self.af = {'inet' : self.inet } + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, tb): + if exc_type is None: + self.change() + else: + return false + @classmethod def from_capi(cls, obj): return cls(capi.link2obj(obj)) From 40457db1f458795de4529973a1bd8386e948cfe3 Mon Sep 17 00:00:00 2001 From: Rich Fought Date: Fri, 5 Oct 2012 06:55:04 -0700 Subject: [PATCH 246/432] Exp checkpoint --- include/netlink-types.h | 22 + include/netlink/netfilter/exp.h | 145 +++++++ lib/netfilter/ct_obj.c | 4 +- lib/netfilter/exp.c | 601 +++++++++++++++++++++++++++ lib/netfilter/exp_obj.c | 698 ++++++++++++++++++++++++++++++++ 5 files changed, 1468 insertions(+), 2 deletions(-) create mode 100644 include/netlink/netfilter/exp.h create mode 100644 lib/netfilter/exp.c create mode 100644 lib/netfilter/exp_obj.c diff --git a/include/netlink-types.h b/include/netlink-types.h index 2e80b05..aeba518 100644 --- a/include/netlink-types.h +++ b/include/netlink-types.h @@ -779,6 +779,28 @@ struct nfnl_ct { struct nfnl_ct_dir ct_repl; }; +struct nfnl_exp { + NLHDR_COMMON + + uint8_t exp_family; // IPv4, IPv6, etc - required + uint8_t exp_proto; // tcp, udp, etc - required + union nfnl_ct_protoinfo exp_protoinfo; // ??? Assured, etc? + + uint32_t exp_timeout; // required afaik + uint32_t exp_id; // optional + uint16_t exp_zone; // optional + uint32_t exp_class; // optional + uint32_t exp_flags; // optional + char * exp_helper_name; //optional + char * exp_fn; //optional + uint8_t exp_nat_dir; // optional + + struct nfnl_ct_dir exp_expect; // required + struct nfnl_ct_dir exp_master; // required + struct nfnl_ct_dir exp_mask; // required + struct nfnl_ct_dir exp_nat; // optional +}; + struct nfnl_log { NLHDR_COMMON diff --git a/include/netlink/netfilter/exp.h b/include/netlink/netfilter/exp.h new file mode 100644 index 0000000..36a28e5 --- /dev/null +++ b/include/netlink/netfilter/exp.h @@ -0,0 +1,145 @@ +/* + * netlink/netfilter/exp.h Conntrack Expectation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2007 Philip Craig + * Copyright (c) 2007 Secure Computing Corporation + */ + +#ifndef NETLINK_EXP_H_ +#define NETLINK_EXP_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct nfnl_exp; + +enum nfnl_exp_tuples { + NFNL_EXP_EXPECT, + NFNL_EXP_MASTER, + NFNL_EXP_MASK, + NFNL_EXP_NAT +}; + +extern struct nl_object_ops exp_obj_ops; + +extern struct nfnl_exp * nfnl_exp_alloc(void); +extern int nfnl_exp_alloc_cache(struct nl_sock *, struct nl_cache **); + +extern int nfnlmsg_exp_group(struct nlmsghdr *); +extern int nfnlmsg_exp_parse(struct nlmsghdr *, struct nfnl_exp **); + +extern void nfnl_exp_get(struct nfnl_exp *); +extern void nfnl_exp_put(struct nfnl_exp *); + +extern int nfnl_exp_dump_request(struct nl_sock *); + +extern int nfnl_exp_build_add_request(const struct nfnl_exp *, int, + struct nl_msg **); +extern int nfnl_exp_add(struct nl_sock *, const struct nfnl_exp *, int); + +extern int nfnl_exp_build_delete_request(const struct nfnl_exp *, int, + struct nl_msg **); +extern int nfnl_exp_del(struct nl_sock *, const struct nfnl_exp *, int); + +extern int nfnl_exp_build_query_request(const struct nfnl_exp *, int, + struct nl_msg **); +extern int nfnl_exp_query(struct nl_sock *, const struct nfnl_exp *, int); + +extern void nfnl_exp_set_family(struct nfnl_exp *, uint8_t); +extern uint8_t nfnl_exp_get_family(const struct nfnl_exp *); + +extern void nfnl_exp_set_proto(struct nfnl_exp *, uint8_t); +extern int nfnl_exp_test_proto(const struct nfnl_exp *); +extern uint8_t nfnl_exp_get_proto(const struct nfnl_exp *); + +extern void nfnl_exp_set_timeout(struct nfnl_exp *, uint32_t); +extern int nfnl_exp_test_timeout(const struct nfnl_exp *); +extern uint32_t nfnl_exp_get_timeout(const struct nfnl_exp *); + +extern void nfnl_exp_set_id(struct nfnl_exp *, uint32_t); +extern int nfnl_exp_test_id(const struct nfnl_exp *); +extern uint32_t nfnl_exp_get_id(const struct nfnl_exp *); + +extern int nfnl_exp_set_helper_name(struct nfnl_exp *, void *); +extern int nfnl_exp_test_helper_name(const struct nfnl_exp *); +extern const char * nfnl_exp_get_helper_name(const struct nfnl_exp *); + +extern void nfnl_exp_set_zone(struct nfnl_exp *, uint16_t); +extern int nfnl_exp_test_zone(const struct nfnl_exp *); +extern uint16_t nfnl_exp_get_zone(const struct nfnl_exp *); + +extern void nfnl_exp_set_class(struct nfnl_exp *, uint32_t); +extern int nfnl_exp_test_class(const struct nfnl_exp *); +extern uint32_t nfnl_exp_get_class(const struct nfnl_exp *); + +extern void nfnl_exp_set_flags(struct nfnl_exp *, uint32_t); +extern int nfnl_exp_test_flags(const struct nfnl_exp *); +extern uint32_t nfnl_exp_get_flags(const struct nfnl_exp *); + +extern int nfnl_exp_set_fn(struct nfnl_exp *, void *); +extern int nfnl_exp_test_fn(const struct nfnl_exp *); +extern const char * nfnl_exp_get_fn(const struct nfnl_exp *); + +extern void nfnl_exp_set_nat_dir(struct nfnl_exp *, int, uint8_t); +extern int nfnl_exp_test_nat_dir(const struct nfnl_exp *, int); +extern uint8_t nfnl_exp_get_nat_dir(const struct nfnl_exp *, int); + +// The int argument specifies which nfnl_ct_dir (expect, master, mask or nat) +// Expectation objects only use orig, not reply +extern int nfnl_exp_test_tuple(const struct nfnl_exp *, int); + +extern int nfnl_exp_set_src(struct nfnl_exp *, int, struct nl_addr *); +extern struct nl_addr * nfnl_ct_get_src(const struct nfnl_exp *, int); + +extern int nfnl_exp_set_dst(struct nfnl_exp *, int, struct nl_addr *); +extern struct nl_addr * nfnl_exp_get_dst(const struct nfnl_exp *, int); + +extern int nfnl_exp_set_l4proto(struct nfnl_exp *, int, uint8_t); +extern int nfnl_exp_test_l4proto(const struct nfnl_exp *); +extern struct uint8_t * nfnl_exp_get_l4proto(const struct nfnl_exp *, int); + +extern void nfnl_exp_set_src_port(struct nfnl_exp *, int, uint16_t); +extern uint16_t nfnl_exp_get_src_port(const struct nfnl_exp *, int); + +extern void nfnl_exp_set_dst_port(struct nfnl_exp *, int, uint16_t); +extern uint16_t nfnl_exp_get_dst_port(const struct nfnl_exp *, int); + +extern void nfnl_exp_set_icmp_id(struct nfnl_exp *, int, uint16_t); +extern uint16_t nfnl_exp_get_icmp_id(const struct nfnl_exp *, int); + +extern void nfnl_exp_set_icmp_type(struct nfnl_exp *, int, uint8_t); +extern uint8_t nfnl_exp_get_icmp_type(const struct nfnl_exp *, int); + +extern void nfnl_exp_set_icmp_code(struct nfnl_exp *, int, uint8_t); +extern uint8_t nfnl_exp_get_icmp_code(const struct nfnl_exp *, int); + +// TODO: Expectation table does support CPU stats get command, not sure if the same +/* +extern void nfnl_ct_set_packets(struct nfnl_ct *, int, uint64_t); +extern int nfnl_ct_test_packets(const struct nfnl_ct *, int); +extern uint64_t nfnl_ct_get_packets(const struct nfnl_ct *,int); + +extern void nfnl_ct_set_bytes(struct nfnl_ct *, int, uint64_t); +extern int nfnl_ct_test_bytes(const struct nfnl_ct *, int); +extern uint64_t nfnl_ct_get_bytes(const struct nfnl_ct *, int); +*/ + + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/netfilter/ct_obj.c b/lib/netfilter/ct_obj.c index d5cd18a..4686170 100644 --- a/lib/netfilter/ct_obj.c +++ b/lib/netfilter/ct_obj.c @@ -121,10 +121,10 @@ static void dump_icmp(struct nl_dump_params *p, struct nfnl_ct *ct, int reply) if (nfnl_ct_test_icmp_type(ct, reply)) nl_dump(p, "icmp type %d ", nfnl_ct_get_icmp_type(ct, reply)); - if (nfnl_ct_test_icmp_type(ct, reply)) + if (nfnl_ct_test_icmp_code(ct, reply)) nl_dump(p, "code %d ", nfnl_ct_get_icmp_code(ct, reply)); - if (nfnl_ct_test_icmp_type(ct, reply)) + if (nfnl_ct_test_icmp_id(ct, reply)) nl_dump(p, "id %d ", nfnl_ct_get_icmp_id(ct, reply)); } diff --git a/lib/netfilter/exp.c b/lib/netfilter/exp.c new file mode 100644 index 0000000..59ee1d9 --- /dev/null +++ b/lib/netfilter/exp.c @@ -0,0 +1,601 @@ +/* + * lib/netfilter/ct.c Conntrack + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2007 Philip Craig + * Copyright (c) 2007 Secure Computing Corporation + * Copyright (c= 2008 Patrick McHardy + */ + +/** + * @ingroup nfnl + * @defgroup ct Conntrack + * @brief + * @{ + */ + +#include +#include +#include + +#include +#include +#include +#include + +static struct nl_cache_ops nfnl_ct_ops; + +#if __BYTE_ORDER == __BIG_ENDIAN +static uint64_t ntohll(uint64_t x) +{ + return x; +} +#elif __BYTE_ORDER == __LITTLE_ENDIAN +static uint64_t ntohll(uint64_t x) +{ + return bswap_64(x); +} +#endif + +static struct nla_policy ct_policy[CTA_MAX+1] = { + [CTA_TUPLE_ORIG] = { .type = NLA_NESTED }, + [CTA_TUPLE_REPLY] = { .type = NLA_NESTED }, + [CTA_STATUS] = { .type = NLA_U32 }, + [CTA_PROTOINFO] = { .type = NLA_NESTED }, + //[CTA_HELP] + //[CTA_NAT_SRC] + [CTA_TIMEOUT] = { .type = NLA_U32 }, + [CTA_MARK] = { .type = NLA_U32 }, + [CTA_COUNTERS_ORIG] = { .type = NLA_NESTED }, + [CTA_COUNTERS_REPLY] = { .type = NLA_NESTED }, + [CTA_USE] = { .type = NLA_U32 }, + [CTA_ID] = { .type = NLA_U32 }, + //[CTA_NAT_DST] +}; + +static struct nla_policy ct_tuple_policy[CTA_TUPLE_MAX+1] = { + [CTA_TUPLE_IP] = { .type = NLA_NESTED }, + [CTA_TUPLE_PROTO] = { .type = NLA_NESTED }, +}; + +static struct nla_policy ct_ip_policy[CTA_IP_MAX+1] = { + [CTA_IP_V4_SRC] = { .type = NLA_U32 }, + [CTA_IP_V4_DST] = { .type = NLA_U32 }, + [CTA_IP_V6_SRC] = { .minlen = 16 }, + [CTA_IP_V6_DST] = { .minlen = 16 }, +}; + +static struct nla_policy ct_proto_policy[CTA_PROTO_MAX+1] = { + [CTA_PROTO_NUM] = { .type = NLA_U8 }, + [CTA_PROTO_SRC_PORT] = { .type = NLA_U16 }, + [CTA_PROTO_DST_PORT] = { .type = NLA_U16 }, + [CTA_PROTO_ICMP_ID] = { .type = NLA_U16 }, + [CTA_PROTO_ICMP_TYPE] = { .type = NLA_U8 }, + [CTA_PROTO_ICMP_CODE] = { .type = NLA_U8 }, + [CTA_PROTO_ICMPV6_ID] = { .type = NLA_U16 }, + [CTA_PROTO_ICMPV6_TYPE] = { .type = NLA_U8 }, + [CTA_PROTO_ICMPV6_CODE] = { .type = NLA_U8 }, +}; + +static struct nla_policy ct_protoinfo_policy[CTA_PROTOINFO_MAX+1] = { + [CTA_PROTOINFO_TCP] = { .type = NLA_NESTED }, +}; + +static struct nla_policy ct_protoinfo_tcp_policy[CTA_PROTOINFO_TCP_MAX+1] = { + [CTA_PROTOINFO_TCP_STATE] = { .type = NLA_U8 }, + [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = { .type = NLA_U8 }, + [CTA_PROTOINFO_TCP_WSCALE_REPLY] = { .type = NLA_U8 }, + [CTA_PROTOINFO_TCP_FLAGS_ORIGINAL] = { .minlen = 2 }, + [CTA_PROTOINFO_TCP_FLAGS_REPLY] = { .minlen = 2 }, + +}; + +static struct nla_policy ct_counters_policy[CTA_COUNTERS_MAX+1] = { + [CTA_COUNTERS_PACKETS] = { .type = NLA_U64 }, + [CTA_COUNTERS_BYTES] = { .type = NLA_U64 }, + [CTA_COUNTERS32_PACKETS]= { .type = NLA_U32 }, + [CTA_COUNTERS32_BYTES] = { .type = NLA_U32 }, +}; + +static int ct_parse_ip(struct nfnl_ct *ct, int repl, struct nlattr *attr) +{ + struct nlattr *tb[CTA_IP_MAX+1]; + struct nl_addr *addr; + int err; + + err = nla_parse_nested(tb, CTA_IP_MAX, attr, ct_ip_policy); + if (err < 0) + goto errout; + + if (tb[CTA_IP_V4_SRC]) { + addr = nl_addr_alloc_attr(tb[CTA_IP_V4_SRC], AF_INET); + if (addr == NULL) + goto errout_enomem; + err = nfnl_ct_set_src(ct, repl, addr); + nl_addr_put(addr); + if (err < 0) + goto errout; + } + if (tb[CTA_IP_V4_DST]) { + addr = nl_addr_alloc_attr(tb[CTA_IP_V4_DST], AF_INET); + if (addr == NULL) + goto errout_enomem; + err = nfnl_ct_set_dst(ct, repl, addr); + nl_addr_put(addr); + if (err < 0) + goto errout; + } + if (tb[CTA_IP_V6_SRC]) { + addr = nl_addr_alloc_attr(tb[CTA_IP_V6_SRC], AF_INET6); + if (addr == NULL) + goto errout_enomem; + err = nfnl_ct_set_src(ct, repl, addr); + nl_addr_put(addr); + if (err < 0) + goto errout; + } + if (tb[CTA_IP_V6_DST]) { + addr = nl_addr_alloc_attr(tb[CTA_IP_V6_DST], AF_INET6); + if (addr == NULL) + goto errout_enomem; + err = nfnl_ct_set_dst(ct, repl, addr); + nl_addr_put(addr); + if (err < 0) + goto errout; + } + + return 0; + +errout_enomem: + err = -NLE_NOMEM; +errout: + return err; +} + +static int ct_parse_proto(struct nfnl_ct *ct, int repl, struct nlattr *attr) +{ + struct nlattr *tb[CTA_PROTO_MAX+1]; + int err; + + err = nla_parse_nested(tb, CTA_PROTO_MAX, attr, ct_proto_policy); + if (err < 0) + return err; + + if (!repl && tb[CTA_PROTO_NUM]) + nfnl_ct_set_proto(ct, nla_get_u8(tb[CTA_PROTO_NUM])); + if (tb[CTA_PROTO_SRC_PORT]) + nfnl_ct_set_src_port(ct, repl, + ntohs(nla_get_u16(tb[CTA_PROTO_SRC_PORT]))); + if (tb[CTA_PROTO_DST_PORT]) + nfnl_ct_set_dst_port(ct, repl, + ntohs(nla_get_u16(tb[CTA_PROTO_DST_PORT]))); + if (tb[CTA_PROTO_ICMP_ID]) + nfnl_ct_set_icmp_id(ct, repl, + ntohs(nla_get_u16(tb[CTA_PROTO_ICMP_ID]))); + if (tb[CTA_PROTO_ICMP_TYPE]) + nfnl_ct_set_icmp_type(ct, repl, + nla_get_u8(tb[CTA_PROTO_ICMP_TYPE])); + if (tb[CTA_PROTO_ICMP_CODE]) + nfnl_ct_set_icmp_code(ct, repl, + nla_get_u8(tb[CTA_PROTO_ICMP_CODE])); + + return 0; +} + +static int ct_parse_tuple(struct nfnl_ct *ct, int repl, struct nlattr *attr) +{ + struct nlattr *tb[CTA_TUPLE_MAX+1]; + int err; + + err = nla_parse_nested(tb, CTA_TUPLE_MAX, attr, ct_tuple_policy); + if (err < 0) + return err; + + if (tb[CTA_TUPLE_IP]) { + err = ct_parse_ip(ct, repl, tb[CTA_TUPLE_IP]); + if (err < 0) + return err; + } + + if (tb[CTA_TUPLE_PROTO]) { + err = ct_parse_proto(ct, repl, tb[CTA_TUPLE_PROTO]); + if (err < 0) + return err; + } + + return 0; +} + +static int ct_parse_protoinfo_tcp(struct nfnl_ct *ct, struct nlattr *attr) +{ + struct nlattr *tb[CTA_PROTOINFO_TCP_MAX+1]; + int err; + + err = nla_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr, + ct_protoinfo_tcp_policy); + if (err < 0) + return err; + + if (tb[CTA_PROTOINFO_TCP_STATE]) + nfnl_ct_set_tcp_state(ct, + nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE])); + + return 0; +} + +static int ct_parse_protoinfo(struct nfnl_ct *ct, struct nlattr *attr) +{ + struct nlattr *tb[CTA_PROTOINFO_MAX+1]; + int err; + + err = nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr, + ct_protoinfo_policy); + if (err < 0) + return err; + + if (tb[CTA_PROTOINFO_TCP]) { + err = ct_parse_protoinfo_tcp(ct, tb[CTA_PROTOINFO_TCP]); + if (err < 0) + return err; + } + + return 0; +} + +static int ct_parse_counters(struct nfnl_ct *ct, int repl, struct nlattr *attr) +{ + struct nlattr *tb[CTA_COUNTERS_MAX+1]; + int err; + + err = nla_parse_nested(tb, CTA_COUNTERS_MAX, attr, ct_counters_policy); + if (err < 0) + return err; + + if (tb[CTA_COUNTERS_PACKETS]) + nfnl_ct_set_packets(ct, repl, + ntohll(nla_get_u64(tb[CTA_COUNTERS_PACKETS]))); + if (tb[CTA_COUNTERS32_PACKETS]) + nfnl_ct_set_packets(ct, repl, + ntohl(nla_get_u32(tb[CTA_COUNTERS32_PACKETS]))); + if (tb[CTA_COUNTERS_BYTES]) + nfnl_ct_set_bytes(ct, repl, + ntohll(nla_get_u64(tb[CTA_COUNTERS_BYTES]))); + if (tb[CTA_COUNTERS32_BYTES]) + nfnl_ct_set_bytes(ct, repl, + ntohl(nla_get_u32(tb[CTA_COUNTERS32_BYTES]))); + + return 0; +} + +int nfnlmsg_ct_group(struct nlmsghdr *nlh) +{ + switch (nfnlmsg_subtype(nlh)) { + case IPCTNL_MSG_CT_NEW: + if (nlh->nlmsg_flags & (NLM_F_CREATE|NLM_F_EXCL)) + return NFNLGRP_CONNTRACK_NEW; + else + return NFNLGRP_CONNTRACK_UPDATE; + case IPCTNL_MSG_CT_DELETE: + return NFNLGRP_CONNTRACK_DESTROY; + default: + return NFNLGRP_NONE; + } +} + +int nfnlmsg_ct_parse(struct nlmsghdr *nlh, struct nfnl_ct **result) +{ + struct nfnl_ct *ct; + struct nlattr *tb[CTA_MAX+1]; + int err; + + ct = nfnl_ct_alloc(); + if (!ct) + return -NLE_NOMEM; + + ct->ce_msgtype = nlh->nlmsg_type; + + err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, CTA_MAX, + ct_policy); + if (err < 0) + goto errout; + + nfnl_ct_set_family(ct, nfnlmsg_family(nlh)); + + if (tb[CTA_TUPLE_ORIG]) { + err = ct_parse_tuple(ct, 0, tb[CTA_TUPLE_ORIG]); + if (err < 0) + goto errout; + } + if (tb[CTA_TUPLE_REPLY]) { + err = ct_parse_tuple(ct, 1, tb[CTA_TUPLE_REPLY]); + if (err < 0) + goto errout; + } + + if (tb[CTA_PROTOINFO]) { + err = ct_parse_protoinfo(ct, tb[CTA_PROTOINFO]); + if (err < 0) + goto errout; + } + + if (tb[CTA_STATUS]) + nfnl_ct_set_status(ct, ntohl(nla_get_u32(tb[CTA_STATUS]))); + if (tb[CTA_TIMEOUT]) + nfnl_ct_set_timeout(ct, ntohl(nla_get_u32(tb[CTA_TIMEOUT]))); + if (tb[CTA_MARK]) + nfnl_ct_set_mark(ct, ntohl(nla_get_u32(tb[CTA_MARK]))); + if (tb[CTA_USE]) + nfnl_ct_set_use(ct, ntohl(nla_get_u32(tb[CTA_USE]))); + if (tb[CTA_ID]) + nfnl_ct_set_id(ct, ntohl(nla_get_u32(tb[CTA_ID]))); + + if (tb[CTA_COUNTERS_ORIG]) { + err = ct_parse_counters(ct, 0, tb[CTA_COUNTERS_ORIG]); + if (err < 0) + goto errout; + } + + if (tb[CTA_COUNTERS_REPLY]) { + err = ct_parse_counters(ct, 1, tb[CTA_COUNTERS_REPLY]); + if (err < 0) + goto errout; + } + + *result = ct; + return 0; + +errout: + nfnl_ct_put(ct); + return err; +} + +static int ct_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, + struct nlmsghdr *nlh, struct nl_parser_param *pp) +{ + struct nfnl_ct *ct; + int err; + + if ((err = nfnlmsg_ct_parse(nlh, &ct)) < 0) + goto errout; + + err = pp->pp_cb((struct nl_object *) ct, pp); +errout: + nfnl_ct_put(ct); + return err; +} + +int nfnl_ct_dump_request(struct nl_sock *sk) +{ + return nfnl_send_simple(sk, NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET, + NLM_F_DUMP, AF_UNSPEC, 0); +} + +static int ct_request_update(struct nl_cache *cache, struct nl_sock *sk) +{ + return nfnl_ct_dump_request(sk); +} + +static int nfnl_ct_build_tuple(struct nl_msg *msg, const struct nfnl_ct *ct, + int repl) +{ + struct nlattr *tuple, *ip, *proto; + struct nl_addr *addr; + int family; + + family = nfnl_ct_get_family(ct); + + tuple = nla_nest_start(msg, repl ? CTA_TUPLE_REPLY : CTA_TUPLE_ORIG); + if (!tuple) + goto nla_put_failure; + + ip = nla_nest_start(msg, CTA_TUPLE_IP); + if (!ip) + goto nla_put_failure; + + addr = nfnl_ct_get_src(ct, repl); + if (addr) + NLA_PUT_ADDR(msg, + family == AF_INET ? CTA_IP_V4_SRC : CTA_IP_V6_SRC, + addr); + + addr = nfnl_ct_get_dst(ct, repl); + if (addr) + NLA_PUT_ADDR(msg, + family == AF_INET ? CTA_IP_V4_DST : CTA_IP_V6_DST, + addr); + + nla_nest_end(msg, ip); + + proto = nla_nest_start(msg, CTA_TUPLE_PROTO); + if (!proto) + goto nla_put_failure; + + if (nfnl_ct_test_proto(ct)) + NLA_PUT_U8(msg, CTA_PROTO_NUM, nfnl_ct_get_proto(ct)); + + if (nfnl_ct_test_src_port(ct, repl)) + NLA_PUT_U16(msg, CTA_PROTO_SRC_PORT, + htons(nfnl_ct_get_src_port(ct, repl))); + + if (nfnl_ct_test_dst_port(ct, repl)) + NLA_PUT_U16(msg, CTA_PROTO_DST_PORT, + htons(nfnl_ct_get_dst_port(ct, repl))); + + if (nfnl_ct_test_icmp_id(ct, repl)) + NLA_PUT_U16(msg, CTA_PROTO_ICMP_ID, + htons(nfnl_ct_get_icmp_id(ct, repl))); + + if (nfnl_ct_test_icmp_type(ct, repl)) + NLA_PUT_U8(msg, CTA_PROTO_ICMP_TYPE, + nfnl_ct_get_icmp_type(ct, repl)); + + if (nfnl_ct_test_icmp_code(ct, repl)) + NLA_PUT_U8(msg, CTA_PROTO_ICMP_CODE, + nfnl_ct_get_icmp_code(ct, repl)); + + nla_nest_end(msg, proto); + + nla_nest_end(msg, tuple); + return 0; + +nla_put_failure: + return -NLE_MSGSIZE; +} + +static int nfnl_ct_build_message(const struct nfnl_ct *ct, int cmd, int flags, + struct nl_msg **result) +{ + struct nl_msg *msg; + int err; + + msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_CTNETLINK, cmd, flags, + nfnl_ct_get_family(ct), 0); + if (msg == NULL) + return -NLE_NOMEM; + + if ((err = nfnl_ct_build_tuple(msg, ct, 0)) < 0) + goto err_out; + + *result = msg; + return 0; + +err_out: + nlmsg_free(msg); + return err; +} + +int nfnl_ct_build_add_request(const struct nfnl_ct *ct, int flags, + struct nl_msg **result) +{ + return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_NEW, flags, result); +} + +int nfnl_ct_add(struct nl_sock *sk, const struct nfnl_ct *ct, int flags) +{ + struct nl_msg *msg; + int err; + + if ((err = nfnl_ct_build_add_request(ct, flags, &msg)) < 0) + return err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return wait_for_ack(sk); +} + +int nfnl_ct_build_delete_request(const struct nfnl_ct *ct, int flags, + struct nl_msg **result) +{ + return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_DELETE, flags, result); +} + +int nfnl_ct_del(struct nl_sock *sk, const struct nfnl_ct *ct, int flags) +{ + struct nl_msg *msg; + int err; + + if ((err = nfnl_ct_build_delete_request(ct, flags, &msg)) < 0) + return err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return wait_for_ack(sk); +} + +int nfnl_ct_build_query_request(const struct nfnl_ct *ct, int flags, + struct nl_msg **result) +{ + return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_GET, flags, result); +} + +int nfnl_ct_query(struct nl_sock *sk, const struct nfnl_ct *ct, int flags) +{ + struct nl_msg *msg; + int err; + + if ((err = nfnl_ct_build_query_request(ct, flags, &msg)) < 0) + return err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return wait_for_ack(sk); +} + +/** + * @name Cache Management + * @{ + */ + +/** + * Build a conntrack cache holding all conntrack currently in the kernel + * @arg sk Netlink socket. + * @arg result Pointer to store resulting cache. + * + * Allocates a new cache, initializes it properly and updates it to + * contain all conntracks currently in the kernel. + * + * @return 0 on success or a negative error code. + */ +int nfnl_ct_alloc_cache(struct nl_sock *sk, struct nl_cache **result) +{ + return nl_cache_alloc_and_fill(&nfnl_ct_ops, sk, result); +} + +/** @} */ + +/** + * @name Conntrack Addition + * @{ + */ + +/** @} */ + +static struct nl_af_group ct_groups[] = { + { AF_UNSPEC, NFNLGRP_CONNTRACK_NEW }, + { AF_UNSPEC, NFNLGRP_CONNTRACK_UPDATE }, + { AF_UNSPEC, NFNLGRP_CONNTRACK_DESTROY }, + { END_OF_GROUP_LIST }, +}; + +#define NFNLMSG_CT_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_CTNETLINK, (type)) +static struct nl_cache_ops nfnl_ct_ops = { + .co_name = "netfilter/ct", + .co_hdrsize = NFNL_HDRLEN, + .co_msgtypes = { + { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_NEW), NL_ACT_NEW, "new" }, + { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_GET), NL_ACT_GET, "get" }, + { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_DELETE), NL_ACT_DEL, "del" }, + END_OF_MSGTYPES_LIST, + }, + .co_protocol = NETLINK_NETFILTER, + .co_groups = ct_groups, + .co_request_update = ct_request_update, + .co_msg_parser = ct_msg_parser, + .co_obj_ops = &ct_obj_ops, +}; + +static void __init ct_init(void) +{ + nl_cache_mngt_register(&nfnl_ct_ops); +} + +static void __exit ct_exit(void) +{ + nl_cache_mngt_unregister(&nfnl_ct_ops); +} + +/** @} */ diff --git a/lib/netfilter/exp_obj.c b/lib/netfilter/exp_obj.c new file mode 100644 index 0000000..8f85b7f --- /dev/null +++ b/lib/netfilter/exp_obj.c @@ -0,0 +1,698 @@ +/* + * lib/netfilter/exp_obj.c Conntrack Expectation Object + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2007 Philip Craig + * Copyright (c) 2007 Secure Computing Corporation + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +// The 32-bit attribute mask in the common object header isn't +// big enough to handle all attributes of an expectation. So +// we'll for sure specify optional attributes + parent attributes +// that are required for valid object comparison. Comparison of +// these parent attributes will include nested attributes. + +/** @cond SKIP */ +#define EXP_ATTR_FAMILY (1UL << 0) +#define EXP_ATTR_PROTO (1UL << 1) + +#define EXP_ATTR_TIMEOUT (1UL << 2) // 32-bit +#define EXP_ATTR_ID (1UL << 3) // 32-bit +#define EXP_ATTR_HELPER_NAME (1UL << 4) // string (16 bytes max) +#define EXP_ATTR_ZONE (1UL << 5) // 16-bit +#define EXP_ATTR_CLASS (1UL << 6) // 32-bit +#define EXP_ATTR_FLAGS (1UL << 7) // 32-bit +#define EXP_ATTR_FN (1UL << 8) // String + +// Tuples +#define EXP_ATTR_EXPECT (1UL << 9) // contains ip, proto +#define EXP_ATTR_EXPECT_IP (1UL << 10) // contains src, dst +#define EXP_ATTR_EXPECT_L4PROTO (1UL << 11) // contains l4proto # + PORT attrs or ICMP attrs +#define EXP_ATTR_EXPECT_L4PROTO_NUM (1UL << 12) +#define EXP_ATTR_MASTER (1UL << 13) // contains ip, proto +#define EXP_ATTR_MASTER_IP (1UL << 14) // contains src, dst +#define EXP_ATTR_MASTER_L4PROTO (1UL << 15) // contains l4proto # + PORT attrs or ICMP attrs +#define EXP_ATTR_MASTER_L4PROTO_NUM (1UL << 16) +#define EXP_ATTR_MASK (1UL << 17) // contains ip, proto +#define EXP_ATTR_MASK_IP (1UL << 18) // contains src, dst +#define EXP_ATTR_MASK_L4PROTO (1UL << 19) // contains l4proto # + PORT attrs or ICMP attrs +#define EXP_ATTR_MASK_L4PROTO_NUM (1UL << 20) +#define EXP_ATTR_NAT (1UL << 21) // contains ip, proto +#define EXP_ATTR_NAT_IP (1UL << 22) // contains src, dst +#define EXP_ATTR_NAT_L4PROTO (1UL << 23) // contains l4proto # + PORT attrs or ICMP attrs +#define EXP_ATTR_NAT_L4PROTO_NUM (1UL << 24) + +#define EXP_ATTR_NAT_DIR (1UL << 25) +/** @endcond */ + +static void exp_free_data(struct nl_object *c) +{ + struct nfnl_exp *exp = (struct nfnl_exp *) c; + + if (exp == NULL) + return; + + nl_addr_put(exp->exp_expect.src); + nl_addr_put(exp->exp_expect.dst); + nl_addr_put(exp->exp_master.src); + nl_addr_put(exp->exp_master.dst); + nl_addr_put(exp->exp_mask.src); + nl_addr_put(exp->exp_mask.dst); + nl_addr_put(exp->exp_nat.src); + nl_addr_put(exp->exp_nat.dst); + + free(exp->exp_fn); + free(exp->exp_helper_name); +} + +static int exp_clone(struct nl_object *_dst, struct nl_object *_src) +{ + struct nfnl_exp *dst = (struct nfnl_exp *) _dst; + struct nfnl_exp *src = (struct nfnl_exp *) _src; + struct nl_addr *addr; + int result = 0; + + // Expectation + if (src->exp_expect.src) { + addr = nl_addr_clone(src->exp_expect.src); + if (!addr) + return -NLE_NOMEM; + dst->exp_expect.src = addr; + } + + if (src->exp_expect.dst) { + addr = nl_addr_clone(src->exp_expect.dst); + if (!addr) + return -NLE_NOMEM; + dst->exp_expect.dst = addr; + } + + // Master CT + if (src->exp_master.src) { + addr = nl_addr_clone(src->exp_master.src); + if (!addr) + return -NLE_NOMEM; + dst->exp_master.src = addr; + } + + if (src->exp_master.dst) { + addr = nl_addr_clone(src->exp_master.dst); + if (!addr) + return -NLE_NOMEM; + dst->exp_master.dst = addr; + } + + // Mask + if (src->exp_mask.src) { + addr = nl_addr_clone(src->exp_mask.src); + if (!addr) + return -NLE_NOMEM; + dst->exp_mask.src = addr; + } + + if (src->exp_mask.dst) { + addr = nl_addr_clone(src->exp_mask.dst); + if (!addr) + return -NLE_NOMEM; + dst->exp_mask.dst = addr; + } + + // NAT + if (src->exp_nat.src) { + addr = nl_addr_clone(src->exp_nat.src); + if (!addr) + return -NLE_NOMEM; + dst->exp_nat.src = addr; + } + + if (src->exp_nat.dst) { + addr = nl_addr_clone(src->exp_nat.dst); + if (!addr) + return -NLE_NOMEM; + dst->exp_nat.dst = addr; + } + + return 0; +} + +static void dump_addr(struct nl_dump_params *p, struct nl_addr *addr, int port) +{ + char buf[64]; + + if (addr) + nl_dump(p, "%s", nl_addr2str(addr, buf, sizeof(buf))); + + if (port) + nl_dump(p, ":%u ", port); + else if (addr) + nl_dump(p, " "); +} + +static void dump_icmp(struct nl_dump_params *p, struct nfnl_ct *ct, int tuple) +{ + nl_dump(p, "icmp type %d ", nfnl_exp_get_icmp_type(ct, tuple)); + + nl_dump(p, "code %d ", nfnl_exp_get_icmp_code(ct, tuple)); + + nl_dump(p, "id %d ", nfnl_exp_get_icmp_id(ct, tuple)); +} + +static void ct_dump_tuples(struct nfnl_exp *exp, struct nl_dump_params *p) +{ + struct nl_addr *tuple_src, *tuple_dst; + int tuple_sport = 0, tuple_dport = 0; + int i = NFNL_EXP_EXPECT; + int icmp = 0; + + for (i; i <= NFNL_EXP_NAT; i++) { + + if (nfnl_exp_test_tuple(exp, i)) { + + tuple_src = nfnl_ct_get_src(exp, i); + tuple_dst = nfnl_ct_get_dst(exp, i); + + // Don't have tests for individual ports/types/codes/ids, + // just test L4 Proto. Ugly, but can't do much else without + // more mask bits + + if (nfnl_exp_test_l4proto(exp, i)) { + int l4proto = nfnl_exp_get_l4proto(exp, i); + if ( !(l4proto == IPPROTO_ICMP || + l4proto == IPPROTO_ICMPV6) ) { + tuple_sport = nfnl_exp_get_src_port(exp, i); + tuple_dport = nfnl_exp_get_dst_port(exp, i); + } else { + icmp = 1; + } + } + dump_addr(p, tuple_src, tuple_sport); + dump_addr(p, tuple_dst, tuple_dport); + if (icmp) + dump_icmp(p, exp, 0); + } +} + +/* Compatible with /proc/net/nf_conntrack */ +static void ct_dump_line(struct nl_object *a, struct nl_dump_params *p) +{ + struct nfnl_ct *ct = (struct nfnl_ct *) a; + char buf[64]; + + nl_new_line(p); + + if (nfnl_ct_test_proto(ct)) + nl_dump(p, "%s ", + nl_ip_proto2str(nfnl_ct_get_proto(ct), buf, sizeof(buf))); + + ct_dump_tuples(ct, p); + + nl_dump(p, "\n"); +} + +static void ct_dump_details(struct nl_object *a, struct nl_dump_params *p) +{ + struct nfnl_ct *ct = (struct nfnl_ct *) a; + char buf[64]; + int fp = 0; + + ct_dump_line(a, p); + + nl_dump(p, " id 0x%x ", ct->ct_id); + nl_dump_line(p, "family %s ", + nl_af2str(ct->ct_family, buf, sizeof(buf))); + + if (nfnl_ct_test_use(ct)) + nl_dump(p, "refcnt %u ", nfnl_ct_get_use(ct)); + + if (nfnl_ct_test_timeout(ct)) { + uint64_t timeout_ms = nfnl_ct_get_timeout(ct) * 1000UL; + nl_dump(p, "timeout %s ", + nl_msec2str(timeout_ms, buf, sizeof(buf))); + } + + if (ct->ct_status) + nl_dump(p, "<"); + +#define PRINT_FLAG(str) \ + { nl_dump(p, "%s%s", fp++ ? "," : "", (str)); } + + if (exp->exp_flags & NF_CT_EXPECT_PERMANENT) + PRINT_FLAG("PERMANENT"); + if (exp->exp_flags & NF_CT_EXPECT_INACTIVE) + PRINT_FLAG("INACTIVE"); + if (exp->exp_flags & NF_CT_EXPECT_USERSPACE) + PRINT_FLAG("USERSPACE"); +#undef PRINT_FLAG + + if (exp->exp_flags) + nl_dump(p, ">"); + nl_dump(p, "\n"); +} + +/* +static void ct_dump_stats(struct nl_object *a, struct nl_dump_params *p) +{ + struct nfnl_ct *ct = (struct nfnl_ct *) a; + double res; + char *unit; + uint64_t packets; + const char * const names[] = {"rx", "tx"}; + int i; + + ct_dump_details(a, p); + + if (!nfnl_ct_test_bytes(ct, 0) || + !nfnl_ct_test_packets(ct, 0) || + !nfnl_ct_test_bytes(ct, 1) || + !nfnl_ct_test_packets(ct, 1)) + { + nl_dump_line(p, " Statistics are not available.\n"); + nl_dump_line(p, " Please set sysctl net.netfilter.nf_conntrack_acct=1\n"); + nl_dump_line(p, " (Require kernel 2.6.27)\n"); + return; + } + + nl_dump_line(p, " # packets volume\n"); + for (i=0; i<=1; i++) { + res = nl_cancel_down_bytes(nfnl_ct_get_bytes(ct, i), &unit); + packets = nfnl_ct_get_packets(ct, i); + nl_dump_line(p, " %s %10" PRIu64 " %7.2f %s\n", names[i], packets, res, unit); + } +} +*/ + +static int exp_cmp_tuples_loose(struct nfnl_ct_dir *a, struct nfnl_ct_dir *b) +{ + // Must return 0 for match, 1 for mismatch + + int d = nl_addr_cmp_prefix(a->src, b->src); + + if (d == 0) { + d = nl_addr_cmp_prefix(a->dst, b->dst); + + if (d == 0) { + } + } +} + +static int exp_compare(struct nl_object *_a, struct nl_object *_b, + uint32_t attrs, int flags) +{ + struct nfnl_exp *a = (struct nfnl_exp *) _a; + struct nfnl_exp *b = (struct nfnl_exp *) _b; + int diff = 0; + +#define EXP_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, EXP_ATTR_##ATTR, a, b, EXPR) +#define EXP_DIFF_VAL(ATTR, FIELD) EXP_DIFF(ATTR, a->FIELD != b->FIELD) +#define EXP_DIFF_ADDR(ATTR, FIELD) \ + ((flags & LOOSE_COMPARISON) \ + ? EXP_DIFF(ATTR, nl_addr_cmp_prefix(a->FIELD, b->FIELD)) \ + : EXP_DIFF(ATTR, nl_addr_cmp(a->FIELD, b->FIELD))) + +#define EXP_DIFF_TUPLE(ATTR, FIELD) \ + ((flags & LOOSE_COMPARISON) \ + ? EXP_DIFF(ATTR, exp_cmp_tuples_loose(a->FIELD, b->FIELD)) \ + : EXP_DIFF(ATTR, exp_cmp_tuples(a->FIELD, b->FIELD))) + + diff |= EXP_DIFF_VAL(FAMILY, exp_family); + diff |= EXP_DIFF_VAL(PROTO, exp_proto); + diff |= EXP_DIFF_VAL(TIMEOUT, exp_timeout); + diff |= EXP_DIFF_VAL(ID, exp_id); + + diff |= EXP_DIFF(FLAGS, (a->exp_flags ^ b->exp_flags)); + +#undef CT_DIFF +#undef CT_DIFF_VAL +#undef CT_DIFF_ADDR +#undef CT_DIFF_TUPLE + + return diff; +} + +static const struct trans_tbl ct_attrs[] = { + __ADD(CT_ATTR_FAMILY, family) + __ADD(CT_ATTR_PROTO, proto) + __ADD(CT_ATTR_TCP_STATE, tcpstate) + __ADD(CT_ATTR_STATUS, status) + __ADD(CT_ATTR_TIMEOUT, timeout) + __ADD(CT_ATTR_MARK, mark) + __ADD(CT_ATTR_USE, use) + __ADD(CT_ATTR_ID, id) + __ADD(CT_ATTR_ORIG_SRC, origsrc) + __ADD(CT_ATTR_ORIG_DST, origdst) + __ADD(CT_ATTR_ORIG_SRC_PORT, origsrcport) + __ADD(CT_ATTR_ORIG_DST_PORT, origdstport) + __ADD(CT_ATTR_ORIG_ICMP_ID, origicmpid) + __ADD(CT_ATTR_ORIG_ICMP_TYPE, origicmptype) + __ADD(CT_ATTR_ORIG_ICMP_CODE, origicmpcode) + __ADD(CT_ATTR_ORIG_PACKETS, origpackets) + __ADD(CT_ATTR_ORIG_BYTES, origbytes) + __ADD(CT_ATTR_REPL_SRC, replysrc) + __ADD(CT_ATTR_REPL_DST, replydst) + __ADD(CT_ATTR_REPL_SRC_PORT, replysrcport) + __ADD(CT_ATTR_REPL_DST_PORT, replydstport) + __ADD(CT_ATTR_REPL_ICMP_ID, replyicmpid) + __ADD(CT_ATTR_REPL_ICMP_TYPE, replyicmptype) + __ADD(CT_ATTR_REPL_ICMP_CODE, replyicmpcode) + __ADD(CT_ATTR_REPL_PACKETS, replypackets) + __ADD(CT_ATTR_REPL_BYTES, replybytes) +}; + +static char *ct_attrs2str(int attrs, char *buf, size_t len) +{ + return __flags2str(attrs, buf, len, ct_attrs, ARRAY_SIZE(ct_attrs)); +} + +/** + * @name Allocation/Freeing + * @{ + */ + +struct nfnl_ct *nfnl_ct_alloc(void) +{ + return (struct nfnl_ct *) nl_object_alloc(&ct_obj_ops); +} + +void nfnl_ct_get(struct nfnl_ct *ct) +{ + nl_object_get((struct nl_object *) ct); +} + +void nfnl_ct_put(struct nfnl_ct *ct) +{ + nl_object_put((struct nl_object *) ct); +} + +/** @} */ + +/** + * @name Attributes + * @{ + */ + +void nfnl_exp_set_family(struct nfnl_exp *exp, uint8_t family) +{ + exp->exp_family = family; + exp->ce_mask |= EXP_ATTR_FAMILY; +} + +uint8_t nfnl_exp_get_family(const struct nfnl_exp *exp) +{ + if (exp->ce_mask & EXP_ATTR_FAMILY) + return exp->exp_family; + else + return AF_UNSPEC; +} + +void nfnl_exp_set_proto(struct nfnl_exp *exp, uint8_t proto) +{ + exp->exp_proto = proto; + exp->ce_mask |= EXP_ATTR_PROTO; +} + +int nfnl_exp_test_proto(const struct nfnl_exp *exp) +{ + return !!(exp->ce_mask & EXP_ATTR_PROTO); +} + +uint8_t nfnl_exp_get_proto(const struct nfnl_exp *ct) +{ + return exp->ct_proto; +} + +void nfnl_exp_set_flags(struct nfnl_exp *exp, uint32_t flags) +{ + exp->exp_flags |= flags; + exp->ce_mask |= EXP_ATTR_FLAGS; +} + +void nfnl_exp_unset_flags(struct nfnl_exp *exp, uint32_t flags) +{ + exp->exp_flags &= ~flags; + exp->ce_mask |= EXP_ATTR_FLAGS; +} + +uint32_t nfnl_exp_get_status(const struct nfnl_exp *exp) +{ + return exp->exp_flags; +} + +static const struct trans_tbl flag_table[] = { + __ADD(IPS_EXPECTED, expected) + __ADD(IPS_SEEN_REPLY, seen_reply) + __ADD(IPS_ASSURED, assured) +}; + +char * nfnl_exp_flags2str(int flags, char *buf, size_t len) +{ + return __flags2str(flags, buf, len, status_flags, + ARRAY_SIZE(flag_table)); +} + +int nfnl_exp_str2status(const char *name) +{ + return __str2flags(name, flag_table, ARRAY_SIZE(flag_table)); +} + +void nfnl_exp_set_timeout(struct nfnl_exp *exp, uint32_t timeout) +{ + exp->exp_timeout = timeout; + exp->ce_mask |= EXP_ATTR_TIMEOUT; +} + +int nfnl_exp_test_timeout(const struct nfnl_exp *exp) +{ + return !!(exp->ce_mask & EXP_ATTR_TIMEOUT); +} + +uint32_t nfnl_exp_get_timeout(const struct nfnl_exp *exp) +{ + return exp->exp_timeout; +} + +void nfnl_exp_set_id(struct nfnl_exp *exp, uint32_t id) +{ + exp->exp_id = id; + exp->ce_mask |= EXP_ATTR_ID; +} + +int nfnl_exp_test_id(const struct nfnl_exp *exp) +{ + return !!(exp->ce_mask & EXP_ATTR_ID); +} + +uint32_t nfnl_exp_get_id(const struct nfnl_exp *exp) +{ + return exp->exp_id; +} + +static int exp_set_addr(struct nfnl_exp *exp, struct nl_addr *addr, + int attr, struct nl_addr ** exp_addr) +{ + if (exp->ce_mask & EXP_ATTR_FAMILY) { + if (addr->a_family != exp->exp_family) + return -NLE_AF_MISMATCH; + } else + nfnl_exp_set_family(exp, addr->a_family); + + if (*exp_addr) + nl_addr_put(*exp_addr); + + nl_addr_get(addr); + *exp_addr = addr; + exp->ce_mask |= attr; + + return 0; +} + +int nfnl_exp_set_src(struct nfnl_exp *exp, int tuple, struct nl_addr *addr) +{ + struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + int attr = repl ? CT_ATTR_REPL_SRC : CT_ATTR_ORIG_SRC; + + switch (tuple) { + case : + dir = &exp->exp_expect; + attr = EXP_ATTR_ + break; + case : + dir = &exp->exp_master; + break; + case : + dir = &exp->exp_mask; + break; + case : + dir = &exp->exp_nat; + default : + } + + return ct_set_addr(ct, addr, attr, &dir->src); +} + +int nfnl_ct_set_dst(struct nfnl_ct *ct, int repl, struct nl_addr *addr) +{ + struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + int attr = repl ? CT_ATTR_REPL_DST : CT_ATTR_ORIG_DST; + return ct_set_addr(ct, addr, attr, &dir->dst); +} + +struct nl_addr *nfnl_ct_get_src(const struct nfnl_ct *ct, int repl) +{ + const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + int attr = repl ? CT_ATTR_REPL_SRC : CT_ATTR_ORIG_SRC; + if (!(ct->ce_mask & attr)) + return NULL; + return dir->src; +} + +struct nl_addr *nfnl_ct_get_dst(const struct nfnl_ct *ct, int repl) +{ + const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + int attr = repl ? CT_ATTR_REPL_DST : CT_ATTR_ORIG_DST; + if (!(ct->ce_mask & attr)) + return NULL; + return dir->dst; +} + +void nfnl_ct_set_src_port(struct nfnl_ct *ct, int repl, uint16_t port) +{ + struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + int attr = repl ? CT_ATTR_REPL_SRC_PORT : CT_ATTR_ORIG_SRC_PORT; + + dir->proto.port.src = port; + ct->ce_mask |= attr; +} + +int nfnl_ct_test_src_port(const struct nfnl_ct *ct, int repl) +{ + int attr = repl ? CT_ATTR_REPL_SRC_PORT : CT_ATTR_ORIG_SRC_PORT; + return !!(ct->ce_mask & attr); +} + +uint16_t nfnl_ct_get_src_port(const struct nfnl_ct *ct, int repl) +{ + const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + + return dir->proto.port.src; +} + +void nfnl_ct_set_dst_port(struct nfnl_ct *ct, int repl, uint16_t port) +{ + struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + int attr = repl ? CT_ATTR_REPL_DST_PORT : CT_ATTR_ORIG_DST_PORT; + + dir->proto.port.dst = port; + ct->ce_mask |= attr; +} + +int nfnl_ct_test_dst_port(const struct nfnl_ct *ct, int repl) +{ + int attr = repl ? CT_ATTR_REPL_DST_PORT : CT_ATTR_ORIG_DST_PORT; + return !!(ct->ce_mask & attr); +} + +uint16_t nfnl_ct_get_dst_port(const struct nfnl_ct *ct, int repl) +{ + const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + + return dir->proto.port.dst; +} + +void nfnl_ct_set_icmp_id(struct nfnl_ct *ct, int repl, uint16_t id) +{ + struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + int attr = repl ? CT_ATTR_REPL_ICMP_ID : CT_ATTR_ORIG_ICMP_ID; + + dir->proto.icmp.id = id; + ct->ce_mask |= attr; +} + +int nfnl_ct_test_icmp_id(const struct nfnl_ct *ct, int repl) +{ + int attr = repl ? CT_ATTR_REPL_ICMP_ID : CT_ATTR_ORIG_ICMP_ID; + return !!(ct->ce_mask & attr); +} + +uint16_t nfnl_ct_get_icmp_id(const struct nfnl_ct *ct, int repl) +{ + const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + + return dir->proto.icmp.id; +} + +void nfnl_ct_set_icmp_type(struct nfnl_ct *ct, int repl, uint8_t type) +{ + struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + int attr = repl ? CT_ATTR_REPL_ICMP_TYPE : CT_ATTR_ORIG_ICMP_TYPE; + + dir->proto.icmp.type = type; + ct->ce_mask |= attr; +} + +int nfnl_ct_test_icmp_type(const struct nfnl_ct *ct, int repl) +{ + int attr = repl ? CT_ATTR_REPL_ICMP_TYPE : CT_ATTR_ORIG_ICMP_TYPE; + return !!(ct->ce_mask & attr); +} + +uint8_t nfnl_ct_get_icmp_type(const struct nfnl_ct *ct, int repl) +{ + const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + + return dir->proto.icmp.type; +} + +void nfnl_ct_set_icmp_code(struct nfnl_ct *ct, int repl, uint8_t code) +{ + struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + int attr = repl ? CT_ATTR_REPL_ICMP_CODE : CT_ATTR_ORIG_ICMP_CODE; + + dir->proto.icmp.code = code; + ct->ce_mask |= attr; +} + +int nfnl_ct_test_icmp_code(const struct nfnl_ct *ct, int repl) +{ + int attr = repl ? CT_ATTR_REPL_ICMP_CODE : CT_ATTR_ORIG_ICMP_CODE; + return !!(ct->ce_mask & attr); +} + +uint8_t nfnl_ct_get_icmp_code(const struct nfnl_ct *ct, int tuple) +{ + const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + + return dir->proto.icmp.code; +} + +/** @} */ + +struct nl_object_ops exp_obj_ops = { + .oo_name = "netfilter/exp", + .oo_size = sizeof(struct nfnl_exp), + .oo_free_data = exp_free_data, + .oo_clone = exp_clone, + .oo_dump = { + [NL_DUMP_LINE] = exp_dump_line, + [NL_DUMP_DETAILS] = exp_dump_details, + [NL_DUMP_STATS] = exp_dump_stats, + }, + .oo_compare = exp_compare, + .oo_attrs2str = exp_attrs2str, +}; + +/** @} */ From 20035ce021cf9f8d465e5ac71e4f5d65ad9596cd Mon Sep 17 00:00:00 2001 From: Rich Fought Date: Fri, 5 Oct 2012 11:09:45 -0700 Subject: [PATCH 247/432] Checkpoint: compare function --- include/netlink-types.h | 28 +++++++- lib/netfilter/exp_obj.c | 137 +++++++++++++++++++++++++++++----------- 2 files changed, 126 insertions(+), 39 deletions(-) diff --git a/include/netlink-types.h b/include/netlink-types.h index aeba518..7884695 100644 --- a/include/netlink-types.h +++ b/include/netlink-types.h @@ -779,13 +779,35 @@ struct nfnl_ct { struct nfnl_ct_dir ct_repl; }; +union nfnl_exp_protodata { + struct { + uint16_t src; + uint16_t dst; + } port; + struct { + uint16_t id; + uint8_t type; + uint8_t code; + } icmp; +}; + +// Allow for different master/expect l4 protocols +struct nfnl_exp_proto +{ + uint8_t l4protonum; + union nfnl_exp_protodata l4protodata; +}; + +struct nfnl_exp_dir { + struct nl_addr * src; + struct nl_addr * dst; + struct nfnl_exp_proto proto; +}; + struct nfnl_exp { NLHDR_COMMON uint8_t exp_family; // IPv4, IPv6, etc - required - uint8_t exp_proto; // tcp, udp, etc - required - union nfnl_ct_protoinfo exp_protoinfo; // ??? Assured, etc? - uint32_t exp_timeout; // required afaik uint32_t exp_id; // optional uint16_t exp_zone; // optional diff --git a/lib/netfilter/exp_obj.c b/lib/netfilter/exp_obj.c index 8f85b7f..4e11edf 100644 --- a/lib/netfilter/exp_obj.c +++ b/lib/netfilter/exp_obj.c @@ -29,35 +29,33 @@ /** @cond SKIP */ #define EXP_ATTR_FAMILY (1UL << 0) -#define EXP_ATTR_PROTO (1UL << 1) - -#define EXP_ATTR_TIMEOUT (1UL << 2) // 32-bit -#define EXP_ATTR_ID (1UL << 3) // 32-bit -#define EXP_ATTR_HELPER_NAME (1UL << 4) // string (16 bytes max) -#define EXP_ATTR_ZONE (1UL << 5) // 16-bit -#define EXP_ATTR_CLASS (1UL << 6) // 32-bit -#define EXP_ATTR_FLAGS (1UL << 7) // 32-bit -#define EXP_ATTR_FN (1UL << 8) // String +#define EXP_ATTR_TIMEOUT (1UL << 1) // 32-bit +#define EXP_ATTR_ID (1UL << 2) // 32-bit +#define EXP_ATTR_HELPER_NAME (1UL << 3) // string (16 bytes max) +#define EXP_ATTR_ZONE (1UL << 4) // 16-bit +#define EXP_ATTR_CLASS (1UL << 5) // 32-bit +#define EXP_ATTR_FLAGS (1UL << 6) // 32-bit +#define EXP_ATTR_FN (1UL << 7) // String // Tuples -#define EXP_ATTR_EXPECT (1UL << 9) // contains ip, proto -#define EXP_ATTR_EXPECT_IP (1UL << 10) // contains src, dst -#define EXP_ATTR_EXPECT_L4PROTO (1UL << 11) // contains l4proto # + PORT attrs or ICMP attrs -#define EXP_ATTR_EXPECT_L4PROTO_NUM (1UL << 12) -#define EXP_ATTR_MASTER (1UL << 13) // contains ip, proto -#define EXP_ATTR_MASTER_IP (1UL << 14) // contains src, dst -#define EXP_ATTR_MASTER_L4PROTO (1UL << 15) // contains l4proto # + PORT attrs or ICMP attrs -#define EXP_ATTR_MASTER_L4PROTO_NUM (1UL << 16) -#define EXP_ATTR_MASK (1UL << 17) // contains ip, proto -#define EXP_ATTR_MASK_IP (1UL << 18) // contains src, dst -#define EXP_ATTR_MASK_L4PROTO (1UL << 19) // contains l4proto # + PORT attrs or ICMP attrs -#define EXP_ATTR_MASK_L4PROTO_NUM (1UL << 20) -#define EXP_ATTR_NAT (1UL << 21) // contains ip, proto -#define EXP_ATTR_NAT_IP (1UL << 22) // contains src, dst -#define EXP_ATTR_NAT_L4PROTO (1UL << 23) // contains l4proto # + PORT attrs or ICMP attrs -#define EXP_ATTR_NAT_L4PROTO_NUM (1UL << 24) +#define EXP_ATTR_EXPECT (1UL << 8) // contains ip, proto +#define EXP_ATTR_EXPECT_IP (1UL << 9) // contains src, dst +#define EXP_ATTR_EXPECT_L4PROTO (1UL << 10) // contains l4proto # + PORT attrs or ICMP attrs +#define EXP_ATTR_EXPECT_L4PROTO_NUM (1UL << 11) +#define EXP_ATTR_MASTER (1UL << 12) // contains ip, proto +#define EXP_ATTR_MASTER_IP (1UL << 13) // contains src, dst +#define EXP_ATTR_MASTER_L4PROTO (1UL << 14) // contains l4proto # + PORT attrs or ICMP attrs +#define EXP_ATTR_MASTER_L4PROTO_NUM (1UL << 15) +#define EXP_ATTR_MASK (1UL << 16) // contains ip, proto +#define EXP_ATTR_MASK_IP (1UL << 17) // contains src, dst +#define EXP_ATTR_MASK_L4PROTO (1UL << 18) // contains l4proto # + PORT attrs or ICMP attrs +#define EXP_ATTR_MASK_L4PROTO_NUM (1UL << 19) +#define EXP_ATTR_NAT (1UL << 20) // contains ip, proto +#define EXP_ATTR_NAT_IP (1UL << 21) // contains src, dst +#define EXP_ATTR_NAT_L4PROTO (1UL << 22) // contains l4proto # + PORT attrs or ICMP attrs +#define EXP_ATTR_NAT_L4PROTO_NUM (1UL << 23) -#define EXP_ATTR_NAT_DIR (1UL << 25) +#define EXP_ATTR_NAT_DIR (1UL << 24) /** @endcond */ static void exp_free_data(struct nl_object *c) @@ -299,15 +297,72 @@ static void ct_dump_stats(struct nl_object *a, struct nl_dump_params *p) static int exp_cmp_tuples_loose(struct nfnl_ct_dir *a, struct nfnl_ct_dir *b) { // Must return 0 for match, 1 for mismatch + // Parent attribute, so must reflect lower level attribute diffs + int d = exp_cmp_tuples_ip_loose(a, b); + if (d == 0) { + d = exp_cmp_tuples_proto(&a->proto, &b->proto)) + } + return d; +} +static int exp_cmp_tuples(struct nfnl_exp_dir *a, struct nfnl_exp_dir *b) +{ + // Must return 0 for match, 1 for mismatch + // Parent attribute, so must reflect lower level attribute diffs + int d = exp_cmp_tuples_ip(a, b); + if (d == 0) { + d = exp_cmp_tuples_proto(&a->proto, &b->proto)) + } + return d; +} + +static int exp_cmp_tuples_ip_loose(struct nfnl_exp_dir *a, struct nfnl_exp_dir *b) { + // Must return 0 for match, 1 for mismatch int d = nl_addr_cmp_prefix(a->src, b->src); if (d == 0) { d = nl_addr_cmp_prefix(a->dst, b->dst); + } + return d; +} - if (d == 0) { + +static int exp_cmp_tuples_ip(struct nfnl_exp_dir *a, struct nfnl_exp_dir *b) { + // Must return 0 for match, 1 for mismatch + int d = nl_addr_cmp(a->src, b->src); + + if (d == 0) { + d = nl_addr_cmp(a->dst, b->dst); + } + return d; +} + + +static int exp_cmp_tuples_proto(struct nfnl_exp_proto *a, struct nfnl_exp_proto *b) { + // Must return 0 for match, 1 for mismatch + + // Parent attribute, so must reflect lower level attribute diffs + int d = exp_cmp_tuples_protonum(a->l4protonum, b->l4protonum); + + if (d == 0) { + // Check actual proto data + if (a->l4protonum == IPPROTO_ICMP || + a->l4protonum == IPPROTO_ICMPV6) { + d == ( (a->l4protodata.icmp.code != b->l4protodata.icmp.code) || + (a->l4protodata.icmp.type != b->l4protodata.icmp.type) || + (a->l4protodata.icmp.id != b->l4protodata.icmp.id) ) + } else { + d == ( (a->l4protodata.port.src != b->l4protodata.port.src) || + (a->l4protodata.port.dst != b->l4protodata.icmp.dst) ) } } + + return d; +} + +static int exp_cmp_tuples_protonum(uint8_t a, uint8_t b) { + // Must return 0 for match, 1 for mismatch + return (a != b) } static int exp_compare(struct nl_object *_a, struct nl_object *_b, @@ -319,27 +374,37 @@ static int exp_compare(struct nl_object *_a, struct nl_object *_b, #define EXP_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, EXP_ATTR_##ATTR, a, b, EXPR) #define EXP_DIFF_VAL(ATTR, FIELD) EXP_DIFF(ATTR, a->FIELD != b->FIELD) -#define EXP_DIFF_ADDR(ATTR, FIELD) \ - ((flags & LOOSE_COMPARISON) \ - ? EXP_DIFF(ATTR, nl_addr_cmp_prefix(a->FIELD, b->FIELD)) \ - : EXP_DIFF(ATTR, nl_addr_cmp(a->FIELD, b->FIELD))) +#define EXP_DIFF_STRING(ATTR, FIELD) EXP_DIFF(ATTR, (strncmp(a->FIELD, b->FIELD, 16) != 0)) #define EXP_DIFF_TUPLE(ATTR, FIELD) \ ((flags & LOOSE_COMPARISON) \ ? EXP_DIFF(ATTR, exp_cmp_tuples_loose(a->FIELD, b->FIELD)) \ : EXP_DIFF(ATTR, exp_cmp_tuples(a->FIELD, b->FIELD))) - diff |= EXP_DIFF_VAL(FAMILY, exp_family); - diff |= EXP_DIFF_VAL(PROTO, exp_proto); - diff |= EXP_DIFF_VAL(TIMEOUT, exp_timeout); - diff |= EXP_DIFF_VAL(ID, exp_id); +#define EXP_DIFF_IP(ATTR, FIELD) \ + ((flags & LOOSE_COMPARISON) \ + ? EXP_DIFF(ATTR, exp_cmp_tuples_ip_loose(a->FIELD, b->FIELD)) \ + : EXP_DIFF(ATTR, exp_cmp_tuples_ip(a->FIELD, b->FIELD))) + +#define EXP_DIFF_PROTO(ATTR, FIELD) \ + EXP_DIFF(ATTR, exp_cmp_tuples_proto(a->FIELD, b->FIELD)) + + diff |= EXP_DIFF_VAL(FAMILY, exp_family); + diff |= EXP_DIFF_VAL(TIMEOUT, exp_timeout); + diff |= EXP_DIFF_VAL(ID, exp_id); + diff |= EXP_DIFF_VAL(ZONE, exp_zone); + diff |= EXP_DIFF_VAL(CLASS, exp_class); + diff |= EXP_DIFF_VAL(FLAGS, exp_flags); + diff |= EXP_DIFF_VAL(NAT_DIR, exp_flags); diff |= EXP_DIFF(FLAGS, (a->exp_flags ^ b->exp_flags)); #undef CT_DIFF #undef CT_DIFF_VAL -#undef CT_DIFF_ADDR +#undef EXP_DIFF_STRING #undef CT_DIFF_TUPLE +#undef CT_DIFF_IP +#undef CT_DIFF_PROTO return diff; } From e8b3356dd2d61f27b2506528e291fc051e8340bc Mon Sep 17 00:00:00 2001 From: Rich Fought Date: Fri, 5 Oct 2012 17:32:20 -0700 Subject: [PATCH 248/432] "checkpoint" --- include/netlink-types.h | 8 +- include/netlink/netfilter/exp.h | 29 +- lib/netfilter/exp_obj.c | 570 +++++++++++++++++++------------- 3 files changed, 354 insertions(+), 253 deletions(-) diff --git a/include/netlink-types.h b/include/netlink-types.h index 7884695..0ee1bda 100644 --- a/include/netlink-types.h +++ b/include/netlink-types.h @@ -817,10 +817,10 @@ struct nfnl_exp { char * exp_fn; //optional uint8_t exp_nat_dir; // optional - struct nfnl_ct_dir exp_expect; // required - struct nfnl_ct_dir exp_master; // required - struct nfnl_ct_dir exp_mask; // required - struct nfnl_ct_dir exp_nat; // optional + struct nfnl_exp_dir exp_expect; // required + struct nfnl_exp_dir exp_master; // required + struct nfnl_exp_dir exp_mask; // required + struct nfnl_exp_dir exp_nat; // optional }; struct nfnl_log { diff --git a/include/netlink/netfilter/exp.h b/include/netlink/netfilter/exp.h index 36a28e5..7ace0e5 100644 --- a/include/netlink/netfilter/exp.h +++ b/include/netlink/netfilter/exp.h @@ -26,10 +26,10 @@ extern "C" { struct nfnl_exp; enum nfnl_exp_tuples { - NFNL_EXP_EXPECT, - NFNL_EXP_MASTER, - NFNL_EXP_MASK, - NFNL_EXP_NAT + NFNL_EXP_TUPLE_EXPECT, + NFNL_EXP_TUPLE_MASTER, + NFNL_EXP_TUPLE_MASK, + NFNL_EXP_TUPLE_NAT }; extern struct nl_object_ops exp_obj_ops; @@ -98,31 +98,28 @@ extern uint8_t nfnl_exp_get_nat_dir(const struct nfnl_exp *, int); // The int argument specifies which nfnl_ct_dir (expect, master, mask or nat) // Expectation objects only use orig, not reply -extern int nfnl_exp_test_tuple(const struct nfnl_exp *, int); extern int nfnl_exp_set_src(struct nfnl_exp *, int, struct nl_addr *); +extern int nfnl_exp_test_src(const struct nfnl_exp *); extern struct nl_addr * nfnl_ct_get_src(const struct nfnl_exp *, int); extern int nfnl_exp_set_dst(struct nfnl_exp *, int, struct nl_addr *); +extern int nfnl_exp_test_dst(const struct nfnl_exp *); extern struct nl_addr * nfnl_exp_get_dst(const struct nfnl_exp *, int); -extern int nfnl_exp_set_l4proto(struct nfnl_exp *, int, uint8_t); -extern int nfnl_exp_test_l4proto(const struct nfnl_exp *); -extern struct uint8_t * nfnl_exp_get_l4proto(const struct nfnl_exp *, int); +extern void nfnl_exp_set_l4protonum(struct nfnl_exp *, int, uint8_t); +extern int nfnl_exp_test_l4protonum(const struct nfnl_exp *, int); +extern uint8_t * nfnl_exp_get_l4protonum(const struct nfnl_exp *, int); -extern void nfnl_exp_set_src_port(struct nfnl_exp *, int, uint16_t); +extern void nfnl_exp_set_ports(struct nfnl_exp *, int, uint16_t, uint16_t); +extern int nfnl_exp_test_ports(const struct nfnl_exp *, int); extern uint16_t nfnl_exp_get_src_port(const struct nfnl_exp *, int); - -extern void nfnl_exp_set_dst_port(struct nfnl_exp *, int, uint16_t); extern uint16_t nfnl_exp_get_dst_port(const struct nfnl_exp *, int); -extern void nfnl_exp_set_icmp_id(struct nfnl_exp *, int, uint16_t); +extern void nfnl_exp_set_icmp(struct nfnl_exp *, int, uint16_t, uint8_t, uint8_t); +extern int nfnl_exp_test_icmp(const struct nfnl_exp *, int); extern uint16_t nfnl_exp_get_icmp_id(const struct nfnl_exp *, int); - -extern void nfnl_exp_set_icmp_type(struct nfnl_exp *, int, uint8_t); extern uint8_t nfnl_exp_get_icmp_type(const struct nfnl_exp *, int); - -extern void nfnl_exp_set_icmp_code(struct nfnl_exp *, int, uint8_t); extern uint8_t nfnl_exp_get_icmp_code(const struct nfnl_exp *, int); // TODO: Expectation table does support CPU stats get command, not sure if the same diff --git a/lib/netfilter/exp_obj.c b/lib/netfilter/exp_obj.c index 4e11edf..2a45f3e 100644 --- a/lib/netfilter/exp_obj.c +++ b/lib/netfilter/exp_obj.c @@ -28,34 +28,38 @@ // these parent attributes will include nested attributes. /** @cond SKIP */ -#define EXP_ATTR_FAMILY (1UL << 0) -#define EXP_ATTR_TIMEOUT (1UL << 1) // 32-bit -#define EXP_ATTR_ID (1UL << 2) // 32-bit -#define EXP_ATTR_HELPER_NAME (1UL << 3) // string (16 bytes max) -#define EXP_ATTR_ZONE (1UL << 4) // 16-bit -#define EXP_ATTR_CLASS (1UL << 5) // 32-bit -#define EXP_ATTR_FLAGS (1UL << 6) // 32-bit -#define EXP_ATTR_FN (1UL << 7) // String +#define EXP_ATTR_FAMILY (1UL << 0) // 8-bit +#define EXP_ATTR_TIMEOUT (1UL << 1) // 32-bit +#define EXP_ATTR_ID (1UL << 2) // 32-bit +#define EXP_ATTR_HELPER_NAME (1UL << 3) // string (16 bytes max) +#define EXP_ATTR_ZONE (1UL << 4) // 16-bit +#define EXP_ATTR_CLASS (1UL << 5) // 32-bit +#define EXP_ATTR_FLAGS (1UL << 6) // 32-bit +#define EXP_ATTR_FN (1UL << 7) // String // Tuples -#define EXP_ATTR_EXPECT (1UL << 8) // contains ip, proto -#define EXP_ATTR_EXPECT_IP (1UL << 9) // contains src, dst -#define EXP_ATTR_EXPECT_L4PROTO (1UL << 10) // contains l4proto # + PORT attrs or ICMP attrs -#define EXP_ATTR_EXPECT_L4PROTO_NUM (1UL << 11) -#define EXP_ATTR_MASTER (1UL << 12) // contains ip, proto -#define EXP_ATTR_MASTER_IP (1UL << 13) // contains src, dst -#define EXP_ATTR_MASTER_L4PROTO (1UL << 14) // contains l4proto # + PORT attrs or ICMP attrs -#define EXP_ATTR_MASTER_L4PROTO_NUM (1UL << 15) -#define EXP_ATTR_MASK (1UL << 16) // contains ip, proto -#define EXP_ATTR_MASK_IP (1UL << 17) // contains src, dst -#define EXP_ATTR_MASK_L4PROTO (1UL << 18) // contains l4proto # + PORT attrs or ICMP attrs -#define EXP_ATTR_MASK_L4PROTO_NUM (1UL << 19) -#define EXP_ATTR_NAT (1UL << 20) // contains ip, proto -#define EXP_ATTR_NAT_IP (1UL << 21) // contains src, dst -#define EXP_ATTR_NAT_L4PROTO (1UL << 22) // contains l4proto # + PORT attrs or ICMP attrs -#define EXP_ATTR_NAT_L4PROTO_NUM (1UL << 23) +#define EXP_ATTR_EXPECT_IP_SRC (1UL << 8) +#define EXP_ATTR_EXPECT_IP_DST (1UL << 9) +#define EXP_ATTR_EXPECT_L4PROTO_NUM (1UL << 10) // contains l4proto # + PORT attrs or ICMP attrs +#define EXP_ATTR_EXPECT_L4PROTO_PORTS (1UL << 11) +#define EXP_ATTR_EXPECT_L4PROTO_ICMP (1UL << 12) +#define EXP_ATTR_MASTER_IP_SRC (1UL << 13) +#define EXP_ATTR_MASTER_IP_DST (1UL << 14) +#define EXP_ATTR_MASTER_L4PROTO_NUM (1UL << 15) // contains l4proto # + PORT attrs or ICMP attrs +#define EXP_ATTR_MASTER_L4PROTO_PORTS (1UL << 16) +#define EXP_ATTR_MASTER_L4PROTO_ICMP (1UL << 17) +#define EXP_ATTR_MASK_IP_SRC (1UL << 18) +#define EXP_ATTR_MASK_IP_DST (1UL << 19) +#define EXP_ATTR_MASK_L4PROTO_NUM (1UL << 20) // contains l4proto # + PORT attrs or ICMP attrs +#define EXP_ATTR_MASK_L4PROTO_PORTS (1UL << 21) +#define EXP_ATTR_MASK_L4PROTO_ICMP (1UL << 22) +#define EXP_ATTR_NAT_IP_SRC (1UL << 23) +#define EXP_ATTR_NAT_IP_DST (1UL << 24) +#define EXP_ATTR_NAT_L4PROTO_NUM (1UL << 25) // contains l4proto # + PORT attrs or ICMP attrs +#define EXP_ATTR_NAT_L4PROTO_PORTS (1UL << 26) +#define EXP_ATTR_NAT_L4PROTO_ICMP (1UL << 27) -#define EXP_ATTR_NAT_DIR (1UL << 24) +#define EXP_ATTR_NAT_DIR (1UL << 28) /** @endcond */ static void exp_free_data(struct nl_object *c) @@ -145,6 +149,12 @@ static int exp_clone(struct nl_object *_dst, struct nl_object *_src) dst->exp_nat.dst = addr; } + if (src->exp_fn) + dst->exp_fn = strdup(src->exp_fn) + + if (src->exp_helper_name) + dst->exp_helper_name = strdup(src->exp_helper_name); + return 0; } @@ -174,15 +184,16 @@ static void ct_dump_tuples(struct nfnl_exp *exp, struct nl_dump_params *p) { struct nl_addr *tuple_src, *tuple_dst; int tuple_sport = 0, tuple_dport = 0; - int i = NFNL_EXP_EXPECT; + int i = NFNL_EXP_TUPLE_EXPECT; int icmp = 0; - for (i; i <= NFNL_EXP_NAT; i++) { + for (i; i <= NFNL_EXP_TUPLE_NAT; i++) { - if (nfnl_exp_test_tuple(exp, i)) { - - tuple_src = nfnl_ct_get_src(exp, i); - tuple_dst = nfnl_ct_get_dst(exp, i); + // Test needed for NAT case + if (nfnl_exp_test_src(exp, i)) + tuple_src = nfnl_exp_get_src(exp, i); + if (nfnl_exp_test_dst(exp, i)) + tuple_dst = nfnl_exp_get_dst(exp, i); // Don't have tests for individual ports/types/codes/ids, // just test L4 Proto. Ugly, but can't do much else without @@ -294,75 +305,23 @@ static void ct_dump_stats(struct nl_object *a, struct nl_dump_params *p) } */ -static int exp_cmp_tuples_loose(struct nfnl_ct_dir *a, struct nfnl_ct_dir *b) -{ +static int exp_cmp_l4proto_ports (union nfnl_exp_protodata *a, union nfnl_exp_protodata *b) { // Must return 0 for match, 1 for mismatch - // Parent attribute, so must reflect lower level attribute diffs - int d = exp_cmp_tuples_ip_loose(a, b); - if (d == 0) { - d = exp_cmp_tuples_proto(&a->proto, &b->proto)) - } - return d; -} - -static int exp_cmp_tuples(struct nfnl_exp_dir *a, struct nfnl_exp_dir *b) -{ - // Must return 0 for match, 1 for mismatch - // Parent attribute, so must reflect lower level attribute diffs - int d = exp_cmp_tuples_ip(a, b); - if (d == 0) { - d = exp_cmp_tuples_proto(&a->proto, &b->proto)) - } - return d; -} - -static int exp_cmp_tuples_ip_loose(struct nfnl_exp_dir *a, struct nfnl_exp_dir *b) { - // Must return 0 for match, 1 for mismatch - int d = nl_addr_cmp_prefix(a->src, b->src); - - if (d == 0) { - d = nl_addr_cmp_prefix(a->dst, b->dst); - } - return d; -} - - -static int exp_cmp_tuples_ip(struct nfnl_exp_dir *a, struct nfnl_exp_dir *b) { - // Must return 0 for match, 1 for mismatch - int d = nl_addr_cmp(a->src, b->src); - - if (d == 0) { - d = nl_addr_cmp(a->dst, b->dst); - } - return d; -} - - -static int exp_cmp_tuples_proto(struct nfnl_exp_proto *a, struct nfnl_exp_proto *b) { - // Must return 0 for match, 1 for mismatch - - // Parent attribute, so must reflect lower level attribute diffs - int d = exp_cmp_tuples_protonum(a->l4protonum, b->l4protonum); - - if (d == 0) { - // Check actual proto data - if (a->l4protonum == IPPROTO_ICMP || - a->l4protonum == IPPROTO_ICMPV6) { - d == ( (a->l4protodata.icmp.code != b->l4protodata.icmp.code) || - (a->l4protodata.icmp.type != b->l4protodata.icmp.type) || - (a->l4protodata.icmp.id != b->l4protodata.icmp.id) ) - } else { - d == ( (a->l4protodata.port.src != b->l4protodata.port.src) || - (a->l4protodata.port.dst != b->l4protodata.icmp.dst) ) - } - } + int d = 0; + d = ( (a->port.src != b->port.src) || + (a->port.dst != b->port.dst) ); return d; } -static int exp_cmp_tuples_protonum(uint8_t a, uint8_t b) { +static int exp_cmp_l4proto_icmp (union nfnl_exp_protodata *a, union nfnl_exp_protodata *b) { // Must return 0 for match, 1 for mismatch - return (a != b) + int d = 0; + d = ( (a->icmp.code != b->icmp.code) || + (a->icmp.type != b->icmp.type) || + (a->icmp.id != b->icmp.id) ); + + return d; } static int exp_compare(struct nl_object *_a, struct nl_object *_b, @@ -374,73 +333,97 @@ static int exp_compare(struct nl_object *_a, struct nl_object *_b, #define EXP_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, EXP_ATTR_##ATTR, a, b, EXPR) #define EXP_DIFF_VAL(ATTR, FIELD) EXP_DIFF(ATTR, a->FIELD != b->FIELD) -#define EXP_DIFF_STRING(ATTR, FIELD) EXP_DIFF(ATTR, (strncmp(a->FIELD, b->FIELD, 16) != 0)) +#define EXP_DIFF_STRING(ATTR, FIELD) EXP_DIFF(ATTR, (strcmp(a->FIELD, b->FIELD) != 0)) +#define EXP_DIFF_ADDR(ATTR, FIELD) \ + ((flags & LOOSE_COMPARISON) \ + ? EXP_DIFF(ATTR, nl_addr_cmp_prefix(a->FIELD, b->FIELD)) \ + : EXP_DIFF(ATTR, nl_addr_cmp(a->FIELD, b->FIELD))) +#define EXP_DIFF_L4PROTO_PORTS(ATTR, FIELD) \ + EXP_DIFF(ATTR, exp_cmp_l4proto_ports(a->FIELD, b->FIELD)) +#define EXP_DIFF_L4PROTO_ICMP(ATTR, FIELD) \ + EXP_DIFF(ATTR, exp_cmp_l4proto_icmp(a->FIELD, b->FIELD)) -#define EXP_DIFF_TUPLE(ATTR, FIELD) \ - ((flags & LOOSE_COMPARISON) \ - ? EXP_DIFF(ATTR, exp_cmp_tuples_loose(a->FIELD, b->FIELD)) \ - : EXP_DIFF(ATTR, exp_cmp_tuples(a->FIELD, b->FIELD))) + diff |= EXP_DIFF_VAL(FAMILY, exp_family); + diff |= EXP_DIFF_VAL(TIMEOUT, exp_timeout); + diff |= EXP_DIFF_VAL(ID, exp_id); + diff |= EXP_DIFF_VAL(ZONE, exp_zone); + diff |= EXP_DIFF_VAL(CLASS, exp_class); + diff |= EXP_DIFF_VAL(FLAGS, exp_flags); + diff |= EXP_DIFF_VAL(NAT_DIR, exp_nat_dir); -#define EXP_DIFF_IP(ATTR, FIELD) \ - ((flags & LOOSE_COMPARISON) \ - ? EXP_DIFF(ATTR, exp_cmp_tuples_ip_loose(a->FIELD, b->FIELD)) \ - : EXP_DIFF(ATTR, exp_cmp_tuples_ip(a->FIELD, b->FIELD))) + diff |= EXP_DIFF_STRING(FN, exp_fn); + diff |= EXP_DIFF_STRING(HELPER_NAME, exp_helper_name); -#define EXP_DIFF_PROTO(ATTR, FIELD) \ - EXP_DIFF(ATTR, exp_cmp_tuples_proto(a->FIELD, b->FIELD)) + diff |= EXP_DIFF_ADDR(EXPECT_IP_SRC, exp_expect.src); + diff |= EXP_DIFF_ADDR(EXPECT_IP_DST, exp_expect.dst); + diff |= EXP_DIFF_VAL(EXPECT_L4PROTO_NUM, exp_expect.proto.l4protonum); + diff |= EXP_DIFF_L4PROTO_PORTS(EXPECT_L4PROTO_PORTS, exp_expect.proto.l4protodata.port); + diff |= EXP_DIFF_L4PROTO_ICMP(EXPECT_L4PROTO_ICMP, exp_expect.proto.l4protodata.icmp); - diff |= EXP_DIFF_VAL(FAMILY, exp_family); - diff |= EXP_DIFF_VAL(TIMEOUT, exp_timeout); - diff |= EXP_DIFF_VAL(ID, exp_id); - diff |= EXP_DIFF_VAL(ZONE, exp_zone); - diff |= EXP_DIFF_VAL(CLASS, exp_class); - diff |= EXP_DIFF_VAL(FLAGS, exp_flags); - diff |= EXP_DIFF_VAL(NAT_DIR, exp_flags); + diff |= EXP_DIFF_ADDR(MASTER_IP_SRC, exp_master.src); + diff |= EXP_DIFF_ADDR(MASTER_IP_DST, exp_master.dst); + diff |= EXP_DIFF_VAL(MASTER_L4PROTO_NUM, exp_master.proto.l4protonum); + diff |= EXP_DIFF_L4PROTO_PORTS(MASTER_L4PROTO_PORTS, exp_master.proto.l4protodata.port); + diff |= EXP_DIFF_L4PROTO_ICMP(MASTER_L4PROTO_ICMP, exp_master.proto.l4protodata.icmp); - diff |= EXP_DIFF(FLAGS, (a->exp_flags ^ b->exp_flags)); + diff |= EXP_DIFF_ADDR(MASK_IP_SRC, exp_mask.src); + diff |= EXP_DIFF_ADDR(MASK_IP_DST, exp_mask.dst); + diff |= EXP_DIFF_VAL(MASK_L4PROTO_NUM, exp_mask.proto.l4protonum); + diff |= EXP_DIFF_L4PROTO_PORTS(MASK_L4PROTO_PORTS, exp_mask.proto.l4protodata.port); + diff |= EXP_DIFF_L4PROTO_ICMP(MASK_L4PROTO_ICMP, exp_mask.proto.l4protodata.icmp); -#undef CT_DIFF -#undef CT_DIFF_VAL + diff |= EXP_DIFF_ADDR(NAT_IP_SRC, exp_nat.src); + diff |= EXP_DIFF_ADDR(NAT_IP_DST, exp_nat.dst); + diff |= EXP_DIFF_VAL(NAT_L4PROTO_NUM, exp_nat.proto.l4protonum); + diff |= EXP_DIFF_L4PROTO_PORTS(NAT_L4PROTO_PORTS, exp_nat.proto.l4protodata.port); + diff |= EXP_DIFF_L4PROTO_ICMP(NAT_L4PROTO_ICMP, exp_nat.proto.l4protodata.icmp); + +#undef EXP_DIFF +#undef EXP_DIFF_VAL #undef EXP_DIFF_STRING -#undef CT_DIFF_TUPLE -#undef CT_DIFF_IP -#undef CT_DIFF_PROTO +#undef EXP_DIFF_ADDR +#undef EXP_DIFF_L4PROTO_PORTS +#undef EXP_DIFF_L4PROTO_ICMP - return diff; + return diff; } -static const struct trans_tbl ct_attrs[] = { - __ADD(CT_ATTR_FAMILY, family) - __ADD(CT_ATTR_PROTO, proto) - __ADD(CT_ATTR_TCP_STATE, tcpstate) - __ADD(CT_ATTR_STATUS, status) - __ADD(CT_ATTR_TIMEOUT, timeout) - __ADD(CT_ATTR_MARK, mark) - __ADD(CT_ATTR_USE, use) - __ADD(CT_ATTR_ID, id) - __ADD(CT_ATTR_ORIG_SRC, origsrc) - __ADD(CT_ATTR_ORIG_DST, origdst) - __ADD(CT_ATTR_ORIG_SRC_PORT, origsrcport) - __ADD(CT_ATTR_ORIG_DST_PORT, origdstport) - __ADD(CT_ATTR_ORIG_ICMP_ID, origicmpid) - __ADD(CT_ATTR_ORIG_ICMP_TYPE, origicmptype) - __ADD(CT_ATTR_ORIG_ICMP_CODE, origicmpcode) - __ADD(CT_ATTR_ORIG_PACKETS, origpackets) - __ADD(CT_ATTR_ORIG_BYTES, origbytes) - __ADD(CT_ATTR_REPL_SRC, replysrc) - __ADD(CT_ATTR_REPL_DST, replydst) - __ADD(CT_ATTR_REPL_SRC_PORT, replysrcport) - __ADD(CT_ATTR_REPL_DST_PORT, replydstport) - __ADD(CT_ATTR_REPL_ICMP_ID, replyicmpid) - __ADD(CT_ATTR_REPL_ICMP_TYPE, replyicmptype) - __ADD(CT_ATTR_REPL_ICMP_CODE, replyicmpcode) - __ADD(CT_ATTR_REPL_PACKETS, replypackets) - __ADD(CT_ATTR_REPL_BYTES, replybytes) +// CLI arguments? +static const struct trans_tbl exp_attrs[] = { + __ADD(EXP_ATTR_FAMILY, family) + __ADD(EXP_ATTR_TIMEOUT, timeout) + __ADD(EXP_ATTR_ID, id) + __ADD(EXP_ATTR_HELPER_NAME, helpername) + __ADD(EXP_ATTR_ZONE, zone) + __ADD(EXP_ATTR_CLASS, class) + __ADD(EXP_ATTR_FLAGS, flags) + __ADD(EXP_ATTR_FN, function) + __ADD(EXP_ATTR_EXPECT_IP_SRC, expectipsrc) + __ADD(EXP_ATTR_EXPECT_IP_DST, expectipdst) + __ADD(EXP_ATTR_EXPECT_L4PROTO_NUM, expectprotonum) + __ADD(EXP_ATTR_EXPECT_L4PROTO_PORTS,expectports) + __ADD(EXP_ATTR_EXPECT_L4PROTO_ICMP ,expecticmp) + __ADD(EXP_ATTR_MASTER_IP_SRC, masteripsrc) + __ADD(EXP_ATTR_MASTER_IP_DST, masteripdst) + __ADD(EXP_ATTR_MASTER_L4PROTO_NUM, masterprotonum) + __ADD(EXP_ATTR_MASTER_L4PROTO_PORTS,masterports) + __ADD(EXP_ATTR_MASTER_L4PROTO_ICMP ,mastericmp) + __ADD(EXP_ATTR_MASK_IP_SRC, maskipsrc) + __ADD(EXP_ATTR_MASK_IP_DST, maskipdst) + __ADD(EXP_ATTR_MASK_L4PROTO_NUM, maskprotonum) + __ADD(EXP_ATTR_MASK_L4PROTO_PORTS, maskports) + __ADD(EXP_ATTR_MASK_L4PROTO_ICMP , maskicmp) + __ADD(EXP_ATTR_NAT_IP_SRC, natipsrc) + __ADD(EXP_ATTR_NAT_IP_DST, natipdst) + __ADD(EXP_ATTR_NAT_L4PROTO_NUM, natprotonum) + __ADD(EXP_ATTR_NAT_L4PROTO_PORTS, natports) + __ADD(EXP_ATTR_NAT_L4PROTO_ICMP, naticmp) + __ADD(EXP_ATTR_NAT_DIR, natdir) }; -static char *ct_attrs2str(int attrs, char *buf, size_t len) +static char *exp_attrs2str(int attrs, char *buf, size_t len) { - return __flags2str(attrs, buf, len, ct_attrs, ARRAY_SIZE(ct_attrs)); + return __flags2str(attrs, buf, len, exp_attrs, ARRAY_SIZE(exp_attrs)); } /** @@ -448,19 +431,19 @@ static char *ct_attrs2str(int attrs, char *buf, size_t len) * @{ */ -struct nfnl_ct *nfnl_ct_alloc(void) +struct nfnl_exp *nfnl_exp_alloc(void) { - return (struct nfnl_ct *) nl_object_alloc(&ct_obj_ops); + return (struct nfnl_exp *) nl_object_alloc(&exp_obj_ops); } -void nfnl_ct_get(struct nfnl_ct *ct) +void nfnl_exp_get(struct nfnl_exp *exp) { - nl_object_get((struct nl_object *) ct); + nl_object_get((struct nl_object *) exp); } -void nfnl_ct_put(struct nfnl_ct *ct) +void nfnl_exp_put(struct nfnl_exp *exp) { - nl_object_put((struct nl_object *) ct); + nl_object_put((struct nl_object *) exp); } /** @} */ @@ -484,22 +467,6 @@ uint8_t nfnl_exp_get_family(const struct nfnl_exp *exp) return AF_UNSPEC; } -void nfnl_exp_set_proto(struct nfnl_exp *exp, uint8_t proto) -{ - exp->exp_proto = proto; - exp->ce_mask |= EXP_ATTR_PROTO; -} - -int nfnl_exp_test_proto(const struct nfnl_exp *exp) -{ - return !!(exp->ce_mask & EXP_ATTR_PROTO); -} - -uint8_t nfnl_exp_get_proto(const struct nfnl_exp *ct) -{ - return exp->ct_proto; -} - void nfnl_exp_set_flags(struct nfnl_exp *exp, uint32_t flags) { exp->exp_flags |= flags; @@ -512,7 +479,7 @@ void nfnl_exp_unset_flags(struct nfnl_exp *exp, uint32_t flags) exp->ce_mask |= EXP_ATTR_FLAGS; } -uint32_t nfnl_exp_get_status(const struct nfnl_exp *exp) +uint32_t nfnl_exp_get_flags(const struct nfnl_exp *exp) { return exp->exp_flags; } @@ -525,11 +492,11 @@ static const struct trans_tbl flag_table[] = { char * nfnl_exp_flags2str(int flags, char *buf, size_t len) { - return __flags2str(flags, buf, len, status_flags, + return __flags2str(flags, buf, len, flag_table, ARRAY_SIZE(flag_table)); } -int nfnl_exp_str2status(const char *name) +int nfnl_exp_str2flags(const char *name) { return __str2flags(name, flag_table, ARRAY_SIZE(flag_table)); } @@ -566,6 +533,75 @@ uint32_t nfnl_exp_get_id(const struct nfnl_exp *exp) return exp->exp_id; } +static struct nfnl_exp_dir *exp_get_dir(struct nfnl_exp *exp, int tuple) +{ + struct nfnl_exp_dir *dir = NULL; + + switch (tuple) { + case NFNL_EXP_TUPLE_MASTER: + dir = &exp->exp_master; + break; + case NFNL_EXP_TUPLE_MASK: + dir = &exp->exp_mask; + break; + case NFNL_EXP_TUPLE_NAT: + dir = &exp->exp_nat; + break; + case NFNL_EXP_TUPLE_EXPECT: + default : + dir = &exp->exp_expect; + break; + } + return dir; +} + +static int exp_get_src_attr(int tuple) +{ + int attr = 0; + + switch (tuple) { + case NFNL_EXP_TUPLE_MASTER: + attr = EXP_ATTR_MASTER_IP_SRC; + break; + case NFNL_EXP_TUPLE_MASK: + attr = EXP_ATTR_MASK_IP_SRC; + break; + case NFNL_EXP_TUPLE_NAT: + attr = EXP_ATTR_NAT_IP_SRC; + break; + case NFNL_EXP_TUPLE_EXPECT: + default : + attr = EXP_ATTR_EXPECT_IP_SRC; + break; + } + + return attr; +} + +static int exp_get_dst_attr(int tuple) +{ + int attr = 0; + + switch (tuple) { + case NFNL_EXP_TUPLE_MASTER: + attr = EXP_ATTR_MASTER_IP_DST; + break; + case NFNL_EXP_TUPLE_MASK: + attr = EXP_ATTR_MASK_IP_DST; + break; + case NFNL_EXP_TUPLE_NAT: + attr = EXP_ATTR_NAT_IP_DST; + break; + case NFNL_EXP_TUPLE_EXPECT: + default : + attr = EXP_ATTR_EXPECT_IP_DST; + break; + } + + return attr; +} + + static int exp_set_addr(struct nfnl_exp *exp, struct nl_addr *addr, int attr, struct nl_addr ** exp_addr) { @@ -587,104 +623,172 @@ static int exp_set_addr(struct nfnl_exp *exp, struct nl_addr *addr, int nfnl_exp_set_src(struct nfnl_exp *exp, int tuple, struct nl_addr *addr) { - struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; - int attr = repl ? CT_ATTR_REPL_SRC : CT_ATTR_ORIG_SRC; + struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); - switch (tuple) { - case : - dir = &exp->exp_expect; - attr = EXP_ATTR_ - break; - case : - dir = &exp->exp_master; - break; - case : - dir = &exp->exp_mask; - break; - case : - dir = &exp->exp_nat; - default : - } - - return ct_set_addr(ct, addr, attr, &dir->src); + return exp_set_addr(exp, addr, exp_get_src_attr(tuple), &dir->src); } -int nfnl_ct_set_dst(struct nfnl_ct *ct, int repl, struct nl_addr *addr) +int nfnl_exp_set_dst(struct nfnl_exp *exp, int tuple, struct nl_addr *addr) { - struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; - int attr = repl ? CT_ATTR_REPL_DST : CT_ATTR_ORIG_DST; - return ct_set_addr(ct, addr, attr, &dir->dst); + struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + + return exp_set_addr(exp, addr, exp_get_dst_attr(tuple), &dir->dst); } -struct nl_addr *nfnl_ct_get_src(const struct nfnl_ct *ct, int repl) +int nfnl_exp_test_src(const struct nfnl_exp *exp, int tuple) { - const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; - int attr = repl ? CT_ATTR_REPL_SRC : CT_ATTR_ORIG_SRC; - if (!(ct->ce_mask & attr)) + return !!(exp->ce_mask & exp_get_src_attr(tuple)); +} + +int nfnl_exp_test_dst(const struct nfnl_exp *exp, int tuple) +{ + + return !!(exp->ce_mask & exp_get_dst_attr(tuple)); +} + +struct nl_addr *nfnl_exp_get_src(const struct nfnl_exp *exp, int tuple) +{ + const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + + if (!(exp->ce_mask & exp_get_src_attr(tuple))) return NULL; return dir->src; } -struct nl_addr *nfnl_ct_get_dst(const struct nfnl_ct *ct, int repl) +struct nl_addr *nfnl_exp_get_dst(const struct nfnl_exp *exp, int tuple) { - const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; - int attr = repl ? CT_ATTR_REPL_DST : CT_ATTR_ORIG_DST; - if (!(ct->ce_mask & attr)) + const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + + if (!(exp->ce_mask & exp_get_dst_attr(tuple))) return NULL; return dir->dst; } -void nfnl_ct_set_src_port(struct nfnl_ct *ct, int repl, uint16_t port) +static int exp_get_l4protonum_attr(int tuple) { - struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; - int attr = repl ? CT_ATTR_REPL_SRC_PORT : CT_ATTR_ORIG_SRC_PORT; + int attr = 0; - dir->proto.port.src = port; - ct->ce_mask |= attr; + switch (tuple) { + case NFNL_EXP_TUPLE_MASTER: + attr = EXP_ATTR_MASTER_L4PROTO_NUM; + break; + case NFNL_EXP_TUPLE_MASK: + attr = EXP_ATTR_MASK_L4PROTO_NUM; + break; + case NFNL_EXP_TUPLE_NAT: + attr = EXP_ATTR_NAT_L4PROTO_NUM; + break; + case NFNL_EXP_TUPLE_EXPECT: + default : + attr = EXP_ATTR_EXPECT_L4PROTO_NUM; + break; + } + + return attr; } -int nfnl_ct_test_src_port(const struct nfnl_ct *ct, int repl) +void nfnl_exp_set_l4protonum(struct nfnl_exp *exp, int tuple, uint8_t l4protonum) { - int attr = repl ? CT_ATTR_REPL_SRC_PORT : CT_ATTR_ORIG_SRC_PORT; - return !!(ct->ce_mask & attr); + const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + + dir->proto.l4protonum = l4protonum; + exp->ce_mask |= exp_get_l4protonum_attr(exp, tuple); } -uint16_t nfnl_ct_get_src_port(const struct nfnl_ct *ct, int repl) +int nfnl_exp_test_l4protonum(const struct nfnl_exp *exp, int tuple) { - const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; - - return dir->proto.port.src; + return !!(exp->ce_mask & exp_get_l4protonum_attr(exp, tuple)); } -void nfnl_ct_set_dst_port(struct nfnl_ct *ct, int repl, uint16_t port) +struct uint8_t * nfnl_exp_get_l4protonum(const struct nfnl_exp *exp, int tuple) { - struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; - int attr = repl ? CT_ATTR_REPL_DST_PORT : CT_ATTR_ORIG_DST_PORT; - - dir->proto.port.dst = port; - ct->ce_mask |= attr; + const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + return dir->proto.l4protonum; } -int nfnl_ct_test_dst_port(const struct nfnl_ct *ct, int repl) +static int exp_get_l4ports_attr(int tuple) { - int attr = repl ? CT_ATTR_REPL_DST_PORT : CT_ATTR_ORIG_DST_PORT; - return !!(ct->ce_mask & attr); + int attr = 0; + + switch (tuple) { + case NFNL_EXP_TUPLE_MASTER: + attr = EXP_ATTR_MASTER_L4PROTO_PORTS; + break; + case NFNL_EXP_TUPLE_MASK: + attr = EXP_ATTR_MASK_L4PROTO_PORTS; + break; + case NFNL_EXP_TUPLE_NAT: + attr = EXP_ATTR_NAT_L4PROTO_PORTS; + break; + case NFNL_EXP_TUPLE_EXPECT: + default : + attr = EXP_ATTR_EXPECT_L4PROTO_PORTS; + break; + } + + return attr; } -uint16_t nfnl_ct_get_dst_port(const struct nfnl_ct *ct, int repl) +void nfnl_exp_set_src_ports(struct nfnl_exp *exp, int tuple, uint16_t srcport, uint16_t dstport) { - const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); - return dir->proto.port.dst; + dir->proto.l4protodata.port.src = srcport; + dir->proto.l4protodata.port.dst = dstport; + + exp->ce_mask |= exp_get_l4ports_attr(tuple); } -void nfnl_ct_set_icmp_id(struct nfnl_ct *ct, int repl, uint16_t id) +int nfnl_exp_test_ports(const struct nfnl_exp *exp, int tuple) { - struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; - int attr = repl ? CT_ATTR_REPL_ICMP_ID : CT_ATTR_ORIG_ICMP_ID; + return !!(exp->ce_mask & exp_get_l4ports_attr(tuple)); +} - dir->proto.icmp.id = id; - ct->ce_mask |= attr; +uint16_t nfnl_exp_get_src_port(const struct nfnl_exp *exp, int tuple) +{ + const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + return dir->proto.l4protodata.port.src; +} + +uint16_t nfnl_exp_get_dst_port(const struct nfnl_exp *exp, int tuple) +{ + const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + + return dir->proto.l4protodata.port.dst; +} + +static int exp_get_l4icmp_attr(int tuple) +{ + int attr = 0; + + switch (tuple) { + case NFNL_EXP_TUPLE_MASTER: + attr = EXP_ATTR_MASTER_L4PROTO_ICMP; + break; + case NFNL_EXP_TUPLE_MASK: + attr = EXP_ATTR_MASK_L4PROTO_ICMP; + break; + case NFNL_EXP_TUPLE_NAT: + attr = EXP_ATTR_NAT_L4PROTO_ICMP; + break; + case NFNL_EXP_TUPLE_EXPECT: + default : + attr = EXP_ATTR_EXPECT_L4PROTO_ICMP; + break; + } + + return attr; +} + +void nfnl_ct_set_icmp(struct nfnl_exp *exp, int tuple, uint16_t id, uint8_t type, uint8_t, code) +{ + struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + + dir->proto.l4protodata.icmp.id = id; + dir->proto.l4protodata.icmp.type = type; + dir->proto.l4protodata.icmp.code = code; + + exp->ce_mask |= exp_get_l4icmp_attr(tuple); } int nfnl_ct_test_icmp_id(const struct nfnl_ct *ct, int repl) From c675bf048669e6387213018298787f4f9415401f Mon Sep 17 00:00:00 2001 From: Rich Fought Date: Mon, 8 Oct 2012 15:26:55 -0700 Subject: [PATCH 249/432] Checkpoint before compilation attempt --- include/Makefile.am | 1 + include/netlink/netfilter/exp.h | 4 - lib/Makefile.am | 3 +- lib/netfilter/exp.c | 431 ++++++++++++++------------------ lib/netfilter/exp_obj.c | 337 +++++++++++++++---------- 5 files changed, 399 insertions(+), 377 deletions(-) diff --git a/include/Makefile.am b/include/Makefile.am index 2ba0ece..80c615c 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -16,6 +16,7 @@ nobase_libnlinclude_HEADERS = \ netlink/netfilter/nfnl.h \ netlink/netfilter/queue.h \ netlink/netfilter/queue_msg.h \ + netlink/netfilter/exp.h \ netlink/addr.h \ netlink/attr.h \ netlink/cache-api.h \ diff --git a/include/netlink/netfilter/exp.h b/include/netlink/netfilter/exp.h index 7ace0e5..ba18b24 100644 --- a/include/netlink/netfilter/exp.h +++ b/include/netlink/netfilter/exp.h @@ -60,10 +60,6 @@ extern int nfnl_exp_query(struct nl_sock *, const struct nfnl_exp *, int); extern void nfnl_exp_set_family(struct nfnl_exp *, uint8_t); extern uint8_t nfnl_exp_get_family(const struct nfnl_exp *); -extern void nfnl_exp_set_proto(struct nfnl_exp *, uint8_t); -extern int nfnl_exp_test_proto(const struct nfnl_exp *); -extern uint8_t nfnl_exp_get_proto(const struct nfnl_exp *); - extern void nfnl_exp_set_timeout(struct nfnl_exp *, uint32_t); extern int nfnl_exp_test_timeout(const struct nfnl_exp *); extern uint32_t nfnl_exp_get_timeout(const struct nfnl_exp *); diff --git a/lib/Makefile.am b/lib/Makefile.am index 9e5efd8..e31e594 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -29,7 +29,8 @@ libnl_nf_3_la_SOURCES = \ netfilter/ct.c netfilter/ct_obj.c netfilter/log.c \ netfilter/log_msg.c netfilter/log_msg_obj.c netfilter/log_obj.c \ netfilter/netfilter.c netfilter/nfnl.c netfilter/queue.c \ - netfilter/queue_msg.c netfilter/queue_msg_obj.c netfilter/queue_obj.c + netfilter/queue_msg.c netfilter/queue_msg_obj.c netfilter/queue_obj.c \ + netfilter/exp.c netfilter/exp_obj.c CLEANFILES = \ route/pktloc_grammar.c route/pktloc_grammar.h \ diff --git a/lib/netfilter/exp.c b/lib/netfilter/exp.c index 59ee1d9..9e29c35 100644 --- a/lib/netfilter/exp.c +++ b/lib/netfilter/exp.c @@ -1,5 +1,5 @@ /* - * lib/netfilter/ct.c Conntrack + * lib/netfilter/ct.c Conntrack Expectation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -14,7 +14,7 @@ /** * @ingroup nfnl - * @defgroup ct Conntrack + * @defgroup exp Expectation * @brief * @{ */ @@ -26,9 +26,9 @@ #include #include #include -#include +#include -static struct nl_cache_ops nfnl_ct_ops; +static struct nl_cache_ops nfnl_exp_ops; #if __BYTE_ORDER == __BIG_ENDIAN static uint64_t ntohll(uint64_t x) @@ -42,35 +42,33 @@ static uint64_t ntohll(uint64_t x) } #endif -static struct nla_policy ct_policy[CTA_MAX+1] = { - [CTA_TUPLE_ORIG] = { .type = NLA_NESTED }, - [CTA_TUPLE_REPLY] = { .type = NLA_NESTED }, - [CTA_STATUS] = { .type = NLA_U32 }, - [CTA_PROTOINFO] = { .type = NLA_NESTED }, - //[CTA_HELP] - //[CTA_NAT_SRC] - [CTA_TIMEOUT] = { .type = NLA_U32 }, - [CTA_MARK] = { .type = NLA_U32 }, - [CTA_COUNTERS_ORIG] = { .type = NLA_NESTED }, - [CTA_COUNTERS_REPLY] = { .type = NLA_NESTED }, - [CTA_USE] = { .type = NLA_U32 }, - [CTA_ID] = { .type = NLA_U32 }, - //[CTA_NAT_DST] +static struct nla_policy exp_policy[CTA_EXPECT_MAX+1] = { + [CTA_EXPECT_MASTER] = { .type = NLA_NESTED }, + [CTA_EXPECT_TUPLE] = { .type = NLA_NESTED }, + [CTA_EXPECT_MASK] = { .type = NLA_NESTED }, + [CTA_EXPECT_TIMEOUT] = { .type = NLA_U32 }, + [CTA_EXPECT_ID] = { .type = NLA_U32 }, + [CTA_EXPECT_HELP_NAME] = { .type = NLA_STRING }, + //[CTA_EXPECT_ZONE] = { .type = NLA_U16 }, // In latest kernel header + //[CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, // In latest kernel header + //[CTA_EXPECT_CLASS] = { .type = NLA_U32 }, // In libnetfilter_conntrack include/linux/linux_nfnetlink_conntrack.h + //[CTA_EXPECT_NAT] = { .type = NLA_NESTED }, // In libnetfilter_conntrack include/linux/linux_nfnetlink_conntrack.h + //[CTA_EXPECT_FN] = { .type = NLA_STRING }, // In libnetfilter_conntrack include/linux/linux_nfnetlink_conntrack.h }; -static struct nla_policy ct_tuple_policy[CTA_TUPLE_MAX+1] = { +static struct nla_policy exp_tuple_policy[CTA_TUPLE_MAX+1] = { [CTA_TUPLE_IP] = { .type = NLA_NESTED }, [CTA_TUPLE_PROTO] = { .type = NLA_NESTED }, }; -static struct nla_policy ct_ip_policy[CTA_IP_MAX+1] = { +static struct nla_policy exp_ip_policy[CTA_IP_MAX+1] = { [CTA_IP_V4_SRC] = { .type = NLA_U32 }, [CTA_IP_V4_DST] = { .type = NLA_U32 }, [CTA_IP_V6_SRC] = { .minlen = 16 }, [CTA_IP_V6_DST] = { .minlen = 16 }, }; -static struct nla_policy ct_proto_policy[CTA_PROTO_MAX+1] = { +static struct nla_policy exp_proto_policy[CTA_PROTO_MAX+1] = { [CTA_PROTO_NUM] = { .type = NLA_U8 }, [CTA_PROTO_SRC_PORT] = { .type = NLA_U16 }, [CTA_PROTO_DST_PORT] = { .type = NLA_U16 }, @@ -82,33 +80,14 @@ static struct nla_policy ct_proto_policy[CTA_PROTO_MAX+1] = { [CTA_PROTO_ICMPV6_CODE] = { .type = NLA_U8 }, }; -static struct nla_policy ct_protoinfo_policy[CTA_PROTOINFO_MAX+1] = { - [CTA_PROTOINFO_TCP] = { .type = NLA_NESTED }, -}; -static struct nla_policy ct_protoinfo_tcp_policy[CTA_PROTOINFO_TCP_MAX+1] = { - [CTA_PROTOINFO_TCP_STATE] = { .type = NLA_U8 }, - [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = { .type = NLA_U8 }, - [CTA_PROTOINFO_TCP_WSCALE_REPLY] = { .type = NLA_U8 }, - [CTA_PROTOINFO_TCP_FLAGS_ORIGINAL] = { .minlen = 2 }, - [CTA_PROTOINFO_TCP_FLAGS_REPLY] = { .minlen = 2 }, - -}; - -static struct nla_policy ct_counters_policy[CTA_COUNTERS_MAX+1] = { - [CTA_COUNTERS_PACKETS] = { .type = NLA_U64 }, - [CTA_COUNTERS_BYTES] = { .type = NLA_U64 }, - [CTA_COUNTERS32_PACKETS]= { .type = NLA_U32 }, - [CTA_COUNTERS32_BYTES] = { .type = NLA_U32 }, -}; - -static int ct_parse_ip(struct nfnl_ct *ct, int repl, struct nlattr *attr) +static int exp_parse_ip(struct nfnl_exp *exp, int tuple, struct nlattr *attr) { struct nlattr *tb[CTA_IP_MAX+1]; struct nl_addr *addr; int err; - err = nla_parse_nested(tb, CTA_IP_MAX, attr, ct_ip_policy); + err = nla_parse_nested(tb, CTA_IP_MAX, attr, exp_ip_policy); if (err < 0) goto errout; @@ -116,7 +95,7 @@ static int ct_parse_ip(struct nfnl_ct *ct, int repl, struct nlattr *attr) addr = nl_addr_alloc_attr(tb[CTA_IP_V4_SRC], AF_INET); if (addr == NULL) goto errout_enomem; - err = nfnl_ct_set_src(ct, repl, addr); + err = nfnl_exp_set_src(exp, tuple, addr); nl_addr_put(addr); if (err < 0) goto errout; @@ -125,7 +104,7 @@ static int ct_parse_ip(struct nfnl_ct *ct, int repl, struct nlattr *attr) addr = nl_addr_alloc_attr(tb[CTA_IP_V4_DST], AF_INET); if (addr == NULL) goto errout_enomem; - err = nfnl_ct_set_dst(ct, repl, addr); + err = nfnl_exp_set_dst(exp, tuple, addr); nl_addr_put(addr); if (err < 0) goto errout; @@ -134,7 +113,7 @@ static int ct_parse_ip(struct nfnl_ct *ct, int repl, struct nlattr *attr) addr = nl_addr_alloc_attr(tb[CTA_IP_V6_SRC], AF_INET6); if (addr == NULL) goto errout_enomem; - err = nfnl_ct_set_src(ct, repl, addr); + err = nfnl_exp_set_src(exp, tuple, addr); nl_addr_put(addr); if (err < 0) goto errout; @@ -143,7 +122,7 @@ static int ct_parse_ip(struct nfnl_ct *ct, int repl, struct nlattr *attr) addr = nl_addr_alloc_attr(tb[CTA_IP_V6_DST], AF_INET6); if (addr == NULL) goto errout_enomem; - err = nfnl_ct_set_dst(ct, repl, addr); + err = nfnl_exp_set_dst(exp, tuple, addr); nl_addr_put(addr); if (err < 0) goto errout; @@ -157,53 +136,55 @@ errout: return err; } -static int ct_parse_proto(struct nfnl_ct *ct, int repl, struct nlattr *attr) +static int exp_parse_proto(struct nfnl_exp *exp, int tuple, struct nlattr *attr) { struct nlattr *tb[CTA_PROTO_MAX+1]; int err; + uint16_t srcport = 0, dstport = 0, icmpid = 0; + uint8_t icmptype = 0, icmpcode = 0; - err = nla_parse_nested(tb, CTA_PROTO_MAX, attr, ct_proto_policy); + err = nla_parse_nested(tb, CTA_PROTO_MAX, attr, exp_proto_policy); if (err < 0) return err; - if (!repl && tb[CTA_PROTO_NUM]) - nfnl_ct_set_proto(ct, nla_get_u8(tb[CTA_PROTO_NUM])); - if (tb[CTA_PROTO_SRC_PORT]) - nfnl_ct_set_src_port(ct, repl, - ntohs(nla_get_u16(tb[CTA_PROTO_SRC_PORT]))); - if (tb[CTA_PROTO_DST_PORT]) - nfnl_ct_set_dst_port(ct, repl, - ntohs(nla_get_u16(tb[CTA_PROTO_DST_PORT]))); - if (tb[CTA_PROTO_ICMP_ID]) - nfnl_ct_set_icmp_id(ct, repl, - ntohs(nla_get_u16(tb[CTA_PROTO_ICMP_ID]))); - if (tb[CTA_PROTO_ICMP_TYPE]) - nfnl_ct_set_icmp_type(ct, repl, - nla_get_u8(tb[CTA_PROTO_ICMP_TYPE])); - if (tb[CTA_PROTO_ICMP_CODE]) - nfnl_ct_set_icmp_code(ct, repl, - nla_get_u8(tb[CTA_PROTO_ICMP_CODE])); + if (tb[CTA_PROTO_NUM]) + nfnl_exp_set_l4protonum(exp, tuple, nla_get_u8(tb[CTA_PROTO_NUM])); + if (tb[CTA_PROTO_SRC_PORT]) + srcport = ntohs(nla_get_u16(tb[CTA_PROTO_SRC_PORT])); + if (tb[CTA_PROTO_DST_PORT]) + dstport = ntohs(nla_get_u16(tb[CTA_PROTO_DST_PORT])); + if (tb[CTA_PROTO_SRC_PORT] || tb[CTA_PROTO_DST_PORT]) + nfnl_exp_set_ports(exp, tuple, srcport, dstport); + + if (tb[CTA_PROTO_ICMP_ID]) + icmpid = ntohs(nla_get_u16(tb[CTA_PROTO_ICMP_ID])); + if (tb[CTA_PROTO_ICMP_TYPE]) + icmptype = nla_get_u8(tb[CTA_PROTO_ICMP_TYPE]); + if (tb[CTA_PROTO_ICMP_CODE]) + icmpcode = nla_get_u8(tb[CTA_PROTO_ICMP_CODE]); + if (tb[CTA_PROTO_ICMP_ID] || tb[CTA_PROTO_ICMP_TYPE] || tb[CTA_PROTO_ICMP_CODE]) + nfnl_exp_set_icmp(exp, tuple, icmpid, icmptype, icmpcode); return 0; } -static int ct_parse_tuple(struct nfnl_ct *ct, int repl, struct nlattr *attr) +static int exp_parse_tuple(struct nfnl_exp *exp, int tuple, struct nlattr *attr) { struct nlattr *tb[CTA_TUPLE_MAX+1]; int err; - err = nla_parse_nested(tb, CTA_TUPLE_MAX, attr, ct_tuple_policy); + err = nla_parse_nested(tb, CTA_TUPLE_MAX, attr, exp_tuple_policy); if (err < 0) return err; if (tb[CTA_TUPLE_IP]) { - err = ct_parse_ip(ct, repl, tb[CTA_TUPLE_IP]); + err = exp_parse_ip(exp, tuple, tb[CTA_TUPLE_IP]); if (err < 0) return err; } if (tb[CTA_TUPLE_PROTO]) { - err = ct_parse_proto(ct, repl, tb[CTA_TUPLE_PROTO]); + err = exp_parse_proto(exp, tuple, tb[CTA_TUPLE_PROTO]); if (err < 0) return err; } @@ -211,185 +192,132 @@ static int ct_parse_tuple(struct nfnl_ct *ct, int repl, struct nlattr *attr) return 0; } -static int ct_parse_protoinfo_tcp(struct nfnl_ct *ct, struct nlattr *attr) -{ - struct nlattr *tb[CTA_PROTOINFO_TCP_MAX+1]; - int err; - - err = nla_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr, - ct_protoinfo_tcp_policy); - if (err < 0) - return err; - - if (tb[CTA_PROTOINFO_TCP_STATE]) - nfnl_ct_set_tcp_state(ct, - nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE])); - - return 0; -} - -static int ct_parse_protoinfo(struct nfnl_ct *ct, struct nlattr *attr) -{ - struct nlattr *tb[CTA_PROTOINFO_MAX+1]; - int err; - - err = nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr, - ct_protoinfo_policy); - if (err < 0) - return err; - - if (tb[CTA_PROTOINFO_TCP]) { - err = ct_parse_protoinfo_tcp(ct, tb[CTA_PROTOINFO_TCP]); - if (err < 0) - return err; - } - - return 0; -} - -static int ct_parse_counters(struct nfnl_ct *ct, int repl, struct nlattr *attr) -{ - struct nlattr *tb[CTA_COUNTERS_MAX+1]; - int err; - - err = nla_parse_nested(tb, CTA_COUNTERS_MAX, attr, ct_counters_policy); - if (err < 0) - return err; - - if (tb[CTA_COUNTERS_PACKETS]) - nfnl_ct_set_packets(ct, repl, - ntohll(nla_get_u64(tb[CTA_COUNTERS_PACKETS]))); - if (tb[CTA_COUNTERS32_PACKETS]) - nfnl_ct_set_packets(ct, repl, - ntohl(nla_get_u32(tb[CTA_COUNTERS32_PACKETS]))); - if (tb[CTA_COUNTERS_BYTES]) - nfnl_ct_set_bytes(ct, repl, - ntohll(nla_get_u64(tb[CTA_COUNTERS_BYTES]))); - if (tb[CTA_COUNTERS32_BYTES]) - nfnl_ct_set_bytes(ct, repl, - ntohl(nla_get_u32(tb[CTA_COUNTERS32_BYTES]))); - - return 0; -} - -int nfnlmsg_ct_group(struct nlmsghdr *nlh) +int nfnlmsg_exp_group(struct nlmsghdr *nlh) { switch (nfnlmsg_subtype(nlh)) { - case IPCTNL_MSG_CT_NEW: + case IPCTNL_MSG_EXP_NEW: if (nlh->nlmsg_flags & (NLM_F_CREATE|NLM_F_EXCL)) - return NFNLGRP_CONNTRACK_NEW; + return NFNLGRP_CONNTRACK_EXP_NEW; else - return NFNLGRP_CONNTRACK_UPDATE; - case IPCTNL_MSG_CT_DELETE: - return NFNLGRP_CONNTRACK_DESTROY; + return NFNLGRP_CONNTRACK_EXP_UPDATE; + case IPCTNL_MSG_EXP_DELETE: + return NFNLGRP_CONNTRACK_EXP_DESTROY; default: return NFNLGRP_NONE; } } -int nfnlmsg_ct_parse(struct nlmsghdr *nlh, struct nfnl_ct **result) +int nfnlmsg_exp_parse(struct nlmsghdr *nlh, struct nfnl_exp **result) { - struct nfnl_ct *ct; + struct nfnl_exp *exp; struct nlattr *tb[CTA_MAX+1]; int err; - ct = nfnl_ct_alloc(); - if (!ct) + exp = nfnl_exp_alloc(); + if (!exp) return -NLE_NOMEM; - ct->ce_msgtype = nlh->nlmsg_type; + exp->ce_msgtype = nlh->nlmsg_type; - err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, CTA_MAX, - ct_policy); + err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, CTA_EXPECT_MAX, + exp_policy); if (err < 0) goto errout; - nfnl_ct_set_family(ct, nfnlmsg_family(nlh)); + nfnl_exp_set_family(exp, nfnlmsg_family(nlh)); - if (tb[CTA_TUPLE_ORIG]) { - err = ct_parse_tuple(ct, 0, tb[CTA_TUPLE_ORIG]); + if (tb[CTA_EXPECT_TUPLE]) { + err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_EXPECT, tb[CTA_EXPECT_TUPLE]); + if (err < 0) + goto errout; + } + if (tb[CTA_EXPECT_MASTER]) { + err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_MASTER, tb[CTA_EXPECT_MASTER]); if (err < 0) goto errout; } - if (tb[CTA_TUPLE_REPLY]) { - err = ct_parse_tuple(ct, 1, tb[CTA_TUPLE_REPLY]); + if (tb[CTA_EXPECT_MASK]) { + err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_MASK, tb[CTA_EXPECT_MASK]); if (err < 0) goto errout; } - if (tb[CTA_PROTOINFO]) { - err = ct_parse_protoinfo(ct, tb[CTA_PROTOINFO]); - if (err < 0) - goto errout; - } + if (tb[CTA_EXPECT_TIMEOUT]) + nfnl_exp_set_timeout(exp, ntohl(nla_get_u32(tb[CTA_EXPECT_TIMEOUT]))); + if (tb[CTA_EXPECT_ID]) + nfnl_exp_set_id(exp, ntohl(nla_get_u32(tb[CTA_EXPECT_ID]))); + if (tb[CTA_EXPECT_HELP_NAME]) + nfnl_exp_set_helper_name(exp, nla_data(tb[CTA_EXPECT_HELP_NAME])); - if (tb[CTA_STATUS]) - nfnl_ct_set_status(ct, ntohl(nla_get_u32(tb[CTA_STATUS]))); - if (tb[CTA_TIMEOUT]) - nfnl_ct_set_timeout(ct, ntohl(nla_get_u32(tb[CTA_TIMEOUT]))); - if (tb[CTA_MARK]) - nfnl_ct_set_mark(ct, ntohl(nla_get_u32(tb[CTA_MARK]))); - if (tb[CTA_USE]) - nfnl_ct_set_use(ct, ntohl(nla_get_u32(tb[CTA_USE]))); - if (tb[CTA_ID]) - nfnl_ct_set_id(ct, ntohl(nla_get_u32(tb[CTA_ID]))); - - if (tb[CTA_COUNTERS_ORIG]) { - err = ct_parse_counters(ct, 0, tb[CTA_COUNTERS_ORIG]); - if (err < 0) - goto errout; - } - - if (tb[CTA_COUNTERS_REPLY]) { - err = ct_parse_counters(ct, 1, tb[CTA_COUNTERS_REPLY]); - if (err < 0) - goto errout; - } - - *result = ct; + *result = exp; return 0; errout: - nfnl_ct_put(ct); + nfnl_exp_put(exp); return err; } -static int ct_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, +static int exp_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, struct nlmsghdr *nlh, struct nl_parser_param *pp) { - struct nfnl_ct *ct; + struct nfnl_exp *exp; int err; - if ((err = nfnlmsg_ct_parse(nlh, &ct)) < 0) + if ((err = nfnlmsg_exp_parse(nlh, &exp)) < 0) goto errout; - err = pp->pp_cb((struct nl_object *) ct, pp); + err = pp->pp_cb((struct nl_object *) exp, pp); errout: - nfnl_ct_put(ct); + nfnl_exp_put(exp); return err; } -int nfnl_ct_dump_request(struct nl_sock *sk) +int nfnl_exp_dump_request(struct nl_sock *sk) { - return nfnl_send_simple(sk, NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET, + return nfnl_send_simple(sk, NFNL_SUBSYS_CTNETLINK_EXP, IPCTNL_MSG_EXP_GET, NLM_F_DUMP, AF_UNSPEC, 0); } -static int ct_request_update(struct nl_cache *cache, struct nl_sock *sk) +static int exp_request_update(struct nl_cache *cache, struct nl_sock *sk) { - return nfnl_ct_dump_request(sk); + return nfnl_exp_dump_request(sk); } -static int nfnl_ct_build_tuple(struct nl_msg *msg, const struct nfnl_ct *ct, - int repl) +static int exp_get_tuple_attr(int tuple) +{ + int attr = 0; + + switch (tuple) { + case NFNL_EXP_TUPLE_MASTER: + attr = CTA_EXPECT_MASTER; + break; + case NFNL_EXP_TUPLE_MASK: + attr = CTA_EXPECT_MASK; + break; + //case NFNL_EXP_TUPLE_NAT: + // attr = EXP_ATTR_NAT_L4PROTO_NUM; + // break; + case NFNL_EXP_TUPLE_EXPECT: + default : + attr = CTA_EXPECT_TUPLE; + break; + } + + return attr; +} + +static int nfnl_exp_build_tuple(struct nl_msg *msg, const struct nfnl_exp *exp, + int type) { struct nlattr *tuple, *ip, *proto; struct nl_addr *addr; int family; - family = nfnl_ct_get_family(ct); + int tupattr = exp_get_tuple_attr(type); - tuple = nla_nest_start(msg, repl ? CTA_TUPLE_REPLY : CTA_TUPLE_ORIG); + family = nfnl_exp_get_family(exp); + + tuple = nla_nest_start(msg, tupattr); if (!tuple) goto nla_put_failure; @@ -397,13 +325,13 @@ static int nfnl_ct_build_tuple(struct nl_msg *msg, const struct nfnl_ct *ct, if (!ip) goto nla_put_failure; - addr = nfnl_ct_get_src(ct, repl); + addr = nfnl_exp_get_src(exp, type); if (addr) NLA_PUT_ADDR(msg, family == AF_INET ? CTA_IP_V4_SRC : CTA_IP_V6_SRC, addr); - addr = nfnl_ct_get_dst(ct, repl); + addr = nfnl_exp_get_dst(exp, type); if (addr) NLA_PUT_ADDR(msg, family == AF_INET ? CTA_IP_V4_DST : CTA_IP_V6_DST, @@ -415,28 +343,27 @@ static int nfnl_ct_build_tuple(struct nl_msg *msg, const struct nfnl_ct *ct, if (!proto) goto nla_put_failure; - if (nfnl_ct_test_proto(ct)) - NLA_PUT_U8(msg, CTA_PROTO_NUM, nfnl_ct_get_proto(ct)); + if (nfnl_exp_test_l4protonum(exp, type)) + NLA_PUT_U8(msg, CTA_PROTO_NUM, nfnl_exp_get_l4protonum(exp, type)); - if (nfnl_ct_test_src_port(ct, repl)) + if (nfnl_exp_test_ports(exp, type)) { NLA_PUT_U16(msg, CTA_PROTO_SRC_PORT, - htons(nfnl_ct_get_src_port(ct, repl))); + htons(nfnl_exp_get_src_port(exp, type))); - if (nfnl_ct_test_dst_port(ct, repl)) NLA_PUT_U16(msg, CTA_PROTO_DST_PORT, - htons(nfnl_ct_get_dst_port(ct, repl))); + htons(nfnl_exp_get_dst_port(exp, type))); + } - if (nfnl_ct_test_icmp_id(ct, repl)) + if (nfnl_exp_test_icmp(exp, type)) { NLA_PUT_U16(msg, CTA_PROTO_ICMP_ID, - htons(nfnl_ct_get_icmp_id(ct, repl))); + htons(nfnl_exp_get_icmp_id(exp, type))); - if (nfnl_ct_test_icmp_type(ct, repl)) NLA_PUT_U8(msg, CTA_PROTO_ICMP_TYPE, - nfnl_ct_get_icmp_type(ct, repl)); + nfnl_exp_get_icmp_type(exp, type)); - if (nfnl_ct_test_icmp_code(ct, repl)) NLA_PUT_U8(msg, CTA_PROTO_ICMP_CODE, - nfnl_ct_get_icmp_code(ct, repl)); + nfnl_exp_get_icmp_code(exp, type)); + } nla_nest_end(msg, proto); @@ -447,20 +374,36 @@ nla_put_failure: return -NLE_MSGSIZE; } -static int nfnl_ct_build_message(const struct nfnl_ct *ct, int cmd, int flags, +static int nfnl_exp_build_message(const struct nfnl_exp *exp, int cmd, int flags, struct nl_msg **result) { struct nl_msg *msg; int err; - msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_CTNETLINK, cmd, flags, - nfnl_ct_get_family(ct), 0); + msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_CTNETLINK_EXP, cmd, flags, + nfnl_exp_get_family(exp), 0); if (msg == NULL) return -NLE_NOMEM; - if ((err = nfnl_ct_build_tuple(msg, ct, 0)) < 0) + if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_TUPLE)) < 0) goto err_out; + if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_MASTER)) < 0) + goto err_out; + + if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_MASK)) < 0) + goto err_out; + + // FIXME timeout and helper name + if (nfnl_exp_test_id(exp)) + NLA_PUT_U32(msg, CTA_EXPECT_ID, htonl(nfnl_exp_get_id(exp))); + + if (nfnl_exp_test_timeout(exp)) + NLA_PUT_U32(msg, CTA_EXPECT_TIMEOUT, htonl(nfnl_exp_get_timeout(exp))); + + if (nfnl_exp_test_helper_name(exp)) + NLA_PUT_STRING(msg, CTA_EXPECT_HELP_NAME, nfnl_exp_get_helper_name(exp)); + *result = msg; return 0; @@ -469,18 +412,18 @@ err_out: return err; } -int nfnl_ct_build_add_request(const struct nfnl_ct *ct, int flags, +int nfnl_exp_build_add_request(const struct nfnl_exp *exp, int flags, struct nl_msg **result) { - return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_NEW, flags, result); + return nfnl_exp_build_message(exp, IPCTNL_MSG_EXP_NEW, flags, result); } -int nfnl_ct_add(struct nl_sock *sk, const struct nfnl_ct *ct, int flags) +int nfnl_exp_add(struct nl_sock *sk, const struct nfnl_exp *exp, int flags) { struct nl_msg *msg; int err; - if ((err = nfnl_ct_build_add_request(ct, flags, &msg)) < 0) + if ((err = nfnl_exp_build_add_request(exp, flags, &msg)) < 0) return err; err = nl_send_auto_complete(sk, msg); @@ -491,18 +434,18 @@ int nfnl_ct_add(struct nl_sock *sk, const struct nfnl_ct *ct, int flags) return wait_for_ack(sk); } -int nfnl_ct_build_delete_request(const struct nfnl_ct *ct, int flags, +int nfnl_exp_build_delete_request(const struct nfnl_exp *exp, int flags, struct nl_msg **result) { - return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_DELETE, flags, result); + return nfnl_exp_build_message(exp, IPCTNL_MSG_EXP_DELETE, flags, result); } -int nfnl_ct_del(struct nl_sock *sk, const struct nfnl_ct *ct, int flags) +int nfnl_exp_del(struct nl_sock *sk, const struct nfnl_exp *exp, int flags) { struct nl_msg *msg; int err; - if ((err = nfnl_ct_build_delete_request(ct, flags, &msg)) < 0) + if ((err = nfnl_exp_build_delete_request(exp, flags, &msg)) < 0) return err; err = nl_send_auto_complete(sk, msg); @@ -513,18 +456,18 @@ int nfnl_ct_del(struct nl_sock *sk, const struct nfnl_ct *ct, int flags) return wait_for_ack(sk); } -int nfnl_ct_build_query_request(const struct nfnl_ct *ct, int flags, +int nfnl_exp_build_query_request(const struct nfnl_exp *exp, int flags, struct nl_msg **result) { - return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_GET, flags, result); + return nfnl_exp_build_message(exp, IPCTNL_MSG_EXP_GET, flags, result); } -int nfnl_ct_query(struct nl_sock *sk, const struct nfnl_ct *ct, int flags) +int nfnl_exp_query(struct nl_sock *sk, const struct nfnl_exp *exp, int flags) { struct nl_msg *msg; int err; - if ((err = nfnl_ct_build_query_request(ct, flags, &msg)) < 0) + if ((err = nfnl_exp_build_query_request(exp, flags, &msg)) < 0) return err; err = nl_send_auto_complete(sk, msg); @@ -541,61 +484,61 @@ int nfnl_ct_query(struct nl_sock *sk, const struct nfnl_ct *ct, int flags) */ /** - * Build a conntrack cache holding all conntrack currently in the kernel + * Build a expectation cache holding all expectations currently in the kernel * @arg sk Netlink socket. * @arg result Pointer to store resulting cache. * * Allocates a new cache, initializes it properly and updates it to - * contain all conntracks currently in the kernel. + * contain all expectations currently in the kernel. * * @return 0 on success or a negative error code. */ -int nfnl_ct_alloc_cache(struct nl_sock *sk, struct nl_cache **result) +int nfnl_exp_alloc_cache(struct nl_sock *sk, struct nl_cache **result) { - return nl_cache_alloc_and_fill(&nfnl_ct_ops, sk, result); + return nl_cache_alloc_and_fill(&nfnl_exp_ops, sk, result); } /** @} */ /** - * @name Conntrack Addition + * @name Expectation Addition * @{ */ /** @} */ -static struct nl_af_group ct_groups[] = { - { AF_UNSPEC, NFNLGRP_CONNTRACK_NEW }, - { AF_UNSPEC, NFNLGRP_CONNTRACK_UPDATE }, - { AF_UNSPEC, NFNLGRP_CONNTRACK_DESTROY }, +static struct nl_af_group exp_groups[] = { + { AF_UNSPEC, NFNLGRP_CONNTRACK_EXP_NEW }, + { AF_UNSPEC, NFNLGRP_CONNTRACK_EXP_UPDATE }, + { AF_UNSPEC, NFNLGRP_CONNTRACK_EXP_DESTROY }, { END_OF_GROUP_LIST }, }; -#define NFNLMSG_CT_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_CTNETLINK, (type)) -static struct nl_cache_ops nfnl_ct_ops = { - .co_name = "netfilter/ct", +#define NFNLMSG_EXP_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_CTNETLINK_EXP, (type)) +static struct nl_cache_ops nfnl_exp_ops = { + .co_name = "netfilter/exp", .co_hdrsize = NFNL_HDRLEN, .co_msgtypes = { - { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_NEW), NL_ACT_NEW, "new" }, - { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_GET), NL_ACT_GET, "get" }, - { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_DELETE), NL_ACT_DEL, "del" }, + { NFNLMSG_CT_TYPE(IPCTNL_MSG_EXP_NEW), NL_ACT_NEW, "new" }, + { NFNLMSG_CT_TYPE(IPCTNL_MSG_EXP_GET), NL_ACT_GET, "get" }, + { NFNLMSG_CT_TYPE(IPCTNL_MSG_EXP_DELETE), NL_ACT_DEL, "del" }, END_OF_MSGTYPES_LIST, }, .co_protocol = NETLINK_NETFILTER, - .co_groups = ct_groups, - .co_request_update = ct_request_update, - .co_msg_parser = ct_msg_parser, - .co_obj_ops = &ct_obj_ops, + .co_groups = exp_groups, + .co_request_update = exp_request_update, + .co_msg_parser = exp_msg_parser, + .co_obj_ops = &exp_obj_ops, }; -static void __init ct_init(void) +static void __init exp_init(void) { - nl_cache_mngt_register(&nfnl_ct_ops); + nl_cache_mngt_register(&nfnl_exp_ops); } -static void __exit ct_exit(void) +static void __exit exp_exit(void) { - nl_cache_mngt_unregister(&nfnl_ct_ops); + nl_cache_mngt_unregister(&nfnl_exp_ops); } /** @} */ diff --git a/lib/netfilter/exp_obj.c b/lib/netfilter/exp_obj.c index 2a45f3e..160c939 100644 --- a/lib/netfilter/exp_obj.c +++ b/lib/netfilter/exp_obj.c @@ -33,9 +33,9 @@ #define EXP_ATTR_ID (1UL << 2) // 32-bit #define EXP_ATTR_HELPER_NAME (1UL << 3) // string (16 bytes max) #define EXP_ATTR_ZONE (1UL << 4) // 16-bit -#define EXP_ATTR_CLASS (1UL << 5) // 32-bit +#define EXP_ATTR_CLASS (1UL << 5) // 32-bit ??? #define EXP_ATTR_FLAGS (1UL << 6) // 32-bit -#define EXP_ATTR_FN (1UL << 7) // String +#define EXP_ATTR_FN (1UL << 7) // String ??? // Tuples #define EXP_ATTR_EXPECT_IP_SRC (1UL << 8) @@ -59,7 +59,7 @@ #define EXP_ATTR_NAT_L4PROTO_PORTS (1UL << 26) #define EXP_ATTR_NAT_L4PROTO_ICMP (1UL << 27) -#define EXP_ATTR_NAT_DIR (1UL << 28) +#define EXP_ATTR_NAT_DIR (1UL << 28) // 8-bit /** @endcond */ static void exp_free_data(struct nl_object *c) @@ -150,7 +150,7 @@ static int exp_clone(struct nl_object *_dst, struct nl_object *_src) } if (src->exp_fn) - dst->exp_fn = strdup(src->exp_fn) + dst->exp_fn = strdup(src->exp_fn); if (src->exp_helper_name) dst->exp_helper_name = strdup(src->exp_helper_name); @@ -171,23 +171,26 @@ static void dump_addr(struct nl_dump_params *p, struct nl_addr *addr, int port) nl_dump(p, " "); } -static void dump_icmp(struct nl_dump_params *p, struct nfnl_ct *ct, int tuple) +static void dump_icmp(struct nl_dump_params *p, struct nfnl_exp *exp, int tuple) { - nl_dump(p, "icmp type %d ", nfnl_exp_get_icmp_type(ct, tuple)); + if (nfnl_exp_test_icmp(exp, tuple)) { - nl_dump(p, "code %d ", nfnl_exp_get_icmp_code(ct, tuple)); + nl_dump(p, "icmp type %d ", nfnl_exp_get_icmp_type(exp, tuple)); - nl_dump(p, "id %d ", nfnl_exp_get_icmp_id(ct, tuple)); + nl_dump(p, "code %d ", nfnl_exp_get_icmp_code(exp, tuple)); + + nl_dump(p, "id %d ", nfnl_exp_get_icmp_id(exp, tuple)); + } } -static void ct_dump_tuples(struct nfnl_exp *exp, struct nl_dump_params *p) +static void exp_dump_tuples(struct nfnl_exp *exp, struct nl_dump_params *p) { struct nl_addr *tuple_src, *tuple_dst; int tuple_sport = 0, tuple_dport = 0; - int i = NFNL_EXP_TUPLE_EXPECT; - int icmp = 0; + int i = 0; + char buf[64]; - for (i; i <= NFNL_EXP_TUPLE_NAT; i++) { + for (i = NFNL_EXP_TUPLE_EXPECT; i <= NFNL_EXP_TUPLE_NAT; i++) { // Test needed for NAT case if (nfnl_exp_test_src(exp, i)) @@ -196,65 +199,68 @@ static void ct_dump_tuples(struct nfnl_exp *exp, struct nl_dump_params *p) tuple_dst = nfnl_exp_get_dst(exp, i); // Don't have tests for individual ports/types/codes/ids, - // just test L4 Proto. Ugly, but can't do much else without - // more mask bits + if (nfnl_exp_test_l4protonum(exp)) { + nl_dump(p, "%s ", + nl_ip_proto2str(nfnl_exp_get_l4protonum(exp), buf, sizeof(buf))); + } - if (nfnl_exp_test_l4proto(exp, i)) { - int l4proto = nfnl_exp_get_l4proto(exp, i); - if ( !(l4proto == IPPROTO_ICMP || - l4proto == IPPROTO_ICMPV6) ) { - tuple_sport = nfnl_exp_get_src_port(exp, i); - tuple_dport = nfnl_exp_get_dst_port(exp, i); - } else { - icmp = 1; - } + if (nfnl_exp_test_ports(exp, i)) { + tuple_sport = nfnl_exp_get_src_port(exp, i); + tuple_dport = nfnl_exp_get_dst_port(exp, i); } dump_addr(p, tuple_src, tuple_sport); dump_addr(p, tuple_dst, tuple_dport); - if (icmp) - dump_icmp(p, exp, 0); + dump_icmp(p, exp, 0); } + + if (nfnl_exp_test_nat_dir(exp)) + nl_dump(p, "nat dir %s ", exp->exp_nat_dir); + } -/* Compatible with /proc/net/nf_conntrack */ -static void ct_dump_line(struct nl_object *a, struct nl_dump_params *p) +/* FIXME Compatible with /proc/net/nf_conntrack */ +static void exp_dump_line(struct nl_object *a, struct nl_dump_params *p) { - struct nfnl_ct *ct = (struct nfnl_ct *) a; - char buf[64]; + struct nfnl_exp *exp = (struct nfnl_exp *) a; nl_new_line(p); - if (nfnl_ct_test_proto(ct)) - nl_dump(p, "%s ", - nl_ip_proto2str(nfnl_ct_get_proto(ct), buf, sizeof(buf))); - - ct_dump_tuples(ct, p); + exp_dump_tuples(exp, p); nl_dump(p, "\n"); } -static void ct_dump_details(struct nl_object *a, struct nl_dump_params *p) +static void exp_dump_details(struct nl_object *a, struct nl_dump_params *p) { - struct nfnl_ct *ct = (struct nfnl_ct *) a; + struct nfnl_exp *exp = (struct nfnl_exp *) a; char buf[64]; int fp = 0; ct_dump_line(a, p); - nl_dump(p, " id 0x%x ", ct->ct_id); + nl_dump(p, " id 0x%x ", exp->exp_id); nl_dump_line(p, "family %s ", - nl_af2str(ct->ct_family, buf, sizeof(buf))); + nl_af2str(exp->exp_family, buf, sizeof(buf))); - if (nfnl_ct_test_use(ct)) - nl_dump(p, "refcnt %u ", nfnl_ct_get_use(ct)); - - if (nfnl_ct_test_timeout(ct)) { - uint64_t timeout_ms = nfnl_ct_get_timeout(ct) * 1000UL; + if (nfnl_exp_test_timeout(exp)) { + uint64_t timeout_ms = nfnl_ct_get_timeout(exp) * 1000UL; nl_dump(p, "timeout %s ", nl_msec2str(timeout_ms, buf, sizeof(buf))); } - if (ct->ct_status) + if (nfnl_exp_test_helper_name(exp)) + nl_dump(p, "helper %s ", exp->exp_helper_name); + + if (nfnl_exp_test_fn(exp)) + nl_dump(p, "fn %s ", exp->exp_fn); + + if (nfnl_exp_test_zone(exp)) + nl_dump(p, "zone %u ", nfnl_exp_get_zone(exp)); + + if (nfnl_exp_test_class(exp)) + nl_dump(p, "class %u ", nfnl_exp_get_class(exp)); + + if (nfnl_exp_test_flags(exp)) nl_dump(p, "<"); #define PRINT_FLAG(str) \ @@ -268,7 +274,7 @@ static void ct_dump_details(struct nl_object *a, struct nl_dump_params *p) PRINT_FLAG("USERSPACE"); #undef PRINT_FLAG - if (exp->exp_flags) + if (nfnl_exp_test_flags(exp)) nl_dump(p, ">"); nl_dump(p, "\n"); } @@ -360,23 +366,23 @@ static int exp_compare(struct nl_object *_a, struct nl_object *_b, diff |= EXP_DIFF_L4PROTO_PORTS(EXPECT_L4PROTO_PORTS, exp_expect.proto.l4protodata.port); diff |= EXP_DIFF_L4PROTO_ICMP(EXPECT_L4PROTO_ICMP, exp_expect.proto.l4protodata.icmp); - diff |= EXP_DIFF_ADDR(MASTER_IP_SRC, exp_master.src); - diff |= EXP_DIFF_ADDR(MASTER_IP_DST, exp_master.dst); + diff |= EXP_DIFF_ADDR(MASTER_IP_SRC, exp_master.src); + diff |= EXP_DIFF_ADDR(MASTER_IP_DST, exp_master.dst); diff |= EXP_DIFF_VAL(MASTER_L4PROTO_NUM, exp_master.proto.l4protonum); diff |= EXP_DIFF_L4PROTO_PORTS(MASTER_L4PROTO_PORTS, exp_master.proto.l4protodata.port); - diff |= EXP_DIFF_L4PROTO_ICMP(MASTER_L4PROTO_ICMP, exp_master.proto.l4protodata.icmp); + diff |= EXP_DIFF_L4PROTO_ICMP(MASTER_L4PROTO_ICMP, exp_master.proto.l4protodata.icmp); - diff |= EXP_DIFF_ADDR(MASK_IP_SRC, exp_mask.src); - diff |= EXP_DIFF_ADDR(MASK_IP_DST, exp_mask.dst); + diff |= EXP_DIFF_ADDR(MASK_IP_SRC, exp_mask.src); + diff |= EXP_DIFF_ADDR(MASK_IP_DST, exp_mask.dst); diff |= EXP_DIFF_VAL(MASK_L4PROTO_NUM, exp_mask.proto.l4protonum); diff |= EXP_DIFF_L4PROTO_PORTS(MASK_L4PROTO_PORTS, exp_mask.proto.l4protodata.port); - diff |= EXP_DIFF_L4PROTO_ICMP(MASK_L4PROTO_ICMP, exp_mask.proto.l4protodata.icmp); + diff |= EXP_DIFF_L4PROTO_ICMP(MASK_L4PROTO_ICMP, exp_mask.proto.l4protodata.icmp); - diff |= EXP_DIFF_ADDR(NAT_IP_SRC, exp_nat.src); - diff |= EXP_DIFF_ADDR(NAT_IP_DST, exp_nat.dst); + diff |= EXP_DIFF_ADDR(NAT_IP_SRC, exp_nat.src); + diff |= EXP_DIFF_ADDR(NAT_IP_DST, exp_nat.dst); diff |= EXP_DIFF_VAL(NAT_L4PROTO_NUM, exp_nat.proto.l4protonum); diff |= EXP_DIFF_L4PROTO_PORTS(NAT_L4PROTO_PORTS, exp_nat.proto.l4protodata.port); - diff |= EXP_DIFF_L4PROTO_ICMP(NAT_L4PROTO_ICMP, exp_nat.proto.l4protodata.icmp); + diff |= EXP_DIFF_L4PROTO_ICMP(NAT_L4PROTO_ICMP, exp_nat.proto.l4protodata.icmp); #undef EXP_DIFF #undef EXP_DIFF_VAL @@ -390,35 +396,35 @@ static int exp_compare(struct nl_object *_a, struct nl_object *_b, // CLI arguments? static const struct trans_tbl exp_attrs[] = { - __ADD(EXP_ATTR_FAMILY, family) - __ADD(EXP_ATTR_TIMEOUT, timeout) - __ADD(EXP_ATTR_ID, id) - __ADD(EXP_ATTR_HELPER_NAME, helpername) - __ADD(EXP_ATTR_ZONE, zone) - __ADD(EXP_ATTR_CLASS, class) - __ADD(EXP_ATTR_FLAGS, flags) - __ADD(EXP_ATTR_FN, function) - __ADD(EXP_ATTR_EXPECT_IP_SRC, expectipsrc) - __ADD(EXP_ATTR_EXPECT_IP_DST, expectipdst) - __ADD(EXP_ATTR_EXPECT_L4PROTO_NUM, expectprotonum) - __ADD(EXP_ATTR_EXPECT_L4PROTO_PORTS,expectports) - __ADD(EXP_ATTR_EXPECT_L4PROTO_ICMP ,expecticmp) - __ADD(EXP_ATTR_MASTER_IP_SRC, masteripsrc) - __ADD(EXP_ATTR_MASTER_IP_DST, masteripdst) - __ADD(EXP_ATTR_MASTER_L4PROTO_NUM, masterprotonum) - __ADD(EXP_ATTR_MASTER_L4PROTO_PORTS,masterports) - __ADD(EXP_ATTR_MASTER_L4PROTO_ICMP ,mastericmp) - __ADD(EXP_ATTR_MASK_IP_SRC, maskipsrc) - __ADD(EXP_ATTR_MASK_IP_DST, maskipdst) - __ADD(EXP_ATTR_MASK_L4PROTO_NUM, maskprotonum) - __ADD(EXP_ATTR_MASK_L4PROTO_PORTS, maskports) - __ADD(EXP_ATTR_MASK_L4PROTO_ICMP , maskicmp) - __ADD(EXP_ATTR_NAT_IP_SRC, natipsrc) - __ADD(EXP_ATTR_NAT_IP_DST, natipdst) - __ADD(EXP_ATTR_NAT_L4PROTO_NUM, natprotonum) - __ADD(EXP_ATTR_NAT_L4PROTO_PORTS, natports) - __ADD(EXP_ATTR_NAT_L4PROTO_ICMP, naticmp) - __ADD(EXP_ATTR_NAT_DIR, natdir) + __ADD(EXP_ATTR_FAMILY, family) + __ADD(EXP_ATTR_TIMEOUT, timeout) + __ADD(EXP_ATTR_ID, id) + __ADD(EXP_ATTR_HELPER_NAME, helpername) + __ADD(EXP_ATTR_ZONE, zone) + __ADD(EXP_ATTR_CLASS, class) + __ADD(EXP_ATTR_FLAGS, flags) + __ADD(EXP_ATTR_FN, function) + __ADD(EXP_ATTR_EXPECT_IP_SRC, expectipsrc) + __ADD(EXP_ATTR_EXPECT_IP_DST, expectipdst) + __ADD(EXP_ATTR_EXPECT_L4PROTO_NUM, expectprotonum) + __ADD(EXP_ATTR_EXPECT_L4PROTO_PORTS, expectports) + __ADD(EXP_ATTR_EXPECT_L4PROTO_ICMP , expecticmp) + __ADD(EXP_ATTR_MASTER_IP_SRC, masteripsrc) + __ADD(EXP_ATTR_MASTER_IP_DST, masteripdst) + __ADD(EXP_ATTR_MASTER_L4PROTO_NUM, masterprotonum) + __ADD(EXP_ATTR_MASTER_L4PROTO_PORTS, masterports) + __ADD(EXP_ATTR_MASTER_L4PROTO_ICMP , mastericmp) + __ADD(EXP_ATTR_MASK_IP_SRC, maskipsrc) + __ADD(EXP_ATTR_MASK_IP_DST, maskipdst) + __ADD(EXP_ATTR_MASK_L4PROTO_NUM, maskprotonum) + __ADD(EXP_ATTR_MASK_L4PROTO_PORTS, maskports) + __ADD(EXP_ATTR_MASK_L4PROTO_ICMP , maskicmp) + __ADD(EXP_ATTR_NAT_IP_SRC, natipsrc) + __ADD(EXP_ATTR_NAT_IP_DST, natipdst) + __ADD(EXP_ATTR_NAT_L4PROTO_NUM, natprotonum) + __ADD(EXP_ATTR_NAT_L4PROTO_PORTS, natports) + __ADD(EXP_ATTR_NAT_L4PROTO_ICMP, naticmp) + __ADD(EXP_ATTR_NAT_DIR, natdir) }; static char *exp_attrs2str(int attrs, char *buf, size_t len) @@ -533,6 +539,112 @@ uint32_t nfnl_exp_get_id(const struct nfnl_exp *exp) return exp->exp_id; } +int nfnl_exp_set_helper_name(struct nfnl_exp *exp, void *name) +{ + free(exp->exp_helper_name); + exp->exp_helper_name = strdup(name); + if (!exp->exp_helper_name) + return -NLE_NOMEM; + + exp->ce_mask |= EXP_ATTR_HELPER_NAME; + return 0; +} + +int nfnl_exp_test_helper_name(const struct nfnl_exp *exp) +{ + return !!(exp->ce_mask & EXP_ATTR_HELPER_NAME); +} + +const char * nfnl_exp_get_helper_name(const struct nfnl_exp *exp) +{ + return exp->exp_helper_name; +} + +void nfnl_exp_set_zone(struct nfnl_exp *exp, uint16_t zone) +{ + exp->exp_zone = zone; + exp->ce_mask |= EXP_ATTR_ZONE; +} + +int nfnl_exp_test_zone(const struct nfnl_exp *exp) +{ + return !!(exp->ce_mask & EXP_ATTR_ZONE); +} + +uint16_t nfnl_exp_get_zone(const struct nfnl_exp *exp) +{ + return exp->exp_zone; +} + +void nfnl_exp_set_class(struct nfnl_exp *exp, uint32_t class) +{ + exp->exp_class = class; + exp->ce_mask |= EXP_ATTR_CLASS; +} + +int nfnl_exp_test_class(const struct nfnl_exp *exp) +{ + return !!(exp->ce_mask & EXP_ATTR_CLASS); +} + +uint32_t nfnl_exp_get_class(const struct nfnl_exp *exp) +{ + return exp->exp_class; +} + +void nfnl_exp_set_flags(struct nfnl_exp *exp, uint32_t flags) +{ + exp->exp_flags = flags; + exp->ce_mask |= EXP_ATTR_FLAGS; +} + +int nfnl_exp_test_flags(const struct nfnl_exp *exp) +{ + return !!(exp->ce_mask & EXP_ATTR_FLAGS); +} + +uint32_t nfnl_exp_get_flags(const struct nfnl_exp *exp) +{ + return exp->exp_flags; +} + +int nfnl_exp_set_fn(struct nfnl_exp *exp, void *fn) +{ + free(exp->exp_fn); + exp->exp_fn = strdup(fn); + if (!exp->exp_fn) + return -NLE_NOMEM; + + exp->ce_mask |= EXP_ATTR_FN; + return 0; +} + +int nfnl_exp_test_fn(const struct nfnl_exp *exp) +{ + return !!(exp->ce_mask & EXP_ATTR_FN); +} + +const char * nfnl_exp_get_fn(const struct nfnl_exp *exp) +{ + return exp->exp_fn; +} + +void nfnl_exp_set_nat_dir(struct nfnl_exp *exp, uint8_t nat_dir) +{ + exp->exp_nat_dir = nat_dir; + exp->ce_mask |= EXP_ATTR_NAT_DIR; +} + +int nfnl_exp_test_nat_dir(const struct nfnl_exp *exp) +{ + return !!(exp->ce_mask & EXP_ATTR_NAT_DIR); +} + +uint8_t nfnl_exp_get_nat_dir(const struct nfnl_exp *exp) +{ + return exp->exp_nat_dir; +} + static struct nfnl_exp_dir *exp_get_dir(struct nfnl_exp *exp, int tuple) { struct nfnl_exp_dir *dir = NULL; @@ -729,7 +841,7 @@ static int exp_get_l4ports_attr(int tuple) return attr; } -void nfnl_exp_set_src_ports(struct nfnl_exp *exp, int tuple, uint16_t srcport, uint16_t dstport) +void nfnl_exp_set_ports(struct nfnl_exp *exp, int tuple, uint16_t srcport, uint16_t dstport) { struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); @@ -780,7 +892,7 @@ static int exp_get_l4icmp_attr(int tuple) return attr; } -void nfnl_ct_set_icmp(struct nfnl_exp *exp, int tuple, uint16_t id, uint8_t type, uint8_t, code) +void nfnl_exp_set_icmp(struct nfnl_exp *exp, int tuple, uint16_t id, uint8_t type, uint8_t, code) { struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); @@ -791,61 +903,31 @@ void nfnl_ct_set_icmp(struct nfnl_exp *exp, int tuple, uint16_t id, uint8_t type exp->ce_mask |= exp_get_l4icmp_attr(tuple); } -int nfnl_ct_test_icmp_id(const struct nfnl_ct *ct, int repl) +int nfnl_exp_test_icmp(const struct nfnl_exp *exp, int tuple) { - int attr = repl ? CT_ATTR_REPL_ICMP_ID : CT_ATTR_ORIG_ICMP_ID; - return !!(ct->ce_mask & attr); + int attr = exp_get_l4icmp_attr(tuple); + return !!(exp->ce_mask & attr); } -uint16_t nfnl_ct_get_icmp_id(const struct nfnl_ct *ct, int repl) +uint16_t nfnl_exp_get_icmp_id(const struct nfnl_exp *exp, int tuple) { - const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); - return dir->proto.icmp.id; + return dir->proto.l4protodata.icmp.id; } -void nfnl_ct_set_icmp_type(struct nfnl_ct *ct, int repl, uint8_t type) +uint8_t nfnl_exp_get_icmp_type(const struct nfnl_exp *exp, int tuple) { - struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; - int attr = repl ? CT_ATTR_REPL_ICMP_TYPE : CT_ATTR_ORIG_ICMP_TYPE; + const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); - dir->proto.icmp.type = type; - ct->ce_mask |= attr; + return dir->proto.l4protodata.icmp.type; } -int nfnl_ct_test_icmp_type(const struct nfnl_ct *ct, int repl) +uint8_t nfnl_ct_get_icmp_code(const struct nfnl_exp *exp, int tuple) { - int attr = repl ? CT_ATTR_REPL_ICMP_TYPE : CT_ATTR_ORIG_ICMP_TYPE; - return !!(ct->ce_mask & attr); -} + const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); -uint8_t nfnl_ct_get_icmp_type(const struct nfnl_ct *ct, int repl) -{ - const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; - - return dir->proto.icmp.type; -} - -void nfnl_ct_set_icmp_code(struct nfnl_ct *ct, int repl, uint8_t code) -{ - struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; - int attr = repl ? CT_ATTR_REPL_ICMP_CODE : CT_ATTR_ORIG_ICMP_CODE; - - dir->proto.icmp.code = code; - ct->ce_mask |= attr; -} - -int nfnl_ct_test_icmp_code(const struct nfnl_ct *ct, int repl) -{ - int attr = repl ? CT_ATTR_REPL_ICMP_CODE : CT_ATTR_ORIG_ICMP_CODE; - return !!(ct->ce_mask & attr); -} - -uint8_t nfnl_ct_get_icmp_code(const struct nfnl_ct *ct, int tuple) -{ - const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; - - return dir->proto.icmp.code; + return dir->proto.l4protodata.icmp.code; } /** @} */ @@ -858,7 +940,6 @@ struct nl_object_ops exp_obj_ops = { .oo_dump = { [NL_DUMP_LINE] = exp_dump_line, [NL_DUMP_DETAILS] = exp_dump_details, - [NL_DUMP_STATS] = exp_dump_stats, }, .oo_compare = exp_compare, .oo_attrs2str = exp_attrs2str, From f111efd894560a3f5d4393ff9aa59d1d87b78f6e Mon Sep 17 00:00:00 2001 From: Rich Fought Date: Mon, 8 Oct 2012 16:49:06 -0700 Subject: [PATCH 250/432] Successful compilation of libnl-nf with expectation --- include/netlink/netfilter/exp.h | 28 +++----- lib/netfilter/exp.c | 19 ++---- lib/netfilter/exp_obj.c | 116 +++++++++++++------------------- 3 files changed, 57 insertions(+), 106 deletions(-) diff --git a/include/netlink/netfilter/exp.h b/include/netlink/netfilter/exp.h index ba18b24..bb4c98e 100644 --- a/include/netlink/netfilter/exp.h +++ b/include/netlink/netfilter/exp.h @@ -88,24 +88,24 @@ extern int nfnl_exp_set_fn(struct nfnl_exp *, void *); extern int nfnl_exp_test_fn(const struct nfnl_exp *); extern const char * nfnl_exp_get_fn(const struct nfnl_exp *); -extern void nfnl_exp_set_nat_dir(struct nfnl_exp *, int, uint8_t); -extern int nfnl_exp_test_nat_dir(const struct nfnl_exp *, int); -extern uint8_t nfnl_exp_get_nat_dir(const struct nfnl_exp *, int); +extern void nfnl_exp_set_nat_dir(struct nfnl_exp *, uint8_t); +extern int nfnl_exp_test_nat_dir(const struct nfnl_exp *); +extern uint8_t nfnl_exp_get_nat_dir(const struct nfnl_exp *); -// The int argument specifies which nfnl_ct_dir (expect, master, mask or nat) +// The int argument specifies which nfnl_exp_dir (expect, master, mask or nat) // Expectation objects only use orig, not reply extern int nfnl_exp_set_src(struct nfnl_exp *, int, struct nl_addr *); -extern int nfnl_exp_test_src(const struct nfnl_exp *); -extern struct nl_addr * nfnl_ct_get_src(const struct nfnl_exp *, int); +extern int nfnl_exp_test_src(const struct nfnl_exp *, int); +extern struct nl_addr * nfnl_exp_get_src(const struct nfnl_exp *, int); extern int nfnl_exp_set_dst(struct nfnl_exp *, int, struct nl_addr *); -extern int nfnl_exp_test_dst(const struct nfnl_exp *); +extern int nfnl_exp_test_dst(const struct nfnl_exp *, int); extern struct nl_addr * nfnl_exp_get_dst(const struct nfnl_exp *, int); extern void nfnl_exp_set_l4protonum(struct nfnl_exp *, int, uint8_t); extern int nfnl_exp_test_l4protonum(const struct nfnl_exp *, int); -extern uint8_t * nfnl_exp_get_l4protonum(const struct nfnl_exp *, int); +extern uint8_t nfnl_exp_get_l4protonum(const struct nfnl_exp *, int); extern void nfnl_exp_set_ports(struct nfnl_exp *, int, uint16_t, uint16_t); extern int nfnl_exp_test_ports(const struct nfnl_exp *, int); @@ -118,18 +118,6 @@ extern uint16_t nfnl_exp_get_icmp_id(const struct nfnl_exp *, int); extern uint8_t nfnl_exp_get_icmp_type(const struct nfnl_exp *, int); extern uint8_t nfnl_exp_get_icmp_code(const struct nfnl_exp *, int); -// TODO: Expectation table does support CPU stats get command, not sure if the same -/* -extern void nfnl_ct_set_packets(struct nfnl_ct *, int, uint64_t); -extern int nfnl_ct_test_packets(const struct nfnl_ct *, int); -extern uint64_t nfnl_ct_get_packets(const struct nfnl_ct *,int); - -extern void nfnl_ct_set_bytes(struct nfnl_ct *, int, uint64_t); -extern int nfnl_ct_test_bytes(const struct nfnl_ct *, int); -extern uint64_t nfnl_ct_get_bytes(const struct nfnl_ct *, int); -*/ - - #ifdef __cplusplus } diff --git a/lib/netfilter/exp.c b/lib/netfilter/exp.c index 9e29c35..c6479f6 100644 --- a/lib/netfilter/exp.c +++ b/lib/netfilter/exp.c @@ -30,18 +30,6 @@ static struct nl_cache_ops nfnl_exp_ops; -#if __BYTE_ORDER == __BIG_ENDIAN -static uint64_t ntohll(uint64_t x) -{ - return x; -} -#elif __BYTE_ORDER == __LITTLE_ENDIAN -static uint64_t ntohll(uint64_t x) -{ - return bswap_64(x); -} -#endif - static struct nla_policy exp_policy[CTA_EXPECT_MAX+1] = { [CTA_EXPECT_MASTER] = { .type = NLA_NESTED }, [CTA_EXPECT_TUPLE] = { .type = NLA_NESTED }, @@ -407,6 +395,7 @@ static int nfnl_exp_build_message(const struct nfnl_exp *exp, int cmd, int flags *result = msg; return 0; +nla_put_failure: err_out: nlmsg_free(msg); return err; @@ -519,9 +508,9 @@ static struct nl_cache_ops nfnl_exp_ops = { .co_name = "netfilter/exp", .co_hdrsize = NFNL_HDRLEN, .co_msgtypes = { - { NFNLMSG_CT_TYPE(IPCTNL_MSG_EXP_NEW), NL_ACT_NEW, "new" }, - { NFNLMSG_CT_TYPE(IPCTNL_MSG_EXP_GET), NL_ACT_GET, "get" }, - { NFNLMSG_CT_TYPE(IPCTNL_MSG_EXP_DELETE), NL_ACT_DEL, "del" }, + { NFNLMSG_EXP_TYPE(IPCTNL_MSG_EXP_NEW), NL_ACT_NEW, "new" }, + { NFNLMSG_EXP_TYPE(IPCTNL_MSG_EXP_GET), NL_ACT_GET, "get" }, + { NFNLMSG_EXP_TYPE(IPCTNL_MSG_EXP_DELETE), NL_ACT_DEL, "del" }, END_OF_MSGTYPES_LIST, }, .co_protocol = NETLINK_NETFILTER, diff --git a/lib/netfilter/exp_obj.c b/lib/netfilter/exp_obj.c index 160c939..41ac214 100644 --- a/lib/netfilter/exp_obj.c +++ b/lib/netfilter/exp_obj.c @@ -87,7 +87,6 @@ static int exp_clone(struct nl_object *_dst, struct nl_object *_src) struct nfnl_exp *dst = (struct nfnl_exp *) _dst; struct nfnl_exp *src = (struct nfnl_exp *) _src; struct nl_addr *addr; - int result = 0; // Expectation if (src->exp_expect.src) { @@ -185,7 +184,7 @@ static void dump_icmp(struct nl_dump_params *p, struct nfnl_exp *exp, int tuple) static void exp_dump_tuples(struct nfnl_exp *exp, struct nl_dump_params *p) { - struct nl_addr *tuple_src, *tuple_dst; + struct nl_addr *tuple_src = NULL, *tuple_dst = NULL; int tuple_sport = 0, tuple_dport = 0; int i = 0; char buf[64]; @@ -199,9 +198,9 @@ static void exp_dump_tuples(struct nfnl_exp *exp, struct nl_dump_params *p) tuple_dst = nfnl_exp_get_dst(exp, i); // Don't have tests for individual ports/types/codes/ids, - if (nfnl_exp_test_l4protonum(exp)) { + if (nfnl_exp_test_l4protonum(exp, i)) { nl_dump(p, "%s ", - nl_ip_proto2str(nfnl_exp_get_l4protonum(exp), buf, sizeof(buf))); + nl_ip_proto2str(nfnl_exp_get_l4protonum(exp, i), buf, sizeof(buf))); } if (nfnl_exp_test_ports(exp, i)) { @@ -236,14 +235,14 @@ static void exp_dump_details(struct nl_object *a, struct nl_dump_params *p) char buf[64]; int fp = 0; - ct_dump_line(a, p); + exp_dump_line(a, p); nl_dump(p, " id 0x%x ", exp->exp_id); nl_dump_line(p, "family %s ", nl_af2str(exp->exp_family, buf, sizeof(buf))); if (nfnl_exp_test_timeout(exp)) { - uint64_t timeout_ms = nfnl_ct_get_timeout(exp) * 1000UL; + uint64_t timeout_ms = nfnl_exp_get_timeout(exp) * 1000UL; nl_dump(p, "timeout %s ", nl_msec2str(timeout_ms, buf, sizeof(buf))); } @@ -345,9 +344,9 @@ static int exp_compare(struct nl_object *_a, struct nl_object *_b, ? EXP_DIFF(ATTR, nl_addr_cmp_prefix(a->FIELD, b->FIELD)) \ : EXP_DIFF(ATTR, nl_addr_cmp(a->FIELD, b->FIELD))) #define EXP_DIFF_L4PROTO_PORTS(ATTR, FIELD) \ - EXP_DIFF(ATTR, exp_cmp_l4proto_ports(a->FIELD, b->FIELD)) + EXP_DIFF(ATTR, exp_cmp_l4proto_ports(&(a->FIELD), &(b->FIELD))) #define EXP_DIFF_L4PROTO_ICMP(ATTR, FIELD) \ - EXP_DIFF(ATTR, exp_cmp_l4proto_icmp(a->FIELD, b->FIELD)) + EXP_DIFF(ATTR, exp_cmp_l4proto_icmp(&(a->FIELD), &(b->FIELD))) diff |= EXP_DIFF_VAL(FAMILY, exp_family); diff |= EXP_DIFF_VAL(TIMEOUT, exp_timeout); @@ -363,26 +362,26 @@ static int exp_compare(struct nl_object *_a, struct nl_object *_b, diff |= EXP_DIFF_ADDR(EXPECT_IP_SRC, exp_expect.src); diff |= EXP_DIFF_ADDR(EXPECT_IP_DST, exp_expect.dst); diff |= EXP_DIFF_VAL(EXPECT_L4PROTO_NUM, exp_expect.proto.l4protonum); - diff |= EXP_DIFF_L4PROTO_PORTS(EXPECT_L4PROTO_PORTS, exp_expect.proto.l4protodata.port); - diff |= EXP_DIFF_L4PROTO_ICMP(EXPECT_L4PROTO_ICMP, exp_expect.proto.l4protodata.icmp); + diff |= EXP_DIFF_L4PROTO_PORTS(EXPECT_L4PROTO_PORTS, exp_expect.proto.l4protodata); + diff |= EXP_DIFF_L4PROTO_ICMP(EXPECT_L4PROTO_ICMP, exp_expect.proto.l4protodata); diff |= EXP_DIFF_ADDR(MASTER_IP_SRC, exp_master.src); diff |= EXP_DIFF_ADDR(MASTER_IP_DST, exp_master.dst); diff |= EXP_DIFF_VAL(MASTER_L4PROTO_NUM, exp_master.proto.l4protonum); - diff |= EXP_DIFF_L4PROTO_PORTS(MASTER_L4PROTO_PORTS, exp_master.proto.l4protodata.port); - diff |= EXP_DIFF_L4PROTO_ICMP(MASTER_L4PROTO_ICMP, exp_master.proto.l4protodata.icmp); + diff |= EXP_DIFF_L4PROTO_PORTS(MASTER_L4PROTO_PORTS, exp_master.proto.l4protodata); + diff |= EXP_DIFF_L4PROTO_ICMP(MASTER_L4PROTO_ICMP, exp_master.proto.l4protodata); diff |= EXP_DIFF_ADDR(MASK_IP_SRC, exp_mask.src); diff |= EXP_DIFF_ADDR(MASK_IP_DST, exp_mask.dst); diff |= EXP_DIFF_VAL(MASK_L4PROTO_NUM, exp_mask.proto.l4protonum); - diff |= EXP_DIFF_L4PROTO_PORTS(MASK_L4PROTO_PORTS, exp_mask.proto.l4protodata.port); - diff |= EXP_DIFF_L4PROTO_ICMP(MASK_L4PROTO_ICMP, exp_mask.proto.l4protodata.icmp); + diff |= EXP_DIFF_L4PROTO_PORTS(MASK_L4PROTO_PORTS, exp_mask.proto.l4protodata); + diff |= EXP_DIFF_L4PROTO_ICMP(MASK_L4PROTO_ICMP, exp_mask.proto.l4protodata); diff |= EXP_DIFF_ADDR(NAT_IP_SRC, exp_nat.src); diff |= EXP_DIFF_ADDR(NAT_IP_DST, exp_nat.dst); diff |= EXP_DIFF_VAL(NAT_L4PROTO_NUM, exp_nat.proto.l4protonum); - diff |= EXP_DIFF_L4PROTO_PORTS(NAT_L4PROTO_PORTS, exp_nat.proto.l4protodata.port); - diff |= EXP_DIFF_L4PROTO_ICMP(NAT_L4PROTO_ICMP, exp_nat.proto.l4protodata.icmp); + diff |= EXP_DIFF_L4PROTO_PORTS(NAT_L4PROTO_PORTS, exp_nat.proto.l4protodata); + diff |= EXP_DIFF_L4PROTO_ICMP(NAT_L4PROTO_ICMP, exp_nat.proto.l4protodata); #undef EXP_DIFF #undef EXP_DIFF_VAL @@ -479,6 +478,11 @@ void nfnl_exp_set_flags(struct nfnl_exp *exp, uint32_t flags) exp->ce_mask |= EXP_ATTR_FLAGS; } +int nfnl_exp_test_flags(const struct nfnl_exp *exp) +{ + return !!(exp->ce_mask & EXP_ATTR_FLAGS); +} + void nfnl_exp_unset_flags(struct nfnl_exp *exp, uint32_t flags) { exp->exp_flags &= ~flags; @@ -592,22 +596,6 @@ uint32_t nfnl_exp_get_class(const struct nfnl_exp *exp) return exp->exp_class; } -void nfnl_exp_set_flags(struct nfnl_exp *exp, uint32_t flags) -{ - exp->exp_flags = flags; - exp->ce_mask |= EXP_ATTR_FLAGS; -} - -int nfnl_exp_test_flags(const struct nfnl_exp *exp) -{ - return !!(exp->ce_mask & EXP_ATTR_FLAGS); -} - -uint32_t nfnl_exp_get_flags(const struct nfnl_exp *exp) -{ - return exp->exp_flags; -} - int nfnl_exp_set_fn(struct nfnl_exp *exp, void *fn) { free(exp->exp_fn); @@ -645,27 +633,13 @@ uint8_t nfnl_exp_get_nat_dir(const struct nfnl_exp *exp) return exp->exp_nat_dir; } -static struct nfnl_exp_dir *exp_get_dir(struct nfnl_exp *exp, int tuple) -{ - struct nfnl_exp_dir *dir = NULL; - - switch (tuple) { - case NFNL_EXP_TUPLE_MASTER: - dir = &exp->exp_master; - break; - case NFNL_EXP_TUPLE_MASK: - dir = &exp->exp_mask; - break; - case NFNL_EXP_TUPLE_NAT: - dir = &exp->exp_nat; - break; - case NFNL_EXP_TUPLE_EXPECT: - default : - dir = &exp->exp_expect; - break; - } - return dir; -} +#define EXP_GET_TUPLE(e, t) \ + (t == NFNL_EXP_TUPLE_MASTER) ? \ + &(e->exp_master) : \ + (t == NFNL_EXP_TUPLE_MASK) ?\ + &(e->exp_mask) : \ + (t == NFNL_EXP_TUPLE_NAT) ?\ + &(e->exp_nat) : &(exp->exp_expect) static int exp_get_src_attr(int tuple) { @@ -735,14 +709,14 @@ static int exp_set_addr(struct nfnl_exp *exp, struct nl_addr *addr, int nfnl_exp_set_src(struct nfnl_exp *exp, int tuple, struct nl_addr *addr) { - struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); return exp_set_addr(exp, addr, exp_get_src_attr(tuple), &dir->src); } int nfnl_exp_set_dst(struct nfnl_exp *exp, int tuple, struct nl_addr *addr) { - struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); return exp_set_addr(exp, addr, exp_get_dst_attr(tuple), &dir->dst); } @@ -760,7 +734,7 @@ int nfnl_exp_test_dst(const struct nfnl_exp *exp, int tuple) struct nl_addr *nfnl_exp_get_src(const struct nfnl_exp *exp, int tuple) { - const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + const struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); if (!(exp->ce_mask & exp_get_src_attr(tuple))) return NULL; @@ -769,7 +743,7 @@ struct nl_addr *nfnl_exp_get_src(const struct nfnl_exp *exp, int tuple) struct nl_addr *nfnl_exp_get_dst(const struct nfnl_exp *exp, int tuple) { - const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + const struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); if (!(exp->ce_mask & exp_get_dst_attr(tuple))) return NULL; @@ -801,20 +775,20 @@ static int exp_get_l4protonum_attr(int tuple) void nfnl_exp_set_l4protonum(struct nfnl_exp *exp, int tuple, uint8_t l4protonum) { - const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); dir->proto.l4protonum = l4protonum; - exp->ce_mask |= exp_get_l4protonum_attr(exp, tuple); + exp->ce_mask |= exp_get_l4protonum_attr(tuple); } int nfnl_exp_test_l4protonum(const struct nfnl_exp *exp, int tuple) { - return !!(exp->ce_mask & exp_get_l4protonum_attr(exp, tuple)); + return !!(exp->ce_mask & exp_get_l4protonum_attr(tuple)); } -struct uint8_t * nfnl_exp_get_l4protonum(const struct nfnl_exp *exp, int tuple) +uint8_t nfnl_exp_get_l4protonum(const struct nfnl_exp *exp, int tuple) { - const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + const struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); return dir->proto.l4protonum; } @@ -843,7 +817,7 @@ static int exp_get_l4ports_attr(int tuple) void nfnl_exp_set_ports(struct nfnl_exp *exp, int tuple, uint16_t srcport, uint16_t dstport) { - struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); dir->proto.l4protodata.port.src = srcport; dir->proto.l4protodata.port.dst = dstport; @@ -858,13 +832,13 @@ int nfnl_exp_test_ports(const struct nfnl_exp *exp, int tuple) uint16_t nfnl_exp_get_src_port(const struct nfnl_exp *exp, int tuple) { - const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + const struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); return dir->proto.l4protodata.port.src; } uint16_t nfnl_exp_get_dst_port(const struct nfnl_exp *exp, int tuple) { - const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + const struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); return dir->proto.l4protodata.port.dst; } @@ -892,9 +866,9 @@ static int exp_get_l4icmp_attr(int tuple) return attr; } -void nfnl_exp_set_icmp(struct nfnl_exp *exp, int tuple, uint16_t id, uint8_t type, uint8_t, code) +void nfnl_exp_set_icmp(struct nfnl_exp *exp, int tuple, uint16_t id, uint8_t type, uint8_t code) { - struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); dir->proto.l4protodata.icmp.id = id; dir->proto.l4protodata.icmp.type = type; @@ -911,21 +885,21 @@ int nfnl_exp_test_icmp(const struct nfnl_exp *exp, int tuple) uint16_t nfnl_exp_get_icmp_id(const struct nfnl_exp *exp, int tuple) { - const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + const struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); return dir->proto.l4protodata.icmp.id; } uint8_t nfnl_exp_get_icmp_type(const struct nfnl_exp *exp, int tuple) { - const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + const struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); return dir->proto.l4protodata.icmp.type; } -uint8_t nfnl_ct_get_icmp_code(const struct nfnl_exp *exp, int tuple) +uint8_t nfnl_exp_get_icmp_code(const struct nfnl_exp *exp, int tuple) { - const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + const struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); return dir->proto.l4protodata.icmp.code; } From 4a702e6b728f0ecfe7994c650403b6e7c8ffc88f Mon Sep 17 00:00:00 2001 From: Rich Fought Date: Mon, 8 Oct 2012 17:31:42 -0700 Subject: [PATCH 251/432] Starting CLI work --- include/netlink/cli/exp.h | 30 +++++++++ src/lib/exp.c | 127 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 157 insertions(+) create mode 100644 include/netlink/cli/exp.h create mode 100644 src/lib/exp.c diff --git a/include/netlink/cli/exp.h b/include/netlink/cli/exp.h new file mode 100644 index 0000000..94609d7 --- /dev/null +++ b/include/netlink/cli/exp.h @@ -0,0 +1,30 @@ +/* + * netlink/cli/exp.h CLI Expectation Helper + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2012 Rich Fought + */ + +#ifndef __NETLINK_CLI_EXP_H_ +#define __NETLINK_CLI_EXP_H_ + +#include +#include + +extern struct nfnl_exp *nl_cli_exp_alloc(void); +extern struct nl_cache *nl_cli_exp_alloc_cache(struct nl_sock *); + +extern void nl_cli_exp_parse_family(struct nfnl_exp *, char *); +extern void nl_cli_exp_parse_timeout(struct nfnl_exp *, char *); +extern void nl_cli_exp_parse_id(struct nfnl_exp *, char *); +extern void nl_cli_exp_parse_src(struct nfnl_exp *, int, char *); +extern void nl_cli_exp_parse_dst(struct nfnl_exp *, int, char *); +extern void nl_cli_exp_parse_l4protonum(struct nfnl_exp *, int, char *); +extern void nl_cli_exp_parse_src_port(struct nfnl_exp *, int, char *); +extern void nl_cli_exp_parse_dst_port(struct nfnl_exp *, int, char *); + +#endif diff --git a/src/lib/exp.c b/src/lib/exp.c new file mode 100644 index 0000000..7e10803 --- /dev/null +++ b/src/lib/exp.c @@ -0,0 +1,127 @@ +/* + * src/lib/exp.c CLI Expectation Helpers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 20012 Rich Fought + */ + +/** + * @ingroup cli + * @defgroup cli_exp Expectation Tracking + * + * @{ + */ + +#include +#include + +struct nfnl_exp *nl_cli_exp_alloc(void) +{ + struct nfnl_exp *exp; + + exp = nfnl_exp_alloc(); + if (!exp) + nl_cli_fatal(ENOMEM, "Unable to allocate expectation object"); + + return exp; +} + +struct nl_cache *nl_cli_exp_alloc_cache(struct nl_sock *sk) +{ + return nl_cli_alloc_cache(sk, "expectation", nfnl_exp_alloc_cache); +} + +void nl_cli_exp_parse_family(struct nfnl_exp *exp, char *arg) +{ + int family; + + if ((family = nl_str2af(arg)) == AF_UNSPEC) + nl_cli_fatal(EINVAL, + "Unable to nl_cli_exp_parse family \"%s\": %s", + arg, nl_geterror(NLE_INVAL)); + + nfnl_exp_set_family(exp, family); +} + +void nl_cli_exp_parse_timeout(struct nfnl_exp *exp, char *arg) +{ + uint32_t timeout = nl_cli_parse_u32(arg); + nfnl_exp_set_timeout(exp, timeout); +} + +void nl_cli_exp_parse_id(struct nfnl_exp *exp, char *arg) +{ + uint32_t id = nl_cli_parse_u32(arg); + nfnl_exp_set_id(exp, id); +} + +void nl_cli_exp_parse_src(struct nfnl_exp *exp, int tuple, char *arg) +{ + int err; + struct nl_addr *a = nl_cli_addr_parse(arg, nfnl_exp_get_family(exp)); + if ((err = nfnl_exp_set_src(exp, tuple, a)) < 0) + nl_cli_fatal(err, "Unable to set source address: %s", + nl_geterror(err)); +} + +void nl_cli_exp_parse_dst(struct nfnl_exp *exp, int tuple, char *arg) +{ + int err; + struct nl_addr *a = nl_cli_addr_parse(arg, nfnl_exp_get_family(exp)); + if ((err = nfnl_exp_set_dst(exp, tuple, a)) < 0) + nl_cli_fatal(err, "Unable to set destination address: %s", + nl_geterror(err)); +} + +void nl_cli_exp_parse_l4protonum(struct nfnl_exp *exp, int tuple, char *arg) +{ + int l4protonum; + + if ((l4protonum = nl_str2ip_proto(arg)) < 0) + nl_cli_fatal(l4protonum, + "Unable to nl_cli_exp_parse protocol \"%s\": %s", + arg, nl_geterror(l4protonum)); + + nfnl_exp_set_l4protonum(exp, tuple, l4protonum); +} + +void nl_cli_exp_parse_src_port(struct nfnl_exp *exp, int tuple, char *arg) +{ + uint32_t sport = nl_cli_parse_u32(arg); + nfnl_exp_set_ports(exp, tuple, sport, 0); +} + +void nl_cli_exp_parse_dst_port(struct nfnl_exp *exp, int tuple, char *arg) +{ + uint32_t dport = nl_cli_parse_u32(arg); + uint32_t sport = nfnl_exp_get_src_port(exp, tuple); + nfnl_exp_set_ports(exp, tuple, sport, dport); +} + +#if 0 + } else if (arg_match("origicmpid")) { + if (argc > ++idx) + nfnl_ct_set_icmp_id(ct, 0, strtoul(argv[idx++], NULL, 0)); + } else if (arg_match("origicmptype")) { + if (argc > ++idx) + nfnl_ct_set_icmp_type(ct, 0, strtoul(argv[idx++], NULL, 0)); + } else if (arg_match("origicmpcode")) { + if (argc > ++idx) + nfnl_ct_set_icmp_code(ct, 0, strtoul(argv[idx++], NULL, 0)); + } else if (arg_match("replyicmpid")) { + if (argc > ++idx) + nfnl_ct_set_icmp_id(ct, 1, strtoul(argv[idx++], NULL, 0)); + } else if (arg_match("replyicmptype")) { + if (argc > ++idx) + nfnl_ct_set_icmp_type(ct, 1, strtoul(argv[idx++], NULL, 0)); + } else if (arg_match("replyicmpcode")) { + if (argc > ++idx) + nfnl_ct_set_icmp_code(ct, 1, strtoul(argv[idx++], NULL, 0)); + } +#endif + +/** @} */ From e4192ff97f3fccbe8347e88139aca9ba49af29ab Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 9 Oct 2012 16:15:08 +0200 Subject: [PATCH 252/432] nl: Provide API to specify the default buffer size when receiving netlink messages New functions: nl_socket_set_msg_buf_size(sk, size) nl_socket_get_msg_buf_size(sk) Default remains getpagesize() Signed-off-by: Thomas Graf --- include/netlink-types.h | 1 + include/netlink/socket.h | 2 ++ lib/nl.c | 2 +- lib/socket.c | 30 ++++++++++++++++++++++++++++++ 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/include/netlink-types.h b/include/netlink-types.h index 2e80b05..e885571 100644 --- a/include/netlink-types.h +++ b/include/netlink-types.h @@ -69,6 +69,7 @@ struct nl_sock unsigned int s_seq_expect; int s_flags; struct nl_cb * s_cb; + size_t s_bufsize; }; struct nl_cache diff --git a/include/netlink/socket.h b/include/netlink/socket.h index d0f5a6a..1007eba 100644 --- a/include/netlink/socket.h +++ b/include/netlink/socket.h @@ -49,6 +49,8 @@ extern int nl_socket_modify_err_cb(struct nl_sock *, enum nl_cb_kind, nl_recvmsg_err_cb_t, void *); extern int nl_socket_set_buffer_size(struct nl_sock *, int, int); +extern int nl_socket_set_msg_buf_size(struct nl_sock *, size_t); +extern size_t nl_socket_get_msg_buf_size(struct nl_sock *); extern int nl_socket_set_passcred(struct nl_sock *, int); extern int nl_socket_recv_pktinfo(struct nl_sock *, int); diff --git a/lib/nl.c b/lib/nl.c index ea3e087..5b37c2a 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -447,7 +447,7 @@ int nl_recv(struct nl_sock *sk, struct sockaddr_nl *nla, if (page_size == 0) page_size = getpagesize(); - iov.iov_len = page_size; + iov.iov_len = sk->s_bufsize ? : page_size; iov.iov_base = *buf = malloc(iov.iov_len); if (sk->s_flags & NL_SOCK_PASSCRED) { diff --git a/lib/socket.c b/lib/socket.c index 7e3ebf6..d53a714 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -586,6 +586,36 @@ int nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf) return 0; } +/** + * Set default message buffer size of netlink socket. + * @arg sk Netlink socket. + * @arg bufsize Default message buffer size in bytes. + * + * Sets the default message buffer size to the specified length in bytes. + * The default message buffer size limits the maximum message size the + * socket will be able to receive. It is generally recommneded to specify + * a buffer size no less than the size of a memory page. + * + * @return 0 on success or a negative error code. + */ +int nl_socket_set_msg_buf_size(struct nl_sock *sk, size_t bufsize) +{ + sk->s_bufsize = bufsize; + + return 0; +} + +/** + * Get default message buffer size of netlink socket. + * @arg sk Netlink socket. + * + * @return Size of default message buffer. + */ +size_t nl_socket_get_msg_buf_size(struct nl_sock *sk) +{ + return sk->s_bufsize; +} + /** * Enable/disable credential passing on netlink socket. * @arg sk Netlink socket. From 6ac07179e580405608a39a377a88b2c65bbdba5c Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 9 Oct 2012 18:15:50 +0200 Subject: [PATCH 253/432] link: Support IFLA_PROMISCUITY link attribute * read-only attribute * dumped in details sections "promisc-mode (N users)" Signed-off-by: Thomas Graf --- include/linux/if_link.h | 18 ++++++ include/netlink-types.h | 1 + include/netlink/route/link.h | 5 +- lib/route/link.c | 119 +++++++++++++++++++++++------------ 4 files changed, 102 insertions(+), 41 deletions(-) diff --git a/include/linux/if_link.h b/include/linux/if_link.h index 8a27d5a..c0a1dd9 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h @@ -137,6 +137,11 @@ enum { IFLA_AF_SPEC, IFLA_GROUP, /* Group the device belongs to */ IFLA_NET_NS_FD, + IFLA_EXT_MASK, /* Extended info mask, VFs, etc */ + IFLA_PROMISCUITY, /* Promiscuity count: > 0 means acts PROMISC */ +#define IFLA_PROMISCUITY IFLA_PROMISCUITY + IFLA_NUM_TX_QUEUES, + IFLA_NUM_RX_QUEUES, __IFLA_MAX }; @@ -246,6 +251,7 @@ struct ifla_vlan_qos_mapping { enum { IFLA_MACVLAN_UNSPEC, IFLA_MACVLAN_MODE, + IFLA_MACVLAN_FLAGS, __IFLA_MACVLAN_MAX, }; @@ -258,6 +264,8 @@ enum macvlan_mode { MACVLAN_MODE_PASSTHRU = 8,/* take over the underlying device */ }; +#define MACVLAN_FLAG_NOPROMISC 1 + /* SR-IOV virtual function management section */ enum { @@ -273,6 +281,7 @@ enum { IFLA_VF_MAC, /* Hardware queue specific attributes */ IFLA_VF_VLAN, IFLA_VF_TX_RATE, /* TX Bandwidth Allocation */ + IFLA_VF_SPOOFCHK, /* Spoof Checking on/off switch */ __IFLA_VF_MAX, }; @@ -294,13 +303,22 @@ struct ifla_vf_tx_rate { __u32 rate; /* Max TX bandwidth in Mbps, 0 disables throttling */ }; +struct ifla_vf_spoofchk { + __u32 vf; + __u32 setting; +}; +#ifdef __KERNEL__ + +/* We don't want this structure exposed to user space */ struct ifla_vf_info { __u32 vf; __u8 mac[32]; __u32 vlan; __u32 qos; __u32 tx_rate; + __u32 spoofchk; }; +#endif /* VF ports management section * diff --git a/include/netlink-types.h b/include/netlink-types.h index e885571..c7f9c4c 100644 --- a/include/netlink-types.h +++ b/include/netlink-types.h @@ -173,6 +173,7 @@ struct rtnl_link void * l_af_data[AF_MAX]; void * l_info; char * l_ifalias; + uint32_t l_promiscuity; }; struct rtnl_ncacheinfo diff --git a/include/netlink/route/link.h b/include/netlink/route/link.h index 42ef7c8..c5824bc 100644 --- a/include/netlink/route/link.h +++ b/include/netlink/route/link.h @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2011 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ #ifndef NETLINK_LINK_H_ @@ -197,6 +197,9 @@ extern int rtnl_link_set_stat(struct rtnl_link *, rtnl_link_stat_id_t, extern int rtnl_link_set_type(struct rtnl_link *, const char *); extern char * rtnl_link_get_type(struct rtnl_link *); +extern void rtnl_link_set_promiscuity(struct rtnl_link *, uint32_t); +extern uint32_t rtnl_link_get_promiscuity(struct rtnl_link *); + extern int rtnl_link_enslave_ifindex(struct nl_sock *, int, int); extern int rtnl_link_enslave(struct nl_sock *, struct rtnl_link *, struct rtnl_link *); diff --git a/lib/route/link.c b/lib/route/link.c index 0e8ac07..7d64aa0 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2011 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ /** @@ -28,27 +28,28 @@ #include /** @cond SKIP */ -#define LINK_ATTR_MTU 0x0001 -#define LINK_ATTR_LINK 0x0002 -#define LINK_ATTR_TXQLEN 0x0004 -#define LINK_ATTR_WEIGHT 0x0008 -#define LINK_ATTR_MASTER 0x0010 -#define LINK_ATTR_QDISC 0x0020 -#define LINK_ATTR_MAP 0x0040 -#define LINK_ATTR_ADDR 0x0080 -#define LINK_ATTR_BRD 0x0100 -#define LINK_ATTR_FLAGS 0x0200 -#define LINK_ATTR_IFNAME 0x0400 -#define LINK_ATTR_IFINDEX 0x0800 -#define LINK_ATTR_FAMILY 0x1000 -#define LINK_ATTR_ARPTYPE 0x2000 -#define LINK_ATTR_STATS 0x4000 -#define LINK_ATTR_CHANGE 0x8000 -#define LINK_ATTR_OPERSTATE 0x10000 -#define LINK_ATTR_LINKMODE 0x20000 -#define LINK_ATTR_LINKINFO 0x40000 -#define LINK_ATTR_IFALIAS 0x80000 -#define LINK_ATTR_NUM_VF 0x100000 +#define LINK_ATTR_MTU (1 << 0) +#define LINK_ATTR_LINK (1 << 1) +#define LINK_ATTR_TXQLEN (1 << 2) +#define LINK_ATTR_WEIGHT (1 << 3) +#define LINK_ATTR_MASTER (1 << 4) +#define LINK_ATTR_QDISC (1 << 5) +#define LINK_ATTR_MAP (1 << 6) +#define LINK_ATTR_ADDR (1 << 7) +#define LINK_ATTR_BRD (1 << 8) +#define LINK_ATTR_FLAGS (1 << 9) +#define LINK_ATTR_IFNAME (1 << 10) +#define LINK_ATTR_IFINDEX (1 << 11) +#define LINK_ATTR_FAMILY (1 << 12) +#define LINK_ATTR_ARPTYPE (1 << 13) +#define LINK_ATTR_STATS (1 << 14) +#define LINK_ATTR_CHANGE (1 << 15) +#define LINK_ATTR_OPERSTATE (1 << 16) +#define LINK_ATTR_LINKMODE (1 << 17) +#define LINK_ATTR_LINKINFO (1 << 18) +#define LINK_ATTR_IFALIAS (1 << 19) +#define LINK_ATTR_NUM_VF (1 << 20) +#define LINK_ATTR_PROMISCUITY (1 << 21) static struct nl_cache_ops rtnl_link_ops; static struct nl_object_ops link_obj_ops; @@ -236,24 +237,25 @@ static int link_clone(struct nl_object *_dst, struct nl_object *_src) } static struct nla_policy link_policy[IFLA_MAX+1] = { - [IFLA_IFNAME] = { .type = NLA_STRING, - .maxlen = IFNAMSIZ }, - [IFLA_MTU] = { .type = NLA_U32 }, - [IFLA_TXQLEN] = { .type = NLA_U32 }, - [IFLA_LINK] = { .type = NLA_U32 }, - [IFLA_WEIGHT] = { .type = NLA_U32 }, - [IFLA_MASTER] = { .type = NLA_U32 }, - [IFLA_OPERSTATE]= { .type = NLA_U8 }, - [IFLA_LINKMODE] = { .type = NLA_U8 }, - [IFLA_LINKINFO] = { .type = NLA_NESTED }, - [IFLA_QDISC] = { .type = NLA_STRING, - .maxlen = IFQDISCSIZ }, - [IFLA_STATS] = { .minlen = sizeof(struct rtnl_link_stats) }, - [IFLA_STATS64] = { .minlen = sizeof(struct rtnl_link_stats64) }, - [IFLA_MAP] = { .minlen = sizeof(struct rtnl_link_ifmap) }, - [IFLA_IFALIAS] = { .type = NLA_STRING, .maxlen = IFALIASZ }, - [IFLA_NUM_VF] = { .type = NLA_U32 }, - [IFLA_AF_SPEC] = { .type = NLA_NESTED }, + [IFLA_IFNAME] = { .type = NLA_STRING, + .maxlen = IFNAMSIZ }, + [IFLA_MTU] = { .type = NLA_U32 }, + [IFLA_TXQLEN] = { .type = NLA_U32 }, + [IFLA_LINK] = { .type = NLA_U32 }, + [IFLA_WEIGHT] = { .type = NLA_U32 }, + [IFLA_MASTER] = { .type = NLA_U32 }, + [IFLA_OPERSTATE] = { .type = NLA_U8 }, + [IFLA_LINKMODE] = { .type = NLA_U8 }, + [IFLA_LINKINFO] = { .type = NLA_NESTED }, + [IFLA_QDISC] = { .type = NLA_STRING, + .maxlen = IFQDISCSIZ }, + [IFLA_STATS] = { .minlen = sizeof(struct rtnl_link_stats) }, + [IFLA_STATS64] = { .minlen = sizeof(struct rtnl_link_stats64)}, + [IFLA_MAP] = { .minlen = sizeof(struct rtnl_link_ifmap) }, + [IFLA_IFALIAS] = { .type = NLA_STRING, .maxlen = IFALIASZ }, + [IFLA_NUM_VF] = { .type = NLA_U32 }, + [IFLA_AF_SPEC] = { .type = NLA_NESTED }, + [IFLA_PROMISCUITY] = { .type = NLA_U32 }, }; static struct nla_policy link_info_policy[IFLA_INFO_MAX+1] = { @@ -535,6 +537,11 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, } } + if (tb[IFLA_PROMISCUITY]) { + link->l_promiscuity = nla_get_u32(tb[IFLA_PROMISCUITY]); + link->l_flags |= LINK_ATTR_PROMISCUITY; + } + err = pp->pp_cb((struct nl_object *) link, pp); errout: rtnl_link_af_ops_put(af_ops); @@ -619,6 +626,8 @@ static void link_dump_details(struct nl_object *obj, struct nl_dump_params *p) if (link->ce_mask & LINK_ATTR_IFINDEX) nl_dump(p, "index %u ", link->l_index); + if (link->ce_mask & LINK_ATTR_PROMISCUITY) + nl_dump(p, "promisc-mode (%u users) ", link->l_promiscuity); nl_dump(p, "\n"); @@ -784,6 +793,7 @@ static int link_compare(struct nl_object *_a, struct nl_object *_b, diff |= LINK_DIFF(BRD, nl_addr_cmp(a->l_bcast, b->l_bcast)); diff |= LINK_DIFF(IFALIAS, strcmp(a->l_ifalias, b->l_ifalias)); diff |= LINK_DIFF(NUM_VF, a->l_num_vf != b->l_num_vf); + diff |= LINK_DIFF(PROMISCUITY, a->l_promiscuity != b->l_promiscuity); if (flags & LOOSE_COMPARISON) diff |= LINK_DIFF(FLAGS, @@ -817,6 +827,7 @@ static const struct trans_tbl link_attrs[] = { __ADD(LINK_ATTR_LINKMODE, linkmode) __ADD(LINK_ATTR_IFALIAS, ifalias) __ADD(LINK_ATTR_NUM_VF, num_vf) + __ADD(LINK_ATTR_PROMISCUITY, promiscuity) }; static char *link_attrs2str(int attrs, char *buf, size_t len) @@ -2011,6 +2022,34 @@ char *rtnl_link_get_type(struct rtnl_link *link) return link->l_info_kind; } +/** + * Set link promiscuity count + * @arg link Link object + * @arg count New promiscuity count + * + * @copydoc read_only_attribute + * + * @see rtnl_link_get_promiscuity() + */ +void rtnl_link_set_promiscuity(struct rtnl_link *link, uint32_t count) +{ + link->l_promiscuity = count; + link->l_master |= LINK_ATTR_PROMISCUITY; +} + +/** + * Return link promiscuity count + * @arg link Link object + * + * @see rtnl_link_set_promiscuity() + * @return Link promiscuity count or 0 + */ +uint32_t rtnl_link_get_promiscuity(struct rtnl_link *link) +{ + return link->l_promiscuity; +} + + /** @} */ /** From daf5f93a138d91d0d041705c276115e94dbeb84b Mon Sep 17 00:00:00 2001 From: Rich Fought Date: Tue, 9 Oct 2012 09:50:31 -0700 Subject: [PATCH 254/432] Compile CLI --- src/lib/Makefile.am | 2 +- src/lib/exp.c | 22 ---------------------- 2 files changed, 1 insertion(+), 23 deletions(-) diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index a88163a..6688e7c 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -38,6 +38,6 @@ libnl_cli_3_la_LIBADD = ${top_builddir}/lib/libnl-3.la \ libnl_cli_3_la_SOURCES = \ utils.c addr.c ct.c link.c neigh.c rule.c route.c \ - tc.c qdisc.c class.c cls.c + tc.c qdisc.c class.c cls.c exp.c # cls/ematch_syntax.c cls/ematch_grammar.c cls/ematch.c # cls/pktloc_syntax.c cls/pktloc_grammar.c cls/utils.c diff --git a/src/lib/exp.c b/src/lib/exp.c index 7e10803..01aae01 100644 --- a/src/lib/exp.c +++ b/src/lib/exp.c @@ -102,26 +102,4 @@ void nl_cli_exp_parse_dst_port(struct nfnl_exp *exp, int tuple, char *arg) nfnl_exp_set_ports(exp, tuple, sport, dport); } -#if 0 - } else if (arg_match("origicmpid")) { - if (argc > ++idx) - nfnl_ct_set_icmp_id(ct, 0, strtoul(argv[idx++], NULL, 0)); - } else if (arg_match("origicmptype")) { - if (argc > ++idx) - nfnl_ct_set_icmp_type(ct, 0, strtoul(argv[idx++], NULL, 0)); - } else if (arg_match("origicmpcode")) { - if (argc > ++idx) - nfnl_ct_set_icmp_code(ct, 0, strtoul(argv[idx++], NULL, 0)); - } else if (arg_match("replyicmpid")) { - if (argc > ++idx) - nfnl_ct_set_icmp_id(ct, 1, strtoul(argv[idx++], NULL, 0)); - } else if (arg_match("replyicmptype")) { - if (argc > ++idx) - nfnl_ct_set_icmp_type(ct, 1, strtoul(argv[idx++], NULL, 0)); - } else if (arg_match("replyicmpcode")) { - if (argc > ++idx) - nfnl_ct_set_icmp_code(ct, 1, strtoul(argv[idx++], NULL, 0)); - } -#endif - /** @} */ From d2876f8657b5d9187a8c2314c88dffa63ba2bc66 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 9 Oct 2012 19:34:23 +0200 Subject: [PATCH 255/432] link: correctly set LINK_ATTR_PROMISCUITY Signed-off-by: Thomas Graf --- lib/route/link.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/route/link.c b/lib/route/link.c index 7d64aa0..0e14f45 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -539,7 +539,7 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, if (tb[IFLA_PROMISCUITY]) { link->l_promiscuity = nla_get_u32(tb[IFLA_PROMISCUITY]); - link->l_flags |= LINK_ATTR_PROMISCUITY; + link->ce_mask |= LINK_ATTR_PROMISCUITY; } err = pp->pp_cb((struct nl_object *) link, pp); @@ -2034,7 +2034,7 @@ char *rtnl_link_get_type(struct rtnl_link *link) void rtnl_link_set_promiscuity(struct rtnl_link *link, uint32_t count) { link->l_promiscuity = count; - link->l_master |= LINK_ATTR_PROMISCUITY; + link->ce_mask |= LINK_ATTR_PROMISCUITY; } /** From 453492c9b2241c1ce9ca89dabe5365d7981cedf7 Mon Sep 17 00:00:00 2001 From: Rich Fought Date: Tue, 9 Oct 2012 10:52:34 -0700 Subject: [PATCH 256/432] Expectation get cli tool --- src/Makefile.am | 2 +- src/nf-exp-list.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 src/nf-exp-list.c diff --git a/src/Makefile.am b/src/Makefile.am index 132a415..cf5cd48 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -21,7 +21,7 @@ sbin_PROGRAMS = \ nl-link-list noinst_PROGRAMS = \ - nf-ct-list nf-log nf-queue nf-monitor \ + nf-ct-list nf-log nf-queue nf-monitor nf-exp-list \ nl-addr-add nl-addr-delete nl-addr-list \ nl-link-set nl-link-stats \ nl-link-ifindex2name nl-link-name2ifindex \ diff --git a/src/nf-exp-list.c b/src/nf-exp-list.c new file mode 100644 index 0000000..5a29b4a --- /dev/null +++ b/src/nf-exp-list.c @@ -0,0 +1,130 @@ +/* + * src/nf-exp-list.c List Conntrack Entries + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2012 Rich Fought + */ + +#include +#include + +static void print_usage(void) +{ + printf( + "Usage: nf-exp-list [OPTION]... [CONNTRACK ENTRY]\n" + "\n" + "Options\n" + " -f, --format=TYPE Output format { brief | details | stats }\n" + " -h, --help Show this help\n" + " -v, --version Show versioning information\n" + "\n" + "Expectation Selection\n" + " -i, --id=NUM Identifier\n" + " --expect-proto=PROTOCOL Expectation protocol\n" + " --expect-src=ADDR Expectation source address\n" + " --expect-sport=PORT Expectation source port\n" + " --expect-dst=ADDR Expectation destination address\n" + " --expect-dport=PORT Expectation destination port\n" + " --master-proto=PROTOCOL Master conntrack protocol\n" + " --master-src=ADDR Master conntrack source address\n" + " --master-sport=PORT Master conntrack source port\n" + " --master-dst=ADDR Master conntrack destination address\n" + " --master-dport=PORT Master conntrack destination port\n" + " -F, --family=FAMILY Address family\n" + " --timeout=NUM Timeout value\n" + //" --flags Flags\n" + ); + exit(0); +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct nl_cache *exp_cache; + struct nfnl_exp *exp; + struct nl_dump_params params = { + .dp_type = NL_DUMP_LINE, + .dp_fd = stdout, + }; + + exp = nl_cli_exp_alloc(); + + for (;;) { + int c, optidx = 0; + enum { + ARG_MARK = 270, + ARG_TCP_STATE = 271, + ARG_EXPECT_PROTO, + ARG_EXPECT_SRC, + ARG_EXPECT_SPORT, + ARG_EXPECT_DST, + ARG_EXPECT_DPORT, + ARG_MASTER_PROTO, + ARG_MASTER_SRC, + ARG_MASTER_SPORT, + ARG_MASTER_DST, + ARG_MASTER_DPORT, + ARG_TIMEOUT, + //ARG_FLAGS, + }; + static struct option long_opts[] = { + { "format", 1, 0, 'f' }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "id", 1, 0, 'i' }, + { "expect-proto", 1, 0, ARG_EXPECT_PROTO }, + { "expect-src", 1, 0, ARG_EXPECT_SRC }, + { "expect-sport", 1, 0, ARG_EXPECT_SPORT }, + { "expect-dst", 1, 0, ARG_EXPECT_DST }, + { "expect-dport", 1, 0, ARG_EXPECT_DPORT }, + { "master-proto", 1, 0, ARG_MASTER_PROTO }, + { "master-src", 1, 0, ARG_MASTER_SRC }, + { "master-sport", 1, 0, ARG_MASTER_SPORT }, + { "master-dst", 1, 0, ARG_MASTER_DST }, + { "master-dport", 1, 0, ARG_MASTER_DPORT }, + { "family", 1, 0, 'F' }, + { "timeout", 1, 0, ARG_TIMEOUT }, + //{ "flags", 1, 0, ARG_FLAGS}, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "46f:hvi:p:F:", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case '?': exit(NLE_INVAL); + case '4': nfnl_exp_set_family(exp, AF_INET); break; + case '6': nfnl_exp_set_family(exp, AF_INET6); break; + case 'f': params.dp_type = nl_cli_parse_dumptype(optarg); break; + case 'h': print_usage(); break; + case 'v': nl_cli_print_version(); break; + case 'i': nl_cli_exp_parse_id(exp, optarg); break; + case ARG_EXPECT_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; + case ARG_EXPECT_SRC: nl_cli_exp_parse_src(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; + case ARG_EXPECT_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; + case ARG_EXPECT_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; + case ARG_EXPECT_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; + case ARG_MASTER_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; + case ARG_MASTER_SRC: nl_cli_exp_parse_src(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; + case ARG_MASTER_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; + case ARG_MASTER_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; + case ARG_MASTER_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; + case 'F': nl_cli_exp_parse_family(exp, optarg); break; + case ARG_TIMEOUT: nl_cli_exp_parse_timeout(exp, optarg); break; + //case ARG_FLAGS: nl_cli_exp_parse_flags(exp, optarg); break; + } + } + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_NETFILTER); + exp_cache = nl_cli_exp_alloc_cache(sock); + + nl_cache_dump_filter(exp_cache, ¶ms, OBJ_CAST(exp)); + + return 0; +} From 3cb581d5986002bb8430a894402b8015b2dd2af3 Mon Sep 17 00:00:00 2001 From: Rich Fought Date: Tue, 9 Oct 2012 10:54:07 -0700 Subject: [PATCH 257/432] update gitignore --- src/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/src/.gitignore b/src/.gitignore index cad6f75..b02885a 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,5 +1,6 @@ genl-ctrl-list nf-ct-list +nf-exp-list nf-log nf-monitor nl-addr-add From 36ed882e003ee54cfde9a8f526007b3a66fff3a4 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 9 Oct 2012 19:57:22 +0200 Subject: [PATCH 258/432] link: Support IFLA_NUM_TX_QUEUES and IFLA_NUM_RX_QUEUES New functions: rtnl_link_set_num_tx_queues(link, nqueues) rtnl_link_get_num_tx_queues(link) rtnl_link_set_num_rx_queues(link, nqueues) rtnl_link_get_num_rx_queues(link) Signed-off-by: Thomas Graf --- include/netlink-types.h | 2 + include/netlink/route/link.h | 6 +++ lib/route/link.c | 85 ++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) diff --git a/include/netlink-types.h b/include/netlink-types.h index c7f9c4c..345486f 100644 --- a/include/netlink-types.h +++ b/include/netlink-types.h @@ -174,6 +174,8 @@ struct rtnl_link void * l_info; char * l_ifalias; uint32_t l_promiscuity; + uint32_t l_num_tx_queues; + uint32_t l_num_rx_queues; }; struct rtnl_ncacheinfo diff --git a/include/netlink/route/link.h b/include/netlink/route/link.h index c5824bc..518bab5 100644 --- a/include/netlink/route/link.h +++ b/include/netlink/route/link.h @@ -200,6 +200,12 @@ extern char * rtnl_link_get_type(struct rtnl_link *); extern void rtnl_link_set_promiscuity(struct rtnl_link *, uint32_t); extern uint32_t rtnl_link_get_promiscuity(struct rtnl_link *); +extern void rtnl_link_set_num_tx_queues(struct rtnl_link *, uint32_t); +extern uint32_t rtnl_link_get_num_tx_queues(struct rtnl_link *); + +extern void rtnl_link_set_num_rx_queues(struct rtnl_link *, uint32_t); +extern uint32_t rtnl_link_get_num_rx_queues(struct rtnl_link *); + extern int rtnl_link_enslave_ifindex(struct nl_sock *, int, int); extern int rtnl_link_enslave(struct nl_sock *, struct rtnl_link *, struct rtnl_link *); diff --git a/lib/route/link.c b/lib/route/link.c index 0e14f45..4592bf0 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -50,6 +50,8 @@ #define LINK_ATTR_IFALIAS (1 << 19) #define LINK_ATTR_NUM_VF (1 << 20) #define LINK_ATTR_PROMISCUITY (1 << 21) +#define LINK_ATTR_NUM_TX_QUEUES (1 << 22) +#define LINK_ATTR_NUM_RX_QUEUES (1 << 23) static struct nl_cache_ops rtnl_link_ops; static struct nl_object_ops link_obj_ops; @@ -256,6 +258,8 @@ static struct nla_policy link_policy[IFLA_MAX+1] = { [IFLA_NUM_VF] = { .type = NLA_U32 }, [IFLA_AF_SPEC] = { .type = NLA_NESTED }, [IFLA_PROMISCUITY] = { .type = NLA_U32 }, + [IFLA_NUM_TX_QUEUES] = { .type = NLA_U32 }, + [IFLA_NUM_RX_QUEUES] = { .type = NLA_U32 }, }; static struct nla_policy link_info_policy[IFLA_INFO_MAX+1] = { @@ -542,6 +546,16 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, link->ce_mask |= LINK_ATTR_PROMISCUITY; } + if (tb[IFLA_NUM_TX_QUEUES]) { + link->l_num_tx_queues = nla_get_u32(tb[IFLA_NUM_TX_QUEUES]); + link->ce_mask |= LINK_ATTR_NUM_TX_QUEUES; + } + + if (tb[IFLA_NUM_RX_QUEUES]) { + link->l_num_rx_queues = nla_get_u32(tb[IFLA_NUM_RX_QUEUES]); + link->ce_mask |= LINK_ATTR_NUM_RX_QUEUES; + }; + err = pp->pp_cb((struct nl_object *) link, pp); errout: rtnl_link_af_ops_put(af_ops); @@ -636,6 +650,12 @@ static void link_dump_details(struct nl_object *obj, struct nl_dump_params *p) nl_dump_line(p, " "); + if (link->ce_mask & LINK_ATTR_NUM_TX_QUEUES) + nl_dump(p, "txq %u ", link->l_num_tx_queues); + + if (link->ce_mask & LINK_ATTR_NUM_RX_QUEUES) + nl_dump(p, "rxq %u ", link->l_num_rx_queues); + if (link->ce_mask & LINK_ATTR_BRD) nl_dump(p, "brd %s ", nl_addr2str(link->l_bcast, buf, sizeof(buf))); @@ -794,6 +814,8 @@ static int link_compare(struct nl_object *_a, struct nl_object *_b, diff |= LINK_DIFF(IFALIAS, strcmp(a->l_ifalias, b->l_ifalias)); diff |= LINK_DIFF(NUM_VF, a->l_num_vf != b->l_num_vf); diff |= LINK_DIFF(PROMISCUITY, a->l_promiscuity != b->l_promiscuity); + diff |= LINK_DIFF(NUM_TX_QUEUES,a->l_num_tx_queues != b->l_num_tx_queues); + diff |= LINK_DIFF(NUM_RX_QUEUES,a->l_num_rx_queues != b->l_num_rx_queues); if (flags & LOOSE_COMPARISON) diff |= LINK_DIFF(FLAGS, @@ -828,6 +850,8 @@ static const struct trans_tbl link_attrs[] = { __ADD(LINK_ATTR_IFALIAS, ifalias) __ADD(LINK_ATTR_NUM_VF, num_vf) __ADD(LINK_ATTR_PROMISCUITY, promiscuity) + __ADD(LINK_ATTR_NUM_TX_QUEUES, num_tx_queues) + __ADD(LINK_ATTR_NUM_RX_QUEUES, num_rx_queues) }; static char *link_attrs2str(int attrs, char *buf, size_t len) @@ -2049,6 +2073,67 @@ uint32_t rtnl_link_get_promiscuity(struct rtnl_link *link) return link->l_promiscuity; } +/** + * Set number of TX queues + * @arg link Link object + * @arg nqueues Number of queues + * + * Sets the number of TX queues of the link object. The value is considered + * by the kernel when creating network devices that can be created via + * netlink. The value will be passed on to alloc_netdev_mqs() + * + * Therefore use of rtnl_link_set_num_tx_queues() only makes sense in + * combination with rtnl_link_add() or if the link object is used as a filter. + * + * @see rtnl_link_get_num_tx_queues() + */ +void rtnl_link_set_num_tx_queues(struct rtnl_link *link, uint32_t nqueues) +{ + link->l_num_tx_queues = nqueues; + link->ce_mask |= LINK_ATTR_NUM_TX_QUEUES; +} + +/** + * Return number of TX queues + * @arg link Link object + * + * @return Number of TX queues or 0 + */ +uint32_t rtnl_link_get_num_tx_queues(struct rtnl_link *link) +{ + return link->l_num_tx_queues; +} + +/** + * Set number of RX queues + * @arg link Link object + * @arg nqueues Number of queues + * + * Sets the number of RX queues of the link object. The value is considered + * by the kernel when creating network devices that can be created via + * netlink. The value will be passed on to alloc_netdev_mqs() + * + * Therefore use of rtnl_link_set_num_rx_queues() only makes sense in + * combination with rtnl_link_add() or if the link object is used as a filter. + * + * @see rtnl_link_get_num_rx_queues() + */ +void rtnl_link_set_num_rx_queues(struct rtnl_link *link, uint32_t nqueues) +{ + link->l_num_rx_queues = nqueues; + link->ce_mask |= LINK_ATTR_NUM_RX_QUEUES; +} + +/** + * Return number of RX queues + * @arg link Link object + * + * @return Number of RX queues or 0 + */ +uint32_t rtnl_link_get_num_rx_queues(struct rtnl_link *link) +{ + return link->l_num_rx_queues; +} /** @} */ From 7f6880ceb9a7919b1a0ec9e5f6eeddb6104fb73b Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 9 Oct 2012 19:58:54 +0200 Subject: [PATCH 259/432] link: Only print "promisc-mode" if users > 0 Signed-off-by: Thomas Graf --- lib/route/link.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/route/link.c b/lib/route/link.c index 4592bf0..1b43401 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -640,7 +640,7 @@ static void link_dump_details(struct nl_object *obj, struct nl_dump_params *p) if (link->ce_mask & LINK_ATTR_IFINDEX) nl_dump(p, "index %u ", link->l_index); - if (link->ce_mask & LINK_ATTR_PROMISCUITY) + if (link->ce_mask & LINK_ATTR_PROMISCUITY && link->l_promiscuity > 0) nl_dump(p, "promisc-mode (%u users) ", link->l_promiscuity); nl_dump(p, "\n"); From f2e2e7feb5586283e443ccea8dd60bc37d44e4cd Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 9 Oct 2012 21:24:35 +0200 Subject: [PATCH 260/432] link: Include IFLA_NUM_TX_QUEUES and IFLA_NUM_RX_QUEUES when building messages Signed-off-by: Thomas Graf --- lib/route/link.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/route/link.c b/lib/route/link.c index 1b43401..ff2b000 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -1164,6 +1164,12 @@ static int build_link_msg(int cmd, struct ifinfomsg *hdr, if (link->ce_mask & LINK_ATTR_MASTER) NLA_PUT_U32(msg, IFLA_MASTER, link->l_master); + if (link->ce_mask & LINK_ATTR_NUM_TX_QUEUES) + NLA_PUT_U32(msg, IFLA_NUM_TX_QUEUES, link->l_num_tx_queues); + + if (link->ce_mask & LINK_ATTR_NUM_RX_QUEUES) + NLA_PUT_U32(msg, IFLA_NUM_RX_QUEUES, link->l_num_rx_queues); + if (link->ce_mask & LINK_ATTR_LINKINFO) { struct nlattr *info; From 36139cf1f044b2631f425d4ceb7333bc9a3facd3 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 9 Oct 2012 21:37:31 +0200 Subject: [PATCH 261/432] doc: Provide documentation for link promis counter and rx/tx queues Signed-off-by: Thomas Graf --- doc/route.txt | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/doc/route.txt b/doc/route.txt index 33f58d0..a01f6d9 100644 --- a/doc/route.txt +++ b/doc/route.txt @@ -570,18 +570,51 @@ link objects to be used for comparison. For more information on how to modify the qdisc of a link, see section <>. -[[link_attr_weight]] -==== Weight -This attribute is unused and obsoleted in all recent kernels. +[source,c] +----- +#include + +void rtnl_link_set_qdisc(struct rtnl_link *link, const char *name); +char *rtnl_link_get_qdisc(struct rtnl_link *link); +----- + +[[link_attr_promiscuity]] +==== Promiscuity +The number of subsystem currently depending on the link being promiscuous mode. +A value of 0 indicates that the link is not in promiscuous mode. It is a +read-only attribute provided by the kernel and cannot be modified. The set +function is provided solely for the purpose of creating link objects to be +used for comparison. [source,c] ----- #include -extern void rtnl_link_set_qdisc(struct rtnl_link *link, const char *name); -extern char *rtnl_link_get_qdisc(struct rtnl_link *link); +void rtnl_link_set_promiscuity(struct rtnl_link *link, uint32_t count); +uint32_t rtnl_link_get_promiscuity(struct rtnl_link *link); ----- +[[link_num_rxtx_queues]] +==== RX/TX Queues +The number of RX/TX queues the link provides. The attribute is writable but +will only be considered when creating a new network device via netlink. + +[source,c] +----- +#include + +void rtnl_link_set_num_tx_queues(struct rtnl_link *link, uint32_t nqueues); +uint32_t rtnl_link_get_num_tx_queues(struct rtnl_link *link); + +void rtnl_link_set_num_rx_queues(struct rtnl_link *link, uint32_t nqueues); +uint32_t rtnl_link_get_num_rx_queues(struct rtnl_link *link); +----- + +[[link_attr_weight]] +==== Weight +This attribute is unused and obsoleted in all recent kernels. + + [[link_modules]] === Modules From a35287a689f91734e3bb8687a24e7a8354132290 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 9 Oct 2012 21:55:31 +0200 Subject: [PATCH 262/432] link: Support link grouping New functions: rtnl_link_set_group(link, group) rtnl_link_get_group(link) The group identifier is printed in the brief section as "group N" Signed-off-by: Thomas Graf --- doc/route.txt | 14 +++++++++++++ include/netlink-types.h | 1 + include/netlink/route/link.h | 3 +++ lib/route/link.c | 39 +++++++++++++++++++++++++++++++++++- 4 files changed, 56 insertions(+), 1 deletion(-) diff --git a/doc/route.txt b/doc/route.txt index a01f6d9..e47c6d3 100644 --- a/doc/route.txt +++ b/doc/route.txt @@ -365,6 +365,20 @@ void rtnl_link_set_ifindex(struct rtnl_link *link, int ifindex); int rtnl_link_get_ifindex(struct rtnl_link *link); ----- +[[link_attr_group]] +==== Group +Each link can be assigned a numeric group identifier to group a bunch of links +together and apply a set of changes to a group instead of just a single link. + + +[source,c] +----- +#include + +void rtnl_link_set_group(struct rtnl_link *link, uint32_t group); +uint32_t rtnl_link_get_group(struct rtnl_link *link); +----- + [[link_attr_address]] ==== Link Layer Address The link layer address (e.g. MAC address). diff --git a/include/netlink-types.h b/include/netlink-types.h index 345486f..10ef218 100644 --- a/include/netlink-types.h +++ b/include/netlink-types.h @@ -176,6 +176,7 @@ struct rtnl_link uint32_t l_promiscuity; uint32_t l_num_tx_queues; uint32_t l_num_rx_queues; + uint32_t l_group; }; struct rtnl_ncacheinfo diff --git a/include/netlink/route/link.h b/include/netlink/route/link.h index 518bab5..8268b13 100644 --- a/include/netlink/route/link.h +++ b/include/netlink/route/link.h @@ -148,6 +148,9 @@ extern char * rtnl_link_get_qdisc(struct rtnl_link *); extern void rtnl_link_set_name(struct rtnl_link *, const char *); extern char * rtnl_link_get_name(struct rtnl_link *); +extern void rtnl_link_set_group(struct rtnl_link *, uint32_t); +extern uint32_t rtnl_link_get_group(struct rtnl_link *); + extern void rtnl_link_set_flags(struct rtnl_link *, unsigned int); extern void rtnl_link_unset_flags(struct rtnl_link *, unsigned int); extern unsigned int rtnl_link_get_flags(struct rtnl_link *); diff --git a/lib/route/link.c b/lib/route/link.c index ff2b000..3f9d9dc 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -52,6 +52,7 @@ #define LINK_ATTR_PROMISCUITY (1 << 21) #define LINK_ATTR_NUM_TX_QUEUES (1 << 22) #define LINK_ATTR_NUM_RX_QUEUES (1 << 23) +#define LINK_ATTR_GROUP (1 << 24) static struct nl_cache_ops rtnl_link_ops; static struct nl_object_ops link_obj_ops; @@ -260,6 +261,7 @@ static struct nla_policy link_policy[IFLA_MAX+1] = { [IFLA_PROMISCUITY] = { .type = NLA_U32 }, [IFLA_NUM_TX_QUEUES] = { .type = NLA_U32 }, [IFLA_NUM_RX_QUEUES] = { .type = NLA_U32 }, + [IFLA_GROUP] = { .type = NLA_U32 }, }; static struct nla_policy link_info_policy[IFLA_INFO_MAX+1] = { @@ -554,7 +556,12 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, if (tb[IFLA_NUM_RX_QUEUES]) { link->l_num_rx_queues = nla_get_u32(tb[IFLA_NUM_RX_QUEUES]); link->ce_mask |= LINK_ATTR_NUM_RX_QUEUES; - }; + } + + if (tb[IFLA_GROUP]) { + link->l_group = nla_get_u32(tb[IFLA_GROUP]); + link->ce_mask |= LINK_ATTR_GROUP; + } err = pp->pp_cb((struct nl_object *) link, pp); errout: @@ -613,6 +620,9 @@ static void link_dump_line(struct nl_object *obj, struct nl_dump_params *p) rtnl_link_put(ll); } + if (link->ce_mask & LINK_ATTR_GROUP) + nl_dump(p, "group %u ", link->l_group); + if (link->l_info_ops && link->l_info_ops->io_dump[NL_DUMP_LINE]) link->l_info_ops->io_dump[NL_DUMP_LINE](link, p); @@ -816,6 +826,7 @@ static int link_compare(struct nl_object *_a, struct nl_object *_b, diff |= LINK_DIFF(PROMISCUITY, a->l_promiscuity != b->l_promiscuity); diff |= LINK_DIFF(NUM_TX_QUEUES,a->l_num_tx_queues != b->l_num_tx_queues); diff |= LINK_DIFF(NUM_RX_QUEUES,a->l_num_rx_queues != b->l_num_rx_queues); + diff |= LINK_DIFF(GROUP, a->l_group != b->l_group); if (flags & LOOSE_COMPARISON) diff |= LINK_DIFF(FLAGS, @@ -852,6 +863,7 @@ static const struct trans_tbl link_attrs[] = { __ADD(LINK_ATTR_PROMISCUITY, promiscuity) __ADD(LINK_ATTR_NUM_TX_QUEUES, num_tx_queues) __ADD(LINK_ATTR_NUM_RX_QUEUES, num_rx_queues) + __ADD(LINK_ATTR_GROUP, group) }; static char *link_attrs2str(int attrs, char *buf, size_t len) @@ -1170,6 +1182,9 @@ static int build_link_msg(int cmd, struct ifinfomsg *hdr, if (link->ce_mask & LINK_ATTR_NUM_RX_QUEUES) NLA_PUT_U32(msg, IFLA_NUM_RX_QUEUES, link->l_num_rx_queues); + if (link->ce_mask & LINK_ATTR_GROUP) + NLA_PUT_U32(msg, IFLA_GROUP, link->l_group); + if (link->ce_mask & LINK_ATTR_LINKINFO) { struct nlattr *info; @@ -1523,6 +1538,28 @@ char *rtnl_link_get_name(struct rtnl_link *link) return link->ce_mask & LINK_ATTR_IFNAME ? link->l_name : NULL; } +/** + * Set the group identifier of a link object + * @arg link Link object + * @arg group Group identifier + */ +void rtnl_link_set_group(struct rtnl_link *link, uint32_t group) +{ + link->l_group = group; + link->ce_mask |= LINK_ATTR_GROUP; +} + +/** + * Return the group identifier of link object + * @arg link Link object + * + * @return Group identifier or 0 if not set. + */ +uint32_t rtnl_link_get_group(struct rtnl_link *link) +{ + return link->l_group; +} + static inline void __assign_addr(struct rtnl_link *link, struct nl_addr **pos, struct nl_addr *new, int flag) { From d3bec59eb93a64e803307b9a2ce0b7aad9be5555 Mon Sep 17 00:00:00 2001 From: Rich Fought Date: Tue, 9 Oct 2012 15:16:00 -0700 Subject: [PATCH 263/432] bugfixes --- include/netlink/cli/exp.h | 1 + lib/netfilter/exp.c | 8 ++++---- lib/netfilter/exp_obj.c | 12 +++++++----- src/lib/exp.c | 6 ++++++ src/nf-exp-list.c | 4 ++++ 5 files changed, 22 insertions(+), 9 deletions(-) diff --git a/include/netlink/cli/exp.h b/include/netlink/cli/exp.h index 94609d7..cbe9649 100644 --- a/include/netlink/cli/exp.h +++ b/include/netlink/cli/exp.h @@ -21,6 +21,7 @@ extern struct nl_cache *nl_cli_exp_alloc_cache(struct nl_sock *); extern void nl_cli_exp_parse_family(struct nfnl_exp *, char *); extern void nl_cli_exp_parse_timeout(struct nfnl_exp *, char *); extern void nl_cli_exp_parse_id(struct nfnl_exp *, char *); +extern void nl_cli_exp_parse_helper_name(struct nfnl_exp *, char *); extern void nl_cli_exp_parse_src(struct nfnl_exp *, int, char *); extern void nl_cli_exp_parse_dst(struct nfnl_exp *, int, char *); extern void nl_cli_exp_parse_l4protonum(struct nfnl_exp *, int, char *); diff --git a/lib/netfilter/exp.c b/lib/netfilter/exp.c index c6479f6..dbdc278 100644 --- a/lib/netfilter/exp.c +++ b/lib/netfilter/exp.c @@ -505,8 +505,8 @@ static struct nl_af_group exp_groups[] = { #define NFNLMSG_EXP_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_CTNETLINK_EXP, (type)) static struct nl_cache_ops nfnl_exp_ops = { - .co_name = "netfilter/exp", - .co_hdrsize = NFNL_HDRLEN, + .co_name = "netfilter/exp", + .co_hdrsize = NFNL_HDRLEN, .co_msgtypes = { { NFNLMSG_EXP_TYPE(IPCTNL_MSG_EXP_NEW), NL_ACT_NEW, "new" }, { NFNLMSG_EXP_TYPE(IPCTNL_MSG_EXP_GET), NL_ACT_GET, "get" }, @@ -514,10 +514,10 @@ static struct nl_cache_ops nfnl_exp_ops = { END_OF_MSGTYPES_LIST, }, .co_protocol = NETLINK_NETFILTER, - .co_groups = exp_groups, + .co_groups = exp_groups, .co_request_update = exp_request_update, .co_msg_parser = exp_msg_parser, - .co_obj_ops = &exp_obj_ops, + .co_obj_ops = &exp_obj_ops, }; static void __init exp_init(void) diff --git a/lib/netfilter/exp_obj.c b/lib/netfilter/exp_obj.c index 41ac214..61b12e1 100644 --- a/lib/netfilter/exp_obj.c +++ b/lib/netfilter/exp_obj.c @@ -58,7 +58,6 @@ #define EXP_ATTR_NAT_L4PROTO_NUM (1UL << 25) // contains l4proto # + PORT attrs or ICMP attrs #define EXP_ATTR_NAT_L4PROTO_PORTS (1UL << 26) #define EXP_ATTR_NAT_L4PROTO_ICMP (1UL << 27) - #define EXP_ATTR_NAT_DIR (1UL << 28) // 8-bit /** @endcond */ @@ -184,14 +183,16 @@ static void dump_icmp(struct nl_dump_params *p, struct nfnl_exp *exp, int tuple) static void exp_dump_tuples(struct nfnl_exp *exp, struct nl_dump_params *p) { - struct nl_addr *tuple_src = NULL, *tuple_dst = NULL; + struct nl_addr *tuple_src, *tuple_dst; int tuple_sport = 0, tuple_dport = 0; int i = 0; char buf[64]; for (i = NFNL_EXP_TUPLE_EXPECT; i <= NFNL_EXP_TUPLE_NAT; i++) { + tuple_src = NULL; + tuple_dst = NULL; - // Test needed for NAT case + // Test needed for NAT case if (nfnl_exp_test_src(exp, i)) tuple_src = nfnl_exp_get_src(exp, i); if (nfnl_exp_test_dst(exp, i)) @@ -207,6 +208,7 @@ static void exp_dump_tuples(struct nfnl_exp *exp, struct nl_dump_params *p) tuple_sport = nfnl_exp_get_src_port(exp, i); tuple_dport = nfnl_exp_get_dst_port(exp, i); } + dump_addr(p, tuple_src, tuple_sport); dump_addr(p, tuple_dst, tuple_dport); dump_icmp(p, exp, 0); @@ -636,9 +638,9 @@ uint8_t nfnl_exp_get_nat_dir(const struct nfnl_exp *exp) #define EXP_GET_TUPLE(e, t) \ (t == NFNL_EXP_TUPLE_MASTER) ? \ &(e->exp_master) : \ - (t == NFNL_EXP_TUPLE_MASK) ?\ + (t == NFNL_EXP_TUPLE_MASK) ? \ &(e->exp_mask) : \ - (t == NFNL_EXP_TUPLE_NAT) ?\ + (t == NFNL_EXP_TUPLE_NAT) ? \ &(e->exp_nat) : &(exp->exp_expect) static int exp_get_src_attr(int tuple) diff --git a/src/lib/exp.c b/src/lib/exp.c index 01aae01..82820f9 100644 --- a/src/lib/exp.c +++ b/src/lib/exp.c @@ -59,6 +59,12 @@ void nl_cli_exp_parse_id(struct nfnl_exp *exp, char *arg) nfnl_exp_set_id(exp, id); } +void nl_cli_exp_parse_helper_name(struct nfnl_exp *exp, char *arg) +{ + int err; + nfnl_exp_set_helper_name(exp, arg); +} + void nl_cli_exp_parse_src(struct nfnl_exp *exp, int tuple, char *arg) { int err; diff --git a/src/nf-exp-list.c b/src/nf-exp-list.c index 5a29b4a..3bdb6c5 100644 --- a/src/nf-exp-list.c +++ b/src/nf-exp-list.c @@ -36,6 +36,7 @@ static void print_usage(void) " --master-dport=PORT Master conntrack destination port\n" " -F, --family=FAMILY Address family\n" " --timeout=NUM Timeout value\n" + " --helper=STRING Helper Name\n" //" --flags Flags\n" ); exit(0); @@ -69,6 +70,7 @@ int main(int argc, char *argv[]) ARG_MASTER_DST, ARG_MASTER_DPORT, ARG_TIMEOUT, + ARG_HELPER_NAME, //ARG_FLAGS, }; static struct option long_opts[] = { @@ -88,6 +90,7 @@ int main(int argc, char *argv[]) { "master-dport", 1, 0, ARG_MASTER_DPORT }, { "family", 1, 0, 'F' }, { "timeout", 1, 0, ARG_TIMEOUT }, + { "helper", 1, 0, ARG_HELPER_NAME }, //{ "flags", 1, 0, ARG_FLAGS}, { 0, 0, 0, 0 } }; @@ -116,6 +119,7 @@ int main(int argc, char *argv[]) case ARG_MASTER_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; case 'F': nl_cli_exp_parse_family(exp, optarg); break; case ARG_TIMEOUT: nl_cli_exp_parse_timeout(exp, optarg); break; + case ARG_HELPER_NAME: nl_cli_exp_parse_helper_name(exp, optarg); break; //case ARG_FLAGS: nl_cli_exp_parse_flags(exp, optarg); break; } } From 547c8f6d50c762d1089785e123bb15e479fe354a Mon Sep 17 00:00:00 2001 From: Rich Fought Date: Tue, 9 Oct 2012 15:22:16 -0700 Subject: [PATCH 264/432] reinit port numers on tuple dump --- lib/netfilter/exp_obj.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/netfilter/exp_obj.c b/lib/netfilter/exp_obj.c index 61b12e1..69ba324 100644 --- a/lib/netfilter/exp_obj.c +++ b/lib/netfilter/exp_obj.c @@ -184,13 +184,15 @@ static void dump_icmp(struct nl_dump_params *p, struct nfnl_exp *exp, int tuple) static void exp_dump_tuples(struct nfnl_exp *exp, struct nl_dump_params *p) { struct nl_addr *tuple_src, *tuple_dst; - int tuple_sport = 0, tuple_dport = 0; + int tuple_sport, tuple_dport; int i = 0; char buf[64]; for (i = NFNL_EXP_TUPLE_EXPECT; i <= NFNL_EXP_TUPLE_NAT; i++) { tuple_src = NULL; tuple_dst = NULL; + tuple_sport = 0; + tuple_dport = 0; // Test needed for NAT case if (nfnl_exp_test_src(exp, i)) From 416459570ff8e714c9e072e42984db7f6ba8b977 Mon Sep 17 00:00:00 2001 From: Rich Fought Date: Wed, 10 Oct 2012 13:08:23 -0700 Subject: [PATCH 265/432] Bugfixes --- lib/netfilter/exp.c | 36 +++++----- src/.gitignore | 1 + src/Makefile.am | 3 +- src/lib/exp.c | 1 - src/nf-exp-create.c | 167 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 189 insertions(+), 19 deletions(-) create mode 100644 src/nf-exp-create.c diff --git a/lib/netfilter/exp.c b/lib/netfilter/exp.c index dbdc278..26eaf0c 100644 --- a/lib/netfilter/exp.c +++ b/lib/netfilter/exp.c @@ -37,11 +37,13 @@ static struct nla_policy exp_policy[CTA_EXPECT_MAX+1] = { [CTA_EXPECT_TIMEOUT] = { .type = NLA_U32 }, [CTA_EXPECT_ID] = { .type = NLA_U32 }, [CTA_EXPECT_HELP_NAME] = { .type = NLA_STRING }, - //[CTA_EXPECT_ZONE] = { .type = NLA_U16 }, // In latest kernel header - //[CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, // In latest kernel header - //[CTA_EXPECT_CLASS] = { .type = NLA_U32 }, // In libnetfilter_conntrack include/linux/linux_nfnetlink_conntrack.h - //[CTA_EXPECT_NAT] = { .type = NLA_NESTED }, // In libnetfilter_conntrack include/linux/linux_nfnetlink_conntrack.h - //[CTA_EXPECT_FN] = { .type = NLA_STRING }, // In libnetfilter_conntrack include/linux/linux_nfnetlink_conntrack.h +#if 0 + [CTA_EXPECT_ZONE] = { .type = NLA_U16 }, // In latest kernel header + [CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, // In latest kernel header + [CTA_EXPECT_CLASS] = { .type = NLA_U32 }, // In libnetfilter_conntrack include/linux/linux_nfnetlink_conntrack.h + [CTA_EXPECT_NAT] = { .type = NLA_NESTED }, // In libnetfilter_conntrack include/linux/linux_nfnetlink_conntrack.h + [CTA_EXPECT_FN] = { .type = NLA_STRING }, // In libnetfilter_conntrack include/linux/linux_nfnetlink_conntrack.h +#endif }; static struct nla_policy exp_tuple_policy[CTA_TUPLE_MAX+1] = { @@ -276,18 +278,18 @@ static int exp_get_tuple_attr(int tuple) int attr = 0; switch (tuple) { - case NFNL_EXP_TUPLE_MASTER: - attr = CTA_EXPECT_MASTER; + case CTA_EXPECT_MASTER: + attr = NFNL_EXP_TUPLE_MASTER; break; - case NFNL_EXP_TUPLE_MASK: - attr = CTA_EXPECT_MASK; + case CTA_EXPECT_MASK: + attr = NFNL_EXP_TUPLE_MASK; break; - //case NFNL_EXP_TUPLE_NAT: - // attr = EXP_ATTR_NAT_L4PROTO_NUM; + //case CTA_EXPECT_NAT: + // attr = NFNL_EXP_TUPLE_NAT; // break; - case NFNL_EXP_TUPLE_EXPECT: + case CTA_EXPECT_TUPLE: default : - attr = CTA_EXPECT_TUPLE; + attr = NFNL_EXP_TUPLE_EXPECT; break; } @@ -295,17 +297,17 @@ static int exp_get_tuple_attr(int tuple) } static int nfnl_exp_build_tuple(struct nl_msg *msg, const struct nfnl_exp *exp, - int type) + int cta) { struct nlattr *tuple, *ip, *proto; struct nl_addr *addr; int family; - int tupattr = exp_get_tuple_attr(type); - family = nfnl_exp_get_family(exp); - tuple = nla_nest_start(msg, tupattr); + int type = exp_get_tuple_attr(cta); + + tuple = nla_nest_start(msg, cta); if (!tuple) goto nla_put_failure; diff --git a/src/.gitignore b/src/.gitignore index b02885a..2c6d839 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,6 +1,7 @@ genl-ctrl-list nf-ct-list nf-exp-list +nf-exp-create nf-log nf-monitor nl-addr-add diff --git a/src/Makefile.am b/src/Makefile.am index cf5cd48..317f2d9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -21,7 +21,8 @@ sbin_PROGRAMS = \ nl-link-list noinst_PROGRAMS = \ - nf-ct-list nf-log nf-queue nf-monitor nf-exp-list \ + nf-ct-list nf-log nf-queue nf-monitor \ + nf-exp-list nf-exp-create \ nl-addr-add nl-addr-delete nl-addr-list \ nl-link-set nl-link-stats \ nl-link-ifindex2name nl-link-name2ifindex \ diff --git a/src/lib/exp.c b/src/lib/exp.c index 82820f9..7cebacc 100644 --- a/src/lib/exp.c +++ b/src/lib/exp.c @@ -61,7 +61,6 @@ void nl_cli_exp_parse_id(struct nfnl_exp *exp, char *arg) void nl_cli_exp_parse_helper_name(struct nfnl_exp *exp, char *arg) { - int err; nfnl_exp_set_helper_name(exp, arg); } diff --git a/src/nf-exp-create.c b/src/nf-exp-create.c new file mode 100644 index 0000000..d003a4a --- /dev/null +++ b/src/nf-exp-create.c @@ -0,0 +1,167 @@ +/* + * src/nf-exp-create.c Create an expectation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2012 Rich Fought + */ + +#include +#include + +static int quiet = 0; + +static void print_usage(void) +{ + printf( + "Usage: nf-exp-list [OPTION]... [CONNTRACK ENTRY]\n" + "\n" + "Options\n" + " --replace Replace the address if it exists.\n" + " -q, --quiet Do not print informal notifications.\n" + " -h, --help Show this help\n" + " -v, --version Show versioning information\n" + "\n" + "Expectation Selection\n" + " -i, --id=NUM Identifier\n" + " --expect-proto=PROTOCOL Expectation protocol\n" + " --expect-src=ADDR Expectation source address\n" + " --expect-sport=PORT Expectation source port\n" + " --expect-dst=ADDR Expectation destination address\n" + " --expect-dport=PORT Expectation destination port\n" + " --master-proto=PROTOCOL Master conntrack protocol\n" + " --master-src=ADDR Master conntrack source address\n" + " --master-sport=PORT Master conntrack source port\n" + " --master-dst=ADDR Master conntrack destination address\n" + " --master-dport=PORT Master conntrack destination port\n" + " --mask-proto=PROTOCOL Mask protocol\n" + " --mask-src=ADDR Mask source address\n" + " --mask-sport=PORT Mask source port\n" + " --mask-dst=ADDR Mask destination address\n" + " --mask-dport=PORT Mask destination port\n" + " -F, --family=FAMILY Address family\n" + " --timeout=NUM Timeout value\n" + " --helper=STRING Helper Name\n" + //" --flags Flags\n" + ); + exit(0); +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct nfnl_exp *exp; + struct nl_dump_params params = { + .dp_type = NL_DUMP_LINE, + .dp_fd = stdout, + }; + int err, nlflags = NLM_F_CREATE; + + exp = nl_cli_exp_alloc(); + + for (;;) { + int c, optidx = 0; + enum { + ARG_MARK = 270, + ARG_TCP_STATE = 271, + ARG_EXPECT_PROTO, + ARG_EXPECT_SRC, + ARG_EXPECT_SPORT, + ARG_EXPECT_DST, + ARG_EXPECT_DPORT, + ARG_MASTER_PROTO, + ARG_MASTER_SRC, + ARG_MASTER_SPORT, + ARG_MASTER_DST, + ARG_MASTER_DPORT, + ARG_MASK_PROTO, + ARG_MASK_SRC, + ARG_MASK_SPORT, + ARG_MASK_DST, + ARG_MASK_DPORT, + ARG_TIMEOUT, + ARG_HELPER_NAME, + ARG_REPLACE, + //ARG_FLAGS, + }; + static struct option long_opts[] = { + { "replace", 1, 0, ARG_REPLACE }, + { "quiet", 0, 0, 'q' }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "id", 1, 0, 'i' }, + { "expect-proto", 1, 0, ARG_EXPECT_PROTO }, + { "expect-src", 1, 0, ARG_EXPECT_SRC }, + { "expect-sport", 1, 0, ARG_EXPECT_SPORT }, + { "expect-dst", 1, 0, ARG_EXPECT_DST }, + { "expect-dport", 1, 0, ARG_EXPECT_DPORT }, + { "master-proto", 1, 0, ARG_MASTER_PROTO }, + { "master-src", 1, 0, ARG_MASTER_SRC }, + { "master-sport", 1, 0, ARG_MASTER_SPORT }, + { "master-dst", 1, 0, ARG_MASTER_DST }, + { "master-dport", 1, 0, ARG_MASTER_DPORT }, + { "mask-proto", 1, 0, ARG_MASK_PROTO }, + { "mask-src", 1, 0, ARG_MASK_SRC }, + { "mask-sport", 1, 0, ARG_MASK_SPORT }, + { "mask-dst", 1, 0, ARG_MASK_DST }, + { "mask-dport", 1, 0, ARG_MASK_DPORT }, + { "family", 1, 0, 'F' }, + { "timeout", 1, 0, ARG_TIMEOUT }, + { "helper", 1, 0, ARG_HELPER_NAME }, + //{ "flags", 1, 0, ARG_FLAGS}, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "46f:hvi:p:F:", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case '?': exit(NLE_INVAL); + case ARG_REPLACE: nlflags |= NLM_F_REPLACE; break; + case 'q': quiet = 1; break; + case '4': nfnl_exp_set_family(exp, AF_INET); break; + case '6': nfnl_exp_set_family(exp, AF_INET6); break; + case 'h': print_usage(); break; + case 'v': nl_cli_print_version(); break; + case 'i': nl_cli_exp_parse_id(exp, optarg); break; + case ARG_EXPECT_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; + case ARG_EXPECT_SRC: nl_cli_exp_parse_src(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; + case ARG_EXPECT_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; + case ARG_EXPECT_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; + case ARG_EXPECT_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; + case ARG_MASTER_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; + case ARG_MASTER_SRC: nl_cli_exp_parse_src(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; + case ARG_MASTER_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; + case ARG_MASTER_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; + case ARG_MASTER_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; + case ARG_MASK_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_MASK, optarg); break; + case ARG_MASK_SRC: nl_cli_exp_parse_src(exp, NFNL_EXP_TUPLE_MASK, optarg); break; + case ARG_MASK_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_MASK, optarg); break; + case ARG_MASK_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_MASK, optarg); break; + case ARG_MASK_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_MASK, optarg); break; + case 'F': nl_cli_exp_parse_family(exp, optarg); break; + case ARG_TIMEOUT: nl_cli_exp_parse_timeout(exp, optarg); break; + case ARG_HELPER_NAME: nl_cli_exp_parse_helper_name(exp, optarg); break; + //case ARG_FLAGS: nl_cli_exp_parse_flags(exp, optarg); break; + } + } + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_NETFILTER); + + if ((err = nfnl_exp_add(sock, exp, nlflags)) < 0) + nl_cli_fatal(err, "Unable to add expectation: %s", + nl_geterror(err)); + + if (!quiet) { + printf("Added "); + nl_object_dump(OBJ_CAST(exp), ¶ms); + } + + + return 0; +} From 07418658a6dae7243f2b7d51aebe9ad0299b40ad Mon Sep 17 00:00:00 2001 From: Rich Fought Date: Fri, 12 Oct 2012 17:44:27 -0700 Subject: [PATCH 266/432] define advanced attributes out --- include/netlink/netfilter/exp.h | 32 ++++++-- lib/netfilter/exp.c | 128 +++++++++++++++++++++++++++++--- lib/netfilter/exp_obj.c | 75 +++++++++---------- 3 files changed, 179 insertions(+), 56 deletions(-) diff --git a/include/netlink/netfilter/exp.h b/include/netlink/netfilter/exp.h index bb4c98e..89a9d01 100644 --- a/include/netlink/netfilter/exp.h +++ b/include/netlink/netfilter/exp.h @@ -19,6 +19,19 @@ #include #include +#include + +#if CTA_EXPECT_MAX > CTA_EXPECT_HELP_NAME +#define NLE_ZONE +#elseif CTA_EXPECT_MAX > CTA_EXPECT_ZONE +#define NLE_ZONE +#define NLE_FLAGS +#elseif (CTA_EXPECT_MAX > CTA_EXPECT_FLAGS) +#define NLE_ZONE +#define NLE_FLAGS +#define NLE_NAT_FN_CLASS +#endif + #ifdef __cplusplus extern "C" { #endif @@ -29,7 +42,10 @@ enum nfnl_exp_tuples { NFNL_EXP_TUPLE_EXPECT, NFNL_EXP_TUPLE_MASTER, NFNL_EXP_TUPLE_MASK, - NFNL_EXP_TUPLE_NAT +#ifdef NLE_NAT_FN_CLASS + NFNL_EXP_TUPLE_NAT, +#endif + NFNL_EXP_TUPLE_MAX }; extern struct nl_object_ops exp_obj_ops; @@ -72,17 +88,22 @@ extern int nfnl_exp_set_helper_name(struct nfnl_exp *, void *); extern int nfnl_exp_test_helper_name(const struct nfnl_exp *); extern const char * nfnl_exp_get_helper_name(const struct nfnl_exp *); +#ifdef NLE_ZONE extern void nfnl_exp_set_zone(struct nfnl_exp *, uint16_t); extern int nfnl_exp_test_zone(const struct nfnl_exp *); extern uint16_t nfnl_exp_get_zone(const struct nfnl_exp *); +#endif -extern void nfnl_exp_set_class(struct nfnl_exp *, uint32_t); -extern int nfnl_exp_test_class(const struct nfnl_exp *); -extern uint32_t nfnl_exp_get_class(const struct nfnl_exp *); - +#ifdef NLE_FLAGS extern void nfnl_exp_set_flags(struct nfnl_exp *, uint32_t); extern int nfnl_exp_test_flags(const struct nfnl_exp *); extern uint32_t nfnl_exp_get_flags(const struct nfnl_exp *); +#endif + +#ifdef NLE_NAT_FN_CLASS +extern void nfnl_exp_set_class(struct nfnl_exp *, uint32_t); +extern int nfnl_exp_test_class(const struct nfnl_exp *); +extern uint32_t nfnl_exp_get_class(const struct nfnl_exp *); extern int nfnl_exp_set_fn(struct nfnl_exp *, void *); extern int nfnl_exp_test_fn(const struct nfnl_exp *); @@ -91,6 +112,7 @@ extern const char * nfnl_exp_get_fn(const struct nfnl_exp *); extern void nfnl_exp_set_nat_dir(struct nfnl_exp *, uint8_t); extern int nfnl_exp_test_nat_dir(const struct nfnl_exp *); extern uint8_t nfnl_exp_get_nat_dir(const struct nfnl_exp *); +#endif // The int argument specifies which nfnl_exp_dir (expect, master, mask or nat) // Expectation objects only use orig, not reply diff --git a/lib/netfilter/exp.c b/lib/netfilter/exp.c index 26eaf0c..cbe1b95 100644 --- a/lib/netfilter/exp.c +++ b/lib/netfilter/exp.c @@ -37,12 +37,16 @@ static struct nla_policy exp_policy[CTA_EXPECT_MAX+1] = { [CTA_EXPECT_TIMEOUT] = { .type = NLA_U32 }, [CTA_EXPECT_ID] = { .type = NLA_U32 }, [CTA_EXPECT_HELP_NAME] = { .type = NLA_STRING }, -#if 0 - [CTA_EXPECT_ZONE] = { .type = NLA_U16 }, // In latest kernel header - [CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, // In latest kernel header - [CTA_EXPECT_CLASS] = { .type = NLA_U32 }, // In libnetfilter_conntrack include/linux/linux_nfnetlink_conntrack.h - [CTA_EXPECT_NAT] = { .type = NLA_NESTED }, // In libnetfilter_conntrack include/linux/linux_nfnetlink_conntrack.h - [CTA_EXPECT_FN] = { .type = NLA_STRING }, // In libnetfilter_conntrack include/linux/linux_nfnetlink_conntrack.h +#ifdef NLE_ZONE + [CTA_EXPECT_ZONE] = { .type = NLA_U16 }, // Added in kernel 2.6.34 +#endif +#ifdef NLE_FLAGS + [CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, // Added in kernel 2.6.37 +#endif +#ifdef NLE_NAT_FN_CLASS + [CTA_EXPECT_CLASS] = { .type = NLA_U32 }, // Added in kernel 3.5 + [CTA_EXPECT_NAT] = { .type = NLA_NESTED }, // Added in kernel 3.5 + [CTA_EXPECT_FN] = { .type = NLA_STRING }, // Added in kernel 3.5 #endif }; @@ -59,10 +63,10 @@ static struct nla_policy exp_ip_policy[CTA_IP_MAX+1] = { }; static struct nla_policy exp_proto_policy[CTA_PROTO_MAX+1] = { - [CTA_PROTO_NUM] = { .type = NLA_U8 }, + [CTA_PROTO_NUM] = { .type = NLA_U8 }, [CTA_PROTO_SRC_PORT] = { .type = NLA_U16 }, [CTA_PROTO_DST_PORT] = { .type = NLA_U16 }, - [CTA_PROTO_ICMP_ID] = { .type = NLA_U16 }, + [CTA_PROTO_ICMP_ID] = { .type = NLA_U16 }, [CTA_PROTO_ICMP_TYPE] = { .type = NLA_U8 }, [CTA_PROTO_ICMP_CODE] = { .type = NLA_U8 }, [CTA_PROTO_ICMPV6_ID] = { .type = NLA_U16 }, @@ -70,6 +74,12 @@ static struct nla_policy exp_proto_policy[CTA_PROTO_MAX+1] = { [CTA_PROTO_ICMPV6_CODE] = { .type = NLA_U8 }, }; +#ifdef NLE_NAT_FN_CLASS +static struct nla_policy exp_nat_policy[CTA_EXPECT_NAT_MAX+1] = { + [CTA_EXPECT_NAT_DIR] = { .type = NLA_U8 }, + [CTA_EXPECT_NAT_TUPLE] = { .type = NLA_NESTED }, +}; +#endif static int exp_parse_ip(struct nfnl_exp *exp, int tuple, struct nlattr *attr) { @@ -182,6 +192,29 @@ static int exp_parse_tuple(struct nfnl_exp *exp, int tuple, struct nlattr *attr) return 0; } +#ifdef NLE_NAT_FN_CLASS +static int exp_parse_nat(struct nfnl_exp *exp, struct nlattr *attr) +{ + struct nlattr *tb[CTA_EXPECT_NAT_MAX+1]; + int err; + + err = nla_parse_nested(tb, CTA_EXPECT_NAT_MAX, attr, exp_nat_policy); + if (err < 0) + return err; + + if (tb[CTA_EXPECT_NAT_DIR]) + nfnl_exp_set_nat_dir(exp, nla_get_u8(tb[CTA_EXPECT_NAT_DIR])); + + if (tb[CTA_EXPECT_NAT_TUPLE]) { + err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_NAT, tb[CTA_EXPECT_NAT_TUPLE]); + if (err < 0) + return err; + } + + return 0; +} +#endif + int nfnlmsg_exp_group(struct nlmsghdr *nlh) { switch (nfnlmsg_subtype(nlh)) { @@ -232,13 +265,41 @@ int nfnlmsg_exp_parse(struct nlmsghdr *nlh, struct nfnl_exp **result) goto errout; } +#ifdef NLE_NAT_FN_CLASS + if (tb[CTA_EXPECT_NAT]) + err = exp_parse_nat(exp, tb[CTA_EXPECT_MASK]); + if (err < 0) + goto errout; + + if (tb[CTA_EXPECT_CLASS]) + nfnl_exp_set_class(exp, ntohl(nla_get_u32(tb[CTA_EXPECT_CLASS]))); + + if (tb[CTA_EXPECT_FN]) + nfnl_exp_set_fn(exp, nla_data(tb[CTA_EXPECT_FN])); + +#endif + + if (tb[CTA_EXPECT_TIMEOUT]) nfnl_exp_set_timeout(exp, ntohl(nla_get_u32(tb[CTA_EXPECT_TIMEOUT]))); + if (tb[CTA_EXPECT_ID]) nfnl_exp_set_id(exp, ntohl(nla_get_u32(tb[CTA_EXPECT_ID]))); - if (tb[CTA_EXPECT_HELP_NAME]) + + if (tb[CTA_EXPECT_HELP_NAME]) nfnl_exp_set_helper_name(exp, nla_data(tb[CTA_EXPECT_HELP_NAME])); +#ifdef NLE_ZONE + if (tb[CTA_EXPECT_ZONE]) + nfnl_exp_set_zone(exp, ntohs(nla_get_u16(tb[CTA_EXPECT_ZONE]))); +#endif + +#ifdef NLE_FLAGS + if (tb[CTA_EXPECT_FLAGS]) + nfnl_exp_set_flags(exp, ntohl(nla_get_u32(tb[CTA_EXPECT_FLAGS]))); +#endif + + *result = exp; return 0; @@ -364,6 +425,30 @@ nla_put_failure: return -NLE_MSGSIZE; } +#ifdef NLE_NAT_FN_CLASS +static int nfnl_exp_build_nat(struct nl_msg *msg, const struct nfnl_exp *exp) +{ + struct nlattr *nat; + int err; + + nat = nla_nest_start(msg, CTA_EXPECT_NAT); + + if (nfnl_exp_test_nat_dir(exp)) { + NLA_PUT_U8(msg, CTA_EXPECT_NAT_DIR, + nfnl_exp_get_nat_dir(exp)); + } + + if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_NAT_TUPLE)) < 0) + goto nla_put_failure; + + nla_nest_end(msg, nat); + return 0; + +nla_put_failure: + return -NLE_MSGSIZE; +} +#endif + static int nfnl_exp_build_message(const struct nfnl_exp *exp, int cmd, int flags, struct nl_msg **result) { @@ -384,7 +469,20 @@ static int nfnl_exp_build_message(const struct nfnl_exp *exp, int cmd, int flags if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_MASK)) < 0) goto err_out; - // FIXME timeout and helper name +#ifdef NLE_NAT_FN_CLASS + if (nfnl_exp_test_src(exp, NFNL_EXP_TUPLE_NAT)) { + if ((err = nfnl_exp_build_nat(msg, exp)) < 0) + goto err_out; + } + + if (nfnl_exp_test_class(exp)) + NLA_PUT_U32(msg, CTA_EXPECT_CLASS, htonl(nfnl_exp_get_class(exp))); + + if (nfnl_exp_test_fn(exp)) + NLA_PUT_STRING(msg, CTA_EXPECT_FN, nfnl_exp_get_fn(exp)); + +#endif + if (nfnl_exp_test_id(exp)) NLA_PUT_U32(msg, CTA_EXPECT_ID, htonl(nfnl_exp_get_id(exp))); @@ -394,6 +492,16 @@ static int nfnl_exp_build_message(const struct nfnl_exp *exp, int cmd, int flags if (nfnl_exp_test_helper_name(exp)) NLA_PUT_STRING(msg, CTA_EXPECT_HELP_NAME, nfnl_exp_get_helper_name(exp)); +#ifdef NLE_ZONE + if (nfnl_exp_test_zone(exp)) + NLA_PUT_U16(msg, CTA_EXPECT_ZONE, htons(nfnl_exp_get_zone(exp))); +#endif + +#ifdef NLE_FLAGS + if (nfnl_exp_test_flags(exp)) + NLA_PUT_U32(msg, CTA_EXPECT_FLAGS, htonl(nfnl_exp_get_flags(exp))); +#endif + *result = msg; return 0; diff --git a/lib/netfilter/exp_obj.c b/lib/netfilter/exp_obj.c index 69ba324..daf4b09 100644 --- a/lib/netfilter/exp_obj.c +++ b/lib/netfilter/exp_obj.c @@ -33,10 +33,9 @@ #define EXP_ATTR_ID (1UL << 2) // 32-bit #define EXP_ATTR_HELPER_NAME (1UL << 3) // string (16 bytes max) #define EXP_ATTR_ZONE (1UL << 4) // 16-bit -#define EXP_ATTR_CLASS (1UL << 5) // 32-bit ??? -#define EXP_ATTR_FLAGS (1UL << 6) // 32-bit +#define EXP_ATTR_FLAGS (1UL << 5) // 32-bit +#define EXP_ATTR_CLASS (1UL << 6) // 32-bit ??? #define EXP_ATTR_FN (1UL << 7) // String ??? - // Tuples #define EXP_ATTR_EXPECT_IP_SRC (1UL << 8) #define EXP_ATTR_EXPECT_IP_DST (1UL << 9) @@ -188,7 +187,7 @@ static void exp_dump_tuples(struct nfnl_exp *exp, struct nl_dump_params *p) int i = 0; char buf[64]; - for (i = NFNL_EXP_TUPLE_EXPECT; i <= NFNL_EXP_TUPLE_NAT; i++) { + for (i = NFNL_EXP_TUPLE_EXPECT; i < NFNL_EXP_TUPLE_MAX; i++) { tuple_src = NULL; tuple_dst = NULL; tuple_sport = 0; @@ -216,8 +215,10 @@ static void exp_dump_tuples(struct nfnl_exp *exp, struct nl_dump_params *p) dump_icmp(p, exp, 0); } +#ifdef NLE_NAT_FN_CLASS if (nfnl_exp_test_nat_dir(exp)) nl_dump(p, "nat dir %s ", exp->exp_nat_dir); +#endif } @@ -254,18 +255,22 @@ static void exp_dump_details(struct nl_object *a, struct nl_dump_params *p) if (nfnl_exp_test_helper_name(exp)) nl_dump(p, "helper %s ", exp->exp_helper_name); +#ifdef NLE_NAT_FN_CLASS if (nfnl_exp_test_fn(exp)) nl_dump(p, "fn %s ", exp->exp_fn); - if (nfnl_exp_test_zone(exp)) - nl_dump(p, "zone %u ", nfnl_exp_get_zone(exp)); - if (nfnl_exp_test_class(exp)) nl_dump(p, "class %u ", nfnl_exp_get_class(exp)); +#endif - if (nfnl_exp_test_flags(exp)) +#ifdef NLE_ZONE + if (nfnl_exp_test_zone(exp)) + nl_dump(p, "zone %u ", nfnl_exp_get_zone(exp)); +#endif + +#ifdef NLE_FLAGS + if (nfnl_exp_test_flags(exp)) nl_dump(p, "<"); - #define PRINT_FLAG(str) \ { nl_dump(p, "%s%s", fp++ ? "," : "", (str)); } @@ -279,41 +284,11 @@ static void exp_dump_details(struct nl_object *a, struct nl_dump_params *p) if (nfnl_exp_test_flags(exp)) nl_dump(p, ">"); +#endif + nl_dump(p, "\n"); } -/* -static void ct_dump_stats(struct nl_object *a, struct nl_dump_params *p) -{ - struct nfnl_ct *ct = (struct nfnl_ct *) a; - double res; - char *unit; - uint64_t packets; - const char * const names[] = {"rx", "tx"}; - int i; - - ct_dump_details(a, p); - - if (!nfnl_ct_test_bytes(ct, 0) || - !nfnl_ct_test_packets(ct, 0) || - !nfnl_ct_test_bytes(ct, 1) || - !nfnl_ct_test_packets(ct, 1)) - { - nl_dump_line(p, " Statistics are not available.\n"); - nl_dump_line(p, " Please set sysctl net.netfilter.nf_conntrack_acct=1\n"); - nl_dump_line(p, " (Require kernel 2.6.27)\n"); - return; - } - - nl_dump_line(p, " # packets volume\n"); - for (i=0; i<=1; i++) { - res = nl_cancel_down_bytes(nfnl_ct_get_bytes(ct, i), &unit); - packets = nfnl_ct_get_packets(ct, i); - nl_dump_line(p, " %s %10" PRIu64 " %7.2f %s\n", names[i], packets, res, unit); - } -} -*/ - static int exp_cmp_l4proto_ports (union nfnl_exp_protodata *a, union nfnl_exp_protodata *b) { // Must return 0 for match, 1 for mismatch int d = 0; @@ -637,6 +612,7 @@ uint8_t nfnl_exp_get_nat_dir(const struct nfnl_exp *exp) return exp->exp_nat_dir; } +#ifdef NLE_NAT_FN_CLASS #define EXP_GET_TUPLE(e, t) \ (t == NFNL_EXP_TUPLE_MASTER) ? \ &(e->exp_master) : \ @@ -644,6 +620,13 @@ uint8_t nfnl_exp_get_nat_dir(const struct nfnl_exp *exp) &(e->exp_mask) : \ (t == NFNL_EXP_TUPLE_NAT) ? \ &(e->exp_nat) : &(exp->exp_expect) +#else +#define EXP_GET_TUPLE(e, t) \ + (t == NFNL_EXP_TUPLE_MASTER) ? \ + &(e->exp_master) : \ + (t == NFNL_EXP_TUPLE_MASK) ? \ + &(e->exp_mask) : &(exp->exp_expect) +#endif static int exp_get_src_attr(int tuple) { @@ -656,9 +639,11 @@ static int exp_get_src_attr(int tuple) case NFNL_EXP_TUPLE_MASK: attr = EXP_ATTR_MASK_IP_SRC; break; +#ifdef NLE_NAT_FN_CLASS case NFNL_EXP_TUPLE_NAT: attr = EXP_ATTR_NAT_IP_SRC; break; +#endif case NFNL_EXP_TUPLE_EXPECT: default : attr = EXP_ATTR_EXPECT_IP_SRC; @@ -679,9 +664,11 @@ static int exp_get_dst_attr(int tuple) case NFNL_EXP_TUPLE_MASK: attr = EXP_ATTR_MASK_IP_DST; break; +#ifdef NLE_NAT_FN_CLASS case NFNL_EXP_TUPLE_NAT: attr = EXP_ATTR_NAT_IP_DST; break; +#endif case NFNL_EXP_TUPLE_EXPECT: default : attr = EXP_ATTR_EXPECT_IP_DST; @@ -765,9 +752,11 @@ static int exp_get_l4protonum_attr(int tuple) case NFNL_EXP_TUPLE_MASK: attr = EXP_ATTR_MASK_L4PROTO_NUM; break; +#ifdef NLE_NAT_FN_CLASS case NFNL_EXP_TUPLE_NAT: attr = EXP_ATTR_NAT_L4PROTO_NUM; break; +#endif case NFNL_EXP_TUPLE_EXPECT: default : attr = EXP_ATTR_EXPECT_L4PROTO_NUM; @@ -807,9 +796,11 @@ static int exp_get_l4ports_attr(int tuple) case NFNL_EXP_TUPLE_MASK: attr = EXP_ATTR_MASK_L4PROTO_PORTS; break; +#ifdef NLE_NAT_FN_CLASS case NFNL_EXP_TUPLE_NAT: attr = EXP_ATTR_NAT_L4PROTO_PORTS; break; +#endif case NFNL_EXP_TUPLE_EXPECT: default : attr = EXP_ATTR_EXPECT_L4PROTO_PORTS; @@ -858,9 +849,11 @@ static int exp_get_l4icmp_attr(int tuple) case NFNL_EXP_TUPLE_MASK: attr = EXP_ATTR_MASK_L4PROTO_ICMP; break; +#ifdef NLE_NAT_FN_CLASS case NFNL_EXP_TUPLE_NAT: attr = EXP_ATTR_NAT_L4PROTO_ICMP; break; +#endif case NFNL_EXP_TUPLE_EXPECT: default : attr = EXP_ATTR_EXPECT_L4PROTO_ICMP; From 2d707513c6d5e83df9e3bcf5d006ca9c819a1f07 Mon Sep 17 00:00:00 2001 From: Rich Fought Date: Tue, 16 Oct 2012 12:13:33 -0700 Subject: [PATCH 267/432] Updated nfnetlink includes; removed ifdefs; added delete exp program --- include/linux/netfilter/nfnetlink.h | 114 +++++--- include/linux/netfilter/nfnetlink_conntrack.h | 268 ++++++++++++------ include/linux/netfilter/nfnetlink_log.h | 44 +-- include/linux/netfilter/nfnetlink_queue.h | 102 +++---- include/netlink/cli/exp.h | 11 + include/netlink/netfilter/exp.h | 20 +- lib/netfilter/exp.c | 28 +- lib/netfilter/exp_obj.c | 33 +-- src/.gitignore | 3 +- src/Makefile.am | 6 +- src/lib/exp.c | 61 +++- src/{nf-exp-create.c => nf-exp-add.c} | 16 +- src/nf-exp-delete.c | 167 +++++++++++ src/nf-exp-list.c | 11 +- 14 files changed, 604 insertions(+), 280 deletions(-) rename src/{nf-exp-create.c => nf-exp-add.c} (93%) create mode 100644 src/nf-exp-delete.c diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h index 1e59984..43979ac 100644 --- a/include/linux/netfilter/nfnetlink.h +++ b/include/linux/netfilter/nfnetlink.h @@ -1,60 +1,96 @@ #ifndef _NFNETLINK_H #define _NFNETLINK_H #include - -#ifndef __KERNEL__ -/* nfnetlink groups: Up to 32 maximum - backwards compatibility for userspace */ -#define NF_NETLINK_CONNTRACK_NEW 0x00000001 -#define NF_NETLINK_CONNTRACK_UPDATE 0x00000002 -#define NF_NETLINK_CONNTRACK_DESTROY 0x00000004 -#define NF_NETLINK_CONNTRACK_EXP_NEW 0x00000008 -#define NF_NETLINK_CONNTRACK_EXP_UPDATE 0x00000010 -#define NF_NETLINK_CONNTRACK_EXP_DESTROY 0x00000020 -#endif +#include enum nfnetlink_groups { - NFNLGRP_NONE, -#define NFNLGRP_NONE NFNLGRP_NONE - NFNLGRP_CONNTRACK_NEW, -#define NFNLGRP_CONNTRACK_NEW NFNLGRP_CONNTRACK_NEW - NFNLGRP_CONNTRACK_UPDATE, -#define NFNLGRP_CONNTRACK_UPDATE NFNLGRP_CONNTRACK_UPDATE - NFNLGRP_CONNTRACK_DESTROY, -#define NFNLGRP_CONNTRACK_DESTROY NFNLGRP_CONNTRACK_DESTROY - NFNLGRP_CONNTRACK_EXP_NEW, -#define NFNLGRP_CONNTRACK_EXP_NEW NFNLGRP_CONNTRACK_EXP_NEW - NFNLGRP_CONNTRACK_EXP_UPDATE, -#define NFNLGRP_CONNTRACK_EXP_UPDATE NFNLGRP_CONNTRACK_EXP_UPDATE - NFNLGRP_CONNTRACK_EXP_DESTROY, -#define NFNLGRP_CONNTRACK_EXP_DESTROY NFNLGRP_CONNTRACK_EXP_DESTROY - __NFNLGRP_MAX, + NFNLGRP_NONE, +#define NFNLGRP_NONE NFNLGRP_NONE + NFNLGRP_CONNTRACK_NEW, +#define NFNLGRP_CONNTRACK_NEW NFNLGRP_CONNTRACK_NEW + NFNLGRP_CONNTRACK_UPDATE, +#define NFNLGRP_CONNTRACK_UPDATE NFNLGRP_CONNTRACK_UPDATE + NFNLGRP_CONNTRACK_DESTROY, +#define NFNLGRP_CONNTRACK_DESTROY NFNLGRP_CONNTRACK_DESTROY + NFNLGRP_CONNTRACK_EXP_NEW, +#define NFNLGRP_CONNTRACK_EXP_NEW NFNLGRP_CONNTRACK_EXP_NEW + NFNLGRP_CONNTRACK_EXP_UPDATE, +#define NFNLGRP_CONNTRACK_EXP_UPDATE NFNLGRP_CONNTRACK_EXP_UPDATE + NFNLGRP_CONNTRACK_EXP_DESTROY, +#define NFNLGRP_CONNTRACK_EXP_DESTROY NFNLGRP_CONNTRACK_EXP_DESTROY + __NFNLGRP_MAX, }; -#define NFNLGRP_MAX (__NFNLGRP_MAX - 1) +#define NFNLGRP_MAX (__NFNLGRP_MAX - 1) /* General form of address family dependent message. */ struct nfgenmsg { - u_int8_t nfgen_family; /* AF_xxx */ - u_int8_t version; /* nfnetlink version */ - __be16 res_id; /* resource id */ + __u8 nfgen_family; /* AF_xxx */ + __u8 version; /* nfnetlink version */ + __be16 res_id; /* resource id */ }; -#define NFNETLINK_V0 0 +#define NFNETLINK_V0 0 /* netfilter netlink message types are split in two pieces: * 8 bit subsystem, 8bit operation. */ -#define NFNL_SUBSYS_ID(x) ((x & 0xff00) >> 8) -#define NFNL_MSG_TYPE(x) (x & 0x00ff) +#define NFNL_SUBSYS_ID(x) ((x & 0xff00) >> 8) +#define NFNL_MSG_TYPE(x) (x & 0x00ff) /* No enum here, otherwise __stringify() trick of MODULE_ALIAS_NFNL_SUBSYS() * won't work anymore */ -#define NFNL_SUBSYS_NONE 0 -#define NFNL_SUBSYS_CTNETLINK 1 -#define NFNL_SUBSYS_CTNETLINK_EXP 2 -#define NFNL_SUBSYS_QUEUE 3 -#define NFNL_SUBSYS_ULOG 4 -#define NFNL_SUBSYS_COUNT 5 +#define NFNL_SUBSYS_NONE 0 +#define NFNL_SUBSYS_CTNETLINK 1 +#define NFNL_SUBSYS_CTNETLINK_EXP 2 +#define NFNL_SUBSYS_QUEUE 3 +#define NFNL_SUBSYS_ULOG 4 +#define NFNL_SUBSYS_OSF 5 +#define NFNL_SUBSYS_IPSET 6 +#define NFNL_SUBSYS_ACCT 7 +#define NFNL_SUBSYS_CTNETLINK_TIMEOUT 8 +#define NFNL_SUBSYS_CTHELPER 9 +#define NFNL_SUBSYS_COUNT 10 -#endif /* _NFNETLINK_H */ +#ifdef __KERNEL__ + +#include +#include +#include + +struct nfnl_callback { + int (*call)(struct sock *nl, struct sk_buff *skb, + const struct nlmsghdr *nlh, + const struct nlattr * const cda[]); + int (*call_rcu)(struct sock *nl, struct sk_buff *skb, + const struct nlmsghdr *nlh, + const struct nlattr * const cda[]); + const struct nla_policy *policy; /* netlink attribute policy */ + const u_int16_t attr_count; /* number of nlattr's */ +}; + +struct nfnetlink_subsystem { + const char *name; + __u8 subsys_id; /* nfnetlink subsystem ID */ + __u8 cb_count; /* number of callbacks */ + const struct nfnl_callback *cb; /* callback for individual types */ +}; + +extern int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n); +extern int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n); + +extern int nfnetlink_has_listeners(struct net *net, unsigned int group); +extern int nfnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned int group, + int echo, gfp_t flags); +extern int nfnetlink_set_err(struct net *net, u32 pid, u32 group, int error); +extern int nfnetlink_unicast(struct sk_buff *skb, struct net *net, u_int32_t pid, int flags); + +extern void nfnl_lock(void); +extern void nfnl_unlock(void); + +#define MODULE_ALIAS_NFNL_SUBSYS(subsys) \ + MODULE_ALIAS("nfnetlink-subsys-" __stringify(subsys)) + +#endif /* __KERNEL__ */ +#endif /* _NFNETLINK_H */ diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux/netfilter/nfnetlink_conntrack.h index d7c3503..c91be60 100644 --- a/include/linux/netfilter/nfnetlink_conntrack.h +++ b/include/linux/netfilter/nfnetlink_conntrack.h @@ -3,138 +3,242 @@ #include enum cntl_msg_types { - IPCTNL_MSG_CT_NEW, - IPCTNL_MSG_CT_GET, - IPCTNL_MSG_CT_DELETE, - IPCTNL_MSG_CT_GET_CTRZERO, + IPCTNL_MSG_CT_NEW, + IPCTNL_MSG_CT_GET, + IPCTNL_MSG_CT_DELETE, + IPCTNL_MSG_CT_GET_CTRZERO, + IPCTNL_MSG_CT_GET_STATS_CPU, + IPCTNL_MSG_CT_GET_STATS, - IPCTNL_MSG_MAX + IPCTNL_MSG_MAX }; enum ctnl_exp_msg_types { - IPCTNL_MSG_EXP_NEW, - IPCTNL_MSG_EXP_GET, - IPCTNL_MSG_EXP_DELETE, + IPCTNL_MSG_EXP_NEW, + IPCTNL_MSG_EXP_GET, + IPCTNL_MSG_EXP_DELETE, + IPCTNL_MSG_EXP_GET_STATS_CPU, - IPCTNL_MSG_EXP_MAX + IPCTNL_MSG_EXP_MAX }; enum ctattr_type { - CTA_UNSPEC, - CTA_TUPLE_ORIG, - CTA_TUPLE_REPLY, - CTA_STATUS, - CTA_PROTOINFO, - CTA_HELP, - CTA_NAT_SRC, -#define CTA_NAT CTA_NAT_SRC /* backwards compatibility */ - CTA_TIMEOUT, - CTA_MARK, - CTA_COUNTERS_ORIG, - CTA_COUNTERS_REPLY, - CTA_USE, - CTA_ID, - CTA_NAT_DST, - __CTA_MAX + CTA_UNSPEC, + CTA_TUPLE_ORIG, + CTA_TUPLE_REPLY, + CTA_STATUS, + CTA_PROTOINFO, + CTA_HELP, + CTA_NAT_SRC, +#define CTA_NAT CTA_NAT_SRC /* backwards compatibility */ + CTA_TIMEOUT, + CTA_MARK, + CTA_COUNTERS_ORIG, + CTA_COUNTERS_REPLY, + CTA_USE, + CTA_ID, + CTA_NAT_DST, + CTA_TUPLE_MASTER, + CTA_NAT_SEQ_ADJ_ORIG, + CTA_NAT_SEQ_ADJ_REPLY, + CTA_SECMARK, /* obsolete */ + CTA_ZONE, + CTA_SECCTX, + CTA_TIMESTAMP, + CTA_MARK_MASK, + __CTA_MAX }; #define CTA_MAX (__CTA_MAX - 1) enum ctattr_tuple { - CTA_TUPLE_UNSPEC, - CTA_TUPLE_IP, - CTA_TUPLE_PROTO, - __CTA_TUPLE_MAX + CTA_TUPLE_UNSPEC, + CTA_TUPLE_IP, + CTA_TUPLE_PROTO, + __CTA_TUPLE_MAX }; #define CTA_TUPLE_MAX (__CTA_TUPLE_MAX - 1) enum ctattr_ip { - CTA_IP_UNSPEC, - CTA_IP_V4_SRC, - CTA_IP_V4_DST, - CTA_IP_V6_SRC, - CTA_IP_V6_DST, - __CTA_IP_MAX + CTA_IP_UNSPEC, + CTA_IP_V4_SRC, + CTA_IP_V4_DST, + CTA_IP_V6_SRC, + CTA_IP_V6_DST, + __CTA_IP_MAX }; #define CTA_IP_MAX (__CTA_IP_MAX - 1) enum ctattr_l4proto { - CTA_PROTO_UNSPEC, - CTA_PROTO_NUM, - CTA_PROTO_SRC_PORT, - CTA_PROTO_DST_PORT, - CTA_PROTO_ICMP_ID, - CTA_PROTO_ICMP_TYPE, - CTA_PROTO_ICMP_CODE, - CTA_PROTO_ICMPV6_ID, - CTA_PROTO_ICMPV6_TYPE, - CTA_PROTO_ICMPV6_CODE, - __CTA_PROTO_MAX + CTA_PROTO_UNSPEC, + CTA_PROTO_NUM, + CTA_PROTO_SRC_PORT, + CTA_PROTO_DST_PORT, + CTA_PROTO_ICMP_ID, + CTA_PROTO_ICMP_TYPE, + CTA_PROTO_ICMP_CODE, + CTA_PROTO_ICMPV6_ID, + CTA_PROTO_ICMPV6_TYPE, + CTA_PROTO_ICMPV6_CODE, + __CTA_PROTO_MAX }; #define CTA_PROTO_MAX (__CTA_PROTO_MAX - 1) enum ctattr_protoinfo { - CTA_PROTOINFO_UNSPEC, - CTA_PROTOINFO_TCP, - __CTA_PROTOINFO_MAX + CTA_PROTOINFO_UNSPEC, + CTA_PROTOINFO_TCP, + CTA_PROTOINFO_DCCP, + CTA_PROTOINFO_SCTP, + __CTA_PROTOINFO_MAX }; #define CTA_PROTOINFO_MAX (__CTA_PROTOINFO_MAX - 1) enum ctattr_protoinfo_tcp { - CTA_PROTOINFO_TCP_UNSPEC, - CTA_PROTOINFO_TCP_STATE, - CTA_PROTOINFO_TCP_WSCALE_ORIGINAL, - CTA_PROTOINFO_TCP_WSCALE_REPLY, - CTA_PROTOINFO_TCP_FLAGS_ORIGINAL, - CTA_PROTOINFO_TCP_FLAGS_REPLY, - __CTA_PROTOINFO_TCP_MAX + CTA_PROTOINFO_TCP_UNSPEC, + CTA_PROTOINFO_TCP_STATE, + CTA_PROTOINFO_TCP_WSCALE_ORIGINAL, + CTA_PROTOINFO_TCP_WSCALE_REPLY, + CTA_PROTOINFO_TCP_FLAGS_ORIGINAL, + CTA_PROTOINFO_TCP_FLAGS_REPLY, + __CTA_PROTOINFO_TCP_MAX }; #define CTA_PROTOINFO_TCP_MAX (__CTA_PROTOINFO_TCP_MAX - 1) +enum ctattr_protoinfo_dccp { + CTA_PROTOINFO_DCCP_UNSPEC, + CTA_PROTOINFO_DCCP_STATE, + CTA_PROTOINFO_DCCP_ROLE, + CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ, + __CTA_PROTOINFO_DCCP_MAX, +}; +#define CTA_PROTOINFO_DCCP_MAX (__CTA_PROTOINFO_DCCP_MAX - 1) + +enum ctattr_protoinfo_sctp { + CTA_PROTOINFO_SCTP_UNSPEC, + CTA_PROTOINFO_SCTP_STATE, + CTA_PROTOINFO_SCTP_VTAG_ORIGINAL, + CTA_PROTOINFO_SCTP_VTAG_REPLY, + __CTA_PROTOINFO_SCTP_MAX +}; +#define CTA_PROTOINFO_SCTP_MAX (__CTA_PROTOINFO_SCTP_MAX - 1) + enum ctattr_counters { - CTA_COUNTERS_UNSPEC, - CTA_COUNTERS_PACKETS, /* old 64bit counters */ - CTA_COUNTERS_BYTES, /* old 64bit counters */ - CTA_COUNTERS32_PACKETS, - CTA_COUNTERS32_BYTES, - __CTA_COUNTERS_MAX + CTA_COUNTERS_UNSPEC, + CTA_COUNTERS_PACKETS, /* 64bit counters */ + CTA_COUNTERS_BYTES, /* 64bit counters */ + CTA_COUNTERS32_PACKETS, /* old 32bit counters, unused */ + CTA_COUNTERS32_BYTES, /* old 32bit counters, unused */ + __CTA_COUNTERS_MAX }; #define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1) +enum ctattr_tstamp { + CTA_TIMESTAMP_UNSPEC, + CTA_TIMESTAMP_START, + CTA_TIMESTAMP_STOP, + __CTA_TIMESTAMP_MAX +}; +#define CTA_TIMESTAMP_MAX (__CTA_TIMESTAMP_MAX - 1) + enum ctattr_nat { - CTA_NAT_UNSPEC, - CTA_NAT_MINIP, - CTA_NAT_MAXIP, - CTA_NAT_PROTO, - __CTA_NAT_MAX + CTA_NAT_UNSPEC, + CTA_NAT_MINIP, + CTA_NAT_MAXIP, + CTA_NAT_PROTO, + __CTA_NAT_MAX }; #define CTA_NAT_MAX (__CTA_NAT_MAX - 1) enum ctattr_protonat { - CTA_PROTONAT_UNSPEC, - CTA_PROTONAT_PORT_MIN, - CTA_PROTONAT_PORT_MAX, - __CTA_PROTONAT_MAX + CTA_PROTONAT_UNSPEC, + CTA_PROTONAT_PORT_MIN, + CTA_PROTONAT_PORT_MAX, + __CTA_PROTONAT_MAX }; #define CTA_PROTONAT_MAX (__CTA_PROTONAT_MAX - 1) +enum ctattr_natseq { + CTA_NAT_SEQ_UNSPEC, + CTA_NAT_SEQ_CORRECTION_POS, + CTA_NAT_SEQ_OFFSET_BEFORE, + CTA_NAT_SEQ_OFFSET_AFTER, + __CTA_NAT_SEQ_MAX +}; +#define CTA_NAT_SEQ_MAX (__CTA_NAT_SEQ_MAX - 1) + enum ctattr_expect { - CTA_EXPECT_UNSPEC, - CTA_EXPECT_MASTER, - CTA_EXPECT_TUPLE, - CTA_EXPECT_MASK, - CTA_EXPECT_TIMEOUT, - CTA_EXPECT_ID, - CTA_EXPECT_HELP_NAME, - __CTA_EXPECT_MAX + CTA_EXPECT_UNSPEC, + CTA_EXPECT_MASTER, + CTA_EXPECT_TUPLE, + CTA_EXPECT_MASK, + CTA_EXPECT_TIMEOUT, + CTA_EXPECT_ID, + CTA_EXPECT_HELP_NAME, + CTA_EXPECT_ZONE, + CTA_EXPECT_FLAGS, + CTA_EXPECT_CLASS, + CTA_EXPECT_NAT, + CTA_EXPECT_FN, + __CTA_EXPECT_MAX }; #define CTA_EXPECT_MAX (__CTA_EXPECT_MAX - 1) +enum ctattr_expect_nat { + CTA_EXPECT_NAT_UNSPEC, + CTA_EXPECT_NAT_DIR, + CTA_EXPECT_NAT_TUPLE, + __CTA_EXPECT_NAT_MAX +}; +#define CTA_EXPECT_NAT_MAX (__CTA_EXPECT_NAT_MAX - 1) + enum ctattr_help { - CTA_HELP_UNSPEC, - CTA_HELP_NAME, - __CTA_HELP_MAX + CTA_HELP_UNSPEC, + CTA_HELP_NAME, + CTA_HELP_INFO, + __CTA_HELP_MAX }; #define CTA_HELP_MAX (__CTA_HELP_MAX - 1) +enum ctattr_secctx { + CTA_SECCTX_UNSPEC, + CTA_SECCTX_NAME, + __CTA_SECCTX_MAX +}; +#define CTA_SECCTX_MAX (__CTA_SECCTX_MAX - 1) + +enum ctattr_stats_cpu { + CTA_STATS_UNSPEC, + CTA_STATS_SEARCHED, + CTA_STATS_FOUND, + CTA_STATS_NEW, + CTA_STATS_INVALID, + CTA_STATS_IGNORE, + CTA_STATS_DELETE, + CTA_STATS_DELETE_LIST, + CTA_STATS_INSERT, + CTA_STATS_INSERT_FAILED, + CTA_STATS_DROP, + CTA_STATS_EARLY_DROP, + CTA_STATS_ERROR, + CTA_STATS_SEARCH_RESTART, + __CTA_STATS_MAX, +}; +#define CTA_STATS_MAX (__CTA_STATS_MAX - 1) + +enum ctattr_stats_global { + CTA_STATS_GLOBAL_UNSPEC, + CTA_STATS_GLOBAL_ENTRIES, + __CTA_STATS_GLOBAL_MAX, +}; +#define CTA_STATS_GLOBAL_MAX (__CTA_STATS_GLOBAL_MAX - 1) + +enum ctattr_expect_stats { + CTA_STATS_EXP_UNSPEC, + CTA_STATS_EXP_NEW, + CTA_STATS_EXP_CREATE, + CTA_STATS_EXP_DELETE, + __CTA_STATS_EXP_MAX, +}; +#define CTA_STATS_EXP_MAX (__CTA_STATS_EXP_MAX - 1) + #endif /* _IPCONNTRACK_NETLINK_H */ diff --git a/include/linux/netfilter/nfnetlink_log.h b/include/linux/netfilter/nfnetlink_log.h index 38fafc1..90c2c95 100644 --- a/include/linux/netfilter/nfnetlink_log.h +++ b/include/linux/netfilter/nfnetlink_log.h @@ -5,10 +5,6 @@ * and not any kind of function definitions. It is shared between kernel and * userspace. Don't put kernel specific stuff in here */ -#ifndef aligned_be64 -#define aligned_be64 u_int64_t __attribute__((aligned(8))) -#endif - #include #include @@ -21,30 +17,30 @@ enum nfulnl_msg_types { struct nfulnl_msg_packet_hdr { __be16 hw_protocol; /* hw protocol (network order) */ - u_int8_t hook; /* netfilter hook */ - u_int8_t _pad; + __u8 hook; /* netfilter hook */ + __u8 _pad; }; struct nfulnl_msg_packet_hw { __be16 hw_addrlen; - u_int16_t _pad; - u_int8_t hw_addr[8]; + __u16 _pad; + __u8 hw_addr[8]; }; struct nfulnl_msg_packet_timestamp { - aligned_be64 sec; - aligned_be64 usec; + __aligned_be64 sec; + __aligned_be64 usec; }; enum nfulnl_attr_type { NFULA_UNSPEC, NFULA_PACKET_HDR, - NFULA_MARK, /* u_int32_t nfmark */ + NFULA_MARK, /* __u32 nfmark */ NFULA_TIMESTAMP, /* nfulnl_msg_packet_timestamp */ - NFULA_IFINDEX_INDEV, /* u_int32_t ifindex */ - NFULA_IFINDEX_OUTDEV, /* u_int32_t ifindex */ - NFULA_IFINDEX_PHYSINDEV, /* u_int32_t ifindex */ - NFULA_IFINDEX_PHYSOUTDEV, /* u_int32_t ifindex */ + NFULA_IFINDEX_INDEV, /* __u32 ifindex */ + NFULA_IFINDEX_OUTDEV, /* __u32 ifindex */ + NFULA_IFINDEX_PHYSINDEV, /* __u32 ifindex */ + NFULA_IFINDEX_PHYSOUTDEV, /* __u32 ifindex */ NFULA_HWADDR, /* nfulnl_msg_packet_hw */ NFULA_PAYLOAD, /* opaque data payload */ NFULA_PREFIX, /* string prefix */ @@ -52,6 +48,9 @@ enum nfulnl_attr_type { NFULA_SEQ, /* instance-local sequence number */ NFULA_SEQ_GLOBAL, /* global sequence number */ NFULA_GID, /* group id of socket */ + NFULA_HWTYPE, /* hardware type */ + NFULA_HWHEADER, /* hardware header */ + NFULA_HWLEN, /* hardware header length */ __NFULA_MAX }; @@ -66,23 +65,23 @@ enum nfulnl_msg_config_cmds { }; struct nfulnl_msg_config_cmd { - u_int8_t command; /* nfulnl_msg_config_cmds */ + __u8 command; /* nfulnl_msg_config_cmds */ } __attribute__ ((packed)); struct nfulnl_msg_config_mode { __be32 copy_range; - u_int8_t copy_mode; - u_int8_t _pad; + __u8 copy_mode; + __u8 _pad; } __attribute__ ((packed)); enum nfulnl_attr_config { NFULA_CFG_UNSPEC, NFULA_CFG_CMD, /* nfulnl_msg_config_cmd */ NFULA_CFG_MODE, /* nfulnl_msg_config_mode */ - NFULA_CFG_NLBUFSIZ, /* u_int32_t buffer size */ - NFULA_CFG_TIMEOUT, /* u_int32_t in 1/100 s */ - NFULA_CFG_QTHRESH, /* u_int32_t */ - NFULA_CFG_FLAGS, /* u_int16_t */ + NFULA_CFG_NLBUFSIZ, /* __u32 buffer size */ + NFULA_CFG_TIMEOUT, /* __u32 in 1/100 s */ + NFULA_CFG_QTHRESH, /* __u32 */ + NFULA_CFG_FLAGS, /* __u16 */ __NFULA_CFG_MAX }; #define NFULA_CFG_MAX (__NFULA_CFG_MAX -1) @@ -90,6 +89,7 @@ enum nfulnl_attr_config { #define NFULNL_COPY_NONE 0x00 #define NFULNL_COPY_META 0x01 #define NFULNL_COPY_PACKET 0x02 +/* 0xff is reserved, don't use it for new copy modes. */ #define NFULNL_CFG_F_SEQ 0x0001 #define NFULNL_CFG_F_SEQ_GLOBAL 0x0002 diff --git a/include/linux/netfilter/nfnetlink_queue.h b/include/linux/netfilter/nfnetlink_queue.h index bf7cfb6..5fcd48c 100644 --- a/include/linux/netfilter/nfnetlink_queue.h +++ b/include/linux/netfilter/nfnetlink_queue.h @@ -4,91 +4,97 @@ #include #include -#ifndef aligned_be64 -#define aligned_be64 u_int64_t __attribute__((aligned(8))) -#endif - enum nfqnl_msg_types { - NFQNL_MSG_PACKET, /* packet from kernel to userspace */ - NFQNL_MSG_VERDICT, /* verdict from userspace to kernel */ - NFQNL_MSG_CONFIG, /* connect to a particular queue */ + NFQNL_MSG_PACKET, /* packet from kernel to userspace */ + NFQNL_MSG_VERDICT, /* verdict from userspace to kernel */ + NFQNL_MSG_CONFIG, /* connect to a particular queue */ + NFQNL_MSG_VERDICT_BATCH, /* batchv from userspace to kernel */ - NFQNL_MSG_MAX + NFQNL_MSG_MAX }; struct nfqnl_msg_packet_hdr { - __be32 packet_id; /* unique ID of packet in queue */ - __be16 hw_protocol; /* hw protocol (network order) */ - u_int8_t hook; /* netfilter hook */ + __be32 packet_id; /* unique ID of packet in queue */ + __be16 hw_protocol; /* hw protocol (network order) */ + __u8 hook; /* netfilter hook */ } __attribute__ ((packed)); struct nfqnl_msg_packet_hw { - __be16 hw_addrlen; - u_int16_t _pad; - u_int8_t hw_addr[8]; + __be16 hw_addrlen; + __u16 _pad; + __u8 hw_addr[8]; }; struct nfqnl_msg_packet_timestamp { - aligned_be64 sec; - aligned_be64 usec; + __aligned_be64 sec; + __aligned_be64 usec; }; enum nfqnl_attr_type { - NFQA_UNSPEC, - NFQA_PACKET_HDR, - NFQA_VERDICT_HDR, /* nfqnl_msg_verdict_hrd */ - NFQA_MARK, /* u_int32_t nfmark */ - NFQA_TIMESTAMP, /* nfqnl_msg_packet_timestamp */ - NFQA_IFINDEX_INDEV, /* u_int32_t ifindex */ - NFQA_IFINDEX_OUTDEV, /* u_int32_t ifindex */ - NFQA_IFINDEX_PHYSINDEV, /* u_int32_t ifindex */ - NFQA_IFINDEX_PHYSOUTDEV, /* u_int32_t ifindex */ - NFQA_HWADDR, /* nfqnl_msg_packet_hw */ - NFQA_PAYLOAD, /* opaque data payload */ + NFQA_UNSPEC, + NFQA_PACKET_HDR, + NFQA_VERDICT_HDR, /* nfqnl_msg_verdict_hrd */ + NFQA_MARK, /* __u32 nfmark */ + NFQA_TIMESTAMP, /* nfqnl_msg_packet_timestamp */ + NFQA_IFINDEX_INDEV, /* __u32 ifindex */ + NFQA_IFINDEX_OUTDEV, /* __u32 ifindex */ + NFQA_IFINDEX_PHYSINDEV, /* __u32 ifindex */ + NFQA_IFINDEX_PHYSOUTDEV, /* __u32 ifindex */ + NFQA_HWADDR, /* nfqnl_msg_packet_hw */ + NFQA_PAYLOAD, /* opaque data payload */ + NFQA_CT, /* nf_conntrack_netlink.h */ + NFQA_CT_INFO, /* enum ip_conntrack_info */ - __NFQA_MAX + __NFQA_MAX }; #define NFQA_MAX (__NFQA_MAX - 1) struct nfqnl_msg_verdict_hdr { - __be32 verdict; - __be32 id; + __be32 verdict; + __be32 id; }; enum nfqnl_msg_config_cmds { - NFQNL_CFG_CMD_NONE, - NFQNL_CFG_CMD_BIND, - NFQNL_CFG_CMD_UNBIND, - NFQNL_CFG_CMD_PF_BIND, - NFQNL_CFG_CMD_PF_UNBIND, + NFQNL_CFG_CMD_NONE, + NFQNL_CFG_CMD_BIND, + NFQNL_CFG_CMD_UNBIND, + NFQNL_CFG_CMD_PF_BIND, + NFQNL_CFG_CMD_PF_UNBIND, }; struct nfqnl_msg_config_cmd { - u_int8_t command; /* nfqnl_msg_config_cmds */ - u_int8_t _pad; - __be16 pf; /* AF_xxx for PF_[UN]BIND */ + __u8 command; /* nfqnl_msg_config_cmds */ + __u8 _pad; + __be16 pf; /* AF_xxx for PF_[UN]BIND */ }; enum nfqnl_config_mode { - NFQNL_COPY_NONE, - NFQNL_COPY_META, - NFQNL_COPY_PACKET, + NFQNL_COPY_NONE, + NFQNL_COPY_META, + NFQNL_COPY_PACKET, }; struct nfqnl_msg_config_params { - __be32 copy_range; - u_int8_t copy_mode; /* enum nfqnl_config_mode */ + __be32 copy_range; + __u8 copy_mode; /* enum nfqnl_config_mode */ } __attribute__ ((packed)); enum nfqnl_attr_config { - NFQA_CFG_UNSPEC, - NFQA_CFG_CMD, /* nfqnl_msg_config_cmd */ - NFQA_CFG_PARAMS, /* nfqnl_msg_config_params */ - NFQA_CFG_QUEUE_MAXLEN, /* u_int32_t */ - __NFQA_CFG_MAX + NFQA_CFG_UNSPEC, + NFQA_CFG_CMD, /* nfqnl_msg_config_cmd */ + NFQA_CFG_PARAMS, /* nfqnl_msg_config_params */ + NFQA_CFG_QUEUE_MAXLEN, /* __u32 */ + NFQA_CFG_MASK, /* identify which flags to change */ + NFQA_CFG_FLAGS, /* value of these flags (__u32) */ + __NFQA_CFG_MAX }; #define NFQA_CFG_MAX (__NFQA_CFG_MAX-1) +/* Flags for NFQA_CFG_FLAGS */ +#define NFQA_CFG_F_FAIL_OPEN (1 << 0) +#define NFQA_CFG_F_CONNTRACK (1 << 1) +#define NFQA_CFG_F_MAX (1 << 2) + #endif /* _NFNETLINK_QUEUE_H */ diff --git a/include/netlink/cli/exp.h b/include/netlink/cli/exp.h index cbe9649..b2418f8 100644 --- a/include/netlink/cli/exp.h +++ b/include/netlink/cli/exp.h @@ -7,6 +7,7 @@ * of the License. * * Copyright (c) 2012 Rich Fought + * Copyright (c) 2008-2009 Thomas Graf */ #ifndef __NETLINK_CLI_EXP_H_ @@ -22,10 +23,20 @@ extern void nl_cli_exp_parse_family(struct nfnl_exp *, char *); extern void nl_cli_exp_parse_timeout(struct nfnl_exp *, char *); extern void nl_cli_exp_parse_id(struct nfnl_exp *, char *); extern void nl_cli_exp_parse_helper_name(struct nfnl_exp *, char *); +extern void nl_cli_exp_parse_zone(struct nfnl_exp *, char *); +extern void nl_cli_exp_parse_flags(struct nfnl_exp *, char *); +extern void nl_cli_exp_parse_class(struct nfnl_exp *, char *); +extern void nl_cli_exp_parse_nat_dir(struct nfnl_exp *, char *); +extern void nl_cli_exp_parse_fn(struct nfnl_exp *, char *); + extern void nl_cli_exp_parse_src(struct nfnl_exp *, int, char *); extern void nl_cli_exp_parse_dst(struct nfnl_exp *, int, char *); extern void nl_cli_exp_parse_l4protonum(struct nfnl_exp *, int, char *); extern void nl_cli_exp_parse_src_port(struct nfnl_exp *, int, char *); extern void nl_cli_exp_parse_dst_port(struct nfnl_exp *, int, char *); +extern void nl_cli_exp_parse_icmp_id(struct nfnl_exp *, int, char *); +extern void nl_cli_exp_parse_icmp_type(struct nfnl_exp *, int, char *); +extern void nl_cli_exp_parse_icmp_code(struct nfnl_exp *, int, char *); + #endif diff --git a/include/netlink/netfilter/exp.h b/include/netlink/netfilter/exp.h index 89a9d01..8b50c30 100644 --- a/include/netlink/netfilter/exp.h +++ b/include/netlink/netfilter/exp.h @@ -9,6 +9,7 @@ * Copyright (c) 2003-2008 Thomas Graf * Copyright (c) 2007 Philip Craig * Copyright (c) 2007 Secure Computing Corporation + * Copyright (c) 2012 Rich Fought */ #ifndef NETLINK_EXP_H_ @@ -21,17 +22,6 @@ #include -#if CTA_EXPECT_MAX > CTA_EXPECT_HELP_NAME -#define NLE_ZONE -#elseif CTA_EXPECT_MAX > CTA_EXPECT_ZONE -#define NLE_ZONE -#define NLE_FLAGS -#elseif (CTA_EXPECT_MAX > CTA_EXPECT_FLAGS) -#define NLE_ZONE -#define NLE_FLAGS -#define NLE_NAT_FN_CLASS -#endif - #ifdef __cplusplus extern "C" { #endif @@ -42,9 +32,7 @@ enum nfnl_exp_tuples { NFNL_EXP_TUPLE_EXPECT, NFNL_EXP_TUPLE_MASTER, NFNL_EXP_TUPLE_MASK, -#ifdef NLE_NAT_FN_CLASS NFNL_EXP_TUPLE_NAT, -#endif NFNL_EXP_TUPLE_MAX }; @@ -88,19 +76,14 @@ extern int nfnl_exp_set_helper_name(struct nfnl_exp *, void *); extern int nfnl_exp_test_helper_name(const struct nfnl_exp *); extern const char * nfnl_exp_get_helper_name(const struct nfnl_exp *); -#ifdef NLE_ZONE extern void nfnl_exp_set_zone(struct nfnl_exp *, uint16_t); extern int nfnl_exp_test_zone(const struct nfnl_exp *); extern uint16_t nfnl_exp_get_zone(const struct nfnl_exp *); -#endif -#ifdef NLE_FLAGS extern void nfnl_exp_set_flags(struct nfnl_exp *, uint32_t); extern int nfnl_exp_test_flags(const struct nfnl_exp *); extern uint32_t nfnl_exp_get_flags(const struct nfnl_exp *); -#endif -#ifdef NLE_NAT_FN_CLASS extern void nfnl_exp_set_class(struct nfnl_exp *, uint32_t); extern int nfnl_exp_test_class(const struct nfnl_exp *); extern uint32_t nfnl_exp_get_class(const struct nfnl_exp *); @@ -112,7 +95,6 @@ extern const char * nfnl_exp_get_fn(const struct nfnl_exp *); extern void nfnl_exp_set_nat_dir(struct nfnl_exp *, uint8_t); extern int nfnl_exp_test_nat_dir(const struct nfnl_exp *); extern uint8_t nfnl_exp_get_nat_dir(const struct nfnl_exp *); -#endif // The int argument specifies which nfnl_exp_dir (expect, master, mask or nat) // Expectation objects only use orig, not reply diff --git a/lib/netfilter/exp.c b/lib/netfilter/exp.c index cbe1b95..05bc044 100644 --- a/lib/netfilter/exp.c +++ b/lib/netfilter/exp.c @@ -1,5 +1,5 @@ /* - * lib/netfilter/ct.c Conntrack Expectation + * lib/netfilter/exp.c Conntrack Expectation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -10,6 +10,7 @@ * Copyright (c) 2007 Philip Craig * Copyright (c) 2007 Secure Computing Corporation * Copyright (c= 2008 Patrick McHardy + * Copyright (c) 2012 Rich Fought */ /** @@ -37,17 +38,11 @@ static struct nla_policy exp_policy[CTA_EXPECT_MAX+1] = { [CTA_EXPECT_TIMEOUT] = { .type = NLA_U32 }, [CTA_EXPECT_ID] = { .type = NLA_U32 }, [CTA_EXPECT_HELP_NAME] = { .type = NLA_STRING }, -#ifdef NLE_ZONE [CTA_EXPECT_ZONE] = { .type = NLA_U16 }, // Added in kernel 2.6.34 -#endif -#ifdef NLE_FLAGS [CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, // Added in kernel 2.6.37 -#endif -#ifdef NLE_NAT_FN_CLASS [CTA_EXPECT_CLASS] = { .type = NLA_U32 }, // Added in kernel 3.5 [CTA_EXPECT_NAT] = { .type = NLA_NESTED }, // Added in kernel 3.5 [CTA_EXPECT_FN] = { .type = NLA_STRING }, // Added in kernel 3.5 -#endif }; static struct nla_policy exp_tuple_policy[CTA_TUPLE_MAX+1] = { @@ -74,12 +69,10 @@ static struct nla_policy exp_proto_policy[CTA_PROTO_MAX+1] = { [CTA_PROTO_ICMPV6_CODE] = { .type = NLA_U8 }, }; -#ifdef NLE_NAT_FN_CLASS static struct nla_policy exp_nat_policy[CTA_EXPECT_NAT_MAX+1] = { [CTA_EXPECT_NAT_DIR] = { .type = NLA_U8 }, [CTA_EXPECT_NAT_TUPLE] = { .type = NLA_NESTED }, }; -#endif static int exp_parse_ip(struct nfnl_exp *exp, int tuple, struct nlattr *attr) { @@ -192,7 +185,6 @@ static int exp_parse_tuple(struct nfnl_exp *exp, int tuple, struct nlattr *attr) return 0; } -#ifdef NLE_NAT_FN_CLASS static int exp_parse_nat(struct nfnl_exp *exp, struct nlattr *attr) { struct nlattr *tb[CTA_EXPECT_NAT_MAX+1]; @@ -213,7 +205,6 @@ static int exp_parse_nat(struct nfnl_exp *exp, struct nlattr *attr) return 0; } -#endif int nfnlmsg_exp_group(struct nlmsghdr *nlh) { @@ -265,7 +256,6 @@ int nfnlmsg_exp_parse(struct nlmsghdr *nlh, struct nfnl_exp **result) goto errout; } -#ifdef NLE_NAT_FN_CLASS if (tb[CTA_EXPECT_NAT]) err = exp_parse_nat(exp, tb[CTA_EXPECT_MASK]); if (err < 0) @@ -277,7 +267,6 @@ int nfnlmsg_exp_parse(struct nlmsghdr *nlh, struct nfnl_exp **result) if (tb[CTA_EXPECT_FN]) nfnl_exp_set_fn(exp, nla_data(tb[CTA_EXPECT_FN])); -#endif if (tb[CTA_EXPECT_TIMEOUT]) @@ -289,16 +278,11 @@ int nfnlmsg_exp_parse(struct nlmsghdr *nlh, struct nfnl_exp **result) if (tb[CTA_EXPECT_HELP_NAME]) nfnl_exp_set_helper_name(exp, nla_data(tb[CTA_EXPECT_HELP_NAME])); -#ifdef NLE_ZONE if (tb[CTA_EXPECT_ZONE]) nfnl_exp_set_zone(exp, ntohs(nla_get_u16(tb[CTA_EXPECT_ZONE]))); -#endif -#ifdef NLE_FLAGS if (tb[CTA_EXPECT_FLAGS]) nfnl_exp_set_flags(exp, ntohl(nla_get_u32(tb[CTA_EXPECT_FLAGS]))); -#endif - *result = exp; return 0; @@ -425,7 +409,6 @@ nla_put_failure: return -NLE_MSGSIZE; } -#ifdef NLE_NAT_FN_CLASS static int nfnl_exp_build_nat(struct nl_msg *msg, const struct nfnl_exp *exp) { struct nlattr *nat; @@ -447,7 +430,6 @@ static int nfnl_exp_build_nat(struct nl_msg *msg, const struct nfnl_exp *exp) nla_put_failure: return -NLE_MSGSIZE; } -#endif static int nfnl_exp_build_message(const struct nfnl_exp *exp, int cmd, int flags, struct nl_msg **result) @@ -469,7 +451,6 @@ static int nfnl_exp_build_message(const struct nfnl_exp *exp, int cmd, int flags if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_MASK)) < 0) goto err_out; -#ifdef NLE_NAT_FN_CLASS if (nfnl_exp_test_src(exp, NFNL_EXP_TUPLE_NAT)) { if ((err = nfnl_exp_build_nat(msg, exp)) < 0) goto err_out; @@ -481,7 +462,6 @@ static int nfnl_exp_build_message(const struct nfnl_exp *exp, int cmd, int flags if (nfnl_exp_test_fn(exp)) NLA_PUT_STRING(msg, CTA_EXPECT_FN, nfnl_exp_get_fn(exp)); -#endif if (nfnl_exp_test_id(exp)) NLA_PUT_U32(msg, CTA_EXPECT_ID, htonl(nfnl_exp_get_id(exp))); @@ -492,15 +472,11 @@ static int nfnl_exp_build_message(const struct nfnl_exp *exp, int cmd, int flags if (nfnl_exp_test_helper_name(exp)) NLA_PUT_STRING(msg, CTA_EXPECT_HELP_NAME, nfnl_exp_get_helper_name(exp)); -#ifdef NLE_ZONE if (nfnl_exp_test_zone(exp)) NLA_PUT_U16(msg, CTA_EXPECT_ZONE, htons(nfnl_exp_get_zone(exp))); -#endif -#ifdef NLE_FLAGS if (nfnl_exp_test_flags(exp)) NLA_PUT_U32(msg, CTA_EXPECT_FLAGS, htonl(nfnl_exp_get_flags(exp))); -#endif *result = msg; return 0; diff --git a/lib/netfilter/exp_obj.c b/lib/netfilter/exp_obj.c index daf4b09..eeb05b3 100644 --- a/lib/netfilter/exp_obj.c +++ b/lib/netfilter/exp_obj.c @@ -9,6 +9,7 @@ * Copyright (c) 2003-2008 Thomas Graf * Copyright (c) 2007 Philip Craig * Copyright (c) 2007 Secure Computing Corporation + * Copyright (c) 2012 Rich Fought */ #include @@ -215,10 +216,8 @@ static void exp_dump_tuples(struct nfnl_exp *exp, struct nl_dump_params *p) dump_icmp(p, exp, 0); } -#ifdef NLE_NAT_FN_CLASS if (nfnl_exp_test_nat_dir(exp)) nl_dump(p, "nat dir %s ", exp->exp_nat_dir); -#endif } @@ -255,20 +254,15 @@ static void exp_dump_details(struct nl_object *a, struct nl_dump_params *p) if (nfnl_exp_test_helper_name(exp)) nl_dump(p, "helper %s ", exp->exp_helper_name); -#ifdef NLE_NAT_FN_CLASS if (nfnl_exp_test_fn(exp)) nl_dump(p, "fn %s ", exp->exp_fn); if (nfnl_exp_test_class(exp)) nl_dump(p, "class %u ", nfnl_exp_get_class(exp)); -#endif -#ifdef NLE_ZONE if (nfnl_exp_test_zone(exp)) nl_dump(p, "zone %u ", nfnl_exp_get_zone(exp)); -#endif -#ifdef NLE_FLAGS if (nfnl_exp_test_flags(exp)) nl_dump(p, "<"); #define PRINT_FLAG(str) \ @@ -284,7 +278,6 @@ static void exp_dump_details(struct nl_object *a, struct nl_dump_params *p) if (nfnl_exp_test_flags(exp)) nl_dump(p, ">"); -#endif nl_dump(p, "\n"); } @@ -612,7 +605,6 @@ uint8_t nfnl_exp_get_nat_dir(const struct nfnl_exp *exp) return exp->exp_nat_dir; } -#ifdef NLE_NAT_FN_CLASS #define EXP_GET_TUPLE(e, t) \ (t == NFNL_EXP_TUPLE_MASTER) ? \ &(e->exp_master) : \ @@ -620,13 +612,6 @@ uint8_t nfnl_exp_get_nat_dir(const struct nfnl_exp *exp) &(e->exp_mask) : \ (t == NFNL_EXP_TUPLE_NAT) ? \ &(e->exp_nat) : &(exp->exp_expect) -#else -#define EXP_GET_TUPLE(e, t) \ - (t == NFNL_EXP_TUPLE_MASTER) ? \ - &(e->exp_master) : \ - (t == NFNL_EXP_TUPLE_MASK) ? \ - &(e->exp_mask) : &(exp->exp_expect) -#endif static int exp_get_src_attr(int tuple) { @@ -639,11 +624,9 @@ static int exp_get_src_attr(int tuple) case NFNL_EXP_TUPLE_MASK: attr = EXP_ATTR_MASK_IP_SRC; break; -#ifdef NLE_NAT_FN_CLASS case NFNL_EXP_TUPLE_NAT: attr = EXP_ATTR_NAT_IP_SRC; break; -#endif case NFNL_EXP_TUPLE_EXPECT: default : attr = EXP_ATTR_EXPECT_IP_SRC; @@ -664,11 +647,9 @@ static int exp_get_dst_attr(int tuple) case NFNL_EXP_TUPLE_MASK: attr = EXP_ATTR_MASK_IP_DST; break; -#ifdef NLE_NAT_FN_CLASS case NFNL_EXP_TUPLE_NAT: attr = EXP_ATTR_NAT_IP_DST; break; -#endif case NFNL_EXP_TUPLE_EXPECT: default : attr = EXP_ATTR_EXPECT_IP_DST; @@ -752,11 +733,9 @@ static int exp_get_l4protonum_attr(int tuple) case NFNL_EXP_TUPLE_MASK: attr = EXP_ATTR_MASK_L4PROTO_NUM; break; -#ifdef NLE_NAT_FN_CLASS case NFNL_EXP_TUPLE_NAT: attr = EXP_ATTR_NAT_L4PROTO_NUM; break; -#endif case NFNL_EXP_TUPLE_EXPECT: default : attr = EXP_ATTR_EXPECT_L4PROTO_NUM; @@ -796,11 +775,9 @@ static int exp_get_l4ports_attr(int tuple) case NFNL_EXP_TUPLE_MASK: attr = EXP_ATTR_MASK_L4PROTO_PORTS; break; -#ifdef NLE_NAT_FN_CLASS case NFNL_EXP_TUPLE_NAT: attr = EXP_ATTR_NAT_L4PROTO_PORTS; break; -#endif case NFNL_EXP_TUPLE_EXPECT: default : attr = EXP_ATTR_EXPECT_L4PROTO_PORTS; @@ -849,11 +826,9 @@ static int exp_get_l4icmp_attr(int tuple) case NFNL_EXP_TUPLE_MASK: attr = EXP_ATTR_MASK_L4PROTO_ICMP; break; -#ifdef NLE_NAT_FN_CLASS case NFNL_EXP_TUPLE_NAT: attr = EXP_ATTR_NAT_L4PROTO_ICMP; break; -#endif case NFNL_EXP_TUPLE_EXPECT: default : attr = EXP_ATTR_EXPECT_L4PROTO_ICMP; @@ -906,14 +881,14 @@ uint8_t nfnl_exp_get_icmp_code(const struct nfnl_exp *exp, int tuple) struct nl_object_ops exp_obj_ops = { .oo_name = "netfilter/exp", .oo_size = sizeof(struct nfnl_exp), - .oo_free_data = exp_free_data, + .oo_free_data = exp_free_data, .oo_clone = exp_clone, .oo_dump = { - [NL_DUMP_LINE] = exp_dump_line, + [NL_DUMP_LINE] = exp_dump_line, [NL_DUMP_DETAILS] = exp_dump_details, }, .oo_compare = exp_compare, - .oo_attrs2str = exp_attrs2str, + .oo_attrs2str = exp_attrs2str, }; /** @} */ diff --git a/src/.gitignore b/src/.gitignore index 2c6d839..3e091cb 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,7 +1,8 @@ genl-ctrl-list nf-ct-list nf-exp-list -nf-exp-create +nf-exp-add +nf-exp-delete nf-log nf-monitor nl-addr-add diff --git a/src/Makefile.am b/src/Makefile.am index 317f2d9..c318dcc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -22,7 +22,7 @@ sbin_PROGRAMS = \ noinst_PROGRAMS = \ nf-ct-list nf-log nf-queue nf-monitor \ - nf-exp-list nf-exp-create \ + nf-exp-list nf-exp-add nf-exp-delete \ nl-addr-add nl-addr-delete nl-addr-list \ nl-link-set nl-link-stats \ nl-link-ifindex2name nl-link-name2ifindex \ @@ -45,6 +45,10 @@ nf_log_SOURCES = nf-log.c nf_queue_SOURCES = nf-queue.c nf_monitor_SOURCES = nf-monitor.c +nf_exp_list_SOURCES = nf-exp-list.c +nf_exp_add_SOURCES = nf-exp-add.c +nf_exp_delete_SOURCES = nf-exp-delete.c + nl_addr_add_SOURCES = nl-addr-add.c nl_addr_delete_SOURCES = nl-addr-delete.c nl_addr_list_SOURCES = nl-addr-list.c diff --git a/src/lib/exp.c b/src/lib/exp.c index 7cebacc..7e0a017 100644 --- a/src/lib/exp.c +++ b/src/lib/exp.c @@ -6,7 +6,8 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 20012 Rich Fought + * Copyright (c) 2008-2009 Thomas Graf + * Copyright (c) 2012 Rich Fought */ /** @@ -64,6 +65,35 @@ void nl_cli_exp_parse_helper_name(struct nfnl_exp *exp, char *arg) nfnl_exp_set_helper_name(exp, arg); } +void nl_cli_exp_parse_zone(struct nfnl_exp *exp, char *arg) +{ + uint32_t zone = nl_cli_parse_u32(arg); + nfnl_exp_set_zone(exp, zone); +} + +void nl_cli_exp_parse_flags(struct nfnl_exp *exp, char *arg) +{ + uint32_t flags = nl_cli_parse_u32(arg); + nfnl_exp_set_flags(exp, flags); +} + +void nl_cli_exp_parse_class(struct nfnl_exp *exp, char *arg) +{ + uint32_t class = nl_cli_parse_u32(arg); + nfnl_exp_set_class(exp, class); +} + +void nl_cli_exp_parse_nat_dir(struct nfnl_exp *exp, char *arg) +{ + uint32_t nat_dir = nl_cli_parse_u32(arg); + nfnl_exp_set_nat_dir(exp, nat_dir); +} + +void nl_cli_exp_parse_fn(struct nfnl_exp *exp, char *arg) +{ + nfnl_exp_set_fn(exp, arg); +} + void nl_cli_exp_parse_src(struct nfnl_exp *exp, int tuple, char *arg) { int err; @@ -97,14 +127,39 @@ void nl_cli_exp_parse_l4protonum(struct nfnl_exp *exp, int tuple, char *arg) void nl_cli_exp_parse_src_port(struct nfnl_exp *exp, int tuple, char *arg) { uint32_t sport = nl_cli_parse_u32(arg); - nfnl_exp_set_ports(exp, tuple, sport, 0); + uint16_t dport = nfnl_exp_get_dst_port(exp, tuple); + nfnl_exp_set_ports(exp, tuple, sport, dport); } void nl_cli_exp_parse_dst_port(struct nfnl_exp *exp, int tuple, char *arg) { uint32_t dport = nl_cli_parse_u32(arg); - uint32_t sport = nfnl_exp_get_src_port(exp, tuple); + uint16_t sport = nfnl_exp_get_src_port(exp, tuple); nfnl_exp_set_ports(exp, tuple, sport, dport); } +void nl_cli_exp_parse_icmp_id(struct nfnl_exp *exp, int tuple, char *arg) +{ + uint32_t id = nl_cli_parse_u32(arg); + uint8_t type = nfnl_exp_get_icmp_type(exp, tuple); + uint8_t code = nfnl_exp_get_icmp_code(exp, tuple); + nfnl_exp_set_icmp(exp, tuple, id, type, code); +} + +void nl_cli_exp_parse_icmp_type(struct nfnl_exp *exp, int tuple, char *arg) +{ + uint32_t type = nl_cli_parse_u32(arg); + uint16_t id = nfnl_exp_get_icmp_id(exp, tuple); + uint8_t code = nfnl_exp_get_icmp_code(exp, tuple); + nfnl_exp_set_icmp(exp, tuple, id, type, code); +} + +void nl_cli_exp_parse_icmp_code(struct nfnl_exp *exp, int tuple, char *arg) +{ + uint32_t code = nl_cli_parse_u32(arg); + uint16_t id = nfnl_exp_get_icmp_id(exp, tuple); + uint8_t type = nfnl_exp_get_icmp_type(exp, tuple); + nfnl_exp_set_icmp(exp, tuple, id, type, code); +} + /** @} */ diff --git a/src/nf-exp-create.c b/src/nf-exp-add.c similarity index 93% rename from src/nf-exp-create.c rename to src/nf-exp-add.c index d003a4a..6b71897 100644 --- a/src/nf-exp-create.c +++ b/src/nf-exp-add.c @@ -1,12 +1,16 @@ /* - * src/nf-exp-create.c Create an expectation + * src/nf-exp-add.c Create an expectation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2012 Rich Fought + * Copyright (c) 2003-2009 Thomas Graf + * Copyright (c) 2007 Philip Craig + * Copyright (c) 2007 Secure Computing Corporation + * Copyright (c) 2012 Rich Fought + * */ #include @@ -45,7 +49,7 @@ static void print_usage(void) " -F, --family=FAMILY Address family\n" " --timeout=NUM Timeout value\n" " --helper=STRING Helper Name\n" - //" --flags Flags\n" + " --flags Flags (Kernel 2.6.37)\n" ); exit(0); } @@ -85,7 +89,7 @@ int main(int argc, char *argv[]) ARG_TIMEOUT, ARG_HELPER_NAME, ARG_REPLACE, - //ARG_FLAGS, + ARG_FLAGS, }; static struct option long_opts[] = { { "replace", 1, 0, ARG_REPLACE }, @@ -111,7 +115,7 @@ int main(int argc, char *argv[]) { "family", 1, 0, 'F' }, { "timeout", 1, 0, ARG_TIMEOUT }, { "helper", 1, 0, ARG_HELPER_NAME }, - //{ "flags", 1, 0, ARG_FLAGS}, + { "flags", 1, 0, ARG_FLAGS}, { 0, 0, 0, 0 } }; @@ -146,7 +150,7 @@ int main(int argc, char *argv[]) case 'F': nl_cli_exp_parse_family(exp, optarg); break; case ARG_TIMEOUT: nl_cli_exp_parse_timeout(exp, optarg); break; case ARG_HELPER_NAME: nl_cli_exp_parse_helper_name(exp, optarg); break; - //case ARG_FLAGS: nl_cli_exp_parse_flags(exp, optarg); break; + case ARG_FLAGS: nl_cli_exp_parse_flags(exp, optarg); break; } } diff --git a/src/nf-exp-delete.c b/src/nf-exp-delete.c new file mode 100644 index 0000000..1253945 --- /dev/null +++ b/src/nf-exp-delete.c @@ -0,0 +1,167 @@ +/* + * src/nf-exp-delete.c Delete an expectation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2009 Thomas Graf + * Copyright (c) 2007 Philip Craig + * Copyright (c) 2007 Secure Computing Corporation + * Copyright (c) 2012 Rich Fought + */ + +#include +#include + +static int quiet = 0; + +static void print_usage(void) +{ + printf( + "Usage: nf-exp-list [OPTION]... [CONNTRACK ENTRY]\n" + "\n" + "Options\n" + " --replace Replace the address if it exists.\n" + " -q, --quiet Do not print informal notifications.\n" + " -h, --help Show this help\n" + " -v, --version Show versioning information\n" + "\n" + "Expectation Selection\n" + " -i, --id=NUM Identifier\n" + " --expect-proto=PROTOCOL Expectation protocol\n" + " --expect-src=ADDR Expectation source address\n" + " --expect-sport=PORT Expectation source port\n" + " --expect-dst=ADDR Expectation destination address\n" + " --expect-dport=PORT Expectation destination port\n" + " --master-proto=PROTOCOL Master conntrack protocol\n" + " --master-src=ADDR Master conntrack source address\n" + " --master-sport=PORT Master conntrack source port\n" + " --master-dst=ADDR Master conntrack destination address\n" + " --master-dport=PORT Master conntrack destination port\n" + " --mask-proto=PROTOCOL Mask protocol\n" + " --mask-src=ADDR Mask source address\n" + " --mask-sport=PORT Mask source port\n" + " --mask-dst=ADDR Mask destination address\n" + " --mask-dport=PORT Mask destination port\n" + " -F, --family=FAMILY Address family\n" + " --timeout=NUM Timeout value\n" + " --helper=STRING Helper Name\n" + " --flags Flags\n" + ); + exit(0); +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct nfnl_exp *exp; + struct nl_dump_params params = { + .dp_type = NL_DUMP_LINE, + .dp_fd = stdout, + }; + int err, nlflags = 0; + + exp = nl_cli_exp_alloc(); + + for (;;) { + int c, optidx = 0; + enum { + ARG_MARK = 270, + ARG_TCP_STATE = 271, + ARG_EXPECT_PROTO, + ARG_EXPECT_SRC, + ARG_EXPECT_SPORT, + ARG_EXPECT_DST, + ARG_EXPECT_DPORT, + ARG_MASTER_PROTO, + ARG_MASTER_SRC, + ARG_MASTER_SPORT, + ARG_MASTER_DST, + ARG_MASTER_DPORT, + ARG_MASK_PROTO, + ARG_MASK_SRC, + ARG_MASK_SPORT, + ARG_MASK_DST, + ARG_MASK_DPORT, + ARG_TIMEOUT, + ARG_HELPER_NAME, + ARG_FLAGS, + }; + static struct option long_opts[] = { + { "quiet", 0, 0, 'q' }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "id", 1, 0, 'i' }, + { "expect-proto", 1, 0, ARG_EXPECT_PROTO }, + { "expect-src", 1, 0, ARG_EXPECT_SRC }, + { "expect-sport", 1, 0, ARG_EXPECT_SPORT }, + { "expect-dst", 1, 0, ARG_EXPECT_DST }, + { "expect-dport", 1, 0, ARG_EXPECT_DPORT }, + { "master-proto", 1, 0, ARG_MASTER_PROTO }, + { "master-src", 1, 0, ARG_MASTER_SRC }, + { "master-sport", 1, 0, ARG_MASTER_SPORT }, + { "master-dst", 1, 0, ARG_MASTER_DST }, + { "master-dport", 1, 0, ARG_MASTER_DPORT }, + { "mask-proto", 1, 0, ARG_MASK_PROTO }, + { "mask-src", 1, 0, ARG_MASK_SRC }, + { "mask-sport", 1, 0, ARG_MASK_SPORT }, + { "mask-dst", 1, 0, ARG_MASK_DST }, + { "mask-dport", 1, 0, ARG_MASK_DPORT }, + { "family", 1, 0, 'F' }, + { "timeout", 1, 0, ARG_TIMEOUT }, + { "helper", 1, 0, ARG_HELPER_NAME }, + { "flags", 1, 0, ARG_FLAGS}, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "46f:hvi:p:F:", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case '?': exit(NLE_INVAL); + case 'q': quiet = 1; break; + case '4': nfnl_exp_set_family(exp, AF_INET); break; + case '6': nfnl_exp_set_family(exp, AF_INET6); break; + case 'h': print_usage(); break; + case 'v': nl_cli_print_version(); break; + case 'i': nl_cli_exp_parse_id(exp, optarg); break; + case ARG_EXPECT_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; + case ARG_EXPECT_SRC: nl_cli_exp_parse_src(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; + case ARG_EXPECT_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; + case ARG_EXPECT_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; + case ARG_EXPECT_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; + case ARG_MASTER_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; + case ARG_MASTER_SRC: nl_cli_exp_parse_src(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; + case ARG_MASTER_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; + case ARG_MASTER_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; + case ARG_MASTER_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; + case ARG_MASK_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_MASK, optarg); break; + case ARG_MASK_SRC: nl_cli_exp_parse_src(exp, NFNL_EXP_TUPLE_MASK, optarg); break; + case ARG_MASK_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_MASK, optarg); break; + case ARG_MASK_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_MASK, optarg); break; + case ARG_MASK_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_MASK, optarg); break; + case 'F': nl_cli_exp_parse_family(exp, optarg); break; + case ARG_TIMEOUT: nl_cli_exp_parse_timeout(exp, optarg); break; + case ARG_HELPER_NAME: nl_cli_exp_parse_helper_name(exp, optarg); break; + case ARG_FLAGS: nl_cli_exp_parse_flags(exp, optarg); break; + } + } + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_NETFILTER); + + if ((err = nfnl_exp_del(sock, exp, nlflags)) < 0) + nl_cli_fatal(err, "Unable to delete expectation: %s", + nl_geterror(err)); + + if (!quiet) { + printf("Deleted "); + nl_object_dump(OBJ_CAST(exp), ¶ms); + } + + + return 0; +} diff --git a/src/nf-exp-list.c b/src/nf-exp-list.c index 3bdb6c5..a447ba2 100644 --- a/src/nf-exp-list.c +++ b/src/nf-exp-list.c @@ -1,12 +1,15 @@ /* - * src/nf-exp-list.c List Conntrack Entries + * src/nf-exp-list.c List Expectation Entries * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2012 Rich Fought + * Copyright (c) 2003-2009 Thomas Graf + * Copyright (c) 2007 Philip Craig + * Copyright (c) 2007 Secure Computing Corporation + * Copyright (c) 2012 Rich Fought */ #include @@ -15,10 +18,10 @@ static void print_usage(void) { printf( - "Usage: nf-exp-list [OPTION]... [CONNTRACK ENTRY]\n" + "Usage: nf-exp-list [OPTION]... [EXPECTATION ENTRY]\n" "\n" "Options\n" - " -f, --format=TYPE Output format { brief | details | stats }\n" + " -f, --format=TYPE Output format { brief | details }\n" " -h, --help Show this help\n" " -v, --version Show versioning information\n" "\n" From c3376e7df646bdbde1b41ef4be62746f04f11849 Mon Sep 17 00:00:00 2001 From: Rich Fought Date: Thu, 4 Oct 2012 21:55:36 +0000 Subject: [PATCH 268/432] Conntrack Dump ICMP Looks like a cut and paste oversight ... --- lib/netfilter/ct_obj.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/netfilter/ct_obj.c b/lib/netfilter/ct_obj.c index d5cd18a..4686170 100644 --- a/lib/netfilter/ct_obj.c +++ b/lib/netfilter/ct_obj.c @@ -121,10 +121,10 @@ static void dump_icmp(struct nl_dump_params *p, struct nfnl_ct *ct, int reply) if (nfnl_ct_test_icmp_type(ct, reply)) nl_dump(p, "icmp type %d ", nfnl_ct_get_icmp_type(ct, reply)); - if (nfnl_ct_test_icmp_type(ct, reply)) + if (nfnl_ct_test_icmp_code(ct, reply)) nl_dump(p, "code %d ", nfnl_ct_get_icmp_code(ct, reply)); - if (nfnl_ct_test_icmp_type(ct, reply)) + if (nfnl_ct_test_icmp_id(ct, reply)) nl_dump(p, "id %d ", nfnl_ct_get_icmp_id(ct, reply)); } From 2d674fed6c0f1417ffa1dc73c43bb13993d15011 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 19 Oct 2012 15:06:50 +0200 Subject: [PATCH 269/432] doc: mark route.txt as WIP --- doc/route.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/route.txt b/doc/route.txt index e47c6d3..61a84c4 100644 --- a/doc/route.txt +++ b/doc/route.txt @@ -13,6 +13,9 @@ Thomas Graf This library provides APIs to the kernel interfaces of the routing family. + +NOTE: Work in progress. + == Addresses [[route_link]] From db138439ac214d1259848ab11447d9b061ec3740 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 19 Oct 2012 16:16:06 +0200 Subject: [PATCH 270/432] doc: Split doc/ into separate packages Separates all the documentation generation trickery to its own configure.in and allows to easily generate a pre built doc dist file for distribution. Arguments to configure will be passed on to doc/configure Signed-off-by: Thomas Graf --- autogen.sh | 2 + configure.in | 86 +----- doc/.gitignore | 6 + doc/AUTHORS | 1 + doc/COPYING | 674 ++++++++++++++++++++++++++++++++++++++++++++ doc/ChangeLog | 0 doc/Doxyfile.in | 10 +- doc/INSTALL | 370 ++++++++++++++++++++++++ doc/Makefile.am | 79 ++---- doc/NEWS | 0 doc/autogen.sh | 4 + doc/configure.in | 106 +++++++ doc/m4/ax_python.m4 | 97 +++++++ 13 files changed, 1284 insertions(+), 151 deletions(-) create mode 100644 doc/AUTHORS create mode 100644 doc/COPYING create mode 100644 doc/ChangeLog create mode 100644 doc/INSTALL create mode 100644 doc/NEWS create mode 100755 doc/autogen.sh create mode 100644 doc/configure.in create mode 100644 doc/m4/ax_python.m4 diff --git a/autogen.sh b/autogen.sh index a569614..c3538bb 100755 --- a/autogen.sh +++ b/autogen.sh @@ -2,3 +2,5 @@ autoreconf -fi; rm -Rf autom4te.cache; + +doc/autogen.sh diff --git a/configure.in b/configure.in index 28d1754..c0e6afa 100644 --- a/configure.in +++ b/configure.in @@ -73,88 +73,6 @@ AC_PROG_YACC AC_C_CONST AC_C_INLINE -# -# Generating the documentation -# -AC_ARG_ENABLE([doc], - AS_HELP_STRING([--disable-doc], [Do not generate documentation]), - [generate_doc="$enableval"], [generate_doc=auto]) - -if test "x$generate_doc" != "xno"; then - AC_PROG_SED - AC_PROG_EGREP - - AX_PYTHON - - AC_CHECK_PROG(HAVE_DOXYGEN, [doxygen], yes, no) - if test "x$HAVE_DOXYGEN" = "xno" -a "x$generate_doc" = "xyes"; then - AC_MSG_ERROR([*** doxygen package required to generate documentation]) - fi - - AC_CHECK_PROG(HAVE_DOT, [dot], yes, no) - if test "x$HAVE_DOT" = "xno"; then - if test "x$generate_doc" = "xyes"; then - AC_MSG_ERROR([*** graphviz package required to generate documentation]) - else - AC_MSG_WARN([*** graphviz not found, disabling building of API reference]) - HAVE_DOXYGEN=no - fi - fi - - AC_CHECK_PROG(HAVE_ASCIIDOC, [asciidoc], yes, no) - if test "x$HAVE_ASCIIDOC" = "xno"; then - if test "x$generate_doc" = "xyes"; then - AC_MSG_ERROR([*** asciidoc package required to generate documentation]) - else - AC_MSG_WARN([*** asciidoc not found, disabling building of guides]) - fi - fi - - AC_CHECK_PROG(HAVE_SOURCE_HIGHLIGHT, [source-highlight], yes, no) - if test "x$HAVE_SOURCE_HIGHLIGHT" = "xno"; then - if test "x$generate_doc" = "xyes"; then - AC_MSG_ERROR([*** source-highlight required to generate documentation]) - else - AC_MSG_WARN([*** source-highlight not found, disabling building of guides]) - HAVE_ASCIIDOC=no - fi - fi - - AC_CHECK_PROG(HAVE_MSCGEN, [mscgen], yes, no) - if test "x$HAVE_MSCGEN" = "xno"; then - AC_MSG_WARN([*** mscgen not found, get it at http://www.mcternan.me.uk/mscgen/]) - if test "x$generate_doc" = "xyes"; then - AC_MSG_ERROR([*** mscgen package required to generate documentation]) - else - AC_MSG_WARN([*** Disabling building of guides]) - HAVE_ASCIIDOC=no - HAVE_DOXYGEN=no - fi - fi - - AC_CHECK_PROG(HAVE_PYGMENTIZE, [pygmentize], yes, no) - if test "x$HAVE_PYGMENTIZE" = "xno"; then - if test "x$generate_doc" = "xyes"; then - AC_MSG_ERROR([*** pygmentize package required to generate documentation]) - else - AC_MSG_WARN([*** Disabling building of guides]) - HAVE_ASCIIDOC=no - fi - fi - - link_doc=yes - if test "x$HAVE_DOXYGEN" = "xno"; then - AC_MSG_WARN([*** Disabling API linking due to missing doxygen package]) - link_doc=no - fi -fi - -AM_CONDITIONAL([LINK_DOC], [test "x$link_doc" = "xyes"]) -AM_CONDITIONAL([HAVE_DOXYGEN], [test "x$HAVE_DOXYGEN" = "xyes"]) -AM_CONDITIONAL([HAVE_ASCIIDOC], [test "x$HAVE_ASCIIDOC" = "xyes"]) - -AM_CONDITIONAL([GENERATE_DOC], [test "x$generate_doc" != "xno"]) - AC_ARG_WITH([pkgconfigdir], AS_HELP_STRING([--with-pkgconfigdir=PATH], [Path to the pkgconfig directory [[LIBDIR/pkgconfig]]]), [pkgconfigdir="$withval"], [pkgconfigdir='${libdir}/pkgconfig']) @@ -168,6 +86,8 @@ AM_CONDITIONAL([ENABLE_CLI], [test "$enable_cli" = "yes"]) AC_CHECK_LIB([m], [pow], [], AC_MSG_ERROR([libm is required])) AC_CHECK_LIB([pthread], [pthread_mutex_lock], [], AC_MSG_ERROR([libpthread is required])) +AC_CONFIG_SUBDIRS([doc]) + AC_CONFIG_FILES([ Makefile libnl-3.0.pc @@ -175,8 +95,6 @@ libnl-route-3.0.pc libnl-genl-3.0.pc libnl-nf-3.0.pc libnl-cli-3.0.pc -doc/Doxyfile -doc/Makefile lib/Makefile include/Makefile src/Makefile diff --git a/doc/.gitignore b/doc/.gitignore index b6e9df2..e7209f6 100644 --- a/doc/.gitignore +++ b/doc/.gitignore @@ -1,3 +1,9 @@ *.html libnl.dict Doxyfile +aclocal.m4 +autom4te.cache +config.log +config.status +configure +missing diff --git a/doc/AUTHORS b/doc/AUTHORS new file mode 100644 index 0000000..26e3cb4 --- /dev/null +++ b/doc/AUTHORS @@ -0,0 +1 @@ +Thomas Graf diff --git a/doc/COPYING b/doc/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/doc/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/doc/ChangeLog b/doc/ChangeLog new file mode 100644 index 0000000..e69de29 diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 7c3bd39..62b2661 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -660,11 +660,11 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = @top_srcdir@/lib \ - @top_srcdir@/src/lib \ - @top_srcdir@/include/netlink \ - @top_srcdir@/src \ - @top_srcdir@/doc/src +INPUT = @top_srcdir@/../lib \ + @top_srcdir@/../src/lib \ + @top_srcdir@/../include/netlink \ + @top_srcdir@/../src \ + @top_srcdir@/../doc/src # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is diff --git a/doc/INSTALL b/doc/INSTALL new file mode 100644 index 0000000..a1e89e1 --- /dev/null +++ b/doc/INSTALL @@ -0,0 +1,370 @@ +Installation Instructions +************************* + +Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation, +Inc. + + Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. This file is offered as-is, +without warranty of any kind. + +Basic Installation +================== + + Briefly, the shell commands `./configure; make; make install' should +configure, build, and install this package. The following +more-detailed instructions are generic; see the `README' file for +instructions specific to this package. Some packages provide this +`INSTALL' file but do not implement all of the features documented +below. The lack of an optional feature in a given package is not +necessarily a bug. More recommendations for GNU packages can be found +in *note Makefile Conventions: (standards)Makefile Conventions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. Caching is +disabled by default to prevent problems with accidental use of stale +cache files. + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You need `configure.ac' if +you want to change it or regenerate `configure' using a newer version +of `autoconf'. + + The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. + + Running `configure' might take a while. While running, it prints + some messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package, generally using the just-built uninstalled binaries. + + 4. Type `make install' to install the programs and any data files and + documentation. When installing into a prefix owned by root, it is + recommended that the package be configured and built as a regular + user, and only the `make install' phase executed with root + privileges. + + 5. Optionally, type `make installcheck' to repeat any self-tests, but + this time using the binaries in their final installed location. + This target does not install anything. Running this target as a + regular user, particularly if the prior `make install' required + root privileges, verifies that the installation completed + correctly. + + 6. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + + 7. Often, you can also type `make uninstall' to remove the installed + files again. In practice, not all packages have tested that + uninstallation works correctly, even though it is required by the + GNU Coding Standards. + + 8. Some packages, particularly those that use Automake, provide `make + distcheck', which can by used by developers to test that all other + targets like `make install' and `make uninstall' work correctly. + This target is generally not run by end users. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c99 CFLAGS=-g LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you can use GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. This +is known as a "VPATH" build. + + With a non-GNU `make', it is safer to compile the package for one +architecture at a time in the source code directory. After you have +installed the package for one architecture, use `make distclean' before +reconfiguring for another architecture. + + On MacOS X 10.5 and later systems, you can create libraries and +executables that work on multiple system types--known as "fat" or +"universal" binaries--by specifying multiple `-arch' options to the +compiler but only a single `-arch' option to the preprocessor. Like +this: + + ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CPP="gcc -E" CXXCPP="g++ -E" + + This is not guaranteed to produce working output in all cases, you +may have to build one architecture at a time and combine the results +using the `lipo' tool if you have problems. + +Installation Names +================== + + By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX', where PREFIX must be an +absolute file name. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. In general, the +default for these options is expressed in terms of `${prefix}', so that +specifying just `--prefix' will affect all of the other directory +specifications that were not explicitly provided. + + The most portable way to affect installation locations is to pass the +correct locations to `configure'; however, many packages provide one or +both of the following shortcuts of passing variable assignments to the +`make install' command line to change installation locations without +having to reconfigure or recompile. + + The first method involves providing an override variable for each +affected directory. For example, `make install +prefix=/alternate/directory' will choose an alternate location for all +directory configuration variables that were expressed in terms of +`${prefix}'. Any directories that were specified during `configure', +but not in terms of `${prefix}', must each be overridden at install +time for the entire installation to be relocated. The approach of +makefile variable overrides for each directory variable is required by +the GNU Coding Standards, and ideally causes no recompilation. +However, some platforms have known limitations with the semantics of +shared libraries that end up requiring recompilation when using this +method, particularly noticeable in packages that use GNU Libtool. + + The second method involves providing the `DESTDIR' variable. For +example, `make install DESTDIR=/alternate/directory' will prepend +`/alternate/directory' before all installation names. The approach of +`DESTDIR' overrides is not required by the GNU Coding Standards, and +does not work on platforms that have drive letters. On the other hand, +it does better at avoiding recompilation issues, and works well even +when some directory options were not specified in terms of `${prefix}' +at `configure' time. + +Optional Features +================= + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + + Some packages offer the ability to configure how verbose the +execution of `make' will be. For these packages, running `./configure +--enable-silent-rules' sets the default to minimal output, which can be +overridden with `make V=1'; while running `./configure +--disable-silent-rules' sets the default to verbose, which can be +overridden with `make V=0'. + +Particular systems +================== + + On HP-UX, the default C compiler is not ANSI C compatible. If GNU +CC is not installed, it is recommended to use the following options in +order to use an ANSI C compiler: + + ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" + +and if that doesn't work, install pre-built binaries of GCC for HP-UX. + + HP-UX `make' updates targets which have the same time stamps as +their prerequisites, which makes it generally unusable when shipped +generated files such as `configure' are involved. Use GNU `make' +instead. + + On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot +parse its `' header file. The option `-nodtk' can be used as +a workaround. If GNU CC is not installed, it is therefore recommended +to try + + ./configure CC="cc" + +and if that doesn't work, try + + ./configure CC="cc -nodtk" + + On Solaris, don't put `/usr/ucb' early in your `PATH'. This +directory contains several dysfunctional programs; working variants of +these programs are available in `/usr/bin'. So, if you need `/usr/ucb' +in your `PATH', put it _after_ `/usr/bin'. + + On Haiku, software installed for all users goes in `/boot/common', +not `/usr/local'. It is recommended to use the following options: + + ./configure --prefix=/boot/common + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS + KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option `--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). + +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf bug. Until the bug is fixed you can use this workaround: + + CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of all of the options to `configure', and exit. + +`--help=short' +`--help=recursive' + Print a summary of the options unique to this package's + `configure', and exit. The `short' variant lists options used + only in the top level, while the `recursive' variant lists options + also present in any nested packages. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--prefix=DIR' + Use DIR as the installation prefix. *note Installation Names:: + for more details, including other options available for fine-tuning + the installation locations. + +`--no-create' +`-n' + Run the configure checks, but stop before creating any output + files. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/doc/Makefile.am b/doc/Makefile.am index ffa2245..338f077 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -10,72 +10,27 @@ ASCIIDOCOPTS=-a pygments -a language=c -a icons \ -a stylesdir="${abs_srcdir}/stylesheets/" EXTRA_DIST = \ - Doxyfile \ - DoxygenLayout.xml \ core.txt \ + core.html \ route.txt \ + route.html \ index.txt \ + index.html \ libnl.css \ - README \ - doxygen-link.py \ - gen-tags.sh \ - resolve-asciidoc-refs.py \ - stylesheets/asciidoc.css \ - stylesheets/asciidoc-manpage.css \ - stylesheets/docbook-xsl.css \ - stylesheets/flask.css \ - stylesheets/flask-manpage.css \ - stylesheets/pygments.css \ - stylesheets/slidy.css \ - stylesheets/toc2.css \ - stylesheets/volnitsky.css \ - stylesheets/volnitsky-manpage.css \ - stylesheets/xhtml11-quirks.css \ - images/asciidoc__1.png \ - images/asciidoc__2.png \ - images/asciidoc__3.png \ - images/asciidoc__4.png \ - images/asciidoc__5.png \ - images/asciidoc__6.png \ - images/asciidoc__7.png \ - images/attribute_hdr.png \ - images/classful_qdisc.png \ - images/classless_qdisc_nbands.png \ - images/classless_qdisc.png \ - images/ifinfomsg.png \ - images/library_overview.png \ - images/nlmsgerr.png \ - images/nlmsghdr.png \ - images/qdisc_default.png \ - images/qdisc_mq.png \ - images/tc_obj.png \ - images/tc_overview.png \ - images/icons/caution.png \ - images/icons/example.png \ - images/icons/home.png \ - images/icons/important.png \ - images/icons/next.png \ - images/icons/note.png \ - images/icons/prev.png \ - images/icons/README \ - images/icons/tip.png \ - images/icons/up.png \ - images/icons/warning.png \ - images/icons/callouts/1.png \ - images/icons/callouts/2.png \ - images/icons/callouts/3.png \ - images/icons/callouts/4.png \ - images/icons/callouts/5.png \ - images/icons/callouts/6.png \ - images/icons/callouts/7.png \ - images/icons/callouts/8.png \ - images/icons/callouts/9.png \ - images/icons/callouts/10.png \ - images/icons/callouts/11.png \ - images/icons/callouts/12.png \ - images/icons/callouts/13.png \ - images/icons/callouts/14.png \ - images/icons/callouts/15.png + stylesheets \ + images \ + api + +dist-hook: + rm -f $(distdir)/aclocal.m4 + rm -f $(distdir)/configure + rm -f $(distdir)/configure.in + rm -rf $(distdir)/m4 + rm -f $(distdir)/README + rm -f $(distdir)/missing + rm -f $(distdir)/Doxyfile.in + rm -f $(distdir)/Makefile.am + rm -f $(distdir)/Makefile.in link_doc: if LINK_DOC diff --git a/doc/NEWS b/doc/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/doc/autogen.sh b/doc/autogen.sh new file mode 100755 index 0000000..a569614 --- /dev/null +++ b/doc/autogen.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +autoreconf -fi; +rm -Rf autom4te.cache; diff --git a/doc/configure.in b/doc/configure.in new file mode 100644 index 0000000..a962c36 --- /dev/null +++ b/doc/configure.in @@ -0,0 +1,106 @@ +# +# configure.in +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation version 2.1 +# of the License. +# +# Copyright (c) 2003-2012 Thomas Graf +# + +AC_INIT(libnl-doc, [3.2.13], [http://www.infradead.org/~tgr/libnl/]) +AC_CONFIG_MACRO_DIR([m4]) +AM_INIT_AUTOMAKE +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES(yes)], []) + +m4_include([m4/ax_python.m4]) + +# +# Generating the documentation +# +AC_ARG_ENABLE([doc], + AS_HELP_STRING([--disable-doc], [Do not generate documentation]), + [generate_doc="$enableval"], [generate_doc=auto]) + +if test "x$generate_doc" != "xno"; then + AC_PROG_SED + AC_PROG_EGREP + + AX_PYTHON + + AC_CHECK_PROG(HAVE_DOXYGEN, [doxygen], yes, no) + if test "x$HAVE_DOXYGEN" = "xno" -a "x$generate_doc" = "xyes"; then + AC_MSG_ERROR([*** doxygen package required to generate documentation]) + fi + + AC_CHECK_PROG(HAVE_DOT, [dot], yes, no) + if test "x$HAVE_DOT" = "xno"; then + if test "x$generate_doc" = "xyes"; then + AC_MSG_ERROR([*** graphviz package required to generate documentation]) + else + AC_MSG_WARN([*** graphviz not found, disabling building of API reference]) + HAVE_DOXYGEN=no + fi + fi + + AC_CHECK_PROG(HAVE_ASCIIDOC, [asciidoc], yes, no) + if test "x$HAVE_ASCIIDOC" = "xno"; then + if test "x$generate_doc" = "xyes"; then + AC_MSG_ERROR([*** asciidoc package required to generate documentation]) + else + AC_MSG_WARN([*** asciidoc not found, disabling building of guides]) + fi + fi + + AC_CHECK_PROG(HAVE_SOURCE_HIGHLIGHT, [source-highlight], yes, no) + if test "x$HAVE_SOURCE_HIGHLIGHT" = "xno"; then + if test "x$generate_doc" = "xyes"; then + AC_MSG_ERROR([*** source-highlight required to generate documentation]) + else + AC_MSG_WARN([*** source-highlight not found, disabling building of guides]) + HAVE_ASCIIDOC=no + fi + fi + + AC_CHECK_PROG(HAVE_MSCGEN, [mscgen], yes, no) + if test "x$HAVE_MSCGEN" = "xno"; then + AC_MSG_WARN([*** mscgen not found, get it at http://www.mcternan.me.uk/mscgen/]) + if test "x$generate_doc" = "xyes"; then + AC_MSG_ERROR([*** mscgen package required to generate documentation]) + else + AC_MSG_WARN([*** Disabling building of guides]) + HAVE_ASCIIDOC=no + HAVE_DOXYGEN=no + fi + fi + + AC_CHECK_PROG(HAVE_PYGMENTIZE, [pygmentize], yes, no) + if test "x$HAVE_PYGMENTIZE" = "xno"; then + if test "x$generate_doc" = "xyes"; then + AC_MSG_ERROR([*** pygmentize package required to generate documentation]) + else + AC_MSG_WARN([*** Disabling building of guides]) + HAVE_ASCIIDOC=no + fi + fi + + link_doc=yes + if test "x$HAVE_DOXYGEN" = "xno"; then + AC_MSG_WARN([*** Disabling API linking due to missing doxygen package]) + link_doc=no + fi +fi + +AM_CONDITIONAL([LINK_DOC], [test "x$link_doc" = "xyes"]) +AM_CONDITIONAL([HAVE_DOXYGEN], [test "x$HAVE_DOXYGEN" = "xyes"]) +AM_CONDITIONAL([HAVE_ASCIIDOC], [test "x$HAVE_ASCIIDOC" = "xyes"]) + +AM_CONDITIONAL([GENERATE_DOC], [test "x$generate_doc" != "xno"]) + +AC_CONFIG_FILES([ +Doxyfile +Makefile +]) + +AC_OUTPUT diff --git a/doc/m4/ax_python.m4 b/doc/m4/ax_python.m4 new file mode 100644 index 0000000..1bc9d8a --- /dev/null +++ b/doc/m4/ax_python.m4 @@ -0,0 +1,97 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_python.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PYTHON +# +# DESCRIPTION +# +# This macro does a complete Python development environment check. +# +# It recurses through several python versions (from 2.1 to 2.6 in this +# version), looking for an executable. When it finds an executable, it +# looks to find the header files and library. +# +# It sets PYTHON_BIN to the name of the python executable, +# PYTHON_INCLUDE_DIR to the directory holding the header files, and +# PYTHON_LIB to the name of the Python library. +# +# This macro calls AC_SUBST on PYTHON_BIN (via AC_CHECK_PROG), +# PYTHON_INCLUDE_DIR and PYTHON_LIB. +# +# LICENSE +# +# Copyright (c) 2008 Michael Tindal +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 9 + +AC_DEFUN([AX_PYTHON], +[AC_MSG_CHECKING(for python build information) +AC_MSG_RESULT([]) +for python in python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python; do +AC_CHECK_PROGS(PYTHON_BIN, [$python]) +ax_python_bin=$PYTHON_BIN +if test x$ax_python_bin != x; then + AC_CHECK_LIB($ax_python_bin, main, ax_python_lib=$ax_python_bin, ax_python_lib=no) + AC_CHECK_HEADER([$ax_python_bin/Python.h], + [[ax_python_header=`locate $ax_python_bin/Python.h | sed -e s,/Python.h,,`]], + ax_python_header=no) + if test $ax_python_lib != no; then + if test $ax_python_header != no; then + break; + fi + fi +fi +done +if test x$ax_python_bin = x; then + ax_python_bin=no +fi +if test x$ax_python_header = x; then + ax_python_header=no +fi +if test x$ax_python_lib = x; then + ax_python_lib=no +fi + +AC_MSG_RESULT([ results of the Python check:]) +AC_MSG_RESULT([ Binary: $ax_python_bin]) +AC_MSG_RESULT([ Library: $ax_python_lib]) +AC_MSG_RESULT([ Include Dir: $ax_python_header]) + +if test x$ax_python_header != xno; then + PYTHON_INCLUDE_DIR=$ax_python_header + AC_SUBST(PYTHON_INCLUDE_DIR) +fi +if test x$ax_python_lib != xno; then + PYTHON_LIB=$ax_python_lib + AC_SUBST(PYTHON_LIB) +fi +])dnl From 65c3919ff49eb589ce114412fa6afbd1c0eaa63f Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 19 Oct 2012 16:35:28 +0200 Subject: [PATCH 271/432] Only include doc/ in dist --- Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index c4617c4..a06daf4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,7 +2,8 @@ ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = include lib doc man python tests +SUBDIRS = include lib man python tests +DIST_SUBDIRS = doc pkgconfig_DATA = libnl-3.0.pc \ libnl-route-3.0.pc \ From 1fa61d189250161474894d8eb6f729aae789b296 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 19 Oct 2012 16:35:51 +0200 Subject: [PATCH 272/432] 3.2.14 release --- configure.in | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.in b/configure.in index c0e6afa..79cd93f 100644 --- a/configure.in +++ b/configure.in @@ -13,7 +13,7 @@ # copied from glib m4_define([libnl_major_version], [3]) m4_define([libnl_minor_version], [2]) -m4_define([libnl_micro_version], [13]) +m4_define([libnl_micro_version], [14]) # If either revision or age are omitted, they default to 0. Also note that age @@ -34,9 +34,9 @@ m4_define([libnl_micro_version], [13]) # 6. If any interfaces have been removed since the last public release, then # set age to 0. -m4_define([libnl_lt_current], [210]) -m4_define([libnl_lt_revision], [1]) -m4_define([libnl_lt_age], [10]) +m4_define([libnl_lt_current], [211]) +m4_define([libnl_lt_revision], [0]) +m4_define([libnl_lt_age], [11]) m4_define([libnl_version], [libnl_major_version.libnl_minor_version.libnl_micro_version]) From 787f14dbe30ca22c9e9c7e9b1ff0ce6dfb00db7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=BD=D0=BE=D1=83=D1=82=D0=B1?= =?UTF-8?q?=D1=83=D0=BA=20=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Sun, 9 Sep 2012 22:30:20 +0600 Subject: [PATCH 273/432] genl/family flags can be damaged during the auto-indentation. "-" was never used in the names of the flags. "_" was used in all places of the library. So, I just changed the undescore to the minus. Automatic indentation can insert spaces on either side of the minus, so the library will be compiled, but will not be usable (in this part of the code), as the parser will split words by white space, and the flag "admin - perm" will never work. --- lib/genl/family.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/genl/family.c b/lib/genl/family.c index 64b98cd..05e45ac 100644 --- a/lib/genl/family.c +++ b/lib/genl/family.c @@ -96,10 +96,10 @@ static void family_dump_line(struct nl_object *obj, struct nl_dump_params *p) } static const struct trans_tbl ops_flags[] = { - __ADD(GENL_ADMIN_PERM, admin-perm) - __ADD(GENL_CMD_CAP_DO, has-doit) - __ADD(GENL_CMD_CAP_DUMP, has-dump) - __ADD(GENL_CMD_CAP_HASPOL, has-policy) + __ADD(GENL_ADMIN_PERM, admin_perm) + __ADD(GENL_CMD_CAP_DO, has_doit) + __ADD(GENL_CMD_CAP_DUMP, has_dump) + __ADD(GENL_CMD_CAP_HASPOL, has_policy) }; static char *ops_flags2str(int flags, char *buf, size_t len) From fedb862ea5a46df327a4de75e613e2d7732e8b46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=BD=D0=BE=D1=83=D1=82=D0=B1?= =?UTF-8?q?=D1=83=D0=BA=20=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Mon, 10 Sep 2012 01:21:52 +0600 Subject: [PATCH 274/432] ROUTE_DIFF result was not used in some place in route_compare --- lib/route/route_obj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/route/route_obj.c b/lib/route/route_obj.c index 7ea4fff..54df023 100644 --- a/lib/route/route_obj.c +++ b/lib/route/route_obj.c @@ -332,7 +332,7 @@ static int route_compare(struct nl_object *_a, struct nl_object *_b, if (a->rt_metrics_mask & (1 << i) && (!(b->rt_metrics_mask & (1 << i)) || a->rt_metrics[i] != b->rt_metrics[i])) - ROUTE_DIFF(METRICS, 1); + diff |= ROUTE_DIFF(METRICS, 1); } diff |= ROUTE_DIFF(FLAGS, From e1b67fb23f8f802f3b287c66fda531e002ca20d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=BD=D0=BE=D1=83=D1=82=D0=B1?= =?UTF-8?q?=D1=83=D0=BA=20=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Mon, 10 Sep 2012 01:33:04 +0600 Subject: [PATCH 275/432] Clang diagnostics Based on clang diagnostics: 1. lib/nl.c: recvmsgs(): nla filling with zeros commented. 2. lib/route/classid.c: & lib/route/pktloc.c: remove zero-filling of struct stat 3. lib/route/qdisc/htb.c: Fix htb_qdisc_msg_fill(): fix zero-filling 4. ematch/container.c: container_parse: commented why only 4 bytes are copied len marked as unused to eliminate compiler warning --- lib/nl.c | 6 ++++++ lib/route/classid.c | 2 +- lib/route/cls/ematch/container.c | 8 +++++++- lib/route/pktloc.c | 2 +- lib/route/qdisc/htb.c | 8 ++++---- 5 files changed, 19 insertions(+), 7 deletions(-) diff --git a/lib/nl.c b/lib/nl.c index 5b37c2a..2fa741f 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -540,6 +540,12 @@ static int recvmsgs(struct nl_sock *sk, struct nl_cb *cb) int n, err = 0, multipart = 0, interrupted = 0, nrecv = 0; unsigned char *buf = NULL; struct nlmsghdr *hdr; + + /* + nla is passed on to not only to nl_recv() but may also be passed + to a function pointer provided by the caller which may or may not + initialize the variable. Thomas Graf. + */ struct sockaddr_nl nla = {0}; struct nl_msg *msg = NULL; struct ucred *creds = NULL; diff --git a/lib/route/classid.c b/lib/route/classid.c index a128773..87025a0 100644 --- a/lib/route/classid.c +++ b/lib/route/classid.c @@ -311,7 +311,7 @@ static int classid_map_add(uint32_t classid, const char *name) int rtnl_tc_read_classid_file(void) { static time_t last_read; - struct stat st = {0}; + struct stat st; char buf[256], *path; FILE *fd; int err; diff --git a/lib/route/cls/ematch/container.c b/lib/route/cls/ematch/container.c index ddbdce0..6d73ab6 100644 --- a/lib/route/cls/ematch/container.c +++ b/lib/route/cls/ematch/container.c @@ -14,8 +14,14 @@ #include #include -static int container_parse(struct rtnl_ematch *e, void *data, size_t len) +static int container_parse(struct rtnl_ematch *e, void *data, size_t len __attribute__((unused))) { + /* + The kernel may provide more than 4 bytes of data in the future and we want + older libnl versions to be ok with that. We want interfaces to be growable + so we only ever enforce a minimum data length and copy as much as we are + aware of. Thomas Graf. + */ memcpy(e->e_data, data, sizeof(uint32_t)); return 0; diff --git a/lib/route/pktloc.c b/lib/route/pktloc.c index e7dffe5..70d552b 100644 --- a/lib/route/pktloc.c +++ b/lib/route/pktloc.c @@ -90,7 +90,7 @@ static int read_pktlocs(void) YY_BUFFER_STATE buf = NULL; yyscan_t scanner = NULL; static time_t last_read; - struct stat st = {0}; + struct stat st; char *path; int i, err; FILE *fd; diff --git a/lib/route/qdisc/htb.c b/lib/route/qdisc/htb.c index 4298580..9fb0bf6 100644 --- a/lib/route/qdisc/htb.c +++ b/lib/route/qdisc/htb.c @@ -190,10 +190,10 @@ static int htb_qdisc_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) { struct rtnl_htb_qdisc *htb = data; - struct tc_htb_glob opts = {0}; - - opts.version = TC_HTB_PROTOVER; - opts.rate2quantum = 10; + struct tc_htb_glob opts = { + .version = TC_HTB_PROTOVER, + .rate2quantum = 10, + }; if (htb) { if (htb->qh_mask & SCH_HTB_HAS_RATE2QUANTUM) From e7ec197da35d5f8efc44af0afbe21b8612478a57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Fri, 21 Sep 2012 23:10:26 +0600 Subject: [PATCH 276/432] nf-log example: correct copy-range parsing --- src/nf-log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nf-log.c b/src/nf-log.c index 26bae6d..913ba16 100644 --- a/src/nf-log.c +++ b/src/nf-log.c @@ -96,7 +96,7 @@ int main(int argc, char *argv[]) copy_range = 0xFFFF; if (argc > 4) - copy_mode = atoi(argv[4]); + copy_range = atoi(argv[4]); nfnl_log_set_copy_range(log, copy_range); if ((err = nfnl_log_create(nf_sock, log)) < 0) From 9d6b104ec8b4dc8ce182158bf6c81db23e937c5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=BD=D0=BE=D1=83=D1=82=D0=B1?= =?UTF-8?q?=D1=83=D0=BA=20=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Mon, 10 Sep 2012 02:25:07 +0600 Subject: [PATCH 277/432] nl_recv(): "else if" logick simplified and refined --- lib/nl.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/lib/nl.c b/lib/nl.c index 2fa741f..8426c58 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -459,25 +459,31 @@ retry: n = recvmsg(sk->s_fd, &msg, flags); if (!n) goto abort; - else if (n < 0) { + + if (n < 0) { + if (errno == EINTR) { NL_DBG(3, "recvmsg() returned EINTR, retrying\n"); goto retry; - } else if (errno == EAGAIN) { + } + + if (errno == EAGAIN) { NL_DBG(3, "recvmsg() returned EAGAIN, aborting\n"); goto abort; - } else { - free(msg.msg_control); - free(*buf); - return -nl_syserr2nlerr(errno); } + + free(msg.msg_control); + free(*buf); + return -nl_syserr2nlerr(errno); } if (msg.msg_flags & MSG_CTRUNC) { msg.msg_controllen *= 2; msg.msg_control = realloc(msg.msg_control, msg.msg_controllen); goto retry; - } else if (iov.iov_len < n || msg.msg_flags & MSG_TRUNC) { + } + + if (iov.iov_len < n || msg.msg_flags & MSG_TRUNC) { /* Provided buffer is not long enough, enlarge it * to size of n (which should be total length of the message) * and try again. */ @@ -485,7 +491,9 @@ retry: iov.iov_base = *buf = realloc(*buf, iov.iov_len); flags = 0; goto retry; - } else if (flags != 0) { + } + + if (flags != 0) { /* Buffer is big enough, do the actual reading */ flags = 0; goto retry; From 69468517d0de1675d80f24661ff57a5dbac7275c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Fri, 19 Oct 2012 22:58:58 +0600 Subject: [PATCH 278/432] nl_recv(): Memory allocation errors are handled properly now 1. all cleanup actions (like free()) now located at the end of function 2. in case of error or EOF, *buf and *creds (if given) set to NULL This protect from invalid code at user's side, like: char *buf; x = nl_recv(..., &buf, ...); if (x<=0) goto cleanup; cleanup: free(buf); 3. all intermediate buffers are stored into local variables, and user's variables only touches at the end. --- lib/nl.c | 75 +++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 22 deletions(-) diff --git a/lib/nl.c b/lib/nl.c index 8426c58..d08f7e1 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -437,9 +437,9 @@ int nl_recv(struct nl_sock *sk, struct sockaddr_nl *nla, .msg_controllen = 0, .msg_flags = 0, }; - struct cmsghdr *cmsg; - memset(nla, 0, sizeof(*nla)); + struct ucred* tmpcreds = NULL; + int retval = 0; if (sk->s_flags & NL_MSG_PEEK) flags |= MSG_PEEK | MSG_TRUNC; @@ -448,20 +448,29 @@ int nl_recv(struct nl_sock *sk, struct sockaddr_nl *nla, page_size = getpagesize(); iov.iov_len = sk->s_bufsize ? : page_size; - iov.iov_base = *buf = malloc(iov.iov_len); + iov.iov_base = malloc(iov.iov_len); + + if (!iov.iov_base) { + retval = -NLE_NOMEM; + goto abort; + } if (sk->s_flags & NL_SOCK_PASSCRED) { msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred)); msg.msg_control = calloc(1, msg.msg_controllen); + if (!msg.msg_control) { + retval = -NLE_NOMEM; + goto abort; + } } retry: n = recvmsg(sk->s_fd, &msg, flags); - if (!n) + if (!n) { + retval = 0; goto abort; - + } if (n < 0) { - if (errno == EINTR) { NL_DBG(3, "recvmsg() returned EINTR, retrying\n"); goto retry; @@ -469,26 +478,37 @@ retry: if (errno == EAGAIN) { NL_DBG(3, "recvmsg() returned EAGAIN, aborting\n"); + retval = 0; goto abort; } - - free(msg.msg_control); - free(*buf); - return -nl_syserr2nlerr(errno); + retval = -nl_syserr2nlerr(errno); + goto abort; } if (msg.msg_flags & MSG_CTRUNC) { + void *tmp; msg.msg_controllen *= 2; - msg.msg_control = realloc(msg.msg_control, msg.msg_controllen); + tmp = realloc(msg.msg_control, msg.msg_controllen); + if (!tmp) { + retval = -NLE_NOMEM; + goto abort; + } + msg.msg_control = tmp; goto retry; } if (iov.iov_len < n || msg.msg_flags & MSG_TRUNC) { + void *tmp; /* Provided buffer is not long enough, enlarge it * to size of n (which should be total length of the message) * and try again. */ iov.iov_len = n; - iov.iov_base = *buf = realloc(*buf, iov.iov_len); + tmp = realloc(iov.iov_base, iov.iov_len); + if (!tmp) { + retval = -NLE_NOMEM; + goto abort; + } + iov.iov_base = tmp; flags = 0; goto retry; } @@ -500,29 +520,40 @@ retry: } if (msg.msg_namelen != sizeof(struct sockaddr_nl)) { - free(msg.msg_control); - free(*buf); - return -NLE_NOADDR; + retval = -NLE_NOADDR; + goto abort; } for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS) { if (creds) { - *creds = calloc(1, sizeof(struct ucred)); - memcpy(*creds, CMSG_DATA(cmsg), sizeof(struct ucred)); + tmpcreds = malloc(sizeof(*tmpcreds)); + if (!tmpcreds) { + retval = -NLE_NOMEM; + goto abort; + } + memcpy(tmpcreds, CMSG_DATA(cmsg), sizeof(*tmpcreds)); } break; } } - free(msg.msg_control); - return n; - + retval = n; abort: free(msg.msg_control); - free(*buf); - return 0; + + if (retval <= 0) { + free(iov.iov_base); iov.iov_base = NULL; + free(tmpcreds); tmpcreds = NULL; + } + + *buf = iov.iov_base; + + if (creds) + *creds = tmpcreds; + + return retval; } /** @cond SKIP */ From 2249eaebd4bde07e33f265e7eaac5ad85b5f1253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Fri, 19 Oct 2012 23:04:23 +0600 Subject: [PATCH 279/432] nl_recv(): EWOULDBLOCK return value also checked --- lib/nl.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/nl.c b/lib/nl.c index d08f7e1..7f47223 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -475,9 +475,8 @@ retry: NL_DBG(3, "recvmsg() returned EINTR, retrying\n"); goto retry; } - - if (errno == EAGAIN) { - NL_DBG(3, "recvmsg() returned EAGAIN, aborting\n"); + if (errno == EAGAIN || errno == EWOULDBLOCK) { + NL_DBG(3, "recvmsg() returned EAGAIN||EWOULDBLOCK, aborting\n"); retval = 0; goto abort; } From da694e6c7b11d475d84ca6addeae34a6dac8c949 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Fri, 19 Oct 2012 23:06:23 +0600 Subject: [PATCH 280/432] nl_recv(): small code cleanups 1. memset around nla is unnecessary 2. calloc() is unnecessary. malloc() used instead. --- lib/nl.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/lib/nl.c b/lib/nl.c index 7f47223..284d23c 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -405,8 +405,8 @@ errout: /** * Receive data from netlink socket * @arg sk Netlink socket. - * @arg nla Destination pointer for peer's netlink address. - * @arg buf Destination pointer for message content. + * @arg nla Destination pointer for peer's netlink address. (required) + * @arg buf Destination pointer for message content. (required) * @arg creds Destination pointer for credentials. * * Receives a netlink message, allocates a buffer in \c *buf and @@ -433,11 +433,7 @@ int nl_recv(struct nl_sock *sk, struct sockaddr_nl *nla, .msg_namelen = sizeof(struct sockaddr_nl), .msg_iov = &iov, .msg_iovlen = 1, - .msg_control = NULL, - .msg_controllen = 0, - .msg_flags = 0, }; - memset(nla, 0, sizeof(*nla)); struct ucred* tmpcreds = NULL; int retval = 0; @@ -457,7 +453,7 @@ int nl_recv(struct nl_sock *sk, struct sockaddr_nl *nla, if (sk->s_flags & NL_SOCK_PASSCRED) { msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred)); - msg.msg_control = calloc(1, msg.msg_controllen); + msg.msg_control = malloc(msg.msg_controllen); if (!msg.msg_control) { retval = -NLE_NOMEM; goto abort; @@ -496,7 +492,7 @@ retry: goto retry; } - if (iov.iov_len < n || msg.msg_flags & MSG_TRUNC) { + if (iov.iov_len < n || (msg.msg_flags & MSG_TRUNC)) { void *tmp; /* Provided buffer is not long enough, enlarge it * to size of n (which should be total length of the message) From 420e4623fd1ebf2a14e2977d82fd477f1e913460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Fri, 19 Oct 2012 23:23:10 +0600 Subject: [PATCH 281/432] nl_recv(): work with credentials only if "creds" given and NL_SOCK_PASSCRED set --- lib/nl.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/lib/nl.c b/lib/nl.c index 284d23c..9858307 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -407,7 +407,7 @@ errout: * @arg sk Netlink socket. * @arg nla Destination pointer for peer's netlink address. (required) * @arg buf Destination pointer for message content. (required) - * @arg creds Destination pointer for credentials. + * @arg creds Destination pointer for credentials. (optional) * * Receives a netlink message, allocates a buffer in \c *buf and * stores the message content. The peer's netlink address is stored @@ -451,7 +451,7 @@ int nl_recv(struct nl_sock *sk, struct sockaddr_nl *nla, goto abort; } - if (sk->s_flags & NL_SOCK_PASSCRED) { + if (creds && (sk->s_flags & NL_SOCK_PASSCRED)) { msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred)); msg.msg_control = malloc(msg.msg_controllen); if (!msg.msg_control) { @@ -519,17 +519,20 @@ retry: goto abort; } - for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { - if (cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_CREDENTIALS) { - if (creds) { - tmpcreds = malloc(sizeof(*tmpcreds)); - if (!tmpcreds) { - retval = -NLE_NOMEM; - goto abort; - } - memcpy(tmpcreds, CMSG_DATA(cmsg), sizeof(*tmpcreds)); + if (creds && (sk->s_flags & NL_SOCK_PASSCRED)) { + struct cmsghdr *cmsg; + + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level != SOL_SOCKET) + continue; + if (cmsg->cmsg_type != SCM_CREDENTIALS) + continue; + tmpcreds = malloc(sizeof(*tmpcreds)); + if (!tmpcreds) { + retval = -NLE_NOMEM; + goto abort; } + memcpy(tmpcreds, CMSG_DATA(cmsg), sizeof(*tmpcreds)); break; } } From d2fff93ccebbc22fe9b8094b93ffde34d802b680 Mon Sep 17 00:00:00 2001 From: Rich Fought Date: Fri, 19 Oct 2012 11:18:52 -0700 Subject: [PATCH 282/432] Source cleanup for upstream --- include/netlink-types.h | 56 +-- include/netlink/netfilter/exp.h | 17 +- lib/netfilter/exp.c | 212 +++++----- lib/netfilter/exp_obj.c | 700 ++++++++++++++++---------------- src/lib/exp.c | 58 +-- src/nf-exp-add.c | 86 ++-- src/nf-exp-delete.c | 82 ++-- src/nf-exp-list.c | 22 +- 8 files changed, 610 insertions(+), 623 deletions(-) diff --git a/include/netlink-types.h b/include/netlink-types.h index 0ee1bda..ec19678 100644 --- a/include/netlink-types.h +++ b/include/netlink-types.h @@ -780,47 +780,47 @@ struct nfnl_ct { }; union nfnl_exp_protodata { - struct { - uint16_t src; - uint16_t dst; - } port; - struct { - uint16_t id; - uint8_t type; - uint8_t code; - } icmp; + struct { + uint16_t src; + uint16_t dst; + } port; + struct { + uint16_t id; + uint8_t type; + uint8_t code; + } icmp; }; // Allow for different master/expect l4 protocols struct nfnl_exp_proto { - uint8_t l4protonum; - union nfnl_exp_protodata l4protodata; + uint8_t l4protonum; + union nfnl_exp_protodata l4protodata; }; struct nfnl_exp_dir { - struct nl_addr * src; - struct nl_addr * dst; - struct nfnl_exp_proto proto; + struct nl_addr * src; + struct nl_addr * dst; + struct nfnl_exp_proto proto; }; struct nfnl_exp { - NLHDR_COMMON + NLHDR_COMMON - uint8_t exp_family; // IPv4, IPv6, etc - required - uint32_t exp_timeout; // required afaik - uint32_t exp_id; // optional - uint16_t exp_zone; // optional - uint32_t exp_class; // optional - uint32_t exp_flags; // optional - char * exp_helper_name; //optional - char * exp_fn; //optional - uint8_t exp_nat_dir; // optional + uint8_t exp_family; + uint32_t exp_timeout; + uint32_t exp_id; + uint16_t exp_zone; + uint32_t exp_class; + uint32_t exp_flags; + char * exp_helper_name; + char * exp_fn; + uint8_t exp_nat_dir; - struct nfnl_exp_dir exp_expect; // required - struct nfnl_exp_dir exp_master; // required - struct nfnl_exp_dir exp_mask; // required - struct nfnl_exp_dir exp_nat; // optional + struct nfnl_exp_dir exp_expect; + struct nfnl_exp_dir exp_master; + struct nfnl_exp_dir exp_mask; + struct nfnl_exp_dir exp_nat; }; struct nfnl_log { diff --git a/include/netlink/netfilter/exp.h b/include/netlink/netfilter/exp.h index 8b50c30..4e95014 100644 --- a/include/netlink/netfilter/exp.h +++ b/include/netlink/netfilter/exp.h @@ -29,11 +29,11 @@ extern "C" { struct nfnl_exp; enum nfnl_exp_tuples { - NFNL_EXP_TUPLE_EXPECT, - NFNL_EXP_TUPLE_MASTER, - NFNL_EXP_TUPLE_MASK, - NFNL_EXP_TUPLE_NAT, - NFNL_EXP_TUPLE_MAX + NFNL_EXP_TUPLE_EXPECT, + NFNL_EXP_TUPLE_MASTER, + NFNL_EXP_TUPLE_MASK, + NFNL_EXP_TUPLE_NAT, + NFNL_EXP_TUPLE_MAX }; extern struct nl_object_ops exp_obj_ops; @@ -50,15 +50,15 @@ extern void nfnl_exp_put(struct nfnl_exp *); extern int nfnl_exp_dump_request(struct nl_sock *); extern int nfnl_exp_build_add_request(const struct nfnl_exp *, int, - struct nl_msg **); + struct nl_msg **); extern int nfnl_exp_add(struct nl_sock *, const struct nfnl_exp *, int); extern int nfnl_exp_build_delete_request(const struct nfnl_exp *, int, - struct nl_msg **); + struct nl_msg **); extern int nfnl_exp_del(struct nl_sock *, const struct nfnl_exp *, int); extern int nfnl_exp_build_query_request(const struct nfnl_exp *, int, - struct nl_msg **); + struct nl_msg **); extern int nfnl_exp_query(struct nl_sock *, const struct nfnl_exp *, int); extern void nfnl_exp_set_family(struct nfnl_exp *, uint8_t); @@ -122,7 +122,6 @@ extern uint16_t nfnl_exp_get_icmp_id(const struct nfnl_exp *, int); extern uint8_t nfnl_exp_get_icmp_type(const struct nfnl_exp *, int); extern uint8_t nfnl_exp_get_icmp_code(const struct nfnl_exp *, int); - #ifdef __cplusplus } #endif diff --git a/lib/netfilter/exp.c b/lib/netfilter/exp.c index 05bc044..5ba2bcb 100644 --- a/lib/netfilter/exp.c +++ b/lib/netfilter/exp.c @@ -32,17 +32,17 @@ static struct nl_cache_ops nfnl_exp_ops; static struct nla_policy exp_policy[CTA_EXPECT_MAX+1] = { - [CTA_EXPECT_MASTER] = { .type = NLA_NESTED }, - [CTA_EXPECT_TUPLE] = { .type = NLA_NESTED }, - [CTA_EXPECT_MASK] = { .type = NLA_NESTED }, - [CTA_EXPECT_TIMEOUT] = { .type = NLA_U32 }, - [CTA_EXPECT_ID] = { .type = NLA_U32 }, - [CTA_EXPECT_HELP_NAME] = { .type = NLA_STRING }, - [CTA_EXPECT_ZONE] = { .type = NLA_U16 }, // Added in kernel 2.6.34 - [CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, // Added in kernel 2.6.37 - [CTA_EXPECT_CLASS] = { .type = NLA_U32 }, // Added in kernel 3.5 - [CTA_EXPECT_NAT] = { .type = NLA_NESTED }, // Added in kernel 3.5 - [CTA_EXPECT_FN] = { .type = NLA_STRING }, // Added in kernel 3.5 + [CTA_EXPECT_MASTER] = { .type = NLA_NESTED }, + [CTA_EXPECT_TUPLE] = { .type = NLA_NESTED }, + [CTA_EXPECT_MASK] = { .type = NLA_NESTED }, + [CTA_EXPECT_TIMEOUT] = { .type = NLA_U32 }, + [CTA_EXPECT_ID] = { .type = NLA_U32 }, + [CTA_EXPECT_HELP_NAME] = { .type = NLA_STRING }, + [CTA_EXPECT_ZONE] = { .type = NLA_U16 }, + [CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, // Added in kernel 2.6.37 + [CTA_EXPECT_CLASS] = { .type = NLA_U32 }, // Added in kernel 3.5 + [CTA_EXPECT_NAT] = { .type = NLA_NESTED }, // Added in kernel 3.5 + [CTA_EXPECT_FN] = { .type = NLA_STRING }, // Added in kernel 3.5 }; static struct nla_policy exp_tuple_policy[CTA_TUPLE_MAX+1] = { @@ -58,10 +58,10 @@ static struct nla_policy exp_ip_policy[CTA_IP_MAX+1] = { }; static struct nla_policy exp_proto_policy[CTA_PROTO_MAX+1] = { - [CTA_PROTO_NUM] = { .type = NLA_U8 }, + [CTA_PROTO_NUM] = { .type = NLA_U8 }, [CTA_PROTO_SRC_PORT] = { .type = NLA_U16 }, [CTA_PROTO_DST_PORT] = { .type = NLA_U16 }, - [CTA_PROTO_ICMP_ID] = { .type = NLA_U16 }, + [CTA_PROTO_ICMP_ID] = { .type = NLA_U16 }, [CTA_PROTO_ICMP_TYPE] = { .type = NLA_U8 }, [CTA_PROTO_ICMP_CODE] = { .type = NLA_U8 }, [CTA_PROTO_ICMPV6_ID] = { .type = NLA_U16 }, @@ -70,8 +70,8 @@ static struct nla_policy exp_proto_policy[CTA_PROTO_MAX+1] = { }; static struct nla_policy exp_nat_policy[CTA_EXPECT_NAT_MAX+1] = { - [CTA_EXPECT_NAT_DIR] = { .type = NLA_U8 }, - [CTA_EXPECT_NAT_TUPLE] = { .type = NLA_NESTED }, + [CTA_EXPECT_NAT_DIR] = { .type = NLA_U8 }, + [CTA_EXPECT_NAT_TUPLE] = { .type = NLA_NESTED }, }; static int exp_parse_ip(struct nfnl_exp *exp, int tuple, struct nlattr *attr) @@ -80,7 +80,7 @@ static int exp_parse_ip(struct nfnl_exp *exp, int tuple, struct nlattr *attr) struct nl_addr *addr; int err; - err = nla_parse_nested(tb, CTA_IP_MAX, attr, exp_ip_policy); + err = nla_parse_nested(tb, CTA_IP_MAX, attr, exp_ip_policy); if (err < 0) goto errout; @@ -144,20 +144,20 @@ static int exp_parse_proto(struct nfnl_exp *exp, int tuple, struct nlattr *attr) nfnl_exp_set_l4protonum(exp, tuple, nla_get_u8(tb[CTA_PROTO_NUM])); if (tb[CTA_PROTO_SRC_PORT]) - srcport = ntohs(nla_get_u16(tb[CTA_PROTO_SRC_PORT])); + srcport = ntohs(nla_get_u16(tb[CTA_PROTO_SRC_PORT])); if (tb[CTA_PROTO_DST_PORT]) - dstport = ntohs(nla_get_u16(tb[CTA_PROTO_DST_PORT])); + dstport = ntohs(nla_get_u16(tb[CTA_PROTO_DST_PORT])); if (tb[CTA_PROTO_SRC_PORT] || tb[CTA_PROTO_DST_PORT]) - nfnl_exp_set_ports(exp, tuple, srcport, dstport); + nfnl_exp_set_ports(exp, tuple, srcport, dstport); if (tb[CTA_PROTO_ICMP_ID]) - icmpid = ntohs(nla_get_u16(tb[CTA_PROTO_ICMP_ID])); + icmpid = ntohs(nla_get_u16(tb[CTA_PROTO_ICMP_ID])); if (tb[CTA_PROTO_ICMP_TYPE]) icmptype = nla_get_u8(tb[CTA_PROTO_ICMP_TYPE]); if (tb[CTA_PROTO_ICMP_CODE]) icmpcode = nla_get_u8(tb[CTA_PROTO_ICMP_CODE]); if (tb[CTA_PROTO_ICMP_ID] || tb[CTA_PROTO_ICMP_TYPE] || tb[CTA_PROTO_ICMP_CODE]) - nfnl_exp_set_icmp(exp, tuple, icmpid, icmptype, icmpcode); + nfnl_exp_set_icmp(exp, tuple, icmpid, icmptype, icmpcode); return 0; } @@ -187,23 +187,23 @@ static int exp_parse_tuple(struct nfnl_exp *exp, int tuple, struct nlattr *attr) static int exp_parse_nat(struct nfnl_exp *exp, struct nlattr *attr) { - struct nlattr *tb[CTA_EXPECT_NAT_MAX+1]; - int err; + struct nlattr *tb[CTA_EXPECT_NAT_MAX+1]; + int err; - err = nla_parse_nested(tb, CTA_EXPECT_NAT_MAX, attr, exp_nat_policy); - if (err < 0) - return err; + err = nla_parse_nested(tb, CTA_EXPECT_NAT_MAX, attr, exp_nat_policy); + if (err < 0) + return err; - if (tb[CTA_EXPECT_NAT_DIR]) - nfnl_exp_set_nat_dir(exp, nla_get_u8(tb[CTA_EXPECT_NAT_DIR])); + if (tb[CTA_EXPECT_NAT_DIR]) + nfnl_exp_set_nat_dir(exp, nla_get_u8(tb[CTA_EXPECT_NAT_DIR])); - if (tb[CTA_EXPECT_NAT_TUPLE]) { - err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_NAT, tb[CTA_EXPECT_NAT_TUPLE]); - if (err < 0) - return err; - } + if (tb[CTA_EXPECT_NAT_TUPLE]) { + err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_NAT, tb[CTA_EXPECT_NAT_TUPLE]); + if (err < 0) + return err; + } - return 0; + return 0; } int nfnlmsg_exp_group(struct nlmsghdr *nlh) @@ -241,10 +241,10 @@ int nfnlmsg_exp_parse(struct nlmsghdr *nlh, struct nfnl_exp **result) nfnl_exp_set_family(exp, nfnlmsg_family(nlh)); if (tb[CTA_EXPECT_TUPLE]) { - err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_EXPECT, tb[CTA_EXPECT_TUPLE]); - if (err < 0) - goto errout; - } + err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_EXPECT, tb[CTA_EXPECT_TUPLE]); + if (err < 0) + goto errout; + } if (tb[CTA_EXPECT_MASTER]) { err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_MASTER, tb[CTA_EXPECT_MASTER]); if (err < 0) @@ -256,18 +256,17 @@ int nfnlmsg_exp_parse(struct nlmsghdr *nlh, struct nfnl_exp **result) goto errout; } - if (tb[CTA_EXPECT_NAT]) - err = exp_parse_nat(exp, tb[CTA_EXPECT_MASK]); - if (err < 0) - goto errout; - - if (tb[CTA_EXPECT_CLASS]) - nfnl_exp_set_class(exp, ntohl(nla_get_u32(tb[CTA_EXPECT_CLASS]))); - - if (tb[CTA_EXPECT_FN]) - nfnl_exp_set_fn(exp, nla_data(tb[CTA_EXPECT_FN])); + if (tb[CTA_EXPECT_NAT]) { + err = exp_parse_nat(exp, tb[CTA_EXPECT_MASK]); + if (err < 0) + goto errout; + } + if (tb[CTA_EXPECT_CLASS]) + nfnl_exp_set_class(exp, ntohl(nla_get_u32(tb[CTA_EXPECT_CLASS]))); + if (tb[CTA_EXPECT_FN]) + nfnl_exp_set_fn(exp, nla_data(tb[CTA_EXPECT_FN])); if (tb[CTA_EXPECT_TIMEOUT]) nfnl_exp_set_timeout(exp, ntohl(nla_get_u32(tb[CTA_EXPECT_TIMEOUT]))); @@ -276,13 +275,13 @@ int nfnlmsg_exp_parse(struct nlmsghdr *nlh, struct nfnl_exp **result) nfnl_exp_set_id(exp, ntohl(nla_get_u32(tb[CTA_EXPECT_ID]))); if (tb[CTA_EXPECT_HELP_NAME]) - nfnl_exp_set_helper_name(exp, nla_data(tb[CTA_EXPECT_HELP_NAME])); + nfnl_exp_set_helper_name(exp, nla_data(tb[CTA_EXPECT_HELP_NAME])); - if (tb[CTA_EXPECT_ZONE]) - nfnl_exp_set_zone(exp, ntohs(nla_get_u16(tb[CTA_EXPECT_ZONE]))); + if (tb[CTA_EXPECT_ZONE]) + nfnl_exp_set_zone(exp, ntohs(nla_get_u16(tb[CTA_EXPECT_ZONE]))); - if (tb[CTA_EXPECT_FLAGS]) - nfnl_exp_set_flags(exp, ntohl(nla_get_u32(tb[CTA_EXPECT_FLAGS]))); + if (tb[CTA_EXPECT_FLAGS]) + nfnl_exp_set_flags(exp, ntohl(nla_get_u32(tb[CTA_EXPECT_FLAGS]))); *result = exp; return 0; @@ -320,25 +319,25 @@ static int exp_request_update(struct nl_cache *cache, struct nl_sock *sk) static int exp_get_tuple_attr(int tuple) { - int attr = 0; + int attr = 0; - switch (tuple) { - case CTA_EXPECT_MASTER: - attr = NFNL_EXP_TUPLE_MASTER; - break; - case CTA_EXPECT_MASK: - attr = NFNL_EXP_TUPLE_MASK; - break; - //case CTA_EXPECT_NAT: - // attr = NFNL_EXP_TUPLE_NAT; - // break; - case CTA_EXPECT_TUPLE: - default : - attr = NFNL_EXP_TUPLE_EXPECT; - break; - } + switch (tuple) { + case CTA_EXPECT_MASTER: + attr = NFNL_EXP_TUPLE_MASTER; + break; + case CTA_EXPECT_MASK: + attr = NFNL_EXP_TUPLE_MASK; + break; + case CTA_EXPECT_NAT: + attr = NFNL_EXP_TUPLE_NAT; + break; + case CTA_EXPECT_TUPLE: + default : + attr = NFNL_EXP_TUPLE_EXPECT; + break; + } - return attr; + return attr; } static int nfnl_exp_build_tuple(struct nl_msg *msg, const struct nfnl_exp *exp, @@ -411,24 +410,24 @@ nla_put_failure: static int nfnl_exp_build_nat(struct nl_msg *msg, const struct nfnl_exp *exp) { - struct nlattr *nat; - int err; + struct nlattr *nat; + int err; - nat = nla_nest_start(msg, CTA_EXPECT_NAT); + nat = nla_nest_start(msg, CTA_EXPECT_NAT); - if (nfnl_exp_test_nat_dir(exp)) { - NLA_PUT_U8(msg, CTA_EXPECT_NAT_DIR, - nfnl_exp_get_nat_dir(exp)); - } + if (nfnl_exp_test_nat_dir(exp)) { + NLA_PUT_U8(msg, CTA_EXPECT_NAT_DIR, + nfnl_exp_get_nat_dir(exp)); + } - if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_NAT_TUPLE)) < 0) - goto nla_put_failure; + if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_NAT_TUPLE)) < 0) + goto nla_put_failure; - nla_nest_end(msg, nat); - return 0; + nla_nest_end(msg, nat); + return 0; nla_put_failure: - return -NLE_MSGSIZE; + return -NLE_MSGSIZE; } static int nfnl_exp_build_message(const struct nfnl_exp *exp, int cmd, int flags, @@ -445,38 +444,37 @@ static int nfnl_exp_build_message(const struct nfnl_exp *exp, int cmd, int flags if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_TUPLE)) < 0) goto err_out; - if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_MASTER)) < 0) - goto err_out; + if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_MASTER)) < 0) + goto err_out; - if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_MASK)) < 0) - goto err_out; + if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_MASK)) < 0) + goto err_out; - if (nfnl_exp_test_src(exp, NFNL_EXP_TUPLE_NAT)) { - if ((err = nfnl_exp_build_nat(msg, exp)) < 0) - goto err_out; - } + if (nfnl_exp_test_src(exp, NFNL_EXP_TUPLE_NAT)) { + if ((err = nfnl_exp_build_nat(msg, exp)) < 0) + goto err_out; + } - if (nfnl_exp_test_class(exp)) - NLA_PUT_U32(msg, CTA_EXPECT_CLASS, htonl(nfnl_exp_get_class(exp))); + if (nfnl_exp_test_class(exp)) + NLA_PUT_U32(msg, CTA_EXPECT_CLASS, htonl(nfnl_exp_get_class(exp))); - if (nfnl_exp_test_fn(exp)) - NLA_PUT_STRING(msg, CTA_EXPECT_FN, nfnl_exp_get_fn(exp)); + if (nfnl_exp_test_fn(exp)) + NLA_PUT_STRING(msg, CTA_EXPECT_FN, nfnl_exp_get_fn(exp)); + if (nfnl_exp_test_id(exp)) + NLA_PUT_U32(msg, CTA_EXPECT_ID, htonl(nfnl_exp_get_id(exp))); - if (nfnl_exp_test_id(exp)) - NLA_PUT_U32(msg, CTA_EXPECT_ID, htonl(nfnl_exp_get_id(exp))); + if (nfnl_exp_test_timeout(exp)) + NLA_PUT_U32(msg, CTA_EXPECT_TIMEOUT, htonl(nfnl_exp_get_timeout(exp))); - if (nfnl_exp_test_timeout(exp)) - NLA_PUT_U32(msg, CTA_EXPECT_TIMEOUT, htonl(nfnl_exp_get_timeout(exp))); + if (nfnl_exp_test_helper_name(exp)) + NLA_PUT_STRING(msg, CTA_EXPECT_HELP_NAME, nfnl_exp_get_helper_name(exp)); - if (nfnl_exp_test_helper_name(exp)) - NLA_PUT_STRING(msg, CTA_EXPECT_HELP_NAME, nfnl_exp_get_helper_name(exp)); + if (nfnl_exp_test_zone(exp)) + NLA_PUT_U16(msg, CTA_EXPECT_ZONE, htons(nfnl_exp_get_zone(exp))); - if (nfnl_exp_test_zone(exp)) - NLA_PUT_U16(msg, CTA_EXPECT_ZONE, htons(nfnl_exp_get_zone(exp))); - - if (nfnl_exp_test_flags(exp)) - NLA_PUT_U32(msg, CTA_EXPECT_FLAGS, htonl(nfnl_exp_get_flags(exp))); + if (nfnl_exp_test_flags(exp)) + NLA_PUT_U32(msg, CTA_EXPECT_FLAGS, htonl(nfnl_exp_get_flags(exp))); *result = msg; return 0; @@ -600,10 +598,10 @@ static struct nl_cache_ops nfnl_exp_ops = { END_OF_MSGTYPES_LIST, }, .co_protocol = NETLINK_NETFILTER, - .co_groups = exp_groups, + .co_groups = exp_groups, .co_request_update = exp_request_update, .co_msg_parser = exp_msg_parser, - .co_obj_ops = &exp_obj_ops, + .co_obj_ops = &exp_obj_ops, }; static void __init exp_init(void) diff --git a/lib/netfilter/exp_obj.c b/lib/netfilter/exp_obj.c index eeb05b3..182df23 100644 --- a/lib/netfilter/exp_obj.c +++ b/lib/netfilter/exp_obj.c @@ -29,36 +29,36 @@ // these parent attributes will include nested attributes. /** @cond SKIP */ -#define EXP_ATTR_FAMILY (1UL << 0) // 8-bit -#define EXP_ATTR_TIMEOUT (1UL << 1) // 32-bit -#define EXP_ATTR_ID (1UL << 2) // 32-bit -#define EXP_ATTR_HELPER_NAME (1UL << 3) // string (16 bytes max) -#define EXP_ATTR_ZONE (1UL << 4) // 16-bit -#define EXP_ATTR_FLAGS (1UL << 5) // 32-bit -#define EXP_ATTR_CLASS (1UL << 6) // 32-bit ??? -#define EXP_ATTR_FN (1UL << 7) // String ??? +#define EXP_ATTR_FAMILY (1UL << 0) // 8-bit +#define EXP_ATTR_TIMEOUT (1UL << 1) // 32-bit +#define EXP_ATTR_ID (1UL << 2) // 32-bit +#define EXP_ATTR_HELPER_NAME (1UL << 3) // string +#define EXP_ATTR_ZONE (1UL << 4) // 16-bit +#define EXP_ATTR_FLAGS (1UL << 5) // 32-bit +#define EXP_ATTR_CLASS (1UL << 6) // 32-bit +#define EXP_ATTR_FN (1UL << 7) // String // Tuples -#define EXP_ATTR_EXPECT_IP_SRC (1UL << 8) -#define EXP_ATTR_EXPECT_IP_DST (1UL << 9) -#define EXP_ATTR_EXPECT_L4PROTO_NUM (1UL << 10) // contains l4proto # + PORT attrs or ICMP attrs -#define EXP_ATTR_EXPECT_L4PROTO_PORTS (1UL << 11) -#define EXP_ATTR_EXPECT_L4PROTO_ICMP (1UL << 12) -#define EXP_ATTR_MASTER_IP_SRC (1UL << 13) -#define EXP_ATTR_MASTER_IP_DST (1UL << 14) -#define EXP_ATTR_MASTER_L4PROTO_NUM (1UL << 15) // contains l4proto # + PORT attrs or ICMP attrs -#define EXP_ATTR_MASTER_L4PROTO_PORTS (1UL << 16) -#define EXP_ATTR_MASTER_L4PROTO_ICMP (1UL << 17) -#define EXP_ATTR_MASK_IP_SRC (1UL << 18) -#define EXP_ATTR_MASK_IP_DST (1UL << 19) -#define EXP_ATTR_MASK_L4PROTO_NUM (1UL << 20) // contains l4proto # + PORT attrs or ICMP attrs -#define EXP_ATTR_MASK_L4PROTO_PORTS (1UL << 21) -#define EXP_ATTR_MASK_L4PROTO_ICMP (1UL << 22) -#define EXP_ATTR_NAT_IP_SRC (1UL << 23) -#define EXP_ATTR_NAT_IP_DST (1UL << 24) -#define EXP_ATTR_NAT_L4PROTO_NUM (1UL << 25) // contains l4proto # + PORT attrs or ICMP attrs -#define EXP_ATTR_NAT_L4PROTO_PORTS (1UL << 26) -#define EXP_ATTR_NAT_L4PROTO_ICMP (1UL << 27) -#define EXP_ATTR_NAT_DIR (1UL << 28) // 8-bit +#define EXP_ATTR_EXPECT_IP_SRC (1UL << 8) +#define EXP_ATTR_EXPECT_IP_DST (1UL << 9) +#define EXP_ATTR_EXPECT_L4PROTO_NUM (1UL << 10) +#define EXP_ATTR_EXPECT_L4PROTO_PORTS (1UL << 11) +#define EXP_ATTR_EXPECT_L4PROTO_ICMP (1UL << 12) +#define EXP_ATTR_MASTER_IP_SRC (1UL << 13) +#define EXP_ATTR_MASTER_IP_DST (1UL << 14) +#define EXP_ATTR_MASTER_L4PROTO_NUM (1UL << 15) +#define EXP_ATTR_MASTER_L4PROTO_PORTS (1UL << 16) +#define EXP_ATTR_MASTER_L4PROTO_ICMP (1UL << 17) +#define EXP_ATTR_MASK_IP_SRC (1UL << 18) +#define EXP_ATTR_MASK_IP_DST (1UL << 19) +#define EXP_ATTR_MASK_L4PROTO_NUM (1UL << 20) +#define EXP_ATTR_MASK_L4PROTO_PORTS (1UL << 21) +#define EXP_ATTR_MASK_L4PROTO_ICMP (1UL << 22) +#define EXP_ATTR_NAT_IP_SRC (1UL << 23) +#define EXP_ATTR_NAT_IP_DST (1UL << 24) +#define EXP_ATTR_NAT_L4PROTO_NUM (1UL << 25) +#define EXP_ATTR_NAT_L4PROTO_PORTS (1UL << 26) +#define EXP_ATTR_NAT_L4PROTO_ICMP (1UL << 27) +#define EXP_ATTR_NAT_DIR (1UL << 28) /** @endcond */ static void exp_free_data(struct nl_object *c) @@ -68,90 +68,90 @@ static void exp_free_data(struct nl_object *c) if (exp == NULL) return; - nl_addr_put(exp->exp_expect.src); - nl_addr_put(exp->exp_expect.dst); - nl_addr_put(exp->exp_master.src); - nl_addr_put(exp->exp_master.dst); - nl_addr_put(exp->exp_mask.src); - nl_addr_put(exp->exp_mask.dst); - nl_addr_put(exp->exp_nat.src); - nl_addr_put(exp->exp_nat.dst); + nl_addr_put(exp->exp_expect.src); + nl_addr_put(exp->exp_expect.dst); + nl_addr_put(exp->exp_master.src); + nl_addr_put(exp->exp_master.dst); + nl_addr_put(exp->exp_mask.src); + nl_addr_put(exp->exp_mask.dst); + nl_addr_put(exp->exp_nat.src); + nl_addr_put(exp->exp_nat.dst); - free(exp->exp_fn); - free(exp->exp_helper_name); + free(exp->exp_fn); + free(exp->exp_helper_name); } static int exp_clone(struct nl_object *_dst, struct nl_object *_src) { - struct nfnl_exp *dst = (struct nfnl_exp *) _dst; - struct nfnl_exp *src = (struct nfnl_exp *) _src; - struct nl_addr *addr; + struct nfnl_exp *dst = (struct nfnl_exp *) _dst; + struct nfnl_exp *src = (struct nfnl_exp *) _src; + struct nl_addr *addr; - // Expectation - if (src->exp_expect.src) { - addr = nl_addr_clone(src->exp_expect.src); - if (!addr) - return -NLE_NOMEM; - dst->exp_expect.src = addr; - } + // Expectation + if (src->exp_expect.src) { + addr = nl_addr_clone(src->exp_expect.src); + if (!addr) + return -NLE_NOMEM; + dst->exp_expect.src = addr; + } - if (src->exp_expect.dst) { - addr = nl_addr_clone(src->exp_expect.dst); - if (!addr) - return -NLE_NOMEM; - dst->exp_expect.dst = addr; - } + if (src->exp_expect.dst) { + addr = nl_addr_clone(src->exp_expect.dst); + if (!addr) + return -NLE_NOMEM; + dst->exp_expect.dst = addr; + } - // Master CT - if (src->exp_master.src) { - addr = nl_addr_clone(src->exp_master.src); - if (!addr) - return -NLE_NOMEM; - dst->exp_master.src = addr; - } + // Master CT + if (src->exp_master.src) { + addr = nl_addr_clone(src->exp_master.src); + if (!addr) + return -NLE_NOMEM; + dst->exp_master.src = addr; + } - if (src->exp_master.dst) { - addr = nl_addr_clone(src->exp_master.dst); - if (!addr) - return -NLE_NOMEM; - dst->exp_master.dst = addr; - } + if (src->exp_master.dst) { + addr = nl_addr_clone(src->exp_master.dst); + if (!addr) + return -NLE_NOMEM; + dst->exp_master.dst = addr; + } - // Mask - if (src->exp_mask.src) { - addr = nl_addr_clone(src->exp_mask.src); - if (!addr) - return -NLE_NOMEM; - dst->exp_mask.src = addr; - } + // Mask + if (src->exp_mask.src) { + addr = nl_addr_clone(src->exp_mask.src); + if (!addr) + return -NLE_NOMEM; + dst->exp_mask.src = addr; + } - if (src->exp_mask.dst) { - addr = nl_addr_clone(src->exp_mask.dst); - if (!addr) - return -NLE_NOMEM; - dst->exp_mask.dst = addr; - } + if (src->exp_mask.dst) { + addr = nl_addr_clone(src->exp_mask.dst); + if (!addr) + return -NLE_NOMEM; + dst->exp_mask.dst = addr; + } // NAT - if (src->exp_nat.src) { - addr = nl_addr_clone(src->exp_nat.src); - if (!addr) - return -NLE_NOMEM; - dst->exp_nat.src = addr; - } + if (src->exp_nat.src) { + addr = nl_addr_clone(src->exp_nat.src); + if (!addr) + return -NLE_NOMEM; + dst->exp_nat.src = addr; + } - if (src->exp_nat.dst) { - addr = nl_addr_clone(src->exp_nat.dst); - if (!addr) - return -NLE_NOMEM; - dst->exp_nat.dst = addr; - } + if (src->exp_nat.dst) { + addr = nl_addr_clone(src->exp_nat.dst); + if (!addr) + return -NLE_NOMEM; + dst->exp_nat.dst = addr; + } - if (src->exp_fn) - dst->exp_fn = strdup(src->exp_fn); + if (src->exp_fn) + dst->exp_fn = strdup(src->exp_fn); - if (src->exp_helper_name) - dst->exp_helper_name = strdup(src->exp_helper_name); + if (src->exp_helper_name) + dst->exp_helper_name = strdup(src->exp_helper_name); return 0; } @@ -173,12 +173,12 @@ static void dump_icmp(struct nl_dump_params *p, struct nfnl_exp *exp, int tuple) { if (nfnl_exp_test_icmp(exp, tuple)) { - nl_dump(p, "icmp type %d ", nfnl_exp_get_icmp_type(exp, tuple)); + nl_dump(p, "icmp type %d ", nfnl_exp_get_icmp_type(exp, tuple)); - nl_dump(p, "code %d ", nfnl_exp_get_icmp_code(exp, tuple)); + nl_dump(p, "code %d ", nfnl_exp_get_icmp_code(exp, tuple)); - nl_dump(p, "id %d ", nfnl_exp_get_icmp_id(exp, tuple)); - } + nl_dump(p, "id %d ", nfnl_exp_get_icmp_id(exp, tuple)); + } } static void exp_dump_tuples(struct nfnl_exp *exp, struct nl_dump_params *p) @@ -186,38 +186,38 @@ static void exp_dump_tuples(struct nfnl_exp *exp, struct nl_dump_params *p) struct nl_addr *tuple_src, *tuple_dst; int tuple_sport, tuple_dport; int i = 0; - char buf[64]; + char buf[64]; for (i = NFNL_EXP_TUPLE_EXPECT; i < NFNL_EXP_TUPLE_MAX; i++) { - tuple_src = NULL; - tuple_dst = NULL; - tuple_sport = 0; - tuple_dport = 0; + tuple_src = NULL; + tuple_dst = NULL; + tuple_sport = 0; + tuple_dport = 0; - // Test needed for NAT case - if (nfnl_exp_test_src(exp, i)) - tuple_src = nfnl_exp_get_src(exp, i); - if (nfnl_exp_test_dst(exp, i)) - tuple_dst = nfnl_exp_get_dst(exp, i); + // Test needed for NAT case + if (nfnl_exp_test_src(exp, i)) + tuple_src = nfnl_exp_get_src(exp, i); + if (nfnl_exp_test_dst(exp, i)) + tuple_dst = nfnl_exp_get_dst(exp, i); // Don't have tests for individual ports/types/codes/ids, - if (nfnl_exp_test_l4protonum(exp, i)) { - nl_dump(p, "%s ", - nl_ip_proto2str(nfnl_exp_get_l4protonum(exp, i), buf, sizeof(buf))); - } + if (nfnl_exp_test_l4protonum(exp, i)) { + nl_dump(p, "%s ", + nl_ip_proto2str(nfnl_exp_get_l4protonum(exp, i), buf, sizeof(buf))); + } - if (nfnl_exp_test_ports(exp, i)) { - tuple_sport = nfnl_exp_get_src_port(exp, i); - tuple_dport = nfnl_exp_get_dst_port(exp, i); - } + if (nfnl_exp_test_ports(exp, i)) { + tuple_sport = nfnl_exp_get_src_port(exp, i); + tuple_dport = nfnl_exp_get_dst_port(exp, i); + } - dump_addr(p, tuple_src, tuple_sport); - dump_addr(p, tuple_dst, tuple_dport); - dump_icmp(p, exp, 0); - } + dump_addr(p, tuple_src, tuple_sport); + dump_addr(p, tuple_dst, tuple_dport); + dump_icmp(p, exp, 0); + } - if (nfnl_exp_test_nat_dir(exp)) - nl_dump(p, "nat dir %s ", exp->exp_nat_dir); + if (nfnl_exp_test_nat_dir(exp)) + nl_dump(p, "nat dir %s ", exp->exp_nat_dir); } @@ -251,19 +251,19 @@ static void exp_dump_details(struct nl_object *a, struct nl_dump_params *p) nl_msec2str(timeout_ms, buf, sizeof(buf))); } - if (nfnl_exp_test_helper_name(exp)) - nl_dump(p, "helper %s ", exp->exp_helper_name); + if (nfnl_exp_test_helper_name(exp)) + nl_dump(p, "helper %s ", exp->exp_helper_name); - if (nfnl_exp_test_fn(exp)) - nl_dump(p, "fn %s ", exp->exp_fn); + if (nfnl_exp_test_fn(exp)) + nl_dump(p, "fn %s ", exp->exp_fn); - if (nfnl_exp_test_class(exp)) - nl_dump(p, "class %u ", nfnl_exp_get_class(exp)); + if (nfnl_exp_test_class(exp)) + nl_dump(p, "class %u ", nfnl_exp_get_class(exp)); - if (nfnl_exp_test_zone(exp)) - nl_dump(p, "zone %u ", nfnl_exp_get_zone(exp)); + if (nfnl_exp_test_zone(exp)) + nl_dump(p, "zone %u ", nfnl_exp_get_zone(exp)); - if (nfnl_exp_test_flags(exp)) + if (nfnl_exp_test_flags(exp)) nl_dump(p, "<"); #define PRINT_FLAG(str) \ { nl_dump(p, "%s%s", fp++ ? "," : "", (str)); } @@ -283,26 +283,26 @@ static void exp_dump_details(struct nl_object *a, struct nl_dump_params *p) } static int exp_cmp_l4proto_ports (union nfnl_exp_protodata *a, union nfnl_exp_protodata *b) { - // Must return 0 for match, 1 for mismatch - int d = 0; - d = ( (a->port.src != b->port.src) || - (a->port.dst != b->port.dst) ); + // Must return 0 for match, 1 for mismatch + int d = 0; + d = ( (a->port.src != b->port.src) || + (a->port.dst != b->port.dst) ); - return d; + return d; } static int exp_cmp_l4proto_icmp (union nfnl_exp_protodata *a, union nfnl_exp_protodata *b) { // Must return 0 for match, 1 for mismatch - int d = 0; - d = ( (a->icmp.code != b->icmp.code) || - (a->icmp.type != b->icmp.type) || - (a->icmp.id != b->icmp.id) ); + int d = 0; + d = ( (a->icmp.code != b->icmp.code) || + (a->icmp.type != b->icmp.type) || + (a->icmp.id != b->icmp.id) ); - return d; + return d; } static int exp_compare(struct nl_object *_a, struct nl_object *_b, - uint32_t attrs, int flags) + uint32_t attrs, int flags) { struct nfnl_exp *a = (struct nfnl_exp *) _a; struct nfnl_exp *b = (struct nfnl_exp *) _b; @@ -312,48 +312,48 @@ static int exp_compare(struct nl_object *_a, struct nl_object *_b, #define EXP_DIFF_VAL(ATTR, FIELD) EXP_DIFF(ATTR, a->FIELD != b->FIELD) #define EXP_DIFF_STRING(ATTR, FIELD) EXP_DIFF(ATTR, (strcmp(a->FIELD, b->FIELD) != 0)) #define EXP_DIFF_ADDR(ATTR, FIELD) \ - ((flags & LOOSE_COMPARISON) \ - ? EXP_DIFF(ATTR, nl_addr_cmp_prefix(a->FIELD, b->FIELD)) \ - : EXP_DIFF(ATTR, nl_addr_cmp(a->FIELD, b->FIELD))) + ((flags & LOOSE_COMPARISON) \ + ? EXP_DIFF(ATTR, nl_addr_cmp_prefix(a->FIELD, b->FIELD)) \ + : EXP_DIFF(ATTR, nl_addr_cmp(a->FIELD, b->FIELD))) #define EXP_DIFF_L4PROTO_PORTS(ATTR, FIELD) \ - EXP_DIFF(ATTR, exp_cmp_l4proto_ports(&(a->FIELD), &(b->FIELD))) + EXP_DIFF(ATTR, exp_cmp_l4proto_ports(&(a->FIELD), &(b->FIELD))) #define EXP_DIFF_L4PROTO_ICMP(ATTR, FIELD) \ - EXP_DIFF(ATTR, exp_cmp_l4proto_icmp(&(a->FIELD), &(b->FIELD))) + EXP_DIFF(ATTR, exp_cmp_l4proto_icmp(&(a->FIELD), &(b->FIELD))) - diff |= EXP_DIFF_VAL(FAMILY, exp_family); - diff |= EXP_DIFF_VAL(TIMEOUT, exp_timeout); - diff |= EXP_DIFF_VAL(ID, exp_id); - diff |= EXP_DIFF_VAL(ZONE, exp_zone); - diff |= EXP_DIFF_VAL(CLASS, exp_class); - diff |= EXP_DIFF_VAL(FLAGS, exp_flags); - diff |= EXP_DIFF_VAL(NAT_DIR, exp_nat_dir); + diff |= EXP_DIFF_VAL(FAMILY, exp_family); + diff |= EXP_DIFF_VAL(TIMEOUT, exp_timeout); + diff |= EXP_DIFF_VAL(ID, exp_id); + diff |= EXP_DIFF_VAL(ZONE, exp_zone); + diff |= EXP_DIFF_VAL(CLASS, exp_class); + diff |= EXP_DIFF_VAL(FLAGS, exp_flags); + diff |= EXP_DIFF_VAL(NAT_DIR, exp_nat_dir); - diff |= EXP_DIFF_STRING(FN, exp_fn); - diff |= EXP_DIFF_STRING(HELPER_NAME, exp_helper_name); + diff |= EXP_DIFF_STRING(FN, exp_fn); + diff |= EXP_DIFF_STRING(HELPER_NAME, exp_helper_name); - diff |= EXP_DIFF_ADDR(EXPECT_IP_SRC, exp_expect.src); - diff |= EXP_DIFF_ADDR(EXPECT_IP_DST, exp_expect.dst); - diff |= EXP_DIFF_VAL(EXPECT_L4PROTO_NUM, exp_expect.proto.l4protonum); - diff |= EXP_DIFF_L4PROTO_PORTS(EXPECT_L4PROTO_PORTS, exp_expect.proto.l4protodata); - diff |= EXP_DIFF_L4PROTO_ICMP(EXPECT_L4PROTO_ICMP, exp_expect.proto.l4protodata); + diff |= EXP_DIFF_ADDR(EXPECT_IP_SRC, exp_expect.src); + diff |= EXP_DIFF_ADDR(EXPECT_IP_DST, exp_expect.dst); + diff |= EXP_DIFF_VAL(EXPECT_L4PROTO_NUM, exp_expect.proto.l4protonum); + diff |= EXP_DIFF_L4PROTO_PORTS(EXPECT_L4PROTO_PORTS, exp_expect.proto.l4protodata); + diff |= EXP_DIFF_L4PROTO_ICMP(EXPECT_L4PROTO_ICMP, exp_expect.proto.l4protodata); - diff |= EXP_DIFF_ADDR(MASTER_IP_SRC, exp_master.src); - diff |= EXP_DIFF_ADDR(MASTER_IP_DST, exp_master.dst); - diff |= EXP_DIFF_VAL(MASTER_L4PROTO_NUM, exp_master.proto.l4protonum); - diff |= EXP_DIFF_L4PROTO_PORTS(MASTER_L4PROTO_PORTS, exp_master.proto.l4protodata); - diff |= EXP_DIFF_L4PROTO_ICMP(MASTER_L4PROTO_ICMP, exp_master.proto.l4protodata); + diff |= EXP_DIFF_ADDR(MASTER_IP_SRC, exp_master.src); + diff |= EXP_DIFF_ADDR(MASTER_IP_DST, exp_master.dst); + diff |= EXP_DIFF_VAL(MASTER_L4PROTO_NUM, exp_master.proto.l4protonum); + diff |= EXP_DIFF_L4PROTO_PORTS(MASTER_L4PROTO_PORTS, exp_master.proto.l4protodata); + diff |= EXP_DIFF_L4PROTO_ICMP(MASTER_L4PROTO_ICMP, exp_master.proto.l4protodata); - diff |= EXP_DIFF_ADDR(MASK_IP_SRC, exp_mask.src); - diff |= EXP_DIFF_ADDR(MASK_IP_DST, exp_mask.dst); - diff |= EXP_DIFF_VAL(MASK_L4PROTO_NUM, exp_mask.proto.l4protonum); - diff |= EXP_DIFF_L4PROTO_PORTS(MASK_L4PROTO_PORTS, exp_mask.proto.l4protodata); - diff |= EXP_DIFF_L4PROTO_ICMP(MASK_L4PROTO_ICMP, exp_mask.proto.l4protodata); + diff |= EXP_DIFF_ADDR(MASK_IP_SRC, exp_mask.src); + diff |= EXP_DIFF_ADDR(MASK_IP_DST, exp_mask.dst); + diff |= EXP_DIFF_VAL(MASK_L4PROTO_NUM, exp_mask.proto.l4protonum); + diff |= EXP_DIFF_L4PROTO_PORTS(MASK_L4PROTO_PORTS, exp_mask.proto.l4protodata); + diff |= EXP_DIFF_L4PROTO_ICMP(MASK_L4PROTO_ICMP, exp_mask.proto.l4protodata); - diff |= EXP_DIFF_ADDR(NAT_IP_SRC, exp_nat.src); - diff |= EXP_DIFF_ADDR(NAT_IP_DST, exp_nat.dst); - diff |= EXP_DIFF_VAL(NAT_L4PROTO_NUM, exp_nat.proto.l4protonum); - diff |= EXP_DIFF_L4PROTO_PORTS(NAT_L4PROTO_PORTS, exp_nat.proto.l4protodata); - diff |= EXP_DIFF_L4PROTO_ICMP(NAT_L4PROTO_ICMP, exp_nat.proto.l4protodata); + diff |= EXP_DIFF_ADDR(NAT_IP_SRC, exp_nat.src); + diff |= EXP_DIFF_ADDR(NAT_IP_DST, exp_nat.dst); + diff |= EXP_DIFF_VAL(NAT_L4PROTO_NUM, exp_nat.proto.l4protonum); + diff |= EXP_DIFF_L4PROTO_PORTS(NAT_L4PROTO_PORTS, exp_nat.proto.l4protodata); + diff |= EXP_DIFF_L4PROTO_ICMP(NAT_L4PROTO_ICMP, exp_nat.proto.l4protodata); #undef EXP_DIFF #undef EXP_DIFF_VAL @@ -362,40 +362,40 @@ static int exp_compare(struct nl_object *_a, struct nl_object *_b, #undef EXP_DIFF_L4PROTO_PORTS #undef EXP_DIFF_L4PROTO_ICMP - return diff; + return diff; } // CLI arguments? static const struct trans_tbl exp_attrs[] = { - __ADD(EXP_ATTR_FAMILY, family) - __ADD(EXP_ATTR_TIMEOUT, timeout) - __ADD(EXP_ATTR_ID, id) - __ADD(EXP_ATTR_HELPER_NAME, helpername) - __ADD(EXP_ATTR_ZONE, zone) - __ADD(EXP_ATTR_CLASS, class) - __ADD(EXP_ATTR_FLAGS, flags) - __ADD(EXP_ATTR_FN, function) - __ADD(EXP_ATTR_EXPECT_IP_SRC, expectipsrc) - __ADD(EXP_ATTR_EXPECT_IP_DST, expectipdst) - __ADD(EXP_ATTR_EXPECT_L4PROTO_NUM, expectprotonum) - __ADD(EXP_ATTR_EXPECT_L4PROTO_PORTS, expectports) - __ADD(EXP_ATTR_EXPECT_L4PROTO_ICMP , expecticmp) - __ADD(EXP_ATTR_MASTER_IP_SRC, masteripsrc) - __ADD(EXP_ATTR_MASTER_IP_DST, masteripdst) - __ADD(EXP_ATTR_MASTER_L4PROTO_NUM, masterprotonum) - __ADD(EXP_ATTR_MASTER_L4PROTO_PORTS, masterports) - __ADD(EXP_ATTR_MASTER_L4PROTO_ICMP , mastericmp) - __ADD(EXP_ATTR_MASK_IP_SRC, maskipsrc) - __ADD(EXP_ATTR_MASK_IP_DST, maskipdst) - __ADD(EXP_ATTR_MASK_L4PROTO_NUM, maskprotonum) - __ADD(EXP_ATTR_MASK_L4PROTO_PORTS, maskports) - __ADD(EXP_ATTR_MASK_L4PROTO_ICMP , maskicmp) - __ADD(EXP_ATTR_NAT_IP_SRC, natipsrc) - __ADD(EXP_ATTR_NAT_IP_DST, natipdst) - __ADD(EXP_ATTR_NAT_L4PROTO_NUM, natprotonum) - __ADD(EXP_ATTR_NAT_L4PROTO_PORTS, natports) - __ADD(EXP_ATTR_NAT_L4PROTO_ICMP, naticmp) - __ADD(EXP_ATTR_NAT_DIR, natdir) + __ADD(EXP_ATTR_FAMILY, family) + __ADD(EXP_ATTR_TIMEOUT, timeout) + __ADD(EXP_ATTR_ID, id) + __ADD(EXP_ATTR_HELPER_NAME, helpername) + __ADD(EXP_ATTR_ZONE, zone) + __ADD(EXP_ATTR_CLASS, class) + __ADD(EXP_ATTR_FLAGS, flags) + __ADD(EXP_ATTR_FN, function) + __ADD(EXP_ATTR_EXPECT_IP_SRC, expectipsrc) + __ADD(EXP_ATTR_EXPECT_IP_DST, expectipdst) + __ADD(EXP_ATTR_EXPECT_L4PROTO_NUM, expectprotonum) + __ADD(EXP_ATTR_EXPECT_L4PROTO_PORTS, expectports) + __ADD(EXP_ATTR_EXPECT_L4PROTO_ICMP, expecticmp) + __ADD(EXP_ATTR_MASTER_IP_SRC, masteripsrc) + __ADD(EXP_ATTR_MASTER_IP_DST, masteripdst) + __ADD(EXP_ATTR_MASTER_L4PROTO_NUM, masterprotonum) + __ADD(EXP_ATTR_MASTER_L4PROTO_PORTS, masterports) + __ADD(EXP_ATTR_MASTER_L4PROTO_ICMP, mastericmp) + __ADD(EXP_ATTR_MASK_IP_SRC, maskipsrc) + __ADD(EXP_ATTR_MASK_IP_DST, maskipdst) + __ADD(EXP_ATTR_MASK_L4PROTO_NUM, maskprotonum) + __ADD(EXP_ATTR_MASK_L4PROTO_PORTS, maskports) + __ADD(EXP_ATTR_MASK_L4PROTO_ICMP, maskicmp) + __ADD(EXP_ATTR_NAT_IP_SRC, natipsrc) + __ADD(EXP_ATTR_NAT_IP_DST, natipdst) + __ADD(EXP_ATTR_NAT_L4PROTO_NUM, natprotonum) + __ADD(EXP_ATTR_NAT_L4PROTO_PORTS, natports) + __ADD(EXP_ATTR_NAT_L4PROTO_ICMP, naticmp) + __ADD(EXP_ATTR_NAT_DIR, natdir) }; static char *exp_attrs2str(int attrs, char *buf, size_t len) @@ -452,7 +452,7 @@ void nfnl_exp_set_flags(struct nfnl_exp *exp, uint32_t flags) int nfnl_exp_test_flags(const struct nfnl_exp *exp) { - return !!(exp->ce_mask & EXP_ATTR_FLAGS); + return !!(exp->ce_mask & EXP_ATTR_FLAGS); } void nfnl_exp_unset_flags(struct nfnl_exp *exp, uint32_t flags) @@ -515,148 +515,146 @@ uint32_t nfnl_exp_get_id(const struct nfnl_exp *exp) return exp->exp_id; } -int nfnl_exp_set_helper_name(struct nfnl_exp *exp, void *name) +int nfnl_exp_set_helper_name(struct nfnl_exp *exp, void *name) { - free(exp->exp_helper_name); - exp->exp_helper_name = strdup(name); - if (!exp->exp_helper_name) - return -NLE_NOMEM; + free(exp->exp_helper_name); + exp->exp_helper_name = strdup(name); + if (!exp->exp_helper_name) + return -NLE_NOMEM; - exp->ce_mask |= EXP_ATTR_HELPER_NAME; - return 0; + exp->ce_mask |= EXP_ATTR_HELPER_NAME; + return 0; } int nfnl_exp_test_helper_name(const struct nfnl_exp *exp) { - return !!(exp->ce_mask & EXP_ATTR_HELPER_NAME); + return !!(exp->ce_mask & EXP_ATTR_HELPER_NAME); } const char * nfnl_exp_get_helper_name(const struct nfnl_exp *exp) { - return exp->exp_helper_name; + return exp->exp_helper_name; } void nfnl_exp_set_zone(struct nfnl_exp *exp, uint16_t zone) { - exp->exp_zone = zone; - exp->ce_mask |= EXP_ATTR_ZONE; + exp->exp_zone = zone; + exp->ce_mask |= EXP_ATTR_ZONE; } int nfnl_exp_test_zone(const struct nfnl_exp *exp) { - return !!(exp->ce_mask & EXP_ATTR_ZONE); + return !!(exp->ce_mask & EXP_ATTR_ZONE); } uint16_t nfnl_exp_get_zone(const struct nfnl_exp *exp) { - return exp->exp_zone; + return exp->exp_zone; } void nfnl_exp_set_class(struct nfnl_exp *exp, uint32_t class) { - exp->exp_class = class; - exp->ce_mask |= EXP_ATTR_CLASS; + exp->exp_class = class; + exp->ce_mask |= EXP_ATTR_CLASS; } int nfnl_exp_test_class(const struct nfnl_exp *exp) { - return !!(exp->ce_mask & EXP_ATTR_CLASS); + return !!(exp->ce_mask & EXP_ATTR_CLASS); } uint32_t nfnl_exp_get_class(const struct nfnl_exp *exp) { - return exp->exp_class; + return exp->exp_class; } int nfnl_exp_set_fn(struct nfnl_exp *exp, void *fn) { - free(exp->exp_fn); - exp->exp_fn = strdup(fn); - if (!exp->exp_fn) - return -NLE_NOMEM; + free(exp->exp_fn); + exp->exp_fn = strdup(fn); + if (!exp->exp_fn) + return -NLE_NOMEM; - exp->ce_mask |= EXP_ATTR_FN; - return 0; + exp->ce_mask |= EXP_ATTR_FN; + return 0; } int nfnl_exp_test_fn(const struct nfnl_exp *exp) { - return !!(exp->ce_mask & EXP_ATTR_FN); + return !!(exp->ce_mask & EXP_ATTR_FN); } const char * nfnl_exp_get_fn(const struct nfnl_exp *exp) { - return exp->exp_fn; + return exp->exp_fn; } void nfnl_exp_set_nat_dir(struct nfnl_exp *exp, uint8_t nat_dir) { - exp->exp_nat_dir = nat_dir; - exp->ce_mask |= EXP_ATTR_NAT_DIR; + exp->exp_nat_dir = nat_dir; + exp->ce_mask |= EXP_ATTR_NAT_DIR; } int nfnl_exp_test_nat_dir(const struct nfnl_exp *exp) { - return !!(exp->ce_mask & EXP_ATTR_NAT_DIR); + return !!(exp->ce_mask & EXP_ATTR_NAT_DIR); } uint8_t nfnl_exp_get_nat_dir(const struct nfnl_exp *exp) { - return exp->exp_nat_dir; + return exp->exp_nat_dir; } #define EXP_GET_TUPLE(e, t) \ - (t == NFNL_EXP_TUPLE_MASTER) ? \ - &(e->exp_master) : \ - (t == NFNL_EXP_TUPLE_MASK) ? \ - &(e->exp_mask) : \ - (t == NFNL_EXP_TUPLE_NAT) ? \ - &(e->exp_nat) : &(exp->exp_expect) + (t == NFNL_EXP_TUPLE_MASTER) ? \ + &(e->exp_master) : \ + (t == NFNL_EXP_TUPLE_MASK) ? \ + &(e->exp_mask) : \ + (t == NFNL_EXP_TUPLE_NAT) ? \ + &(e->exp_nat) : &(exp->exp_expect) static int exp_get_src_attr(int tuple) { - int attr = 0; + int attr = 0; - switch (tuple) { - case NFNL_EXP_TUPLE_MASTER: - attr = EXP_ATTR_MASTER_IP_SRC; - break; - case NFNL_EXP_TUPLE_MASK: - attr = EXP_ATTR_MASK_IP_SRC; - break; - case NFNL_EXP_TUPLE_NAT: - attr = EXP_ATTR_NAT_IP_SRC; - break; - case NFNL_EXP_TUPLE_EXPECT: - default : - attr = EXP_ATTR_EXPECT_IP_SRC; - break; - } + switch (tuple) { + case NFNL_EXP_TUPLE_MASTER: + attr = EXP_ATTR_MASTER_IP_SRC; + break; + case NFNL_EXP_TUPLE_MASK: + attr = EXP_ATTR_MASK_IP_SRC; + break; + case NFNL_EXP_TUPLE_NAT: + attr = EXP_ATTR_NAT_IP_SRC; + break; + case NFNL_EXP_TUPLE_EXPECT: + default : + attr = EXP_ATTR_EXPECT_IP_SRC; + } - return attr; + return attr; } static int exp_get_dst_attr(int tuple) { - int attr = 0; + int attr = 0; - switch (tuple) { - case NFNL_EXP_TUPLE_MASTER: - attr = EXP_ATTR_MASTER_IP_DST; - break; - case NFNL_EXP_TUPLE_MASK: - attr = EXP_ATTR_MASK_IP_DST; - break; - case NFNL_EXP_TUPLE_NAT: - attr = EXP_ATTR_NAT_IP_DST; - break; - case NFNL_EXP_TUPLE_EXPECT: - default : - attr = EXP_ATTR_EXPECT_IP_DST; - break; - } + switch (tuple) { + case NFNL_EXP_TUPLE_MASTER: + attr = EXP_ATTR_MASTER_IP_DST; + break; + case NFNL_EXP_TUPLE_MASK: + attr = EXP_ATTR_MASK_IP_DST; + break; + case NFNL_EXP_TUPLE_NAT: + attr = EXP_ATTR_NAT_IP_DST; + break; + case NFNL_EXP_TUPLE_EXPECT: + default : + attr = EXP_ATTR_EXPECT_IP_DST; + } - return attr; + return attr; } @@ -688,27 +686,26 @@ int nfnl_exp_set_src(struct nfnl_exp *exp, int tuple, struct nl_addr *addr) int nfnl_exp_set_dst(struct nfnl_exp *exp, int tuple, struct nl_addr *addr) { - struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); + struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); - return exp_set_addr(exp, addr, exp_get_dst_attr(tuple), &dir->dst); + return exp_set_addr(exp, addr, exp_get_dst_attr(tuple), &dir->dst); } int nfnl_exp_test_src(const struct nfnl_exp *exp, int tuple) { - return !!(exp->ce_mask & exp_get_src_attr(tuple)); + return !!(exp->ce_mask & exp_get_src_attr(tuple)); } int nfnl_exp_test_dst(const struct nfnl_exp *exp, int tuple) { - - return !!(exp->ce_mask & exp_get_dst_attr(tuple)); + return !!(exp->ce_mask & exp_get_dst_attr(tuple)); } struct nl_addr *nfnl_exp_get_src(const struct nfnl_exp *exp, int tuple) { - const struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); + const struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); - if (!(exp->ce_mask & exp_get_src_attr(tuple))) + if (!(exp->ce_mask & exp_get_src_attr(tuple))) return NULL; return dir->src; } @@ -724,67 +721,65 @@ struct nl_addr *nfnl_exp_get_dst(const struct nfnl_exp *exp, int tuple) static int exp_get_l4protonum_attr(int tuple) { - int attr = 0; + int attr = 0; - switch (tuple) { - case NFNL_EXP_TUPLE_MASTER: - attr = EXP_ATTR_MASTER_L4PROTO_NUM; - break; - case NFNL_EXP_TUPLE_MASK: - attr = EXP_ATTR_MASK_L4PROTO_NUM; - break; - case NFNL_EXP_TUPLE_NAT: - attr = EXP_ATTR_NAT_L4PROTO_NUM; - break; - case NFNL_EXP_TUPLE_EXPECT: - default : - attr = EXP_ATTR_EXPECT_L4PROTO_NUM; - break; - } + switch (tuple) { + case NFNL_EXP_TUPLE_MASTER: + attr = EXP_ATTR_MASTER_L4PROTO_NUM; + break; + case NFNL_EXP_TUPLE_MASK: + attr = EXP_ATTR_MASK_L4PROTO_NUM; + break; + case NFNL_EXP_TUPLE_NAT: + attr = EXP_ATTR_NAT_L4PROTO_NUM; + break; + case NFNL_EXP_TUPLE_EXPECT: + default : + attr = EXP_ATTR_EXPECT_L4PROTO_NUM; + } - return attr; + return attr; } void nfnl_exp_set_l4protonum(struct nfnl_exp *exp, int tuple, uint8_t l4protonum) { - struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); + struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); - dir->proto.l4protonum = l4protonum; - exp->ce_mask |= exp_get_l4protonum_attr(tuple); + dir->proto.l4protonum = l4protonum; + exp->ce_mask |= exp_get_l4protonum_attr(tuple); } int nfnl_exp_test_l4protonum(const struct nfnl_exp *exp, int tuple) { - return !!(exp->ce_mask & exp_get_l4protonum_attr(tuple)); + return !!(exp->ce_mask & exp_get_l4protonum_attr(tuple)); } uint8_t nfnl_exp_get_l4protonum(const struct nfnl_exp *exp, int tuple) { - const struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); - return dir->proto.l4protonum; + const struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); + return dir->proto.l4protonum; } static int exp_get_l4ports_attr(int tuple) { - int attr = 0; + int attr = 0; - switch (tuple) { - case NFNL_EXP_TUPLE_MASTER: - attr = EXP_ATTR_MASTER_L4PROTO_PORTS; - break; - case NFNL_EXP_TUPLE_MASK: - attr = EXP_ATTR_MASK_L4PROTO_PORTS; - break; - case NFNL_EXP_TUPLE_NAT: - attr = EXP_ATTR_NAT_L4PROTO_PORTS; - break; - case NFNL_EXP_TUPLE_EXPECT: - default : - attr = EXP_ATTR_EXPECT_L4PROTO_PORTS; - break; - } + switch (tuple) { + case NFNL_EXP_TUPLE_MASTER: + attr = EXP_ATTR_MASTER_L4PROTO_PORTS; + break; + case NFNL_EXP_TUPLE_MASK: + attr = EXP_ATTR_MASK_L4PROTO_PORTS; + break; + case NFNL_EXP_TUPLE_NAT: + attr = EXP_ATTR_NAT_L4PROTO_PORTS; + break; + case NFNL_EXP_TUPLE_EXPECT: + default : + attr = EXP_ATTR_EXPECT_L4PROTO_PORTS; + } - return attr; + return attr; } void nfnl_exp_set_ports(struct nfnl_exp *exp, int tuple, uint16_t srcport, uint16_t dstport) @@ -810,32 +805,31 @@ uint16_t nfnl_exp_get_src_port(const struct nfnl_exp *exp, int tuple) uint16_t nfnl_exp_get_dst_port(const struct nfnl_exp *exp, int tuple) { - const struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); + const struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); return dir->proto.l4protodata.port.dst; } static int exp_get_l4icmp_attr(int tuple) { - int attr = 0; + int attr = 0; - switch (tuple) { - case NFNL_EXP_TUPLE_MASTER: - attr = EXP_ATTR_MASTER_L4PROTO_ICMP; - break; - case NFNL_EXP_TUPLE_MASK: - attr = EXP_ATTR_MASK_L4PROTO_ICMP; - break; - case NFNL_EXP_TUPLE_NAT: - attr = EXP_ATTR_NAT_L4PROTO_ICMP; - break; - case NFNL_EXP_TUPLE_EXPECT: - default : - attr = EXP_ATTR_EXPECT_L4PROTO_ICMP; - break; - } + switch (tuple) { + case NFNL_EXP_TUPLE_MASTER: + attr = EXP_ATTR_MASTER_L4PROTO_ICMP; + break; + case NFNL_EXP_TUPLE_MASK: + attr = EXP_ATTR_MASK_L4PROTO_ICMP; + break; + case NFNL_EXP_TUPLE_NAT: + attr = EXP_ATTR_NAT_L4PROTO_ICMP; + break; + case NFNL_EXP_TUPLE_EXPECT: + default : + attr = EXP_ATTR_EXPECT_L4PROTO_ICMP; + } - return attr; + return attr; } void nfnl_exp_set_icmp(struct nfnl_exp *exp, int tuple, uint16_t id, uint8_t type, uint8_t code) @@ -844,7 +838,7 @@ void nfnl_exp_set_icmp(struct nfnl_exp *exp, int tuple, uint16_t id, uint8_t typ dir->proto.l4protodata.icmp.id = id; dir->proto.l4protodata.icmp.type = type; - dir->proto.l4protodata.icmp.code = code; + dir->proto.l4protodata.icmp.code = code; exp->ce_mask |= exp_get_l4icmp_attr(tuple); } @@ -864,14 +858,14 @@ uint16_t nfnl_exp_get_icmp_id(const struct nfnl_exp *exp, int tuple) uint8_t nfnl_exp_get_icmp_type(const struct nfnl_exp *exp, int tuple) { - const struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); + const struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); return dir->proto.l4protodata.icmp.type; } uint8_t nfnl_exp_get_icmp_code(const struct nfnl_exp *exp, int tuple) { - const struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); + const struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); return dir->proto.l4protodata.icmp.code; } @@ -879,15 +873,15 @@ uint8_t nfnl_exp_get_icmp_code(const struct nfnl_exp *exp, int tuple) /** @} */ struct nl_object_ops exp_obj_ops = { - .oo_name = "netfilter/exp", - .oo_size = sizeof(struct nfnl_exp), + .oo_name = "netfilter/exp", + .oo_size = sizeof(struct nfnl_exp), .oo_free_data = exp_free_data, - .oo_clone = exp_clone, + .oo_clone = exp_clone, .oo_dump = { - [NL_DUMP_LINE] = exp_dump_line, - [NL_DUMP_DETAILS] = exp_dump_details, + [NL_DUMP_LINE] = exp_dump_line, + [NL_DUMP_DETAILS] = exp_dump_details, }, - .oo_compare = exp_compare, + .oo_compare = exp_compare, .oo_attrs2str = exp_attrs2str, }; diff --git a/src/lib/exp.c b/src/lib/exp.c index 7e0a017..a7a74f5 100644 --- a/src/lib/exp.c +++ b/src/lib/exp.c @@ -62,36 +62,36 @@ void nl_cli_exp_parse_id(struct nfnl_exp *exp, char *arg) void nl_cli_exp_parse_helper_name(struct nfnl_exp *exp, char *arg) { - nfnl_exp_set_helper_name(exp, arg); + nfnl_exp_set_helper_name(exp, arg); } void nl_cli_exp_parse_zone(struct nfnl_exp *exp, char *arg) { - uint32_t zone = nl_cli_parse_u32(arg); - nfnl_exp_set_zone(exp, zone); + uint32_t zone = nl_cli_parse_u32(arg); + nfnl_exp_set_zone(exp, zone); } void nl_cli_exp_parse_flags(struct nfnl_exp *exp, char *arg) { - uint32_t flags = nl_cli_parse_u32(arg); - nfnl_exp_set_flags(exp, flags); + uint32_t flags = nl_cli_parse_u32(arg); + nfnl_exp_set_flags(exp, flags); } void nl_cli_exp_parse_class(struct nfnl_exp *exp, char *arg) { - uint32_t class = nl_cli_parse_u32(arg); - nfnl_exp_set_class(exp, class); + uint32_t class = nl_cli_parse_u32(arg); + nfnl_exp_set_class(exp, class); } void nl_cli_exp_parse_nat_dir(struct nfnl_exp *exp, char *arg) { - uint32_t nat_dir = nl_cli_parse_u32(arg); - nfnl_exp_set_nat_dir(exp, nat_dir); + uint32_t nat_dir = nl_cli_parse_u32(arg); + nfnl_exp_set_nat_dir(exp, nat_dir); } void nl_cli_exp_parse_fn(struct nfnl_exp *exp, char *arg) { - nfnl_exp_set_fn(exp, arg); + nfnl_exp_set_fn(exp, arg); } void nl_cli_exp_parse_src(struct nfnl_exp *exp, int tuple, char *arg) @@ -114,20 +114,20 @@ void nl_cli_exp_parse_dst(struct nfnl_exp *exp, int tuple, char *arg) void nl_cli_exp_parse_l4protonum(struct nfnl_exp *exp, int tuple, char *arg) { - int l4protonum; + int l4protonum; - if ((l4protonum = nl_str2ip_proto(arg)) < 0) - nl_cli_fatal(l4protonum, - "Unable to nl_cli_exp_parse protocol \"%s\": %s", - arg, nl_geterror(l4protonum)); + if ((l4protonum = nl_str2ip_proto(arg)) < 0) + nl_cli_fatal(l4protonum, + "Unable to nl_cli_exp_parse protocol \"%s\": %s", + arg, nl_geterror(l4protonum)); - nfnl_exp_set_l4protonum(exp, tuple, l4protonum); + nfnl_exp_set_l4protonum(exp, tuple, l4protonum); } void nl_cli_exp_parse_src_port(struct nfnl_exp *exp, int tuple, char *arg) { uint32_t sport = nl_cli_parse_u32(arg); - uint16_t dport = nfnl_exp_get_dst_port(exp, tuple); + uint16_t dport = nfnl_exp_get_dst_port(exp, tuple); nfnl_exp_set_ports(exp, tuple, sport, dport); } @@ -140,26 +140,26 @@ void nl_cli_exp_parse_dst_port(struct nfnl_exp *exp, int tuple, char *arg) void nl_cli_exp_parse_icmp_id(struct nfnl_exp *exp, int tuple, char *arg) { - uint32_t id = nl_cli_parse_u32(arg); - uint8_t type = nfnl_exp_get_icmp_type(exp, tuple); - uint8_t code = nfnl_exp_get_icmp_code(exp, tuple); - nfnl_exp_set_icmp(exp, tuple, id, type, code); + uint32_t id = nl_cli_parse_u32(arg); + uint8_t type = nfnl_exp_get_icmp_type(exp, tuple); + uint8_t code = nfnl_exp_get_icmp_code(exp, tuple); + nfnl_exp_set_icmp(exp, tuple, id, type, code); } void nl_cli_exp_parse_icmp_type(struct nfnl_exp *exp, int tuple, char *arg) { - uint32_t type = nl_cli_parse_u32(arg); - uint16_t id = nfnl_exp_get_icmp_id(exp, tuple); - uint8_t code = nfnl_exp_get_icmp_code(exp, tuple); - nfnl_exp_set_icmp(exp, tuple, id, type, code); + uint32_t type = nl_cli_parse_u32(arg); + uint16_t id = nfnl_exp_get_icmp_id(exp, tuple); + uint8_t code = nfnl_exp_get_icmp_code(exp, tuple); + nfnl_exp_set_icmp(exp, tuple, id, type, code); } void nl_cli_exp_parse_icmp_code(struct nfnl_exp *exp, int tuple, char *arg) { - uint32_t code = nl_cli_parse_u32(arg); - uint16_t id = nfnl_exp_get_icmp_id(exp, tuple); - uint8_t type = nfnl_exp_get_icmp_type(exp, tuple); - nfnl_exp_set_icmp(exp, tuple, id, type, code); + uint32_t code = nl_cli_parse_u32(arg); + uint16_t id = nfnl_exp_get_icmp_id(exp, tuple); + uint8_t type = nfnl_exp_get_icmp_type(exp, tuple); + nfnl_exp_set_icmp(exp, tuple, id, type, code); } /** @} */ diff --git a/src/nf-exp-add.c b/src/nf-exp-add.c index 6b71897..f760ee5 100644 --- a/src/nf-exp-add.c +++ b/src/nf-exp-add.c @@ -24,31 +24,31 @@ static void print_usage(void) "Usage: nf-exp-list [OPTION]... [CONNTRACK ENTRY]\n" "\n" "Options\n" - " --replace Replace the address if it exists.\n" - " -q, --quiet Do not print informal notifications.\n" + " --replace Replace the address if it exists.\n" + " -q, --quiet Do not print informal notifications.\n" " -h, --help Show this help\n" " -v, --version Show versioning information\n" "\n" "Expectation Selection\n" " -i, --id=NUM Identifier\n" - " --expect-proto=PROTOCOL Expectation protocol\n" + " --expect-proto=PROTOCOL Expectation protocol\n" " --expect-src=ADDR Expectation source address\n" " --expect-sport=PORT Expectation source port\n" " --expect-dst=ADDR Expectation destination address\n" " --expect-dport=PORT Expectation destination port\n" - " --master-proto=PROTOCOL Master conntrack protocol\n" + " --master-proto=PROTOCOL Master conntrack protocol\n" " --master-src=ADDR Master conntrack source address\n" " --master-sport=PORT Master conntrack source port\n" " --master-dst=ADDR Master conntrack destination address\n" " --master-dport=PORT Master conntrack destination port\n" - " --mask-proto=PROTOCOL Mask protocol\n" - " --mask-src=ADDR Mask source address\n" - " --mask-sport=PORT Mask source port\n" - " --mask-dst=ADDR Mask destination address\n" - " --mask-dport=PORT Mask destination port\n" + " --mask-proto=PROTOCOL Mask protocol\n" + " --mask-src=ADDR Mask source address\n" + " --mask-sport=PORT Mask source port\n" + " --mask-dst=ADDR Mask destination address\n" + " --mask-dport=PORT Mask destination port\n" " -F, --family=FAMILY Address family\n" " --timeout=NUM Timeout value\n" - " --helper=STRING Helper Name\n" + " --helper=STRING Helper Name\n" " --flags Flags (Kernel 2.6.37)\n" ); exit(0); @@ -76,24 +76,24 @@ int main(int argc, char *argv[]) ARG_EXPECT_SPORT, ARG_EXPECT_DST, ARG_EXPECT_DPORT, - ARG_MASTER_PROTO, + ARG_MASTER_PROTO, ARG_MASTER_SRC, ARG_MASTER_SPORT, ARG_MASTER_DST, ARG_MASTER_DPORT, - ARG_MASK_PROTO, - ARG_MASK_SRC, - ARG_MASK_SPORT, - ARG_MASK_DST, - ARG_MASK_DPORT, + ARG_MASK_PROTO, + ARG_MASK_SRC, + ARG_MASK_SPORT, + ARG_MASK_DST, + ARG_MASK_DPORT, ARG_TIMEOUT, - ARG_HELPER_NAME, - ARG_REPLACE, + ARG_HELPER_NAME, + ARG_REPLACE, ARG_FLAGS, }; static struct option long_opts[] = { { "replace", 1, 0, ARG_REPLACE }, - { "quiet", 0, 0, 'q' }, + { "quiet", 0, 0, 'q' }, { "help", 0, 0, 'h' }, { "version", 0, 0, 'v' }, { "id", 1, 0, 'i' }, @@ -102,20 +102,20 @@ int main(int argc, char *argv[]) { "expect-sport", 1, 0, ARG_EXPECT_SPORT }, { "expect-dst", 1, 0, ARG_EXPECT_DST }, { "expect-dport", 1, 0, ARG_EXPECT_DPORT }, - { "master-proto", 1, 0, ARG_MASTER_PROTO }, + { "master-proto", 1, 0, ARG_MASTER_PROTO }, { "master-src", 1, 0, ARG_MASTER_SRC }, { "master-sport", 1, 0, ARG_MASTER_SPORT }, { "master-dst", 1, 0, ARG_MASTER_DST }, { "master-dport", 1, 0, ARG_MASTER_DPORT }, - { "mask-proto", 1, 0, ARG_MASK_PROTO }, - { "mask-src", 1, 0, ARG_MASK_SRC }, - { "mask-sport", 1, 0, ARG_MASK_SPORT }, - { "mask-dst", 1, 0, ARG_MASK_DST }, - { "mask-dport", 1, 0, ARG_MASK_DPORT }, + { "mask-proto", 1, 0, ARG_MASK_PROTO }, + { "mask-src", 1, 0, ARG_MASK_SRC }, + { "mask-sport", 1, 0, ARG_MASK_SPORT }, + { "mask-dst", 1, 0, ARG_MASK_DST }, + { "mask-dport", 1, 0, ARG_MASK_DPORT }, { "family", 1, 0, 'F' }, { "timeout", 1, 0, ARG_TIMEOUT }, { "helper", 1, 0, ARG_HELPER_NAME }, - { "flags", 1, 0, ARG_FLAGS}, + { "flags", 1, 0, ARG_FLAGS}, { 0, 0, 0, 0 } }; @@ -125,9 +125,9 @@ int main(int argc, char *argv[]) switch (c) { case '?': exit(NLE_INVAL); - case ARG_REPLACE: nlflags |= NLM_F_REPLACE; break; - case 'q': quiet = 1; break; - case '4': nfnl_exp_set_family(exp, AF_INET); break; + case ARG_REPLACE: nlflags |= NLM_F_REPLACE; break; + case 'q': quiet = 1; break; + case '4': nfnl_exp_set_family(exp, AF_INET); break; case '6': nfnl_exp_set_family(exp, AF_INET6); break; case 'h': print_usage(); break; case 'v': nl_cli_print_version(); break; @@ -137,19 +137,19 @@ int main(int argc, char *argv[]) case ARG_EXPECT_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; case ARG_EXPECT_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; case ARG_EXPECT_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; - case ARG_MASTER_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; + case ARG_MASTER_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; case ARG_MASTER_SRC: nl_cli_exp_parse_src(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; case ARG_MASTER_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; case ARG_MASTER_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; case ARG_MASTER_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; - case ARG_MASK_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_MASK, optarg); break; - case ARG_MASK_SRC: nl_cli_exp_parse_src(exp, NFNL_EXP_TUPLE_MASK, optarg); break; - case ARG_MASK_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_MASK, optarg); break; - case ARG_MASK_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_MASK, optarg); break; - case ARG_MASK_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_MASK, optarg); break; + case ARG_MASK_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_MASK, optarg); break; + case ARG_MASK_SRC: nl_cli_exp_parse_src(exp, NFNL_EXP_TUPLE_MASK, optarg); break; + case ARG_MASK_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_MASK, optarg); break; + case ARG_MASK_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_MASK, optarg); break; + case ARG_MASK_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_MASK, optarg); break; case 'F': nl_cli_exp_parse_family(exp, optarg); break; case ARG_TIMEOUT: nl_cli_exp_parse_timeout(exp, optarg); break; - case ARG_HELPER_NAME: nl_cli_exp_parse_helper_name(exp, optarg); break; + case ARG_HELPER_NAME: nl_cli_exp_parse_helper_name(exp, optarg); break; case ARG_FLAGS: nl_cli_exp_parse_flags(exp, optarg); break; } } @@ -157,15 +157,13 @@ int main(int argc, char *argv[]) sock = nl_cli_alloc_socket(); nl_cli_connect(sock, NETLINK_NETFILTER); - if ((err = nfnl_exp_add(sock, exp, nlflags)) < 0) - nl_cli_fatal(err, "Unable to add expectation: %s", - nl_geterror(err)); - - if (!quiet) { - printf("Added "); - nl_object_dump(OBJ_CAST(exp), ¶ms); - } + if ((err = nfnl_exp_add(sock, exp, nlflags)) < 0) + nl_cli_fatal(err, "Unable to add expectation: %s", nl_geterror(err)); + if (!quiet) { + printf("Added "); + nl_object_dump(OBJ_CAST(exp), ¶ms); + } return 0; } diff --git a/src/nf-exp-delete.c b/src/nf-exp-delete.c index 1253945..2ec45ae 100644 --- a/src/nf-exp-delete.c +++ b/src/nf-exp-delete.c @@ -23,31 +23,31 @@ static void print_usage(void) "Usage: nf-exp-list [OPTION]... [CONNTRACK ENTRY]\n" "\n" "Options\n" - " --replace Replace the address if it exists.\n" - " -q, --quiet Do not print informal notifications.\n" + " --replace Replace the address if it exists.\n" + " -q, --quiet Do not print informal notifications.\n" " -h, --help Show this help\n" " -v, --version Show versioning information\n" "\n" "Expectation Selection\n" " -i, --id=NUM Identifier\n" - " --expect-proto=PROTOCOL Expectation protocol\n" + " --expect-proto=PROTOCOL Expectation protocol\n" " --expect-src=ADDR Expectation source address\n" " --expect-sport=PORT Expectation source port\n" " --expect-dst=ADDR Expectation destination address\n" " --expect-dport=PORT Expectation destination port\n" - " --master-proto=PROTOCOL Master conntrack protocol\n" + " --master-proto=PROTOCOL Master conntrack protocol\n" " --master-src=ADDR Master conntrack source address\n" " --master-sport=PORT Master conntrack source port\n" " --master-dst=ADDR Master conntrack destination address\n" " --master-dport=PORT Master conntrack destination port\n" - " --mask-proto=PROTOCOL Mask protocol\n" - " --mask-src=ADDR Mask source address\n" - " --mask-sport=PORT Mask source port\n" - " --mask-dst=ADDR Mask destination address\n" - " --mask-dport=PORT Mask destination port\n" + " --mask-proto=PROTOCOL Mask protocol\n" + " --mask-src=ADDR Mask source address\n" + " --mask-sport=PORT Mask source port\n" + " --mask-dst=ADDR Mask destination address\n" + " --mask-dport=PORT Mask destination port\n" " -F, --family=FAMILY Address family\n" " --timeout=NUM Timeout value\n" - " --helper=STRING Helper Name\n" + " --helper=STRING Helper Name\n" " --flags Flags\n" ); exit(0); @@ -75,22 +75,22 @@ int main(int argc, char *argv[]) ARG_EXPECT_SPORT, ARG_EXPECT_DST, ARG_EXPECT_DPORT, - ARG_MASTER_PROTO, + ARG_MASTER_PROTO, ARG_MASTER_SRC, ARG_MASTER_SPORT, ARG_MASTER_DST, ARG_MASTER_DPORT, - ARG_MASK_PROTO, - ARG_MASK_SRC, - ARG_MASK_SPORT, - ARG_MASK_DST, - ARG_MASK_DPORT, + ARG_MASK_PROTO, + ARG_MASK_SRC, + ARG_MASK_SPORT, + ARG_MASK_DST, + ARG_MASK_DPORT, ARG_TIMEOUT, - ARG_HELPER_NAME, + ARG_HELPER_NAME, ARG_FLAGS, }; static struct option long_opts[] = { - { "quiet", 0, 0, 'q' }, + { "quiet", 0, 0, 'q' }, { "help", 0, 0, 'h' }, { "version", 0, 0, 'v' }, { "id", 1, 0, 'i' }, @@ -99,20 +99,20 @@ int main(int argc, char *argv[]) { "expect-sport", 1, 0, ARG_EXPECT_SPORT }, { "expect-dst", 1, 0, ARG_EXPECT_DST }, { "expect-dport", 1, 0, ARG_EXPECT_DPORT }, - { "master-proto", 1, 0, ARG_MASTER_PROTO }, + { "master-proto", 1, 0, ARG_MASTER_PROTO }, { "master-src", 1, 0, ARG_MASTER_SRC }, { "master-sport", 1, 0, ARG_MASTER_SPORT }, { "master-dst", 1, 0, ARG_MASTER_DST }, { "master-dport", 1, 0, ARG_MASTER_DPORT }, - { "mask-proto", 1, 0, ARG_MASK_PROTO }, - { "mask-src", 1, 0, ARG_MASK_SRC }, - { "mask-sport", 1, 0, ARG_MASK_SPORT }, - { "mask-dst", 1, 0, ARG_MASK_DST }, - { "mask-dport", 1, 0, ARG_MASK_DPORT }, + { "mask-proto", 1, 0, ARG_MASK_PROTO }, + { "mask-src", 1, 0, ARG_MASK_SRC }, + { "mask-sport", 1, 0, ARG_MASK_SPORT }, + { "mask-dst", 1, 0, ARG_MASK_DST }, + { "mask-dport", 1, 0, ARG_MASK_DPORT }, { "family", 1, 0, 'F' }, { "timeout", 1, 0, ARG_TIMEOUT }, { "helper", 1, 0, ARG_HELPER_NAME }, - { "flags", 1, 0, ARG_FLAGS}, + { "flags", 1, 0, ARG_FLAGS}, { 0, 0, 0, 0 } }; @@ -122,8 +122,8 @@ int main(int argc, char *argv[]) switch (c) { case '?': exit(NLE_INVAL); - case 'q': quiet = 1; break; - case '4': nfnl_exp_set_family(exp, AF_INET); break; + case 'q': quiet = 1; break; + case '4': nfnl_exp_set_family(exp, AF_INET); break; case '6': nfnl_exp_set_family(exp, AF_INET6); break; case 'h': print_usage(); break; case 'v': nl_cli_print_version(); break; @@ -133,19 +133,19 @@ int main(int argc, char *argv[]) case ARG_EXPECT_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; case ARG_EXPECT_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; case ARG_EXPECT_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; - case ARG_MASTER_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; + case ARG_MASTER_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; case ARG_MASTER_SRC: nl_cli_exp_parse_src(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; case ARG_MASTER_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; case ARG_MASTER_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; case ARG_MASTER_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; - case ARG_MASK_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_MASK, optarg); break; - case ARG_MASK_SRC: nl_cli_exp_parse_src(exp, NFNL_EXP_TUPLE_MASK, optarg); break; - case ARG_MASK_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_MASK, optarg); break; - case ARG_MASK_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_MASK, optarg); break; - case ARG_MASK_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_MASK, optarg); break; + case ARG_MASK_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_MASK, optarg); break; + case ARG_MASK_SRC: nl_cli_exp_parse_src(exp, NFNL_EXP_TUPLE_MASK, optarg); break; + case ARG_MASK_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_MASK, optarg); break; + case ARG_MASK_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_MASK, optarg); break; + case ARG_MASK_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_MASK, optarg); break; case 'F': nl_cli_exp_parse_family(exp, optarg); break; case ARG_TIMEOUT: nl_cli_exp_parse_timeout(exp, optarg); break; - case ARG_HELPER_NAME: nl_cli_exp_parse_helper_name(exp, optarg); break; + case ARG_HELPER_NAME: nl_cli_exp_parse_helper_name(exp, optarg); break; case ARG_FLAGS: nl_cli_exp_parse_flags(exp, optarg); break; } } @@ -153,15 +153,13 @@ int main(int argc, char *argv[]) sock = nl_cli_alloc_socket(); nl_cli_connect(sock, NETLINK_NETFILTER); - if ((err = nfnl_exp_del(sock, exp, nlflags)) < 0) - nl_cli_fatal(err, "Unable to delete expectation: %s", - nl_geterror(err)); - - if (!quiet) { - printf("Deleted "); - nl_object_dump(OBJ_CAST(exp), ¶ms); - } + if ((err = nfnl_exp_del(sock, exp, nlflags)) < 0) + nl_cli_fatal(err, "Unable to delete expectation: %s", nl_geterror(err)); + if (!quiet) { + printf("Deleted "); + nl_object_dump(OBJ_CAST(exp), ¶ms); + } return 0; } diff --git a/src/nf-exp-list.c b/src/nf-exp-list.c index a447ba2..1c6ec69 100644 --- a/src/nf-exp-list.c +++ b/src/nf-exp-list.c @@ -27,19 +27,19 @@ static void print_usage(void) "\n" "Expectation Selection\n" " -i, --id=NUM Identifier\n" - " --expect-proto=PROTOCOL Expectation protocol\n" + " --expect-proto=PROTOCOL Expectation protocol\n" " --expect-src=ADDR Expectation source address\n" " --expect-sport=PORT Expectation source port\n" " --expect-dst=ADDR Expectation destination address\n" " --expect-dport=PORT Expectation destination port\n" - " --master-proto=PROTOCOL Master conntrack protocol\n" + " --master-proto=PROTOCOL Master conntrack protocol\n" " --master-src=ADDR Master conntrack source address\n" " --master-sport=PORT Master conntrack source port\n" " --master-dst=ADDR Master conntrack destination address\n" " --master-dport=PORT Master conntrack destination port\n" " -F, --family=FAMILY Address family\n" " --timeout=NUM Timeout value\n" - " --helper=STRING Helper Name\n" + " --helper=STRING Helper Name\n" //" --flags Flags\n" ); exit(0); @@ -67,14 +67,14 @@ int main(int argc, char *argv[]) ARG_EXPECT_SPORT, ARG_EXPECT_DST, ARG_EXPECT_DPORT, - ARG_MASTER_PROTO, + ARG_MASTER_PROTO, ARG_MASTER_SRC, ARG_MASTER_SPORT, ARG_MASTER_DST, ARG_MASTER_DPORT, ARG_TIMEOUT, - ARG_HELPER_NAME, - //ARG_FLAGS, + ARG_HELPER_NAME, + ARG_FLAGS, }; static struct option long_opts[] = { { "format", 1, 0, 'f' }, @@ -86,7 +86,7 @@ int main(int argc, char *argv[]) { "expect-sport", 1, 0, ARG_EXPECT_SPORT }, { "expect-dst", 1, 0, ARG_EXPECT_DST }, { "expect-dport", 1, 0, ARG_EXPECT_DPORT }, - { "master-proto", 1, 0, ARG_MASTER_PROTO }, + { "master-proto", 1, 0, ARG_MASTER_PROTO }, { "master-src", 1, 0, ARG_MASTER_SRC }, { "master-sport", 1, 0, ARG_MASTER_SPORT }, { "master-dst", 1, 0, ARG_MASTER_DST }, @@ -94,7 +94,7 @@ int main(int argc, char *argv[]) { "family", 1, 0, 'F' }, { "timeout", 1, 0, ARG_TIMEOUT }, { "helper", 1, 0, ARG_HELPER_NAME }, - //{ "flags", 1, 0, ARG_FLAGS}, + { "flags", 1, 0, ARG_FLAGS}, { 0, 0, 0, 0 } }; @@ -115,15 +115,15 @@ int main(int argc, char *argv[]) case ARG_EXPECT_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; case ARG_EXPECT_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; case ARG_EXPECT_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; - case ARG_MASTER_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; + case ARG_MASTER_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; case ARG_MASTER_SRC: nl_cli_exp_parse_src(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; case ARG_MASTER_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; case ARG_MASTER_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; case ARG_MASTER_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; case 'F': nl_cli_exp_parse_family(exp, optarg); break; case ARG_TIMEOUT: nl_cli_exp_parse_timeout(exp, optarg); break; - case ARG_HELPER_NAME: nl_cli_exp_parse_helper_name(exp, optarg); break; - //case ARG_FLAGS: nl_cli_exp_parse_flags(exp, optarg); break; + case ARG_HELPER_NAME: nl_cli_exp_parse_helper_name(exp, optarg); break; + case ARG_FLAGS: nl_cli_exp_parse_flags(exp, optarg); break; } } From 5535f59746d896630b62e5383965344f3a5ae4cb Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Mon, 22 Oct 2012 12:09:03 +0200 Subject: [PATCH 283/432] Don't include doc/ in toplevel dist On a second thought, don't include doc/ in dist at all and distribute it separately. The doc source files are available in the git tree anyway. Signed-off-by: Thomas Graf --- Makefile.am | 1 - doc/configure.in | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index a06daf4..6ec9aa2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,7 +3,6 @@ ACLOCAL_AMFLAGS = -I m4 SUBDIRS = include lib man python tests -DIST_SUBDIRS = doc pkgconfig_DATA = libnl-3.0.pc \ libnl-route-3.0.pc \ diff --git a/doc/configure.in b/doc/configure.in index a962c36..1d0d65b 100644 --- a/doc/configure.in +++ b/doc/configure.in @@ -9,7 +9,7 @@ # Copyright (c) 2003-2012 Thomas Graf # -AC_INIT(libnl-doc, [3.2.13], [http://www.infradead.org/~tgr/libnl/]) +AC_INIT(libnl-doc, [3.2.14], [http://www.infradead.org/~tgr/libnl/]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES(yes)], []) From 3c1ab421eea2a51a3ee1c2f4515c59d8f85c8247 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 23 Oct 2012 15:28:24 +0200 Subject: [PATCH 284/432] add missing '}' in __cplusplus namespaces Signed-off-by: Thomas Graf --- include/netlink/route/link/api.h | 3 +++ include/netlink/route/link/inet.h | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/include/netlink/route/link/api.h b/include/netlink/route/link/api.h index 960d3f1..e6dad27 100644 --- a/include/netlink/route/link/api.h +++ b/include/netlink/route/link/api.h @@ -130,5 +130,8 @@ extern void * rtnl_link_af_data(const struct rtnl_link *, extern int rtnl_link_af_register(struct rtnl_link_af_ops *); extern int rtnl_link_af_unregister(struct rtnl_link_af_ops *); +#ifdef __cplusplus +} +#endif #endif diff --git a/include/netlink/route/link/inet.h b/include/netlink/route/link/inet.h index 66419e3..506542f 100644 --- a/include/netlink/route/link/inet.h +++ b/include/netlink/route/link/inet.h @@ -26,4 +26,8 @@ extern int rtnl_link_inet_get_conf(struct rtnl_link *, extern int rtnl_link_inet_set_conf(struct rtnl_link *, const unsigned int, uint32_t); +#ifdef __cplusplus +} +#endif + #endif From a8ef3525c89b0a2049abedd2a0b2d54f0d574476 Mon Sep 17 00:00:00 2001 From: Rich Fought Date: Fri, 26 Oct 2012 12:19:26 -0700 Subject: [PATCH 285/432] Add configure option to disable pthreads support --- configure.in | 14 ++++++++++++-- lib/socket.c | 16 ++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 79cd93f..9a190c2 100644 --- a/configure.in +++ b/configure.in @@ -41,7 +41,7 @@ m4_define([libnl_lt_age], [11]) m4_define([libnl_version], [libnl_major_version.libnl_minor_version.libnl_micro_version]) -AC_INIT(libnl, [libnl_version], [http://www.infradead.org/~tgr/libnl/]) +AC_INIT(libnl, [libnl_version], [], [], [http://www.infradead.org/~tgr/libnl/]) AC_CONFIG_HEADERS([lib/defs.h]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([-Wall foreign subdir-objects]) @@ -83,8 +83,18 @@ AC_ARG_ENABLE([cli], [enable_cli="$enableval"], [enable_cli="yes"]) AM_CONDITIONAL([ENABLE_CLI], [test "$enable_cli" = "yes"]) +AC_ARG_ENABLE([pthreads], + AS_HELP_STRING([--disable-pthreads], [Disable pthreads support]), + [enable_pthreads="$enableval"], [enable_pthreads="yes"]) +AM_CONDITIONAL([DISABLE_PTHREADS], [test "$enable_pthreads" = "no"]) + AC_CHECK_LIB([m], [pow], [], AC_MSG_ERROR([libm is required])) -AC_CHECK_LIB([pthread], [pthread_mutex_lock], [], AC_MSG_ERROR([libpthread is required])) + +if test "x$enable_pthreads" = "xno"; then + AC_DEFINE([DISABLE_PTHREADS], [1], [Define to 1 to disable pthreads]) +else + AC_CHECK_LIB([pthread], [pthread_mutex_lock], [], AC_MSG_ERROR([libpthread is required])) +fi AC_CONFIG_SUBDIRS([doc]) diff --git a/lib/socket.c b/lib/socket.c index d53a714..4e1d84c 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -27,7 +27,11 @@ * ~~~~ */ +#include "defs.h" + +#ifndef DISABLE_PTHREADS #include +#endif #include #include @@ -57,14 +61,18 @@ static void __init init_default_cb(void) } static uint32_t used_ports_map[32]; +#ifndef DISABLE_PTHREADS static pthread_mutex_t port_map_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif static uint32_t generate_local_port(void) { int i, n; uint32_t pid = getpid() & 0x3FFFFF; +#ifndef DISABLE_PTHREADS pthread_mutex_lock(&port_map_mutex); +#endif for (i = 0; i < 32; i++) { if (used_ports_map[i] == 0xFFFFFFFF) @@ -80,13 +88,17 @@ static uint32_t generate_local_port(void) /* PID_MAX_LIMIT is currently at 2^22, leaving 10 bit * to, i.e. 1024 unique ports per application. */ +#ifndef DISABLE_PTHREADS pthread_mutex_unlock(&port_map_mutex); +#endif return pid + (n << 22); } } +#ifndef DISABLE_PTHREADS pthread_mutex_unlock(&port_map_mutex); +#endif /* Out of sockets in our own PID namespace, what to do? FIXME */ return UINT_MAX; @@ -101,9 +113,13 @@ static void release_local_port(uint32_t port) nr = port >> 22; +#ifndef DISABLE_PTHREADS pthread_mutex_lock(&port_map_mutex); +#endif used_ports_map[nr / 32] &= ~(1 << (nr % 32)); +#ifndef DISABLE_PTHREADS pthread_mutex_unlock(&port_map_mutex); +#endif } /** From 503270c1c8558f5e2a96a01dec0cee86267ee325 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sat, 27 Oct 2012 20:38:20 +0200 Subject: [PATCH 286/432] Remove unreachable code This code gets never called anyway --- lib/route/addr.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/route/addr.c b/lib/route/addr.c index 600857b..8ae16ef 100644 --- a/lib/route/addr.c +++ b/lib/route/addr.c @@ -890,11 +890,6 @@ struct nl_addr *rtnl_addr_get_local(struct rtnl_addr *addr) int rtnl_addr_set_peer(struct rtnl_addr *addr, struct nl_addr *peer) { return __assign_addr(addr, &addr->a_peer, peer, ADDR_ATTR_PEER); - - addr->a_prefixlen = nl_addr_get_prefixlen(addr->a_peer); - addr->ce_mask |= ADDR_ATTR_PREFIXLEN; - - return 0; } struct nl_addr *rtnl_addr_get_peer(struct rtnl_addr *addr) From 16e54c4e6e767e5c923e7d5849a285b38d3345d0 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sat, 27 Oct 2012 20:38:22 +0200 Subject: [PATCH 287/432] Add missing va_end() calls Add missing va_end() calls on all error paths --- lib/socket.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/socket.c b/lib/socket.c index 4e1d84c..724fb7a 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -347,13 +347,17 @@ int nl_socket_add_memberships(struct nl_sock *sk, int group, ...) va_start(ap, group); while (group != 0) { - if (group < 0) + if (group < 0) { + va_end(ap); return -NLE_INVAL; + } err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &group, sizeof(group)); - if (err < 0) + if (err < 0) { + va_end(ap); return -nl_syserr2nlerr(errno); + } group = va_arg(ap, int); } @@ -391,13 +395,17 @@ int nl_socket_drop_memberships(struct nl_sock *sk, int group, ...) va_start(ap, group); while (group != 0) { - if (group < 0) + if (group < 0) { + va_end(ap); return -NLE_INVAL; + } err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP, &group, sizeof(group)); - if (err < 0) + if (err < 0) { + va_end(ap); return -nl_syserr2nlerr(errno); + } group = va_arg(ap, int); } From 3750e2ac31c15c85069ab3a087c4353f8bc6e80a Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sat, 27 Oct 2012 20:38:21 +0200 Subject: [PATCH 288/432] Set err and free ntbl when leaving neightbl_msg_parser Make sure we leave neightbl_msg_parser() by setting the proper err variable and freeing ntbl --- lib/route/neightbl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/route/neightbl.c b/lib/route/neightbl.c index 7725482..1efa5cb 100644 --- a/lib/route/neightbl.c +++ b/lib/route/neightbl.c @@ -143,7 +143,7 @@ static int neightbl_msg_parser(struct nl_cache_ops *ops, ntbl->nt_family = rtmsg->rtgen_family; if (tb[NDTA_NAME] == NULL) { - return -NLE_MISSING_ATTR; + err = -NLE_MISSING_ATTR; goto errout; } From 690264a193c2cf548e3561bec3c7bbe3e4407ee4 Mon Sep 17 00:00:00 2001 From: roopa Date: Thu, 1 Nov 2012 07:15:28 -0700 Subject: [PATCH 289/432] Add new object op oo_id_attrs_get The current oo_id_attrs nl_object op allows a fixed id attribute list for an cache. But a cache with multiple families may need to specify different id attributes for different families. An example for this is the bridge fdb entries in the neigh cache: neigh entries belonging to the AF_UNSPEC family use (NEIGH_ATTR_IFINDEX | NEIGH_ATTR_DST | NEIGH_ATTR_FAMILY) as id attributes. AF_BRIDGE fdb entries which also support the same msg type, will need to use (NEIGH_ATTR_LLADDR | NEIGH_ATTR_FAMILY) as id attributes. Today you cannot specify different set of attributes to two families belonging to the same cache. This patch adds a new object function oo_id_attrs_get to get the attributes. An example implementation of oo_id_attrs_get for the neigh cache will look like: static uint32_t neigh_id_attrs_get(struct nl_object *obj) { struct rtnl_neigh *neigh = (struct rtnl_neigh *)obj; if (neigh->n_family == AF_BRIDGE) return (NEIGH_ATTR_LLADDR | NEIGH_ATTR_FAMILY); else return (NEIGH_ATTR_IFINDEX | NEIGH_ATTR_DST | NEIGH_ATTR_FAMILY); } Signed-off-by: Roopa Prabhu Reviewed-by: Nolan Leake Reviewed-by: Shrijeet Mukherjee Reviewed-by: Wilson Kok --- include/netlink/object-api.h | 5 +++++ lib/object.c | 10 +++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/include/netlink/object-api.h b/include/netlink/object-api.h index 70a4ddd..cfd5699 100644 --- a/include/netlink/object-api.h +++ b/include/netlink/object-api.h @@ -337,6 +337,11 @@ struct nl_object_ops char *(*oo_attrs2str)(int, char *, size_t); + + /** + * Get key attributes by family function + */ + uint32_t (*oo_id_attrs_get)(struct nl_object *); }; /** @} */ diff --git a/lib/object.c b/lib/object.c index 055a208..585189e 100644 --- a/lib/object.c +++ b/lib/object.c @@ -291,7 +291,15 @@ int nl_object_identical(struct nl_object *a, struct nl_object *b) if (ops != obj_ops(b)) return 0; - req_attrs = ops->oo_id_attrs; + if (ops->oo_id_attrs_get) { + int req_attrs_a = ops->oo_id_attrs_get(a); + int req_attrs_b = ops->oo_id_attrs_get(b); + if (req_attrs_a != req_attrs_b) + return 0; + req_attrs = req_attrs_a; + } else { + req_attrs = ops->oo_id_attrs; + } if (req_attrs == 0xFFFFFFFF) req_attrs = a->ce_mask & b->ce_mask; From bc7c822f54ac2b22d0d6595ca756464cf087c3a1 Mon Sep 17 00:00:00 2001 From: roopa Date: Thu, 1 Nov 2012 14:13:30 -0700 Subject: [PATCH 290/432] Add support for updating objects in the cache This patch adds support to update a cache object during cache_include instead of the current approach of deleting the original object and adding a new one. This operation is conditional on the object implementing the operation. If the update is not successful, cache_include falls back to the existing cache inclusion process of deleting and adding the object. It adds a new object operation called oo_update. oo_update takes two objects as arguments, first being the existing cache object that needs update, the second argument being the new object. Currently it is left to the implementor to use the msg type to decide wether to delete or add the new object attributes to the old one. But the operation type or msg type can be easily made part of the object arguments. The motivation for this change is explained below in the context of including support for AF_BRIDGE objects into the link cache. libnl today deletes an object before it includes an identical object. But for some objects like the AF_BRIDGE objects this does not work well. link cache uses the ifindex as its key in object searches. If link cache were to support AF_BRIDGE family objects, todays implementation, - will replace the original link object with the bridge port link object for add notifications - And a bridge port delete notification from kernel would delete the link object from the cache leaving the cache without the link object until the kernel sends another notification for that link The bridge port link notification contains some base link object attributes plus bridge specific protocol info attributes. In such cases we think an operation to update the existing object in place in cache might be useful. This can be made to work for AF_INET6 link objects too. Signed-off-by: Roopa Prabhu Reviewed-by: Nolan Leake Reviewed-by: Shrijeet Mukherjee Reviewed-by: Wilson Kok --- include/netlink/object-api.h | 12 ++++++++++++ include/netlink/object.h | 2 ++ lib/cache.c | 11 +++++++++++ lib/object.c | 17 +++++++++++++++++ 4 files changed, 42 insertions(+) diff --git a/include/netlink/object-api.h b/include/netlink/object-api.h index cfd5699..ec2192b 100644 --- a/include/netlink/object-api.h +++ b/include/netlink/object-api.h @@ -336,6 +336,18 @@ struct nl_object_ops uint32_t, int); + /** + * update function + * + * Will be called when the object given by first argument + * needs to be updated with the contents of the second object + * + * The function must return 0 for success and error for failure + * to update. In case of failure its assumed that the original + * object is not touched + */ + int (*oo_update)(struct nl_object *, struct nl_object *); + char *(*oo_attrs2str)(int, char *, size_t); /** diff --git a/include/netlink/object.h b/include/netlink/object.h index bbda5f5..788ae48 100644 --- a/include/netlink/object.h +++ b/include/netlink/object.h @@ -31,6 +31,8 @@ extern int nl_object_alloc_name(const char *, struct nl_object **); extern void nl_object_free(struct nl_object *); extern struct nl_object * nl_object_clone(struct nl_object *obj); +extern int nl_object_update(struct nl_object *dst, + struct nl_object *src); extern void nl_object_get(struct nl_object *); extern void nl_object_put(struct nl_object *); extern int nl_object_shared(struct nl_object *); diff --git a/lib/cache.c b/lib/cache.c index 45a1a27..f73fedf 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -642,6 +642,17 @@ static int cache_include(struct nl_cache *cache, struct nl_object *obj, case NL_ACT_DEL: old = nl_cache_search(cache, obj); if (old) { + /* + * Some objects types might support merging the new + * object with the old existing cache object. + * Handle them first. + */ + if (nl_object_update(old, obj) == 0) { + cb(cache, old, NL_ACT_CHANGE, data); + nl_object_put(obj); + return 0; + } + nl_cache_remove(old); if (type->mt_act == NL_ACT_DEL) { if (cb) diff --git a/lib/object.c b/lib/object.c index 585189e..d58f9a7 100644 --- a/lib/object.c +++ b/lib/object.c @@ -138,6 +138,23 @@ struct nl_object *nl_object_clone(struct nl_object *obj) return new; } +/** + * Merge a cacheable object + * @arg dst object to be merged into + * @arg src new object to be merged into dst + * + * @return 0 or a negative error code. + */ +int nl_object_update(struct nl_object *dst, struct nl_object *src) +{ + struct nl_object_ops *ops = obj_ops(dst); + + if (ops->oo_update) + return ops->oo_update(dst, src); + + return -NLE_OPNOTSUPP; +} + /** * Free a cacheable object * @arg obj object to free From ceb8fb9e8747dd21f4067720e1090384910d348b Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 6 Nov 2012 00:19:28 +0100 Subject: [PATCH 291/432] Document buffer size limitations of nl_recv() --- lib/nl.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/nl.c b/lib/nl.c index 9858307..0ed248e 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -416,9 +416,16 @@ errout: * are handled by repeating the read. The input buffer size is determined * by peeking before the actual read is done. * + * The buffer size used when reading from the netlink socket and thus limiting + * the maximum size of a netlink message that can be read defaults to the size + * of a memory page (getpagesize()). The buffer size can be modified on a per + * socket level using the function nl_socket_set_msg_buf_size(). + * * A non-blocking sockets causes the function to return immediately with * a return value of 0 if no data is available. * + * @see nl_socket_set_msg_buf_size() + * * @return Number of octets read, 0 on EOF or a negative error code. */ int nl_recv(struct nl_sock *sk, struct sockaddr_nl *nla, From 6d52ae6440fe324e94b1a08ebd40bc6e81d333f3 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 6 Nov 2012 00:21:35 +0100 Subject: [PATCH 292/432] nl_recv: Don't update *buf in error path iov.iov_base is either NULL or invalid --- lib/nl.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/nl.c b/lib/nl.c index 0ed248e..6ba4828 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -551,9 +551,8 @@ abort: if (retval <= 0) { free(iov.iov_base); iov.iov_base = NULL; free(tmpcreds); tmpcreds = NULL; - } - - *buf = iov.iov_base; + } else + *buf = iov.iov_base; if (creds) *creds = tmpcreds; From fb42f19e2e2d02149049f3733f9a0131afc0fe65 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 6 Nov 2012 14:21:18 +0100 Subject: [PATCH 293/432] nl_recv: improve function documentation --- lib/nl.c | 46 +++++++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/lib/nl.c b/lib/nl.c index 6ba4828..f4141e7 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -404,29 +404,49 @@ errout: /** * Receive data from netlink socket - * @arg sk Netlink socket. - * @arg nla Destination pointer for peer's netlink address. (required) - * @arg buf Destination pointer for message content. (required) - * @arg creds Destination pointer for credentials. (optional) + * @arg sk Netlink socket (required) + * @arg nla Netlink socket structure to hold address of peer (required) + * @arg buf Destination pointer for message content (required) + * @arg creds Destination pointer for credentials (optional) * - * Receives a netlink message, allocates a buffer in \c *buf and - * stores the message content. The peer's netlink address is stored - * in \c *nla. The caller is responsible for freeing the buffer allocated - * in \c *buf if a positive value is returned. Interrupted system calls - * are handled by repeating the read. The input buffer size is determined - * by peeking before the actual read is done. + * Receives data from a connected netlink socket using recvmsg() and returns + * the number of bytes read. The read data is stored in a newly allocated + * buffer that is assigned to \c *buf. The peer's netlink address will be + * stored in \c *nla. + * + * This function blocks until data is available to be read unless the socket + * has been put into non-blocking mode using nl_socket_set_nonblocking() in + * which case this function will return immediately with a return value of 0. * * The buffer size used when reading from the netlink socket and thus limiting * the maximum size of a netlink message that can be read defaults to the size * of a memory page (getpagesize()). The buffer size can be modified on a per * socket level using the function nl_socket_set_msg_buf_size(). * - * A non-blocking sockets causes the function to return immediately with - * a return value of 0 if no data is available. + * If message peeking is enabled using nl_socket_enable_msg_peek() the size of + * the message to be read will be determined using the MSG_PEEK flag prior to + * performing the actual read. This leads to an additional recvmsg() call for + * every read operation which has performance implications and is not + * recommended for high throughput protocols. * + * An eventual interruption of the recvmsg() system call is automatically + * handled by retrying the operation. + * + * If receiving of credentials has been enabled using the function + * nl_socket_set_passcred(), this function will allocate a new struct ucred + * filled with the received credentials and assign it to \c *creds. The caller + * is responsible for freeing the buffer. + * + * @note The caller is responsible to free the returned data buffer and if + * enabled, the credentials buffer. + * + * @see nl_socket_set_nonblocking() * @see nl_socket_set_msg_buf_size() + * @see nl_socket_enable_msg_peek() + * @see nl_socket_set_passcred() * - * @return Number of octets read, 0 on EOF or a negative error code. + * @return Number of bytes read, 0 on EOF, 0 on no data event (non-blocking + * mode), or a negative error code. */ int nl_recv(struct nl_sock *sk, struct sockaddr_nl *nla, unsigned char **buf, struct ucred **creds) From eb3606690973420d3d402f1d8e4ac5c2b3304615 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 6 Nov 2012 14:22:50 +0100 Subject: [PATCH 294/432] nl_recv: return NLE_INVAL if buf is NULL --- lib/nl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/nl.c b/lib/nl.c index f4141e7..17bd834 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -464,6 +464,9 @@ int nl_recv(struct nl_sock *sk, struct sockaddr_nl *nla, struct ucred* tmpcreds = NULL; int retval = 0; + if (!buf) + return -NLE_INVAL; + if (sk->s_flags & NL_MSG_PEEK) flags |= MSG_PEEK | MSG_TRUNC; From 220d8e141d22e6ef73b8b6b4b061a46f6c88c061 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 6 Nov 2012 14:24:09 +0100 Subject: [PATCH 295/432] nl_recv: return NLE_INVAL if socket address pointer is NULL --- lib/nl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nl.c b/lib/nl.c index 17bd834..161cfa5 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -464,7 +464,7 @@ int nl_recv(struct nl_sock *sk, struct sockaddr_nl *nla, struct ucred* tmpcreds = NULL; int retval = 0; - if (!buf) + if (!buf || !nla) return -NLE_INVAL; if (sk->s_flags & NL_MSG_PEEK) From 65f97deb6342310f212e88d7095d2b26cd53e89b Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 6 Nov 2012 14:27:34 +0100 Subject: [PATCH 296/432] nl_recv: fix indent style --- lib/nl.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/nl.c b/lib/nl.c index 161cfa5..57281ea 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -477,8 +477,8 @@ int nl_recv(struct nl_sock *sk, struct sockaddr_nl *nla, iov.iov_base = malloc(iov.iov_len); if (!iov.iov_base) { - retval = -NLE_NOMEM; - goto abort; + retval = -NLE_NOMEM; + goto abort; } if (creds && (sk->s_flags & NL_SOCK_PASSCRED)) { @@ -515,8 +515,8 @@ retry: msg.msg_controllen *= 2; tmp = realloc(msg.msg_control, msg.msg_controllen); if (!tmp) { - retval = -NLE_NOMEM; - goto abort; + retval = -NLE_NOMEM; + goto abort; } msg.msg_control = tmp; goto retry; @@ -530,8 +530,8 @@ retry: iov.iov_len = n; tmp = realloc(iov.iov_base, iov.iov_len); if (!tmp) { - retval = -NLE_NOMEM; - goto abort; + retval = -NLE_NOMEM; + goto abort; } iov.iov_base = tmp; flags = 0; @@ -572,13 +572,15 @@ abort: free(msg.msg_control); if (retval <= 0) { - free(iov.iov_base); iov.iov_base = NULL; - free(tmpcreds); tmpcreds = NULL; + free(iov.iov_base); + iov.iov_base = NULL; + free(tmpcreds); + tmpcreds = NULL; } else *buf = iov.iov_base; if (creds) - *creds = tmpcreds; + *creds = tmpcreds; return retval; } From b25f26b896de785b9aecf871222d1762de800dbc Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 6 Nov 2012 17:36:53 +0100 Subject: [PATCH 297/432] socket: document nl_socket_get_fd() --- lib/socket.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/socket.c b/lib/socket.c index 724fb7a..0335f07 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -472,6 +472,15 @@ void nl_socket_set_peer_groups(struct nl_sock *sk, uint32_t groups) * @{ */ +/** + * Return the file descriptor of the backing socket + * @arg sk Netlink socket + * + * Only valid after calling nl_connect() to create and bind the respective + * socket. + * + * @return File descriptor or -1 if not available. + */ int nl_socket_get_fd(const struct nl_sock *sk) { return sk->s_fd; From 8f47501741afa27c405648a2005a6e6acc4b69a9 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 6 Nov 2012 17:48:28 +0100 Subject: [PATCH 298/432] nl: improve nl_sendto() docs and error checks Make nl_sendto() return NLE_INVAL if provided buffer is NULL and make it return NLE_BAD_SOCK if the socket is not connected. Add note in docs about lack of NL_CB_MSG_OUT invokation --- lib/nl.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/lib/nl.c b/lib/nl.c index 57281ea..f069b69 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -158,16 +158,38 @@ void nl_close(struct nl_sock *sk) */ /** - * Send raw data over netlink socket. - * @arg sk Netlink socket. - * @arg buf Data buffer. - * @arg size Size of data buffer. - * @return Number of characters written on success or a negative error code. + * Transmit raw data over netlink socket. + * @arg sk Netlink socket (required) + * @arg buf Buffer carrying data to send (required) + * @arg size Size of buffer (required) + * + * Transmits "raw" data over the specified netlink socket. Unlike the other + * transmit functions it does not modify the data in any way. It directly + * passes the buffer \c buf of \c size to sendto(). + * + * The message is addressed to the peer as specified in the socket by either + * the nl_socket_set_peer_port() or nl_socket_set_peer_groups() function. + * + * @note Because there is no indication on the message boundaries of the data + * being sent, the \c NL_CB_MSG_OUT callback handler will not be invoked + * for data that is being sent using this function. + * + * @see nl_socket_set_peer_port() + * @see nl_socket_set_peer_groups() + * @see nl_sendmsg() + * + * @return Number of bytes sent or a negative error code. */ int nl_sendto(struct nl_sock *sk, void *buf, size_t size) { int ret; + if (!buf) + return -NLE_INVAL; + + if (sk->s_fd < 0) + return -NLE_BAD_SOCK; + ret = sendto(sk->s_fd, buf, size, 0, (struct sockaddr *) &sk->s_peer, sizeof(sk->s_peer)); if (ret < 0) From a721c1d445c0cd8c1d555821e5a5e62e77006a87 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 8 Nov 2012 00:11:13 +0100 Subject: [PATCH 299/432] doc: increase dot max graph nodes to 100 --- doc/Doxyfile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 62b2661..c43d764 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -1762,7 +1762,7 @@ MSCFILE_DIRS = # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. -DOT_GRAPH_MAX_NODES = 50 +DOT_GRAPH_MAX_NODES = 100 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable From b132ee7e27899b07f30e9a53dd6ce5f09efd8bf6 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 8 Nov 2012 01:29:12 +0100 Subject: [PATCH 300/432] nl: improve API doc of transmit functions Signed-off-by: Thomas Graf --- doc/Doxyfile.in | 4 +- doc/DoxygenLayout.xml | 1 - doc/src/hidden.c | 7 ++ lib/nl.c | 205 +++++++++++++++++++++++++++++++----------- 4 files changed, 164 insertions(+), 53 deletions(-) diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index c43d764..7a0640c 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -198,7 +198,9 @@ ALIASES = arg=\param \ "ref_core{2}=\ref_asciidoc{core,\1,\2 (Netlink Core Library Development Guide)}" \ "ref_route{2}=\ref_asciidoc{route,\1,\2 (Netlink Routing Development Guide)}" \ "core_doc{2}=\ref_core{\1,\2}" \ - "route_doc{2}=\ref_route{\1,\2}" + "route_doc{2}=\ref_route{\1,\2}" \ + "callback=\par Callback Invocation:\n" \ + "lowlevel=\copydoc low_level_api" # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding diff --git a/doc/DoxygenLayout.xml b/doc/DoxygenLayout.xml index 8d3e3ff..680d3da 100644 --- a/doc/DoxygenLayout.xml +++ b/doc/DoxygenLayout.xml @@ -18,7 +18,6 @@ - diff --git a/doc/src/hidden.c b/doc/src/hidden.c index be4a042..a63621d 100644 --- a/doc/src/hidden.c +++ b/doc/src/hidden.c @@ -32,4 +32,11 @@ accessor function is provided solely for the purpose of creating objects for comparison and filtering. +\page low_level_api Low Level API + +\note This is a low level API function. A high level function implementing + the same functionality with a simplified usage pattern exists. This + function is available as an alternative if the default library + behaviour is not desirable. + */ diff --git a/lib/nl.c b/lib/nl.c index f069b69..5f4ab94 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -158,12 +158,12 @@ void nl_close(struct nl_sock *sk) */ /** - * Transmit raw data over netlink socket. + * Transmit raw data over Netlink socket. * @arg sk Netlink socket (required) * @arg buf Buffer carrying data to send (required) * @arg size Size of buffer (required) * - * Transmits "raw" data over the specified netlink socket. Unlike the other + * Transmits "raw" data over the specified Netlink socket. Unlike the other * transmit functions it does not modify the data in any way. It directly * passes the buffer \c buf of \c size to sendto(). * @@ -199,17 +199,49 @@ int nl_sendto(struct nl_sock *sk, void *buf, size_t size) } /** - * Send netlink message with control over sendmsg() message header. - * @arg sk Netlink socket. - * @arg msg Netlink message to be sent. - * @arg hdr Sendmsg() message header. - * @return Number of characters sent on sucess or a negative error code. + * Transmit Netlink message using sendmsg() + * @arg sk Netlink socket (required) + * @arg msg Netlink message to be sent (required) + * @arg hdr sendmsg() message header (required) + * + * Transmits the message specified in \c hdr over the Netlink socket using the + * sendmsg() system call. + * + * @attention + * The `msg` argument will *not* be used to derive the message payload that + * is being sent out. The `msg` argument is *only* passed on to the + * `NL_CB_MSG_OUT` callback. The caller is responsible to initialize the + * `hdr` struct properly and have it point to the message payload and + * socket address. + * + * @note + * This function uses `nlmsg_set_src()` to modify the `msg` argument prior to + * invoking the `NL_CB_MSG_OUT` callback to provide the local port number. + * + * @callback This function triggers the `NL_CB_MSG_OUT` callback. + * + * @attention + * Think twice before using this function. It provides a low level access to + * the Netlink socket. Among other limitations, it does not add credentials + * even if enabled or respect the destination address specified in the `msg` + * object. + * + * @see nl_socket_set_local_port() + * @see nl_send_auto() + * @see nl_send_iovec() + * + * @return Number of bytes sent on success or a negative error code. + * + * @lowlevel */ int nl_sendmsg(struct nl_sock *sk, struct nl_msg *msg, struct msghdr *hdr) { struct nl_cb *cb; int ret; + if (sk->s_fd < 0) + return -NLE_BAD_SOCK; + nlmsg_set_src(msg, &sk->s_local); cb = sk->s_cb; @@ -227,13 +259,23 @@ int nl_sendmsg(struct nl_sock *sk, struct nl_msg *msg, struct msghdr *hdr) /** - * Send netlink message. - * @arg sk Netlink socket. - * @arg msg Netlink message to be sent. - * @arg iov iovec to be sent. - * @arg iovlen number of struct iovec to be sent. - * @see nl_sendmsg() - * @return Number of characters sent on success or a negative error code. + * Transmit Netlink message (taking IO vector) + * @arg sk Netlink socket (required) + * @arg msg Netlink message to be sent (required) + * @arg iov IO vector to be sent (required) + * @arg iovlen Number of struct iovec to be sent (required) + * + * This function is identical to nl_send() except that instead of taking a + * `struct nl_msg` object it takes an IO vector. Please see the description + * of `nl_send()`. + * + * @callback This function triggers the `NL_CB_MSG_OUT` callback. + * + * @see nl_send() + * + * @return Number of bytes sent on success or a negative error code. + * + * @lowlevel */ int nl_send_iovec(struct nl_sock *sk, struct nl_msg *msg, struct iovec *iov, unsigned iovlen) { @@ -272,14 +314,37 @@ int nl_send_iovec(struct nl_sock *sk, struct nl_msg *msg, struct iovec *iov, uns return nl_sendmsg(sk, msg, &hdr); } - - /** -* Send netlink message. -* @arg sk Netlink socket. -* @arg msg Netlink message to be sent. -* @see nl_sendmsg() -* @return Number of characters sent on success or a negative error code. + * Transmit Netlink message + * @arg sk Netlink socket (required) + * @arg msg Netlink message (required) + * + * Transmits the Netlink message `msg` over the Netlink socket using the + * `sendmsg()` system call. This function is based on `nl_send_iovec()` but + * takes care of initializing a `struct iovec` based on the `msg` object. + * + * The message is addressed to the peer as specified in the socket by either + * the nl_socket_set_peer_port() or nl_socket_set_peer_groups() function. + * The peer address can be overwritten by specifying an address in the `msg` + * object using nlmsg_set_dst(). + * + * If present in the `msg`, credentials set by the nlmsg_set_creds() function + * are added to the control buffer of the message. + * + * @callback This function triggers the `NL_CB_MSG_OUT` callback. + * + * @attention + * Unlike `nl_send_auto()`, this function does *not* finalize the message in + * terms of automatically adding needed flags or filling out port numbers. + * + * @see nl_send_auto() + * @see nl_send_iovec() + * @see nl_socket_set_peer_port() + * @see nl_socket_set_peer_groups() + * @see nlmsg_set_dst() + * @see nlmsg_set_creds() + * + * @return Number of bytes sent on success or a negative error code. */ int nl_send(struct nl_sock *sk, struct nl_msg *msg) { @@ -291,6 +356,24 @@ int nl_send(struct nl_sock *sk, struct nl_msg *msg) return nl_send_iovec(sk, msg, &iov, 1); } +/** + * Finalize Netlink message + * @arg sk Netlink socket (required) + * @arg msg Netlink message (required) + * + * This function finalizes a Netlink message by completing the message with + * desirable flags and values depending on the socket configuration. + * + * - If not yet filled out, the source address of the message (`nlmsg_pid`) + * will be set to the local port number of the socket. + * - If not yet specified, the next available sequence number is assigned + * to the message (`nlmsg_seq`). + * - If not yet specified, the protocol field of the message will be set to + * the protocol field of the socket. + * - The `NLM_F_REQUEST` Netlink message flag will be set. + * - The `NLM_F_ACK` flag will be set if Auto-ACK mode is enabled on the + * socket. + */ void nl_complete_msg(struct nl_sock *sk, struct nl_msg *msg) { struct nlmsghdr *nlh; @@ -311,25 +394,20 @@ void nl_complete_msg(struct nl_sock *sk, struct nl_msg *msg) nlh->nlmsg_flags |= NLM_F_ACK; } -void nl_auto_complete(struct nl_sock *sk, struct nl_msg *msg) -{ - nl_complete_msg(sk, msg); -} - /** - * Automatically complete and send a netlink message - * @arg sk Netlink socket. - * @arg msg Netlink message to be sent. + * Finalize and transmit Netlink message + * @arg sk Netlink socket (required) + * @arg msg Netlink message (required) * - * This function takes a netlink message and passes it on to - * nl_auto_complete() for completion. + * Finalizes the message by passing it to `nl_complete_msg()` and transmits it + * by passing it to `nl_send()`. * - * Checks the netlink message \c nlh for completness and extends it - * as required before sending it out. Checked fields include pid, - * sequence nr, and flags. + * @callback This function triggers the `NL_CB_MSG_OUT` callback. * + * @see nl_complete_msg() * @see nl_send() - * @return Number of characters sent or a negative error code. + * + * @return Number of bytes sent or a negative error code. */ int nl_send_auto(struct nl_sock *sk, struct nl_msg *msg) { @@ -343,27 +421,28 @@ int nl_send_auto(struct nl_sock *sk, struct nl_msg *msg) return nl_send(sk, msg); } -int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg) -{ - return nl_send_auto(sk, msg); -} - /** - * Send netlink message and wait for response (sync request-response) - * @arg sk Netlink socket - * @arg msg Netlink message to be sent + * Finalize and transmit Netlink message and wait for ACK or error message + * @arg sk Netlink socket (required) + * @arg msg Netlink message (required) * - * This function takes a netlink message and sends it using nl_send_auto(). - * It will then wait for the response (ACK or error message) to be - * received. Threfore this function will block until the operation has - * been completed. + * Passes the `msg` to `nl_send_auto()` to finalize and transmit it. Frees the + * message and waits (sleeps) for the ACK or error message to be received. * - * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause - * this function to return immediately after sending. In this case, - * it is the responsibility of the caller to handle any eventual - * error messages returned. + * @attention + * Disabling Auto-ACK (nl_socket_disable_auto_ack()) will cause this function + * to return immediately after transmitting the message. However, the peer may + * still be returning an error message in response to the request. It is the + * responsibility of the caller to handle such messages. + * + * @callback This function triggers the `NL_CB_MSG_OUT` callback. + * + * @attention + * This function frees the `msg` object after transmitting it by calling + * `nlmsg_free()`. * * @see nl_send_auto(). + * @see nl_wait_for_ack() * * @return 0 on success or a negative error code. */ @@ -994,6 +1073,30 @@ errout: return err; } +/** @} */ + +/** + * @name Deprecated + * @{ + */ + +/** + * @deprecated Please use nl_complete_msg() + */ +void nl_auto_complete(struct nl_sock *sk, struct nl_msg *msg) +{ + nl_complete_msg(sk, msg); +} + +/** + * @deprecated Please use nl_send_auto() + */ +int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg) +{ + return nl_send_auto(sk, msg); +} + + /** @} */ /** @} */ From fd6f205f8a14e8bf7288e65be435641d5ee2956a Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 8 Nov 2012 13:19:07 +0100 Subject: [PATCH 301/432] nl: Allow to overwrite nl_send() Up to now only calls to nl_send_auto() could be overwritten with nl_cb_overwrite_send(). This patch extends the capability to nl_send() Signed-off-by: Thomas Graf --- lib/nl.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/lib/nl.c b/lib/nl.c index 5f4ab94..efdd095 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -331,6 +331,10 @@ int nl_send_iovec(struct nl_sock *sk, struct nl_msg *msg, struct iovec *iov, uns * If present in the `msg`, credentials set by the nlmsg_set_creds() function * are added to the control buffer of the message. * + * @par Overwriting Capability: + * Calls to this function can be overwritten by providing an alternative using + * the nl_cb_overwrite_send() function. + * * @callback This function triggers the `NL_CB_MSG_OUT` callback. * * @attention @@ -343,17 +347,24 @@ int nl_send_iovec(struct nl_sock *sk, struct nl_msg *msg, struct iovec *iov, uns * @see nl_socket_set_peer_groups() * @see nlmsg_set_dst() * @see nlmsg_set_creds() + * @see nl_cb_overwrite_send() * * @return Number of bytes sent on success or a negative error code. */ int nl_send(struct nl_sock *sk, struct nl_msg *msg) { - struct iovec iov = { - .iov_base = (void *) nlmsg_hdr(msg), - .iov_len = nlmsg_hdr(msg)->nlmsg_len, - }; + struct nl_cb *cb = sk->s_cb; - return nl_send_iovec(sk, msg, &iov, 1); + if (cb->cb_send_ow) + return cb->cb_send_ow(sk, msg); + else { + struct iovec iov = { + .iov_base = (void *) nlmsg_hdr(msg), + .iov_len = nlmsg_hdr(msg)->nlmsg_len, + }; + + return nl_send_iovec(sk, msg, &iov, 1); + } } /** @@ -411,14 +422,9 @@ void nl_complete_msg(struct nl_sock *sk, struct nl_msg *msg) */ int nl_send_auto(struct nl_sock *sk, struct nl_msg *msg) { - struct nl_cb *cb = sk->s_cb; - nl_complete_msg(sk, msg); - if (cb->cb_send_ow) - return cb->cb_send_ow(sk, msg); - else - return nl_send(sk, msg); + return nl_send(sk, msg); } /** From b28c25eb236c535017a0d17ceca02f277e20953f Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 8 Nov 2012 13:41:54 +0100 Subject: [PATCH 302/432] nl: Improve API doc of nl_connect() and nl_close() Signed-off-by: Thomas Graf --- lib/nl.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/lib/nl.c b/lib/nl.c index efdd095..4e8b992 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -62,18 +62,25 @@ */ /** - * Create and connect netlink socket. - * @arg sk Netlink socket. - * @arg protocol Netlink protocol to use. + * Create file descriptor and bind socket. + * @arg sk Netlink socket (required) + * @arg protocol Netlink protocol to use (required) * - * Creates a netlink socket using the specified protocol, binds the socket - * and issues a connection attempt. + * Creates a new Netlink socket using `socket()` and binds the socket to the + * protocol and local port specified in the `sk` socket object. Fails if + * the socket is already connected. * - * This function fail if socket is already connected. + * @note If available, the `close-on-exec` (`SOCK_CLOEXEC`) feature is enabled + * automatically on the new file descriptor. This causes the socket to + * be closed automatically if any of the `exec` family functions succeed. + * This is essential for multi threaded programs. * - * @note SOCK_CLOEXEC is set on the socket if available. + * @see nl_socket_alloc() + * @see nl_close() * * @return 0 on success or a negative error code. + * + * @retval -NLE_BAD_SOCK Socket is already connected */ int nl_connect(struct nl_sock *sk, int protocol) { @@ -137,8 +144,15 @@ errout: } /** - * Close/Disconnect netlink socket. - * @arg sk Netlink socket. + * Close Netlink socket + * @arg sk Netlink socket (required) + * + * Closes the Netlink socket using `close()`. + * + * @note The socket is closed automatically if a `struct nl_sock` object is + * freed using `nl_socket_free()`. + * + * @see nl_connect() */ void nl_close(struct nl_sock *sk) { From 665464cde54e9c31f0efa67799b3d4f254a072e2 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 8 Nov 2012 21:17:32 +0100 Subject: [PATCH 303/432] nl: Improve API doc of nl_send_simple() Signed-off-by: Thomas Graf --- lib/nl.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/lib/nl.c b/lib/nl.c index 4e8b992..ec1db01 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -479,18 +479,24 @@ int nl_send_sync(struct nl_sock *sk, struct nl_msg *msg) } /** - * Send simple netlink message using nl_send_auto_complete() - * @arg sk Netlink socket. - * @arg type Netlink message type. - * @arg flags Netlink message flags. - * @arg buf Data buffer. - * @arg size Size of data buffer. + * Construct and transmit a Netlink message + * @arg sk Netlink socket (required) + * @arg type Netlink message type (required) + * @arg flags Netlink message flags (optional) + * @arg buf Data buffer (optional) + * @arg size Size of data buffer (optional) * - * Builds a netlink message with the specified type and flags and - * appends the specified data as payload to the message. + * Allocates a new Netlink message based on `type` and `flags`. If `buf` + * points to payload of length `size` that payload will be appended to the + * message. + * + * Sends out the message using `nl_send_auto()` and frees the message + * afterwards. + * + * @see nl_send_auto() * - * @see nl_send_auto_complete() * @return Number of characters sent on success or a negative error code. + * @retval -NLE_NOMEM Unable to allocate Netlink message */ int nl_send_simple(struct nl_sock *sk, int type, int flags, void *buf, size_t size) @@ -507,9 +513,8 @@ int nl_send_simple(struct nl_sock *sk, int type, int flags, void *buf, if (err < 0) goto errout; } - - err = nl_send_auto_complete(sk, msg); + err = nl_send_auto(sk, msg); errout: nlmsg_free(msg); From a8741fab8e48e55fe10cfb080ba4b28ed4441fb0 Mon Sep 17 00:00:00 2001 From: roopa Date: Fri, 9 Nov 2012 14:41:31 -0800 Subject: [PATCH 304/432] Add hash function This patch adds a hash function for hashing libnl objects. This hash function is from: http://ccodearchive.net/info/hash.html The original code was modified to remove unwanted dependencies, unwanted code and fixes to header file locations One requirement with this hash function is, hashing over multiple fields of an un-packed struct requires that the struct be zeroed, otherwise random padding bytes will change the hash. Signed-off-by: Shrijeet Mukherjee Signed-off-by: Nolan Leake Signed-off-by: Roopa Prabhu Reviewed-by: Wilson Kok Signed-off-by: Thomas Graf --- include/netlink/hash.h | 69 ++++++ lib/Makefile.am | 2 +- lib/hash.c | 482 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 552 insertions(+), 1 deletion(-) create mode 100644 include/netlink/hash.h create mode 100644 lib/hash.c diff --git a/include/netlink/hash.h b/include/netlink/hash.h new file mode 100644 index 0000000..8ca1f5b --- /dev/null +++ b/include/netlink/hash.h @@ -0,0 +1,69 @@ +/* + * This file was taken from http://ccodearchive.net/info/hash.html + * Changes to the original file include cleanups and removal of unwanted code + * and also code that depended on build_asert + */ +#ifndef CCAN_HASH_H +#define CCAN_HASH_H +#include +#include +#include + +/* Stolen mostly from: lookup3.c, by Bob Jenkins, May 2006, Public Domain. + * + * http://burtleburtle.net/bob/c/lookup3.c + */ + +#ifdef __LITTLE_ENDIAN +# define HAVE_LITTLE_ENDIAN 1 +#elif __BIG_ENDIAN +# define HAVE_BIG_ENDIAN 1 +#else +#error Unknown endianness. Failure in endian.h +#endif + +/** + * hash - fast hash of an array for internal use + * @p: the array or pointer to first element + * @num: the number of elements to hash + * @base: the base number to roll into the hash (usually 0) + * + * The memory region pointed to by p is combined with the base to form + * a 32-bit hash. + * + * This hash will have different results on different machines, so is + * only useful for internal hashes (ie. not hashes sent across the + * network or saved to disk). + * + * It may also change with future versions: it could even detect at runtime + * what the fastest hash to use is. + * + * See also: hash64, hash_stable. + * + * Example: + * #include + * #include + * #include + * #include + * + * // Simple demonstration: idential strings will have the same hash, but + * // two different strings will probably not. + * int main(int argc, char *argv[]) + * { + * uint32_t hash1, hash2; + * + * if (argc != 3) + * err(1, "Usage: %s ", argv[0]); + * + * hash1 = hash(argv[1], strlen(argv[1]), 0); + * hash2 = hash(argv[2], strlen(argv[2]), 0); + * printf("Hash is %s\n", hash1 == hash2 ? "same" : "different"); + * return 0; + * } + */ +#define hash(p, num, base) hash_any((p), (num)*sizeof(*(p)), (base)) + +/* Our underlying operations. */ +uint32_t hash_any(const void *key, size_t length, uint32_t base); + +#endif /* HASH_H */ diff --git a/lib/Makefile.am b/lib/Makefile.am index e31e594..c79ba29 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -18,7 +18,7 @@ lib_LTLIBRARIES = \ libnl_3_la_SOURCES = \ addr.c attr.c cache.c cache_mngr.c cache_mngt.c data.c \ error.c handlers.c msg.c nl.c object.c socket.c utils.c \ - version.c + version.c hash.c libnl_genl_3_la_LIBADD = libnl-3.la libnl_genl_3_la_SOURCES = \ diff --git a/lib/hash.c b/lib/hash.c new file mode 100644 index 0000000..6fdf2b8 --- /dev/null +++ b/lib/hash.c @@ -0,0 +1,482 @@ +/* + * This code was taken from http://ccodearchive.net/info/hash.html + * The original file was modified to remove unwanted code + * and some changes to fit the current build environment + */ +/* +------------------------------------------------------------------------------- +lookup3.c, by Bob Jenkins, May 2006, Public Domain. + +These are functions for producing 32-bit hashes for hash table lookup. +hash_word(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() +are externally useful functions. Routines to test the hash are included +if SELF_TEST is defined. You can use this free for any purpose. It's in +the public domain. It has no warranty. + +You probably want to use hashlittle(). hashlittle() and hashbig() +hash byte arrays. hashlittle() is is faster than hashbig() on +little-endian machines. Intel and AMD are little-endian machines. +On second thought, you probably want hashlittle2(), which is identical to +hashlittle() except it returns two 32-bit hashes for the price of one. +You could implement hashbig2() if you wanted but I haven't bothered here. + +If you want to find a hash of, say, exactly 7 integers, do + a = i1; b = i2; c = i3; + mix(a,b,c); + a += i4; b += i5; c += i6; + mix(a,b,c); + a += i7; + final(a,b,c); +then use c as the hash value. If you have a variable length array of +4-byte integers to hash, use hash_word(). If you have a byte array (like +a character string), use hashlittle(). If you have several byte arrays, or +a mix of things, see the comments above hashlittle(). + +Why is this so big? I read 12 bytes at a time into 3 4-byte integers, +then mix those integers. This is fast (you can do a lot more thorough +mixing with 12*3 instructions on 3 integers than you can with 3 instructions +on 1 byte), but shoehorning those bytes into integers efficiently is messy. +------------------------------------------------------------------------------- +*/ +#include + +#if HAVE_LITTLE_ENDIAN +#define HASH_LITTLE_ENDIAN 1 +#define HASH_BIG_ENDIAN 0 +#elif HAVE_BIG_ENDIAN +#define HASH_LITTLE_ENDIAN 0 +#define HASH_BIG_ENDIAN 1 +#else +#error Unknown endian +#endif + +#define hashsize(n) ((uint32_t)1<<(n)) +#define hashmask(n) (hashsize(n)-1) +#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) + +/* +------------------------------------------------------------------------------- +mix -- mix 3 32-bit values reversibly. + +This is reversible, so any information in (a,b,c) before mix() is +still in (a,b,c) after mix(). + +If four pairs of (a,b,c) inputs are run through mix(), or through +mix() in reverse, there are at least 32 bits of the output that +are sometimes the same for one pair and different for another pair. +This was tested for: +* pairs that differed by one bit, by two bits, in any combination + of top bits of (a,b,c), or in any combination of bottom bits of + (a,b,c). +* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed + the output delta to a Gray code (a^(a>>1)) so a string of 1's (as + is commonly produced by subtraction) look like a single 1-bit + difference. +* the base values were pseudorandom, all zero but one bit set, or + all zero plus a counter that starts at zero. + +Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that +satisfy this are + 4 6 8 16 19 4 + 9 15 3 18 27 15 + 14 9 3 7 17 3 +Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing +for "differ" defined as + with a one-bit base and a two-bit delta. I +used http://burtleburtle.net/bob/hash/avalanche.html to choose +the operations, constants, and arrangements of the variables. + +This does not achieve avalanche. There are input bits of (a,b,c) +that fail to affect some output bits of (a,b,c), especially of a. The +most thoroughly mixed value is c, but it doesn't really even achieve +avalanche in c. + +This allows some parallelism. Read-after-writes are good at doubling +the number of bits affected, so the goal of mixing pulls in the opposite +direction as the goal of parallelism. I did what I could. Rotates +seem to cost as much as shifts on every machine I could lay my hands +on, and rotates are much kinder to the top and bottom bits, so I used +rotates. +------------------------------------------------------------------------------- +*/ +#define mix(a,b,c) \ +{ \ + a -= c; a ^= rot(c, 4); c += b; \ + b -= a; b ^= rot(a, 6); a += c; \ + c -= b; c ^= rot(b, 8); b += a; \ + a -= c; a ^= rot(c,16); c += b; \ + b -= a; b ^= rot(a,19); a += c; \ + c -= b; c ^= rot(b, 4); b += a; \ +} + +/* +------------------------------------------------------------------------------- +final -- final mixing of 3 32-bit values (a,b,c) into c + +Pairs of (a,b,c) values differing in only a few bits will usually +produce values of c that look totally different. This was tested for +* pairs that differed by one bit, by two bits, in any combination + of top bits of (a,b,c), or in any combination of bottom bits of + (a,b,c). +* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed + the output delta to a Gray code (a^(a>>1)) so a string of 1's (as + is commonly produced by subtraction) look like a single 1-bit + difference. +* the base values were pseudorandom, all zero but one bit set, or + all zero plus a counter that starts at zero. + +These constants passed: + 14 11 25 16 4 14 24 + 12 14 25 16 4 14 24 +and these came close: + 4 8 15 26 3 22 24 + 10 8 15 26 3 22 24 + 11 8 15 26 3 22 24 +------------------------------------------------------------------------------- +*/ +#define final(a,b,c) \ +{ \ + c ^= b; c -= rot(b,14); \ + a ^= c; a -= rot(c,11); \ + b ^= a; b -= rot(a,25); \ + c ^= b; c -= rot(b,16); \ + a ^= c; a -= rot(c,4); \ + b ^= a; b -= rot(a,14); \ + c ^= b; c -= rot(b,24); \ +} + +/* +------------------------------------------------------------------------------- +hashlittle() -- hash a variable-length key into a 32-bit value + k : the key (the unaligned variable-length array of bytes) + length : the length of the key, counting by bytes + val2 : IN: can be any 4-byte value OUT: second 32 bit hash. +Returns a 32-bit value. Every bit of the key affects every bit of +the return value. Two keys differing by one or two bits will have +totally different hash values. Note that the return value is better +mixed than val2, so use that first. + +The best hash table sizes are powers of 2. There is no need to do +mod a prime (mod is sooo slow!). If you need less than 32 bits, +use a bitmask. For example, if you need only 10 bits, do + h = (h & hashmask(10)); +In which case, the hash table should have hashsize(10) elements. + +If you are hashing n strings (uint8_t **)k, do it like this: + for (i=0, h=0; i 12) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 12; + k += 3; + } + + /*----------------------------- handle the last (probably partial) block */ + /* + * "k[2]&0xffffff" actually reads beyond the end of the string, but + * then masks off the part it's not allowed to read. Because the + * string is aligned, the masked-off tail is in the same word as the + * rest of the string. Every machine with memory protection I've seen + * does it on word boundaries, so is OK with this. But VALGRIND will + * still catch it and complain. The masking trick does make the hash + * noticably faster for short strings (like English words). + * + * Not on my testing with gcc 4.5 on an intel i5 CPU, at least --RR. + */ +#if 0 + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break; + case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break; + case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break; + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=k[1]&0xffffff; a+=k[0]; break; + case 6 : b+=k[1]&0xffff; a+=k[0]; break; + case 5 : b+=k[1]&0xff; a+=k[0]; break; + case 4 : a+=k[0]; break; + case 3 : a+=k[0]&0xffffff; break; + case 2 : a+=k[0]&0xffff; break; + case 1 : a+=k[0]&0xff; break; + case 0 : return c; /* zero length strings require no mixing */ + } + +#else /* make valgrind happy */ + + k8 = (const uint8_t *)k; + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ + case 10: c+=((uint32_t)k8[9])<<8; /* fall through */ + case 9 : c+=k8[8]; /* fall through */ + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ + case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */ + case 5 : b+=k8[4]; /* fall through */ + case 4 : a+=k[0]; break; + case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ + case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */ + case 1 : a+=k8[0]; break; + case 0 : return c; + } + +#endif /* !valgrind */ + + } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { + const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ + const uint8_t *k8; + + /*--------------- all but last block: aligned reads and different mixing */ + while (length > 12) + { + a += k[0] + (((uint32_t)k[1])<<16); + b += k[2] + (((uint32_t)k[3])<<16); + c += k[4] + (((uint32_t)k[5])<<16); + mix(a,b,c); + length -= 12; + k += 6; + } + + /*----------------------------- handle the last (probably partial) block */ + k8 = (const uint8_t *)k; + switch(length) + { + case 12: c+=k[4]+(((uint32_t)k[5])<<16); + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ + case 10: c+=k[4]; + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 9 : c+=k8[8]; /* fall through */ + case 8 : b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ + case 6 : b+=k[2]; + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 5 : b+=k8[4]; /* fall through */ + case 4 : a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ + case 2 : a+=k[0]; + break; + case 1 : a+=k8[0]; + break; + case 0 : return c; /* zero length requires no mixing */ + } + + } else { /* need to read the key one byte at a time */ + const uint8_t *k = (const uint8_t *)key; + + /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0]; + a += ((uint32_t)k[1])<<8; + a += ((uint32_t)k[2])<<16; + a += ((uint32_t)k[3])<<24; + b += k[4]; + b += ((uint32_t)k[5])<<8; + b += ((uint32_t)k[6])<<16; + b += ((uint32_t)k[7])<<24; + c += k[8]; + c += ((uint32_t)k[9])<<8; + c += ((uint32_t)k[10])<<16; + c += ((uint32_t)k[11])<<24; + mix(a,b,c); + length -= 12; + k += 12; + } + + /*-------------------------------- last block: affect all 32 bits of (c) */ + switch(length) /* all the case statements fall through */ + { + case 12: c+=((uint32_t)k[11])<<24; + case 11: c+=((uint32_t)k[10])<<16; + case 10: c+=((uint32_t)k[9])<<8; + case 9 : c+=k[8]; + case 8 : b+=((uint32_t)k[7])<<24; + case 7 : b+=((uint32_t)k[6])<<16; + case 6 : b+=((uint32_t)k[5])<<8; + case 5 : b+=k[4]; + case 4 : a+=((uint32_t)k[3])<<24; + case 3 : a+=((uint32_t)k[2])<<16; + case 2 : a+=((uint32_t)k[1])<<8; + case 1 : a+=k[0]; + break; + case 0 : return c; + } + } + + final(a,b,c); + *val2 = b; + return c; +} + +/* + * hashbig(): + * This is the same as hash_word() on big-endian machines. It is different + * from hashlittle() on all machines. hashbig() takes advantage of + * big-endian byte ordering. + */ +static uint32_t hashbig( const void *key, size_t length, uint32_t *val2) +{ + uint32_t a,b,c; + union { const void *ptr; size_t i; } u; /* to cast key to (size_t) happily */ + + /* Set up the internal state */ + a = b = c = 0xdeadbeef + ((uint32_t)length) + *val2; + + u.ptr = key; + if (HASH_BIG_ENDIAN && ((u.i & 0x3) == 0)) { + const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */ + const uint8_t *k8; + + /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 12; + k += 3; + } + + /*----------------------------- handle the last (probably partial) block */ + /* + * "k[2]<<8" actually reads beyond the end of the string, but + * then shifts out the part it's not allowed to read. Because the + * string is aligned, the illegal read is in the same word as the + * rest of the string. Every machine with memory protection I've seen + * does it on word boundaries, so is OK with this. But VALGRIND will + * still catch it and complain. The masking trick does make the hash + * noticably faster for short strings (like English words). + * + * Not on my testing with gcc 4.5 on an intel i5 CPU, at least --RR. + */ +#if 0 + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=k[2]&0xffffff00; b+=k[1]; a+=k[0]; break; + case 10: c+=k[2]&0xffff0000; b+=k[1]; a+=k[0]; break; + case 9 : c+=k[2]&0xff000000; b+=k[1]; a+=k[0]; break; + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=k[1]&0xffffff00; a+=k[0]; break; + case 6 : b+=k[1]&0xffff0000; a+=k[0]; break; + case 5 : b+=k[1]&0xff000000; a+=k[0]; break; + case 4 : a+=k[0]; break; + case 3 : a+=k[0]&0xffffff00; break; + case 2 : a+=k[0]&0xffff0000; break; + case 1 : a+=k[0]&0xff000000; break; + case 0 : return c; /* zero length strings require no mixing */ + } + +#else /* make valgrind happy */ + + k8 = (const uint8_t *)k; + switch(length) /* all the case statements fall through */ + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=((uint32_t)k8[10])<<8; /* fall through */ + case 10: c+=((uint32_t)k8[9])<<16; /* fall through */ + case 9 : c+=((uint32_t)k8[8])<<24; /* fall through */ + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=((uint32_t)k8[6])<<8; /* fall through */ + case 6 : b+=((uint32_t)k8[5])<<16; /* fall through */ + case 5 : b+=((uint32_t)k8[4])<<24; /* fall through */ + case 4 : a+=k[0]; break; + case 3 : a+=((uint32_t)k8[2])<<8; /* fall through */ + case 2 : a+=((uint32_t)k8[1])<<16; /* fall through */ + case 1 : a+=((uint32_t)k8[0])<<24; break; + case 0 : return c; + } + +#endif /* !VALGRIND */ + + } else { /* need to read the key one byte at a time */ + const uint8_t *k = (const uint8_t *)key; + + /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ + while (length > 12) + { + a += ((uint32_t)k[0])<<24; + a += ((uint32_t)k[1])<<16; + a += ((uint32_t)k[2])<<8; + a += ((uint32_t)k[3]); + b += ((uint32_t)k[4])<<24; + b += ((uint32_t)k[5])<<16; + b += ((uint32_t)k[6])<<8; + b += ((uint32_t)k[7]); + c += ((uint32_t)k[8])<<24; + c += ((uint32_t)k[9])<<16; + c += ((uint32_t)k[10])<<8; + c += ((uint32_t)k[11]); + mix(a,b,c); + length -= 12; + k += 12; + } + + /*-------------------------------- last block: affect all 32 bits of (c) */ + switch(length) /* all the case statements fall through */ + { + case 12: c+=k[11]; + case 11: c+=((uint32_t)k[10])<<8; + case 10: c+=((uint32_t)k[9])<<16; + case 9 : c+=((uint32_t)k[8])<<24; + case 8 : b+=k[7]; + case 7 : b+=((uint32_t)k[6])<<8; + case 6 : b+=((uint32_t)k[5])<<16; + case 5 : b+=((uint32_t)k[4])<<24; + case 4 : a+=k[3]; + case 3 : a+=((uint32_t)k[2])<<8; + case 2 : a+=((uint32_t)k[1])<<16; + case 1 : a+=((uint32_t)k[0])<<24; + break; + case 0 : return c; + } + } + + final(a,b,c); + *val2 = b; + return c; +} + +uint32_t hash_any(const void *key, size_t length, uint32_t base) +{ + if (HASH_BIG_ENDIAN) + return hashbig(key, length, &base); + else + return hashlittle(key, length, &base); +} From c6f89ed02f04ac4984be34418774a7b06ff54f79 Mon Sep 17 00:00:00 2001 From: roopa Date: Fri, 9 Nov 2012 14:41:32 -0800 Subject: [PATCH 305/432] Add nl hashtable structures and access functions This patch adds the required structures and access functions to create and manage hashtables for netlink cache objects Signed-off-by: Shrijeet Mukherjee Signed-off-by: Nolan Leake Signed-off-by: Roopa Prabhu Reviewed-by: Wilson Kok Signed-off-by: Thomas Graf --- include/netlink/hashtable.h | 52 +++++++++++++ include/netlink/object-api.h | 10 +++ include/netlink/object.h | 2 + lib/Makefile.am | 2 +- lib/hashtable.c | 141 +++++++++++++++++++++++++++++++++++ lib/object.c | 21 ++++++ 6 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 include/netlink/hashtable.h create mode 100644 lib/hashtable.c diff --git a/include/netlink/hashtable.h b/include/netlink/hashtable.h new file mode 100644 index 0000000..d9e6ee4 --- /dev/null +++ b/include/netlink/hashtable.h @@ -0,0 +1,52 @@ +/* + * netlink/hashtable.h Netlink hashtable Utilities + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2012 Cumulus Networks, Inc + */ + +#ifndef NETLINK_HASHTABLE_H_ +#define NETLINK_HASHTABLE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct nl_hash_node { + uint32_t key; + uint32_t key_size; + struct nl_object * obj; + struct nl_hash_node * next; +} nl_hash_node_t; + +typedef struct nl_hash_table { + int size; + nl_hash_node_t ** nodes; +} nl_hash_table_t; + +/* Default hash table size */ +#define NL_MAX_HASH_ENTRIES 1024 + +/* Access Functions */ +extern nl_hash_table_t * nl_hash_table_alloc(int size); +extern void nl_hash_table_free(nl_hash_table_t *ht); + +extern int nl_hash_table_add(nl_hash_table_t *ht, + struct nl_object *obj); +extern int nl_hash_table_del(nl_hash_table_t *ht, + struct nl_object *obj); + +extern struct nl_object * nl_hash_table_lookup(nl_hash_table_t *ht, + struct nl_object *obj); +extern uint32_t nl_hash(void *k, size_t length, + uint32_t initval); + +#ifdef __cplusplus +} +#endif + +#endif /* NETLINK_HASHTABLE_H_ */ diff --git a/include/netlink/object-api.h b/include/netlink/object-api.h index ec2192b..ae6180a 100644 --- a/include/netlink/object-api.h +++ b/include/netlink/object-api.h @@ -348,6 +348,16 @@ struct nl_object_ops */ int (*oo_update)(struct nl_object *, struct nl_object *); + /** + * Hash Key generator function + * + * When called returns a hash key for the object being + * referenced. This key will be used by higher level hash functions + * to build association lists. Each object type gets to specify + * it's own key formulation + */ + void (*oo_keygen)(struct nl_object *, uint32_t *, uint32_t); + char *(*oo_attrs2str)(int, char *, size_t); /** diff --git a/include/netlink/object.h b/include/netlink/object.h index 788ae48..f25713e 100644 --- a/include/netlink/object.h +++ b/include/netlink/object.h @@ -50,6 +50,8 @@ extern char * nl_object_attrs2str(struct nl_object *, size_t); extern char * nl_object_attr_list(struct nl_object *, char *, size_t); +extern void nl_object_keygen(struct nl_object *, + uint32_t *, uint32_t); /* Marks */ extern void nl_object_mark(struct nl_object *); diff --git a/lib/Makefile.am b/lib/Makefile.am index c79ba29..7481941 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -18,7 +18,7 @@ lib_LTLIBRARIES = \ libnl_3_la_SOURCES = \ addr.c attr.c cache.c cache_mngr.c cache_mngt.c data.c \ error.c handlers.c msg.c nl.c object.c socket.c utils.c \ - version.c hash.c + version.c hash.c hashtable.c libnl_genl_3_la_LIBADD = libnl-3.la libnl_genl_3_la_SOURCES = \ diff --git a/lib/hashtable.c b/lib/hashtable.c new file mode 100644 index 0000000..59cd91e --- /dev/null +++ b/lib/hashtable.c @@ -0,0 +1,141 @@ +/* + * netlink/hashtable.c Netlink hashtable Utilities + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2012 Cumulus Networks, Inc + */ +#include +#include +#include +#include +#include + +nl_hash_table_t *nl_hash_table_alloc(int size) +{ + nl_hash_table_t *ht; + + ht = calloc(1, sizeof (*ht)); + if (!ht) + goto errout; + + ht->nodes = calloc(size, sizeof (*ht->nodes)); + if (!ht->nodes) { + free(ht); + goto errout; + } + + ht->size = size; + + return ht; +errout: + return NULL; +} + +void nl_hash_table_free(nl_hash_table_t *ht) +{ + int i; + + for(i = 0; i < ht->size; i++) { + nl_hash_node_t *node = ht->nodes[i]; + nl_hash_node_t *saved_node; + + while (node) { + saved_node = node; + node = node->next; + free(saved_node); + } + } + + free(ht->nodes); + free(ht); +} + +struct nl_object* nl_hash_table_lookup(nl_hash_table_t *ht, + struct nl_object *obj) +{ + nl_hash_node_t *node; + uint32_t key_hash; + + nl_object_keygen(obj, &key_hash, ht->size); + node = ht->nodes[key_hash]; + + while (node) { + if (nl_object_identical(node->obj, obj)) + return node->obj; + node = node->next; + } + + return NULL; +} + +int nl_hash_table_add(nl_hash_table_t *ht, struct nl_object *obj) +{ + nl_hash_node_t *node; + uint32_t key_hash; + + nl_object_keygen(obj, &key_hash, ht->size); + node = ht->nodes[key_hash]; + + while (node) { + if (nl_object_identical(node->obj, obj)) { + NL_DBG(2, "Warning: Add to hashtable found duplicate...\n"); + return -NLE_EXIST; + } + node = node->next; + } + + NL_DBG (5, "adding cache entry of obj %p in table %p, with hash 0x%x\n", + obj, ht, key_hash); + + node = malloc(sizeof(nl_hash_node_t)); + if (!node) + return -NLE_NOMEM; + nl_object_get(obj); + node->obj = obj; + node->key = key_hash; + node->key_size = sizeof(uint32_t); + node->next = ht->nodes[key_hash]; + ht->nodes[key_hash] = node; + + return 0; +} + +int nl_hash_table_del(nl_hash_table_t *ht, struct nl_object *obj) +{ + nl_hash_node_t *node, *prev; + uint32_t key_hash; + + nl_object_keygen(obj, &key_hash, ht->size); + prev = node = ht->nodes[key_hash]; + + while (node) { + if (nl_object_identical(node->obj, obj)) { + nl_object_put(obj); + + NL_DBG (5, "deleting cache entry of obj %p in table %p, with" + " hash 0x%x\n", obj, ht, key_hash); + + if (node == ht->nodes[key_hash]) + ht->nodes[key_hash] = node->next; + else + prev->next = node->next; + + free(node); + + return 0; + } + prev = node; + node = node->next; + } + + return -1; +} + +uint32_t nl_hash(void *k, size_t length, uint32_t initval) +{ + return(hash(k, length, initval)); +} diff --git a/lib/object.c b/lib/object.c index d58f9a7..024062e 100644 --- a/lib/object.c +++ b/lib/object.c @@ -413,6 +413,27 @@ char *nl_object_attr_list(struct nl_object *obj, char *buf, size_t len) return nl_object_attrs2str(obj, obj->ce_mask, buf, len); } +/** + * Generate object hash key + * @arg obj the object + * @arg hashkey destination buffer to be used for key stream + * @arg hashtbl_sz hash table size + * + * @return hash key in destination buffer + */ +void nl_object_keygen(struct nl_object *obj, uint32_t *hashkey, + uint32_t hashtbl_sz) +{ + struct nl_object_ops *ops = obj_ops(obj); + + if (ops->oo_keygen) + ops->oo_keygen(obj, hashkey, hashtbl_sz); + else + *hashkey = 0; + + return; +} + /** @} */ /** From 55c0e036b04b567a81cca441117b4e2ce5e22ef2 Mon Sep 17 00:00:00 2001 From: roopa Date: Fri, 9 Nov 2012 14:41:33 -0800 Subject: [PATCH 306/432] Add hash support in cache mngr This patch adds support to create, delete modify hash table for a cache Signed-off-by: Shrijeet Mukherjee Signed-off-by: Nolan Leake Signed-off-by: Roopa Prabhu Reviewed-by: Wilson Kok Signed-off-by: Thomas Graf --- include/netlink-types.h | 2 ++ include/netlink/cache-api.h | 3 ++ include/netlink/cache.h | 2 ++ lib/cache.c | 71 +++++++++++++++++++++++++++++++++++-- 4 files changed, 75 insertions(+), 3 deletions(-) diff --git a/include/netlink-types.h b/include/netlink-types.h index 23930b8..0be58d1 100644 --- a/include/netlink-types.h +++ b/include/netlink-types.h @@ -30,6 +30,7 @@ struct nl_cache_ops; struct nl_sock; struct nl_object; +struct nl_hash_table; struct nl_cb { @@ -78,6 +79,7 @@ struct nl_cache int c_nitems; int c_iarg1; int c_iarg2; + struct nl_hash_table * hashtable; struct nl_cache_ops * c_ops; }; diff --git a/include/netlink/cache-api.h b/include/netlink/cache-api.h index 390cbea..aa5eeb6 100644 --- a/include/netlink/cache-api.h +++ b/include/netlink/cache-api.h @@ -186,6 +186,9 @@ struct nl_cache_ops /** Netlink protocol */ int co_protocol; + /** cache object hash size **/ + int co_hash_size; + /** Group definition */ struct nl_af_group * co_groups; diff --git a/include/netlink/cache.h b/include/netlink/cache.h index fd137e1..c919e6b 100644 --- a/include/netlink/cache.h +++ b/include/netlink/cache.h @@ -71,6 +71,8 @@ extern void nl_cache_set_arg2(struct nl_cache *, int); extern int nl_cache_is_empty(struct nl_cache *); extern struct nl_object * nl_cache_search(struct nl_cache *, struct nl_object *); +extern struct nl_object * nl_cache_lookup(struct nl_cache *, + struct nl_object *); extern void nl_cache_mark_all(struct nl_cache *); /* Dumping */ diff --git a/lib/cache.c b/lib/cache.c index f73fedf..af4ee95 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -53,6 +53,7 @@ #include #include #include +#include #include /** @@ -190,6 +191,22 @@ struct nl_cache *nl_cache_alloc(struct nl_cache_ops *ops) nl_init_list_head(&cache->c_items); cache->c_ops = ops; + /* + * If object type provides a hash keygen + * functions, allocate a hash table for the + * cache objects for faster lookups + */ + if (ops->co_obj_ops->oo_keygen) { + int hashtable_size; + + if (ops->co_hash_size) + hashtable_size = ops->co_hash_size; + else + hashtable_size = NL_MAX_HASH_ENTRIES; + + cache->hashtable = nl_hash_table_alloc(hashtable_size); + } + NL_DBG(2, "Allocated cache %p <%s>.\n", cache, nl_cache_name(cache)); return cache; @@ -362,6 +379,10 @@ void nl_cache_free(struct nl_cache *cache) return; nl_cache_clear(cache); + + if (cache->hashtable) + nl_hash_table_free(cache->hashtable); + NL_DBG(1, "Freeing cache %p <%s>...\n", cache, nl_cache_name(cache)); free(cache); } @@ -375,8 +396,18 @@ void nl_cache_free(struct nl_cache *cache) static int __cache_add(struct nl_cache *cache, struct nl_object *obj) { + int ret; + obj->ce_cache = cache; + if (cache->hashtable) { + ret = nl_hash_table_add(cache->hashtable, obj); + if (ret < 0) { + obj->ce_cache = NULL; + return ret; + } + } + nl_list_add_tail(&obj->ce_list, &cache->c_items); cache->c_nitems++; @@ -411,6 +442,7 @@ static int __cache_add(struct nl_cache *cache, struct nl_object *obj) int nl_cache_add(struct nl_cache *cache, struct nl_object *obj) { struct nl_object *new; + int ret = 0; if (cache->c_ops->co_obj_ops != obj->ce_ops) return -NLE_OBJ_MISMATCH; @@ -424,7 +456,11 @@ int nl_cache_add(struct nl_cache *cache, struct nl_object *obj) new = obj; } - return __cache_add(cache, new); + ret = __cache_add(cache, new); + if (ret < 0) + nl_object_put(new); + + return ret; } /** @@ -474,11 +510,19 @@ int nl_cache_move(struct nl_cache *cache, struct nl_object *obj) */ void nl_cache_remove(struct nl_object *obj) { + int ret; struct nl_cache *cache = obj->ce_cache; if (cache == NULL) return; + if (cache->hashtable) { + ret = nl_hash_table_del(cache->hashtable, obj); + if (ret < 0) + NL_DBG(3, "Failed to delete %p from cache %p <%s>.\n", + obj, cache, nl_cache_name(cache)); + } + nl_list_del(&obj->ce_list); obj->ce_cache = NULL; nl_object_put(obj); @@ -566,8 +610,13 @@ struct update_xdata { static int update_msg_parser(struct nl_msg *msg, void *arg) { struct update_xdata *x = arg; - - return nl_cache_parse(x->ops, &msg->nm_src, msg->nm_nlh, x->params); + int ret = 0; + + ret = nl_cache_parse(x->ops, &msg->nm_src, msg->nm_nlh, x->params); + if (ret == -NLE_EXIST) + return NL_SKIP; + else + return ret; } /** @endcond */ @@ -842,6 +891,19 @@ restart: * @name Utillities * @{ */ +static struct nl_object *__cache_fast_lookup(struct nl_cache *cache, + struct nl_object *needle) +{ + struct nl_object *obj; + + obj = nl_hash_table_lookup(cache->hashtable, needle); + if (obj) { + nl_object_get(obj); + return obj; + } + + return NULL; +} /** * Search object in cache @@ -863,6 +925,9 @@ struct nl_object *nl_cache_search(struct nl_cache *cache, { struct nl_object *obj; + if (cache->hashtable) + return __cache_fast_lookup(cache, needle); + nl_list_for_each_entry(obj, &cache->c_items, ce_list) { if (nl_object_identical(obj, needle)) { nl_object_get(obj); From e16e8fdcdbacbd8179ec7a53fa678211d79e550e Mon Sep 17 00:00:00 2001 From: roopa Date: Fri, 9 Nov 2012 14:41:34 -0800 Subject: [PATCH 307/432] Add hash support to link cache This patch adds keygen function to link cache Signed-off-by: Shrijeet Mukherjee Signed-off-by: Nolan Leake Signed-off-by: Roopa Prabhu Reviewed-by: Wilson Kok Signed-off-by: Thomas Graf --- lib/route/link.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/lib/route/link.c b/lib/route/link.c index 3f9d9dc..f8646d1 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -799,6 +800,27 @@ static int link_handle_event(struct nl_object *a, struct rtnl_link_event_cb *cb) } #endif + +static void link_keygen(struct nl_object *obj, uint32_t *hashkey, + uint32_t table_sz) +{ + struct rtnl_link *link = (struct rtnl_link *) obj; + unsigned int lkey_sz; + struct link_hash_key { + uint32_t l_index; + } __attribute__((packed)) lkey; + + lkey_sz = sizeof(lkey); + lkey.l_index = link->l_index; + + *hashkey = nl_hash(&lkey, lkey_sz, 0) % table_sz; + + NL_DBG(5, "link %p key (dev %d) keysz %d, hash 0x%x\n", + link, lkey.l_index, lkey_sz, *hashkey); + + return; +} + static int link_compare(struct nl_object *_a, struct nl_object *_b, uint32_t attrs, int flags) { @@ -2500,6 +2522,7 @@ static struct nl_object_ops link_obj_ops = { [NL_DUMP_STATS] = link_dump_stats, }, .oo_compare = link_compare, + .oo_keygen = link_keygen, .oo_attrs2str = link_attrs2str, .oo_id_attrs = LINK_ATTR_IFINDEX, }; From 6f24cf12caae88e1a09f0516e00188966a232290 Mon Sep 17 00:00:00 2001 From: roopa Date: Fri, 9 Nov 2012 14:41:35 -0800 Subject: [PATCH 308/432] Add hash support to neigh cache This patch adds keygen function to the neigh object Signed-off-by: Shrijeet Mukherjee Signed-off-by: Nolan Leake Signed-off-by: Roopa Prabhu Reviewed-by: Wilson Kok Signed-off-by: Thomas Graf --- lib/route/neigh.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/lib/route/neigh.c b/lib/route/neigh.c index bb61571..1986ef5 100644 --- a/lib/route/neigh.c +++ b/lib/route/neigh.c @@ -151,6 +151,7 @@ #include #include #include +#include #include #include #include @@ -197,6 +198,50 @@ static int neigh_clone(struct nl_object *_dst, struct nl_object *_src) return 0; } +static void neigh_keygen(struct nl_object *obj, uint32_t *hashkey, + uint32_t table_sz) +{ + struct rtnl_neigh *neigh = (struct rtnl_neigh *) obj; + unsigned int nkey_sz; + struct nl_addr *addr = NULL; + struct neigh_hash_key { + uint32_t n_family; + uint32_t n_ifindex; + char n_addr[0]; + } __attribute__((packed)) *nkey; + char buf[INET6_ADDRSTRLEN+5]; + + if (neigh->n_dst) + addr = neigh->n_dst; + + nkey_sz = sizeof(*nkey); + if (addr) + nkey_sz += nl_addr_get_len(addr); + + nkey = calloc(1, nkey_sz); + if (!nkey) { + *hashkey = 0; + return; + } + nkey->n_family = neigh->n_family; + nkey->n_ifindex = neigh->n_ifindex; + if (addr) + memcpy(nkey->n_addr, + nl_addr_get_binary_addr(addr), + nl_addr_get_len(addr)); + + *hashkey = nl_hash(nkey, nkey_sz, 0) % table_sz; + + NL_DBG(5, "neigh %p key (fam %d dev %d addr %s) keysz %d hash 0x%x\n", + neigh, nkey->n_family, nkey->n_ifindex, + nl_addr2str(addr, buf, sizeof(buf)), + nkey_sz, *hashkey); + + free(nkey); + + return; +} + static int neigh_compare(struct nl_object *_a, struct nl_object *_b, uint32_t attrs, int flags) { @@ -825,6 +870,7 @@ static struct nl_object_ops neigh_obj_ops = { [NL_DUMP_STATS] = neigh_dump_stats, }, .oo_compare = neigh_compare, + .oo_keygen = neigh_keygen, .oo_attrs2str = neigh_attrs2str, .oo_id_attrs = (NEIGH_ATTR_IFINDEX | NEIGH_ATTR_DST | NEIGH_ATTR_FAMILY), }; From a2207c7beb80050671d209650aaaeba429658e49 Mon Sep 17 00:00:00 2001 From: roopa Date: Fri, 9 Nov 2012 14:41:36 -0800 Subject: [PATCH 309/432] Add hash support to route cache This patch adds keygen function to route object Signed-off-by: Shrijeet Mukherjee Signed-off-by: Nolan Leake Signed-off-by: Roopa Prabhu Reviewed-by: Wilson Kok Signed-off-by: Thomas Graf --- lib/route/route_obj.c | 47 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/lib/route/route_obj.c b/lib/route/route_obj.c index 54df023..0ee9ca0 100644 --- a/lib/route/route_obj.c +++ b/lib/route/route_obj.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -289,6 +290,51 @@ static void route_dump_stats(struct nl_object *obj, struct nl_dump_params *p) } } +static void route_keygen(struct nl_object *obj, uint32_t *hashkey, + uint32_t table_sz) +{ + struct rtnl_route *route = (struct rtnl_route *) obj; + unsigned int rkey_sz; + struct nl_addr *addr = NULL; + struct route_hash_key { + uint8_t rt_family; + uint8_t rt_tos; + uint32_t rt_table; + char rt_addr[0]; + } __attribute__((packed)) *rkey; + char buf[INET6_ADDRSTRLEN+5]; + + if (route->rt_dst) + addr = route->rt_dst; + + rkey_sz = sizeof(*rkey); + if (addr) + rkey_sz += nl_addr_get_len(addr); + rkey = calloc(1, rkey_sz); + if (!rkey) { + NL_DBG(2, "Warning: calloc failed for %d bytes...\n", rkey_sz); + *hashkey = 0; + return; + } + rkey->rt_family = route->rt_family; + rkey->rt_tos = route->rt_tos; + rkey->rt_table = route->rt_table; + if (addr) + memcpy(rkey->rt_addr, nl_addr_get_binary_addr(addr), + nl_addr_get_len(addr)); + + *hashkey = nl_hash(rkey, rkey_sz, 0) % table_sz; + + NL_DBG(5, "route %p key (fam %d tos %d table %d addr %s) keysz %d " + "hash 0x%x\n", route, rkey->rt_family, rkey->rt_tos, + rkey->rt_table, nl_addr2str(addr, buf, sizeof(buf)), + rkey_sz, *hashkey); + + free(rkey); + + return; +} + static int route_compare(struct nl_object *_a, struct nl_object *_b, uint32_t attrs, int flags) { @@ -1151,6 +1197,7 @@ struct nl_object_ops route_obj_ops = { [NL_DUMP_STATS] = route_dump_stats, }, .oo_compare = route_compare, + .oo_keygen = route_keygen, .oo_attrs2str = route_attrs2str, .oo_id_attrs = (ROUTE_ATTR_FAMILY | ROUTE_ATTR_TOS | ROUTE_ATTR_TABLE | ROUTE_ATTR_DST), From 5641c0ea6156fc04abc3c843cf11657718eced68 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 10 Nov 2012 10:20:08 +0100 Subject: [PATCH 310/432] Hash: Properly prefix hash functions Do not pollute public namespace with unprefixed functions. Signed-off-by: Thomas Graf --- include/netlink/hash.h | 8 ++++---- lib/hash.c | 2 +- lib/hashtable.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/netlink/hash.h b/include/netlink/hash.h index 8ca1f5b..0bda74e 100644 --- a/include/netlink/hash.h +++ b/include/netlink/hash.h @@ -55,15 +55,15 @@ * if (argc != 3) * err(1, "Usage: %s ", argv[0]); * - * hash1 = hash(argv[1], strlen(argv[1]), 0); - * hash2 = hash(argv[2], strlen(argv[2]), 0); + * hash1 = __nl_hash(argv[1], strlen(argv[1]), 0); + * hash2 = __nl_hash(argv[2], strlen(argv[2]), 0); * printf("Hash is %s\n", hash1 == hash2 ? "same" : "different"); * return 0; * } */ -#define hash(p, num, base) hash_any((p), (num)*sizeof(*(p)), (base)) +#define __nl_hash(p, num, base) nl_hash_any((p), (num)*sizeof(*(p)), (base)) /* Our underlying operations. */ -uint32_t hash_any(const void *key, size_t length, uint32_t base); +uint32_t nl_hash_any(const void *key, size_t length, uint32_t base); #endif /* HASH_H */ diff --git a/lib/hash.c b/lib/hash.c index 6fdf2b8..47c938b 100644 --- a/lib/hash.c +++ b/lib/hash.c @@ -473,7 +473,7 @@ static uint32_t hashbig( const void *key, size_t length, uint32_t *val2) return c; } -uint32_t hash_any(const void *key, size_t length, uint32_t base) +uint32_t nl_hash_any(const void *key, size_t length, uint32_t base) { if (HASH_BIG_ENDIAN) return hashbig(key, length, &base); diff --git a/lib/hashtable.c b/lib/hashtable.c index 59cd91e..938f2e4 100644 --- a/lib/hashtable.c +++ b/lib/hashtable.c @@ -137,5 +137,5 @@ int nl_hash_table_del(nl_hash_table_t *ht, struct nl_object *obj) uint32_t nl_hash(void *k, size_t length, uint32_t initval) { - return(hash(k, length, initval)); + return(__nl_hash(k, length, initval)); } From ae1e236809d79f932b38a154ba1c2fce75f03701 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 10 Nov 2012 10:50:16 +0100 Subject: [PATCH 311/432] hashtable: Add API reference documentation Signed-off-by: Thomas Graf --- lib/hashtable.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/lib/hashtable.c b/lib/hashtable.c index 938f2e4..5cea985 100644 --- a/lib/hashtable.c +++ b/lib/hashtable.c @@ -14,6 +14,25 @@ #include #include +/** + * @ingroup core_types + * @defgroup hashtable Hashtable + * + * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ + */ + +/** + * Allocate hashtable + * @arg size Size of hashtable in number of elements + * + * @return Allocated hashtable or NULL. + */ nl_hash_table_t *nl_hash_table_alloc(int size) { nl_hash_table_t *ht; @@ -35,6 +54,10 @@ errout: return NULL; } +/** + * Free hashtable including all nodes + * @arg ht Hashtable + */ void nl_hash_table_free(nl_hash_table_t *ht) { int i; @@ -54,6 +77,16 @@ void nl_hash_table_free(nl_hash_table_t *ht) free(ht); } +/** + * Lookup identical object in hashtable + * @arg ht Hashtable + * @arg obj Object to lookup + * + * Generates hashkey for `obj` and traverses the corresponding chain calling + * `nl_object_identical()` on each trying to find a match. + * + * @return Pointer to object if match was found or NULL. + */ struct nl_object* nl_hash_table_lookup(nl_hash_table_t *ht, struct nl_object *obj) { @@ -72,6 +105,19 @@ struct nl_object* nl_hash_table_lookup(nl_hash_table_t *ht, return NULL; } +/** + * Add object to hashtable + * @arg ht Hashtable + * @arg obj Object to add + * + * Adds `obj` to the hashtable. Object type must support hashing, otherwise all + * objects will be added to the chain `0`. + * + * @note The reference counter of the object is incremented. + * + * @return 0 on success or a negative error code + * @retval -NLE_EXIST Identical object already present in hashtable + */ int nl_hash_table_add(nl_hash_table_t *ht, struct nl_object *obj) { nl_hash_node_t *node; @@ -104,6 +150,18 @@ int nl_hash_table_add(nl_hash_table_t *ht, struct nl_object *obj) return 0; } +/** + * Remove object from hashtable + * @arg ht Hashtable + * @arg obj Object to remove + * + * Remove `obj` from hashtable if it exists. + * + * @note Reference counter of object will be decremented. + * + * @return 0 on success or a negative error code. + * @retval -NLE_OBJ_NOTFOUND Object not present in hashtable. + */ int nl_hash_table_del(nl_hash_table_t *ht, struct nl_object *obj) { nl_hash_node_t *node, *prev; @@ -132,10 +190,12 @@ int nl_hash_table_del(nl_hash_table_t *ht, struct nl_object *obj) node = node->next; } - return -1; + return -NLE_OBJ_NOTFOUND; } uint32_t nl_hash(void *k, size_t length, uint32_t initval) { return(__nl_hash(k, length, initval)); } + +/** @} */ From 59a6b003a95cdceb60e17c8cf765efc0d7bec797 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 10 Nov 2012 10:52:26 +0100 Subject: [PATCH 312/432] hashtable: Fix reference leak in nl_hashtable_free() The reference counter of the linked object must be dec'ed before freeing the node or the reference is leaked. Signed-off-by: Thomas Graf --- lib/hashtable.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/hashtable.c b/lib/hashtable.c index 5cea985..6a1e8f5 100644 --- a/lib/hashtable.c +++ b/lib/hashtable.c @@ -57,6 +57,8 @@ errout: /** * Free hashtable including all nodes * @arg ht Hashtable + * + * @note Reference counter of all objects in the hashtable will be decremented. */ void nl_hash_table_free(nl_hash_table_t *ht) { @@ -69,6 +71,7 @@ void nl_hash_table_free(nl_hash_table_t *ht) while (node) { saved_node = node; node = node->next; + nl_object_put(saved_node->obj); free(saved_node); } } From b66d26711a3ff013313edf61e20e5dd1a9784060 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sun, 11 Nov 2012 11:21:10 +0100 Subject: [PATCH 313/432] hashtable: remove doc section crashing doxygen Signed-off-by: Thomas Graf --- lib/hashtable.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/lib/hashtable.c b/lib/hashtable.c index 6a1e8f5..ecd5730 100644 --- a/lib/hashtable.c +++ b/lib/hashtable.c @@ -17,14 +17,7 @@ /** * @ingroup core_types * @defgroup hashtable Hashtable - * * @{ - * - * Header - * ------ - * ~~~~{.c} - * #include - * ~~~~ */ /** From 7e075c600de9619530ab32d13ee931e7393362ea Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sun, 11 Nov 2012 11:21:34 +0100 Subject: [PATCH 314/432] doc: update Doxygen layout file to latest format Sigend-off-by: Thomas Graf --- doc/DoxygenLayout.xml | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/doc/DoxygenLayout.xml b/doc/DoxygenLayout.xml index 680d3da..589d0f1 100644 --- a/doc/DoxygenLayout.xml +++ b/doc/DoxygenLayout.xml @@ -4,18 +4,18 @@ - - + + - - + + - - + + @@ -62,14 +62,15 @@ + + - @@ -89,6 +90,7 @@ + @@ -116,6 +118,7 @@ + @@ -129,15 +132,15 @@ - - - - + + + + @@ -149,8 +152,8 @@ - + From 5a0476032e19f6abd65daa488b3091e8600b5f9e Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sun, 11 Nov 2012 16:36:29 +0100 Subject: [PATCH 315/432] addr: Return -NLE_AF_NOSUPPORT when trying to set unsupported attributes - multicast and anycast address only supported with IPv6 - brodcast address only supported with IPv4 Signed-off-by: Thomas Graf --- lib/route/addr.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/route/addr.c b/lib/route/addr.c index 8ae16ef..430fb54 100644 --- a/lib/route/addr.c +++ b/lib/route/addr.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2011 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf * Copyright (c) 2003-2006 Baruch Even , * Mediatrix Telecom, inc. */ @@ -227,6 +227,7 @@ static int addr_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, addr->ce_mask |= ADDR_ATTR_LABEL; } + /* IPv6 only */ if (tb[IFA_CACHEINFO]) { struct ifa_cacheinfo *ca; @@ -269,6 +270,7 @@ static int addr_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, nl_addr_set_prefixlen(peer_prefix ? addr->a_peer : addr->a_local, addr->a_prefixlen); + /* IPv4 only */ if (tb[IFA_BROADCAST]) { addr->a_bcast = nl_addr_alloc_attr(tb[IFA_BROADCAST], family); if (!addr->a_bcast) @@ -277,6 +279,7 @@ static int addr_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, addr->ce_mask |= ADDR_ATTR_BROADCAST; } + /* IPv6 only */ if (tb[IFA_MULTICAST]) { addr->a_multicast = nl_addr_alloc_attr(tb[IFA_MULTICAST], family); @@ -286,6 +289,7 @@ static int addr_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, addr->ce_mask |= ADDR_ATTR_MULTICAST; } + /* IPv6 only */ if (tb[IFA_ANYCAST]) { addr->a_anycast = nl_addr_alloc_attr(tb[IFA_ANYCAST], family); @@ -899,6 +903,9 @@ struct nl_addr *rtnl_addr_get_peer(struct rtnl_addr *addr) int rtnl_addr_set_broadcast(struct rtnl_addr *addr, struct nl_addr *bcast) { + if (bcast->a_family != AF_INET) + return -NLE_AF_NOSUPPORT; + return __assign_addr(addr, &addr->a_bcast, bcast, ADDR_ATTR_BROADCAST); } @@ -909,6 +916,9 @@ struct nl_addr *rtnl_addr_get_broadcast(struct rtnl_addr *addr) int rtnl_addr_set_multicast(struct rtnl_addr *addr, struct nl_addr *multicast) { + if (multicast->a_family != AF_INET6) + return -NLE_AF_NOSUPPORT; + return __assign_addr(addr, &addr->a_multicast, multicast, ADDR_ATTR_MULTICAST); } @@ -920,6 +930,9 @@ struct nl_addr *rtnl_addr_get_multicast(struct rtnl_addr *addr) int rtnl_addr_set_anycast(struct rtnl_addr *addr, struct nl_addr *anycast) { + if (anycast->a_family != AF_INET6) + return -NLE_AF_NOSUPPORT; + return __assign_addr(addr, &addr->a_anycast, anycast, ADDR_ATTR_ANYCAST); } From 3132db51620064b55fece9166af7f6cf165efb89 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sun, 11 Nov 2012 21:01:19 +0100 Subject: [PATCH 316/432] addr: rtnl_addr_set_peer() is limited to IPv4 Signed-off-by: Thomas Graf --- lib/route/addr.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/route/addr.c b/lib/route/addr.c index 430fb54..d9c1b50 100644 --- a/lib/route/addr.c +++ b/lib/route/addr.c @@ -893,6 +893,9 @@ struct nl_addr *rtnl_addr_get_local(struct rtnl_addr *addr) int rtnl_addr_set_peer(struct rtnl_addr *addr, struct nl_addr *peer) { + if (peer->a_family != AF_INET) + return -NLE_AF_NOSUPPORT; + return __assign_addr(addr, &addr->a_peer, peer, ADDR_ATTR_PEER); } From c83ecb38c16dd8da7e3b1e84d7e73c259fc917a4 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Mon, 12 Nov 2012 10:26:38 +0100 Subject: [PATCH 317/432] doc: Revert to default stylesheet Use of a custom stylesheet breaks with almost every release of doxygen and is thus completely unuseable. Signed-off-by: Thomas Graf --- doc/libnl.css | 632 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 464 insertions(+), 168 deletions(-) diff --git a/doc/libnl.css b/doc/libnl.css index 6b04f0d..8589450 100644 --- a/doc/libnl.css +++ b/doc/libnl.css @@ -3,14 +3,11 @@ body, table, div, p, dl { font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif; font-size: 13px; + line-height: 1.3; } /* @group Heading Levels */ -h1, h2, h3 { - color: #990000; -} - h1 { font-size: 150%; } @@ -29,6 +26,19 @@ h3 { font-size: 100%; } +h1, h2, h3, h4, h5, h6 { + -webkit-transition: text-shadow 0.5s linear; + -moz-transition: text-shadow 0.5s linear; + -ms-transition: text-shadow 0.5s linear; + -o-transition: text-shadow 0.5s linear; + transition: text-shadow 0.5s linear; + margin-right: 15px; +} + +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px cyan; +} + dt { font-weight: bold; } @@ -76,8 +86,6 @@ div.qindex, div.navtab{ background-color: #EBEFF6; border: 1px solid #A3B4D7; text-align: center; - margin: 2px; - padding: 2px; } div.qindex, div.navpath { @@ -92,15 +100,13 @@ div.navtab { /* @group Link Styling */ a { - /* color: #3D578C; */ - color: #990000; + color: #3D578C; font-weight: normal; text-decoration: none; } .contents a:visited { - /* color: #4665A2; */ - color: #990000; + color: #4665A2; } a:hover { @@ -129,13 +135,12 @@ a.el { a.elRef { } -a.code { - /* color: #4665A2; */ - color: #990000; +a.code, a.code:visited { + color: #4665A2; } -a.codeRef { - color: #4665A2; +a.codeRef, a.codeRef:visited { + color: #4665A2; } /* @end */ @@ -144,20 +149,72 @@ dl.el { margin-left: -1cm; } -.fragment { - font-family: monospace, fixed; - font-size: 105%; +pre.fragment { + border: 1px solid #C4CFE5; + background-color: #FBFCFD; + padding: 4px 6px; + margin: 4px 8px 4px 2px; + overflow: auto; + word-wrap: break-word; + font-size: 9pt; + line-height: 125%; + font-family: monospace, fixed; + font-size: 105%; } -pre.fragment { - border: 1px solid #C4CFE5; +div.fragment { + padding: 4px; + margin: 4px; background-color: #FBFCFD; - padding: 4px 6px; - margin: 4px 8px 4px 2px; - overflow: auto; - word-wrap: break-word; - font-size: 9pt; - line-height: 125%; + border: 1px solid #C4CFE5; +} + +div.line { + font-family: monospace, fixed; + font-size: 13px; + min-height: 13px; + line-height: 1.0; + text-wrap: unrestricted; + white-space: -moz-pre-wrap; /* Moz */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: pre-wrap; /* CSS3 */ + word-wrap: break-word; /* IE 5.5+ */ + text-indent: -53px; + padding-left: 53px; + padding-bottom: 0px; + margin: 0px; + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +div.line.glow { + background-color: cyan; + box-shadow: 0 0 10px cyan; +} + + +span.lineno { + padding-right: 4px; + text-align: right; + border-right: 2px solid #0F0; + background-color: #E8E8E8; + white-space: pre; +} +span.lineno a { + background-color: #D8D8D8; +} + +span.lineno a:hover { + background-color: #C8C8C8; } div.ah { @@ -190,15 +247,15 @@ div.groupText { } body { - background: white; + background-color: white; color: black; margin: 0; } div.contents { margin-top: 10px; - margin-left: 10px; - margin-right: 5px; + margin-left: 12px; + margin-right: 8px; } td.indexkey { @@ -207,6 +264,8 @@ td.indexkey { border: 1px solid #C4CFE5; margin: 2px 0px 2px 0; padding: 2px 10px; + white-space: nowrap; + vertical-align: top; } td.indexvalue { @@ -299,6 +358,13 @@ span.vhdllogic { color: #ff0000 } +blockquote { + background-color: #F7F8FB; + border-left: 2px solid #9CAFD4; + margin: 0 24px 0 4px; + padding: 0 12px 0 16px; +} + /* @end */ /* @@ -352,6 +418,24 @@ table.memberdecls { padding: 0px; } +.memberdecls td { + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +.memberdecls td.glow { + background-color: cyan; + box-shadow: 0 0 15px cyan; +} + .mdescLeft, .mdescRight, .memItemLeft, .memItemRight, .memTemplItemLeft, .memTemplItemRight, .memTemplParams { @@ -361,22 +445,13 @@ table.memberdecls { padding: 1px 0 0 8px; } -.mdescRight > p { - padding: 0px; - margin: 0px; -} - -.mdescRight > br { - font-size: 0pt; -} - .mdescLeft, .mdescRight { padding: 0px 8px 4px 8px; color: #555; } .memItemLeft, .memItemRight, .memTemplParams { - border-top: 1px solid #a7a7a7; + border-top: 1px solid #C4CFE5; } .memItemLeft, .memTemplItemLeft { @@ -388,8 +463,7 @@ table.memberdecls { } .memTemplParams { - /* color: #4665A2; */ - color: #990000; + color: #4665A2; white-space: nowrap; } @@ -401,8 +475,7 @@ table.memberdecls { .memtemplate { font-size: 80%; - /* color: #4665A2; */ - color: #990000; + color: #4665A2; font-weight: normal; margin-left: 9px; } @@ -424,60 +497,85 @@ table.memberdecls { padding: 0; margin-bottom: 10px; margin-right: 5px; + -webkit-transition: box-shadow 0.5s linear; + -moz-transition: box-shadow 0.5s linear; + -ms-transition: box-shadow 0.5s linear; + -o-transition: box-shadow 0.5s linear; + transition: box-shadow 0.5s linear; + display: table !important; + width: 100%; +} + +.memitem.glow { + box-shadow: 0 0 15px cyan; } .memname { - white-space: nowrap; - font-family: monospace, fixed; - font-weight: bold; - font-size: 110%; + font-weight: bold; margin-left: 6px; } -.memproto { - border: 1px solid #990000; - padding: 6px 0px 6px 0px; - /* color: #253555; */ - color: #990000; - /* text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); */ - /* opera specific markup */ - box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - border-top-right-radius: 8px; - border-top-left-radius: 8px; - /* firefox specific markup */ - -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; - -moz-border-radius-topright: 8px; - -moz-border-radius-topleft: 8px; - /* webkit specific markup */ - -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - -webkit-border-top-right-radius: 8px; - -webkit-border-top-left-radius: 8px; - /* background-image:url('nav_f.png'); - background-repeat:repeat-x; */ - background-color: #f1f1f1; +.memname td { + vertical-align: bottom; } -.memdoc { - border-bottom: 1px solid #990000; - border-left: 1px solid #990000; - border-right: 1px solid #990000; - padding: 10px 15px; +.memproto, dl.reflist dt { + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 0px 6px 0px; + color: #253555; + font-weight: bold; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + /* opera specific markup */ + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + border-top-right-radius: 4px; + border-top-left-radius: 4px; + /* firefox specific markup */ + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + -moz-border-radius-topright: 4px; + -moz-border-radius-topleft: 4px; + /* webkit specific markup */ + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -webkit-border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; + +} + +.memdoc, dl.reflist dd { + border-bottom: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 10px 2px 10px; background-color: #FBFCFD; border-top-width: 0; + background-image:url('nav_g.png'); + background-repeat:repeat-x; + background-color: #FFFFFF; /* opera specific markup */ - border-bottom-left-radius: 8px; - border-bottom-right-radius: 8px; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); /* firefox specific markup */ - -moz-border-radius-bottomleft: 8px; - -moz-border-radius-bottomright: 8px; + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; - background-image: -moz-linear-gradient(center top, #FFFFFF 0%, #FFFFFF 60%, #F7F8FB 95%, #EEF1F7); /* webkit specific markup */ - -webkit-border-bottom-left-radius: 8px; - -webkit-border-bottom-right-radius: 8px; + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - background-image: -webkit-gradient(linear,center top,center bottom,from(#FFFFFF), color-stop(0.6,#FFFFFF), color-stop(0.60,#FFFFFF), color-stop(0.95,#F7F8FB), to(#EEF1F7)); +} + +dl.reflist dt { + padding: 5px; +} + +dl.reflist dd { + margin: 0px 0px 10px 0px; + padding: 5px; } .paramkey { @@ -485,22 +583,23 @@ table.memberdecls { } .paramtype { - color: #c87424; white-space: nowrap; - font-family: monospace, fixed; } .paramname { - color: #990000; + color: #602020; white-space: nowrap; - font-family: monospace, fixed; } .paramname em { font-style: normal; } +.paramname code { + line-height: 14px; +} .params, .retval, .exception, .tparams { - border-spacing: 6px 2px; + margin-left: 0px; + padding-left: 0px; } .params .paramname, .retval .paramname { @@ -518,105 +617,114 @@ table.memberdecls { vertical-align: top; } +table.mlabels { + border-spacing: 0px; +} + +td.mlabels-left { + width: 100%; + padding: 0px; +} + +td.mlabels-right { + vertical-align: bottom; + padding: 0px; + white-space: nowrap; +} + +span.mlabels { + margin-left: 8px; +} + +span.mlabel { + background-color: #728DC1; + border-top:1px solid #5373B4; + border-left:1px solid #5373B4; + border-right:1px solid #C4CFE5; + border-bottom:1px solid #C4CFE5; + text-shadow: none; + color: white; + margin-right: 4px; + padding: 2px 3px; + border-radius: 3px; + font-size: 7pt; + white-space: nowrap; +} /* @end */ -/* @group Directory (tree) */ +/* these are for tree view when not used as main index */ -/* for the tree view */ - -.ftvtree { - font-family: sans-serif; - margin: 0px; +div.directory { + margin: 10px 0px; + border-top: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + width: 100%; } -/* these are for tree view when used as main index */ - -.directory { - font-size: 9pt; - font-weight: bold; - margin: 5px; +.directory table { + border-collapse:collapse; } -.directory h3 { - margin: 0px; - margin-top: 1em; - font-size: 11pt; +.directory td { + margin: 0px; + padding: 0px; + vertical-align: top; } -/* -The following two styles can be used to replace the root node title -with an image of your choice. Simply uncomment the next two styles, -specify the name of your image and be sure to set 'height' to the -proper pixel height of your image. -*/ - -/* -.directory h3.swap { - height: 61px; - background-repeat: no-repeat; - background-image: url("yourimage.gif"); -} -.directory h3.swap span { - display: none; -} -*/ - -.directory > h3 { - margin-top: 0; +.directory td.entry { + white-space: nowrap; + padding-right: 6px; } -.directory p { - margin: 0px; - white-space: nowrap; +.directory td.entry a { + outline:none; } -.directory div { - display: none; - margin: 0px; +.directory td.entry a img { + border: none; +} + +.directory td.desc { + width: 100%; + padding-left: 6px; + padding-right: 6px; + border-left: 1px solid rgba(0,0,0,0.05); +} + +.directory tr.even { + padding-left: 6px; + background-color: #F7F8FB; } .directory img { vertical-align: -30%; } -/* these are for tree view when not used as main index */ - -.directory-alt { - font-size: 100%; - font-weight: bold; +.directory .levels { + white-space: nowrap; + width: 100%; + text-align: right; + font-size: 9pt; } -.directory-alt h3 { - margin: 0px; - margin-top: 1em; - font-size: 11pt; +.directory .levels span { + cursor: pointer; + padding-left: 2px; + padding-right: 2px; + color: #3D578C; } -.directory-alt > h3 { - margin-top: 0; -} - -.directory-alt p { - margin: 0px; - white-space: nowrap; -} - -.directory-alt div { - display: none; - margin: 0px; -} - -.directory-alt img { - vertical-align: -30%; -} - -/* @end */ - div.dynheader { margin-top: 8px; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } address { @@ -626,6 +734,8 @@ address { table.doxtable { border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; } table.doxtable td, table.doxtable th { @@ -639,9 +749,60 @@ table.doxtable th { font-size: 110%; padding-bottom: 4px; padding-top: 5px; - text-align:left; } +table.fieldtable { + width: 100%; + margin-bottom: 10px; + border: 1px solid #A8B8D9; + border-spacing: 0px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); +} + +.fieldtable td, .fieldtable th { + padding: 3px 7px 2px; +} + +.fieldtable td.fieldtype, .fieldtable td.fieldname { + white-space: nowrap; + border-right: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + vertical-align: top; +} + +.fieldtable td.fielddoc { + border-bottom: 1px solid #A8B8D9; + width: 100%; +} + +.fieldtable tr:last-child td { + border-bottom: none; +} + +.fieldtable th { + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + font-size: 90%; + color: #253555; + padding-bottom: 4px; + padding-top: 5px; + text-align:left; + -moz-border-radius-topleft: 4px; + -moz-border-radius-topright: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom: 1px solid #A8B8D9; +} + + .tabsearch { top: 0px; left: 10px; @@ -722,7 +883,6 @@ div.summary a div.ingroups { font-size: 8pt; - padding-left: 5px; width: 50%; text-align: left; } @@ -743,7 +903,7 @@ div.header div.headertitle { - padding: 5px 5px 5px 10px; + padding: 5px 5px 5px 7px; } dl @@ -751,52 +911,74 @@ dl padding: 0 0 0 10px; } -.memdoc > dl +/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */ +dl.section { - padding: 0px; -} - -dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug -{ - border-left:4px solid; - padding: 0 0 0 6px; + margin-left: 0px; + padding-left: 0px; } dl.note { + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; border-color: #D0C000; } dl.warning, dl.attention { + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; border-color: #FF0000; } dl.pre, dl.post, dl.invariant { + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; border-color: #00D000; } dl.deprecated { + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; border-color: #505050; } dl.todo { + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; border-color: #00C0E0; } dl.test { + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; border-color: #3030E0; } dl.bug { + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; border-color: #C08050; } +dl.section dd { + margin-bottom: 6px; +} + + #projectlogo { text-align: center; @@ -858,3 +1040,117 @@ dl.bug font-weight: bold; } +div.zoom +{ + border: 1px solid #90A5CE; +} + +dl.citelist { + margin-bottom:50px; +} + +dl.citelist dt { + color:#334975; + float:left; + font-weight:bold; + margin-right:10px; + padding:5px; +} + +dl.citelist dd { + margin:2px 0; + padding:5px 0; +} + +div.toc { + padding: 14px 25px; + background-color: #F4F6FA; + border: 1px solid #D8DFEE; + border-radius: 7px 7px 7px 7px; + float: right; + height: auto; + margin: 0 20px 10px 10px; + width: 200px; +} + +div.toc li { + background: url("bdwn.png") no-repeat scroll 0 5px transparent; + font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; + margin-top: 5px; + padding-left: 10px; + padding-top: 2px; +} + +div.toc h3 { + font: bold 12px/1.2 Arial,FreeSans,sans-serif; + color: #4665A2; + border-bottom: 0 none; + margin: 0; +} + +div.toc ul { + list-style: none outside none; + border: medium none; + padding: 0px; +} + +div.toc li.level1 { + margin-left: 0px; +} + +div.toc li.level2 { + margin-left: 15px; +} + +div.toc li.level3 { + margin-left: 30px; +} + +div.toc li.level4 { + margin-left: 45px; +} + +.inherit_header { + font-weight: bold; + color: gray; + cursor: pointer; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.inherit_header td { + padding: 6px 0px 2px 5px; +} + +.inherit { + display: none; +} + +tr.heading h2 { + margin-top: 12px; + margin-bottom: 4px; +} + +@media print +{ + #top { display: none; } + #side-nav { display: none; } + #nav-path { display: none; } + body { overflow:visible; } + h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } + .summary { display: none; } + .memitem { page-break-inside: avoid; } + #doc-content + { + margin-left:0 !important; + height:auto !important; + width:auto !important; + overflow:inherit; + display:inline; + } +} + From dd8a87da9653848bb8811cc61ed97574254536c9 Mon Sep 17 00:00:00 2001 From: roopa Date: Mon, 12 Nov 2012 12:38:31 -0800 Subject: [PATCH 318/432] Add support for per cache flags This patch adds support for per cache flags and adds a flag NL_CACHE_AF_ITER to iter over all supported families when filling the cache. Signed-off-by: Thomas Graf --- include/netlink-types.h | 1 + include/netlink/cache-api.h | 8 ++++++++ include/netlink/cache.h | 1 + lib/cache.c | 21 +++++++++++++++++++++ 4 files changed, 31 insertions(+) diff --git a/include/netlink-types.h b/include/netlink-types.h index 0be58d1..01b4505 100644 --- a/include/netlink-types.h +++ b/include/netlink-types.h @@ -79,6 +79,7 @@ struct nl_cache int c_nitems; int c_iarg1; int c_iarg2; + unsigned int c_flags; struct nl_hash_table * hashtable; struct nl_cache_ops * c_ops; }; diff --git a/include/netlink/cache-api.h b/include/netlink/cache-api.h index aa5eeb6..ccb4098 100644 --- a/include/netlink/cache-api.h +++ b/include/netlink/cache-api.h @@ -168,6 +168,11 @@ struct nl_parser_param void * pp_arg; }; +/** + * Cache flags + */ +#define NL_CACHE_AF_ITER 0x0001 + /** * Cache Operations * @@ -189,6 +194,9 @@ struct nl_cache_ops /** cache object hash size **/ int co_hash_size; + /** cache flags */ + unsigned int co_flags; + /** Group definition */ struct nl_af_group * co_groups; diff --git a/include/netlink/cache.h b/include/netlink/cache.h index c919e6b..ee3b5d8 100644 --- a/include/netlink/cache.h +++ b/include/netlink/cache.h @@ -66,6 +66,7 @@ extern int nl_cache_include(struct nl_cache *, void *); extern void nl_cache_set_arg1(struct nl_cache *, int); extern void nl_cache_set_arg2(struct nl_cache *, int); +extern void nl_cache_set_flags(struct nl_cache *, unsigned int); /* General */ extern int nl_cache_is_empty(struct nl_cache *); diff --git a/lib/cache.c b/lib/cache.c index af4ee95..f21df2b 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -190,6 +190,7 @@ struct nl_cache *nl_cache_alloc(struct nl_cache_ops *ops) nl_init_list_head(&cache->c_items); cache->c_ops = ops; + cache->c_flags |= ops->co_flags; /* * If object type provides a hash keygen @@ -565,6 +566,26 @@ void nl_cache_set_arg2(struct nl_cache *cache, int arg) cache->c_iarg2 = arg; } +/** + * Set cache ops flags + * @arg ops Cache ops + * @arg arg flags + */ +void nl_cache_ops_set_flags(struct nl_cache_ops *ops, unsigned int flags) +{ + ops->co_flags |= flags; +} + +/** + * Set cache flags + * @arg cache Cache + * @arg arg flags + */ +void nl_cache_set_flags(struct nl_cache *cache, unsigned int flags) +{ + cache->c_flags |= flags; +} + /** * Invoke the request-update operation * @arg sk Netlink socket. From 30d862650bcc26588ddcb07d1126b43e0ec4c121 Mon Sep 17 00:00:00 2001 From: roopa Date: Mon, 12 Nov 2012 12:38:32 -0800 Subject: [PATCH 319/432] New cache manager add cache api This patch is an attempt to add a new nl_cache_mngr_add_cache api to allow adding an existing cache to cache manager. Since the new api is similar to nl_cache_mngr_add except for allocating the cache, the patch moves most of the nl_cache_mngr_add code to nl_cache_mngr_add_cache and changes nl_cache_mngr_add to call nl_cache_mngr_add_cache. One use case for this api as pointed out by thomas would be to set cache flags before associating the cache with a cache manager. nl_cache_alloc_name("route/link", &cache); nl_cache_set_flags(cache, NL_CACHE_AF_ITER); nl_cache_mngr_add_cache(mngr, cache, ...); Signed-off-by: Thomas Graf --- include/netlink/cache.h | 3 ++ lib/cache_mngr.c | 86 +++++++++++++++++++++++++++++++---------- 2 files changed, 68 insertions(+), 21 deletions(-) diff --git a/include/netlink/cache.h b/include/netlink/cache.h index ee3b5d8..7de389d 100644 --- a/include/netlink/cache.h +++ b/include/netlink/cache.h @@ -124,6 +124,9 @@ extern int nl_cache_mngr_add(struct nl_cache_mngr *, change_func_t, void *, struct nl_cache **); +extern int nl_cache_mngr_add_cache(struct nl_cache_mngr *mngr, + struct nl_cache *cache, + change_func_t cb, void *data); extern int nl_cache_mngr_get_fd(struct nl_cache_mngr *); extern int nl_cache_mngr_poll(struct nl_cache_mngr *, int); diff --git a/lib/cache_mngr.c b/lib/cache_mngr.c index cdf2b7b..63cc0d3 100644 --- a/lib/cache_mngr.c +++ b/lib/cache_mngr.c @@ -183,18 +183,16 @@ errout: } /** - * Add cache responsibility to cache manager + * Add cache to cache manager * @arg mngr Cache manager. - * @arg name Name of cache to keep track of + * @arg cache Cache to be added to cache manager * @arg cb Function to be called upon changes. * @arg data Argument passed on to change callback - * @arg result Pointer to store added cache (optional) * - * Allocates a new cache of the specified type and adds it to the manager. - * The operation will trigger a full dump request from the kernel to - * initially fill the contents of the cache. The manager will subscribe - * to the notification group of the cache and keep track of any further - * changes. + * Adds cache to the manager. The operation will trigger a full + * dump request from the kernel to initially fill the contents + * of the cache. The manager will subscribe to the notification group + * of the cache and keep track of any further changes. * * The user is responsible for calling nl_cache_mngr_poll() or monitor * the socket and call nl_cache_mngr_data_ready() to allow the library @@ -204,23 +202,21 @@ errout: * @see nl_cache_mngr_data_ready() * * @return 0 on success or a negative error code. - * @return -NLE_NOCACHE Unknown cache type * @return -NLE_PROTO_MISMATCH Protocol mismatch between cache manager and * cache type * @return -NLE_OPNOTSUPP Cache type does not support updates * @return -NLE_EXIST Cache of this type already being managed */ -int nl_cache_mngr_add(struct nl_cache_mngr *mngr, const char *name, - change_func_t cb, void *data, struct nl_cache **result) +int nl_cache_mngr_add_cache(struct nl_cache_mngr *mngr, struct nl_cache *cache, + change_func_t cb, void *data) { struct nl_cache_ops *ops; - struct nl_cache *cache; struct nl_af_group *grp; int err, i; - ops = nl_cache_ops_lookup(name); + ops = cache->c_ops; if (!ops) - return -NLE_NOCACHE; + return -NLE_INVAL; if (ops->co_protocol != mngr->cm_protocol) return -NLE_PROTO_MISMATCH; @@ -254,14 +250,10 @@ retry: goto retry; } - cache = nl_cache_alloc(ops); - if (!cache) - return -NLE_NOMEM; - for (grp = ops->co_groups; grp->ag_group; grp++) { err = nl_socket_add_membership(mngr->cm_sock, grp->ag_group); if (err < 0) - goto errout_free_cache; + return err; } err = nl_cache_refill(mngr->cm_sock, cache); @@ -278,13 +270,65 @@ retry: NL_DBG(1, "Added cache %p <%s> to cache manager %p\n", cache, nl_cache_name(cache), mngr); - if (result) - *result = cache; return 0; errout_drop_membership: for (grp = ops->co_groups; grp->ag_group; grp++) nl_socket_drop_membership(mngr->cm_sock, grp->ag_group); + + return err; +} + +/** + * Add cache to cache manager + * @arg mngr Cache manager. + * @arg name Name of cache to keep track of + * @arg cb Function to be called upon changes. + * @arg data Argument passed on to change callback + * @arg result Pointer to store added cache (optional) + * + * Allocates a new cache of the specified type and adds it to the manager. + * The operation will trigger a full dump request from the kernel to + * initially fill the contents of the cache. The manager will subscribe + * to the notification group of the cache and keep track of any further + * changes. + * + * The user is responsible for calling nl_cache_mngr_poll() or monitor + * the socket and call nl_cache_mngr_data_ready() to allow the library + * to process netlink notification events. + * + * @see nl_cache_mngr_poll() + * @see nl_cache_mngr_data_ready() + * + * @return 0 on success or a negative error code. + * @return -NLE_NOCACHE Unknown cache type + * @return -NLE_PROTO_MISMATCH Protocol mismatch between cache manager and + * cache type + * @return -NLE_OPNOTSUPP Cache type does not support updates + * @return -NLE_EXIST Cache of this type already being managed + */ +int nl_cache_mngr_add(struct nl_cache_mngr *mngr, const char *name, + change_func_t cb, void *data, struct nl_cache **result) +{ + struct nl_cache_ops *ops; + struct nl_cache *cache; + int err; + + ops = nl_cache_ops_lookup(name); + if (!ops) + return -NLE_NOCACHE; + + cache = nl_cache_alloc(ops); + if (!cache) + return -NLE_NOMEM; + + err = nl_cache_mngr_add_cache(mngr, cache, cb, data); + if (err < 0) + goto errout_free_cache; + + *result = cache; + return 0; + errout_free_cache: nl_cache_free(cache); From 0bd14aa2d689604b22b1d9f87a57c0e09c21b522 Mon Sep 17 00:00:00 2001 From: roopa Date: Mon, 12 Nov 2012 12:38:33 -0800 Subject: [PATCH 320/432] Add NL_CACHE_AF_ITER support during refill and resync This patch adds support to iter over all supported families during cache fill and resync. The motivation for this was previously introduced at http://lists.infradead.org/pipermail/libnl/2012-November/000734.html In short, this patch allows caches to request dump on all supported families instead of only AF_UNSPEC as done today. With feedback from thomas this patch makes the iter over all families conditional on per cache flag NL_CACHE_AF_ITER Signed-off-by: Thomas Graf --- lib/cache.c | 60 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/lib/cache.c b/lib/cache.c index f21df2b..7b70324 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -779,6 +779,7 @@ int nl_cache_resync(struct nl_sock *sk, struct nl_cache *cache, change_func_t change_cb, void *data) { struct nl_object *obj, *next; + struct nl_af_group *grp; struct nl_cache_assoc ca = { .ca_cache = cache, .ca_change = change_cb, @@ -792,19 +793,28 @@ int nl_cache_resync(struct nl_sock *sk, struct nl_cache *cache, NL_DBG(1, "Resyncing cache %p <%s>...\n", cache, nl_cache_name(cache)); -restart: /* Mark all objects so we can see if some of them are obsolete */ nl_cache_mark_all(cache); - err = nl_cache_request_full_dump(sk, cache); - if (err < 0) - goto errout; + grp = cache->c_ops->co_groups; + do { + if (grp && grp->ag_group && + (cache->c_flags & NL_CACHE_AF_ITER)) + nl_cache_set_arg1(cache, grp->ag_family); - err = __cache_pickup(sk, cache, &p); - if (err == -NLE_DUMP_INTR) - goto restart; - else if (err < 0) - goto errout; +restart: + err = nl_cache_request_full_dump(sk, cache); + if (err < 0) + goto errout; + + err = __cache_pickup(sk, cache, &p); + if (err == -NLE_DUMP_INTR) + goto restart; + else if (err < 0) + goto errout; + grp++; + } while (grp && grp->ag_group && + (cache->c_flags & NL_CACHE_AF_ITER)); nl_list_for_each_entry_safe(obj, next, &cache->c_items, ce_list) { if (nl_object_is_marked(obj)) { @@ -886,23 +896,35 @@ int nl_cache_parse_and_add(struct nl_cache *cache, struct nl_msg *msg) */ int nl_cache_refill(struct nl_sock *sk, struct nl_cache *cache) { + struct nl_af_group *grp; int err; + nl_cache_clear(cache); + grp = cache->c_ops->co_groups; + do { + if (grp && grp->ag_group && + (cache->c_flags & NL_CACHE_AF_ITER)) + nl_cache_set_arg1(cache, grp->ag_family); + restart: - err = nl_cache_request_full_dump(sk, cache); - if (err < 0) - return err; + err = nl_cache_request_full_dump(sk, cache); + if (err < 0) + return err; + + err = nl_cache_pickup(sk, cache); + if (err == -NLE_DUMP_INTR) { + fprintf(stderr, "dump interrupted, restarting!\n"); + goto restart; + } else if (err < 0) + break; + + grp++; + } while (grp && grp->ag_group && + (cache->c_flags & NL_CACHE_AF_ITER)); NL_DBG(2, "Upading cache %p <%s>, request sent, waiting for dump...\n", cache, nl_cache_name(cache)); - nl_cache_clear(cache); - err = nl_cache_pickup(sk, cache); - if (err == -NLE_DUMP_INTR) { - fprintf(stderr, "dump interrupted, restarting!\n"); - goto restart; - } - return err; } From ce72565f2649347103219056b9b5ae7c18247087 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Mon, 12 Nov 2012 21:59:54 +0100 Subject: [PATCH 321/432] cache: Move NL_CACHE_AF_ITER to alreay requires anyway. Signed-off-by: Thomas Graf --- include/netlink/cache-api.h | 5 ----- include/netlink/cache.h | 6 ++++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/netlink/cache-api.h b/include/netlink/cache-api.h index ccb4098..dd42671 100644 --- a/include/netlink/cache-api.h +++ b/include/netlink/cache-api.h @@ -168,11 +168,6 @@ struct nl_parser_param void * pp_arg; }; -/** - * Cache flags - */ -#define NL_CACHE_AF_ITER 0x0001 - /** * Cache Operations * diff --git a/include/netlink/cache.h b/include/netlink/cache.h index 7de389d..1eb1427 100644 --- a/include/netlink/cache.h +++ b/include/netlink/cache.h @@ -24,6 +24,12 @@ extern "C" { struct nl_cache; +/** + * @ingroup cache + * Explicitely iterate over all address families when updating the cache + */ +#define NL_CACHE_AF_ITER 0x0001 + /* Access Functions */ extern int nl_cache_nitems(struct nl_cache *); extern int nl_cache_nitems_filter(struct nl_cache *, From 57340112286d2de74248818e51236c45d60e86d4 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Mon, 12 Nov 2012 22:03:22 +0100 Subject: [PATCH 322/432] cache: Fix typo in API doc of nl_cache_set_flags() Signed-off-by: Thomas Graf --- lib/cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cache.c b/lib/cache.c index 7b70324..6a0e71a 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -579,7 +579,7 @@ void nl_cache_ops_set_flags(struct nl_cache_ops *ops, unsigned int flags) /** * Set cache flags * @arg cache Cache - * @arg arg flags + * @arg flags Flags */ void nl_cache_set_flags(struct nl_cache *cache, unsigned int flags) { From 8ffa257bfa36affebbca1505151b2cac42875e69 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Mon, 12 Nov 2012 22:07:39 +0100 Subject: [PATCH 323/432] cache: Move nl_cache_ops_set_flags() to cache_mngt.c Signed-off-by: Thomas Graf --- lib/cache.c | 10 ---------- lib/cache_mngt.c | 13 +++++++++++++ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/lib/cache.c b/lib/cache.c index 6a0e71a..b776abf 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -566,16 +566,6 @@ void nl_cache_set_arg2(struct nl_cache *cache, int arg) cache->c_iarg2 = arg; } -/** - * Set cache ops flags - * @arg ops Cache ops - * @arg arg flags - */ -void nl_cache_ops_set_flags(struct nl_cache_ops *ops, unsigned int flags) -{ - ops->co_flags |= flags; -} - /** * Set cache flags * @arg cache Cache diff --git a/lib/cache_mngt.c b/lib/cache_mngt.c index 6691454..fa1ac22 100644 --- a/lib/cache_mngt.c +++ b/lib/cache_mngt.c @@ -129,6 +129,19 @@ void nl_cache_ops_foreach(void (*cb)(struct nl_cache_ops *, void *), void *arg) cb(ops, arg); } +/** + * Set default flags for caches of this type + * @arg ops Cache ops + * @arg flags Flags to set + * + * The cache operation flags will be derived to all caches allocates + * based on this set of cache operations. + */ +void nl_cache_ops_set_flags(struct nl_cache_ops *ops, unsigned int flags) +{ + ops->co_flags |= flags; +} + /** * Register a set of cache operations * @arg ops cache operations From ea79a762886a6b723e70686c5db0ec4d8bf707a6 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Mon, 12 Nov 2012 23:48:02 +0100 Subject: [PATCH 324/432] addr: Support setting local/peer/anycast/multicast/broadcast address to NULL Signed-off-by: Thomas Graf --- lib/route/addr.c | 56 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/lib/route/addr.c b/lib/route/addr.c index d9c1b50..7e29529 100644 --- a/lib/route/addr.c +++ b/lib/route/addr.c @@ -855,17 +855,25 @@ unsigned int rtnl_addr_get_flags(struct rtnl_addr *addr) static inline int __assign_addr(struct rtnl_addr *addr, struct nl_addr **pos, struct nl_addr *new, int flag) { - if (addr->ce_mask & ADDR_ATTR_FAMILY) { - if (new->a_family != addr->a_family) - return -NLE_AF_MISMATCH; - } else - addr->a_family = new->a_family; + if (new) { + if (addr->ce_mask & ADDR_ATTR_FAMILY) { + if (new->a_family != addr->a_family) + return -NLE_AF_MISMATCH; + } else + addr->a_family = new->a_family; - if (*pos) - nl_addr_put(*pos); + if (*pos) + nl_addr_put(*pos); - *pos = nl_addr_get(new); - addr->ce_mask |= (flag | ADDR_ATTR_FAMILY); + *pos = nl_addr_get(new); + addr->ce_mask |= (flag | ADDR_ATTR_FAMILY); + } else { + if (*pos) + nl_addr_put(*pos); + + *pos = NULL; + addr->ce_mask &= ~flag; + } return 0; } @@ -874,14 +882,18 @@ int rtnl_addr_set_local(struct rtnl_addr *addr, struct nl_addr *local) { int err; + /* Prohibit local address with prefix length if peer address is present */ + if ((addr->ce_mask & ADDR_ATTR_PEER) && local && + nl_addr_get_prefixlen(local)) + return -NLE_INVAL; + err = __assign_addr(addr, &addr->a_local, local, ADDR_ATTR_LOCAL); if (err < 0) return err; - if (!(addr->ce_mask & ADDR_ATTR_PEER)) { - addr->a_prefixlen = nl_addr_get_prefixlen(addr->a_local); - addr->ce_mask |= ADDR_ATTR_PREFIXLEN; - } + /* Never overwrite the prefix length if a peer address is present */ + if (!(addr->ce_mask & ADDR_ATTR_PEER)) + rtnl_addr_set_prefixlen(addr, local ? nl_addr_get_prefixlen(local) : 0); return 0; } @@ -893,10 +905,18 @@ struct nl_addr *rtnl_addr_get_local(struct rtnl_addr *addr) int rtnl_addr_set_peer(struct rtnl_addr *addr, struct nl_addr *peer) { - if (peer->a_family != AF_INET) + int err; + + if (peer && peer->a_family != AF_INET) return -NLE_AF_NOSUPPORT; - return __assign_addr(addr, &addr->a_peer, peer, ADDR_ATTR_PEER); + err = __assign_addr(addr, &addr->a_peer, peer, ADDR_ATTR_PEER); + if (err < 0) + return err; + + rtnl_addr_set_prefixlen(addr, peer ? nl_addr_get_prefixlen(peer) : 0); + + return 0; } struct nl_addr *rtnl_addr_get_peer(struct rtnl_addr *addr) @@ -906,7 +926,7 @@ struct nl_addr *rtnl_addr_get_peer(struct rtnl_addr *addr) int rtnl_addr_set_broadcast(struct rtnl_addr *addr, struct nl_addr *bcast) { - if (bcast->a_family != AF_INET) + if (bcast && bcast->a_family != AF_INET) return -NLE_AF_NOSUPPORT; return __assign_addr(addr, &addr->a_bcast, bcast, ADDR_ATTR_BROADCAST); @@ -919,7 +939,7 @@ struct nl_addr *rtnl_addr_get_broadcast(struct rtnl_addr *addr) int rtnl_addr_set_multicast(struct rtnl_addr *addr, struct nl_addr *multicast) { - if (multicast->a_family != AF_INET6) + if (multicast && multicast->a_family != AF_INET6) return -NLE_AF_NOSUPPORT; return __assign_addr(addr, &addr->a_multicast, multicast, @@ -933,7 +953,7 @@ struct nl_addr *rtnl_addr_get_multicast(struct rtnl_addr *addr) int rtnl_addr_set_anycast(struct rtnl_addr *addr, struct nl_addr *anycast) { - if (anycast->a_family != AF_INET6) + if (anycast && anycast->a_family != AF_INET6) return -NLE_AF_NOSUPPORT; return __assign_addr(addr, &addr->a_anycast, anycast, From 125119aff05e16f150ad881dc9479686495cb5bd Mon Sep 17 00:00:00 2001 From: roopa Date: Wed, 14 Nov 2012 06:06:41 -0800 Subject: [PATCH 325/432] Add AF_BRIDGE support to link cache This patch was previously submitted as the first approach in RFC http://lists.infradead.org/pipermail/libnl/2012-November/000730.html It adds support for AF_BRIDGE family in link cache. And the key for link object lookups will now be ifindex and family. This allows for AF_UNSPEC rtnl link objects to co-exist with the AF_BRIDGE link objects in the same cache. I have changed some of the rtnl_link api's to explicitly check for AF_UNSPEC to not break existing apps. I will submit a new patch to introduce equivalent rtnl_bridge_link_* api's. We had also discussed updating the existing link objects with AF_BRIDGE attributes, but realized that the updates to link objects will be both AF_UNSPEC and AF_BRIDGE. And that would change link cache to always update existing objects, resulting in comparing and updating close to thirty attributes at cache_include time which seems like a overkill. Signed-off-by: Roopa Prabhu Reviewed-by: Nolan Leake Reviewed-by: Shrijeet Mukherjee Reviewed-by: Wilson Kok Signed-off-by: Thomas Graf --- lib/route/link.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/lib/route/link.c b/lib/route/link.c index f8646d1..b378f30 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -571,19 +571,6 @@ errout: return err; } -static int link_event_filter(struct nl_cache *cache, struct nl_object *obj) -{ - struct rtnl_link *link = (struct rtnl_link *) obj; - - /* - * Ignore bridging messages when keeping the cache manager up to date. - */ - if (link->l_family == AF_BRIDGE) - return NL_SKIP; - - return NL_OK; -} - static int link_request_update(struct nl_cache *cache, struct nl_sock *sk) { int family = cache->c_iarg1; @@ -808,15 +795,17 @@ static void link_keygen(struct nl_object *obj, uint32_t *hashkey, unsigned int lkey_sz; struct link_hash_key { uint32_t l_index; + uint32_t l_family; } __attribute__((packed)) lkey; lkey_sz = sizeof(lkey); lkey.l_index = link->l_index; + lkey.l_family = link->l_family; *hashkey = nl_hash(&lkey, lkey_sz, 0) % table_sz; - NL_DBG(5, "link %p key (dev %d) keysz %d, hash 0x%x\n", - link, lkey.l_index, lkey_sz, *hashkey); + NL_DBG(5, "link %p key (dev %d fam %d) keysz %d, hash 0x%x\n", + link, lkey.l_index, lkey.l_family, lkey_sz, *hashkey); return; } @@ -966,7 +955,7 @@ struct rtnl_link *rtnl_link_get(struct nl_cache *cache, int ifindex) return NULL; nl_list_for_each_entry(link, &cache->c_items, ce_list) { - if (link->l_index == ifindex) { + if (link->l_family == AF_UNSPEC && link->l_index == ifindex) { nl_object_get((struct nl_object *) link); return link; } @@ -999,7 +988,8 @@ struct rtnl_link *rtnl_link_get_by_name(struct nl_cache *cache, return NULL; nl_list_for_each_entry(link, &cache->c_items, ce_list) { - if (!strcmp(name, link->l_name)) { + if (link->l_family == AF_UNSPEC && + !strcmp(name, link->l_name)) { nl_object_get((struct nl_object *) link); return link; } @@ -2524,11 +2514,12 @@ static struct nl_object_ops link_obj_ops = { .oo_compare = link_compare, .oo_keygen = link_keygen, .oo_attrs2str = link_attrs2str, - .oo_id_attrs = LINK_ATTR_IFINDEX, + .oo_id_attrs = LINK_ATTR_IFINDEX | LINK_ATTR_FAMILY, }; static struct nl_af_group link_groups[] = { { AF_UNSPEC, RTNLGRP_LINK }, + { AF_BRIDGE, RTNLGRP_LINK }, { END_OF_GROUP_LIST }, }; @@ -2546,7 +2537,6 @@ static struct nl_cache_ops rtnl_link_ops = { .co_groups = link_groups, .co_request_update = link_request_update, .co_msg_parser = link_msg_parser, - .co_event_filter = link_event_filter, .co_obj_ops = &link_obj_ops, }; From 64fcb47a36ec12d7e7f00605f6a8952ce985dd08 Mon Sep 17 00:00:00 2001 From: roopa Date: Wed, 14 Nov 2012 11:33:50 -0800 Subject: [PATCH 326/432] Add AF_BRIDGE support to neigh cache This patch adds AF_BRIDGE to the list of families supported by the cache. Implements oo_id_attrs_get to declare separate id attributes for AF_UNSPEC and AF_BRIDGE neigh objects Signed-off-by: Roopa Prabhu Reviewed-by: Nolan Leake Reviewed-by: Shrijeet Mukherjee Reviewed-by: Wilson Kok Signed-off-by: Thomas Graf --- lib/route/neigh.c | 46 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/lib/route/neigh.c b/lib/route/neigh.c index 1986ef5..8e1f422 100644 --- a/lib/route/neigh.c +++ b/lib/route/neigh.c @@ -155,6 +155,7 @@ #include #include #include +#include /** @cond SKIP */ #define NEIGH_ATTR_FLAGS 0x01 @@ -211,8 +212,12 @@ static void neigh_keygen(struct nl_object *obj, uint32_t *hashkey, } __attribute__((packed)) *nkey; char buf[INET6_ADDRSTRLEN+5]; - if (neigh->n_dst) + if (neigh->n_family == AF_BRIDGE) { + if (neigh->n_lladdr) + addr = neigh->n_lladdr; + } else if (neigh->n_dst) { addr = neigh->n_dst; + } nkey_sz = sizeof(*nkey); if (addr) @@ -224,7 +229,8 @@ static void neigh_keygen(struct nl_object *obj, uint32_t *hashkey, return; } nkey->n_family = neigh->n_family; - nkey->n_ifindex = neigh->n_ifindex; + if (neigh->n_family != AF_BRIDGE) + nkey->n_ifindex = neigh->n_ifindex; if (addr) memcpy(nkey->n_addr, nl_addr_get_binary_addr(addr), @@ -290,6 +296,16 @@ static char *neigh_attrs2str(int attrs, char *buf, size_t len) ARRAY_SIZE(neigh_attrs)); } +static uint32_t neigh_id_attrs_get(struct nl_object *obj) +{ + struct rtnl_neigh *neigh = (struct rtnl_neigh *)obj; + + if (neigh->n_family == AF_BRIDGE) + return (NEIGH_ATTR_LLADDR | NEIGH_ATTR_FAMILY); + else + return (NEIGH_ATTR_IFINDEX | NEIGH_ATTR_DST | NEIGH_ATTR_FAMILY); +} + static struct nla_policy neigh_policy[NDA_MAX+1] = { [NDA_CACHEINFO] = { .minlen = sizeof(struct nda_cacheinfo) }, [NDA_PROBES] = { .type = NLA_U32 }, @@ -387,7 +403,9 @@ errout: static int neigh_request_update(struct nl_cache *c, struct nl_sock *h) { - return nl_rtgen_request(h, RTM_GETNEIGH, AF_UNSPEC, NLM_F_DUMP); + int family = c->c_iarg1; + + return nl_rtgen_request(h, RTM_GETNEIGH, family, NLM_F_DUMP); } @@ -400,7 +418,8 @@ static void neigh_dump_line(struct nl_object *a, struct nl_dump_params *p) link_cache = nl_cache_mngt_require("route/link"); - nl_dump_line(p, "%s ", nl_addr2str(n->n_dst, dst, sizeof(dst))); + if (n->n_family != AF_BRIDGE) + nl_dump_line(p, "%s ", nl_addr2str(n->n_dst, dst, sizeof(dst))); if (link_cache) nl_dump(p, "dev %s ", @@ -496,7 +515,8 @@ struct rtnl_neigh * rtnl_neigh_get(struct nl_cache *cache, int ifindex, struct rtnl_neigh *neigh; nl_list_for_each_entry(neigh, &cache->c_items, ce_list) { - if (neigh->n_ifindex == ifindex && + if (neigh->n_family == AF_UNSPEC && + neigh->n_ifindex == ifindex && !nl_addr_cmp(neigh->n_dst, dst)) { nl_object_get((struct nl_object *) neigh); return neigh; @@ -522,10 +542,13 @@ static int build_neigh_msg(struct rtnl_neigh *tmpl, int cmd, int flags, .ndm_state = NUD_PERMANENT, }; - if (!(tmpl->ce_mask & NEIGH_ATTR_DST)) - return -NLE_MISSING_ATTR; - - nhdr.ndm_family = nl_addr_get_family(tmpl->n_dst); + if (tmpl->n_family != AF_BRIDGE) { + if (!(tmpl->ce_mask & NEIGH_ATTR_DST)) + return -NLE_MISSING_ATTR; + nhdr.ndm_family = nl_addr_get_family(tmpl->n_dst); + } + else + nhdr.ndm_family = AF_BRIDGE; if (tmpl->ce_mask & NEIGH_ATTR_FLAGS) nhdr.ndm_flags = tmpl->n_flags; @@ -540,7 +563,8 @@ static int build_neigh_msg(struct rtnl_neigh *tmpl, int cmd, int flags, if (nlmsg_append(msg, &nhdr, sizeof(nhdr), NLMSG_ALIGNTO) < 0) goto nla_put_failure; - NLA_PUT_ADDR(msg, NDA_DST, tmpl->n_dst); + if (tmpl->n_family != AF_BRIDGE) + NLA_PUT_ADDR(msg, NDA_DST, tmpl->n_dst); if (tmpl->ce_mask & NEIGH_ATTR_LLADDR) NLA_PUT_ADDR(msg, NDA_LLADDR, tmpl->n_lladdr); @@ -873,10 +897,12 @@ static struct nl_object_ops neigh_obj_ops = { .oo_keygen = neigh_keygen, .oo_attrs2str = neigh_attrs2str, .oo_id_attrs = (NEIGH_ATTR_IFINDEX | NEIGH_ATTR_DST | NEIGH_ATTR_FAMILY), + .oo_id_attrs_get = neigh_id_attrs_get }; static struct nl_af_group neigh_groups[] = { { AF_UNSPEC, RTNLGRP_NEIGH }, + { AF_BRIDGE, RTNLGRP_NEIGH }, { END_OF_GROUP_LIST }, }; From cb25338ac35b5174f03c19e00733d9366f6b9482 Mon Sep 17 00:00:00 2001 From: roopa Date: Wed, 14 Nov 2012 11:33:51 -0800 Subject: [PATCH 327/432] Add master support to rtnl_neigh for AF_BRIDGE objects AF_BRIDGE neigh objects can be uniquely identified by the family, lladdr and bridge ifindex. This patch adds bridge ifindex to AF_BRIDGE neigh objects. Things will be ok even without this patch with just family and lladdr if we assume that we will have unique lladdr's accross bridges in a system. Kernel does not send the bridge ifindex in the AF_BRIDGE fdb/neigh message. This patch tries to get that info by a link cache lookup and adds it to the bridge neigh object Signed-off-by: Roopa Prabhu Reviewed-by: Nolan Leake Reviewed-by: Shrijeet Mukherjee Reviewed-by: Wilson Kok Signed-off-by: Thomas Graf --- include/netlink-types.h | 1 + lib/route/neigh.c | 24 ++++++++++++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/include/netlink-types.h b/include/netlink-types.h index 01b4505..02ecf04 100644 --- a/include/netlink-types.h +++ b/include/netlink-types.h @@ -205,6 +205,7 @@ struct rtnl_neigh struct rtnl_ncacheinfo n_cacheinfo; uint32_t n_state_mask; uint32_t n_flag_mask; + uint32_t n_master; }; diff --git a/lib/route/neigh.c b/lib/route/neigh.c index 8e1f422..4b5893a 100644 --- a/lib/route/neigh.c +++ b/lib/route/neigh.c @@ -167,6 +167,7 @@ #define NEIGH_ATTR_FAMILY 0x40 #define NEIGH_ATTR_TYPE 0x80 #define NEIGH_ATTR_PROBES 0x100 +#define NEIGH_ATTR_MASTER 0x200 static struct nl_cache_ops rtnl_neigh_ops; static struct nl_object_ops neigh_obj_ops; @@ -229,7 +230,9 @@ static void neigh_keygen(struct nl_object *obj, uint32_t *hashkey, return; } nkey->n_family = neigh->n_family; - if (neigh->n_family != AF_BRIDGE) + if (neigh->n_family == AF_BRIDGE) + nkey->n_ifindex = neigh->n_master; + else nkey->n_ifindex = neigh->n_ifindex; if (addr) memcpy(nkey->n_addr, @@ -262,6 +265,7 @@ static int neigh_compare(struct nl_object *_a, struct nl_object *_b, diff |= NEIGH_DIFF(TYPE, a->n_type != b->n_type); diff |= NEIGH_DIFF(LLADDR, nl_addr_cmp(a->n_lladdr, b->n_lladdr)); diff |= NEIGH_DIFF(DST, nl_addr_cmp(a->n_dst, b->n_dst)); + diff |= NEIGH_DIFF(MASTER, a->n_master != b->n_master); if (flags & LOOSE_COMPARISON) { diff |= NEIGH_DIFF(STATE, @@ -301,7 +305,7 @@ static uint32_t neigh_id_attrs_get(struct nl_object *obj) struct rtnl_neigh *neigh = (struct rtnl_neigh *)obj; if (neigh->n_family == AF_BRIDGE) - return (NEIGH_ATTR_LLADDR | NEIGH_ATTR_FAMILY); + return (NEIGH_ATTR_LLADDR | NEIGH_ATTR_FAMILY | NEIGH_ATTR_MASTER); else return (NEIGH_ATTR_IFINDEX | NEIGH_ATTR_DST | NEIGH_ATTR_FAMILY); } @@ -393,6 +397,22 @@ int rtnl_neigh_parse(struct nlmsghdr *n, struct rtnl_neigh **result) neigh->ce_mask |= NEIGH_ATTR_PROBES; } + /* + * Get the bridge index for AF_BRIDGE family entries + */ + if (neigh->n_family == AF_BRIDGE) { + struct nl_cache *lcache = nl_cache_mngt_require("route/link"); + if (lcache ) { + struct rtnl_link *link = rtnl_link_get(lcache, + neigh->n_ifindex); + if (link) { + neigh->n_master = link->l_master; + rtnl_link_put(link); + neigh->ce_mask |= NEIGH_ATTR_MASTER; + } + } + } + *result = neigh; return 0; From c658a6eef8bfaa9347305e532f063cb848087d31 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 15 Nov 2012 20:45:44 +0100 Subject: [PATCH 328/432] cache: Add reference counter to caches Signed-off-by: Thomas Graf --- include/netlink-types.h | 1 + include/netlink/cache.h | 1 + lib/cache.c | 34 +++++++++++++++++++++++++++------- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/include/netlink-types.h b/include/netlink-types.h index 02ecf04..2bb4f0a 100644 --- a/include/netlink-types.h +++ b/include/netlink-types.h @@ -79,6 +79,7 @@ struct nl_cache int c_nitems; int c_iarg1; int c_iarg2; + int c_refcnt; unsigned int c_flags; struct nl_hash_table * hashtable; struct nl_cache_ops * c_ops; diff --git a/include/netlink/cache.h b/include/netlink/cache.h index 1eb1427..0bd4037 100644 --- a/include/netlink/cache.h +++ b/include/netlink/cache.h @@ -50,6 +50,7 @@ extern struct nl_cache * nl_cache_subset(struct nl_cache *, struct nl_object *); extern struct nl_cache * nl_cache_clone(struct nl_cache *); extern void nl_cache_clear(struct nl_cache *); +extern void nl_cache_get(struct nl_cache *); extern void nl_cache_free(struct nl_cache *); /* Cache modification */ diff --git a/lib/cache.c b/lib/cache.c index b776abf..257a41b 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2012 Thomas Graf */ /** @@ -191,6 +191,7 @@ struct nl_cache *nl_cache_alloc(struct nl_cache_ops *ops) nl_init_list_head(&cache->c_items); cache->c_ops = ops; cache->c_flags |= ops->co_flags; + cache->c_refcnt = 1; /* * If object type provides a hash keygen @@ -365,6 +366,26 @@ void nl_cache_clear(struct nl_cache *cache) nl_cache_remove(obj); } +static void __nl_cache_free(struct nl_cache *cache) +{ + nl_cache_clear(cache); + + if (cache->hashtable) + nl_hash_table_free(cache->hashtable); + + NL_DBG(1, "Freeing cache %p <%s>...\n", cache, nl_cache_name(cache)); + free(cache); +} + +/** + * Increase reference counter of cache + * @arg cache Cache + */ +void nl_cache_get(struct nl_cache *cache) +{ + cache->c_refcnt++; +} + /** * Free a cache. * @arg cache Cache to free. @@ -379,13 +400,12 @@ void nl_cache_free(struct nl_cache *cache) if (!cache) return; - nl_cache_clear(cache); + cache->c_refcnt--; + NL_DBG(4, "Returned cache reference %p, %d remaining\n", + cache, cache->c_refcnt); - if (cache->hashtable) - nl_hash_table_free(cache->hashtable); - - NL_DBG(1, "Freeing cache %p <%s>...\n", cache, nl_cache_name(cache)); - free(cache); + if (cache->c_refcnt <= 0) + __nl_cache_free(cache); } /** @} */ From 3ed1f9ab5fba2b43fb3c67ac03e0da90ac042ed0 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 15 Nov 2012 20:49:33 +0100 Subject: [PATCH 329/432] cache: Hold cache reference while a cache is being provided Signed-off-by: Thomas Graf --- lib/cache_mngt.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/cache_mngt.c b/lib/cache_mngt.c index fa1ac22..540c5c1 100644 --- a/lib/cache_mngt.c +++ b/lib/cache_mngt.c @@ -217,8 +217,10 @@ void nl_cache_mngt_provide(struct nl_cache *cache) ops = cache_ops_lookup_for_obj(cache->c_ops->co_obj_ops); if (!ops) BUG(); - else + else { + nl_cache_get(cache); ops->co_major_cache = cache; + } } /** @@ -236,8 +238,10 @@ void nl_cache_mngt_unprovide(struct nl_cache *cache) ops = cache_ops_lookup_for_obj(cache->c_ops->co_obj_ops); if (!ops) BUG(); - else if (ops->co_major_cache == cache) + else if (ops->co_major_cache == cache) { + nl_cache_free(ops->co_major_cache); ops->co_major_cache = NULL; + } } struct nl_cache *__nl_cache_mngt_require(const char *name) From 20efa14e5c188738c15a013e092af51b780fde61 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 15 Nov 2012 21:30:57 +0100 Subject: [PATCH 330/432] lock abstraction layer Hide pthread availability and enablement behind internal API Signed-off-by: Thomas Graf --- include/netlink-local.h | 50 +++++++++++++++++++++++++++++++++++++++++ lib/socket.c | 28 +++++------------------ 2 files changed, 56 insertions(+), 22 deletions(-) diff --git a/include/netlink-local.h b/include/netlink-local.h index 01c611a..1f580c6 100644 --- a/include/netlink-local.h +++ b/include/netlink-local.h @@ -53,6 +53,10 @@ #include #include +#ifndef DISABLE_PTHREADS +#include +#endif + #include #include #include @@ -210,4 +214,50 @@ static inline int build_sysconf_path(char **strp, const char *filename) return asprintf(strp, "%s/%s", sysconfdir, filename); } +#ifndef DISABLE_PTHREADS +#define NL_LOCK(NAME) pthread_mutex_t (NAME) = PTHREAD_MUTEX_INITIALIZER +#define NL_RW_LOCK(NAME) pthread_rwlock_t (NAME) = PTHREAD_RWLOCK_INITIALIZER + +static inline void nl_lock(pthread_mutex_t *lock) +{ + pthread_mutex_lock(lock); +} + +static inline void nl_unlock(pthread_mutex_t *lock) +{ + pthread_mutex_unlock(lock); +} + +static inline void nl_read_lock(pthread_rwlock_t *lock) +{ + pthread_rwlock_rdlock(lock); +} + +static inline void nl_read_unlock(pthread_rwlock_t *lock) +{ + pthread_rwlock_unlock(lock); +} + +static inline void nl_write_lock(pthread_rwlock_t *lock) +{ + pthread_rwlock_wrlock(lock); +} + +static inline void nl_write_unlock(pthread_rwlock_t *lock) +{ + pthread_rwlock_unlock(lock); +} + +#else +#define NL_LOCK(NAME) int __unused_lock_ ##NAME __attribute__((unused)) +#define NL_RW_LOCK(NAME) int __unused_lock_ ##NAME __attribute__((unused)) + +#define nl_lock(LOCK) do { } while(0) +#define nl_unlock(LOCK) do { } while(0) +#define nl_read_lock(LOCK) do { } while(0) +#define nl_read_unlock(LOCK) do { } while(0) +#define nl_write_lock(LOCK) do { } while(0) +#define nl_write_unlock(LOCK) do { } while(0) +#endif + #endif diff --git a/lib/socket.c b/lib/socket.c index 0335f07..b30058b 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -29,10 +29,6 @@ #include "defs.h" -#ifndef DISABLE_PTHREADS -#include -#endif - #include #include #include @@ -61,18 +57,14 @@ static void __init init_default_cb(void) } static uint32_t used_ports_map[32]; -#ifndef DISABLE_PTHREADS -static pthread_mutex_t port_map_mutex = PTHREAD_MUTEX_INITIALIZER; -#endif +static NL_RW_LOCK(port_map_lock); static uint32_t generate_local_port(void) { int i, n; uint32_t pid = getpid() & 0x3FFFFF; -#ifndef DISABLE_PTHREADS - pthread_mutex_lock(&port_map_mutex); -#endif + nl_write_lock(&port_map_lock); for (i = 0; i < 32; i++) { if (used_ports_map[i] == 0xFFFFFFFF) @@ -88,17 +80,13 @@ static uint32_t generate_local_port(void) /* PID_MAX_LIMIT is currently at 2^22, leaving 10 bit * to, i.e. 1024 unique ports per application. */ -#ifndef DISABLE_PTHREADS - pthread_mutex_unlock(&port_map_mutex); -#endif + nl_write_unlock(&port_map_lock); return pid + (n << 22); } } -#ifndef DISABLE_PTHREADS - pthread_mutex_unlock(&port_map_mutex); -#endif + nl_write_unlock(&port_map_lock); /* Out of sockets in our own PID namespace, what to do? FIXME */ return UINT_MAX; @@ -113,13 +101,9 @@ static void release_local_port(uint32_t port) nr = port >> 22; -#ifndef DISABLE_PTHREADS - pthread_mutex_lock(&port_map_mutex); -#endif + nl_write_lock(&port_map_lock); used_ports_map[nr / 32] &= ~(1 << (nr % 32)); -#ifndef DISABLE_PTHREADS - pthread_mutex_unlock(&port_map_mutex); -#endif + nl_write_unlock(&port_map_lock); } /** From f5af5c5ecd7245bef2f16fcb1e1270abbf435de0 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 15 Nov 2012 21:42:02 +0100 Subject: [PATCH 331/432] cache: rwlock accesses to cache operations Puts an rwlock around 'cache_ops'. Signed-off-by: Thomas Graf --- lib/cache_mngt.c | 54 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/lib/cache_mngt.c b/lib/cache_mngt.c index 540c5c1..65c4707 100644 --- a/lib/cache_mngt.c +++ b/lib/cache_mngt.c @@ -31,12 +31,24 @@ #include static struct nl_cache_ops *cache_ops; +static NL_RW_LOCK(cache_ops_lock); /** * @name Cache Operations Sets * @{ */ +struct nl_cache_ops *__nl_cache_ops_lookup(const char *name) +{ + struct nl_cache_ops *ops; + + for (ops = cache_ops; ops; ops = ops->co_next) + if (!strcmp(ops->co_name, name)) + return ops; + + return NULL; +} + /** * Lookup the set cache operations of a certain cache type * @arg name name of the cache type @@ -48,11 +60,11 @@ struct nl_cache_ops *nl_cache_ops_lookup(const char *name) { struct nl_cache_ops *ops; - for (ops = cache_ops; ops; ops = ops->co_next) - if (!strcmp(ops->co_name, name)) - return ops; + nl_read_lock(&cache_ops_lock); + ops = __nl_cache_ops_lookup(name); + nl_read_unlock(&cache_ops_lock); - return NULL; + return ops; } /** @@ -71,14 +83,19 @@ struct nl_cache_ops *nl_cache_ops_associate(int protocol, int msgtype) int i; struct nl_cache_ops *ops; + nl_read_lock(&cache_ops_lock); for (ops = cache_ops; ops; ops = ops->co_next) { if (ops->co_protocol != protocol) continue; - for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++) - if (ops->co_msgtypes[i].mt_id == msgtype) + for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++) { + if (ops->co_msgtypes[i].mt_id == msgtype) { + nl_read_unlock(&cache_ops_lock); return ops; + } + } } + nl_read_unlock(&cache_ops_lock); return NULL; } @@ -104,6 +121,7 @@ struct nl_msgtype *nl_msgtype_lookup(struct nl_cache_ops *ops, int msgtype) return NULL; } +/* Must hold cache_ops_lock */ static struct nl_cache_ops *cache_ops_lookup_for_obj(struct nl_object_ops *obj_ops) { struct nl_cache_ops *ops; @@ -125,8 +143,10 @@ void nl_cache_ops_foreach(void (*cb)(struct nl_cache_ops *, void *), void *arg) { struct nl_cache_ops *ops; + nl_read_lock(&cache_ops_lock); for (ops = cache_ops; ops; ops = ops->co_next) cb(ops, arg); + nl_read_unlock(&cache_ops_lock); } /** @@ -156,11 +176,15 @@ int nl_cache_mngt_register(struct nl_cache_ops *ops) if (!ops->co_name || !ops->co_obj_ops) return -NLE_INVAL; - if (nl_cache_ops_lookup(ops->co_name)) + nl_write_lock(&cache_ops_lock); + if (__nl_cache_ops_lookup(ops->co_name)) { + nl_write_unlock(&cache_ops_lock); return -NLE_EXIST; + } ops->co_next = cache_ops; cache_ops = ops; + nl_write_unlock(&cache_ops_lock); NL_DBG(1, "Registered cache operations %s\n", ops->co_name); @@ -182,16 +206,22 @@ int nl_cache_mngt_unregister(struct nl_cache_ops *ops) { struct nl_cache_ops *t, **tp; + nl_write_lock(&cache_ops_lock); + for (tp = &cache_ops; (t=*tp) != NULL; tp = &t->co_next) if (t == ops) break; - if (!t) + if (!t) { + nl_write_unlock(&cache_ops_lock); return -NLE_NOCACHE; + } NL_DBG(1, "Unregistered cache operations %s\n", ops->co_name); *tp = t->co_next; + nl_write_unlock(&cache_ops_lock); + return 0; } @@ -214,6 +244,8 @@ void nl_cache_mngt_provide(struct nl_cache *cache) { struct nl_cache_ops *ops; + nl_write_lock(&cache_ops_lock); + ops = cache_ops_lookup_for_obj(cache->c_ops->co_obj_ops); if (!ops) BUG(); @@ -221,6 +253,8 @@ void nl_cache_mngt_provide(struct nl_cache *cache) nl_cache_get(cache); ops->co_major_cache = cache; } + + nl_write_unlock(&cache_ops_lock); } /** @@ -235,6 +269,8 @@ void nl_cache_mngt_unprovide(struct nl_cache *cache) { struct nl_cache_ops *ops; + nl_write_lock(&cache_ops_lock); + ops = cache_ops_lookup_for_obj(cache->c_ops->co_obj_ops); if (!ops) BUG(); @@ -242,6 +278,8 @@ void nl_cache_mngt_unprovide(struct nl_cache *cache) nl_cache_free(ops->co_major_cache); ops->co_major_cache = NULL; } + + nl_write_unlock(&cache_ops_lock); } struct nl_cache *__nl_cache_mngt_require(const char *name) From 74926f92dd3a65e378def1a3e7309a027b8efbd3 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 15 Nov 2012 22:33:23 +0100 Subject: [PATCH 332/432] link: Protect registration of af and link ops with rwlock Signed-off-by: Thomas Graf --- lib/route/link/api.c | 74 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 57 insertions(+), 17 deletions(-) diff --git a/lib/route/link/api.c b/lib/route/link/api.c index f7907a7..a12eb09 100644 --- a/lib/route/link/api.c +++ b/lib/route/link/api.c @@ -47,6 +47,9 @@ static NL_LIST_HEAD(info_ops); +/* lock protecting info_ops and af_ops */ +static NL_RW_LOCK(info_lock); + static struct rtnl_link_info_ops *__rtnl_link_info_ops_lookup(const char *name) { struct rtnl_link_info_ops *ops; @@ -75,8 +78,10 @@ struct rtnl_link_info_ops *rtnl_link_info_ops_lookup(const char *name) { struct rtnl_link_info_ops *ops; + nl_write_lock(&info_lock); if ((ops = __rtnl_link_info_ops_lookup(name))) ops->io_refcnt++; + nl_write_unlock(&info_lock); return ops; } @@ -105,17 +110,24 @@ void rtnl_link_info_ops_put(struct rtnl_link_info_ops *ops) */ int rtnl_link_register_info(struct rtnl_link_info_ops *ops) { + int err = 0; + if (ops->io_name == NULL) return -NLE_INVAL; - if (__rtnl_link_info_ops_lookup(ops->io_name)) - return -NLE_EXIST; + nl_write_lock(&info_lock); + if (__rtnl_link_info_ops_lookup(ops->io_name)) { + err = -NLE_EXIST; + goto errout; + } NL_DBG(1, "Registered link info operations %s\n", ops->io_name); nl_list_add_tail(&ops->io_list, &info_ops); +errout: + nl_write_unlock(&info_lock); - return 0; + return err; } /** @@ -134,22 +146,30 @@ int rtnl_link_register_info(struct rtnl_link_info_ops *ops) int rtnl_link_unregister_info(struct rtnl_link_info_ops *ops) { struct rtnl_link_info_ops *t; + int err = -NLE_OPNOTSUPP; + + nl_write_lock(&info_lock); nl_list_for_each_entry(t, &info_ops, io_list) { if (t == ops) { - if (t->io_refcnt > 0) - return -NLE_BUSY; + if (t->io_refcnt > 0) { + err = -NLE_BUSY; + goto errout; + } nl_list_del(&t->io_list); NL_DBG(1, "Unregistered link info operations %s\n", ops->io_name); - - return 0; + err = 0; + goto errout; } } - return -NLE_OPNOTSUPP; +errout: + nl_write_unlock(&info_lock); + + return err; } /** @} */ @@ -174,8 +194,10 @@ struct rtnl_link_af_ops *rtnl_link_af_ops_lookup(const unsigned int family) if (family == AF_UNSPEC || family >= AF_MAX) return NULL; + nl_write_lock(&info_lock); if (af_ops[family]) af_ops[family]->ao_refcnt++; + nl_write_unlock(&info_lock); return af_ops[family]; } @@ -262,11 +284,16 @@ void *rtnl_link_af_data(const struct rtnl_link *link, */ int rtnl_link_af_register(struct rtnl_link_af_ops *ops) { + int err = 0; + if (ops->ao_family == AF_UNSPEC || ops->ao_family >= AF_MAX) return -NLE_INVAL; - if (af_ops[ops->ao_family]) - return -NLE_EXIST; + nl_write_lock(&info_lock); + if (af_ops[ops->ao_family]) { + err = -NLE_EXIST; + goto errout; + } ops->ao_refcnt = 0; af_ops[ops->ao_family] = ops; @@ -274,7 +301,10 @@ int rtnl_link_af_register(struct rtnl_link_af_ops *ops) NL_DBG(1, "Registered link address family operations %u\n", ops->ao_family); - return 0; +errout: + nl_write_unlock(&info_lock); + + return err; } /** @@ -293,21 +323,31 @@ int rtnl_link_af_register(struct rtnl_link_af_ops *ops) */ int rtnl_link_af_unregister(struct rtnl_link_af_ops *ops) { + int err = -NLE_INVAL; + if (!ops) - return -NLE_INVAL; + goto errout; - if (!af_ops[ops->ao_family]) - return -NLE_OBJ_NOTFOUND; + nl_write_lock(&info_lock); + if (!af_ops[ops->ao_family]) { + err = -NLE_OBJ_NOTFOUND; + goto errout; + } - if (ops->ao_refcnt > 0) - return -NLE_BUSY; + if (ops->ao_refcnt > 0) { + err = -NLE_BUSY; + goto errout; + } af_ops[ops->ao_family] = NULL; NL_DBG(1, "Unregistered link address family operations %u\n", ops->ao_family); - return 0; +errout: + nl_write_lock(&info_lock); + + return err; } /** @} */ From 1a2c3e36a8aa6b3a0a568f587669c7c8d5ddac28 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 15 Nov 2012 23:48:03 +0100 Subject: [PATCH 333/432] cache: Add reference counter to cache operations Signed-off-by: Thomas Graf --- include/netlink/cache-api.h | 6 ++++++ lib/cache_mngt.c | 32 +++++++++++++++++++++++++++++--- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/include/netlink/cache-api.h b/include/netlink/cache-api.h index dd42671..f2111b9 100644 --- a/include/netlink/cache-api.h +++ b/include/netlink/cache-api.h @@ -192,6 +192,9 @@ struct nl_cache_ops /** cache flags */ unsigned int co_flags; + /** Reference counter */ + unsigned int co_refcnt; + /** Group definition */ struct nl_af_group * co_groups; @@ -262,6 +265,9 @@ struct nl_cache_ops struct nl_msgtype co_msgtypes[]; }; +extern void nl_cache_ops_get(struct nl_cache_ops *); +extern void nl_cache_ops_put(struct nl_cache_ops *); + /** @} */ #ifdef __cplusplus diff --git a/lib/cache_mngt.c b/lib/cache_mngt.c index 65c4707..d0dfcdd 100644 --- a/lib/cache_mngt.c +++ b/lib/cache_mngt.c @@ -49,6 +49,24 @@ struct nl_cache_ops *__nl_cache_ops_lookup(const char *name) return NULL; } +/** + * Increment reference counter + * @arg ops Cache operations + */ +void nl_cache_ops_get(struct nl_cache_ops *ops) +{ + ops->co_refcnt++; +} + +/** + * Decrement reference counter + * @arg ops Cache operations + */ +void nl_cache_ops_put(struct nl_cache_ops *ops) +{ + ops->co_refcnt--; +} + /** * Lookup the set cache operations of a certain cache type * @arg name name of the cache type @@ -182,6 +200,7 @@ int nl_cache_mngt_register(struct nl_cache_ops *ops) return -NLE_EXIST; } + ops->co_refcnt = 0; ops->co_next = cache_ops; cache_ops = ops; nl_write_unlock(&cache_ops_lock); @@ -205,24 +224,31 @@ int nl_cache_mngt_register(struct nl_cache_ops *ops) int nl_cache_mngt_unregister(struct nl_cache_ops *ops) { struct nl_cache_ops *t, **tp; + int err = 0; nl_write_lock(&cache_ops_lock); + if (ops->co_refcnt > 0) { + err = -NLE_BUSY; + goto errout; + } + for (tp = &cache_ops; (t=*tp) != NULL; tp = &t->co_next) if (t == ops) break; if (!t) { - nl_write_unlock(&cache_ops_lock); - return -NLE_NOCACHE; + err = -NLE_NOCACHE; + goto errout; } NL_DBG(1, "Unregistered cache operations %s\n", ops->co_name); *tp = t->co_next; +errout: nl_write_unlock(&cache_ops_lock); - return 0; + return err; } /** @} */ From 2b3912a320ef74b31d84380d91ec036dbf1b9f52 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 16 Nov 2012 00:19:38 +0100 Subject: [PATCH 334/432] cache: Provide safe versions of nl_cache_ops_associate() and nl_cache_ops_lookup() Signed-off-by: Thomas Graf --- include/netlink/cache.h | 2 + lib/cache_mngt.c | 94 +++++++++++++++++++++++++++++++++-------- 2 files changed, 78 insertions(+), 18 deletions(-) diff --git a/include/netlink/cache.h b/include/netlink/cache.h index 0bd4037..f193c76 100644 --- a/include/netlink/cache.h +++ b/include/netlink/cache.h @@ -106,7 +106,9 @@ extern void nl_cache_foreach_filter(struct nl_cache *, /* Cache type management */ extern struct nl_cache_ops * nl_cache_ops_lookup(const char *); +extern struct nl_cache_ops * nl_cache_ops_lookup_safe(const char *); extern struct nl_cache_ops * nl_cache_ops_associate(int, int); +extern struct nl_cache_ops * nl_cache_ops_associate_safe(int, int); extern struct nl_msgtype * nl_msgtype_lookup(struct nl_cache_ops *, int); extern void nl_cache_ops_foreach(void (*cb)(struct nl_cache_ops *, void *), void *); extern int nl_cache_mngt_register(struct nl_cache_ops *); diff --git a/lib/cache_mngt.c b/lib/cache_mngt.c index d0dfcdd..d5ca6d3 100644 --- a/lib/cache_mngt.c +++ b/lib/cache_mngt.c @@ -68,11 +68,13 @@ void nl_cache_ops_put(struct nl_cache_ops *ops) } /** - * Lookup the set cache operations of a certain cache type + * Lookup cache operations by name * @arg name name of the cache type * - * @return The cache operations or NULL if no operations - * have been registered under the specified name. + * @attention This function is not safe, it does not increment the reference + * counter. Please use nl_cache_ops_lookup_safe(). + * + * @return The cache operations or NULL if not found. */ struct nl_cache_ops *nl_cache_ops_lookup(const char *name) { @@ -86,38 +88,91 @@ struct nl_cache_ops *nl_cache_ops_lookup(const char *name) } /** - * Associate a message type to a set of cache operations - * @arg protocol netlink protocol - * @arg msgtype netlink message type + * Lookup cache operations by name + * @arg name name of the cache type * - * Associates the specified netlink message type with - * a registered set of cache operations. + * @note The reference counter of the returned cache operation is incremented + * and must be decremented after use with nl_cache_ops_put(). * - * @return The cache operations or NULL if no association - * could be made. + * @return The cache operations or NULL if not found. */ -struct nl_cache_ops *nl_cache_ops_associate(int protocol, int msgtype) +struct nl_cache_ops *nl_cache_ops_lookup_safe(const char *name) +{ + struct nl_cache_ops *ops; + + nl_write_lock(&cache_ops_lock); + if ((ops = __nl_cache_ops_lookup(name))) + nl_cache_ops_get(ops); + nl_write_unlock(&cache_ops_lock); + + return ops; +} + +static struct nl_cache_ops *__cache_ops_associate(int protocol, int msgtype) { int i; struct nl_cache_ops *ops; - nl_read_lock(&cache_ops_lock); for (ops = cache_ops; ops; ops = ops->co_next) { if (ops->co_protocol != protocol) continue; - for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++) { - if (ops->co_msgtypes[i].mt_id == msgtype) { - nl_read_unlock(&cache_ops_lock); + for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++) + if (ops->co_msgtypes[i].mt_id == msgtype) return ops; - } - } } - nl_read_unlock(&cache_ops_lock); return NULL; } +/** + * Associate protocol and message type to cache operations + * @arg protocol netlink protocol + * @arg msgtype netlink message type + * + * @attention This function is not safe, it does not increment the reference + * counter. Please use nl_cache_ops_associate_safe(). + * + * @see nl_cache_ops_associate_safe() + * + * @return The cache operations or NULL if no match found. + */ +struct nl_cache_ops *nl_cache_ops_associate(int protocol, int msgtype) +{ + struct nl_cache_ops *ops; + + nl_read_lock(&cache_ops_lock); + ops = __cache_ops_associate(protocol, msgtype); + nl_read_unlock(&cache_ops_lock); + + return ops; +} + +/** + * Associate protocol and message type to cache operations + * @arg protocol netlink protocol + * @arg msgtype netlink message type + * + * Searches the registered cache operations for a matching protocol + * and message type. + * + * @note The reference counter of the returned cache operation is incremented + * and must be decremented after use with nl_cache_ops_put(). + * + * @return The cache operations or NULL if no no match was found. + */ +struct nl_cache_ops *nl_cache_ops_associate_safe(int protocol, int msgtype) +{ + struct nl_cache_ops *ops; + + nl_write_lock(&cache_ops_lock); + if ((ops = __cache_ops_associate(protocol, msgtype))) + nl_cache_ops_get(ops); + nl_write_unlock(&cache_ops_lock); + + return ops; +} + /** * Lookup message type cache association * @arg ops cache operations @@ -126,6 +181,9 @@ struct nl_cache_ops *nl_cache_ops_associate(int protocol, int msgtype) * Searches for a matching message type association ing the specified * cache operations. * + * @attention The guranteed lifetime of the returned message type is bound + * to the lifetime of the underlying cache operations. + * * @return A message type association or NULL. */ struct nl_msgtype *nl_msgtype_lookup(struct nl_cache_ops *ops, int msgtype) From cb82c2a5451a52e7365957a2325258af1b179aee Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 16 Nov 2012 00:20:18 +0100 Subject: [PATCH 335/432] use safe cache lookup variants internally Signed-off-by: Thomas Graf --- lib/cache.c | 6 ++++-- lib/cache_mngr.c | 3 ++- lib/msg.c | 20 ++++++++++++++------ lib/object.c | 6 ++++-- 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/lib/cache.c b/lib/cache.c index 257a41b..36566e0 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -266,11 +266,13 @@ int nl_cache_alloc_name(const char *kind, struct nl_cache **result) struct nl_cache_ops *ops; struct nl_cache *cache; - ops = nl_cache_ops_lookup(kind); + ops = nl_cache_ops_lookup_safe(kind); if (!ops) return -NLE_NOCACHE; - if (!(cache = nl_cache_alloc(ops))) + cache = nl_cache_alloc(ops); + nl_cache_ops_put(ops); + if (!cache) return -NLE_NOMEM; *result = cache; diff --git a/lib/cache_mngr.c b/lib/cache_mngr.c index 63cc0d3..bf92d11 100644 --- a/lib/cache_mngr.c +++ b/lib/cache_mngr.c @@ -314,11 +314,12 @@ int nl_cache_mngr_add(struct nl_cache_mngr *mngr, const char *name, struct nl_cache *cache; int err; - ops = nl_cache_ops_lookup(name); + ops = nl_cache_ops_lookup_safe(name); if (!ops) return -NLE_NOCACHE; cache = nl_cache_alloc(ops); + nl_cache_ops_put(ops); if (!cache) return -NLE_NOMEM; diff --git a/lib/msg.c b/lib/msg.c index 0adc091..23c137d 100644 --- a/lib/msg.c +++ b/lib/msg.c @@ -733,14 +733,18 @@ int nl_msg_parse(struct nl_msg *msg, void (*cb)(struct nl_object *, void *), .cb = cb, .arg = arg, }; + int err; - ops = nl_cache_ops_associate(nlmsg_get_proto(msg), - nlmsg_hdr(msg)->nlmsg_type); + ops = nl_cache_ops_associate_safe(nlmsg_get_proto(msg), + nlmsg_hdr(msg)->nlmsg_type); if (ops == NULL) return -NLE_MSGTYPE_NOSUPPORT; p.pp_arg = &x; - return nl_cache_parse(ops, NULL, nlmsg_hdr(msg), &p); + err = nl_cache_parse(ops, NULL, nlmsg_hdr(msg), &p); + nl_cache_ops_put(ops); + + return err; } /** @} */ @@ -801,13 +805,14 @@ static void print_hdr(FILE *ofd, struct nl_msg *msg) fprintf(ofd, " .nlmsg_len = %d\n", nlh->nlmsg_len); - ops = nl_cache_ops_associate(nlmsg_get_proto(msg), nlh->nlmsg_type); + ops = nl_cache_ops_associate_safe(nlmsg_get_proto(msg), nlh->nlmsg_type); if (ops) { mt = nl_msgtype_lookup(ops, nlh->nlmsg_type); if (!mt) BUG(); snprintf(buf, sizeof(buf), "%s::%s", ops->co_name, mt->mt_name); + nl_cache_ops_put(ops); } else nl_nlmsgtype2str(nlh->nlmsg_type, buf, sizeof(buf)); @@ -888,8 +893,8 @@ void nl_msg_dump(struct nl_msg *msg, FILE *ofd) int payloadlen = nlmsg_len(hdr); int attrlen = 0; - ops = nl_cache_ops_associate(nlmsg_get_proto(msg), - hdr->nlmsg_type); + ops = nl_cache_ops_associate_safe(nlmsg_get_proto(msg), + hdr->nlmsg_type); if (ops) { attrlen = nlmsg_attrlen(hdr, ops->co_hdrsize); payloadlen -= attrlen; @@ -906,6 +911,9 @@ void nl_msg_dump(struct nl_msg *msg, FILE *ofd) attrlen = nlmsg_attrlen(hdr, ops->co_hdrsize); dump_attrs(ofd, attrs, attrlen, 0); } + + if (ops) + nl_cache_ops_put(ops); } fprintf(ofd, diff --git a/lib/object.c b/lib/object.c index 024062e..806bae6 100644 --- a/lib/object.c +++ b/lib/object.c @@ -85,11 +85,13 @@ int nl_object_alloc_name(const char *kind, struct nl_object **result) { struct nl_cache_ops *ops; - ops = nl_cache_ops_lookup(kind); + ops = nl_cache_ops_lookup_safe(kind); if (!ops) return -NLE_OPNOTSUPP; - if (!(*result = nl_object_alloc(ops->co_obj_ops))) + *result = nl_object_alloc(ops->co_obj_ops); + nl_cache_ops_put(ops); + if (!*result) return -NLE_NOMEM; return 0; From 235aa7ff17e12ca7a76dcfd77abfe143c2ce4dea Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 16 Nov 2012 00:27:51 +0100 Subject: [PATCH 336/432] cache: hold a reference to the cache ops while a cache is provided over it Signed-off-by: Thomas Graf --- lib/cache_mngt.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/lib/cache_mngt.c b/lib/cache_mngt.c index d5ca6d3..8f011fb 100644 --- a/lib/cache_mngt.c +++ b/lib/cache_mngt.c @@ -335,6 +335,14 @@ void nl_cache_mngt_provide(struct nl_cache *cache) BUG(); else { nl_cache_get(cache); + + /* + * Hold a reference to the cache operations to ensure the + * ops don't go away while we use it to store the cache pointer. + */ + if (!ops->co_major_cache) + nl_cache_ops_get(ops); + ops->co_major_cache = cache; } @@ -360,6 +368,7 @@ void nl_cache_mngt_unprovide(struct nl_cache *cache) BUG(); else if (ops->co_major_cache == cache) { nl_cache_free(ops->co_major_cache); + nl_cache_ops_put(ops); ops->co_major_cache = NULL; } @@ -369,12 +378,15 @@ void nl_cache_mngt_unprovide(struct nl_cache *cache) struct nl_cache *__nl_cache_mngt_require(const char *name) { struct nl_cache_ops *ops; + struct nl_cache *cache = NULL; - ops = nl_cache_ops_lookup(name); - if (ops) - return ops->co_major_cache; + ops = nl_cache_ops_lookup_safe(name); + if (ops) { + cache = ops->co_major_cache; + nl_cache_ops_put(ops); + } - return NULL; + return cache; } /** From 23c4ef67c735813fd41f66f6722b996d1ad7314a Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 16 Nov 2012 00:42:34 +0100 Subject: [PATCH 337/432] Use NL_DBG() instead of printing warnings and errors to stderr Signed-off-by: Thomas Graf --- include/netlink-local.h | 12 ++++++------ lib/attr.c | 4 ++-- lib/cache.c | 2 +- lib/cache_mngt.c | 8 ++++---- lib/route/classid.c | 2 +- lib/utils.c | 2 +- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/include/netlink-local.h b/include/netlink-local.h index 1f580c6..2bfae3e 100644 --- a/include/netlink-local.h +++ b/include/netlink-local.h @@ -86,16 +86,16 @@ struct trans_list { fprintf(stderr, "DBG<" #LVL ">: " FMT, ##ARG); \ } while (0) -#define BUG() \ - do { \ - fprintf(stderr, "BUG: %s:%d\n", \ - __FILE__, __LINE__); \ - assert(0); \ +#define BUG() \ + do { \ + NL_DBG(1, "BUG: %s:%d\n", \ + __FILE__, __LINE__); \ + assert(0); \ } while (0) #define APPBUG(msg) \ do { \ - fprintf(stderr, "APPLICATION BUG: %s:%d:%s: %s\n", \ + NL_DBG(1, "APPLICATION BUG: %s:%d:%s: %s\n", \ __FILE__, __LINE__, __PRETTY_FUNCTION__, msg); \ assert(0); \ } while(0) diff --git a/lib/attr.c b/lib/attr.c index a095649..1601061 100644 --- a/lib/attr.c +++ b/lib/attr.c @@ -253,7 +253,7 @@ int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len, int type = nla_type(nla); if (type == 0) { - fprintf(stderr, "Illegal nla->nla_type == 0\n"); + NL_DBG(1, "Illegal nla->nla_type == 0\n"); continue; } @@ -269,7 +269,7 @@ int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len, } if (rem > 0) - fprintf(stderr, "netlink: %d bytes leftover after parsing " + NL_DBG(1, "netlink: %d bytes leftover after parsing " "attributes.\n", rem); err = 0; diff --git a/lib/cache.c b/lib/cache.c index 36566e0..aa17ad8 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -925,7 +925,7 @@ restart: err = nl_cache_pickup(sk, cache); if (err == -NLE_DUMP_INTR) { - fprintf(stderr, "dump interrupted, restarting!\n"); + NL_DBG(1, "dump interrupted, restarting!\n"); goto restart; } else if (err < 0) break; diff --git a/lib/cache_mngt.c b/lib/cache_mngt.c index 8f011fb..914ab9b 100644 --- a/lib/cache_mngt.c +++ b/lib/cache_mngt.c @@ -404,10 +404,10 @@ struct nl_cache *nl_cache_mngt_require(const char *name) struct nl_cache *cache; if (!(cache = __nl_cache_mngt_require(name))) - fprintf(stderr, "Application BUG: Your application must " - "call nl_cache_mngt_provide() and\nprovide a valid " - "%s cache to be used for internal lookups.\nSee the " - " API documentation for more details.\n", name); + NL_DBG(1, "Application BUG: Your application must " + "call nl_cache_mngt_provide() and\nprovide a valid " + "%s cache to be used for internal lookups.\nSee the " + " API documentation for more details.\n", name); return cache; } diff --git a/lib/route/classid.c b/lib/route/classid.c index 87025a0..255e075 100644 --- a/lib/route/classid.c +++ b/lib/route/classid.c @@ -441,7 +441,7 @@ static void __init classid_init(void) nl_init_list_head(&tbl_name[i]); if ((err = rtnl_tc_read_classid_file()) < 0) - fprintf(stderr, "Failed to read classid file: %s\n", nl_geterror(err)); + NL_DBG(1, "Failed to read classid file: %s\n", nl_geterror(err)); } static void free_map(void *map) { diff --git a/lib/utils.c b/lib/utils.c index b5e32c3..b434bee 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -426,7 +426,7 @@ static void __init get_psched_settings(void) if (fscanf(fd, "%08x %08x %08x %08x", &ns_per_usec, &ns_per_tick, &nom, &denom) != 4) { - fprintf(stderr, "Fatal error: can not read psched settings from \"%s\". " \ + NL_DBG(1, "Fatal error: can not read psched settings from \"%s\". " \ "Try to set TICKS_PER_USEC, PROC_NET_PSCHED or PROC_ROOT " \ "environment variables\n", name); exit(1); From 00132b46968fff7975eb8d20a307c626dfefe2f1 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 16 Nov 2012 01:11:55 +0100 Subject: [PATCH 338/432] cache: provide safe variant of nl_cache_mngt_require() and use it This makes runtime removal of cache operations possible if non-safe API is not in use by application. The non-safe API will be removed in the next major version. Signed-off-by: Thomas Graf --- include/netlink-local.h | 8 -------- include/netlink/cache.h | 2 ++ lib/cache.c | 5 +++++ lib/cache_mngt.c | 32 ++++++++++++++++++++++++++------ lib/netfilter/log_msg_obj.c | 5 ++++- lib/netfilter/queue_msg_obj.c | 5 ++++- lib/route/addr.c | 5 ++++- lib/route/link.c | 2 +- lib/route/neigh.c | 9 +++++++-- lib/route/neightbl.c | 3 ++- lib/route/nexthop.c | 10 ++++++++-- lib/route/route_obj.c | 5 ++++- lib/route/tc.c | 5 ++++- src/nl-addr-list.c | 5 ++++- 14 files changed, 75 insertions(+), 26 deletions(-) diff --git a/include/netlink-local.h b/include/netlink-local.h index 2bfae3e..b891d8c 100644 --- a/include/netlink-local.h +++ b/include/netlink-local.h @@ -117,14 +117,6 @@ extern int __str2flags(const char *, const struct trans_tbl *, size_t); extern void dump_from_ops(struct nl_object *, struct nl_dump_params *); -static inline struct nl_cache *dp_cache(struct nl_object *obj) -{ - if (obj->ce_cache == NULL) - return nl_cache_mngt_require(obj->ce_ops->oo_name); - - return obj->ce_cache; -} - static inline int nl_cb_call(struct nl_cb *cb, int type, struct nl_msg *msg) { return cb->cb_set[type](msg, cb->cb_args[type]); diff --git a/include/netlink/cache.h b/include/netlink/cache.h index f193c76..ac03842 100644 --- a/include/netlink/cache.h +++ b/include/netlink/cache.h @@ -52,6 +52,7 @@ extern struct nl_cache * nl_cache_clone(struct nl_cache *); extern void nl_cache_clear(struct nl_cache *); extern void nl_cache_get(struct nl_cache *); extern void nl_cache_free(struct nl_cache *); +extern void nl_cache_put(struct nl_cache *cache); /* Cache modification */ extern int nl_cache_add(struct nl_cache *, @@ -118,6 +119,7 @@ extern int nl_cache_mngt_unregister(struct nl_cache_ops *); extern void nl_cache_mngt_provide(struct nl_cache *); extern void nl_cache_mngt_unprovide(struct nl_cache *); extern struct nl_cache * nl_cache_mngt_require(const char *); +extern struct nl_cache * nl_cache_mngt_require_safe(const char *); extern struct nl_cache * __nl_cache_mngt_require(const char *); struct nl_cache_mngr; diff --git a/lib/cache.c b/lib/cache.c index aa17ad8..415e471 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -410,6 +410,11 @@ void nl_cache_free(struct nl_cache *cache) __nl_cache_free(cache); } +void nl_cache_put(struct nl_cache *cache) +{ + return nl_cache_free(cache); +} + /** @} */ /** diff --git a/lib/cache_mngt.c b/lib/cache_mngt.c index 914ab9b..fbb702f 100644 --- a/lib/cache_mngt.c +++ b/lib/cache_mngt.c @@ -390,14 +390,15 @@ struct nl_cache *__nl_cache_mngt_require(const char *name) } /** - * Demand the use of a global cache - * @arg name name of the required object type + * Return cache previously provided via nl_cache_mngt_provide() + * @arg name Name of cache to lookup * - * Trys to find a cache of the specified type for global - * use. + * @attention This function is not safe, it does not increment the reference + * counter. Please use nl_cache_mngt_require_safe(). * - * @return A cache provided by another subsystem of the - * specified type marked to be available. + * @see nl_cache_mngt_require_safe() + * + * @return Pointer to cache or NULL if none registered */ struct nl_cache *nl_cache_mngt_require(const char *name) { @@ -412,6 +413,25 @@ struct nl_cache *nl_cache_mngt_require(const char *name) return cache; } +/** + * Return cache previously provided via nl_cache_mngt_provide() + * @arg name Name of cache to lookup + * + * @note The reference counter of the returned cache is incremented + * and must be decremented after use with nl_cache_put(). + * + * @return Pointer to cache or NULL if none registered + */ +struct nl_cache *nl_cache_mngt_require_safe(const char *name) +{ + struct nl_cache *cache; + + if ((cache = nl_cache_mngt_require(name))) + nl_cache_get(cache); + + return cache; +} + /** @} */ /** @} */ diff --git a/lib/netfilter/log_msg_obj.c b/lib/netfilter/log_msg_obj.c index d2cde4e..d2ad0ff 100644 --- a/lib/netfilter/log_msg_obj.c +++ b/lib/netfilter/log_msg_obj.c @@ -76,7 +76,7 @@ static void log_msg_dump(struct nl_object *a, struct nl_dump_params *p) struct nl_cache *link_cache; char buf[64]; - link_cache = nl_cache_mngt_require("route/link"); + link_cache = nl_cache_mngt_require_safe("route/link"); nl_new_line(p); @@ -167,6 +167,9 @@ static void log_msg_dump(struct nl_object *a, struct nl_dump_params *p) nl_dump(p, "SEQGLOBAL=%d ", msg->log_msg_seq_global); nl_dump(p, "\n"); + + if (link_cache) + nl_cache_put(link_cache); } /** diff --git a/lib/netfilter/queue_msg_obj.c b/lib/netfilter/queue_msg_obj.c index 33305ed..bfaafc5 100644 --- a/lib/netfilter/queue_msg_obj.c +++ b/lib/netfilter/queue_msg_obj.c @@ -66,7 +66,7 @@ static void nfnl_queue_msg_dump(struct nl_object *a, struct nl_dump_params *p) struct nl_cache *link_cache; char buf[64]; - link_cache = nl_cache_mngt_require("route/link"); + link_cache = nl_cache_mngt_require_safe("route/link"); nl_new_line(p); @@ -152,6 +152,9 @@ static void nfnl_queue_msg_dump(struct nl_object *a, struct nl_dump_params *p) buf, sizeof(buf))); nl_dump(p, "\n"); + + if (link_cache) + nl_cache_put(link_cache); } /** diff --git a/lib/route/addr.c b/lib/route/addr.c index 7e29529..c5e14bb 100644 --- a/lib/route/addr.c +++ b/lib/route/addr.c @@ -332,7 +332,7 @@ static void addr_dump_line(struct nl_object *obj, struct nl_dump_params *p) struct nl_cache *link_cache; char buf[128]; - link_cache = nl_cache_mngt_require("route/link"); + link_cache = nl_cache_mngt_require_safe("route/link"); if (addr->ce_mask & ADDR_ATTR_LOCAL) nl_dump_line(p, "%s", @@ -361,6 +361,9 @@ static void addr_dump_line(struct nl_object *obj, struct nl_dump_params *p) nl_dump(p, " <%s>", buf); nl_dump(p, "\n"); + + if (link_cache) + nl_cache_put(link_cache); } static void addr_dump_details(struct nl_object *obj, struct nl_dump_params *p) diff --git a/lib/route/link.c b/lib/route/link.c index b378f30..1cecd54 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -581,7 +581,7 @@ static int link_request_update(struct nl_cache *cache, struct nl_sock *sk) static void link_dump_line(struct nl_object *obj, struct nl_dump_params *p) { char buf[128]; - struct nl_cache *cache = dp_cache(obj); + struct nl_cache *cache = obj->ce_cache; struct rtnl_link *link = (struct rtnl_link *) obj; nl_dump_line(p, "%s %s ", link->l_name, diff --git a/lib/route/neigh.c b/lib/route/neigh.c index 4b5893a..4a85a85 100644 --- a/lib/route/neigh.c +++ b/lib/route/neigh.c @@ -401,7 +401,7 @@ int rtnl_neigh_parse(struct nlmsghdr *n, struct rtnl_neigh **result) * Get the bridge index for AF_BRIDGE family entries */ if (neigh->n_family == AF_BRIDGE) { - struct nl_cache *lcache = nl_cache_mngt_require("route/link"); + struct nl_cache *lcache = nl_cache_mngt_require_safe("route/link"); if (lcache ) { struct rtnl_link *link = rtnl_link_get(lcache, neigh->n_ifindex); @@ -410,6 +410,8 @@ int rtnl_neigh_parse(struct nlmsghdr *n, struct rtnl_neigh **result) rtnl_link_put(link); neigh->ce_mask |= NEIGH_ATTR_MASTER; } + + nl_cache_put(lcache); } } @@ -436,7 +438,7 @@ static void neigh_dump_line(struct nl_object *a, struct nl_dump_params *p) struct nl_cache *link_cache; char state[128], flags[64]; - link_cache = nl_cache_mngt_require("route/link"); + link_cache = nl_cache_mngt_require_safe("route/link"); if (n->n_family != AF_BRIDGE) nl_dump_line(p, "%s ", nl_addr2str(n->n_dst, dst, sizeof(dst))); @@ -462,6 +464,9 @@ static void neigh_dump_line(struct nl_object *a, struct nl_dump_params *p) if (state[0] || flags[0]) nl_dump(p, ">"); nl_dump(p, "\n"); + + if (link_cache) + nl_cache_put(link_cache); } static void neigh_dump_details(struct nl_object *a, struct nl_dump_params *p) diff --git a/lib/route/neightbl.c b/lib/route/neightbl.c index 1efa5cb..509617b 100644 --- a/lib/route/neightbl.c +++ b/lib/route/neightbl.c @@ -237,7 +237,7 @@ static void neightbl_dump_line(struct nl_object *arg, struct nl_dump_params *p) if (ntbl->nt_parms.ntp_mask & NEIGHTBLPARM_ATTR_IFINDEX) { struct nl_cache *link_cache; - link_cache = nl_cache_mngt_require("route/link"); + link_cache = nl_cache_mngt_require_safe("route/link"); if (link_cache) { char buf[32]; @@ -245,6 +245,7 @@ static void neightbl_dump_line(struct nl_object *arg, struct nl_dump_params *p) rtnl_link_i2name(link_cache, ntbl->nt_parms.ntp_ifindex, buf, sizeof(buf))); + nl_cache_put(link_cache); } else nl_dump(p, "<%u> ", ntbl->nt_parms.ntp_ifindex); } else diff --git a/lib/route/nexthop.c b/lib/route/nexthop.c index 189bccd..9990c51 100644 --- a/lib/route/nexthop.c +++ b/lib/route/nexthop.c @@ -109,7 +109,7 @@ static void nh_dump_line(struct rtnl_nexthop *nh, struct nl_dump_params *dp) struct nl_cache *link_cache; char buf[128]; - link_cache = nl_cache_mngt_require("route/link"); + link_cache = nl_cache_mngt_require_safe("route/link"); nl_dump(dp, "via"); @@ -128,6 +128,9 @@ static void nh_dump_line(struct rtnl_nexthop *nh, struct nl_dump_params *dp) } nl_dump(dp, " "); + + if (link_cache) + nl_cache_put(link_cache); } static void nh_dump_details(struct rtnl_nexthop *nh, struct nl_dump_params *dp) @@ -135,7 +138,7 @@ static void nh_dump_details(struct rtnl_nexthop *nh, struct nl_dump_params *dp) struct nl_cache *link_cache; char buf[128]; - link_cache = nl_cache_mngt_require("route/link"); + link_cache = nl_cache_mngt_require_safe("route/link"); nl_dump(dp, "nexthop"); @@ -164,6 +167,9 @@ static void nh_dump_details(struct rtnl_nexthop *nh, struct nl_dump_params *dp) if (nh->ce_mask & NH_ATTR_FLAGS) nl_dump(dp, " <%s>", rtnl_route_nh_flags2str(nh->rtnh_flags, buf, sizeof(buf))); + + if (link_cache) + nl_cache_put(link_cache); } void rtnl_route_nh_dump(struct rtnl_nexthop *nh, struct nl_dump_params *dp) diff --git a/lib/route/route_obj.c b/lib/route/route_obj.c index 0ee9ca0..cc29746 100644 --- a/lib/route/route_obj.c +++ b/lib/route/route_obj.c @@ -210,7 +210,7 @@ static void route_dump_details(struct nl_object *a, struct nl_dump_params *p) char buf[128]; int i; - link_cache = nl_cache_mngt_require("route/link"); + link_cache = nl_cache_mngt_require_safe("route/link"); route_dump_line(a, p); nl_dump_line(p, " "); @@ -271,6 +271,9 @@ static void route_dump_details(struct nl_object *a, struct nl_dump_params *p) r->rt_metrics[i]); nl_dump(p, "]\n"); } + + if (link_cache) + nl_cache_put(link_cache); } static void route_dump_stats(struct nl_object *obj, struct nl_dump_params *p) diff --git a/lib/route/tc.c b/lib/route/tc.c index 6c72c15..5a0b783 100644 --- a/lib/route/tc.c +++ b/lib/route/tc.c @@ -822,7 +822,7 @@ void rtnl_tc_dump_line(struct nl_object *obj, struct nl_dump_params *p) nl_dump(p, "%s ", tc->tc_kind); - if ((link_cache = nl_cache_mngt_require("route/link"))) { + if ((link_cache = nl_cache_mngt_require_safe("route/link"))) { nl_dump(p, "dev %s ", rtnl_link_i2name(link_cache, tc->tc_ifindex, buf, sizeof(buf))); @@ -837,6 +837,9 @@ void rtnl_tc_dump_line(struct nl_object *obj, struct nl_dump_params *p) tc_dump(tc, NL_DUMP_LINE, p); nl_dump(p, "\n"); + + if (link_cache) + nl_cache_put(link_cache); } void rtnl_tc_dump_details(struct nl_object *obj, struct nl_dump_params *p) diff --git a/src/nl-addr-list.c b/src/nl-addr-list.c index 5044d5c..20995a8 100644 --- a/src/nl-addr-list.c +++ b/src/nl-addr-list.c @@ -65,7 +65,7 @@ static void env_dump(struct nl_object *obj, void *arg) nl_addr2str(rtnl_addr_get_local(addr), buf, sizeof(buf))); nl_dump_line(p, "%s_IFINDEX=%u\n", pfx, rtnl_addr_get_ifindex(addr)); - link_cache = nl_cache_mngt_require("route/link"); + link_cache = nl_cache_mngt_require_safe("route/link"); if (link_cache) nl_dump_line(p, "%s_IFNAME=%s\n", pfx, rtnl_link_i2name(link_cache, @@ -94,6 +94,9 @@ static void env_dump(struct nl_object *obj, void *arg) nl_dump_line(p, "%s_CACHEINFO_VALID=%u\n", pfx, rtnl_addr_get_valid_lifetime(addr)); + if (link_cache) + nl_cache_put(link_cache); + #if 0 if (addr->ce_mask & ADDR_ATTR_CACHEINFO) { struct rtnl_addr_cacheinfo *ci = &addr->a_cacheinfo; From 4d94ed5f6bd3492965882f080120fed9de7131a5 Mon Sep 17 00:00:00 2001 From: roopa Date: Sun, 18 Nov 2012 22:14:23 -0800 Subject: [PATCH 339/432] Bug Fix: Add new fill socket to cache manager This patch adds a new socket to cache manager to request fill's on. cache manager today uses cm_sock to request dump from the kernel. It also listens to netlink async events on the same sock. The problem with this is that when libnl is waiting to process the response to get dump request sent to the kernel during fill, it may receive an async event, resulting in libnl complaining about unexpected msg This is usually reproducible when there is heavy netlink async event traffic during nl_cache_mngr_add. This patch adds a new cm_sync_sock to use for fill during cache manager add cache. The other option is to provide an api to set the cm_sync_sock. But since this is a bug fix its probably better to fix the cache manager add api like this patch does. Please suggest otherwise. Signed-off-by: Roopa Prabhu Reviewed-by: Nolan Leake Reviewed-by: Shrijeet Mukherjee Signed-off-by: Thomas Graf --- include/netlink-types.h | 1 + lib/cache_mngr.c | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/include/netlink-types.h b/include/netlink-types.h index 2bb4f0a..057ea2b 100644 --- a/include/netlink-types.h +++ b/include/netlink-types.h @@ -98,6 +98,7 @@ struct nl_cache_mngr int cm_flags; int cm_nassocs; struct nl_sock * cm_sock; + struct nl_sock * cm_sync_sock; struct nl_cache_assoc * cm_assocs; }; diff --git a/lib/cache_mngr.c b/lib/cache_mngr.c index bf92d11..d5dc1f3 100644 --- a/lib/cache_mngr.c +++ b/lib/cache_mngr.c @@ -171,12 +171,21 @@ int nl_cache_mngr_alloc(struct nl_sock *sk, int protocol, int flags, if ((err = nl_socket_set_nonblocking(mngr->cm_sock) < 0)) goto errout; + /* Create and allocate socket for sync cache fills */ + mngr->cm_sync_sock = nl_socket_alloc(); + if (!mngr->cm_sync_sock) + goto errout; + if ((err = nl_connect(mngr->cm_sync_sock, protocol)) < 0) + goto errout_free_sync_sock; + NL_DBG(1, "Allocated cache manager %p, protocol %d, %d caches\n", mngr, protocol, mngr->cm_nassocs); *result = mngr; return 0; +errout_free_sync_sock: + nl_socket_free(mngr->cm_sync_sock); errout: nl_cache_mngr_free(mngr); return err; @@ -256,7 +265,7 @@ retry: return err; } - err = nl_cache_refill(mngr->cm_sock, cache); + err = nl_cache_refill(mngr->cm_sync_sock, cache); if (err < 0) goto errout_drop_membership; @@ -490,6 +499,11 @@ void nl_cache_mngr_free(struct nl_cache_mngr *mngr) if (mngr->cm_sock) nl_close(mngr->cm_sock); + if (mngr->cm_sync_sock) { + nl_close(mngr->cm_sync_sock); + nl_socket_free(mngr->cm_sync_sock); + } + if (mngr->cm_flags & NL_ALLOCATED_SOCK) nl_socket_free(mngr->cm_sock); From a2c4bd8f094a7247903578860a9c42049991860b Mon Sep 17 00:00:00 2001 From: Richard Marshall Date: Mon, 19 Nov 2012 20:20:22 -0800 Subject: [PATCH 340/432] Updated configure.in to make sure bison and lex are installed. Fixes issue #7 --- configure.in | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 9a190c2..a06bee1 100644 --- a/configure.in +++ b/configure.in @@ -68,7 +68,7 @@ AM_PROG_CC_C_O AC_PROG_INSTALL AM_PROG_LIBTOOL AM_PROG_LEX -AC_PROG_YACC +AC_CHECK_PROGS(YACC, 'bison -y') AC_C_CONST AC_C_INLINE @@ -118,6 +118,19 @@ python/netlink/route/Makefile include/netlink/version.h ]) +ac_errcount=0 +if test -z "$YACC"; then + AC_MSG_WARN(bison not found. Please install before continuing.) + ac_errcount=$((ac_errcount + 1)) +fi +if test -z "$LEXLIB"; then + AC_MSG_WARN(flex or lex not found. Please install before continuing.) + ac_errcount=$((ac_errcount + 1)) +fi +if test $ac_errcount -gt 0; then + AC_MSG_ERROR(Required packages are missing. Please install them and rerun ./configure) +fi + AC_OUTPUT echo "-------------------------------------------------------------------------------" From 0a9d5fcfa4c3fe8c930103f7639723dfd1ae4889 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 23 Nov 2012 16:40:14 +0100 Subject: [PATCH 341/432] configure: Replace broken AM_PROG_LEX with AC_CHECK_PROGS Signed-off-by: Thomas Graf --- configure.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.in b/configure.in index a06bee1..7ccc131 100644 --- a/configure.in +++ b/configure.in @@ -67,7 +67,7 @@ AC_PROG_CC AM_PROG_CC_C_O AC_PROG_INSTALL AM_PROG_LIBTOOL -AM_PROG_LEX +AC_CHECK_PROGS(FLEX, 'flex') AC_CHECK_PROGS(YACC, 'bison -y') AC_C_CONST @@ -123,8 +123,8 @@ if test -z "$YACC"; then AC_MSG_WARN(bison not found. Please install before continuing.) ac_errcount=$((ac_errcount + 1)) fi -if test -z "$LEXLIB"; then - AC_MSG_WARN(flex or lex not found. Please install before continuing.) +if test -z "$FLEX"; then + AC_MSG_WARN(flex not found. Please install before continuing.) ac_errcount=$((ac_errcount + 1)) fi if test $ac_errcount -gt 0; then From 3163fa707b198ee6db5aa2bb03d569812bacdaa4 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 23 Nov 2012 16:50:06 +0100 Subject: [PATCH 342/432] cache: reserve room in cache_ops to avoid breaking module ABI too frequently Signed-off-by: Thomas Graf --- include/netlink/cache-api.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/netlink/cache-api.h b/include/netlink/cache-api.h index f2111b9..b332415 100644 --- a/include/netlink/cache-api.h +++ b/include/netlink/cache-api.h @@ -252,6 +252,15 @@ struct nl_cache_ops int (*co_include_event)(struct nl_cache *cache, struct nl_object *obj, change_func_t change_cb, void *data); + void (*reserved_1)(void); + void (*reserved_2)(void); + void (*reserved_3)(void); + void (*reserved_4)(void); + void (*reserved_5)(void); + void (*reserved_6)(void); + void (*reserved_7)(void); + void (*reserved_8)(void); + /** Object operations */ struct nl_object_ops * co_obj_ops; From ed3d7066f7fbe26f41a3e0f4321be0eeb35332be Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 23 Nov 2012 17:05:05 +0100 Subject: [PATCH 343/432] Include the newly added header files in next release Signed-off-by: Thomas Graf --- include/Makefile.am | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/Makefile.am b/include/Makefile.am index 80c615c..54fd71f 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -24,6 +24,8 @@ nobase_libnlinclude_HEADERS = \ netlink/data.h \ netlink/errno.h \ netlink/handlers.h \ + netlink/hash.h \ + netlink/hashtable.h \ netlink/list.h \ netlink/msg.h \ netlink/netlink-compat.h \ @@ -81,6 +83,7 @@ nobase_libnlinclude_HEADERS += \ netlink/cli/class.h \ netlink/cli/cls.h \ netlink/cli/ct.h \ + netlink/cli/exp.h \ netlink/cli/link.h \ netlink/cli/neigh.h \ netlink/cli/qdisc.h \ From 05a6723eb5d63d9d1a3eb025b8f20dd6af2bde35 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 23 Nov 2012 17:05:52 +0100 Subject: [PATCH 344/432] 3.2.15 release Signed-off-by: Thomas Graf --- configure.in | 6 +++--- doc/configure.in | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.in b/configure.in index 7ccc131..d120db4 100644 --- a/configure.in +++ b/configure.in @@ -13,7 +13,7 @@ # copied from glib m4_define([libnl_major_version], [3]) m4_define([libnl_minor_version], [2]) -m4_define([libnl_micro_version], [14]) +m4_define([libnl_micro_version], [15]) # If either revision or age are omitted, they default to 0. Also note that age @@ -34,9 +34,9 @@ m4_define([libnl_micro_version], [14]) # 6. If any interfaces have been removed since the last public release, then # set age to 0. -m4_define([libnl_lt_current], [211]) +m4_define([libnl_lt_current], [212]) m4_define([libnl_lt_revision], [0]) -m4_define([libnl_lt_age], [11]) +m4_define([libnl_lt_age], [12]) m4_define([libnl_version], [libnl_major_version.libnl_minor_version.libnl_micro_version]) diff --git a/doc/configure.in b/doc/configure.in index 1d0d65b..8e93968 100644 --- a/doc/configure.in +++ b/doc/configure.in @@ -9,7 +9,7 @@ # Copyright (c) 2003-2012 Thomas Graf # -AC_INIT(libnl-doc, [3.2.14], [http://www.infradead.org/~tgr/libnl/]) +AC_INIT(libnl-doc, [3.2.15], [http://www.infradead.org/~tgr/libnl/]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES(yes)], []) From 4149154c226a47f67f5ad32b5532831534a755e9 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Mon, 26 Nov 2012 11:50:56 +0100 Subject: [PATCH 345/432] cache: only continue iterating over co_groups if it is available A co_groups == NULL must enter the loop to trigger the initial fill of the cache but may never bump the grp pointer as doing so prevents the loop from being escaped correctly. Signed-off-by: Thomas Graf --- lib/cache.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/cache.c b/lib/cache.c index 415e471..8ba3d5b 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -829,7 +829,9 @@ restart: goto restart; else if (err < 0) goto errout; - grp++; + + if (grp) + grp++; } while (grp && grp->ag_group && (cache->c_flags & NL_CACHE_AF_ITER)); @@ -935,7 +937,8 @@ restart: } else if (err < 0) break; - grp++; + if (grp) + grp++; } while (grp && grp->ag_group && (cache->c_flags & NL_CACHE_AF_ITER)); From f535de36afe72550334065ec09d5a5afb18db681 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Mon, 26 Nov 2012 17:43:12 +0100 Subject: [PATCH 346/432] 3.2.16 release --- configure.in | 4 ++-- doc/configure.in | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.in b/configure.in index d120db4..d12b195 100644 --- a/configure.in +++ b/configure.in @@ -13,7 +13,7 @@ # copied from glib m4_define([libnl_major_version], [3]) m4_define([libnl_minor_version], [2]) -m4_define([libnl_micro_version], [15]) +m4_define([libnl_micro_version], [16]) # If either revision or age are omitted, they default to 0. Also note that age @@ -35,7 +35,7 @@ m4_define([libnl_micro_version], [15]) # set age to 0. m4_define([libnl_lt_current], [212]) -m4_define([libnl_lt_revision], [0]) +m4_define([libnl_lt_revision], [1]) m4_define([libnl_lt_age], [12]) m4_define([libnl_version], diff --git a/doc/configure.in b/doc/configure.in index 8e93968..aaf51af 100644 --- a/doc/configure.in +++ b/doc/configure.in @@ -9,7 +9,7 @@ # Copyright (c) 2003-2012 Thomas Graf # -AC_INIT(libnl-doc, [3.2.15], [http://www.infradead.org/~tgr/libnl/]) +AC_INIT(libnl-doc, [3.2.16], [http://www.infradead.org/~tgr/libnl/]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES(yes)], []) From a96a3b6828ef4793a7187ceee85201a40c17bb91 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 26 Nov 2012 20:48:13 +0100 Subject: [PATCH 347/432] build: rename configure.in -> .ac "configure.in" is a very, very old, obsolete name. Newer automake will reject it, so rename it now. Signed-off-by: Jan Engelhardt --- configure.in => configure.ac | 0 doc/{configure.in => configure.ac} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename configure.in => configure.ac (100%) rename doc/{configure.in => configure.ac} (100%) diff --git a/configure.in b/configure.ac similarity index 100% rename from configure.in rename to configure.ac diff --git a/doc/configure.in b/doc/configure.ac similarity index 100% rename from doc/configure.in rename to doc/configure.ac From 9d92564566255c157fd6c2c0ac92c1b640af25fa Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 26 Nov 2012 20:49:02 +0100 Subject: [PATCH 348/432] build: resolve automake-1.12 warnings /usr/share/automake-1.12/am/ltlibrary.am: warning: 'libnl-cli-3.la': linking libtool libraries using a non-POSIX archiver requires 'AM_PROG_AR' in 'configure.ac' (one for each .la file) Signed-off-by: Jan Engelhardt --- .gitignore | 1 + configure.ac | 1 + 2 files changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index ec94f8d..12c9b94 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ defs.h.in~ cscope.* /aclocal.m4 +/ar-lib /autom4te.cache /compile /config.* diff --git a/configure.ac b/configure.ac index d120db4..56966a1 100644 --- a/configure.ac +++ b/configure.ac @@ -46,6 +46,7 @@ AC_CONFIG_HEADERS([lib/defs.h]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([-Wall foreign subdir-objects]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES(yes)], []) +m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) MAJ_VERSION=libnl_major_version AC_SUBST(MAJ_VERSION) From f3cd3fe95069ddab55263c6226d1176169fa28d8 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 26 Nov 2012 20:51:51 +0100 Subject: [PATCH 349/432] build: use AC_CONFIG_AUX_DIR Stash all those scripts into a separate directory and ignore that. Signed-off-by: Jan Engelhardt --- .gitignore | 7 +------ configure.ac | 1 + doc/.gitignore | 11 +++++------ doc/configure.ac | 1 + 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 12c9b94..f9fe4bd 100644 --- a/.gitignore +++ b/.gitignore @@ -16,15 +16,10 @@ defs.h.in~ cscope.* /aclocal.m4 -/ar-lib /autom4te.cache -/compile +/build-aux/ /config.* /configure -/depcomp /libtool -/ltmain.sh -/install-sh -/missing /*.pc diff --git a/configure.ac b/configure.ac index 56966a1..e449117 100644 --- a/configure.ac +++ b/configure.ac @@ -43,6 +43,7 @@ m4_define([libnl_version], AC_INIT(libnl, [libnl_version], [], [], [http://www.infradead.org/~tgr/libnl/]) AC_CONFIG_HEADERS([lib/defs.h]) +AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([-Wall foreign subdir-objects]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES(yes)], []) diff --git a/doc/.gitignore b/doc/.gitignore index e7209f6..f7cb70d 100644 --- a/doc/.gitignore +++ b/doc/.gitignore @@ -1,9 +1,8 @@ *.html libnl.dict Doxyfile -aclocal.m4 -autom4te.cache -config.log -config.status -configure -missing +/aclocal.m4 +/autom4te.cache/ +/build-aux/ +/config.* +/configure diff --git a/doc/configure.ac b/doc/configure.ac index 8e93968..c245baa 100644 --- a/doc/configure.ac +++ b/doc/configure.ac @@ -11,6 +11,7 @@ AC_INIT(libnl-doc, [3.2.15], [http://www.infradead.org/~tgr/libnl/]) AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_AUX_DIR([build-aux]) AM_INIT_AUTOMAKE m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES(yes)], []) From 0ba9e99381b5dffbdd22fc63c7b1f0fe288211d2 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 26 Nov 2012 20:54:04 +0100 Subject: [PATCH 350/432] build: use foreign mode This is the magic trick to get rid of files like NEWS, INSTALL, etc. that are unused in some projects, like libnl. Signed-off-by: Jan Engelhardt --- doc/ChangeLog | 0 doc/INSTALL | 370 ----------------------------------------------- doc/NEWS | 0 doc/configure.ac | 2 +- 4 files changed, 1 insertion(+), 371 deletions(-) delete mode 100644 doc/ChangeLog delete mode 100644 doc/INSTALL delete mode 100644 doc/NEWS diff --git a/doc/ChangeLog b/doc/ChangeLog deleted file mode 100644 index e69de29..0000000 diff --git a/doc/INSTALL b/doc/INSTALL deleted file mode 100644 index a1e89e1..0000000 --- a/doc/INSTALL +++ /dev/null @@ -1,370 +0,0 @@ -Installation Instructions -************************* - -Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation, -Inc. - - Copying and distribution of this file, with or without modification, -are permitted in any medium without royalty provided the copyright -notice and this notice are preserved. This file is offered as-is, -without warranty of any kind. - -Basic Installation -================== - - Briefly, the shell commands `./configure; make; make install' should -configure, build, and install this package. The following -more-detailed instructions are generic; see the `README' file for -instructions specific to this package. Some packages provide this -`INSTALL' file but do not implement all of the features documented -below. The lack of an optional feature in a given package is not -necessarily a bug. More recommendations for GNU packages can be found -in *note Makefile Conventions: (standards)Makefile Conventions. - - The `configure' shell script attempts to guess correct values for -various system-dependent variables used during compilation. It uses -those values to create a `Makefile' in each directory of the package. -It may also create one or more `.h' files containing system-dependent -definitions. Finally, it creates a shell script `config.status' that -you can run in the future to recreate the current configuration, and a -file `config.log' containing compiler output (useful mainly for -debugging `configure'). - - It can also use an optional file (typically called `config.cache' -and enabled with `--cache-file=config.cache' or simply `-C') that saves -the results of its tests to speed up reconfiguring. Caching is -disabled by default to prevent problems with accidental use of stale -cache files. - - If you need to do unusual things to compile the package, please try -to figure out how `configure' could check whether to do them, and mail -diffs or instructions to the address given in the `README' so they can -be considered for the next release. If you are using the cache, and at -some point `config.cache' contains results you don't want to keep, you -may remove or edit it. - - The file `configure.ac' (or `configure.in') is used to create -`configure' by a program called `autoconf'. You need `configure.ac' if -you want to change it or regenerate `configure' using a newer version -of `autoconf'. - - The simplest way to compile this package is: - - 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. - - Running `configure' might take a while. While running, it prints - some messages telling which features it is checking for. - - 2. Type `make' to compile the package. - - 3. Optionally, type `make check' to run any self-tests that come with - the package, generally using the just-built uninstalled binaries. - - 4. Type `make install' to install the programs and any data files and - documentation. When installing into a prefix owned by root, it is - recommended that the package be configured and built as a regular - user, and only the `make install' phase executed with root - privileges. - - 5. Optionally, type `make installcheck' to repeat any self-tests, but - this time using the binaries in their final installed location. - This target does not install anything. Running this target as a - regular user, particularly if the prior `make install' required - root privileges, verifies that the installation completed - correctly. - - 6. You can remove the program binaries and object files from the - source code directory by typing `make clean'. To also remove the - files that `configure' created (so you can compile the package for - a different kind of computer), type `make distclean'. There is - also a `make maintainer-clean' target, but that is intended mainly - for the package's developers. If you use it, you may have to get - all sorts of other programs in order to regenerate files that came - with the distribution. - - 7. Often, you can also type `make uninstall' to remove the installed - files again. In practice, not all packages have tested that - uninstallation works correctly, even though it is required by the - GNU Coding Standards. - - 8. Some packages, particularly those that use Automake, provide `make - distcheck', which can by used by developers to test that all other - targets like `make install' and `make uninstall' work correctly. - This target is generally not run by end users. - -Compilers and Options -===================== - - Some systems require unusual options for compilation or linking that -the `configure' script does not know about. Run `./configure --help' -for details on some of the pertinent environment variables. - - You can give `configure' initial values for configuration parameters -by setting variables in the command line or in the environment. Here -is an example: - - ./configure CC=c99 CFLAGS=-g LIBS=-lposix - - *Note Defining Variables::, for more details. - -Compiling For Multiple Architectures -==================================== - - You can compile the package for more than one kind of computer at the -same time, by placing the object files for each architecture in their -own directory. To do this, you can use GNU `make'. `cd' to the -directory where you want the object files and executables to go and run -the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. This -is known as a "VPATH" build. - - With a non-GNU `make', it is safer to compile the package for one -architecture at a time in the source code directory. After you have -installed the package for one architecture, use `make distclean' before -reconfiguring for another architecture. - - On MacOS X 10.5 and later systems, you can create libraries and -executables that work on multiple system types--known as "fat" or -"universal" binaries--by specifying multiple `-arch' options to the -compiler but only a single `-arch' option to the preprocessor. Like -this: - - ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ - CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ - CPP="gcc -E" CXXCPP="g++ -E" - - This is not guaranteed to produce working output in all cases, you -may have to build one architecture at a time and combine the results -using the `lipo' tool if you have problems. - -Installation Names -================== - - By default, `make install' installs the package's commands under -`/usr/local/bin', include files under `/usr/local/include', etc. You -can specify an installation prefix other than `/usr/local' by giving -`configure' the option `--prefix=PREFIX', where PREFIX must be an -absolute file name. - - You can specify separate installation prefixes for -architecture-specific files and architecture-independent files. If you -pass the option `--exec-prefix=PREFIX' to `configure', the package uses -PREFIX as the prefix for installing programs and libraries. -Documentation and other data files still use the regular prefix. - - In addition, if you use an unusual directory layout you can give -options like `--bindir=DIR' to specify different values for particular -kinds of files. Run `configure --help' for a list of the directories -you can set and what kinds of files go in them. In general, the -default for these options is expressed in terms of `${prefix}', so that -specifying just `--prefix' will affect all of the other directory -specifications that were not explicitly provided. - - The most portable way to affect installation locations is to pass the -correct locations to `configure'; however, many packages provide one or -both of the following shortcuts of passing variable assignments to the -`make install' command line to change installation locations without -having to reconfigure or recompile. - - The first method involves providing an override variable for each -affected directory. For example, `make install -prefix=/alternate/directory' will choose an alternate location for all -directory configuration variables that were expressed in terms of -`${prefix}'. Any directories that were specified during `configure', -but not in terms of `${prefix}', must each be overridden at install -time for the entire installation to be relocated. The approach of -makefile variable overrides for each directory variable is required by -the GNU Coding Standards, and ideally causes no recompilation. -However, some platforms have known limitations with the semantics of -shared libraries that end up requiring recompilation when using this -method, particularly noticeable in packages that use GNU Libtool. - - The second method involves providing the `DESTDIR' variable. For -example, `make install DESTDIR=/alternate/directory' will prepend -`/alternate/directory' before all installation names. The approach of -`DESTDIR' overrides is not required by the GNU Coding Standards, and -does not work on platforms that have drive letters. On the other hand, -it does better at avoiding recompilation issues, and works well even -when some directory options were not specified in terms of `${prefix}' -at `configure' time. - -Optional Features -================= - - If the package supports it, you can cause programs to be installed -with an extra prefix or suffix on their names by giving `configure' the -option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. - - Some packages pay attention to `--enable-FEATURE' options to -`configure', where FEATURE indicates an optional part of the package. -They may also pay attention to `--with-PACKAGE' options, where PACKAGE -is something like `gnu-as' or `x' (for the X Window System). The -`README' should mention any `--enable-' and `--with-' options that the -package recognizes. - - For packages that use the X Window System, `configure' can usually -find the X include and library files automatically, but if it doesn't, -you can use the `configure' options `--x-includes=DIR' and -`--x-libraries=DIR' to specify their locations. - - Some packages offer the ability to configure how verbose the -execution of `make' will be. For these packages, running `./configure ---enable-silent-rules' sets the default to minimal output, which can be -overridden with `make V=1'; while running `./configure ---disable-silent-rules' sets the default to verbose, which can be -overridden with `make V=0'. - -Particular systems -================== - - On HP-UX, the default C compiler is not ANSI C compatible. If GNU -CC is not installed, it is recommended to use the following options in -order to use an ANSI C compiler: - - ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" - -and if that doesn't work, install pre-built binaries of GCC for HP-UX. - - HP-UX `make' updates targets which have the same time stamps as -their prerequisites, which makes it generally unusable when shipped -generated files such as `configure' are involved. Use GNU `make' -instead. - - On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot -parse its `' header file. The option `-nodtk' can be used as -a workaround. If GNU CC is not installed, it is therefore recommended -to try - - ./configure CC="cc" - -and if that doesn't work, try - - ./configure CC="cc -nodtk" - - On Solaris, don't put `/usr/ucb' early in your `PATH'. This -directory contains several dysfunctional programs; working variants of -these programs are available in `/usr/bin'. So, if you need `/usr/ucb' -in your `PATH', put it _after_ `/usr/bin'. - - On Haiku, software installed for all users goes in `/boot/common', -not `/usr/local'. It is recommended to use the following options: - - ./configure --prefix=/boot/common - -Specifying the System Type -========================== - - There may be some features `configure' cannot figure out -automatically, but needs to determine by the type of machine the package -will run on. Usually, assuming the package is built to be run on the -_same_ architectures, `configure' can figure that out, but if it prints -a message saying it cannot guess the machine type, give it the -`--build=TYPE' option. TYPE can either be a short name for the system -type, such as `sun4', or a canonical name which has the form: - - CPU-COMPANY-SYSTEM - -where SYSTEM can have one of these forms: - - OS - KERNEL-OS - - See the file `config.sub' for the possible values of each field. If -`config.sub' isn't included in this package, then this package doesn't -need to know the machine type. - - If you are _building_ compiler tools for cross-compiling, you should -use the option `--target=TYPE' to select the type of system they will -produce code for. - - If you want to _use_ a cross compiler, that generates code for a -platform different from the build platform, you should specify the -"host" platform (i.e., that on which the generated programs will -eventually be run) with `--host=TYPE'. - -Sharing Defaults -================ - - If you want to set default values for `configure' scripts to share, -you can create a site shell script called `config.site' that gives -default values for variables like `CC', `cache_file', and `prefix'. -`configure' looks for `PREFIX/share/config.site' if it exists, then -`PREFIX/etc/config.site' if it exists. Or, you can set the -`CONFIG_SITE' environment variable to the location of the site script. -A warning: not all `configure' scripts look for a site script. - -Defining Variables -================== - - Variables not defined in a site shell script can be set in the -environment passed to `configure'. However, some packages may run -configure again during the build, and the customized values of these -variables may be lost. In order to avoid this problem, you should set -them in the `configure' command line, using `VAR=value'. For example: - - ./configure CC=/usr/local2/bin/gcc - -causes the specified `gcc' to be used as the C compiler (unless it is -overridden in the site shell script). - -Unfortunately, this technique does not work for `CONFIG_SHELL' due to -an Autoconf bug. Until the bug is fixed you can use this workaround: - - CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash - -`configure' Invocation -====================== - - `configure' recognizes the following options to control how it -operates. - -`--help' -`-h' - Print a summary of all of the options to `configure', and exit. - -`--help=short' -`--help=recursive' - Print a summary of the options unique to this package's - `configure', and exit. The `short' variant lists options used - only in the top level, while the `recursive' variant lists options - also present in any nested packages. - -`--version' -`-V' - Print the version of Autoconf used to generate the `configure' - script, and exit. - -`--cache-file=FILE' - Enable the cache: use and save the results of the tests in FILE, - traditionally `config.cache'. FILE defaults to `/dev/null' to - disable caching. - -`--config-cache' -`-C' - Alias for `--cache-file=config.cache'. - -`--quiet' -`--silent' -`-q' - Do not print messages saying which checks are being made. To - suppress all normal output, redirect it to `/dev/null' (any error - messages will still be shown). - -`--srcdir=DIR' - Look for the package's source code in directory DIR. Usually - `configure' can determine that directory automatically. - -`--prefix=DIR' - Use DIR as the installation prefix. *note Installation Names:: - for more details, including other options available for fine-tuning - the installation locations. - -`--no-create' -`-n' - Run the configure checks, but stop before creating any output - files. - -`configure' also accepts some other, not widely useful, options. Run -`configure --help' for more details. - diff --git a/doc/NEWS b/doc/NEWS deleted file mode 100644 index e69de29..0000000 diff --git a/doc/configure.ac b/doc/configure.ac index c245baa..4533a70 100644 --- a/doc/configure.ac +++ b/doc/configure.ac @@ -12,7 +12,7 @@ AC_INIT(libnl-doc, [3.2.15], [http://www.infradead.org/~tgr/libnl/]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_AUX_DIR([build-aux]) -AM_INIT_AUTOMAKE +AM_INIT_AUTOMAKE([foreign]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES(yes)], []) m4_include([m4/ax_python.m4]) From ab7f42e0bc97f4e04bcbc9f09b0ac41a06f90cf3 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Tue, 27 Nov 2012 00:01:53 +0100 Subject: [PATCH 351/432] build: resolve lex failure This is an addendum to 0a9d5fcfa4c3fe8c930103f7639723dfd1ae4889, which forgot to change ${LEX} to ${FLEX} in lib/Makefile.am. On openSUSE, /usr/bin/lex is a wrapper that calls `flex -l ...`. libnl however requires flex, not lex or a compat mode thereof, so using ${FLEX} is the proper thing to do. Signed-off-by: Jan Engelhardt --- lib/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Makefile.am b/lib/Makefile.am index 7481941..5adaffb 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -41,13 +41,13 @@ CLEANFILES = \ # Hack to avoid using ylwrap. It does not function correctly in combination # with --header-file= route/pktloc_grammar.c: route/pktloc_grammar.l - $(AM_V_GEN) $(LEX) --header-file=route/pktloc_grammar.h $(LFLAGS) -o $@ $^ + $(AM_V_GEN) $(FLEX) --header-file=route/pktloc_grammar.h $(LFLAGS) -o $@ $^ route/pktloc_syntax.c: route/pktloc_syntax.y $(AM_V_GEN) $(YACC) -d $(YFLAGS) -o $@ $^ route/cls/ematch_grammar.c: route/cls/ematch_grammar.l - $(AM_V_GEN) $(LEX) --header-file=route/cls/ematch_grammar.h $(LFLAGS) -o $@ $^ + $(AM_V_GEN) $(FLEX) --header-file=route/cls/ematch_grammar.h $(LFLAGS) -o $@ $^ route/cls/ematch_syntax.c: route/cls/ematch_syntax.y $(AM_V_GEN) $(YACC) -d $(YFLAGS) -o $@ $^ From 5251188673e425bfddcbbe7fad19f7e0e945bf62 Mon Sep 17 00:00:00 2001 From: Benedikt Spranger Date: Thu, 29 Nov 2012 19:48:45 +0100 Subject: [PATCH 352/432] link: basic socket-CAN support Controller Area Network (CAN) is a networking technology which has widespread use in automation, embedded devices and automotive fields. The socket-CAN package is an implementation of CAN protocols for Linux. All socket-CAN related configurations are carried out through Netlink. Add basic socket-CAN support to libnl to be able to configure CAN devices with libnl. Signed-off-by: Benedikt Spranger Signed-off-by: Thomas Graf --- include/netlink/route/link/can.h | 32 +++ lib/Makefile.am | 2 +- lib/route/link/can.c | 404 +++++++++++++++++++++++++++++++ 3 files changed, 437 insertions(+), 1 deletion(-) create mode 100644 include/netlink/route/link/can.h create mode 100644 lib/route/link/can.c diff --git a/include/netlink/route/link/can.h b/include/netlink/route/link/can.h new file mode 100644 index 0000000..0a99dfd --- /dev/null +++ b/include/netlink/route/link/can.h @@ -0,0 +1,32 @@ +/* + * netlink/route/link/can.h CAN interface + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2012 Benedikt Spranger + */ + +#ifndef NETLINK_LINK_CAN_H_ +#define NETLINK_LINK_CAN_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int rtnl_link_is_can(struct rtnl_link *link); + +extern char *rtnl_link_can_ctrlmode2str(int, char *, size_t); +extern int rtnl_link_can_str2ctrlmode(const char *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/Makefile.am b/lib/Makefile.am index 5adaffb..677a89c 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -69,7 +69,7 @@ libnl_route_3_la_SOURCES = \ \ route/link/api.c route/link/vlan.c route/link/dummy.c \ route/link/bridge.c route/link/inet6.c route/link/inet.c \ - route/link/bonding.c \ + route/link/bonding.c route/link/can.c \ \ route/qdisc/blackhole.c route/qdisc/cbq.c route/qdisc/dsmark.c \ route/qdisc/fifo.c route/qdisc/htb.c route/qdisc/netem.c \ diff --git a/lib/route/link/can.c b/lib/route/link/can.c new file mode 100644 index 0000000..a987ca3 --- /dev/null +++ b/lib/route/link/can.c @@ -0,0 +1,404 @@ +/* + * lib/route/link/can.c CAN Link Info + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2012 Benedikt Spranger + */ + +/** + * @ingroup link + * @defgroup can CAN + * Controller Area Network link module + * + * @details + * \b Link Type Name: "can" + * + * @route_doc{link_can, CAN Documentation} + * + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/** @cond SKIP */ +#define CAN_HAS_BITTIMING (1<<0) +#define CAN_HAS_BITTIMING_CONST (1<<1) +#define CAN_HAS_CLOCK (1<<2) +#define CAN_HAS_STATE (1<<3) +#define CAN_HAS_CTRLMODE (1<<4) +#define CAN_HAS_RESTART_MS (1<<5) +#define CAN_HAS_RESTART (1<<6) +#define CAN_HAS_BERR_COUNTER (1<<7) + +struct can_info { + uint32_t ci_state; + uint32_t ci_restart; + uint32_t ci_restart_ms; + struct can_ctrlmode ci_ctrlmode; + struct can_bittiming ci_bittiming; + struct can_bittiming_const ci_bittiming_const; + struct can_clock ci_clock; + struct can_berr_counter ci_berr_counter; + uint32_t ci_mask; +}; + +/** @endcond */ + +static struct nla_policy can_policy[IFLA_CAN_MAX + 1] = { + [IFLA_CAN_STATE] = { .type = NLA_U32 }, + [IFLA_CAN_CTRLMODE] = { .minlen = sizeof(struct can_ctrlmode) }, + [IFLA_CAN_RESTART_MS] = { .type = NLA_U32 }, + [IFLA_CAN_RESTART] = { .type = NLA_U32 }, + [IFLA_CAN_BITTIMING] = { .minlen = sizeof(struct can_bittiming) }, + [IFLA_CAN_BITTIMING_CONST] + = { .minlen = sizeof(struct can_bittiming_const) }, + [IFLA_CAN_CLOCK] = { .minlen = sizeof(struct can_clock) }, + [IFLA_CAN_BERR_COUNTER] = { .minlen = sizeof(struct can_berr_counter) }, +}; + +static int can_alloc(struct rtnl_link *link) +{ + struct can_info *ci; + + ci = calloc(1, sizeof(*ci)); + if (!ci) + return -NLE_NOMEM; + + link->l_info = ci; + + return 0; +} + +static int can_parse(struct rtnl_link *link, struct nlattr *data, + struct nlattr *xstats) +{ + struct nlattr *tb[IFLA_CAN_MAX+1]; + struct can_info *ci; + int err; + + NL_DBG(3, "Parsing CAN link info"); + + if ((err = nla_parse_nested(tb, IFLA_CAN_MAX, data, can_policy)) < 0) + goto errout; + + if ((err = can_alloc(link)) < 0) + goto errout; + + ci = link->l_info; + + if (tb[IFLA_CAN_STATE]) { + ci->ci_state = nla_get_u32(tb[IFLA_CAN_STATE]); + ci->ci_mask |= CAN_HAS_STATE; + } + + if (tb[IFLA_CAN_RESTART]) { + ci->ci_restart = nla_get_u32(tb[IFLA_CAN_RESTART]); + ci->ci_mask |= CAN_HAS_RESTART; + } + + if (tb[IFLA_CAN_RESTART_MS]) { + ci->ci_restart_ms = nla_get_u32(tb[IFLA_CAN_RESTART_MS]); + ci->ci_mask |= CAN_HAS_RESTART_MS; + } + + if (tb[IFLA_CAN_CTRLMODE]) { + nla_memcpy(&ci->ci_ctrlmode, tb[IFLA_CAN_CTRLMODE], + sizeof(ci->ci_ctrlmode)); + ci->ci_mask |= CAN_HAS_CTRLMODE; + } + + if (tb[IFLA_CAN_BITTIMING]) { + nla_memcpy(&ci->ci_bittiming, tb[IFLA_CAN_BITTIMING], + sizeof(ci->ci_bittiming)); + ci->ci_mask |= CAN_HAS_BITTIMING; + } + + if (tb[IFLA_CAN_BITTIMING_CONST]) { + nla_memcpy(&ci->ci_bittiming_const, + tb[IFLA_CAN_BITTIMING_CONST], + sizeof(ci->ci_bittiming_const)); + ci->ci_mask |= CAN_HAS_BITTIMING_CONST; + } + + if (tb[IFLA_CAN_CLOCK]) { + nla_memcpy(&ci->ci_clock, tb[IFLA_CAN_CLOCK], + sizeof(ci->ci_clock)); + ci->ci_mask |= CAN_HAS_CLOCK; + } + + if (tb[IFLA_CAN_BERR_COUNTER]) { + nla_memcpy(&ci->ci_berr_counter, tb[IFLA_CAN_BERR_COUNTER], + sizeof(ci->ci_berr_counter)); + ci->ci_mask |= CAN_HAS_BERR_COUNTER; + } + + err = 0; +errout: + return err; +} + +static void can_free(struct rtnl_link *link) +{ + struct can_info *ci = link->l_info; + + free(ci); + link->l_info = NULL; +} + +static char *print_can_state (uint32_t state) +{ + char *text; + + switch (state) + { + case CAN_STATE_ERROR_ACTIVE: + text = "error active"; + break; + case CAN_STATE_ERROR_WARNING: + text = "error warning"; + break; + case CAN_STATE_ERROR_PASSIVE: + text = "error passive"; + break; + case CAN_STATE_BUS_OFF: + text = "bus off"; + break; + case CAN_STATE_STOPPED: + text = "stopped"; + break; + case CAN_STATE_SLEEPING: + text = "sleeping"; + break; + default: + text = "unknown state"; + } + + return text; +} + +static void can_dump_line(struct rtnl_link *link, struct nl_dump_params *p) +{ + struct can_info *ci = link->l_info; + char buf [64]; + + rtnl_link_can_ctrlmode2str(ci->ci_ctrlmode.flags, buf, sizeof(buf)); + nl_dump(p, "bitrate %d %s <%s>", + ci->ci_bittiming.bitrate, print_can_state(ci->ci_state), buf); +} + +static void can_dump_details(struct rtnl_link *link, struct nl_dump_params *p) +{ + struct can_info *ci = link->l_info; + char buf [64]; + + rtnl_link_can_ctrlmode2str(ci->ci_ctrlmode.flags, buf, sizeof(buf)); + nl_dump(p, " bitrate %d %s <%s>", + ci->ci_bittiming.bitrate, print_can_state(ci->ci_state), buf); + + if (ci->ci_mask & CAN_HAS_RESTART) { + if (ci->ci_restart) + nl_dump_line(p," restarting\n"); + } + + if (ci->ci_mask & CAN_HAS_RESTART_MS) { + nl_dump_line(p," restart interval %d ms\n", + ci->ci_restart_ms); + } + + if (ci->ci_mask & CAN_HAS_BITTIMING) { + nl_dump_line(p," sample point %f %%\n", + ((float) ci->ci_bittiming.sample_point)/10); + nl_dump_line(p," time quanta %d ns\n", + ci->ci_bittiming.tq); + nl_dump_line(p," propagation segment %d tq\n", + ci->ci_bittiming.prop_seg); + nl_dump_line(p," phase buffer segment1 %d tq\n", + ci->ci_bittiming.phase_seg1); + nl_dump_line(p," phase buffer segment2 %d tq\n", + ci->ci_bittiming.phase_seg2); + nl_dump_line(p," synchronisation jump width %d tq\n", + ci->ci_bittiming.sjw); + nl_dump_line(p," bitrate prescaler %d\n", + ci->ci_bittiming.brp); + } + + if (ci->ci_mask & CAN_HAS_BITTIMING_CONST) { + nl_dump_line(p," minimum tsig1 %d tq\n", + ci->ci_bittiming_const.tseg1_min); + nl_dump_line(p," maximum tsig1 %d tq\n", + ci->ci_bittiming_const.tseg1_max); + nl_dump_line(p," minimum tsig2 %d tq\n", + ci->ci_bittiming_const.tseg2_min); + nl_dump_line(p," maximum tsig2 %d tq\n", + ci->ci_bittiming_const.tseg2_max); + nl_dump_line(p," maximum sjw %d tq\n", + ci->ci_bittiming_const.sjw_max); + nl_dump_line(p," minimum brp %d\n", + ci->ci_bittiming_const.brp_min); + nl_dump_line(p," maximum brp %d\n", + ci->ci_bittiming_const.brp_max); + nl_dump_line(p," brp increment %d\n", + ci->ci_bittiming_const.brp_inc); + } + + if (ci->ci_mask & CAN_HAS_CLOCK) { + nl_dump_line(p," base freq %d Hz\n", ci->ci_clock); + + } + + if (ci->ci_mask & CAN_HAS_BERR_COUNTER) { + nl_dump_line(p," bus error RX %d\n", + ci->ci_berr_counter.rxerr); + nl_dump_line(p," bus error TX %d\n", + ci->ci_berr_counter.txerr); + } + + return; +} + +static int can_clone(struct rtnl_link *dst, struct rtnl_link *src) +{ + struct can_info *cdst, *csrc = src->l_info; + int ret; + + dst->l_info = NULL; + ret = rtnl_link_set_type(dst, "can"); + if (ret < 0) + return ret; + + cdst = malloc(sizeof(*cdst)); + if (!cdst) + return -NLE_NOMEM; + + *cdst = *csrc; + dst->l_info = cdst; + + return 0; +} + +static int can_put_attrs(struct nl_msg *msg, struct rtnl_link *link) +{ + struct can_info *ci = link->l_info; + struct nlattr *data; + + data = nla_nest_start(msg, IFLA_INFO_DATA); + if (!data) + return -NLE_MSGSIZE; + + if (ci->ci_mask & CAN_HAS_RESTART) + NLA_PUT_U32(msg, CAN_HAS_RESTART, ci->ci_restart); + + if (ci->ci_mask & CAN_HAS_RESTART_MS) + NLA_PUT_U32(msg, CAN_HAS_RESTART_MS, ci->ci_restart_ms); + + if (ci->ci_mask & CAN_HAS_CTRLMODE) + NLA_PUT(msg, CAN_HAS_CTRLMODE, sizeof(ci->ci_ctrlmode), + &ci->ci_ctrlmode); + + if (ci->ci_mask & CAN_HAS_BITTIMING) + NLA_PUT(msg, CAN_HAS_BITTIMING, sizeof(ci->ci_bittiming), + &ci->ci_bittiming); + + if (ci->ci_mask & CAN_HAS_BITTIMING_CONST) + NLA_PUT(msg, CAN_HAS_BITTIMING_CONST, + sizeof(ci->ci_bittiming_const), + &ci->ci_bittiming_const); + + if (ci->ci_mask & CAN_HAS_CLOCK) + NLA_PUT(msg, CAN_HAS_CLOCK, sizeof(ci->ci_clock), + &ci->ci_clock); + +nla_put_failure: + + return 0; +} + +static struct rtnl_link_info_ops can_info_ops = { + .io_name = "can", + .io_alloc = can_alloc, + .io_parse = can_parse, + .io_dump = { + [NL_DUMP_LINE] = can_dump_line, + [NL_DUMP_DETAILS] = can_dump_details, + }, + .io_clone = can_clone, + .io_put_attrs = can_put_attrs, + .io_free = can_free, +}; + +/** @cond SKIP */ +#define IS_CAN_LINK_ASSERT(link) \ + if ((link)->l_info_ops != &can_info_ops) { \ + APPBUG("Link is not a CAN link. set type \"can\" first."); \ + return -NLE_OPNOTSUPP; \ + } +/** @endcond */ + +/** + * @name CAN Object + * @{ + */ + +/** + * Check if link is a CAN link + * @arg link Link object + * + * @return True if link is a CAN link, otherwise false is returned. + */ +int rtnl_link_is_can(struct rtnl_link *link) +{ + return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "can"); +} + +/** @} */ + +/** + * @name Control Mode Translation + * @{ + */ + +static const struct trans_tbl can_ctrlmode[] = { + __ADD(CAN_CTRLMODE_LOOPBACK, loopback) + __ADD(CAN_CTRLMODE_LISTENONLY, listen-only) + __ADD(CAN_CTRLMODE_3_SAMPLES, triple-sampling) + __ADD(CAN_CTRLMODE_ONE_SHOT, one-shot) + __ADD(CAN_CTRLMODE_BERR_REPORTING, berr-reporting) +}; + +char *rtnl_link_can_ctrlmode2str(int ctrlmode, char *buf, size_t len) +{ + return __flags2str(ctrlmode, buf, len, can_ctrlmode, + ARRAY_SIZE(can_ctrlmode)); +} + +int rtnl_link_can_str2ctrlmode(const char *name) +{ + return __str2flags(name, can_ctrlmode, ARRAY_SIZE(can_ctrlmode)); +} + +/** @} */ + +static void __init can_init(void) +{ + rtnl_link_register_info(&can_info_ops); +} + +static void __exit can_exit(void) +{ + rtnl_link_unregister_info(&can_info_ops); +} + +/** @} */ From c86088ff01b867431d439b4524465709f47dd700 Mon Sep 17 00:00:00 2001 From: Benedikt Spranger Date: Thu, 29 Nov 2012 19:48:46 +0100 Subject: [PATCH 353/432] link: socket-CAN helper functions Add helper functions to make socket-CAN configuration easy. Signed-off-by: Benedikt Spranger Signed-off-by: Thomas Graf --- include/netlink/route/link/can.h | 27 +++ lib/route/link/can.c | 359 +++++++++++++++++++++++++++++++ 2 files changed, 386 insertions(+) diff --git a/include/netlink/route/link/can.h b/include/netlink/route/link/can.h index 0a99dfd..90296f1 100644 --- a/include/netlink/route/link/can.h +++ b/include/netlink/route/link/can.h @@ -25,6 +25,33 @@ extern int rtnl_link_is_can(struct rtnl_link *link); extern char *rtnl_link_can_ctrlmode2str(int, char *, size_t); extern int rtnl_link_can_str2ctrlmode(const char *); +extern int rtnl_link_can_restart(struct rtnl_link *); +extern int rtnl_link_can_freq(struct rtnl_link *, uint32_t *); + +extern int rtnl_link_can_berr_rx(struct rtnl_link *); +extern int rtnl_link_can_berr_tx(struct rtnl_link *); +extern int rtnl_link_can_berr(struct rtnl_link *, struct can_berr_counter *); + +extern int rtnl_link_can_get_bt_const(struct rtnl_link *, + struct can_bittiming_const *); +extern int rtnl_link_can_get_bittiming(struct rtnl_link *, + struct can_bittiming *); +extern int rtnl_link_can_set_bittiming(struct rtnl_link *, + struct can_bittiming *); + +extern int rtnl_link_can_get_bitrate(struct rtnl_link *, uint32_t *); +extern int rtnl_link_can_set_bitrate(struct rtnl_link *, uint32_t); + +extern int rtnl_link_can_get_sample_point(struct rtnl_link *, uint32_t *); +extern int rtnl_link_can_set_sample_point(struct rtnl_link *, uint32_t); + +extern int rtnl_link_can_get_restart_ms(struct rtnl_link *, uint32_t *); +extern int rtnl_link_can_set_restart_ms(struct rtnl_link *, uint32_t); + +extern int rtnl_link_can_get_ctrlmode(struct rtnl_link *, uint32_t *); +extern int rtnl_link_can_set_ctrlmode(struct rtnl_link *, uint32_t); +extern int rtnl_link_can_unset_ctrlmode(struct rtnl_link *, uint32_t); + #ifdef __cplusplus } #endif diff --git a/lib/route/link/can.c b/lib/route/link/can.c index a987ca3..4b80d94 100644 --- a/lib/route/link/can.c +++ b/lib/route/link/can.c @@ -363,6 +363,365 @@ int rtnl_link_is_can(struct rtnl_link *link) return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "can"); } +/** + * Restart CAN device + * @arg link Link object + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_restart(struct rtnl_link *link) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + + ci->ci_restart = 1; + ci->ci_restart |= CAN_HAS_RESTART; + + return 0; +} + +/** + * Get CAN base frequency + * @arg link Link object + * @arg freq frequency in Hz + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_freq(struct rtnl_link *link, uint32_t *freq) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + if (!freq) + return -NLE_INVAL; + + if (ci->ci_mask & CAN_HAS_CLOCK) + *freq = ci->ci_clock.freq; + else + return -NLE_AGAIN; + + return 0; +} + +/** + * Get CAN RX bus error count + * @arg link Link object + * + * @return RX bus error count on success or a negative error code + */ +int rtnl_link_can_berr_rx(struct rtnl_link *link) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + + if (ci->ci_mask & CAN_HAS_BERR_COUNTER) + return ci->ci_berr_counter.rxerr; + else + return -NLE_AGAIN; +} + +/** + * Get CAN TX bus error count + * @arg link Link object + * + * @return TX bus error count on success or a negative error code + */ +int rtnl_link_can_berr_tx(struct rtnl_link *link) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + + if (ci->ci_mask & CAN_HAS_BERR_COUNTER) + return ci->ci_berr_counter.txerr; + else + return -NLE_AGAIN; +} + +/** + * Get CAN bus error count + * @arg link Link object + * @arg berr Bus error count + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_berr(struct rtnl_link *link, struct can_berr_counter *berr) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + if (!berr) + return -NLE_INVAL; + + if (ci->ci_mask & CAN_HAS_BERR_COUNTER) + *berr = ci->ci_berr_counter; + else + return -NLE_AGAIN; + + return 0; +} + +/** + * Get CAN harware-dependent bit-timing constant + * @arg link Link object + * @arg bt_const Bit-timing constant + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_get_bt_const(struct rtnl_link *link, + struct can_bittiming_const *bt_const) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + if (!bt_const) + return -NLE_INVAL; + + if (ci->ci_mask & CAN_HAS_BITTIMING_CONST) + *bt_const = ci->ci_bittiming_const; + else + return -NLE_AGAIN; + + return 0; +} + +/** + * Get CAN device bit-timing + * @arg link Link object + * @arg bit_timing CAN bit-timing + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_get_bittiming(struct rtnl_link *link, + struct can_bittiming *bit_timing) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + if (!bit_timing) + return -NLE_INVAL; + + if (ci->ci_mask & CAN_HAS_BITTIMING) + *bit_timing = ci->ci_bittiming; + else + return -NLE_AGAIN; + + return 0; +} + +/** + * Set CAN device bit-timing + * @arg link Link object + * @arg bit_timing CAN bit-timing + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_set_bittiming(struct rtnl_link *link, + struct can_bittiming *bit_timing) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + if (!bit_timing) + return -NLE_INVAL; + + ci->ci_bittiming = *bit_timing; + ci->ci_mask |= CAN_HAS_BITTIMING; + + return 0; +} + +/** + * Get CAN device bit-timing + * @arg link Link object + * @arg bitrate CAN bitrate + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_get_bitrate(struct rtnl_link *link, uint32_t *bitrate) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + if (!bitrate) + return -NLE_INVAL; + + if (ci->ci_mask & CAN_HAS_BITTIMING) + *bitrate = ci->ci_bittiming.bitrate; + else + return -NLE_AGAIN; + + return 0; +} + +/** + * Set CAN device bit-rate + * @arg link Link object + * @arg bitrate CAN bitrate + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_set_bitrate(struct rtnl_link *link, uint32_t bitrate) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + + ci->ci_bittiming.bitrate = bitrate; + ci->ci_mask |= CAN_HAS_BITTIMING; + + return 0; +} + +/** + * Get CAN device sample point + * @arg link Link object + * @arg sp CAN sample point + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_get_sample_point(struct rtnl_link *link, uint32_t *sp) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + if (!sp) + return -NLE_INVAL; + + if (ci->ci_mask & CAN_HAS_BITTIMING) + *sp = ci->ci_bittiming.sample_point; + else + return -NLE_AGAIN; + + return 0; +} + +/** + * Set CAN device sample point + * @arg link Link object + * @arg sp CAN sample point + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_set_sample_point(struct rtnl_link *link, uint32_t sp) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + + ci->ci_bittiming.sample_point = sp; + ci->ci_mask |= CAN_HAS_BITTIMING; + + return 0; +} + +/** + * Get CAN device restart intervall + * @arg link Link object + * @arg interval Restart intervall in ms + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_get_restart_ms(struct rtnl_link *link, uint32_t *interval) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + if (!interval) + return -NLE_INVAL; + + if (ci->ci_mask & CAN_HAS_RESTART_MS) + *interval = ci->ci_restart_ms; + else + return -NLE_AGAIN; + + return 0; +} + +/** + * Set CAN device restart intervall + * @arg link Link object + * @arg interval Restart intervall in ms + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_set_restart_ms(struct rtnl_link *link, uint32_t interval) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + + ci->ci_restart_ms = interval; + ci->ci_mask |= CAN_HAS_RESTART_MS; + + return 0; +} + +/** + * Get CAN control mode + * @arg link Link object + * @arg ctrlmode CAN control mode + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_get_ctrlmode(struct rtnl_link *link, uint32_t *ctrlmode) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + if (!ctrlmode) + return -NLE_INVAL; + + if (ci->ci_mask & CAN_HAS_CTRLMODE) + *ctrlmode = ci->ci_ctrlmode.flags; + else + return -NLE_AGAIN; + + return 0; +} + +/** + * Set a CAN Control Mode + * @arg link Link object + * @arg ctrlmode CAN control mode + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_set_ctrlmode(struct rtnl_link *link, uint32_t ctrlmode) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + + ci->ci_ctrlmode.flags |= ctrlmode; + ci->ci_ctrlmode.mask |= ctrlmode; + ci->ci_mask |= CAN_HAS_CTRLMODE; + + return 0; +} + +/** + * Unset a CAN Control Mode + * @arg link Link object + * @arg ctrlmode CAN control mode + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_unset_ctrlmode(struct rtnl_link *link, uint32_t ctrlmode) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + + ci->ci_ctrlmode.flags &= ~ctrlmode; + ci->ci_ctrlmode.mask |= ctrlmode; + ci->ci_mask |= CAN_HAS_CTRLMODE; + + return 0; +} + /** @} */ /** From 68967eb10e82a071cd84fcd9e9b954793afda0c8 Mon Sep 17 00:00:00 2001 From: Gilles Espinasse Date: Wed, 5 Dec 2012 00:08:01 +0100 Subject: [PATCH 354/432] Fix python detection code Signed-off-by: Gilles Espinasse Compiling libnl versions that include doc or the git tree produce this checking for python build information... checking for python2.6... python2.6 checking for main in -lpython2.6... yes checking python2.6/Python.h usability... yes checking python2.6/Python.h presence... yes checking for python2.6/Python.h... yes ./configure: line 4272: test: !=: unary operator expected checking for python2.5... (cached) python2.6 checking for main in -lpython2.6... (cached) yes checking for python2.6/Python.h... (cached) yes ./configure: line 4272: test: !=: unary operator expected checking for python2.4... (cached) python2.6 checking for main in -lpython2.6... (cached) yes checking for python2.6/Python.h... (cached) yes ./configure: line 4272: test: !=: unary operator expected checking for python2.3... (cached) python2.6 checking for main in -lpython2.6... (cached) yes checking for python2.6/Python.h... (cached) yes ./configure: line 4272: test: !=: unary operator expected checking for python2.2... (cached) python2.6 checking for main in -lpython2.6... (cached) yes checking for python2.6/Python.h... (cached) yes ./configure: line 4272: test: !=: unary operator expected checking for python2.1... (cached) python2.6 checking for main in -lpython2.6... (cached) yes checking for python2.6/Python.h... (cached) yes ./configure: line 4272: test: !=: unary operator expected checking for python... (cached) python2.6 checking for main in -lpython2.6... (cached) yes checking for python2.6/Python.h... (cached) yes ./configure: line 4272: test: !=: unary operator expected results of the Python check: Binary: python2.6 Library: python2.6 Include Dir: no Fix the unary operator warning allow to break when one python version is found Add the more recent python versions Change send upstream as http://savannah.gnu.org/patch/index.php?7897 Signed-off-by: Thomas Graf --- doc/m4/ax_python.m4 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/m4/ax_python.m4 b/doc/m4/ax_python.m4 index 1bc9d8a..f9a5135 100644 --- a/doc/m4/ax_python.m4 +++ b/doc/m4/ax_python.m4 @@ -56,7 +56,7 @@ AC_DEFUN([AX_PYTHON], [AC_MSG_CHECKING(for python build information) AC_MSG_RESULT([]) -for python in python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python; do +for python in python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python; do AC_CHECK_PROGS(PYTHON_BIN, [$python]) ax_python_bin=$PYTHON_BIN if test x$ax_python_bin != x; then @@ -64,8 +64,8 @@ if test x$ax_python_bin != x; then AC_CHECK_HEADER([$ax_python_bin/Python.h], [[ax_python_header=`locate $ax_python_bin/Python.h | sed -e s,/Python.h,,`]], ax_python_header=no) - if test $ax_python_lib != no; then - if test $ax_python_header != no; then + if test x$ax_python_lib != xno; then + if test x$ax_python_header != xno; then break; fi fi From de141363045e60ebdf9cf17b52e04068d1851fd9 Mon Sep 17 00:00:00 2001 From: Gilles Espinasse Date: Wed, 5 Dec 2012 00:08:00 +0100 Subject: [PATCH 355/432] Fix make check when using --disable-cli Signed-off-by: Gilles Espinasse Signed-off-by: Thomas Graf --- tests/Makefile.am | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index 1272f98..9c0ab8d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -3,22 +3,26 @@ AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -D_GNU_SOURCE -DSYSCONFDIR=\"$(sysconfdir)/libnl\" LDADD = \ - ${top_builddir}/src/lib/libnl-cli-3.la \ ${top_builddir}/lib/libnl-3.la \ ${top_builddir}/lib/libnl-nf-3.la \ ${top_builddir}/lib/libnl-genl-3.la \ ${top_builddir}/lib/libnl-route-3.la check_PROGRAMS = \ - test-cache-mngr \ test-create-bond \ test-create-vlan \ test-delete-link \ - test-genl \ - test-nf-cache-mngr \ test-socket-creation \ test-complex-HTB-with-hash-filters +if ENABLE_CLI +LDADD += ${top_builddir}/src/lib/libnl-cli-3.la +check_PROGRAMS += \ + test-cache-mngr \ + test-genl \ + test-nf-cache-mngr +endif + # Eventually add these to TESTS once converted to be real # test programs # TESTS = $(check_PROGRAMS) From 913a689de34686e5ed2fa3c56e46e81f9f6eb682 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 11 Dec 2012 17:59:30 +0100 Subject: [PATCH 356/432] can: provide local copy of Signed-off-by: Thomas Graf --- include/linux/can/netlink.h | 122 ++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 include/linux/can/netlink.h diff --git a/include/linux/can/netlink.h b/include/linux/can/netlink.h new file mode 100644 index 0000000..14966dd --- /dev/null +++ b/include/linux/can/netlink.h @@ -0,0 +1,122 @@ +/* + * linux/can/netlink.h + * + * Definitions for the CAN netlink interface + * + * Copyright (c) 2009 Wolfgang Grandegger + * + */ + +#ifndef CAN_NETLINK_H +#define CAN_NETLINK_H + +#include + +/* + * CAN bit-timing parameters + * + * For further information, please read chapter "8 BIT TIMING + * REQUIREMENTS" of the "Bosch CAN Specification version 2.0" + * at http://www.semiconductors.bosch.de/pdf/can2spec.pdf. + */ +struct can_bittiming { + __u32 bitrate; /* Bit-rate in bits/second */ + __u32 sample_point; /* Sample point in one-tenth of a percent */ + __u32 tq; /* Time quanta (TQ) in nanoseconds */ + __u32 prop_seg; /* Propagation segment in TQs */ + __u32 phase_seg1; /* Phase buffer segment 1 in TQs */ + __u32 phase_seg2; /* Phase buffer segment 2 in TQs */ + __u32 sjw; /* Synchronisation jump width in TQs */ + __u32 brp; /* Bit-rate prescaler */ +}; + +/* + * CAN harware-dependent bit-timing constant + * + * Used for calculating and checking bit-timing parameters + */ +struct can_bittiming_const { + char name[16]; /* Name of the CAN controller hardware */ + __u32 tseg1_min; /* Time segement 1 = prop_seg + phase_seg1 */ + __u32 tseg1_max; + __u32 tseg2_min; /* Time segement 2 = phase_seg2 */ + __u32 tseg2_max; + __u32 sjw_max; /* Synchronisation jump width */ + __u32 brp_min; /* Bit-rate prescaler */ + __u32 brp_max; + __u32 brp_inc; +}; + +/* + * CAN clock parameters + */ +struct can_clock { + __u32 freq; /* CAN system clock frequency in Hz */ +}; + +/* + * CAN operational and error states + */ +enum can_state { + CAN_STATE_ERROR_ACTIVE = 0, /* RX/TX error count < 96 */ + CAN_STATE_ERROR_WARNING, /* RX/TX error count < 128 */ + CAN_STATE_ERROR_PASSIVE, /* RX/TX error count < 256 */ + CAN_STATE_BUS_OFF, /* RX/TX error count >= 256 */ + CAN_STATE_STOPPED, /* Device is stopped */ + CAN_STATE_SLEEPING, /* Device is sleeping */ + CAN_STATE_MAX +}; + +/* + * CAN bus error counters + */ +struct can_berr_counter { + __u16 txerr; + __u16 rxerr; +}; + +/* + * CAN controller mode + */ +struct can_ctrlmode { + __u32 mask; + __u32 flags; +}; + +#define CAN_CTRLMODE_LOOPBACK 0x01 /* Loopback mode */ +#define CAN_CTRLMODE_LISTENONLY 0x02 /* Listen-only mode */ +#define CAN_CTRLMODE_3_SAMPLES 0x04 /* Triple sampling mode */ +#define CAN_CTRLMODE_ONE_SHOT 0x08 /* One-Shot mode */ +#define CAN_CTRLMODE_BERR_REPORTING 0x10 /* Bus-error reporting */ + +/* + * CAN device statistics + */ +struct can_device_stats { + __u32 bus_error; /* Bus errors */ + __u32 error_warning; /* Changes to error warning state */ + __u32 error_passive; /* Changes to error passive state */ + __u32 bus_off; /* Changes to bus off state */ + __u32 arbitration_lost; /* Arbitration lost errors */ + __u32 restarts; /* CAN controller re-starts */ +}; + +/* + * CAN netlink interface + */ +enum { + IFLA_CAN_UNSPEC, + IFLA_CAN_BITTIMING, + IFLA_CAN_BITTIMING_CONST, + IFLA_CAN_CLOCK, + IFLA_CAN_STATE, + IFLA_CAN_CTRLMODE, + IFLA_CAN_RESTART_MS, + IFLA_CAN_RESTART, + IFLA_CAN_BERR_COUNTER, + __IFLA_CAN_MAX +}; + +#define IFLA_CAN_MAX (__IFLA_CAN_MAX - 1) + +#endif /* CAN_NETLINK_H */ From 7c85b8a53bfa19872c1165c1fddb321ed38d92c5 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 11 Dec 2012 18:06:29 +0100 Subject: [PATCH 357/432] netfilter: update local header files Needed to NF_CT_EXPECT_PERMANENT etc. Signed-off-by: Thomas Graf --- include/linux/netfilter/nf_conntrack_common.h | 117 +++++++ include/linux/netfilter/nfnetlink.h | 112 +++---- include/linux/netfilter/nfnetlink_compat.h | 63 ++++ include/linux/netfilter/nfnetlink_conntrack.h | 304 +++++++++--------- include/linux/netfilter/nfnetlink_queue.h | 105 +++--- 5 files changed, 423 insertions(+), 278 deletions(-) create mode 100644 include/linux/netfilter/nf_conntrack_common.h create mode 100644 include/linux/netfilter/nfnetlink_compat.h diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h new file mode 100644 index 0000000..1644cdd --- /dev/null +++ b/include/linux/netfilter/nf_conntrack_common.h @@ -0,0 +1,117 @@ +#ifndef _UAPI_NF_CONNTRACK_COMMON_H +#define _UAPI_NF_CONNTRACK_COMMON_H +/* Connection state tracking for netfilter. This is separated from, + but required by, the NAT layer; it can also be used by an iptables + extension. */ +enum ip_conntrack_info { + /* Part of an established connection (either direction). */ + IP_CT_ESTABLISHED, + + /* Like NEW, but related to an existing connection, or ICMP error + (in either direction). */ + IP_CT_RELATED, + + /* Started a new connection to track (only + IP_CT_DIR_ORIGINAL); may be a retransmission. */ + IP_CT_NEW, + + /* >= this indicates reply direction */ + IP_CT_IS_REPLY, + + IP_CT_ESTABLISHED_REPLY = IP_CT_ESTABLISHED + IP_CT_IS_REPLY, + IP_CT_RELATED_REPLY = IP_CT_RELATED + IP_CT_IS_REPLY, + IP_CT_NEW_REPLY = IP_CT_NEW + IP_CT_IS_REPLY, + /* Number of distinct IP_CT types (no NEW in reply dirn). */ + IP_CT_NUMBER = IP_CT_IS_REPLY * 2 - 1 +}; + +/* Bitset representing status of connection. */ +enum ip_conntrack_status { + /* It's an expected connection: bit 0 set. This bit never changed */ + IPS_EXPECTED_BIT = 0, + IPS_EXPECTED = (1 << IPS_EXPECTED_BIT), + + /* We've seen packets both ways: bit 1 set. Can be set, not unset. */ + IPS_SEEN_REPLY_BIT = 1, + IPS_SEEN_REPLY = (1 << IPS_SEEN_REPLY_BIT), + + /* Conntrack should never be early-expired. */ + IPS_ASSURED_BIT = 2, + IPS_ASSURED = (1 << IPS_ASSURED_BIT), + + /* Connection is confirmed: originating packet has left box */ + IPS_CONFIRMED_BIT = 3, + IPS_CONFIRMED = (1 << IPS_CONFIRMED_BIT), + + /* Connection needs src nat in orig dir. This bit never changed. */ + IPS_SRC_NAT_BIT = 4, + IPS_SRC_NAT = (1 << IPS_SRC_NAT_BIT), + + /* Connection needs dst nat in orig dir. This bit never changed. */ + IPS_DST_NAT_BIT = 5, + IPS_DST_NAT = (1 << IPS_DST_NAT_BIT), + + /* Both together. */ + IPS_NAT_MASK = (IPS_DST_NAT | IPS_SRC_NAT), + + /* Connection needs TCP sequence adjusted. */ + IPS_SEQ_ADJUST_BIT = 6, + IPS_SEQ_ADJUST = (1 << IPS_SEQ_ADJUST_BIT), + + /* NAT initialization bits. */ + IPS_SRC_NAT_DONE_BIT = 7, + IPS_SRC_NAT_DONE = (1 << IPS_SRC_NAT_DONE_BIT), + + IPS_DST_NAT_DONE_BIT = 8, + IPS_DST_NAT_DONE = (1 << IPS_DST_NAT_DONE_BIT), + + /* Both together */ + IPS_NAT_DONE_MASK = (IPS_DST_NAT_DONE | IPS_SRC_NAT_DONE), + + /* Connection is dying (removed from lists), can not be unset. */ + IPS_DYING_BIT = 9, + IPS_DYING = (1 << IPS_DYING_BIT), + + /* Connection has fixed timeout. */ + IPS_FIXED_TIMEOUT_BIT = 10, + IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT), + + /* Conntrack is a template */ + IPS_TEMPLATE_BIT = 11, + IPS_TEMPLATE = (1 << IPS_TEMPLATE_BIT), + + /* Conntrack is a fake untracked entry */ + IPS_UNTRACKED_BIT = 12, + IPS_UNTRACKED = (1 << IPS_UNTRACKED_BIT), + + /* Conntrack got a helper explicitly attached via CT target. */ + IPS_HELPER_BIT = 13, + IPS_HELPER = (1 << IPS_HELPER_BIT), +}; + +/* Connection tracking event types */ +enum ip_conntrack_events { + IPCT_NEW, /* new conntrack */ + IPCT_RELATED, /* related conntrack */ + IPCT_DESTROY, /* destroyed conntrack */ + IPCT_REPLY, /* connection has seen two-way traffic */ + IPCT_ASSURED, /* connection status has changed to assured */ + IPCT_PROTOINFO, /* protocol information has changed */ + IPCT_HELPER, /* new helper has been set */ + IPCT_MARK, /* new mark has been set */ + IPCT_NATSEQADJ, /* NAT is doing sequence adjustment */ + IPCT_SECMARK, /* new security mark has been set */ +}; + +enum ip_conntrack_expect_events { + IPEXP_NEW, /* new expectation */ + IPEXP_DESTROY, /* destroyed expectation */ +}; + +/* expectation flags */ +#define NF_CT_EXPECT_PERMANENT 0x1 +#define NF_CT_EXPECT_INACTIVE 0x2 +#define NF_CT_EXPECT_USERSPACE 0x4 + + +#endif /* _UAPI_NF_CONNTRACK_COMMON_H */ diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h index 43979ac..4a4efaf 100644 --- a/include/linux/netfilter/nfnetlink.h +++ b/include/linux/netfilter/nfnetlink.h @@ -1,96 +1,56 @@ -#ifndef _NFNETLINK_H -#define _NFNETLINK_H +#ifndef _UAPI_NFNETLINK_H +#define _UAPI_NFNETLINK_H #include #include enum nfnetlink_groups { - NFNLGRP_NONE, -#define NFNLGRP_NONE NFNLGRP_NONE - NFNLGRP_CONNTRACK_NEW, -#define NFNLGRP_CONNTRACK_NEW NFNLGRP_CONNTRACK_NEW - NFNLGRP_CONNTRACK_UPDATE, -#define NFNLGRP_CONNTRACK_UPDATE NFNLGRP_CONNTRACK_UPDATE - NFNLGRP_CONNTRACK_DESTROY, -#define NFNLGRP_CONNTRACK_DESTROY NFNLGRP_CONNTRACK_DESTROY - NFNLGRP_CONNTRACK_EXP_NEW, -#define NFNLGRP_CONNTRACK_EXP_NEW NFNLGRP_CONNTRACK_EXP_NEW - NFNLGRP_CONNTRACK_EXP_UPDATE, -#define NFNLGRP_CONNTRACK_EXP_UPDATE NFNLGRP_CONNTRACK_EXP_UPDATE - NFNLGRP_CONNTRACK_EXP_DESTROY, -#define NFNLGRP_CONNTRACK_EXP_DESTROY NFNLGRP_CONNTRACK_EXP_DESTROY - __NFNLGRP_MAX, + NFNLGRP_NONE, +#define NFNLGRP_NONE NFNLGRP_NONE + NFNLGRP_CONNTRACK_NEW, +#define NFNLGRP_CONNTRACK_NEW NFNLGRP_CONNTRACK_NEW + NFNLGRP_CONNTRACK_UPDATE, +#define NFNLGRP_CONNTRACK_UPDATE NFNLGRP_CONNTRACK_UPDATE + NFNLGRP_CONNTRACK_DESTROY, +#define NFNLGRP_CONNTRACK_DESTROY NFNLGRP_CONNTRACK_DESTROY + NFNLGRP_CONNTRACK_EXP_NEW, +#define NFNLGRP_CONNTRACK_EXP_NEW NFNLGRP_CONNTRACK_EXP_NEW + NFNLGRP_CONNTRACK_EXP_UPDATE, +#define NFNLGRP_CONNTRACK_EXP_UPDATE NFNLGRP_CONNTRACK_EXP_UPDATE + NFNLGRP_CONNTRACK_EXP_DESTROY, +#define NFNLGRP_CONNTRACK_EXP_DESTROY NFNLGRP_CONNTRACK_EXP_DESTROY + __NFNLGRP_MAX, }; -#define NFNLGRP_MAX (__NFNLGRP_MAX - 1) +#define NFNLGRP_MAX (__NFNLGRP_MAX - 1) /* General form of address family dependent message. */ struct nfgenmsg { - __u8 nfgen_family; /* AF_xxx */ - __u8 version; /* nfnetlink version */ - __be16 res_id; /* resource id */ + __u8 nfgen_family; /* AF_xxx */ + __u8 version; /* nfnetlink version */ + __be16 res_id; /* resource id */ }; -#define NFNETLINK_V0 0 +#define NFNETLINK_V0 0 /* netfilter netlink message types are split in two pieces: * 8 bit subsystem, 8bit operation. */ -#define NFNL_SUBSYS_ID(x) ((x & 0xff00) >> 8) -#define NFNL_MSG_TYPE(x) (x & 0x00ff) +#define NFNL_SUBSYS_ID(x) ((x & 0xff00) >> 8) +#define NFNL_MSG_TYPE(x) (x & 0x00ff) /* No enum here, otherwise __stringify() trick of MODULE_ALIAS_NFNL_SUBSYS() * won't work anymore */ -#define NFNL_SUBSYS_NONE 0 -#define NFNL_SUBSYS_CTNETLINK 1 -#define NFNL_SUBSYS_CTNETLINK_EXP 2 -#define NFNL_SUBSYS_QUEUE 3 -#define NFNL_SUBSYS_ULOG 4 -#define NFNL_SUBSYS_OSF 5 -#define NFNL_SUBSYS_IPSET 6 -#define NFNL_SUBSYS_ACCT 7 -#define NFNL_SUBSYS_CTNETLINK_TIMEOUT 8 -#define NFNL_SUBSYS_CTHELPER 9 -#define NFNL_SUBSYS_COUNT 10 +#define NFNL_SUBSYS_NONE 0 +#define NFNL_SUBSYS_CTNETLINK 1 +#define NFNL_SUBSYS_CTNETLINK_EXP 2 +#define NFNL_SUBSYS_QUEUE 3 +#define NFNL_SUBSYS_ULOG 4 +#define NFNL_SUBSYS_OSF 5 +#define NFNL_SUBSYS_IPSET 6 +#define NFNL_SUBSYS_ACCT 7 +#define NFNL_SUBSYS_CTNETLINK_TIMEOUT 8 +#define NFNL_SUBSYS_CTHELPER 9 +#define NFNL_SUBSYS_COUNT 10 -#ifdef __KERNEL__ - -#include -#include -#include - -struct nfnl_callback { - int (*call)(struct sock *nl, struct sk_buff *skb, - const struct nlmsghdr *nlh, - const struct nlattr * const cda[]); - int (*call_rcu)(struct sock *nl, struct sk_buff *skb, - const struct nlmsghdr *nlh, - const struct nlattr * const cda[]); - const struct nla_policy *policy; /* netlink attribute policy */ - const u_int16_t attr_count; /* number of nlattr's */ -}; - -struct nfnetlink_subsystem { - const char *name; - __u8 subsys_id; /* nfnetlink subsystem ID */ - __u8 cb_count; /* number of callbacks */ - const struct nfnl_callback *cb; /* callback for individual types */ -}; - -extern int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n); -extern int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n); - -extern int nfnetlink_has_listeners(struct net *net, unsigned int group); -extern int nfnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned int group, - int echo, gfp_t flags); -extern int nfnetlink_set_err(struct net *net, u32 pid, u32 group, int error); -extern int nfnetlink_unicast(struct sk_buff *skb, struct net *net, u_int32_t pid, int flags); - -extern void nfnl_lock(void); -extern void nfnl_unlock(void); - -#define MODULE_ALIAS_NFNL_SUBSYS(subsys) \ - MODULE_ALIAS("nfnetlink-subsys-" __stringify(subsys)) - -#endif /* __KERNEL__ */ -#endif /* _NFNETLINK_H */ +#endif /* _UAPI_NFNETLINK_H */ diff --git a/include/linux/netfilter/nfnetlink_compat.h b/include/linux/netfilter/nfnetlink_compat.h new file mode 100644 index 0000000..ffb9503 --- /dev/null +++ b/include/linux/netfilter/nfnetlink_compat.h @@ -0,0 +1,63 @@ +#ifndef _NFNETLINK_COMPAT_H +#define _NFNETLINK_COMPAT_H + +#include + +#ifndef __KERNEL__ +/* Old nfnetlink macros for userspace */ + +/* nfnetlink groups: Up to 32 maximum */ +#define NF_NETLINK_CONNTRACK_NEW 0x00000001 +#define NF_NETLINK_CONNTRACK_UPDATE 0x00000002 +#define NF_NETLINK_CONNTRACK_DESTROY 0x00000004 +#define NF_NETLINK_CONNTRACK_EXP_NEW 0x00000008 +#define NF_NETLINK_CONNTRACK_EXP_UPDATE 0x00000010 +#define NF_NETLINK_CONNTRACK_EXP_DESTROY 0x00000020 + +/* Generic structure for encapsulation optional netfilter information. + * It is reminiscent of sockaddr, but with sa_family replaced + * with attribute type. + * ! This should someday be put somewhere generic as now rtnetlink and + * ! nfnetlink use the same attributes methods. - J. Schulist. + */ + +struct nfattr { + __u16 nfa_len; + __u16 nfa_type; /* we use 15 bits for the type, and the highest + * bit to indicate whether the payload is nested */ +}; + +/* FIXME: Apart from NFNL_NFA_NESTED shamelessly copy and pasted from + * rtnetlink.h, it's time to put this in a generic file */ + +#define NFNL_NFA_NEST 0x8000 +#define NFA_TYPE(attr) ((attr)->nfa_type & 0x7fff) + +#define NFA_ALIGNTO 4 +#define NFA_ALIGN(len) (((len) + NFA_ALIGNTO - 1) & ~(NFA_ALIGNTO - 1)) +#define NFA_OK(nfa,len) ((len) > 0 && (nfa)->nfa_len >= sizeof(struct nfattr) \ + && (nfa)->nfa_len <= (len)) +#define NFA_NEXT(nfa,attrlen) ((attrlen) -= NFA_ALIGN((nfa)->nfa_len), \ + (struct nfattr *)(((char *)(nfa)) + NFA_ALIGN((nfa)->nfa_len))) +#define NFA_LENGTH(len) (NFA_ALIGN(sizeof(struct nfattr)) + (len)) +#define NFA_SPACE(len) NFA_ALIGN(NFA_LENGTH(len)) +#define NFA_DATA(nfa) ((void *)(((char *)(nfa)) + NFA_LENGTH(0))) +#define NFA_PAYLOAD(nfa) ((int)((nfa)->nfa_len) - NFA_LENGTH(0)) +#define NFA_NEST(skb, type) \ +({ struct nfattr *__start = (struct nfattr *)skb_tail_pointer(skb); \ + NFA_PUT(skb, (NFNL_NFA_NEST | type), 0, NULL); \ + __start; }) +#define NFA_NEST_END(skb, start) \ +({ (start)->nfa_len = skb_tail_pointer(skb) - (unsigned char *)(start); \ + (skb)->len; }) +#define NFA_NEST_CANCEL(skb, start) \ +({ if (start) \ + skb_trim(skb, (unsigned char *) (start) - (skb)->data); \ + -1; }) + +#define NFM_NFA(n) ((struct nfattr *)(((char *)(n)) \ + + NLMSG_ALIGN(sizeof(struct nfgenmsg)))) +#define NFM_PAYLOAD(n) NLMSG_PAYLOAD(n, sizeof(struct nfgenmsg)) + +#endif /* ! __KERNEL__ */ +#endif /* _NFNETLINK_COMPAT_H */ diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux/netfilter/nfnetlink_conntrack.h index c91be60..43bfe3e 100644 --- a/include/linux/netfilter/nfnetlink_conntrack.h +++ b/include/linux/netfilter/nfnetlink_conntrack.h @@ -3,241 +3,245 @@ #include enum cntl_msg_types { - IPCTNL_MSG_CT_NEW, - IPCTNL_MSG_CT_GET, - IPCTNL_MSG_CT_DELETE, - IPCTNL_MSG_CT_GET_CTRZERO, - IPCTNL_MSG_CT_GET_STATS_CPU, - IPCTNL_MSG_CT_GET_STATS, + IPCTNL_MSG_CT_NEW, + IPCTNL_MSG_CT_GET, + IPCTNL_MSG_CT_DELETE, + IPCTNL_MSG_CT_GET_CTRZERO, + IPCTNL_MSG_CT_GET_STATS_CPU, + IPCTNL_MSG_CT_GET_STATS, - IPCTNL_MSG_MAX + IPCTNL_MSG_MAX }; enum ctnl_exp_msg_types { - IPCTNL_MSG_EXP_NEW, - IPCTNL_MSG_EXP_GET, - IPCTNL_MSG_EXP_DELETE, - IPCTNL_MSG_EXP_GET_STATS_CPU, + IPCTNL_MSG_EXP_NEW, + IPCTNL_MSG_EXP_GET, + IPCTNL_MSG_EXP_DELETE, + IPCTNL_MSG_EXP_GET_STATS_CPU, - IPCTNL_MSG_EXP_MAX + IPCTNL_MSG_EXP_MAX }; enum ctattr_type { - CTA_UNSPEC, - CTA_TUPLE_ORIG, - CTA_TUPLE_REPLY, - CTA_STATUS, - CTA_PROTOINFO, - CTA_HELP, - CTA_NAT_SRC, -#define CTA_NAT CTA_NAT_SRC /* backwards compatibility */ - CTA_TIMEOUT, - CTA_MARK, - CTA_COUNTERS_ORIG, - CTA_COUNTERS_REPLY, - CTA_USE, - CTA_ID, - CTA_NAT_DST, - CTA_TUPLE_MASTER, - CTA_NAT_SEQ_ADJ_ORIG, - CTA_NAT_SEQ_ADJ_REPLY, - CTA_SECMARK, /* obsolete */ - CTA_ZONE, - CTA_SECCTX, - CTA_TIMESTAMP, - CTA_MARK_MASK, - __CTA_MAX + CTA_UNSPEC, + CTA_TUPLE_ORIG, + CTA_TUPLE_REPLY, + CTA_STATUS, + CTA_PROTOINFO, + CTA_HELP, + CTA_NAT_SRC, +#define CTA_NAT CTA_NAT_SRC /* backwards compatibility */ + CTA_TIMEOUT, + CTA_MARK, + CTA_COUNTERS_ORIG, + CTA_COUNTERS_REPLY, + CTA_USE, + CTA_ID, + CTA_NAT_DST, + CTA_TUPLE_MASTER, + CTA_NAT_SEQ_ADJ_ORIG, + CTA_NAT_SEQ_ADJ_REPLY, + CTA_SECMARK, /* obsolete */ + CTA_ZONE, + CTA_SECCTX, + CTA_TIMESTAMP, + CTA_MARK_MASK, + __CTA_MAX }; #define CTA_MAX (__CTA_MAX - 1) enum ctattr_tuple { - CTA_TUPLE_UNSPEC, - CTA_TUPLE_IP, - CTA_TUPLE_PROTO, - __CTA_TUPLE_MAX + CTA_TUPLE_UNSPEC, + CTA_TUPLE_IP, + CTA_TUPLE_PROTO, + __CTA_TUPLE_MAX }; #define CTA_TUPLE_MAX (__CTA_TUPLE_MAX - 1) enum ctattr_ip { - CTA_IP_UNSPEC, - CTA_IP_V4_SRC, - CTA_IP_V4_DST, - CTA_IP_V6_SRC, - CTA_IP_V6_DST, - __CTA_IP_MAX + CTA_IP_UNSPEC, + CTA_IP_V4_SRC, + CTA_IP_V4_DST, + CTA_IP_V6_SRC, + CTA_IP_V6_DST, + __CTA_IP_MAX }; #define CTA_IP_MAX (__CTA_IP_MAX - 1) enum ctattr_l4proto { - CTA_PROTO_UNSPEC, - CTA_PROTO_NUM, - CTA_PROTO_SRC_PORT, - CTA_PROTO_DST_PORT, - CTA_PROTO_ICMP_ID, - CTA_PROTO_ICMP_TYPE, - CTA_PROTO_ICMP_CODE, - CTA_PROTO_ICMPV6_ID, - CTA_PROTO_ICMPV6_TYPE, - CTA_PROTO_ICMPV6_CODE, - __CTA_PROTO_MAX + CTA_PROTO_UNSPEC, + CTA_PROTO_NUM, + CTA_PROTO_SRC_PORT, + CTA_PROTO_DST_PORT, + CTA_PROTO_ICMP_ID, + CTA_PROTO_ICMP_TYPE, + CTA_PROTO_ICMP_CODE, + CTA_PROTO_ICMPV6_ID, + CTA_PROTO_ICMPV6_TYPE, + CTA_PROTO_ICMPV6_CODE, + __CTA_PROTO_MAX }; #define CTA_PROTO_MAX (__CTA_PROTO_MAX - 1) enum ctattr_protoinfo { - CTA_PROTOINFO_UNSPEC, - CTA_PROTOINFO_TCP, - CTA_PROTOINFO_DCCP, - CTA_PROTOINFO_SCTP, - __CTA_PROTOINFO_MAX + CTA_PROTOINFO_UNSPEC, + CTA_PROTOINFO_TCP, + CTA_PROTOINFO_DCCP, + CTA_PROTOINFO_SCTP, + __CTA_PROTOINFO_MAX }; #define CTA_PROTOINFO_MAX (__CTA_PROTOINFO_MAX - 1) enum ctattr_protoinfo_tcp { - CTA_PROTOINFO_TCP_UNSPEC, - CTA_PROTOINFO_TCP_STATE, - CTA_PROTOINFO_TCP_WSCALE_ORIGINAL, - CTA_PROTOINFO_TCP_WSCALE_REPLY, - CTA_PROTOINFO_TCP_FLAGS_ORIGINAL, - CTA_PROTOINFO_TCP_FLAGS_REPLY, - __CTA_PROTOINFO_TCP_MAX + CTA_PROTOINFO_TCP_UNSPEC, + CTA_PROTOINFO_TCP_STATE, + CTA_PROTOINFO_TCP_WSCALE_ORIGINAL, + CTA_PROTOINFO_TCP_WSCALE_REPLY, + CTA_PROTOINFO_TCP_FLAGS_ORIGINAL, + CTA_PROTOINFO_TCP_FLAGS_REPLY, + __CTA_PROTOINFO_TCP_MAX }; #define CTA_PROTOINFO_TCP_MAX (__CTA_PROTOINFO_TCP_MAX - 1) enum ctattr_protoinfo_dccp { - CTA_PROTOINFO_DCCP_UNSPEC, - CTA_PROTOINFO_DCCP_STATE, - CTA_PROTOINFO_DCCP_ROLE, - CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ, - __CTA_PROTOINFO_DCCP_MAX, + CTA_PROTOINFO_DCCP_UNSPEC, + CTA_PROTOINFO_DCCP_STATE, + CTA_PROTOINFO_DCCP_ROLE, + CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ, + __CTA_PROTOINFO_DCCP_MAX, }; #define CTA_PROTOINFO_DCCP_MAX (__CTA_PROTOINFO_DCCP_MAX - 1) enum ctattr_protoinfo_sctp { - CTA_PROTOINFO_SCTP_UNSPEC, - CTA_PROTOINFO_SCTP_STATE, - CTA_PROTOINFO_SCTP_VTAG_ORIGINAL, - CTA_PROTOINFO_SCTP_VTAG_REPLY, - __CTA_PROTOINFO_SCTP_MAX + CTA_PROTOINFO_SCTP_UNSPEC, + CTA_PROTOINFO_SCTP_STATE, + CTA_PROTOINFO_SCTP_VTAG_ORIGINAL, + CTA_PROTOINFO_SCTP_VTAG_REPLY, + __CTA_PROTOINFO_SCTP_MAX }; #define CTA_PROTOINFO_SCTP_MAX (__CTA_PROTOINFO_SCTP_MAX - 1) enum ctattr_counters { - CTA_COUNTERS_UNSPEC, - CTA_COUNTERS_PACKETS, /* 64bit counters */ - CTA_COUNTERS_BYTES, /* 64bit counters */ - CTA_COUNTERS32_PACKETS, /* old 32bit counters, unused */ - CTA_COUNTERS32_BYTES, /* old 32bit counters, unused */ - __CTA_COUNTERS_MAX + CTA_COUNTERS_UNSPEC, + CTA_COUNTERS_PACKETS, /* 64bit counters */ + CTA_COUNTERS_BYTES, /* 64bit counters */ + CTA_COUNTERS32_PACKETS, /* old 32bit counters, unused */ + CTA_COUNTERS32_BYTES, /* old 32bit counters, unused */ + __CTA_COUNTERS_MAX }; #define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1) enum ctattr_tstamp { - CTA_TIMESTAMP_UNSPEC, - CTA_TIMESTAMP_START, - CTA_TIMESTAMP_STOP, - __CTA_TIMESTAMP_MAX + CTA_TIMESTAMP_UNSPEC, + CTA_TIMESTAMP_START, + CTA_TIMESTAMP_STOP, + __CTA_TIMESTAMP_MAX }; #define CTA_TIMESTAMP_MAX (__CTA_TIMESTAMP_MAX - 1) enum ctattr_nat { - CTA_NAT_UNSPEC, - CTA_NAT_MINIP, - CTA_NAT_MAXIP, - CTA_NAT_PROTO, - __CTA_NAT_MAX + CTA_NAT_UNSPEC, + CTA_NAT_V4_MINIP, +#define CTA_NAT_MINIP CTA_NAT_V4_MINIP + CTA_NAT_V4_MAXIP, +#define CTA_NAT_MAXIP CTA_NAT_V4_MAXIP + CTA_NAT_PROTO, + CTA_NAT_V6_MINIP, + CTA_NAT_V6_MAXIP, + __CTA_NAT_MAX }; #define CTA_NAT_MAX (__CTA_NAT_MAX - 1) enum ctattr_protonat { - CTA_PROTONAT_UNSPEC, - CTA_PROTONAT_PORT_MIN, - CTA_PROTONAT_PORT_MAX, - __CTA_PROTONAT_MAX + CTA_PROTONAT_UNSPEC, + CTA_PROTONAT_PORT_MIN, + CTA_PROTONAT_PORT_MAX, + __CTA_PROTONAT_MAX }; #define CTA_PROTONAT_MAX (__CTA_PROTONAT_MAX - 1) enum ctattr_natseq { - CTA_NAT_SEQ_UNSPEC, - CTA_NAT_SEQ_CORRECTION_POS, - CTA_NAT_SEQ_OFFSET_BEFORE, - CTA_NAT_SEQ_OFFSET_AFTER, - __CTA_NAT_SEQ_MAX + CTA_NAT_SEQ_UNSPEC, + CTA_NAT_SEQ_CORRECTION_POS, + CTA_NAT_SEQ_OFFSET_BEFORE, + CTA_NAT_SEQ_OFFSET_AFTER, + __CTA_NAT_SEQ_MAX }; #define CTA_NAT_SEQ_MAX (__CTA_NAT_SEQ_MAX - 1) enum ctattr_expect { - CTA_EXPECT_UNSPEC, - CTA_EXPECT_MASTER, - CTA_EXPECT_TUPLE, - CTA_EXPECT_MASK, - CTA_EXPECT_TIMEOUT, - CTA_EXPECT_ID, - CTA_EXPECT_HELP_NAME, - CTA_EXPECT_ZONE, - CTA_EXPECT_FLAGS, - CTA_EXPECT_CLASS, - CTA_EXPECT_NAT, - CTA_EXPECT_FN, - __CTA_EXPECT_MAX + CTA_EXPECT_UNSPEC, + CTA_EXPECT_MASTER, + CTA_EXPECT_TUPLE, + CTA_EXPECT_MASK, + CTA_EXPECT_TIMEOUT, + CTA_EXPECT_ID, + CTA_EXPECT_HELP_NAME, + CTA_EXPECT_ZONE, + CTA_EXPECT_FLAGS, + CTA_EXPECT_CLASS, + CTA_EXPECT_NAT, + CTA_EXPECT_FN, + __CTA_EXPECT_MAX }; #define CTA_EXPECT_MAX (__CTA_EXPECT_MAX - 1) enum ctattr_expect_nat { - CTA_EXPECT_NAT_UNSPEC, - CTA_EXPECT_NAT_DIR, - CTA_EXPECT_NAT_TUPLE, - __CTA_EXPECT_NAT_MAX + CTA_EXPECT_NAT_UNSPEC, + CTA_EXPECT_NAT_DIR, + CTA_EXPECT_NAT_TUPLE, + __CTA_EXPECT_NAT_MAX }; #define CTA_EXPECT_NAT_MAX (__CTA_EXPECT_NAT_MAX - 1) enum ctattr_help { - CTA_HELP_UNSPEC, - CTA_HELP_NAME, - CTA_HELP_INFO, - __CTA_HELP_MAX + CTA_HELP_UNSPEC, + CTA_HELP_NAME, + CTA_HELP_INFO, + __CTA_HELP_MAX }; #define CTA_HELP_MAX (__CTA_HELP_MAX - 1) enum ctattr_secctx { - CTA_SECCTX_UNSPEC, - CTA_SECCTX_NAME, - __CTA_SECCTX_MAX + CTA_SECCTX_UNSPEC, + CTA_SECCTX_NAME, + __CTA_SECCTX_MAX }; #define CTA_SECCTX_MAX (__CTA_SECCTX_MAX - 1) enum ctattr_stats_cpu { - CTA_STATS_UNSPEC, - CTA_STATS_SEARCHED, - CTA_STATS_FOUND, - CTA_STATS_NEW, - CTA_STATS_INVALID, - CTA_STATS_IGNORE, - CTA_STATS_DELETE, - CTA_STATS_DELETE_LIST, - CTA_STATS_INSERT, - CTA_STATS_INSERT_FAILED, - CTA_STATS_DROP, - CTA_STATS_EARLY_DROP, - CTA_STATS_ERROR, - CTA_STATS_SEARCH_RESTART, - __CTA_STATS_MAX, + CTA_STATS_UNSPEC, + CTA_STATS_SEARCHED, + CTA_STATS_FOUND, + CTA_STATS_NEW, + CTA_STATS_INVALID, + CTA_STATS_IGNORE, + CTA_STATS_DELETE, + CTA_STATS_DELETE_LIST, + CTA_STATS_INSERT, + CTA_STATS_INSERT_FAILED, + CTA_STATS_DROP, + CTA_STATS_EARLY_DROP, + CTA_STATS_ERROR, + CTA_STATS_SEARCH_RESTART, + __CTA_STATS_MAX, }; #define CTA_STATS_MAX (__CTA_STATS_MAX - 1) enum ctattr_stats_global { - CTA_STATS_GLOBAL_UNSPEC, - CTA_STATS_GLOBAL_ENTRIES, - __CTA_STATS_GLOBAL_MAX, + CTA_STATS_GLOBAL_UNSPEC, + CTA_STATS_GLOBAL_ENTRIES, + __CTA_STATS_GLOBAL_MAX, }; #define CTA_STATS_GLOBAL_MAX (__CTA_STATS_GLOBAL_MAX - 1) enum ctattr_expect_stats { - CTA_STATS_EXP_UNSPEC, - CTA_STATS_EXP_NEW, - CTA_STATS_EXP_CREATE, - CTA_STATS_EXP_DELETE, - __CTA_STATS_EXP_MAX, + CTA_STATS_EXP_UNSPEC, + CTA_STATS_EXP_NEW, + CTA_STATS_EXP_CREATE, + CTA_STATS_EXP_DELETE, + __CTA_STATS_EXP_MAX, }; #define CTA_STATS_EXP_MAX (__CTA_STATS_EXP_MAX - 1) diff --git a/include/linux/netfilter/nfnetlink_queue.h b/include/linux/netfilter/nfnetlink_queue.h index 5fcd48c..70ec8c2 100644 --- a/include/linux/netfilter/nfnetlink_queue.h +++ b/include/linux/netfilter/nfnetlink_queue.h @@ -5,96 +5,97 @@ #include enum nfqnl_msg_types { - NFQNL_MSG_PACKET, /* packet from kernel to userspace */ - NFQNL_MSG_VERDICT, /* verdict from userspace to kernel */ - NFQNL_MSG_CONFIG, /* connect to a particular queue */ - NFQNL_MSG_VERDICT_BATCH, /* batchv from userspace to kernel */ + NFQNL_MSG_PACKET, /* packet from kernel to userspace */ + NFQNL_MSG_VERDICT, /* verdict from userspace to kernel */ + NFQNL_MSG_CONFIG, /* connect to a particular queue */ + NFQNL_MSG_VERDICT_BATCH, /* batchv from userspace to kernel */ - NFQNL_MSG_MAX + NFQNL_MSG_MAX }; struct nfqnl_msg_packet_hdr { - __be32 packet_id; /* unique ID of packet in queue */ - __be16 hw_protocol; /* hw protocol (network order) */ - __u8 hook; /* netfilter hook */ + __be32 packet_id; /* unique ID of packet in queue */ + __be16 hw_protocol; /* hw protocol (network order) */ + __u8 hook; /* netfilter hook */ } __attribute__ ((packed)); struct nfqnl_msg_packet_hw { - __be16 hw_addrlen; - __u16 _pad; - __u8 hw_addr[8]; + __be16 hw_addrlen; + __u16 _pad; + __u8 hw_addr[8]; }; struct nfqnl_msg_packet_timestamp { - __aligned_be64 sec; - __aligned_be64 usec; + __aligned_be64 sec; + __aligned_be64 usec; }; enum nfqnl_attr_type { - NFQA_UNSPEC, - NFQA_PACKET_HDR, - NFQA_VERDICT_HDR, /* nfqnl_msg_verdict_hrd */ - NFQA_MARK, /* __u32 nfmark */ - NFQA_TIMESTAMP, /* nfqnl_msg_packet_timestamp */ - NFQA_IFINDEX_INDEV, /* __u32 ifindex */ - NFQA_IFINDEX_OUTDEV, /* __u32 ifindex */ - NFQA_IFINDEX_PHYSINDEV, /* __u32 ifindex */ - NFQA_IFINDEX_PHYSOUTDEV, /* __u32 ifindex */ - NFQA_HWADDR, /* nfqnl_msg_packet_hw */ - NFQA_PAYLOAD, /* opaque data payload */ - NFQA_CT, /* nf_conntrack_netlink.h */ - NFQA_CT_INFO, /* enum ip_conntrack_info */ + NFQA_UNSPEC, + NFQA_PACKET_HDR, + NFQA_VERDICT_HDR, /* nfqnl_msg_verdict_hrd */ + NFQA_MARK, /* __u32 nfmark */ + NFQA_TIMESTAMP, /* nfqnl_msg_packet_timestamp */ + NFQA_IFINDEX_INDEV, /* __u32 ifindex */ + NFQA_IFINDEX_OUTDEV, /* __u32 ifindex */ + NFQA_IFINDEX_PHYSINDEV, /* __u32 ifindex */ + NFQA_IFINDEX_PHYSOUTDEV, /* __u32 ifindex */ + NFQA_HWADDR, /* nfqnl_msg_packet_hw */ + NFQA_PAYLOAD, /* opaque data payload */ + NFQA_CT, /* nf_conntrack_netlink.h */ + NFQA_CT_INFO, /* enum ip_conntrack_info */ + NFQA_CAP_LEN, /* __u32 length of captured packet */ - __NFQA_MAX + __NFQA_MAX }; #define NFQA_MAX (__NFQA_MAX - 1) struct nfqnl_msg_verdict_hdr { - __be32 verdict; - __be32 id; + __be32 verdict; + __be32 id; }; enum nfqnl_msg_config_cmds { - NFQNL_CFG_CMD_NONE, - NFQNL_CFG_CMD_BIND, - NFQNL_CFG_CMD_UNBIND, - NFQNL_CFG_CMD_PF_BIND, - NFQNL_CFG_CMD_PF_UNBIND, + NFQNL_CFG_CMD_NONE, + NFQNL_CFG_CMD_BIND, + NFQNL_CFG_CMD_UNBIND, + NFQNL_CFG_CMD_PF_BIND, + NFQNL_CFG_CMD_PF_UNBIND, }; struct nfqnl_msg_config_cmd { - __u8 command; /* nfqnl_msg_config_cmds */ - __u8 _pad; - __be16 pf; /* AF_xxx for PF_[UN]BIND */ + __u8 command; /* nfqnl_msg_config_cmds */ + __u8 _pad; + __be16 pf; /* AF_xxx for PF_[UN]BIND */ }; enum nfqnl_config_mode { - NFQNL_COPY_NONE, - NFQNL_COPY_META, - NFQNL_COPY_PACKET, + NFQNL_COPY_NONE, + NFQNL_COPY_META, + NFQNL_COPY_PACKET, }; struct nfqnl_msg_config_params { - __be32 copy_range; - __u8 copy_mode; /* enum nfqnl_config_mode */ + __be32 copy_range; + __u8 copy_mode; /* enum nfqnl_config_mode */ } __attribute__ ((packed)); enum nfqnl_attr_config { - NFQA_CFG_UNSPEC, - NFQA_CFG_CMD, /* nfqnl_msg_config_cmd */ - NFQA_CFG_PARAMS, /* nfqnl_msg_config_params */ - NFQA_CFG_QUEUE_MAXLEN, /* __u32 */ - NFQA_CFG_MASK, /* identify which flags to change */ - NFQA_CFG_FLAGS, /* value of these flags (__u32) */ - __NFQA_CFG_MAX + NFQA_CFG_UNSPEC, + NFQA_CFG_CMD, /* nfqnl_msg_config_cmd */ + NFQA_CFG_PARAMS, /* nfqnl_msg_config_params */ + NFQA_CFG_QUEUE_MAXLEN, /* __u32 */ + NFQA_CFG_MASK, /* identify which flags to change */ + NFQA_CFG_FLAGS, /* value of these flags (__u32) */ + __NFQA_CFG_MAX }; #define NFQA_CFG_MAX (__NFQA_CFG_MAX-1) /* Flags for NFQA_CFG_FLAGS */ -#define NFQA_CFG_F_FAIL_OPEN (1 << 0) -#define NFQA_CFG_F_CONNTRACK (1 << 1) -#define NFQA_CFG_F_MAX (1 << 2) +#define NFQA_CFG_F_FAIL_OPEN (1 << 0) +#define NFQA_CFG_F_CONNTRACK (1 << 1) +#define NFQA_CFG_F_MAX (1 << 2) #endif /* _NFNETLINK_QUEUE_H */ From 25c407c71f3e11b0581bb8fb83dc7b3aa53a9c94 Mon Sep 17 00:00:00 2001 From: Rich Fought Date: Thu, 13 Dec 2012 14:23:28 -0800 Subject: [PATCH 358/432] Re-adding #defines for __aligned_be64 for older kernels --- include/linux/netfilter/nfnetlink_log.h | 4 ++++ include/linux/netfilter/nfnetlink_queue.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/include/linux/netfilter/nfnetlink_log.h b/include/linux/netfilter/nfnetlink_log.h index 90c2c95..2cfbf13 100644 --- a/include/linux/netfilter/nfnetlink_log.h +++ b/include/linux/netfilter/nfnetlink_log.h @@ -5,6 +5,10 @@ * and not any kind of function definitions. It is shared between kernel and * userspace. Don't put kernel specific stuff in here */ +#ifndef __aligned_be64 +#define __aligned_be64 u_int64_t __attribute__((aligned(8))) +#endif + #include #include diff --git a/include/linux/netfilter/nfnetlink_queue.h b/include/linux/netfilter/nfnetlink_queue.h index 70ec8c2..95af967 100644 --- a/include/linux/netfilter/nfnetlink_queue.h +++ b/include/linux/netfilter/nfnetlink_queue.h @@ -4,6 +4,10 @@ #include #include +#ifndef __aligned_be64 +#define __aligned_be64 u_int64_t __attribute__((aligned(8))) +#endif + enum nfqnl_msg_types { NFQNL_MSG_PACKET, /* packet from kernel to userspace */ NFQNL_MSG_VERDICT, /* verdict from userspace to kernel */ From 89e1b30256a0b98b30c18d0a06f55a1262a8dd85 Mon Sep 17 00:00:00 2001 From: Rich Fought Date: Thu, 13 Dec 2012 15:56:04 -0800 Subject: [PATCH 359/432] Included defs.h so DISABLE_PTHREADS is visible. --- include/netlink-local.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/netlink-local.h b/include/netlink-local.h index b891d8c..c0915f8 100644 --- a/include/netlink-local.h +++ b/include/netlink-local.h @@ -33,6 +33,8 @@ #include #include +#include + #ifndef SOL_NETLINK #define SOL_NETLINK 270 #endif From 29b71371e764b04666d903bcbda452426aa1c634 Mon Sep 17 00:00:00 2001 From: roopa Date: Wed, 12 Dec 2012 21:50:49 -0800 Subject: [PATCH 360/432] route cache: Fix handling of ipv6 multipath routes There are two ways kernel handles ipv6 equal cost multipath routes depending on which kernel version you are looking at. older kernels without ipv6 ECMP support, accept the below ECMP routes, #ip -6 route add 2001::/16 nexthop via fe80:2::2 dev swp1 #ip -6 route add 2001::/16 nexthop via fe80:2::3 dev swp1 store them as separate routes and pick the last one during lookup. Newer kernels, after the support for equal cost multipath routes was added http://patchwork.ozlabs.org/patch/188562/, now accept multipath routes added individually using the above 'ip -6 route' format OR sent using RTA_MULTIPATH with the below command #ip -6 route add 2001::/16 nexthop via fe80:2::2 dev swp1 nexthop via fe80:2::3 dev swp1 And the kernel now stores and treats them as equal cost multipath routes during lookups. However in all cases above, netlink notifications to ipv6 ECMP route adds and deletes come separately for each next hop. Example libnl notification in the above case with both old and new kernels: inet6 2001::/16 table main type unicast scope global priority 0x400 protocol boot nexthop via fe80:2::2 dev swp1 inet6 2001::/16 table main type unicast scope global priority 0x400 protocol boot nexthop via fe80:2::3 dev swp1 Since they are separate route notifications for objects with same key, libnl replaces the existing ones and hence only the last route update sticks. This patch uses the oo_update feature to not replace but update an existing route if its a ipv6 equal cost multipath route. The object after an update looks like the below (similar to ipv4 ECMP routes): inet6 2001::/16 table main type unicast scope global priority 0x400 protocol boot nexthop via fe80:2::2 dev swp1 nexthop via fe80:2::3 dev swp1 Signed-off-by: Shrijeet Mukherjee Signed-off-by: Roopa Prabhu Reviewed-by: Nolan Leake Reviewed-by: Wilson Kok Signed-off-by: Thomas Graf --- lib/route/route_obj.c | 96 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/lib/route/route_obj.c b/lib/route/route_obj.c index cc29746..e092d80 100644 --- a/lib/route/route_obj.c +++ b/lib/route/route_obj.c @@ -441,6 +441,101 @@ nh_mismatch: #undef ROUTE_DIFF } +static int route_update(struct nl_object *old_obj, struct nl_object *new_obj) +{ + struct rtnl_route *new_route = (struct rtnl_route *) new_obj; + struct rtnl_route *old_route = (struct rtnl_route *) old_obj; + struct rtnl_nexthop *new_nh; + char buf[INET6_ADDRSTRLEN+5]; + int action = new_obj->ce_msgtype; + + /* + * ipv6 ECMP route notifications from the kernel come as + * separate notifications, one for every nexthop. This update + * function collapses such route msgs into a single + * route with multiple nexthops. The resulting object looks + * similar to a ipv4 ECMP route + */ + if (new_route->rt_family != AF_INET6 || + new_route->rt_table == RT_TABLE_LOCAL) + return -NLE_OPNOTSUPP; + + /* + * For routes that are already multipath, + * or dont have a nexthop dont do anything + */ + if (rtnl_route_get_nnexthops(new_route) != 1) + return -NLE_OPNOTSUPP; + + /* + * Get the only nexthop entry from the new route. For + * IPv6 we always get a route with a 0th NH + * filled or nothing at all + */ + new_nh = rtnl_route_nexthop_n(new_route, 0); + if (!new_nh || !rtnl_route_nh_get_gateway(new_nh)) + return -NLE_OPNOTSUPP; + + switch(action) { + case RTM_NEWROUTE : { + struct rtnl_nexthop *cloned_nh; + + /* + * Add the nexthop to old route + */ + cloned_nh = rtnl_route_nh_clone(new_nh); + if (!cloned_nh) + return -NLE_NOMEM; + rtnl_route_add_nexthop(old_route, cloned_nh); + + NL_DBG(2, "Route obj %p updated. Added " + "nexthop %p via %s\n", old_route, cloned_nh, + nl_addr2str(cloned_nh->rtnh_gateway, buf, + sizeof(buf))); + } + break; + case RTM_DELROUTE : { + struct rtnl_nexthop *old_nh; + + /* + * Only take care of nexthop deletes and not + * route deletes. So, if there is only one nexthop + * quite likely we did not update it. So dont do + * anything and return + */ + if (rtnl_route_get_nnexthops(old_route) <= 1) + return -NLE_OPNOTSUPP; + + /* + * Find the next hop in old route and delete it + */ + nl_list_for_each_entry(old_nh, &old_route->rt_nexthops, + rtnh_list) { + if (!rtnl_route_nh_compare(old_nh, new_nh, ~0, 0)) { + + rtnl_route_remove_nexthop(old_route, old_nh); + + NL_DBG(2, "Route obj %p updated. Removed " + "nexthop %p via %s\n", old_route, + old_nh, + nl_addr2str(old_nh->rtnh_gateway, buf, + sizeof(buf))); + + rtnl_route_nh_free(old_nh); + break; + } + } + } + break; + default: + NL_DBG(2, "Unknown action associated " + "to object %p during route update\n", new_obj); + return -NLE_OPNOTSUPP; + } + + return NLE_SUCCESS; +} + static const struct trans_tbl route_attrs[] = { __ADD(ROUTE_ATTR_FAMILY, family) __ADD(ROUTE_ATTR_TOS, tos) @@ -1201,6 +1296,7 @@ struct nl_object_ops route_obj_ops = { }, .oo_compare = route_compare, .oo_keygen = route_keygen, + .oo_update = route_update, .oo_attrs2str = route_attrs2str, .oo_id_attrs = (ROUTE_ATTR_FAMILY | ROUTE_ATTR_TOS | ROUTE_ATTR_TABLE | ROUTE_ATTR_DST), From 20a051237c014c593be37487a60fd1666d264f8f Mon Sep 17 00:00:00 2001 From: roopa Date: Wed, 12 Dec 2012 21:48:30 -0800 Subject: [PATCH 361/432] Bug Fix: cache_include: Fix object ref release after successful object update The current code does a rtnl_link_put on new object instead of old object. This patch fixes it. None of the caches have support for object update, so this should not have affected anyone yet. Signed-off-by: Roopa Prabhu --- lib/cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cache.c b/lib/cache.c index 8ba3d5b..36c45e1 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -736,7 +736,7 @@ static int cache_include(struct nl_cache *cache, struct nl_object *obj, */ if (nl_object_update(old, obj) == 0) { cb(cache, old, NL_ACT_CHANGE, data); - nl_object_put(obj); + nl_object_put(old); return 0; } From 91ab1bea5eb8737c19256c04306afa4d3364344e Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sun, 2 Dec 2012 19:16:49 +0100 Subject: [PATCH 362/432] make: automake provides a cscope target these days Signed-off-by: Thomas Graf --- Makefile.am | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Makefile.am b/Makefile.am index 6ec9aa2..bc4266d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -20,7 +20,3 @@ pkgsysconf_DATA = etc/pktloc etc/classid EXTRA_DIST = \ $(pkgsysconf_DATA) - -.PHONY: cscope -cscope: - cscope -b -q -R -Iinclude -slib -ssrc; From 96bb7c9a4cdd10a2665c0f56120943e79e33c560 Mon Sep 17 00:00:00 2001 From: roopa Date: Thu, 20 Dec 2012 18:32:00 -0800 Subject: [PATCH 363/432] cache pickup: Avoid duplicates during cache pickup This patch adds search and replace/update functionality to cache pickup_cb. This change is required to avoid duplicates getting into the cache during pickup. Also helps updating existing objects during cache pickup. We have seen this in cases of ipv6 equal cost multipath routes changes v1 to v2: - Updated documentation Signed-off-by: Roopa Prabhu --- lib/cache.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/lib/cache.c b/lib/cache.c index 36c45e1..883aa51 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -696,7 +696,21 @@ static int __cache_pickup(struct nl_sock *sk, struct nl_cache *cache, static int pickup_cb(struct nl_object *c, struct nl_parser_param *p) { - return nl_cache_add((struct nl_cache *) p->pp_arg, c); + struct nl_cache *cache = (struct nl_cache *)p->pp_arg; + struct nl_object *old; + + old = nl_cache_search(cache, c); + if (old) { + if (nl_object_update(old, c) == 0) { + nl_object_put(old); + return 0; + } + + nl_cache_remove(old); + nl_object_put(old); + } + + return nl_cache_add(cache, c); } /** @@ -705,7 +719,10 @@ static int pickup_cb(struct nl_object *c, struct nl_parser_param *p) * @arg cache Cache to put items into. * * Waits for netlink messages to arrive, parses them and puts them into - * the specified cache. + * the specified cache. If an old object with same key attributes is + * present in the cache, it is replaced with the new object. + * If the old object type supports an update operation, an update is + * attempted before a replace. * * @return 0 on success or a negative error code. */ @@ -889,7 +906,10 @@ errout: * @arg msg netlink message * * Parses a netlink message by calling the cache specific message parser - * and adds the new element to the cache. + * and adds the new element to the cache. If an old object with same key + * attributes is present in the cache, it is replaced with the new object. + * If the old object type supports an update operation, an update is + * attempted before a replace. * * @return 0 or a negative error code. */ From de213328f810afbf39380561855507c8b8c78e08 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 18 Dec 2012 14:56:26 +0100 Subject: [PATCH 364/432] cache: Take cache_ops lock when modifying cache ops flags Signed-off-by: Thomas Graf --- lib/cache_mngt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/cache_mngt.c b/lib/cache_mngt.c index fbb702f..62cde06 100644 --- a/lib/cache_mngt.c +++ b/lib/cache_mngt.c @@ -235,7 +235,9 @@ void nl_cache_ops_foreach(void (*cb)(struct nl_cache_ops *, void *), void *arg) */ void nl_cache_ops_set_flags(struct nl_cache_ops *ops, unsigned int flags) { + nl_write_lock(&cache_ops_lock); ops->co_flags |= flags; + nl_write_unlock(&cache_ops_lock); } /** From 69719322546f8550208a7ad984f704259c9091cb Mon Sep 17 00:00:00 2001 From: Thomas Jarosch Date: Thu, 27 Dec 2012 10:44:30 +0100 Subject: [PATCH 365/432] Fix file descriptor leak on error Detected by cppcheck Signed-off-by: Thomas Jarosch Signed-off-by: Thomas Graf --- lib/utils.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/utils.c b/lib/utils.c index b434bee..5511189 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -84,24 +84,32 @@ int __nl_read_num_str_file(const char *path, int (*cb)(long, const char *)) continue; num = strtol(buf, &end, 0); - if (end == buf) + if (end == buf) { + fclose(fd); return -NLE_INVAL; + } - if (num == LONG_MIN || num == LONG_MAX) + if (num == LONG_MIN || num == LONG_MAX) { + fclose(fd); return -NLE_RANGE; + } while (*end == ' ' || *end == '\t') end++; goodlen = strcspn(end, "#\r\n\t "); - if (goodlen == 0) + if (goodlen == 0) { + fclose(fd); return -NLE_INVAL; + } end[goodlen] = '\0'; err = cb(num, end); - if (err < 0) + if (err < 0) { + fclose(fd); return err; + } } fclose(fd); From 5d53626100f3b747109d4fc05a6d4107b09df642 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 3 Jan 2013 14:26:00 -0500 Subject: [PATCH 366/432] nlmsg_ok comparison between signed and unsigned The nlmsg_ok macro has a comparison between an int and a size_t (unsigned int). The C spec says the int is cast to unsigned int before the comparison. This is a problem as the audit system will send skb's with skb->len == nlhhdr->nlmsg_len which are NOT aligned. Thus you can end up with remaining being negative. So the comparison becomes (unsigned int)(-1) >= (unsigned int)16 Which turns out to be true! It should clearly be false. So if we cast the size_t to an int we get a signed comparison and it works. (This is what linux/netlink.h and all of the kernel netlink headers do) Signed-off-by: Eric Paris Signed-off-by: Thomas Graf --- lib/msg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msg.c b/lib/msg.c index 23c137d..2613c78 100644 --- a/lib/msg.c +++ b/lib/msg.c @@ -178,7 +178,7 @@ int nlmsg_valid_hdr(const struct nlmsghdr *nlh, int hdrlen) */ int nlmsg_ok(const struct nlmsghdr *nlh, int remaining) { - return (remaining >= sizeof(struct nlmsghdr) && + return (remaining >= (int)sizeof(struct nlmsghdr) && nlh->nlmsg_len >= sizeof(struct nlmsghdr) && nlh->nlmsg_len <= remaining); } From 6369e1fdd9a029cdf7ad02adcce5e9fb6fd59901 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 4 Jan 2013 16:44:52 +0100 Subject: [PATCH 367/432] 3.2.17 release --- configure.ac | 8 ++++---- doc/configure.ac | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index a2c231e..9f62d05 100644 --- a/configure.ac +++ b/configure.ac @@ -13,7 +13,7 @@ # copied from glib m4_define([libnl_major_version], [3]) m4_define([libnl_minor_version], [2]) -m4_define([libnl_micro_version], [16]) +m4_define([libnl_micro_version], [17]) # If either revision or age are omitted, they default to 0. Also note that age @@ -34,9 +34,9 @@ m4_define([libnl_micro_version], [16]) # 6. If any interfaces have been removed since the last public release, then # set age to 0. -m4_define([libnl_lt_current], [212]) -m4_define([libnl_lt_revision], [1]) -m4_define([libnl_lt_age], [12]) +m4_define([libnl_lt_current], [213]) +m4_define([libnl_lt_revision], [0]) +m4_define([libnl_lt_age], [13]) m4_define([libnl_version], [libnl_major_version.libnl_minor_version.libnl_micro_version]) diff --git a/doc/configure.ac b/doc/configure.ac index 63a7d04..d4e8e99 100644 --- a/doc/configure.ac +++ b/doc/configure.ac @@ -9,7 +9,7 @@ # Copyright (c) 2003-2012 Thomas Graf # -AC_INIT(libnl-doc, [3.2.16], [http://www.infradead.org/~tgr/libnl/]) +AC_INIT(libnl-doc, [3.2.17], [http://www.infradead.org/~tgr/libnl/]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_AUX_DIR([build-aux]) AM_INIT_AUTOMAKE([foreign]) From 00a5879e6e0b6b8f65730d77570780126c96c96a Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 4 Jan 2013 17:44:43 +0100 Subject: [PATCH 368/432] Add to dist target Signed-off-by: Thomas Graf --- include/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/include/Makefile.am b/include/Makefile.am index 54fd71f..e0f41fc 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -45,6 +45,7 @@ nobase_libnlinclude_HEADERS = \ netlink/route/cls/u32.h \ netlink/route/link/api.h \ netlink/route/link/bonding.h \ + netlink/route/link/can.h \ netlink/route/link/info-api.h \ netlink/route/link/inet.h \ netlink/route/link/vlan.h \ From ba38f3919835c39d7bc1e939ef3ca89cfe31600d Mon Sep 17 00:00:00 2001 From: "mihai.dontu@gmail.com" Date: Sun, 6 Jan 2013 07:07:02 +0200 Subject: [PATCH 369/432] cache: make sure the user has specified a callback In cache_include(), the user callback is used even though one might not have been specified, leading to a crash. This happens, for example, when NetworkManager calls nl_cache_include() with the change_cb argument set to NULL. Fix it by making sure the callback points to a valid address. Signed-off-by: Mihai Dontu Signed-off-by: Thomas Graf --- lib/cache.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/cache.c b/lib/cache.c index 883aa51..42c0b5e 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -752,7 +752,8 @@ static int cache_include(struct nl_cache *cache, struct nl_object *obj, * Handle them first. */ if (nl_object_update(old, obj) == 0) { - cb(cache, old, NL_ACT_CHANGE, data); + if (cb) + cb(cache, old, NL_ACT_CHANGE, data); nl_object_put(old); return 0; } From de5744fb65f4e10ccce1baf5a275b433e32b0893 Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Mon, 7 Jan 2013 17:10:00 -0200 Subject: [PATCH 370/432] build: Fix distribution to include 'nfnetlink_conntrack.h' The header has not been included in the headers list so it has been been distributed in the tarball making it fail to build in old kernels. Signed-off-by: Otavio Salvador Signed-off-by: Thomas Graf --- include/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/Makefile.am b/include/Makefile.am index e0f41fc..9ea97b8 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -109,8 +109,9 @@ noinst_HEADERS = \ linux/ipv6.h \ linux/neighbour.h \ linux/netfilter.h \ - linux/netfilter/nfnetlink_conntrack.h \ + linux/netfilter/nf_conntrack_common.h \ linux/netfilter/nfnetlink.h \ + linux/netfilter/nfnetlink_conntrack.h \ linux/netfilter/nfnetlink_log.h \ linux/netfilter/nfnetlink_queue.h \ linux/netlink.h \ From 383ff943b4a4b3c56a49b2cf323271d9897636d0 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 8 Jan 2013 14:44:47 +0100 Subject: [PATCH 371/432] fix include/Makefile.am Signed-off-by: Thomas Graf --- include/Makefile.am | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/Makefile.am b/include/Makefile.am index 9ea97b8..5284739 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -10,13 +10,13 @@ nobase_libnlinclude_HEADERS = \ netlink/genl/genl.h \ netlink/genl/mngt.h \ netlink/netfilter/ct.h \ + netlink/netfilter/exp.h \ netlink/netfilter/log.h \ netlink/netfilter/log_msg.h \ netlink/netfilter/netfilter.h \ netlink/netfilter/nfnl.h \ netlink/netfilter/queue.h \ netlink/netfilter/queue_msg.h \ - netlink/netfilter/exp.h \ netlink/addr.h \ netlink/attr.h \ netlink/cache-api.h \ @@ -110,8 +110,9 @@ noinst_HEADERS = \ linux/neighbour.h \ linux/netfilter.h \ linux/netfilter/nf_conntrack_common.h \ - linux/netfilter/nfnetlink.h \ + linux/netfilter/nfnetlink_compat.h \ linux/netfilter/nfnetlink_conntrack.h \ + linux/netfilter/nfnetlink.h \ linux/netfilter/nfnetlink_log.h \ linux/netfilter/nfnetlink_queue.h \ linux/netlink.h \ From f12379543415e10e3d546b6e1ba70e88ff431710 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 8 Jan 2013 14:47:03 +0100 Subject: [PATCH 372/432] 3.2.18 release --- configure.ac | 6 +++--- doc/configure.ac | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 9f62d05..5e57e43 100644 --- a/configure.ac +++ b/configure.ac @@ -13,7 +13,7 @@ # copied from glib m4_define([libnl_major_version], [3]) m4_define([libnl_minor_version], [2]) -m4_define([libnl_micro_version], [17]) +m4_define([libnl_micro_version], [18]) # If either revision or age are omitted, they default to 0. Also note that age @@ -34,8 +34,8 @@ m4_define([libnl_micro_version], [17]) # 6. If any interfaces have been removed since the last public release, then # set age to 0. -m4_define([libnl_lt_current], [213]) -m4_define([libnl_lt_revision], [0]) +m4_define([libnl_lt_current], [214]) +m4_define([libnl_lt_revision], [1]) m4_define([libnl_lt_age], [13]) m4_define([libnl_version], diff --git a/doc/configure.ac b/doc/configure.ac index d4e8e99..fb7ba6d 100644 --- a/doc/configure.ac +++ b/doc/configure.ac @@ -9,7 +9,7 @@ # Copyright (c) 2003-2012 Thomas Graf # -AC_INIT(libnl-doc, [3.2.17], [http://www.infradead.org/~tgr/libnl/]) +AC_INIT(libnl-doc, [3.2.18], [http://www.infradead.org/~tgr/libnl/]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_AUX_DIR([build-aux]) AM_INIT_AUTOMAKE([foreign]) From 3540e44b158f0f45fc2364d99e70433fba176b21 Mon Sep 17 00:00:00 2001 From: Flavio Leitner Date: Mon, 7 Jan 2013 18:36:12 -0200 Subject: [PATCH 373/432] link: add carrier support Signed-off-by: Flavio Leitner Signed-off-by: Thomas Graf --- include/linux/if.h | 6 ++++ include/linux/if_link.h | 1 + include/netlink-types.h | 1 + include/netlink/route/link.h | 7 +++++ lib/route/link.c | 59 +++++++++++++++++++++++++++++++++++- 5 files changed, 73 insertions(+), 1 deletion(-) diff --git a/include/linux/if.h b/include/linux/if.h index 32f910f..238cf43 100644 --- a/include/linux/if.h +++ b/include/linux/if.h @@ -117,6 +117,12 @@ enum { IF_LINK_MODE_DORMANT, /* limit upward transition to dormant */ }; +/* carrier state */ +enum { + IF_CARRIER_DOWN, + IF_CARRIER_UP +}; + /* * Device mapping structure. I'd just gone off and designed a * beautiful scheme using only loadable modules with arguments diff --git a/include/linux/if_link.h b/include/linux/if_link.h index c0a1dd9..a753d11 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h @@ -142,6 +142,7 @@ enum { #define IFLA_PROMISCUITY IFLA_PROMISCUITY IFLA_NUM_TX_QUEUES, IFLA_NUM_RX_QUEUES, + IFLA_CARRIER, __IFLA_MAX }; diff --git a/include/netlink-types.h b/include/netlink-types.h index 057ea2b..46856a3 100644 --- a/include/netlink-types.h +++ b/include/netlink-types.h @@ -182,6 +182,7 @@ struct rtnl_link uint32_t l_num_tx_queues; uint32_t l_num_rx_queues; uint32_t l_group; + uint8_t l_carrier; }; struct rtnl_ncacheinfo diff --git a/include/netlink/route/link.h b/include/netlink/route/link.h index 8268b13..dbde72f 100644 --- a/include/netlink/route/link.h +++ b/include/netlink/route/link.h @@ -141,6 +141,10 @@ extern int rtnl_link_str2operstate(const char *); extern char * rtnl_link_mode2str(uint8_t, char *, size_t); extern int rtnl_link_str2mode(const char *); +/* Carrier State Translations */ +extern char * rtnl_link_carrier2str(uint8_t, char *, size_t); +extern int rtnl_link_str2carrier(const char *); + /* Access Functions */ extern void rtnl_link_set_qdisc(struct rtnl_link *, const char *); extern char * rtnl_link_get_qdisc(struct rtnl_link *); @@ -182,6 +186,9 @@ extern int rtnl_link_get_link(struct rtnl_link *); extern void rtnl_link_set_master(struct rtnl_link *, int); extern int rtnl_link_get_master(struct rtnl_link *); +extern void rtnl_link_set_carrier(struct rtnl_link *, uint8_t); +extern uint8_t rtnl_link_get_carrier(struct rtnl_link *); + extern void rtnl_link_set_operstate(struct rtnl_link *, uint8_t); extern uint8_t rtnl_link_get_operstate(struct rtnl_link *); diff --git a/lib/route/link.c b/lib/route/link.c index 1cecd54..377135e 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -54,6 +54,7 @@ #define LINK_ATTR_NUM_TX_QUEUES (1 << 22) #define LINK_ATTR_NUM_RX_QUEUES (1 << 23) #define LINK_ATTR_GROUP (1 << 24) +#define LINK_ATTR_CARRIER (1 << 25) static struct nl_cache_ops rtnl_link_ops; static struct nl_object_ops link_obj_ops; @@ -263,6 +264,7 @@ static struct nla_policy link_policy[IFLA_MAX+1] = { [IFLA_NUM_TX_QUEUES] = { .type = NLA_U32 }, [IFLA_NUM_RX_QUEUES] = { .type = NLA_U32 }, [IFLA_GROUP] = { .type = NLA_U32 }, + [IFLA_CARRIER] = { .type = NLA_U8 }, }; static struct nla_policy link_info_policy[IFLA_INFO_MAX+1] = { @@ -456,6 +458,11 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, link->ce_mask |= LINK_ATTR_MASTER; } + if (tb[IFLA_CARRIER]) { + link->l_carrier = nla_get_u8(tb[IFLA_CARRIER]); + link->ce_mask |= LINK_ATTR_CARRIER; + } + if (tb[IFLA_OPERSTATE]) { link->l_operstate = nla_get_u8(tb[IFLA_OPERSTATE]); link->ce_mask |= LINK_ATTR_OPERSTATE; @@ -667,9 +674,14 @@ static void link_dump_details(struct nl_object *obj, struct nl_dump_params *p) if (link->ce_mask & LINK_ATTR_NUM_VF) nl_dump(p, "num-vf %u ", link->l_num_vf); - nl_dump(p, "mode %s\n", + nl_dump(p, "mode %s ", rtnl_link_mode2str(link->l_linkmode, buf, sizeof(buf))); + nl_dump(p, "carrier %s", + rtnl_link_carrier2str(link->l_carrier, buf, sizeof(buf))); + + nl_dump(p, "\n"); + if (link->l_info_ops && link->l_info_ops->io_dump[NL_DUMP_DETAILS]) link->l_info_ops->io_dump[NL_DUMP_DETAILS](link, p); @@ -875,6 +887,7 @@ static const struct trans_tbl link_attrs[] = { __ADD(LINK_ATTR_NUM_TX_QUEUES, num_tx_queues) __ADD(LINK_ATTR_NUM_RX_QUEUES, num_rx_queues) __ADD(LINK_ATTR_GROUP, group) + __ADD(LINK_ATTR_CARRIER, carrier) }; static char *link_attrs2str(int attrs, char *buf, size_t len) @@ -1176,6 +1189,9 @@ static int build_link_msg(int cmd, struct ifinfomsg *hdr, if (link->ce_mask & LINK_ATTR_OPERSTATE) NLA_PUT_U8(msg, IFLA_OPERSTATE, link->l_operstate); + if (link->ce_mask & LINK_ATTR_CARRIER) + NLA_PUT_U8(msg, IFLA_CARRIER, link->l_carrier); + if (link->ce_mask & LINK_ATTR_LINKMODE) NLA_PUT_U8(msg, IFLA_LINKMODE, link->l_linkmode); @@ -1865,6 +1881,31 @@ int rtnl_link_get_master(struct rtnl_link *link) return link->l_master; } +/** + * Set carrier of link object + * @arg link Link object + * @arg status New carrier status + * + * @see rtnl_link_get_carrier() + */ +void rtnl_link_set_carrier(struct rtnl_link *link, uint8_t status) +{ + link->l_carrier = status; + link->ce_mask |= LINK_ATTR_CARRIER; +} + +/** + * Return carrier status of link object + * @arg link Link object + * + * @see rtnl_link_set_master() + * @return Carrier state. + */ +uint8_t rtnl_link_get_carrier(struct rtnl_link *link) +{ + return link->l_carrier; +} + /** * Set operational status of link object * @arg link Link object @@ -2450,6 +2491,11 @@ static const struct trans_tbl link_modes[] = { __ADD(IF_LINK_MODE_DORMANT, dormant) }; +static const struct trans_tbl carrier_states[] = { + __ADD(IF_CARRIER_DOWN, down) + __ADD(IF_CARRIER_UP, up) +}; + char *rtnl_link_mode2str(uint8_t st, char *buf, size_t len) { return __type2str(st, buf, len, link_modes, ARRAY_SIZE(link_modes)); @@ -2460,6 +2506,17 @@ int rtnl_link_str2mode(const char *name) return __str2type(name, link_modes, ARRAY_SIZE(link_modes)); } +char *rtnl_link_carrier2str(uint8_t st, char *buf, size_t len) +{ + return __type2str(st, buf, len, carrier_states, + ARRAY_SIZE(carrier_states)); +} + +int rtnl_link_str2carrier(const char *name) +{ + return __str2type(name, carrier_states, ARRAY_SIZE(carrier_states)); +} + /** @} */ /** From b1ebda92410c57c09c7aff3e4d5ce3572d9fc1c1 Mon Sep 17 00:00:00 2001 From: roopa Date: Tue, 8 Jan 2013 04:33:29 -0800 Subject: [PATCH 374/432] cache: Add new nl_cache_find api This patch adds new cache find api nl_cache_find api was suggested by Thomas. Unlike nl_cache_search, this patch uses nl_object_match_filter() to look for an object match. Am not sure this matches what was decided on the list few weeks back. I will be happy to make any changes. Signed-off-by: Roopa Prabhu Signed-off-by: Thomas Graf --- include/netlink/object.h | 1 + lib/cache.c | 39 +++++++++++++++++++++++++++++++++++++++ lib/object.c | 22 ++++++++++++++++++++++ 3 files changed, 62 insertions(+) diff --git a/include/netlink/object.h b/include/netlink/object.h index f25713e..a95feda 100644 --- a/include/netlink/object.h +++ b/include/netlink/object.h @@ -64,6 +64,7 @@ extern struct nl_cache * nl_object_get_cache(struct nl_object *); extern const char * nl_object_get_type(const struct nl_object *); extern int nl_object_get_msgtype(const struct nl_object *); struct nl_object_ops * nl_object_get_ops(const struct nl_object *); +uint32_t nl_object_get_id_attrs(struct nl_object *obj); static inline void * nl_object_priv(struct nl_object *obj) diff --git a/lib/cache.c b/lib/cache.c index 42c0b5e..24ffa31 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -1022,6 +1022,45 @@ struct nl_object *nl_cache_search(struct nl_cache *cache, return NULL; } +/** + * Find object in cache + * @arg cache Cache + * @arg filter object acting as a filter + * + * Searches the cache for an object which matches the object filter. + * If the filter attributes matches the object type id attributes, + * and the cache supports hash lookups, a faster hashtable lookup + * is used to return the object. Else, function nl_object_match_filter() is + * used to determine if the objects match. If a matching object is + * found, the reference counter is incremented and the object is returned. + * + * Therefore, if an object is returned, the reference to the object + * must be returned by calling nl_object_put() after usage. + * + * @return Reference to object or NULL if not found. + */ +struct nl_object *nl_cache_find(struct nl_cache *cache, + struct nl_object *filter) +{ + struct nl_object *obj; + + if (cache->c_ops == NULL) + BUG(); + + if ((nl_object_get_id_attrs(filter) == filter->ce_mask) + && cache->hashtable) + return __cache_fast_lookup(cache, filter); + + nl_list_for_each_entry(obj, &cache->c_items, ce_list) { + if (nl_object_match_filter(obj, filter)) { + nl_object_get(obj); + return obj; + } + } + + return NULL; +} + /** * Mark all objects of a cache * @arg cache Cache diff --git a/lib/object.c b/lib/object.c index 806bae6..7361194 100644 --- a/lib/object.c +++ b/lib/object.c @@ -506,6 +506,28 @@ struct nl_object_ops *nl_object_get_ops(const struct nl_object *obj) return obj->ce_ops; } +/** + * Return object id attribute mask + * @arg obj object + * + * @return object id attribute mask + */ +uint32_t nl_object_get_id_attrs(struct nl_object *obj) +{ + struct nl_object_ops *ops = obj_ops(obj); + uint32_t id_attrs; + + if (!ops) + return 0; + + if (ops->oo_id_attrs_get) + id_attrs = ops->oo_id_attrs_get(obj); + else + id_attrs = ops->oo_id_attrs; + + return id_attrs; +} + /** @} */ /** @} */ From 09213ee5ee9a7cd7a083ee6360efec006fc9adcc Mon Sep 17 00:00:00 2001 From: roopa Date: Tue, 8 Jan 2013 05:29:08 -0800 Subject: [PATCH 375/432] link af ops: Add new ao_compare op to compare link af_data This patch adds new operation to compare link af_data. ao_compare is similar to object oo_compare operation. This op can be used when two links are compared for their af data. It takes two link objects in question, an object specific bitmask defining which attributes should be compared and flags to control the behaviour. The function must return a bitmask with the relevant bit set for each attribute that mismatches. Signed-off-by: Roopa Prabhu Signed-off-by: Thomas Graf --- include/netlink/route/link/api.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/netlink/route/link/api.h b/include/netlink/route/link/api.h index e6dad27..92a48f7 100644 --- a/include/netlink/route/link/api.h +++ b/include/netlink/route/link/api.h @@ -119,6 +119,19 @@ struct rtnl_link_af_ops void (*ao_dump[NL_DUMP_MAX+1])(struct rtnl_link *, struct nl_dump_params *, void *); + + /** Comparison function + * + * Will be called when two links are compared for their af data. It + * takes two link objects in question, an object specific bitmask + * defining which attributes should be compared and flags to control + * the behaviour + * + * The function must return a bitmask with the relevant bit set for + * each attribute that mismatches + */ + int (*ao_compare)(struct rtnl_link *, + struct rtnl_link *, int, uint32_t, int); }; extern struct rtnl_link_af_ops *rtnl_link_af_ops_lookup(unsigned int); From 310ec86b391ca94509db57e8bdbafee2ff6d39e7 Mon Sep 17 00:00:00 2001 From: roopa Date: Tue, 8 Jan 2013 05:29:10 -0800 Subject: [PATCH 376/432] Add ao_compare support to bridge family af_data This patch adds support for ao_compare operation to bridge link af data operations. Adds field ce_mask to struct bridge_data to work with the ATTR attributes. I can submit separate patches to introduce mask field to ATTR macros. Signed-off-by: Roopa Prabhu Signed-off-by: Wilson Kok Signed-off-by: Thomas Graf --- lib/route/link/bridge.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/route/link/bridge.c b/lib/route/link/bridge.c index 32fd38f..cd9f462 100644 --- a/lib/route/link/bridge.c +++ b/lib/route/link/bridge.c @@ -15,9 +15,12 @@ #include #include +#define BRIDGE_ATTR_PORT_STATE 0x0001 + struct bridge_data { uint8_t b_port_state; + uint32_t ce_mask; /* HACK to support attr macros */ }; static void *bridge_alloc(struct rtnl_link *link) @@ -46,6 +49,7 @@ static int bridge_parse_protinfo(struct rtnl_link *link, struct nlattr *attr, struct bridge_data *bd = data; bd->b_port_state = nla_get_u8(attr); + bd->ce_mask |= BRIDGE_ATTR_PORT_STATE; return 0; } @@ -55,7 +59,22 @@ static void bridge_dump_details(struct rtnl_link *link, { struct bridge_data *bd = data; - nl_dump(p, "port-state %u ", bd->b_port_state); + if (bd->ce_mask & BRIDGE_ATTR_PORT_STATE) + nl_dump(p, "port-state %u ", bd->b_port_state); +} + +static int bridge_compare(struct rtnl_link *_a, struct rtnl_link *_b, + int family, uint32_t attrs, int flags) +{ + struct bridge_data *a = (struct bridge_data *)_a->l_af_data; + struct bridge_data *b = (struct bridge_data *)_b->l_af_data; + int diff = 0; + +#define BRIDGE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, BRIDGE_ATTR_##ATTR, a, b, EXPR) + diff |= BRIDGE_DIFF(PORT_STATE, a->b_port_state != b->b_port_state); + + return diff; +#undef BRIDGE_DIFF } static const struct nla_policy protinfo_policy = { @@ -70,6 +89,7 @@ static struct rtnl_link_af_ops bridge_ops = { .ao_parse_protinfo = &bridge_parse_protinfo, .ao_dump[NL_DUMP_DETAILS] = &bridge_dump_details, .ao_protinfo_policy = &protinfo_policy, + .ao_compare = &bridge_compare, }; static void __init bridge_init(void) From 6b4a2cb634701b72eba6c50220611d0787ec4601 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 17 Jan 2013 14:02:35 +0100 Subject: [PATCH 377/432] 3.2.19 release --- configure.ac | 8 ++++---- doc/configure.ac | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index 5e57e43..148cf5d 100644 --- a/configure.ac +++ b/configure.ac @@ -13,7 +13,7 @@ # copied from glib m4_define([libnl_major_version], [3]) m4_define([libnl_minor_version], [2]) -m4_define([libnl_micro_version], [18]) +m4_define([libnl_micro_version], [19]) # If either revision or age are omitted, they default to 0. Also note that age @@ -34,9 +34,9 @@ m4_define([libnl_micro_version], [18]) # 6. If any interfaces have been removed since the last public release, then # set age to 0. -m4_define([libnl_lt_current], [214]) -m4_define([libnl_lt_revision], [1]) -m4_define([libnl_lt_age], [13]) +m4_define([libnl_lt_current], [215]) +m4_define([libnl_lt_revision], [0]) +m4_define([libnl_lt_age], [14]) m4_define([libnl_version], [libnl_major_version.libnl_minor_version.libnl_micro_version]) diff --git a/doc/configure.ac b/doc/configure.ac index fb7ba6d..6a0be3c 100644 --- a/doc/configure.ac +++ b/doc/configure.ac @@ -9,7 +9,7 @@ # Copyright (c) 2003-2012 Thomas Graf # -AC_INIT(libnl-doc, [3.2.18], [http://www.infradead.org/~tgr/libnl/]) +AC_INIT(libnl-doc, [3.2.19], [http://www.infradead.org/~tgr/libnl/]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_AUX_DIR([build-aux]) AM_INIT_AUTOMAKE([foreign]) From 99399ca9c07499cfeadf4a24a9b66006d3b48b40 Mon Sep 17 00:00:00 2001 From: roopa Date: Thu, 17 Jan 2013 16:29:03 -0800 Subject: [PATCH 378/432] Add new rtnl_link_af_data_compare function to compare af_data This patch adds a new api rtnl_linl_af_data_compare to compare link af_data Signed-off-by: Roopa Prabhu Signed-off-by: Thomas Graf --- include/netlink/route/link/api.h | 3 +++ lib/route/link/api.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/include/netlink/route/link/api.h b/include/netlink/route/link/api.h index 92a48f7..28f2464 100644 --- a/include/netlink/route/link/api.h +++ b/include/netlink/route/link/api.h @@ -142,6 +142,9 @@ extern void * rtnl_link_af_data(const struct rtnl_link *, const struct rtnl_link_af_ops *); extern int rtnl_link_af_register(struct rtnl_link_af_ops *); extern int rtnl_link_af_unregister(struct rtnl_link_af_ops *); +extern int rtnl_link_af_data_compare(struct rtnl_link *a, + struct rtnl_link *b, + int family); #ifdef __cplusplus } diff --git a/lib/route/link/api.c b/lib/route/link/api.c index a12eb09..9387bc5 100644 --- a/lib/route/link/api.c +++ b/lib/route/link/api.c @@ -350,6 +350,38 @@ errout: return err; } +/** + * Compare af data for a link address family + * @arg a Link object a + * @arg b Link object b + * @arg family af data family + * + * This function will compare af_data between two links + * a and b of family given by arg family + * + * @return 0 if address family specific data matches or is not present + * or != 0 if it mismatches. + */ +int rtnl_link_af_data_compare(struct rtnl_link *a, struct rtnl_link *b, + int family) +{ + struct rtnl_link_af_ops *af_ops = rtnl_link_af_ops_lookup(family); + + if (!af_ops) + return ~0; + + if (!a->l_af_data[family] && !b->l_af_data[family]) + return 0; + + if (!a->l_af_data[family] || !b->l_af_data[family]) + return ~0; + + if (af_ops->ao_compare) + return af_ops->ao_compare(a, b, family, ~0, 0); + + return 0; +} + /** @} */ /** @} */ From 5c3f2f015a6ee4cd9cd461a9c2e3054e4a8698ff Mon Sep 17 00:00:00 2001 From: roopa Date: Thu, 17 Jan 2013 16:29:04 -0800 Subject: [PATCH 379/432] link: Add af data compare to link objects Today the link compare function does not compare af data of a link. We have found a need for this to get approriate change callbacks when af_data of a link changes. This patch adds support to compare af_data to link_compare function. This patch today only adds support to compare af_data set by PROTINFO attributes. It can be extended to support compares of af_data set by AF_SPEC attributes It has been tested for AF_BRIDGE objects. In case of AF_BRIDGE objects, this helps with bridge port change notification callbacks. Signed-off-by: Wilson Kok Signed-off-by: Roopa Prabhu Signed-off-by: Thomas Graf --- lib/route/link.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/route/link.c b/lib/route/link.c index 377135e..f817b3a 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -55,6 +55,8 @@ #define LINK_ATTR_NUM_RX_QUEUES (1 << 23) #define LINK_ATTR_GROUP (1 << 24) #define LINK_ATTR_CARRIER (1 << 25) +#define LINK_ATTR_PROTINFO (1 << 26) +#define LINK_ATTR_AF_SPEC (1 << 27) static struct nl_cache_ops rtnl_link_ops; static struct nl_object_ops link_obj_ops; @@ -522,6 +524,7 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, } } } + link->ce_mask |= LINK_ATTR_LINKINFO; } if (tb[IFLA_PROTINFO] && af_ops && af_ops->ao_parse_protinfo) { @@ -529,6 +532,7 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, link->l_af_data[link->l_family]); if (err < 0) goto errout; + link->ce_mask |= LINK_ATTR_PROTINFO; } if (tb[IFLA_AF_SPEC]) { @@ -549,6 +553,7 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, } } + link->ce_mask |= LINK_ATTR_AF_SPEC; } if (tb[IFLA_PROMISCUITY]) { @@ -851,15 +856,28 @@ static int link_compare(struct nl_object *_a, struct nl_object *_b, diff |= LINK_DIFF(NUM_RX_QUEUES,a->l_num_rx_queues != b->l_num_rx_queues); diff |= LINK_DIFF(GROUP, a->l_group != b->l_group); + /* + * Compare LINK_ATTR_PROTINFO af_data + */ + if (a->l_family == b->l_family) { + if (rtnl_link_af_data_compare(a, b, a->l_family) != 0) + goto protinfo_mismatch; + } + if (flags & LOOSE_COMPARISON) diff |= LINK_DIFF(FLAGS, (a->l_flags ^ b->l_flags) & b->l_flag_mask); else diff |= LINK_DIFF(FLAGS, a->l_flags != b->l_flags); -#undef LINK_DIFF - +out: return diff; + +protinfo_mismatch: + diff |= LINK_DIFF(PROTINFO, 1); + goto out; + +#undef LINK_DIFF } static const struct trans_tbl link_attrs[] = { From 5291af6fb502e1bde7545a6eef261cdf40246110 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 18 Jan 2013 14:49:08 +0100 Subject: [PATCH 380/432] link: fix reference leak in rtnl_link_af_data_compare() Signed-off-by: Thomas Graf --- lib/route/link/api.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/route/link/api.c b/lib/route/link/api.c index 9387bc5..392ded3 100644 --- a/lib/route/link/api.c +++ b/lib/route/link/api.c @@ -366,20 +366,25 @@ int rtnl_link_af_data_compare(struct rtnl_link *a, struct rtnl_link *b, int family) { struct rtnl_link_af_ops *af_ops = rtnl_link_af_ops_lookup(family); + int ret = 0; if (!af_ops) return ~0; if (!a->l_af_data[family] && !b->l_af_data[family]) - return 0; + goto out; - if (!a->l_af_data[family] || !b->l_af_data[family]) - return ~0; + if (!a->l_af_data[family] || !b->l_af_data[family]) { + ret = ~0; + goto out; + } if (af_ops->ao_compare) - return af_ops->ao_compare(a, b, family, ~0, 0); + ret = af_ops->ao_compare(a, b, family, ~0, 0); +out: + rtnl_link_af_ops_put(af_ops); - return 0; + return ret; } /** @} */ From 7559157f2d21a7fe52853c76eb4dd7fa8d0ffd7c Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 22 Jan 2013 19:07:09 +0100 Subject: [PATCH 381/432] Undo soname bump The soname was bumped before 3.2.18 was released to reflect an ABI change in the cache and object API. This caused a discussion with various distribution maintainers involved as it prevented them from including the release in their stable branches. This is especially unfortunate as the corresponding API is unused outside of libnl as of now. For this reason, I have decided to undo the soname bump and instead remove the corresponding header files from the list of installable headers and thus remove them from the public API. This is a API break technically but since nobody is using them it should not matter. If you are in fact using any of the *-api.h headers please let me know and we are most likely to start a new development branch. If your application linked against 3.2.18 or 3.2.19 you will need to relink if you want it to use >= 3.2.20. Signed-off-by: Thomas Graf --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 148cf5d..08b61a4 100644 --- a/configure.ac +++ b/configure.ac @@ -34,9 +34,9 @@ m4_define([libnl_micro_version], [19]) # 6. If any interfaces have been removed since the last public release, then # set age to 0. -m4_define([libnl_lt_current], [215]) +m4_define([libnl_lt_current], [216]) m4_define([libnl_lt_revision], [0]) -m4_define([libnl_lt_age], [14]) +m4_define([libnl_lt_age], [16]) m4_define([libnl_version], [libnl_major_version.libnl_minor_version.libnl_micro_version]) From f20bbe1f07fcff1509425884f5ed72ca8d5fb6ab Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 22 Jan 2013 19:10:38 +0100 Subject: [PATCH 382/432] No longer install module API headers Various header files providing an API to implement own cache and object types or implement link types have been available in the past. Their API is marked unstable in the documentation and nobody is using them so far. Technically they have been causing ABI breakages in at least two 3.2.x releases. In order to avoid future accidental breakage, no longer install these and require module developers to clone the git tree and build modules off the git tree directly to make sure that the API is unstable at this point. Signed-off-by: Thomas Graf --- include/Makefile.am | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/Makefile.am b/include/Makefile.am index 5284739..50d1e4e 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -19,7 +19,6 @@ nobase_libnlinclude_HEADERS = \ netlink/netfilter/queue_msg.h \ netlink/addr.h \ netlink/attr.h \ - netlink/cache-api.h \ netlink/cache.h \ netlink/data.h \ netlink/errno.h \ @@ -31,7 +30,6 @@ nobase_libnlinclude_HEADERS = \ netlink/netlink-compat.h \ netlink/netlink-kernel.h \ netlink/netlink.h \ - netlink/object-api.h \ netlink/object.h \ netlink/route/cls/ematch/cmp.h \ netlink/route/cls/ematch/meta.h \ @@ -43,10 +41,8 @@ nobase_libnlinclude_HEADERS = \ netlink/route/cls/fw.h \ netlink/route/cls/police.h \ netlink/route/cls/u32.h \ - netlink/route/link/api.h \ netlink/route/link/bonding.h \ netlink/route/link/can.h \ - netlink/route/link/info-api.h \ netlink/route/link/inet.h \ netlink/route/link/vlan.h \ netlink/route/qdisc/cbq.h \ @@ -72,7 +68,6 @@ nobase_libnlinclude_HEADERS = \ netlink/route/rtnl.h \ netlink/route/rule.h \ netlink/route/tc.h \ - netlink/route/tc-api.h \ netlink/socket.h \ netlink/types.h \ netlink/utils.h \ @@ -124,4 +119,9 @@ noinst_HEADERS = \ netlink-generic.h \ netlink-local.h \ netlink-tc.h \ - netlink-types.h + netlink-types.h \ + netlink/cache-api.h \ + netlink/object-api.h \ + netlink/route/link/api.h \ + netlink/route/link/info-api.h \ + netlink/route/tc-api.h From 2b96c3381d1048d36e58d312b186f439d74c895d Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 22 Jan 2013 19:15:34 +0100 Subject: [PATCH 383/432] Remove obsolete release notes at end of configure Signed-off-by: Thomas Graf --- configure.ac | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 08b61a4..2c31552 100644 --- a/configure.ac +++ b/configure.ac @@ -149,10 +149,7 @@ echo " - The library basename was renamed to libnl-${MAJ_VERSION}, i.e. the S echo " libnl-${MAJ_VERSION}.so., libnl-route-${MAJ_VERSION}.so, etc." echo "" echo " - libtool versioning was assumed, to ease detection of compatible library" -echo " versions. libnl-${MAJ_VERSION}.so.CURRENT.REVISION.AGE where." -echo " CURRENT := 100 * \$MINOR_VERSION + \$MICRO_VERSION" -echo " REVISION := nth revision if API was unchanged" -echo " AGE := nth revision that is backwards compatible." +echo " versions." echo "" echo " If you are using pkg-config for detecting and linking against the library " echo " things will continue magically as if nothing every happened. If you are " From 1481f97d3663ed35dc86020911aa9cf8ea104859 Mon Sep 17 00:00:00 2001 From: roopa Date: Thu, 17 Jan 2013 06:48:59 -0800 Subject: [PATCH 384/432] route cache: This patch adds route priority to route object oo_id_attrs The kernel allows multiple entries in the main table which differ in the priority value. In libnl currently, since priority is not part of the base netlink route message, it is not used as part of the key. This patch includes priority in the key/oo_id_attrs and defaults the value to zero for messages where priority is not included. One point to note is that the actual selection of route from multiple options is done implicitly in the kernel by storing the routes in sort priority order, but there is no explicit communication to a client of libnl of that. Signed-off-by: Shrijeet Mukherjee Signed-off-by: Roopa Prabhu Signed-off-by: Thomas Graf --- lib/route/route_obj.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/route/route_obj.c b/lib/route/route_obj.c index e092d80..0c472b7 100644 --- a/lib/route/route_obj.c +++ b/lib/route/route_obj.c @@ -71,6 +71,7 @@ static void route_constructor(struct nl_object *c) r->rt_table = RT_TABLE_MAIN; r->rt_protocol = RTPROT_STATIC; r->rt_type = RTN_UNICAST; + r->rt_prio = 0; nl_init_list_head(&r->rt_nexthops); } @@ -303,6 +304,7 @@ static void route_keygen(struct nl_object *obj, uint32_t *hashkey, uint8_t rt_family; uint8_t rt_tos; uint32_t rt_table; + uint32_t rt_prio; char rt_addr[0]; } __attribute__((packed)) *rkey; char buf[INET6_ADDRSTRLEN+5]; @@ -322,6 +324,7 @@ static void route_keygen(struct nl_object *obj, uint32_t *hashkey, rkey->rt_family = route->rt_family; rkey->rt_tos = route->rt_tos; rkey->rt_table = route->rt_table; + rkey->rt_prio = route->rt_prio; if (addr) memcpy(rkey->rt_addr, nl_addr_get_binary_addr(addr), nl_addr_get_len(addr)); @@ -1026,11 +1029,12 @@ int rtnl_route_parse(struct nlmsghdr *nlh, struct rtnl_route **result) route->rt_scope = rtm->rtm_scope; route->rt_protocol = rtm->rtm_protocol; route->rt_flags = rtm->rtm_flags; + route->rt_prio = 0; route->ce_mask |= ROUTE_ATTR_FAMILY | ROUTE_ATTR_TOS | ROUTE_ATTR_TABLE | ROUTE_ATTR_TYPE | ROUTE_ATTR_SCOPE | ROUTE_ATTR_PROTOCOL | - ROUTE_ATTR_FLAGS; + ROUTE_ATTR_FLAGS | ROUTE_ATTR_PRIO; if (tb[RTA_DST]) { if (!(dst = nl_addr_alloc_attr(tb[RTA_DST], family))) @@ -1299,7 +1303,8 @@ struct nl_object_ops route_obj_ops = { .oo_update = route_update, .oo_attrs2str = route_attrs2str, .oo_id_attrs = (ROUTE_ATTR_FAMILY | ROUTE_ATTR_TOS | - ROUTE_ATTR_TABLE | ROUTE_ATTR_DST), + ROUTE_ATTR_TABLE | ROUTE_ATTR_DST | + ROUTE_ATTR_PRIO), }; /** @endcond */ From 26e22d887e2842eaf993dd3b743ce620e0c7eb46 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 22 Jan 2013 19:30:16 +0100 Subject: [PATCH 385/432] 3.2.20 release --- configure.ac | 2 +- doc/configure.ac | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 2c31552..9599476 100644 --- a/configure.ac +++ b/configure.ac @@ -13,7 +13,7 @@ # copied from glib m4_define([libnl_major_version], [3]) m4_define([libnl_minor_version], [2]) -m4_define([libnl_micro_version], [19]) +m4_define([libnl_micro_version], [20]) # If either revision or age are omitted, they default to 0. Also note that age diff --git a/doc/configure.ac b/doc/configure.ac index 6a0be3c..1316f23 100644 --- a/doc/configure.ac +++ b/doc/configure.ac @@ -9,7 +9,7 @@ # Copyright (c) 2003-2012 Thomas Graf # -AC_INIT(libnl-doc, [3.2.19], [http://www.infradead.org/~tgr/libnl/]) +AC_INIT(libnl-doc, [3.2.20], [http://www.infradead.org/~tgr/libnl/]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_AUX_DIR([build-aux]) AM_INIT_AUTOMAKE([foreign]) From 1419851eb46aa5823c27792c3d4bb6a2b55ca9f4 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 23 Jan 2013 13:17:43 +0100 Subject: [PATCH 386/432] fix includes after removing some headers commit f20bbe1f07fcff1509425884f5ed72ca8d5fb6ab Author: Thomas Graf Date: Tue Jan 22 19:10:38 2013 +0100 No longer install module API headers This commit causes a regression so no app using libnl can be compiled against it. This patch fixes it by removing includes of no-longe existing headers. Signed-off-by: Jiri Pirko Signed-off-by: Thomas Graf --- include/netlink/cache-api.h | 3 +-- include/netlink/cache.h | 2 +- include/netlink/cli/tc.h | 4 +++- include/netlink/netlink.h | 3 ++- include/netlink/route/tc-api.h | 7 ------- include/netlink/route/tc.h | 7 +++++++ 6 files changed, 14 insertions(+), 12 deletions(-) diff --git a/include/netlink/cache-api.h b/include/netlink/cache-api.h index b332415..493a551 100644 --- a/include/netlink/cache-api.h +++ b/include/netlink/cache-api.h @@ -13,13 +13,12 @@ #define NETLINK_CACHE_API_H_ #include +#include #ifdef __cplusplus extern "C" { #endif -typedef void (*change_func_t)(struct nl_cache *, struct nl_object *, int, void *); - /** * @ingroup cache * @defgroup cache_api Cache Implementation diff --git a/include/netlink/cache.h b/include/netlink/cache.h index ac03842..0da1377 100644 --- a/include/netlink/cache.h +++ b/include/netlink/cache.h @@ -16,13 +16,13 @@ #include #include #include -#include #ifdef __cplusplus extern "C" { #endif struct nl_cache; +typedef void (*change_func_t)(struct nl_cache *, struct nl_object *, int, void *); /** * @ingroup cache diff --git a/include/netlink/cli/tc.h b/include/netlink/cli/tc.h index 85d2e30..77042c7 100644 --- a/include/netlink/cli/tc.h +++ b/include/netlink/cli/tc.h @@ -12,7 +12,9 @@ #ifndef __NETLINK_CLI_TC_H_ #define __NETLINK_CLI_TC_H_ -#include +#include + +struct rtnl_tc_ops; extern void nl_cli_tc_parse_dev(struct rtnl_tc *, struct nl_cache *, char *); extern void nl_cli_tc_parse_parent(struct rtnl_tc *, char *); diff --git a/include/netlink/netlink.h b/include/netlink/netlink.h index a501eaa..5f68548 100644 --- a/include/netlink/netlink.h +++ b/include/netlink/netlink.h @@ -32,13 +32,14 @@ #include #include #include -#include #ifdef __cplusplus extern "C" { #endif struct ucred; +struct nl_cache_ops; +struct nl_parser_param; extern int nl_debug; extern struct nl_dump_params nl_debug_dp; diff --git a/include/netlink/route/tc-api.h b/include/netlink/route/tc-api.h index d89408f..601a8df 100644 --- a/include/netlink/route/tc-api.h +++ b/include/netlink/route/tc-api.h @@ -20,13 +20,6 @@ extern "C" { #endif -enum rtnl_tc_type { - RTNL_TC_TYPE_QDISC, - RTNL_TC_TYPE_CLASS, - RTNL_TC_TYPE_CLS, - __RTNL_TC_TYPE_MAX, -}; - #define RTNL_TC_TYPE_MAX (__RTNL_TC_TYPE_MAX - 1) /** diff --git a/include/netlink/route/tc.h b/include/netlink/route/tc.h index 50ca6de..caee60c 100644 --- a/include/netlink/route/tc.h +++ b/include/netlink/route/tc.h @@ -23,6 +23,13 @@ extern "C" { #endif +enum rtnl_tc_type { + RTNL_TC_TYPE_QDISC, + RTNL_TC_TYPE_CLASS, + RTNL_TC_TYPE_CLS, + __RTNL_TC_TYPE_MAX, +}; + /** * Compute tc handle based on major and minor parts * @ingroup tc From 56352ab9f6b1a55449a675ed97130233f7eaedd2 Mon Sep 17 00:00:00 2001 From: Rich Fought Date: Wed, 23 Jan 2013 13:59:27 -0800 Subject: [PATCH 387/432] netfilter: expectation NAT direction is 32 bit attribute --- include/netlink/netfilter/exp.h | 4 ++-- lib/netfilter/exp.c | 6 +++--- lib/netfilter/exp_obj.c | 4 ++-- src/nf-exp-add.c | 18 ++++++++++++++++++ 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/include/netlink/netfilter/exp.h b/include/netlink/netfilter/exp.h index 4e95014..761d3d5 100644 --- a/include/netlink/netfilter/exp.h +++ b/include/netlink/netfilter/exp.h @@ -92,9 +92,9 @@ extern int nfnl_exp_set_fn(struct nfnl_exp *, void *); extern int nfnl_exp_test_fn(const struct nfnl_exp *); extern const char * nfnl_exp_get_fn(const struct nfnl_exp *); -extern void nfnl_exp_set_nat_dir(struct nfnl_exp *, uint8_t); +extern void nfnl_exp_set_nat_dir(struct nfnl_exp *, uint32_t); extern int nfnl_exp_test_nat_dir(const struct nfnl_exp *); -extern uint8_t nfnl_exp_get_nat_dir(const struct nfnl_exp *); +extern uint32_t nfnl_exp_get_nat_dir(const struct nfnl_exp *); // The int argument specifies which nfnl_exp_dir (expect, master, mask or nat) // Expectation objects only use orig, not reply diff --git a/lib/netfilter/exp.c b/lib/netfilter/exp.c index 5ba2bcb..4f4984f 100644 --- a/lib/netfilter/exp.c +++ b/lib/netfilter/exp.c @@ -70,7 +70,7 @@ static struct nla_policy exp_proto_policy[CTA_PROTO_MAX+1] = { }; static struct nla_policy exp_nat_policy[CTA_EXPECT_NAT_MAX+1] = { - [CTA_EXPECT_NAT_DIR] = { .type = NLA_U8 }, + [CTA_EXPECT_NAT_DIR] = { .type = NLA_U32 }, [CTA_EXPECT_NAT_TUPLE] = { .type = NLA_NESTED }, }; @@ -195,7 +195,7 @@ static int exp_parse_nat(struct nfnl_exp *exp, struct nlattr *attr) return err; if (tb[CTA_EXPECT_NAT_DIR]) - nfnl_exp_set_nat_dir(exp, nla_get_u8(tb[CTA_EXPECT_NAT_DIR])); + nfnl_exp_set_nat_dir(exp, nla_get_u32(tb[CTA_EXPECT_NAT_DIR])); if (tb[CTA_EXPECT_NAT_TUPLE]) { err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_NAT, tb[CTA_EXPECT_NAT_TUPLE]); @@ -416,7 +416,7 @@ static int nfnl_exp_build_nat(struct nl_msg *msg, const struct nfnl_exp *exp) nat = nla_nest_start(msg, CTA_EXPECT_NAT); if (nfnl_exp_test_nat_dir(exp)) { - NLA_PUT_U8(msg, CTA_EXPECT_NAT_DIR, + NLA_PUT_U32(msg, CTA_EXPECT_NAT_DIR, nfnl_exp_get_nat_dir(exp)); } diff --git a/lib/netfilter/exp_obj.c b/lib/netfilter/exp_obj.c index 182df23..71caeda 100644 --- a/lib/netfilter/exp_obj.c +++ b/lib/netfilter/exp_obj.c @@ -589,7 +589,7 @@ const char * nfnl_exp_get_fn(const struct nfnl_exp *exp) return exp->exp_fn; } -void nfnl_exp_set_nat_dir(struct nfnl_exp *exp, uint8_t nat_dir) +void nfnl_exp_set_nat_dir(struct nfnl_exp *exp, uint32_t nat_dir) { exp->exp_nat_dir = nat_dir; exp->ce_mask |= EXP_ATTR_NAT_DIR; @@ -600,7 +600,7 @@ int nfnl_exp_test_nat_dir(const struct nfnl_exp *exp) return !!(exp->ce_mask & EXP_ATTR_NAT_DIR); } -uint8_t nfnl_exp_get_nat_dir(const struct nfnl_exp *exp) +uint32_t nfnl_exp_get_nat_dir(const struct nfnl_exp *exp) { return exp->exp_nat_dir; } diff --git a/src/nf-exp-add.c b/src/nf-exp-add.c index f760ee5..4b7f9d9 100644 --- a/src/nf-exp-add.c +++ b/src/nf-exp-add.c @@ -86,6 +86,12 @@ int main(int argc, char *argv[]) ARG_MASK_SPORT, ARG_MASK_DST, ARG_MASK_DPORT, + ARG_NAT_PROTO, + ARG_NAT_SRC, + ARG_NAT_SPORT, + ARG_NAT_DST, + ARG_NAT_DPORT, + ARG_NAT_DIR, ARG_TIMEOUT, ARG_HELPER_NAME, ARG_REPLACE, @@ -112,6 +118,12 @@ int main(int argc, char *argv[]) { "mask-sport", 1, 0, ARG_MASK_SPORT }, { "mask-dst", 1, 0, ARG_MASK_DST }, { "mask-dport", 1, 0, ARG_MASK_DPORT }, + { "nat-proto", 1, 0, ARG_NAT_PROTO }, + { "nat-src", 1, 0, ARG_NAT_SRC }, + { "nat-sport", 1, 0, ARG_NAT_SPORT }, + { "nat-dst", 1, 0, ARG_NAT_DST }, + { "nat-dport", 1, 0, ARG_NAT_DPORT }, + { "nat-dir", 1, 0, ARG_NAT_DIR }, { "family", 1, 0, 'F' }, { "timeout", 1, 0, ARG_TIMEOUT }, { "helper", 1, 0, ARG_HELPER_NAME }, @@ -147,6 +159,12 @@ int main(int argc, char *argv[]) case ARG_MASK_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_MASK, optarg); break; case ARG_MASK_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_MASK, optarg); break; case ARG_MASK_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_MASK, optarg); break; + case ARG_NAT_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_NAT, optarg); break; + case ARG_NAT_SRC: nl_cli_exp_parse_src(exp, NFNL_EXP_TUPLE_NAT, optarg); break; + case ARG_NAT_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_NAT, optarg); break; + case ARG_NAT_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_NAT, optarg); break; + case ARG_NAT_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_NAT, optarg); break; + case ARG_NAT_DIR: nl_cli_exp_parse_nat_dir(exp, optarg); break; case 'F': nl_cli_exp_parse_family(exp, optarg); break; case ARG_TIMEOUT: nl_cli_exp_parse_timeout(exp, optarg); break; case ARG_HELPER_NAME: nl_cli_exp_parse_helper_name(exp, optarg); break; From 9680f910f46b78d700ae66a16c08d8927dfc2199 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 24 Jan 2013 13:51:24 +0100 Subject: [PATCH 388/432] Move private header files to This clarifies the seperation between public and private header files. Signed-off-by: Thomas Graf --- include/Makefile.am | 17 ++++++++-------- .../{netlink => netlink-private}/cache-api.h | 4 ++-- .../genl.h} | 6 +++--- .../netlink.h} | 10 +++++----- .../{netlink => netlink-private}/object-api.h | 5 +++-- .../route/link/api.h | 4 ++-- .../route/tc-api.h | 6 ++---- .../{netlink-tc.h => netlink-private/tc.h} | 6 +++--- .../types.h} | 6 +++--- include/netlink/route/link/info-api.h | 20 ------------------- include/netlink/route/tc.h | 2 ++ lib/addr.c | 2 +- lib/attr.c | 2 +- lib/cache.c | 2 +- lib/cache_mngr.c | 2 +- lib/cache_mngt.c | 2 +- lib/data.c | 2 +- lib/error.c | 2 +- lib/fib_lookup/lookup.c | 2 +- lib/fib_lookup/request.c | 2 +- lib/genl/ctrl.c | 2 +- lib/genl/family.c | 2 +- lib/genl/genl.c | 2 +- lib/genl/mngt.c | 2 +- lib/handlers.c | 2 +- lib/hashtable.c | 2 +- lib/msg.c | 2 +- lib/netfilter/ct.c | 2 +- lib/netfilter/ct_obj.c | 2 +- lib/netfilter/exp.c | 2 +- lib/netfilter/exp_obj.c | 2 +- lib/netfilter/log.c | 2 +- lib/netfilter/log_msg.c | 2 +- lib/netfilter/log_msg_obj.c | 2 +- lib/netfilter/log_obj.c | 2 +- lib/netfilter/netfilter.c | 2 +- lib/netfilter/nfnl.c | 2 +- lib/netfilter/queue.c | 2 +- lib/netfilter/queue_msg.c | 2 +- lib/netfilter/queue_msg_obj.c | 2 +- lib/netfilter/queue_obj.c | 2 +- lib/nl.c | 2 +- lib/object.c | 2 +- lib/route/addr.c | 2 +- lib/route/class.c | 8 ++++---- lib/route/classid.c | 6 +++--- lib/route/cls.c | 8 ++++---- lib/route/cls/basic.c | 8 ++++---- lib/route/cls/cgroup.c | 8 ++++---- lib/route/cls/ematch.c | 6 +++--- lib/route/cls/ematch/cmp.c | 6 +++--- lib/route/cls/ematch/container.c | 6 +++--- lib/route/cls/ematch/meta.c | 6 +++--- lib/route/cls/ematch/nbyte.c | 6 +++--- lib/route/cls/ematch/text.c | 6 +++--- lib/route/cls/ematch_grammar.l | 6 +++--- lib/route/cls/ematch_syntax.y | 6 +++--- lib/route/cls/fw.c | 8 ++++---- lib/route/cls/police.c | 8 ++++---- lib/route/cls/u32.c | 8 ++++---- lib/route/link.c | 4 ++-- lib/route/link/api.c | 4 ++-- lib/route/link/bonding.c | 4 ++-- lib/route/link/bridge.c | 4 ++-- lib/route/link/can.c | 4 ++-- lib/route/link/dummy.c | 4 ++-- lib/route/link/inet.c | 4 ++-- lib/route/link/inet6.c | 4 ++-- lib/route/link/vlan.c | 4 ++-- lib/route/neigh.c | 2 +- lib/route/neightbl.c | 2 +- lib/route/nexthop.c | 2 +- lib/route/pktloc.c | 6 +++--- lib/route/pktloc_grammar.l | 4 ++-- lib/route/pktloc_syntax.y | 4 ++-- lib/route/qdisc.c | 6 +++--- lib/route/qdisc/blackhole.c | 4 ++-- lib/route/qdisc/cbq.c | 6 +++--- lib/route/qdisc/dsmark.c | 6 +++--- lib/route/qdisc/fifo.c | 6 +++--- lib/route/qdisc/htb.c | 6 +++--- lib/route/qdisc/netem.c | 6 +++--- lib/route/qdisc/plug.c | 6 +++--- lib/route/qdisc/prio.c | 6 +++--- lib/route/qdisc/red.c | 6 +++--- lib/route/qdisc/sfq.c | 6 +++--- lib/route/qdisc/tbf.c | 6 +++--- lib/route/route.c | 2 +- lib/route/route_obj.c | 2 +- lib/route/route_utils.c | 2 +- lib/route/rtnl.c | 2 +- lib/route/rule.c | 2 +- lib/route/tc.c | 6 +++--- lib/socket.c | 2 +- lib/utils.c | 2 +- src/lib/tc.c | 2 +- src/nl-list-caches.c | 2 +- 97 files changed, 196 insertions(+), 216 deletions(-) rename include/{netlink => netlink-private}/cache-api.h (98%) rename include/{netlink-generic.h => netlink-private/genl.h} (71%) rename include/{netlink-local.h => netlink-private/netlink.h} (96%) rename include/{netlink => netlink-private}/object-api.h (98%) rename include/{netlink => netlink-private}/route/link/api.h (97%) rename include/{netlink => netlink-private}/route/tc-api.h (95%) rename include/{netlink-tc.h => netlink-private/tc.h} (88%) rename include/{netlink-types.h => netlink-private/types.h} (99%) delete mode 100644 include/netlink/route/link/info-api.h diff --git a/include/Makefile.am b/include/Makefile.am index 50d1e4e..50f96b7 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -116,12 +116,11 @@ noinst_HEADERS = \ linux/rtnetlink.h \ linux/snmp.h \ linux/tc_ematch/tc_em_meta.h \ - netlink-generic.h \ - netlink-local.h \ - netlink-tc.h \ - netlink-types.h \ - netlink/cache-api.h \ - netlink/object-api.h \ - netlink/route/link/api.h \ - netlink/route/link/info-api.h \ - netlink/route/tc-api.h + netlink-private/genl.h \ + netlink-private/netlink.h \ + netlink-private/tc.h \ + netlink-private/types.h \ + netlink-private/cache-api.h \ + netlink-private/object-api.h \ + netlink-private/route/link/api.h \ + netlink-private/route/tc-api.h diff --git a/include/netlink/cache-api.h b/include/netlink-private/cache-api.h similarity index 98% rename from include/netlink/cache-api.h rename to include/netlink-private/cache-api.h index 493a551..5d9b0ad 100644 --- a/include/netlink/cache-api.h +++ b/include/netlink-private/cache-api.h @@ -1,12 +1,12 @@ /* - * netlink/cache-api.h Caching API + * netlink-private/cache-api.h Caching API * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2012 Thomas Graf + * Copyright (c) 2003-2013 Thomas Graf */ #ifndef NETLINK_CACHE_API_H_ diff --git a/include/netlink-generic.h b/include/netlink-private/genl.h similarity index 71% rename from include/netlink-generic.h rename to include/netlink-private/genl.h index 10aa2f0..0aca6d7 100644 --- a/include/netlink-generic.h +++ b/include/netlink-private/genl.h @@ -1,18 +1,18 @@ /* - * netlink-generic.h Local Generic Netlink Interface + * netlink-private/genl.h Local Generic Netlink Interface * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2006 Thomas Graf + * Copyright (c) 2003-2013 Thomas Graf */ #ifndef NETLINK_GENL_PRIV_H_ #define NETLINK_GENL_PRIV_H_ -#include +#include #include #define GENL_HDRSIZE(hdrlen) (GENL_HDRLEN + (hdrlen)) diff --git a/include/netlink-local.h b/include/netlink-private/netlink.h similarity index 96% rename from include/netlink-local.h rename to include/netlink-private/netlink.h index c0915f8..6ae6d17 100644 --- a/include/netlink-local.h +++ b/include/netlink-private/netlink.h @@ -1,12 +1,12 @@ /* - * netlink-local.h Local Netlink Interface + * netlink-private/netlink.h Local Netlink Interface * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2011 Thomas Graf + * Copyright (c) 2003-2013 Thomas Graf */ #ifndef NETLINK_LOCAL_H_ @@ -63,9 +63,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include struct trans_tbl { int i; diff --git a/include/netlink/object-api.h b/include/netlink-private/object-api.h similarity index 98% rename from include/netlink/object-api.h rename to include/netlink-private/object-api.h index ae6180a..f4fd71e 100644 --- a/include/netlink/object-api.h +++ b/include/netlink-private/object-api.h @@ -1,12 +1,12 @@ /* - * netlink/object-api.c Object API + * netlink-private/object-api.c Object API * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2007 Thomas Graf + * Copyright (c) 2003-2013 Thomas Graf */ #ifndef NETLINK_OBJECT_API_H_ @@ -14,6 +14,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { diff --git a/include/netlink/route/link/api.h b/include/netlink-private/route/link/api.h similarity index 97% rename from include/netlink/route/link/api.h rename to include/netlink-private/route/link/api.h index 28f2464..bb98ccc 100644 --- a/include/netlink/route/link/api.h +++ b/include/netlink-private/route/link/api.h @@ -1,12 +1,12 @@ /* - * netlink/route/link/api.h Link Modules API + * netlink-private/route/link/api.h Link Modules API * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2010 Thomas Graf + * Copyright (c) 2003-2013 Thomas Graf */ #ifndef NETLINK_LINK_API_H_ diff --git a/include/netlink/route/tc-api.h b/include/netlink-private/route/tc-api.h similarity index 95% rename from include/netlink/route/tc-api.h rename to include/netlink-private/route/tc-api.h index 601a8df..bf0c8a3 100644 --- a/include/netlink/route/tc-api.h +++ b/include/netlink-private/route/tc-api.h @@ -1,12 +1,12 @@ /* - * netlink/route/tc-api.h Traffic Control API + * netlink-private/route/tc-api.h Traffic Control API * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2011 Thomas Graf + * Copyright (c) 2011-2013 Thomas Graf */ #ifndef NETLINK_TC_API_H_ @@ -20,8 +20,6 @@ extern "C" { #endif -#define RTNL_TC_TYPE_MAX (__RTNL_TC_TYPE_MAX - 1) - /** * Traffic control object operations * @ingroup tc diff --git a/include/netlink-tc.h b/include/netlink-private/tc.h similarity index 88% rename from include/netlink-tc.h rename to include/netlink-private/tc.h index 3e44642..182adaa 100644 --- a/include/netlink-tc.h +++ b/include/netlink-private/tc.h @@ -1,18 +1,18 @@ /* - * netlink-tc.h Local Traffic Control Interface + * netlink-private/tc.h Local Traffic Control Interface * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2010 Thomas Graf + * Copyright (c) 2003-2013 Thomas Graf */ #ifndef NETLINK_TC_PRIV_H_ #define NETLINK_TC_PRIV_H_ -#include +#include #ifdef __cplusplus extern "C" { diff --git a/include/netlink-types.h b/include/netlink-private/types.h similarity index 99% rename from include/netlink-types.h rename to include/netlink-private/types.h index 46856a3..60a3bce 100644 --- a/include/netlink-types.h +++ b/include/netlink-private/types.h @@ -1,12 +1,12 @@ /* - * netlink-types.h Netlink Types (Private) + * netlink-private/types.h Netlink Types (Private) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2012 Thomas Graf + * Copyright (c) 2003-2013 Thomas Graf */ #ifndef NETLINK_LOCAL_TYPES_H_ @@ -17,7 +17,7 @@ #include #include #include -#include +#include #define NL_SOCK_BUFSIZE_SET (1<<0) #define NL_SOCK_PASSCRED (1<<1) diff --git a/include/netlink/route/link/info-api.h b/include/netlink/route/link/info-api.h deleted file mode 100644 index 4750e18..0000000 --- a/include/netlink/route/link/info-api.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * netlink/route/link/info-api.h Link Info API - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * Copyright (c) 2003-2010 Thomas Graf - */ - -#ifndef NETLINK_LINK_INFO_API_H_ -#define NETLINK_LINK_INFO_API_H_ - -#warning " is obsolete and may be removed in the future." -#warning "include instead. - -#include - -#endif diff --git a/include/netlink/route/tc.h b/include/netlink/route/tc.h index caee60c..836f7b1 100644 --- a/include/netlink/route/tc.h +++ b/include/netlink/route/tc.h @@ -30,6 +30,8 @@ enum rtnl_tc_type { __RTNL_TC_TYPE_MAX, }; +#define RTNL_TC_TYPE_MAX (__RTNL_TC_TYPE_MAX - 1) + /** * Compute tc handle based on major and minor parts * @ingroup tc diff --git a/lib/addr.c b/lib/addr.c index 1f1478a..806664b 100644 --- a/lib/addr.c +++ b/lib/addr.c @@ -27,7 +27,7 @@ * ~~~~ */ -#include +#include #include #include #include diff --git a/lib/attr.c b/lib/attr.c index 1601061..10ea682 100644 --- a/lib/attr.c +++ b/lib/attr.c @@ -9,7 +9,7 @@ * Copyright (c) 2003-2008 Thomas Graf */ -#include +#include #include #include #include diff --git a/lib/cache.c b/lib/cache.c index 24ffa31..fafc023 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -49,7 +49,7 @@ * ~~~~ */ -#include +#include #include #include #include diff --git a/lib/cache_mngr.c b/lib/cache_mngr.c index d5dc1f3..f8a65e3 100644 --- a/lib/cache_mngr.c +++ b/lib/cache_mngr.c @@ -32,7 +32,7 @@ * ~~~~ */ -#include +#include #include #include #include diff --git a/lib/cache_mngt.c b/lib/cache_mngt.c index 62cde06..4d3d6ff 100644 --- a/lib/cache_mngt.c +++ b/lib/cache_mngt.c @@ -25,7 +25,7 @@ * ~~~~ */ -#include +#include #include #include #include diff --git a/lib/data.c b/lib/data.c index f019539..1a3a3fb 100644 --- a/lib/data.c +++ b/lib/data.c @@ -27,7 +27,7 @@ * ~~~~ */ -#include +#include #include #include #include diff --git a/lib/error.c b/lib/error.c index e8ee474..f30b9a5 100644 --- a/lib/error.c +++ b/lib/error.c @@ -9,7 +9,7 @@ * Copyright (c) 2008 Thomas Graf */ -#include +#include #include static const char *errmsg[NLE_MAX+1] = { diff --git a/lib/fib_lookup/lookup.c b/lib/fib_lookup/lookup.c index ec82c16..6fe8dae 100644 --- a/lib/fib_lookup/lookup.c +++ b/lib/fib_lookup/lookup.c @@ -16,7 +16,7 @@ * @{ */ -#include +#include #include #include #include diff --git a/lib/fib_lookup/request.c b/lib/fib_lookup/request.c index ffcf8f5..1b021b6 100644 --- a/lib/fib_lookup/request.c +++ b/lib/fib_lookup/request.c @@ -16,7 +16,7 @@ * @{ */ -#include +#include #include #include #include diff --git a/lib/genl/ctrl.c b/lib/genl/ctrl.c index 057a1bf..c6db742 100644 --- a/lib/genl/ctrl.c +++ b/lib/genl/ctrl.c @@ -21,7 +21,7 @@ * @{ */ -#include +#include #include #include #include diff --git a/lib/genl/family.c b/lib/genl/family.c index 05e45ac..897c809 100644 --- a/lib/genl/family.c +++ b/lib/genl/family.c @@ -18,7 +18,7 @@ * @{ */ -#include +#include #include #include #include diff --git a/lib/genl/genl.c b/lib/genl/genl.c index 8d3def3..0c9b11e 100644 --- a/lib/genl/genl.c +++ b/lib/genl/genl.c @@ -15,7 +15,7 @@ * @{ */ -#include +#include #include #include #include diff --git a/lib/genl/mngt.c b/lib/genl/mngt.c index ad25172..a3faaf2 100644 --- a/lib/genl/mngt.c +++ b/lib/genl/mngt.c @@ -18,7 +18,7 @@ * @{ */ -#include +#include #include #include #include diff --git a/lib/handlers.c b/lib/handlers.c index 74276a1..ee1376b 100644 --- a/lib/handlers.c +++ b/lib/handlers.c @@ -25,7 +25,7 @@ * ~~~~ */ -#include +#include #include #include #include diff --git a/lib/hashtable.c b/lib/hashtable.c index ecd5730..8b15925 100644 --- a/lib/hashtable.c +++ b/lib/hashtable.c @@ -9,7 +9,7 @@ * Copyright (c) 2012 Cumulus Networks, Inc */ #include -#include +#include #include #include #include diff --git a/lib/msg.c b/lib/msg.c index 2613c78..8198ded 100644 --- a/lib/msg.c +++ b/lib/msg.c @@ -26,7 +26,7 @@ * ~~~~ */ -#include +#include #include #include #include diff --git a/lib/netfilter/ct.c b/lib/netfilter/ct.c index 59ee1d9..5dde1d1 100644 --- a/lib/netfilter/ct.c +++ b/lib/netfilter/ct.c @@ -23,7 +23,7 @@ #include #include -#include +#include #include #include #include diff --git a/lib/netfilter/ct_obj.c b/lib/netfilter/ct_obj.c index 4686170..bac775b 100644 --- a/lib/netfilter/ct_obj.c +++ b/lib/netfilter/ct_obj.c @@ -16,7 +16,7 @@ #include #include -#include +#include #include #include diff --git a/lib/netfilter/exp.c b/lib/netfilter/exp.c index 5ba2bcb..952ef3a 100644 --- a/lib/netfilter/exp.c +++ b/lib/netfilter/exp.c @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include #include diff --git a/lib/netfilter/exp_obj.c b/lib/netfilter/exp_obj.c index 182df23..69b4dd3 100644 --- a/lib/netfilter/exp_obj.c +++ b/lib/netfilter/exp_obj.c @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include diff --git a/lib/netfilter/log.c b/lib/netfilter/log.c index 96ae6c5..1bab9b6 100644 --- a/lib/netfilter/log.c +++ b/lib/netfilter/log.c @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include #include diff --git a/lib/netfilter/log_msg.c b/lib/netfilter/log_msg.c index 65448f9..6e09da2 100644 --- a/lib/netfilter/log_msg.c +++ b/lib/netfilter/log_msg.c @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include #include diff --git a/lib/netfilter/log_msg_obj.c b/lib/netfilter/log_msg_obj.c index d2ad0ff..57db9d4 100644 --- a/lib/netfilter/log_msg_obj.c +++ b/lib/netfilter/log_msg_obj.c @@ -11,7 +11,7 @@ * Copyright (c) 2007 Secure Computing Corporation */ -#include +#include #include #include #include diff --git a/lib/netfilter/log_obj.c b/lib/netfilter/log_obj.c index 43c4a06..2b11414 100644 --- a/lib/netfilter/log_obj.c +++ b/lib/netfilter/log_obj.c @@ -12,7 +12,7 @@ * Copyright (c) 2008 Patrick McHardy */ -#include +#include #include #include diff --git a/lib/netfilter/netfilter.c b/lib/netfilter/netfilter.c index addecd7..0062994 100644 --- a/lib/netfilter/netfilter.c +++ b/lib/netfilter/netfilter.c @@ -9,7 +9,7 @@ * Copyright (c) 2008 Patrick McHardy */ -#include +#include #include #include diff --git a/lib/netfilter/nfnl.c b/lib/netfilter/nfnl.c index 6d27c44..f028a85 100644 --- a/lib/netfilter/nfnl.c +++ b/lib/netfilter/nfnl.c @@ -61,7 +61,7 @@ * @{ */ -#include +#include #include #include diff --git a/lib/netfilter/queue.c b/lib/netfilter/queue.c index ff1de0e..5655647 100644 --- a/lib/netfilter/queue.c +++ b/lib/netfilter/queue.c @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include #include diff --git a/lib/netfilter/queue_msg.c b/lib/netfilter/queue_msg.c index 30c522f..95d8ad3 100644 --- a/lib/netfilter/queue_msg.c +++ b/lib/netfilter/queue_msg.c @@ -20,7 +20,7 @@ #include #include -#include +#include #include #include #include diff --git a/lib/netfilter/queue_msg_obj.c b/lib/netfilter/queue_msg_obj.c index bfaafc5..8085f1b 100644 --- a/lib/netfilter/queue_msg_obj.c +++ b/lib/netfilter/queue_msg_obj.c @@ -9,7 +9,7 @@ * Copyright (c) 2007, 2008 Patrick McHardy */ -#include +#include #include #include #include diff --git a/lib/netfilter/queue_obj.c b/lib/netfilter/queue_obj.c index 05a9cb8..5edcc68 100644 --- a/lib/netfilter/queue_obj.c +++ b/lib/netfilter/queue_obj.c @@ -16,7 +16,7 @@ * @{ */ -#include +#include #include #include diff --git a/lib/nl.c b/lib/nl.c index ec1db01..fa43c56 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -25,7 +25,7 @@ * @{ */ -#include +#include #include #include #include diff --git a/lib/object.c b/lib/object.c index 7361194..17b98f6 100644 --- a/lib/object.c +++ b/lib/object.c @@ -27,7 +27,7 @@ * ~~~~ */ -#include +#include #include #include #include diff --git a/lib/route/addr.c b/lib/route/addr.c index c5e14bb..95a9447 100644 --- a/lib/route/addr.c +++ b/lib/route/addr.c @@ -106,7 +106,7 @@ * @{ */ -#include +#include #include #include #include diff --git a/lib/route/class.c b/lib/route/class.c index 399e8a2..050f42a 100644 --- a/lib/route/class.c +++ b/lib/route/class.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2011 Thomas Graf + * Copyright (c) 2003-2013 Thomas Graf */ /** @@ -15,10 +15,10 @@ * @{ */ -#include -#include +#include +#include #include -#include +#include #include #include #include diff --git a/lib/route/classid.c b/lib/route/classid.c index 255e075..f2d3a01 100644 --- a/lib/route/classid.c +++ b/lib/route/classid.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2010 Thomas Graf + * Copyright (c) 2010-2013 Thomas Graf */ /** @@ -15,8 +15,8 @@ * @{ */ -#include -#include +#include +#include #include #include #include diff --git a/lib/route/cls.c b/lib/route/cls.c index 35a010a..7a809bb 100644 --- a/lib/route/cls.c +++ b/lib/route/cls.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2011 Thomas Graf + * Copyright (c) 2003-2013 Thomas Graf */ /** @@ -15,11 +15,11 @@ * @{ */ -#include -#include +#include +#include #include #include -#include +#include #include #include diff --git a/lib/route/cls/basic.c b/lib/route/cls/basic.c index 9d7710a..fb1c382 100644 --- a/lib/route/cls/basic.c +++ b/lib/route/cls/basic.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2008-2011 Thomas Graf + * Copyright (c) 2008-2013 Thomas Graf */ /** @@ -22,10 +22,10 @@ * @{ */ -#include -#include +#include +#include #include -#include +#include #include #include #include diff --git a/lib/route/cls/cgroup.c b/lib/route/cls/cgroup.c index 230863b..c5b7561 100644 --- a/lib/route/cls/cgroup.c +++ b/lib/route/cls/cgroup.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2009-2011 Thomas Graf + * Copyright (c) 2009-2013 Thomas Graf */ /** @@ -16,12 +16,12 @@ * @{ */ -#include -#include +#include +#include #include #include #include -#include +#include #include #include #include diff --git a/lib/route/cls/ematch.c b/lib/route/cls/ematch.c index 8c9c3dd..89b5067 100644 --- a/lib/route/cls/ematch.c +++ b/lib/route/cls/ematch.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2008-2010 Thomas Graf + * Copyright (c) 2008-2013 Thomas Graf */ /** @@ -16,8 +16,8 @@ * @{ */ -#include -#include +#include +#include #include #include #include diff --git a/lib/route/cls/ematch/cmp.c b/lib/route/cls/ematch/cmp.c index 2a1070a..2997cdb 100644 --- a/lib/route/cls/ematch/cmp.c +++ b/lib/route/cls/ematch/cmp.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2008-2010 Thomas Graf + * Copyright (c) 2008-2013 Thomas Graf */ /** @@ -16,8 +16,8 @@ * @{ */ -#include -#include +#include +#include #include #include #include diff --git a/lib/route/cls/ematch/container.c b/lib/route/cls/ematch/container.c index 6d73ab6..813391a 100644 --- a/lib/route/cls/ematch/container.c +++ b/lib/route/cls/ematch/container.c @@ -6,11 +6,11 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2008-2010 Thomas Graf + * Copyright (c) 2008-2013 Thomas Graf */ -#include -#include +#include +#include #include #include diff --git a/lib/route/cls/ematch/meta.c b/lib/route/cls/ematch/meta.c index 11f87d6..44f11b9 100644 --- a/lib/route/cls/ematch/meta.c +++ b/lib/route/cls/ematch/meta.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2010 Thomas Graf + * Copyright (c) 2010-2013 Thomas Graf */ /** @@ -16,8 +16,8 @@ * @{ */ -#include -#include +#include +#include #include #include #include diff --git a/lib/route/cls/ematch/nbyte.c b/lib/route/cls/ematch/nbyte.c index 25a9866..8852489 100644 --- a/lib/route/cls/ematch/nbyte.c +++ b/lib/route/cls/ematch/nbyte.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2010 Thomas Graf + * Copyright (c) 2010-2013 Thomas Graf */ /** @@ -16,8 +16,8 @@ * @{ */ -#include -#include +#include +#include #include #include #include diff --git a/lib/route/cls/ematch/text.c b/lib/route/cls/ematch/text.c index 9d0241e..e8cdcae 100644 --- a/lib/route/cls/ematch/text.c +++ b/lib/route/cls/ematch/text.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2010 Thomas Graf + * Copyright (c) 2010-2013 Thomas Graf */ /** @@ -16,8 +16,8 @@ * @{ */ -#include -#include +#include +#include #include #include #include diff --git a/lib/route/cls/ematch_grammar.l b/lib/route/cls/ematch_grammar.l index 07e7e8c..96ef1a0 100644 --- a/lib/route/cls/ematch_grammar.l +++ b/lib/route/cls/ematch_grammar.l @@ -6,12 +6,12 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2010 Thomas Graf + * Copyright (c) 2010-2013 Thomas Graf */ %{ - #include - #include + #include + #include #include #include #include diff --git a/lib/route/cls/ematch_syntax.y b/lib/route/cls/ematch_syntax.y index 39123be..da21039 100644 --- a/lib/route/cls/ematch_syntax.y +++ b/lib/route/cls/ematch_syntax.y @@ -6,12 +6,12 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2010 Thomas Graf + * Copyright (c) 2010-2013 Thomas Graf */ %{ -#include -#include +#include +#include #include #include #include diff --git a/lib/route/cls/fw.c b/lib/route/cls/fw.c index d24779a..b569d4f 100644 --- a/lib/route/cls/fw.c +++ b/lib/route/cls/fw.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2011 Thomas Graf + * Copyright (c) 2003-2013 Thomas Graf * Copyright (c) 2006 Petr Gotthard * Copyright (c) 2006 Siemens AG Oesterreich */ @@ -18,10 +18,10 @@ * @{ */ -#include -#include +#include +#include #include -#include +#include #include #include diff --git a/lib/route/cls/police.c b/lib/route/cls/police.c index d7ab26b..1f5d284 100644 --- a/lib/route/cls/police.c +++ b/lib/route/cls/police.c @@ -6,14 +6,14 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2006 Thomas Graf + * Copyright (c) 2003-2013 Thomas Graf */ -#include -#include +#include +#include #include #include -#include +#include #include #include diff --git a/lib/route/cls/u32.c b/lib/route/cls/u32.c index aa9eb77..c468ba7 100644 --- a/lib/route/cls/u32.c +++ b/lib/route/cls/u32.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2011 Thomas Graf + * Copyright (c) 2003-2013 Thomas Graf * Copyright (c) 2005-2006 Petr Gotthard * Copyright (c) 2005-2006 Siemens AG Oesterreich */ @@ -18,12 +18,12 @@ * @{ */ -#include -#include +#include +#include #include #include #include -#include +#include #include #include diff --git a/lib/route/link.c b/lib/route/link.c index f817b3a..3171513 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -18,7 +18,7 @@ * @{ */ -#include +#include #include #include #include @@ -26,7 +26,7 @@ #include #include #include -#include +#include /** @cond SKIP */ #define LINK_ATTR_MTU (1 << 0) diff --git a/lib/route/link/api.c b/lib/route/link/api.c index 392ded3..63ff99c 100644 --- a/lib/route/link/api.c +++ b/lib/route/link/api.c @@ -39,11 +39,11 @@ * @{ */ -#include +#include #include #include #include -#include +#include static NL_LIST_HEAD(info_ops); diff --git a/lib/route/link/bonding.c b/lib/route/link/bonding.c index 5e78084..b060ee1 100644 --- a/lib/route/link/bonding.c +++ b/lib/route/link/bonding.c @@ -20,9 +20,9 @@ * @{ */ -#include +#include #include -#include +#include /** * Create a new kernel bonding device diff --git a/lib/route/link/bridge.c b/lib/route/link/bridge.c index cd9f462..52beedd 100644 --- a/lib/route/link/bridge.c +++ b/lib/route/link/bridge.c @@ -9,11 +9,11 @@ * Copyright (c) 2010 Thomas Graf */ -#include +#include #include #include #include -#include +#include #define BRIDGE_ATTR_PORT_STATE 0x0001 diff --git a/lib/route/link/can.c b/lib/route/link/can.c index 4b80d94..76bfa1a 100644 --- a/lib/route/link/can.c +++ b/lib/route/link/can.c @@ -22,13 +22,13 @@ * @{ */ -#include +#include #include #include #include #include #include -#include +#include #include #include diff --git a/lib/route/link/dummy.c b/lib/route/link/dummy.c index c7dabc1..1fd9f5a 100644 --- a/lib/route/link/dummy.c +++ b/lib/route/link/dummy.c @@ -19,9 +19,9 @@ * @{ */ -#include +#include #include -#include +#include static struct rtnl_link_info_ops dummy_info_ops = { .io_name = "dummy", diff --git a/lib/route/link/inet.c b/lib/route/link/inet.c index a0e2318..e2c867d 100644 --- a/lib/route/link/inet.c +++ b/lib/route/link/inet.c @@ -57,11 +57,11 @@ */ -#include +#include #include #include #include -#include +#include /** @cond SKIP */ struct inet_data diff --git a/lib/route/link/inet6.c b/lib/route/link/inet6.c index 9ee8226..4c627bd 100644 --- a/lib/route/link/inet6.c +++ b/lib/route/link/inet6.c @@ -9,11 +9,11 @@ * Copyright (c) 2010 Thomas Graf */ -#include +#include #include #include #include -#include +#include struct inet6_data { diff --git a/lib/route/link/vlan.c b/lib/route/link/vlan.c index a9bf955..4f44aa5 100644 --- a/lib/route/link/vlan.c +++ b/lib/route/link/vlan.c @@ -22,13 +22,13 @@ * @{ */ -#include +#include #include #include #include #include #include -#include +#include #include #include diff --git a/lib/route/neigh.c b/lib/route/neigh.c index 4a85a85..c0f80a2 100644 --- a/lib/route/neigh.c +++ b/lib/route/neigh.c @@ -148,7 +148,7 @@ * @{ */ -#include +#include #include #include #include diff --git a/lib/route/neightbl.c b/lib/route/neightbl.c index 509617b..f9c9c27 100644 --- a/lib/route/neightbl.c +++ b/lib/route/neightbl.c @@ -16,7 +16,7 @@ * @{ */ -#include +#include #include #include #include diff --git a/lib/route/nexthop.c b/lib/route/nexthop.c index 9990c51..d3ca499 100644 --- a/lib/route/nexthop.c +++ b/lib/route/nexthop.c @@ -15,7 +15,7 @@ * @{ */ -#include +#include #include #include #include diff --git a/lib/route/pktloc.c b/lib/route/pktloc.c index 70d552b..9fcf4a4 100644 --- a/lib/route/pktloc.c +++ b/lib/route/pktloc.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2008-2011 Thomas Graf + * Copyright (c) 2008-2013 Thomas Graf */ /** @@ -31,8 +31,8 @@ * @{ */ -#include -#include +#include +#include #include #include #include diff --git a/lib/route/pktloc_grammar.l b/lib/route/pktloc_grammar.l index 6b7a933..cbb42b3 100644 --- a/lib/route/pktloc_grammar.l +++ b/lib/route/pktloc_grammar.l @@ -1,6 +1,6 @@ %{ - #include - #include + #include + #include #include #include #include diff --git a/lib/route/pktloc_syntax.y b/lib/route/pktloc_syntax.y index 4a2ce48..25d8710 100644 --- a/lib/route/pktloc_syntax.y +++ b/lib/route/pktloc_syntax.y @@ -1,6 +1,6 @@ %{ -#include -#include +#include +#include #include #include #include diff --git a/lib/route/qdisc.c b/lib/route/qdisc.c index 3d618c6..250d191 100644 --- a/lib/route/qdisc.c +++ b/lib/route/qdisc.c @@ -15,12 +15,12 @@ * @{ */ -#include -#include +#include +#include #include #include #include -#include +#include #include #include #include diff --git a/lib/route/qdisc/blackhole.c b/lib/route/qdisc/blackhole.c index 06f5380..339cf78 100644 --- a/lib/route/qdisc/blackhole.c +++ b/lib/route/qdisc/blackhole.c @@ -15,9 +15,9 @@ * @{ */ -#include +#include #include -#include +#include static struct rtnl_tc_ops blackhole_ops = { .to_kind = "blackhole", diff --git a/lib/route/qdisc/cbq.c b/lib/route/qdisc/cbq.c index e791a10..95f1761 100644 --- a/lib/route/qdisc/cbq.c +++ b/lib/route/qdisc/cbq.c @@ -9,11 +9,11 @@ * Copyright (c) 2003-2011 Thomas Graf */ -#include -#include +#include +#include #include #include -#include +#include #include #include #include diff --git a/lib/route/qdisc/dsmark.c b/lib/route/qdisc/dsmark.c index b5fd0d6..fd9553d 100644 --- a/lib/route/qdisc/dsmark.c +++ b/lib/route/qdisc/dsmark.c @@ -16,12 +16,12 @@ * @{ */ -#include -#include +#include +#include #include #include #include -#include +#include #include #include diff --git a/lib/route/qdisc/fifo.c b/lib/route/qdisc/fifo.c index e87c79a..d94c007 100644 --- a/lib/route/qdisc/fifo.c +++ b/lib/route/qdisc/fifo.c @@ -29,10 +29,10 @@ * @{ */ -#include -#include +#include +#include #include -#include +#include #include #include #include diff --git a/lib/route/qdisc/htb.c b/lib/route/qdisc/htb.c index 9fb0bf6..5a61a4e 100644 --- a/lib/route/qdisc/htb.c +++ b/lib/route/qdisc/htb.c @@ -18,12 +18,12 @@ * @{ */ -#include -#include +#include +#include #include #include #include -#include +#include #include #include #include diff --git a/lib/route/qdisc/netem.c b/lib/route/qdisc/netem.c index ddd404d..06d9fe8 100644 --- a/lib/route/qdisc/netem.c +++ b/lib/route/qdisc/netem.c @@ -18,11 +18,11 @@ * @{ */ -#include -#include +#include +#include #include #include -#include +#include #include #include diff --git a/lib/route/qdisc/plug.c b/lib/route/qdisc/plug.c index a99b9be..9f53637 100644 --- a/lib/route/qdisc/plug.c +++ b/lib/route/qdisc/plug.c @@ -60,11 +60,11 @@ * @{ */ -#include -#include +#include +#include #include #include -#include +#include #include static int plug_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) diff --git a/lib/route/qdisc/prio.c b/lib/route/qdisc/prio.c index 2433c61..54a46f0 100644 --- a/lib/route/qdisc/prio.c +++ b/lib/route/qdisc/prio.c @@ -26,11 +26,11 @@ * @{ */ -#include -#include +#include +#include #include #include -#include +#include #include #include diff --git a/lib/route/qdisc/red.c b/lib/route/qdisc/red.c index 0480282..f05626e 100644 --- a/lib/route/qdisc/red.c +++ b/lib/route/qdisc/red.c @@ -16,11 +16,11 @@ * @{ */ -#include -#include +#include +#include #include #include -#include +#include #include #include diff --git a/lib/route/qdisc/sfq.c b/lib/route/qdisc/sfq.c index 207140f..acbb4ef 100644 --- a/lib/route/qdisc/sfq.c +++ b/lib/route/qdisc/sfq.c @@ -23,11 +23,11 @@ * @{ */ -#include -#include +#include +#include #include #include -#include +#include #include #include diff --git a/lib/route/qdisc/tbf.c b/lib/route/qdisc/tbf.c index a115548..eb574d9 100644 --- a/lib/route/qdisc/tbf.c +++ b/lib/route/qdisc/tbf.c @@ -15,12 +15,12 @@ * @{ */ -#include -#include +#include +#include #include #include #include -#include +#include #include #include #include diff --git a/lib/route/route.c b/lib/route/route.c index 2218a60..2985187 100644 --- a/lib/route/route.c +++ b/lib/route/route.c @@ -16,7 +16,7 @@ * @{ */ -#include +#include #include #include #include diff --git a/lib/route/route_obj.c b/lib/route/route_obj.c index 0c472b7..8f1e515 100644 --- a/lib/route/route_obj.c +++ b/lib/route/route_obj.c @@ -30,7 +30,7 @@ * @{ */ -#include +#include #include #include #include diff --git a/lib/route/route_utils.c b/lib/route/route_utils.c index 8b73f2b..a5b3966 100644 --- a/lib/route/route_utils.c +++ b/lib/route/route_utils.c @@ -37,7 +37,7 @@ * @{ */ -#include +#include #include #include #include diff --git a/lib/route/rtnl.c b/lib/route/rtnl.c index 12a7e97..82397e9 100644 --- a/lib/route/rtnl.c +++ b/lib/route/rtnl.c @@ -14,7 +14,7 @@ * @{ */ -#include +#include #include #include #include diff --git a/lib/route/rule.c b/lib/route/rule.c index 076ca51..b2161a2 100644 --- a/lib/route/rule.c +++ b/lib/route/rule.c @@ -16,7 +16,7 @@ * @{ */ -#include +#include #include #include #include diff --git a/lib/route/tc.c b/lib/route/tc.c index 5a0b783..29954fd 100644 --- a/lib/route/tc.c +++ b/lib/route/tc.c @@ -15,14 +15,14 @@ * @{ */ -#include -#include +#include +#include #include #include #include #include #include -#include +#include /** @cond SKIP */ diff --git a/lib/socket.c b/lib/socket.c index b30058b..d3e636e 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -29,7 +29,7 @@ #include "defs.h" -#include +#include #include #include #include diff --git a/lib/utils.c b/lib/utils.c index 5511189..3bfa604 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -24,7 +24,7 @@ * ~~~~ */ -#include +#include #include #include #include diff --git a/src/lib/tc.c b/src/lib/tc.c index 26124f1..dde729f 100644 --- a/src/lib/tc.c +++ b/src/lib/tc.c @@ -11,7 +11,7 @@ #include #include -#include +#include /** * @ingroup cli diff --git a/src/nl-list-caches.c b/src/nl-list-caches.c index 14cbab1..853d8a4 100644 --- a/src/nl-list-caches.c +++ b/src/nl-list-caches.c @@ -9,7 +9,7 @@ * Copyright (c) 2003-2009 Thomas Graf */ -#include +#include #include static void print_usage(void) From 1b9de9a49d02cf311a3dcf1d06fff4dea7794282 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 24 Jan 2013 14:03:52 +0100 Subject: [PATCH 389/432] Provide compat headers for removed private API Some projects seem to have mistakenly included the private API headers without actually needing them. Provide dummy headers referring to the real headers to provide backwards compatibility. Signed-off-by: Thomas Graf --- include/Makefile.am | 8 +++++++- include/netlink/cache-api.h | 20 ++++++++++++++++++++ include/netlink/object-api.h | 21 +++++++++++++++++++++ include/netlink/route/link/api.h | 20 ++++++++++++++++++++ include/netlink/route/link/info-api.h | 20 ++++++++++++++++++++ include/netlink/route/tc-api.h | 21 +++++++++++++++++++++ 6 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 include/netlink/cache-api.h create mode 100644 include/netlink/object-api.h create mode 100644 include/netlink/route/link/api.h create mode 100644 include/netlink/route/link/info-api.h create mode 100644 include/netlink/route/tc-api.h diff --git a/include/Makefile.am b/include/Makefile.am index 50f96b7..1e07fdb 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -71,7 +71,13 @@ nobase_libnlinclude_HEADERS = \ netlink/socket.h \ netlink/types.h \ netlink/utils.h \ - netlink/version.h + netlink/version.h \ + netlink/cache-api.h \ + netlink/object-api.h \ + netlink/route/link/api.h \ + netlink/route/link/info-api.h \ + netlink/route/tc-api.h + if ENABLE_CLI nobase_libnlinclude_HEADERS += \ diff --git a/include/netlink/cache-api.h b/include/netlink/cache-api.h new file mode 100644 index 0000000..e43c7ca --- /dev/null +++ b/include/netlink/cache-api.h @@ -0,0 +1,20 @@ +/* + * netlink/cache-api.h Caching API + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2013 Thomas Graf + */ + +#ifndef NETLINK_DUMMY_CACHE_API_H_ +#define NETLINK_DUMMY_CACHE_API_H_ + +#include +#include + +#warning "You are including a deprecated header file, include ." + +#endif diff --git a/include/netlink/object-api.h b/include/netlink/object-api.h new file mode 100644 index 0000000..6f8f010 --- /dev/null +++ b/include/netlink/object-api.h @@ -0,0 +1,21 @@ +/* + * netlink/object-api.h Object API + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2013 Thomas Graf + */ + +#ifndef NETLINK_DUMMY_OBJECT_API_H_ +#define NETLINK_DUMMY_OBJECT_API_H_ + +#include +#include +#include + +#warning "You are including a deprecated header file, include ." + +#endif diff --git a/include/netlink/route/link/api.h b/include/netlink/route/link/api.h new file mode 100644 index 0000000..03b1e5e --- /dev/null +++ b/include/netlink/route/link/api.h @@ -0,0 +1,20 @@ +/* + * netlink/route/link/api.h Link Modules API + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2013 Thomas Graf + */ + +#ifndef NETLINK_DUMMY_LINK_API_H_ +#define NETLINK_DUMMY_LINK_API_H_ + +#include +#include + +#warning "You are including a deprecated header file, include ." + +#endif diff --git a/include/netlink/route/link/info-api.h b/include/netlink/route/link/info-api.h new file mode 100644 index 0000000..1087ad4 --- /dev/null +++ b/include/netlink/route/link/info-api.h @@ -0,0 +1,20 @@ +/* + * netlink/route/link/info-api.h Link Modules API + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2013 Thomas Graf + */ + +#ifndef NETLINK_DUMMY_LINK_INFO_API_H_ +#define NETLINK_DUMMY_LINK_INFO_API_H_ + +#include +#include + +#warning "You are including a deprecated header file, include ." + +#endif diff --git a/include/netlink/route/tc-api.h b/include/netlink/route/tc-api.h new file mode 100644 index 0000000..b7771b5 --- /dev/null +++ b/include/netlink/route/tc-api.h @@ -0,0 +1,21 @@ +/* + * netlink/route/tc-api.h Traffic Control API + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2013 Thomas Graf + */ + +#ifndef NETLINK_DUMMY_TC_API_H_ +#define NETLINK_DUMMY_TC_API_H_ + +#include +#include +#include + +#warning "You are including a deprecated header file, include ." + +#endif From c6abb44e383948e173c4da280b5c8849e33d8269 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 24 Jan 2013 14:05:48 +0100 Subject: [PATCH 390/432] Fix test-cache-mngr test Needs to include Reported-by: Jeroen Roovers Signed-off-by: Thomas Graf --- tests/test-cache-mngr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test-cache-mngr.c b/tests/test-cache-mngr.c index da17018..8999e58 100644 --- a/tests/test-cache-mngr.c +++ b/tests/test-cache-mngr.c @@ -3,6 +3,8 @@ #include #include +#include + static int quit = 0; static struct nl_dump_params dp = { From c4f803366e7519f90075d08a29eacc6ab8d78bed Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 24 Jan 2013 14:10:33 +0100 Subject: [PATCH 391/432] Fix build warnings of nl-(qdisc|class|cls)-add Reported-by: Jeroen Roovers Signed-off-by: Thomas Graf --- src/nl-class-add.c | 2 ++ src/nl-cls-add.c | 2 ++ src/nl-qdisc-add.c | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/nl-class-add.c b/src/nl-class-add.c index 9698f0d..b9a17dc 100644 --- a/src/nl-class-add.c +++ b/src/nl-class-add.c @@ -15,6 +15,8 @@ #include #include +#include + static int quiet = 0; static void print_usage(void) diff --git a/src/nl-cls-add.c b/src/nl-cls-add.c index 054bab3..6acb320 100644 --- a/src/nl-cls-add.c +++ b/src/nl-cls-add.c @@ -13,6 +13,8 @@ #include #include +#include + static int quiet = 0; static void print_usage(void) diff --git a/src/nl-qdisc-add.c b/src/nl-qdisc-add.c index dd2ed2b..c2a7c9f 100644 --- a/src/nl-qdisc-add.c +++ b/src/nl-qdisc-add.c @@ -14,6 +14,8 @@ #include #include +#include + static int quiet = 0; static void print_usage(void) From 776cde0a10df271e7c9e3b5e192b511c270d67a7 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 24 Jan 2013 14:29:18 +0100 Subject: [PATCH 392/432] Remove obsolete warning from as it breaks NM build NM uses -Werror=cpp thus the build breaks if we emit #warning upon inclusion of Signed-off-by: Thomas Graf --- include/netlink/object-api.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/netlink/object-api.h b/include/netlink/object-api.h index 6f8f010..75f29cb 100644 --- a/include/netlink/object-api.h +++ b/include/netlink/object-api.h @@ -16,6 +16,4 @@ #include #include -#warning "You are including a deprecated header file, include ." - #endif From b6afd0bf1aee1abcf71ff48e223e9ff627d56092 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 24 Jan 2013 14:34:22 +0100 Subject: [PATCH 393/432] Provide better help text when bumping CURRENT,AGE,REVISION Signed-off-by: Thomas Graf --- configure.ac | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/configure.ac b/configure.ac index 9599476..7654b70 100644 --- a/configure.ac +++ b/configure.ac @@ -16,23 +16,23 @@ m4_define([libnl_minor_version], [2]) m4_define([libnl_micro_version], [20]) -# If either revision or age are omitted, they default to 0. Also note that age -# must be less than or equal to the current interface number. +# The following explanation may help to understand the above rules a bit +# better: consider that there are three possible kinds of reactions from +# users of your library to changes in a shared library: # -# Here are a set of rules to help you update your library version information: +# 1. Programs using the previous version may use the new version as drop-in +# replacement, and programs using the new version can also work with the +# previous one. In other words, no recompiling nor relinking is needed. +# In this case, bump revision only, don't touch current nor age. # -# 1. Start with version information of `0:0:0' for each libtool library. -# 2. Update the version information only immediately before a public release -# of your software. More frequent updates are unnecessary, and only -# guarantee that the current interface number gets larger faster. -# 3. If the library source code has changed at all since the last update, then -# increment revision (`c:r:a' becomes `c:r+1:a'). -# 4. If any interfaces have been added, removed, or changed since the last -# update, increment current, and set revision to 0. -# 5. If any interfaces have been added since the last public release, then -# increment age. -# 6. If any interfaces have been removed since the last public release, then -# set age to 0. +# 2. Programs using the previous version may use the new version as drop-in +# replacement, but programs using the new version may use APIs not +# present in the previous one. In other words, a program linking against +# the new version may fail with “unresolved symbols” if linking against +# the old version at runtime: set revision to 0, bump current and age. +# +# 3. Programs may need to be changed, recompiled, relinked in order to use +# the new version. Bump current, set revision and age to 0. m4_define([libnl_lt_current], [216]) m4_define([libnl_lt_revision], [0]) From 83c762d7cf6a6c54831e8d684b22804f497704c4 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 24 Jan 2013 15:00:26 +0100 Subject: [PATCH 394/432] 3.2.21 release --- configure.ac | 6 +++--- doc/configure.ac | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index 7654b70..66f4f7b 100644 --- a/configure.ac +++ b/configure.ac @@ -6,14 +6,14 @@ # License as published by the Free Software Foundation version 2.1 # of the License. # -# Copyright (c) 2003-2012 Thomas Graf +# Copyright (c) 2003-2013 Thomas Graf # # copied from glib m4_define([libnl_major_version], [3]) m4_define([libnl_minor_version], [2]) -m4_define([libnl_micro_version], [20]) +m4_define([libnl_micro_version], [21]) # The following explanation may help to understand the above rules a bit @@ -35,7 +35,7 @@ m4_define([libnl_micro_version], [20]) # the new version. Bump current, set revision and age to 0. m4_define([libnl_lt_current], [216]) -m4_define([libnl_lt_revision], [0]) +m4_define([libnl_lt_revision], [1]) m4_define([libnl_lt_age], [16]) m4_define([libnl_version], diff --git a/doc/configure.ac b/doc/configure.ac index 1316f23..4c3a52f 100644 --- a/doc/configure.ac +++ b/doc/configure.ac @@ -6,10 +6,10 @@ # License as published by the Free Software Foundation version 2.1 # of the License. # -# Copyright (c) 2003-2012 Thomas Graf +# Copyright (c) 2003-2013 Thomas Graf # -AC_INIT(libnl-doc, [3.2.20], [http://www.infradead.org/~tgr/libnl/]) +AC_INIT(libnl-doc, [3.2.21], [http://www.infradead.org/~tgr/libnl/]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_AUX_DIR([build-aux]) AM_INIT_AUTOMAKE([foreign]) From 87244f739c60522dae305b82a0ad7e864b1401ae Mon Sep 17 00:00:00 2001 From: Rich Fought Date: Thu, 24 Jan 2013 08:18:35 -0800 Subject: [PATCH 395/432] netfilter: keep 8-bit API for 32-bit NAT dir attribute --- include/netlink/netfilter/exp.h | 4 ++-- lib/netfilter/exp_obj.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/netlink/netfilter/exp.h b/include/netlink/netfilter/exp.h index 761d3d5..4e95014 100644 --- a/include/netlink/netfilter/exp.h +++ b/include/netlink/netfilter/exp.h @@ -92,9 +92,9 @@ extern int nfnl_exp_set_fn(struct nfnl_exp *, void *); extern int nfnl_exp_test_fn(const struct nfnl_exp *); extern const char * nfnl_exp_get_fn(const struct nfnl_exp *); -extern void nfnl_exp_set_nat_dir(struct nfnl_exp *, uint32_t); +extern void nfnl_exp_set_nat_dir(struct nfnl_exp *, uint8_t); extern int nfnl_exp_test_nat_dir(const struct nfnl_exp *); -extern uint32_t nfnl_exp_get_nat_dir(const struct nfnl_exp *); +extern uint8_t nfnl_exp_get_nat_dir(const struct nfnl_exp *); // The int argument specifies which nfnl_exp_dir (expect, master, mask or nat) // Expectation objects only use orig, not reply diff --git a/lib/netfilter/exp_obj.c b/lib/netfilter/exp_obj.c index 71caeda..182df23 100644 --- a/lib/netfilter/exp_obj.c +++ b/lib/netfilter/exp_obj.c @@ -589,7 +589,7 @@ const char * nfnl_exp_get_fn(const struct nfnl_exp *exp) return exp->exp_fn; } -void nfnl_exp_set_nat_dir(struct nfnl_exp *exp, uint32_t nat_dir) +void nfnl_exp_set_nat_dir(struct nfnl_exp *exp, uint8_t nat_dir) { exp->exp_nat_dir = nat_dir; exp->ce_mask |= EXP_ATTR_NAT_DIR; @@ -600,7 +600,7 @@ int nfnl_exp_test_nat_dir(const struct nfnl_exp *exp) return !!(exp->ce_mask & EXP_ATTR_NAT_DIR); } -uint32_t nfnl_exp_get_nat_dir(const struct nfnl_exp *exp) +uint8_t nfnl_exp_get_nat_dir(const struct nfnl_exp *exp) { return exp->exp_nat_dir; } From 6cc5fdc0e915c76d43055bf58e1e133f6ad2f1c8 Mon Sep 17 00:00:00 2001 From: Benedikt Spranger Date: Fri, 25 Jan 2013 16:50:32 +0100 Subject: [PATCH 396/432] can: add helper function to get CAN bus state Add a helper function to get the CAN bus state. Signed-off-by: Benedikt Spranger --- include/netlink/route/link/can.h | 1 + lib/route/link/can.c | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/include/netlink/route/link/can.h b/include/netlink/route/link/can.h index 90296f1..61c9f47 100644 --- a/include/netlink/route/link/can.h +++ b/include/netlink/route/link/can.h @@ -27,6 +27,7 @@ extern int rtnl_link_can_str2ctrlmode(const char *); extern int rtnl_link_can_restart(struct rtnl_link *); extern int rtnl_link_can_freq(struct rtnl_link *, uint32_t *); +extern int rtnl_link_can_state(struct rtnl_link *, uint32_t *); extern int rtnl_link_can_berr_rx(struct rtnl_link *); extern int rtnl_link_can_berr_tx(struct rtnl_link *); diff --git a/lib/route/link/can.c b/lib/route/link/can.c index 76bfa1a..307dec0 100644 --- a/lib/route/link/can.c +++ b/lib/route/link/can.c @@ -404,6 +404,25 @@ int rtnl_link_can_freq(struct rtnl_link *link, uint32_t *freq) return 0; } +/** + * Get CAN state + * @arg link Link object + * @arg state CAN bus state + * @return 0 on success or a negative error code + */ +int rtnl_link_can_state(struct rtnl_link *link, uint32_t *state) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + if (!state) + return -NLE_INVAL; + + *state = ci->ci_state; + + return 0; +} + /** * Get CAN RX bus error count * @arg link Link object From 4f088d38aecd86f5377287f8a0ad8534fe441ad9 Mon Sep 17 00:00:00 2001 From: Rich Fought Date: Tue, 29 Jan 2013 15:10:01 -0800 Subject: [PATCH 397/432] netfilter: correct error in construction of NAT tuple --- lib/netfilter/exp.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/netfilter/exp.c b/lib/netfilter/exp.c index a348f99..86ed8d1 100644 --- a/lib/netfilter/exp.c +++ b/lib/netfilter/exp.c @@ -351,7 +351,11 @@ static int nfnl_exp_build_tuple(struct nl_msg *msg, const struct nfnl_exp *exp, int type = exp_get_tuple_attr(cta); - tuple = nla_nest_start(msg, cta); + if (cta == CTA_EXPECT_NAT) + tuple = nla_nest_start(msg, CTA_EXPECT_NAT_TUPLE); + else + tuple = nla_nest_start(msg, cta); + if (!tuple) goto nla_put_failure; @@ -420,7 +424,7 @@ static int nfnl_exp_build_nat(struct nl_msg *msg, const struct nfnl_exp *exp) nfnl_exp_get_nat_dir(exp)); } - if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_NAT_TUPLE)) < 0) + if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_NAT)) < 0) goto nla_put_failure; nla_nest_end(msg, nat); From b06c23a9dd6e93fc7325421897dbaa81af7a9e8c Mon Sep 17 00:00:00 2001 From: roopa Date: Mon, 28 Jan 2013 07:46:16 -0800 Subject: [PATCH 398/432] link cache: remove AF_UNSPEC check in rtnl_get_link and rtnl_get_link_by_name This patch reverts back the AF_UNSPEC check introduced by AF_BRIDGE changes at http://lists.infradead.org/pipermail/libnl/2012-November/000796.html After the addition of AF_BRIDGE support, link cache can now contain objects of type AF_BRIDGE. To make sure existing api's did not return AF_BRIDGE objects and surprise existing callers, I introduced the check for AF_UNSPEC. But from what Andy Wang reported, rtnl_link_get_by_name returns the first link object with matching ifindex and that could have not only been AF_UNSPEC but also of family AF_INET6. And his app always got an AF_INET6 object prior to the patch that introduced the AF_UNSPEC check. I could just add AF_INET6 family check along with AF_UNSPEC in the apis and that should work well. But thinking about it some more, removing the AF_UNSPEC change seems to be safer at this point. That way this api will retain its semantics and return the first object with matching ifindex. It could be of any supported family. The user will know if the cache contains bridge objects, because they are available only with the cache flag NL_CACHE_AF_ITER. Besides, if new users want to search for a specific object, nl_cache_find is a better option. Reported-by: Andy Wang Signed-off-by: Roopa Prabhu Signed-off-by: Thomas Graf --- lib/route/link.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/route/link.c b/lib/route/link.c index 3171513..8b5227e 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -986,7 +986,7 @@ struct rtnl_link *rtnl_link_get(struct nl_cache *cache, int ifindex) return NULL; nl_list_for_each_entry(link, &cache->c_items, ce_list) { - if (link->l_family == AF_UNSPEC && link->l_index == ifindex) { + if (link->l_index == ifindex) { nl_object_get((struct nl_object *) link); return link; } @@ -1019,8 +1019,7 @@ struct rtnl_link *rtnl_link_get_by_name(struct nl_cache *cache, return NULL; nl_list_for_each_entry(link, &cache->c_items, ce_list) { - if (link->l_family == AF_UNSPEC && - !strcmp(name, link->l_name)) { + if (!strcmp(name, link->l_name)) { nl_object_get((struct nl_object *) link); return link; } From 87458abbd03b0928b9d2ddd84b7bcb07892450d0 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 31 Jan 2013 10:59:10 +0100 Subject: [PATCH 399/432] Fix mask calculation in nl_addr_cmp_prefix() Signed-off-by: Malte Langermann Signed-off-by: Thomas Graf --- lib/addr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/addr.c b/lib/addr.c index 806664b..9089be8 100644 --- a/lib/addr.c +++ b/lib/addr.c @@ -525,8 +525,8 @@ int nl_addr_cmp_prefix(struct nl_addr *a, struct nl_addr *b) int bytes = len / 8; d = memcmp(a->a_addr, b->a_addr, bytes); - if (d == 0) { - int mask = (1UL << (len % 8)) - 1UL; + if (d == 0 && (len % 8) != 0) { + int mask = (0xFF00 >> (len % 8)) & 0xFF; d = (a->a_addr[bytes] & mask) - (b->a_addr[bytes] & mask); From 2005c2ecacdf5e1ba5be630c85f1288eeb8ad6af Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 1 Feb 2013 10:21:58 +0100 Subject: [PATCH 400/432] cache: Make NL_ACT_* and nl_cache_ops_(get|put)() available Move NL_ACT_* definition and the functions nl_cache_ops_get() and nl_cache_ops_put() into the public facing API. They can be considered stable. Signed-off-by: Thomas Graf --- include/netlink-private/cache-api.h | 15 --------------- include/netlink/cache.h | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/include/netlink-private/cache-api.h b/include/netlink-private/cache-api.h index 5d9b0ad..f3d9f01 100644 --- a/include/netlink-private/cache-api.h +++ b/include/netlink-private/cache-api.h @@ -109,18 +109,6 @@ extern "C" { * @{ */ -enum { - NL_ACT_UNSPEC, - NL_ACT_NEW, - NL_ACT_DEL, - NL_ACT_GET, - NL_ACT_SET, - NL_ACT_CHANGE, - __NL_ACT_MAX, -}; - -#define NL_ACT_MAX (__NL_ACT_MAX - 1) - #define END_OF_MSGTYPES_LIST { -1, -1, NULL } /** @@ -273,9 +261,6 @@ struct nl_cache_ops struct nl_msgtype co_msgtypes[]; }; -extern void nl_cache_ops_get(struct nl_cache_ops *); -extern void nl_cache_ops_put(struct nl_cache_ops *); - /** @} */ #ifdef __cplusplus diff --git a/include/netlink/cache.h b/include/netlink/cache.h index 0da1377..415bb00 100644 --- a/include/netlink/cache.h +++ b/include/netlink/cache.h @@ -21,6 +21,18 @@ extern "C" { #endif +enum { + NL_ACT_UNSPEC, + NL_ACT_NEW, + NL_ACT_DEL, + NL_ACT_GET, + NL_ACT_SET, + NL_ACT_CHANGE, + __NL_ACT_MAX, +}; + +#define NL_ACT_MAX (__NL_ACT_MAX - 1) + struct nl_cache; typedef void (*change_func_t)(struct nl_cache *, struct nl_object *, int, void *); @@ -146,6 +158,9 @@ extern void nl_cache_mngr_info(struct nl_cache_mngr *, struct nl_dump_params *); extern void nl_cache_mngr_free(struct nl_cache_mngr *); +extern void nl_cache_ops_get(struct nl_cache_ops *); +extern void nl_cache_ops_put(struct nl_cache_ops *); + #ifdef __cplusplus } #endif From 8571f58f23763d8db7365d02c9b27832ad3d7005 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 1 Feb 2013 10:41:45 +0100 Subject: [PATCH 401/432] neigh: Remove check for AF_UNSPEC in rtnl_neigh_get() This check was introduces to not accidently return AF_BRIDGE objects to unaware API users as they do differ in structure. However, such objects are only available if explicitely requests using the NL_CACHE_AF_ITER flag or by using arg1 == AF_BRIDGE for the cache. Therefore remove this check and allow rtnl_neigh_get() to be used to fetch any neighbor object of a cache. Reported-by: Maxime Bizon Signed-off-by: Thomas Graf --- lib/route/neigh.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/route/neigh.c b/lib/route/neigh.c index c0f80a2..288bb85 100644 --- a/lib/route/neigh.c +++ b/lib/route/neigh.c @@ -532,6 +532,7 @@ int rtnl_neigh_alloc_cache(struct nl_sock *sock, struct nl_cache **result) * @arg cache neighbour cache * @arg ifindex interface index the neighbour is on * @arg dst destination address of the neighbour + * * @return neighbour handle or NULL if no match was found. */ struct rtnl_neigh * rtnl_neigh_get(struct nl_cache *cache, int ifindex, @@ -540,8 +541,7 @@ struct rtnl_neigh * rtnl_neigh_get(struct nl_cache *cache, int ifindex, struct rtnl_neigh *neigh; nl_list_for_each_entry(neigh, &cache->c_items, ce_list) { - if (neigh->n_family == AF_UNSPEC && - neigh->n_ifindex == ifindex && + if (neigh->n_ifindex == ifindex && !nl_addr_cmp(neigh->n_dst, dst)) { nl_object_get((struct nl_object *) neigh); return neigh; From 1c244801801abaa67921ea9ca4e9ad6a91d18e53 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 1 Feb 2013 10:51:33 +0100 Subject: [PATCH 402/432] can: Include "linux/can/netlink.h" in the distribution Needed to compile if local kernel headers are outdated. Signed-off-by: Thomas Graf --- include/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/include/Makefile.am b/include/Makefile.am index 1e07fdb..af1c136 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -108,6 +108,7 @@ noinst_HEADERS = \ linux/inetdevice.h \ linux/ip_mp_alg.h \ linux/ipv6.h \ + linux/can/netlink.h \ linux/neighbour.h \ linux/netfilter.h \ linux/netfilter/nf_conntrack_common.h \ From 506020ae99377ce45992d225e3b2917ee7b45b77 Mon Sep 17 00:00:00 2001 From: Holger Dengler Date: Fri, 1 Feb 2013 11:56:47 +0100 Subject: [PATCH 403/432] can: Fix nested message creation in can_put_attrs() Signed-off-by: Benedikt Spranger Signed-off-by: Holger Dengler Signed-off-by: Thomas Graf --- lib/route/link/can.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/route/link/can.c b/lib/route/link/can.c index 307dec0..60da42d 100644 --- a/lib/route/link/can.c +++ b/lib/route/link/can.c @@ -321,6 +321,8 @@ static int can_put_attrs(struct nl_msg *msg, struct rtnl_link *link) NLA_PUT(msg, CAN_HAS_CLOCK, sizeof(ci->ci_clock), &ci->ci_clock); + nla_nest_end(msg, data); + nla_put_failure: return 0; From 8b8e26b33304c56370096cecbe58fdb3ede318c2 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 5 Feb 2013 13:03:02 +0100 Subject: [PATCH 404/432] link: Fix af_ops leak on ENOMEM Signed-off-by: Thomas Graf --- lib/route/link.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/route/link.c b/lib/route/link.c index 8b5227e..e395529 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -72,8 +72,10 @@ static struct rtnl_link_af_ops *af_lookup_and_alloc(struct rtnl_link *link, if (!af_ops) return NULL; - if (!(data = rtnl_link_af_alloc(link, af_ops))) + if (!(data = rtnl_link_af_alloc(link, af_ops))) { + rtnl_link_af_ops_put(af_ops); return NULL; + } return af_ops; } From 2d36371aa1ff7d3ecf18e6ca93a8b5fd9c1e8f0e Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 5 Feb 2013 13:18:25 +0100 Subject: [PATCH 405/432] link: Keep reference to af_ops during lifetime of link object Signed-off-by: Thomas Graf --- include/netlink-private/types.h | 2 ++ lib/route/link.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/include/netlink-private/types.h b/include/netlink-private/types.h index 60a3bce..89f6418 100644 --- a/include/netlink-private/types.h +++ b/include/netlink-private/types.h @@ -183,6 +183,8 @@ struct rtnl_link uint32_t l_num_rx_queues; uint32_t l_group; uint8_t l_carrier; + /* 3 byte hole */ + struct rtnl_link_af_ops * l_af_ops; }; struct rtnl_ncacheinfo diff --git a/lib/route/link.c b/lib/route/link.c index e395529..752f63a 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -201,6 +201,8 @@ static void link_free_data(struct nl_object *c) if ((io = link->l_info_ops) != NULL) release_link_info(link); + rtnl_link_af_ops_put(link->l_af_ops); + nl_addr_put(link->l_addr); nl_addr_put(link->l_bcast); @@ -313,6 +315,8 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, af_ops->ao_protinfo_policy, sizeof(struct nla_policy)); } + + link->l_af_ops = af_ops; } err = nlmsg_parse(n, sizeof(*ifi), tb, IFLA_MAX, link_policy); From e5767684a6cae113c2fc4b1b16798a1b51595ab4 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 5 Feb 2013 13:21:10 +0100 Subject: [PATCH 406/432] link: Modify link policy on the stack Signed-off-by: Thomas Graf --- lib/route/link.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/route/link.c b/lib/route/link.c index 752f63a..26bd3da 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -287,6 +287,9 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, struct nlattr *tb[IFLA_MAX+1]; struct rtnl_link_af_ops *af_ops = NULL; int err, family; + struct nla_policy real_link_policy[IFLA_MAX+1]; + + memcpy(&real_link_policy, link_policy, sizeof(link_policy)); link = rtnl_link_alloc(); if (link == NULL) { @@ -311,7 +314,7 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, if ((af_ops = af_lookup_and_alloc(link, family))) { if (af_ops->ao_protinfo_policy) { - memcpy(&link_policy[IFLA_PROTINFO], + memcpy(&real_link_policy[IFLA_PROTINFO], af_ops->ao_protinfo_policy, sizeof(struct nla_policy)); } @@ -319,7 +322,7 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, link->l_af_ops = af_ops; } - err = nlmsg_parse(n, sizeof(*ifi), tb, IFLA_MAX, link_policy); + err = nlmsg_parse(n, sizeof(*ifi), tb, IFLA_MAX, real_link_policy); if (err < 0) goto errout; From 4a793a4235585d88a9e5f6e413bf59cf1abdd3db Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 5 Feb 2013 13:46:42 +0100 Subject: [PATCH 407/432] link: Hold af_ops reference for each AF_SPEC block during lifetime of link object Signed-off-by: Thomas Graf --- lib/route/link.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/route/link.c b/lib/route/link.c index 26bd3da..99c5013 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -171,7 +171,11 @@ static int do_foreach_af(struct rtnl_link *link, if (!(ops = rtnl_link_af_ops_lookup(i))) BUG(); - if ((err = cb(link, ops, link->l_af_data[i], arg)) < 0) + err = cb(link, ops, link->l_af_data[i], arg); + + rtnl_link_af_ops_put(ops); + + if (err < 0) return err; } } @@ -201,6 +205,7 @@ static void link_free_data(struct nl_object *c) if ((io = link->l_info_ops) != NULL) release_link_info(link); + /* proto info af reference */ rtnl_link_af_ops_put(link->l_af_ops); nl_addr_put(link->l_addr); @@ -554,9 +559,6 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, char *af_data = link->l_af_data[nla_type(af_attr)]; err = af_ops->ao_parse_af(link, af_attr, af_data); - - rtnl_link_af_ops_put(af_ops); - if (err < 0) goto errout; } From 8026fe2e3a9089eff3f5a06ee6e3cc78d96334ed Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 5 Feb 2013 13:52:22 +0100 Subject: [PATCH 408/432] link: Free and realloc af specific data upon rtnl_link_set_family() Signed-off-by: Thomas Graf --- lib/route/link.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/route/link.c b/lib/route/link.c index 99c5013..7450545 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -1742,6 +1742,12 @@ void rtnl_link_set_family(struct rtnl_link *link, int family) { link->l_family = family; link->ce_mask |= LINK_ATTR_FAMILY; + + if (link->l_af_ops) + af_free(link, link->l_af_ops, + link->l_af_data[link->l_af_ops->ao_family], NULL); + + link->l_af_ops = af_lookup_and_alloc(link, family); } /** From 9f8548b5513a9e9aba52b417c4e36e817d68781f Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 5 Feb 2013 22:31:31 +0100 Subject: [PATCH 409/432] attr: Provide nla_is_nested() function Signed-off-by: Thomas Graf --- include/netlink/attr.h | 3 ++- lib/attr.c | 13 ++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/include/netlink/attr.h b/include/netlink/attr.h index 4d32113..69ecb08 100644 --- a/include/netlink/attr.h +++ b/include/netlink/attr.h @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2013 Thomas Graf */ #ifndef NETLINK_ATTR_H_ @@ -126,6 +126,7 @@ extern struct nlattr * nla_nest_start(struct nl_msg *, int); extern int nla_nest_end(struct nl_msg *, struct nlattr *); extern int nla_parse_nested(struct nlattr **, int, struct nlattr *, struct nla_policy *); +extern int nla_is_nested(struct nlattr *); /** * @name Attribute Construction (Exception Based) diff --git a/lib/attr.c b/lib/attr.c index 10ea682..26bece3 100644 --- a/lib/attr.c +++ b/lib/attr.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2013 Thomas Graf */ #include @@ -868,6 +868,17 @@ int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy); } +/** + * Return true if attribute has NLA_F_NESTED flag set + * @arg attr Netlink attribute + * + * @return True if attribute has NLA_F_NESTED flag set, oterhwise False. + */ +int nla_is_nested(struct nlattr *attr) +{ + return !!(nla_type(attr) & NLA_F_NESTED); +} + /** @} */ /** @} */ From fd19dae352d761760bc161a81a98bc14cbe99733 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 5 Feb 2013 22:41:26 +0100 Subject: [PATCH 410/432] bridge: Support the new bridging attributes This provides support for the new bridging attributes provided in IFLA_PROTINFO while maintaining backwards compatibility with older kernels. A set of new API functions are exported to access the bridging information. rtnl_link_bridge_has_ext_info() can be used to check whether a bridge object has been constructed based on the newly available attributes or the old message format. Signed-off-by: Thomas Graf --- include/Makefile.am | 2 + include/linux/if_bridge.h | 185 ++++++++++++++ include/linux/if_link.h | 80 ++++-- include/netlink/route/link/bridge.h | 54 ++++ lib/route/link/bridge.c | 374 +++++++++++++++++++++++++++- 5 files changed, 668 insertions(+), 27 deletions(-) create mode 100644 include/linux/if_bridge.h create mode 100644 include/netlink/route/link/bridge.h diff --git a/include/Makefile.am b/include/Makefile.am index af1c136..3488c52 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -42,6 +42,7 @@ nobase_libnlinclude_HEADERS = \ netlink/route/cls/police.h \ netlink/route/cls/u32.h \ netlink/route/link/bonding.h \ + netlink/route/link/bridge.h \ netlink/route/link/can.h \ netlink/route/link/inet.h \ netlink/route/link/vlan.h \ @@ -103,6 +104,7 @@ noinst_HEADERS = \ linux/if_arp.h \ linux/if_ether.h \ linux/if.h \ + linux/if_bridge.h \ linux/if_link.h \ linux/if_vlan.h \ linux/inetdevice.h \ diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h new file mode 100644 index 0000000..5db2975 --- /dev/null +++ b/include/linux/if_bridge.h @@ -0,0 +1,185 @@ +/* + * Linux ethernet bridge + * + * Authors: + * Lennert Buytenhek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _UAPI_LINUX_IF_BRIDGE_H +#define _UAPI_LINUX_IF_BRIDGE_H + +#include + +#define SYSFS_BRIDGE_ATTR "bridge" +#define SYSFS_BRIDGE_FDB "brforward" +#define SYSFS_BRIDGE_PORT_SUBDIR "brif" +#define SYSFS_BRIDGE_PORT_ATTR "brport" +#define SYSFS_BRIDGE_PORT_LINK "bridge" + +#define BRCTL_VERSION 1 + +#define BRCTL_GET_VERSION 0 +#define BRCTL_GET_BRIDGES 1 +#define BRCTL_ADD_BRIDGE 2 +#define BRCTL_DEL_BRIDGE 3 +#define BRCTL_ADD_IF 4 +#define BRCTL_DEL_IF 5 +#define BRCTL_GET_BRIDGE_INFO 6 +#define BRCTL_GET_PORT_LIST 7 +#define BRCTL_SET_BRIDGE_FORWARD_DELAY 8 +#define BRCTL_SET_BRIDGE_HELLO_TIME 9 +#define BRCTL_SET_BRIDGE_MAX_AGE 10 +#define BRCTL_SET_AGEING_TIME 11 +#define BRCTL_SET_GC_INTERVAL 12 +#define BRCTL_GET_PORT_INFO 13 +#define BRCTL_SET_BRIDGE_STP_STATE 14 +#define BRCTL_SET_BRIDGE_PRIORITY 15 +#define BRCTL_SET_PORT_PRIORITY 16 +#define BRCTL_SET_PATH_COST 17 +#define BRCTL_GET_FDB_ENTRIES 18 + +#define BR_STATE_DISABLED 0 +#define BR_STATE_LISTENING 1 +#define BR_STATE_LEARNING 2 +#define BR_STATE_FORWARDING 3 +#define BR_STATE_BLOCKING 4 + +struct __bridge_info { + __u64 designated_root; + __u64 bridge_id; + __u32 root_path_cost; + __u32 max_age; + __u32 hello_time; + __u32 forward_delay; + __u32 bridge_max_age; + __u32 bridge_hello_time; + __u32 bridge_forward_delay; + __u8 topology_change; + __u8 topology_change_detected; + __u8 root_port; + __u8 stp_enabled; + __u32 ageing_time; + __u32 gc_interval; + __u32 hello_timer_value; + __u32 tcn_timer_value; + __u32 topology_change_timer_value; + __u32 gc_timer_value; +}; + +struct __port_info { + __u64 designated_root; + __u64 designated_bridge; + __u16 port_id; + __u16 designated_port; + __u32 path_cost; + __u32 designated_cost; + __u8 state; + __u8 top_change_ack; + __u8 config_pending; + __u8 unused0; + __u32 message_age_timer_value; + __u32 forward_delay_timer_value; + __u32 hold_timer_value; +}; + +struct __fdb_entry { + __u8 mac_addr[6]; + __u8 port_no; + __u8 is_local; + __u32 ageing_timer_value; + __u8 port_hi; + __u8 pad0; + __u16 unused; +}; + +/* Bridge Flags */ +#define BRIDGE_FLAGS_MASTER 1 /* Bridge command to/from master */ +#define BRIDGE_FLAGS_SELF 2 /* Bridge command to/from lowerdev */ + +#define BRIDGE_MODE_VEB 0 /* Default loopback mode */ +#define BRIDGE_MODE_VEPA 1 /* 802.1Qbg defined VEPA mode */ + +/* Bridge management nested attributes + * [IFLA_AF_SPEC] = { + * [IFLA_BRIDGE_FLAGS] + * [IFLA_BRIDGE_MODE] + * } + */ +enum { + IFLA_BRIDGE_FLAGS, + IFLA_BRIDGE_MODE, + __IFLA_BRIDGE_MAX, +}; +#define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1) + +/* Bridge multicast database attributes + * [MDBA_MDB] = { + * [MDBA_MDB_ENTRY] = { + * [MDBA_MDB_ENTRY_INFO] + * } + * } + * [MDBA_ROUTER] = { + * [MDBA_ROUTER_PORT] + * } + */ +enum { + MDBA_UNSPEC, + MDBA_MDB, + MDBA_ROUTER, + __MDBA_MAX, +}; +#define MDBA_MAX (__MDBA_MAX - 1) + +enum { + MDBA_MDB_UNSPEC, + MDBA_MDB_ENTRY, + __MDBA_MDB_MAX, +}; +#define MDBA_MDB_MAX (__MDBA_MDB_MAX - 1) + +enum { + MDBA_MDB_ENTRY_UNSPEC, + MDBA_MDB_ENTRY_INFO, + __MDBA_MDB_ENTRY_MAX, +}; +#define MDBA_MDB_ENTRY_MAX (__MDBA_MDB_ENTRY_MAX - 1) + +enum { + MDBA_ROUTER_UNSPEC, + MDBA_ROUTER_PORT, + __MDBA_ROUTER_MAX, +}; +#define MDBA_ROUTER_MAX (__MDBA_ROUTER_MAX - 1) + +struct br_port_msg { + __u8 family; + __u32 ifindex; +}; + +struct br_mdb_entry { + __u32 ifindex; +#define MDB_TEMPORARY 0 +#define MDB_PERMANENT 1 + __u8 state; + struct { + union { + __be32 ip4; + struct in6_addr ip6; + } u; + __be16 proto; + } addr; +}; + +enum { + MDBA_SET_ENTRY_UNSPEC, + MDBA_SET_ENTRY, + __MDBA_SET_ENTRY_MAX, +}; +#define MDBA_SET_ENTRY_MAX (__MDBA_SET_ENTRY_MAX - 1) + +#endif /* _UAPI_LINUX_IF_BRIDGE_H */ diff --git a/include/linux/if_link.h b/include/linux/if_link.h index a753d11..73ee05c 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h @@ -1,5 +1,5 @@ -#ifndef _LINUX_IF_LINK_H -#define _LINUX_IF_LINK_H +#ifndef _UAPI_LINUX_IF_LINK_H +#define _UAPI_LINUX_IF_LINK_H #include #include @@ -200,6 +200,24 @@ enum { #define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1) +enum { + BRIDGE_MODE_UNSPEC, + BRIDGE_MODE_HAIRPIN, +}; + +enum { + IFLA_BRPORT_UNSPEC, + IFLA_BRPORT_STATE, /* Spanning tree state */ + IFLA_BRPORT_PRIORITY, /* " priority */ + IFLA_BRPORT_COST, /* " cost */ + IFLA_BRPORT_MODE, /* mode (hairpin) */ + IFLA_BRPORT_GUARD, /* bpdu guard */ + IFLA_BRPORT_PROTECT, /* root port protection */ + IFLA_BRPORT_FAST_LEAVE, /* multicast fast leave */ + __IFLA_BRPORT_MAX +}; +#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) + struct ifla_cacheinfo { __u32 max_reasm_len; __u32 tstamp; /* ipv6InterfaceTable updated timestamp */ @@ -267,6 +285,32 @@ enum macvlan_mode { #define MACVLAN_FLAG_NOPROMISC 1 +/* VXLAN section */ +enum { + IFLA_VXLAN_UNSPEC, + IFLA_VXLAN_ID, + IFLA_VXLAN_GROUP, + IFLA_VXLAN_LINK, + IFLA_VXLAN_LOCAL, + IFLA_VXLAN_TTL, + IFLA_VXLAN_TOS, + IFLA_VXLAN_LEARNING, + IFLA_VXLAN_AGEING, + IFLA_VXLAN_LIMIT, + IFLA_VXLAN_PORT_RANGE, + IFLA_VXLAN_PROXY, + IFLA_VXLAN_RSC, + IFLA_VXLAN_L2MISS, + IFLA_VXLAN_L3MISS, + __IFLA_VXLAN_MAX +}; +#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) + +struct ifla_vxlan_port_range { + __be16 low; + __be16 high; +}; + /* SR-IOV virtual function management section */ enum { @@ -308,18 +352,6 @@ struct ifla_vf_spoofchk { __u32 vf; __u32 setting; }; -#ifdef __KERNEL__ - -/* We don't want this structure exposed to user space */ -struct ifla_vf_info { - __u32 vf; - __u8 mac[32]; - __u32 vlan; - __u32 qos; - __u32 tx_rate; - __u32 spoofchk; -}; -#endif /* VF ports management section * @@ -393,4 +425,22 @@ struct ifla_port_vsi { __u8 pad[3]; }; -#endif /* _LINUX_IF_LINK_H */ + +/* IPoIB section */ + +enum { + IFLA_IPOIB_UNSPEC, + IFLA_IPOIB_PKEY, + IFLA_IPOIB_MODE, + IFLA_IPOIB_UMCAST, + __IFLA_IPOIB_MAX +}; + +enum { + IPOIB_MODE_DATAGRAM = 0, /* using unreliable datagram QPs */ + IPOIB_MODE_CONNECTED = 1, /* using connected QPs */ +}; + +#define IFLA_IPOIB_MAX (__IFLA_IPOIB_MAX - 1) + +#endif /* _UAPI_LINUX_IF_LINK_H */ diff --git a/include/netlink/route/link/bridge.h b/include/netlink/route/link/bridge.h new file mode 100644 index 0000000..5522fc0 --- /dev/null +++ b/include/netlink/route/link/bridge.h @@ -0,0 +1,54 @@ +/* + * netlink/route/link/bridge.h Bridge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2013 Thomas Graf + */ + +#ifndef NETLINK_LINK_BRIDGE_H_ +#define NETLINK_LINK_BRIDGE_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Bridge flags + * @ingroup bridge + */ +enum rtnl_link_bridge_flags { + RTNL_BRIDGE_HAIRPIN_MODE = 0x0001, + RTNL_BRIDGE_BPDU_GUARD = 0x0002, + RTNL_BRIDGE_ROOT_BLOCK = 0x0004, + RTNL_BRIDGE_FAST_LEAVE = 0x0008, +}; + +extern int rtnl_link_is_bridge(struct rtnl_link *); +extern int rtnl_link_bridge_has_ext_info(struct rtnl_link *); + +extern int rtnl_link_bridge_set_port_state(struct rtnl_link *, uint8_t ); +extern int rtnl_link_bridge_get_port_state(struct rtnl_link *); + +extern int rtnl_link_bridge_set_priority(struct rtnl_link *, uint16_t); +extern int rtnl_link_bridge_get_priority(struct rtnl_link *); + +extern int rtnl_link_bridge_set_cost(struct rtnl_link *, uint32_t); +extern int rtnl_link_bridge_get_cost(struct rtnl_link *, uint32_t *); + +extern int rtnl_link_bridge_unset_flags(struct rtnl_link *, unsigned int); +extern int rtnl_link_bridge_set_flags(struct rtnl_link *, unsigned int); +extern int rtnl_link_bridge_get_flags(struct rtnl_link *); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/lib/route/link/bridge.c b/lib/route/link/bridge.c index 52beedd..a306c9c 100644 --- a/lib/route/link/bridge.c +++ b/lib/route/link/bridge.c @@ -1,28 +1,62 @@ /* - * lib/route/link/bridge.c AF_BRIDGE link oeprations + * lib/route/link/bridge.c AF_BRIDGE link support * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2010 Thomas Graf + * Copyright (c) 2010-2013 Thomas Graf + */ + +/** + * @ingroup link + * @defgroup bridge Bridging + * + * @details + * @{ */ #include #include #include #include +#include #include +#include -#define BRIDGE_ATTR_PORT_STATE 0x0001 +/** @cond SKIP */ +#define BRIDGE_ATTR_PORT_STATE (1 << 0) +#define BRIDGE_ATTR_PRIORITY (1 << 1) +#define BRIDGE_ATTR_COST (1 << 2) +#define BRIDGE_ATTR_FLAGS (1 << 3) + +#define PRIV_FLAG_NEW_ATTRS (1 << 0) struct bridge_data { uint8_t b_port_state; + uint8_t b_priv_flags; /* internal flags */ + uint16_t b_priority; + uint32_t b_cost; + uint32_t b_flags; + uint32_t b_flags_mask; uint32_t ce_mask; /* HACK to support attr macros */ }; +static struct rtnl_link_af_ops bridge_ops; + +#define IS_BRIDGE_LINK_ASSERT(link) \ + if (!rtnl_link_is_bridge(link)) { \ + APPBUG("A function was expecting a link object of type bridge."); \ + return -NLE_OPNOTSUPP; \ + } + +static inline struct bridge_data *bridge_data(struct rtnl_link *link) +{ + return rtnl_link_af_data(link, &bridge_ops); +} + static void *bridge_alloc(struct rtnl_link *link) { return calloc(1, sizeof(struct bridge_data)); @@ -43,13 +77,66 @@ static void bridge_free(struct rtnl_link *link, void *data) free(data); } +static struct nla_policy br_attrs_policy[IFLA_BRPORT_MAX+1] = { + [IFLA_BRPORT_STATE] = { .type = NLA_U8 }, + [IFLA_BRPORT_PRIORITY] = { .type = NLA_U16 }, + [IFLA_BRPORT_COST] = { .type = NLA_U32 }, + [IFLA_BRPORT_MODE] = { .type = NLA_U8 }, + [IFLA_BRPORT_GUARD] = { .type = NLA_U8 }, + [IFLA_BRPORT_PROTECT] = { .type = NLA_U8 }, + [IFLA_BRPORT_FAST_LEAVE] = { .type = NLA_U8 }, +}; + +static void check_flag(struct rtnl_link *link, struct nlattr *attrs[], + int type, int flag) +{ + if (attrs[type] && nla_get_u8(attrs[type])) + rtnl_link_bridge_set_flags(link, flag); +} + static int bridge_parse_protinfo(struct rtnl_link *link, struct nlattr *attr, void *data) { struct bridge_data *bd = data; + struct nlattr *br_attrs[IFLA_BRPORT_MAX+1]; + int err; - bd->b_port_state = nla_get_u8(attr); - bd->ce_mask |= BRIDGE_ATTR_PORT_STATE; + /* Backwards compatibility */ + if (!nla_is_nested(attr)) { + if (nla_len(attr) < 1) + return -NLE_RANGE; + + bd->b_port_state = nla_get_u8(attr); + bd->ce_mask |= BRIDGE_ATTR_PORT_STATE; + + return 0; + } + + if ((err = nla_parse_nested(br_attrs, IFLA_BRPORT_MAX, attr, + br_attrs_policy)) < 0) + return err; + + bd->b_priv_flags |= PRIV_FLAG_NEW_ATTRS; + + if (br_attrs[IFLA_BRPORT_STATE]) { + bd->b_port_state = nla_get_u8(br_attrs[IFLA_BRPORT_STATE]); + bd->ce_mask |= BRIDGE_ATTR_PORT_STATE; + } + + if (br_attrs[IFLA_BRPORT_PRIORITY]) { + bd->b_priority = nla_get_u16(br_attrs[IFLA_BRPORT_PRIORITY]); + bd->ce_mask |= BRIDGE_ATTR_PRIORITY; + } + + if (br_attrs[IFLA_BRPORT_COST]) { + bd->b_cost = nla_get_u32(br_attrs[IFLA_BRPORT_COST]); + bd->ce_mask |= BRIDGE_ATTR_COST; + } + + check_flag(link, br_attrs, IFLA_BRPORT_MODE, RTNL_BRIDGE_HAIRPIN_MODE); + check_flag(link, br_attrs, IFLA_BRPORT_GUARD, RTNL_BRIDGE_BPDU_GUARD); + check_flag(link, br_attrs, IFLA_BRPORT_PROTECT, RTNL_BRIDGE_ROOT_BLOCK); + check_flag(link, br_attrs, IFLA_BRPORT_FAST_LEAVE, RTNL_BRIDGE_FAST_LEAVE); return 0; } @@ -59,27 +146,289 @@ static void bridge_dump_details(struct rtnl_link *link, { struct bridge_data *bd = data; + nl_dump_line(p, " bridge: "); + if (bd->ce_mask & BRIDGE_ATTR_PORT_STATE) nl_dump(p, "port-state %u ", bd->b_port_state); + + if (bd->ce_mask & BRIDGE_ATTR_PRIORITY) + nl_dump(p, "prio %u ", bd->b_priority); + + if (bd->ce_mask & BRIDGE_ATTR_COST) + nl_dump(p, "cost %u ", bd->b_cost); + + nl_dump(p, "\n"); } static int bridge_compare(struct rtnl_link *_a, struct rtnl_link *_b, int family, uint32_t attrs, int flags) { - struct bridge_data *a = (struct bridge_data *)_a->l_af_data; - struct bridge_data *b = (struct bridge_data *)_b->l_af_data; + struct bridge_data *a = bridge_data(_a); + struct bridge_data *b = bridge_data(_b); int diff = 0; #define BRIDGE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, BRIDGE_ATTR_##ATTR, a, b, EXPR) diff |= BRIDGE_DIFF(PORT_STATE, a->b_port_state != b->b_port_state); + diff |= BRIDGE_DIFF(PRIORITY, a->b_priority != b->b_priority); + diff |= BRIDGE_DIFF(COST, a->b_cost != b->b_cost); + + if (flags & LOOSE_COMPARISON) + diff |= BRIDGE_DIFF(FLAGS, + (a->b_flags ^ b->b_flags) & b->b_flags_mask); + else + diff |= BRIDGE_DIFF(FLAGS, a->b_flags != b->b_flags); +#undef BRIDGE_DIFF return diff; -#undef BRIDGE_DIFF +} +/** @endcond */ + +/** + * Check if a link is a bridge + * @arg link Link object + * + * @return 1 if the link is a bridge, 0 otherwise. + */ +int rtnl_link_is_bridge(struct rtnl_link *link) +{ + return link->l_family == AF_BRIDGE && + link->l_af_ops == &bridge_ops; } -static const struct nla_policy protinfo_policy = { - .type = NLA_U8, -}; +/** + * Check if bridge has extended information + * @arg link Link object of type bridge + * + * Checks if the bridge object has been constructed based on + * information that is only available in newer kernels. This + * affectes the following functions: + * - rtnl_link_bridge_get_cost() + * - rtnl_link_bridge_get_priority() + * - rtnl_link_bridge_get_flags() + * + * @return 1 if extended information is available, otherwise 0 is returned. + */ +int rtnl_link_bridge_has_ext_info(struct rtnl_link *link) +{ + struct bridge_data *bd; + + if (!rtnl_link_is_bridge(link)) + return 0; + + bd = bridge_data(link); + return !!(bd->b_priv_flags & PRIV_FLAG_NEW_ATTRS); +} + +/** + * Set Spanning Tree Protocol (STP) port state + * @arg link Link object of type bridge + * @arg state New STP port state + * + * The value of state must be one of the following: + * - BR_STATE_DISABLED + * - BR_STATE_LISTENING + * - BR_STATE_LEARNING + * - BR_STATE_FORWARDING + * - BR_STATE_BLOCKING + * + * @see rtnl_link_bridge_get_port_state() + * + * @return 0 on success or a negative error code. + * @retval -NLE_OPNOTSUPP Link is not a bridge + * @retval -NLE_INVAL Invalid state value (0..BR_STATE_BLOCKING) + */ +int rtnl_link_bridge_set_port_state(struct rtnl_link *link, uint8_t state) +{ + struct bridge_data *bd = bridge_data(link); + + IS_BRIDGE_LINK_ASSERT(link); + + if (state > BR_STATE_BLOCKING) + return -NLE_INVAL; + + bd->b_port_state = state; + bd->ce_mask |= BRIDGE_ATTR_PORT_STATE; + + return 0; +} + +/** + * Get Spanning Tree Protocol (STP) port state + * @arg link Link object of type bridge + * + * @see rtnl_link_bridge_set_port_state() + * + * @return The STP port state or a negative error code. + * @retval -NLE_OPNOTSUPP Link is not a bridge + */ +int rtnl_link_bridge_get_port_state(struct rtnl_link *link) +{ + struct bridge_data *bd = bridge_data(link); + + IS_BRIDGE_LINK_ASSERT(link); + + return bd->b_port_state; +} + +/** + * Set priority + * @arg link Link object of type bridge + * @arg prio Bridge priority + * + * @see rtnl_link_bridge_get_priority() + * + * @return 0 on success or a negative error code. + * @retval -NLE_OPNOTSUPP Link is not a bridge + */ +int rtnl_link_bridge_set_priority(struct rtnl_link *link, uint16_t prio) +{ + struct bridge_data *bd = bridge_data(link); + + IS_BRIDGE_LINK_ASSERT(link); + + bd->b_priority = prio; + bd->ce_mask |= BRIDGE_ATTR_PRIORITY; + + return 0; +} + +/** + * Get priority + * @arg link Link object of type bridge + * + * @see rtnl_link_bridge_set_priority() + * + * @return 0 on success or a negative error code. + * @retval -NLE_OPNOTSUPP Link is not a bridge + */ +int rtnl_link_bridge_get_priority(struct rtnl_link *link) +{ + struct bridge_data *bd = bridge_data(link); + + IS_BRIDGE_LINK_ASSERT(link); + + return bd->b_priority; +} + +/** + * Set Spanning Tree Protocol (STP) path cost + * @arg link Link object of type bridge + * @arg cost New STP path cost value + * + * @see rtnl_link_bridge_get_cost() + * + * @return The bridge priority or a negative error code. + * @retval -NLE_OPNOTSUPP Link is not a bridge + */ +int rtnl_link_bridge_set_cost(struct rtnl_link *link, uint32_t cost) +{ + struct bridge_data *bd = bridge_data(link); + + IS_BRIDGE_LINK_ASSERT(link); + + bd->b_cost = cost; + bd->ce_mask |= BRIDGE_ATTR_COST; + + return 0; +} + +/** + * Get Spanning Tree Protocol (STP) path cost + * @arg link Link object of type bridge + * @arg cost Pointer to store STP cost value + * + * @see rtnl_link_bridge_set_cost() + * + * @return 0 on success or a negative error code. + * @retval -NLE_OPNOTSUPP Link is not a bridge + * @retval -NLE_INVAL `cost` is not a valid pointer + */ +int rtnl_link_bridge_get_cost(struct rtnl_link *link, uint32_t *cost) +{ + struct bridge_data *bd = bridge_data(link); + + IS_BRIDGE_LINK_ASSERT(link); + + if (!cost) + return -NLE_INVAL; + + *cost = bd->b_cost; + + return 0; +} + +/** + * Unset flags + * @arg link Link object of type bridge + * @arg flags Bridging flags to unset + * + * @see rtnl_link_bridge_set_flags() + * @see rtnl_link_bridge_get_flags() + * + * @return 0 on success or a negative error code. + * @retval -NLE_OPNOTSUPP Link is not a bridge + */ +int rtnl_link_bridge_unset_flags(struct rtnl_link *link, unsigned int flags) +{ + struct bridge_data *bd = bridge_data(link); + + IS_BRIDGE_LINK_ASSERT(link); + + bd->b_flags_mask |= flags; + bd->b_flags &= ~flags; + bd->ce_mask |= BRIDGE_ATTR_FLAGS; + + return 0; +} + +/** + * Set flags + * @arg link Link object of type bridge + * @arg flags Bridging flags to set + * + * Valid flags are: + * - RTNL_BRIDGE_HAIRPIN_MODE + * - RTNL_BRIDGE_BPDU_GUARD + * - RTNL_BRIDGE_ROOT_BLOCK + * - RTNL_BRIDGE_FAST_LEAVE + * + * @see rtnl_link_bridge_unset_flags() + * @see rtnl_link_bridge_get_flags() + * + * @return 0 on success or a negative error code. + * @retval -NLE_OPNOTSUPP Link is not a bridge + */ +int rtnl_link_bridge_set_flags(struct rtnl_link *link, unsigned int flags) +{ + struct bridge_data *bd = bridge_data(link); + + IS_BRIDGE_LINK_ASSERT(link); + + bd->b_flags_mask |= flags; + bd->b_flags |= flags; + bd->ce_mask |= BRIDGE_ATTR_FLAGS; + + return 0; +} + +/** + * Get flags + * @arg link Link object of type bridge + * + * @see rtnl_link_bridge_set_flags() + * @see rtnl_link_bridge_unset_flags() + * + * @return Flags or a negative error code. + * @retval -NLE_OPNOTSUPP Link is not a bridge + */ +int rtnl_link_bridge_get_flags(struct rtnl_link *link) +{ + struct bridge_data *bd = bridge_data(link); + + IS_BRIDGE_LINK_ASSERT(link); + + return bd->b_flags; +} static struct rtnl_link_af_ops bridge_ops = { .ao_family = AF_BRIDGE, @@ -88,7 +437,6 @@ static struct rtnl_link_af_ops bridge_ops = { .ao_free = &bridge_free, .ao_parse_protinfo = &bridge_parse_protinfo, .ao_dump[NL_DUMP_DETAILS] = &bridge_dump_details, - .ao_protinfo_policy = &protinfo_policy, .ao_compare = &bridge_compare, }; @@ -101,3 +449,5 @@ static void __exit bridge_exit(void) { rtnl_link_af_unregister(&bridge_ops); } + +/** @} */ From 5a5aa73158027ae74eef3433388350c214b908f1 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 14 Feb 2013 12:34:57 +0100 Subject: [PATCH 411/432] bridge: Provide rtnl_link_bridge_alloc() Signed-off-by: Thomas Graf --- include/netlink/route/link/bridge.h | 2 ++ lib/route/link/bridge.c | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/include/netlink/route/link/bridge.h b/include/netlink/route/link/bridge.h index 5522fc0..71dcc24 100644 --- a/include/netlink/route/link/bridge.h +++ b/include/netlink/route/link/bridge.h @@ -30,6 +30,8 @@ enum rtnl_link_bridge_flags { RTNL_BRIDGE_FAST_LEAVE = 0x0008, }; +extern struct rtnl_link *rtnl_link_bridge_alloc(void); + extern int rtnl_link_is_bridge(struct rtnl_link *); extern int rtnl_link_bridge_has_ext_info(struct rtnl_link *); diff --git a/lib/route/link/bridge.c b/lib/route/link/bridge.c index a306c9c..eb02b22 100644 --- a/lib/route/link/bridge.c +++ b/lib/route/link/bridge.c @@ -183,6 +183,27 @@ static int bridge_compare(struct rtnl_link *_a, struct rtnl_link *_b, } /** @endcond */ +/** + * Allocate link object of type bridge + * + * @return Allocated link object or NULL. + */ +struct rtnl_link *rtnl_link_bridge_alloc(void) +{ + struct rtnl_link *link; + int err; + + if (!(link = rtnl_link_alloc())) + return NULL; + + if ((err = rtnl_link_set_type(link, "bridge")) < 0) { + rtnl_link_put(link); + return NULL; + } + + return link; +} + /** * Check if a link is a bridge * @arg link Link object From bb9911b5a337aeba34b6be53a2ef654828a92897 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 14 Feb 2013 12:37:10 +0100 Subject: [PATCH 412/432] netlink: Forward declare frequent libnl types to ease inclusion deps Signed-off-by: Thomas Graf --- include/netlink/netlink.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/netlink/netlink.h b/include/netlink/netlink.h index 5f68548..1d74ba1 100644 --- a/include/netlink/netlink.h +++ b/include/netlink/netlink.h @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2006 Thomas Graf + * Copyright (c) 2003-2013 Thomas Graf */ #ifndef NETLINK_NETLINK_H_ @@ -40,6 +40,8 @@ extern "C" { struct ucred; struct nl_cache_ops; struct nl_parser_param; +struct nl_object; +struct nl_sock; extern int nl_debug; extern struct nl_dump_params nl_debug_dp; From ee4122a12edcf7f10f03fbb7e35fe1388a8c3399 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 14 Feb 2013 12:42:07 +0100 Subject: [PATCH 413/432] vlan: Provide rtnl_link_vlan_alloc() Signed-off-by: Thomas Graf --- doc/route.txt | 7 ++----- include/netlink/route/link/vlan.h | 4 +++- lib/route/link/vlan.c | 23 ++++++++++++++++++++++- tests/test-create-vlan.c | 7 +------ 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/doc/route.txt b/doc/route.txt index 61a84c4..cd24eef 100644 --- a/doc/route.txt +++ b/doc/route.txt @@ -693,15 +693,12 @@ int master_index; if (!(master_index = rtnl_link_name2i(link_cache, "eth0"))) /* error */ -/* allocate new link object to configure the vlan device */ -link = rtnl_link_alloc(); +/* allocate new link object of type vlan */ +link = rtnl_link_vlan_alloc(); /* set eth0 to be our master device */ rtnl_link_set_link(link, master_index); -if ((err = rtnl_link_set_type(link, "vlan")) < 0) - /* error */ - rtnl_link_vlan_set_id(link, 10); if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) diff --git a/include/netlink/route/link/vlan.h b/include/netlink/route/link/vlan.h index 42768b6..f274163 100644 --- a/include/netlink/route/link/vlan.h +++ b/include/netlink/route/link/vlan.h @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2013 Thomas Graf */ #ifndef NETLINK_LINK_VLAN_H_ @@ -27,6 +27,8 @@ struct vlan_map #define VLAN_PRIO_MAX 7 +extern struct rtnl_link *rtnl_link_vlan_alloc(void); + extern int rtnl_link_is_vlan(struct rtnl_link *); extern char * rtnl_link_vlan_flags2str(int, char *, size_t); diff --git a/lib/route/link/vlan.c b/lib/route/link/vlan.c index 4f44aa5..9bbe7d5 100644 --- a/lib/route/link/vlan.c +++ b/lib/route/link/vlan.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2010 Thomas Graf + * Copyright (c) 2003-2013 Thomas Graf */ /** @@ -340,6 +340,27 @@ static struct rtnl_link_info_ops vlan_info_ops = { * @{ */ +/** + * Allocate link object of type VLAN + * + * @return Allocated link object or NULL. + */ +struct rtnl_link *rtnl_link_vlan_alloc(void) +{ + struct rtnl_link *link; + int err; + + if (!(link = rtnl_link_alloc())) + return NULL; + + if ((err = rtnl_link_set_type(link, "vlan")) < 0) { + rtnl_link_put(link); + return NULL; + } + + return link; +} + /** * Check if link is a VLAN link * @arg link Link object diff --git a/tests/test-create-vlan.c b/tests/test-create-vlan.c index 00a4d91..64e478f 100644 --- a/tests/test-create-vlan.c +++ b/tests/test-create-vlan.c @@ -25,15 +25,10 @@ int main(int argc, char *argv[]) return -1; } - link = rtnl_link_alloc(); + link = rtnl_link_vlan_alloc(); rtnl_link_set_link(link, master_index); - if ((err = rtnl_link_set_type(link, "vlan")) < 0) { - nl_perror(err, "Unable to set link info type"); - return err; - } - rtnl_link_vlan_set_id(link, 10); if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) { From 1ecf98a23e4ba309eb1f94b824d5f973d3fee0d2 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 14 Feb 2013 12:48:00 +0100 Subject: [PATCH 414/432] bond: Provide rtnl_link_bond_alloc() Signed-off-by: Thomas Graf --- doc/route.txt | 3 +- include/netlink/route/link/bonding.h | 4 ++- lib/route/link/bonding.c | 41 ++++++++++++++++++---------- tests/test-create-bond.c | 8 ++---- 4 files changed, 33 insertions(+), 23 deletions(-) diff --git a/doc/route.txt b/doc/route.txt index cd24eef..c8f1735 100644 --- a/doc/route.txt +++ b/doc/route.txt @@ -645,9 +645,8 @@ This attribute is unused and obsoleted in all recent kernels. struct rtnl_link *link; -link = rtnl_link_alloc(); +link = rtnl_link_bond_alloc(); rtnl_link_set_name(link, "my_bond"); -rtnl_link_set_type(link, "bond"); /* requires admin privileges */ if (rtnl_link_add(sk, link, NLM_F_CREATE) < 0) diff --git a/include/netlink/route/link/bonding.h b/include/netlink/route/link/bonding.h index 78ee6bd..5c34662 100644 --- a/include/netlink/route/link/bonding.h +++ b/include/netlink/route/link/bonding.h @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2011 Thomas Graf + * Copyright (c) 2011-2013 Thomas Graf */ #ifndef NETLINK_LINK_BONDING_H_ @@ -19,6 +19,8 @@ extern "C" { #endif +extern struct rtnl_link *rtnl_link_bond_alloc(void); + extern int rtnl_link_bond_add(struct nl_sock *, const char *, struct rtnl_link *); diff --git a/lib/route/link/bonding.c b/lib/route/link/bonding.c index b060ee1..f4c520b 100644 --- a/lib/route/link/bonding.c +++ b/lib/route/link/bonding.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2011 Thomas Graf + * Copyright (c) 2011-2013 Thomas Graf */ /** @@ -24,6 +24,27 @@ #include #include +/** + * Allocate link object of type bond + * + * @return Allocated link object or NULL. + */ +struct rtnl_link *rtnl_link_bond_alloc(void) +{ + struct rtnl_link *link; + int err; + + if (!(link = rtnl_link_alloc())) + return NULL; + + if ((err = rtnl_link_set_type(link, "bond")) < 0) { + rtnl_link_put(link); + return NULL; + } + + return link; +} + /** * Create a new kernel bonding device * @arg sock netlink socket @@ -54,22 +75,17 @@ int rtnl_link_bond_add(struct nl_sock *sock, const char *name, struct rtnl_link *link; int err; - if (!(link = rtnl_link_alloc())) + if (!(link = rtnl_link_bond_alloc())) return -NLE_NOMEM; - if (!name) { - if (opts) - name = rtnl_link_get_name(opts); - } - - if ((err = rtnl_link_set_type(link, "bond")) < 0) - goto errout; + if (!name && opts) + name = rtnl_link_get_name(opts); if (name) rtnl_link_set_name(link, name); err = rtnl_link_add(sock, link, NLM_F_CREATE); -errout: + rtnl_link_put(link); return err; @@ -94,12 +110,9 @@ int rtnl_link_bond_enslave_ifindex(struct nl_sock *sock, int master, struct rtnl_link *link; int err; - if (!(link = rtnl_link_alloc())) + if (!(link = rtnl_link_bond_alloc())) return -NLE_NOMEM; - if ((err = rtnl_link_set_type(link, "bond")) < 0) - goto errout; - rtnl_link_set_ifindex(link, slave); rtnl_link_set_master(link, master); diff --git a/tests/test-create-bond.c b/tests/test-create-bond.c index e54b0e6..11bc5b0 100644 --- a/tests/test-create-bond.c +++ b/tests/test-create-bond.c @@ -1,5 +1,6 @@ #include #include +#include int main(int argc, char *argv[]) { @@ -13,14 +14,9 @@ int main(int argc, char *argv[]) return err; } - link = rtnl_link_alloc(); + link = rtnl_link_bond_alloc(); rtnl_link_set_name(link, "my_bond"); - if ((err = rtnl_link_set_type(link, "bond")) < 0) { - nl_perror(err, "Unable to set link info type"); - return err; - } - if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) { nl_perror(err, "Unable to add link"); return err; From 8f151fadda62bdbd363b8d4a0167d5d29bb5163b Mon Sep 17 00:00:00 2001 From: roopa Date: Fri, 15 Feb 2013 10:26:29 -0800 Subject: [PATCH 415/432] link: move af_data_compare to the end In the current code if rtnl_link_af_data_compare returns value > 0 we mark PROTINFO attribute in the diff mask and return without comparing flags. This patch makes af_data to be the last thing we compare. Signed-off-by: Roopa Prabhu Reviewed-by: Nolan Leake Reviewed-by: Shrijeet Mukherjee Reviewed-by: Wilson Kok Signed-off-by: Thomas Graf --- lib/route/link.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/route/link.c b/lib/route/link.c index 7450545..77dd7f1 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -867,6 +867,12 @@ static int link_compare(struct nl_object *_a, struct nl_object *_b, diff |= LINK_DIFF(NUM_RX_QUEUES,a->l_num_rx_queues != b->l_num_rx_queues); diff |= LINK_DIFF(GROUP, a->l_group != b->l_group); + if (flags & LOOSE_COMPARISON) + diff |= LINK_DIFF(FLAGS, + (a->l_flags ^ b->l_flags) & b->l_flag_mask); + else + diff |= LINK_DIFF(FLAGS, a->l_flags != b->l_flags); + /* * Compare LINK_ATTR_PROTINFO af_data */ @@ -875,12 +881,6 @@ static int link_compare(struct nl_object *_a, struct nl_object *_b, goto protinfo_mismatch; } - if (flags & LOOSE_COMPARISON) - diff |= LINK_DIFF(FLAGS, - (a->l_flags ^ b->l_flags) & b->l_flag_mask); - else - diff |= LINK_DIFF(FLAGS, a->l_flags != b->l_flags); - out: return diff; From ded20487fd631f7fcfc8f3cc547f6a8852501b83 Mon Sep 17 00:00:00 2001 From: roopa Date: Fri, 15 Feb 2013 10:26:30 -0800 Subject: [PATCH 416/432] link: Fix rtnl_link_af_data_compare return value This patch fixes a bug where because of the af_ops check being first in the function, we were returning ~0 if af_ops was null even if both objects really did not have af_data and we should be returning 0. Its better to have the af_data present check before anything else. So, Rearranged some of the code in rtnl_link_af_data_compare. Changes include: - Do the attribute present check before anything else - If ao_compare op not present, return ~0 Signed-off-by: Roopa Prabhu Reviewed-by: Nolan Leake Reviewed-by: Shrijeet Mukherjee Reviewed-by: Wilson Kok Signed-off-by: Thomas Graf --- lib/route/link/api.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/route/link/api.c b/lib/route/link/api.c index 63ff99c..352bb83 100644 --- a/lib/route/link/api.c +++ b/lib/route/link/api.c @@ -365,22 +365,26 @@ errout: int rtnl_link_af_data_compare(struct rtnl_link *a, struct rtnl_link *b, int family) { - struct rtnl_link_af_ops *af_ops = rtnl_link_af_ops_lookup(family); + struct rtnl_link_af_ops *af_ops; int ret = 0; + if (!a->l_af_data[family] && !b->l_af_data[family]) + return 0; + + if (!a->l_af_data[family] || !b->l_af_data[family]) + return ~0; + + af_ops = rtnl_link_af_ops_lookup(family); if (!af_ops) return ~0; - if (!a->l_af_data[family] && !b->l_af_data[family]) - goto out; - - if (!a->l_af_data[family] || !b->l_af_data[family]) { + if (af_ops->ao_compare == NULL) { ret = ~0; goto out; } - if (af_ops->ao_compare) - ret = af_ops->ao_compare(a, b, family, ~0, 0); + ret = af_ops->ao_compare(a, b, family, ~0, 0); + out: rtnl_link_af_ops_put(af_ops); From 4d7680c19c131175e2ec431de9a026230c968a7e Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 28 Feb 2013 13:07:04 +0100 Subject: [PATCH 417/432] Use thread-safe strerror_r() instead of strerror() We have only ever fed well known error codes into strerror() so it should never have been a problem though. Signed-off-by: Thomas Graf --- lib/fib_lookup/lookup.c | 4 ++-- lib/handlers.c | 3 ++- lib/msg.c | 3 ++- lib/route/route_obj.c | 4 ++-- src/lib/utils.c | 3 ++- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/fib_lookup/lookup.c b/lib/fib_lookup/lookup.c index 6fe8dae..3d07317 100644 --- a/lib/fib_lookup/lookup.c +++ b/lib/fib_lookup/lookup.c @@ -124,7 +124,7 @@ errout: static void result_dump_line(struct nl_object *obj, struct nl_dump_params *p) { struct flnl_result *res = (struct flnl_result *) obj; - char buf[128]; + char buf[256]; nl_dump_line(p, "table %s prefixlen %u next-hop-selector %u\n", rtnl_route_table2str(res->fr_table_id, buf, sizeof(buf)), @@ -133,7 +133,7 @@ static void result_dump_line(struct nl_object *obj, struct nl_dump_params *p) nl_rtntype2str(res->fr_type, buf, sizeof(buf))); nl_dump(p, "scope %s error %s (%d)\n", rtnl_scope2str(res->fr_scope, buf, sizeof(buf)), - strerror(-res->fr_error), res->fr_error); + strerror_r(-res->fr_error, buf, sizeof(buf)), res->fr_error); } static void result_dump_details(struct nl_object *obj, struct nl_dump_params *p) diff --git a/lib/handlers.c b/lib/handlers.c index ee1376b..e52c850 100644 --- a/lib/handlers.c +++ b/lib/handlers.c @@ -79,9 +79,10 @@ static int nl_error_handler_verbose(struct sockaddr_nl *who, struct nlmsgerr *e, void *arg) { FILE *ofd = arg ? arg : stderr; + char buf[256]; fprintf(ofd, "-- Error received: %s\n-- Original message: ", - strerror(-e->error)); + strerror_r(-e->error, buf, sizeof(buf))); print_header_content(ofd, &e->msg); fprintf(ofd, "\n"); diff --git a/lib/msg.c b/lib/msg.c index 8198ded..62d9683 100644 --- a/lib/msg.c +++ b/lib/msg.c @@ -879,10 +879,11 @@ void nl_msg_dump(struct nl_msg *msg, FILE *ofd) hdr->nlmsg_len >= nlmsg_msg_size(sizeof(struct nlmsgerr))) { struct nl_msg *errmsg; struct nlmsgerr *err = nlmsg_data(hdr); + char buf[256]; fprintf(ofd, " [ERRORMSG] %zu octets\n", sizeof(*err)); fprintf(ofd, " .error = %d \"%s\"\n", err->error, - strerror(-err->error)); + strerror_r(-err->error, buf, sizeof(buf))); fprintf(ofd, " [ORIGINAL MESSAGE] %zu octets\n", sizeof(*hdr)); errmsg = nlmsg_inherit(&err->msg); diff --git a/lib/route/route_obj.c b/lib/route/route_obj.c index 8f1e515..795047f 100644 --- a/lib/route/route_obj.c +++ b/lib/route/route_obj.c @@ -208,7 +208,7 @@ static void route_dump_details(struct nl_object *a, struct nl_dump_params *p) { struct rtnl_route *r = (struct rtnl_route *) a; struct nl_cache *link_cache; - char buf[128]; + char buf[256]; int i; link_cache = nl_cache_mngt_require_safe("route/link"); @@ -259,7 +259,7 @@ static void route_dump_details(struct nl_object *a, struct nl_dump_params *p) if ((r->ce_mask & ROUTE_ATTR_CACHEINFO) && r->rt_cacheinfo.rtci_error) { nl_dump_line(p, " cacheinfo error %d (%s)\n", r->rt_cacheinfo.rtci_error, - strerror(-r->rt_cacheinfo.rtci_error)); + strerror_r(-r->rt_cacheinfo.rtci_error, buf, sizeof(buf))); } if (r->ce_mask & ROUTE_ATTR_METRICS) { diff --git a/src/lib/utils.c b/src/lib/utils.c index 78ad260..e5eacde 100644 --- a/src/lib/utils.c +++ b/src/lib/utils.c @@ -70,6 +70,7 @@ void nl_cli_print_version(void) void nl_cli_fatal(int err, const char *fmt, ...) { va_list ap; + char buf[256]; fprintf(stderr, "Error: "); @@ -79,7 +80,7 @@ void nl_cli_fatal(int err, const char *fmt, ...) va_end(ap); fprintf(stderr, "\n"); } else - fprintf(stderr, "%s\n", strerror(err)); + fprintf(stderr, "%s\n", strerror_r(err, buf, sizeof(buf))); exit(abs(err)); } From 9e6cdbf6fc60f95e232c4ca34004606da9536d01 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 13 Mar 2013 16:53:07 +0100 Subject: [PATCH 418/432] attr: Add nla_nest_cancel() to remove partially added nested attributes Signed-off-by: Thomas Graf --- doc/core.txt | 1 + include/netlink/attr.h | 1 + lib/attr.c | 25 +++++++++++++++++++++++-- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/doc/core.txt b/doc/core.txt index 8a26dba..1e951d0 100644 --- a/doc/core.txt +++ b/doc/core.txt @@ -2316,6 +2316,7 @@ int put_opts(struct nl_msg *msg) return 0; nla_put_failure: + nla_nest_cancel(msg, opts); return -EMSGSIZE; } -------- diff --git a/include/netlink/attr.h b/include/netlink/attr.h index 69ecb08..0ed3da3 100644 --- a/include/netlink/attr.h +++ b/include/netlink/attr.h @@ -124,6 +124,7 @@ extern int nla_put_msecs(struct nl_msg *, int, unsigned long); extern int nla_put_nested(struct nl_msg *, int, struct nl_msg *); extern struct nlattr * nla_nest_start(struct nl_msg *, int); extern int nla_nest_end(struct nl_msg *, struct nlattr *); +extern void nla_nest_cancel(struct nl_msg *, struct nlattr *); extern int nla_parse_nested(struct nlattr **, int, struct nlattr *, struct nla_policy *); extern int nla_is_nested(struct nlattr *); diff --git a/lib/attr.c b/lib/attr.c index 26bece3..2c03fa1 100644 --- a/lib/attr.c +++ b/lib/attr.c @@ -820,8 +820,7 @@ int nla_nest_end(struct nl_msg *msg, struct nlattr *start) * Kernel can't handle empty nested attributes, trim the * attribute header again */ - msg->nm_nlh->nlmsg_len -= NLA_HDRLEN; - memset(nlmsg_tail(msg->nm_nlh), 0, NLA_HDRLEN); + nla_nest_cancel(msg, start); return 0; } @@ -849,6 +848,28 @@ int nla_nest_end(struct nl_msg *msg, struct nlattr *start) return 0; } +/** + * Cancel the addition of a nested attribute + * @arg msg Netlink message + * @arg attr Nested netlink attribute + * + * Removes any partially added nested Netlink attribute from the message + * by resetting the message to the size before the call to nla_nest_start() + * and by overwriting any potentially touched message segments with 0. + */ +void nla_nest_cancel(struct nl_msg *msg, struct nlattr *attr) +{ + ssize_t len; + + len = (void *) nlmsg_tail(msg->nm_nlh) - (void *) attr; + if (len < 0) + BUG(); + else if (len > 0) { + msg->nm_nlh->nlmsg_len -= len; + memset(nlmsg_tail(msg->nm_nlh), 0, len); + } +} + /** * Create attribute index based on nested attribute * @arg tb Index array to be filled (maxtype+1 elements). From 60b370de8ca2c66a9259182ae2fc4588ed8777d9 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 13 Mar 2013 17:01:54 +0100 Subject: [PATCH 419/432] attr: Do not enforce maximum length for NLA_FLAG attributes Although wasteful, NLA_FLAG with non zero payload cause no harm and should thus not be rejected. Signed-off-by: Thomas Graf --- lib/attr.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/attr.c b/lib/attr.c index 2c03fa1..90070df 100644 --- a/lib/attr.c +++ b/lib/attr.c @@ -182,6 +182,7 @@ static uint16_t nla_attr_minlen[NLA_TYPE_MAX+1] = { [NLA_U32] = sizeof(uint32_t), [NLA_U64] = sizeof(uint64_t), [NLA_STRING] = 1, + [NLA_FLAG] = 0, }; static int validate_nla(struct nlattr *nla, int maxtype, @@ -204,9 +205,6 @@ static int validate_nla(struct nlattr *nla, int maxtype, else if (pt->type != NLA_UNSPEC) minlen = nla_attr_minlen[pt->type]; - if (pt->type == NLA_FLAG && nla_len(nla) > 0) - return -NLE_RANGE; - if (nla_len(nla) < minlen) return -NLE_RANGE; From 64315f731cedb3ca1736533dab92592c330a1083 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 13 Mar 2013 17:07:01 +0100 Subject: [PATCH 420/432] attr: No longer warn about attribute of type 0 The kernel will start using type 0 attributes for padding purposes. Signed-off-by: Thomas Graf --- lib/attr.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/attr.c b/lib/attr.c index 90070df..093ffb5 100644 --- a/lib/attr.c +++ b/lib/attr.c @@ -250,10 +250,9 @@ int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len, nla_for_each_attr(nla, head, len, rem) { int type = nla_type(nla); - if (type == 0) { - NL_DBG(1, "Illegal nla->nla_type == 0\n"); + /* Padding attributes */ + if (type == 0) continue; - } if (type <= maxtype) { if (policy) { From 1395c69901834f66e1e1522d5253a84b45901066 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 13 Mar 2013 17:12:03 +0100 Subject: [PATCH 421/432] attr: Warn application if nla_parse() observes same attribute multiple times Use a debugging message to warn applications if an attribute is found multiple times in the same message. It is perfectly valid to rely on this behaviour but it is likely to indicate a bug. Signed-off-by: Thomas Graf --- lib/attr.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/attr.c b/lib/attr.c index 093ffb5..e6efe4e 100644 --- a/lib/attr.c +++ b/lib/attr.c @@ -254,15 +254,20 @@ int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len, if (type == 0) continue; - if (type <= maxtype) { - if (policy) { - err = validate_nla(nla, maxtype, policy); - if (err < 0) - goto errout; - } + if (type > maxtype) + continue; - tb[type] = nla; + if (policy) { + err = validate_nla(nla, maxtype, policy); + if (err < 0) + goto errout; } + + if (tb[type]) + NL_DBG(1, "Attribute of type %#x found multiple times in message, " + "previous attribute is being ignored.\n", type); + + tb[type] = nla; } if (rem > 0) From c608b4d151d221542e6b0bbb8a95b45a4cde0fb7 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 13 Mar 2013 17:28:07 +0100 Subject: [PATCH 422/432] msg: Pretty print padding attributes in nl_msg_dump() Signed-off-by: Thomas Graf --- lib/msg.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/msg.c b/lib/msg.c index 62d9683..043efe9 100644 --- a/lib/msg.c +++ b/lib/msg.c @@ -834,9 +834,13 @@ static void dump_attrs(FILE *ofd, struct nlattr *attrs, int attrlen, int padlen, alen = nla_len(nla); prefix_line(ofd, prefix); - fprintf(ofd, " [ATTR %02d%s] %d octets\n", nla_type(nla), - nla->nla_type & NLA_F_NESTED ? " NESTED" : "", - alen); + + if (nla->nla_type == 0) + fprintf(ofd, " [ATTR PADDING] %d octets\n", alen); + else + fprintf(ofd, " [ATTR %02d%s] %d octets\n", nla_type(nla), + nla->nla_type & NLA_F_NESTED ? " NESTED" : "", + alen); if (nla->nla_type & NLA_F_NESTED) dump_attrs(ofd, nla_data(nla), alen, prefix+1); From f72bfc72205366f2f877fef379c79c9a2a1cce03 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 13 Mar 2013 17:44:47 +0100 Subject: [PATCH 423/432] msg: Pretty print error message header even if incomplete Signed-off-by: Thomas Graf --- lib/msg.c | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/lib/msg.c b/lib/msg.c index 043efe9..b07de63 100644 --- a/lib/msg.c +++ b/lib/msg.c @@ -863,6 +863,27 @@ static void dump_attrs(FILE *ofd, struct nlattr *attrs, int attrlen, } } +static void dump_error_msg(struct nl_msg *msg, FILE *ofd) +{ + struct nlmsghdr *hdr = nlmsg_hdr(msg); + struct nlmsgerr *err = nlmsg_data(hdr); + + fprintf(ofd, " [ERRORMSG] %zu octets\n", sizeof(*err)); + + if (nlmsg_len(hdr) >= sizeof(*err)) { + char buf[256]; + struct nl_msg *errmsg; + + fprintf(ofd, " .error = %d \"%s\"\n", err->error, + strerror_r(-err->error, buf, sizeof(buf))); + fprintf(ofd, " [ORIGINAL MESSAGE] %zu octets\n", sizeof(*hdr)); + + errmsg = nlmsg_inherit(&err->msg); + print_hdr(ofd, errmsg); + nlmsg_free(errmsg); + } +} + /** * Dump message in human readable format to file descriptor * @arg msg Message to print @@ -879,21 +900,9 @@ void nl_msg_dump(struct nl_msg *msg, FILE *ofd) fprintf(ofd, " [HEADER] %zu octets\n", sizeof(struct nlmsghdr)); print_hdr(ofd, msg); - if (hdr->nlmsg_type == NLMSG_ERROR && - hdr->nlmsg_len >= nlmsg_msg_size(sizeof(struct nlmsgerr))) { - struct nl_msg *errmsg; - struct nlmsgerr *err = nlmsg_data(hdr); - char buf[256]; - - fprintf(ofd, " [ERRORMSG] %zu octets\n", sizeof(*err)); - fprintf(ofd, " .error = %d \"%s\"\n", err->error, - strerror_r(-err->error, buf, sizeof(buf))); - fprintf(ofd, " [ORIGINAL MESSAGE] %zu octets\n", sizeof(*hdr)); - - errmsg = nlmsg_inherit(&err->msg); - print_hdr(ofd, errmsg); - nlmsg_free(errmsg); - } else if (nlmsg_len(hdr) > 0) { + if (hdr->nlmsg_type == NLMSG_ERROR) + dump_error_msg(msg, ofd); + else if (nlmsg_len(hdr) > 0) { struct nl_cache_ops *ops; int payloadlen = nlmsg_len(hdr); int attrlen = 0; From f0f33c394b97341e824b5fdf62707fcd25ef84cc Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 14 Mar 2013 14:41:12 +0100 Subject: [PATCH 424/432] addr: Reset unused portion of binary address in nl_addr_set_binary_addr() memset() the binary address before overwriting it with new data to avoid leaving around old portions of the address. Signed-off-by: Thomas Graf --- lib/addr.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/addr.c b/lib/addr.c index 9089be8..e75ef70 100644 --- a/lib/addr.c +++ b/lib/addr.c @@ -766,7 +766,10 @@ int nl_addr_set_binary_addr(struct nl_addr *addr, void *buf, size_t len) return -NLE_RANGE; addr->a_len = len; - memcpy(addr->a_addr, buf, len); + memset(addr->a_addr, 0, addr->a_maxsize); + + if (len) + memcpy(addr->a_addr, buf, len); return 0; } From 88527534ba08bf8946dcf9f61c725133facb97af Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 14 Mar 2013 15:37:46 +0100 Subject: [PATCH 425/432] addr: improve API reference documentation for nl_addr_*() Signed-off-by: Thomas Graf --- include/netlink/addr.h | 4 +- lib/addr.c | 204 +++++++++++++++++++++++++++++++++-------- 2 files changed, 166 insertions(+), 42 deletions(-) diff --git a/include/netlink/addr.h b/include/netlink/addr.h index 794c4ff..db3e4c2 100644 --- a/include/netlink/addr.h +++ b/include/netlink/addr.h @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2010 Thomas Graf + * Copyright (c) 2003-2013 Thomas Graf */ #ifndef NETLINK_ADDR_H_ @@ -40,7 +40,7 @@ extern int nl_addr_guess_family(struct nl_addr *); extern int nl_addr_fill_sockaddr(struct nl_addr *, struct sockaddr *, socklen_t *); extern int nl_addr_info(struct nl_addr *, struct addrinfo **); -extern int nl_addr_resolve(struct nl_addr *addr, char *host, size_t hostlen); +extern int nl_addr_resolve(struct nl_addr *, char *, size_t); /* Access Functions */ extern void nl_addr_set_family(struct nl_addr *, int); diff --git a/lib/addr.c b/lib/addr.c index e75ef70..3db30ee 100644 --- a/lib/addr.c +++ b/lib/addr.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2012 Thomas Graf + * Copyright (c) 2003-2013 Thomas Graf */ /** @@ -170,9 +170,17 @@ static void addr_destroy(struct nl_addr *addr) */ /** - * Allocate new abstract address object. - * @arg maxsize Maximum size of the binary address. - * @return Newly allocated address object or NULL + * Allocate empty abstract address + * @arg maxsize Upper limit of the binary address to be stored + * + * The new address object will be empty with a prefix length of 0 and will + * be capable of holding binary addresses up to the specified limit. + * + * @see nl_addr_build() + * @see nl_addr_parse() + * @see nl_addr_put() + * + * @return Allocated address object or NULL upon failure. */ struct nl_addr *nl_addr_alloc(size_t maxsize) { @@ -189,11 +197,21 @@ struct nl_addr *nl_addr_alloc(size_t maxsize) } /** - * Allocate new abstract address object based on a binary address. - * @arg family Address family. - * @arg buf Buffer containing the binary address. - * @arg size Length of binary address buffer. - * @return Newly allocated address handle or NULL + * Allocate abstract address based on a binary address. + * @arg family Address family + * @arg buf Binary address + * @arg size Length of binary address + * + * This function will allocate an abstract address capable of holding the + * binary address specified. The prefix length will be set to the full + * length of the binary address provided. + * + * @see nl_addr_alloc() + * @see nl_addr_alloc_attr() + * @see nl_addr_parse() + * @see nl_addr_put() + * + * @return Allocated address object or NULL upon failure. */ struct nl_addr *nl_addr_build(int family, void *buf, size_t size) { @@ -214,14 +232,25 @@ struct nl_addr *nl_addr_build(int family, void *buf, size_t size) } /** - * Allocate abstract address based on netlink attribute. - * @arg nla Netlink attribute of unspecific type. + * Allocate abstract address based on Netlink attribute. + * @arg nla Netlink attribute * @arg family Address family. * - * Considers the netlink attribute payload a address of the specified - * family and allocates a new abstract address based on it. + * Allocates an abstract address based on the specified Netlink attribute + * by interpreting the payload of the Netlink attribute as the binary + * address. * - * @return Newly allocated address handle or NULL. + * This function is identical to: + * @code + * nl_addr_build(family, nla_data(nla), nla_len(nla)); + * @endcode + * + * @see nl_addr_alloc() + * @see nl_addr_build() + * @see nl_addr_parse() + * @see nl_addr_put() + * + * @return Allocated address object or NULL upon failure. */ struct nl_addr *nl_addr_alloc_attr(struct nlattr *nla, int family) { @@ -229,13 +258,13 @@ struct nl_addr *nl_addr_alloc_attr(struct nlattr *nla, int family) } /** - * Allocate abstract address object based on a character string + * Allocate abstract address based on character string * @arg addrstr Address represented as character string. * @arg hint Address family hint or AF_UNSPEC. * @arg result Pointer to store resulting address. * * Regognizes the following address formats: - *@code + * @code * Format Len Family * ---------------------------------------------------------------- * IPv6 address format 16 AF_INET6 @@ -253,6 +282,10 @@ struct nl_addr *nl_addr_alloc_attr(struct nlattr *nla, int family) * The prefix length may be appened at the end prefixed with a * slash, e.g. 10.0.0.0/8. * + * @see nl_addr_alloc() + * @see nl_addr_build() + * @see nl_addr_put() + * * @return 0 on success or a negative error code. */ int nl_addr_parse(const char *addrstr, int hint, struct nl_addr **result) @@ -424,10 +457,16 @@ errout: } /** - * Clone existing abstract address object. - * @arg addr Abstract address object. - * @return Newly allocated abstract address object being a duplicate of the - * specified address object or NULL if a failure occured. + * Clone existing abstract address object + * @arg addr Abstract address object + * + * Allocates new abstract address representing an identical clone of an + * existing address. + * + * @see nl_addr_alloc() + * @see nl_addr_put() + * + * @return Allocated abstract address or NULL upon failure. */ struct nl_addr *nl_addr_clone(struct nl_addr *addr) { @@ -447,6 +486,18 @@ struct nl_addr *nl_addr_clone(struct nl_addr *addr) * @{ */ +/** + * Increase the reference counter of an abstract address + * @arg addr Abstract address + * + * Increases the reference counter of the address and thus prevents the + * release of the memory resources until the reference is given back + * using the function nl_addr_put(). + * + * @see nl_addr_put() + * + * @return Pointer to the existing abstract address + */ struct nl_addr *nl_addr_get(struct nl_addr *addr) { addr->a_refcnt++; @@ -454,6 +505,15 @@ struct nl_addr *nl_addr_get(struct nl_addr *addr) return addr; } +/** + * Decrease the reference counter of an abstract address + * @arg addr Abstract addr + * + * @note The resources of the abstract address will be freed after the + * last reference to the address has been returned. + * + * @see nl_addr_get() + */ void nl_addr_put(struct nl_addr *addr) { if (!addr) @@ -466,9 +526,10 @@ void nl_addr_put(struct nl_addr *addr) } /** - * Check whether an abstract address object is shared. + * Check whether an abstract address is shared. * @arg addr Abstract address object. - * @return Non-zero if the abstract address object is shared, otherwise 0. + * + * @return Non-zero if the abstract address is shared, otherwise 0. */ int nl_addr_shared(struct nl_addr *addr) { @@ -483,12 +544,21 @@ int nl_addr_shared(struct nl_addr *addr) */ /** - * Compares two abstract address objects. - * @arg a A abstract address object. - * @arg b Another abstract address object. + * Compare abstract addresses + * @arg a An abstract address + * @arg b Another abstract address * - * @return Integer less than, equal to or greather than zero if \c is found, - * respectively to be less than, to, or be greater than \c b. + * Verifies whether the address family, address length, prefix length, and + * binary addresses of two abstract addresses matches. + * + * @note This function will *not* respect the prefix length in the sense + * that only the actual prefix will be compared. Please refer to the + * nl_addr_cmp_prefix() function if you require this functionality. + * + * @see nl_addr_cmp_prefix() + * + * @return Integer less than, equal to or greather than zero if the two + * addresses match. */ int nl_addr_cmp(struct nl_addr *a, struct nl_addr *b) { @@ -509,12 +579,17 @@ int nl_addr_cmp(struct nl_addr *a, struct nl_addr *b) } /** - * Compares the prefix of two abstract address objects. - * @arg a A abstract address object. - * @arg b Another abstract address object. + * Compare the prefix of two abstract addresses + * @arg a An abstract address + * @arg b Another abstract address * - * @return Integer less than, equal to or greather than zero if \c is found, - * respectively to be less than, to, or be greater than \c b. + * Verifies whether the address family and the binary address covered by + * the smaller prefix length of the two abstract addresses matches. + * + * @see nl_addr_cmp() + * + * @return Integer less than, equal to or greather than zero if the two + * addresses match. */ int nl_addr_cmp_prefix(struct nl_addr *a, struct nl_addr *b) { @@ -538,7 +613,9 @@ int nl_addr_cmp_prefix(struct nl_addr *a, struct nl_addr *b) /** * Returns true if the address consists of all zeros - * @arg addr Address to look at. + * @arg addr Abstract address + * + * @return 1 if the binary address consists of all zeros, 0 otherwise. */ int nl_addr_iszero(struct nl_addr *addr) { @@ -552,11 +629,11 @@ int nl_addr_iszero(struct nl_addr *addr) } /** - * Check if an address matches a certain family. + * Check if address string is parseable for a specific address family * @arg addr Address represented as character string. * @arg family Desired address family. * - * @return 1 if the address is of the desired address family, + * @return 1 if the address is parseable assuming the specified address family, * otherwise 0 is returned. */ int nl_addr_valid(char *addr, int family) @@ -588,9 +665,10 @@ int nl_addr_valid(char *addr, int family) } /** - * Guess address family of an abstract address object based on address size. + * Guess address family of abstract address based on address size * @arg addr Abstract address object. - * @return Address family or AF_UNSPEC if guessing wasn't successful. + * + * @return Numeric address family or AF_UNSPEC */ int nl_addr_guess_family(struct nl_addr *addr) { @@ -666,7 +744,7 @@ int nl_addr_fill_sockaddr(struct nl_addr *addr, struct sockaddr *sa, * Call getaddrinfo() for an abstract address object. * @arg addr Abstract address object. * @arg result Pointer to store resulting address list. - * + * * Calls getaddrinfo() for the specified abstract address in AI_NUMERICHOST * mode. * @@ -744,11 +822,26 @@ int nl_addr_resolve(struct nl_addr *addr, char *host, size_t hostlen) * @{ */ +/** + * Set address family + * @arg addr Abstract address object + * @arg family Address family + * + * @see nl_addr_get_family() + */ void nl_addr_set_family(struct nl_addr *addr, int family) { addr->a_family = family; } +/** + * Return address family + * @arg addr Abstract address object + * + * @see nl_addr_set_family() + * + * @return The numeric address family or `AF_UNSPEC` + */ int nl_addr_get_family(struct nl_addr *addr) { return addr->a_family; @@ -759,6 +852,20 @@ int nl_addr_get_family(struct nl_addr *addr) * @arg addr Abstract address object. * @arg buf Buffer containing binary address. * @arg len Length of buffer containing binary address. + * + * Modifies the binary address portion of the abstract address. The + * abstract address must be capable of holding the required amount + * or this function will fail. + * + * @note This function will *not* modify the prefix length. It is within + * the responsibility of the caller to set the prefix length to the + * desirable length. + * + * @see nl_addr_alloc() + * @see nl_addr_get_binary_addr() + * @see nl_addr_get_len() + * + * @return 0 on success or a negative error code. */ int nl_addr_set_binary_addr(struct nl_addr *addr, void *buf, size_t len) { @@ -777,6 +884,11 @@ int nl_addr_set_binary_addr(struct nl_addr *addr, void *buf, size_t len) /** * Get binary address of abstract address object. * @arg addr Abstract address object. + * + * @see nl_addr_set_binary_addr() + * @see nl_addr_get_len() + * + * @return Pointer to binary address of length nl_addr_get_len() */ void *nl_addr_get_binary_addr(struct nl_addr *addr) { @@ -786,20 +898,32 @@ void *nl_addr_get_binary_addr(struct nl_addr *addr) /** * Get length of binary address of abstract address object. * @arg addr Abstract address object. + * + * @see nl_addr_get_binary_addr() + * @see nl_addr_set_binary_addr() */ unsigned int nl_addr_get_len(struct nl_addr *addr) { return addr->a_len; } +/** + * Set the prefix length of an abstract address + * @arg addr Abstract address object + * @arg prefixlen New prefix length + * + * @see nl_addr_get_prefixlen() + */ void nl_addr_set_prefixlen(struct nl_addr *addr, int prefixlen) { addr->a_prefixlen = prefixlen; } /** - * Get prefix length of abstract address object. - * @arg addr Abstract address object. + * Return prefix length of abstract address object. + * @arg addr Abstract address object + * + * @see nl_addr_set_prefixlen() */ unsigned int nl_addr_get_prefixlen(struct nl_addr *addr) { From 780a0423dc7a7f248d6a71a7ae6f531fe95ba911 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 14 Mar 2013 16:09:19 +0100 Subject: [PATCH 426/432] addr: Update to latest address familiy definition for translation Signed-off-by: Thomas Graf --- lib/addr.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/addr.c b/lib/addr.c index 3db30ee..557b0ad 100644 --- a/lib/addr.c +++ b/lib/addr.c @@ -1005,7 +1005,6 @@ prefix: static const struct trans_tbl afs[] = { __ADD(AF_UNSPEC,unspec) __ADD(AF_UNIX,unix) - __ADD(AF_LOCAL,local) __ADD(AF_INET,inet) __ADD(AF_AX25,ax25) __ADD(AF_IPX,ipx) @@ -1021,17 +1020,27 @@ static const struct trans_tbl afs[] = { __ADD(AF_SECURITY,security) __ADD(AF_KEY,key) __ADD(AF_NETLINK,netlink) - __ADD(AF_ROUTE,route) __ADD(AF_PACKET,packet) __ADD(AF_ASH,ash) __ADD(AF_ECONET,econet) __ADD(AF_ATMSVC,atmsvc) + __ADD(AF_RDS,rds) __ADD(AF_SNA,sna) __ADD(AF_IRDA,irda) __ADD(AF_PPPOX,pppox) __ADD(AF_WANPIPE,wanpipe) __ADD(AF_LLC,llc) + __ADD(AF_CAN,can) + __ADD(AF_TIPC,tipc) __ADD(AF_BLUETOOTH,bluetooth) + __ADD(AF_IUCV,iucv) + __ADD(AF_RXRPC,rxrpc) + __ADD(AF_ISDN,isdn) + __ADD(AF_PHONET,phonet) + __ADD(AF_IEEE802154,ieee802154) + __ADD(AF_CAIF,caif) + __ADD(AF_ALG,alg) + __ADD(AF_NFC,nfc) }; char *nl_af2str(int family, char *buf, size_t size) From e09e7f1035fc2a8c918822cbfcfac61c77153497 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 14 Mar 2013 16:25:17 +0100 Subject: [PATCH 427/432] tests: Add check based unit test system Introduces new unit tests based on `check`. Each subsystem/module can have its own unit tests in tests/check-.c that will be linked together in tests/check-all.c. Running 'make check' will compile and run the unit tests automatically. A reference unit test implementation has been done for the abstract address module. Signed-off-by: Thomas Graf --- configure.ac | 2 + tests/.gitignore | 1 + tests/Makefile.am | 22 +++-- tests/check-addr.c | 212 +++++++++++++++++++++++++++++++++++++++++++++ tests/check-all.c | 42 +++++++++ 5 files changed, 273 insertions(+), 6 deletions(-) create mode 100644 tests/check-addr.c create mode 100644 tests/check-all.c diff --git a/configure.ac b/configure.ac index 66f4f7b..744e34e 100644 --- a/configure.ac +++ b/configure.ac @@ -75,6 +75,8 @@ AC_CHECK_PROGS(YACC, 'bison -y') AC_C_CONST AC_C_INLINE +AM_PATH_CHECK() + AC_ARG_WITH([pkgconfigdir], AS_HELP_STRING([--with-pkgconfigdir=PATH], [Path to the pkgconfig directory [[LIBDIR/pkgconfig]]]), [pkgconfigdir="$withval"], [pkgconfigdir='${libdir}/pkgconfig']) diff --git a/tests/.gitignore b/tests/.gitignore index b386c45..151e9b5 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -6,3 +6,4 @@ test-delete-link test-genl test-nf-cache-mngr test-socket-creation +check-all diff --git a/tests/Makefile.am b/tests/Makefile.am index 9c0ab8d..6a5606a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -6,14 +6,23 @@ LDADD = \ ${top_builddir}/lib/libnl-3.la \ ${top_builddir}/lib/libnl-nf-3.la \ ${top_builddir}/lib/libnl-genl-3.la \ - ${top_builddir}/lib/libnl-route-3.la + ${top_builddir}/lib/libnl-route-3.la \ + @CHECK_LIBS@ + +CFLAGS += @CHECK_CFLAGS@ + +UNIT_TESTS = check-all check_PROGRAMS = \ test-create-bond \ test-create-vlan \ test-delete-link \ test-socket-creation \ - test-complex-HTB-with-hash-filters + test-complex-HTB-with-hash-filters \ + ${UNIT_TESTS} + +TESTS = \ + ${UNIT_TESTS} if ENABLE_CLI LDADD += ${top_builddir}/src/lib/libnl-cli-3.la @@ -23,10 +32,6 @@ check_PROGRAMS += \ test-nf-cache-mngr endif -# Eventually add these to TESTS once converted to be real -# test programs -# TESTS = $(check_PROGRAMS) - test_cache_mngr_SOURCES = test-cache-mngr.c test_create_bond_SOURCES = test-create-bond.c test_create_vlan_SOURCES = test-create-vlan.c @@ -35,3 +40,8 @@ test_genl_SOURCES = test-genl.c test_nf_cache_mngr_SOURCES = test-nf-cache-mngr.c test_socket_creation_SOURCES = test-socket-creation.c test_complex_HTB_with_hash_filters_SOURCES = test-complex-HTB-with-hash-filters.c + +# Unit tests +check_all_SOURCES = \ + check-all.c \ + check-addr.c diff --git a/tests/check-addr.c b/tests/check-addr.c new file mode 100644 index 0000000..39f3ede --- /dev/null +++ b/tests/check-addr.c @@ -0,0 +1,212 @@ +/* + * tests/check-addr.c nl_addr unit tests + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2013 Thomas Graf + */ + +#include +#include + +START_TEST(addr_alloc) +{ + struct nl_addr *addr; + + addr = nl_addr_alloc(16); + fail_if(addr == NULL, + "Allocation should not return NULL"); + + fail_if(nl_addr_iszero(addr) == 0, + "New empty address should be all zeros"); + + fail_if(nl_addr_get_family(addr) != AF_UNSPEC, + "New empty address should have family AF_UNSPEC"); + + fail_if(nl_addr_get_prefixlen(addr) != 0, + "New empty address should have prefix length 0"); + + fail_if(nl_addr_shared(addr), + "New empty address should not be shared"); + + fail_if(nl_addr_get(addr) != addr, + "nl_addr_get() should return pointer to address"); + + fail_if(nl_addr_shared(addr) == 0, + "Address should be shared after call to nl_addr_get()"); + + nl_addr_put(addr); + + fail_if(nl_addr_shared(addr), + "Address should not be shared after call to nl_addr_put()"); + + fail_if(nl_addr_fill_sockaddr(addr, NULL, 0) == 0, + "Socket address filling should fail for empty address"); + + nl_addr_put(addr); +} +END_TEST + +START_TEST(addr_binary_addr) +{ + struct nl_addr *addr, *addr2; + char baddr[4] = { 0x1, 0x2, 0x3, 0x4 }; + char baddr2[6] = { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6 }; + + addr = nl_addr_alloc(4); + fail_if(addr == NULL, + "Allocation should not return NULL"); + + fail_if(nl_addr_set_binary_addr(addr, baddr, 4) < 0, + "Valid binary address should be settable"); + + fail_if(nl_addr_get_prefixlen(addr) != 0, + "Prefix length should be unchanged after nl_addr_set_binary_addr()"); + + fail_if(nl_addr_get_len(addr) != 4, + "Address length should be 4"); + + fail_if(nl_addr_set_binary_addr(addr, baddr2, 6) == 0, + "Should not be able to set binary address exceeding maximum length"); + + fail_if(nl_addr_get_len(addr) != 4, + "Address length should still be 4"); + + fail_if(nl_addr_guess_family(addr) != AF_INET, + "Binary address of length 4 should be guessed as AF_INET"); + + fail_if(memcmp(baddr, nl_addr_get_binary_addr(addr), 4) != 0, + "Binary address mismatches"); + + addr2 = nl_addr_build(AF_UNSPEC, baddr, 4); + fail_if(addr2 == NULL, + "Building of address should not fail"); + + nl_addr_set_prefixlen(addr, 32); + fail_if(nl_addr_get_prefixlen(addr) != 32, + "Prefix length should be successful changed after nl_addr_set_prefixlen()"); + + fail_if(nl_addr_cmp(addr, addr2), + "Addresses built from same binary address should match"); + + nl_addr_put(addr); + nl_addr_put(addr2); +} +END_TEST + +START_TEST(addr_parse4) +{ + struct nl_addr *addr4, *clone; + struct sockaddr_in sin; + socklen_t len = sizeof(sin); + char *addr_str = "10.0.0.1/16"; + char buf[128]; + + fail_if(nl_addr_parse(addr_str, AF_INET6, &addr4) == 0, + "Should not be able to parse IPv4 address in IPv6 mode"); + + fail_if(nl_addr_parse(addr_str, AF_UNSPEC, &addr4) != 0, + "Should be able to parse \"%s\"", addr_str); + + fail_if(nl_addr_get_family(addr4) != AF_INET, + "Address family should be AF_INET"); + + fail_if(nl_addr_get_prefixlen(addr4) != 16, + "Prefix length should be 16"); + + fail_if(nl_addr_iszero(addr4), + "Address should not be all zeroes"); + + clone = nl_addr_clone(addr4); + fail_if(clone == NULL, + "Cloned address should not be NULL"); + + fail_if(nl_addr_cmp(addr4, clone) != 0, + "Cloned address should not mismatch original"); + + fail_if(nl_addr_fill_sockaddr(addr4, (struct sockaddr *) &sin, &len) != 0, + "Should be able to fill socketaddr"); + + fail_if(strcmp(nl_addr2str(addr4, buf, sizeof(buf)), addr_str), + "Address translated back to string does not match original"); + + nl_addr_put(addr4); + nl_addr_put(clone); +} +END_TEST + +START_TEST(addr_parse6) +{ + struct nl_addr *addr6, *clone; + struct sockaddr_in6 sin; + socklen_t len = sizeof(sin); + char *addr_str = "2001:1:2::3/64"; + char buf[128]; + + fail_if(nl_addr_parse(addr_str, AF_INET, &addr6) == 0, + "Should not be able to parse IPv6 address in IPv4 mode"); + + fail_if(nl_addr_parse(addr_str, AF_UNSPEC, &addr6) != 0, + "Should be able to parse \"%s\"", addr_str); + + fail_if(nl_addr_get_family(addr6) != AF_INET6, + "Address family should be AF_INET6"); + + fail_if(nl_addr_get_prefixlen(addr6) != 64, + "Prefix length should be 64"); + + fail_if(nl_addr_iszero(addr6), + "Address should not be all zeroes"); + + clone = nl_addr_clone(addr6); + fail_if(clone == NULL, + "Cloned address should not be NULL"); + + fail_if(nl_addr_cmp(addr6, clone) != 0, + "Cloned address should not mismatch original"); + + fail_if(nl_addr_fill_sockaddr(addr6, (struct sockaddr *) &sin, &len) != 0, + "Should be able to fill socketaddr"); + + fail_if(strcmp(nl_addr2str(addr6, buf, sizeof(buf)), addr_str), + "Address translated back to string does not match original"); + + nl_addr_put(addr6); + nl_addr_put(clone); +} +END_TEST + +START_TEST(addr_info) +{ + struct nl_addr *addr; + char *addr_str = "127.0.0.1"; + struct addrinfo *result; + + fail_if(nl_addr_parse(addr_str, AF_UNSPEC, &addr) != 0, + "Parsing of valid address should not fail"); + + fail_if(nl_addr_info(addr, &result) != 0, + "getaddrinfo() on loopback address should work"); + + freeaddrinfo(result); + nl_addr_put(addr); +} +END_TEST + +Suite *make_nl_addr_suite(void) +{ + Suite *suite = suite_create("Abstract addresses"); + + TCase *tc_addr = tcase_create("Core"); + tcase_add_test(tc_addr, addr_alloc); + tcase_add_test(tc_addr, addr_binary_addr); + tcase_add_test(tc_addr, addr_parse4); + tcase_add_test(tc_addr, addr_parse6); + tcase_add_test(tc_addr, addr_info); + suite_add_tcase(suite, tc_addr); + + return suite; +} diff --git a/tests/check-all.c b/tests/check-all.c new file mode 100644 index 0000000..e801003 --- /dev/null +++ b/tests/check-all.c @@ -0,0 +1,42 @@ +/* + * tests/check-all.c overall unit test program + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2013 Thomas Graf + */ + +#include + +extern Suite *make_nl_addr_suite(void); + +static Suite *main_suite(void) +{ + Suite *suite = suite_create("main"); + + return suite; +} + +int main(int argc, char *argv[]) +{ + SRunner *runner; + int nfailed; + + runner = srunner_create(main_suite()); + + /* Add testsuites below */ + + srunner_add_suite(runner, make_nl_addr_suite()); + + /* Do not add testsuites below this line */ + + srunner_run_all(runner, CK_ENV); + + nfailed = srunner_ntests_failed(runner); + srunner_free(runner); + + return nfailed != 0; +} From 549d26dc87a8430f99aa8e48236a25630b2b1d31 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 14 Mar 2013 18:52:17 +0100 Subject: [PATCH 428/432] rtnl-addr: Inherit prefix length to nl_addr objs in rtnl_addr_set_prefixlen() Previously if using rtnl_addr_set_prefixlen() the new prefix length was not forwarded to the corresponding 'struct nl_addr' objects associated with address already and thus the comparison function would fail. This patch also clears the internal ADDR_ATTR_PREFIXLEN flag if the prefix length has been reset. Signed-off-by: Thomas Graf --- lib/route/addr.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/lib/route/addr.c b/lib/route/addr.c index 95a9447..e62c964 100644 --- a/lib/route/addr.c +++ b/lib/route/addr.c @@ -814,10 +814,39 @@ int rtnl_addr_get_family(struct rtnl_addr *addr) return addr->a_family; } -void rtnl_addr_set_prefixlen(struct rtnl_addr *addr, int prefix) +/** + * Set the prefix length / netmask + * @arg addr Address + * @arg prefixlen Length of prefix (netmask) + * + * Modifies the length of the prefix. If the address object contains a peer + * address the prefix length will apply to it, otherwise the prefix length + * will apply to the local address of the address. + * + * If the address object contains a peer or local address the corresponding + * `struct nl_addr` will be updated with the new prefix length. + * + * @note Specifying a length of 0 will remove the prefix length alltogether. + * + * @see rtnl_addr_get_prefixlen() + */ +void rtnl_addr_set_prefixlen(struct rtnl_addr *addr, int prefixlen) { - addr->a_prefixlen = prefix; - addr->ce_mask |= ADDR_ATTR_PREFIXLEN; + addr->a_prefixlen = prefixlen; + + if (prefixlen) + addr->ce_mask |= ADDR_ATTR_PREFIXLEN; + else + addr->ce_mask &= ~ADDR_ATTR_PREFIXLEN; + + /* + * The prefix length always applies to the peer address if + * a peer address is present. + */ + if (addr->a_peer) + nl_addr_set_prefixlen(addr->a_peer, prefixlen); + else if (addr->a_local) + nl_addr_set_prefixlen(addr->a_local, prefixlen); } int rtnl_addr_get_prefixlen(struct rtnl_addr *addr) From b39c9f7a53bdaecda444675bbacf25df4c7292a6 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 14 Mar 2013 18:57:15 +0100 Subject: [PATCH 429/432] rtnl-addr: Fix invalid call to nl_addr_set_prefixlen() if neither local or peer address are present Signed-off-by: Thomas Graf --- lib/route/addr.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/route/addr.c b/lib/route/addr.c index e62c964..71fca94 100644 --- a/lib/route/addr.c +++ b/lib/route/addr.c @@ -199,8 +199,9 @@ static int addr_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, struct rtnl_addr *addr; struct ifaddrmsg *ifa; struct nlattr *tb[IFA_MAX+1]; - int err, peer_prefix = 0, family; + int err, family; struct nl_cache *link_cache; + struct nl_addr *plen_addr = NULL; addr = rtnl_addr_alloc(); if (!addr) @@ -244,6 +245,7 @@ static int addr_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, if (!addr->a_local) goto errout_nomem; addr->ce_mask |= ADDR_ATTR_LOCAL; + plen_addr = addr->a_local; } if (tb[IFA_ADDRESS]) { @@ -263,12 +265,13 @@ static int addr_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, } else { addr->a_peer = a; addr->ce_mask |= ADDR_ATTR_PEER; - peer_prefix = 1; } + + plen_addr = a; } - nl_addr_set_prefixlen(peer_prefix ? addr->a_peer : addr->a_local, - addr->a_prefixlen); + if (plen_addr) + nl_addr_set_prefixlen(plen_addr, addr->a_prefixlen); /* IPv4 only */ if (tb[IFA_BROADCAST]) { From 4db11517fd7b28a48f19c79a0867331c536722d0 Mon Sep 17 00:00:00 2001 From: Tony Cheneau Date: Sat, 16 Mar 2013 00:23:19 -0400 Subject: [PATCH 430/432] Remove superfluous declaration of rtnl_route_put() rtnl_route_put() is declared twice in the same header file Signed-off-by: Tony Cheneau Signed-off-by: Thomas Graf --- include/netlink/route/route.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/netlink/route/route.h b/include/netlink/route/route.h index d3543af..477250d 100644 --- a/include/netlink/route/route.h +++ b/include/netlink/route/route.h @@ -54,7 +54,6 @@ extern int rtnl_route_alloc_cache(struct nl_sock *, int, int, struct nl_cache **); extern void rtnl_route_get(struct rtnl_route *); -extern void rtnl_route_put(struct rtnl_route *); extern int rtnl_route_parse(struct nlmsghdr *, struct rtnl_route **); extern int rtnl_route_build_msg(struct nl_msg *, struct rtnl_route *); From 23e26e9e054f921a0c91379c628abb8126c42195 Mon Sep 17 00:00:00 2001 From: Tony Cheneau Date: Sat, 16 Mar 2013 00:23:18 -0400 Subject: [PATCH 431/432] Remove rtnl_link_free() declaration from the header file. Reason: there is no rtnl_link_free() definition anywhere in the code. Signed-off-by: Tony Cheneau Signed-off-by: Thomas Graf --- include/netlink/route/link.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/netlink/route/link.h b/include/netlink/route/link.h index dbde72f..321a80d 100644 --- a/include/netlink/route/link.h +++ b/include/netlink/route/link.h @@ -99,7 +99,6 @@ typedef enum { extern struct rtnl_link *rtnl_link_alloc(void); extern void rtnl_link_put(struct rtnl_link *); -extern void rtnl_link_free(struct rtnl_link *); extern int rtnl_link_alloc_cache(struct nl_sock *, int, struct nl_cache **); extern struct rtnl_link *rtnl_link_get(struct nl_cache *, int); From 6c9be5a31681ddf9a669ecf643092928ab0f2138 Mon Sep 17 00:00:00 2001 From: roopa Date: Sat, 23 Mar 2013 17:42:59 -0700 Subject: [PATCH 432/432] nl-route-add: Add NLM_F_EXCL flag to route add Signed-off-by: Roopa Prabhu Signed-off-by: Thomas Graf --- src/nl-route-add.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nl-route-add.c b/src/nl-route-add.c index 2f187df..d4aa767 100644 --- a/src/nl-route-add.c +++ b/src/nl-route-add.c @@ -120,7 +120,7 @@ int main(int argc, char *argv[]) } } - if ((err = rtnl_route_add(sock, route, 0)) < 0) + if ((err = rtnl_route_add(sock, route, NLM_F_EXCL)) < 0) nl_cli_fatal(err, "Unable to add route: %s", nl_geterror(err)); if (!quiet) {