diff options
author | Paul Stewart <pstew@google.com> | 2016-11-04 10:50:31 -0700 |
---|---|---|
committer | Paul Stewart <pstew@google.com> | 2016-11-11 12:31:50 -0800 |
commit | 054c80d775f2ae9b8f50260bdfcb821e99c0da2a (patch) | |
tree | 9749e9fc8313b0745b2b96e0102d41a63b2a2db4 /src | |
parent | 3f563dcf99d53a43799e5bd75d7761fcd9716c5a (diff) | |
download | libnl-054c80d775f2ae9b8f50260bdfcb821e99c0da2a.tar.gz |
Update libnl to 3.2.25
Commits:
2dbc1ca Generic Netlink multicast groups support
3229b32 - Prepare for 2.1.x tree - Bump interface number, we will break API in the development tree
c0cd587 nl-qdisc-add tool
fa89403 HTB: Append TCA_OPTIONS even if no options are set
757592e classid database
23c6191 remove obsolete nl-qdisc-add code
1884809 pfifo/bfifo qdisc support for cli libs
27883b0 nl-class-add tool
a670ee5 make nl-qdisc-list installable
420438c Remove NL_DUMP_ENV code
cefe7db Make nl-qdisc-delete installable
8699ba8 nl-class-delete tool
2a9c3ef nl-class-list tool
3a96527 nl-qdisc-add(8), nl-qdisc-delete(8), nl-qdisc-list(8)
b9d965b Update include/linux header copies
4c6d1c5 Unified TC attributes interface
b57a697 nl-cls-* tools
65e386c Packet location updates
0fe5b29 Extended pktloc to support nbyte locations for ipv6, etc.
d0e5645 Avoid memcpy()/memset() when reserving space for nested attributes
e1eacd6 Fix use of uninitialized data at the end of netlink message
d7a561a Tons of ematch work
2f86768 basic: Only add ematches to message if available
691905b cgroup classifier improvements - enabled again - ematch support - cli tools module
897828d src/nf-queue: revert nonsensical change
ee88c71 routing rules: mark support
6862c65 Include RTA_MARK in routing rule messages
6d43441 Updated arp and ethernet codes
873a64e Support for 64bit link counters IFLA_STATS64
2e6d497 Support neighbour flag NTF_USE
48cdb1f Support RT_TABLE_COMPAT
8585276 Revert "Include RTA_MARK in routing rule messages"
1eccb7b Revert "routing rules: mark support"
f703192 routing rules: adapt to unified routing rules
cc22992 Improved debugging messages while constructing messages/attributes
93f992e attr: Add padding if nested data does not end at an alignment boundry
c7a6737 text ematch support
7903d6a Support for meta match
4267d8f classid auto generation if provided tc name does not exist
4e48d90 Correctly parse and generate classids
54e2539 nl-qdisc-list: --recursive - print tc objects recursively
df36c25 nl-classid-lookup: Added --raw option to print classid without pretty printing it
d95a419 ematch/meta: id definitions
738ee7f nl-qdisc-delete: Do not attempt to delete default qdiscs
d283c8e Correctly state the process of sending a netlink message. A message passes through nl_send_iovec() before hitting nl_sendmsg()
59880cb pktloc: support to specify a shift operator for packet locations
8970c5c link: Support IFLA_IFALIAS attribute
fd857ee link: Support IFLA_NUM_VF attribute - parses attribute if available - provides API to access value rtnl_link_get_num_vf(link, num_vf)
3fa6a6b link: API for address family specific link data
280d457 link/api: Check for null pointer in rtnl_link_af_ops_put()
800013b link: Support for AF_BRIDGE address family
67aeb74 link/api: Convert link info ops to use nl_list_head
12b82e4 link/api: Improve API documentation.
2847cf0 Make nl_str2af return a negative value if parsing fails
7ff4dee Extend rtnl_link_alloc_cache() to support address families
f64ebab Add all libraries for libtool to improve linkage
407e9eb Add local copies of linux/ipv6.h and linux/snmp.h
e69efad Add support for per interface ICMPv6 statistics
a4efc65 link: Add support for IPv6 specific link data - parses IFLA_PROTINFO - dumps flags, cacheinfo, devconf and all statistics
2e3ca4d link: Support for IFLA_AF_SPEC
53015f8 link: AF_INET link module
b6592cb link: Fix typo, use rtnl_link_af_alloc() to make sure data buffer is allocated
e209971 link/inet: Fix array access
2575d03 link: Add missing IFLA_AF_SPEC container attribute
ee57cc7 link: define RTM_SETLINK to allow pretty printing
01bc3c5 link/inet: documentation: add examples
a3ea8a6 Make syntax of nl-link-list consistent and install it
f56317f update Doxyfile to latest version
4d28cc5 link/inet: pretty printing, make output more readable
3a95620 sfq: perturb period is in seconds, not jiffies
10424b2 Rename nl_get_hz() to nl_get_user_hz() to indicate it's not the in-kernel HZ value
d8eeb0a New function nl_size2str()
98ffede link/inet6: pretty printing
cf5577d constify struct trans_tbl
c32c3f3 socket: constify interface
09daef3 Don't build doc.c, there is no real code in it
063a2eb only perform automatic sequence checking if auto-ack mode is enabled
8a365db rename nl_send_auto_complete() -> nl_send_auto(), nl_auto_complete -> nl_complete_msg()
5a08c8f Inherit return code of NL_CB_MSG_OUT in nl_sendmsg()
6545206 Documentation updates - moved documentation from lib/doc.c to doc/src/ - splitted pages into separate files - worked over core sections, explaining the receiving and sending behaviour in much more details including the the available mechanisms to customize the behaviour - updated the html stylesheet file for increased readability, probably needs some doxygen patching to achieve what I am looking for. - enabled call graphs, not expanded by default
e52a09c nl: rename nlmsg_msg_size() to nlmsg_size(), nlmsg_len() -> nlmsg_datalen()
9fbdf6c nl_recv(): Make passing creds pointer optional
4fb528b nl_recv(): Zero out sockaddr in case the caller forgot
9513d4c Rename nlmsg_for_each_msg() to nlmsg_for_each()
c158d06 rename NL_AUTO_PID to NL_AUTO_PORT
7105aea addr: hide nl_addr_destroy()
5644578 Tons of documentation
82fe785 use linux/netlink.h instead of netlink/netlink-kernel.h
4b0126b prefix ipv6 link statistics identifiers with IP6
2d1626b Include <linux/pkt_cls.h> and <linux/pkt_sched.h> in <netlink/route/tc.h> for convenience
5f3dbf8 Fix function nfnl_ct_del name
b5c474e allowing silent rules in build
d8d67c0 Provide numeric version defines
59c3474 Add missing argument in rtnl_link_change example
ae5dfb1 Make struct nl_object public, NLHDR_COMMON has been public anyway
5a9f50b __nlmsg_alloc(): Guarantee minimal message size of at least the header
2c75886 Fix off-by-one when reading IFLA_INET6_CONF and IFLA_INET6_STATS
33e9403 Print debugging info while iterating a cache based on a filter
552c85c Hold reference to obj while calling callback of cache iterator
5dc897d provide function to retrieve htb rate
8eb5b55 Unified TC API
45941f9 rename sch -> qdisc
722a227 fix module parent references
55f803c libnl-3.0
c1073d6 Documentation updates
f0603a4 add missing checks for ROUTE_ATTR_MULTIPATH
38db636 add missing nl_cache_search in cache.h
a0fe7a1 Omit empty nested attributes
913579b Fix out-of-tree build.
9f1abdd Fix "make distcheck".
14fa557 Set default MTU to 1500
93b6c11 Add NLE_NODEV error
a62bfdb Check if all mandatory attributes are present in rtnl_tc_msg_build()
8d54934 Cleanup <netlink/route/qdisc.h> - remove dead prototypes - reformat
f523f29 Allow NLSYSCONFDIR environment variable to overwrite built-in sysconfdir
e4b507e Deprecate rtnl_qdisc_foreach_child() and rtnl_qdisc_foreach_cls()
7e9d5f6 correctly handle the object not found case
23845e9 Add nl_send_sync()
747b892 Qdisc API improvements and documentation
7c62050 trafic class/classifer API improvements and documentation
350b15f Move to asciidoc
475dffa Provide TC_HANDLE(maj, min) macro to generate tc handles
2dbe7d7 Initialize dump buffer in case caller missed it
ef327ff Provide nl_object_dump_buf() to easily dump to buffers
23c27b4 Provide nl_cache_set_arg{1,2}() to specify cache args
0893aaf link: Make return and argument type match
41fb241 link: Provide rtnl_link_delete() to delete virtual links
48d543c API to issue direct GET requests to the kernel
b5918b5 fix line removed by mistake
96bc6d6 Improve rtnl_link_change() behaviour
e81814a Support for rtnl_link_add()
5a66101 dummy interface support
8ffab45 export rtnl_link_add() and rtnl_link_build_add_request()
3d70697 Add support for ARPHRD_NONE
36b0474 Support link info types with no payload
4c6dd3a Expose <netlink/route/link/inet.h>
fac4885 Improve readability of classid string representation
c18730d Set tc->tc_link if link cache is available
83f1411 Fix clone() of AF specific link data
daefa76 Provide rtnl_tc_get_link() and fix link refcnt
cc33b09 Add missing declaration of rtnl_tc_get_link()
cb6a089 Adding rule with "From" option doesn't work
d44c31d addr: store link object and provide rtnl_addr_get()
023c662 Use name "global" instead of "universe" for largest scope
f443be6 python interface to netlink protocols
4cb1666 Provide silent variation of nl_cache_require()
ed69b2a Add rtnl_tc_data_check()
58e0e1e Add nl_rate2str()
aba3689 Provide documentation for rtnl_tc_data() and rtnl_tc_data_check()
053c93f Update local copies of include/linux
09210d9 HTB: Add support for level and direct pkt stats, complete access functions
e56eb06 Work on libnl-python
4806c5c Don't redefine offsetof when already defined by e.g. stddef.h
c881908 neigh: include ndm flags while building message
ca0fc75 socket: Set SOCK_CLOEXEC if available
21d52ea Support for NLM_F_INTR
63548f5 documentation updates
7d48455 Documentation updates
dea6de4 Include IFLA_LINK in link messages
5007473 more documentation updates - improved stylesheets for both doxygen and asciidoc - use of xml doxygen layout - python script to resolve <<foo>> asciidoc references to <<foo, title>> based on the target caption - graphics for netlink and netlink error headers - more link documentation
4d23836 bonding link module
c79ab52 ignore various generated files
49d29e9 ignore python build directory
16d38a4 Use 'link type' instead of 'link info type'
8219cc7 VLAN: rtnl_link_is_vlan() function and API documentation
bf1b5d2 removed autogenerated swig interface files from git tree
20e9797 use rtnl_link_set/get_type()
f3ee216 include <linux/if.h> from <netlink/route/link.h> to export IFF_* flags
915a23f Hack doxygen CSS to avoid stupid margins in modules listing
70c9371 Updated link documentation
f1c8d5b 3.1 release
f999383 Remove write-only variables in lib/cache.c
7701c85 Make some functions and global variables static
bbe5e94 Put "break" inside the "if" block in route_compare()
d886de5 Allow building documentation out of the tree
b5d081d Avoid freeing memory if vasprintf() failed
569bec5 make port map thread safe
7a46ef0 Include all files necessary to build documentation in distribution
d8d96bb link: fix unaligned access to 64bit link stats
23333e5 python: Include python/ in distribution and provide a README on how to build & install
cc9ae9b doc: need to include @srcdir@/src not @top_srcdir@/src
4be7adb htb: fix misplaced memset() overwriting already set htb prio option
b367024 Local port leak on nl_socket_alloc/nl_socket_set_local_port(, 0)
eabb753 nl-link-name2ifindex: fix usage text
6faeffe socket: introduce nl_socket_modify_err_cb
17781e4 socket: fix two typos
7adaad7 genl: genl_ctrl_grp_by_name: fix retval in case group id not found
f1d9e9d 64bit unaligned access
b4b853e Do not require python and swig to be present
db6de56 fix license of lib/route/pktloc.c
7ac948c Remove GPL-3.0 license file.
80569bb remove dist lines for non existing files
2a37ab5 prepare for 3.2 release
5a59cf8 asciidoc xhtml stylesheet
7b0d063 lib: Use @MAJ_VERSION and @MAJ_MINOR@ for -version-info
226b387 Install headers in ${includedir}/libnl3
6e5332b Inform users about changed include location at end of configure script
a73cb2f build: always install files into /etc/libnl
4c210ad Switch to libtool versioning system
b50195c addr: Add missing header to <netlink/route/addr.h>
6d93b83 route: Remove dead link_cache variable
109ea68 tools: Use LDADD and link against .la files instead of LDFLAGS and -llib
67bd56f Fix a73cb2f26 fallout to allow building in separate directory
5151cbc link: Eat ACK followed by RTM_NEWLINK when requesting single link
96f17ce bonding: API to create/enslave/release
15b13dd bonding: Install <netlink/route/link/bonding.h>
076909a Bonding: Fix header guard of <netlink/route/link/bonding.h>
0d9958e Ingnore src/nl-link-enslave and nl-link-release
1c9b175 Provide micro version in <netlink/version.h>
d3bb7c9 3.2.1 release
f90dc63 Add libnl-cli-3.0 to pkg-config tool
d17379d Fix rtnl_link object memory leak when freeing rtnl_addr objects.
6c70cf7 Don't install CLI header files when --disable-cli has been configured.
790966d Only use the MULTIPATH attribute when adding routes with more than one next hop.
30d3f8c utils: Initialize list head after freeing translation list
2bcd8ec cache: event_filter() cache operation to filter notifications
7f20c57 link: Ignore bridging notifications in link cache manager
9c7593c python: Link against nl-3 and nl-route-3
8104b52 Fix typo in debug message
659b6d6 bump to 3.2.2
03f3a58 link: generic link enslaving API
bd70009 add missing IFLA_MASTER fillup
32f30b7 release 3.2.3
88940b7 build: simplify optional dirs/files in Makefile.am processing
ef75c4e link: allow to add/get linkinfo of unknown type
847e269 rtnl_link_bond_add: allow to allocate bond name in case NULL is given
4a7791e dsmark: Add missing declarations for rtnl_class_dsmark_(get|set)_bitmask()
9819717 avoid dangling co_major_cache reference to NL_AUTO_PROVIDE caches
d7222e5 3.2.4 release
794ac78 nl_addr_cmp(): handle prefix length during address comparison
4035e5b link: fix regression in link message parser
9015d11 3.2.5 release
d111b1d cli: Use -avoid-version to link cli modules
c857625 Update COPYING to fix FSF address
83ab0ae man: Remove bogus .LO macro in manpages
4cc1daa 3.2.6 release
9cbcbca 3.2.7 release
a39bb56 add new function to provide neighbour event parsing
a17970b Support plug qdisc - queue traffic until explicit release
0b40364 Add new nl_cache_clone() function.
f7d0661 doc: Fix typos in autoconf example
965fd78 missing extended Table attribute for lib/route/
7d47666 doc: Fix incorrect nl_socket_add_memberships() example
f54ac3d Memory leak in classid.c
073ef6a genl-ctrl-list: Introduce -d|--details as a shortcut for --format=details
5399b3d genl-ctrl-list: Provide manual page
4a2962d genl-ctrl-list: fix copyright and summary
5f4d4d3 genl-ctrl-list: Mark for installation
653ea34 cache_mngr: document uncommon error codes
9af5469 tests: Convert tests/Makefile to use automake
e78975a tests: fix test programs to compile again
b320112 cache_mngr: Don't modify callback setup of socket
c55acc4 cache_manager: Move documentation to doc/core.txt
e34ed95 cache_mngr: Automatically allocate socket if needed
a143037 test-cache-mngr: Let the cache manager allocate the socket
adbc568 cache_mngr: Fix memory corruption after resizing
e048279 nl: Make nl_recvmsgs() return the number of netlink messages processed
a518a31 cache_mngr: Let nl_cache_mngr_data_ready() read multiple messages
743756f cache_mngr: API doc updates
5165366 cache_mngr: Provide nl_cache_mngr_info() to pring cache manager details
2ed371e test-cache-mngr: Allow for management of arbitary caches via argument string
2e93940 cache_mngr: Make providing the result pointer to nl_cache_mngr_add() optional
8bbcd22 genl: Make genl_unregister() a NOP if NULL pointer is passed
2e23491 cache: improve documentation of co_event_filter
bd1e4d0 cache: Add co_include_event allowing caches to provide their own nl_cache_include() implementation
ff3e9e3 object: Add functions to access the object type, cache and object ops
ad5d2b7 3.2.8 release
d726ecd Fix two bugs in 3.2.8/doc/
6f156a7 nl: Fix return value of nl_recvmsgs()
f8b4f92 3.2.9 release
beb40e2 u32: add support for hashing
7b503a1 u32: example/test code for u32 hashing with HTB
183e869 doc: Check documentation generation requirements with autoconf
2fbab02 doc: add section about addressing
100403a route: Add FIXME to rtnl_route_nh_set_gateway() to fix return value
32057bc __str2flags fix
fec10a2 doc: documentation restructuring
996b502 FTBFS with musl libc: Missing includes
6627ec3 tc: fix included headers
24d577c u32: fix various u32 hashing related warnings
ca883b6 Fix for dumping objects to a buffer instead of file descriptor
9bb30a5 add fwmark mask support
970f5d0 correct HTB rtable/HZ calculations
d733f8a use MSG_TRUNC flag to get recv message size at once
0b70de5 genl: updates to API reference documentation
71b442b genl: Add genlmsg_hdr()
3656b6f genl: Add genlmsg_user_hdr(), genlmsg_user_data(), and genlmsg_user_datalen()
faef2fa genl: Support registration of families without depending on caches
8fad2e3 genl: Export genl_ops_resolve() and genl_mngt_resolve() in header
43eab46 genl: Update genl-ctrl-list(8)
0c408aa genl: modify genl_ctrl_resolve and friends to allow for module auto-loading
405d168 libnl 3.2.10
2275bb0 Fix compilation with clang
d3dcde2 rtnl_netem_set_delay_distribution: fix possible segfault
d8a25e4 netem: Use ARRAY_SIZE()
bf54d6d Fixed address deletion
9d60ef0 Removed generated .pyc files from repository
1e75bd0 Make syntax highlighters happy
f55ea7f Fix typo in still unused function that generate colored message
4be1ae2 Introduce Python's absolute_imports
b369d22 Fix whitespaces at EOL
38fefc5 Fixed various str-related logick
c1547d9 Flags properties description and implementation fixed
fb890a5 Code cleanups
83f06bf Fix indentation (spaces vs tabs)
8959d95 Using only single quotes now and multi-line lists
454ea4a pylint's first review and trivial fixes
482c602 Refine some places
08e8b35 Remove unnecessary comments
139e3d3 nl_pickup removed from python binding
87d3709 netlink.nlattr re-implemented in more pythonic way
dca358c rtnl_link_(get|set)_weight is deprecated in libnl.
ffa461d Fixed memory leak in Cache destructor
3c53265 Add 'ingress' to the list of recognized TC handles.
84037be Correct missing fwmark mask proto.
69da6af genl: Wait for ACK after successful ctrl reply
49fe936 genl: cleanup genl_ctrl_resolve()
4f93364 link: rtnl_link_get_kernel() should only wait for ACK if AUTO-ACK is on
2bdcde7 Fix types-related warnings based on clang diagnostics
941ba95 libnl 3.2.11
9426d03 tbf: fix false missing attr
052a131 nl_cli_route_parse_table fixed typo in code
a0f1c0e ct_dump_stats: detect when stats are not available
25d640d lib/utils.c: One kilobit now is a 1000bits (instead of 1024)
8222519 Fix the always false if (a->rt_nr_nh != a->rt_nr_nh) test
376a0e2 Fix build warning after const char ** convert
97d2460 route_clone : fix segmentation fault using nl_cache_subset to filter routes
de28daf nl_addr_parse handling of 'default', 'any', and 'all'
b62e019 single nexthop flags bug
d10d963 Added lex.yy.c to .gitignore
582a324 Run-time version information is now available
ab15d06 "%llu" replaced with "%" PRIu64
8cd2f57 Fix typo in textual description in ct_dump_stats()
a2b23ff Fix warning "not checking return value of fscanf" in lib/utils.c: get_psched_settings
5eee974 Prevent potential socket file descriptor leak
717fabc configure: Check for graphviz and source-highlight before building documentation
b377ab1 route: Document ROUTE_CACHE_CONTENT flag
5eeb3d3 doc: Update Doxyfile config to latest release
929bd01 configure: Check for pygmentize when building docs
3bf8712 3.2.12 release
8f2ce4d More clean NL_AUTO_PORT and NL_AUTO_SEQ usage in nl_complete_msg
0026125 Address comparison bug fixed
49c94c3 genl_ctrl_probe_by_name: fix checking of genlmsg_put() return value
49be8cd doc: Update Doxyfile.in to latest syntax
b1e0a0c Remove auto-generated Doxyfile from git
a820222 asprintf related fixed in yy parser
fddba71 libnl-3.2.12 - ./configure --disable-doc: error: conditional "LINK_DOC" was never defined. \ Usually this means the macro was only invoked conditionally.
ce72837 3.2.13 release
72c2cb9 Enabled the use of Links as context managers.
e4192ff nl: Provide API to specify the default buffer size when receiving netlink messages
6ac0717 link: Support IFLA_PROMISCUITY link attribute
d2876f8 link: correctly set LINK_ATTR_PROMISCUITY
36ed882 link: Support IFLA_NUM_TX_QUEUES and IFLA_NUM_RX_QUEUES
7f6880c link: Only print "promisc-mode" if users > 0
f2e2e7f link: Include IFLA_NUM_TX_QUEUES and IFLA_NUM_RX_QUEUES when building messages
36139cf doc: Provide documentation for link promis counter and rx/tx queues
a35287a link: Support link grouping
c3376e7 Conntrack Dump ICMP
2d674fe doc: mark route.txt as WIP
db13843 doc: Split doc/ into separate packages
65c3919 Only include doc/ in dist
1fa61d1 3.2.14 release
5535f59 Don't include doc/ in toplevel dist
787f14d genl/family flags can be damaged during the auto-indentation.
fedb862 ROUTE_DIFF result was not used in some place in route_compare
e1b67fb Clang diagnostics
e7ec197 nf-log example: correct copy-range parsing
9d6b104 nl_recv(): "else if" logick simplified and refined
6946851 nl_recv(): Memory allocation errors are handled properly now
2249eae nl_recv(): EWOULDBLOCK return value also checked
da694e6 nl_recv(): small code cleanups
420e462 nl_recv(): work with credentials only if "creds" given and NL_SOCK_PASSCRED set
3c1ab42 add missing '}' in __cplusplus namespaces
40457db Exp checkpoint
20035ce Checkpoint: compare function
e8b3356 "checkpoint"
c675bf0 Checkpoint before compilation attempt
f111efd Successful compilation of libnl-nf with expectation
4a702e6 Starting CLI work
daf5f93 Compile CLI
453492c Expectation get cli tool
3cb581d update gitignore
d3bec59 bugfixes
547c8f6 reinit port numers on tuple dump
4164595 Bugfixes
0741865 define advanced attributes out
2d70751 Updated nfnetlink includes; removed ifdefs; added delete exp program
d2fff93 Source cleanup for upstream
a8ef352 Add configure option to disable pthreads support
503270c Remove unreachable code
16e54c4 Add missing va_end() calls
3750e2a Set err and free ntbl when leaving neightbl_msg_parser
690264a Add new object op oo_id_attrs_get
bc7c822 Add support for updating objects in the cache
ceb8fb9 Document buffer size limitations of nl_recv()
6d52ae6 nl_recv: Don't update *buf in error path
fb42f19 nl_recv: improve function documentation
eb36066 nl_recv: return NLE_INVAL if buf is NULL
220d8e1 nl_recv: return NLE_INVAL if socket address pointer is NULL
65f97de nl_recv: fix indent style
b25f26b socket: document nl_socket_get_fd()
8f47501 nl: improve nl_sendto() docs and error checks
a721c1d doc: increase dot max graph nodes to 100
b132ee7 nl: improve API doc of transmit functions
fd6f205 nl: Allow to overwrite nl_send()
b28c25e nl: Improve API doc of nl_connect() and nl_close()
665464c nl: Improve API doc of nl_send_simple()
a8741fa Add hash function
c6f89ed Add nl hashtable structures and access functions
55c0e03 Add hash support in cache mngr
e16e8fd Add hash support to link cache
6f24cf1 Add hash support to neigh cache
a2207c7 Add hash support to route cache
5641c0e Hash: Properly prefix hash functions
ae1e236 hashtable: Add API reference documentation
59a6b00 hashtable: Fix reference leak in nl_hashtable_free()
b66d267 hashtable: remove doc section crashing doxygen
7e075c6 doc: update Doxygen layout file to latest format
5a04760 addr: Return -NLE_AF_NOSUPPORT when trying to set unsupported attributes
3132db5 addr: rtnl_addr_set_peer() is limited to IPv4
c83ecb3 doc: Revert to default stylesheet
dd8a87d Add support for per cache flags
30d8626 New cache manager add cache api
0bd14aa Add NL_CACHE_AF_ITER support during refill and resync
ce72565 cache: Move NL_CACHE_AF_ITER to <netlink/cache.h>
5734011 cache: Fix typo in API doc of nl_cache_set_flags()
8ffa257 cache: Move nl_cache_ops_set_flags() to cache_mngt.c
ea79a76 addr: Support setting local/peer/anycast/multicast/broadcast address to NULL
125119a Add AF_BRIDGE support to link cache
64fcb47 Add AF_BRIDGE support to neigh cache
cb25338 Add master support to rtnl_neigh for AF_BRIDGE objects
c658a6e cache: Add reference counter to caches
3ed1f9a cache: Hold cache reference while a cache is being provided
20efa14 lock abstraction layer
f5af5c5 cache: rwlock accesses to cache operations
74926f9 link: Protect registration of af and link ops with rwlock
1a2c3e3 cache: Add reference counter to cache operations
2b3912a cache: Provide safe versions of nl_cache_ops_associate() and nl_cache_ops_lookup()
cb82c2a use safe cache lookup variants internally
235aa7f cache: hold a reference to the cache ops while a cache is provided over it
23c4ef6 Use NL_DBG() instead of printing warnings and errors to stderr
00132b4 cache: provide safe variant of nl_cache_mngt_require() and use it
4d94ed5 Bug Fix: Add new fill socket to cache manager
a2c4bd8 Updated configure.in to make sure bison and lex are installed.
0a9d5fc configure: Replace broken AM_PROG_LEX with AC_CHECK_PROGS
3163fa7 cache: reserve room in cache_ops to avoid breaking module ABI too frequently
ed3d706 Include the newly added header files in next release
05a6723 3.2.15 release
4149154 cache: only continue iterating over co_groups if it is available
f535de3 3.2.16 release
a96a3b6 build: rename configure.in -> .ac
9d92564 build: resolve automake-1.12 warnings
f3cd3fe build: use AC_CONFIG_AUX_DIR
0ba9e99 build: use foreign mode
ab7f42e build: resolve lex failure
5251188 link: basic socket-CAN support
c86088f link: socket-CAN helper functions
68967eb Fix python detection code
de14136 Fix make check when using --disable-cli
913a689 can: provide local copy of <linux/can/netlink.h>
7c85b8a netfilter: update local header files
89e1b30 Included defs.h so DISABLE_PTHREADS is visible.
25c407c Re-adding #defines for __aligned_be64 for older kernels
29b7137 route cache: Fix handling of ipv6 multipath routes
20a0512 Bug Fix: cache_include: Fix object ref release after successful object update
91ab1be make: automake provides a cscope target these days
96bb7c9 cache pickup: Avoid duplicates during cache pickup
de21332 cache: Take cache_ops lock when modifying cache ops flags
6971932 Fix file descriptor leak on error
5d53626 nlmsg_ok comparison between signed and unsigned
6369e1f 3.2.17 release
00a5879 Add <netlink/route/link/can.h> to dist target
ba38f39 cache: make sure the user has specified a callback
de5744f build: Fix distribution to include 'nfnetlink_conntrack.h'
383ff94 fix include/Makefile.am
f123795 3.2.18 release
3540e44 link: add carrier support
b1ebda9 cache: Add new nl_cache_find api
09213ee link af ops: Add new ao_compare op to compare link af_data
310ec86 Add ao_compare support to bridge family af_data
6b4a2cb 3.2.19 release
99399ca Add new rtnl_link_af_data_compare function to compare af_data
5c3f2f0 link: Add af data compare to link objects
5291af6 link: fix reference leak in rtnl_link_af_data_compare()
7559157 Undo soname bump
f20bbe1 No longer install module API headers
2b96c33 Remove obsolete release notes at end of configure
1481f97 route cache: This patch adds route priority to route object oo_id_attrs
26e22d8 3.2.20 release
1419851 fix includes after removing some headers
9680f91 Move private header files to <netlink-private/*>
1b9de9a Provide compat headers for removed private API
c6abb44 Fix test-cache-mngr test
c4f8033 Fix build warnings of nl-(qdisc|class|cls)-add
776cde0 Remove obsolete warning from <netlink/object-api.h> as it breaks NM build
b6afd0b Provide better help text when bumping CURRENT,AGE,REVISION
83c762d 3.2.21 release
56352ab netfilter: expectation NAT direction is 32 bit attribute
87244f7 netfilter: keep 8-bit API for 32-bit NAT dir attribute
6cc5fdc can: add helper function to get CAN bus state
b06c23a link cache: remove AF_UNSPEC check in rtnl_get_link and rtnl_get_link_by_name
4f088d3 netfilter: correct error in construction of NAT tuple
87458ab Fix mask calculation in nl_addr_cmp_prefix()
2005c2e cache: Make NL_ACT_* and nl_cache_ops_(get|put)() available
8571f58 neigh: Remove check for AF_UNSPEC in rtnl_neigh_get()
1c24480 can: Include "linux/can/netlink.h" in the distribution
506020a can: Fix nested message creation in can_put_attrs()
8b8e26b link: Fix af_ops leak on ENOMEM
2d36371 link: Keep reference to af_ops during lifetime of link object
e576768 link: Modify link policy on the stack
4a793a4 link: Hold af_ops reference for each AF_SPEC block during lifetime of link object
8026fe2 link: Free and realloc af specific data upon rtnl_link_set_family()
9f8548b attr: Provide nla_is_nested() function
fd19dae bridge: Support the new bridging attributes
5a5aa73 bridge: Provide rtnl_link_bridge_alloc()
bb9911b netlink: Forward declare frequent libnl types to ease inclusion deps
ee4122a vlan: Provide rtnl_link_vlan_alloc()
1ecf98a bond: Provide rtnl_link_bond_alloc()
8f151fa link: move af_data_compare to the end
ded2048 link: Fix rtnl_link_af_data_compare return value
4d7680c Use thread-safe strerror_r() instead of strerror()
9e6cdbf attr: Add nla_nest_cancel() to remove partially added nested attributes
60b370d attr: Do not enforce maximum length for NLA_FLAG attributes
64315f7 attr: No longer warn about attribute of type 0
1395c69 attr: Warn application if nla_parse() observes same attribute multiple times
c608b4d msg: Pretty print padding attributes in nl_msg_dump()
f72bfc7 msg: Pretty print error message header even if incomplete
f0f33c3 addr: Reset unused portion of binary address in nl_addr_set_binary_addr()
8852753 addr: improve API reference documentation for nl_addr_*()
780a042 addr: Update to latest address familiy definition for translation
e09e7f1 tests: Add check based unit test system
549d26d rtnl-addr: Inherit prefix length to nl_addr objs in rtnl_addr_set_prefixlen()
b39c9f7 rtnl-addr: Fix invalid call to nl_addr_set_prefixlen() if neither local or peer address are present
4db1151 Remove superfluous declaration of rtnl_route_put()
23e26e9 Remove rtnl_link_free() declaration from the header file.
6c9be5a nl-route-add: Add NLM_F_EXCL flag to route add
aad041c genl: Provide internal function to resolve name to id
ad545f2 genl: Update mt_id of cache ops when resolving genl id
f9241d5 cache: Improve debugging messages of cache operations
ff56710 nl: Print file:line:func in debugging messages and provide --disable-debug to disable debugging
18152ca ct: add ICMPv6 type,code and ID
df66b0f genl: Fix cb reference leak in genl_ctrl_probe_by_name()
375a629 nl: Return -NLE_AGAIN if non-blocking socket would block
56eb22f msg: Pretty print generic netlink header in nl_msg_dump()
ea43644 Perform no operation on nl_object_free(NULL).
d3cf89e addr: only translate more recent address family names and ARP types if defined
d505165 autoconf: Use PKG_CHECK_MODULES() instead of AM_PATH_CHECK()
ead4cde tests: Make unit test building optional
c07a6a3 attr: nla_is_nested() must access nla_type directly
59db7fb dump_attrs: "NLA_F_NESTED" => nla_is_nested(nla)
33396fa Fix leak of cb if nl_socket_alloc_cb() failed to allocate socket
3a6d256 attr: Fix typo in nla_is_nested()
979ea33 Wrong calcultation in nla_reserve
ffc0ee3 configure: Convert ENABLE_UNIT_TESTS to a mere AM conditional
4e9aa6a tests: Add basic attribute unit tests
ed1f4cb tests: Include util.h in dist
183052d Prepare for 3.2.22-rc1 release
8983fa9 rtnl_link_af_unregister: fix locking
807fddc nl: Increase receive buffer size to 4 pages
c4d846f 3.2.22 release
c76393e Add macvlan support
87bbfb6 Default to comparing all attributes if no oo_id_attrs defined
53ac502 Handle -NLE_AGAIN in nl_cache_mngr_data_ready
34a96ba netfilter/queue: generalize nfnl_queue_msg_build_verdict()
d612180 netfilter/queue: introduce nfnl_queue_msg_send_verdict_batch()
01cfa9c msg: Avoid returning a negative value for nlmsg_attrlen()
cd1c1e1 tests: use AM_CFLAGS instead of CFLAGS directly
2d0810e socket: Warn via debug message if local port namespace is exhausted
408a1b8 cache: Return -NLE_PROTO_MISMATCH if socket provided mismatches cache protocol
c08aacc handle the case where 0 is passed to nl_size2str
e77ea93 add support functions for attributes and callback handlers
7dc033f add python module for generic netlink library
89b0011 add generic netlink functions to swig
81d2b1d Add support for inet diag Netlink protocol.
b3fb89f Handle the case where nl_msec2str is passed 0 msecs
162c906 Add VXLAN support.
57f1d9f link: add support for IFLA_PHYS_PORT_ID
c97c8c2 Add idiag-socket-details
2ef91da More safely parse vegas info and mem info.
0eb665c Enable linker versioning
6f37b43 fix double free caused by freeing link af_data in rtnl_link_set_family()
c31467e Priority of the '<' operator is higher than that of the '=' operator
8a4f16b Call to_msg_fill_raw when defined to_msg_fill is NULL
56d2bbe netfilter/ct: support optional CTA_TIMESTAMP attribute
db08ef4 netfilter/ct: support optional CTA_ZONE attribute
9828326 add python examples using swig provided api
9346269 nl_cb: store nl_cb_type in struct nl_cb
86207d4 python: rework netlink callback handling
2d55872 use Callback object constructing Socket
522cf98 python: allow callback function to be a class method
fa23414 python: remove unnecessary callback type definitions
6726895 python: fix typo in Socket::__str__() function
b9284bc python: add send and receive functions to Socket class
ae7f8cc python: remove use of PyArg_ParseTuple() for callback result
f2e6f50 python: fixup VLANLink() initialization
a4e588d Fixed ObjIterator for python3, fixed output of _color and added missing parameter to nl_cache_resync
1daa48c nl: Fix comment typo on recvmsgs
27019c5 nl-link-set: Add --state option
fdd1ba2 route/link: fixup link->l_af_ops must be set for some kind of links
cb034e1 test: add bridge creation sample
defebe3 python: add basic netlink protocol bridge interface support
07669b0 test: add python bridge testing sample
978bb85 python: add bridge flags API
d976e2e obj: Check for NULL pointer in nl_object_clone()
549010c rtnl-addr: set ifa_flags when creating/updating address
74db300 libnl-3.2.23-rc1 release
72bf363 doxygen-link: Be python3 compatible
3151eda doc: Add instructions on how to build docs
7f066d0 Fix up -rc1 versioning to not be included in libnl_micro_version
71ad234 include: Provide <netlink/route/link/vxlan.h> in distribution
f44b82f libnl-3.2.23-rc2 release
ac344b9 tests: fix make test-create-vxlan
60ceeef 3.2.23 release
43e9438 add ingress qdisc
1f3511c factor out rtnl_link_fill_info()
4263106 add veth link support
760bfab add link netns support
678753b factor out rtnl_link_info_parse()
2ae5298 python: Include all files in distribution
2d20d09 Remove extra memset from __nlmsg_alloc
4f075a4 do not compile some address families when not available
d6cfd04 add initial tc action support
9073aaf add mirred tc action
6cdc32d add u32 action support
2e90ed5 add u32 action test
24e8b52 basic: add action support
ff94045 add veth.h into include/Makefile.am
0404011 link: Fall back to global provisioned link cache if object is not a cache resident
3ddecb3 fix linux/pkt_act.h inclusion
d969a19 add fq_codel qdisc
ae19ac0 add fq_codel cli module
bda0f66 build: separate compiler and linker flags
6a8d90f attr: Allow attribute type 0
b50a36b The commit 6a8d90f5fec4 "attr: Allow attribute type 0" intended to allow the parsing of {netlink,packet,unix}_diag, even if they are using type 0 for valid attributes.
8b87ae5 fix rtnl_link_info_parse() and rtnl_link_fill_info()
aa1c562 add a parameter to rtnl_link_veth_add()
2b7d1d5 add declaration for rtnl_cls_change()
b5309e1 fix a bug in rtnl_act_fill()
017c971 rename rtnl_mirred_set_index() to rtnl_mirred_set_ifindex()
ffbfe92 add rtnl_mirred_get* functions
507897a u32: add action removal API
efdde42 basic: add action removal API
4b84836 basic: Add missing declaration for rtnl_basic_add_action()
438e3ff fix some typo in lib/route/act.c
a858d99 basic: Declare rtnl_act in basic.h to silence warning
ea0eec9 add an assertion in rtnl_tc_set_link()
7744a5a Revert "basic: Declare rtnl_act in basic.h to silence warning"
85c0192 Revert "basic: Add missing declaration for rtnl_basic_add_action()"
c855e4f add declaration for rtnl_basic_add_action()
bc717a9 cache: Add missing declaration for nl_cache_find()
d7aca17 u32: add rtnl_u32_get_key()
02c9c25 build: fix build failure when using different build dir (make distcheck)
62c37fa libnl-3.2.24-rc1 release
2cf635b route: add libnl name prefix to global variable link_policy
42c4133 add support for IFA_FLAGS nl attribute
dcc0baa addr: add address flag IFA_F_MANAGETEMPADDR
8dabf9f bridge: add rtnl_link_add_bridge() function
aa8877d act: remove rtnl_act_alloc_cache()
b203c89 addr: add address flag IFA_F_NOPREFIXROUTE
815e192 python: fix build error for missing library_path in setup.py
894acf7 doc: fix typo in documentation
1a510c5 libnl-3.2.24 release
4c7a307 build: fix error when running `configure --disable-doc`
b701746 route: fix return value of nl_rtgen_request()
7dbf4d5 remove the obsolete src/cls directory
b3b8d72 remove nl_cache_lookup() from cache.h
3fb0aae utils: fix nl_msec2str() which always returned '0msec' for whole second durations
85ec9c7 route: rtnl_route_build_msg() should not overwrite the route scope
20aa732 basic: make BASIC_ATTR_TARGET optional
59547d2 fix comments for rtnl_act_add()
cdfdfb1 remove some useless code in lib/route/cls/u32.c
a126d66 fill prio and protocol attr bits when parsing cls message
68d6bd7 utils: add nl_has_capability() function
015c4ee utils: indicate capability NL_CAPABILITY_ROUTE_BUILD_MSG_SET_SCOPE
67a7046 link: document sk == NULL case for rtnl_link_alloc_cache()
c0a5b39 u32: add const to rtnl_u32_add_key_in*_addr()
dfd0a80 route: don't enforce minlen in inet6_parse_protinfo() (IFLA_PROTINFO) and inet_parse_af() (IFLA_AF_SPEC)
3584a7a route: detect missing cfgid in rtnl_link_inet_get_conf()
5981a39 route: update kernel header snmp.h and fix inet6_parse_protinfo() after kernel API breakage
1048a61 route: rename internal copy of kernel header file 'inetdevice.h' to 'ip.h'
a593803 route: update copy of kernel header 'ip.h'
baa2cad route: fix off-by-one in rtnl_act_parse()
34bfce6 link: Catch missing io_free() implementations
5206c05 route/addr: only sent IFA_FLAGS when needed to workaround picky older kernels
690545a act: fix policy range check
ab55ea8 link: call rtnl_link_set_type() in link_msg_parser()
12bd035 veth: implement ->io_alloc
6c8f67b veth: implement ->io_free
3700bf5 veth: use nl_object_clone() to deep copy rtnl_link object
65f218b add NLM_F_EXCL to rtnl_link_veth_add()
cb319e2 python: fix wrongly passing argument to function in ObjIterator.next()
8ff1999 netfilter/ct: expand CT parameters that can be used in add/delete operations
69f4a03 gitignore: ignore ctags file
6722853 doc/core: reply message should send from kernel to app
f55ef93 gitignore: ignore patch files
0ba7e66 veth: grab a reference for rtnl_link_veth_get_peer()
e5d9b82 act: grab a reference when adding an action to a filter
a5917da gitignore: ignore 'nf-ct-add' (netfilter/ct)
6d70d83 docs: add code comment to explain the meaning of the fields in rtnl_addr_cacheinfo
b8d90d9 act: fix a pointer in rtnl_act_msg_parse()
35f4473 act: fix memory leak in rtnl_act_parse()
a1c9915 doc: fix wrong name in documentation for rtnl_link_bridge_alloc()
0482cdc gitignore: ignore test binaries and artifacts in "tests/"
3a95fad introduce ipip tunnel support
57bdc4f introduce gre tunnel support
d715b8a introduce sit tunnel support
737d5f0 ipgre: fix attribute IPGRE_ATTR_OKEY in ipgre_put_attrs()
adb9f5d ipgre: rename new public API to avoid confusion
8f63014 ipvti: introduce vti tunnel support
657e257 gitignore: ignore test binaries and artifacts in "tests/"
0fd510b lib/socket: use proper typed constant UINT32_MAX for uint32_t typed port
0271578 lib/socket: don't fail if no more local ports can be assigned in nl_socket_alloc
4dd5fdd lib/socket: retry generate local port in nl_connect on ADDRINUSE
1f734a8 lib/socket: randomize the generated local port
c797542 tunnel: add a copy of include/linux/if_tunnel.h
430eb40 vlan: add support for IFLA_VLAN_PROTOCOL
4dc7246 Explicitly create output directories for flex/yacc output.
425d3d6 Use paths relative to srcdir in setup.py.
1087eb5 obj: Fix dereference before NULL check
872544c msg: Remove unnecessary call of nlmsg_free on known NULL pointer
6608cd5 act: fix the logic of parsing actions
bb44548 route/link: pass proper type to sizeof() for calloc() in vlan_parse()
29a3894 lib: reorder free() after printf("%p") statements
d50758c route: remove unnecessary non-null check in pktloc and ematch
87682a0 cli: add error checking to nl-route-get about out-of-memory
8532ac5 cls: fix array overrun in rtnl_ematch_opnd2txt()
dae0a23 cache: fix crash in nl_cache_dump_filter() when omitting the params argument
d7a9e74 route/link: fix dangling pointer after rtnl_link_get_ifalias(link, NULL)
90cfeee netfilter/ct: fix calling nfnl_*_put() on uninitialized memory after nfnlmsg_*_parse()
3d5e488 route/pktloc: read_pktlocs() always returned success status
11f9cc0 ip6tnl: introduce ip6 tunnel support
f8144b1 build: fix error in include/Makefile.am
feda705 cli: Fix typo in error message
8f82270 cache_mngr: Return proper error code if nl_socket_alloc() fails
b6cadfe cache_mngr: Fix assignment of error code in nl_cache_mngr_alloc()
e4c94ea doc: fix error in core documentation for nl_cache_mngr_alloc()
2ca01af u32: prevent memcpy from NULL
8e052f5 attr: prevent garbage return value for NULL param
a8b352a attr: fix compile warning in headers
853c045 cache: add missing declaration of nl_cache_move() in include/netlink/cache.h
940e5d5 doc: fix doxygen-link.py by skipping invalid entries in libnl.dict
558df52 attr: nla_get_u64() should return 0 if the attribute does not fully contain 64 bit
0446731 libnl-3.2.25-rc1 release
9e0960c doc: state in documentation that libnl3 is supposed to work with 3.x kernels
9c2dbdf ip6tnl: Use <netinet/in.h> for in6_addr and stuff
c62cda9 build: let autogen.sh script change into top source directory
94e1345 build: embed the git commit id of HEAD in the configure script
c4d7000 tc: add co_groups for tc qdisc and filter
dcc5375 libnl-3.2.25 release
Change-Id: I5c46e7d2b808ad7baf037a49523ad69191450cbf
Bug: 32255299
Test: Compile (fails)
Diffstat (limited to 'src')
49 files changed, 2709 insertions, 931 deletions
diff --git a/src/.gitignore b/src/.gitignore index 60233c8c..5de9f293 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,5 +1,9 @@ genl-ctrl-list +/nf-ct-add nf-ct-list +nf-exp-list +nf-exp-add +nf-exp-delete nf-log nf-monitor nl-addr-add @@ -21,6 +25,12 @@ nl-neightbl-list nl-qdisc-add nl-qdisc-delete nl-qdisc-list +nl-class-add +nl-class-delete +nl-class-list +nl-cls-add +nl-cls-delete +nl-cls-list nl-route-add nl-route-delete nl-route-list @@ -29,3 +39,8 @@ nl-rule-list nl-tctree-list nl-util-addr nf-queue +nl-classid-lookup +nl-pktloc-lookup +nl-link-enslave +nl-link-release +idiag-socket-details diff --git a/src/Makefile.am b/src/Makefile.am index dda32a78..f8ac4ca0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,17 +2,33 @@ SUBDIRS = lib -AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -D_GNU_SOURCE -AM_LDFLAGS = -L${top_builddir}/lib -L${top_builddir}/src/lib -lnl-cli +AM_CPPFLAGS = -I${top_srcdir}/include -I${top_builddir}/include -D_GNU_SOURCE -DSYSCONFDIR=\"$(sysconfdir)/libnl\" +AM_CFLAGS = -Wall + +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 \ + ${top_builddir}/lib/libnl-idiag-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 \ + nl-classid-lookup \ + nl-pktloc-lookup \ + nl-link-list noinst_PROGRAMS = \ - genl-ctrl-list \ - nf-ct-list nf-log nf-queue nf-monitor \ + nf-ct-list nf-ct-add nf-log nf-queue nf-monitor \ + nf-exp-list nf-exp-add nf-exp-delete \ nl-addr-add nl-addr-delete nl-addr-list \ - nl-link-list nl-link-set nl-link-stats \ + nl-link-set nl-link-stats \ nl-link-ifindex2name nl-link-name2ifindex \ nl-neigh-add nl-neigh-delete nl-neigh-list \ - nl-qdisc-delete nl-qdisc-list \ nl-rule-list \ nl-neightbl-list \ nl-monitor \ @@ -21,81 +37,70 @@ noinst_PROGRAMS = \ nl-fib-lookup \ nl-list-caches nl-list-sockets \ nl-util-addr \ - nl-pktloc-lookup + nl-link-enslave \ + nl-link-release \ + idiag-socket-details genl_ctrl_list_SOURCES = genl-ctrl-list.c -genl_ctrl_list_LDADD = -lnl-genl -lnl-route nf_ct_list_SOURCES = nf-ct-list.c -nf_ct_list_LDADD = -lnl-nf +nf_ct_add_SOURCES = nf-ct-add.c nf_log_SOURCES = nf-log.c -nf_log_LDADD = -lnl-nf nf_queue_SOURCES = nf-queue.c -nf_queue_LDADD = -lnl-nf nf_monitor_SOURCES = nf-monitor.c -nf_monitor_LDADD = -lnl-nf + +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_add_LDADD = -lnl-route nl_addr_delete_SOURCES = nl-addr-delete.c -nl_addr_delete_LDADD = -lnl-route nl_addr_list_SOURCES = nl-addr-list.c -nl_addr_list_LDADD = -lnl-route nl_link_list_SOURCES = nl-link-list.c -nl_link_list_LDADD = -lnl-route nl_link_set_SOURCES = nl-link-set.c -nl_link_set_LDADD = -lnl-route nl_link_stats_SOURCES = nl-link-stats.c -nl_link_stats_LDADD = -lnl-route nl_link_ifindex2name_SOURCES = nl-link-ifindex2name.c -nl_link_ifindex2name_LDADD = -lnl-route nl_link_name2ifindex_SOURCES = nl-link-name2ifindex.c -nl_link_name2ifindex_LDADD = -lnl-route nl_monitor_SOURCES = nl-monitor.c -nl_monitor_LDADD = -lnl-route nl_neigh_add_SOURCES = nl-neigh-add.c -nl_neigh_add_LDADD = -lnl-route nl_neigh_delete_SOURCES = nl-neigh-delete.c -nl_neigh_delete_LDADD = -lnl-route nl_neigh_list_SOURCES = nl-neigh-list.c -nl_neigh_list_LDADD = -lnl-route nl_neightbl_list_SOURCES = nl-neightbl-list.c -nl_neightbl_list_LDADD = -lnl-route +nl_qdisc_add_SOURCES = nl-qdisc-add.c nl_qdisc_delete_SOURCES = nl-qdisc-delete.c -nl_qdisc_delete_LDADD = -lnl-route nl_qdisc_list_SOURCES = nl-qdisc-list.c -nl_qdisc_list_LDADD = -lnl-route + +nl_class_add_SOURCES = nl-class-add.c +nl_class_delete_SOURCES = nl-class-delete.c +nl_class_list_SOURCES = nl-class-list.c + +nl_cls_add_SOURCES = nl-cls-add.c +nl_cls_list_SOURCES = nl-cls-list.c +nl_cls_delete_SOURCES = nl-cls-delete.c nl_route_add_SOURCES = nl-route-add.c -nl_route_add_LDADD = -lnl-route nl_route_delete_SOURCES = nl-route-delete.c -nl_route_delete_LDADD = -lnl-route nl_route_get_SOURCES = nl-route-get.c -nl_route_get_LDADD = -lnl-route nl_route_list_SOURCES = nl-route-list.c -nl_route_list_LDADD = -lnl-route nl_rule_list_SOURCES = nl-rule-list.c -nl_rule_list_LDADD = -lnl-route nl_tctree_list_SOURCES = nl-tctree-list.c -nl_tctree_list_LDADD = -lnl-route nl_fib_lookup_SOURCES = nl-fib-lookup.c -nl_fib_lookup_LDADD = -lnl-route nl_list_caches_SOURCES = nl-list-caches.c -nl_list_caches_LDADD = -lnl-route nl_list_sockets_SOURCES = nl-list-sockets.c -nl_list_sockets_LDADD = -lnl-route nl_util_addr_SOURCES = nl-util-addr.c -nl_util_addr_LDADD = -lnl-route nl_pktloc_lookup_SOURCES = nl-pktloc-lookup.c -nl_pktloc_lookup_LDADD = -lnl-route + +nl_classid_lookup_SOURCES = nl-classid-lookup.c + +idiag_socket_details_SOURCES = idiag-socket-details.c diff --git a/src/cls/basic.c b/src/cls/basic.c deleted file mode 100644 index df1c1122..00000000 --- a/src/cls/basic.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * src/cls/basic.c Basic Classifier - * - * 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. - * - * Copyright (c) 2008 Thomas Graf <tgraf@suug.ch> - */ - -#include "utils.h" -#include <netlink/route/cls/basic.h> -#include <netlink/route/cls/ematch.h> - -static void print_usage(void) -{ - printf( -"Usage: ... basic [OPTIONS]...\n" -"\n" -"Options\n" -" -h, --help Show this help.\n" -" -e, --ematch=MATCH Extended match (See --ematch help).\n" -" -c, --classid=HANDLE Target class to classify matching packets to.\n" - ); - exit(0); -} - -static void basic_parse_argv(struct rtnl_cls *cls, int argc, char **argv) -{ - uint32_t classid; - - for (;;) { - int c, optidx = 0, err; - static struct option long_opts[] = { - { "help", 0, 0, 'h' }, - { "ematch", 1, 0, 'e' }, - { "classid", 1, 0, 'c' }, - { 0, 0, 0, 0 } - }; - - c = getopt_long(argc, argv, "he:c:", long_opts, &optidx); - if (c == -1) - break; - - switch (c) { - case '?': - exit(NLE_INVAL); - - case 'h': - print_usage(); - - case 'e': -#if 0 - if ((err = parse_ematch_syntax(optarg, &tree)) < 0) - fatal(err, "Error while parsing ematch: %s", - nl_geterror(err)); - - if ((err = rtnl_basic_set_ematch(cls, tree)) < 0) - fatal(err, "Unable to set ematch: %s", - nl_geterror(err)); -#endif - break; - - case 'c': - if ((err = rtnl_tc_str2handle(optarg, &classid)) < 0) - fatal(err, "Invalid classid \"%s\": %s", - optarg, nl_geterror(err)); - - if ((err = rtnl_basic_set_classid(cls, classid)) < 0) - fatal(err, "Unable to set classid: %s", - nl_geterror(err)); - break; - } - } -} - -static struct cls_module basic_module = { - .name = "basic", - .parse_argv = basic_parse_argv, -}; - -static void __attribute__ ((constructor)) basic_init(void) -{ - register_cls_module(&basic_module); -} - -static void __attribute__ ((destructor)) basic_exit(void) -{ - unregister_cls_module(&basic_module); -} diff --git a/src/cls/cgroup.c b/src/cls/cgroup.c deleted file mode 100644 index ad0392f7..00000000 --- a/src/cls/cgroup.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * src/cls/cgroup.c Control Groups Classifier - * - * 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. - * - * Copyright (c) 2009 Thomas Graf <tgraf@suug.ch> - */ - -#include "utils.h" -#include <netlink/route/cls/cgroup.h> -#include <netlink/route/cls/ematch.h> - -static void print_usage(void) -{ - printf( -"Usage: ... cgroup [OPTIONS]...\n" -"\n" -"Options\n" -" -h, --help Show this help.\n" -" -e, --ematch=MATCH Extended match (See --ematch help).\n" -" -c, --classid=HANDLE Target class to classify matching packets to.\n" - ); - exit(0); -} - -static void basic_parse_argv(struct rtnl_cls *cls, int argc, char **argv) -{ - for (;;) { - int c, optidx = 0; - static struct option long_opts[] = { - { "help", 0, 0, 'h' }, - { "ematch", 1, 0, 'e' }, - { "classid", 1, 0, 'c' }, - { 0, 0, 0, 0 } - }; - - c = getopt_long(argc, argv, "he:c:", long_opts, &optidx); - if (c == -1) - break; - - switch (c) { - case '?': - exit(NLE_INVAL); - - case 'h': - print_usage(); - -#if 0 - case 'e': - if ((err = parse_ematch_syntax(optarg, &tree)) < 0) - fatal(err, "Error while parsing ematch: %s", - nl_geterror(err)); - - if ((err = rtnl_basic_set_ematch(cls, tree)) < 0) - fatal(err, "Unable to set ematch: %s", - nl_geterror(err)); - break; -#endif - } - } -} - -static struct cls_module cgroup_module = { - .name = "cgroup", - .parse_argv = basic_parse_argv, -}; - -static void __init cgroup_init(void) -{ - register_cls_module(&cgroup_module); -} - -static void __exit cgroup_exit(void) -{ - unregister_cls_module(&cgroup_module); -} diff --git a/src/cls/utils.c b/src/cls/utils.c deleted file mode 100644 index ef6603b6..00000000 --- a/src/cls/utils.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * src/cls-utils.c Classifier Helpers - * - * 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. - * - * Copyright (c) 2008-2009 Thomas Graf <tgraf@suug.ch> - */ - -#include "utils.h" - -struct rtnl_cls *nlt_alloc_cls(void) -{ - struct rtnl_cls *cls; - - cls = rtnl_cls_alloc(); - if (!cls) - fatal(ENOMEM, "Unable to allocate classifier object"); - - return cls; -} - -void parse_dev(struct rtnl_cls *cls, struct nl_cache *link_cache, char *arg) -{ - int ival; - - if (!(ival = rtnl_link_name2i(link_cache, arg))) - fatal(ENOENT, "Link \"%s\" does not exist", arg); - - rtnl_cls_set_ifindex(cls, ival); -} - -void parse_prio(struct rtnl_cls *cls, char *arg) -{ - uint32_t prio = parse_u32(arg); - rtnl_cls_set_prio(cls, prio); -} - -void parse_parent(struct rtnl_cls *cls, char *arg) -{ - uint32_t parent; - int err; - - if ((err = rtnl_tc_str2handle(arg, &parent)) < 0) - fatal(err, "Unable to parse handle \"%s\": %s", - arg, nl_geterror(err)); - - rtnl_cls_set_parent(cls, parent); -} - -void parse_handle(struct rtnl_cls *cls, char *arg) -{ - uint32_t handle; - int err; - - if ((err = rtnl_tc_str2handle(arg, &handle)) < 0) - fatal(err, "Unable to parse handle \"%s\": %s", - arg, nl_geterror(err)); - - rtnl_cls_set_handle(cls, handle); -} - -void parse_proto(struct rtnl_cls *cls, char *arg) -{ - int proto = nl_str2ether_proto(arg); - if (proto < 0) - fatal(proto, "Unable to parse protocol \"%s\": %s", - arg, nl_geterror(proto)); - rtnl_cls_set_protocol(cls, proto); -} - -static NL_LIST_HEAD(cls_modules); - -struct cls_module *lookup_cls_mod(struct rtnl_cls_ops *ops) -{ - struct cls_module *mod; - - nl_list_for_each_entry(mod, &cls_modules, list) { - if (mod->ops == ops) - return mod; - } - - return NULL; -} - -void register_cls_module(struct cls_module *mod) -{ - struct rtnl_cls_ops *ops; - - if (!(ops = __rtnl_cls_lookup_ops(mod->name))) - fatal(ENOENT, "Could not locate classifier module \"%s\"", - mod->name); - - if (lookup_cls_mod(ops) != NULL) - fatal(EEXIST, "Duplicate classifier module registration."); - - mod->ops = ops; - nl_list_add_tail(&mod->list, &cls_modules); -} - -void unregister_cls_module(struct cls_module *mod) -{ - nl_list_del(&mod->list); -} diff --git a/src/cls/utils.h b/src/cls/utils.h deleted file mode 100644 index 1a8ee9bc..00000000 --- a/src/cls/utils.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * src/cls-utils.h Classifier Helpers - * - * 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. - * - * Copyright (c) 2008-2009 Thomas Graf <tgraf@suug.ch> - */ - -#ifndef __CLS_UTILS_H_ -#define __CLS_UTILS_H_ - -#include "../utils.h" -#include <netlink/route/classifier-modules.h> -#include <netlink/route/cls/ematch.h> - -struct cls_module -{ - const char * name; - struct rtnl_cls_ops * ops; - void (*parse_argv)(struct rtnl_cls *, int, char **); - struct nl_list_head list; -}; - -extern struct cls_module *lookup_cls_mod(struct rtnl_cls_ops *); -extern void register_cls_module(struct cls_module *); -extern void unregister_cls_module(struct cls_module *); - -struct ematch_module -{ - int kind; - struct rtnl_ematch_ops *ops; - void (*parse_argv)(struct rtnl_ematch *, int, char **); - struct nl_list_head list; -}; - -extern struct ematch_module *lookup_ematch_mod(struct rtnl_ematch_ops *); -extern void register_ematch_module(struct ematch_module *); -extern void unregister_ematch_module(struct ematch_module *); - -extern struct rtnl_cls *nlt_alloc_cls(void); -extern void parse_dev(struct rtnl_cls *, struct nl_cache *, char *); -extern void parse_prio(struct rtnl_cls *, char *); -extern void parse_parent(struct rtnl_cls *, char *); -extern void parse_handle(struct rtnl_cls *, char *); -extern void parse_proto(struct rtnl_cls *, char *); - -extern int parse_ematch_syntax(const char *, struct rtnl_ematch_tree **); - -#endif diff --git a/src/disabled-nl-qdisc-add.c b/src/disabled-nl-qdisc-add.c deleted file mode 100644 index a1fab4e2..00000000 --- a/src/disabled-nl-qdisc-add.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * src/nl-qdisc-dump.c Dump qdisc attributes - * - * 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 <tgraf@suug.ch> - */ - -#include "utils.h" -#include <netlink/route/sch/fifo.h> -#include <netlink/route/sch/prio.h> - -static void print_usage(void) -{ - printf( -"Usage: nl-qdisc-add <ifindex> <handle> <parent> <kind>\n"); - exit(1); -} - -static int parse_blackhole_opts(struct rtnl_qdisc *qdisc, char *argv[], - int argc) -{ - return 0; -} - -static int parse_pfifo_opts(struct rtnl_qdisc *qdisc, char *argv[], int argc) -{ - int err, limit; - - if (argc > 0) { - if (argc != 2 || strcasecmp(argv[0], "limit")) { - fprintf(stderr, "Usage: ... pfifo limit <limit>\n"); - return -1; - } - - limit = strtoul(argv[1], NULL, 0); - err = rtnl_qdisc_fifo_set_limit(qdisc, limit); - if (err < 0) { - fprintf(stderr, "%s\n", nl_geterror()); - return -1; - } - } - - return 0; -} - -static int parse_bfifo_opts(struct rtnl_qdisc *qdisc, char *argv[], int argc) -{ - int err, limit; - - if (argc > 0) { - if (argc != 2 || strcasecmp(argv[0], "limit")) { - fprintf(stderr, "Usage: ... bfifo limit <limit>\n"); - return -1; - } - - limit = nl_size2int(argv[1]); - if (limit < 0) { - fprintf(stderr, "Invalid value for limit.\n"); - return -1; - } - - err = rtnl_qdisc_fifo_set_limit(qdisc, limit); - if (err < 0) { - fprintf(stderr, "%s\n", nl_geterror()); - return -1; - } - } - - return 0; -} - -static int parse_prio_opts(struct rtnl_qdisc *qdisc, char *argv[], int argc) -{ - int i, err, bands; - uint8_t map[] = QDISC_PRIO_DEFAULT_PRIOMAP; - - if (argc > 0) { - if (argc < 2 || strcasecmp(argv[0], "bands")) - goto usage; - - bands = strtoul(argv[1], NULL, 0); - err = rtnl_qdisc_prio_set_bands(qdisc, bands); - if (err < 0) { - fprintf(stderr, "%s\n", nl_geterror()); - return -1; - } - } - - if (argc > 2) { - if (argc < 5 || strcasecmp(argv[2], "map")) - goto usage; - - for (i = 3; i < (argc & ~1U); i += 2) { - int prio, band; - - prio = rtnl_str2prio(argv[i]); - if (prio < 0 || prio > sizeof(map)/sizeof(map[0])) { - fprintf(stderr, "Invalid priority \"%s\"\n", - argv[i]); - return -1; - } - - band = strtoul(argv[i+1], NULL, 0); - - map[prio] = band; - } - } - - err = rtnl_qdisc_prio_set_priomap(qdisc, map, sizeof(map)); - if (err < 0) { - fprintf(stderr, "%s\n", nl_geterror()); - return -1; - } - - return 0; -usage: - fprintf(stderr, "Usage: ... prio bands <nbands> map MAP\n" - "MAP := <prio> <band>\n"); - return -1; -} - -int main(int argc, char *argv[]) -{ - struct nl_sock *nlh; - struct rtnl_qdisc *qdisc; - uint32_t handle, parent; - int err = 1; - - if (nltool_init(argc, argv) < 0) - return -1; - - if (argc < 5 || !strcmp(argv[1], "-h")) - print_usage(); - - nlh = nltool_alloc_handle(); - if (!nlh) - goto errout; - - qdisc = rtnl_qdisc_alloc(); - if (!qdisc) - goto errout_free_handle; - - rtnl_qdisc_set_ifindex(qdisc, strtoul(argv[1], NULL, 0)); - - if (rtnl_tc_str2handle(argv[2], &handle) < 0) { - fprintf(stderr, "%s\n", nl_geterror()); - goto errout_free_qdisc; - } - - if (rtnl_tc_str2handle(argv[3], &parent) < 0) { - fprintf(stderr, "%s\n", nl_geterror()); - goto errout_free_qdisc; - } - - rtnl_qdisc_set_handle(qdisc, handle); - rtnl_qdisc_set_parent(qdisc, parent); - rtnl_qdisc_set_kind(qdisc, argv[4]); - - if (!strcasecmp(argv[4], "blackhole")) - err = parse_blackhole_opts(qdisc, &argv[5], argc-5); - else if (!strcasecmp(argv[4], "pfifo")) - err = parse_pfifo_opts(qdisc, &argv[5], argc-5); - else if (!strcasecmp(argv[4], "bfifo")) - err = parse_bfifo_opts(qdisc, &argv[5], argc-5); - else if (!strcasecmp(argv[4], "prio")) - err = parse_prio_opts(qdisc, &argv[5], argc-5); - else { - fprintf(stderr, "Unknown qdisc \"%s\"\n", argv[4]); - goto errout_free_qdisc; - } - - if (err < 0) - goto errout_free_qdisc; - - if (nltool_connect(nlh, NETLINK_ROUTE) < 0) - goto errout_free_qdisc; - - if (rtnl_qdisc_add(nlh, qdisc, NLM_F_REPLACE) < 0) { - fprintf(stderr, "Unable to add Qdisc: %s\n", nl_geterror()); - goto errout_close; - } - - err = 0; -errout_close: - nl_close(nlh); -errout_free_qdisc: - rtnl_qdisc_put(qdisc); -errout_free_handle: - nl_handle_destroy(nlh); -errout: - return err; -} diff --git a/src/genl-ctrl-list.c b/src/genl-ctrl-list.c index e25eb2ae..0895bcce 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 <tgraf@suug.ch> + * Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch> */ #include <netlink/cli/utils.h> @@ -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; } diff --git a/src/idiag-socket-details.c b/src/idiag-socket-details.c new file mode 100644 index 00000000..95686768 --- /dev/null +++ b/src/idiag-socket-details.c @@ -0,0 +1,90 @@ +/* + * src/idiag-socket-details.c List socket details + * + * 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. + * + * Copyright (c) 2013 Sassano Systems LLC <joe@sassanosystems.com> + */ + +#include <netlink/cli/utils.h> +#include <netlink/idiag/idiagnl.h> +#include <netlink/idiag/msg.h> +#include <linux/netlink.h> + +static void print_usage(void) +{ + printf( +"Usage: idiag-socket-details [OPTION]\n" +"\n" +"Options\n" +" --summary Show socket detail summary.\n" +" --details Show socket details on multiple lines.\n" +" --stats Show full socket statistics.\n" +" -h, --help Show this help.\n" +" -v, --version Show versioning information.\n" + ); + exit(0); +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct nl_cache *idiag_cache; + struct nl_dump_params params = { + .dp_type = NL_DUMP_LINE, + .dp_nl_cb = NULL, + .dp_fd = stdout, + }; + int err = 0; + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_INET_DIAG); + for (;;) { + int c, optidx = 0; + enum { + ARG_SUMMARY = 257, + ARG_DETAILS = 258, + ARG_STATS = 259, + ARG_FAMILY, + }; + static struct option long_opts[] = { + { "details", 0, 0, ARG_DETAILS }, + { "summary", 0, 0, ARG_SUMMARY }, + { "stats", 0, 0, ARG_STATS}, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "hv", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case '?': exit(NLE_INVAL); + case ARG_SUMMARY: params.dp_type = NL_DUMP_LINE; break; + case ARG_DETAILS: params.dp_type = NL_DUMP_DETAILS; break; + case ARG_STATS: params.dp_type = NL_DUMP_STATS; break; + case 'h': print_usage(); break; + case 'v': nl_cli_print_version(); break; + } + } + + if ((err = idiagnl_msg_alloc_cache(sock, AF_INET, IDIAG_SS_ALL, + &idiag_cache))) { + nl_cli_fatal(err, "Unable to allocate idiag msg cache: %s", + nl_geterror(err)); + } + + nl_cache_mngt_provide(idiag_cache); + + nl_cache_dump_filter(idiag_cache, ¶ms, NULL); + + nl_cache_mngt_unprovide(idiag_cache); + nl_cache_free(idiag_cache); + nl_socket_free(sock); + + return 0; +} diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 80c217c9..51611151 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -1,7 +1,12 @@ # -*- 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 +AM_CPPFLAGS = -I${top_srcdir}/include -I${top_builddir}/include -D_GNU_SOURCE -DPKGLIBDIR=\"$(pkglibdir)\" -DSYSCONFDIR=\"$(sysconfdir)\" -rdynamic +AM_CFLAGS = -Wall +AM_LDFLAGS = \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) +NL_LIBADD = \ + -L${top_builddir}/lib \ + -ldl #nobase_pkglib_LTLIBRARIES = cls/basic.la cls/ematch/cmp.la #cls_basic_la_LDFLAGS = -module -version-info 2:0:0 @@ -26,16 +31,15 @@ AM_LDFLAGS = -L${top_builddir}/lib -ldl # cls/pktloc_syntax.c cls/pktloc_syntax.h lib_LTLIBRARIES = \ - libnl-cli.la + libnl-cli-3.la -libnl_cli_la_LDFLAGS = -version-info 2:0:0 +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 ${NL_LIBADD} -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_la_SOURCES = \ - utils.c addr.c ct.c link.c neigh.c qdisc.c rule.c route.c +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 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/class.c b/src/lib/class.c new file mode 100644 index 00000000..96f60cd1 --- /dev/null +++ b/src/lib/class.c @@ -0,0 +1,45 @@ +/* + * src/lib/class.c CLI Class 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) 2010-2011 Thomas Graf <tgraf@suug.ch> + */ + +/** + * @ingroup cli + * @defgroup cli_class Traffic Classes + * @{ + */ + +#include <netlink/cli/utils.h> +#include <netlink/cli/class.h> + +struct rtnl_class *nl_cli_class_alloc(void) +{ + struct rtnl_class *class; + + if (!(class = rtnl_class_alloc())) + nl_cli_fatal(ENOMEM, "Unable to allocate class object"); + + return class; +} + +struct nl_cache *nl_cli_class_alloc_cache(struct nl_sock *sock, int ifindex) +{ + struct nl_cache *cache; + int err; + + if ((err = rtnl_class_alloc_cache(sock, ifindex, &cache)) < 0) + nl_cli_fatal(err, "Unable to allocate class cache: %s", + nl_geterror(err)); + + nl_cache_mngt_provide(cache); + + return cache; +} + +/** @} */ diff --git a/src/lib/cls.c b/src/lib/cls.c new file mode 100644 index 00000000..86d775d2 --- /dev/null +++ b/src/lib/cls.c @@ -0,0 +1,71 @@ +/* + * src/lib/cls.c CLI Classifier 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) 2010-2011 Thomas Graf <tgraf@suug.ch> + */ + +/** + * @ingroup cli + * @defgroup cli_cls Classifiers + * @{ + */ + +#include <netlink/cli/utils.h> +#include <netlink/cli/cls.h> +#include <netlink/route/cls/ematch.h> + +struct rtnl_cls *nl_cli_cls_alloc(void) +{ + struct rtnl_cls *cls; + + if (!(cls = rtnl_cls_alloc())) + nl_cli_fatal(ENOMEM, "Unable to allocate classifier object"); + + return cls; +} + +struct nl_cache *nl_cli_cls_alloc_cache(struct nl_sock *sock, int ifindex, + uint32_t parent) +{ + struct nl_cache *cache; + int err; + + if ((err = rtnl_cls_alloc_cache(sock, ifindex, parent, &cache)) < 0) + nl_cli_fatal(err, "Unable to allocate classifier cache: %s", + nl_geterror(err)); + + return cache; +} + +void nl_cli_cls_parse_proto(struct rtnl_cls *cls, char *arg) +{ + int proto; + + if ((proto = nl_str2ether_proto(arg)) < 0) + nl_cli_fatal(proto, "Unknown protocol \"%s\".", arg); + + rtnl_cls_set_protocol(cls, proto); +} + +struct rtnl_ematch_tree *nl_cli_cls_parse_ematch(struct rtnl_cls *cls, char *arg) +{ + struct rtnl_ematch_tree *tree; + char *errstr = NULL; + int err; + + if ((err = rtnl_ematch_parse_expr(arg, &errstr, &tree)) < 0) + nl_cli_fatal(err, "Unable to parse ematch expression: %s", + errstr); + + if (errstr) + free(errstr); + + return tree; +} + +/** @} */ diff --git a/src/lib/ct.c b/src/lib/ct.c index 5bab08f7..c9038780 100644 --- a/src/lib/ct.c +++ b/src/lib/ct.c @@ -137,6 +137,12 @@ void nl_cli_ct_parse_status(struct nfnl_ct *ct, char *arg) nfnl_ct_set_status(ct, status); } +void nl_cli_ct_parse_zone(struct nfnl_ct *ct, char *arg) +{ + uint32_t zone = nl_cli_parse_u32(arg); + nfnl_ct_set_zone(ct, zone); +} + #if 0 } else if (arg_match("origicmpid")) { if (argc > ++idx) diff --git a/src/lib/exp.c b/src/lib/exp.c new file mode 100644 index 00000000..a7a74f5a --- /dev/null +++ b/src/lib/exp.c @@ -0,0 +1,165 @@ +/* + * 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) 2008-2009 Thomas Graf <tgraf@suug.ch> + * Copyright (c) 2012 Rich Fought <rich.fought@watchguard.com> + */ + +/** + * @ingroup cli + * @defgroup cli_exp Expectation Tracking + * + * @{ + */ + +#include <netlink/cli/utils.h> +#include <netlink/cli/exp.h> + +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_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; + 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); + 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); + 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/lib/link.c b/src/lib/link.c index c192569a..5bce8240 100644 --- a/src/lib/link.c +++ b/src/lib/link.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2008-2009 Thomas Graf <tgraf@suug.ch> + * Copyright (c) 2008-2010 Thomas Graf <tgraf@suug.ch> */ /** @@ -18,6 +18,7 @@ #include <netlink/cli/utils.h> #include <netlink/cli/link.h> +#include <linux/if.h> struct rtnl_link *nl_cli_link_alloc(void) { @@ -30,11 +31,30 @@ struct rtnl_link *nl_cli_link_alloc(void) return link; } +struct nl_cache *nl_cli_link_alloc_cache_family(struct nl_sock *sock, int family) +{ + struct nl_cache *cache; + int err; + + if ((err = rtnl_link_alloc_cache(sock, family, &cache)) < 0) + nl_cli_fatal(err, "Unable to allocate link cache: %s", + nl_geterror(err)); + + nl_cache_mngt_provide(cache); + + return cache; +} + +struct nl_cache *nl_cli_link_alloc_cache(struct nl_sock *sock) +{ + return nl_cli_link_alloc_cache_family(sock, AF_UNSPEC); +} + void nl_cli_link_parse_family(struct rtnl_link *link, char *arg) { int family; - if ((family = nl_str2af(arg)) == AF_UNSPEC) + if ((family = nl_str2af(arg)) < 0) nl_cli_fatal(EINVAL, "Unable to translate address family \"%s\"", arg); @@ -66,8 +86,16 @@ 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) +{ + if (strlen(arg) > IFALIASZ) + nl_cli_fatal(ERANGE, + "Link ifalias too big, must not exceed %u in length.", + IFALIASZ); + + rtnl_link_set_ifalias(link, arg); } /** @} */ diff --git a/src/lib/neigh.c b/src/lib/neigh.c index a814bd8f..4518e460 100644 --- a/src/lib/neigh.c +++ b/src/lib/neigh.c @@ -25,7 +25,7 @@ struct rtnl_neigh *nl_cli_neigh_alloc(void) neigh = rtnl_neigh_alloc(); if (!neigh) - nl_cli_fatal(ENOMEM, "Unable to allocate neighbout object"); + nl_cli_fatal(ENOMEM, "Unable to allocate neighbour object"); return neigh; } diff --git a/src/lib/qdisc.c b/src/lib/qdisc.c index bc7ff925..ccf7d269 100644 --- a/src/lib/qdisc.c +++ b/src/lib/qdisc.c @@ -6,67 +6,27 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2008-2009 Thomas Graf <tgraf@suug.ch> + * Copyright (c) 2008-2011 Thomas Graf <tgraf@suug.ch> */ /** * @ingroup cli * @defgroup cli_qdisc Queueing Disciplines - * * @{ */ #include <netlink/cli/utils.h> #include <netlink/cli/qdisc.h> +#include <netlink/route/class.h> struct rtnl_qdisc *nl_cli_qdisc_alloc(void) { struct rtnl_qdisc *qdisc; - qdisc = rtnl_qdisc_alloc(); - if (!qdisc) + if (!(qdisc = rtnl_qdisc_alloc())) nl_cli_fatal(ENOMEM, "Unable to allocate qdisc object"); return qdisc; } -void nl_cli_qdisc_parse_dev(struct rtnl_qdisc *qdisc, struct nl_cache *link_cache, char *arg) -{ - int ival; - - if (!(ival = rtnl_link_name2i(link_cache, arg))) - nl_cli_fatal(ENOENT, "Link \"%s\" does not exist", arg); - - rtnl_qdisc_set_ifindex(qdisc, ival); -} - -void nl_cli_qdisc_parse_parent(struct rtnl_qdisc *qdisc, char *arg) -{ - uint32_t parent; - int err; - - if ((err = rtnl_tc_str2handle(arg, &parent)) < 0) - nl_cli_fatal(err, "Unable to parse handle \"%s\": %s", - arg, nl_geterror(err)); - - rtnl_qdisc_set_parent(qdisc, parent); -} - -void nl_cli_qdisc_parse_handle(struct rtnl_qdisc *qdisc, char *arg) -{ - uint32_t handle; - int err; - - if ((err = rtnl_tc_str2handle(arg, &handle)) < 0) - nl_cli_fatal(err, "Unable to parse handle \"%s\": %s", - arg, nl_geterror(err)); - - rtnl_qdisc_set_handle(qdisc, handle); -} - -void nl_cli_qdisc_parse_kind(struct rtnl_qdisc *qdisc, char *arg) -{ - rtnl_qdisc_set_kind(qdisc, arg); -} - /** @} */ diff --git a/src/lib/route.c b/src/lib/route.c index 05cb2ada..cd3e8978 100644 --- a/src/lib/route.c +++ b/src/lib/route.c @@ -198,14 +198,18 @@ 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); + rtnl_route_set_table(route, table); } void nl_cli_route_parse_prio(struct rtnl_route *route, char *arg) @@ -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) diff --git a/src/lib/tc.c b/src/lib/tc.c new file mode 100644 index 00000000..dde729fa --- /dev/null +++ b/src/lib/tc.c @@ -0,0 +1,165 @@ +/* + * src/lib/tc.c CLI Traffic Control 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) 2010 Thomas Graf <tgraf@suug.ch> + */ + +#include <netlink/cli/utils.h> +#include <netlink/cli/tc.h> +#include <netlink-private/route/tc-api.h> + +/** + * @ingroup cli + * @defgroup cli_tc Traffic Control + * @{ + */ +void nl_cli_tc_parse_dev(struct rtnl_tc *tc, struct nl_cache *link_cache, char *name) +{ + struct rtnl_link *link; + + link = rtnl_link_get_by_name(link_cache, name); + if (!link) + nl_cli_fatal(ENOENT, "Link \"%s\" does not exist.", name); + + rtnl_tc_set_link(tc, link); + rtnl_link_put(link); +} + +void nl_cli_tc_parse_parent(struct rtnl_tc *tc, char *arg) +{ + uint32_t parent; + int err; + + if ((err = rtnl_tc_str2handle(arg, &parent)) < 0) + nl_cli_fatal(err, "Unable to parse handle \"%s\": %s", + arg, nl_geterror(err)); + + rtnl_tc_set_parent(tc, parent); +} + +void nl_cli_tc_parse_handle(struct rtnl_tc *tc, char *arg, int create) +{ + uint32_t handle, parent; + int err; + + parent = rtnl_tc_get_parent(tc); + + if ((err = rtnl_tc_str2handle(arg, &handle)) < 0) { + if (err == -NLE_OBJ_NOTFOUND && create) + err = rtnl_classid_generate(arg, &handle, parent); + + if (err < 0) + nl_cli_fatal(err, "Unable to parse handle \"%s\": %s", + arg, nl_geterror(err)); + } + + rtnl_tc_set_handle(tc, handle); +} + +void nl_cli_tc_parse_mtu(struct rtnl_tc *tc, char *arg) +{ + rtnl_tc_set_mtu(tc, nl_cli_parse_u32(arg)); +} + +void nl_cli_tc_parse_mpu(struct rtnl_tc *tc, char *arg) +{ + rtnl_tc_set_mpu(tc, nl_cli_parse_u32(arg)); +} + +void nl_cli_tc_parse_overhead(struct rtnl_tc *tc, char *arg) +{ + rtnl_tc_set_overhead(tc, nl_cli_parse_u32(arg)); +} + +void nl_cli_tc_parse_kind(struct rtnl_tc *tc, char *arg) +{ + rtnl_tc_set_kind(tc, arg); +} + +void nl_cli_tc_parse_linktype(struct rtnl_tc *tc, char *arg) +{ + int type; + + if ((type = nl_str2llproto(arg)) < 0) + nl_cli_fatal(type, "Unable to parse linktype \"%s\": %s", + arg, nl_geterror(type)); + + rtnl_tc_set_linktype(tc, type); +} + +static NL_LIST_HEAD(tc_modules); + +static struct nl_cli_tc_module *__nl_cli_tc_lookup(struct rtnl_tc_ops *ops) +{ + struct nl_cli_tc_module *tm; + + nl_list_for_each_entry(tm, &tc_modules, tm_list) + if (tm->tm_ops == ops) + return tm; + + return NULL; +} + +struct nl_cli_tc_module *nl_cli_tc_lookup(struct rtnl_tc_ops *ops) +{ + struct nl_cli_tc_module *tm; + + if ((tm = __nl_cli_tc_lookup(ops))) + return tm; + + switch (ops->to_type) { + case RTNL_TC_TYPE_QDISC: + case RTNL_TC_TYPE_CLASS: + nl_cli_load_module("cli/qdisc", ops->to_kind); + break; + + case RTNL_TC_TYPE_CLS: + nl_cli_load_module("cli/cls", ops->to_kind); + break; + + default: + nl_cli_fatal(EINVAL, "BUG: unhandled TC object type %d", + ops->to_type); + } + + if (!(tm = __nl_cli_tc_lookup(ops))) { + nl_cli_fatal(EINVAL, "Application bug: The shared library for " + "the tc object \"%s\" was successfully loaded but it " + "seems that module did not register itself", + ops->to_kind); + } + + return tm; +} + +void nl_cli_tc_register(struct nl_cli_tc_module *tm) +{ + struct rtnl_tc_ops *ops; + + if (!(ops = rtnl_tc_lookup_ops(tm->tm_type, tm->tm_name))) { + nl_cli_fatal(ENOENT, "Unable to register CLI TC module " + "\"%s\": No matching libnl TC module found.", tm->tm_name); + } + + if (__nl_cli_tc_lookup(ops)) { + nl_cli_fatal(EEXIST, "Unable to register CLI TC module " + "\"%s\": Module already registered.", tm->tm_name); + } + + tm->tm_ops = ops; + + nl_list_add_tail(&tm->tm_list, &tc_modules); +} + +void nl_cli_tc_unregister(struct nl_cli_tc_module *tm) +{ + nl_list_del(&tm->tm_list); +} + + +/** @} */ diff --git a/src/lib/utils.c b/src/lib/utils.c index 02a7be12..e5eacdec 100644 --- a/src/lib/utils.c +++ b/src/lib/utils.c @@ -13,10 +13,25 @@ * @defgroup cli Command Line Interface API * * @{ + * + * These modules provide an interface for text based applications. The + * functions provided are wrappers for their libnl equivalent with + * added error handling. The functions check for allocation failures, + * invalid input, and unknown types and will print error messages + * accordingly via nl_cli_fatal(). */ #include <netlink/cli/utils.h> +/** + * Parse a text based 32 bit unsigned integer argument + * @arg arg Integer in text form. + * + * Tries to convert the number provided in arg to a uint32_t. Will call + * nl_cli_fatal() if the conversion fails. + * + * @return 32bit unsigned integer. + */ uint32_t nl_cli_parse_u32(const char *arg) { unsigned long lval; @@ -34,7 +49,7 @@ void nl_cli_print_version(void) { printf("libnl tools version %s\n", LIBNL_VERSION); printf( - "Copyright (C) 2003-2009 Thomas Graf <tgraf@redhat.com>\n" + "Copyright (C) 2003-2010 Thomas Graf <tgraf@redhat.com>\n" "\n" "This program comes with ABSOLUTELY NO WARRANTY. This is free \n" "software, and you are welcome to redistribute it under certain\n" @@ -44,9 +59,18 @@ void nl_cli_print_version(void) exit(0); } +/** + * Print error message and quit application + * @arg err Error code. + * @arg fmt Error message. + * + * Prints the formatted error message to stderr and quits the application + * using the provided error code. + */ void nl_cli_fatal(int err, const char *fmt, ...) { va_list ap; + char buf[256]; fprintf(stderr, "Error: "); @@ -56,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)); } @@ -102,8 +126,6 @@ int nl_cli_parse_dumptype(const char *str) return NL_DUMP_DETAILS; else if (!strcasecmp(str, "stats")) return NL_DUMP_STATS; - else if (!strcasecmp(str, "env")) - return NL_DUMP_ENV; else nl_cli_fatal(EINVAL, "Invalid dump type \"%s\".\n", str); @@ -113,20 +135,34 @@ int nl_cli_parse_dumptype(const char *str) int nl_cli_confirm(struct nl_object *obj, struct nl_dump_params *params, int default_yes) { - int answer; - nl_object_dump(obj, params); - printf("Delete? (%c/%c) ", - default_yes ? 'Y' : 'y', - default_yes ? 'n' : 'N'); - do { - answer = tolower(getchar()); - if (answer == '\n') + for (;;) { + char buf[32] = { 0 }; + int answer; + + printf("Delete? (%c/%c) ", + default_yes ? 'Y' : 'y', + default_yes ? 'n' : 'N'); + + if (!fgets(buf, sizeof(buf), stdin)) { + fprintf(stderr, "Error while reading\n."); + continue; + } + + switch ((answer = tolower(buf[0]))) { + case '\n': answer = default_yes ? 'y' : 'n'; - } while (answer != 'y' && answer != 'n'); + case 'y': + case 'n': + return answer == 'y'; + } + + fprintf(stderr, "Invalid input, try again.\n"); + } + + return 0; - return answer == 'y'; } struct nl_cache *nl_cli_alloc_cache(struct nl_sock *sock, const char *name, @@ -144,4 +180,17 @@ struct nl_cache *nl_cli_alloc_cache(struct nl_sock *sock, const char *name, return cache; } +void nl_cli_load_module(const char *prefix, const char *name) +{ + char path[FILENAME_MAX+1]; + void *handle; + + snprintf(path, sizeof(path), "%s/%s/%s.so", + PKGLIBDIR, prefix, name); + + if (!(handle = dlopen(path, RTLD_NOW))) + nl_cli_fatal(ENOENT, "Unable to load module \"%s\": %s\n", + path, dlerror()); +} + /** @} */ diff --git a/src/nf-ct-add.c b/src/nf-ct-add.c new file mode 100644 index 00000000..8ad4c534 --- /dev/null +++ b/src/nf-ct-add.c @@ -0,0 +1,142 @@ +/* + * src/nf-ct-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) 2003-2009 Thomas Graf <tgraf@suug.ch> + * Copyright (c) 2007 Philip Craig <philipc@snapgear.com> + * Copyright (c) 2007 Secure Computing Corporation + */ + +#include <netlink/cli/utils.h> +#include <netlink/cli/ct.h> + +static int quiet = 0; + +static void print_usage(void) +{ + printf( + "Usage: nf-ct-add [OPTION]... [CONNTRACK ENTRY]\n" + "\n" + "Options\n" + " -q, --quiet Do not print informal notifications.\n" + " -h, --help Show this help\n" + " -v, --version Show versioning information\n" + "\n" + "Conntrack Selection\n" + " -p, --proto=PROTOCOL Protocol\n" + " --orig-src=ADDR Original source address\n" + " --orig-sport=PORT Original source port\n" + " --orig-dst=ADDR Original destination address\n" + " --orig-dport=PORT Original destination port\n" + " --reply-src=ADDR Reply source address\n" + " --reply-sport=PORT Reply source port\n" + " --reply-dst=ADDR Reply destination address\n" + " --reply-dport=PORT Reply destination port\n" + " -F, --family=FAMILY Address family\n" + " --mark=NUM Mark value\n" + " --timeout=NUM Timeout value\n" + " --status Bitset representing status of connection.\n" + " --zone=NUM Zone value\n" + ); + exit(0); +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct nfnl_ct *ct; + struct nl_dump_params params = { + .dp_type = NL_DUMP_LINE, + .dp_fd = stdout, + }; + int err, nlflags = NLM_F_CREATE; + + ct = nl_cli_ct_alloc(); + + for (;;) { + int c, optidx = 0; + enum { + ARG_ORIG_SRC = 257, + ARG_ORIG_SPORT = 258, + ARG_ORIG_DST, + ARG_ORIG_DPORT, + ARG_REPLY_SRC, + ARG_REPLY_SPORT, + ARG_REPLY_DST, + ARG_REPLY_DPORT, + ARG_MARK, + ARG_TIMEOUT, + ARG_STATUS, + ARG_ZONE, + }; + static struct option long_opts[] = { + { "quiet", 0, 0, 'q' }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "proto", 1, 0, 'p' }, + { "orig-src", 1, 0, ARG_ORIG_SRC }, + { "orig-sport", 1, 0, ARG_ORIG_SPORT }, + { "orig-dst", 1, 0, ARG_ORIG_DST }, + { "orig-dport", 1, 0, ARG_ORIG_DPORT }, + { "reply-src", 1, 0, ARG_REPLY_SRC }, + { "reply-sport", 1, 0, ARG_REPLY_SPORT }, + { "reply-dst", 1, 0, ARG_REPLY_DST }, + { "reply-dport", 1, 0, ARG_REPLY_DPORT }, + { "family", 1, 0, 'F' }, + { "mark", 1, 0, ARG_MARK }, + { "timeout", 1, 0, ARG_TIMEOUT }, + { "status", 1, 0, ARG_STATUS }, + { "zone", 1, 0, ARG_ZONE }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "46q:hv:p:F:", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case '?': exit(NLE_INVAL); + case 'q': quiet = 1; break; + case '4': nfnl_ct_set_family(ct, AF_INET); break; + case '6': nfnl_ct_set_family(ct, AF_INET6); break; + case 'h': print_usage(); break; + case 'v': nl_cli_print_version(); break; + case 'p': nl_cli_ct_parse_protocol(ct, optarg); break; + case ARG_ORIG_SRC: nl_cli_ct_parse_src(ct, 0, optarg); break; + case ARG_ORIG_SPORT: nl_cli_ct_parse_src_port(ct, 0, optarg); break; + case ARG_ORIG_DST: nl_cli_ct_parse_dst(ct, 0, optarg); break; + case ARG_ORIG_DPORT: nl_cli_ct_parse_dst_port(ct, 0, optarg); break; + case ARG_REPLY_SRC: nl_cli_ct_parse_src(ct, 1, optarg); break; + case ARG_REPLY_SPORT: nl_cli_ct_parse_src_port(ct, 1, optarg); break; + case ARG_REPLY_DST: nl_cli_ct_parse_dst(ct, 1, optarg); break; + case ARG_REPLY_DPORT: nl_cli_ct_parse_dst_port(ct, 1, optarg); break; + case 'F': nl_cli_ct_parse_family(ct, optarg); break; + case ARG_MARK: nl_cli_ct_parse_mark(ct, optarg); break; + case ARG_TIMEOUT: nl_cli_ct_parse_timeout(ct, optarg); break; + case ARG_STATUS: nl_cli_ct_parse_status(ct, optarg); break; + case ARG_ZONE: nl_cli_ct_parse_zone(ct, optarg); break; + } + } + + if (!quiet) { + printf("Adding "); + nl_object_dump(OBJ_CAST(ct), ¶ms); + } + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_NETFILTER); + + if ((err = nfnl_ct_add(sock, ct, nlflags)) < 0) + nl_cli_fatal(err, "Unable to add conntrack: %s", nl_geterror(err)); + + if (!quiet) { + printf("Added "); + nl_object_dump(OBJ_CAST(ct), ¶ms); + } + + return 0; +} diff --git a/src/nf-exp-add.c b/src/nf-exp-add.c new file mode 100644 index 00000000..4b7f9d98 --- /dev/null +++ b/src/nf-exp-add.c @@ -0,0 +1,187 @@ +/* + * 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) 2003-2009 Thomas Graf <tgraf@suug.ch> + * Copyright (c) 2007 Philip Craig <philipc@snapgear.com> + * Copyright (c) 2007 Secure Computing Corporation + * Copyright (c) 2012 Rich Fought <rich.fought@watchguard.com> + * + */ + +#include <netlink/cli/utils.h> +#include <netlink/cli/exp.h> + +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 (Kernel 2.6.37)\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_NAT_PROTO, + ARG_NAT_SRC, + ARG_NAT_SPORT, + ARG_NAT_DST, + ARG_NAT_DPORT, + ARG_NAT_DIR, + 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 }, + { "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 }, + { "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 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; + 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; +} diff --git a/src/nf-exp-delete.c b/src/nf-exp-delete.c new file mode 100644 index 00000000..2ec45aea --- /dev/null +++ b/src/nf-exp-delete.c @@ -0,0 +1,165 @@ +/* + * 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 <tgraf@suug.ch> + * Copyright (c) 2007 Philip Craig <philipc@snapgear.com> + * Copyright (c) 2007 Secure Computing Corporation + * Copyright (c) 2012 Rich Fought <rich.fought@watchguard.com> + */ + +#include <netlink/cli/utils.h> +#include <netlink/cli/exp.h> + +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 new file mode 100644 index 00000000..1c6ec690 --- /dev/null +++ b/src/nf-exp-list.c @@ -0,0 +1,137 @@ +/* + * 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) 2003-2009 Thomas Graf <tgraf@suug.ch> + * Copyright (c) 2007 Philip Craig <philipc@snapgear.com> + * Copyright (c) 2007 Secure Computing Corporation + * Copyright (c) 2012 Rich Fought <rich.fought@watchguard.com> + */ + +#include <netlink/cli/utils.h> +#include <netlink/cli/exp.h> + +static void print_usage(void) +{ + printf( + "Usage: nf-exp-list [OPTION]... [EXPECTATION ENTRY]\n" + "\n" + "Options\n" + " -f, --format=TYPE Output format { brief | details }\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" + " --helper=STRING Helper Name\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_HELPER_NAME, + 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 }, + { "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 '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_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); + exp_cache = nl_cli_exp_alloc_cache(sock); + + nl_cache_dump_filter(exp_cache, ¶ms, OBJ_CAST(exp)); + + return 0; +} diff --git a/src/nf-log.c b/src/nf-log.c index 26bae6da..913ba163 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) diff --git a/src/nf-queue.c b/src/nf-queue.c index 3fb3c11f..922d9c8e 100644 --- a/src/nf-queue.c +++ b/src/nf-queue.c @@ -13,6 +13,7 @@ #include <netlink/cli/utils.h> #include <netlink/cli/link.h> +#include <netinet/in.h> #include <linux/netfilter.h> #include <linux/netfilter/nfnetlink_queue.h> #include <netlink/netfilter/nfnl.h> @@ -41,31 +42,7 @@ static void obj_input(struct nl_object *obj, void *arg) .dp_fd = stdout, .dp_dump_msgtype = 1, }; - uint32_t packet_id = nfnl_queue_msg_get_packetid(msg); - static uint32_t next_packet_id = 0; - struct nfnl_queue_msg *lost_msg = NULL; - uint8_t family; - uint16_t group; - - if (packet_id > next_packet_id) { - printf("Warning: %d Out of order packets. Queue or socket overload \n", packet_id - next_packet_id); - group = nfnl_queue_msg_get_group(msg); - family = nfnl_queue_msg_get_family(msg); - lost_msg = nfnl_queue_msg_alloc(); - - do { - nfnl_queue_msg_set_group(lost_msg, group); - nfnl_queue_msg_set_family(lost_msg, family); - nfnl_queue_msg_set_packetid(lost_msg, next_packet_id); - nfnl_queue_msg_set_verdict(lost_msg, NF_ACCEPT); - nfnl_queue_msg_send_verdict(nf_sock, lost_msg); - next_packet_id++; - } while (packet_id > next_packet_id); - - nfnl_queue_msg_put(lost_msg); - } - next_packet_id = packet_id + 1; nfnl_queue_msg_set_verdict(msg, NF_ACCEPT); nl_object_dump(obj, &dp); nfnl_queue_msg_send_verdict(nf_sock, msg); diff --git a/src/nl-addr-list.c b/src/nl-addr-list.c index 9b045a52..20995a84 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); @@ -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; diff --git a/src/nl-class-add.c b/src/nl-class-add.c new file mode 100644 index 00000000..b9a17dc6 --- /dev/null +++ b/src/nl-class-add.c @@ -0,0 +1,155 @@ +/* + * src/nl-class-add.c Add/Update/Replace Traffic Class + * + * 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 <tgraf@suug.ch> + */ + +#include <netlink/cli/utils.h> +#include <netlink/cli/tc.h> +#include <netlink/cli/qdisc.h> +#include <netlink/cli/class.h> +#include <netlink/cli/link.h> + +#include <netlink-private/route/tc-api.h> + +static int quiet = 0; + +static void print_usage(void) +{ + printf( +"Usage: nl-class-add [OPTIONS]... class [CONFIGURATION]...\n" +"\n" +"OPTIONS\n" +" -q, --quiet Do not print informal notifications.\n" +" -h, --help Show this help text.\n" +" -v, --version Show versioning information.\n" +" --update Update class if it exists.\n" +" --update-only Only update class, never create it.\n" +" -d, --dev=DEV Network device the class should be attached to.\n" +" -i, --id=ID ID of new class (default: auto-generated)\n" +" -p, --parent=ID ID of parent { root | ingress | class-ID }\n" +" --mtu=SIZE Overwrite MTU (default: MTU of network device)\n" +" --mpu=SIZE Minimum packet size on the link (default: 0).\n" +" --overhead=SIZE Overhead in bytes per packet (default: 0).\n" +" --linktype=TYPE Overwrite linktype (default: type of network device)\n" +"\n" +"CONFIGURATION\n" +" -h, --help Show help text of class specific options.\n" +"\n" +"EXAMPLE\n" +" $ nl-class-add --dev=eth1 --parent=root htb --rate=100mbit\n" +"\n" + ); + exit(0); +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct rtnl_class *class; + struct rtnl_tc *tc; + struct nl_cache *link_cache; + struct nl_dump_params dp = { + .dp_type = NL_DUMP_DETAILS, + .dp_fd = stdout, + }; + struct nl_cli_tc_module *tm; + struct rtnl_tc_ops *ops; + int err, flags = NLM_F_CREATE | NLM_F_EXCL; + char *kind, *id = NULL; + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + + link_cache = nl_cli_link_alloc_cache(sock); + + class = nl_cli_class_alloc(); + tc = (struct rtnl_tc *) class; + + for (;;) { + int c, optidx = 0; + enum { + ARG_UPDATE = 257, + ARG_UPDATE_ONLY = 258, + ARG_MTU, + ARG_MPU, + ARG_OVERHEAD, + ARG_LINKTYPE, + }; + static struct option long_opts[] = { + { "quiet", 0, 0, 'q' }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "dev", 1, 0, 'd' }, + { "parent", 1, 0, 'p' }, + { "id", 1, 0, 'i' }, + { "update", 0, 0, ARG_UPDATE }, + { "update-only", 0, 0, ARG_UPDATE_ONLY }, + { "mtu", 1, 0, ARG_MTU }, + { "mpu", 1, 0, ARG_MPU }, + { "overhead", 1, 0, ARG_OVERHEAD }, + { "linktype", 1, 0, ARG_LINKTYPE }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "+qhvd:p:i:", + long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case 'q': quiet = 1; break; + case 'h': print_usage(); break; + case 'v': nl_cli_print_version(); break; + case 'd': nl_cli_tc_parse_dev(tc, link_cache, optarg); break; + case 'p': nl_cli_tc_parse_parent(tc, optarg); break; + case 'i': id = strdup(optarg); break; + case ARG_UPDATE: flags = NLM_F_CREATE; break; + case ARG_UPDATE_ONLY: flags = 0; break; + case ARG_MTU: nl_cli_tc_parse_mtu(tc, optarg); break; + case ARG_MPU: nl_cli_tc_parse_mpu(tc, optarg); break; + case ARG_OVERHEAD: nl_cli_tc_parse_overhead(tc, optarg); break; + case ARG_LINKTYPE: nl_cli_tc_parse_linktype(tc, optarg); break; + } + } + + if (optind >= argc) + print_usage(); + + if (!rtnl_tc_get_ifindex(tc)) + nl_cli_fatal(EINVAL, "You must specify a network device (--dev=XXX)"); + + if (!rtnl_tc_get_parent(tc)) + nl_cli_fatal(EINVAL, "You must specify a parent (--parent=XXX)"); + + if (id) { + nl_cli_tc_parse_handle(tc, id, 1); + free(id); + } + + kind = argv[optind++]; + rtnl_tc_set_kind(tc, kind); + + if (!(ops = rtnl_tc_get_ops(tc))) + nl_cli_fatal(ENOENT, "Unknown class \"%s\"", kind); + + if (!(tm = nl_cli_tc_lookup(ops))) + nl_cli_fatal(ENOTSUP, "class type \"%s\" not supported.", kind); + + tm->tm_parse_argv(tc, argc, argv); + + if (!quiet) { + printf("Adding "); + nl_object_dump(OBJ_CAST(class), &dp); + } + + if ((err = rtnl_class_add(sock, class, flags)) < 0) + nl_cli_fatal(EINVAL, "Unable to add class: %s", nl_geterror(err)); + + return 0; +} diff --git a/src/nl-class-delete.c b/src/nl-class-delete.c new file mode 100644 index 00000000..37657a47 --- /dev/null +++ b/src/nl-class-delete.c @@ -0,0 +1,128 @@ +/* + * src/nl-class-delete.c Delete 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) 2010 Thomas Graf <tgraf@suug.ch> + */ + +#include <netlink/cli/utils.h> +#include <netlink/cli/class.h> +#include <netlink/cli/link.h> + +static int quiet = 0, default_yes = 0, deleted = 0, interactive = 0; +static struct nl_sock *sock; + +static void print_usage(void) +{ + printf( + "Usage: nl-class-delete [OPTION]... [class]\n" + "\n" + "OPTIONS\n" + " --interactive Run interactively.\n" + " --yes Set default answer to yes.\n" + " -q, --quiet Do not print informal notifications.\n" + " -h, --help Show this help text and exit.\n" + " -v, --version Show versioning information and exit.\n" + "\n" + " -d, --dev=DEV Device the class is attached to.\n" + " -p, --parent=ID Identifier of parent qdisc/class.\n" + " -i, --id=ID Identifier\n" + " -k, --kind=NAME Kind of class (e.g. pfifo_fast)\n" + "\n" + "EXAMPLE\n" + " # Delete all classes on eth0 attached to parent 1:\n" + " $ nl-class-delete --dev eth0 --parent 1:\n" + "\n" + ); + + exit(0); +} + +static void delete_cb(struct nl_object *obj, void *arg) +{ + struct rtnl_class *class = nl_object_priv(obj); + struct nl_dump_params params = { + .dp_type = NL_DUMP_LINE, + .dp_fd = stdout, + }; + int err; + + if (interactive && !nl_cli_confirm(obj, ¶ms, default_yes)) + return; + + if ((err = rtnl_class_delete(sock, class)) < 0) + nl_cli_fatal(err, "Unable to delete class: %s\n", nl_geterror(err)); + + if (!quiet) { + printf("Deleted "); + nl_object_dump(obj, ¶ms); + } + + deleted++; +} + +int main(int argc, char *argv[]) +{ + struct rtnl_class *class; + struct rtnl_tc *tc; + struct nl_cache *link_cache, *class_cache; + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(sock); + class = nl_cli_class_alloc(); + tc = (struct rtnl_tc *) class; + + for (;;) { + int c, optidx = 0; + enum { + ARG_YES = 257, + ARG_INTERACTIVE = 258, + }; + static struct option long_opts[] = { + { "interactive", 0, 0, ARG_INTERACTIVE }, + { "yes", 0, 0, ARG_YES }, + { "quiet", 0, 0, 'q' }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "dev", 1, 0, 'd' }, + { "parent", 1, 0, 'p' }, + { "id", 1, 0, 'i' }, + { "kind", 1, 0, 'k' }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "qhvd:p:i:k:", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case '?': nl_cli_fatal(EINVAL, "Invalid options"); + case ARG_INTERACTIVE: interactive = 1; break; + case ARG_YES: default_yes = 1; break; + case 'q': quiet = 1; break; + case 'h': print_usage(); break; + case 'v': nl_cli_print_version(); break; + case 'd': nl_cli_tc_parse_dev(tc, link_cache, optarg); break; + case 'p': nl_cli_tc_parse_parent(tc, optarg); break; + case 'i': nl_cli_tc_parse_handle(tc, optarg, 0); break; + case 'k': nl_cli_tc_parse_kind(tc, optarg); break; + } + } + + if (!rtnl_tc_get_ifindex(tc)) + nl_cli_fatal(EINVAL, "You must specify a network device (--dev=XXX)"); + + class_cache = nl_cli_class_alloc_cache(sock, rtnl_tc_get_ifindex(tc)); + + nl_cache_foreach_filter(class_cache, OBJ_CAST(class), delete_cb, NULL); + + if (!quiet) + printf("Deleted %d classs\n", deleted); + + return 0; +} diff --git a/src/nl-class-list.c b/src/nl-class-list.c new file mode 100644 index 00000000..c2423fbf --- /dev/null +++ b/src/nl-class-list.c @@ -0,0 +1,117 @@ +/* + * src/nl-class-list.c List 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) 2010 Thomas Graf <tgraf@suug.ch> + */ + +#include <netlink/cli/utils.h> +#include <netlink/cli/tc.h> +#include <netlink/cli/class.h> +#include <netlink/cli/link.h> + +static struct nl_sock *sock; + +static struct nl_dump_params params = { + .dp_type = NL_DUMP_LINE, +}; + +static void print_usage(void) +{ + printf( + "Usage: nl-class-list [OPTION]...\n" + "\n" + "OPTIONS\n" + " --details Show details\n" + " --stats Show statistics\n" + " -h, --help Show this help\n" + " -v, --version Show versioning information\n" + "\n" + " -d, --dev=DEV Device the class is attached to. (default: all)\n" + " -p, --parent=ID Identifier of parent class.\n" + " -i, --id=ID Identifier.\n" + " -k, --kind=NAME Kind of class (e.g. pfifo_fast)\n" + "\n" + "EXAMPLE\n" + " # Display statistics of all classes on eth0\n" + " $ nl-class-list --stats --dev=eth0\n" + "\n" + ); + exit(0); +} + +static void __dump_class(int ifindex, struct rtnl_class *filter) +{ + struct nl_cache *cache; + + cache = nl_cli_class_alloc_cache(sock, ifindex); + nl_cache_dump_filter(cache, ¶ms, OBJ_CAST(filter)); +} + +static void dump_class(struct nl_object *obj, void *arg) +{ + struct rtnl_link *link = nl_object_priv(obj); + + __dump_class(rtnl_link_get_ifindex(link), arg); +} + +int main(int argc, char *argv[]) +{ + struct rtnl_class *class; + struct rtnl_tc *tc; + struct nl_cache *link_cache; + int ifindex; + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(sock); + class = nl_cli_class_alloc(); + tc = (struct rtnl_tc *) class; + + params.dp_fd = stdout; + + for (;;) { + int c, optidx = 0; + enum { + ARG_DETAILS = 257, + ARG_STATS = 258, + }; + static struct option long_opts[] = { + { "details", 0, 0, ARG_DETAILS }, + { "stats", 0, 0, ARG_STATS }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "dev", 1, 0, 'd' }, + { "parent", 1, 0, 'p' }, + { "id", 1, 0, 'i' }, + { "kind", 1, 0, 'k' }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "hvd:p:i:k:", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case ARG_DETAILS: params.dp_type = NL_DUMP_DETAILS; break; + case ARG_STATS: params.dp_type = NL_DUMP_STATS; break; + case 'h': print_usage(); break; + case 'v': nl_cli_print_version(); break; + case 'd': nl_cli_tc_parse_dev(tc, link_cache, optarg); break; + case 'p': nl_cli_tc_parse_parent(tc, optarg); break; + case 'i': nl_cli_tc_parse_handle(tc, optarg, 0); break; + case 'k': nl_cli_tc_parse_kind(tc, optarg); break; + } + } + + if ((ifindex = rtnl_tc_get_ifindex(tc))) + __dump_class(ifindex, class); + else + nl_cache_foreach(link_cache, dump_class, class); + + return 0; +} diff --git a/src/nl-classid-lookup.c b/src/nl-classid-lookup.c new file mode 100644 index 00000000..1d45d0b2 --- /dev/null +++ b/src/nl-classid-lookup.c @@ -0,0 +1,87 @@ +/* + * src/nl-classid-lookup.c Lookup classid + * + * 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 <tgraf@suug.ch> + */ + +#include <netlink/cli/utils.h> + +static void print_usage(void) +{ + printf( +"Usage: nl-classid-lookup [OPTIONS]... NAME\n" +"\n" +"OPTIONS\n" +" -h, --help Show this help text.\n" +" -v, --version Show versioning information.\n" +" -r, --reverse Do a reverse lookup, i.e. classid to name.\n" +" --raw Print the raw classid, not pretty printed.\n" +"\n" +"EXAMPLE\n" +" $ nl-classid-lookup low_latency\n" +" $ nl-classid-lookup -r 1:12\n" +"\n" + ); + exit(0); +} + +int main(int argc, char *argv[]) +{ + uint32_t classid; + char *name; + int err, reverse = 0, raw = 0; + + for (;;) { + int c, optidx = 0; + enum { + ARG_RAW = 257, + }; + static struct option long_opts[] = { + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "reverse", 0, 0, 'r' }, + { "raw", 0, 0, ARG_RAW }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "hvr", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case 'h': print_usage(); break; + case 'v': nl_cli_print_version(); break; + case 'r': reverse = 1; break; + case ARG_RAW: raw = 1; break; + } + } + + if (optind >= argc) + print_usage(); + + name = argv[optind++]; + + /* + * We use rtnl_tc_str2handle() even while doing a reverse lookup. This + * allows for name -> name lookups. This is intentional, it does not + * do any harm and avoids duplicating a lot of code. + */ + if ((err = rtnl_tc_str2handle(name, &classid)) < 0) + nl_cli_fatal(err, "Unable to lookup classid \"%s\": %s", + name, nl_geterror(err)); + + if (reverse) { + char buf[64]; + printf("%s\n", rtnl_tc_handle2str(classid, buf, sizeof(buf))); + } else if (raw) + printf("%#x\n", classid); + else + printf("%x:%x\n", TC_H_MAJ(classid) >> 16, TC_H_MIN(classid)); + + return 0; +} diff --git a/src/nl-cls-add.c b/src/nl-cls-add.c index 997f02f8..6acb3202 100644 --- a/src/nl-cls-add.c +++ b/src/nl-cls-add.c @@ -5,29 +5,45 @@ * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation version 2 of the License. * - * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch> + * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch> */ -#include "cls/utils.h" +#include <netlink/cli/utils.h> +#include <netlink/cli/tc.h> +#include <netlink/cli/cls.h> +#include <netlink/cli/link.h> + +#include <netlink-private/route/tc-api.h> static int quiet = 0; static void print_usage(void) { printf( -"Usage: nl-cls-add [OPTION]... [CLASSIFIER] TYPE [TYPE OPTIONS]...\n" +"Usage: nl-cls-add [OPTIONS]... classifier [CONFIGURATION]...\n" "\n" -"Options\n" +"OPTIONS\n" " -q, --quiet Do not print informal notifications.\n" -" -h, --help Show this help.\n" +" -h, --help Show this help text.\n" " -v, --version Show versioning information.\n" +" --update Update classifier if it exists.\n" +" --update-only Only update classifier, never create it.\n" +" -d, --dev=DEV Network device the classifier should be attached to.\n" +" -i, --id=ID ID of new classifier (default: auto-generated)\n" +" -p, --parent=ID ID of parent { root | ingress | class-ID }\n" +" --protocol=PROTO Protocol to match (default: all)\n" +" --prio=PRIO Priority (default: 0)\n" +" --mtu=SIZE Overwrite MTU (default: MTU of network device)\n" +" --mpu=SIZE Minimum packet size on the link (default: 0).\n" +" --overhead=SIZE Overhead in bytes per packet (default: 0).\n" +" --linktype=TYPE Overwrite linktype (default: type of network device)\n" +"\n" +"CONFIGURATION\n" +" -h, --help Show help text of classifier specific options.\n" +"\n" +"EXAMPLE\n" +" $ nl-cls-add --dev=eth1 --parent=q_root basic --target c_www\n" "\n" -"Classifier Options\n" -" -d, --dev=DEV Device the classifier should be assigned to.\n" -" -p, --parent=HANDLE Parent QDisc\n" -" --proto=PROTO Protocol (default=IPv4)\n" -" --prio=NUM Priority (0..256)\n" -" --id=HANDLE Unique identifier\n" ); exit(0); } @@ -36,27 +52,36 @@ int main(int argc, char *argv[]) { struct nl_sock *sock; struct rtnl_cls *cls; + struct rtnl_tc *tc; struct nl_cache *link_cache; - struct rtnl_cls_ops *ops; - struct cls_module *mod; struct nl_dump_params dp = { .dp_type = NL_DUMP_DETAILS, .dp_fd = stdout, }; - char *kind; - int err, nlflags = NLM_F_CREATE; + struct nl_cli_tc_module *tm; + struct rtnl_tc_ops *ops; + int err, flags = NLM_F_CREATE | NLM_F_EXCL; + char *kind, *id = NULL; - sock = nlt_alloc_socket(); - nlt_connect(sock, NETLINK_ROUTE); - link_cache = nlt_alloc_link_cache(sock); - cls = nlt_alloc_cls(); + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(sock); + + cls = nl_cli_cls_alloc(); + tc = (struct rtnl_tc *) cls; + for (;;) { int c, optidx = 0; enum { - ARG_PROTO = 257, - ARG_PRIO = 258, - ARG_ID, + ARG_UPDATE = 257, + ARG_UPDATE_ONLY = 258, + ARG_MTU, + ARG_MPU, + ARG_OVERHEAD, + ARG_LINKTYPE, + ARG_PROTO, + ARG_PRIO, }; static struct option long_opts[] = { { "quiet", 0, 0, 'q' }, @@ -64,54 +89,75 @@ int main(int argc, char *argv[]) { "version", 0, 0, 'v' }, { "dev", 1, 0, 'd' }, { "parent", 1, 0, 'p' }, + { "id", 1, 0, 'i' }, { "proto", 1, 0, ARG_PROTO }, { "prio", 1, 0, ARG_PRIO }, - { "id", 1, 0, ARG_ID }, + { "update", 0, 0, ARG_UPDATE }, + { "update-only", 0, 0, ARG_UPDATE_ONLY }, + { "mtu", 1, 0, ARG_MTU }, + { "mpu", 1, 0, ARG_MPU }, + { "overhead", 1, 0, ARG_OVERHEAD }, + { "linktype", 1, 0, ARG_LINKTYPE }, { 0, 0, 0, 0 } }; - c = getopt_long(argc, argv, "+qhva:d:", long_opts, &optidx); + c = getopt_long(argc, argv, "+qhvd:p:i:", + long_opts, &optidx); if (c == -1) break; switch (c) { - case '?': exit(NLE_INVAL); case 'q': quiet = 1; break; case 'h': print_usage(); break; - case 'v': nlt_print_version(); break; - case 'd': parse_dev(cls, link_cache, optarg); break; - case 'p': parse_parent(cls, optarg); break; - case ARG_PRIO: parse_prio(cls, optarg); break; - case ARG_ID: parse_handle(cls, optarg); break; - case ARG_PROTO: parse_proto(cls, optarg); break; + case 'v': nl_cli_print_version(); break; + case 'd': nl_cli_tc_parse_dev(tc, link_cache, optarg); break; + case 'p': nl_cli_tc_parse_parent(tc, optarg); break; + case 'i': id = strdup(optarg); break; + case ARG_UPDATE: flags = NLM_F_CREATE; break; + case ARG_UPDATE_ONLY: flags = 0; break; + case ARG_MTU: nl_cli_tc_parse_mtu(tc, optarg); break; + case ARG_MPU: nl_cli_tc_parse_mpu(tc, optarg); break; + case ARG_OVERHEAD: nl_cli_tc_parse_overhead(tc, optarg); break; + case ARG_LINKTYPE: nl_cli_tc_parse_linktype(tc, optarg); break; + case ARG_PROTO: nl_cli_cls_parse_proto(cls, optarg); break; + case ARG_PRIO: + rtnl_cls_set_prio(cls, nl_cli_parse_u32(optarg)); + break; } } - if (optind >= argc) { + if (optind >= argc) print_usage(); - fatal(EINVAL, "Missing classifier type"); + + if (!rtnl_tc_get_ifindex(tc)) + nl_cli_fatal(EINVAL, "You must specify a network device (--dev=XXX)"); + + if (!rtnl_tc_get_parent(tc)) + nl_cli_fatal(EINVAL, "You must specify a parent (--parent=XXX)"); + + if (id) { + nl_cli_tc_parse_handle(tc, id, 1); + free(id); } kind = argv[optind++]; - if ((err = rtnl_cls_set_kind(cls, kind)) < 0) - fatal(ENOENT, "Unknown classifier type \"%s\".", kind); - - ops = rtnl_cls_get_ops(cls); - if (!(mod = lookup_cls_mod(ops))) - fatal(ENOTSUP, "Classifier type \"%s\" not supported.", kind); + rtnl_tc_set_kind(tc, kind); - mod->parse_argv(cls, argc, argv); + if (!(ops = rtnl_tc_get_ops(tc))) + nl_cli_fatal(ENOENT, "Unknown classifier \"%s\".", kind); - printf("Adding "); - nl_object_dump(OBJ_CAST(cls), &dp); + if (!(tm = nl_cli_tc_lookup(ops))) + nl_cli_fatal(ENOTSUP, "Classifier type \"%s\" not supported.", kind); - if ((err = rtnl_cls_add(sock, cls, nlflags)) < 0) - fatal(err, "Unable to add classifier: %s", nl_geterror(err)); + tm->tm_parse_argv(tc, argc, argv); if (!quiet) { - printf("Added "); + printf("Adding "); nl_object_dump(OBJ_CAST(cls), &dp); } + if ((err = rtnl_cls_add(sock, cls, flags)) < 0) + nl_cli_fatal(EINVAL, "Unable to add classifier: %s", nl_geterror(err)); + return 0; } diff --git a/src/nl-cls-delete.c b/src/nl-cls-delete.c index cfdc1709..2b3db1f1 100644 --- a/src/nl-cls-delete.c +++ b/src/nl-cls-delete.c @@ -6,52 +6,59 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2008 Thomas Graf <tgraf@suug.ch> + * Copyright (c) 2008-2010 Thomas Graf <tgraf@suug.ch> */ -#include "cls/utils.h" +#include <netlink/cli/utils.h> +#include <netlink/cli/cls.h> +#include <netlink/cli/link.h> -static int interactive = 0, default_yes = 0, quiet = 0; -static int deleted = 0; +static int quiet = 0, default_yes = 0, deleted = 0, interactive = 0; static struct nl_sock *sock; static void print_usage(void) { printf( - "Usage: nl-cls-list [OPTION]... [CLASSIFIER]\n" - "\n" - "Options\n" - " -i, --interactive Run interactively\n" - " --yes Set default answer to yes\n" - " -q, --quiet Do not print informal notifications\n" - " -h, --help Show this help\n" - " -v, --version Show versioning information\n" - "\n" - "Classifier Options\n" - " -d, --dev=DEV Device the classifier should be assigned to.\n" - " -p, --parent=HANDLE Parent qdisc/class\n" - " --proto=PROTO Protocol\n" - " --prio=NUM Priority (0..256)\n" - " --id=HANDLE Unique identifier\n" +"Usage: nl-cls-delete [OPTION]... [class]\n" +"\n" +"OPTIONS\n" +" --interactive Run interactively.\n" +" --yes Set default answer to yes.\n" +" -q, --quiet Do not print informal notifications.\n" +" -h, --help Show this help text and exit.\n" +" -v, --version Show versioning information and exit.\n" +"\n" +" -d, --dev=DEV Device the classifer is attached to.\n" +" -p, --parent=ID Identifier of parent qdisc/class.\n" +" -i, --id=ID Identifier\n" +" -k, --kind=NAME Kind of classifier (e.g. basic, u32, fw)\n" +" --protocol=PROTO Protocol to match (default: all)\n" +" --prio=PRIO Priority (default: 0)\n" +"\n" +"EXAMPLE\n" +" # Delete all classifiers on eth0 attached to parent q_root:\n" +" $ nl-cls-delete --dev eth0 --parent q_root:\n" +"\n" ); + exit(0); } static void delete_cb(struct nl_object *obj, void *arg) { - struct rtnl_cls *cls = (struct rtnl_cls *) obj; + struct rtnl_cls *cls = nl_object_priv(obj); struct nl_dump_params params = { .dp_type = NL_DUMP_LINE, .dp_fd = stdout, }; int err; - if (interactive && !nlt_confirm(obj, ¶ms, default_yes)) + if (interactive && !nl_cli_confirm(obj, ¶ms, default_yes)) return; if ((err = rtnl_cls_delete(sock, cls, 0)) < 0) - fatal(err, "Unable to delete classifier: %s", - nl_geterror(err)); + nl_cli_fatal(err, "Unable to delete classifier: %s\n", + nl_geterror(err)); if (!quiet) { printf("Deleted "); @@ -61,73 +68,88 @@ static void delete_cb(struct nl_object *obj, void *arg) deleted++; } -int main(int argc, char *argv[]) +static void __delete_link(int ifindex, struct rtnl_cls *filter) { - struct nl_cache *link_cache, *cls_cache; - struct rtnl_cls *cls; - int nf = 0, err; + struct nl_cache *cache; + uint32_t parent = rtnl_tc_get_parent((struct rtnl_tc *) filter); + + cache = nl_cli_cls_alloc_cache(sock, ifindex, parent); + nl_cache_foreach_filter(cache, OBJ_CAST(filter), delete_cb, NULL); + nl_cache_free(cache); +} + +static void delete_link(struct nl_object *obj, void *arg) +{ + struct rtnl_link *link = nl_object_priv(obj); - sock = nlt_alloc_socket(); - nlt_connect(sock, NETLINK_ROUTE); - link_cache = nlt_alloc_link_cache(sock); - cls = nlt_alloc_cls(); + __delete_link(rtnl_link_get_ifindex(link), arg); +} +int main(int argc, char *argv[]) +{ + struct rtnl_cls *cls; + struct rtnl_tc *tc; + struct nl_cache *link_cache; + int ifindex; + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(sock); + cls = nl_cli_cls_alloc(); + tc = (struct rtnl_tc *) cls; + for (;;) { int c, optidx = 0; enum { - ARG_PRIO = 257, - ARG_PROTO = 258, - ARG_ID, - ARG_YES, + ARG_YES = 257, + ARG_INTERACTIVE = 258, + ARG_PROTO, + ARG_PRIO, }; static struct option long_opts[] = { - { "interactive", 0, 0, 'i' }, + { "interactive", 0, 0, ARG_INTERACTIVE }, { "yes", 0, 0, ARG_YES }, { "quiet", 0, 0, 'q' }, { "help", 0, 0, 'h' }, { "version", 0, 0, 'v' }, { "dev", 1, 0, 'd' }, { "parent", 1, 0, 'p' }, + { "id", 1, 0, 'i' }, + { "kind", 1, 0, 'k' }, { "proto", 1, 0, ARG_PROTO }, { "prio", 1, 0, ARG_PRIO }, - { "id", 1, 0, ARG_ID }, { 0, 0, 0, 0 } }; - c = getopt_long(argc, argv, "iqhvd:p:", long_opts, &optidx); + c = getopt_long(argc, argv, "qhvd:p:i:k:", long_opts, &optidx); if (c == -1) break; switch (c) { - case 'i': interactive = 1; break; + case '?': nl_cli_fatal(EINVAL, "Invalid options"); + case ARG_INTERACTIVE: interactive = 1; break; case ARG_YES: default_yes = 1; break; case 'q': quiet = 1; break; case 'h': print_usage(); break; - case 'v': nlt_print_version(); break; - case 'd': nf++; parse_dev(cls, link_cache, optarg); break; - case 'p': nf++; parse_parent(cls, optarg); break; - case ARG_PRIO: nf++; parse_prio(cls, optarg); break; - case ARG_ID: nf++; parse_handle(cls, optarg); break; - case ARG_PROTO: nf++; parse_proto(cls, optarg); break; + case 'v': nl_cli_print_version(); break; + case 'd': nl_cli_tc_parse_dev(tc, link_cache, optarg); break; + case 'p': nl_cli_tc_parse_parent(tc, optarg); break; + case 'i': nl_cli_tc_parse_handle(tc, optarg, 0); break; + case 'k': nl_cli_tc_parse_kind(tc, optarg); break; + case ARG_PROTO: nl_cli_cls_parse_proto(cls, optarg); break; + case ARG_PRIO: + rtnl_cls_set_prio(cls, nl_cli_parse_u32(optarg)); + break; } - } - - if (nf == 0 && !interactive && !default_yes) { - fprintf(stderr, "You attempted to delete all classifiers in " - "non-interactive mode, aborting.\n"); - exit(0); - } - - err = rtnl_cls_alloc_cache(sock, rtnl_cls_get_ifindex(cls), - rtnl_cls_get_parent(cls), &cls_cache); - if (err < 0) - fatal(err, "Unable to allocate classifier cache: %s", - nl_geterror(err)); + } - nl_cache_foreach_filter(cls_cache, OBJ_CAST(cls), delete_cb, NULL); + if ((ifindex = rtnl_tc_get_ifindex(tc))) + __delete_link(ifindex, cls); + else + nl_cache_foreach(link_cache, delete_link, cls); if (!quiet) - printf("Deleted %d classifiers\n", deleted); + printf("Deleted %d classs\n", deleted); return 0; } diff --git a/src/nl-cls-list.c b/src/nl-cls-list.c index 9121d523..50725850 100644 --- a/src/nl-cls-list.c +++ b/src/nl-cls-list.c @@ -6,13 +6,16 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2008 Thomas Graf <tgraf@suug.ch> + * Copyright (c) 2008-2010 Thomas Graf <tgraf@suug.ch> */ -#include "cls/utils.h" +#include <netlink/cli/utils.h> +#include <netlink/cli/tc.h> +#include <netlink/cli/cls.h> +#include <netlink/cli/link.h> static struct nl_sock *sock; -static struct rtnl_cls *cls; + static struct nl_dump_params params = { .dp_type = NL_DUMP_LINE, }; @@ -20,94 +23,107 @@ static struct nl_dump_params params = { static void print_usage(void) { printf( - "Usage: nl-cls-list [OPTION]... [CLASSIFIER]\n" - "\n" - "Options\n" - " -f, --format=TYPE Output format { brief | details | stats }\n" - " -h, --help Show this help text.\n" - " -v, --version Show versioning information.\n" - "\n" - "Classifier Options\n" - " -d, --dev=DEV Device the classifier should be assigned to.\n" - " -p, --parent=HANDLE Parent qdisc/class\n" - " --proto=PROTO Protocol\n" - " --prio=NUM Priority\n" - " --id=NUM Identifier\n" +"Usage: nl-cls-list [OPTION]...\n" +"\n" +"OPTIONS\n" +" --details Show details\n" +" --stats Show statistics\n" +" -h, --help Show this help\n" +" -v, --version Show versioning information\n" +"\n" +" -d, --dev=DEV Device the classifier is attached to. (default: all)\n" +" -p, --parent=ID Identifier of parent class.\n" +" -i, --id=ID Identifier.\n" +" -k, --kind=NAME Kind of classifier (e.g. basic, u32, fw)\n" +" --protocol=PROTO Protocol to match (default: all)\n" +" --prio=PRIO Priority (default: 0)\n" +"\n" +"EXAMPLE\n" +" # Display statistics of all classes on eth0\n" +" $ nl-cls-list --stats --dev=eth0\n" +"\n" ); exit(0); } -static void print_cls(struct nl_object *obj, void *arg) +static void __dump_link(int ifindex, struct rtnl_cls *filter) { - struct nl_cache *cls_cache; - int err, ifindex; + struct nl_cache *cache; + uint32_t parent = rtnl_tc_get_parent((struct rtnl_tc *) filter); - if (obj) - ifindex = rtnl_link_get_ifindex((struct rtnl_link *) obj); - else - ifindex = rtnl_cls_get_ifindex(cls); + cache = nl_cli_cls_alloc_cache(sock, ifindex, parent); + nl_cache_dump_filter(cache, ¶ms, OBJ_CAST(filter)); + nl_cache_free(cache); +} - err = rtnl_cls_alloc_cache(sock, ifindex, rtnl_cls_get_parent(cls), - &cls_cache); - if (err < 0) - fatal(err, "Unable to allocate classifier cache: %s", - nl_geterror(err)); +static void dump_link(struct nl_object *obj, void *arg) +{ + struct rtnl_link *link = nl_object_priv(obj); - nl_cache_dump_filter(cls_cache, ¶ms, OBJ_CAST(cls)); - nl_cache_free(cls_cache); + __dump_link(rtnl_link_get_ifindex(link), arg); } int main(int argc, char *argv[]) { + struct rtnl_cls *cls; + struct rtnl_tc *tc; struct nl_cache *link_cache; - int dev = 0; + int ifindex; + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(sock); + cls = nl_cli_cls_alloc(); + tc = (struct rtnl_tc *) cls; params.dp_fd = stdout; - sock = nlt_alloc_socket(); - nlt_connect(sock, NETLINK_ROUTE); - link_cache = nlt_alloc_link_cache(sock); - cls = nlt_alloc_cls(); - + for (;;) { int c, optidx = 0; enum { - ARG_PROTO = 257, - ARG_PRIO = 258, - ARG_ID, + ARG_DETAILS = 257, + ARG_STATS = 258, + ARG_PROTO, + ARG_PRIO, }; static struct option long_opts[] = { - { "format", 1, 0, 'f' }, + { "details", 0, 0, ARG_DETAILS }, + { "stats", 0, 0, ARG_STATS }, { "help", 0, 0, 'h' }, { "version", 0, 0, 'v' }, { "dev", 1, 0, 'd' }, { "parent", 1, 0, 'p' }, + { "id", 1, 0, 'i' }, + { "kind", 1, 0, 'k' }, { "proto", 1, 0, ARG_PROTO }, { "prio", 1, 0, ARG_PRIO }, - { "id", 1, 0, ARG_ID }, { 0, 0, 0, 0 } }; - c = getopt_long(argc, argv, "+f:qhva:d:", long_opts, &optidx); + c = getopt_long(argc, argv, "hvd:p:i:k:", long_opts, &optidx); if (c == -1) break; switch (c) { - case '?': exit(NLE_INVAL); - case 'f': params.dp_type = nlt_parse_dumptype(optarg); break; + case ARG_DETAILS: params.dp_type = NL_DUMP_DETAILS; break; + case ARG_STATS: params.dp_type = NL_DUMP_STATS; break; case 'h': print_usage(); break; - case 'v': nlt_print_version(); break; - case 'd': dev = 1; parse_dev(cls, link_cache, optarg); break; - case 'p': parse_parent(cls, optarg); break; - case ARG_PRIO: parse_prio(cls, optarg); break; - case ARG_ID: parse_handle(cls, optarg); break; - case ARG_PROTO: parse_proto(cls, optarg); break; + case 'v': nl_cli_print_version(); break; + case 'd': nl_cli_tc_parse_dev(tc, link_cache, optarg); break; + case 'p': nl_cli_tc_parse_parent(tc, optarg); break; + case 'i': nl_cli_tc_parse_handle(tc, optarg, 0); break; + case 'k': nl_cli_tc_parse_kind(tc, optarg); break; + case ARG_PROTO: nl_cli_cls_parse_proto(cls, optarg); break; + case ARG_PRIO: + rtnl_cls_set_prio(cls, nl_cli_parse_u32(optarg)); + break; } } - if (!dev) - nl_cache_foreach(link_cache, print_cls, NULL); - else - print_cls(NULL, NULL); + if ((ifindex = rtnl_tc_get_ifindex(tc))) + __dump_link(ifindex, cls); + else + nl_cache_foreach(link_cache, dump_link, cls); return 0; } diff --git a/src/nl-link-enslave.c b/src/nl-link-enslave.c new file mode 100644 index 00000000..2b5d47db --- /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 <tgraf@suug.ch> + */ + +#include <netlink/cli/utils.h> +#include <netlink/cli/link.h> +#include <netlink/route/link/bonding.h> + +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-list.c b/src/nl-link-list.c index 5e1e3f6a..b5c98b40 100644 --- a/src/nl-link-list.c +++ b/src/nl-link-list.c @@ -6,43 +6,29 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch> + * Copyright (c) 2003-2010 Thomas Graf <tgraf@suug.ch> */ -#if 0 -static void print_usage(void) -{ - printf( - "Usage: nl-link-dump <mode> [<filter>]\n" - " mode := { brief | detailed | stats | xml }\n" - " filter := [dev DEV] [mtu MTU] [txqlen TXQLEN] [weight WEIGHT] [link LINK]\n" - " [master MASTER] [qdisc QDISC] [addr ADDR] [broadcast BRD]\n" - " [{ up | down }] [{ arp | noarp }] [{ promisc | nopromisc }]\n" - " [{ dynamic | nodynamic }] [{ multicast | nomulticast }]\n" - " [{ trailers | notrailers }] [{ allmulticast | noallmulticast }]\n"); - exit(1); -} -#endif - #include <netlink/cli/utils.h> #include <netlink/cli/link.h> static void print_usage(void) { printf( - "Usage: nl-link-list [OPTION]... [Link]\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" - "Link Options\n" - " -n, --name=NAME link name\n" - " -i, --index interface index\n" - " --mtu=NUM MTU value\n" - " --txqlen=NUM TX queue length\n" - " --weight=NUM weight\n" +"Usage: nl-link-list [OPTIONS]... \n" +"\n" +"OPTIONS\n" +" --details Show detailed information of each link\n" +" --stats Show statistics, implies --details\n" +" -h, --help Show this help text.\n" +" -v, --version Show versioning information.\n" +"\n" +" -n, --name=NAME Name of link\n" +" -i, --index Interface index (unique identifier)\n" +" --family=NAME Link address family\n" +" --mtu=NUM MTU value\n" +" --txqlen=NUM TX queue length\n" +" --weight=NUM Weight\n" ); exit(0); } @@ -59,7 +45,6 @@ int main(int argc, char *argv[]) sock = nl_cli_alloc_socket(); nl_cli_connect(sock, NETLINK_ROUTE); - link_cache = nl_cli_link_alloc_cache(sock); link = nl_cli_link_alloc(); for (;;) { @@ -69,9 +54,12 @@ int main(int argc, char *argv[]) ARG_MTU = 258, ARG_TXQLEN, ARG_WEIGHT, + ARG_DETAILS, + ARG_STATS, }; static struct option long_opts[] = { - { "format", 1, 0, 'f' }, + { "details", 0, 0, ARG_DETAILS }, + { "stats", 0, 0, ARG_STATS }, { "help", 0, 0, 'h' }, { "version", 0, 0, 'v' }, { "name", 1, 0, 'n' }, @@ -83,12 +71,13 @@ int main(int argc, char *argv[]) { 0, 0, 0, 0 } }; - c = getopt_long(argc, argv, "f:hvn:i:", long_opts, &optidx); + c = getopt_long(argc, argv, "hvn:i:", long_opts, &optidx); if (c == -1) break; switch (c) { - case 'f': params.dp_type = nl_cli_parse_dumptype(optarg); break; + case ARG_DETAILS: params.dp_type = NL_DUMP_DETAILS; break; + case ARG_STATS: params.dp_type = NL_DUMP_STATS; break; case 'h': print_usage(); break; case 'v': nl_cli_print_version(); break; case 'n': nl_cli_link_parse_name(link, optarg); break; @@ -100,6 +89,9 @@ int main(int argc, char *argv[]) } } + link_cache = nl_cli_link_alloc_cache_family(sock, + rtnl_link_get_family(link)); + nl_cache_dump_filter(link_cache, ¶ms, OBJ_CAST(link)); return 0; diff --git a/src/nl-link-name2ifindex.c b/src/nl-link-name2ifindex.c index b04af04e..b8ae4bcd 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 <ifindex>\n"); + printf("Usage: nl-link-name2ifindex <name>\n"); exit(0); } diff --git a/src/nl-link-release.c b/src/nl-link-release.c new file mode 100644 index 00000000..4c9f15a5 --- /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 <tgraf@suug.ch> + */ + +#include <netlink/cli/utils.h> +#include <netlink/cli/link.h> +#include <netlink/route/link/bonding.h> + +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; +} + diff --git a/src/nl-link-set.c b/src/nl-link-set.c index 94c94e78..bbb60f97 100644 --- a/src/nl-link-set.c +++ b/src/nl-link-set.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch> + * Copyright (c) 2003-2010 Thomas Graf <tgraf@suug.ch> */ #include <netlink/cli/utils.h> @@ -41,6 +41,8 @@ static void print_usage(void) " --mtu=NUM MTU value\n" " --txqlen=NUM TX queue length\n" " --weight=NUM weight\n" + " --ifalias=NAME alias name (SNMP IfAlias)\n" + " --state=up/down set interface up/down\n" ); exit(0); } @@ -55,7 +57,7 @@ static void set_cb(struct nl_object *obj, void *arg) }; int err; - if ((err = rtnl_link_change(sock, link, change, 0) < 0)) + if ((err = rtnl_link_change(sock, link, change, 0)) < 0) nl_cli_fatal(err, "Unable to change link: %s", nl_geterror(err)); @@ -84,6 +86,8 @@ int main(int argc, char *argv[]) ARG_MTU = 258, ARG_TXQLEN, ARG_WEIGHT, + ARG_IFALIAS, + ARG_STATE, }; static struct option long_opts[] = { { "quiet", 0, 0, 'q' }, @@ -95,6 +99,8 @@ int main(int argc, char *argv[]) { "mtu", 1, 0, ARG_MTU }, { "txqlen", 1, 0, ARG_TXQLEN }, { "weight", 1, 0, ARG_WEIGHT }, + { "ifalias", 1, 0, ARG_IFALIAS }, + { "state", 1, 0, ARG_STATE }, { 0, 0, 0, 0 } }; @@ -109,9 +115,16 @@ int main(int argc, char *argv[]) case 'n': ok++; nl_cli_link_parse_name(link, optarg); break; case 'i': ok++; nl_cli_link_parse_ifindex(link, optarg); break; case ARG_RENAME: nl_cli_link_parse_name(change, optarg); break; - case ARG_MTU: nl_cli_link_parse_mtu(link, optarg); break; - case ARG_TXQLEN: nl_cli_link_parse_txqlen(link, optarg); break; - case ARG_WEIGHT: nl_cli_link_parse_weight(link, optarg); break; + case ARG_MTU: nl_cli_link_parse_mtu(change, optarg); break; + case ARG_TXQLEN: nl_cli_link_parse_txqlen(change, optarg); break; + case ARG_WEIGHT: nl_cli_link_parse_weight(change, optarg); break; + case ARG_IFALIAS: nl_cli_link_parse_ifalias(change, optarg); break; + case ARG_STATE: + if(!strcmp(optarg, "up")) + rtnl_link_set_flags(change, IFF_UP); + else if(!strcmp(optarg, "down")) + rtnl_link_unset_flags(change, IFF_UP); + break; } } diff --git a/src/nl-list-caches.c b/src/nl-list-caches.c index 7e4ffc15..853d8a40 100644 --- a/src/nl-list-caches.c +++ b/src/nl-list-caches.c @@ -9,7 +9,7 @@ * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch> */ -#include <netlink-local.h> +#include <netlink-private/netlink.h> #include <netlink/cli/utils.h> static void print_usage(void) @@ -48,7 +48,6 @@ static void print(struct nl_cache_ops *ops, void *arg) "brief", "detailed", "stats", - "env", }; int i; @@ -82,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/src/nl-list-sockets.c b/src/nl-list-sockets.c index 868006eb..c2fa1cdb 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, diff --git a/src/nl-neigh-delete.c b/src/nl-neigh-delete.c index 887bd846..c4186088 100644 --- a/src/nl-neigh-delete.c +++ b/src/nl-neigh-delete.c @@ -14,7 +14,7 @@ #include <netlink/cli/link.h> 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-pktloc-lookup.c b/src/nl-pktloc-lookup.c index 09b04b24..17c867b5 100644 --- a/src/nl-pktloc-lookup.c +++ b/src/nl-pktloc-lookup.c @@ -14,24 +14,141 @@ static void print_usage(void) { - printf("Usage: nl-pktloc-lookup <name>\n"); +printf( +"Usage: nl-pktloc-lookup [OPTIONS] <name>\n" +"\n" +"OPTIONS\n" +" -h, --help Show this help text.\n" +" -v, --version Show versioning information.\n" +" -l, --list List all packet location definitions.\n" +" --u32=VALUE Print in iproute2's u32 selector style\n" +"\n" +"\n" +"EXAMPLE\n" +" $ nl-pktloc-lookup ip.dst\n" +" $ nl-pktloc-lookup --list\n" +"\n" +); exit(0); } +static const char *align_txt[] = { + [TCF_EM_ALIGN_U8] = "u8", + [TCF_EM_ALIGN_U16] = "u16", + [TCF_EM_ALIGN_U32] = "u32" +}; + +static uint32_t align_mask[] = { + [TCF_EM_ALIGN_U8] = 0xff, + [TCF_EM_ALIGN_U16] = 0xffff, + [TCF_EM_ALIGN_U32] = 0xffffffff, +}; + +static const char *layer_txt[] = { + [TCF_LAYER_LINK] = "eth", + [TCF_LAYER_NETWORK] = "ip", + [TCF_LAYER_TRANSPORT] = "tcp" +}; + +static void dump_u32_style(struct rtnl_pktloc *loc, uint32_t value) +{ + if (loc->align > 4) + nl_cli_fatal(EINVAL, "u32 only supports alignments u8|u16|u32."); + + if (loc->layer == TCF_LAYER_LINK) + nl_cli_fatal(EINVAL, "u32 does not support link " + "layer locations."); + + if (loc->shift > 0) + nl_cli_fatal(EINVAL, "u32 does not support shifting."); + + printf("%s %x %x at %s%u\n", + align_txt[loc->align], + value, loc->mask ? loc->mask : align_mask[loc->align], + loc->layer == TCF_LAYER_TRANSPORT ? "nexthdr+" : "", + loc->offset); +} + +static char *get_align_txt(struct rtnl_pktloc *loc) +{ + static char buf[16]; + + if (loc->align <= 4) + strcpy(buf, align_txt[loc->align]); + else + snprintf(buf, sizeof(buf), "%u", loc->align); + + return buf; +} + +static void dump_loc(struct rtnl_pktloc *loc) +{ + printf("%s = %s at %s+%u & %#x >> %u\n", + loc->name, get_align_txt(loc), layer_txt[loc->layer], + loc->offset, loc->mask, loc->shift); +} + +static void list_cb(struct rtnl_pktloc *loc, void *arg) +{ + printf("%-26s %-5s %3s+%-4u %#-10x %-8u %u\n", + loc->name, get_align_txt(loc), layer_txt[loc->layer], + loc->offset, loc->mask, loc->shift, loc->refcnt); +} + +static void do_list(void) +{ + printf( +"name align offset mask shift refcnt\n"); + printf("---------------------------------------------------------\n"); + + rtnl_pktloc_foreach(&list_cb, NULL); +} + int main(int argc, char *argv[]) { struct rtnl_pktloc *loc; - int err; + int err, ustyle = 0; + uint32_t uvalue = 0; + + for (;;) { + int c, optidx = 0; + enum { + ARG_U32 = 257, + }; + static struct option long_opts[] = { + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "list", 0, 0, 'l' }, + { "u32", 1, 0, ARG_U32 }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "hvl", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case 'h': print_usage(); break; + case 'v': nl_cli_print_version(); break; + case 'l': do_list(); exit(0); + case ARG_U32: + ustyle = 1; + uvalue = nl_cli_parse_u32(optarg); + break; + } + } - if (argc < 2) + if (optind >= argc) print_usage(); - if ((err = rtnl_pktloc_lookup(argv[1], &loc)) < 0) + if ((err = rtnl_pktloc_lookup(argv[optind++], &loc)) < 0) nl_cli_fatal(err, "Unable to lookup packet location: %s", nl_geterror(err)); - printf("%s: %u %u+%u 0x%x %u\n", loc->name, loc->align, - loc->layer, loc->offset, loc->mask, loc->flags); + if (ustyle) + dump_u32_style(loc, uvalue); + else + dump_loc(loc); return 0; } diff --git a/src/nl-qdisc-add.c b/src/nl-qdisc-add.c new file mode 100644 index 00000000..c2a7c9f7 --- /dev/null +++ b/src/nl-qdisc-add.c @@ -0,0 +1,146 @@ +/* + * src/nl-qdisc-add.c Add Queueing Discipline + * + * 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 <tgraf@suug.ch> + */ + +#include <netlink/cli/utils.h> +#include <netlink/cli/tc.h> +#include <netlink/cli/qdisc.h> +#include <netlink/cli/link.h> + +#include <netlink-private/route/tc-api.h> + +static int quiet = 0; + +static void print_usage(void) +{ + printf( +"Usage: nl-qdisc-add [OPTIONS]... QDISC [CONFIGURATION]...\n" +"\n" +"OPTIONS\n" +" -q, --quiet Do not print informal notifications.\n" +" -h, --help Show this help text.\n" +" -v, --version Show versioning information.\n" +" --update Update qdisc if it exists.\n" +" --replace Replace or update qdisc if it exists.\n" +" --update-only Only update qdisc, never create it.\n" +" --replace-only Only replace or update qdisc, never create it.\n" +" -d, --dev=DEV Network device the qdisc should be attached to.\n" +" -i, --id=ID ID of new qdisc (default: auto-generated)r\n" +" -p, --parent=ID ID of parent { root | ingress | QDISC-ID }\n" +"\n" +"CONFIGURATION\n" +" -h, --help Show help text of qdisc specific options.\n" +"\n" +"EXAMPLE\n" +" $ nl-qdisc-add --dev=eth1 --parent=root htb --rate=100mbit\n" +"\n" + ); + exit(0); +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct rtnl_qdisc *qdisc; + struct rtnl_tc *tc; + struct nl_cache *link_cache; + struct nl_dump_params dp = { + .dp_type = NL_DUMP_DETAILS, + .dp_fd = stdout, + }; + struct nl_cli_tc_module *tm; + struct rtnl_tc_ops *ops; + int err, flags = NLM_F_CREATE | NLM_F_EXCL; + char *kind, *id = NULL; + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + + link_cache = nl_cli_link_alloc_cache(sock); + + qdisc = nl_cli_qdisc_alloc(); + tc = (struct rtnl_tc *) qdisc; + + for (;;) { + int c, optidx = 0; + enum { + ARG_REPLACE = 257, + ARG_UPDATE = 258, + ARG_REPLACE_ONLY, + ARG_UPDATE_ONLY, + }; + static struct option long_opts[] = { + { "quiet", 0, 0, 'q' }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "dev", 1, 0, 'd' }, + { "parent", 1, 0, 'p' }, + { "id", 1, 0, 'i' }, + { "replace", 0, 0, ARG_REPLACE }, + { "update", 0, 0, ARG_UPDATE }, + { "replace-only", 0, 0, ARG_REPLACE_ONLY }, + { "update-only", 0, 0, ARG_UPDATE_ONLY }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "+qhvd:p:i:", + long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case 'q': quiet = 1; break; + case 'h': print_usage(); break; + case 'v': nl_cli_print_version(); break; + case 'd': nl_cli_tc_parse_dev(tc, link_cache, optarg); break; + case 'p': nl_cli_tc_parse_parent(tc, optarg); break; + case 'i': id = strdup(optarg); break; + case ARG_UPDATE: flags = NLM_F_CREATE; break; + case ARG_REPLACE: flags = NLM_F_CREATE | NLM_F_REPLACE; break; + case ARG_UPDATE_ONLY: flags = 0; break; + case ARG_REPLACE_ONLY: flags = NLM_F_REPLACE; break; + } + } + + if (optind >= argc) + print_usage(); + + if (!rtnl_tc_get_ifindex(tc)) + nl_cli_fatal(EINVAL, "You must specify a network device (--dev=XXX)"); + + if (!rtnl_tc_get_parent(tc)) + nl_cli_fatal(EINVAL, "You must specify a parent"); + + if (id) { + nl_cli_tc_parse_handle(tc, id, 1); + free(id); + } + + kind = argv[optind++]; + rtnl_tc_set_kind(tc, kind); + + if (!(ops = rtnl_tc_get_ops(tc))) + nl_cli_fatal(ENOENT, "Unknown qdisc \"%s\"", kind); + + if (!(tm = nl_cli_tc_lookup(ops))) + nl_cli_fatal(ENOTSUP, "Qdisc type \"%s\" not supported.", kind); + + tm->tm_parse_argv(tc, argc, argv); + + if (!quiet) { + printf("Adding "); + nl_object_dump(OBJ_CAST(qdisc), &dp); + } + + if ((err = rtnl_qdisc_add(sock, qdisc, flags)) < 0) + nl_cli_fatal(EINVAL, "Unable to add qdisc: %s", nl_geterror(err)); + + return 0; +} diff --git a/src/nl-qdisc-delete.c b/src/nl-qdisc-delete.c index 5cb7aa35..2f945bb2 100644 --- a/src/nl-qdisc-delete.c +++ b/src/nl-qdisc-delete.c @@ -6,32 +6,32 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch> + * Copyright (c) 2003-2010 Thomas Graf <tgraf@suug.ch> */ #include <netlink/cli/utils.h> +#include <netlink/cli/tc.h> #include <netlink/cli/qdisc.h> #include <netlink/cli/link.h> 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) { printf( "Usage: nl-qdisc-delete [OPTION]... [QDISC]\n" "\n" - "Options\n" - " -i, --interactive Run interactively\n" - " --yes Set default answer to yes\n" - " -q, --quiet Do not print informal notifications\n" - " -h, --help Show this help\n" - " -v, --version Show versioning information\n" + "OPTIONS\n" + " --interactive Run interactively.\n" + " --yes Set default answer to yes.\n" + " -q, --quiet Do not print informal notifications.\n" + " -h, --help Show this help text and exit.\n" + " -v, --version Show versioning information and exit.\n" "\n" - "QDisc Options\n" - " -d, --dev=DEV Device the qdisc is attached to\n" - " -p, --parent=HANDLE Identifier of parent qdisc\n" - " -H, --handle=HANDLE Identifier\n" + " -d, --dev=DEV Device the qdisc is attached to.\n" + " -p, --parent=ID Identifier of parent qdisc/class.\n" + " -i, --id=ID Identifier\n" " -k, --kind=NAME Kind of qdisc (e.g. pfifo_fast)\n" ); @@ -47,6 +47,10 @@ static void delete_cb(struct nl_object *obj, void *arg) }; int err; + /* Ignore default qdiscs, unable to delete */ + if (rtnl_tc_get_handle((struct rtnl_tc *) qdisc) == 0) + return; + if (interactive && !nl_cli_confirm(obj, ¶ms, default_yes)) return; @@ -64,49 +68,73 @@ static void delete_cb(struct nl_object *obj, void *arg) int main(int argc, char *argv[]) { struct rtnl_qdisc *qdisc; + struct rtnl_tc *tc; struct nl_cache *link_cache, *qdisc_cache; + int nfilter = 0; sock = nl_cli_alloc_socket(); nl_cli_connect(sock, NETLINK_ROUTE); link_cache = nl_cli_link_alloc_cache(sock); qdisc_cache = nl_cli_qdisc_alloc_cache(sock); qdisc = nl_cli_qdisc_alloc(); + tc = (struct rtnl_tc *) qdisc; for (;;) { int c, optidx = 0; enum { ARG_YES = 257, + ARG_INTERACTIVE = 258, }; static struct option long_opts[] = { - { "interactive", 0, 0, 'i' }, + { "interactive", 0, 0, ARG_INTERACTIVE }, { "yes", 0, 0, ARG_YES }, { "quiet", 0, 0, 'q' }, { "help", 0, 0, 'h' }, { "version", 0, 0, 'v' }, { "dev", 1, 0, 'd' }, { "parent", 1, 0, 'p' }, - { "handle", 1, 0, 'H' }, + { "id", 1, 0, 'i' }, { "kind", 1, 0, 'k' }, { 0, 0, 0, 0 } }; - c = getopt_long(argc, argv, "iqhvd:p:H:k:", long_opts, &optidx); + c = getopt_long(argc, argv, "qhvd:p:i:k:", long_opts, &optidx); if (c == -1) break; switch (c) { - case 'i': interactive = 1; break; + case '?': nl_cli_fatal(EINVAL, "Invalid options"); + case ARG_INTERACTIVE: interactive = 1; break; case ARG_YES: default_yes = 1; break; case 'q': quiet = 1; break; case 'h': print_usage(); break; case 'v': nl_cli_print_version(); break; - case 'd': nl_cli_qdisc_parse_dev(qdisc, link_cache, optarg); break; - case 'p': nl_cli_qdisc_parse_parent(qdisc, optarg); break; - case 'H': nl_cli_qdisc_parse_handle(qdisc, optarg); break; - case 'k': nl_cli_qdisc_parse_kind(qdisc, optarg); break; + case 'd': + nfilter++; + nl_cli_tc_parse_dev(tc, link_cache, optarg); + break; + case 'p': + nfilter++; + nl_cli_tc_parse_parent(tc, optarg); + break; + case 'i': + nfilter++; + nl_cli_tc_parse_handle(tc, optarg, 0); + break; + case 'k': + nfilter++; + nl_cli_tc_parse_kind(tc, optarg); + break; } } + if (nfilter == 0 && !interactive && !default_yes) { + nl_cli_fatal(EINVAL, + "You are attempting to delete all qdiscs on all devices.\n" + "If you want to proceed, run nl-qdisc-delete --yes.\n" + "Aborting..."); + } + nl_cache_foreach_filter(qdisc_cache, OBJ_CAST(qdisc), delete_cb, NULL); if (!quiet) diff --git a/src/nl-qdisc-list.c b/src/nl-qdisc-list.c index ec6e25f0..5b0a3f00 100644 --- a/src/nl-qdisc-list.c +++ b/src/nl-qdisc-list.c @@ -1,90 +1,183 @@ /* - * src/nl-qdisc-list.c List Qdiscs + * src/nl-qdisc-list.c List Queueing Disciplines * * 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 <tgraf@suug.ch> + * Copyright (c) 2003-2010 Thomas Graf <tgraf@suug.ch> */ #include <netlink/cli/utils.h> +#include <netlink/cli/tc.h> #include <netlink/cli/qdisc.h> +#include <netlink/cli/class.h> +#include <netlink/cli/cls.h> #include <netlink/cli/link.h> -static int quiet = 0; +#define NUM_INDENT 4 + +static struct nl_sock *sock; +static int recursive = 0; +static struct nl_dump_params params = { + .dp_type = NL_DUMP_LINE, +}; static void print_usage(void) { printf( "Usage: nl-qdisc-list [OPTION]... [QDISC]\n" "\n" - "Options\n" - " -f, --format=TYPE Output format { brief | details | stats }\n" + "OPTIONS\n" + " --details Show details\n" + " --stats Show statistics\n" + " -r, --recursive Show recursive tree\n" " -h, --help Show this help\n" " -v, --version Show versioning information\n" "\n" - "QDisc Options\n" - " -d, --dev=DEV Device the qdisc is attached to\n" - " -p, --parent=HANDLE Identifier of parent qdisc\n" - " -H, --handle=HANDLE Identifier\n" + " -d, --dev=DEV Device the qdisc is attached to. (default: all)\n" + " -p, --parent=ID Identifier of parent qdisc.\n" + " -i, --id=ID Identifier.\n" " -k, --kind=NAME Kind of qdisc (e.g. pfifo_fast)\n" + "\n" + "EXAMPLE\n" + " # Display statistics of all qdiscs attached to eth0\n" + " $ nl-qdisc-list --details --dev=eth0\n" + "\n" ); exit(0); } +static void list_classes(int ifindex, uint32_t parent); +static void list_qdiscs(int ifindex, uint32_t parent); + +static void list_class(struct nl_object *obj, void *arg) +{ + struct rtnl_tc *tc = nl_object_priv(obj); + nl_object_dump(obj, ¶ms); + + list_classes(rtnl_tc_get_ifindex(tc), rtnl_tc_get_handle(tc)); + list_qdiscs(rtnl_tc_get_ifindex(tc), rtnl_tc_get_handle(tc)); +} + +static void list_classes(int ifindex, uint32_t parent) +{ + struct nl_cache *class_cache; + struct rtnl_class *filter = nl_cli_class_alloc(); + + class_cache = nl_cli_class_alloc_cache(sock, ifindex); + + rtnl_tc_set_parent((struct rtnl_tc *) filter, parent); + params.dp_prefix += NUM_INDENT; + nl_cache_foreach_filter(class_cache, OBJ_CAST(filter), list_class, NULL); + params.dp_prefix -= NUM_INDENT; + + rtnl_class_put(filter); + nl_cache_free(class_cache); +} + +static void list_cls(int ifindex, uint32_t parent) +{ + struct nl_cache *cls_cache; + + cls_cache = nl_cli_cls_alloc_cache(sock, ifindex, parent); + + params.dp_prefix += NUM_INDENT; + nl_cache_dump(cls_cache, ¶ms); + params.dp_prefix -= NUM_INDENT; + + nl_cache_free(cls_cache); +} + +static void list_qdisc(struct nl_object *obj, void *arg) +{ + struct rtnl_qdisc *qdisc = nl_object_priv(obj); + struct rtnl_tc *tc = (struct rtnl_tc *) qdisc; + + nl_object_dump(obj, ¶ms); + + list_cls(rtnl_tc_get_ifindex(tc), rtnl_tc_get_handle(tc)); + + if (rtnl_tc_get_parent(tc) == TC_H_ROOT) { + list_cls(rtnl_tc_get_ifindex(tc), TC_H_ROOT); + list_classes(rtnl_tc_get_ifindex(tc), TC_H_ROOT); + } + + list_classes(rtnl_tc_get_ifindex(tc), rtnl_tc_get_handle(tc)); +} + +static void list_qdiscs(int ifindex, uint32_t parent) +{ + struct nl_cache *qdisc_cache; + struct rtnl_qdisc *filter = nl_cli_qdisc_alloc(); + + qdisc_cache = nl_cli_qdisc_alloc_cache(sock); + + rtnl_tc_set_ifindex((struct rtnl_tc *) filter, ifindex); + rtnl_tc_set_parent((struct rtnl_tc *) filter, parent); + params.dp_prefix += NUM_INDENT; + nl_cache_foreach_filter(qdisc_cache, OBJ_CAST(filter), list_qdisc, NULL); + params.dp_prefix -= NUM_INDENT; + + rtnl_qdisc_put(filter); + nl_cache_free(qdisc_cache); +} + int main(int argc, char *argv[]) { - struct nl_sock *sock; struct rtnl_qdisc *qdisc; + struct rtnl_tc *tc; struct nl_cache *link_cache, *qdisc_cache; - struct nl_dump_params params = { - .dp_type = NL_DUMP_LINE, - .dp_fd = stdout, - }; + params.dp_fd = stdout; sock = nl_cli_alloc_socket(); nl_cli_connect(sock, NETLINK_ROUTE); link_cache = nl_cli_link_alloc_cache(sock); qdisc_cache = nl_cli_qdisc_alloc_cache(sock); qdisc = nl_cli_qdisc_alloc(); + tc = (struct rtnl_tc *) qdisc; for (;;) { int c, optidx = 0; enum { - ARG_YES = 257, + ARG_DETAILS = 257, + ARG_STATS = 258, }; static struct option long_opts[] = { - { "format", 1, 0, 'f' }, - { "quiet", 0, 0, 'q' }, + { "details", 0, 0, ARG_DETAILS }, + { "stats", 0, 0, ARG_STATS }, + { "recursive", 0, 0, 'r' }, { "help", 0, 0, 'h' }, { "version", 0, 0, 'v' }, { "dev", 1, 0, 'd' }, { "parent", 1, 0, 'p' }, - { "handle", 1, 0, 'H' }, + { "id", 1, 0, 'i' }, { "kind", 1, 0, 'k' }, { 0, 0, 0, 0 } }; - c = getopt_long(argc, argv, "f:qhvd:p:H:k:", - long_opts, &optidx); + c = getopt_long(argc, argv, "rhvd:p:i:k:", long_opts, &optidx); if (c == -1) break; switch (c) { - case 'f': params.dp_type = nl_cli_parse_dumptype(optarg); break; - case 'q': quiet = 1; break; + case ARG_DETAILS: params.dp_type = NL_DUMP_DETAILS; break; + case ARG_STATS: params.dp_type = NL_DUMP_STATS; break; + case 'r': recursive = 1; break; case 'h': print_usage(); break; case 'v': nl_cli_print_version(); break; - case 'd': nl_cli_qdisc_parse_dev(qdisc, link_cache, optarg); break; - case 'p': nl_cli_qdisc_parse_parent(qdisc, optarg); break; - case 'H': nl_cli_qdisc_parse_handle(qdisc, optarg); break; - case 'k': nl_cli_qdisc_parse_kind(qdisc, optarg); break; + case 'd': nl_cli_tc_parse_dev(tc, link_cache, optarg); break; + case 'p': nl_cli_tc_parse_parent(tc, optarg); break; + case 'i': nl_cli_tc_parse_handle(tc, optarg, 0); break; + case 'k': nl_cli_tc_parse_kind(tc, optarg); break; } } - nl_cache_dump_filter(qdisc_cache, ¶ms, OBJ_CAST(qdisc)); + if (recursive) + nl_cache_foreach_filter(qdisc_cache, OBJ_CAST(qdisc), list_qdisc, NULL); + else + nl_cache_dump_filter(qdisc_cache, ¶ms, OBJ_CAST(qdisc)); return 0; } diff --git a/src/nl-route-add.c b/src/nl-route-add.c index 2f187df3..d4aa767e 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) { diff --git a/src/nl-route-get.c b/src/nl-route-get.c index c2f07d4c..9d9a4484 100644 --- a/src/nl-route-get.c +++ b/src/nl-route-get.c @@ -65,8 +65,12 @@ int main(int argc, char *argv[]) }; m = nlmsg_alloc_simple(RTM_GETROUTE, 0); - nlmsg_append(m, &rmsg, sizeof(rmsg), NLMSG_ALIGNTO); - nla_put_addr(m, RTA_DST, dst); + if (!m) + nl_cli_fatal(ENOMEM, "out of memory"); + if (nlmsg_append(m, &rmsg, sizeof(rmsg), NLMSG_ALIGNTO) < 0) + nl_cli_fatal(ENOMEM, "out of memory"); + if (nla_put_addr(m, RTA_DST, dst) < 0) + nl_cli_fatal(ENOMEM, "out of memory"); err = nl_send_auto_complete(sock, m); nlmsg_free(m); diff --git a/src/nl-tctree-list.c b/src/nl-tctree-list.c index a074a512..d90cb28f 100644 --- a/src/nl-tctree-list.c +++ b/src/nl-tctree-list.c @@ -12,6 +12,7 @@ #include <netlink/cli/utils.h> #include <netlink/cli/link.h> #include <netlink/cli/qdisc.h> +#include <netlink/cli/class.h> #include <linux/pkt_sched.h> static struct nl_sock *sock; @@ -22,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) { @@ -41,7 +43,7 @@ static void print_class(struct nl_object *obj, void *arg) struct rtnl_qdisc *leaf; struct rtnl_class *class = (struct rtnl_class *) obj; struct nl_cache *cls_cache; - uint32_t parent = rtnl_class_get_handle(class); + uint32_t parent = rtnl_tc_get_handle((struct rtnl_tc *) class); params.dp_prefix = (int)(long) arg; nl_object_dump(obj, ¶ms); @@ -50,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; @@ -60,16 +62,30 @@ static void print_class(struct nl_object *obj, void *arg) nl_cache_free(cls_cache); } +static void print_tc_childs(struct rtnl_tc *tc, void *arg) +{ + 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; struct nl_cache *cls_cache; - uint32_t parent = rtnl_qdisc_get_handle(qdisc); + uint32_t parent = rtnl_tc_get_handle((struct rtnl_tc *) qdisc); params.dp_prefix = (int)(long) arg; nl_object_dump(obj, ¶ms); - rtnl_qdisc_foreach_child(qdisc, class_cache, &print_class, arg + 2); + print_tc_childs(TC_CAST(qdisc), arg + 2); if (rtnl_cls_alloc_cache(sock, ifindex, parent, &cls_cache) < 0) return; |